forked from espressif/esp-idf
Merge branch 'bugfix/strict_data_partition_alignment' into 'master'
partition_table: warn if data partition offset is not 4kB aligned Closes IDFGH-5572 and IDFGH-5630 See merge request espressif/esp-idf!14902
This commit is contained in:
@@ -92,6 +92,19 @@ def get_subtype_as_int(ptype, subtype):
|
|||||||
return subtype
|
return subtype
|
||||||
|
|
||||||
|
|
||||||
|
ALIGNMENT = {
|
||||||
|
APP_TYPE: 0x10000,
|
||||||
|
DATA_TYPE: 0x4,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
STRICT_DATA_ALIGNMENT = 0x1000
|
||||||
|
|
||||||
|
|
||||||
|
def get_alignment_for_type(ptype):
|
||||||
|
return ALIGNMENT.get(ptype, ALIGNMENT[DATA_TYPE])
|
||||||
|
|
||||||
|
|
||||||
quiet = False
|
quiet = False
|
||||||
md5sum = True
|
md5sum = True
|
||||||
secure = False
|
secure = False
|
||||||
@@ -161,7 +174,7 @@ class PartitionTable(list):
|
|||||||
raise InputError('CSV Error: Partitions overlap. Partition at line %d sets offset 0x%x. Previous partition ends 0x%x'
|
raise InputError('CSV Error: Partitions overlap. Partition at line %d sets offset 0x%x. Previous partition ends 0x%x'
|
||||||
% (e.line_no, e.offset, last_end))
|
% (e.line_no, e.offset, last_end))
|
||||||
if e.offset is None:
|
if e.offset is None:
|
||||||
pad_to = 0x10000 if e.type == APP_TYPE else 4
|
pad_to = get_alignment_for_type(e.type)
|
||||||
if last_end % pad_to != 0:
|
if last_end % pad_to != 0:
|
||||||
last_end += pad_to - (last_end % pad_to)
|
last_end += pad_to - (last_end % pad_to)
|
||||||
e.offset = last_end
|
e.offset = last_end
|
||||||
@@ -211,10 +224,10 @@ class PartitionTable(list):
|
|||||||
|
|
||||||
# print sorted duplicate partitions by name
|
# print sorted duplicate partitions by name
|
||||||
if len(duplicates) != 0:
|
if len(duplicates) != 0:
|
||||||
print('A list of partitions that have the same name:')
|
critical('A list of partitions that have the same name:')
|
||||||
for p in sorted(self, key=lambda x:x.name):
|
for p in sorted(self, key=lambda x:x.name):
|
||||||
if len(duplicates.intersection([p.name])) != 0:
|
if len(duplicates.intersection([p.name])) != 0:
|
||||||
print('%s' % (p.to_csv()))
|
critical('%s' % (p.to_csv()))
|
||||||
raise InputError('Partition names must be unique')
|
raise InputError('Partition names must be unique')
|
||||||
|
|
||||||
# check for overlaps
|
# check for overlaps
|
||||||
@@ -230,12 +243,12 @@ class PartitionTable(list):
|
|||||||
otadata_duplicates = [p for p in self if p.type == TYPES['data'] and p.subtype == SUBTYPES[DATA_TYPE]['ota']]
|
otadata_duplicates = [p for p in self if p.type == TYPES['data'] and p.subtype == SUBTYPES[DATA_TYPE]['ota']]
|
||||||
if len(otadata_duplicates) > 1:
|
if len(otadata_duplicates) > 1:
|
||||||
for p in otadata_duplicates:
|
for p in otadata_duplicates:
|
||||||
print(p.name, p.type, p.subtype)
|
critical('%s' % (p.to_csv()))
|
||||||
raise InputError('Found multiple otadata partitions. Only one partition can be defined with type="data"(1) and subtype="ota"(0).')
|
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:
|
if len(otadata_duplicates) == 1 and otadata_duplicates[0].size != 0x2000:
|
||||||
p = otadata_duplicates[0]
|
p = otadata_duplicates[0]
|
||||||
print(p.name, p.type, p.subtype, p.offset, p.size)
|
critical('%s' % (p.to_csv()))
|
||||||
raise InputError('otadata partition must have size = 0x2000')
|
raise InputError('otadata partition must have size = 0x2000')
|
||||||
|
|
||||||
def flash_size(self):
|
def flash_size(self):
|
||||||
@@ -287,11 +300,6 @@ class PartitionTable(list):
|
|||||||
class PartitionDefinition(object):
|
class PartitionDefinition(object):
|
||||||
MAGIC_BYTES = b'\xAA\x50'
|
MAGIC_BYTES = b'\xAA\x50'
|
||||||
|
|
||||||
ALIGNMENT = {
|
|
||||||
APP_TYPE: 0x10000,
|
|
||||||
DATA_TYPE: 0x04,
|
|
||||||
}
|
|
||||||
|
|
||||||
# dictionary maps flag name (as used in CSV flags list, property name)
|
# dictionary maps flag name (as used in CSV flags list, property name)
|
||||||
# to bit set in flags words in binary format
|
# to bit set in flags words in binary format
|
||||||
FLAGS = {
|
FLAGS = {
|
||||||
@@ -388,10 +396,15 @@ class PartitionDefinition(object):
|
|||||||
raise ValidationError(self, 'Subtype field is not set')
|
raise ValidationError(self, 'Subtype field is not set')
|
||||||
if self.offset is None:
|
if self.offset is None:
|
||||||
raise ValidationError(self, 'Offset field is not set')
|
raise ValidationError(self, 'Offset field is not set')
|
||||||
align = self.ALIGNMENT.get(self.type, 4)
|
align = get_alignment_for_type(self.type)
|
||||||
if self.offset % align:
|
if self.offset % align:
|
||||||
raise ValidationError(self, 'Offset 0x%x is not aligned to 0x%x' % (self.offset, align))
|
raise ValidationError(self, 'Offset 0x%x is not aligned to 0x%x' % (self.offset, align))
|
||||||
if self.size % align and secure:
|
# The alignment requirement for non-app partition is 4 bytes, but it should be 4 kB.
|
||||||
|
# Print a warning for now, make it an error in IDF 5.0 (IDF-3742).
|
||||||
|
if self.type != APP_TYPE and self.offset % STRICT_DATA_ALIGNMENT:
|
||||||
|
critical('WARNING: Partition %s not aligned to 0x%x.'
|
||||||
|
'This is deprecated and will be considered an error in the future release.' % (self.name, STRICT_DATA_ALIGNMENT))
|
||||||
|
if self.size % align and secure and self.type == APP_TYPE:
|
||||||
raise ValidationError(self, 'Size 0x%x is not aligned to 0x%x' % (self.size, align))
|
raise ValidationError(self, 'Size 0x%x is not aligned to 0x%x' % (self.size, align))
|
||||||
if self.size is None:
|
if self.size is None:
|
||||||
raise ValidationError(self, 'Size field is not set')
|
raise ValidationError(self, 'Size field is not set')
|
||||||
|
@@ -451,6 +451,19 @@ ota_1, 0, ota_1, , 1M,
|
|||||||
self.assertIn('WARNING', sys.stderr.getvalue())
|
self.assertIn('WARNING', sys.stderr.getvalue())
|
||||||
self.assertIn('partition subtype', sys.stderr.getvalue())
|
self.assertIn('partition subtype', sys.stderr.getvalue())
|
||||||
|
|
||||||
|
sys.stderr = io.StringIO()
|
||||||
|
csv_3 = 'nvs, data, nvs, 0x8800, 32k'
|
||||||
|
gen_esp32part.PartitionTable.from_csv(csv_3).verify()
|
||||||
|
self.assertIn('WARNING', sys.stderr.getvalue())
|
||||||
|
self.assertIn('not aligned to 0x1000', sys.stderr.getvalue())
|
||||||
|
|
||||||
|
sys.stderr = io.StringIO()
|
||||||
|
csv_4 = 'factory, app, factory, 0x10000, 0x100100\n' \
|
||||||
|
'nvs, data, nvs, , 32k'
|
||||||
|
gen_esp32part.PartitionTable.from_csv(csv_4).verify()
|
||||||
|
self.assertIn('WARNING', sys.stderr.getvalue())
|
||||||
|
self.assertIn('not aligned to 0x1000', sys.stderr.getvalue())
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
sys.stderr = sys.__stderr__
|
sys.stderr = sys.__stderr__
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user