diff --git a/ltchiptool/soc/ambz2/binary.py b/ltchiptool/soc/ambz2/binary.py index e0e6b67..f7a1957 100644 --- a/ltchiptool/soc/ambz2/binary.py +++ b/ltchiptool/soc/ambz2/binary.py @@ -28,6 +28,7 @@ Section, ) from .util.models.utils import FF_32 +from .util.ota import patch_firmware_for_ota class AmebaZ2Binary(SocInterface, ABC): @@ -110,6 +111,12 @@ def elf2bin(self, input: str, ota_idx: int) -> List[FirmwareBinary]: description="Firmware partition image for direct flashing", public=True, ) + out_ota1_ota = FirmwareBinary( + location=input, + name="firmware_is_ota", + offset=ota1_offset, + title="Application Image for OTA", + ) out_ptab = FirmwareBinary( location=input, name="part_table", @@ -215,6 +222,10 @@ def elf2bin(self, input: str, ota_idx: int) -> List[FirmwareBinary]: with out_ota1.write() as f: ota1 = data[ota1_offset:ota1_end] f.write(ota1) + with out_ota1_ota.write() as f: + ota1 = data[ota1_offset:ota1_end] + ota1_ota = patch_firmware_for_ota(ota1) + f.write(ota1_ota) return output.group() def detect_file_type( diff --git a/ltchiptool/soc/ambz2/util/models/images.py b/ltchiptool/soc/ambz2/util/models/images.py index da6804a..031b752 100644 --- a/ltchiptool/soc/ambz2/util/models/images.py +++ b/ltchiptool/soc/ambz2/util/models/images.py @@ -29,6 +29,9 @@ FLASH_CALIBRATION = b"\x99\x99\x96\x96\x3F\xCC\x66\xFC\xC0\x33\xCC\x03\xE5\xDC\x31\x62" +IMAGE_SIGNATURE_OFFSET = 0 +IMAGE_PUBLIC_KEY_OFFSET = 32 + @dataclass class Image(DataStruct): diff --git a/ltchiptool/soc/ambz2/util/ota.py b/ltchiptool/soc/ambz2/util/ota.py new file mode 100644 index 0000000..fdff561 --- /dev/null +++ b/ltchiptool/soc/ambz2/util/ota.py @@ -0,0 +1,10 @@ +# Copyright (c) Martin Prokopič 2024-12-02 + +from .models.images import IMAGE_PUBLIC_KEY_OFFSET, IMAGE_SIGNATURE_OFFSET + + +def patch_firmware_for_ota(data: bytes) -> bytes: + copy = bytearray(data) + copy[IMAGE_SIGNATURE_OFFSET] ^= 0xFF # negate first signature byte + copy[IMAGE_PUBLIC_KEY_OFFSET] ^= 0xFF # negate first pubkey byte + return bytes(copy) diff --git a/uf2tool/models/context.py b/uf2tool/models/context.py index e8851e7..b938ce1 100644 --- a/uf2tool/models/context.py +++ b/uf2tool/models/context.py @@ -91,6 +91,9 @@ def get_offset(self, part: str, offs: int) -> Optional[int]: return None return start + offs + def rewind(self) -> None: + self.seq = 0 + def read_next(self, scheme: OTAScheme) -> Optional[Tuple[str, int, bytes]]: """ Read next available data block for the specified OTA scheme. @@ -152,6 +155,10 @@ def collect_data(self, scheme: OTAScheme) -> Optional[Dict[int, BytesIO]]: if not self.board_name: raise ValueError("This UF2 is not readable, since no board name is present") + # rewind to the beginning of the UF2 so collect_data can be called + # multiple times + self.rewind() + out: Dict[int, BytesIO] = {} while True: ret = self.read_next(scheme)