Skip to content

Commit 053fb47

Browse files
committed
Merge branch 'fix/esp_partition_api_with_error_reporting' into 'master'
feat(esp_partition): add error-returning variants for partition find APIs Closes IDFGH-7740 See merge request espressif/esp-idf!42089
2 parents 59f5bb4 + 5b65634 commit 053fb47

File tree

4 files changed

+442
-27
lines changed

4 files changed

+442
-27
lines changed

components/esp_partition/host_test/partition_api_test/main/partition_api_test.c

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,62 @@ TEST(partition_api, test_partition_find_first)
8888
TEST_ASSERT_NOT_NULL(partition_data);
8989
}
9090

91+
TEST(partition_api, test_partition_find_err)
92+
{
93+
esp_partition_iterator_t iter = NULL;
94+
esp_err_t err = esp_partition_find_err(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage", &iter);
95+
TEST_ESP_OK(err);
96+
TEST_ASSERT_NOT_NULL(iter);
97+
98+
const esp_partition_t *part = esp_partition_get(iter);
99+
TEST_ASSERT_NOT_NULL(part);
100+
101+
esp_partition_iterator_release(iter);
102+
103+
// Test error cases
104+
err = esp_partition_find_err(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "nonexistent", &iter);
105+
TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, err);
106+
TEST_ASSERT_NULL(iter); // But iterator should be NULL
107+
108+
// Test invalid argument
109+
err = esp_partition_find_err(ESP_PARTITION_TYPE_ANY, ESP_PARTITION_SUBTYPE_DATA_NVS, NULL, &iter);
110+
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, err);
111+
TEST_ASSERT_NULL(iter); // But iterator should be NULL
112+
113+
// Test NULL pointer
114+
err = esp_partition_find_err(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage", NULL);
115+
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, err);
116+
TEST_ASSERT_NULL(iter); // But iterator should be NULL
117+
}
118+
119+
TEST(partition_api, test_partition_find_first_err)
120+
{
121+
const esp_partition_t *partition_app = NULL;
122+
esp_err_t err = esp_partition_find_first_err(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_ANY, NULL, &partition_app);
123+
TEST_ESP_OK(err);
124+
TEST_ASSERT_NOT_NULL(partition_app);
125+
126+
const esp_partition_t *partition_data = NULL;
127+
err = esp_partition_find_first_err(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage", &partition_data);
128+
TEST_ESP_OK(err);
129+
TEST_ASSERT_NOT_NULL(partition_data);
130+
131+
// Test partition not found
132+
const esp_partition_t *partition_nonexistent = NULL;
133+
err = esp_partition_find_first_err(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "nonexistent", &partition_nonexistent);
134+
TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, err);
135+
TEST_ASSERT_NULL(partition_nonexistent); // But partition should be NULL
136+
137+
// Test error cases
138+
err = esp_partition_find_first_err(ESP_PARTITION_TYPE_ANY, ESP_PARTITION_SUBTYPE_DATA_NVS, NULL, &partition_data);
139+
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, err);
140+
TEST_ASSERT_NULL(partition_data); // But partition should be NULL
141+
142+
// Test NULL pointer
143+
err = esp_partition_find_first_err(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage", NULL);
144+
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, err);
145+
}
146+
91147
TEST(partition_api, test_partition_ops)
92148
{
93149
const esp_partition_t *partition_data = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage");
@@ -122,6 +178,59 @@ TEST(partition_api, test_partition_ops)
122178
TEST_ASSERT_NOT_NULL(verified_partition);
123179
}
124180

181+
TEST(partition_api, test_partition_verify_err)
182+
{
183+
// Get a valid partition for testing
184+
const esp_partition_t *partition_data = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage");
185+
TEST_ASSERT_NOT_NULL(partition_data);
186+
187+
const esp_partition_t *verified_partition = NULL;
188+
esp_err_t err;
189+
190+
// Test 1: Valid partition verification
191+
err = esp_partition_verify_err(partition_data, &verified_partition);
192+
TEST_ESP_OK(err);
193+
TEST_ASSERT_EQUAL_PTR(partition_data, verified_partition);
194+
195+
// Test 2: Both parameters NULL
196+
err = esp_partition_verify_err(NULL, NULL);
197+
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, err);
198+
199+
// Test 3: Partition with wrong address should not match
200+
esp_partition_t partition_copy = *partition_data;
201+
partition_copy.address = 0xFFFFFFFF; // Invalid address
202+
verified_partition = NULL;
203+
err = esp_partition_verify_err(&partition_copy, &verified_partition);
204+
TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, err);
205+
TEST_ASSERT_NULL(verified_partition);
206+
207+
// Test 4: Partition with wrong size should not match
208+
partition_copy = *partition_data;
209+
partition_copy.size = 0xFFFFFFFF; // Invalid size
210+
verified_partition = NULL;
211+
err = esp_partition_verify_err(&partition_copy, &verified_partition);
212+
TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, err);
213+
TEST_ASSERT_NULL(verified_partition);
214+
215+
// Test 5: Partition with wrong type should not match
216+
partition_copy = *partition_data;
217+
partition_copy.type = ESP_PARTITION_TYPE_APP; // Wrong type
218+
verified_partition = NULL;
219+
err = esp_partition_verify_err(&partition_copy, &verified_partition);
220+
TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, err);
221+
TEST_ASSERT_NULL(verified_partition);
222+
223+
// Test 6: Test with a partition that has empty label
224+
const esp_partition_t *app_partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_ANY, NULL);
225+
if (app_partition != NULL && strlen(app_partition->label) == 0) {
226+
verified_partition = NULL;
227+
err = esp_partition_verify_err(app_partition, &verified_partition);
228+
TEST_ESP_OK(err);
229+
TEST_ASSERT_NOT_NULL(verified_partition);
230+
TEST_ASSERT_EQUAL_PTR(app_partition, verified_partition);
231+
}
232+
}
233+
125234
TEST(partition_api, test_partition_mmap)
126235
{
127236
const esp_partition_t *partition_data = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage");
@@ -750,8 +859,11 @@ TEST_GROUP_RUNNER(partition_api)
750859
RUN_TEST_CASE(partition_api, test_partition_find_app);
751860
RUN_TEST_CASE(partition_api, test_partition_find_data);
752861
RUN_TEST_CASE(partition_api, test_partition_find_first);
862+
RUN_TEST_CASE(partition_api, test_partition_find_err);
863+
RUN_TEST_CASE(partition_api, test_partition_find_first_err);
753864
RUN_TEST_CASE(partition_api, test_partition_ops);
754865
RUN_TEST_CASE(partition_api, test_partition_mmap);
866+
RUN_TEST_CASE(partition_api, test_partition_verify_err);
755867
RUN_TEST_CASE(partition_api, test_partition_mmap_support_for_greater_than_4M);
756868
RUN_TEST_CASE(partition_api, test_partition_mmap_diff_size);
757869
RUN_TEST_CASE(partition_api, test_partition_mmap_reopen);

components/esp_partition/include/esp_partition.h

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -169,6 +169,35 @@ typedef struct {
169169
*/
170170
esp_partition_iterator_t esp_partition_find(esp_partition_type_t type, esp_partition_subtype_t subtype, const char* label);
171171

172+
/**
173+
* @brief Find partition based on one or more parameters with error reporting
174+
*
175+
* This function provides the same functionality as esp_partition_find() but returns
176+
* error information instead of just NULL on failure. This allows applications
177+
* to distinguish between "no partitions found" and actual error conditions.
178+
*
179+
* @param type Partition type, one of esp_partition_type_t values or an 8-bit unsigned integer.
180+
* To find all partitions, no matter the type, use ESP_PARTITION_TYPE_ANY, and set
181+
* subtype argument to ESP_PARTITION_SUBTYPE_ANY.
182+
* @param subtype Partition subtype, one of esp_partition_subtype_t values or an 8-bit unsigned integer.
183+
* To find all partitions of given type, use ESP_PARTITION_SUBTYPE_ANY.
184+
* @param label (optional) Partition label. Set this value if looking
185+
* for partition with a specific name. Pass NULL otherwise.
186+
* @param[out] it Output iterator which can be used to enumerate all the partitions found. Must not be NULL.
187+
* Set to NULL if no partitions were found or on error.
188+
* If not NULL after successful call, iterator must be released using
189+
* esp_partition_iterator_release when not used any more.
190+
*
191+
* @return
192+
* - ESP_OK: Operation completed successfully
193+
* - ESP_ERR_INVALID_ARG: if param[out] it is NULL, or if type is ESP_PARTITION_TYPE_ANY
194+
* but subtype is not ESP_PARTITION_SUBTYPE_ANY
195+
* - ESP_ERR_NO_MEM: if memory allocation failed
196+
* - ESP_ERR_NOT_FOUND: if no partition were found
197+
* - Other error codes from partition loading functions
198+
*/
199+
esp_err_t esp_partition_find_err(esp_partition_type_t type, esp_partition_subtype_t subtype, const char* label, esp_partition_iterator_t* it);
200+
172201
/**
173202
* @brief Find first partition based on one or more parameters
174203
*
@@ -185,6 +214,34 @@ esp_partition_iterator_t esp_partition_find(esp_partition_type_t type, esp_parti
185214
*/
186215
const esp_partition_t* esp_partition_find_first(esp_partition_type_t type, esp_partition_subtype_t subtype, const char* label);
187216

217+
/**
218+
* @brief Find first partition based on one or more parameters with error reporting
219+
*
220+
* This function provides the same functionality as esp_partition_find_first() but returns
221+
* error information instead of just NULL on failure. This allows applications
222+
* to distinguish between "no partition found" and actual error conditions.
223+
*
224+
* @param type Partition type, one of esp_partition_type_t values or an 8-bit unsigned integer.
225+
* To find all partitions, no matter the type, use ESP_PARTITION_TYPE_ANY, and set
226+
* subtype argument to ESP_PARTITION_SUBTYPE_ANY.
227+
* @param subtype Partition subtype, one of esp_partition_subtype_t values or an 8-bit unsigned integer
228+
* To find all partitions of given type, use ESP_PARTITION_SUBTYPE_ANY.
229+
* @param label (optional) Partition label. Set this value if looking
230+
* for partition with a specific name. Pass NULL otherwise.
231+
* @param[out] partition Output pointer to esp_partition_t structure. Must not be NULL.
232+
* Set to NULL if no partition is found or on error.
233+
* If not NULL after successful call, this pointer is valid for the lifetime of the application.
234+
*
235+
* @return
236+
* - ESP_OK: Operation completed successfully (regardless of whether partition was found)
237+
* - ESP_ERR_INVALID_ARG: if param[out] partition is NULL, or if type is ESP_PARTITION_TYPE_ANY
238+
* but subtype is not ESP_PARTITION_SUBTYPE_ANY
239+
* - ESP_ERR_NO_MEM: if memory allocation failed
240+
* - ESP_ERR_NOT_FOUND: if no partition were found
241+
* - Other error codes from partition loading functions
242+
*/
243+
esp_err_t esp_partition_find_first_err(esp_partition_type_t type, esp_partition_subtype_t subtype, const char* label, const esp_partition_t** partition);
244+
188245
/**
189246
* @brief Get esp_partition_t structure for given partition
190247
*
@@ -236,6 +293,45 @@ void esp_partition_iterator_release(esp_partition_iterator_t iterator);
236293
*/
237294
const esp_partition_t* esp_partition_verify(const esp_partition_t* partition);
238295

296+
/**
297+
* @brief Verify partition data with error reporting
298+
*
299+
* This function provides the same functionality as esp_partition_verify() but returns
300+
* error information instead of just NULL on failure. This allows applications
301+
* to distinguish between "partition not found" and actual error conditions
302+
*
303+
* Given a pointer to partition data, verify this partition exists in the partition table
304+
* by comparing all key fields (flash_chip, address, size, encrypted status). The function
305+
* searches through all registered partitions with matching type, subtype, and label.
306+
*
307+
* This function is useful to:
308+
* - Take partition data from RAM buffer and convert to permanent flash-based pointer
309+
* - Validate partition structures obtained from external sources
310+
* - Ensure partition data integrity before performing operations
311+
*
312+
* @param partition Pointer to partition data to verify. Must be non-NULL.
313+
* The following fields are used for verification:
314+
* - type: Partition type
315+
* - subtype: Partition subtype
316+
* - label: Partition label (if non-empty)
317+
* - flash_chip: Flash chip pointer
318+
* - address: Starting address
319+
* - size: Partition size
320+
* - encrypted: Encryption status
321+
* @param[out] out_partition Output pointer to verified esp_partition_t structure. Must not be NULL.
322+
* Set to NULL if partition is not found or on error.
323+
* If not NULL after successful call, this pointer is valid for the
324+
* lifetime of the application and points to the permanent partition
325+
* structure in flash.
326+
*
327+
* @return
328+
* - ESP_OK: Partition verified successfully and found in partition table
329+
* - ESP_ERR_INVALID_ARG: if partition or out_partition is NULL
330+
* - ESP_ERR_NO_MEM: if memory allocation failed during partition search
331+
* - ESP_ERR_NOT_FOUND: if no matching partition found in partition table
332+
*/
333+
esp_err_t esp_partition_verify_err(const esp_partition_t* partition, const esp_partition_t** out_partition);
334+
239335
/**
240336
* @brief Read data from the partition
241337
*

0 commit comments

Comments
 (0)