mirror of
https://github.com/0xFEEDC0DE64/arduino-esp32.git
synced 2025-06-28 19:40:59 +02:00
Update IDF to aaf1239 (#1539)
* fix sdmmc config * Fix warnings in EEPROM from @Curclamas * remove leftover TAG in EEPROM * Initial add of @stickbreaker i2c * Add log_n * fix warnings when log is off * i2c code clean up and reorganization * add flags to interrupt allocator * fix sdmmc config * Fix warnings in EEPROM from @Curclamas * remove leftover TAG in EEPROM * fix errors with latest IDF * fix debug optimization (#1365) incorrect optimization for debugging tick markers. * Fix some missing BT header * Change BTSerial log calls * Update BLE lib * Arduino-ESP32 release management scripted (#1515) * Calculate an absolute path for a custom partitions table (#1452) * * Arduino-ESP32 release management scripted (ready-to-merge) * * secure env for espressif/arduino-esp32 * * build tests enabled * gitter webhook enabled * * gitter room link fixed * better comment * * filepaths fixed * BT Serial adjustments * * don't run sketch builds & tests for tagged builds * Return false from WiFi.hostByName() if hostname is not resolved * Free BT Memory when BT is not used * WIFI_MODE_NULL is not supported anymore * Select some key examples to build with PlatformIO to save some time * Update BLE lib * Fixed BLE lib * Major WiFi overhaul - auto reconnect on connection loss now works - moved to event groups - some code clean up and procedure optimizations - new methods to get a more elaborate system ststus * Add cmake tests to travis * Add initial AsyncUDP * Add NetBIOS lib and fix CMake includes * Add Initial WebServer * Fix WebServer and examples * travis not quiting on build fail * Try different travis build * Update IDF to aaf1239 * Fix WPS Example * fix script permission and add some fail tests to sketch builder * Add missing space in WiFiClient::write(Stream &stream)
This commit is contained in:
@ -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
|
||||
@ -31,11 +31,38 @@ 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.2'
|
||||
|
||||
APP_TYPE = 0x00
|
||||
DATA_TYPE = 0x01
|
||||
|
||||
TYPES = {
|
||||
"app" : APP_TYPE,
|
||||
"data" : DATA_TYPE,
|
||||
}
|
||||
|
||||
# Keep this map in sync with esp_partition_subtype_t enum in esp_partition.h
|
||||
SUBTYPES = {
|
||||
APP_TYPE : {
|
||||
"factory" : 0x00,
|
||||
"test" : 0x20,
|
||||
},
|
||||
DATA_TYPE : {
|
||||
"ota" : 0x00,
|
||||
"phy" : 0x01,
|
||||
"nvs" : 0x02,
|
||||
"coredump" : 0x03,
|
||||
"esphttpd" : 0x80,
|
||||
"fat" : 0x81,
|
||||
"spiffs" : 0x82,
|
||||
},
|
||||
}
|
||||
|
||||
quiet = False
|
||||
md5sum = True
|
||||
offset_part_table = 0
|
||||
|
||||
def status(msg):
|
||||
""" Print status message to stderr """
|
||||
@ -44,9 +71,8 @@ def status(msg):
|
||||
|
||||
def critical(msg):
|
||||
""" Print critical message to stderr """
|
||||
if not quiet:
|
||||
sys.stderr.write(msg)
|
||||
sys.stderr.write('\n')
|
||||
sys.stderr.write(msg)
|
||||
sys.stderr.write('\n')
|
||||
|
||||
class PartitionTable(list):
|
||||
def __init__(self):
|
||||
@ -77,10 +103,13 @@ 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
|
||||
pad_to = 0x10000 if e.type == APP_TYPE else 4
|
||||
if last_end % pad_to != 0:
|
||||
last_end += pad_to - (last_end % pad_to)
|
||||
e.offset = last_end
|
||||
@ -101,6 +130,36 @@ 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 """
|
||||
# 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:
|
||||
@ -108,12 +167,22 @@ 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();
|
||||
@ -150,30 +219,6 @@ class PartitionTable(list):
|
||||
return "\n".join(rows) + "\n"
|
||||
|
||||
class PartitionDefinition(object):
|
||||
APP_TYPE = 0x00
|
||||
DATA_TYPE = 0x01
|
||||
TYPES = {
|
||||
"app" : APP_TYPE,
|
||||
"data" : DATA_TYPE,
|
||||
}
|
||||
|
||||
# Keep this map in sync with esp_partition_subtype_t enum in esp_partition.h
|
||||
SUBTYPES = {
|
||||
APP_TYPE : {
|
||||
"factory" : 0x00,
|
||||
"test" : 0x20,
|
||||
},
|
||||
DATA_TYPE : {
|
||||
"ota" : 0x00,
|
||||
"phy" : 0x01,
|
||||
"nvs" : 0x02,
|
||||
"coredump" : 0x03,
|
||||
"esphttpd" : 0x80,
|
||||
"fat" : 0x81,
|
||||
"spiffs" : 0x82,
|
||||
},
|
||||
}
|
||||
|
||||
MAGIC_BYTES = b"\xAA\x50"
|
||||
|
||||
ALIGNMENT = {
|
||||
@ -187,7 +232,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
|
||||
|
||||
@ -240,15 +285,27 @@ 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.")
|
||||
return parse_int(strval, self.TYPES)
|
||||
return parse_int(strval, TYPES)
|
||||
|
||||
def parse_subtype(self, strval):
|
||||
if strval == "":
|
||||
return 0 # default
|
||||
return parse_int(strval, self.SUBTYPES.get(self.type, {}))
|
||||
return parse_int(strval, SUBTYPES.get(self.type, {}))
|
||||
|
||||
def parse_address(self, strval):
|
||||
if strval == "":
|
||||
@ -268,6 +325,14 @@ class PartitionDefinition(object):
|
||||
if self.size is None:
|
||||
raise ValidationError(self, "Size field is not set")
|
||||
|
||||
if self.name in TYPES and TYPES.get(self.name, "") != self.type:
|
||||
critical("WARNING: Partition has name '%s' which is a partition type, but does not match this partition's type (0x%x). Mistake in partition table?" % (self.name, self.type))
|
||||
all_subtype_names = []
|
||||
for names in (t.keys() for t in SUBTYPES.values()):
|
||||
all_subtype_names += names
|
||||
if self.name in all_subtype_names and SUBTYPES.get(self.type, {}).get(self.name, "") != self.subtype:
|
||||
critical("WARNING: Partition has name '%s' which is a partition subtype, but this partition has non-matching type 0x%x and subtype 0x%x. Mistake in partition table?" % (self.name, self.type, self.subtype))
|
||||
|
||||
STRUCT_FORMAT = "<2sBBLL16sL"
|
||||
|
||||
@classmethod
|
||||
@ -321,8 +386,8 @@ class PartitionDefinition(object):
|
||||
return ":".join(self.get_flags_list())
|
||||
|
||||
return ",".join([ self.name,
|
||||
lookup_keyword(self.type, self.TYPES),
|
||||
lookup_keyword(self.subtype, self.SUBTYPES.get(self.type, {})),
|
||||
lookup_keyword(self.type, TYPES),
|
||||
lookup_keyword(self.subtype, SUBTYPES.get(self.type, {})),
|
||||
addr_format(self.offset, False),
|
||||
addr_format(self.size, True),
|
||||
generate_text_flags()])
|
||||
@ -348,21 +413,26 @@ def parse_int(v, keywords={}):
|
||||
def main():
|
||||
global quiet
|
||||
global md5sum
|
||||
global offset_part_table
|
||||
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('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='?',
|
||||
default='-')
|
||||
parser.add_argument('--no-verify', help="Don't verify partition table fields", action='store_true')
|
||||
parser.add_argument('--verify', '-v', help="Verify partition table fields (deprecated, this behaviour is enabled by default and this flag does nothing.", action='store_true')
|
||||
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('input', help='Path to CSV or binary file to parse.', type=argparse.FileType('rb'))
|
||||
parser.add_argument('output', help='Path to output converted binary or CSV file. Will use stdout if omitted.',
|
||||
nargs='?', default='-')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
quiet = args.quiet
|
||||
md5sum = not args.disable_md5sum
|
||||
offset_part_table = int(args.offset, 0)
|
||||
input = args.input.read()
|
||||
input_is_binary = input[0:2] == PartitionDefinition.MAGIC_BYTES
|
||||
if input_is_binary:
|
||||
@ -373,17 +443,29 @@ def main():
|
||||
status("Parsing CSV input...")
|
||||
table = PartitionTable.from_csv(input)
|
||||
|
||||
if args.verify:
|
||||
if not args.no_verify:
|
||||
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:
|
||||
f.write(output)
|
||||
else:
|
||||
output = table.to_binary()
|
||||
with sys.stdout.buffer if args.output == '-' else open(args.output, 'wb') as f:
|
||||
try:
|
||||
stdout_binary = sys.stdout.buffer # Python 3
|
||||
except AttributeError:
|
||||
stdout_binary = sys.stdout
|
||||
with stdout_binary if args.output == '-' else open(args.output, 'wb') as f:
|
||||
f.write(output)
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user