X-Git-Url: http://git.code-monkey.de/?a=blobdiff_plain;f=tools%2Fupdate-firmware;h=306674031a8784291cc5c7d82430fe3a0d7c0f02;hb=HEAD;hp=32381dc47393ac39b32d4819d5f0ddbb54214485;hpb=3350b7e23a8afca5882b895c9a570a490f0c7502;p=gps-watch.git diff --git a/tools/update-firmware b/tools/update-firmware index 32381dc..3066740 100755 --- a/tools/update-firmware +++ b/tools/update-firmware @@ -1,4 +1,25 @@ #!/usr/bin/env python3 +# +# Copyright (c) 2019-2020 Tilman Sauerbeck (tilman at code-monkey de) +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import argparse import serial @@ -94,6 +115,12 @@ class ChecksumMismatch(BootloaderError): 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 @@ -162,6 +189,13 @@ class Application: 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 @@ -179,15 +213,19 @@ class Application: 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 @@ -295,6 +333,8 @@ class Application: 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)