mirror of
https://github.com/espressif/esp-idf
synced 2025-03-09 09:09:10 -04:00
feat(partition_table): Support recovery bootloader subtype
This commit is contained in:
parent
1689c7e14f
commit
52f14f344d
@ -32,6 +32,7 @@ extern "C" {
|
||||
#define PART_TYPE_BOOTLOADER 0x02
|
||||
#define PART_SUBTYPE_BOOTLOADER_PRIMARY 0x00
|
||||
#define PART_SUBTYPE_BOOTLOADER_OTA 0x01
|
||||
#define PART_SUBTYPE_BOOTLOADER_RECOVERY 0x02
|
||||
|
||||
#define PART_TYPE_PARTITION_TABLE 0x03
|
||||
#define PART_SUBTYPE_PARTITION_TABLE_PRIMARY 0x00
|
||||
|
@ -208,6 +208,9 @@ bool bootloader_utility_load_partition_table(bootloader_state_t *bs)
|
||||
case PART_SUBTYPE_BOOTLOADER_OTA:
|
||||
partition_usage = "ota bootloader";
|
||||
break;
|
||||
case PART_SUBTYPE_BOOTLOADER_RECOVERY:
|
||||
partition_usage = "recovery bootloader";
|
||||
break;
|
||||
}
|
||||
break; /* PART_TYPE_BOOTLOADER */
|
||||
case PART_TYPE_PARTITION_TABLE: /* Partition table partition */
|
||||
|
@ -69,6 +69,7 @@ typedef enum {
|
||||
typedef enum {
|
||||
ESP_PARTITION_SUBTYPE_BOOTLOADER_PRIMARY = 0x00, //!< Primary Bootloader
|
||||
ESP_PARTITION_SUBTYPE_BOOTLOADER_OTA = 0x01, //!< Temporary OTA storage for Bootloader, where the OTA uploads a new Bootloader image
|
||||
ESP_PARTITION_SUBTYPE_BOOTLOADER_RECOVERY = 0x02, //!< Recovery Bootloader
|
||||
|
||||
ESP_PARTITION_SUBTYPE_PARTITION_TABLE_PRIMARY = 0x00, //!< Primary Partition table
|
||||
ESP_PARTITION_SUBTYPE_PARTITION_TABLE_OTA = 0x01, //!< Temporary OTA storage for Partition table, where the OTA uploads a new Partition table image
|
||||
|
@ -80,6 +80,7 @@ const char *esp_partition_subtype_to_str(const uint32_t type, const uint32_t sub
|
||||
switch (subtype) {
|
||||
case PART_SUBTYPE_BOOTLOADER_PRIMARY: return "primary";
|
||||
case PART_SUBTYPE_BOOTLOADER_OTA: return "ota";
|
||||
case PART_SUBTYPE_BOOTLOADER_RECOVERY: return "recovery";
|
||||
default: return "unknown";
|
||||
}
|
||||
case PART_TYPE_PARTITION_TABLE:
|
||||
|
@ -32,6 +32,10 @@ else()
|
||||
set(final_partition_target "build_partition_table")
|
||||
endif()
|
||||
|
||||
if(CONFIG_BOOTLOADER_RECOVERY_OFFSET)
|
||||
set(recovery_bootloader_option --recovery-bootloader-offset ${CONFIG_BOOTLOADER_RECOVERY_OFFSET})
|
||||
endif()
|
||||
|
||||
if(NOT CONFIG_PARTITION_TABLE_MD5)
|
||||
set(md5_opt --disable-md5sum)
|
||||
endif()
|
||||
@ -67,6 +71,7 @@ set(gen_partition_table "${python}" "${CMAKE_CURRENT_SOURCE_DIR}/gen_esp32part.p
|
||||
"-q"
|
||||
"--offset" "${PARTITION_TABLE_OFFSET}"
|
||||
"--primary-bootloader-offset" "${BOOTLOADER_OFFSET}"
|
||||
"${recovery_bootloader_option}"
|
||||
"${md5_opt}"
|
||||
"${flashsize_opt}"
|
||||
"${partition_secure_opt}" ${extra_partition_subtypes} "--")
|
||||
|
@ -29,7 +29,7 @@ SECURE_NONE = None
|
||||
SECURE_V1 = 'v1'
|
||||
SECURE_V2 = 'v2'
|
||||
|
||||
__version__ = '1.3'
|
||||
__version__ = '1.4'
|
||||
|
||||
APP_TYPE = 0x00
|
||||
DATA_TYPE = 0x01
|
||||
@ -60,6 +60,7 @@ SUBTYPES = {
|
||||
BOOTLOADER_TYPE: {
|
||||
'primary': 0x00,
|
||||
'ota': 0x01,
|
||||
'recovery': 0x02,
|
||||
},
|
||||
PARTITION_TABLE_TYPE: {
|
||||
'primary': 0x00,
|
||||
@ -154,6 +155,7 @@ md5sum = True
|
||||
secure = SECURE_NONE
|
||||
offset_part_table = 0
|
||||
primary_bootloader_offset = None
|
||||
recovery_bootloader_offset = None
|
||||
|
||||
|
||||
def status(msg):
|
||||
@ -464,10 +466,15 @@ class PartitionDefinition(object):
|
||||
return parse_int(strval)
|
||||
|
||||
def parse_address(self, strval, ptype, psubtype):
|
||||
if ptype == BOOTLOADER_TYPE and psubtype == SUBTYPES[ptype]['primary']:
|
||||
if primary_bootloader_offset is None:
|
||||
raise InputError(f'Primary bootloader offset is not defined. Please use --primary-bootloader-offset')
|
||||
return primary_bootloader_offset
|
||||
if ptype == BOOTLOADER_TYPE:
|
||||
if psubtype == SUBTYPES[ptype]['primary']:
|
||||
if primary_bootloader_offset is None:
|
||||
raise InputError(f'Primary bootloader offset is not defined. Please use --primary-bootloader-offset')
|
||||
return primary_bootloader_offset
|
||||
if psubtype == SUBTYPES[ptype]['recovery']:
|
||||
if recovery_bootloader_offset is None:
|
||||
raise InputError(f'Recovery bootloader offset is not defined. Please use --recovery-bootloader-offset')
|
||||
return recovery_bootloader_offset
|
||||
if ptype == PARTITION_TABLE_TYPE and psubtype == SUBTYPES[ptype]['primary']:
|
||||
return offset_part_table
|
||||
if strval == '':
|
||||
@ -590,6 +597,7 @@ def main():
|
||||
global offset_part_table
|
||||
global secure
|
||||
global primary_bootloader_offset
|
||||
global recovery_bootloader_offset
|
||||
parser = argparse.ArgumentParser(description='ESP32 partition table utility')
|
||||
|
||||
parser.add_argument('--flash-size', help='Optional flash size limit, checks partition table fits in flash',
|
||||
@ -601,6 +609,7 @@ def main():
|
||||
parser.add_argument('--quiet', '-q', help="Don't print non-critical status messages to stderr", action='store_true')
|
||||
parser.add_argument('--offset', '-o', help='Set offset partition table', default='0x8000')
|
||||
parser.add_argument('--primary-bootloader-offset', help='Set primary bootloader offset', default=None)
|
||||
parser.add_argument('--recovery-bootloader-offset', help='Set recovery bootloader offset', default=None)
|
||||
parser.add_argument('--secure', help='Require app partitions to be suitable for secure boot', nargs='?', const=SECURE_V1, choices=[SECURE_V1, SECURE_V2])
|
||||
parser.add_argument('--extra-partition-subtypes', help='Extra partition subtype entries', nargs='*')
|
||||
parser.add_argument('input', help='Path to CSV or binary file to parse.', type=argparse.FileType('rb'))
|
||||
@ -620,6 +629,8 @@ def main():
|
||||
f'Unsupported configuration. Primary bootloader must be below partition table. '
|
||||
f'Check --primary-bootloader-offset={primary_bootloader_offset:#x} and --offset={offset_part_table:#x}'
|
||||
)
|
||||
if args.recovery_bootloader_offset is not None:
|
||||
recovery_bootloader_offset = int(args.recovery_bootloader_offset, 0)
|
||||
if args.extra_partition_subtypes:
|
||||
add_extra_subtypes(args.extra_partition_subtypes)
|
||||
|
||||
|
@ -14,7 +14,7 @@ import tempfile
|
||||
|
||||
import gen_esp32part as gen
|
||||
|
||||
__version__ = '2.1'
|
||||
__version__ = '2.2'
|
||||
|
||||
COMPONENTS_PATH = os.path.expandvars(os.path.join('$IDF_PATH', 'components'))
|
||||
ESPTOOL_PY = os.path.join(COMPONENTS_PATH, 'esptool_py', 'esptool', 'esptool.py')
|
||||
@ -56,13 +56,14 @@ PARTITION_BOOT_DEFAULT = _PartitionId()
|
||||
|
||||
class ParttoolTarget():
|
||||
|
||||
def __init__(self, port=None, baud=None, partition_table_offset=PARTITION_TABLE_OFFSET, primary_bootloader_offset=None, partition_table_file=None,
|
||||
esptool_args=[], esptool_write_args=[], esptool_read_args=[], esptool_erase_args=[]):
|
||||
def __init__(self, port=None, baud=None, partition_table_offset=PARTITION_TABLE_OFFSET, primary_bootloader_offset=None, recovery_bootloader_offset=None,
|
||||
partition_table_file=None, esptool_args=[], esptool_write_args=[], esptool_read_args=[], esptool_erase_args=[]):
|
||||
self.port = port
|
||||
self.baud = baud
|
||||
|
||||
gen.offset_part_table = partition_table_offset
|
||||
gen.primary_bootloader_offset = primary_bootloader_offset
|
||||
gen.recovery_bootloader_offset = recovery_bootloader_offset
|
||||
|
||||
def parse_esptool_args(esptool_args):
|
||||
results = list()
|
||||
@ -241,6 +242,7 @@ def main():
|
||||
|
||||
parser.add_argument('--partition-table-offset', '-o', help='offset to read the partition table from', type=str)
|
||||
parser.add_argument('--primary-bootloader-offset', help='offset for primary bootloader', type=str)
|
||||
parser.add_argument('--recovery-bootloader-offset', help='offset for recovery bootloader', type=str)
|
||||
parser.add_argument('--partition-table-file', '-f', help='file (CSV/binary) to read the partition table from; \
|
||||
overrides device attached to specified port as the partition table source when defined')
|
||||
|
||||
@ -318,6 +320,9 @@ def main():
|
||||
if args.primary_bootloader_offset:
|
||||
target_args['primary_bootloader_offset'] = int(args.primary_bootloader_offset, 0)
|
||||
|
||||
if args.recovery_bootloader_offset:
|
||||
target_args['recovery_bootloader_offset'] = int(args.recovery_bootloader_offset, 0)
|
||||
|
||||
if args.esptool_args:
|
||||
target_args['esptool_args'] = args.esptool_args
|
||||
|
||||
|
@ -7,6 +7,12 @@ if(NOT DEFINED BOOTLOADER_OFFSET) # For Linux target
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CONFIG_BOOTLOADER_RECOVERY_OFFSET)
|
||||
set(RECOVERY_BOOTLOADER_OPTION --recovery-bootloader-offset ${CONFIG_BOOTLOADER_RECOVERY_OFFSET})
|
||||
else()
|
||||
set(RECOVERY_BOOTLOADER_OPTION "")
|
||||
endif()
|
||||
|
||||
set(PARTITION_TABLE_CHECK_SIZES_TOOL_PATH "${CMAKE_CURRENT_LIST_DIR}/check_sizes.py")
|
||||
|
||||
idf_build_get_property(build_dir BUILD_DIR)
|
||||
@ -66,6 +72,7 @@ function(partition_table_get_partition_info result get_part_info_args part_info)
|
||||
${idf_path}/components/partition_table/parttool.py -q
|
||||
--partition-table-offset ${PARTITION_TABLE_OFFSET}
|
||||
--primary-bootloader-offset ${BOOTLOADER_OFFSET}
|
||||
${RECOVERY_BOOTLOADER_OPTION}
|
||||
--partition-table-file ${PARTITION_CSV_PATH}
|
||||
get_partition_info ${get_part_info_args} --info ${part_info}
|
||||
${extra_partition_subtypes}
|
||||
|
@ -64,6 +64,7 @@ def _strip_trailing_ffs(binary_table):
|
||||
class CSVParserTests(Py23TestCase):
|
||||
def tearDown(self):
|
||||
gen_esp32part.primary_bootloader_offset = None
|
||||
gen_esp32part.recovery_bootloader_offset = None
|
||||
gen_esp32part.offset_part_table = 0
|
||||
|
||||
def test_simple_partition(self):
|
||||
@ -197,8 +198,10 @@ partition_table, partition_table, primary, N/A, N/A
|
||||
FactoryApp, app, factory, , 1M
|
||||
OtaBTLDR, bootloader, ota, , N/A
|
||||
OtaPrtTable, partition_table, ota, , N/A
|
||||
RecoveryBTLDR, bootloader, recovery, N/A, N/A
|
||||
"""
|
||||
gen_esp32part.primary_bootloader_offset = 0x1000
|
||||
gen_esp32part.recovery_bootloader_offset = 0x200000
|
||||
gen_esp32part.offset_part_table = 0x9000
|
||||
part_table_size = 0x1000
|
||||
bootloader_size = gen_esp32part.offset_part_table - gen_esp32part.primary_bootloader_offset
|
||||
@ -218,6 +221,9 @@ OtaPrtTable, partition_table, ota, , N/A
|
||||
# OtaPrtTable
|
||||
self.assertEqual(t[4].offset, 0x118000)
|
||||
self.assertEqual(t[4].size, part_table_size)
|
||||
# RecoveryBTLDR
|
||||
self.assertEqual(t[5].offset, gen_esp32part.recovery_bootloader_offset)
|
||||
self.assertEqual(t[5].size, bootloader_size)
|
||||
|
||||
|
||||
class BinaryOutputTests(Py23TestCase):
|
||||
|
@ -84,6 +84,7 @@ Here is an example of a CSV partition table that includes bootloader and partiti
|
||||
nvs, data, nvs, , 0x6000,
|
||||
phy_init, data, phy, , 0x1000,
|
||||
factory, app, factory, , 1M,
|
||||
recoveryBloader, bootloader, recovery, N/A, N/A,
|
||||
|
||||
The ``gen_esp32part.py`` tool will replace each ``N/A`` with appropriate values based on the selected Kconfig options: {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} for the bootloader offset and :ref:`CONFIG_PARTITION_TABLE_OFFSET` for the partition table offset.
|
||||
|
||||
@ -136,6 +137,7 @@ See enum :cpp:type:`esp_partition_subtype_t` for the full list of subtypes defin
|
||||
|
||||
- ``primary`` (0x00). This is the 2nd stage bootloader, located at the {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH} address in flash memory. The tool automatically determines the appropriate size and offset for this subtype, so any size or offset specified for this subtype will be ignored. You can either leave these fields blank or use ``N/A`` as a placeholder.
|
||||
- ``ota`` (0x01). This is a temporary bootloader partition used by the bootloader OTA update functionality to download a new image. The tool ignores the size for this subtype, allowing you to leave it blank or use ``N/A``. You can only specify an offset, or leave it blank to have the tool calculate it based on the offsets of previously used partitions.
|
||||
- ``recovery`` (0x02). This is the recovery bootloader partition used for safely performing OTA updates to the bootloader. The ``gen_esp32part.py`` tool automatically determines the address and size for this partition, so you can leave these fields blank or use ``N/A`` as a placeholder. The address must match an eFuse field, which is defined through a Kconfig option. If the normal bootloader loading path fails, the ROM bootloader will attempt to load the recovery partition at the address specified by the eFuse field.
|
||||
|
||||
The size of the bootloader type is calculated by the ``gen_esp32part.py`` tool based on the specified ``--offset`` (the partition table offset) and ``--primary-partition-offset`` arguments. Specifically, the bootloader size is defined as (:ref:`CONFIG_PARTITION_TABLE_OFFSET` - {IDF_TARGET_CONFIG_BOOTLOADER_OFFSET_IN_FLASH}). This calculated size applies to all subtypes of the bootloader.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user