diff --git a/docs/fw_binaries.md b/docs/fw_binaries.md index 7afa151..bb6bb5e 100644 --- a/docs/fw_binaries.md +++ b/docs/fw_binaries.md @@ -289,3 +289,142 @@ extract the FSBL and PMUFW from the complete boot image. configuration: * path +## For Rockchip devices + +Current implementation of support for the Rockchip SoCs, RAMboot and +SPL DFU are supported. + +As there's no implementation for Rockchip USB protocol support, it is +possible to push the DDR init files and SPL files from Rockchip but the next +step will fail. + +Mainline u-boot does not support boot from RAM and boot from SPL DFU, +it has to be patched. + +The patches have been sent to the u-boot mailing list by their authors +and not yet merged. The patches can all be found inside this +[merge request](https://gitlab.collabora.com/hardware-enablement/rockchip-3588/u-boot/-/merge_requests/7). + +### Using binary generated by Rockchip's ``boot_merger`` + +[example](../src/snagrecover/templates/rockchip-merger.yaml) + +Snagboot can upload the ``CODE471_OPTION`` and ``CODE472_OPTION`` of a binary +generated with the ``boot_merger`` tool and configuration files from +[Rockchip rkbin](https://github.com/radxa/rkbin/tree/develop-v2024.03/). + +In case of u-boot, this would mean to upload the TPL, SPL and then use SPL DFU +to boot u-boot proper (see later section for SPL DFU). + +An example configuration for rk3399 would be: +``` +[CHIP_NAME] +NAME=RK330C +[VERSION] +MAJOR=1 +MINOR=123 +[CODE471_OPTION] +NUM=1 +Path1=tpl/u-boot-tpl-dtb.bin +Sleep=1 +[CODE472_OPTION] +NUM=1 +Path1=spl/u-boot-spl-dtb.bin +Sleep=3000 +[LOADER_OPTION] +NUM=2 +LOADER1=FlashData +LOADER2=FlashBoot +FlashData=spl/u-boot-spl-dtb.bin +FlashBoot=u-boot.itb +[OUTPUT] +PATH=rk3399_uboot.bin +[FLAG] +471_RC4_OFF=false +``` + +The ``tpl/u-boot-tpl-dtb.bin``, ``spl/u-boot-spl-dtb.bin``, ``u-boot.itb`` +files are generated during u-boot's build. Please note has the ``LOADER_OPTION`` +is not handled by snagboot. + +The configuration parameters are: + +**xpl:** Binary blob generated with bootmerger. For instance, here, ``rk3399_uboot.bin``. + * path: path to the blob + +**u-boot-fit:** U-boot FIT image. + * path: Path to the FIT image. Typically, ``u-boot.itb`` + + +### Boot from Ram + +[example](../src/snagrecover/templates/rockchip-ramboot.yaml) + +When building u-boot with the previously mentioned patches, u-boot will generate two files: + +- ``u-boot-rockchip-usb471.bin`` +- ``u-boot-rockchip-usb472.bin`` + +These are the files needed to boot from RAM. + +The configuration parameters are: + +**code471:** File to use for maskrom code 0x471. + +configuration: + * path: Path to the ``u-boot-rockchip-usb471.bin`` file + * delay: Optional delay in milliseconds before loading next binary + +**code472:** File to use for maskrom code 0x472. + +configuration: + * path: Path to the ``u-boot-rockchip-usb472.bin`` file + + +### Boot from SPL DFU + +[example](../src/snagrecover/templates/rockchip-spl-dfu.yaml) + +To enable u-boot with SPL DFU support in the u-boot configuration, ensure that the +following options are enabled: + +``` +CONFIG_SPL_DM_USB_GADGET=y +CONFIG_SPL_USB_GADGET=y +CONFIG_SPL_DFU=y +``` + +On some systems, rebooting the system won't reset the memory content. This means that +booting over DFU after having done a boot from RAM will result in u-boot loading the +u-boot version from the boot from RAM boot and won't try to load u-boot over DFU. + +To solve this, disable boot from RAM with: + +``` +# CONFIG_SPL_RAM_DEVICE is not set +``` + +The (SPL) USB gadget driver needs to be enabled too. + +At the end of the build, the following files will be needed: + +- ``mkimage-in-simple-bin.mkimage-u-boot-tpl`` or ``mkimage-in-simple-bin.mkimage-rockchip-tpl`` +- ``mkimage-in-simple-bin.mkimage-u-boot-spl`` +- ``u-boot.itb`` + +The configuration parameters are: + +**code471:** File to use for maskrom code 0x471. + +configuration: + * path: Path to the TPL file. For instance, ``mkimage-in-simple-bin.mkimage-rockchip-tpl``. + * delay: Optional delay in milliseconds before loading next binary + +**code472:** File to use for maskrom code 0x472. + +configuration: + * path: Path to the SPL. For instance, ``mkimage-in-simple-bin.mkimage-u-boot-spl``. + * delay: Optional delay in milliseconds before loading next binary + +**u-boot-fit:** U-boot FIT image. + * path: Path to the FIT image. Typically, ``u-boot.itb`` diff --git a/src/snagrecover/50-snagboot.rules b/src/snagrecover/50-snagboot.rules index d4f4dde..f3dae0b 100644 --- a/src/snagrecover/50-snagboot.rules +++ b/src/snagrecover/50-snagboot.rules @@ -76,3 +76,21 @@ SUBSYSTEM=="usb", ATTRS{idVendor}=="0451", ATTRS{idProduct}=="d022", MODE="0660" #Xilinx rules SUBSYSTEM=="usb", ATTRS{idVendor}=="03fd", ATTRS{idProduct}=="0050", MODE="0660", TAG+="uaccess" + +#Rockchip systems +SUBSYSTEM=="usb", ATTRS{idVendor}=="2207", ATTRS{idProduct}=="2207", MODE="0660", TAG+="uaccess" +SUBSYSTEM=="usb", ATTRS{idVendor}=="2207", ATTRS{idProduct}=="110a", MODE="0660", TAG+="uaccess" +SUBSYSTEM=="usb", ATTRS{idVendor}=="2207", ATTRS{idProduct}=="110b", MODE="0660", TAG+="uaccess" +SUBSYSTEM=="usb", ATTRS{idVendor}=="2207", ATTRS{idProduct}=="300a", MODE="0660", TAG+="uaccess" +SUBSYSTEM=="usb", ATTRS{idVendor}=="2207", ATTRS{idProduct}=="301a", MODE="0660", TAG+="uaccess" +SUBSYSTEM=="usb", ATTRS{idVendor}=="2207", ATTRS{idProduct}=="310b", MODE="0660", TAG+="uaccess" +SUBSYSTEM=="usb", ATTRS{idVendor}=="2207", ATTRS{idProduct}=="310c", MODE="0660", TAG+="uaccess" +SUBSYSTEM=="usb", ATTRS{idVendor}=="2207", ATTRS{idProduct}=="320a", MODE="0660", TAG+="uaccess" +SUBSYSTEM=="usb", ATTRS{idVendor}=="2207", ATTRS{idProduct}=="320b", MODE="0660", TAG+="uaccess" +SUBSYSTEM=="usb", ATTRS{idVendor}=="2207", ATTRS{idProduct}=="320c", MODE="0660", TAG+="uaccess" +SUBSYSTEM=="usb", ATTRS{idVendor}=="2207", ATTRS{idProduct}=="330a", MODE="0660", TAG+="uaccess" +SUBSYSTEM=="usb", ATTRS{idVendor}=="2207", ATTRS{idProduct}=="330c", MODE="0660", TAG+="uaccess" +SUBSYSTEM=="usb", ATTRS{idVendor}=="2207", ATTRS{idProduct}=="330d", MODE="0660", TAG+="uaccess" +SUBSYSTEM=="usb", ATTRS{idVendor}=="2207", ATTRS{idProduct}=="330e", MODE="0660", TAG+="uaccess" +SUBSYSTEM=="usb", ATTRS{idVendor}=="2207", ATTRS{idProduct}=="350a", MODE="0660", TAG+="uaccess" +SUBSYSTEM=="usb", ATTRS{idVendor}=="2207", ATTRS{idProduct}=="350b", MODE="0660", TAG+="uaccess" diff --git a/src/snagrecover/config.py b/src/snagrecover/config.py index fa86a04..4f08ed6 100644 --- a/src/snagrecover/config.py +++ b/src/snagrecover/config.py @@ -52,6 +52,23 @@ "imx8mm": "1fc9:0134", "imx8mq": "1fc9:012b", "imx53" : "15a2:004e", + }, + "rockchip": { + "rv1108": "2207:110a", + "rv1126": "2207:110b", + "rk3066": "2207:300a", + "rk3036": "2207:301a", + "rk3188": "2207:310b", + "rk3128": "2207:310c", + "rk3288": "2207:320a", + "rk322x": "2207:320b", + "rk3328": "2207:320c", + "rk3368": "2207:330a", + "rk3399": "2207:330c", + "px30": "2207:330d", + "rk3308": "2207:330e", + "rk3568": "2207:350a", + "rk3588": "2207:350b" } } @@ -80,6 +97,8 @@ def init_config(args: list): if args.usb_path is None: if soc_family == "imx": usb_ids = default_usb_ids["imx"][soc_model] + elif soc_family == "rockchip": + usb_ids = default_usb_ids["rockchip"][soc_model] else: usb_ids = default_usb_ids[soc_family] diff --git a/src/snagrecover/firmware/firmware.py b/src/snagrecover/firmware/firmware.py index a177fd9..6d22203 100644 --- a/src/snagrecover/firmware/firmware.py +++ b/src/snagrecover/firmware/firmware.py @@ -146,6 +146,9 @@ def run_firmware(port, fw_name: str, subfw_name: str = ""): elif soc_family == "zynqmp": from snagrecover.firmware.zynqmp_fw import zynqmp_run zynqmp_run(port, fw_name, fw_blob, subfw_name) + elif soc_family == "rockchip": + from snagrecover.firmware.rk_fw import rockchip_run + rockchip_run(port, fw_name, fw_blob) else: raise Exception(f"Unsupported SoC family {soc_family}") logger.info(f"Done installing firmware {fw_name}") diff --git a/src/snagrecover/firmware/rk_fw.py b/src/snagrecover/firmware/rk_fw.py new file mode 100644 index 0000000..1700316 --- /dev/null +++ b/src/snagrecover/firmware/rk_fw.py @@ -0,0 +1,287 @@ +#!/usr/bin/python3 +# Copyright 2025 Collabora Ltd. +# +# SPDX-License-Identifier: GPL-2.0+ +# +# Author: Arnaud Patard +# +# Notes: +# to unpack / descramble encrypted parts, the rc4 key is inside u-boot's code. +# Some information used here are coming from rkdeveloptool, which is GPL-2.0+ + +import logging +import struct +import time +from crccheck import crc +from dataclasses import dataclass + +logger = logging.getLogger("snagrecover") +from snagrecover.protocols import rockchip +from snagrecover.protocols import dfu +from snagrecover.utils import BinFileHeader +from snagrecover.config import recovery_config + + +# List generated with a grep on rkbin repository +NEWIDB_LIST = ["rk3506", "rk3506b", "rk3528", "rk3562", "rk3566", "rk3568", "rk3576", "rk3583", "rk3588", "rv1103b", "rv1106"] + +BOOTTAG = b"BOOT" +LDRTAG = b"LDR " +TAG_LIST = [BOOTTAG, LDRTAG] +BOOTENTRYSIZE = 57 +BOOTHEADERENTRYSIZE = 6 +BOOTHEADERSIZE = 102 +BOOTHEADERTIMESIZE = 7 +RC4_KEY = bytearray([124, 78, 3, 4, 85, 5, 9, 7, 45, 44, 123, 56, 23, 13, 23, 17]) + + +@dataclass +class BootEntry(BinFileHeader): + size: int + type: int + name: bytes + data_offset: int + data_size: int + data_delay: int + + fmt = "> 8 + self.min_ver = self.version & 0xff + self.releasetime = BootReleaseTime.read(self.releasetime, 0) + # the code should possible check that the soc_model in cfg is matching + # this information but a mapping is needed. + self.chip = self.chip[::-1] + self.entry471 = BootHeaderEntry.read(self.entry471, 0) + self.entry472 = BootHeaderEntry.read(self.entry472, 0) + self.loader = BootHeaderEntry.read(self.loader, 0) + if self.rc4: + self.rc4 = False + else: + self.rc4 = True + if self.sign == 'S': + self.sign = True + else: + self.sign = False + + def __str__(self): + return f"{self.tag}, {self.size} ,{self.maj_ver}.{self.min_ver}, 0x{self.merge_version:0x}, {self.releasetime}, {self.chip}, {self.entry471}, {self.entry472}, {self.loader}, sign: {self.sign}, enc: {self.rc4}" + + +class RkCrc32(crc.Crc32Base): + """CRC-32/ROCKCHIP + """ + _names = ('CRC-32/ROCKCHIP') + _width = 32 + _poly = 0x04c10db7 + _initvalue = 0x00000000 + _reflect_input = False + _reflect_output = False + _xor_output = 0 + + +class LoaderFile(): + def __init__(self, blob): + self.blob = blob + offset = BOOTHEADERSIZE + self.header = BootHeader.read(self.blob, 0) + + offset = self.header.entry471.offset + self.entry471 = [] + for _i in range(self.header.entry471.count): + entry = BootEntry.read(self.blob, offset) + self.entry471.append(entry) + offset += BOOTENTRYSIZE + + offset = self.header.entry472.offset + self.entry472 = [] + for _i in range(self.header.entry472.count): + entry = BootEntry.read(self.blob, offset) + self.entry472.append(entry) + offset += BOOTENTRYSIZE + + offset = self.header.loader.offset + self.loader = [] + for _i in range(self.header.loader.count): + entry = BootEntry.read(self.blob, offset) + self.loader.append(entry) + offset += BOOTENTRYSIZE + crc32 = self.blob[-4:] + calc_crc32 = RkCrc32.calc(self.blob[:-4]) + (self.crc32,) = struct.unpack(" len(entry): + raise LoaderFileError(f"Invalid index {idx}. Only has {len(entry)} entries.") + e = entry[idx] + logger.debug(f"{e}") + return (self.blob[e.data_offset:e.data_offset+e.data_size], e.data_delay) + + def __str__(self): + return f"{self.header} crc: {self.crc32:02x}" + + +# Manual implementation of RC4, from Wikipedia's page +# Not very secure, so don't use it elsewhere. +class rc4(): + def __init__(self): + self.S = list(range(256)) + self.i = 0 + self.j = 0 + + def ksa(self, key): + keylength = len(key) + self.S = list(range(256)) + j = 0 + for i in range(256): + j = (j + self.S[i] + key[i % keylength]) % 256 + self.S[i], self.S[j] = self.S[j], self.S[i] + + def prga(self): + self.i = (self.i + 1) % 256 + self.j = (self.j + self.S[self.i]) % 256 + self.S[self.i], self.S[self.j] = self.S[self.j], self.S[self.i] + K = self.S[(self.S[self.i] + self.S[self.j]) % 256] + return K + + def encrypt(self, buf): + obuf = bytearray(len(buf)) + + for offset in list(range(len(buf))): + obuf[offset] = buf[offset] ^ self.prga() + return obuf + + +def rc4_encrypt(fw_blob): + + soc_model = recovery_config["soc_model"] + if soc_model in NEWIDB_LIST: + return fw_blob + + # Round to 4096 block size + blob_len = len(fw_blob) + padded_len = (blob_len+4095)//4096 * 4096 + fw_blob = bytearray(fw_blob) + fw_blob += bytearray([0]*(padded_len - blob_len)) + encoder = rc4() + encoder.ksa(RC4_KEY) + obuf = bytearray() + for i in range(padded_len): + obuf += encoder.encrypt(fw_blob[i*512:(i+1)*512]) + return obuf + + +def rockchip_run(dev, fw_name, fw_blob): + + if fw_name == 'code471': + logger.info("Downloading code471...") + rom = rockchip.RochipBootRom(dev) + blob = rc4_encrypt(fw_blob) + rom.write_blob(blob, 0x471) + elif fw_name == 'code472': + logger.info("Downloading code472...") + rom = rockchip.RochipBootRom(dev) + blob = rc4_encrypt(fw_blob) + rom.write_blob(blob, 0x472) + elif fw_name == "u-boot-fit": + id = dfu.search_partid(dev, "u-boot.itb") + if id is None: + logger.error("Missing u-boot.itb DFU partition") + dfu_cmd = dfu.DFU(dev, stm32=False) + dfu_cmd.get_status() + dfu_cmd.download_and_run(fw_blob, id, 0, len(fw_blob)) + dfu_cmd.get_status() + dfu_cmd.detach(id) + else: + fw = LoaderFile(fw_blob) + logger.info(f"{fw}") + rom = rockchip.RochipBootRom(dev) + for i in range(fw.header.entry471.count): + logger.info(f"Downloading entry 471 {i}...") + (data, delay) = fw.entry_data("471", i) + rom.write_blob(data, 0x471) + logger.info(f"Sleeping {delay}ms") + time.sleep(delay / 1000) + logger.info("Done") + for i in range(fw.header.entry472.count): + logger.info(f"Downloading entry 472 {i}...") + (data, delay) = fw.entry_data("472", i) + rom.write_blob(data, 0x472) + logger.info(f"Sleeping {delay}ms") + time.sleep(delay / 1000) + logger.info("Done") diff --git a/src/snagrecover/protocols/rockchip.py b/src/snagrecover/protocols/rockchip.py new file mode 100644 index 0000000..e81b951 --- /dev/null +++ b/src/snagrecover/protocols/rockchip.py @@ -0,0 +1,90 @@ +# Copyright 2025 Collabora Ltd. +# +# SPDX-License-Identifier: GPL-2.0+ +# +# Author: Arnaud Patard + + +from crccheck.crc import Crc16Ibm3740 +import logging +import usb + +from snagrecover import utils + +logger = logging.getLogger("snagrecover") + +class RochipBootRomError(Exception): + pass + +class RochipBootRom(): + def __init__(self, dev: usb.core.Device): + self.dev = dev + cfg = dev.get_active_configuration() + + eps_found = False + for intf in cfg.interfaces(): + ep_in, ep_out = None, None + for ep in intf.endpoints(): + is_bulk = (ep.bmAttributes & usb.ENDPOINT_TYPE_MASK) == usb.ENDPOINT_TYPE_BULK + is_in = (ep.bmAttributes & usb.ENDPOINT_TYPE_MASK) == usb.ENDPOINT_TYPE_BULK + if not is_bulk: + continue + is_in = (ep.bEndpointAddress & usb.ENDPOINT_DIR_MASK) == usb.ENDPOINT_IN + if is_in: + ep_in = ep.bEndpointAddress + else: + ep_out = ep.bEndpointAddress + if not ((ep_in is None) or (ep_out is None)): + eps_found = True + break + if not eps_found: + raise RochipBootRomError("No BULK IN/OUT endpoint pair found in device") + self.ep_in = ep_in + self.ep_out = ep_out + + def __write_chunk(self, code: int, chunk: bytes) -> bool: + logger.debug(f"Sending {len(chunk)} bytes") + return self.dev.ctrl_transfer(usb.TYPE_VENDOR, 0x0c, 0, code, chunk, timeout=5000) + + def write_blob(self, blob: bytes, code: int) -> bool: + if code != 0x471 and code != 0x472: + raise RochipBootRomError("Invalid code value. Can only be 0x471 or 0x472") + crc = Crc16Ibm3740() + total_written = 0 + crc_sent = False + for chunk in utils.dnload_iter(blob, 4096): + chunk_len = len(chunk) + if chunk_len == 4096: + crc.process(chunk) + elif chunk_len == 4095: + chunk.append(0x00) + crc.process(chunk) + else: + crc.process(chunk) + crcbytes = crc.final() + chunk = bytearray(chunk) + chunk.append(crcbytes >> 8) + chunk.append(crcbytes & 0xff) + crc_sent = True + written = self.__write_chunk(code, chunk) + ret = written == len(chunk) + if ret is False: + return ret + total_written += written + if chunk_len+2 == 4096: + chunk = [0x00] + written = self.__write_chunk(code, chunk) + ret = written == len(chunk) + if ret is False: + return ret + if crc_sent is False: + chunk = bytearray() + crcbytes = crc.final() + chunk.append(crcbytes >> 8) + chunk.append(crcbytes & 0xff) + written = self.__write_chunk(code, chunk) + ret = written == len(chunk) + if ret is False: + return ret + + return True diff --git a/src/snagrecover/recoveries/rockchip.py b/src/snagrecover/recoveries/rockchip.py new file mode 100644 index 0000000..ce9ff1c --- /dev/null +++ b/src/snagrecover/recoveries/rockchip.py @@ -0,0 +1,54 @@ +import usb +import logging +logger = logging.getLogger("snagrecover") +from snagrecover.firmware.firmware import run_firmware +from snagrecover.utils import get_usb +from snagrecover.utils import cli_error +from snagrecover.config import recovery_config +import time + + +def main(): + usb_addr = recovery_config["usb_path"] + dev = get_usb(usb_addr) + + # Blob made with boot_merger + if "xpl" in recovery_config["firmware"]: + try: + run_firmware(dev, "xpl") + usb.util.dispose_resources(dev) + except Exception as e: + cli_error(f"Failed to run firmware: {e}") + + # u-boot binaries. + elif "code471" in recovery_config["firmware"] and "code472" in recovery_config["firmware"]: + try: + run_firmware(dev, "code471") + usb.util.dispose_resources(dev) + except Exception as e: + cli_error(f"Failed to run code471 firmware: {e}") + if "delay" in recovery_config["firmware"]["code471"]: + delay = recovery_config["firmware"]["code471"]["delay"] + logger.info(f"Sleeping {delay}ms") + time.sleep(delay / 1000) + try: + run_firmware(dev, "code472") + usb.util.dispose_resources(dev) + except Exception as e: + cli_error(f"Failed to run code472 firmware: {e}") + if "delay" in recovery_config["firmware"]["code472"]: + delay = recovery_config["firmware"]["code472"]["delay"] + logger.info(f"Sleeping {delay}ms") + time.sleep(delay / 1000) + else: + cli_error(("Missing xpl or " + "code471 (*_ddr_*.bin' or 'mkimage-in-simple-bin.mkimage-u-boot-tpl') / " + "code472 ('*_usbplug_*.bin' or 'mkimage-in-simple-bin.mkimage-u-boot-spl')" + "binary configuration.")) + + if "u-boot-fit" in recovery_config["firmware"]: + try: + dev = get_usb(usb_addr) + run_firmware(dev, "u-boot-fit") + except Exception as e: + cli_error(f"Failed to load u-boot.itb: {e}") diff --git a/src/snagrecover/supported_socs.yaml b/src/snagrecover/supported_socs.yaml index 8bb71ce..137ea97 100644 --- a/src/snagrecover/supported_socs.yaml +++ b/src/snagrecover/supported_socs.yaml @@ -57,6 +57,10 @@ tested: family: stm32mp zynqmp: family: zynqmp + rk3399: + family: rockchip + rk3588: + family: rockchip untested: a10: family: sunxi @@ -144,4 +148,29 @@ untested: family: sunxi v853: family: sunxi - + rv1108: + family: rockchip + rv1126: + family: rockchip + rk3066: + family: rockchip + rk3036: + family: rockchip + rk3188: + family: rockchip + rk3128: + family: rockchip + rk3288: + family: rockchip + rk322x: + family: rockchip + rk3328: + family: rockchip + rk3368: + family: rockchip + px30: + family: rockchip + rk3308: + family: rockchip + rk3568: + family: rockchip diff --git a/src/snagrecover/templates/rockchip-merger.yaml b/src/snagrecover/templates/rockchip-merger.yaml new file mode 100644 index 0000000..b5a8269 --- /dev/null +++ b/src/snagrecover/templates/rockchip-merger.yaml @@ -0,0 +1,6 @@ +xpl: + # u-boot TPL+SPL with SPL configured for DFU boot + path: rk3399_uboot.bin +u-boot-fit: + # proper u-boot + path: u-boot.itb diff --git a/src/snagrecover/templates/rockchip-ramboot.yaml b/src/snagrecover/templates/rockchip-ramboot.yaml new file mode 100644 index 0000000..e87dd7a --- /dev/null +++ b/src/snagrecover/templates/rockchip-ramboot.yaml @@ -0,0 +1,5 @@ +code471: + path: u-boot-rockchip-usb471.bin + delay: 1 +code472: + path: u-boot-rockchip-usb472.bin diff --git a/src/snagrecover/templates/rockchip-spl-dfu.yaml b/src/snagrecover/templates/rockchip-spl-dfu.yaml new file mode 100644 index 0000000..d815733 --- /dev/null +++ b/src/snagrecover/templates/rockchip-spl-dfu.yaml @@ -0,0 +1,8 @@ +code471: + path: mkimage-in-simple-bin.mkimage-u-boot-tpl + delay: 1 +code472: + path: mkimage-in-simple-bin.mkimage-u-boot-spl + delay: 10000 +u-boot-fit: + path: u-boot.itb diff --git a/src/snagrecover/utils.py b/src/snagrecover/utils.py index 8c515eb..28fc6fb 100644 --- a/src/snagrecover/utils.py +++ b/src/snagrecover/utils.py @@ -191,6 +191,9 @@ def get_recovery(soc_family: str): elif soc_family == "zynqmp": from snagrecover.recoveries.zynqmp import main as zynqmp_recovery return zynqmp_recovery + elif soc_family == "rockchip": + from snagrecover.recoveries.rockchip import main as rockchip_recovery + return rockchip_recovery else: cli_error(f"unsupported board family {soc_family}") @@ -203,16 +206,16 @@ class BinFileHeader(): fmt = "" class_size = 0 - offset = 0 + class_offset = 0 @classmethod def read(cls, data, offset=0): obj = cls(*struct.unpack(cls.fmt, data[offset:offset + cls.class_size])) - obj.offset = offset + obj.class_offset = offset return obj @classmethod def write(cls, self, data): - offset = self.offset + offset = self.class_offset data[offset:offset + cls.class_size] = struct.pack(cls.fmt, *astuple(self))