diff --git a/strategies/tftpstrategy.py b/strategies/tftpstrategy.py index 4d66cca..bd8b18e 100644 --- a/strategies/tftpstrategy.py +++ b/strategies/tftpstrategy.py @@ -180,9 +180,13 @@ def _resolve_tftp_server_ip(self): logger.info("Using exporter external_ip: %s", exporter_ip) return exporter_ip - def _prepare_uboot_commands(self, staged_file, tftp_server_ip): + def _prepare_uboot_commands(self, staged_file, tftp_server_ip, staged_initrd=None): """Prepare a fresh set of U-Boot init commands for this boot attempt.""" - init_commands = (f"setenv bootfile {staged_file}",) + self._base_init_commands + bootfile_cmds = (f"setenv bootfile {staged_file}",) + if staged_initrd: + bootfile_cmds += (f"setenv bootfile_initrd {staged_initrd}",) + + init_commands = bootfile_cmds + self._base_init_commands if tftp_server_ip: tftp_dut_ip = ipaddress.ip_address(tftp_server_ip) + 1 @@ -286,6 +290,15 @@ def _transition_to_uboot_once(self): """Power-cycle the node and activate the U-Boot console.""" self.target.activate(self.tftp) staged_file = self.tftp.stage(self.target.env.config.get_image_path("root")) + + staged_initrd = None + try: + initrd_path = self.target.env.config.get_image_path("initrd") + staged_initrd = self.tftp.stage(initrd_path) + logger.info("Staged initrd image: %s", staged_initrd) + except KeyError: + pass + tftp_server_ip = self._resolve_tftp_server_ip() self.target.deactivate(self.console) @@ -306,7 +319,7 @@ def _transition_to_uboot_once(self): self._spam_uboot_interrupt() self._drain_serial_buffer() - self._prepare_uboot_commands(staged_file, tftp_server_ip) + self._prepare_uboot_commands(staged_file, tftp_server_ip, staged_initrd) self.target.activate(self.uboot) self.status = Status.uboot diff --git a/targets/librerouter_librerouter-v1.yaml b/targets/librerouter_librerouter-v1.yaml deleted file mode 100644 index 7b0f608..0000000 --- a/targets/librerouter_librerouter-v1.yaml +++ /dev/null @@ -1,93 +0,0 @@ -targets: - main: - features: - - wan_port - - wifi - resources: - RemotePlace: - name: !template "$LG_PLACE" - drivers: - - PDUDaemonDriver: {} - - TFTPProviderDriver: {} - - SerialDriver: - txdelay: 0.01 - - UBootDriver: - login_timeout: 30 - # CONFIG_AUTOBOOT_KEYED is not set in the LibreRouter U-Boot - # 1.1.x build (see include/955x.h: only CONFIG_BOOTDELAY=2 and - # the simple "Hit any key to stop autoboot" loop in - # common/main.c). Any byte sent during the 2 s window aborts - # autoboot, so a single newline is enough — _spam_uboot_interrupt - # in tftpstrategy.py blasts these for ~12 s by default which - # comfortably brackets the bootdelay window. - interrupt: "\n" - autoboot: "Hit any key to stop autoboot" - # The QCA9558 Atheros U-Boot prompt is `ath> ` (trailing - # space; see include/955x.h CFG_PROMPT). pexpect matches on - # substring so the trailing space is optional here. - prompt: "ath>" - # init_commands run at the U-Boot prompt before the - # boot_command. Lines starting with `tftp`/`dhcp` are pulled - # out by UBootTFTPStrategy and routed through its retry path - # (TFTPProviderDriver pre-stages the file on the exporter and - # bumps `bootfile` for us, so a bare `tftp ` is enough). - # The remaining lines are passed through verbatim. - # - # IMAGE FORMAT: this YAML expects LG_IMAGE to point at a - # `*-initramfs-kernel.bin` (a uImage on ath79; DTB appended - # into kernel-bin upstream, LibreMesh CPIO embedded in the - # kernel`s own .init.ramfs section via CONFIG_INITRAMFS_SOURCE). - # U-Boot only needs `bootm ` and the kernel`s - # populate_rootfs() drops the embedded CPIO into rootfs with - # no bootloader cooperation. - # - # The pi-lime-packages CI does NOT build this artifact — see - # docs/followups/imagebuilder_initramfs_limitations.md in that - # repo for why. For local / manual runs, supply your own - # `*-initramfs-kernel.bin` (e.g. from a LibreMesh release or a - # local OpenWrt source build) via LG_IMAGE. - # - # Why we still `setenv bootargs` here: the LibreRouter`s - # persistent U-Boot env may hold `bootargs=... - # root=/dev/mtdblock4 ...` left over from sysupgrade. We - # override it RAM-only (no `saveenv`) to keep serial console - # output going and avoid surprises if a future kernel decides - # to re-honour root= from cmdline. The initramfs kernel - # itself ignores root= when populate_rootfs() succeeds. - init_commands: - - "setenv bootargs console=ttyS0,115200n8" - - "tftp 0x82000000" - # `bootm ` on the initramfs uImage: - # * U-Boot reads the 64-byte uImage header at , - # * decompresses the lzma payload (kernel + appended DTB + - # embedded initramfs, all in one blob) to KERNEL_LOADADDR - # (0x80060000, set by the ath79/generic recipe upstream; - # embedded in the uImage header by the build). - # * jumps to the kernel entry point with the linux_argv - # array populated from `bootargs`. The MIPS kernel finds - # its appended DTB at the end of the uncompressed image - # and its embedded CPIO inside .init.ramfs, then runs - # /init from the unpacked rootfs. - boot_command: bootm 0x82000000 - - ShellDriver: - # Strict prompt: only match LibreMesh's default `LiMe-<6 hex>` - # hostname so we never engage with pre-`lime-config` prompts like - # `root@(none):~#` or `root@OpenWrt:~#`. See openwrt_one.yaml for - # rationale. login_timeout bumped to 180s — first-boot - # uci-defaults can take >60s on this device's 8 MiB SPI NOR. - prompt: "(?:\x1b\\][^\x07]*\x07)?(?:\x1b\\[[\\d;]*m)*root@LiMe-[0-9A-Fa-f]{6}:[^ ]*[#$] " - login_prompt: Please press Enter to activate this console. - await_login_timeout: 15 - login_timeout: 180 - post_login_settle_time: 5 - username: root - - UBootTFTPStrategy: {} - - SSHDriver: - connection_timeout: 120.0 - explicit_scp_mode: True - -images: - root: !template $LG_IMAGE - -imports: - - ../strategies/tftpstrategy.py diff --git a/targets/librerouter_v1.yaml b/targets/librerouter_v1.yaml new file mode 100644 index 0000000..472b17b --- /dev/null +++ b/targets/librerouter_v1.yaml @@ -0,0 +1,79 @@ +targets: + main: + features: + - wan_port + - wifi + resources: + RemotePlace: + name: !template "$LG_PLACE" + drivers: + - PDUDaemonDriver: {} + - TFTPProviderDriver: {} + - SerialDriver: + txdelay: 0.01 + - UBootDriver: + login_timeout: 30 + # CONFIG_AUTOBOOT_KEYED is not set in the LibreRouter U-Boot + # 1.1.x build (see include/955x.h: only CONFIG_BOOTDELAY=2 and + # the simple "Hit any key to stop autoboot" loop in + # common/main.c). Any byte sent during the 2 s window aborts + # autoboot, so a single newline is enough -- _spam_uboot_interrupt + # in tftpstrategy.py blasts these for ~12 s by default which + # comfortably brackets the bootdelay window. + interrupt: "\n" + autoboot: "Hit any key to stop autoboot" + # The QCA9558 Atheros U-Boot prompt is `ath> ` (trailing + # space; see include/955x.h CFG_PROMPT). pexpect matches on + # substring so the trailing space is optional here. + prompt: "ath>" + # DUAL-TFTP BOOT (kernel + ramdisk uImage): + # + # The ath79 ImageBuilder cannot produce an initramfs kernel + # (CONFIG_INITRAMFS_SOURCE requires kernel recompilation). + # Instead we ship the pre-built kernel.bin and a LibreMesh + # rootfs wrapped as a uImage ramdisk (mkimage -T ramdisk). + # U-Boot TFTP-loads each to a distinct RAM address: + # + # 0x82000000 kernel.bin (uImage lzma kernel + appended DTB) + # 0x84000FC0 rootfs.uimage (uImage ramdisk wrapping newc CPIO) + # + # The ramdisk loads to 0x84000FC0 so the CPIO data past the + # 64-byte uImage header starts at 0x84001000, which is + # page-aligned (PAGE_SIZE=4K). The kernel rejects non-aligned + # initrd with "initrd start must be page aligned". + # + # `bootm 0x82000000 0x84000FC0` tells U-Boot about both + # images natively. do_bootm_linux() passes initrd_start/end + # to the MIPS kernel via linux_env_set(), bypassing the + # CONFIG_CMDLINE_OVERRIDE that ignores rd_start/rd_size + # bootargs on this target. + # + # For manual / local runs, set both env vars: + # export LG_IMAGE=/path/to/kernel.bin + # export LG_IMAGE_INITRD=/path/to/rootfs.uimage + init_commands: + - "tftp 0x82000000" + - "tftp 0x84000FC0 ${bootfile_initrd}" + boot_command: "bootm 0x82000000 0x84000FC0" + - ShellDriver: + # Strict prompt: only match LibreMesh's default `LiMe-<6 hex>` + # hostname. If this times out, lime-config didn't run - fix the + # initramfs (missing /proc mountpoint, mount_root failure, etc.) + # rather than relaxing this regex. + prompt: "(?:\\x1b\\][^\\x07]*\\x07)?(?:\\x1b\\[[\\d;]*m)*root@LiMe-[0-9A-Fa-f]{6}:[^ ]*[#$] " + login_prompt: Please press Enter to activate this console. + await_login_timeout: 15 + login_timeout: 180 + post_login_settle_time: 5 + username: root + - UBootTFTPStrategy: {} + - SSHDriver: + connection_timeout: 120.0 + explicit_scp_mode: True + +images: + root: !template $LG_IMAGE + initrd: !template $LG_IMAGE_INITRD + +imports: + - ../strategies/tftpstrategy.py