mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 02:11:53 +00:00
Adds stack overflow backtraces, debug info compilation, and SSH password auth for development. Reduces shutdown timeouts from 60s to 100ms for faster iteration. Fixes race condition in NetService cleanup.
545 lines
18 KiB
Bash
Executable File
545 lines
18 KiB
Bash
Executable File
#!/bin/bash
|
|
set -e
|
|
|
|
|
|
echo "==== StartOS Image Build ===="
|
|
|
|
echo "Building for architecture: $IB_TARGET_ARCH"
|
|
|
|
SOURCE_DIR="$(realpath $(dirname "${BASH_SOURCE[0]}"))"
|
|
|
|
base_dir="$(pwd -P)"
|
|
prep_results_dir="$base_dir/images-prep"
|
|
RESULTS_DIR="$base_dir/results"
|
|
echo "Saving results in: $RESULTS_DIR"
|
|
|
|
DEB_PATH="$base_dir/$1"
|
|
|
|
VERSION="$(dpkg-deb --fsys-tarfile $DEB_PATH | tar --to-stdout -xvf - ./usr/lib/startos/VERSION.txt)"
|
|
GIT_HASH="$(dpkg-deb --fsys-tarfile $DEB_PATH | tar --to-stdout -xvf - ./usr/lib/startos/GIT_HASH.txt)"
|
|
if [[ "$GIT_HASH" =~ ^@ ]]; then
|
|
GIT_HASH="unknown"
|
|
else
|
|
GIT_HASH="$(echo -n "$GIT_HASH" | head -c 7)"
|
|
fi
|
|
IB_OS_ENV="$(dpkg-deb --fsys-tarfile $DEB_PATH | tar --to-stdout -xvf - ./usr/lib/startos/ENVIRONMENT.txt)"
|
|
IB_TARGET_PLATFORM="$(dpkg-deb --fsys-tarfile $DEB_PATH | tar --to-stdout -xvf - ./usr/lib/startos/PLATFORM.txt)"
|
|
|
|
VERSION_FULL="${VERSION}-${GIT_HASH}"
|
|
if [ -n "$IB_OS_ENV" ]; then
|
|
VERSION_FULL="$VERSION_FULL~${IB_OS_ENV}"
|
|
fi
|
|
|
|
IMAGE_BASENAME=startos-${VERSION_FULL}_${IB_TARGET_PLATFORM}
|
|
|
|
BOOTLOADERS=grub-efi
|
|
if [ "$IB_TARGET_PLATFORM" = "x86_64" ] || [ "$IB_TARGET_PLATFORM" = "x86_64-nonfree" ] || [ "$IB_TARGET_PLATFORM" = "x86_64-nvidia" ]; then
|
|
IB_TARGET_ARCH=amd64
|
|
QEMU_ARCH=x86_64
|
|
BOOTLOADERS=grub-efi,syslinux
|
|
elif [ "$IB_TARGET_PLATFORM" = "aarch64" ] || [ "$IB_TARGET_PLATFORM" = "aarch64-nonfree" ] || [ "$IB_TARGET_PLATFORM" = "aarch64-nvidia" ] || [ "$IB_TARGET_PLATFORM" = "raspberrypi" ] || [ "$IB_TARGET_PLATFORM" = "rockchip64" ]; then
|
|
IB_TARGET_ARCH=arm64
|
|
QEMU_ARCH=aarch64
|
|
elif [ "$IB_TARGET_PLATFORM" = "riscv64" ] || [ "$IB_TARGET_PLATFORM" = "riscv64-nonfree" ]; then
|
|
IB_TARGET_ARCH=riscv64
|
|
QEMU_ARCH=riscv64
|
|
else
|
|
IB_TARGET_ARCH="$IB_TARGET_PLATFORM"
|
|
QEMU_ARCH="$IB_TARGET_PLATFORM"
|
|
fi
|
|
|
|
QEMU_ARGS=()
|
|
if [ "$QEMU_ARCH" != $(uname -m) ]; then
|
|
QEMU_ARGS+=(--bootstrap-qemu-arch ${IB_TARGET_ARCH})
|
|
QEMU_ARGS+=(--bootstrap-qemu-static /usr/bin/qemu-${QEMU_ARCH}-static)
|
|
fi
|
|
|
|
mkdir -p $prep_results_dir
|
|
|
|
cd $prep_results_dir
|
|
|
|
NON_FREE=
|
|
if [[ "${IB_TARGET_PLATFORM}" =~ -nonfree$ ]] || [[ "${IB_TARGET_PLATFORM}" =~ -nvidia$ ]] || [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ]; then
|
|
NON_FREE=1
|
|
fi
|
|
NVIDIA=
|
|
if [[ "${IB_TARGET_PLATFORM}" =~ -nvidia$ ]]; then
|
|
NVIDIA=1
|
|
fi
|
|
IMAGE_TYPE=iso
|
|
if [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ] || [ "${IB_TARGET_PLATFORM}" = "rockchip64" ]; then
|
|
IMAGE_TYPE=img
|
|
fi
|
|
|
|
ARCHIVE_AREAS="main contrib"
|
|
if [ "$NON_FREE" = 1 ]; then
|
|
if [ "$IB_SUITE" = "bullseye" ]; then
|
|
ARCHIVE_AREAS="$ARCHIVE_AREAS non-free"
|
|
else
|
|
ARCHIVE_AREAS="$ARCHIVE_AREAS non-free non-free-firmware"
|
|
fi
|
|
fi
|
|
|
|
PLATFORM_CONFIG_EXTRAS=()
|
|
if [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ]; then
|
|
PLATFORM_CONFIG_EXTRAS+=( --firmware-binary false )
|
|
PLATFORM_CONFIG_EXTRAS+=( --firmware-chroot false )
|
|
RPI_KERNEL_VERSION=6.12.47+rpt
|
|
PLATFORM_CONFIG_EXTRAS+=( --linux-packages linux-image-$RPI_KERNEL_VERSION )
|
|
PLATFORM_CONFIG_EXTRAS+=( --linux-flavours "rpi-v8 rpi-2712" )
|
|
elif [ "${IB_TARGET_PLATFORM}" = "rockchip64" ]; then
|
|
PLATFORM_CONFIG_EXTRAS+=( --linux-flavours rockchip64 )
|
|
elif [ "${IB_TARGET_ARCH}" = "riscv64" ]; then
|
|
PLATFORM_CONFIG_EXTRAS+=( --uefi-secure-boot=disable )
|
|
fi
|
|
|
|
|
|
cat > /etc/wgetrc << EOF
|
|
retry_connrefused = on
|
|
tries = 100
|
|
EOF
|
|
lb config \
|
|
--iso-application "StartOS v${VERSION_FULL} ${IB_TARGET_ARCH}" \
|
|
--iso-volume "StartOS v${VERSION} ${IB_TARGET_ARCH}" \
|
|
--iso-preparer "START9 LABS; HTTPS://START9.COM" \
|
|
--iso-publisher "START9 LABS; HTTPS://START9.COM" \
|
|
--backports true \
|
|
--bootappend-live "boot=live noautologin console=tty0" \
|
|
--bootloaders $BOOTLOADERS \
|
|
--cache false \
|
|
--mirror-bootstrap "https://deb.debian.org/debian/" \
|
|
--mirror-chroot "https://deb.debian.org/debian/" \
|
|
--mirror-chroot-security "https://security.debian.org/debian-security" \
|
|
-d ${IB_SUITE} \
|
|
-a ${IB_TARGET_ARCH} \
|
|
${QEMU_ARGS[@]} \
|
|
--archive-areas "${ARCHIVE_AREAS}" \
|
|
${PLATFORM_CONFIG_EXTRAS[@]}
|
|
|
|
# Overlays
|
|
|
|
mkdir -p config/packages.chroot/
|
|
cp $RESULTS_DIR/$IMAGE_BASENAME.deb config/packages.chroot/
|
|
dpkg-name config/packages.chroot/*.deb
|
|
|
|
mkdir -p config/includes.chroot/etc
|
|
echo start > config/includes.chroot/etc/hostname
|
|
cat > config/includes.chroot/etc/hosts << EOT
|
|
127.0.0.1 localhost start
|
|
::1 localhost start ip6-localhost ip6-loopback
|
|
ff02::1 ip6-allnodes
|
|
ff02::2 ip6-allrouters
|
|
EOT
|
|
|
|
if [[ "${IB_OS_ENV}" =~ (^|-)dev($|-) ]]; then
|
|
mkdir -p config/includes.chroot/etc/ssh/sshd_config.d
|
|
echo "PasswordAuthentication yes" > config/includes.chroot/etc/ssh/sshd_config.d/dev-password-auth.conf
|
|
fi
|
|
|
|
# Installer marker file (used by installed GRUB to detect the live USB)
|
|
mkdir -p config/includes.binary
|
|
touch config/includes.binary/.startos-installer
|
|
|
|
if [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ]; then
|
|
mkdir -p config/includes.chroot
|
|
git clone --depth=1 --branch=stable https://github.com/raspberrypi/rpi-firmware.git config/includes.chroot/boot
|
|
rm -rf config/includes.chroot/boot/.git config/includes.chroot/boot/modules
|
|
rsync -rLp $SOURCE_DIR/raspberrypi/squashfs/ config/includes.chroot/
|
|
fi
|
|
|
|
# Bootloaders
|
|
|
|
rm -rf config/bootloaders
|
|
cp -r /usr/share/live/build/bootloaders config/bootloaders
|
|
|
|
cat > config/bootloaders/syslinux/syslinux.cfg << EOF
|
|
include menu.cfg
|
|
default vesamenu.c32
|
|
prompt 0
|
|
timeout 50
|
|
EOF
|
|
|
|
cat > config/bootloaders/isolinux/isolinux.cfg << EOF
|
|
include menu.cfg
|
|
default vesamenu.c32
|
|
prompt 0
|
|
timeout 50
|
|
EOF
|
|
|
|
# Extract splash.png from the deb package
|
|
dpkg-deb --fsys-tarfile $DEB_PATH | tar --to-stdout -xf - ./usr/lib/startos/splash.png > /tmp/splash.png
|
|
cp /tmp/splash.png config/bootloaders/syslinux_common/splash.png
|
|
cp /tmp/splash.png config/bootloaders/isolinux/splash.png
|
|
cp /tmp/splash.png config/bootloaders/grub-pc/splash.png
|
|
rm /tmp/splash.png
|
|
|
|
sed -i -e '2i set timeout=5' config/bootloaders/grub-pc/config.cfg
|
|
|
|
# Archives
|
|
|
|
mkdir -p config/archives
|
|
|
|
if [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ]; then
|
|
# Fetch the keyring package (not the old raspberrypi.gpg.key, which has
|
|
# SHA1-only binding signatures that sqv on Trixie rejects).
|
|
KEYRING_DEB=$(mktemp)
|
|
curl -fsSL -o "$KEYRING_DEB" https://archive.raspberrypi.com/debian/pool/main/r/raspberrypi-archive-keyring/raspberrypi-archive-keyring_2025.1+rpt1_all.deb
|
|
dpkg-deb -x "$KEYRING_DEB" "$KEYRING_DEB.d"
|
|
cp "$KEYRING_DEB.d/usr/share/keyrings/raspberrypi-archive-keyring.gpg" config/archives/raspi.key
|
|
rm -rf "$KEYRING_DEB" "$KEYRING_DEB.d"
|
|
echo "deb [arch=${IB_TARGET_ARCH} signed-by=/etc/apt/trusted.gpg.d/raspi.key.gpg] https://archive.raspberrypi.com/debian/ ${IB_SUITE} main" > config/archives/raspi.list
|
|
fi
|
|
|
|
if [ "${IB_TARGET_PLATFORM}" = "rockchip64" ]; then
|
|
curl -fsSL https://apt.armbian.com/armbian.key | gpg --dearmor -o config/archives/armbian.key
|
|
echo "deb https://apt.armbian.com/ ${IB_SUITE} main" > config/archives/armbian.list
|
|
fi
|
|
|
|
if [ "$NVIDIA" = 1 ]; then
|
|
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | gpg --dearmor -o config/archives/nvidia-container-toolkit.key
|
|
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list \
|
|
| sed 's#deb https://#deb [signed-by=/etc/apt/trusted.gpg.d/nvidia-container-toolkit.key.gpg] https://#g' \
|
|
> config/archives/nvidia-container-toolkit.list
|
|
fi
|
|
|
|
cat > config/archives/backports.pref <<-EOF
|
|
Package: linux-image-*
|
|
Pin: release n=${IB_SUITE}-backports
|
|
Pin-Priority: 500
|
|
|
|
Package: linux-headers-*
|
|
Pin: release n=${IB_SUITE}-backports
|
|
Pin-Priority: 500
|
|
|
|
Package: *nvidia*
|
|
Pin: release n=${IB_SUITE}-backports
|
|
Pin-Priority: 500
|
|
EOF
|
|
|
|
# Hooks
|
|
|
|
cat > config/hooks/normal/9000-install-startos.hook.chroot << EOF
|
|
#!/bin/bash
|
|
|
|
set -e
|
|
|
|
if [ "${IB_TARGET_PLATFORM}" != "raspberrypi" ]; then
|
|
/usr/lib/startos/scripts/enable-kiosk
|
|
fi
|
|
|
|
if [ "${NVIDIA}" = "1" ]; then
|
|
# install a specific NVIDIA driver version
|
|
|
|
# ---------------- configuration ----------------
|
|
NVIDIA_DRIVER_VERSION="\${NVIDIA_DRIVER_VERSION:-580.126.09}"
|
|
|
|
BASE_URL="https://download.nvidia.com/XFree86/Linux-${QEMU_ARCH}"
|
|
|
|
echo "[nvidia-hook] Using NVIDIA driver: \${NVIDIA_DRIVER_VERSION}" >&2
|
|
|
|
# ---------------- kernel version ----------------
|
|
|
|
# Determine target kernel version from newest /boot/vmlinuz-* in the chroot.
|
|
KVER="\$(
|
|
ls -1t /boot/vmlinuz-* 2>/dev/null \
|
|
| head -n1 \
|
|
| sed 's|.*/vmlinuz-||'
|
|
)"
|
|
|
|
if [ -z "\${KVER}" ]; then
|
|
echo "[nvidia-hook] ERROR: no /boot/vmlinuz-* found; cannot determine kernel version" >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "[nvidia-hook] Target kernel version: \${KVER}" >&2
|
|
|
|
# Ensure kernel headers are present
|
|
TEMP_APT_DEPS=(build-essential pkg-config)
|
|
if [ ! -e "/lib/modules/\${KVER}/build" ]; then
|
|
TEMP_APT_DEPS+=(linux-headers-\${KVER})
|
|
fi
|
|
|
|
echo "[nvidia-hook] Installing build dependencies" >&2
|
|
|
|
/usr/lib/startos/scripts/install-equivs <<-EOF
|
|
Package: nvidia-depends
|
|
Version: \${NVIDIA_DRIVER_VERSION}
|
|
Section: unknown
|
|
Priority: optional
|
|
Depends: \${dep_list="\$(IFS=', '; echo "\${TEMP_APT_DEPS[*]}")"}
|
|
EOF
|
|
|
|
# ---------------- download and run installer ----------------
|
|
|
|
RUN_NAME="NVIDIA-Linux-${QEMU_ARCH}-\${NVIDIA_DRIVER_VERSION}.run"
|
|
RUN_PATH="/root/\${RUN_NAME}"
|
|
RUN_URL="\${BASE_URL}/\${NVIDIA_DRIVER_VERSION}/\${RUN_NAME}"
|
|
|
|
echo "[nvidia-hook] Downloading \${RUN_URL}" >&2
|
|
wget -O "\${RUN_PATH}" "\${RUN_URL}"
|
|
chmod +x "\${RUN_PATH}"
|
|
|
|
echo "[nvidia-hook] Running NVIDIA installer for kernel \${KVER}" >&2
|
|
|
|
if ! sh "\${RUN_PATH}" \
|
|
--silent \
|
|
--kernel-name="\${KVER}" \
|
|
--no-x-check \
|
|
--no-nouveau-check \
|
|
--no-runlevel-check; then
|
|
cat /var/log/nvidia-installer.log
|
|
exit 1
|
|
fi
|
|
|
|
# Rebuild module metadata
|
|
echo "[nvidia-hook] Running depmod for \${KVER}" >&2
|
|
depmod -a "\${KVER}"
|
|
|
|
echo "[nvidia-hook] NVIDIA \${NVIDIA_DRIVER_VERSION} installation complete for kernel \${KVER}" >&2
|
|
|
|
echo "[nvidia-hook] Removing .run installer..." >&2
|
|
rm -f "\${RUN_PATH}"
|
|
|
|
echo "[nvidia-hook] Blacklisting nouveau..." >&2
|
|
echo "blacklist nouveau" > /etc/modprobe.d/blacklist-nouveau.conf
|
|
echo "options nouveau modeset=0" >> /etc/modprobe.d/blacklist-nouveau.conf
|
|
|
|
echo "[nvidia-hook] Rebuilding initramfs..." >&2
|
|
update-initramfs -u -k "\${KVER}"
|
|
|
|
echo "[nvidia-hook] Removing build dependencies..." >&2
|
|
apt-get purge -y nvidia-depends
|
|
apt-get autoremove -y
|
|
echo "[nvidia-hook] Removed build dependencies." >&2
|
|
fi
|
|
|
|
# Install linux-kbuild for sign-file (Secure Boot module signing)
|
|
KVER_ALL="\$(ls -1t /boot/vmlinuz-* 2>/dev/null | head -n1 | sed 's|.*/vmlinuz-||')"
|
|
if [ -n "\${KVER_ALL}" ]; then
|
|
KBUILD_VER="\$(echo "\${KVER_ALL}" | grep -oP '^\d+\.\d+')"
|
|
if [ -n "\${KBUILD_VER}" ]; then
|
|
echo "[build] Installing linux-kbuild-\${KBUILD_VER} for Secure Boot support" >&2
|
|
apt-get install -y "linux-kbuild-\${KBUILD_VER}" || echo "[build] WARNING: linux-kbuild-\${KBUILD_VER} not available" >&2
|
|
fi
|
|
fi
|
|
|
|
cp /etc/resolv.conf /etc/resolv.conf.bak
|
|
|
|
if [ "${IB_SUITE}" = trixie ] && [ "${IB_TARGET_ARCH}" != riscv64 ]; then
|
|
echo 'deb https://deb.debian.org/debian/ bookworm main' > /etc/apt/sources.list.d/bookworm.list
|
|
apt-get update
|
|
apt-get install -y postgresql-15
|
|
rm /etc/apt/sources.list.d/bookworm.list
|
|
apt-get update
|
|
systemctl mask postgresql
|
|
fi
|
|
|
|
if [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ]; then
|
|
ln -sf /usr/bin/pi-beep /usr/local/bin/beep
|
|
sh /boot/firmware/config.sh > /boot/firmware/config.txt
|
|
mkinitramfs -c gzip -o /boot/initrd.img-${RPI_KERNEL_VERSION}-rpi-v8 ${RPI_KERNEL_VERSION}-rpi-v8
|
|
mkinitramfs -c gzip -o /boot/initrd.img-${RPI_KERNEL_VERSION}-rpi-2712 ${RPI_KERNEL_VERSION}-rpi-2712
|
|
cp /usr/lib/u-boot/rpi_arm64/u-boot.bin /boot/firmware/u-boot.bin
|
|
fi
|
|
|
|
useradd --shell /bin/bash -G startos -m start9
|
|
echo start9:embassy | chpasswd
|
|
usermod -aG sudo start9
|
|
usermod -aG systemd-journal start9
|
|
|
|
echo "start9 ALL=(ALL:ALL) NOPASSWD: ALL" | sudo tee "/etc/sudoers.d/010_start9-nopasswd"
|
|
|
|
if ! [[ "${IB_OS_ENV}" =~ (^|-)dev($|-) ]]; then
|
|
passwd -l start9
|
|
fi
|
|
|
|
EOF
|
|
|
|
SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:-$(date '+%s')}"
|
|
|
|
if lb bootstrap; then
|
|
true
|
|
else
|
|
EXIT=$?
|
|
cat ./chroot/debootstrap/debootstrap.log
|
|
exit $EXIT
|
|
fi
|
|
lb chroot
|
|
lb installer
|
|
lb binary_chroot
|
|
lb chroot_prep install all mode-apt-install-binary mode-archives-chroot
|
|
mv chroot/chroot/etc/resolv.conf.bak chroot/chroot/etc/resolv.conf
|
|
lb binary_rootfs
|
|
|
|
cp $prep_results_dir/binary/live/filesystem.squashfs $RESULTS_DIR/$IMAGE_BASENAME.squashfs
|
|
|
|
if [ "${IMAGE_TYPE}" = iso ]; then
|
|
|
|
lb binary_manifest
|
|
lb binary_package-lists
|
|
lb binary_linux-image
|
|
lb binary_memtest
|
|
lb binary_grub-legacy
|
|
lb binary_grub-pc
|
|
lb binary_grub_cfg
|
|
lb binary_syslinux
|
|
lb binary_disk
|
|
lb binary_loadlin
|
|
lb binary_win32-loader
|
|
lb binary_includes
|
|
lb binary_grub-efi
|
|
lb binary_hooks
|
|
lb binary_checksums
|
|
find binary -newermt "$(date -d@${SOURCE_DATE_EPOCH} '+%Y-%m-%d %H:%M:%S')" -printf "%y %p\n" -exec touch '{}' -d@${SOURCE_DATE_EPOCH} --no-dereference ';' > binary.modified_timestamps
|
|
lb binary_iso
|
|
lb binary_onie
|
|
lb binary_netboot
|
|
lb binary_tar
|
|
lb binary_hdd
|
|
lb binary_zsync
|
|
lb chroot_prep remove all mode-archives-chroot
|
|
lb source
|
|
|
|
mv $prep_results_dir/live-image-${IB_TARGET_ARCH}.hybrid.iso $RESULTS_DIR/$IMAGE_BASENAME.iso
|
|
|
|
elif [ "${IMAGE_TYPE}" = img ]; then
|
|
|
|
SECTOR_LEN=512
|
|
FW_START=$((1024 * 1024)) # 1MiB (sector 2048) — Pi-specific
|
|
FW_LEN=$((128 * 1024 * 1024)) # 128MiB (Pi firmware + U-Boot + DTBs)
|
|
FW_END=$((FW_START + FW_LEN - 1))
|
|
ESP_START=$((FW_END + 1)) # 100MB EFI System Partition (matches os_install)
|
|
ESP_LEN=$((100 * 1024 * 1024))
|
|
ESP_END=$((ESP_START + ESP_LEN - 1))
|
|
BOOT_START=$((ESP_END + 1)) # 2GB /boot (matches os_install)
|
|
BOOT_LEN=$((2 * 1024 * 1024 * 1024))
|
|
BOOT_END=$((BOOT_START + BOOT_LEN - 1))
|
|
ROOT_START=$((BOOT_END + 1))
|
|
|
|
# Size root partition to fit the squashfs + 256MB overhead for btrfs
|
|
# metadata and config overlay, avoiding the need for btrfs resize
|
|
SQUASHFS_SIZE=$(stat -c %s $prep_results_dir/binary/live/filesystem.squashfs)
|
|
ROOT_LEN=$(( SQUASHFS_SIZE + 256 * 1024 * 1024 ))
|
|
# Align to sector boundary
|
|
ROOT_LEN=$(( (ROOT_LEN + SECTOR_LEN - 1) / SECTOR_LEN * SECTOR_LEN ))
|
|
|
|
# Total image: partitions + GPT backup header (34 sectors)
|
|
IMG_LEN=$((ROOT_START + ROOT_LEN + 34 * SECTOR_LEN))
|
|
|
|
# Fixed GPT partition UUIDs (deterministic, based on old MBR disk ID cb15ae4d)
|
|
FW_UUID=cb15ae4d-0001-4000-8000-000000000001
|
|
ESP_UUID=cb15ae4d-0002-4000-8000-000000000002
|
|
BOOT_UUID=cb15ae4d-0003-4000-8000-000000000003
|
|
ROOT_UUID=cb15ae4d-0004-4000-8000-000000000004
|
|
|
|
TARGET_NAME=$prep_results_dir/${IMAGE_BASENAME}.img
|
|
truncate -s $IMG_LEN $TARGET_NAME
|
|
|
|
sfdisk $TARGET_NAME <<-EOF
|
|
label: gpt
|
|
|
|
${TARGET_NAME}1 : start=$((FW_START / SECTOR_LEN)), size=$((FW_LEN / SECTOR_LEN)), type=EBD0A0A2-B9E5-4433-87C0-68B6B72699C7, uuid=${FW_UUID}, name="firmware"
|
|
${TARGET_NAME}2 : start=$((ESP_START / SECTOR_LEN)), size=$((ESP_LEN / SECTOR_LEN)), type=C12A7328-F81F-11D2-BA4B-00A0C93EC93B, uuid=${ESP_UUID}, name="efi"
|
|
${TARGET_NAME}3 : start=$((BOOT_START / SECTOR_LEN)), size=$((BOOT_LEN / SECTOR_LEN)), type=0FC63DAF-8483-4772-8E79-3D69D8477DE4, uuid=${BOOT_UUID}, name="boot"
|
|
${TARGET_NAME}4 : start=$((ROOT_START / SECTOR_LEN)), size=$((ROOT_LEN / SECTOR_LEN)), type=B921B045-1DF0-41C3-AF44-4C6F280D3FAE, uuid=${ROOT_UUID}, name="root"
|
|
EOF
|
|
|
|
# Create named loop device nodes (high minor numbers to avoid conflicts)
|
|
# and detach any stale ones from previous failed builds
|
|
FW_DEV=/dev/startos-loop-fw
|
|
ESP_DEV=/dev/startos-loop-esp
|
|
BOOT_DEV=/dev/startos-loop-boot
|
|
ROOT_DEV=/dev/startos-loop-root
|
|
for dev in $FW_DEV:200 $ESP_DEV:201 $BOOT_DEV:202 $ROOT_DEV:203; do
|
|
name=${dev%:*}
|
|
minor=${dev#*:}
|
|
[ -e $name ] || mknod $name b 7 $minor
|
|
losetup -d $name 2>/dev/null || true
|
|
done
|
|
|
|
losetup $FW_DEV --offset $FW_START --sizelimit $FW_LEN $TARGET_NAME
|
|
losetup $ESP_DEV --offset $ESP_START --sizelimit $ESP_LEN $TARGET_NAME
|
|
losetup $BOOT_DEV --offset $BOOT_START --sizelimit $BOOT_LEN $TARGET_NAME
|
|
losetup $ROOT_DEV --offset $ROOT_START --sizelimit $ROOT_LEN $TARGET_NAME
|
|
|
|
mkfs.vfat -F32 -n firmware $FW_DEV
|
|
mkfs.vfat -F32 -n efi $ESP_DEV
|
|
mkfs.vfat -F32 -n boot $BOOT_DEV
|
|
mkfs.btrfs -f -L rootfs $ROOT_DEV
|
|
|
|
TMPDIR=$(mktemp -d)
|
|
|
|
# Extract boot files from squashfs to staging area
|
|
BOOT_STAGING=$(mktemp -d)
|
|
unsquashfs -n -f -d $BOOT_STAGING $prep_results_dir/binary/live/filesystem.squashfs boot
|
|
|
|
# Mount partitions (nested: firmware and efi inside boot)
|
|
mkdir -p $TMPDIR/boot $TMPDIR/root
|
|
mount $BOOT_DEV $TMPDIR/boot
|
|
mkdir -p $TMPDIR/boot/firmware $TMPDIR/boot/efi
|
|
mount $FW_DEV $TMPDIR/boot/firmware
|
|
mount $ESP_DEV $TMPDIR/boot/efi
|
|
mount $ROOT_DEV $TMPDIR/root
|
|
|
|
# Copy boot files — nested mounts route firmware/* to the firmware partition
|
|
cp -a $BOOT_STAGING/boot/. $TMPDIR/boot/
|
|
rm -rf $BOOT_STAGING
|
|
|
|
mkdir $TMPDIR/root/images $TMPDIR/root/config
|
|
B3SUM=$(b3sum $prep_results_dir/binary/live/filesystem.squashfs | head -c 16)
|
|
cp $prep_results_dir/binary/live/filesystem.squashfs $TMPDIR/root/images/$B3SUM.rootfs
|
|
ln -rsf $TMPDIR/root/images/$B3SUM.rootfs $TMPDIR/root/config/current.rootfs
|
|
|
|
mkdir -p $TMPDIR/next $TMPDIR/lower $TMPDIR/root/config/work $TMPDIR/root/config/overlay
|
|
mount $TMPDIR/root/config/current.rootfs $TMPDIR/lower
|
|
|
|
mount -t overlay -o lowerdir=$TMPDIR/lower,workdir=$TMPDIR/root/config/work,upperdir=$TMPDIR/root/config/overlay overlay $TMPDIR/next
|
|
|
|
if [ "${IB_TARGET_PLATFORM}" = "raspberrypi" ]; then
|
|
rsync -a $SOURCE_DIR/raspberrypi/img/ $TMPDIR/next/
|
|
|
|
# Install GRUB: ESP at /boot/efi (Part 2), /boot (Part 3)
|
|
mkdir -p $TMPDIR/next/boot \
|
|
$TMPDIR/next/dev $TMPDIR/next/proc $TMPDIR/next/sys $TMPDIR/next/media/startos/root
|
|
mount --rbind $TMPDIR/boot $TMPDIR/next/boot
|
|
mount --bind /dev $TMPDIR/next/dev
|
|
mount --bind /proc $TMPDIR/next/proc
|
|
mount --bind /sys $TMPDIR/next/sys
|
|
mount --bind $TMPDIR/root $TMPDIR/next/media/startos/root
|
|
|
|
chroot $TMPDIR/next grub-install --target=arm64-efi --removable --efi-directory=/boot/efi --boot-directory=/boot --no-nvram
|
|
chroot $TMPDIR/next update-grub
|
|
|
|
umount $TMPDIR/next/media/startos/root
|
|
umount $TMPDIR/next/sys
|
|
umount $TMPDIR/next/proc
|
|
umount $TMPDIR/next/dev
|
|
umount -l $TMPDIR/next/boot
|
|
|
|
# Fix root= in grub.cfg: update-grub sees loop devices, but the
|
|
# real device uses a fixed GPT PARTUUID for root (Part 4).
|
|
sed -i "s|root=[^ ]*|root=PARTUUID=${ROOT_UUID}|g" $TMPDIR/boot/grub/grub.cfg
|
|
|
|
# Inject first-boot resize script into GRUB config
|
|
sed -i 's| boot=startos| boot=startos init=/usr/lib/startos/scripts/init_resize\.sh|' $TMPDIR/boot/grub/grub.cfg
|
|
fi
|
|
|
|
umount $TMPDIR/next
|
|
umount $TMPDIR/lower
|
|
|
|
umount $TMPDIR/boot/firmware
|
|
umount $TMPDIR/boot/efi
|
|
umount $TMPDIR/boot
|
|
umount $TMPDIR/root
|
|
|
|
losetup -d $ROOT_DEV
|
|
losetup -d $BOOT_DEV
|
|
losetup -d $ESP_DEV
|
|
losetup -d $FW_DEV
|
|
|
|
mv $TARGET_NAME $RESULTS_DIR/$IMAGE_BASENAME.img
|
|
|
|
fi
|
|
|
|
chown $IB_UID:$IB_UID $RESULTS_DIR/$IMAGE_BASENAME.*
|