示例#1
0
def open_mboot() -> McuBoot:
    """Open USB communication with RT5xx boot-loader

    :return: McuBoot instance
    :raises ConnectionError: if device not connected
    """
    assert not TEST_IMG_CONTENT

    devs = []
    for _ in range(
            5
    ):  # try three times to find USB device (wait until shadows registers are ready)
        devs = scan_usb("RT5xx")
        if len(devs) == 1:
            break

        sleep(1)

    if len(devs) != 1:
        raise ConnectionError(
            "RT5xx not connected via USB, "
            "ensure BOOT CONFIG SW7 is ON,OFF,ON and connect USB cable via J38"
        )

    mboot = McuBoot(devs[0], True)
    mboot.open()
    assert mboot.is_opened

    # test connection
    # blhost -u 0x1FC9,0x20 get-property 1
    res = mboot.get_property(PropertyTag.CURRENT_VERSION)
    assert res is not None

    return mboot
示例#2
0
def init_flashloader(cpu_params: CpuParams) -> McuBoot:
    """Load an execute flash-loader binary in i.MX-RT
       The function signs the flashloader if needed (if HAB enabled)

       :param cpu_params: processor specific parameters of the test
       :return: McuBoot instance to communicate with flash-loader
       :raises ConnectionError: if connection cannot be established
       """
    devs = mboot_scan_usb(cpu_params.com_processor_name
                          )  # check whether flashloader is already running
    if len(devs) == 0:
        # if flash-loader not running yet, it must be downloaded to RAM and launched
        flshldr_img = BootImgRT.parse(
            load_binary(cpu_params.data_dir, 'ivt_flashloader.bin'))

        devs = sdp_scan_usb(cpu_params.com_processor_name)
        if len(devs) != 1:
            raise ConnectionError('Cannot connect to ROM bootloader')

        with SDP(devs[0], cmd_exception=True) as sd:
            assert sd.is_opened
            try:
                sd.read(INT_RAM_ADDR_CODE, 4)  # dummy read to receive response
            except SdpCommandError:  # there is an exception if HAB is locked, cause read not supported
                pass

            if (sd.status_code
                    == StatusCode.HAB_IS_LOCKED) and (sd.response_value
                                                      == ResponseValue.LOCKED):
                auth_flshldr_img = BootImgRT(flshldr_img.address,
                                             BootImgRT.IVT_OFFSET_OTHER)
                _to_authenticated_image(
                    cpu_params, auth_flshldr_img, flshldr_img.app.data, 0,
                    flshldr_img.ivt.app_address
                )  # entry addr cannot be detected from img
            else:
                auth_flshldr_img = flshldr_img
            assert sd.write_file(auth_flshldr_img.address,
                                 auth_flshldr_img.export())
            try:
                assert sd.jump_and_run(auth_flshldr_img.address +
                                       auth_flshldr_img.ivt_offset)
            except SdpCommandError:
                pass  # SDP may return an exception if HAB locked

        for _ in range(10):  # wait 10 sec until flash-loader is inited
            sleep(1)
            # Scan for MCU-BOOT device
            devs = mboot_scan_usb(cpu_params.com_processor_name)
            if len(devs) == 1:
                break

    if len(devs) != 1:
        raise ConnectionError('Cannot connect to Flash-Loader')

    result = McuBoot(devs[0], cmd_exception=True)
    result.open()
    assert result.is_opened
    result.reopen = False  # reopen not supported for RT1050???
    return result
示例#3
0
def mcuboot(device):
    mb = McuBoot(device)
    mb.open()
    yield mb
    mb.close()
示例#4
0
class Nitrokey3Bootloader(Nitrokey3Base):
    """A Nitrokey 3 device running the bootloader."""
    def __init__(self, device: RawHid):
        from . import PID_NITROKEY3_BOOTLOADER, VID_NITROKEY

        if (device.vid, device.pid) != (VID_NITROKEY,
                                        PID_NITROKEY3_BOOTLOADER):
            raise ValueError("Not a Nitrokey 3 device: expected VID:PID "
                             f"{VID_NITROKEY:x}:{PID_NITROKEY3_BOOTLOADER:x}, "
                             f"got {device.vid:x}:{device.pid:x}")
        self._path = device.path
        self.device = McuBoot(device)

    def __enter__(self) -> "Nitrokey3Bootloader":
        self.device.open()
        return self

    @property
    def path(self) -> str:
        if isinstance(self._path, bytes):
            return self._path.decode("UTF-8")
        return self._path

    @property
    def name(self) -> str:
        return "Nitrokey 3 Bootloader"

    @property
    def status(self) -> Tuple[int, str]:
        code = self.device.status_code
        message = StatusCode.desc(code)
        return (code, message)

    def close(self) -> None:
        self.device.close()

    def reboot(self) -> None:
        if not self.device.reset(reopen=False):
            # On Windows, this function returns false even if the reset was successful
            if platform.system() == "Windows":
                logger.warning("Failed to reboot Nitrokey 3 bootloader")
            else:
                raise Exception("Failed to reboot Nitrokey 3 bootloader")

    def uuid(self) -> Optional[int]:
        uuid = self.device.get_property(
            PropertyTag.UNIQUE_DEVICE_IDENT)  # type: ignore[arg-type]
        if not uuid:
            raise ValueError("Missing response for UUID property query")
        if len(uuid) != UUID_LEN:
            raise ValueError(f"UUID response has invalid length {len(uuid)}")

        # See GetProperties::device_uuid in the lpc55 crate:
        # https://github.com/lpc55/lpc55-host/blob/main/src/bootloader/property.rs#L222
        wrong_endian = (uuid[3] << 96) + (uuid[2] << 64) + (
            uuid[1] << 32) + uuid[0]
        right_endian = wrong_endian.to_bytes(16, byteorder="little")
        return int.from_bytes(right_endian, byteorder="big")

    def update(
        self,
        image: bytes,
        callback: Optional[Callable[[int, int], None]] = None,
        check_errors: bool = False,
    ) -> bool:
        return self.device.receive_sb_file(
            image,
            progress_callback=callback,
            check_errors=check_errors,
        )

    @staticmethod
    def list() -> List["Nitrokey3Bootloader"]:
        from . import PID_NITROKEY3_BOOTLOADER, VID_NITROKEY

        device_filter = USBDeviceFilter(
            f"0x{VID_NITROKEY:x}:0x{PID_NITROKEY3_BOOTLOADER:x}")
        devices = []
        for device in RawHid.enumerate(device_filter):
            # TODO: remove assert if https://github.com/NXPmicro/spsdk/issues/32 is fixed
            assert isinstance(device, RawHid)
            try:
                devices.append(Nitrokey3Bootloader(device))
            except ValueError:
                logger.warn(
                    f"Invalid Nitrokey 3 bootloader returned by enumeration: {device}"
                )
        return devices

    @staticmethod
    def open(path: str) -> Optional["Nitrokey3Bootloader"]:
        device_filter = USBDeviceFilter(path)
        devices = RawHid.enumerate(device_filter)
        if len(devices) == 0:
            logger.warn(f"No HID device at {path}")
            return None
        if len(devices) > 1:
            logger.warn(f"Multiple HID devices at {path}: {devices}")
            return None

        try:
            # TODO: remove assert if https://github.com/NXPmicro/spsdk/issues/32 is fixed
            assert isinstance(devices[0], RawHid)
            return Nitrokey3Bootloader(devices[0])
        except ValueError:
            logger.warn(f"No Nitrokey 3 bootloader at path {path}",
                        exc_info=sys.exc_info())
            return None