#!/bin/bash # Kernel building with embedded initramfs # Source common functions LIB_SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "${LIB_SCRIPT_DIR}/common.sh" # Kernel configuration KERNEL_VERSION="${KERNEL_VERSION:-6.12.44}" KERNEL_SOURCE_URL="${KERNEL_SOURCE_URL:-https://cdn.kernel.org/pub/linux/kernel}" KERNEL_CONFIG_SOURCE="${KERNEL_CONFIG_SOURCE:-${PROJECT_ROOT}/configs/kernel-config-generic}" # Download kernel source function kernel_download_source() { local kernel_dir="$1" local version="${2:-$KERNEL_VERSION}" section_header "Downloading Kernel Source" local major_version=$(echo "$version" | cut -d. -f1) local url="${KERNEL_SOURCE_URL}/v${major_version}.x/linux-${version}.tar.xz" local temp_file="/tmp/linux-${version}.tar.xz" local source_dir="${kernel_dir}/linux-${version}" log_info "Kernel version: ${version}" log_info "Download URL: ${url}" log_info "Target directory: ${kernel_dir}" # Clean existing kernel directory if [[ -d "$kernel_dir" ]]; then log_info "Cleaning existing kernel directory" safe_rmdir "$kernel_dir" fi safe_mkdir "$kernel_dir" # Download kernel source if [[ ! -f "$temp_file" ]]; then log_info "Downloading kernel source: ${version}" safe_execute wget --progress=dot:giga -O "$temp_file" "$url" else log_info "Using cached kernel source: ${temp_file}" fi # Verify download local file_size=$(get_file_size "$temp_file") log_info "Kernel source size: ${file_size}" # Extract kernel source log_info "Extracting kernel source" safe_execute tar -xJf "$temp_file" -C "$kernel_dir" # Verify extraction if [[ ! -d "$source_dir" ]]; then log_error "Kernel source extraction failed" return 1 fi # Create symlink for easier access safe_execute ln -sf "linux-${version}" "${kernel_dir}/current" # Cleanup download safe_execute rm "$temp_file" log_info "Kernel source download complete: ${source_dir}" } # Apply kernel configuration with embedded initramfs function kernel_apply_config() { local kernel_dir="$1" local initramfs_path="$2" local config_source="${3:-$KERNEL_CONFIG_SOURCE}" section_header "Applying Kernel Configuration" local source_dir="${kernel_dir}/current" if [[ ! -d "$source_dir" ]]; then log_error "Kernel source directory not found: ${source_dir}" return 1 fi if [[ ! -f "$config_source" ]]; then log_error "Kernel config source not found: ${config_source}" return 1 fi if [[ ! -f "$initramfs_path" ]]; then log_error "Initramfs file not found: ${initramfs_path}" return 1 fi safe_execute cd "$source_dir" # Copy base configuration log_info "Copying kernel configuration from: ${config_source}" safe_copy "$config_source" ".config" # Update configuration for embedded initramfs log_info "Updating configuration for embedded initramfs" log_info "Initramfs path: ${initramfs_path}" # Resolve absolute path for initramfs local abs_initramfs_path=$(resolve_path "$initramfs_path") # Modify config for embedded initramfs kernel_modify_config_for_initramfs "$abs_initramfs_path" # Run olddefconfig to apply defaults for any new options log_info "Running olddefconfig to finalize configuration" safe_execute make olddefconfig log_info "Kernel configuration applied successfully" } # Modify kernel config for embedded initramfs function kernel_modify_config_for_initramfs() { local initramfs_path="$1" log_info "Modifying kernel config for embedded initramfs" # Use sed to update configuration safe_execute sed -i "s|^CONFIG_INITRAMFS_SOURCE=.*|CONFIG_INITRAMFS_SOURCE=\"${initramfs_path}\"|" .config # Ensure XZ compression is enabled for initramfs safe_execute sed -i 's/^# CONFIG_RD_XZ is not set/CONFIG_RD_XZ=y/' .config safe_execute sed -i 's/^CONFIG_INITRAMFS_COMPRESSION_NONE=y/# CONFIG_INITRAMFS_COMPRESSION_NONE is not set/' .config safe_execute sed -i 's/^# CONFIG_INITRAMFS_COMPRESSION_XZ is not set/CONFIG_INITRAMFS_COMPRESSION_XZ=y/' .config # Verify critical settings if ! grep -q "CONFIG_INITRAMFS_SOURCE=\"${initramfs_path}\"" .config; then log_error "Failed to set INITRAMFS_SOURCE in kernel config" return 1 fi if ! grep -q "CONFIG_RD_XZ=y" .config; then log_error "Failed to enable XZ decompression in kernel config" return 1 fi log_info "Kernel config updated for embedded initramfs" } # Build kernel with embedded initramfs function kernel_build_with_initramfs() { local kernel_config="$1" local initramfs_path="$2" local output_file="$3" local kernel_dir="${4:-${PROJECT_ROOT}/kernel}" section_header "Building Kernel with Embedded Initramfs" # Download kernel source if needed if [[ ! -d "${kernel_dir}/current" ]]; then kernel_download_source "$kernel_dir" fi # Apply configuration kernel_apply_config "$kernel_dir" "$initramfs_path" "$kernel_config" local source_dir="${kernel_dir}/current" safe_execute cd "$source_dir" # Clean previous build log_info "Cleaning previous kernel build" safe_execute make clean # Determine number of cores for parallel build local cores=$(nproc) local jobs=$((cores > 1 ? cores - 1 : 1)) # Leave one core free log_info "Building with ${jobs} parallel jobs" # Build kernel log_info "Building kernel (this may take a while)..." safe_execute make -j${jobs} bzImage # Verify kernel was built local kernel_image="arch/x86/boot/bzImage" if [[ ! -f "$kernel_image" ]]; then log_error "Kernel build failed - bzImage not found" return 1 fi # Copy to output location local output_dir=$(dirname "$output_file") safe_mkdir "$output_dir" safe_copy "$kernel_image" "$output_file" # Verify final kernel local kernel_size=$(get_file_size "$output_file") log_info "Kernel build complete:" log_info " Output file: ${output_file}" log_info " Kernel size: ${kernel_size}" # Verify initramfs is embedded if strings "$output_file" | grep -q "initramfs"; then log_info "✓ Initramfs appears to be embedded in kernel" else log_warn "Initramfs embedding verification inconclusive" fi } # Build modules for initramfs function kernel_build_modules() { local kernel_dir="$1" local modules_install_dir="$2" local version="${3:-$KERNEL_VERSION}" section_header "Building Kernel Modules" local source_dir="${kernel_dir}/current" if [[ ! -d "$source_dir" ]]; then log_error "Kernel source directory not found: ${source_dir}" return 1 fi safe_execute cd "$source_dir" # Build modules local cores=$(nproc) local jobs=$((cores > 1 ? cores - 1 : 1)) log_info "Building kernel modules with ${jobs} parallel jobs" safe_execute make -j${jobs} modules # Install modules to staging area log_info "Installing modules to: ${modules_install_dir}" safe_mkdir "$modules_install_dir" safe_execute make modules_install INSTALL_MOD_PATH="$modules_install_dir" # Run depmod to create module dependencies local modules_dir="${modules_install_dir}/lib/modules/${version}" if [[ -d "$modules_dir" ]]; then log_info "Running depmod for module dependencies" safe_execute depmod -a -b "$modules_install_dir" "$version" fi log_info "Kernel modules build complete" } # Clean kernel build artifacts function kernel_cleanup() { local kernel_dir="$1" local keep_source="${2:-false}" section_header "Cleaning Kernel Build Artifacts" if [[ "$keep_source" == "true" ]]; then log_info "Keeping source, cleaning build artifacts only" local source_dir="${kernel_dir}/current" if [[ -d "$source_dir" ]]; then safe_execute cd "$source_dir" safe_execute make clean fi else log_info "Removing entire kernel directory" safe_rmdir "$kernel_dir" fi log_info "Kernel cleanup complete" } # Export functions export -f kernel_download_source kernel_apply_config kernel_modify_config_for_initramfs export -f kernel_build_with_initramfs kernel_build_modules kernel_cleanup