super(ChecksumMismatch, self).__init__(msg)
+class PermissionDenied(BootloaderError):
+ def __init__(self, command):
+ msg = 'Target reported permission denied for command {}'.format(command)
+
+ super(PermissionDenied, self).__init__(msg)
+
class Command:
def __init__(self, num, name):
self._num = num
sys.stderr.write('File too large.\n')
return 3
+ # The bootloader only accepts chunks whose size is word-aligned:
+ num_extra = len(chunks[-1]) & 3
+
+ if num_extra != 0:
+ num_pad = 4 - extra
+ chunks[-1] += b'\xff' * num_pad
+
# Defaulting to zero seems too dangerous:
if self._offset is None:
sector0 = None
for i in range(len(chunks)):
sector = sector0 + i
- self._erase(sector)
+ # The bootloader will refuse to erase the second sector
+ # as it contains the precious flash configuration field.
+ if sector != 1:
+ self._erase(sector)
# Write first sector last, to prevent the bootloader from
# jumping to partially programmed code.
for i, chunk in reversed(list(enumerate(chunks))):
sector = sector0 + i
- self._load_chunk(chunk)
- self._program(sector)
+ if sector != 1:
+ self._load_chunk(chunk)
+ self._program(sector)
num_verify_errors = 0
raise InvalidArgument(self._last_command)
elif e == 3:
raise ChecksumMismatch(self._last_command)
+ elif e == 4:
+ raise PermissionDenied(self._last_command)
else:
msg = 'Target reported some other error for {}'.format(self._last_command)