Merge pull request #1222 from kernelkit/xpi-boot-time

This commit is contained in:
Joachim Wiberg
2025-11-02 08:33:00 +01:00
committed by GitHub
11 changed files with 273 additions and 40 deletions
@@ -4,16 +4,23 @@ image cfg.ext4 {
size = 128M
ext4 {
label = "cfg"
use-mke2fs = true
features = "uninit_bg"
extraargs = "-m 0 -i 4096"
}
}
# The /var partition will be expanded automatically at first boot
# to use the full size of the SD-card or eMMC media.
image var.ext4 {
empty = true
temporary = true
size = 1G
size = 128M
ext4 {
label = "var"
use-mke2fs = true
features = "uninit_bg"
extraargs = "-m 0 -i 4096"
}
}
@@ -5,17 +5,24 @@ image cfg.ext4 {
ext4 {
label = "cfg"
use-mke2fs = true
features = "uninit_bg"
extraargs = "-m 0 -i 4096"
}
}
# The /var partition will be expanded automatically at first boot
# to use the full size of the SD-card or eMMC media.
image var.ext4 {
empty = true
temporary = true
size = 512M
size = 128M
ext4 {
label = "var"
use-mke2fs = true
use-mke2fs = true
features = "uninit_bg"
extraargs = "-m 0 -i 4096"
}
}
@@ -15,17 +15,24 @@ image cfg.ext4 {
ext4 {
label = "cfg"
use-mke2fs = true
features = "uninit_bg"
extraargs = "-m 0 -i 4096"
}
}
# The /var partition will be expanded automatically at first boot
# to use the full size of the SD-card or eMMC media.
image var.ext4 {
empty = true
temporary = true
size = 512M
size = 128M
ext4 {
label = "var"
use-mke2fs = true
use-mke2fs = true
features = "uninit_bg"
extraargs = "-m 0 -i 4096"
}
}
+2 -1
View File
@@ -11,7 +11,8 @@ image aux.ext4 {
ext4 {
label = "aux"
use-mke2fs = true
features = "^metadata_csum,^metadata_csum_seed"
features = "^metadata_csum,^metadata_csum_seed,uninit_bg"
extraargs = "-m 0 -i 4096"
}
}
+6 -6
View File
@@ -15,9 +15,9 @@ cfgfs /config configfs nofail,noauto 0 0
# The chosen backing storage for the overlays placed on /cfg, /etc,
# /home, /root, and /var, are determined dynamically by /usr/libexec/infix/mnt
# depending on the available devices.
mnttmp /mnt/tmp tmpfs defaults 0 0
LABEL=aux /mnt/aux auto noatime,nodiratime,noauto 0 0
LABEL=var /mnt/var auto noatime,nodiratime,noauto 0 0
LABEL=cfg /mnt/cfg auto noatime,nodiratime,noauto 0 0
hostfs /mnt/host 9p cache=none,msize=16384,noauto 0 0
/usr/libexec/infix/mnt# /cfg helper none 0 0
mnttmp /mnt/tmp tmpfs defaults 0 0
LABEL=aux /mnt/aux auto noatime,nodiratime,noauto,commit=30,errors=remount-ro 0 0
LABEL=var /mnt/var auto noatime,nodiratime,noauto,commit=30,errors=remount-ro 0 0
LABEL=cfg /mnt/cfg auto noatime,nodiratime,noauto,commit=30,errors=remount-ro 0 0
hostfs /mnt/host 9p cache=none,msize=16384,noauto 0 0
/usr/libexec/infix/mnt# /cfg helper none 0 0
+27 -4
View File
@@ -19,6 +19,7 @@ set -e
nm=$(basename "$0")
err=0
mmc=""
opt="-k"
# External button or bootloader changed kernel command line
@@ -53,17 +54,22 @@ factory_reset()
is_mmc()
{
[ -n "$mmc" ] && return $mmc
# Check if primary or secondary partition (our rootfs) is on MMC
for label in primary secondary; do
devname=$(find_partition_by_label "$label" 2>/dev/null)
if [ -n "$devname" ]; then
case "$devname" in
mmcblk*)
mmc=0
return 0
;;
esac
fi
done
mmc=1
return 1
}
@@ -89,8 +95,15 @@ find_partition_by_label()
for diskpath in /sys/class/block/*; do
devname=$(basename "$diskpath")
# Skip partitions, only check whole disks
[ -f "$diskpath/partition" ] && continue
# Skip ram, loop, and other virtual devices
case "$devname" in
ram*|loop*|nullb*|dm-*) continue ;;
esac
disk="/dev/$devname"
result=$(sgdisk -p "$disk" 2>/dev/null | awk -v label="$label" -v devname="$devname" '
/^ *[0-9]/ {
@@ -133,7 +146,7 @@ status()
print_start()
{
printf '\r%s%s' "$(status 3)" "$*" > /dev/console
printf '\r\033[K%s%s' "$(status 3)" "$*" > /dev/console
}
print_end()
@@ -146,6 +159,12 @@ print_end()
fi
}
# Restore Finit's original progress message so its [ OK ] appears correctly
print_restore()
{
print_start "Mounting filesystems from /etc/fstab"
}
# Helper to log resize error and create failure marker (stage 1)
resize_err()
{
@@ -245,9 +264,7 @@ resize_filesystem()
mv /mnt/aux/resized.pending /mnt/aux/resized
sync
# Restore Finit's original progress message so its [ OK ] appears correctly
print_start "Mounting filesystems from /etc/fstab"
print_restore
return 0
}
@@ -259,15 +276,21 @@ mount_rw()
# Check if /var has been resized to fill the sdcard/eMMC
if [ "$1" = "var" ] && is_mmc; then
if [ -f /mnt/aux/resized ] || [ -f /mnt/aux/resized.failed ]; then
# 3. Already done
:
elif [ -f /mnt/aux/resized.pending ]; then
# 2. After reboot we can resize ext4
resize_filesystem "$1"
else
# 1. Start with resizing the var partition to the end of the media
resize_partition "$1"
fi
fi
# TODO: Also look for UBI partitions
#
tune2fs -c 0 -i 0 LABEL="$1" 2>/dev/null
mount LABEL="$1" 2>/dev/null && return 0
return 1
+1
View File
@@ -124,6 +124,7 @@ BR2_PACKAGE_MG=y
BR2_PACKAGE_NANO=y
BR2_TARGET_ROOTFS_SQUASHFS=y
# BR2_TARGET_ROOTFS_TAR is not set
BR2_PACKAGE_HOST_BMAP_TOOLS=y
BR2_PACKAGE_HOST_E2FSPROGS=y
BR2_PACKAGE_HOST_ENVIRONMENT_SETUP=y
BR2_PACKAGE_HOST_GENEXT2FS=y
+4
View File
@@ -100,6 +100,7 @@ BR2_PACKAGE_MG=y
BR2_PACKAGE_NANO=y
BR2_TARGET_ROOTFS_SQUASHFS=y
# BR2_TARGET_ROOTFS_TAR is not set
BR2_PACKAGE_HOST_BMAP_TOOLS=y
BR2_PACKAGE_HOST_E2FSPROGS=y
BR2_PACKAGE_HOST_ENVIRONMENT_SETUP=y
BR2_PACKAGE_HOST_GENEXT2FS=y
@@ -114,8 +115,11 @@ INFIX_HOME="https://github.com/kernelkit/infix/"
INFIX_DOC="https://kernelkit.org/infix/"
INFIX_SUPPORT="mailto:kernelkit@googlegroups.com"
BR2_PACKAGE_ALDER_ALDER=y
BR2_PACKAGE_BANANAPI_BPI_R3=y
BR2_PACKAGE_FRIENDLYARM_NANOPI_R2S=y
BR2_PACKAGE_MARVELL_CN9130_CRB=y
BR2_PACKAGE_MARVELL_ESPRESSOBIN=y
BR2_PACKAGE_RASPBERRYPI_RPI64=y
BR2_PACKAGE_STYX_DCP_SC_28P=y
BR2_PACKAGE_CONFD=y
BR2_PACKAGE_CONFD_TEST_MODE=y
+1
View File
@@ -164,6 +164,7 @@ BR2_TARGET_UBOOT_FORMAT_CUSTOM_NAME="u-boot.itb"
BR2_TARGET_UBOOT_SPL=y
BR2_TARGET_UBOOT_SPL_NAME="spl/u-boot-spl.bin.normal.out"
BR2_TARGET_UBOOT_CUSTOM_DTS_PATH="$(BR2_EXTERNAL_INFIX_PATH)/board/riscv64/visionfive2/uboot/visionfive2-env.dtsi"
BR2_PACKAGE_HOST_BMAP_TOOLS=y
BR2_PACKAGE_HOST_GENIMAGE=y
BR2_PACKAGE_HOST_RAUC=y
BR2_PACKAGE_HOST_UBOOT_TOOLS=y
+21 -1
View File
@@ -3,6 +3,25 @@ Change Log
All notable changes to the project are documented in this file.
[v25.11.0][UNRELEASED]
-------------------------
### Changes
- Improvements to `sdcard.img` generation, useful for developers mostly:
- The NanoPi R2S bootloader is now automatically built and uploaded to
the [`latest-boot` release][lastest-boot] tag
- The `utils/mkimage.sh` script now supports fetching the bootloader
- The raspberrypi-rpi64 board's bootloader is now aptly named rpi64
### Fixes
- Fix #855: User admin sometimes fails to be added to `wheel` group
- Fix serious regression in boot time, introduced in v25.10, delays the
boot step "Mounting filesystems ..." with up to 30 seconds!
[lastest-boot]: https://github.com/kernelkit/infix/releases/latest-boot
[v25.10.0][] - 2025-10-31
-------------------------
@@ -1725,7 +1744,8 @@ Supported YANG models in addition to those used by sysrepo and netopeer:
- N/A
[buildroot]: https://buildroot.org/
[UNRELEASED]: https://github.com/kernelkit/infix/compare/v25.09.0...HEAD
[UNRELEASED]: https://github.com/kernelkit/infix/compare/v25.10.0...HEAD
[v25.11.0]: https://github.com/kernelkit/infix/compare/v25.10.0...v26.11.0
[v25.10.0]: https://github.com/kernelkit/infix/compare/v25.09.0...v26.10.0
[v25.09.0]: https://github.com/kernelkit/infix/compare/v25.08.0...v26.09.0
[v25.08.0]: https://github.com/kernelkit/infix/compare/v25.06.1...v26.08.0
+185 -23
View File
@@ -18,10 +18,12 @@ Usage:
$0 [OPTIONS] <board-name>
Options:
-b boot-dir Path to bootloader build directory (default: O= or output/)
-d Download bootloader files from latest-boot release
-f Force re-download of bootloader even if cached
-h This help text
-l List available boards
-o Override auto-detection of genimage.sh, use host installed version
-b boot-dir Path to bootloader build directory (default: O= or output/)
-r root-dir Path to rootfs build directory or rootfs.squashfs file (default: O= or output/)
Arguments:
@@ -44,8 +46,11 @@ Examples:
# Standalone with separate boot/rootfs builds:
$0 -b x-boot -r output raspberrypi-rpi64
# With downloaded rootfs:
$0 -b x-boot -r ~/Downloads/rootfs.squashfs friendlyarm-nanopi-r2s
# With downloaded rootfs and bootloader:
$0 -d -r ~/Downloads/rootfs.squashfs friendlyarm-nanopi-r2s
# Download bootloader and compose with Linux image in output directory:
$0 -od bananapi-bpi-r3
EOF
}
@@ -153,6 +158,83 @@ find_build_dir()
return 1
}
# Map board name to bootloader identifier
# Returns bootloader name used in artifact naming
get_bootloader_name()
{
board="$1"
case "$board" in
raspberrypi-rpi64)
echo "rpi64_boot"
;;
bananapi-bpi-r3)
echo "bpi_r3_boot"
;;
friendlyarm-nanopi-r2s)
echo "nanopi_r2s_boot"
;;
*)
err "Unknown bootloader for board: $board"
return 1
;;
esac
}
# Download and extract bootloader from latest-boot release
# Downloads to dl/bootloader/ cache and extracts to temporary build directory
# Returns the temporary directory path in SDCARD_TEMP_DIR variable
download_bootloader()
{
board="$1"
build_dir="$2"
bootloader=$(get_bootloader_name "$board") || return 1
if ! command -v gh >/dev/null 2>&1; then
die "gh CLI not found. Install it or build bootloader locally."
fi
# Set up download cache directory
dl_dir="${BR2_EXTERNAL_INFIX_PATH}/dl/bootloader"
mkdir -p "$dl_dir"
# Convert underscores to dashes for filename pattern matching
bootloader_pattern=$(echo "$bootloader" | tr '_' '-')
# Find or download bootloader tarball
tarball=$(ls "$dl_dir"/${bootloader_pattern}*.tar.gz 2>/dev/null | head -n1)
if [ -z "$tarball" ] || [ -n "$FORCE_DOWNLOAD" ]; then
if [ -n "$FORCE_DOWNLOAD" ] && [ -n "$tarball" ]; then
log "Force re-downloading bootloader..."
rm -f "$tarball" "$tarball.sha256"
else
log "Downloading bootloader $bootloader from latest-boot release..."
fi
if ! gh release download latest-boot \
--repo kernelkit/infix \
--pattern "*${bootloader_pattern}*.tar.gz" \
--dir "$dl_dir"; then
die "Failed downloading bootloader from latest-boot release. Check gh authentication and network connectivity."
fi
tarball=$(ls "$dl_dir"/${bootloader_pattern}*.tar.gz 2>/dev/null | head -n1)
[ -n "$tarball" ] || die "Downloaded tarball not found in $dl_dir"
else
log "Using cached bootloader: $(basename "$tarball")"
fi
# Create temporary directory for SD card composition
SDCARD_TEMP_DIR="${build_dir}/sdcard-${board}-$$"
mkdir -p "$SDCARD_TEMP_DIR"
log "Extracting bootloader to $SDCARD_TEMP_DIR..."
tar -xzf "$tarball" --strip-components=1 -C "$SDCARD_TEMP_DIR/"
log "Bootloader ready in temporary directory"
}
# Discover boot files for Raspberry Pi boot partition
# Scans rpi-firmware directory and builds file list for genimage
discover_rpi_boot_files()
@@ -189,8 +271,19 @@ discover_rpi_boot_files()
echo "$files"
}
while getopts "hlob:r:" opt; do
while getopts "hldfob:r:" opt; do
case $opt in
b)
BOOT_DIR="$OPTARG"
STANDALONE=1
;;
d)
DOWNLOAD_BOOT=1
STANDALONE=1
;;
f)
FORCE_DOWNLOAD=1
;;
h)
usage
exit 0
@@ -199,10 +292,6 @@ while getopts "hlob:r:" opt; do
list_boards
exit 0
;;
b)
BOOT_DIR="$OPTARG"
STANDALONE=1
;;
o)
OVERRIDE=1
;;
@@ -225,12 +314,19 @@ fi
# Standalone mode: set up environment from build directories
if [ -n "$STANDALONE" ]; then
if [ -z "$BOOT_DIR" ]; then
BOOT_DIR=$(find_build_dir) || die "Could not find boot directory. Use -b option"
fi
# In download mode without explicit dirs, default to same location for both
if [ -n "$DOWNLOAD_BOOT" ]; then
default_dir=$(find_build_dir) || die "Could not find build directory. Set O= or use -b/-r option"
: "${BOOT_DIR:=$default_dir}"
: "${ROOT_DIR:=$default_dir}"
else
if [ -z "$BOOT_DIR" ]; then
BOOT_DIR=$(find_build_dir) || die "Could not find boot directory. Use -b option"
fi
if [ -z "$ROOT_DIR" ]; then
ROOT_DIR=$(find_build_dir) || die "Could not find rootfs directory. Set O= or use -r option"
if [ -z "$ROOT_DIR" ]; then
ROOT_DIR=$(find_build_dir) || die "Could not find rootfs directory. Set O= or use -r option"
fi
fi
# Set up environment variables, some required by genimage.sh
@@ -248,22 +344,33 @@ if [ -n "$STANDALONE" ]; then
fi
done
# Copy rootfs and partition images to BINARIES_DIR
# Copy rootfs and partition images to BINARIES_DIR (skip if same directory)
mkdir -p "$BINARIES_DIR"
# Normalize paths for comparison
boot_images=$(cd "$BOOT_DIR" && pwd)/images
root_images=""
if [ -f "$ROOT_DIR" ]; then
# Direct path to rootfs.squashfs file
log "Copying rootfs from $ROOT_DIR to $BINARIES_DIR/rootfs.squashfs"
cp "$ROOT_DIR" "$BINARIES_DIR/rootfs.squashfs"
elif [ -f "$ROOT_DIR/images/rootfs.squashfs" ]; then
# Build directory with images/ - copy rootfs and partition images
log "Copying artifacts from $ROOT_DIR/images/ to $BINARIES_DIR/"
cp "$ROOT_DIR/images/rootfs.squashfs" "$BINARIES_DIR/"
# Copy partition images if they exist
for img in aux.ext4 cfg.ext4 var.ext4; do
if [ -f "$ROOT_DIR/images/$img" ]; then
cp "$ROOT_DIR/images/$img" "$BINARIES_DIR/"
fi
done
root_images=$(cd "$ROOT_DIR" && pwd)/images
# Only copy if different directories
if [ "$boot_images" != "$root_images" ]; then
# Build directory with images/ - copy rootfs and partition images
log "Copying artifacts from $ROOT_DIR/images/ to $BINARIES_DIR/"
cp "$ROOT_DIR/images/rootfs.squashfs" "$BINARIES_DIR/"
# Copy partition images if they exist
for img in aux.ext4 cfg.ext4 var.ext4; do
if [ -f "$ROOT_DIR/images/$img" ]; then
cp "$ROOT_DIR/images/$img" "$BINARIES_DIR/"
fi
done
else
log "Rootfs already in place at $BINARIES_DIR/"
fi
elif [ -f "$ROOT_DIR/rootfs.squashfs" ]; then
# Directory directly containing rootfs.squashfs
log "Copying rootfs from $ROOT_DIR/rootfs.squashfs"
@@ -292,6 +399,42 @@ fi
: "${RELEASE:=""}"
: "${INFIX_ID:="infix"}"
# Download bootloader if requested
if [ -n "$DOWNLOAD_BOOT" ]; then
# Save original output location
ORIGINAL_BINARIES_DIR="$BINARIES_DIR"
download_bootloader "$BOARD" "$BUILD_DIR"
# Now use the temporary directory for composition
BINARIES_DIR="$SDCARD_TEMP_DIR"
log "Linking rootfs files to $BINARIES_DIR..."
# Link rootfs and partition images to temp directory
if [ -f "$ROOT_DIR" ]; then
# Direct path to rootfs.squashfs file
ln -sf "$(realpath "$ROOT_DIR")" "$BINARIES_DIR/rootfs.squashfs"
elif [ -f "$ROOT_DIR/images/rootfs.squashfs" ]; then
ln -sf "$(realpath "$ROOT_DIR/images/rootfs.squashfs")" "$BINARIES_DIR/rootfs.squashfs"
# Link partition images if they exist
for img in aux.ext4 cfg.ext4 var.ext4; do
if [ -f "$ROOT_DIR/images/$img" ]; then
ln -sf "$(realpath "$ROOT_DIR/images/$img")" "$BINARIES_DIR/$img"
fi
done
elif [ -f "$ROOT_DIR/rootfs.squashfs" ]; then
ln -sf "$(realpath "$ROOT_DIR/rootfs.squashfs")" "$BINARIES_DIR/rootfs.squashfs"
# Link partition images if they exist
for img in aux.ext4 cfg.ext4 var.ext4; do
if [ -f "$ROOT_DIR/$img" ]; then
ln -sf "$(realpath "$ROOT_DIR/$img")" "$BINARIES_DIR/$img"
fi
done
else
die "Could not find rootfs.squashfs in $ROOT_DIR"
fi
fi
# Template expansion
log "Generating genimage configuration for $BOARD..."
@@ -343,6 +486,25 @@ else
run_genimage "$GENIMAGE_CFG"
fi
# Post-processing: move images and cleanup if using download mode
if [ -n "$DOWNLOAD_BOOT" ]; then
log "Moving SD card images to $ORIGINAL_BINARIES_DIR..."
mkdir -p "$ORIGINAL_BINARIES_DIR"
for img in "${BINARIES_DIR}"/*-sdcard.img*; do
if [ -f "$img" ]; then
mv "$img" "$ORIGINAL_BINARIES_DIR/"
log " $(basename "$img")"
fi
done
log "Cleaning up temporary directory..."
rm -rf "$SDCARD_TEMP_DIR"
# Update BINARIES_DIR for final output message
BINARIES_DIR="$ORIGINAL_BINARIES_DIR"
fi
log "SD card image created successfully:"
for img in "${BINARIES_DIR}"/*-sdcard.img*; do
if [ -f "$img" ]; then