fix(esp_partition): read-only and encrypted partition support

This commit is contained in:
Martin Vychodil
2025-10-08 14:03:00 +02:00
parent 5c8a10e61e
commit 3ce5725282
5 changed files with 295 additions and 136 deletions
@@ -119,10 +119,76 @@ TEST(partition_bdl, test_two_partitions_bdl_ops)
TEST_ESP_OK(part_blockdev_2->ops->release(part_blockdev_2));
}
TEST(partition_bdl, test_partition_bdl_limits)
{
// Limits tested:
// - geometry alignment with parameter size for all ops
// - dst buffer size check when reading
// Partition boundaries and other checks are provided by underlying partition APIs and are not verified here
esp_blockdev_handle_t part_blockdev = NULL;
TEST_ESP_OK(esp_partition_get_blockdev(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage1", &part_blockdev));
//artifitial setup setup for this test only
part_blockdev->geometry.erase_size = 512;
part_blockdev->geometry.read_size = 4;
part_blockdev->geometry.write_size = 16;
const size_t data_size = part_blockdev->geometry.erase_size;
uint8_t test_data[data_size];
uint8_t test_data_err[data_size-3];
const off_t target_addr_err = 3;
//correct addr, wrong length
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_SIZE, part_blockdev->ops->erase(part_blockdev, 0, data_size+3));
//wrong addr, correct length
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_SIZE, part_blockdev->ops->erase(part_blockdev, target_addr_err, part_blockdev->geometry.erase_size));
//correct addr, correct dst buff, wrong length
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_SIZE, part_blockdev->ops->read(part_blockdev, test_data, data_size, 0, data_size+3));
//wrong addr, correct dst buff, correct length
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_SIZE, part_blockdev->ops->read(part_blockdev, test_data, data_size, target_addr_err, data_size));
//correct addr, wrong dst buff, correct length
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, part_blockdev->ops->read(part_blockdev, test_data_err, sizeof(test_data_err), 0, data_size));
//correct addr, wrong length
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_SIZE, part_blockdev->ops->write(part_blockdev, test_data, 0, data_size+3));
//wrong addr, correct length
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_SIZE, part_blockdev->ops->write(part_blockdev, test_data, target_addr_err, data_size));
//release the BDL objects
TEST_ESP_OK(part_blockdev->ops->release(part_blockdev));
}
TEST(partition_bdl, test_bdl_partition_readonly)
{
//storage3 is readonly partition
esp_blockdev_handle_t part_blockdev = NULL;
TEST_ESP_OK(esp_partition_get_blockdev(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage3", &part_blockdev));
//test flags
TEST_ASSERT_EQUAL(1, part_blockdev->device_flags.read_only);
TEST_ASSERT_EQUAL(0, part_blockdev->geometry.write_size);
TEST_ASSERT_EQUAL(0, part_blockdev->geometry.erase_size);
TEST_ASSERT_EQUAL(0, part_blockdev->geometry.recommended_write_size);
TEST_ASSERT_EQUAL(0, part_blockdev->geometry.recommended_erase_size);
uint8_t dummy_test_buff[1024];
//write & erase must fail and read must work normally
TEST_ASSERT_EQUAL(ESP_ERR_NOT_SUPPORTED, part_blockdev->ops->erase(part_blockdev, 0, sizeof(dummy_test_buff)));
TEST_ASSERT_EQUAL(ESP_ERR_NOT_SUPPORTED, part_blockdev->ops->write(part_blockdev, dummy_test_buff, 0, sizeof(dummy_test_buff)));
TEST_ESP_OK(part_blockdev->ops->read(part_blockdev, dummy_test_buff, sizeof(dummy_test_buff), 0, sizeof(dummy_test_buff)));
TEST_ESP_OK(part_blockdev->ops->release(part_blockdev));
}
TEST_GROUP_RUNNER(partition_bdl)
{
RUN_TEST_CASE(partition_bdl, test_partition_bdl_ops);
RUN_TEST_CASE(partition_bdl, test_two_partitions_bdl_ops);
RUN_TEST_CASE(partition_bdl, test_partition_bdl_limits);
RUN_TEST_CASE(partition_bdl, test_bdl_partition_readonly);
}
static void run_all_tests(void)
@@ -3,5 +3,6 @@
nvs, data, nvs, 0x9000, 0x6000,
phy_init, data, phy, 0xf000, 0x1000,
factory, app, factory, 0x10000, 1M,
storage1, data, , 0x110000, 512K
storage2, data, , 0x190000, 512K,
storage1, data, , 0x110000, 512K,
storage2, data, , 0x190000, 128K,
storage3, data, , 0x1B0000, 128K, readonly
1 # Name, Type, SubType, Offset, Size, Flags
3 nvs, data, nvs, 0x9000, 0x6000,
4 phy_init, data, phy, 0xf000, 0x1000,
5 factory, app, factory, 0x10000, 1M,
6 storage1, data, , 0x110000, 512K storage1, data, , 0x110000, 512K,
7 storage2, data, , 0x190000, 512K, storage2, data, , 0x190000, 128K,
8 storage3, data, , 0x1B0000, 128K, readonly
+35 -10
View File
@@ -635,12 +635,16 @@ esp_err_t esp_partition_copy(const esp_partition_t* dest_part, uint32_t dest_off
static esp_err_t esp_partition_blockdev_read(esp_blockdev_handle_t dev_handle, uint8_t* dst_buf, size_t dst_buf_size, uint64_t src_addr, size_t data_read_len)
{
if (dev_handle->geometry.read_size == 0) {
return ESP_ERR_NOT_SUPPORTED;
}
//the simplest boundary check. Should be replaced by auxiliary geometry mapping function
if (src_addr % dev_handle->geometry.read_size != 0 || data_read_len % dev_handle->geometry.read_size) {
if (src_addr % dev_handle->geometry.read_size != 0 || data_read_len % dev_handle->geometry.read_size != 0) {
return ESP_ERR_INVALID_SIZE;
}
if (dst_buf_size > data_read_len) {
if (dst_buf_size < data_read_len) {
return ESP_ERR_INVALID_ARG;
}
@@ -655,8 +659,12 @@ static esp_err_t esp_partition_blockdev_read(esp_blockdev_handle_t dev_handle, u
static esp_err_t esp_partition_blockdev_write(esp_blockdev_handle_t dev_handle, const uint8_t* src_buf, uint64_t dst_addr, size_t data_write_len)
{
if (dev_handle->device_flags.read_only || dev_handle->geometry.write_size == 0) {
return ESP_ERR_NOT_SUPPORTED;
}
//the simplest boundary check. Should be replaced by auxiliary geometry mapping function
if (dst_addr % dev_handle->geometry.write_size != 0 || data_write_len % dev_handle->geometry.write_size) {
if (dst_addr % dev_handle->geometry.write_size != 0 || data_write_len % dev_handle->geometry.write_size != 0) {
return ESP_ERR_INVALID_SIZE;
}
@@ -671,8 +679,12 @@ static esp_err_t esp_partition_blockdev_write(esp_blockdev_handle_t dev_handle,
static esp_err_t esp_partition_blockdev_erase(esp_blockdev_handle_t dev_handle, uint64_t start_addr, size_t erase_len)
{
if (dev_handle->device_flags.read_only || dev_handle->geometry.erase_size == 0) {
return ESP_ERR_NOT_SUPPORTED;
}
//the simplest boundary check. Should be replaced by auxiliary geometry mapping function
if (start_addr % dev_handle->geometry.erase_size != 0 || erase_len % dev_handle->geometry.erase_size) {
if (start_addr % dev_handle->geometry.erase_size != 0 || erase_len % dev_handle->geometry.erase_size != 0) {
return ESP_ERR_INVALID_SIZE;
}
@@ -710,16 +722,29 @@ esp_err_t esp_partition_ptr_get_blockdev(const esp_partition_t* partition, esp_b
ESP_BLOCKDEV_FLAGS_INST_CONFIG_DEFAULT(out->device_flags);
out->geometry.disk_size = partition->size;
out->geometry.write_size = 1;
if(partition->readonly) {
out->device_flags.read_only = 1;
out->geometry.write_size = 0;
out->geometry.erase_size = 0;
out->geometry.recommended_write_size = 0;
out->geometry.recommended_erase_size = 0;
}
else {
if (partition->encrypted) {
out->geometry.write_size = 16;
out->geometry.recommended_write_size = 16;
} else {
out->geometry.write_size = 1;
out->geometry.recommended_write_size = 1;
}
out->geometry.erase_size = partition->erase_size;
out->geometry.recommended_erase_size = partition->erase_size;
}
out->geometry.read_size = 1;
out->geometry.erase_size = partition->erase_size;
out->geometry.recommended_write_size = 1;
out->geometry.recommended_read_size = 1;
out->geometry.recommended_erase_size = partition->erase_size;
out->geometry.disk_size = partition->size;
out->ops = &s_bdl_ops;
*out_bdl_handle_ptr = out;
return ESP_OK;
@@ -3,155 +3,221 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <inttypes.h>
#include "unity.h"
#include "unity_fixture.h"
#include "esp_flash.h"
#include "esp_partition.h"
#include "sdkconfig.h"
#include <string.h>
#include <inttypes.h>
#include "unity.h"
#include "unity_fixture.h"
#include "esp_flash.h"
#include "esp_partition.h"
#include "sdkconfig.h"
TEST_GROUP(esp_partition);
TEST_GROUP(esp_partition);
TEST_SETUP(esp_partition)
{
}
TEST_SETUP(esp_partition)
{
}
TEST_TEAR_DOWN(esp_partition)
{
}
TEST_TEAR_DOWN(esp_partition)
{
}
TEST(esp_partition, test_bdl_interface)
{
//get the block-device interface instance
esp_blockdev_handle_t part_blockdev = NULL;
TEST_ESP_OK(esp_partition_get_blockdev(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage1", &part_blockdev));
TEST(esp_partition, test_bdl_interface)
{
//get the block-device interface instance
esp_blockdev_handle_t part_blockdev = NULL;
TEST_ESP_OK(esp_partition_get_blockdev(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage1", &part_blockdev));
const size_t data_size = 256;
uint8_t test_data[data_size];
const off_t target_addr = 3*4*1024;
uint8_t data_buffer[data_size];
memset((void*)data_buffer, 0, data_size);
const size_t data_size = 256;
uint8_t test_data[data_size];
const off_t target_addr = 3*4*1024;
uint8_t data_buffer[data_size];
memset((void*)data_buffer, 0, data_size);
//erase the first sector data from the blockdev and check it's really wiped
TEST_ESP_OK(part_blockdev->ops->erase(part_blockdev, target_addr, part_blockdev->geometry.erase_size));
memset((void*)test_data, 0xFF, data_size); //erased NOR flash sector contains only 1s
TEST_ESP_OK(part_blockdev->ops->read(part_blockdev, data_buffer, sizeof(data_buffer), target_addr, data_size));
TEST_ASSERT_EQUAL(0, memcmp(test_data, data_buffer, data_size));
//erase the first sector data from the blockdev and check it's really wiped
TEST_ESP_OK(part_blockdev->ops->erase(part_blockdev, target_addr, part_blockdev->geometry.erase_size));
memset((void*)test_data, 0xFF, data_size); //erased NOR flash sector contains only 1s
TEST_ESP_OK(part_blockdev->ops->read(part_blockdev, data_buffer, sizeof(data_buffer), target_addr, data_size));
TEST_ASSERT_EQUAL(0, memcmp(test_data, data_buffer, data_size));
//write to the blockdev
memset((void*)test_data, 'A', data_size);
TEST_ESP_OK(part_blockdev->ops->write(part_blockdev, test_data, target_addr, data_size));
//write to the blockdev
memset((void*)test_data, 'A', data_size);
TEST_ESP_OK(part_blockdev->ops->write(part_blockdev, test_data, target_addr, data_size));
//read from the blockdev the data written before
TEST_ESP_OK(part_blockdev->ops->read(part_blockdev, data_buffer, sizeof(data_buffer), target_addr, data_size));
TEST_ASSERT_EQUAL(0, memcmp(test_data, data_buffer, data_size));
//read from the blockdev the data written before
TEST_ESP_OK(part_blockdev->ops->read(part_blockdev, data_buffer, sizeof(data_buffer), target_addr, data_size));
TEST_ASSERT_EQUAL(0, memcmp(test_data, data_buffer, data_size));
//release the BDL object - nothing to check here, the BDL memory is just freed
TEST_ESP_OK(part_blockdev->ops->release(part_blockdev));
}
//release the BDL object - nothing to check here, the BDL memory is just freed
TEST_ESP_OK(part_blockdev->ops->release(part_blockdev));
}
TEST(esp_partition, test_bdl_interface_external)
{
//register external partition
const esp_partition_t* ext_partition;
TEST_ESP_OK(esp_partition_register_external(NULL, 0x1D0000, 0x20000, "storage3", ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, &ext_partition));
TEST(esp_partition, test_bdl_interface_external)
{
//register external partition
const esp_partition_t* ext_partition;
TEST_ESP_OK(esp_partition_register_external(NULL, 0x1D0000, 0x20000, "storage4", ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, &ext_partition));
//get the block-device interface instance and test all the ops over external partition
esp_blockdev_handle_t part_blockdev = NULL;
TEST_ESP_OK(esp_partition_ptr_get_blockdev(ext_partition, &part_blockdev));
//get the block-device interface instance and test all the ops over external partition
esp_blockdev_handle_t part_blockdev = NULL;
TEST_ESP_OK(esp_partition_ptr_get_blockdev(ext_partition, &part_blockdev));
const size_t data_size = 256;
uint8_t test_data[data_size];
const off_t target_addr = 3*4*1024;
uint8_t data_buffer[data_size];
memset((void*)data_buffer, 0, data_size);
const size_t data_size = 256;
uint8_t test_data[data_size];
const off_t target_addr = 3*4*1024;
uint8_t data_buffer[data_size];
memset((void*)data_buffer, 0, data_size);
//erase the first sector data from the blockdev and check it's really wiped
TEST_ESP_OK(part_blockdev->ops->erase(part_blockdev, target_addr, part_blockdev->geometry.erase_size));
memset((void*)test_data, 0xFF, data_size); //erased NOR flash sector contains only 1s
TEST_ESP_OK(part_blockdev->ops->read(part_blockdev, data_buffer, sizeof(data_buffer), target_addr, data_size));
TEST_ASSERT_EQUAL(0, memcmp(test_data, data_buffer, data_size));
//erase the first sector data from the blockdev and check it's really wiped
TEST_ESP_OK(part_blockdev->ops->erase(part_blockdev, target_addr, part_blockdev->geometry.erase_size));
memset((void*)test_data, 0xFF, data_size); //erased NOR flash sector contains only 1s
TEST_ESP_OK(part_blockdev->ops->read(part_blockdev, data_buffer, sizeof(data_buffer), target_addr, data_size));
TEST_ASSERT_EQUAL(0, memcmp(test_data, data_buffer, data_size));
//write to the blockdev
memset((void*)test_data, 'A', data_size);
TEST_ESP_OK(part_blockdev->ops->write(part_blockdev, test_data, target_addr, data_size));
//write to the blockdev
memset((void*)test_data, 'A', data_size);
TEST_ESP_OK(part_blockdev->ops->write(part_blockdev, test_data, target_addr, data_size));
//read from the blockdev the data written before
TEST_ESP_OK(part_blockdev->ops->read(part_blockdev, data_buffer, sizeof(data_buffer), target_addr, data_size));
TEST_ASSERT_EQUAL(0, memcmp(test_data, data_buffer, data_size));
//read from the blockdev the data written before
TEST_ESP_OK(part_blockdev->ops->read(part_blockdev, data_buffer, sizeof(data_buffer), target_addr, data_size));
TEST_ASSERT_EQUAL(0, memcmp(test_data, data_buffer, data_size));
//release the BDL object - nothing to check here, the BDL memory is just freed
TEST_ESP_OK(part_blockdev->ops->release(part_blockdev));
//release the BDL object - nothing to check here, the BDL memory is just freed
TEST_ESP_OK(part_blockdev->ops->release(part_blockdev));
//deregister the external partition
TEST_ESP_OK(esp_partition_deregister_external(ext_partition));
}
//deregister the external partition
TEST_ESP_OK(esp_partition_deregister_external(ext_partition));
}
TEST(esp_partition, test_bdl_two_partitions)
{
//get the block-device interface instance for partition 'storage1'
esp_blockdev_handle_t part_blockdev_1 = NULL;
TEST_ESP_OK(esp_partition_get_blockdev(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage1", &part_blockdev_1));
TEST(esp_partition, test_bdl_two_partitions)
{
//get the block-device interface instance for partition 'storage1'
esp_blockdev_handle_t part_blockdev_1 = NULL;
TEST_ESP_OK(esp_partition_get_blockdev(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage1", &part_blockdev_1));
//get pointer to esp_partition_t object for partition 'storage2'
esp_partition_iterator_t iter = esp_partition_find(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage2");
TEST_ASSERT_NOT_NULL(iter);
const esp_partition_t *part = esp_partition_get(iter);
TEST_ASSERT_NOT_NULL(part);
esp_partition_iterator_release(iter);
//get pointer to esp_partition_t object for partition 'storage2'
esp_partition_iterator_t iter = esp_partition_find(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage2");
TEST_ASSERT_NOT_NULL(iter);
const esp_partition_t *part = esp_partition_get(iter);
TEST_ASSERT_NOT_NULL(part);
esp_partition_iterator_release(iter);
esp_blockdev_handle_t part_blockdev_2 = NULL;
TEST_ESP_OK(esp_partition_ptr_get_blockdev(part, &part_blockdev_2));
esp_blockdev_handle_t part_blockdev_2 = NULL;
TEST_ESP_OK(esp_partition_ptr_get_blockdev(part, &part_blockdev_2));
//erase & write & read data on both partitions in parallel
const size_t data_size = 256;
uint8_t test_data[data_size];
const off_t target_addr = 3*4*1024;
uint8_t data_buffer_1[data_size];
uint8_t data_buffer_2[data_size];
memset((void*)data_buffer_1, 0, data_size);
memset((void*)data_buffer_2, 0, data_size);
//erase & write & read data on both partitions in parallel
const size_t data_size = 256;
uint8_t test_data[data_size];
const off_t target_addr = 3*4*1024;
uint8_t data_buffer_1[data_size];
uint8_t data_buffer_2[data_size];
memset((void*)data_buffer_1, 0, data_size);
memset((void*)data_buffer_2, 0, data_size);
//erase the first sector data from the blockdev and check it's really wiped
TEST_ESP_OK(part_blockdev_1->ops->erase(part_blockdev_1, target_addr, part_blockdev_1->geometry.erase_size));
TEST_ESP_OK(part_blockdev_2->ops->erase(part_blockdev_2, target_addr, part_blockdev_2->geometry.erase_size));
memset((void*)test_data, 0xFF, data_size); //erased NOR flash sector contains only 1s
//erase the first sector data from the blockdev and check it's really wiped
TEST_ESP_OK(part_blockdev_1->ops->erase(part_blockdev_1, target_addr, part_blockdev_1->geometry.erase_size));
TEST_ESP_OK(part_blockdev_2->ops->erase(part_blockdev_2, target_addr, part_blockdev_2->geometry.erase_size));
memset((void*)test_data, 0xFF, data_size); //erased NOR flash sector contains only 1s
TEST_ESP_OK(part_blockdev_1->ops->read(part_blockdev_1, data_buffer_1, sizeof(data_buffer_1), target_addr, data_size));
TEST_ESP_OK(part_blockdev_2->ops->read(part_blockdev_2, data_buffer_2, sizeof(data_buffer_2), target_addr, data_size));
TEST_ASSERT_EQUAL(0, memcmp(test_data, data_buffer_1, data_size));
TEST_ASSERT_EQUAL(0, memcmp(test_data, data_buffer_2, data_size));
TEST_ESP_OK(part_blockdev_1->ops->read(part_blockdev_1, data_buffer_1, sizeof(data_buffer_1), target_addr, data_size));
TEST_ESP_OK(part_blockdev_2->ops->read(part_blockdev_2, data_buffer_2, sizeof(data_buffer_2), target_addr, data_size));
TEST_ASSERT_EQUAL(0, memcmp(test_data, data_buffer_1, data_size));
TEST_ASSERT_EQUAL(0, memcmp(test_data, data_buffer_2, data_size));
//write to the blockdev 1
memset((void*)test_data, 'A', data_size);
TEST_ESP_OK(part_blockdev_1->ops->write(part_blockdev_1, test_data, target_addr, data_size));
//write to the blockdev 1
memset((void*)test_data, 'A', data_size);
TEST_ESP_OK(part_blockdev_1->ops->write(part_blockdev_1, test_data, target_addr, data_size));
//read the data written before from the blockdev 1
TEST_ESP_OK(part_blockdev_1->ops->read(part_blockdev_1, data_buffer_1, sizeof(data_buffer_1), target_addr, data_size));
TEST_ASSERT_EQUAL(0, memcmp(test_data, data_buffer_1, data_size));
//read the data written before from the blockdev 1
TEST_ESP_OK(part_blockdev_1->ops->read(part_blockdev_1, data_buffer_1, sizeof(data_buffer_1), target_addr, data_size));
TEST_ASSERT_EQUAL(0, memcmp(test_data, data_buffer_1, data_size));
//write to the blockdev 2
memset((void*)test_data, 'B', data_size);
TEST_ESP_OK(part_blockdev_2->ops->write(part_blockdev_2, test_data, target_addr, data_size));
//write to the blockdev 2
memset((void*)test_data, 'B', data_size);
TEST_ESP_OK(part_blockdev_2->ops->write(part_blockdev_2, test_data, target_addr, data_size));
//read the data written before from the blockdev 2
TEST_ESP_OK(part_blockdev_2->ops->read(part_blockdev_2, data_buffer_2, sizeof(data_buffer_2), target_addr, data_size));
TEST_ASSERT_EQUAL(0, memcmp(test_data, data_buffer_2, data_size));
//read the data written before from the blockdev 2
TEST_ESP_OK(part_blockdev_2->ops->read(part_blockdev_2, data_buffer_2, sizeof(data_buffer_2), target_addr, data_size));
TEST_ASSERT_EQUAL(0, memcmp(test_data, data_buffer_2, data_size));
//release the BDL objects
TEST_ESP_OK(part_blockdev_1->ops->release(part_blockdev_1));
TEST_ESP_OK(part_blockdev_2->ops->release(part_blockdev_2));
}
//release the BDL objects
TEST_ESP_OK(part_blockdev_1->ops->release(part_blockdev_1));
TEST_ESP_OK(part_blockdev_2->ops->release(part_blockdev_2));
}
TEST_GROUP_RUNNER(esp_partition)
{
RUN_TEST_CASE(esp_partition, test_bdl_interface)
RUN_TEST_CASE(esp_partition, test_bdl_interface_external)
RUN_TEST_CASE(esp_partition, test_bdl_two_partitions)
}
TEST(esp_partition, test_bdl_interface_limits)
{
// Limits tested:
// - geometry alignment with parameter size for all ops
// - dst buffer size check when reading
// Partition boundaries and other checks are provided by underlying partition APIs and are not verified here
void app_main(void)
{
UNITY_MAIN(esp_partition);
}
esp_blockdev_handle_t part_blockdev = NULL;
TEST_ESP_OK(esp_partition_get_blockdev(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage1", &part_blockdev));
//artifitial setup setup for this test only
part_blockdev->geometry.erase_size = 512;
part_blockdev->geometry.read_size = 4;
part_blockdev->geometry.write_size = 16;
const size_t data_size = part_blockdev->geometry.erase_size;
uint8_t test_data[data_size];
uint8_t test_data_err[data_size-3];
const off_t target_addr_err = 3;
//correct addr, wrong length
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_SIZE, part_blockdev->ops->erase(part_blockdev, 0, data_size+3));
//wrong addr, correct length
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_SIZE, part_blockdev->ops->erase(part_blockdev, target_addr_err, part_blockdev->geometry.erase_size));
//correct addr, correct dst buff, wrong length
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_SIZE, part_blockdev->ops->read(part_blockdev, test_data, data_size, 0, data_size+3));
//wrong addr, correct dst buff, correct length
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_SIZE, part_blockdev->ops->read(part_blockdev, test_data, data_size, target_addr_err, data_size));
//correct addr, wrong dst buff, correct length
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, part_blockdev->ops->read(part_blockdev, test_data_err, sizeof(test_data_err), 0, data_size));
//correct addr, wrong length
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_SIZE, part_blockdev->ops->write(part_blockdev, test_data, 0, data_size+3));
//wrong addr, correct length
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_SIZE, part_blockdev->ops->write(part_blockdev, test_data, target_addr_err, data_size));
//release the BDL objects
TEST_ESP_OK(part_blockdev->ops->release(part_blockdev));
}
TEST(esp_partition, test_bdl_interface_readonly)
{
//storage3 is readonly partition
esp_blockdev_handle_t part_blockdev = NULL;
TEST_ESP_OK(esp_partition_get_blockdev(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage3", &part_blockdev));
//test flags
TEST_ASSERT_EQUAL(1, part_blockdev->device_flags.read_only);
TEST_ASSERT_EQUAL(0, part_blockdev->geometry.write_size);
TEST_ASSERT_EQUAL(0, part_blockdev->geometry.erase_size);
TEST_ASSERT_EQUAL(0, part_blockdev->geometry.recommended_write_size);
TEST_ASSERT_EQUAL(0, part_blockdev->geometry.recommended_erase_size);
uint8_t dummy_test_buff[1024];
//write & erase must fail and read must work normally
TEST_ASSERT_EQUAL(ESP_ERR_NOT_SUPPORTED, part_blockdev->ops->erase(part_blockdev, 0, sizeof(dummy_test_buff)));
TEST_ASSERT_EQUAL(ESP_ERR_NOT_SUPPORTED, part_blockdev->ops->write(part_blockdev, dummy_test_buff, 0, sizeof(dummy_test_buff)));
TEST_ESP_OK(part_blockdev->ops->read(part_blockdev, dummy_test_buff, sizeof(dummy_test_buff), 0, sizeof(dummy_test_buff)));
TEST_ESP_OK(part_blockdev->ops->release(part_blockdev));
}
TEST_GROUP_RUNNER(esp_partition)
{
RUN_TEST_CASE(esp_partition, test_bdl_interface)
RUN_TEST_CASE(esp_partition, test_bdl_interface_external)
RUN_TEST_CASE(esp_partition, test_bdl_two_partitions)
RUN_TEST_CASE(esp_partition, test_bdl_interface_limits)
RUN_TEST_CASE(esp_partition, test_bdl_interface_readonly)
}
void app_main(void)
{
UNITY_MAIN(esp_partition);
}
@@ -3,5 +3,6 @@
nvs, data, nvs, 0x9000, 0x6000,
phy_init, data, phy, 0xf000, 0x1000,
factory, app, factory, 0x10000, 1M,
storage1, data, , 0x110000, 512K
storage2, data, , 0x190000, 256K,
storage1, data, , 0x110000, 512K,
storage2, data, , 0x190000, 128K,
storage3, data, , 0x1B0000, 128K, readonly
1 # Name, Type, SubType, Offset, Size, Flags
3 nvs, data, nvs, 0x9000, 0x6000,
4 phy_init, data, phy, 0xf000, 0x1000,
5 factory, app, factory, 0x10000, 1M,
6 storage1, data, , 0x110000, 512K storage1, data, , 0x110000, 512K,
7 storage2, data, , 0x190000, 256K, storage2, data, , 0x190000, 128K,
8 storage3, data, , 0x1B0000, 128K, readonly