소스 검색

partition_table: Fix case when a few similar to otadata partitions in the table

It was when in the partition table there is a partition with type="data" and suptype=""(empty),
in this case type=1, suptype=0. It is similar to otadata partition.

This commit fixes it, now it will handle it as type=1, suptype=6 (ESP_PARTITION_SUBTYPE_DATA_UNDEFINED).
KonstantinKondrashov 4 년 전
부모
커밋
fc0f90e8aa

+ 28 - 13
components/partition_table/gen_esp32part.py

@@ -55,15 +55,16 @@ SUBTYPES = {
         "test": 0x20,
     },
     DATA_TYPE: {
-        "ota": 0x00,
-        "phy": 0x01,
-        "nvs": 0x02,
-        "coredump": 0x03,
-        "nvs_keys": 0x04,
-        "efuse": 0x05,
-        "esphttpd": 0x80,
-        "fat": 0x81,
-        "spiffs": 0x82,
+        'ota': 0x00,
+        'phy': 0x01,
+        'nvs': 0x02,
+        'coredump': 0x03,
+        'nvs_keys': 0x04,
+        'efuse': 0x05,
+        'undefined': 0x06,
+        'esphttpd': 0x80,
+        'fat': 0x81,
+        'spiffs': 0x82,
     },
 }
 
@@ -107,8 +108,8 @@ class PartitionTable(list):
                 continue
             try:
                 res.append(PartitionDefinition.from_csv(line, line_no + 1))
-            except InputError as e:
-                raise InputError("Error at line %d: %s" % (line_no + 1, e))
+            except InputError as err:
+                raise InputError('Error at line %d: %s' % (line_no + 1, err))
             except Exception:
                 critical("Unexpected error parsing CSV line %d: %s" % (line_no + 1, line))
                 raise
@@ -201,6 +202,18 @@ class PartitionTable(list):
                 raise InputError("Partition at 0x%x overlaps 0x%x-0x%x" % (p.offset, last.offset, last.offset + last.size - 1))
             last = p
 
+        # check that otadata should be unique
+        otadata_duplicates = [p for p in self if p.type == TYPES['data'] and p.subtype == SUBTYPES[DATA_TYPE]['ota']]
+        if len(otadata_duplicates) > 1:
+            for p in otadata_duplicates:
+                print(p.name, p.type, p.subtype)
+            raise InputError('Found multiple otadata partitions. Only one partition can be defined with type="data"(1) and subtype="ota"(0).')
+
+        if len(otadata_duplicates) == 1 and otadata_duplicates[0].size != 0x2000:
+            p = otadata_duplicates[0]
+            print(p.name, p.type, p.subtype, p.offset, p.size)
+            raise InputError('otadata partition must have size = 0x2000')
+
     def flash_size(self):
         """ Return the size that partitions will occupy in flash
             (ie the offset the last partition ends at)
@@ -333,8 +346,10 @@ class PartitionDefinition(object):
         return parse_int(strval, TYPES)
 
     def parse_subtype(self, strval):
-        if strval == "":
-            return 0  # default
+        if strval == '':
+            if self.type == TYPES['app']:
+                raise InputError('App partition cannot have an empty subtype')
+            return SUBTYPES[DATA_TYPE]['undefined']
         return parse_int(strval, SUBTYPES.get(self.type, {}))
 
     def parse_address(self, strval):

+ 66 - 2
components/partition_table/test_gen_esp32part_host/gen_esp32part_tests.py

@@ -98,7 +98,7 @@ myota_0, 0, 0x10,, 0x100000
 myota_1, 0, 0x11,, 0x100000
 myota_15, 0, 0x1f,, 0x100000
 mytest, 0, 0x20,, 0x100000
-myota_status, 1, 0,, 0x100000
+myota_status, 1, 0,, 0x2000
         """
         csv_nomagicnumbers = """
 # Name, Type, SubType, Offset, Size
@@ -107,7 +107,7 @@ myota_0, app, ota_0,, 0x100000
 myota_1, app, ota_1,, 0x100000
 myota_15, app, ota_15,, 0x100000
 mytest, app, test,, 0x100000
-myota_status, data, ota,, 0x100000
+myota_status, data, ota,, 0x2000
 """
         # make two equivalent partition tables, one using
         # magic numbers and one using shortcuts. Ensure they match
@@ -229,6 +229,30 @@ first, app, factory,, 1M, encrypted
         tr = gen_esp32part.PartitionTable.from_binary(tb)
         self.assertTrue(tr[0].encrypted)
 
+    def test_only_empty_subtype_is_not_0(self):
+        csv_txt = """
+# Name,Type, SubType,Offset,Size
+nvs,            data,    nvs,          , 0x4000,
+otadata,        data,    ota,          , 0x2000,
+phy_init,       data,    phy,          , 0x1000,
+factory,        app, factory,          , 1M
+ota_0,             0,  ota_0,          , 1M,
+ota_1,             0,  ota_1,          , 1M,
+storage,        data,       ,          , 512k,
+storage2,       data, undefined,       , 12k,
+"""
+        t = gen_esp32part.PartitionTable.from_csv(csv_txt)
+        t.verify()
+        self.assertEqual(t[1].name,   'otadata')
+        self.assertEqual(t[1].type,    1)
+        self.assertEqual(t[1].subtype, 0)
+        self.assertEqual(t[6].name,   'storage')
+        self.assertEqual(t[6].type,    1)
+        self.assertEqual(t[6].subtype, 0x06)
+        self.assertEqual(t[7].name,   'storage2')
+        self.assertEqual(t[7].type,    1)
+        self.assertEqual(t[7].subtype, 0x06)
+
 
 class BinaryParserTests(Py23TestCase):
     def test_parse_one_entry(self):
@@ -382,6 +406,46 @@ app,app, factory, 32K, 1M
             t = gen_esp32part.PartitionTable.from_csv(csv)
             t.verify()
 
+    def test_only_one_otadata(self):
+        csv_txt = """
+# Name,Type, SubType,Offset,Size
+nvs,            data,    nvs,          , 0x4000,
+otadata,        data,    ota,          , 0x2000,
+otadata2,       data,    ota,          , 0x2000,
+factory,        app, factory,          , 1M
+ota_0,             0,  ota_0,          , 1M,
+ota_1,             0,  ota_1,          , 1M,
+"""
+        with self.assertRaisesRegex(gen_esp32part.InputError, r'Found multiple otadata partitions'):
+            t = gen_esp32part.PartitionTable.from_csv(csv_txt)
+            t.verify()
+
+    def test_otadata_must_have_fixed_size(self):
+        csv_txt = """
+# Name,Type, SubType,Offset,Size
+nvs,            data,    nvs,          , 0x4000,
+otadata,        data,    ota,          , 0x3000,
+factory,        app, factory,          , 1M
+ota_0,             0,  ota_0,          , 1M,
+ota_1,             0,  ota_1,          , 1M,
+"""
+        with self.assertRaisesRegex(gen_esp32part.InputError, r'otadata partition must have size = 0x2000'):
+            t = gen_esp32part.PartitionTable.from_csv(csv_txt)
+            t.verify()
+
+    def test_app_cannot_have_empty_subtype(self):
+        csv_txt = """
+# Name,Type, SubType,Offset,Size
+nvs,            data,    nvs,          , 0x4000,
+otadata,        data,    ota,          , 0x2000,
+factory,        app,        ,          , 1M
+ota_0,             0,  ota_0,          , 1M,
+ota_1,             0,  ota_1,          , 1M,
+"""
+        with self.assertRaisesRegex(gen_esp32part.InputError, r'App partition cannot have an empty subtype'):
+            t = gen_esp32part.PartitionTable.from_csv(csv_txt)
+            t.verify()
+
     def test_warnings(self):
         try:
             sys.stderr = io.StringIO()  # capture stderr

+ 1 - 0
components/spi_flash/include/esp_partition.h

@@ -85,6 +85,7 @@ typedef enum {
     ESP_PARTITION_SUBTYPE_DATA_COREDUMP = 0x03,                               //!< COREDUMP partition
     ESP_PARTITION_SUBTYPE_DATA_NVS_KEYS = 0x04,                               //!< Partition for NVS keys
     ESP_PARTITION_SUBTYPE_DATA_EFUSE_EM = 0x05,                               //!< Partition for emulate eFuse bits
+    ESP_PARTITION_SUBTYPE_DATA_UNDEFINED = 0x06,                              //!< Undefined (or unspecified) data partition
 
     ESP_PARTITION_SUBTYPE_DATA_ESPHTTPD = 0x80,                               //!< ESPHTTPD partition
     ESP_PARTITION_SUBTYPE_DATA_FAT = 0x81,                                    //!< FAT partition

+ 96 - 0
components/spi_flash/sim/stubs/spi_flash/esp_partition.h

@@ -0,0 +1,96 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef __ESP_PARTITION_H__
+#define __ESP_PARTITION_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include "esp_err.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+    ESP_PARTITION_TYPE_APP = 0x00,       //!< Application partition type
+    ESP_PARTITION_TYPE_DATA = 0x01,      //!< Data partition type
+} esp_partition_type_t;
+
+typedef enum {
+    ESP_PARTITION_SUBTYPE_APP_FACTORY = 0x00,                                 //!< Factory application partition
+    ESP_PARTITION_SUBTYPE_APP_OTA_MIN = 0x10,                                 //!< Base for OTA partition subtypes
+    ESP_PARTITION_SUBTYPE_APP_OTA_0 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 0,  //!< OTA partition 0
+    ESP_PARTITION_SUBTYPE_APP_OTA_1 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 1,  //!< OTA partition 1
+    ESP_PARTITION_SUBTYPE_APP_OTA_2 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 2,  //!< OTA partition 2
+    ESP_PARTITION_SUBTYPE_APP_OTA_3 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 3,  //!< OTA partition 3
+    ESP_PARTITION_SUBTYPE_APP_OTA_4 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 4,  //!< OTA partition 4
+    ESP_PARTITION_SUBTYPE_APP_OTA_5 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 5,  //!< OTA partition 5
+    ESP_PARTITION_SUBTYPE_APP_OTA_6 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 6,  //!< OTA partition 6
+    ESP_PARTITION_SUBTYPE_APP_OTA_7 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 7,  //!< OTA partition 7
+    ESP_PARTITION_SUBTYPE_APP_OTA_8 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 8,  //!< OTA partition 8
+    ESP_PARTITION_SUBTYPE_APP_OTA_9 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 9,  //!< OTA partition 9
+    ESP_PARTITION_SUBTYPE_APP_OTA_10 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 10,//!< OTA partition 10
+    ESP_PARTITION_SUBTYPE_APP_OTA_11 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 11,//!< OTA partition 11
+    ESP_PARTITION_SUBTYPE_APP_OTA_12 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 12,//!< OTA partition 12
+    ESP_PARTITION_SUBTYPE_APP_OTA_13 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 13,//!< OTA partition 13
+    ESP_PARTITION_SUBTYPE_APP_OTA_14 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 14,//!< OTA partition 14
+    ESP_PARTITION_SUBTYPE_APP_OTA_15 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 15,//!< OTA partition 15
+    ESP_PARTITION_SUBTYPE_APP_OTA_MAX = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 16,//!< Max subtype of OTA partition
+    ESP_PARTITION_SUBTYPE_APP_TEST = 0x20,                                    //!< Test application partition
+
+    ESP_PARTITION_SUBTYPE_DATA_OTA = 0x00,                                    //!< OTA selection partition
+    ESP_PARTITION_SUBTYPE_DATA_PHY = 0x01,                                    //!< PHY init data partition
+    ESP_PARTITION_SUBTYPE_DATA_NVS = 0x02,                                    //!< NVS partition
+    ESP_PARTITION_SUBTYPE_DATA_COREDUMP = 0x03,                               //!< COREDUMP partition
+    ESP_PARTITION_SUBTYPE_DATA_NVS_KEYS = 0x04,                               //!< Partition for NVS keys
+    ESP_PARTITION_SUBTYPE_DATA_EFUSE_EM = 0x05,                               //!< Partition for emulate eFuse bits
+    ESP_PARTITION_SUBTYPE_DATA_UNDEFINED = 0x06,                              //!< Undefined (or unspecified) data partition
+
+    ESP_PARTITION_SUBTYPE_DATA_ESPHTTPD = 0x80,                               //!< ESPHTTPD partition
+    ESP_PARTITION_SUBTYPE_DATA_FAT = 0x81,                                    //!< FAT partition
+    ESP_PARTITION_SUBTYPE_DATA_SPIFFS = 0x82,                                 //!< SPIFFS partition
+
+    ESP_PARTITION_SUBTYPE_ANY = 0xff,                                         //!< Used to search for partitions with any subtype
+} esp_partition_subtype_t;
+
+/**
+ * @brief Opaque partition iterator type
+ */
+typedef struct esp_partition_iterator_opaque_* esp_partition_iterator_t;
+
+/**
+ * @brief partition information structure
+ *
+ * This is not the format in flash, that format is esp_partition_info_t.
+ *
+ * However, this is the format used by this API.
+ */
+typedef struct {
+    void* flash_chip;            /*!< SPI flash chip on which the partition resides */
+    esp_partition_type_t type;          /*!< partition type (app/data) */
+    esp_partition_subtype_t subtype;    /*!< partition subtype */
+    uint32_t address;                   /*!< starting address of the partition in flash */
+    uint32_t size;                      /*!< size of the partition, in bytes */
+    char label[17];                     /*!< partition label, zero-terminated ASCII string */
+    bool encrypted;                     /*!< flag is set to true if partition is encrypted */
+} esp_partition_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __ESP_PARTITION_H__ */