From d080228ad80acac84710e1393ba6067322359ba6 Mon Sep 17 00:00:00 2001 From: Michal Skrivanek Date: Thu, 26 Jun 2025 10:25:51 +0200 Subject: [PATCH 1/7] builroot-based flasher images A single config building two FIT images supporting similar-enough boards using either upstream or kernel-automotive kernel. Includes TI J784S4EVM, SK-AM69 and Renesas R-Car S4 Spider and SK. --- .../oci_bundles/buildroot/automotive.its | 78 +++++++++++++++++++ .../oci_bundles/buildroot/build_fits.sh | 20 +++++ .../oci_bundles/buildroot/buildroot.its | 77 ++++++++++++++++++ .../oci_bundles/buildroot/buildroot_defconfig | 33 ++++++++ .../oci_bundles/buildroot/data/.gitkeep | 0 .../buildroot/manifest-automotive.yaml | 20 +++++ .../buildroot/manifest-buildroot.yaml | 37 +++++++++ .../etc/network/if-pre-up.d/wait-carrier.sh | 19 +++++ .../oci_bundles/buildroot/replace_kernel.sh | 69 ++++++++++++++++ 9 files changed, 353 insertions(+) create mode 100644 packages/jumpstarter-driver-flashers/oci_bundles/buildroot/automotive.its create mode 100755 packages/jumpstarter-driver-flashers/oci_bundles/buildroot/build_fits.sh create mode 100644 packages/jumpstarter-driver-flashers/oci_bundles/buildroot/buildroot.its create mode 100644 packages/jumpstarter-driver-flashers/oci_bundles/buildroot/buildroot_defconfig create mode 100644 packages/jumpstarter-driver-flashers/oci_bundles/buildroot/data/.gitkeep create mode 100644 packages/jumpstarter-driver-flashers/oci_bundles/buildroot/manifest-automotive.yaml create mode 100644 packages/jumpstarter-driver-flashers/oci_bundles/buildroot/manifest-buildroot.yaml create mode 100755 packages/jumpstarter-driver-flashers/oci_bundles/buildroot/overlay/etc/network/if-pre-up.d/wait-carrier.sh create mode 100755 packages/jumpstarter-driver-flashers/oci_bundles/buildroot/replace_kernel.sh diff --git a/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/automotive.its b/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/automotive.its new file mode 100644 index 000000000..838103627 --- /dev/null +++ b/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/automotive.its @@ -0,0 +1,78 @@ +/dts-v1/; + +/ { + description = "kernel-automotive flasher FIT Image"; + #address-cells = <1>; + + images { + kernel { + description = "kernel-automotive"; + data = /incbin/("/kernel-automotive/vmlinuz"); + type = "kernel"; + arch = "arm64"; + os = "linux"; + compression = "none"; + load = <0x48080000>; + entry = <0x48080000>; + hash { + algo = "sha256"; + }; + }; + fdt-spider { + description = "DTB Renesas 8779f0-spider"; + data = /incbin/("/kernel-automotive/dtb/renesas/r8a779f0-spider.dtb"); + type = "flat_dt"; + arch = "arm64"; + compression = "none"; + load = <0x48000000>; + entry = <0x48000000>; + hash { + algo = "sha256"; + }; + }; + fdt-s4sk { + description = "DTB Renesas r8a779f4-s4sk"; + data = /incbin/("/kernel-automotive/dtb/renesas/r8a779f4-s4sk.dtb"); + type = "flat_dt"; + arch = "arm64"; + compression = "none"; + load = <0x48000000>; + entry = <0x48000000>; + hash { + algo = "sha256"; + }; + }; + initrd { + description = "Initrd"; + data = /incbin/("/buildroot/output/images/rootfs.cpio.lzo"); + type = "ramdisk"; + arch = "arm64"; + os = "linux"; + hash { + algo = "sha256"; + }; + }; + }; + + configurations { + default = "spider"; + spider { + description = "Boot Renesas R-Car S4 Spider"; + kernel = "kernel"; + fdt = "fdt-spider"; + ramdisk = "initrd"; + hash { + algo = "sha256"; + }; + }; + s4sk { + description = "Boot Renesas R-Car S4 SK"; + kernel = "kernel"; + fdt = "fdt-s4sk"; + ramdisk = "initrd"; + hash { + algo = "sha256"; + }; + }; + }; +}; diff --git a/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/build_fits.sh b/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/build_fits.sh new file mode 100755 index 000000000..1a2c5d64a --- /dev/null +++ b/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/build_fits.sh @@ -0,0 +1,20 @@ +#!/bin/bash +set -euo pipefail + +dnf install --setopt=install_weak_deps=false -y git make gcc gcc-c++ which file diffutils wget cpio rsync bc lzop zip patch perl tar qemu-system-aarch64 qemu-img unzboot uboot-tools kmod awk + +git clone --depth 1 --branch 2025.05 https://github.com/buildroot/buildroot /buildroot + +# build default buildroot kernel & initramfs +cp buildroot_defconfig /buildroot/configs/ +cp -R overlay /buildroot +( cd /buildroot; make buildroot_defconfig && make ) +mkimage -f buildroot.its data/flasher-buildroot.itb +rm -rf /buildroot/overlay + +# replace kernel with kernel-automotive and rebuild +cp -R overlay /buildroot +./replace_kernel.sh /buildroot/overlay +( cd /buildroot && make ) +mkimage -f automotive.its data/flasher-automotive.itb +rm -rf /buildroot/overlay diff --git a/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/buildroot.its b/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/buildroot.its new file mode 100644 index 000000000..504074ccc --- /dev/null +++ b/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/buildroot.its @@ -0,0 +1,77 @@ +/dts-v1/; + +/ { + description = "buildroot kernel flasher FIT Image"; + #address-cells = <1>; + + images { + kernel { + description = "buildroot Kernel"; + data = /incbin/("/buildroot/output/images/Image"); + type = "kernel"; + arch = "arm64"; + os = "linux"; + compression = "none"; + load = <0x80000000>; + entry = <0x80000000>; + hash { + algo = "sha256"; + }; + }; + initrd { + description = "Initrd"; + data = /incbin/("/buildroot/output/images/rootfs.cpio.lzo"); + type = "ramdisk"; + arch = "arm64"; + os = "linux"; + compression = "none"; + hash { + algo = "sha256"; + }; + }; + fdt-j784s4 { + description = "DTB TI J784S4EVM"; + data = /incbin/("/buildroot/output/images/k3-j784s4-evm.dtb"); + type = "flat_dt"; + arch = "arm64"; + compression = "none"; + load = <0x88000000>; + hash { + algo = "sha256"; + }; + }; + fdt-am69 { + description = "DTB TI SK-AM69"; + data = /incbin/("/buildroot/output/images/k3-am69-sk.dtb"); + type = "flat_dt"; + arch = "arm64"; + compression = "none"; + load = <0x88000000>; + hash { + algo = "sha256"; + }; + }; + }; + + configurations { + default = "j784s4"; + j784s4 { + description = "Boot TI J784S4EVM"; + kernel = "kernel"; + fdt = "fdt-j784s4"; + ramdisk = "initrd"; + hash { + algo = "sha256"; + }; + }; + am69 { + description = "Boot TI SK-AM69"; + kernel = "kernel"; + fdt = "fdt-am69"; + ramdisk = "initrd"; + hash { + algo = "sha256"; + }; + }; + }; +}; diff --git a/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/buildroot_defconfig b/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/buildroot_defconfig new file mode 100644 index 000000000..2c7843886 --- /dev/null +++ b/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/buildroot_defconfig @@ -0,0 +1,33 @@ +# Initrd config +BR2_aarch64=y +BR2_TOOLCHAIN_EXTERNAL=y +BR2_TARGET_GENERIC_HOSTNAME="flasher" +BR2_TARGET_GENERIC_ISSUE="flasher" +BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV=y +BR2_TARGET_GENERIC_ROOT_PASSWD="" +BR2_SYSTEM_DHCP="eth0" +BR2_ROOTFS_OVERLAY="$(CONFIG_DIR)/overlay" +BR2_PACKAGE_CA_CERTIFICATES=y +BR2_PACKAGE_OPENSSL=y +BR2_PACKAGE_LIBCURL=y +BR2_PACKAGE_LIBCURL_CURL=y +BR2_PACKAGE_NTP=y +BR2_PACKAGE_NTP_SNTP=y +BR2_PACKAGE_NTP_NTPDATE=y +BR2_TARGET_ROOTFS_CPIO=y +BR2_TARGET_ROOTFS_CPIO_LZO=y +BR2_PACKAGE_DROPBEAR=n +# BR2_TARGET_ROOTFS_TAR is not set +# +# +# Buildroot Kernel config +# include initramfs within the kernel Image +# on J784S4 the size exceeds uboot's CONFIG_SYS_BOOTM_LEN +# BR2_TARGET_ROOTFS_INITRAMFS=y +BR2_LINUX_KERNEL=y +BR2_LINUX_KERNEL_USE_ARCH_DEFAULT_CONFIG=y +BR2_LINUX_KERNEL_LZO=y +BR2_LINUX_KERNEL_IMAGE=y +BR2_LINUX_KERNEL_DTS_SUPPORT=y +BR2_LINUX_KERNEL_INTREE_DTS_NAME="ti/k3-j784s4-evm ti/k3-am69-sk" + diff --git a/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/data/.gitkeep b/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/data/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/manifest-automotive.yaml b/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/manifest-automotive.yaml new file mode 100644 index 000000000..71cb6a111 --- /dev/null +++ b/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/manifest-automotive.yaml @@ -0,0 +1,20 @@ +apiVersion: jumpstarter.dev/v1alpha1 +kind: FlashBundleManifest +metadata: + name: rcar-s4 +spec: + manufacturer: Renesas + link: "https://www.renesas.com/en/products/automotive-products/automotive-system-chips-socs/r-car-s4-automotive-system-chip-soc-car-servercommunication-gateway" + # boot default configuration R-Car S4 Spider, for S4SK use "bootm 0x58000000#s4sk" + bootcmd: "bootm 0x58000000" + shelltype: "busybox" + login: + login_prompt: "login:" + username: "root" + prompt: "#" + default_target: "emmc" + targets: + emmc: "/dev/mmcblk0" + kernel: + file: data/automotive.itb + address: "0x58000000" diff --git a/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/manifest-buildroot.yaml b/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/manifest-buildroot.yaml new file mode 100644 index 000000000..e3b6aa209 --- /dev/null +++ b/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/manifest-buildroot.yaml @@ -0,0 +1,37 @@ +apiVersion: jumpstarter.dev/v1alpha1 +kind: FlashBundleManifest +metadata: + name: ti-j784s4 +spec: + manufacturer: Texas Instruments + link: "https://www.ti.com/tool/PROCESSOR-SDK-J784S4" +# boot using the default configuration built-in flasher.itb, j784s4 +# you can boot included alternative configurations, e.g. for SK-AM69 use "bootm 0x90000000#am69" + bootcmd: "bootm 0x90000000" + shelltype: "busybox" + login: + login_prompt: "login:" + username: "root" + prompt: "#" + default_target: "usd" + targets: + usd: "/sys/class/block#4fb0000" + emmc: "/sys/class/block#4f80000" +# removed for now, even if it's our documented procedure, if +# the board is configured to boot from sd or emmc (and not SPI), and +# the flashing of the final image fails, it will result in an un-bootable +# system -> lab admin going to the site and re-flashing SD, this can +# only be avoided by using something like sdwire +# +# preflash_commands: +# - "dd if=/dev/zero of=/dev/mmcblk0 bs=512 count=34" +# - "dd if=/dev/zero of=/dev/mmcblk1 bs=512 count=34" +# +# supply custom DTB by loading your own re-using the included kernel and initrd by e.g: +# bootcmd: "bootm 0x90000000:kernel 0x90000000:initrd 0x88000000" +# dtb: +# file: my.dtb +# address: "0x88000000" + kernel: + file: data/buildroot.itb + address: "0x90000000" diff --git a/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/overlay/etc/network/if-pre-up.d/wait-carrier.sh b/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/overlay/etc/network/if-pre-up.d/wait-carrier.sh new file mode 100755 index 000000000..7afc9a34a --- /dev/null +++ b/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/overlay/etc/network/if-pre-up.d/wait-carrier.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +IF_WAIT_DELAY=30 + +if [ "${IFACE}" != "lo" ]; then + ip link set ${IFACE} up + printf "Waiting for interface %s carrier" "${IFACE}" + while [ ${IF_WAIT_DELAY} -gt 0 ]; do + if [ "$(cat /sys/class/net/${IFACE}/carrier)" = "1" ]; then + printf "\n" + exit 0 + fi + sleep 1 + printf "." + : $((IF_WAIT_DELAY -= 1)) + done + printf " timeout!\n" + exit 1 +fi diff --git a/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/replace_kernel.sh b/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/replace_kernel.sh new file mode 100755 index 000000000..373e57956 --- /dev/null +++ b/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/replace_kernel.sh @@ -0,0 +1,69 @@ +#!/bin/bash + +KVER="5.14.0-594.543.el9iv.aarch64" +KMOD=( + # R-Car S4 storage + fixed + renesas_sdhi_internal_dmac + mmc_block + # R-Car S4 networking + gpio-rcar + r8a779f0-ether-serdes + marvell10g + rswitch +) + +[ $# -ne 1 ] && { echo "$0 [target_overlay_dir]"; exit 1; } +ODIR=$1 +mkdir -p /kernel-automotive +pushd /kernel-automotive + +url="https://cbs.centos.org/kojifiles/packages/kernel-automotive" +url="$url/$(echo $KVER | sed -r 's|-|/|; s|\.([^.]*)$|/\1|')" +pkgs=( + kernel-automotive-core-$KVER.rpm + kernel-automotive-modules-$KVER.rpm + kernel-automotive-modules-core-$KVER.rpm +) + + +# fetch kernel rpm packages +for pkg in "${pkgs[@]}"; do + [[ -f $pkg ]] || wget "$url/$pkg" || exit 1 +done + +# extract kernel rpm packages +for pkg in "${pkgs[@]}"; do + echo -n "extracting $pkg ... " + rpm2cpio $pkg | cpio -id +done +echo "extracting kernel ..." +unzboot lib/modules/$KVER/vmlinuz vmlinuz +ln -sfn lib/modules/$KVER/dtb dtb +echo "updating module deps ..." +depmod --errsyms --filesyms lib/modules/$KVER/System.map --basedir $PWD $KVER +echo "building required modules list ..." +for mod in ${KMOD[@]}; do + modprobe -d $PWD -S $KVER --show-depends $mod +done | sed "s|$PWD||; s|^builtin|# builtin|; s|\\.ko\\.zst|.ko|" > modlist + +popd + +echo "installing modules into overlay dir ..." +mkdir -p $ODIR/lib/modules $ODIR/etc/init.d || exit 1 +sed -nr 's|^insmod ||p' < /kernel-automotive/modlist | while read mod; do + mkdir -p "$ODIR$(dirname $mod)" + zstd -d "/kernel-automotive$mod.zst" -o "$ODIR$mod" +done + +echo "adding modules start-up script to overlay ..." +script=$ODIR/etc/init.d/S01modules +cat >$script < Date: Thu, 26 Jun 2025 14:21:15 +0200 Subject: [PATCH 2/7] Allow for dtb injection --- .../{buildroot => aarch64-itb}/automotive.its | 0 .../{buildroot => aarch64-itb}/build_fits.sh | 0 .../{buildroot => aarch64-itb}/buildroot.its | 0 .../{buildroot => aarch64-itb}/buildroot_defconfig | 0 .../{buildroot => aarch64-itb}/data/.gitkeep | 0 .../manifest-automotive.yaml | 10 ++++++++++ .../manifest-buildroot.yaml | 11 +++++++++++ .../overlay/etc/network/if-pre-up.d/wait-carrier.sh | 0 .../{buildroot => aarch64-itb}/replace_kernel.sh | 0 9 files changed, 21 insertions(+) rename packages/jumpstarter-driver-flashers/oci_bundles/{buildroot => aarch64-itb}/automotive.its (100%) rename packages/jumpstarter-driver-flashers/oci_bundles/{buildroot => aarch64-itb}/build_fits.sh (100%) rename packages/jumpstarter-driver-flashers/oci_bundles/{buildroot => aarch64-itb}/buildroot.its (100%) rename packages/jumpstarter-driver-flashers/oci_bundles/{buildroot => aarch64-itb}/buildroot_defconfig (100%) rename packages/jumpstarter-driver-flashers/oci_bundles/{buildroot => aarch64-itb}/data/.gitkeep (100%) rename packages/jumpstarter-driver-flashers/oci_bundles/{buildroot => aarch64-itb}/manifest-automotive.yaml (70%) rename packages/jumpstarter-driver-flashers/oci_bundles/{buildroot => aarch64-itb}/manifest-buildroot.yaml (83%) rename packages/jumpstarter-driver-flashers/oci_bundles/{buildroot => aarch64-itb}/overlay/etc/network/if-pre-up.d/wait-carrier.sh (100%) rename packages/jumpstarter-driver-flashers/oci_bundles/{buildroot => aarch64-itb}/replace_kernel.sh (100%) diff --git a/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/automotive.its b/packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/automotive.its similarity index 100% rename from packages/jumpstarter-driver-flashers/oci_bundles/buildroot/automotive.its rename to packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/automotive.its diff --git a/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/build_fits.sh b/packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/build_fits.sh similarity index 100% rename from packages/jumpstarter-driver-flashers/oci_bundles/buildroot/build_fits.sh rename to packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/build_fits.sh diff --git a/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/buildroot.its b/packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/buildroot.its similarity index 100% rename from packages/jumpstarter-driver-flashers/oci_bundles/buildroot/buildroot.its rename to packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/buildroot.its diff --git a/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/buildroot_defconfig b/packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/buildroot_defconfig similarity index 100% rename from packages/jumpstarter-driver-flashers/oci_bundles/buildroot/buildroot_defconfig rename to packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/buildroot_defconfig diff --git a/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/data/.gitkeep b/packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/data/.gitkeep similarity index 100% rename from packages/jumpstarter-driver-flashers/oci_bundles/buildroot/data/.gitkeep rename to packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/data/.gitkeep diff --git a/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/manifest-automotive.yaml b/packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/manifest-automotive.yaml similarity index 70% rename from packages/jumpstarter-driver-flashers/oci_bundles/buildroot/manifest-automotive.yaml rename to packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/manifest-automotive.yaml index 71cb6a111..fbd871e86 100644 --- a/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/manifest-automotive.yaml +++ b/packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/manifest-automotive.yaml @@ -18,3 +18,13 @@ spec: kernel: file: data/automotive.itb address: "0x58000000" + dtb: + default: s4sk + address: "0x48000000" + variants: + spider: + bootcmd: "bootm 0x58000000#spider" + s4sk: + bootcmd: "bootm 0x58000000#s4sk" + custom: + bootcmd "bootm 0x58000000:kernel 0x58000000:initrd 0x48000000" diff --git a/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/manifest-buildroot.yaml b/packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/manifest-buildroot.yaml similarity index 83% rename from packages/jumpstarter-driver-flashers/oci_bundles/buildroot/manifest-buildroot.yaml rename to packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/manifest-buildroot.yaml index e3b6aa209..60153b326 100644 --- a/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/manifest-buildroot.yaml +++ b/packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/manifest-buildroot.yaml @@ -35,3 +35,14 @@ spec: kernel: file: data/buildroot.itb address: "0x90000000" + + dtb: + default: j784s4 + address: "0x88000000" + variants: + j784s4: + bootcmd: "bootm 0x90000000#j784s4" + am69: + bootcmd: "bootm 0x90000000#am69" + custom: + bootcmd "bootm 0x90000000:kernel 0x90000000:initrd 0x88000000" diff --git a/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/overlay/etc/network/if-pre-up.d/wait-carrier.sh b/packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/overlay/etc/network/if-pre-up.d/wait-carrier.sh similarity index 100% rename from packages/jumpstarter-driver-flashers/oci_bundles/buildroot/overlay/etc/network/if-pre-up.d/wait-carrier.sh rename to packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/overlay/etc/network/if-pre-up.d/wait-carrier.sh diff --git a/packages/jumpstarter-driver-flashers/oci_bundles/buildroot/replace_kernel.sh b/packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/replace_kernel.sh similarity index 100% rename from packages/jumpstarter-driver-flashers/oci_bundles/buildroot/replace_kernel.sh rename to packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/replace_kernel.sh From 95a7f1feb593861aa17c46778241acadba28e869 Mon Sep 17 00:00:00 2001 From: Miguel Angel Ajo Pelayo Date: Thu, 26 Jun 2025 17:29:39 +0200 Subject: [PATCH 3/7] Implement more flexible variants: including bootcmd --- .../jumpstarter-driver-flashers/README.md | 3 +- .../jumpstarter_driver_flashers/bundle.py | 41 +++++++++++--- .../jumpstarter_driver_flashers/client.py | 6 +- .../jumpstarter_driver_flashers/driver.py | 30 +++++++--- .../driver_test.py | 55 ++++++++++++++++++- .../test_bundle.py | 39 +++++++++++++ .../oci_bundles/test/manifest.yaml | 9 ++- .../oci_bundles/ti_j784s4xevm/manifest.yaml | 3 +- 8 files changed, 162 insertions(+), 24 deletions(-) diff --git a/packages/jumpstarter-driver-flashers/README.md b/packages/jumpstarter-driver-flashers/README.md index c9cbc0de1..e6085203c 100644 --- a/packages/jumpstarter-driver-flashers/README.md +++ b/packages/jumpstarter-driver-flashers/README.md @@ -68,7 +68,8 @@ HTTP servers are used to serve images to the DUT bootloader and busybox shell. | cache_dir | The directory to cache the images | str | no | /var/lib/jumpstarter/flasher | | tftp_dir | The directory to serve the images via TFTP | str | no | /var/lib/tftpboot | | http_dir | The directory to serve the images via HTTP | str | no | /var/www/html | - +| variant | The variant of the DUT DTB to flash to | str | no | (the default defined in the manifest) | +| manifest | The manifest to use from the bundle. Every bundle can have multiple manifests, this is the name of the manifest to use | str | no | manifest.yaml | ## BaseFlasher API diff --git a/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/bundle.py b/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/bundle.py index ef124b078..e593a0e4d 100644 --- a/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/bundle.py +++ b/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/bundle.py @@ -1,5 +1,5 @@ import os -from typing import Literal, Optional +from typing import Literal import yaml from pydantic import BaseModel, Field @@ -9,12 +9,14 @@ class FileAddress(BaseModel): file: str address: str - class DtbVariant(BaseModel): + bootcmd: None | str = None + file: None | str = None + +class Dtb(BaseModel): default: str address: str - variants: dict[str, str] - + variants: dict[str, DtbVariant] class FlasherLogin(BaseModel): login_prompt: str @@ -25,15 +27,15 @@ class FlasherLogin(BaseModel): class FlashBundleSpecV1Alpha1(BaseModel): manufacturer: str - link: Optional[str] + link: None | str bootcmd: str shelltype: Literal["busybox"] = Field(default="busybox") login: FlasherLogin = Field(default_factory=lambda: FlasherLogin(login_prompt="login:", prompt="#")) default_target: str targets: dict[str, str] kernel: FileAddress - initram: Optional[FileAddress] = None - dtb: Optional[DtbVariant] = None + initram: None | FileAddress = None + dtb: None | Dtb = None preflash_commands: list[str] = Field(default_factory=list) @@ -56,10 +58,33 @@ def get_dtb_file(self, variant: str | None = None) -> str | None: if not self.spec.dtb: return None + # if no variant is provided, use the default variant name from the manifest if not variant: variant = self.spec.dtb.default - return self.spec.dtb.variants.get(variant) + # look for the variant struct in this manifest + variant_struct = self.spec.dtb.variants.get(variant) + if variant_struct: + return variant_struct.file + else: + raise ValueError(f"DTB variant {variant} not found in the manifest.") + + def get_boot_cmd(self, variant: str | None = None) -> str: + if not self.spec.dtb: + return self.spec.bootcmd + # if no variant is provided, use the default variant name from the manifest + if not variant: + variant = self.spec.dtb.default + # look for the variant struct in this manifest + variant_struct = self.spec.dtb.variants.get(variant) + if variant_struct: + # If variant has a custom bootcmd, use it; otherwise fall back to default + if variant_struct.bootcmd: + return variant_struct.bootcmd + else: + return self.spec.bootcmd + else: + raise ValueError(f"DTB variant {variant} not found in the manifest.") def get_kernel_address(self) -> str: return self.spec.kernel.address diff --git a/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/client.py b/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/client.py index 162052c00..ecba2824f 100644 --- a/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/client.py +++ b/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/client.py @@ -412,8 +412,10 @@ def _busybox(self): if self._console_debug: console.logfile_read = sys.stdout.buffer - self.logger.info(f"Running boot command: {manifest.spec.bootcmd}") - console.send(manifest.spec.bootcmd + "\n") + bootcmd = self.call("get_bootcmd") + + self.logger.info(f"Running boot command: {bootcmd}") + console.send(bootcmd + "\n") # if manifest has login details, we need to login if manifest.spec.login.username: diff --git a/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/driver.py b/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/driver.py index d85814e97..802eab34d 100644 --- a/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/driver.py +++ b/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/driver.py @@ -17,6 +17,8 @@ class BaseFlasher(Driver): """driver for Jumpstarter""" flasher_bundle: str = field(default="quay.io/jumpstarter-dev/jumpstarter-flasher-test:latest") + variant: None | str = field(default=None) + manifest: str = field(default="manifest.yaml") cache_dir: str = field(default="/var/lib/jumpstarter/flasher") tftp_dir: str = field(default="/var/lib/tftpboot") http_dir: str = field(default="/var/www/html") @@ -56,7 +58,6 @@ def __post_init__(self): # bundles that have already been downloaded in the current session self._downloaded = {} - self._use_dtb = None # use default dtb unless set by client @classmethod def client(cls) -> str: @@ -84,7 +85,7 @@ async def setup_flasher_bundle(self, force_flash_bundle: str | None = None): self.logger.info(f"Setting up initram in tftp: {initram_path}") await self.tftp.storage.copy_exporter_file(initram_path, initram_path.name) - dtb_path = await self._get_file_path(manifest.get_dtb_file(self._use_dtb)) if manifest.spec.dtb else None + dtb_path = await self._get_file_path(manifest.get_dtb_file(self.variant)) if manifest.spec.dtb else None if dtb_path: self.logger.info(f"Setting up dtb in tftp: {dtb_path}") await self.tftp.storage.copy_exporter_file(dtb_path, dtb_path.name) @@ -98,12 +99,16 @@ def set_dtb(self, handle): async def use_dtb_variant(self, variant): """Provide a different dtb reference from the flasher bundle""" manifest = await self.get_flasher_manifest() - if manifest.get_dtb_file(variant) is None: + # Check if the variant exists in the manifest + if not manifest.spec.dtb or variant not in manifest.spec.dtb.variants: + variant_list = [] + if manifest.spec.dtb: + variant_list = list(manifest.spec.dtb.variants.keys()) raise ValueError( f"DTB variant {variant} not found in the flasher bundle, " - f"available variants are: {list(manifest.spec.dtb.variants.keys())}" + f"available variants are: {variant_list}." ) - self._use_dtb = variant + self.variant = variant def set_kernel(self, handle): """Provide a different kernel from client""" @@ -152,11 +157,11 @@ async def _get_file_path(self, filename) -> Path: @export async def get_flasher_manifest_yaml(self) -> str: """Return the manifest yaml as a string for client side consumption""" - with open(await self._get_file_path("manifest.yaml")) as f: + with open(await self._get_file_path(self.manifest)) as f: return f.read() async def get_flasher_manifest(self) -> FlasherBundleManifestV1Alpha1: - filename = await self._get_file_path("manifest.yaml") + filename = await self._get_file_path(self.manifest) return FlasherBundleManifestV1Alpha1.from_file(filename) @export @@ -177,7 +182,11 @@ async def get_initram_filename(self) -> str | None: async def get_dtb_filename(self) -> str: """Return the dtb filename""" manifest = await self.get_flasher_manifest() - return Path(manifest.get_dtb_file(self._use_dtb)).name + dtb_file = manifest.get_dtb_file(self.variant) + if dtb_file: + return Path(manifest.get_dtb_file(self.variant)).name + else: + return "" @export async def get_dtb_address(self) -> str: @@ -197,6 +206,11 @@ async def get_initram_address(self) -> str: manifest = await self.get_flasher_manifest() return manifest.get_initram_address() + @export + async def get_bootcmd(self) -> str: + """Return the bootcmd""" + manifest = await self.get_flasher_manifest() + return manifest.get_boot_cmd(self.variant) @dataclass(kw_only=True) class TIJ784S4Flasher(BaseFlasher): diff --git a/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/driver_test.py b/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/driver_test.py index 15d17fa05..aaeae2820 100644 --- a/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/driver_test.py +++ b/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/driver_test.py @@ -6,6 +6,7 @@ from jumpstarter_driver_pyserial.driver import PySerial from .driver import BaseFlasher +from jumpstarter.client.core import DriverInvalidArgument from jumpstarter.common.exceptions import ConfigurationError from jumpstarter.common.utils import serve @@ -26,6 +27,7 @@ def temp_dirs(): def complete_flasher(temp_dirs): cache, http, tftp = temp_dirs yield BaseFlasher( + flasher_bundle="quay.io/jumpstarter-dev/jumpstarter-flasher-test:new", cache_dir=cache, http_dir=http, tftp_dir=tftp, @@ -35,7 +37,6 @@ def complete_flasher(temp_dirs): }, ) - def test_missing_serial(temp_dirs): cache, http, tftp = temp_dirs with pytest.raises(ConfigurationError): @@ -88,3 +89,55 @@ def test_drivers_flashers_addresses(complete_flasher): assert client.call("get_kernel_address") == "0x82000000" assert client.call("get_initram_address") == "0x83000000" assert client.call("get_dtb_address") == "0x84000000" + + +def test_drivers_flashers_get_bootcmd_default(complete_flasher): + """Test getting the default boot command""" + with serve(complete_flasher) as client: + bootcmd = client.call("get_bootcmd") + assert bootcmd == "booti 0x82000000 - 0x84000000" + + +def test_drivers_flashers_get_bootcmd_with_dtb_variant(complete_flasher): + """Test getting boot command with DTB variant that has custom bootcmd""" + with serve(complete_flasher) as client: + # Switch to variant with custom boot command + client.call("use_dtb_variant", "othercmd") + bootcmd = client.call("get_bootcmd") + assert bootcmd == "bootm" + + +def test_drivers_flashers_get_bootcmd_with_dtb_variant_no_custom_cmd(complete_flasher): + """Test getting boot command with DTB variant that has no custom bootcmd (should use default)""" + with serve(complete_flasher) as client: + # Switch to variant without custom boot command + client.call("use_dtb_variant", "alternate") + bootcmd = client.call("get_bootcmd") + assert bootcmd == "booti 0x82000000 - 0x84000000" + + +def test_drivers_flashers_get_bootcmd_variant_switching(complete_flasher): + """Test that boot command changes when switching between DTB variants""" + with serve(complete_flasher) as client: + # Start with default variant + bootcmd = client.call("get_bootcmd") + assert bootcmd == "booti 0x82000000 - 0x84000000" + + # Switch to variant with custom boot command + client.call("use_dtb_variant", "othercmd") + bootcmd = client.call("get_bootcmd") + assert bootcmd == "bootm" + + # Switch back to default variant + client.call("use_dtb_variant", "test-dtb") + bootcmd = client.call("get_bootcmd") + assert bootcmd == "booti 0x82000000 - 0x84000000" + + +def test_drivers_flashers_get_bootcmd_invalid_variant(complete_flasher): + """Test that get_bootcmd raises DriverInvalidArgument for invalid DTB variant""" + with serve(complete_flasher) as client: + # Set an invalid variant + with pytest.raises(DriverInvalidArgument): + client.call("use_dtb_variant", "noexists") + diff --git a/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/test_bundle.py b/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/test_bundle.py index 05e9d5a4f..6f145eade 100644 --- a/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/test_bundle.py +++ b/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/test_bundle.py @@ -1,5 +1,7 @@ from pathlib import Path +import pytest + from . import bundle @@ -13,3 +15,40 @@ def test_bundle_read(): "usd": "/sys/class/block#4fb0000", "emmc": "/sys/class/block#4f80000", } + + +def test_bundle_get_boot_cmd_default(): + """Test getting default boot command from test bundle""" + manifest_file = Path(__file__).parent / "../oci_bundles/test/manifest.yaml" + flasher_bundle = bundle.FlasherBundleManifestV1Alpha1.from_file(manifest_file) + + # Test default boot command (no variant specified) + bootcmd = flasher_bundle.get_boot_cmd() + assert bootcmd == "booti 0x82000000 - 0x84000000" + + +def test_bundle_get_boot_cmd_with_variant(): + """Test getting boot command with specific DTB variant""" + manifest_file = Path(__file__).parent / "../oci_bundles/test/manifest.yaml" + flasher_bundle = bundle.FlasherBundleManifestV1Alpha1.from_file(manifest_file) + + # Test variant with custom boot command + bootcmd = flasher_bundle.get_boot_cmd("othercmd") + assert bootcmd == "bootm" + + # Test variant without custom boot command (should use default) + bootcmd = flasher_bundle.get_boot_cmd("alternate") + assert bootcmd == "booti 0x82000000 - 0x84000000" + + # Test default variant explicitly + bootcmd = flasher_bundle.get_boot_cmd("test-dtb") + assert bootcmd == "booti 0x82000000 - 0x84000000" + + +def test_bundle_get_boot_cmd_invalid_variant(): + """Test that get_boot_cmd raises ValueError for invalid variant""" + manifest_file = Path(__file__).parent / "../oci_bundles/test/manifest.yaml" + flasher_bundle = bundle.FlasherBundleManifestV1Alpha1.from_file(manifest_file) + + with pytest.raises(ValueError, match="DTB variant noexists not found in the manifest"): + flasher_bundle.get_boot_cmd("noexists") diff --git a/packages/jumpstarter-driver-flashers/oci_bundles/test/manifest.yaml b/packages/jumpstarter-driver-flashers/oci_bundles/test/manifest.yaml index 31cb22c94..f4e0d4b6e 100644 --- a/packages/jumpstarter-driver-flashers/oci_bundles/test/manifest.yaml +++ b/packages/jumpstarter-driver-flashers/oci_bundles/test/manifest.yaml @@ -31,6 +31,9 @@ spec: default: test-dtb address: "0x84000000" variants: - test-dtb: data/dtbs/test-dtb.dtb - alternate: data/dtbs/alternate.dtb - + test-dtb: + file: data/dtbs/test-dtb.dtb + alternate: + file: data/dtbs/alternate.dtb + othercmd: + bootcmd: "bootm" diff --git a/packages/jumpstarter-driver-flashers/oci_bundles/ti_j784s4xevm/manifest.yaml b/packages/jumpstarter-driver-flashers/oci_bundles/ti_j784s4xevm/manifest.yaml index 029671178..156ba3f93 100644 --- a/packages/jumpstarter-driver-flashers/oci_bundles/ti_j784s4xevm/manifest.yaml +++ b/packages/jumpstarter-driver-flashers/oci_bundles/ti_j784s4xevm/manifest.yaml @@ -31,4 +31,5 @@ spec: default: k3-j784s4-evm address: "0x84000000" variants: - k3-j784s4-evm: data/dtbs/k3-j784s4-evm.dtb + k3-j784s4-evm: + file: data/dtbs/k3-j784s4-evm.dtb From ea20e291055bd08606c70055406a169b0a0ab62e Mon Sep 17 00:00:00 2001 From: Michal Skrivanek Date: Fri, 27 Jun 2025 10:34:45 +0200 Subject: [PATCH 4/7] build bundles with multiple manifests all *.yaml files are treated as manifests. A default manifest manifest.yaml should still exist --- .../{manifest-automotive.yaml => manifest-renesas.yaml} | 6 +++--- .../{manifest-buildroot.yaml => manifest-ti.yaml} | 4 ++-- .../oci_bundles/aarch64-itb/manifest.yaml | 1 + .../overlay/etc/udev/rules.d/10-rename-tsn0.rules | 2 ++ .../oci_bundles/build_bundle.sh | 8 ++++++-- 5 files changed, 14 insertions(+), 7 deletions(-) rename packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/{manifest-automotive.yaml => manifest-renesas.yaml} (85%) rename packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/{manifest-buildroot.yaml => manifest-ti.yaml} (93%) create mode 120000 packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/manifest.yaml create mode 100644 packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/overlay/etc/udev/rules.d/10-rename-tsn0.rules diff --git a/packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/manifest-automotive.yaml b/packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/manifest-renesas.yaml similarity index 85% rename from packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/manifest-automotive.yaml rename to packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/manifest-renesas.yaml index fbd871e86..e38cbc6e6 100644 --- a/packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/manifest-automotive.yaml +++ b/packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/manifest-renesas.yaml @@ -16,10 +16,10 @@ spec: targets: emmc: "/dev/mmcblk0" kernel: - file: data/automotive.itb + file: data/flasher-automotive.itb address: "0x58000000" dtb: - default: s4sk + default: spider address: "0x48000000" variants: spider: @@ -27,4 +27,4 @@ spec: s4sk: bootcmd: "bootm 0x58000000#s4sk" custom: - bootcmd "bootm 0x58000000:kernel 0x58000000:initrd 0x48000000" + bootcmd: "bootm 0x58000000:kernel 0x58000000:initrd 0x48000000" diff --git a/packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/manifest-buildroot.yaml b/packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/manifest-ti.yaml similarity index 93% rename from packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/manifest-buildroot.yaml rename to packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/manifest-ti.yaml index 60153b326..edec8ca78 100644 --- a/packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/manifest-buildroot.yaml +++ b/packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/manifest-ti.yaml @@ -33,7 +33,7 @@ spec: # file: my.dtb # address: "0x88000000" kernel: - file: data/buildroot.itb + file: data/flasher-buildroot.itb address: "0x90000000" dtb: @@ -45,4 +45,4 @@ spec: am69: bootcmd: "bootm 0x90000000#am69" custom: - bootcmd "bootm 0x90000000:kernel 0x90000000:initrd 0x88000000" + bootcmd: "bootm 0x90000000:kernel 0x90000000:initrd 0x88000000" diff --git a/packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/manifest.yaml b/packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/manifest.yaml new file mode 120000 index 000000000..d8d479014 --- /dev/null +++ b/packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/manifest.yaml @@ -0,0 +1 @@ +manifest-ti.yaml \ No newline at end of file diff --git a/packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/overlay/etc/udev/rules.d/10-rename-tsn0.rules b/packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/overlay/etc/udev/rules.d/10-rename-tsn0.rules new file mode 100644 index 000000000..e3fd0b5f1 --- /dev/null +++ b/packages/jumpstarter-driver-flashers/oci_bundles/aarch64-itb/overlay/etc/udev/rules.d/10-rename-tsn0.rules @@ -0,0 +1,2 @@ +# rename Renesas S4 main interface tsn0 to eth0 to unify setup +SUBSYSTEM=="net", ACTION=="add", KERNEL=="tsn0", NAME="eth0" diff --git a/packages/jumpstarter-driver-flashers/oci_bundles/build_bundle.sh b/packages/jumpstarter-driver-flashers/oci_bundles/build_bundle.sh index 56a0982ae..14a9804c1 100755 --- a/packages/jumpstarter-driver-flashers/oci_bundles/build_bundle.sh +++ b/packages/jumpstarter-driver-flashers/oci_bundles/build_bundle.sh @@ -12,12 +12,16 @@ echo "Building and pushing ${FLASHER_OCI_CONTAINER}" set -x cd "${BUNDLE_FILES}" +MANIFESTS= +for file in $(ls -1 *.yaml); do + MANIFESTS="${MANIFESTS} ${file}:application/yaml " +done DATA_FILES= -for file in $(find ./data -type f); do +for file in $(find ./data -type f -prune -a -not -name .gitkeep); do DATA_FILES="${DATA_FILES} ${file}:application/octet-stream " done oras push $FLASHER_OCI_CONTAINER \ --artifact-type application/vnd.oci.bundle.v1 \ - ./manifest.yaml:application/yaml \ + $MANIFESTS \ $DATA_FILES From 2c3b3d998eaa6f9735bafcf9f58fc3e63bb8d9fc Mon Sep 17 00:00:00 2001 From: Miguel Angel Ajo Pelayo Date: Mon, 30 Jun 2025 18:00:13 +0200 Subject: [PATCH 5/7] Handle corner cases for None initram/dtb --- .../jumpstarter_driver_flashers/client.py | 19 +++++++++++++------ .../jumpstarter_driver_flashers/driver.py | 14 +++++++++----- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/client.py b/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/client.py index ecba2824f..9934f336a 100644 --- a/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/client.py +++ b/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/client.py @@ -401,12 +401,19 @@ def _busybox(self): if manifest.get_initram_file(): initram_filename = Path(manifest.get_initram_file()).name initram_address = manifest.get_initram_address() - self.uboot.run_command(f"tftpboot {initram_address} {initram_filename}", timeout=120) - - if manifest.get_dtb_file(): - dtb_filename = Path(manifest.get_dtb_file()).name - dtb_address = manifest.get_dtb_address() - self.uboot.run_command(f"tftpboot {dtb_address} {dtb_filename}", timeout=120) + if initram_address: + self.uboot.run_command(f"tftpboot {initram_address} {initram_filename}", timeout=120) + + try: + dtb_file = manifest.get_dtb_file() + if dtb_file: + dtb_filename = Path(dtb_file).name + dtb_address = manifest.get_dtb_address() + if dtb_address: + self.uboot.run_command(f"tftpboot {dtb_address} {dtb_filename}", timeout=120) + except ValueError: + # DTB variant not found, skip DTB loading + pass with self.serial.pexpect() as console: if self._console_debug: diff --git a/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/driver.py b/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/driver.py index 802eab34d..c8080b218 100644 --- a/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/driver.py +++ b/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/driver.py @@ -80,13 +80,15 @@ async def setup_flasher_bundle(self, force_flash_bundle: str | None = None): self.logger.info(f"Setting up kernel in tftp: {kernel_path}") await self.tftp.storage.copy_exporter_file(kernel_path, kernel_path.name) - initram_path = await self._get_file_path(manifest.spec.initram.file) if manifest.spec.initram else None - if initram_path: + initram_file = manifest.get_initram_file() + if initram_file: + initram_path = await self._get_file_path(initram_file) self.logger.info(f"Setting up initram in tftp: {initram_path}") await self.tftp.storage.copy_exporter_file(initram_path, initram_path.name) - dtb_path = await self._get_file_path(manifest.get_dtb_file(self.variant)) if manifest.spec.dtb else None - if dtb_path: + dtb_file = manifest.get_dtb_file(self.variant) if manifest.spec.dtb else None + if dtb_file: + dtb_path = await self._get_file_path(dtb_file) self.logger.info(f"Setting up dtb in tftp: {dtb_path}") await self.tftp.storage.copy_exporter_file(dtb_path, dtb_path.name) @@ -151,6 +153,8 @@ async def _get_file_path(self, filename) -> Path: This function will ensure that the bundle is downloaded into cache, and then return the path to the requested file in the cache directory. """ + if filename is None: + raise ValueError("filename cannot be None") bundle_dir = await anyio.to_thread.run_sync(self._download_to_cache) return Path(bundle_dir) / filename @@ -184,7 +188,7 @@ async def get_dtb_filename(self) -> str: manifest = await self.get_flasher_manifest() dtb_file = manifest.get_dtb_file(self.variant) if dtb_file: - return Path(manifest.get_dtb_file(self.variant)).name + return Path(dtb_file).name else: return "" From 6f1069bffe892d9439d3c7352e825cd96e2835c2 Mon Sep 17 00:00:00 2001 From: Miguel Angel Ajo Pelayo Date: Mon, 30 Jun 2025 18:00:43 +0200 Subject: [PATCH 6/7] Nicer tracebacks for j failures --- packages/jumpstarter-cli/jumpstarter_cli/j.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/jumpstarter-cli/jumpstarter_cli/j.py b/packages/jumpstarter-cli/jumpstarter_cli/j.py index 29624c230..8dae7d7f9 100644 --- a/packages/jumpstarter-cli/jumpstarter_cli/j.py +++ b/packages/jumpstarter-cli/jumpstarter_cli/j.py @@ -9,6 +9,7 @@ from jumpstarter_cli_common.exceptions import async_handle_exceptions, leaf_exceptions from jumpstarter_cli_common.signal import signal_handler +from rich import traceback from jumpstarter.utils.env import env_async @@ -43,6 +44,7 @@ async def cli(): def j(): + traceback.install() run(j_async) From 3d1f825cec91d7a3ac324d3267956ae45ed5e405 Mon Sep 17 00:00:00 2001 From: Miguel Angel Ajo Pelayo Date: Mon, 30 Jun 2025 18:38:28 +0200 Subject: [PATCH 7/7] Allow setting up a default storage target --- packages/jumpstarter-cli/jumpstarter_cli/j.py | 2 +- .../jumpstarter-driver-flashers/README.md | 1 + .../jumpstarter_driver_flashers/client.py | 2 +- .../jumpstarter_driver_flashers/driver.py | 6 ++++ uv.lock | 31 +++++++++++++++++++ 5 files changed, 40 insertions(+), 2 deletions(-) diff --git a/packages/jumpstarter-cli/jumpstarter_cli/j.py b/packages/jumpstarter-cli/jumpstarter_cli/j.py index 8dae7d7f9..5f9a8c552 100644 --- a/packages/jumpstarter-cli/jumpstarter_cli/j.py +++ b/packages/jumpstarter-cli/jumpstarter_cli/j.py @@ -8,8 +8,8 @@ from anyio.from_thread import BlockingPortal from jumpstarter_cli_common.exceptions import async_handle_exceptions, leaf_exceptions from jumpstarter_cli_common.signal import signal_handler - from rich import traceback + from jumpstarter.utils.env import env_async diff --git a/packages/jumpstarter-driver-flashers/README.md b/packages/jumpstarter-driver-flashers/README.md index e6085203c..6c21cb4a4 100644 --- a/packages/jumpstarter-driver-flashers/README.md +++ b/packages/jumpstarter-driver-flashers/README.md @@ -70,6 +70,7 @@ HTTP servers are used to serve images to the DUT bootloader and busybox shell. | http_dir | The directory to serve the images via HTTP | str | no | /var/www/html | | variant | The variant of the DUT DTB to flash to | str | no | (the default defined in the manifest) | | manifest | The manifest to use from the bundle. Every bundle can have multiple manifests, this is the name of the manifest to use | str | no | manifest.yaml | +| default_target | The default target to flash to if none specified | str | no | | ## BaseFlasher API diff --git a/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/client.py b/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/client.py index 9934f336a..09d47293d 100644 --- a/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/client.py +++ b/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/client.py @@ -117,7 +117,7 @@ def flash( with self._services_up(): with self._busybox() as console: manifest = self.manifest - target = partition or manifest.spec.default_target + target = partition or self.call("get_default_target") or manifest.spec.default_target if not target: raise ArgumentError("No partition or default target specified") diff --git a/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/driver.py b/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/driver.py index c8080b218..e9fc177bf 100644 --- a/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/driver.py +++ b/packages/jumpstarter-driver-flashers/jumpstarter_driver_flashers/driver.py @@ -19,6 +19,7 @@ class BaseFlasher(Driver): flasher_bundle: str = field(default="quay.io/jumpstarter-dev/jumpstarter-flasher-test:latest") variant: None | str = field(default=None) manifest: str = field(default="manifest.yaml") + default_target: None | str = field(default=None) cache_dir: str = field(default="/var/lib/jumpstarter/flasher") tftp_dir: str = field(default="/var/lib/tftpboot") http_dir: str = field(default="/var/www/html") @@ -63,6 +64,11 @@ def __post_init__(self): def client(cls) -> str: return "jumpstarter_driver_flashers.client.BaseFlasherClient" + @export + async def get_default_target(self): + """Return the default target""" + return self.default_target + @export async def setup_flasher_bundle(self, force_flash_bundle: str | None = None): """Setup flasher bundle diff --git a/uv.lock b/uv.lock index 6d889b236..544aa62fe 100644 --- a/uv.lock +++ b/uv.lock @@ -26,6 +26,7 @@ members = [ "jumpstarter-driver-pyserial", "jumpstarter-driver-qemu", "jumpstarter-driver-raspberrypi", + "jumpstarter-driver-ridesx", "jumpstarter-driver-sdwire", "jumpstarter-driver-shell", "jumpstarter-driver-snmp", @@ -1074,6 +1075,7 @@ dependencies = [ { name = "jumpstarter-driver-pyserial" }, { name = "jumpstarter-driver-qemu" }, { name = "jumpstarter-driver-raspberrypi" }, + { name = "jumpstarter-driver-ridesx" }, { name = "jumpstarter-driver-sdwire" }, { name = "jumpstarter-driver-shell" }, { name = "jumpstarter-driver-snmp" }, @@ -1107,6 +1109,7 @@ requires-dist = [ { name = "jumpstarter-driver-pyserial", editable = "packages/jumpstarter-driver-pyserial" }, { name = "jumpstarter-driver-qemu", editable = "packages/jumpstarter-driver-qemu" }, { name = "jumpstarter-driver-raspberrypi", editable = "packages/jumpstarter-driver-raspberrypi" }, + { name = "jumpstarter-driver-ridesx", editable = "packages/jumpstarter-driver-ridesx" }, { name = "jumpstarter-driver-sdwire", editable = "packages/jumpstarter-driver-sdwire" }, { name = "jumpstarter-driver-shell", editable = "packages/jumpstarter-driver-shell" }, { name = "jumpstarter-driver-snmp", editable = "packages/jumpstarter-driver-snmp" }, @@ -1763,6 +1766,34 @@ dev = [ { name = "pytest-cov", specifier = ">=5.0.0" }, ] +[[package]] +name = "jumpstarter-driver-ridesx" +source = { editable = "packages/jumpstarter-driver-ridesx" } +dependencies = [ + { name = "jumpstarter" }, + { name = "jumpstarter-driver-opendal" }, + { name = "jumpstarter-driver-pyserial" }, +] + +[package.dev-dependencies] +dev = [ + { name = "pytest" }, + { name = "pytest-cov" }, +] + +[package.metadata] +requires-dist = [ + { name = "jumpstarter", editable = "packages/jumpstarter" }, + { name = "jumpstarter-driver-opendal", editable = "packages/jumpstarter-driver-opendal" }, + { name = "jumpstarter-driver-pyserial", editable = "packages/jumpstarter-driver-pyserial" }, +] + +[package.metadata.requires-dev] +dev = [ + { name = "pytest", specifier = ">=8.3.3" }, + { name = "pytest-cov", specifier = ">=6.0.0" }, +] + [[package]] name = "jumpstarter-driver-sdwire" source = { editable = "packages/jumpstarter-driver-sdwire" }