Skip to content

Commit b9fcc9d

Browse files
authored
Merge pull request #455 from timg236/rpi-eeprom-config-padding
rpi-eeprom-config: Improve robustness of padding code
2 parents 7bbbd94 + 2c709e0 commit b9fcc9d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+328
-74
lines changed

rpi-eeprom-config

Lines changed: 48 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@ import time
1616

1717
IMAGE_SIZE = 512 * 1024
1818

19-
# Larger files won't with with "vcgencmd bootloader_config"
20-
MAX_FILE_SIZE = 2024
21-
ALIGN_SIZE = 4096
2219
BOOTCONF_TXT = 'bootconf.txt'
2320
BOOTCONF_SIG = 'bootconf.sig'
2421
PUBKEY_BIN = 'pubkey.bin'
@@ -39,6 +36,11 @@ FILE_HDR_LEN = 20
3936
FILENAME_LEN = 12
4037
TEMP_DIR = None
4138

39+
# Modifiable files are stored in a single 4K erasable sector.
40+
# The max content 4076 bytes because of the file header.
41+
ERASE_ALIGN_SIZE = 4096
42+
MAX_FILE_SIZE = ERASE_ALIGN_SIZE - FILE_HDR_LEN
43+
4244
DEBUG = False
4345
def debug(s):
4446
if DEBUG:
@@ -221,7 +223,7 @@ class ImageSection:
221223
self.offset = offset
222224
self.length = length
223225
self.filename = filename
224-
debug("ImageSection %x %x %x %s" % (magic, offset, length, filename))
226+
debug("ImageSection %x offset %d length %d %s" % (magic, offset, length, filename))
225227

226228
class BootloaderImage(object):
227229
def __init__(self, filename, output=None):
@@ -250,7 +252,6 @@ class BootloaderImage(object):
250252
"""
251253
offset = 0
252254
magic = 0
253-
found = False
254255
while offset < IMAGE_SIZE:
255256
magic, length = struct.unpack_from('>LL', self._bytes, offset)
256257
if magic == 0x0 or magic == 0xffffffff:
@@ -262,6 +263,7 @@ class BootloaderImage(object):
262263
if magic == FILE_MAGIC: # Found a file
263264
# Discard trailing null characters used to pad filename
264265
filename = self._bytes[offset + 8: offset + FILE_HDR_LEN].decode('utf-8').replace('\0', '')
266+
debug("section at %d length %d magic %08x %s" % (offset, length, magic, filename))
265267
self._sections.append(ImageSection(magic, offset, length, filename))
266268

267269
offset += 8 + length # length + type
@@ -272,26 +274,46 @@ class BootloaderImage(object):
272274
Returns the offset, length and whether this is the last section in the
273275
EEPROM for a modifiable file within the image.
274276
"""
275-
ret = (-1, -1, False)
277+
offset = -1
278+
length = -1
279+
is_last = False
280+
281+
next_offset = IMAGE_SIZE - ERASE_ALIGN_SIZE # Don't create padding inside the bootloader scratch page
276282
for i in range(0, len(self._sections)):
277283
s = self._sections[i]
278284
if s.magic == FILE_MAGIC and s.filename == filename:
279285
is_last = (i == len(self._sections) - 1)
280-
ret = (s.offset, s.length, is_last)
286+
offset = s.offset
287+
length = s.length
288+
break
289+
290+
# Find the start of the next non padding section
291+
i += 1
292+
while i < len(self._sections):
293+
if self._sections[i].magic == PAD_MAGIC:
294+
i += 1
295+
else:
296+
next_offset = self._sections[i].offset
281297
break
282-
debug('%s offset %d length %d last %s' % (filename, ret[0], ret[1], ret[2]))
298+
ret = (offset, length, is_last, next_offset)
299+
debug('%s offset %d length %d is-last %d next %d' % (filename, ret[0], ret[1], ret[2], ret[3]))
283300
return ret
284301

285302
def update(self, src_bytes, dst_filename):
286303
"""
287304
Replaces a modifiable file with specified byte array.
288305
"""
289-
hdr_offset, length, is_last = self.find_file(dst_filename)
306+
hdr_offset, length, is_last, next_offset = self.find_file(dst_filename)
307+
update_len = len(src_bytes) + FILE_HDR_LEN
308+
309+
if hdr_offset + update_len > IMAGE_SIZE - ERASE_ALIGN_SIZE:
310+
raise Exception('No space available - image past EOF.')
311+
290312
if hdr_offset < 0:
291313
raise Exception('Update target %s not found' % dst_filename)
292314

293-
if hdr_offset + len(src_bytes) + FILE_HDR_LEN > IMAGE_SIZE:
294-
raise Exception('EEPROM image size exceeded')
315+
if hdr_offset + update_len > next_offset:
316+
raise Exception('Update %d bytes is larger than section size %d' % (update_len, next_offset - hdr_offset))
295317

296318
new_len = len(src_bytes) + FILENAME_LEN + 4
297319
struct.pack_into('>L', self._bytes, hdr_offset + 4, new_len)
@@ -312,7 +334,7 @@ class BootloaderImage(object):
312334
# by convention bootconf.txt is the last section and there's no need to
313335
# pad to the end of the sector. This also ensures that the loopback
314336
# config read/write tests produce identical binaries.
315-
pad_bytes = ALIGN_SIZE - (pad_start % ALIGN_SIZE)
337+
pad_bytes = next_offset - pad_start
316338
if pad_bytes > 8 and not is_last:
317339
pad_bytes -= 8
318340
struct.pack_into('>i', self._bytes, pad_start, PAD_MAGIC)
@@ -358,10 +380,17 @@ class BootloaderImage(object):
358380
sys.stdout.write(self._bytes)
359381

360382
def get_file(self, filename):
361-
hdr_offset, length, is_last = self.find_file(filename)
383+
hdr_offset, length, is_last, next_offset = self.find_file(filename)
362384
offset = hdr_offset + 4 + FILE_HDR_LEN
363-
config_bytes = self._bytes[offset:offset+length-FILENAME_LEN-4]
364-
return config_bytes
385+
file_bytes = self._bytes[offset:offset+length-FILENAME_LEN-4]
386+
return file_bytes
387+
388+
def extract_files(self):
389+
for i in range(0, len(self._sections)):
390+
s = self._sections[i]
391+
if s.magic == FILE_MAGIC:
392+
file_bytes = self.get_file(s.filename)
393+
open(s.filename, 'wb').write(file_bytes)
365394

366395
def read(self):
367396
config_bytes = self.get_file('bootconf.txt')
@@ -457,6 +486,7 @@ See 'rpi-eeprom-update -h' for more information about the available EEPROM image
457486
parser.add_argument('-o', '--out', help='Name of output file', required=False)
458487
parser.add_argument('-d', '--digest', help='Signed boot only. The name of the .sig file generated by rpi-eeprom-dgst for config.txt ', required=False)
459488
parser.add_argument('-p', '--pubkey', help='Signed boot only. The name of the RSA public key file to store in the EEPROM', required=False)
489+
parser.add_argument('-x', '--extract', action='store_true', default=False, help='Extract the modifiable files (boot.conf, pubkey, signature)', required=False)
460490
parser.add_argument('eeprom', nargs='?', help='Name of EEPROM file to use as input')
461491
args = parser.parse_args()
462492

@@ -468,6 +498,9 @@ See 'rpi-eeprom-update -h' for more information about the available EEPROM image
468498

469499
if args.edit:
470500
edit_config(args.eeprom)
501+
elif args.eeprom is not None and args.extract:
502+
image = BootloaderImage(args.eeprom, args.out)
503+
image.extract_files()
471504
elif args.apply is not None:
472505
if not os.path.exists(args.apply):
473506
exit_error("config file '%s' not found" % args.apply)

test/bootconf-2024.txt

Lines changed: 0 additions & 28 deletions
This file was deleted.

test/bootconf-2025.txt

Lines changed: 0 additions & 28 deletions
This file was deleted.

test/bootconf-4076.txt

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
[all]
2+
BOOT_UART=0
3+
WAKE_ON_GPIO=1
4+
POWER_OFF_ON_HALT=0
5+
[none]
6+
userdata0=0x12345789
7+
userdata1=0x12345789
8+
userdata2=0x12345789
9+
userdata3=0x12345789
10+
userdata4=0x12345789
11+
userdata5=0x12345789
12+
userdata6=0x12345789
13+
userdata7=0x12345789
14+
userdata8=0x12345789
15+
userdata9=0x12345789
16+
usercert=ZZZZZZZZZZZZlhEAAAADAQABAAABAQDg2l41l7troIKOA0hk3p9y4KuITWBL/aaTMORoqmXfyqEONNULSMElaLWch/b8ScHmcS+kxkS5DtLmKFo1JI14IaQNL5fr4C6Dp23CyMGIgjp3ZFg9tXs/qWpw36Ge0MCxjabbFeKVcMXD10voMT0AHfJtQb2YfOl37ffzC4bR3phUnp0Ceqpl0Loe6hxUP/r4Jen1OKskdfjsldfjalAjn9ASdkjnkjbaAKjnLKJbaKJHDRDkllDAlciaIKSPX2b0uk2MJRJhfarMHDnmxZtEzqMgwLdLol9XVjiSu/7EUzR9Qtvs8xhf6XuUJPRD6OtJCb49L+bb/pXAej/GOk0f
17+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
18+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
19+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
20+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
21+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
22+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
23+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
24+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
25+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
26+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
27+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
28+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
29+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
30+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
31+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
32+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
33+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
34+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
35+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
36+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
37+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
38+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
39+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
40+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
41+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
42+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
43+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
44+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
45+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
46+
# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

test/bootconf-4077.txt

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
[all]
2+
BOOT_UART=0
3+
WAKE_ON_GPIO=1
4+
POWER_OFF_ON_HALT=0
5+
[none]
6+
userdata0=0x12345789
7+
userdata1=0x12345789
8+
userdata2=0x12345789
9+
userdata3=0x12345789
10+
userdata4=0x12345789
11+
userdata5=0x12345789
12+
userdata6=0x12345789
13+
userdata7=0x12345789
14+
userdata8=0x12345789
15+
userdata9=0x12345789
16+
usercert=ZZZZZZZZZZZZlhEAAAADAQABAAABAQDg2l41l7troIKOA0hk3p9y4KuITWBL/aaTMORoqmXfyqEONNULSMElaLWch/b8ScHmcS+kxkS5DtLmKFo1JI14IaQNL5fr4C6Dp23CyMGIgjp3ZFg9tXs/qWpw36Ge0MCxjabbFeKVcMXD10voMT0AHfJtQb2YfOl37ffzC4bR3phUnp0Ceqpl0Loe6hxUP/r4Jen1OKskdfjsldfjalAjn9ASdkjnkjbaAKjnLKJbaKJHDRDkllDAlciaIKSPX2b0uk2MJRJhfarMHDnmxZtEzqMgwLdLol9XVjiSu/7EUzR9Qtvs8xhf6XuUJPRD6OtJCb49L+bb/pXAej/GOk0f
17+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
18+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
19+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
20+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
21+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
22+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
23+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
24+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
25+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
26+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
27+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
28+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
29+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
30+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
31+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
32+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
33+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
34+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
35+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
36+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
37+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
38+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
39+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
40+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
41+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
42+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
43+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
44+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
45+
# 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789 0123456789
46+
# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[all]
2+
BOOT_UART=0
3+
WAKE_ON_GPIO=1
4+
POWER_OFF_ON_HALT=0
5+
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[all]
2+
BOOT_UART=0
3+
WAKE_ON_GPIO=1
4+
POWER_OFF_ON_HALT=0
5+
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[all]
2+
BOOT_UART=0
3+
WAKE_ON_GPIO=1
4+
POWER_OFF_ON_HALT=0
5+
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[all]
2+
BOOT_UART=0
3+
WAKE_ON_GPIO=1
4+
POWER_OFF_ON_HALT=0
5+
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[all]
2+
BOOT_UART=0
3+
WAKE_ON_GPIO=1
4+
POWER_OFF_ON_HALT=0
5+

0 commit comments

Comments
 (0)