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
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
def mcuboot(device): mb = McuBoot(device) mb.open() yield mb mb.close()
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