#!/bin/bash set -e KERNEL_DIR="/build/kernel" OUTPUT_DIR="/build/output" CONFIG_DIR="/build/configs" # Parse command line arguments KERNEL_ONLY=false EMBED_ONLY=false while [ $# -gt 0 ]; do case $1 in --kernel-only) KERNEL_ONLY=true shift ;; --embed-only) EMBED_ONLY=true shift ;; *) echo "Unknown option: $1" exit 1 ;; esac done echo "[+] Building custom Zero-OS kernel..." echo " Mode: $([ "$KERNEL_ONLY" = "true" ] && echo "kernel-only" || [ "$EMBED_ONLY" = "true" ] && echo "embed-only" || echo "full-build")" # DIAGNOSTIC: Check prerequisites echo "[DEBUG] Checking kernel build prerequisites..." echo "[DEBUG] Initramfs file exists: $([ -f "$OUTPUT_DIR/initramfs.cpio.xz" ] && echo 'YES' || echo 'NO')" echo "[DEBUG] Kernel config exists: $([ -f "$CONFIG_DIR/kernel-config-generic" ] && echo 'YES' || echo 'NO')" # Only check for initramfs if we're doing embedding if [ "$KERNEL_ONLY" != "true" ] && [ ! -f "$OUTPUT_DIR/initramfs.cpio.xz" ]; then echo "[DEBUG] ERROR: Initramfs not found - kernel build will fail" exit 1 fi if [ ! -f "$CONFIG_DIR/kernel-config-generic" ]; then echo "[DEBUG] ERROR: Kernel config not found - kernel build will fail" exit 1 fi echo "[DEBUG] Initramfs size: $(stat -c%s "$OUTPUT_DIR/initramfs.cpio.xz") bytes" # Read kernel version from config if [ -f "$CONFIG_DIR/kernel-version" ]; then KERNEL_VERSION=$(cat "$CONFIG_DIR/kernel-version" | tr -d '\n') echo " Using kernel version from config: $KERNEL_VERSION" else echo " Error: kernel-version config file not found" >&2 exit 1 fi KERNEL_MAJOR=$(echo $KERNEL_VERSION | cut -d. -f1) KERNEL_URL="https://cdn.kernel.org/pub/linux/kernel/v${KERNEL_MAJOR}.x/linux-${KERNEL_VERSION}.tar.xz" echo " Kernel version: $KERNEL_VERSION" echo " Download URL: $KERNEL_URL" # Create kernel build directory echo " Setting up kernel build environment..." mkdir -p "$KERNEL_DIR" cd "$KERNEL_DIR" # Install kernel build dependencies echo " Installing kernel build dependencies..." apk add --no-cache build-base bc bison flex openssl-dev elfutils-dev \ perl linux-headers cpio xz wget # Download kernel source if not already present if [ ! -f "linux-${KERNEL_VERSION}.tar.xz" ]; then echo " Downloading Linux kernel ${KERNEL_VERSION}..." wget -q --show-progress "$KERNEL_URL" fi # Extract kernel source if not already extracted if [ ! -d "linux-${KERNEL_VERSION}" ]; then echo " Extracting kernel source..." tar -xf "linux-${KERNEL_VERSION}.tar.xz" fi cd "linux-${KERNEL_VERSION}" # Copy kernel config echo " Setting up kernel configuration..." cp "$CONFIG_DIR/kernel-config-generic" .config # Handle different build modes if [ "$KERNEL_ONLY" = "true" ]; then echo " Building kernel only (no initramfs embedding)..." # Disable initramfs in config for kernel-only build sed -i 's/CONFIG_INITRAMFS_SOURCE="..\/..\/root"/CONFIG_INITRAMFS_SOURCE=""/' .config # Update config and build kernel make olddefconfig make -j$(nproc) bzImage make -j$(nproc) modules echo " Kernel built successfully (cached for later embedding)" exit 0 elif [ "$EMBED_ONLY" = "true" ]; then echo " Embedding initramfs into existing kernel..." # The kernel config expects initramfs at "../../root" relative to kernel build directory echo " Extracting initramfs for embedding..." mkdir -p ../../root cd ../../root rm -rf ./* xz -dc "$OUTPUT_DIR/initramfs.cpio.xz" | cpio -id cd "$KERNEL_DIR/linux-${KERNEL_VERSION}" # Restore initramfs path in config sed -i 's/CONFIG_INITRAMFS_SOURCE=""/CONFIG_INITRAMFS_SOURCE="..\/..\/root"/' .config # Rebuild with embedded initramfs make olddefconfig make -j$(nproc) bzImage # Copy final kernel echo " Copying embedded kernel..." cp arch/x86/boot/bzImage "$OUTPUT_DIR/vmlinuz.efi" kernel_size=$(stat -c%s "$OUTPUT_DIR/vmlinuz.efi") echo " Embedded kernel created: $(echo "$kernel_size / 1024 / 1024" | bc)MB" exit 0 else # Full build mode (original behavior) echo " Full build: kernel + embedded initramfs..." # The kernel config expects initramfs at "../../root" relative to kernel build directory echo " Setting up initramfs for kernel embedding..." mkdir -p ../../root cd ../../root # Extract our initramfs to the location expected by kernel config echo " Extracting initramfs to expected location..." # Remove any existing contents first rm -rf ./* # Extract the initramfs cpio archive xz -dc "$OUTPUT_DIR/initramfs.cpio.xz" | cpio -id echo " Initramfs extracted to: $(pwd)" echo " Initramfs contents:" find . -maxdepth 2 -type f -o -type d | head -20 # Return to kernel source directory cd "$KERNEL_DIR/linux-${KERNEL_VERSION}" # Verify kernel config is properly set up echo " Verifying kernel configuration..." if grep -q 'CONFIG_INITRAMFS_SOURCE="../../root"' .config; then echo " ✓ Initramfs source path configured correctly" else echo " ✗ Warning: Initramfs source path not found in config" fi if grep -q 'CONFIG_INITRAMFS_COMPRESSION_XZ=y' .config; then echo " ✓ XZ compression enabled" else echo " ✗ Warning: XZ compression not enabled" fi # Update config to handle any new options echo " Updating kernel configuration..." make olddefconfig # Build the kernel echo " Building kernel with embedded initramfs..." echo " This may take several minutes..." make -j$(nproc) bzImage fi # Verify kernel was built if [ ! -f "arch/x86/boot/bzImage" ]; then echo " Error: Kernel build failed - bzImage not found" >&2 exit 1 fi # Copy built kernel to output location echo " Installing built kernel..." cp arch/x86/boot/bzImage "$OUTPUT_DIR/vmlinuz.efi" # Get kernel size info kernel_size=$(stat -c%s "$OUTPUT_DIR/vmlinuz.efi") initramfs_size=$(stat -c%s "$OUTPUT_DIR/initramfs.cpio.xz") echo "[DEBUG] Built kernel size: $kernel_size bytes" echo "[DEBUG] Original initramfs size: $initramfs_size bytes" # Create version info file echo " Creating version information..." cat > "$OUTPUT_DIR/version.txt" << EOF Zero-OS Custom Kernel (Linux $KERNEL_VERSION) Built: $(date) Source: $KERNEL_URL Config: kernel-config-generic Initramfs: Embedded during compilation Final size: $kernel_size bytes Original initramfs: $initramfs_size bytes Boot Options: Method: Custom kernel with embedded initramfs Usage: Boot vmlinuz.efi directly GRUB: linux vmlinuz.efi No separate initramfs needed Build Environment: Alpine Linux $(cat /etc/alpine-release 2>/dev/null || echo 'unknown') GCC: $(gcc --version | head -1) Make: $(make --version | head -1) EOF # Build kernel modules echo " Building kernel modules..." make -j$(nproc) modules # Install modules to output directory echo " Installing kernel modules..." mkdir -p "$OUTPUT_DIR/modules" make INSTALL_MOD_PATH="$OUTPUT_DIR/modules" modules_install # Find the installed module directory MODULE_DIR=$(find "$OUTPUT_DIR/modules/lib/modules" -maxdepth 1 -type d -name "*" | head -1) if [ -n "$MODULE_DIR" ]; then echo " Modules installed to: $MODULE_DIR" echo "Modules: $MODULE_DIR" >> "$OUTPUT_DIR/version.txt" else echo " Warning: No modules installed" fi # Clean up intermediate files echo " Cleaning up build artifacts..." cd "$KERNEL_DIR" rm -rf "linux-${KERNEL_VERSION}" rm -f "linux-${KERNEL_VERSION}.tar.xz" echo "[+] Custom kernel build completed successfully" echo " Kernel: $OUTPUT_DIR/vmlinuz.efi ($(du -h $OUTPUT_DIR/vmlinuz.efi | cut -f1))" echo " Version: Linux $KERNEL_VERSION Zero-OS" if [ -d "$OUTPUT_DIR/modules" ]; then echo " Modules: $OUTPUT_DIR/modules/ ($(du -sh $OUTPUT_DIR/modules | cut -f1))" fi echo " Method: Custom compilation with embedded initramfs" # Final verification if [ ! -f "$OUTPUT_DIR/vmlinuz.efi" ] || [ "$(stat -c%s "$OUTPUT_DIR/vmlinuz.efi")" -eq 0 ]; then echo " Error: Final kernel verification failed" >&2 exit 1 fi echo " ✓ Kernel ready for deployment"