Merge branch 'bugfix/bootloader_ota_sel' into 'master'
Fix bootloader OTA regression See merge request !1205
This commit is contained in:
commit
11a87ca811
|
@ -413,6 +413,34 @@ esp_err_t esp_ota_set_boot_partition(const esp_partition_t *partition)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const esp_partition_t *find_default_boot_partition(void)
|
||||||
|
{
|
||||||
|
// This logic matches the logic of bootloader get_selected_boot_partition() & load_boot_image().
|
||||||
|
|
||||||
|
// Default to factory if present
|
||||||
|
const esp_partition_t *result = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL);
|
||||||
|
if (result != NULL) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try first OTA slot if no factory partition
|
||||||
|
for (esp_partition_subtype_t s = ESP_PARTITION_SUBTYPE_APP_OTA_MIN; s != ESP_PARTITION_SUBTYPE_APP_OTA_MAX; s++) {
|
||||||
|
result = esp_partition_find_first(ESP_PARTITION_TYPE_APP, s, NULL);
|
||||||
|
if (result != NULL) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test app slot if present
|
||||||
|
result = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_TEST, NULL);
|
||||||
|
if (result != NULL) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGE(TAG, "invalid partition table, no app partitions");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
const esp_partition_t *esp_ota_get_boot_partition(void)
|
const esp_partition_t *esp_ota_get_boot_partition(void)
|
||||||
{
|
{
|
||||||
esp_err_t ret;
|
esp_err_t ret;
|
||||||
|
@ -443,8 +471,7 @@ const esp_partition_t *esp_ota_get_boot_partition(void)
|
||||||
|
|
||||||
if (s_ota_select[0].ota_seq == 0xFFFFFFFF && s_ota_select[1].ota_seq == 0xFFFFFFFF) {
|
if (s_ota_select[0].ota_seq == 0xFFFFFFFF && s_ota_select[1].ota_seq == 0xFFFFFFFF) {
|
||||||
ESP_LOGD(TAG, "finding factory app......");
|
ESP_LOGD(TAG, "finding factory app......");
|
||||||
|
return find_default_boot_partition();
|
||||||
return esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL);
|
|
||||||
} else if (ota_select_valid(&s_ota_select[0]) && ota_select_valid(&s_ota_select[1])) {
|
} else if (ota_select_valid(&s_ota_select[0]) && ota_select_valid(&s_ota_select[1])) {
|
||||||
ESP_LOGD(TAG, "finding ota_%d app......", \
|
ESP_LOGD(TAG, "finding ota_%d app......", \
|
||||||
ESP_PARTITION_SUBTYPE_APP_OTA_MIN + ((OTA_MAX(s_ota_select[0].ota_seq, s_ota_select[1].ota_seq) - 1) % ota_app_count));
|
ESP_PARTITION_SUBTYPE_APP_OTA_MIN + ((OTA_MAX(s_ota_select[0].ota_seq, s_ota_select[1].ota_seq) - 1) % ota_app_count));
|
||||||
|
@ -467,7 +494,7 @@ const esp_partition_t *esp_ota_get_boot_partition(void)
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGE(TAG, "ota data invalid, no current app. Assuming factory");
|
ESP_LOGE(TAG, "ota data invalid, no current app. Assuming factory");
|
||||||
return esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL);
|
return find_default_boot_partition();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -126,13 +126,17 @@ esp_err_t esp_ota_set_boot_partition(const esp_partition_t* partition);
|
||||||
*
|
*
|
||||||
* If esp_ota_set_boot_partition() has been called, the partition which was set by that function will be returned.
|
* If esp_ota_set_boot_partition() has been called, the partition which was set by that function will be returned.
|
||||||
*
|
*
|
||||||
* If esp_ota_set_boot_partition() has not been called, the result is
|
* If esp_ota_set_boot_partition() has not been called, the result is usually the same as esp_ota_get_running_partition().
|
||||||
* equivalent to esp_ota_get_running_partition().
|
* The two results are not equal if the configured boot partition does not contain a valid app (meaning that the running partition
|
||||||
|
* will be an app that the bootloader chose via fallback).
|
||||||
|
*
|
||||||
|
* If the OTA data partition is not present or not valid then the result is the first app partition found in the
|
||||||
|
* partition table. In priority order, this means: the factory app, the first OTA app slot, or the test app partition.
|
||||||
*
|
*
|
||||||
* Note that there is no guarantee the returned partition is a valid app. Use esp_image_load(ESP_IMAGE_VERIFY, ...) to verify if the
|
* Note that there is no guarantee the returned partition is a valid app. Use esp_image_load(ESP_IMAGE_VERIFY, ...) to verify if the
|
||||||
* partition contains a bootable image.
|
* returned partition contains a bootable image.
|
||||||
*
|
*
|
||||||
* @return Pointer to info for partition structure, or NULL if no partition is found or flash read operation failed. Returned pointer is valid for the lifetime of the application.
|
* @return Pointer to info for partition structure, or NULL if partition table is invalid or a flash read operation failed. Any returned pointer is valid for the lifetime of the application.
|
||||||
*/
|
*/
|
||||||
const esp_partition_t* esp_ota_get_boot_partition(void);
|
const esp_partition_t* esp_ota_get_boot_partition(void);
|
||||||
|
|
||||||
|
|
|
@ -289,7 +289,8 @@ static void log_invalid_app_partition(int index)
|
||||||
|
|
||||||
/* Return the index of the selected boot partition.
|
/* Return the index of the selected boot partition.
|
||||||
|
|
||||||
This is the preferred boot partition, as determined by the partition table & OTA data.
|
This is the preferred boot partition, as determined by the partition table &
|
||||||
|
any OTA sequence number found in OTA data.
|
||||||
|
|
||||||
This partition will only be booted if it contains a valid app image, otherwise load_boot_image() will search
|
This partition will only be booted if it contains a valid app image, otherwise load_boot_image() will search
|
||||||
for a valid partition using this selection as the starting point.
|
for a valid partition using this selection as the starting point.
|
||||||
|
@ -327,15 +328,27 @@ static int get_selected_boot_partition(const bootloader_state_t *bs)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
bool ota_valid = false;
|
||||||
|
const char *ota_msg;
|
||||||
|
int ota_seq; // Raw OTA sequence number. May be more than # of OTA slots
|
||||||
if(ota_select_valid(&sa) && ota_select_valid(&sb)) {
|
if(ota_select_valid(&sa) && ota_select_valid(&sb)) {
|
||||||
ESP_LOGD(TAG, "Both OTA sequence valid, using OTA slot %d", MAX(sa.ota_seq, sb.ota_seq)-1);
|
ota_valid = true;
|
||||||
return MAX(sa.ota_seq, sb.ota_seq) - 1;
|
ota_msg = "Both OTA values";
|
||||||
|
ota_seq = MAX(sa.ota_seq, sb.ota_seq) - 1;
|
||||||
} else if(ota_select_valid(&sa)) {
|
} else if(ota_select_valid(&sa)) {
|
||||||
ESP_LOGD(TAG, "Only OTA sequence A is valid, using OTA slot %d", sa.ota_seq - 1);
|
ota_valid = true;
|
||||||
return sa.ota_seq - 1;
|
ota_msg = "Only OTA sequence A is";
|
||||||
|
ota_seq = sa.ota_seq - 1;
|
||||||
} else if(ota_select_valid(&sb)) {
|
} else if(ota_select_valid(&sb)) {
|
||||||
ESP_LOGD(TAG, "Only OTA sequence B is valid, using OTA slot %d", sb.ota_seq - 1);
|
ota_valid = true;
|
||||||
return sb.ota_seq - 1;
|
ota_msg = "Only OTA sequence B is";
|
||||||
|
ota_seq = sb.ota_seq - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ota_valid) {
|
||||||
|
int ota_slot = ota_seq % bs->app_count; // Actual OTA partition selection
|
||||||
|
ESP_LOGD(TAG, "%s valid. Mapping seq %d -> OTA slot %d", ota_msg, ota_seq, ota_slot);
|
||||||
|
return ota_slot;
|
||||||
} else if (bs->factory.offset != 0) {
|
} else if (bs->factory.offset != 0) {
|
||||||
ESP_LOGE(TAG, "ota data partition invalid, falling back to factory");
|
ESP_LOGE(TAG, "ota data partition invalid, falling back to factory");
|
||||||
return FACTORY_INDEX;
|
return FACTORY_INDEX;
|
||||||
|
|
Loading…
Reference in a new issue