diff options
author | Farouk Bouabid <farouk.bouabid@theobroma-systems.com> | 2023-10-13 11:50:58 +0200 |
---|---|---|
committer | Farouk Bouabid <farouk.bouabid@theobroma-systems.com> | 2023-10-13 12:16:22 +0200 |
commit | 893ef579c6ca9e2cbcc09cb2112e0b06b2b07556 (patch) | |
tree | d689f5e12884d93ce4012b90eab64f3d22fdcb29 | |
parent | b5707693f5ec9d8f7ef8c51c5ac78ae4f39a6858 (diff) |
mule-attiny: i2c_flash: implement bl_data reading from flashloader
After entering the flashloader mode, clearing the boot request gpio
sets the flashloader into read-only mode where the flashing tool can read
bootloader data through i2c (i2c-write ops are ignored).
This data contain:
* Bootloader version
This tool will print out all bootloader data to the console.
Relates-to: RNG-147
Signed-off-by: Farouk Bouabid <farouk.bouabid@theobroma-systems.com>
-rwxr-xr-x | mule-attiny/i2c-flash/src/mule-attiny_i2c_flash/i2c_flash.py | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/mule-attiny/i2c-flash/src/mule-attiny_i2c_flash/i2c_flash.py b/mule-attiny/i2c-flash/src/mule-attiny_i2c_flash/i2c_flash.py index c867558..7beea78 100755 --- a/mule-attiny/i2c-flash/src/mule-attiny_i2c_flash/i2c_flash.py +++ b/mule-attiny/i2c-flash/src/mule-attiny_i2c_flash/i2c_flash.py @@ -11,6 +11,9 @@ from time import sleep from argparse import ArgumentParser import pathlib import logging +from abc import abstractmethod +from enum import IntEnum + # Bootloader I2C slave address BL_I2C_DEV = 0x6f # Reuse isl1208 address @@ -82,6 +85,83 @@ class BootModeController: raise Exception("UPDI Reset command failed!") +class BLHdrID(IntEnum): + VERSION = 0 + # Add other bootloader header IDs here + + +def get_blhdr(blhdr): + id = (blhdr & (0b111 << 5)) + if id == BLHdrID.VERSION: + return BLVersionHdr(blhdr) + # Add other bootloader header IDs here + raise Exception(f"Unknown {id} ID for payload header") + + +class BLHdr(): + def __init__(self, hdr): + self.hdr = hdr + + @abstractmethod + def len(self): + """Returns length of payload excluding header""" + pass + + @abstractmethod + def payload_class(self): + """Returns the class to use for representing the data following the header""" + pass + + +class BLVersionHdr(BLHdr): + DIRTY_BIT_p = 4 + DIRTY_BIT_m = (0b1 << DIRTY_BIT_p) + LAST_HASH_CHAR_p = 0 + LAST_HASH_CHAR_m = (0xf << LAST_HASH_CHAR_p) + + def len(self): + """1B for MAJOR + 1B for MINOR + 1B for PATCH + 1B for NCOMMITS + 3B for 6 hex digits of the hash""" + return 7 + + def payload_class(self): + return BLVersion + + def is_dirty(self): + return bool(self.hdr & BLVersionHdr.DIRTY_BIT_m) + + def last_hash(self): + return self.hdr & BLVersionHdr.LAST_HASH_CHAR_m + + +class BLVersion(): + def __init__(self, header, payload): + self.major, self.minor, self.patch, self.ncommits, hash_12, hash_34, hash_56 = payload + self.header = header + self.dirty = self.header.is_dirty() + self.hash = f"{hash_12:02x}{hash_34:02x}{hash_56:02x}{self.header.last_hash():0x}" + + def __str__(self): + return f"Bootloader v{self.major}.{self.minor}.{self.patch}-{self.ncommits}-g{self.hash}{'-dirty' if self.dirty else ''} is online" # noqa: E501 + + +class BLParser(): + @classmethod + def parse(cls, payload): + if not payload: + logging.error("No bootloader data is available!") + return + cursor = 0 + while cursor < len(payload): + blhdr = get_blhdr(payload[cursor]) + clss = blhdr.payload_class() + cursor += 1 + if len(payload) < cursor + blhdr.len(): + logging.error(f"Invalid data header of type {type(blhdr).__name__}") + return + yield clss(blhdr, payload[cursor:cursor + blhdr.len()]) + cursor += blhdr.len() + + def crc16_xmodem(data): # Credits: https://gist.github.com/oysstu/68072c44c02879a2abf94ef350d1c7c6?permalink_comment_id=3943460#gistcomment-3943460 # noqa: E501 ''' @@ -190,6 +270,22 @@ def main(): try: # Request flashloader through bootloader (Set to read-only-mode by default) bootCtrl.enterFlashloader() + + bus = SMBus(args.i2c_bus) + bl_raw_data = [] + while True: + try: + # Read bl_data byte per byte + bl_raw_data.append(bus.read_byte(BL_I2C_DEV)) + except IOError: + # Bootloader finished sending bl_data + break + + bl_data = BLParser.parse(bl_raw_data) + + for d in bl_data: + logging.info(d) + bootCtrl.exitRoMode() ret = fw_flash(_bin, args.i2c_bus) |