From 3e7e30c889a567b77071321c89af0589a4ad12ff Mon Sep 17 00:00:00 2001 From: dongheng Date: Fri, 22 Feb 2019 18:11:49 +0800 Subject: [PATCH] feat(partition_table): Compiling script gets partition information from partition binary --- components/esp8266/Makefile.projbuild | 48 +++---- components/esp8266/component.mk | 4 +- components/partition_table/Kconfig.projbuild | 59 -------- components/partition_table/Makefile.projbuild | 39 +++-- components/partition_table/gen_esp32part.py | 109 +++++++++++++- components/partition_table/parttool.py | 133 ++++++++++++++++++ docs/en/api-guides/fota-from-old-new.rst | 71 +--------- examples/system/ota/README.md | 29 +--- examples/system/ota/sdkconfig.defaults | 4 - make/project.mk | 4 +- 10 files changed, 287 insertions(+), 213 deletions(-) create mode 100755 components/partition_table/parttool.py diff --git a/components/esp8266/Makefile.projbuild b/components/esp8266/Makefile.projbuild index 06498487..690a16f5 100644 --- a/components/esp8266/Makefile.projbuild +++ b/components/esp8266/Makefile.projbuild @@ -35,8 +35,8 @@ PHY_INIT_DATA_OBJ = $(BUILD_DIR_BASE)/phy_init_data.o PHY_INIT_DATA_BIN = $(BUILD_DIR_BASE)/phy_init_data.bin # Command to flash PHY init data partition -PHY_INIT_DATA_FLASH_CMD = $(ESPTOOLPY_SERIAL) write_flash $(CONFIG_PHY_DATA_OFFSET) $(PHY_INIT_DATA_BIN) -ESPTOOL_ALL_FLASH_ARGS += $(CONFIG_PHY_DATA_OFFSET) $(PHY_INIT_DATA_BIN) +PHY_INIT_DATA_FLASH_CMD = $(ESPTOOLPY_SERIAL) write_flash $(PHY_DATA_OFFSET) $(PHY_INIT_DATA_BIN) +ESPTOOL_ALL_FLASH_ARGS += $(PHY_DATA_OFFSET) $(PHY_INIT_DATA_BIN) ESP8266_COMPONENT_PATH := $(COMPONENT_PATH) @@ -91,51 +91,35 @@ OTA2_BIN := ./build/$(PROJECT_NAME).app2.bin OTA_V2_TO_V3_BIN := ./build/$(PROJECT_NAME).v2_to_v3.ota.bin -ifndef CONFIG_APP2_OFFSET -CONFIG_APP2_OFFSET := $(CONFIG_APP1_OFFSET) +ifndef CONFIG_ESP8266_BOOT_COPY_APP +ifdef CONFIG_ESPTOOLPY_FLASHSIZE_1MB +__COMBILE_OTA_BIN := 1 +endif endif -ifndef CONFIG_APP2_SIZE -CONFIG_APP2_SIZE := $(CONFIG_APP1_SIZE) -endif +$(OTA1_BIN): all_binaries + @cp $(RAW_BIN) $(OTA1_BIN) + @echo [GEN] $(OTA1_BIN) -OTA1_OFFSET := $(CONFIG_APP1_OFFSET) -ifdef CONFIG_ESP8266_BOOT_COPY_APP -OTA2_LINK_OFFSET := $(CONFIG_APP1_OFFSET) -else -OTA2_LINK_OFFSET := $(CONFIG_APP2_OFFSET) -endif - -$(OTA2_BIN): all_binaries -ifneq ($(OTA1_OFFSET), $(OTA2_LINK_OFFSET)) +$(OTA2_BIN): $(OTA1_BIN) +ifdef __COMBILE_OTA_BIN @rm -f ./build/esp8266/esp8266_out.ld - @make APP_OFFSET=$(OTA2_LINK_OFFSET) APP_SIZE=$(CONFIG_APP2_SIZE) CFLAGS= CXXFLAGS= + @export CFLAGS= && export CXXFLAGS= && make APP_OFFSET=$(APP2_OFFSET) APP_SIZE=$(APP2_SIZE) endif @cp $(RAW_BIN) $(OTA2_BIN) @echo [GEN] $(OTA2_BIN) -$(OTA1_BIN): all_binaries -ifneq ($(OTA1_OFFSET), $(OTA2_LINK_OFFSET)) - @rm -f ./build/esp8266/esp8266_out.ld -endif - @make APP_OFFSET=$(OTA1_OFFSET) APP_SIZE=$(CONFIG_APP1_SIZE) CFLAGS= CXXFLAGS= - @cp $(RAW_BIN) $(OTA1_BIN) - @echo [GEN] $(OTA1_BIN) - -$(OTA_BIN): $(OTA1_BIN) $(OTA2_BIN) +$(OTA_BIN): $(OTA2_BIN) @cp $(OTA1_BIN) $(OTA_BIN) -ifneq ($(OTA1_OFFSET), $(OTA2_LINK_OFFSET)) +ifdef __COMBILE_OTA_BIN @cat $(OTA2_BIN) >> $(OTA_BIN) -endif @cp $(OTA1_BIN) $(RAW_BIN) +endif @echo [GEN] $(OTA_BIN) ifdef CONFIG_ESP8266_OTA_FROM_OLD -$(OTA_V2_TO_V3_BIN): $(OTA_BIN) - @cp $(RAW_BIN) $(RAW_BIN).tmp.bak - @cp $(OTA1_BIN) $(RAW_BIN) +$(OTA_V2_TO_V3_BIN): @python $(IDF_PATH)/tools/pack_fw.py --output $(OTA_V2_TO_V3_BIN) pack3 $(ESPTOOL_ALL_FLASH_ARGS) - @cp $(RAW_BIN).tmp.bak $(RAW_BIN) @echo [GEN] $(OTA_V2_TO_V3_BIN) endif diff --git a/components/esp8266/component.mk b/components/esp8266/component.mk index 3f55a7d6..6b7d027e 100644 --- a/components/esp8266/component.mk +++ b/components/esp8266/component.mk @@ -41,10 +41,8 @@ COMPONENT_ADD_LINKER_DEPS := $(ALL_LIB_FILES) $(addprefix ld/,$(LINKER_SCRIPTS)) # saves us from having to add the target to a Makefile.projbuild $(COMPONENT_LIBRARY): esp8266_out.ld esp8266_common_out.ld -OUTLD_CFLAGS := -DAPP_OFFSET=$(APP_OFFSET) -DAPP_SIZE=$(APP_SIZE) - esp8266_out.ld: $(COMPONENT_PATH)/ld/esp8266.ld ../include/sdkconfig.h - $(CC) $(OUTLD_CFLAGS) -I ../include -C -P -x c -E $< -o $@ + $(CC) $(CFLAGS) -I ../include -C -P -x c -E $< -o $@ esp8266_common_out.ld: $(COMPONENT_PATH)/ld/esp8266.common.ld ../include/sdkconfig.h $(CC) -I ../include -C -P -x c -E $< -o $@ diff --git a/components/partition_table/Kconfig.projbuild b/components/partition_table/Kconfig.projbuild index eed3820d..2fd122d1 100644 --- a/components/partition_table/Kconfig.projbuild +++ b/components/partition_table/Kconfig.projbuild @@ -33,15 +33,6 @@ config PARTITION_TABLE_OFFSET help The partition table cannot be placed at application address. -config PARTITION_TABLE_CUSTOM_PHY_DATA_OFFSET - hex "PHY data partition offset" if PARTITION_TABLE_CUSTOM - depends on ESP_PHY_INIT_DATA_IN_PARTITION - default 0xf000 - help - If using a custom partition table, specify the offset in the flash - where 'make flash' should write the initial PHY data file. - - config PARTITION_TABLE_FILENAME string default partitions_singleapp.csv if PARTITION_TABLE_SINGLE_APP && !ESP32_ENABLE_COREDUMP_TO_FLASH @@ -51,56 +42,6 @@ config PARTITION_TABLE_FILENAME default partitions_two_ota_coredump.csv if PARTITION_TABLE_TWO_OTA && ESP32_ENABLE_COREDUMP_TO_FLASH default PARTITION_TABLE_CUSTOM_FILENAME if PARTITION_TABLE_CUSTOM -config PHY_DATA_OFFSET - depends on ESP_PHY_INIT_DATA_IN_PARTITION - hex - default PARTITION_TABLE_CUSTOM_PHY_DATA_OFFSET if PARTITION_TABLE_CUSTOM - default 0xf000 # this is the factory app offset used by the default tables - -config APP2_SUPPORT - depends on ESPTOOLPY_FLASHSIZE_1MB && (PARTITION_TABLE_TWO_OTA || PARTITION_TABLE_CUSTOM) - bool "Support to setup partition parameter of APP2" if PARTITION_TABLE_CUSTOM - default y - help - Enable this option, if you want to have APP1 & APP2 in 1MB SPI Flash. - -config APP1_OFFSET - hex "APP1 partition offset" if PARTITION_TABLE_CUSTOM - default 0x10000 - help - If using a custom partition table, specify the offset in the flash - where the APP1 located. - - It should be same as the value in the custom partition table CSV. - -config APP1_SIZE - hex "APP1 partition size(by bytes)" if PARTITION_TABLE_CUSTOM - default 0x70000 if APP2_SUPPORT - default 0xF0000 - help - APP1 partition size by bytes. - - It should be same as the value in the custom partition table CSV. - -config APP2_OFFSET - depends on APP2_SUPPORT - hex "APP2 partition offset" if PARTITION_TABLE_CUSTOM - default 0x80000 - help - If using a custom partition table, specify the offset in the flash - where the APP2 located. - - It should be same as the value in the custom partition table CSV. - -config APP2_SIZE - depends on APP2_SUPPORT - hex "APP2 partition size(by bytes)" if PARTITION_TABLE_CUSTOM - default 0x70000 - help - APP2 partition size by bytes. - - It should be same as the value in the custom partition table CSV. - endmenu diff --git a/components/partition_table/Makefile.projbuild b/components/partition_table/Makefile.projbuild index 841495b9..40581cc5 100644 --- a/components/partition_table/Makefile.projbuild +++ b/components/partition_table/Makefile.projbuild @@ -6,14 +6,24 @@ # the partition table binary as part of the build process. This # binary is then added to the list of files for esptool.py to flash. # -.PHONY: partition_table partition_table-flash partition_table-clean +.PHONY: partition_table partition_table-flash partition_table-clean partition_table_get_info + +PARTITION_MD5_OPT := "--disable-md5sum" + +PARTITION_FLASHSIZE_OPT := +ifneq ("$(CONFIG_ESPTOOLPY_FLASHSIZE)", "") +PARTITION_FLASHSIZE_OPT := --flash-size $(CONFIG_ESPTOOLPY_FLASHSIZE) +endif + +PARTITION_SECURE_OPT := + +# Address of partition table +PARTITION_TABLE_OFFSET := $(CONFIG_PARTITION_TABLE_OFFSET) +PARTITION_TABLE_OFFSET_ARG := --offset $(PARTITION_TABLE_OFFSET) # NB: gen_esp32part.py lives in the sdk/bin/ dir not component dir -GEN_ESP32PART := $(PYTHON) $(COMPONENT_PATH)/gen_esp32part.py -q - -# Has a matching value in bootloader_support esp_flash_partitions.h - -PARTITION_TABLE_OFFSET := $(CONFIG_PARTITION_TABLE_OFFSET) +GEN_ESP32PART := $(PYTHON) $(COMPONENT_PATH)/gen_esp32part.py -q $(PARTITION_MD5_OPT) $(PARTITION_FLASHSIZE_OPT) $(PARTITION_TABLE_OFFSET_ARG) $(PARTITION_SECURE_OPT) +GET_PART_INFO := $(COMPONENT_PATH)/parttool.py -q # if CONFIG_PARTITION_TABLE_FILENAME is unset, means we haven't re-generated config yet... ifneq ("$(CONFIG_PARTITION_TABLE_FILENAME)","") @@ -43,17 +53,22 @@ $(PARTITION_TABLE_BIN_UNSIGNED): $(PARTITION_TABLE_CSV_PATH) $(SDKCONFIG_MAKEFIL @echo "Building partitions from $(PARTITION_TABLE_CSV_PATH)..." $(GEN_ESP32PART) $< $@ -all_binaries: $(PARTITION_TABLE_BIN) +all_binaries: $(PARTITION_TABLE_BIN) partition_table_get_info -APP_OFFSET ?= $(CONFIG_APP1_OFFSET) -APP_SIZE ?= $(CONFIG_APP1_SIZE) +partition_table_get_info: $(PARTITION_TABLE_BIN) + $(eval PHY_DATA_OFFSET:=$(shell $(GET_PART_INFO) --type data --subtype phy --offset $(PARTITION_TABLE_BIN))) + $(eval APP_OFFSET:=$(shell $(GET_PART_INFO) --default-boot-partition --offset $(PARTITION_TABLE_BIN))) + $(eval APP_SIZE:=$(shell $(GET_PART_INFO) --default-boot-partition --size $(PARTITION_TABLE_BIN))) + $(eval APP2_OFFSET:=$(shell $(GET_PART_INFO) --type app --subtype ota_1 --offset $(PARTITION_TABLE_BIN))) + $(eval APP2_SIZE:=$(shell $(GET_PART_INFO) --type app --subtype ota_1 --size $(PARTITION_TABLE_BIN))) + $(eval CFLAGS += -DAPP_OFFSET=$(APP_OFFSET) -DAPP_SIZE=$(APP_SIZE)) -export APP_OFFSET APP_SIZE +export PHY_DATA_OFFSET APP_OFFSET APP_SIZE APP2_OFFSET APP2_SIZE PARTITION_TABLE_FLASH_CMD = $(ESPTOOLPY_SERIAL) write_flash $(PARTITION_TABLE_OFFSET) $(PARTITION_TABLE_BIN) ESPTOOL_ALL_FLASH_ARGS += $(PARTITION_TABLE_OFFSET) $(PARTITION_TABLE_BIN) -partition_table: $(PARTITION_TABLE_BIN) +partition_table: $(PARTITION_TABLE_BIN) partition_table_get_info @echo "Partition table binary generated. Contents:" @echo $(SEPARATOR) $(GEN_ESP32PART) $< @@ -68,6 +83,8 @@ partition_table-flash: $(PARTITION_TABLE_BIN) partition_table-clean: rm -f $(PARTITION_TABLE_BIN) +global-macro: partition_table_get_info + clean: partition_table-clean endif diff --git a/components/partition_table/gen_esp32part.py b/components/partition_table/gen_esp32part.py index e789261f..732eff6d 100755 --- a/components/partition_table/gen_esp32part.py +++ b/components/partition_table/gen_esp32part.py @@ -4,7 +4,7 @@ # # Converts partition tables to/from CSV and binary formats. # -# See http://esp-idf.readthedocs.io/en/latest/api-guides/partition-tables.html +# See https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/partition-tables.html # for explanation of partition table structure and uses. # # Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD @@ -26,12 +26,19 @@ import os import re import struct import sys +import hashlib +import binascii MAX_PARTITION_LENGTH = 0xC00 # 3K for partition data (96 entries) leaves 1K in a 4K sector for signature +MD5_PARTITION_BEGIN = b"\xEB\xEB" + b"\xFF" * 14 # The first 2 bytes are like magic numbers for MD5 sum +PARTITION_TABLE_SIZE = 0x1000 # Size of partition table -__version__ = '1.0' +__version__ = '1.1' quiet = False +md5sum = True +secure = False +offset_part_table = 0 def status(msg): """ Print status message to stderr """ @@ -73,8 +80,11 @@ class PartitionTable(list): raise # fix up missing offsets & negative sizes - last_end = 0x5000 # first offset after partition table + last_end = offset_part_table + PARTITION_TABLE_SIZE # first offset after partition table for e in res: + if offset_part_table != 0 and e.offset is not None and e.offset < last_end: + critical("WARNING: 0x%x address in the partition table is below 0x%x" % (e.offset, last_end)) + e.offset = None if e.offset is None: pad_to = 0x10000 if e.type == PartitionDefinition.APP_TYPE else 4 if last_end % pad_to != 0: @@ -97,6 +107,38 @@ class PartitionTable(list): else: return super(PartitionTable, self).__getitem__(item) + def find_by_type(self, ptype, subtype): + """ Return a partition by type & subtype, returns + None if not found """ + TYPES = PartitionDefinition.TYPES + SUBTYPES = PartitionDefinition.SUBTYPES + # convert ptype & subtypes names (if supplied this way) to integer values + try: + ptype = TYPES[ptype] + except KeyError: + try: + ptypes = int(ptype, 0) + except TypeError: + pass + try: + subtype = SUBTYPES[int(ptype)][subtype] + except KeyError: + try: + ptypes = int(ptype, 0) + except TypeError: + pass + + for p in self: + if p.type == ptype and p.subtype == subtype: + return p + return None + + def find_by_name(self, name): + for p in self: + if p.name == name: + return p + return None + def verify(self): # verify each partition individually for p in self: @@ -104,14 +146,25 @@ class PartitionTable(list): # check for overlaps last = None for p in sorted(self, key=lambda x:x.offset): - if p.offset < 0x5000: - raise InputError("Partition offset 0x%x is below 0x5000" % p.offset) + if p.offset < offset_part_table + PARTITION_TABLE_SIZE: + raise InputError("Partition offset 0x%x is below 0x%x" % (p.offset, offset_part_table + PARTITION_TABLE_SIZE)) if last is not None and p.offset < last.offset + last.size: raise InputError("Partition at 0x%x overlaps 0x%x-0x%x" % (p.offset, last.offset, last.offset+last.size-1)) last = p + def flash_size(self): + """ Return the size that partitions will occupy in flash + (ie the offset the last partition ends at) + """ + try: + last = sorted(self, reverse=True)[0] + except IndexError: + return 0 # empty table! + return last.offset + last.size + @classmethod def from_binary(cls, b): + md5 = hashlib.md5(); result = cls() for o in range(0,len(b),32): data = b[o:o+32] @@ -119,11 +172,20 @@ class PartitionTable(list): raise InputError("Partition table length must be a multiple of 32 bytes") if data == b'\xFF'*32: return result # got end marker + if md5sum and data[:2] == MD5_PARTITION_BEGIN[:2]: #check only the magic number part + if data[16:] == md5.digest(): + continue # the next iteration will check for the end marker + else: + raise InputError("MD5 checksums don't match! (computed: 0x%s, parsed: 0x%s)" % (md5.hexdigest(), binascii.hexlify(data[16:]))) + else: + md5.update(data) result.append(PartitionDefinition.from_binary(data)) raise InputError("Partition table is missing an end-of-table marker") def to_binary(self): result = b"".join(e.to_binary() for e in self) + if md5sum: + result += MD5_PARTITION_BEGIN + hashlib.md5(result).digest() if len(result )>= MAX_PARTITION_LENGTH: raise InputError("Binary partition table length (%d) longer than max" % len(result)) result += b"\xFF" * (MAX_PARTITION_LENGTH - len(result)) # pad the sector, for signing @@ -154,6 +216,7 @@ class PartitionDefinition(object): "phy" : 0x01, "nvs" : 0x02, "coredump" : 0x03, + "nvs_keys" : 0x04, "esphttpd" : 0x80, "fat" : 0x81, "spiffs" : 0x82, @@ -173,7 +236,7 @@ class PartitionDefinition(object): "encrypted" : 0 } - # add subtypes for the 16 OTA slot values ("ota_XXX, etc.") + # add subtypes for the 16 OTA slot values ("ota_XX, etc.") for ota_slot in range(16): SUBTYPES[TYPES["app"]]["ota_%d" % ota_slot] = 0x10 + ota_slot @@ -226,6 +289,18 @@ class PartitionDefinition(object): def __cmp__(self, other): return self.offset - other.offset + def __lt__(self, other): + return self.offset < other.offset + + def __gt__(self, other): + return self.offset > other.offset + + def __le__(self, other): + return self.offset <= other.offset + + def __ge__(self, other): + return self.offset >= other.offset + def parse_type(self, strval): if strval == "": raise InputError("Field 'type' can't be left empty.") @@ -251,6 +326,8 @@ class PartitionDefinition(object): align = self.ALIGNMENT.get(self.type, 4) if self.offset % align: raise ValidationError(self, "Offset 0x%x is not aligned to 0x%x" % (self.offset, align)) + if self.size % align and secure: + raise ValidationError(self, "Size 0x%x is not aligned to 0x%x" % (self.size, align)) if self.size is None: raise ValidationError(self, "Size field is not set") @@ -333,11 +410,18 @@ def parse_int(v, keywords={}): def main(): global quiet + global md5sum + global offset_part_table + global secure parser = argparse.ArgumentParser(description='ESP32 partition table utility') + parser.add_argument('--flash-size', help='Optional flash size limit, checks partition table fits in flash', + nargs='?', choices=[ '1MB', '2MB', '4MB', '8MB', '16MB' ]) + parser.add_argument('--disable-md5sum', help='Disable md5 checksum for the partition table', default=False, action='store_true') parser.add_argument('--verify', '-v', help='Verify partition table fields', default=True, action='store_false') parser.add_argument('--quiet', '-q', help="Don't print status messages to stderr", action='store_true') - + parser.add_argument('--offset', '-o', help='Set offset partition table', default='0x8000') + parser.add_argument('--secure', help="Require app partitions to be suitable for secure boot", action='store_true') parser.add_argument('input', help='Path to CSV or binary file to parse. Will use stdin if omitted.', type=argparse.FileType('rb'), default=sys.stdin) parser.add_argument('output', help='Path to output converted binary or CSV file. Will use stdout if omitted, unless the --display argument is also passed (in which case only the summary is printed.)', nargs='?', @@ -346,6 +430,9 @@ def main(): args = parser.parse_args() quiet = args.quiet + md5sum = not args.disable_md5sum + secure = args.secure + offset_part_table = int(args.offset, 0) input = args.input.read() input_is_binary = input[0:2] == PartitionDefinition.MAGIC_BYTES if input_is_binary: @@ -360,6 +447,14 @@ def main(): status("Verifying table...") table.verify() + if args.flash_size: + size_mb = int(args.flash_size.replace("MB", "")) + size = size_mb * 1024 * 1024 # flash memory uses honest megabytes! + table_size = table.flash_size() + if size < table_size: + raise InputError("Partitions defined in '%s' occupy %.1fMB of flash (%d bytes) which does not fit in configured flash size %dMB. Change the flash size in menuconfig under the 'Serial Flasher Config' menu." % + (args.input.name, table_size / 1024.0 / 1024.0, table_size, size_mb)) + if input_is_binary: output = table.to_csv() with sys.stdout if args.output == '-' else open(args.output, 'w') as f: diff --git a/components/partition_table/parttool.py b/components/partition_table/parttool.py new file mode 100755 index 00000000..145fb8d3 --- /dev/null +++ b/components/partition_table/parttool.py @@ -0,0 +1,133 @@ +#!/usr/bin/env python +# +# parttool returns info about the required partition. +# +# This utility is used by the make system to get information +# about the start addresses: partition table, factory area, phy area. +# +# Copyright 2018 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. +from __future__ import print_function, division +import argparse +import os +import re +import struct +import sys +import hashlib +import binascii +import gen_esp32part as gen + +__version__ = '1.0' + +quiet = False + +def status(msg): + """ Print status message to stderr """ + if not quiet: + critical(msg) + +def critical(msg): + """ Print critical message to stderr """ + if not quiet: + sys.stderr.write(msg) + sys.stderr.write('\n') + +def main(): + global quiet + parser = argparse.ArgumentParser(description='Returns info about the required partition.') + + parser.add_argument('--quiet', '-q', help="Don't print status messages to stderr", action='store_true') + + parser.add_argument('--partition-table-offset', help='The offset of the partition table in flash. Only consulted if partition table is in CSV format.', type=str, default='0x8000') + + search_type = parser.add_mutually_exclusive_group() + search_type.add_argument('--partition-name', '-p', help='The name of the required partition', type=str, default=None) + search_type.add_argument('--type', '-t', help='The type of the required partition', type=str, default=None) + search_type.add_argument('--default-boot-partition', help='Select the default boot partition, '+ + 'using the same fallback logic as the IDF bootloader', action="store_true") + + parser.add_argument('--subtype', '-s', help='The subtype of the required partition', type=str, default=None) + + parser.add_argument('--offset', '-o', help='Return offset of required partition', action="store_true") + parser.add_argument('--size', help='Return size of required partition', action="store_true") + + parser.add_argument('input', help='Path to CSV or binary file to parse. Will use stdin if omitted.', + type=argparse.FileType('rb'), default=sys.stdin) + + args = parser.parse_args() + + if args.type is not None and args.subtype is None: + status("If --type is specified, --subtype is required") + return 2 + if args.type is None and args.subtype is not None: + status("--subtype is only used with --type") + return 2 + + quiet = args.quiet + + gen.offset_part_table = int(args.partition_table_offset, 0) + + input = args.input.read() + input_is_binary = input[0:2] == gen.PartitionDefinition.MAGIC_BYTES + if input_is_binary: + status("Parsing binary partition input...") + table = gen.PartitionTable.from_binary(input) + else: + input = input.decode() + status("Parsing CSV input...") + table = gen.PartitionTable.from_csv(input) + + found_partition = None + + if args.default_boot_partition: + search = [ "factory" ] + [ "ota_%d" % d for d in range(16) ] + for subtype in search: + found_partition = table.find_by_type("app", subtype) + if found_partition is not None: + break + elif args.partition_name is not None: + found_partition = table.find_by_name(args.partition_name) + elif args.type is not None: + found_partition = table.find_by_type(args.type, args.subtype) + else: + raise RuntimeError("invalid partition selection choice") + + if found_partition is None: + return 1 # nothing found + + if args.offset: + print('0x%x ' % (found_partition.offset)) + if args.size: + print('0x%x' % (found_partition.size)) + + return 0 + +class InputError(RuntimeError): + def __init__(self, e): + super(InputError, self).__init__(e) + + +class ValidationError(InputError): + def __init__(self, partition, message): + super(ValidationError, self).__init__( + "Partition %s invalid: %s" % (partition.name, message)) + + +if __name__ == '__main__': + try: + r = main() + sys.exit(r) + except InputError as e: + print(e, file=sys.stderr) + sys.exit(2) diff --git a/docs/en/api-guides/fota-from-old-new.rst b/docs/en/api-guides/fota-from-old-new.rst index 5d46ccac..4382ab29 100644 --- a/docs/en/api-guides/fota-from-old-new.rst +++ b/docs/en/api-guides/fota-from-old-new.rst @@ -76,75 +76,8 @@ Open a new terminal on your PC, set the following configurations, and then compi [*] (**Expected**)ESP8266 update from old SDK by OTA -3. Configure the target custom partition -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The last 16KB flash, which is used to store system parameters of the old SDKs, must be reserved. - -ESP8285(ESP8266 + 1MB flash) configuration: -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Set the file "partitions_two_ota_v2tov3.1MB.csv" to configure the partition of the example. Users can refer to its note for the partition layout. - -:: - - Partition Table ---> - Partition Table (Custom partition table CSV) ---> - Custom partition table CSV - (partitions_two_ota_v2tov3.1MB.csv) Custom partition CSV file - (0x5000) Partition table offset address at flash - [*] Support to setup partition parameter of APP2 - (0x7000) APP1 partition offset - (0x77000) APP1 partition size(by bytes) - (0x85000) APP2 partition offset - (0x77000) APP2 partition size(by bytes) - -Partition information of file "partitions_two_ota_v2tov3.1MB.csv" is following: - -:: - - Name, Type, SubType, Offset, Size, Flags - phy_init, data, phy, 0x6000, 0x1000 - ota_0, 0, ota_0, 0x7000, 0x77000 - nvs, data, nvs, 0x7f000, 0x4000 - otadata, data, ota, 0x83000, 0x2000 - ota_1, 0, ota_1, 0x85000, 0x77000 - -- Partition table offset address at flash: partition table layout address -- APP1 partition offset: ota_0 base address -- APP1 partition size: ota_0 size -- APP2 partition offset: ota_1 base address -- APP2 partition size: ota_1 size - -ESP8266 + 2MB(including larger size flash) flash configuration: -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Set the file "partitions_two_ota_v2tov3.2MB.csv" to configure the partition of the example. Users can refer to its note for the partition layout. - -:: - - Partition Table ---> - Partition Table (Custom partition table CSV) ---> - Custom partition table CSV - (partitions_two_ota_v2tov3.2MB.csv) Custom partition CSV file - (0x8000) Partition table offset address at flash - (0x10000) APP1 partition offset - (0xEC000) APP1 partition size(by bytes) - -Partition information of file "partitions_two_ota_v2tov3.2MB.csv" is following: - -:: - - Name, Type, SubType, Offset, Size, Flags - nvs, data, nvs, 0x9000, 0x4000 - otadata, data, ota, 0xd000, 0x2000 - phy_init, data, phy, 0xf000, 0x1000 - ota_0, 0, ota_0, 0x10000, 0xEC000 - ota_1, 0, ota_1, 0x110000,0xEC000 - -- Partition table offset address at flash: partition table layout address -- APP1 partition offset: ota_0 base address -- APP1 partition size: ota_0 size +3. ESP8285(ESP8266 + 1MB flash) configuration: +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Configure the flash size according to your actual development board's flash. diff --git a/examples/system/ota/README.md b/examples/system/ota/README.md index 2086a4f9..4786f258 100644 --- a/examples/system/ota/README.md +++ b/examples/system/ota/README.md @@ -53,32 +53,7 @@ Note: System will add the absolute path of the project to the head of the "Custo (XXXXXX)Partition table offset address at flash ``` -## Step 3: Configurate application location: - -Configurate application location at "mennuconfig" like following base on partition table file. - -If you select 1MB flash, application location configuration menu is like following: - -``` -Partition Table ---> - - [*] Support to setup partition parameter of APP2 - (0x5000) App1 offset address - (0x7B000) App1 size by bytes - (0x85000) App2 offset address - (0x7b000) App2 size by bytes -``` - -If you select 2MB flash and above size, application location configuration menu is like following: - -``` -Partition Table ---> - - (0x10000) APP1 partition offset - (0xF0000) APP1 partition size(by bytes) -``` - -Note: The firmware location information must be same as partition table file. **make ota flash** will only download the app1 at **APP1 partition offset**. +**make ota flash** will only download the app1 at **APP1 partition offset**. # Workflow @@ -144,7 +119,7 @@ Serial flasher config ---> (X) 1 MB ``` -Configurate the application location information and it must be the same as the OTA example's information, you can refer to the **Step 3: Configurate application location** of **Custom partition configuration**. +Configurate the application partition table information and it must be the same as the OTA example's information, you can refer to the **Custom partition configuration**. Save your changes, and type `make` to build the example. diff --git a/examples/system/ota/sdkconfig.defaults b/examples/system/ota/sdkconfig.defaults index 5afc779b..2476365a 100644 --- a/examples/system/ota/sdkconfig.defaults +++ b/examples/system/ota/sdkconfig.defaults @@ -6,7 +6,3 @@ CONFIG_ESPTOOLPY_FLASHSIZE_1MB=y CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_two_ota.1MB.mini.csv" CONFIG_PARTITION_TABLE_OFFSET=0x4000 -CONFIG_APP1_OFFSET=0x6000 -CONFIG_APP1_SIZE=0x7A000 -CONFIG_APP2_OFFSET=0x86000 -CONFIG_APP2_SIZE=0x7A000 diff --git a/make/project.mk b/make/project.mk index 6abcf722..12407e0b 100644 --- a/make/project.mk +++ b/make/project.mk @@ -192,6 +192,8 @@ COMPONENT_LDFLAGS := COMPONENT_SUBMODULES := COMPONENT_LIBRARIES := +global-macro: + # COMPONENT_PROJECT_VARS is the list of component_project_vars.mk generated makefiles # for each component. # @@ -437,7 +439,7 @@ endef define GenerateComponentTargets .PHONY: component-$(2)-build component-$(2)-clean -component-$(2)-build: check-submodules $(call prereq_if_explicit, component-$(2)-clean) | $(BUILD_DIR_BASE)/$(2) +component-$(2)-build: check-submodules global-macro $(call prereq_if_explicit, component-$(2)-clean) | $(BUILD_DIR_BASE)/$(2) $(call ComponentMake,$(1),$(2)) build component-$(2)-clean: | $(BUILD_DIR_BASE)/$(2) $(BUILD_DIR_BASE)/$(2)/component_project_vars.mk