]> granicus.if.org Git - esp-idf/commitdiff
ota_ops: Fix get_selected_boot_partition() in case there is no factory partition
authorAngus Gratton <angus@espressif.com>
Mon, 4 Sep 2017 07:05:16 +0000 (17:05 +1000)
committerAngus Gratton <gus@projectgus.com>
Mon, 4 Sep 2017 07:37:28 +0000 (17:37 +1000)
get_selected_boot_partition() now follows the same basic logic as the bootloader to find the
default boot partition.

components/app_update/esp_ota_ops.c
components/app_update/include/esp_ota_ops.h

index 534fbb110a509d40571bc4f1086f61e69c9d02d5..ceb6a705261cca6a1fa7da3cec74eabb4a5c8a6d 100644 (file)
@@ -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)
 {
     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) {
         ESP_LOGD(TAG, "finding factory app......");
-
-        return esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL);
+        return find_default_boot_partition();
     } else if (ota_select_valid(&s_ota_select[0]) && ota_select_valid(&s_ota_select[1])) {
         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));
@@ -467,7 +494,7 @@ const esp_partition_t *esp_ota_get_boot_partition(void)
 
     } else {
         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();
     }
 }
 
index 9bc8798e477bbc54aed256bada2b1def78d454b5..a089a92be0519a6d3d8cdff68640e22bb4257848 100755 (executable)
@@ -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 not been called, the result is
- * equivalent to esp_ota_get_running_partition().
+ * If esp_ota_set_boot_partition() has not been called, the result is usually the same as 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
- * 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);