mirror of
https://github.com/espressif/ESP8266_RTOS_SDK.git
synced 2025-05-21 17:16:29 +08:00
Merge branch 'feature/get_partition_info_v3.1' into 'release/v3.1'
feat(partition_table): Compiling script gets partition information from partition binary (backport v3.1) See merge request sdk/ESP8266_RTOS_SDK!820
This commit is contained in:
@ -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
|
||||
|
||||
|
@ -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 $@
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
133
components/partition_table/parttool.py
Executable file
133
components/partition_table/parttool.py
Executable file
@ -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)
|
@ -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.
|
||||
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user