Răsfoiți Sursa

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 ani în urmă
părinte
comite
fc0f90e8aa

+ 28 - 13
components/partition_table/gen_esp32part.py

@@ -55,15 +55,16 @@ SUBTYPES = {
         "test": 0x20,
         "test": 0x20,
     },
     },
     DATA_TYPE: {
     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
                 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
@@ -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))
                 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)
@@ -333,8 +346,10 @@ class PartitionDefinition(object):
         return parse_int(strval, TYPES)
         return parse_int(strval, TYPES)
 
 
     def parse_subtype(self, strval):
     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, {}))
         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

@@ -98,7 +98,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
@@ -107,7 +107,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
@@ -229,6 +229,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):
@@ -382,6 +406,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

@@ -85,6 +85,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

+ 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__ */