Browse Source

Merge branch 'bugfix/select_boot_app' into 'master'

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

Closes IDFGH-5282

See merge request espressif/esp-idf!13953
Konstantin Kondrashov 4 years ago
parent
commit
c480afa70a

+ 18 - 3
components/partition_table/gen_esp32part.py

@@ -73,6 +73,7 @@ SUBTYPES = {
         'coredump': 0x03,
         'coredump': 0x03,
         'nvs_keys': 0x04,
         'nvs_keys': 0x04,
         'efuse': 0x05,
         'efuse': 0x05,
+        'undefined': 0x06,
         'esphttpd': 0x80,
         'esphttpd': 0x80,
         'fat': 0x81,
         'fat': 0x81,
         'spiffs': 0x82,
         'spiffs': 0x82,
@@ -143,8 +144,8 @@ class PartitionTable(list):
                 continue
                 continue
             try:
             try:
                 res.append(PartitionDefinition.from_csv(line, line_no + 1))
                 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:
             except Exception:
                 critical('Unexpected error parsing CSV line %d: %s' % (line_no + 1, line))
                 critical('Unexpected error parsing CSV line %d: %s' % (line_no + 1, line))
                 raise
                 raise
@@ -225,6 +226,18 @@ class PartitionTable(list):
                 raise InputError('Partition at 0x%x overlaps 0x%x-0x%x' % (p.offset, last.offset, last.offset + last.size - 1))
                 raise InputError('Partition at 0x%x overlaps 0x%x-0x%x' % (p.offset, last.offset, last.offset + last.size - 1))
             last = p
             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):
     def flash_size(self):
         """ Return the size that partitions will occupy in flash
         """ Return the size that partitions will occupy in flash
             (ie the offset the last partition ends at)
             (ie the offset the last partition ends at)
@@ -358,7 +371,9 @@ class PartitionDefinition(object):
 
 
     def parse_subtype(self, strval):
     def parse_subtype(self, strval):
         if strval == '':
         if strval == '':
-            return 0  # default
+            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, {}))
         return parse_int(strval, SUBTYPES.get(self.type, {}))
 
 
     def parse_address(self, strval):
     def parse_address(self, strval):

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

@@ -88,7 +88,7 @@ myota_0, 0, 0x10,, 0x100000
 myota_1, 0, 0x11,, 0x100000
 myota_1, 0, 0x11,, 0x100000
 myota_15, 0, 0x1f,, 0x100000
 myota_15, 0, 0x1f,, 0x100000
 mytest, 0, 0x20,, 0x100000
 mytest, 0, 0x20,, 0x100000
-myota_status, 1, 0,, 0x100000
+myota_status, 1, 0,, 0x2000
         """
         """
         csv_nomagicnumbers = """
         csv_nomagicnumbers = """
 # Name, Type, SubType, Offset, Size
 # Name, Type, SubType, Offset, Size
@@ -97,7 +97,7 @@ myota_0, app, ota_0,, 0x100000
 myota_1, app, ota_1,, 0x100000
 myota_1, app, ota_1,, 0x100000
 myota_15, app, ota_15,, 0x100000
 myota_15, app, ota_15,, 0x100000
 mytest, app, test,, 0x100000
 mytest, app, test,, 0x100000
-myota_status, data, ota,, 0x100000
+myota_status, data, ota,, 0x2000
 """
 """
         # make two equivalent partition tables, one using
         # make two equivalent partition tables, one using
         # magic numbers and one using shortcuts. Ensure they match
         # magic numbers and one using shortcuts. Ensure they match
@@ -219,6 +219,30 @@ first, app, factory,, 1M, encrypted
         tr = gen_esp32part.PartitionTable.from_binary(tb)
         tr = gen_esp32part.PartitionTable.from_binary(tb)
         self.assertTrue(tr[0].encrypted)
         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):
 class BinaryParserTests(Py23TestCase):
     def test_parse_one_entry(self):
     def test_parse_one_entry(self):
@@ -372,6 +396,46 @@ app,app, factory, 32K, 1M
             t = gen_esp32part.PartitionTable.from_csv(csv)
             t = gen_esp32part.PartitionTable.from_csv(csv)
             t.verify()
             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):
     def test_warnings(self):
         try:
         try:
             sys.stderr = io.StringIO()  # capture stderr
             sys.stderr = io.StringIO()  # capture stderr

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

@@ -87,6 +87,7 @@ typedef enum {
     ESP_PARTITION_SUBTYPE_DATA_COREDUMP = 0x03,                               //!< COREDUMP partition
     ESP_PARTITION_SUBTYPE_DATA_COREDUMP = 0x03,                               //!< COREDUMP partition
     ESP_PARTITION_SUBTYPE_DATA_NVS_KEYS = 0x04,                               //!< Partition for NVS keys
     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_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_ESPHTTPD = 0x80,                               //!< ESPHTTPD partition
     ESP_PARTITION_SUBTYPE_DATA_FAT = 0x81,                                    //!< FAT partition
     ESP_PARTITION_SUBTYPE_DATA_FAT = 0x81,                                    //!< FAT partition

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

@@ -51,6 +51,7 @@ typedef enum {
     ESP_PARTITION_SUBTYPE_DATA_COREDUMP = 0x03,                               //!< COREDUMP partition
     ESP_PARTITION_SUBTYPE_DATA_COREDUMP = 0x03,                               //!< COREDUMP partition
     ESP_PARTITION_SUBTYPE_DATA_NVS_KEYS = 0x04,                               //!< Partition for NVS keys
     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_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_ESPHTTPD = 0x80,                               //!< ESPHTTPD partition
     ESP_PARTITION_SUBTYPE_DATA_FAT = 0x81,                                    //!< FAT partition
     ESP_PARTITION_SUBTYPE_DATA_FAT = 0x81,                                    //!< FAT partition