Wip
This commit is contained in:
@@ -2,6 +2,49 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## V30 2026-03-20 07:50:00
|
||||||
|
|
||||||
|
**Add kernel build script, initramfs, and live ISO boot support (Phase 4)**
|
||||||
|
|
||||||
|
### Changes:
|
||||||
|
- Created `kernel/build-kernel.sh` — automated kernel build script:
|
||||||
|
- Downloads Linux 6.19.9 from cdn.kernel.org (with mirror fallback)
|
||||||
|
- Applies DarkForge config via `make olddefconfig`
|
||||||
|
- Verifies all critical config options (EFI_STUB, NVME, EXT4, PREEMPT, etc.)
|
||||||
|
- Compiles bzImage with `-j32` and KCFLAGS="-march=znver4 -pipe"
|
||||||
|
- Outputs to `kernel/vmlinuz`, `kernel/vmlinuz.efi`, `kernel/System.map`
|
||||||
|
- Installs modules to `kernel/modules/`
|
||||||
|
- Updated `kernel/config`:
|
||||||
|
- Added CONFIG_CMDLINE_BOOL=y with serial console (ttyS0,115200n8)
|
||||||
|
- Added CONFIG_CMDLINE_OVERRIDE=n (allows efibootmgr to override at boot)
|
||||||
|
- Added CONFIG_BLK_DEV_INITRD=y (needed for live ISO squashfs boot)
|
||||||
|
- Added CONFIG_SERIAL_8250=y + CONFIG_SERIAL_8250_CONSOLE=y
|
||||||
|
- Created `src/iso/initramfs/init` — live ISO init script:
|
||||||
|
- Mounts proc/sys/devtmpfs, scans for DarkForge media on CD/USB/NVMe
|
||||||
|
- Mounts squashfs root, creates tmpfs overlay for writable root
|
||||||
|
- switch_roots into the live system
|
||||||
|
- Falls back to emergency shell if media not found
|
||||||
|
- Created `src/iso/build-initramfs.sh` — builds initramfs.cpio.gz from busybox
|
||||||
|
- Updated `src/iso/build-iso-arch.sh`:
|
||||||
|
- Now builds initramfs automatically if not present
|
||||||
|
- Includes initramfs in the EFI partition alongside kernel
|
||||||
|
- Creates startup.nsh for UEFI shell fallback
|
||||||
|
- Dynamically sizes the ESP based on kernel + initramfs size
|
||||||
|
- Updated `tests/run-tests.sh` QEMU test:
|
||||||
|
- Uses QEMU direct kernel boot (`-kernel` + `-initrd`) when a compiled kernel
|
||||||
|
is available — more reliable than UEFI ISO boot for testing
|
||||||
|
- Falls back to OVMF UEFI boot when no compiled kernel exists
|
||||||
|
|
||||||
|
### Plan deviation/changes:
|
||||||
|
- Kernel version bumped from 6.19.8 to 6.19.9 (latest 6.19.x stable)
|
||||||
|
|
||||||
|
### What is missing/needs polish:
|
||||||
|
- Kernel must be compiled by running `bash kernel/build-kernel.sh` on the target machine
|
||||||
|
- Once kernel is built, `qemu.kernel_boots` and `qemu.reaches_userspace` should pass
|
||||||
|
- Live ISO boot chain: kernel → initramfs → squashfs → overlay → init — needs end-to-end test
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## V29 2026-03-20 07:36:03
|
## V29 2026-03-20 07:36:03
|
||||||
|
|
||||||
**Fix brace expansion failure in ISO build script causing missing directories**
|
**Fix brace expansion failure in ISO build script causing missing directories**
|
||||||
|
|||||||
227
kernel/build-kernel.sh
Executable file
227
kernel/build-kernel.sh
Executable file
@@ -0,0 +1,227 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# ============================================================================
|
||||||
|
# DarkForge Linux — Kernel Build Script
|
||||||
|
# ============================================================================
|
||||||
|
# Downloads, configures, and compiles the Linux kernel for DarkForge.
|
||||||
|
#
|
||||||
|
# Prerequisites (Arch Linux):
|
||||||
|
# sudo pacman -S base-devel bc flex bison libelf perl openssl
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# cd /path/to/project-root
|
||||||
|
# bash kernel/build-kernel.sh
|
||||||
|
#
|
||||||
|
# Output:
|
||||||
|
# kernel/vmlinuz — Compressed kernel (bzImage)
|
||||||
|
# kernel/vmlinuz.efi — Copy with .efi extension for EFISTUB
|
||||||
|
# kernel/System.map — Symbol map
|
||||||
|
# kernel/modules/ — Kernel modules (if any)
|
||||||
|
# build/linux-<version>/ — Full kernel source tree (for module builds)
|
||||||
|
#
|
||||||
|
# Notes:
|
||||||
|
# - Runs as regular user (no sudo needed for compile)
|
||||||
|
# - Uses the config at kernel/config
|
||||||
|
# - Applies 'make olddefconfig' to fill in defaults for unspecified options
|
||||||
|
# - Builds with -j32 (16C/32T)
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||||
|
|
||||||
|
# --- Configuration -----------------------------------------------------------
|
||||||
|
KERNEL_VERSION="6.19.9"
|
||||||
|
KERNEL_MAJOR="6.19"
|
||||||
|
KERNEL_URL="https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-${KERNEL_VERSION}.tar.xz"
|
||||||
|
KERNEL_SIGN_URL="${KERNEL_URL}.sign"
|
||||||
|
BUILD_DIR="${PROJECT_ROOT}/build"
|
||||||
|
KERNEL_SRC="${BUILD_DIR}/linux-${KERNEL_VERSION}"
|
||||||
|
CONFIG_FILE="${SCRIPT_DIR}/config"
|
||||||
|
JOBS=32
|
||||||
|
|
||||||
|
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; NC='\033[0m'
|
||||||
|
info() { echo -e "${CYAN}>>> $1${NC}"; }
|
||||||
|
ok() { echo -e "${GREEN}>>> $1${NC}"; }
|
||||||
|
warn() { echo -e "${YELLOW}!!! $1${NC}"; }
|
||||||
|
die() { echo -e "${RED}!!! $1${NC}"; exit 1; }
|
||||||
|
|
||||||
|
# --- Preflight ---------------------------------------------------------------
|
||||||
|
info "DarkForge Kernel Builder — Linux ${KERNEL_VERSION}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check required tools
|
||||||
|
for tool in gcc make flex bison bc perl; do
|
||||||
|
command -v "$tool" >/dev/null 2>&1 || die "Missing: $tool — install with pacman"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Check for libelf headers (needed for CONFIG_BPF_SYSCALL, etc.)
|
||||||
|
if ! pkg-config --exists libelf 2>/dev/null; then
|
||||||
|
warn "libelf not found — install with: sudo pacman -S libelf"
|
||||||
|
warn "Continuing anyway (may fail if CONFIG_BPF_SYSCALL=y)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for openssl headers (needed for module signing)
|
||||||
|
if ! pkg-config --exists openssl 2>/dev/null && ! [ -f /usr/include/openssl/opensslv.h ]; then
|
||||||
|
warn "OpenSSL headers not found — install with: sudo pacman -S openssl"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- Download kernel source --------------------------------------------------
|
||||||
|
mkdir -p "${BUILD_DIR}"
|
||||||
|
|
||||||
|
TARBALL="${BUILD_DIR}/linux-${KERNEL_VERSION}.tar.xz"
|
||||||
|
if [ -f "$TARBALL" ]; then
|
||||||
|
info "Kernel tarball already downloaded: ${TARBALL}"
|
||||||
|
else
|
||||||
|
info "Downloading Linux ${KERNEL_VERSION}..."
|
||||||
|
# Try cdn.kernel.org first, then mirrors
|
||||||
|
for url in \
|
||||||
|
"https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-${KERNEL_VERSION}.tar.xz" \
|
||||||
|
"https://mirrors.edge.kernel.org/pub/linux/kernel/v6.x/linux-${KERNEL_VERSION}.tar.xz" \
|
||||||
|
"https://mirror.aarnet.edu.au/pub/ftp.kernel.org/linux/kernel/v6.x/linux-${KERNEL_VERSION}.tar.xz"; do
|
||||||
|
if curl --connect-timeout 15 -fL# -o "$TARBALL" "$url" 2>&1; then
|
||||||
|
ok "Downloaded from ${url}"
|
||||||
|
break
|
||||||
|
else
|
||||||
|
warn "Failed: ${url}"
|
||||||
|
rm -f "$TARBALL"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
[ -f "$TARBALL" ] || die "Failed to download kernel tarball"
|
||||||
|
|
||||||
|
# Verify tarball is valid
|
||||||
|
if ! xz -t "$TARBALL" 2>/dev/null; then
|
||||||
|
die "Kernel tarball is corrupt — delete ${TARBALL} and re-run"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- Extract kernel source ---------------------------------------------------
|
||||||
|
if [ -d "$KERNEL_SRC" ] && [ -f "$KERNEL_SRC/Makefile" ]; then
|
||||||
|
info "Kernel source already extracted: ${KERNEL_SRC}"
|
||||||
|
else
|
||||||
|
info "Extracting Linux ${KERNEL_VERSION}..."
|
||||||
|
tar -xf "$TARBALL" -C "${BUILD_DIR}"
|
||||||
|
[ -d "$KERNEL_SRC" ] || die "Expected directory ${KERNEL_SRC} not found after extraction"
|
||||||
|
ok "Extracted to ${KERNEL_SRC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- Apply DarkForge config --------------------------------------------------
|
||||||
|
info "Applying DarkForge kernel config..."
|
||||||
|
|
||||||
|
# Copy our config
|
||||||
|
cp "$CONFIG_FILE" "${KERNEL_SRC}/.config"
|
||||||
|
|
||||||
|
# Update version target in config header comment (informational only)
|
||||||
|
# The actual version comes from the kernel source, not the config
|
||||||
|
|
||||||
|
# Run olddefconfig to fill in all unspecified options with defaults
|
||||||
|
# This is critical — our config only specifies ~176 options out of thousands
|
||||||
|
cd "$KERNEL_SRC"
|
||||||
|
make olddefconfig
|
||||||
|
|
||||||
|
ok "Config applied — $(grep -c '=y\|=m' .config) options enabled"
|
||||||
|
|
||||||
|
# Verify critical options survived olddefconfig
|
||||||
|
CRITICAL_OPTS=(
|
||||||
|
"CONFIG_EFI_STUB=y"
|
||||||
|
"CONFIG_BLK_DEV_NVME=y"
|
||||||
|
"CONFIG_EXT4_FS=y"
|
||||||
|
"CONFIG_PREEMPT=y"
|
||||||
|
"CONFIG_MODULES=y"
|
||||||
|
"CONFIG_DRM=y"
|
||||||
|
"CONFIG_R8169=y"
|
||||||
|
"CONFIG_EFI=y"
|
||||||
|
)
|
||||||
|
FAIL=0
|
||||||
|
for opt in "${CRITICAL_OPTS[@]}"; do
|
||||||
|
key="${opt%%=*}"
|
||||||
|
if ! grep -q "^${opt}$" .config; then
|
||||||
|
warn "CRITICAL: ${opt} not set in final config!"
|
||||||
|
FAIL=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ "$FAIL" -eq 1 ]; then
|
||||||
|
die "Critical config options missing after olddefconfig — review .config"
|
||||||
|
fi
|
||||||
|
ok "All critical config options verified"
|
||||||
|
|
||||||
|
# --- Compile -----------------------------------------------------------------
|
||||||
|
info "Compiling Linux ${KERNEL_VERSION} with -j${JOBS}..."
|
||||||
|
info "This will take a few minutes on 16C/32T..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Set DarkForge compiler flags for kernel build
|
||||||
|
# Note: kernel has its own CFLAGS handling; -march is passed via KCFLAGS
|
||||||
|
# The kernel's CONFIG_MZEN4 handles most CPU-specific codegen
|
||||||
|
KCFLAGS="-march=znver4 -pipe"
|
||||||
|
# znver4 because znver5 may not be fully supported by all kernel assembly
|
||||||
|
# TODO: test znver5 when compiler+kernel support is confirmed
|
||||||
|
|
||||||
|
START_TIME=$(date +%s)
|
||||||
|
|
||||||
|
make -j${JOBS} KCFLAGS="$KCFLAGS" bzImage 2>&1 | tail -20
|
||||||
|
|
||||||
|
END_TIME=$(date +%s)
|
||||||
|
ELAPSED=$((END_TIME - START_TIME))
|
||||||
|
|
||||||
|
if [ -f "arch/x86/boot/bzImage" ]; then
|
||||||
|
ok "Kernel compiled in ${ELAPSED}s"
|
||||||
|
else
|
||||||
|
die "Kernel compilation failed — check output above"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build modules (for any =m options)
|
||||||
|
info "Building kernel modules..."
|
||||||
|
make -j${JOBS} modules 2>&1 | tail -5
|
||||||
|
ok "Modules built"
|
||||||
|
|
||||||
|
# --- Install outputs ---------------------------------------------------------
|
||||||
|
info "Installing kernel outputs..."
|
||||||
|
|
||||||
|
# Copy bzImage
|
||||||
|
cp arch/x86/boot/bzImage "${SCRIPT_DIR}/vmlinuz"
|
||||||
|
cp arch/x86/boot/bzImage "${SCRIPT_DIR}/vmlinuz.efi"
|
||||||
|
ok "Kernel: ${SCRIPT_DIR}/vmlinuz ($(du -h "${SCRIPT_DIR}/vmlinuz" | cut -f1))"
|
||||||
|
|
||||||
|
# Copy System.map
|
||||||
|
cp System.map "${SCRIPT_DIR}/System.map"
|
||||||
|
|
||||||
|
# Install modules to a staging directory
|
||||||
|
MODULES_DIR="${SCRIPT_DIR}/modules"
|
||||||
|
rm -rf "$MODULES_DIR"
|
||||||
|
make INSTALL_MOD_PATH="$MODULES_DIR" modules_install 2>&1 | tail -3
|
||||||
|
ok "Modules installed to ${MODULES_DIR}"
|
||||||
|
|
||||||
|
# Verify the kernel is a valid EFI application
|
||||||
|
if file "${SCRIPT_DIR}/vmlinuz" | grep -q "bzImage"; then
|
||||||
|
ok "Kernel is a valid bzImage"
|
||||||
|
elif file "${SCRIPT_DIR}/vmlinuz" | grep -q "EFI\|PE32"; then
|
||||||
|
ok "Kernel is a valid EFI binary"
|
||||||
|
else
|
||||||
|
warn "Kernel type: $(file "${SCRIPT_DIR}/vmlinuz")"
|
||||||
|
warn "May not boot via EFISTUB — verify manually"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- Summary -----------------------------------------------------------------
|
||||||
|
echo ""
|
||||||
|
echo "============================================================================"
|
||||||
|
echo -e "${GREEN} DarkForge Kernel Build Complete${NC}"
|
||||||
|
echo "============================================================================"
|
||||||
|
echo ""
|
||||||
|
echo " Version: Linux ${KERNEL_VERSION}-darkforge"
|
||||||
|
echo " Kernel: ${SCRIPT_DIR}/vmlinuz"
|
||||||
|
echo " Kernel EFI: ${SCRIPT_DIR}/vmlinuz.efi"
|
||||||
|
echo " System.map: ${SCRIPT_DIR}/System.map"
|
||||||
|
echo " Modules: ${MODULES_DIR}/"
|
||||||
|
echo " Source: ${KERNEL_SRC}/"
|
||||||
|
echo ""
|
||||||
|
echo " Compile time: ${ELAPSED}s"
|
||||||
|
echo " Kernel size: $(du -h "${SCRIPT_DIR}/vmlinuz" | cut -f1)"
|
||||||
|
echo ""
|
||||||
|
echo " Next steps:"
|
||||||
|
echo " 1. Rebuild ISO: sudo bash src/iso/build-iso-arch.sh"
|
||||||
|
echo " 2. Test in QEMU: see tests/run-tests.sh"
|
||||||
|
echo " 3. For real hardware: copy vmlinuz.efi to ESP as /EFI/Linux/vmlinuz.efi"
|
||||||
|
echo ""
|
||||||
|
echo "============================================================================"
|
||||||
@@ -443,3 +443,26 @@ CONFIG_FANOTIFY=y
|
|||||||
|
|
||||||
CONFIG_EXPERT=y
|
CONFIG_EXPERT=y
|
||||||
# Enable expert mode to access all configuration options
|
# Enable expert mode to access all configuration options
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# KERNEL COMMAND LINE
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
CONFIG_CMDLINE_BOOL=y
|
||||||
|
CONFIG_CMDLINE="console=tty0 console=ttyS0,115200n8"
|
||||||
|
CONFIG_CMDLINE_OVERRIDE=n
|
||||||
|
# Embedded default command line for EFISTUB boot:
|
||||||
|
# - console=tty0: keep framebuffer console for real hardware
|
||||||
|
# - console=ttyS0: serial console for QEMU testing and debugging
|
||||||
|
# CMDLINE_OVERRIDE=n allows efibootmgr to append/override at boot time
|
||||||
|
# Root device is set per-boot:
|
||||||
|
# Live ISO: root= is handled by the initramfs (mounts squashfs)
|
||||||
|
# Installed: efibootmgr -u "root=/dev/nvme0n1p2 rootfstype=ext4"
|
||||||
|
|
||||||
|
CONFIG_BLK_DEV_INITRD=y
|
||||||
|
# Initramfs support — needed for live ISO boot (squashfs overlay)
|
||||||
|
# Installed system boots without initramfs (NVMe + ext4 are built-in)
|
||||||
|
|
||||||
|
CONFIG_SERIAL_8250=y
|
||||||
|
CONFIG_SERIAL_8250_CONSOLE=y
|
||||||
|
# Serial console support — needed for QEMU testing and remote debugging
|
||||||
|
|||||||
80
src/iso/build-initramfs.sh
Executable file
80
src/iso/build-initramfs.sh
Executable file
@@ -0,0 +1,80 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# ============================================================================
|
||||||
|
# DarkForge Linux — Build Initramfs for Live ISO
|
||||||
|
# ============================================================================
|
||||||
|
# Creates a minimal initramfs containing busybox and the init script.
|
||||||
|
# The initramfs is used by the live ISO to mount the squashfs root.
|
||||||
|
#
|
||||||
|
# Output: src/iso/initramfs.cpio.gz (embedded in the ISO alongside the kernel)
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# bash src/iso/build-initramfs.sh
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
|
||||||
|
INITRAMFS_DIR=$(mktemp -d /tmp/darkforge-initramfs-XXXXX)
|
||||||
|
OUTPUT="${SCRIPT_DIR}/initramfs.cpio.gz"
|
||||||
|
|
||||||
|
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; NC='\033[0m'
|
||||||
|
info() { echo -e "${CYAN}>>> $1${NC}"; }
|
||||||
|
ok() { echo -e "${GREEN}>>> $1${NC}"; }
|
||||||
|
warn() { echo -e "${YELLOW}!!! $1${NC}"; }
|
||||||
|
die() { echo -e "${RED}!!! $1${NC}"; exit 1; }
|
||||||
|
|
||||||
|
info "Building DarkForge initramfs..."
|
||||||
|
|
||||||
|
# Create directory structure
|
||||||
|
mkdir -p "${INITRAMFS_DIR}"/{bin,sbin,dev,proc,sys,media,rootfs,overlay,tmpfs,newroot,etc,tmp}
|
||||||
|
|
||||||
|
# Find busybox
|
||||||
|
BUSYBOX=""
|
||||||
|
if command -v busybox >/dev/null 2>&1; then
|
||||||
|
BUSYBOX="$(which busybox)"
|
||||||
|
elif [ -f /usr/bin/busybox ]; then
|
||||||
|
BUSYBOX="/usr/bin/busybox"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$BUSYBOX" ]; then
|
||||||
|
die "busybox not found — install with: sudo pacman -S busybox"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Copy busybox and create symlinks for all needed applets
|
||||||
|
cp "$BUSYBOX" "${INITRAMFS_DIR}/bin/busybox"
|
||||||
|
chmod +x "${INITRAMFS_DIR}/bin/busybox"
|
||||||
|
|
||||||
|
# Create symlinks for commands used by the init script
|
||||||
|
for cmd in sh mount umount mkdir echo sleep cat switch_root exec \
|
||||||
|
mount.squashfs losetup mdev modprobe; do
|
||||||
|
ln -sf busybox "${INITRAMFS_DIR}/bin/$cmd"
|
||||||
|
done
|
||||||
|
|
||||||
|
# switch_root is typically in /sbin
|
||||||
|
ln -sf ../bin/busybox "${INITRAMFS_DIR}/sbin/switch_root"
|
||||||
|
|
||||||
|
# Copy the init script
|
||||||
|
cp "${SCRIPT_DIR}/initramfs/init" "${INITRAMFS_DIR}/init"
|
||||||
|
chmod +x "${INITRAMFS_DIR}/init"
|
||||||
|
|
||||||
|
# Create essential device nodes
|
||||||
|
mknod -m 622 "${INITRAMFS_DIR}/dev/console" c 5 1 2>/dev/null || true
|
||||||
|
mknod -m 666 "${INITRAMFS_DIR}/dev/null" c 1 3 2>/dev/null || true
|
||||||
|
mknod -m 666 "${INITRAMFS_DIR}/dev/zero" c 1 5 2>/dev/null || true
|
||||||
|
mknod -m 666 "${INITRAMFS_DIR}/dev/tty" c 5 0 2>/dev/null || true
|
||||||
|
|
||||||
|
# Create the cpio archive
|
||||||
|
info "Creating cpio archive..."
|
||||||
|
cd "${INITRAMFS_DIR}"
|
||||||
|
find . -print0 | cpio --null --create --format=newc 2>/dev/null | gzip -9 > "$OUTPUT"
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
rm -rf "${INITRAMFS_DIR}"
|
||||||
|
|
||||||
|
SIZE=$(du -h "$OUTPUT" | cut -f1)
|
||||||
|
ok "Initramfs created: ${OUTPUT} (${SIZE})"
|
||||||
|
echo ""
|
||||||
|
echo " To use with the ISO:"
|
||||||
|
echo " The build-iso-arch.sh script will automatically include this initramfs."
|
||||||
|
echo ""
|
||||||
@@ -210,6 +210,19 @@ done
|
|||||||
chmod -R a+rX "${ROOTFS}/var/lib/dpack/repos/"
|
chmod -R a+rX "${ROOTFS}/var/lib/dpack/repos/"
|
||||||
ls -la "${ROOTFS}/var/lib/dpack/repos/" || true
|
ls -la "${ROOTFS}/var/lib/dpack/repos/" || true
|
||||||
|
|
||||||
|
# --- Build initramfs for live boot -------------------------------------------
|
||||||
|
INITRAMFS_PATH="${SCRIPT_DIR}/initramfs.cpio.gz"
|
||||||
|
if [ ! -f "$INITRAMFS_PATH" ]; then
|
||||||
|
info "Building initramfs..."
|
||||||
|
bash "${SCRIPT_DIR}/build-initramfs.sh"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "$INITRAMFS_PATH" ]; then
|
||||||
|
ok "Initramfs: ${INITRAMFS_PATH} ($(du -h "$INITRAMFS_PATH" | cut -f1))"
|
||||||
|
else
|
||||||
|
warn "No initramfs — live ISO will not be able to mount squashfs root"
|
||||||
|
fi
|
||||||
|
|
||||||
# --- Install kernel ----------------------------------------------------------
|
# --- Install kernel ----------------------------------------------------------
|
||||||
KERNEL_PATH=""
|
KERNEL_PATH=""
|
||||||
for kp in "${PROJECT_ROOT}/kernel/vmlinuz" "${PROJECT_ROOT}/build/vmlinuz" /boot/vmlinuz-linux; do
|
for kp in "${PROJECT_ROOT}/kernel/vmlinuz" "${PROJECT_ROOT}/build/vmlinuz" /boot/vmlinuz-linux; do
|
||||||
@@ -220,8 +233,15 @@ for kp in "${PROJECT_ROOT}/kernel/vmlinuz" "${PROJECT_ROOT}/build/vmlinuz" /boot
|
|||||||
done
|
done
|
||||||
|
|
||||||
if [ -n "$KERNEL_PATH" ]; then
|
if [ -n "$KERNEL_PATH" ]; then
|
||||||
|
# Copy kernel to ISO
|
||||||
cp "$KERNEL_PATH" "${ISO_DIR}/EFI/BOOT/BOOTX64.EFI"
|
cp "$KERNEL_PATH" "${ISO_DIR}/EFI/BOOT/BOOTX64.EFI"
|
||||||
ok "Kernel: ${KERNEL_PATH}"
|
ok "Kernel: ${KERNEL_PATH}"
|
||||||
|
|
||||||
|
# Also copy initramfs alongside kernel in the ISO
|
||||||
|
if [ -f "$INITRAMFS_PATH" ]; then
|
||||||
|
cp "$INITRAMFS_PATH" "${ISO_DIR}/LiveOS/initramfs.img"
|
||||||
|
ok "Initramfs copied to ISO"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
warn "No kernel found — ISO will not be bootable!"
|
warn "No kernel found — ISO will not be bootable!"
|
||||||
warn "Build the kernel first (Phase 4) or copy vmlinuz to kernel/vmlinuz"
|
warn "Build the kernel first (Phase 4) or copy vmlinuz to kernel/vmlinuz"
|
||||||
@@ -241,12 +261,34 @@ ok "squashfs: $(du -sh "${ISO_DIR}/LiveOS/rootfs.img" | cut -f1)"
|
|||||||
info "Creating EFI boot image..."
|
info "Creating EFI boot image..."
|
||||||
# efiboot.img MUST be inside ISO_DIR so xorriso can find it via -e flag
|
# efiboot.img MUST be inside ISO_DIR so xorriso can find it via -e flag
|
||||||
ESP_IMG="${ISO_DIR}/efiboot.img"
|
ESP_IMG="${ISO_DIR}/efiboot.img"
|
||||||
ESP_SIZE=8192 # 8MB
|
# Size the ESP large enough for kernel + initramfs
|
||||||
|
KERNEL_SIZE=$(stat -c%s "${ISO_DIR}/EFI/BOOT/BOOTX64.EFI" 2>/dev/null || echo "1048576")
|
||||||
|
INITRD_SIZE=0
|
||||||
|
if [ -f "${ISO_DIR}/LiveOS/initramfs.img" ]; then
|
||||||
|
INITRD_SIZE=$(stat -c%s "${ISO_DIR}/LiveOS/initramfs.img")
|
||||||
|
fi
|
||||||
|
# ESP size: kernel + initramfs + 4MB padding, minimum 8MB
|
||||||
|
ESP_SIZE=$(( (KERNEL_SIZE + INITRD_SIZE + 4194304) / 1024 ))
|
||||||
|
[ "$ESP_SIZE" -lt 8192 ] && ESP_SIZE=8192
|
||||||
|
|
||||||
dd if=/dev/zero of="${ESP_IMG}" bs=1K count=${ESP_SIZE} 2>/dev/null
|
dd if=/dev/zero of="${ESP_IMG}" bs=1K count=${ESP_SIZE} 2>/dev/null
|
||||||
mkfs.fat -F 12 "${ESP_IMG}" >/dev/null
|
mkfs.fat -F 12 "${ESP_IMG}" >/dev/null
|
||||||
mmd -i "${ESP_IMG}" ::/EFI ::/EFI/BOOT
|
mmd -i "${ESP_IMG}" ::/EFI ::/EFI/BOOT
|
||||||
mcopy -i "${ESP_IMG}" "${ISO_DIR}/EFI/BOOT/BOOTX64.EFI" ::/EFI/BOOT/BOOTX64.EFI
|
mcopy -i "${ESP_IMG}" "${ISO_DIR}/EFI/BOOT/BOOTX64.EFI" ::/EFI/BOOT/BOOTX64.EFI
|
||||||
|
|
||||||
|
# Include initramfs in the EFI partition if available
|
||||||
|
if [ -f "${ISO_DIR}/LiveOS/initramfs.img" ]; then
|
||||||
|
mcopy -i "${ESP_IMG}" "${ISO_DIR}/LiveOS/initramfs.img" ::/EFI/BOOT/initramfs.img
|
||||||
|
# Create a startup.nsh script for UEFI shell fallback
|
||||||
|
STARTUP_NSH=$(mktemp)
|
||||||
|
echo '\EFI\BOOT\BOOTX64.EFI initrd=\EFI\BOOT\initramfs.img' > "$STARTUP_NSH"
|
||||||
|
mcopy -i "${ESP_IMG}" "$STARTUP_NSH" ::/startup.nsh
|
||||||
|
rm -f "$STARTUP_NSH"
|
||||||
|
ok "EFI boot image includes kernel + initramfs (ESP: $((ESP_SIZE/1024))MB)"
|
||||||
|
else
|
||||||
|
ok "EFI boot image: kernel only (no initramfs)"
|
||||||
|
fi
|
||||||
|
|
||||||
# --- Build ISO ----------------------------------------------------------------
|
# --- Build ISO ----------------------------------------------------------------
|
||||||
info "Building ISO..."
|
info "Building ISO..."
|
||||||
xorriso -as mkisofs \
|
xorriso -as mkisofs \
|
||||||
|
|||||||
101
src/iso/initramfs/init
Executable file
101
src/iso/initramfs/init
Executable file
@@ -0,0 +1,101 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# ============================================================================
|
||||||
|
# DarkForge Linux — Live ISO Initramfs Init Script
|
||||||
|
# ============================================================================
|
||||||
|
# This script runs as PID 1 from the initramfs during live ISO boot.
|
||||||
|
# It finds the ISO media, mounts the squashfs, sets up an overlay, and
|
||||||
|
# switch_roots into the live system.
|
||||||
|
#
|
||||||
|
# Boot flow:
|
||||||
|
# UEFI → EFISTUB kernel → initramfs (this script) → switch_root → /sbin/init
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
# Mount essential virtual filesystems
|
||||||
|
mount -t proc none /proc
|
||||||
|
mount -t sysfs none /sys
|
||||||
|
mount -t devtmpfs none /dev
|
||||||
|
|
||||||
|
# Enable kernel messages on console
|
||||||
|
echo 1 > /proc/sys/kernel/printk
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo " DarkForge Linux — Live Boot"
|
||||||
|
echo " Searching for installation media..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Wait for devices to settle
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
# Try to find the DarkForge ISO media
|
||||||
|
# The ISO has a LiveOS/rootfs.img squashfs file
|
||||||
|
MEDIA_FOUND=0
|
||||||
|
MEDIA_MNT="/media"
|
||||||
|
ROOTFS_MNT="/rootfs"
|
||||||
|
OVERLAY_MNT="/overlay"
|
||||||
|
|
||||||
|
mkdir -p "$MEDIA_MNT" "$ROOTFS_MNT" "$OVERLAY_MNT"
|
||||||
|
|
||||||
|
# Check CD-ROM devices and USB drives
|
||||||
|
for attempt in 1 2 3 4 5; do
|
||||||
|
for dev in /dev/sr0 /dev/sr1 /dev/sda /dev/sda1 /dev/sdb /dev/sdb1 \
|
||||||
|
/dev/nvme0n1p1 /dev/nvme1n1p1 /dev/vda /dev/vda1; do
|
||||||
|
[ -b "$dev" ] || continue
|
||||||
|
|
||||||
|
if mount -o ro "$dev" "$MEDIA_MNT" 2>/dev/null; then
|
||||||
|
if [ -f "$MEDIA_MNT/LiveOS/rootfs.img" ]; then
|
||||||
|
echo " Found DarkForge media on ${dev}"
|
||||||
|
MEDIA_FOUND=1
|
||||||
|
break 2
|
||||||
|
fi
|
||||||
|
umount "$MEDIA_MNT" 2>/dev/null
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo " Attempt ${attempt}/5 — waiting for devices..."
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$MEDIA_FOUND" -eq 0 ]; then
|
||||||
|
echo ""
|
||||||
|
echo " ERROR: Could not find DarkForge installation media!"
|
||||||
|
echo " Make sure the ISO is written to a USB drive or mounted as CD-ROM."
|
||||||
|
echo ""
|
||||||
|
echo " Dropping to emergency shell..."
|
||||||
|
exec /bin/sh
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Mount the squashfs root filesystem
|
||||||
|
echo " Mounting squashfs root filesystem..."
|
||||||
|
if ! mount -t squashfs -o ro "$MEDIA_MNT/LiveOS/rootfs.img" "$ROOTFS_MNT" 2>/dev/null; then
|
||||||
|
echo " ERROR: Failed to mount squashfs!"
|
||||||
|
echo " Dropping to emergency shell..."
|
||||||
|
exec /bin/sh
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set up tmpfs overlay for writable root
|
||||||
|
echo " Setting up writable overlay..."
|
||||||
|
mkdir -p /tmpfs
|
||||||
|
mount -t tmpfs -o size=75% tmpfs /tmpfs
|
||||||
|
mkdir -p /tmpfs/upper /tmpfs/work
|
||||||
|
|
||||||
|
# Mount overlayfs: squashfs (read-only lower) + tmpfs (writable upper)
|
||||||
|
mkdir -p /newroot
|
||||||
|
if mount -t overlay overlay -o "lowerdir=${ROOTFS_MNT},upperdir=/tmpfs/upper,workdir=/tmpfs/work" /newroot 2>/dev/null; then
|
||||||
|
echo " Overlay root mounted (squashfs + tmpfs)"
|
||||||
|
else
|
||||||
|
# Fallback: if overlay not available, bind-mount the squashfs directly
|
||||||
|
echo " WARNING: overlayfs not available, root will be read-only"
|
||||||
|
mount --bind "$ROOTFS_MNT" /newroot
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Move virtual filesystems into the new root
|
||||||
|
mkdir -p /newroot/proc /newroot/sys /newroot/dev /newroot/media
|
||||||
|
mount --move /proc /newroot/proc
|
||||||
|
mount --move /sys /newroot/sys
|
||||||
|
mount --move /dev /newroot/dev
|
||||||
|
mount --move "$MEDIA_MNT" /newroot/media
|
||||||
|
|
||||||
|
echo " Switching to live root filesystem..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Switch to the real root and exec init
|
||||||
|
exec switch_root /newroot /sbin/init
|
||||||
@@ -869,6 +869,32 @@ if [ "$QUICK_MODE" = false ] && [ -n "${OVMF_PATH:-}" ] && [ -f "${ISO}" ]; then
|
|||||||
OVMF_FLAGS="-bios ${OVMF_PATH}"
|
OVMF_FLAGS="-bios ${OVMF_PATH}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Check if we have a real kernel for direct boot (more reliable than UEFI ISO in QEMU)
|
||||||
|
HAS_KERNEL=false
|
||||||
|
[ -f "${PROJECT_ROOT}/kernel/vmlinuz" ] && HAS_KERNEL=true
|
||||||
|
|
||||||
|
INITRD_FLAGS=""
|
||||||
|
[ -f "${PROJECT_ROOT}/src/iso/initramfs.cpio.gz" ] && \
|
||||||
|
INITRD_FLAGS="-initrd ${PROJECT_ROOT}/src/iso/initramfs.cpio.gz"
|
||||||
|
|
||||||
|
if [ "$HAS_KERNEL" = true ]; then
|
||||||
|
echo " Using direct kernel boot (kernel + initramfs)..."
|
||||||
|
timeout 60 qemu-system-x86_64 \
|
||||||
|
${KVM_FLAG} \
|
||||||
|
-m 2G \
|
||||||
|
-smp 2 \
|
||||||
|
-kernel "${PROJECT_ROOT}/kernel/vmlinuz" \
|
||||||
|
${INITRD_FLAGS} \
|
||||||
|
-append "console=ttyS0,115200n8" \
|
||||||
|
-cdrom "$ISO" \
|
||||||
|
-drive file="$QEMU_DISK",format=qcow2,if=virtio \
|
||||||
|
-nographic \
|
||||||
|
-serial mon:stdio \
|
||||||
|
-no-reboot \
|
||||||
|
2>"${LOG_DIR}/qemu-stderr.log" | head -200 > "${LOG_DIR}/qemu-output.log" &
|
||||||
|
QEMU_PID=$!
|
||||||
|
else
|
||||||
|
echo " Using UEFI ISO boot (no compiled kernel found)..."
|
||||||
timeout 60 qemu-system-x86_64 \
|
timeout 60 qemu-system-x86_64 \
|
||||||
${KVM_FLAG} \
|
${KVM_FLAG} \
|
||||||
-m 2G \
|
-m 2G \
|
||||||
@@ -881,6 +907,7 @@ if [ "$QUICK_MODE" = false ] && [ -n "${OVMF_PATH:-}" ] && [ -f "${ISO}" ]; then
|
|||||||
-no-reboot \
|
-no-reboot \
|
||||||
2>"${LOG_DIR}/qemu-stderr.log" | head -200 > "${LOG_DIR}/qemu-output.log" &
|
2>"${LOG_DIR}/qemu-stderr.log" | head -200 > "${LOG_DIR}/qemu-output.log" &
|
||||||
QEMU_PID=$!
|
QEMU_PID=$!
|
||||||
|
fi
|
||||||
|
|
||||||
sleep 60
|
sleep 60
|
||||||
kill $QEMU_PID 2>/dev/null
|
kill $QEMU_PID 2>/dev/null
|
||||||
|
|||||||
Reference in New Issue
Block a user