forked from tfgrid/zosbuilder
Fix module dependency resolution issues
- Fix dependency resolution to use built modules from /lib/modules/6.12.44-Zero-OS instead of fresh container - Fix stage1/stage2 configuration mismatch (only using stage1 modules as intended) - Fix firmware parsing to ignore comments in modules.conf - Fix variable binding issues for incremental builds (FULL_KERNEL_VERSION, KERNEL_OUTPUT) - Module resolution now properly expands 31 → 48 modules with dependencies - Firmware requirements reduced from 157 bogus → 3 correct packages - All 48/48 resolved modules validated as available .ko files
This commit is contained in:
@@ -2,12 +2,14 @@
|
|||||||
# Format: STAGE:MODULE_NAME:FIRMWARE_PACKAGE (optional)
|
# Format: STAGE:MODULE_NAME:FIRMWARE_PACKAGE (optional)
|
||||||
# Focus on most common NIC modules to ensure networking works on most hardware
|
# Focus on most common NIC modules to ensure networking works on most hardware
|
||||||
|
|
||||||
# Stage 1: ALL networking and essential boot modules
|
# Stage 1: Core subsystems + networking and essential boot modules
|
||||||
# All NICs must be loaded BEFORE network can come up
|
# All core subsystems and NICs must be loaded BEFORE network can come up
|
||||||
|
stage1:virtio:none # Core virtio subsystem (REQUIRED)
|
||||||
|
stage1:virtio_ring:none # Virtio ring buffer (REQUIRED)
|
||||||
|
stage1:virtio_pci:none # Virtio PCI bus
|
||||||
stage1:virtio_net:none # Virtio network (VMs, cloud)
|
stage1:virtio_net:none # Virtio network (VMs, cloud)
|
||||||
stage1:virtio_scsi:none # Virtio SCSI (VMs, cloud)
|
stage1:virtio_scsi:none # Virtio SCSI (VMs, cloud)
|
||||||
stage1:virtio_blk:none # Virtio block (VMs, cloud)
|
stage1:virtio_blk:none # Virtio block (VMs, cloud)
|
||||||
stage1:virtio_pci:none # Virtio PCI bus
|
|
||||||
stage1:e1000:linux-firmware-intel # Intel E1000 (very common)
|
stage1:e1000:linux-firmware-intel # Intel E1000 (very common)
|
||||||
stage1:e1000e:linux-firmware-intel # Intel E1000E (very common)
|
stage1:e1000e:linux-firmware-intel # Intel E1000E (very common)
|
||||||
stage1:r8169:linux-firmware-realtek # Realtek (most common desktop/server)
|
stage1:r8169:linux-firmware-realtek # Realtek (most common desktop/server)
|
||||||
@@ -25,9 +27,11 @@ stage1:atl1:none # Atheros L1
|
|||||||
stage1:atl1e:none # Atheros L1E
|
stage1:atl1e:none # Atheros L1E
|
||||||
stage1:atl1c:none # Atheros L1C
|
stage1:atl1c:none # Atheros L1C
|
||||||
stage1:alx:none # Atheros Alx
|
stage1:alx:none # Atheros Alx
|
||||||
|
stage1:libata:none # Core ATA subsystem (REQUIRED)
|
||||||
stage1:scsi_mod:none # SCSI subsystem
|
stage1:scsi_mod:none # SCSI subsystem
|
||||||
stage1:sd_mod:none # SCSI disk support
|
stage1:sd_mod:none # SCSI disk support
|
||||||
stage1:ahci:none # SATA AHCI
|
stage1:ahci:none # SATA AHCI
|
||||||
|
stage1:nvme_core:none # Core NVMe subsystem (REQUIRED)
|
||||||
stage1:nvme:none # NVMe storage
|
stage1:nvme:none # NVMe storage
|
||||||
stage1:tun:none # TUN/TAP for networking
|
stage1:tun:none # TUN/TAP for networking
|
||||||
stage1:overlay:none # OverlayFS for containers
|
stage1:overlay:none # OverlayFS for containers
|
||||||
|
|||||||
210
scripts/build.sh
210
scripts/build.sh
@@ -9,6 +9,7 @@ PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
|||||||
|
|
||||||
# Source all libraries
|
# Source all libraries
|
||||||
source "${SCRIPT_DIR}/lib/common.sh"
|
source "${SCRIPT_DIR}/lib/common.sh"
|
||||||
|
source "${SCRIPT_DIR}/lib/stages.sh"
|
||||||
source "${SCRIPT_DIR}/lib/docker.sh"
|
source "${SCRIPT_DIR}/lib/docker.sh"
|
||||||
source "${SCRIPT_DIR}/lib/alpine.sh"
|
source "${SCRIPT_DIR}/lib/alpine.sh"
|
||||||
source "${SCRIPT_DIR}/lib/components.sh"
|
source "${SCRIPT_DIR}/lib/components.sh"
|
||||||
@@ -47,7 +48,7 @@ KEEP_ARTIFACTS="${KEEP_ARTIFACTS:-false}"
|
|||||||
# Display usage information
|
# Display usage information
|
||||||
function show_usage() {
|
function show_usage() {
|
||||||
cat << EOF
|
cat << EOF
|
||||||
Zero OS Alpine Initramfs Builder
|
Zero OS Alpine Initramfs Builder (Incremental)
|
||||||
|
|
||||||
Usage: $0 [OPTIONS]
|
Usage: $0 [OPTIONS]
|
||||||
|
|
||||||
@@ -55,20 +56,31 @@ Options:
|
|||||||
--clean Clean build (remove all artifacts first)
|
--clean Clean build (remove all artifacts first)
|
||||||
--skip-tests Skip boot tests
|
--skip-tests Skip boot tests
|
||||||
--keep-artifacts Keep build artifacts after completion
|
--keep-artifacts Keep build artifacts after completion
|
||||||
|
--force-rebuild Force rebuild all stages (ignore completion markers)
|
||||||
|
--rebuild-from=STAGE Force rebuild from specific stage onward
|
||||||
|
--show-stages Show stage completion status
|
||||||
--help Show this help message
|
--help Show this help message
|
||||||
|
|
||||||
Environment Variables:
|
Environment Variables:
|
||||||
ALPINE_VERSION Alpine Linux version (default: 3.22)
|
ALPINE_VERSION Alpine Linux version (default: 3.22)
|
||||||
KERNEL_VERSION Linux kernel version (default: 6.8.8)
|
KERNEL_VERSION Linux kernel version (default: 6.12.44)
|
||||||
RUST_TARGET Rust compilation target (default: x86_64-unknown-linux-musl)
|
RUST_TARGET Rust compilation target (default: x86_64-unknown-linux-musl)
|
||||||
OPTIMIZATION_LEVEL Optimization level: max|size|speed (default: max)
|
OPTIMIZATION_LEVEL Optimization level: max|size|speed (default: max)
|
||||||
DEBUG Enable debug output (default: 0)
|
DEBUG Enable debug output (default: 0)
|
||||||
|
FORCE_REBUILD Force rebuild all stages (default: false)
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
$0 # Basic build
|
$0 # Incremental build (skip completed stages)
|
||||||
$0 --clean # Clean build
|
$0 --clean # Clean build (remove artifacts + stage markers)
|
||||||
$0 --container # Force container build
|
$0 --force-rebuild # Force rebuild all stages
|
||||||
DEBUG=1 $0 # Build with debug output
|
$0 --rebuild-from=zinit_setup # Rebuild from zinit setup onward
|
||||||
|
$0 --show-stages # Show which stages are completed
|
||||||
|
DEBUG=1 $0 # Build with debug output
|
||||||
|
|
||||||
|
Development Workflow:
|
||||||
|
./scripts/dev-container.sh start # Start persistent container
|
||||||
|
./scripts/dev-container.sh shell # Enter container for debugging
|
||||||
|
DEBUG=1 ./scripts/build.sh # Run incremental build inside container
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,6 +100,22 @@ function parse_arguments() {
|
|||||||
KEEP_ARTIFACTS="true"
|
KEEP_ARTIFACTS="true"
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
|
--force-rebuild)
|
||||||
|
export FORCE_REBUILD="true"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--rebuild-from=*)
|
||||||
|
export REBUILD_FROM_STAGE="${1#*=}"
|
||||||
|
export FORCE_REBUILD="true"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--show-stages)
|
||||||
|
# Initialize stage tracking and show status
|
||||||
|
source "${SCRIPT_DIR}/lib/stages.sh"
|
||||||
|
stages_init
|
||||||
|
stages_status
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
--help|-h)
|
--help|-h)
|
||||||
show_usage
|
show_usage
|
||||||
exit 0
|
exit 0
|
||||||
@@ -174,82 +202,140 @@ function verify_configuration_files() {
|
|||||||
log_info "All configuration files verified"
|
log_info "All configuration files verified"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Main build process
|
# Incremental build process with stage tracking
|
||||||
function main_build_process() {
|
function main_build_process() {
|
||||||
section_header "Starting Zero OS Alpine Initramfs Build"
|
section_header "Starting Zero OS Alpine Initramfs Build (Incremental)"
|
||||||
|
|
||||||
local start_time=$(date +%s)
|
local start_time=$(date +%s)
|
||||||
|
|
||||||
# Phase 1: Extract Alpine miniroot
|
# Initialize stage tracking
|
||||||
alpine_extract_miniroot "$INSTALL_DIR" "$ALPINE_VERSION"
|
stages_init
|
||||||
|
|
||||||
# Phase 2: Configure Alpine system
|
# Define stage wrapper functions
|
||||||
alpine_configure_repos "$INSTALL_DIR" "$ALPINE_VERSION"
|
function stage_alpine_extract() {
|
||||||
alpine_configure_system "$INSTALL_DIR"
|
alpine_extract_miniroot "$INSTALL_DIR" "$ALPINE_VERSION"
|
||||||
|
}
|
||||||
|
|
||||||
# Phase 3: Install Alpine packages (NO OpenRC)
|
function stage_alpine_configure() {
|
||||||
alpine_install_packages "$INSTALL_DIR" "$PACKAGES_LIST"
|
alpine_configure_repos "$INSTALL_DIR" "$ALPINE_VERSION"
|
||||||
|
alpine_configure_system "$INSTALL_DIR"
|
||||||
|
}
|
||||||
|
|
||||||
# Phase 3.5: Install firmware packages for hardware support
|
function stage_alpine_packages() {
|
||||||
alpine_install_firmware "$INSTALL_DIR" "$FIRMWARE_CONF"
|
alpine_install_packages "$INSTALL_DIR" "$PACKAGES_LIST"
|
||||||
|
}
|
||||||
|
|
||||||
# Phase 4: Build and install ThreeFold components
|
function stage_alpine_firmware() {
|
||||||
components_parse_sources_conf "$SOURCES_CONF" "$COMPONENTS_DIR" "$INSTALL_DIR"
|
alpine_install_firmware "$INSTALL_DIR" "$FIRMWARE_CONF"
|
||||||
|
}
|
||||||
|
|
||||||
# Phase 5: Verify component installation
|
function stage_components_build() {
|
||||||
components_verify_installation
|
components_parse_sources_conf "$SOURCES_CONF" "$COMPONENTS_DIR" "$INSTALL_DIR"
|
||||||
|
}
|
||||||
|
|
||||||
# Phase 6: Create placeholder initramfs for kernel build (chicken-egg problem)
|
function stage_components_verify() {
|
||||||
local initramfs_archive="${DIST_DIR}/initramfs.cpio.xz"
|
components_verify_installation
|
||||||
safe_mkdir "$DIST_DIR"
|
}
|
||||||
log_info "Creating placeholder initramfs for initial kernel build"
|
|
||||||
safe_execute touch "$initramfs_archive"
|
|
||||||
|
|
||||||
# Phase 7: Prepare kernel source and build modules (with placeholder initramfs)
|
function stage_kernel_modules() {
|
||||||
log_info "Downloading and configuring kernel source for module build"
|
# Create placeholder for kernel build
|
||||||
kernel_download_source "$KERNEL_DIR" "$KERNEL_VERSION"
|
local initramfs_archive="${DIST_DIR}/initramfs.cpio.xz"
|
||||||
kernel_apply_config "$KERNEL_DIR" "$initramfs_archive" "$KERNEL_CONFIG"
|
safe_mkdir "$DIST_DIR"
|
||||||
|
safe_execute touch "$initramfs_archive"
|
||||||
|
|
||||||
log_info "Building kernel modules for initramfs inclusion"
|
# Download and build kernel modules
|
||||||
kernel_build_modules "$KERNEL_DIR" "$INSTALL_DIR" "$KERNEL_VERSION"
|
kernel_download_source "$KERNEL_DIR" "$KERNEL_VERSION"
|
||||||
|
kernel_apply_config "$KERNEL_DIR" "$initramfs_archive" "$KERNEL_CONFIG"
|
||||||
|
kernel_build_modules "$KERNEL_DIR" "$INSTALL_DIR" "$KERNEL_VERSION"
|
||||||
|
|
||||||
# Phase 8: Setup zinit as init system
|
# Set full kernel version for later stages
|
||||||
initramfs_setup_zinit "$INSTALL_DIR" "$ZINIT_CONFIG_DIR"
|
FULL_KERNEL_VERSION=$(kernel_get_full_version "$KERNEL_VERSION" "$KERNEL_CONFIG")
|
||||||
|
export FULL_KERNEL_VERSION
|
||||||
|
log_info "Full kernel version: ${FULL_KERNEL_VERSION}"
|
||||||
|
}
|
||||||
|
|
||||||
# Phase 9: Install critical /init script for initramfs boot
|
function stage_zinit_setup() {
|
||||||
initramfs_install_init_script "$INSTALL_DIR" "${CONFIG_DIR}/init"
|
initramfs_setup_zinit "$INSTALL_DIR" "$ZINIT_CONFIG_DIR"
|
||||||
|
}
|
||||||
|
|
||||||
# Phase 10: Setup 2-stage module loading
|
function stage_init_script() {
|
||||||
initramfs_setup_modules "$INSTALL_DIR" "$MODULES_CONF" "$KERNEL_VERSION"
|
initramfs_install_init_script "$INSTALL_DIR" "${CONFIG_DIR}/init"
|
||||||
|
}
|
||||||
|
|
||||||
# Phase 11: Aggressive cleanup for size optimization
|
function stage_modules_setup() {
|
||||||
alpine_aggressive_cleanup "$INSTALL_DIR"
|
# Calculate full kernel version (needed for incremental builds when kernel_modules stage is skipped)
|
||||||
|
local full_kernel_version=$(kernel_get_full_version "$KERNEL_VERSION" "$KERNEL_CONFIG")
|
||||||
|
export FULL_KERNEL_VERSION="$full_kernel_version"
|
||||||
|
log_info "Using full kernel version: ${full_kernel_version}"
|
||||||
|
|
||||||
# Phase 12: Strip and UPX all binaries (temporarily skipped to reach kernel phase)
|
initramfs_setup_modules "$INSTALL_DIR" "$MODULES_CONF" "$full_kernel_version"
|
||||||
log_info "Skipping strip/UPX optimization to proceed to kernel compilation"
|
}
|
||||||
# initramfs_strip_and_upx "$INSTALL_DIR"
|
|
||||||
|
|
||||||
# Phase 13: Validate initramfs
|
function stage_modules_copy() {
|
||||||
initramfs_validate "$INSTALL_DIR"
|
# Ensure FULL_KERNEL_VERSION is set (for incremental builds)
|
||||||
|
if [[ -z "${FULL_KERNEL_VERSION:-}" ]]; then
|
||||||
|
FULL_KERNEL_VERSION=$(kernel_get_full_version "$KERNEL_VERSION" "$KERNEL_CONFIG")
|
||||||
|
export FULL_KERNEL_VERSION
|
||||||
|
fi
|
||||||
|
|
||||||
# Phase 14: Create real initramfs archive (now with modules)
|
log_info "About to copy modules - FULL_KERNEL_VERSION: ${FULL_KERNEL_VERSION}"
|
||||||
log_info "Creating real initramfs archive with all components and modules"
|
log_info "CONTAINER_MODULES_PATH: ${CONTAINER_MODULES_PATH:-not-set}"
|
||||||
initramfs_create_cpio "$INSTALL_DIR" "$initramfs_archive"
|
initramfs_copy_resolved_modules "$INSTALL_DIR" "$FULL_KERNEL_VERSION"
|
||||||
|
}
|
||||||
|
|
||||||
# Phase 15: Test archive integrity
|
function stage_cleanup() {
|
||||||
initramfs_test_archive "$initramfs_archive"
|
alpine_aggressive_cleanup "$INSTALL_DIR"
|
||||||
|
}
|
||||||
|
|
||||||
# Phase 16: Second kernel build with real embedded initramfs
|
function stage_validation() {
|
||||||
local kernel_output="${DIST_DIR}/vmlinuz.efi"
|
initramfs_validate "$INSTALL_DIR"
|
||||||
log_info "Final kernel build: embedding complete initramfs"
|
}
|
||||||
kernel_build_with_initramfs "$KERNEL_CONFIG" "$initramfs_archive" "$kernel_output"
|
|
||||||
|
|
||||||
# Phase 17: Run boot tests (unless skipped)
|
function stage_initramfs_create() {
|
||||||
if [[ "$SKIP_TESTS" != "true" ]]; then
|
local initramfs_archive="${DIST_DIR}/initramfs.cpio.xz"
|
||||||
testing_run_all "$kernel_output"
|
initramfs_create_cpio "$INSTALL_DIR" "$initramfs_archive"
|
||||||
else
|
export INITRAMFS_ARCHIVE="$initramfs_archive"
|
||||||
log_info "Skipping boot tests as requested"
|
}
|
||||||
fi
|
|
||||||
|
function stage_initramfs_test() {
|
||||||
|
initramfs_test_archive "$INITRAMFS_ARCHIVE"
|
||||||
|
}
|
||||||
|
|
||||||
|
function stage_kernel_build() {
|
||||||
|
local kernel_output="${DIST_DIR}/vmlinuz.efi"
|
||||||
|
kernel_build_with_initramfs "$KERNEL_CONFIG" "$INITRAMFS_ARCHIVE" "$kernel_output"
|
||||||
|
export KERNEL_OUTPUT="$kernel_output"
|
||||||
|
}
|
||||||
|
|
||||||
|
function stage_boot_tests() {
|
||||||
|
if [[ "$SKIP_TESTS" != "true" ]]; then
|
||||||
|
# Ensure KERNEL_OUTPUT is set (for incremental builds)
|
||||||
|
if [[ -z "${KERNEL_OUTPUT:-}" ]]; then
|
||||||
|
KERNEL_OUTPUT="${DIST_DIR}/vmlinuz.efi"
|
||||||
|
export KERNEL_OUTPUT
|
||||||
|
fi
|
||||||
|
testing_run_all "$KERNEL_OUTPUT"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Run all stages with incremental tracking
|
||||||
|
stage_run "alpine_extract" stage_alpine_extract
|
||||||
|
stage_run "alpine_configure" stage_alpine_configure
|
||||||
|
stage_run "alpine_packages" stage_alpine_packages
|
||||||
|
stage_run "alpine_firmware" stage_alpine_firmware
|
||||||
|
stage_run "components_build" stage_components_build
|
||||||
|
stage_run "components_verify" stage_components_verify
|
||||||
|
stage_run "kernel_modules" stage_kernel_modules
|
||||||
|
stage_run "zinit_setup" stage_zinit_setup
|
||||||
|
stage_run "init_script" stage_init_script
|
||||||
|
stage_run "modules_setup" stage_modules_setup
|
||||||
|
stage_run "modules_copy" stage_modules_copy
|
||||||
|
stage_run "cleanup" stage_cleanup
|
||||||
|
stage_run "validation" stage_validation
|
||||||
|
stage_run "initramfs_create" stage_initramfs_create
|
||||||
|
stage_run "initramfs_test" stage_initramfs_test
|
||||||
|
stage_run "kernel_build" stage_kernel_build
|
||||||
|
stage_run "boot_tests" stage_boot_tests
|
||||||
|
|
||||||
# Calculate build time
|
# Calculate build time
|
||||||
local end_time=$(date +%s)
|
local end_time=$(date +%s)
|
||||||
@@ -260,8 +346,8 @@ function main_build_process() {
|
|||||||
section_header "Build Complete"
|
section_header "Build Complete"
|
||||||
log_info "Build time: ${build_minutes}m ${build_seconds}s"
|
log_info "Build time: ${build_minutes}m ${build_seconds}s"
|
||||||
log_info "Output files:"
|
log_info "Output files:"
|
||||||
log_info " Kernel: ${kernel_output} ($(get_file_size "$kernel_output"))"
|
log_info " Kernel: ${KERNEL_OUTPUT} ($(get_file_size "$KERNEL_OUTPUT"))"
|
||||||
log_info " Initramfs: ${initramfs_archive} ($(get_file_size "$initramfs_archive"))"
|
log_info " Initramfs: ${INITRAMFS_ARCHIVE} ($(get_file_size "$INITRAMFS_ARCHIVE"))"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Cleanup build artifacts
|
# Cleanup build artifacts
|
||||||
|
|||||||
@@ -118,9 +118,11 @@ function initramfs_setup_modules() {
|
|||||||
local stage1_modules=()
|
local stage1_modules=()
|
||||||
local stage1_firmware=()
|
local stage1_firmware=()
|
||||||
|
|
||||||
while IFS=: read -r stage module firmware; do
|
while IFS=: read -r stage module firmware_line; do
|
||||||
if [[ "$stage" == "stage1" && -n "$module" ]]; then
|
if [[ "$stage" == "stage1" && -n "$module" ]]; then
|
||||||
stage1_modules+=("$module")
|
stage1_modules+=("$module")
|
||||||
|
# Extract firmware package name (before any comment)
|
||||||
|
local firmware=$(echo "$firmware_line" | sed 's/[[:space:]]*#.*//' | tr -d ' ')
|
||||||
if [[ -n "$firmware" && "$firmware" != "none" ]]; then
|
if [[ -n "$firmware" && "$firmware" != "none" ]]; then
|
||||||
stage1_firmware+=("$firmware")
|
stage1_firmware+=("$firmware")
|
||||||
required_firmware+=("$firmware")
|
required_firmware+=("$firmware")
|
||||||
@@ -131,44 +133,25 @@ function initramfs_setup_modules() {
|
|||||||
|
|
||||||
local stage1_with_deps=()
|
local stage1_with_deps=()
|
||||||
if [[ ${#stage1_modules[@]} -gt 0 ]]; then
|
if [[ ${#stage1_modules[@]} -gt 0 ]]; then
|
||||||
|
log_info "Resolving dependencies for ${#stage1_modules[@]} stage1 modules: ${stage1_modules[*]}"
|
||||||
stage1_with_deps=($(initramfs_resolve_module_dependencies "${stage1_modules[@]}"))
|
stage1_with_deps=($(initramfs_resolve_module_dependencies "${stage1_modules[@]}"))
|
||||||
|
log_info "Stage1 expanded to ${#stage1_with_deps[@]} modules (including dependencies)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Write stage1 list with dependencies
|
# Write stage1 list with dependencies
|
||||||
printf '%s\n' "${stage1_with_deps[@]}" > "${modules_dir}/stage1.list"
|
printf '%s\n' "${stage1_with_deps[@]}" > "${modules_dir}/stage1.list"
|
||||||
|
|
||||||
# Create stage2 module list with dependencies and firmware
|
# Debug: show what's in stage1 list
|
||||||
log_info "Resolving stage2 module dependencies (extended hardware)"
|
if [[ ${#stage1_with_deps[@]} -gt 50 ]]; then
|
||||||
local stage2_modules=()
|
log_warn "Stage1 module list unexpectedly large: ${#stage1_with_deps[@]} modules"
|
||||||
local stage2_firmware=()
|
log_warn "This may indicate excessive dependency resolution"
|
||||||
|
log_debug "First 10 stage1 modules: ${stage1_with_deps[@]:0:10}"
|
||||||
while IFS=: read -r stage module firmware; do
|
|
||||||
if [[ "$stage" == "stage2" && -n "$module" ]]; then
|
|
||||||
stage2_modules+=("$module")
|
|
||||||
if [[ -n "$firmware" && "$firmware" != "none" ]]; then
|
|
||||||
stage2_firmware+=("$firmware")
|
|
||||||
required_firmware+=("$firmware")
|
|
||||||
log_debug "Module $module requires firmware: $firmware"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done < <(grep "^stage2:" "$modules_conf")
|
|
||||||
|
|
||||||
local stage2_with_deps=()
|
|
||||||
if [[ ${#stage2_modules[@]} -gt 0 ]]; then
|
|
||||||
stage2_with_deps=($(initramfs_resolve_module_dependencies "${stage2_modules[@]}"))
|
|
||||||
|
|
||||||
# Remove stage1 modules from stage2 to avoid duplicates
|
|
||||||
local stage2_unique=()
|
|
||||||
for mod in "${stage2_with_deps[@]}"; do
|
|
||||||
if ! printf '%s\n' "${stage1_with_deps[@]}" | grep -q "^${mod}$"; then
|
|
||||||
stage2_unique+=("$mod")
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
stage2_with_deps=("${stage2_unique[@]}")
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Write stage2 list with unique dependencies
|
# Create empty stage2 list (stage2 not used, only stage1)
|
||||||
printf '%s\n' "${stage2_with_deps[@]}" > "${modules_dir}/stage2.list"
|
log_info "Creating empty stage2 list (only using stage1 modules)"
|
||||||
|
echo > "${modules_dir}/stage2.list"
|
||||||
|
local stage2_with_deps=()
|
||||||
|
|
||||||
# Create firmware requirements list (remove duplicates)
|
# Create firmware requirements list (remove duplicates)
|
||||||
local unique_firmware=($(printf '%s\n' "${required_firmware[@]}" | sort -u))
|
local unique_firmware=($(printf '%s\n' "${required_firmware[@]}" | sort -u))
|
||||||
@@ -191,58 +174,119 @@ function initramfs_setup_modules() {
|
|||||||
|
|
||||||
# Report final counts
|
# Report final counts
|
||||||
local stage1_count=${#stage1_with_deps[@]}
|
local stage1_count=${#stage1_with_deps[@]}
|
||||||
local stage2_count=${#stage2_with_deps[@]}
|
|
||||||
local firmware_count=${#unique_firmware[@]}
|
local firmware_count=${#unique_firmware[@]}
|
||||||
|
|
||||||
log_info "Module configuration complete:"
|
log_info "Module configuration complete:"
|
||||||
log_info " Stage1 (critical + deps): ${stage1_count} modules"
|
log_info " Stage1 (critical + deps): ${stage1_count} modules"
|
||||||
log_info " Stage2 (extended + deps): ${stage2_count} modules"
|
log_info " Stage2: disabled (only using stage1)"
|
||||||
log_info " Required firmware packages: ${firmware_count}"
|
log_info " Required firmware packages: ${firmware_count}"
|
||||||
log_info " Total unique modules: $((stage1_count + stage2_count))"
|
log_info " Total modules: ${stage1_count}"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Resolve module dependencies recursively using modinfo
|
# Resolve module dependencies using built modules from initramfs
|
||||||
function initramfs_resolve_module_dependencies() {
|
function initramfs_resolve_module_dependencies() {
|
||||||
local modules=("$@")
|
local modules=("$@")
|
||||||
local resolved_modules=()
|
local resolved_modules=()
|
||||||
local processed_modules=()
|
local processed_modules=()
|
||||||
|
|
||||||
log_debug "Resolving dependencies for modules: ${modules[*]}"
|
log_debug "Resolving dependencies for modules using built modules: ${modules[*]}"
|
||||||
|
|
||||||
# Function to recursively resolve a single module's dependencies
|
# Use full kernel version from build process, not host kernel (uname -r)
|
||||||
|
local kernel_version="${KERNEL_FULL_VERSION:-${FULL_KERNEL_VERSION:-}}"
|
||||||
|
if [[ -z "$kernel_version" ]]; then
|
||||||
|
# Fallback: calculate from KERNEL_VERSION + LOCALVERSION
|
||||||
|
source "${LIB_SCRIPT_DIR}/kernel.sh"
|
||||||
|
kernel_version=$(kernel_get_full_version "${KERNEL_VERSION:-6.12.44}" "${PROJECT_ROOT}/config/kernel.config")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Use the built modules from initramfs directory (host path)
|
||||||
|
local modules_path="${PROJECT_ROOT}/initramfs/lib/modules/${kernel_version}"
|
||||||
|
|
||||||
|
log_debug "Using target kernel version: ${kernel_version}"
|
||||||
|
log_debug "Looking for built modules at: ${modules_path}"
|
||||||
|
|
||||||
|
if [[ ! -d "$modules_path" ]]; then
|
||||||
|
log_warn "Built modules not found at: $modules_path"
|
||||||
|
log_warn "Falling back to simple module list without dependencies"
|
||||||
|
printf '%s\n' "${modules[@]}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Ensure depmod has been run on the built modules
|
||||||
|
if [[ ! -f "${modules_path}/modules.dep" ]]; then
|
||||||
|
log_info "Running depmod on built modules"
|
||||||
|
depmod -a -b "${PROJECT_ROOT}/initramfs" "$kernel_version" 2>/dev/null || {
|
||||||
|
log_warn "depmod failed, using simple module list"
|
||||||
|
printf '%s\n' "${modules[@]}"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_debug "Using built modules from: $modules_path"
|
||||||
|
|
||||||
|
# Function to recursively resolve a single module's dependencies (with depth limit)
|
||||||
function resolve_single_module() {
|
function resolve_single_module() {
|
||||||
local module="$1"
|
local module="$1"
|
||||||
|
local depth="${2:-0}"
|
||||||
|
local max_depth=3 # Limit dependency depth to prevent explosion
|
||||||
|
|
||||||
# Skip if already processed
|
# Skip if already processed
|
||||||
if printf '%s\n' "${processed_modules[@]}" | grep -q "^${module}$"; then
|
if printf '%s\n' "${processed_modules[@]}" | grep -q "^${module}$"; then
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Skip if we've gone too deep
|
||||||
|
if [[ $depth -gt $max_depth ]]; then
|
||||||
|
log_debug "Skipping $module - dependency depth limit ($max_depth) reached"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
processed_modules+=("$module")
|
processed_modules+=("$module")
|
||||||
|
|
||||||
# Get module dependencies using modinfo
|
# Get module dependencies using modinfo from built modules
|
||||||
local deps=()
|
local deps=()
|
||||||
if command_exists "modinfo"; then
|
if command_exists "modinfo"; then
|
||||||
# Try to get dependencies - modinfo may fail for built-in modules
|
|
||||||
local modinfo_output
|
local modinfo_output
|
||||||
if modinfo_output=$(modinfo "$module" 2>/dev/null); then
|
local module_found=false
|
||||||
# Extract depends line and parse comma-separated dependencies
|
|
||||||
local depends_line=$(echo "$modinfo_output" | grep '^depends:' | head -1 | cut -d: -f2- | tr -d ' ')
|
# Find the actual module file
|
||||||
if [[ -n "$depends_line" && "$depends_line" != "-" ]]; then
|
local module_file=$(find "$modules_path" -name "${module}.ko*" -type f | head -1)
|
||||||
IFS=',' read -ra deps <<< "$depends_line"
|
|
||||||
|
if [[ -n "$module_file" && -f "$module_file" ]]; then
|
||||||
|
# Use direct file path for modinfo
|
||||||
|
if modinfo_output=$(modinfo "$module_file" 2>/dev/null); then
|
||||||
|
module_found=true
|
||||||
|
|
||||||
|
# Extract depends line and parse comma-separated dependencies
|
||||||
|
local depends_line=$(echo "$modinfo_output" | grep '^depends:' | head -1 | cut -d: -f2- | tr -d ' ')
|
||||||
|
if [[ -n "$depends_line" && "$depends_line" != "-" ]]; then
|
||||||
|
IFS=',' read -ra deps <<< "$depends_line"
|
||||||
|
if [[ ${#deps[@]} -gt 0 ]]; then
|
||||||
|
log_debug "Module $module (depth $depth) depends on: ${deps[*]}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
log_debug "modinfo failed for module: $module (may be built-in)"
|
# Check if module might be built-in
|
||||||
|
if grep -q "^$module\$" "${modules_path}/modules.builtin" 2>/dev/null; then
|
||||||
|
log_debug "Module $module is built-in (no .ko file needed)"
|
||||||
|
module_found=true
|
||||||
|
elif [[ "$module" == "virtio" || "$module" == "virtio_ring" ]]; then
|
||||||
|
# Special case: virtio core components may be integrated into virtio_pci in newer kernels
|
||||||
|
log_debug "Module $module is likely integrated into virtio subsystem (skipping dependency)"
|
||||||
|
module_found=true
|
||||||
|
else
|
||||||
|
log_debug "Module $module not found - may be built-in or integrated"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
log_warn "modinfo not available, skipping dependency resolution"
|
log_warn "modinfo not available, skipping dependency resolution"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Recursively resolve dependencies first
|
# Recursively resolve dependencies first (with incremented depth)
|
||||||
for dep in "${deps[@]}"; do
|
for dep in "${deps[@]}"; do
|
||||||
if [[ -n "$dep" ]]; then
|
if [[ -n "$dep" ]]; then
|
||||||
log_debug "Module $module depends on: $dep"
|
resolve_single_module "$dep" $((depth + 1))
|
||||||
resolve_single_module "$dep"
|
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
@@ -266,7 +310,7 @@ function initramfs_resolve_module_dependencies() {
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
log_debug "Resolved ${#unique_modules[@]} unique modules with dependencies"
|
log_debug "Resolved ${#unique_modules[@]} unique modules with dependencies from container"
|
||||||
printf '%s\n' "${unique_modules[@]}"
|
printf '%s\n' "${unique_modules[@]}"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -622,7 +666,126 @@ function initramfs_test_archive() {
|
|||||||
log_info "Archive integrity test passed"
|
log_info "Archive integrity test passed"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Copy resolved modules from container to initramfs
|
||||||
|
function initramfs_copy_resolved_modules() {
|
||||||
|
local initramfs_dir="$1"
|
||||||
|
local kernel_version="${2:-$(uname -r)}"
|
||||||
|
|
||||||
|
log_info "ENTRY: initramfs_copy_resolved_modules called with:"
|
||||||
|
log_info " initramfs_dir: ${initramfs_dir}"
|
||||||
|
log_info " kernel_version: ${kernel_version}"
|
||||||
|
log_info " CONTAINER_MODULES_PATH: ${CONTAINER_MODULES_PATH:-not-set}"
|
||||||
|
|
||||||
|
section_header "Copying Resolved Modules to Initramfs"
|
||||||
|
|
||||||
|
local container_modules_path="${CONTAINER_MODULES_PATH:-/lib/modules/${kernel_version}}"
|
||||||
|
local initramfs_modules_dir="${initramfs_dir}/lib/modules/${kernel_version}"
|
||||||
|
|
||||||
|
log_info "Container modules path: ${container_modules_path}"
|
||||||
|
log_info "Initramfs modules dir: ${initramfs_modules_dir}"
|
||||||
|
|
||||||
|
if [[ ! -d "$container_modules_path" ]]; then
|
||||||
|
log_error "Container modules not found: $container_modules_path"
|
||||||
|
log_info "Available module directories:"
|
||||||
|
ls -la /lib/modules/ 2>/dev/null || log_error "No /lib/modules directory"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "Container modules directory exists, proceeding..."
|
||||||
|
|
||||||
|
# Create initramfs modules directory
|
||||||
|
safe_mkdir "$initramfs_modules_dir"
|
||||||
|
|
||||||
|
# Read the stage1 module list (only using stage1, no stage2)
|
||||||
|
local stage1_modules=()
|
||||||
|
|
||||||
|
if [[ -f "${initramfs_modules_dir}/stage1.list" ]]; then
|
||||||
|
while IFS= read -r module; do
|
||||||
|
[[ -n "$module" ]] && stage1_modules+=("$module")
|
||||||
|
done < "${initramfs_modules_dir}/stage1.list"
|
||||||
|
fi
|
||||||
|
|
||||||
|
local all_modules=("${stage1_modules[@]}")
|
||||||
|
|
||||||
|
if [[ ${#all_modules[@]} -eq 0 ]]; then
|
||||||
|
log_warn "No modules to copy (empty stage1 module list)"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_info "Copying ${#all_modules[@]} stage1 modules to initramfs"
|
||||||
|
log_info "Stage1 modules: ${#stage1_modules[@]} (stage2 disabled)"
|
||||||
|
|
||||||
|
# Debug: show what we're copying if the list is reasonable
|
||||||
|
if [[ ${#all_modules[@]} -lt 200 ]]; then
|
||||||
|
log_debug "Modules to copy: ${all_modules[*]}"
|
||||||
|
else
|
||||||
|
log_warn "Module list is very large (${#all_modules[@]}), showing sample:"
|
||||||
|
log_debug "First 10: ${all_modules[@]:0:10}"
|
||||||
|
log_debug "Last 10: ${all_modules[@]:-10}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Copy essential module metadata first
|
||||||
|
local essential_files=(
|
||||||
|
"modules.order"
|
||||||
|
"modules.builtin"
|
||||||
|
"modules.builtin.modinfo"
|
||||||
|
"modules.dep"
|
||||||
|
"modules.dep.bin"
|
||||||
|
"modules.symbols"
|
||||||
|
"modules.symbols.bin"
|
||||||
|
"modules.alias"
|
||||||
|
"modules.alias.bin"
|
||||||
|
"modules.devname"
|
||||||
|
)
|
||||||
|
|
||||||
|
for file in "${essential_files[@]}"; do
|
||||||
|
if [[ -f "${container_modules_path}/${file}" ]]; then
|
||||||
|
safe_execute cp "${container_modules_path}/${file}" "${initramfs_modules_dir}/"
|
||||||
|
log_debug "Copied module metadata: $file"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Copy actual module files
|
||||||
|
local copied_count=0
|
||||||
|
local failed_count=0
|
||||||
|
|
||||||
|
for module in "${all_modules[@]}"; do
|
||||||
|
local module_found=false
|
||||||
|
|
||||||
|
# Try to find module file
|
||||||
|
local module_file=$(find "$container_modules_path" -name "${module}.ko*" -type f | head -1)
|
||||||
|
|
||||||
|
if [[ -n "$module_file" && -f "$module_file" ]]; then
|
||||||
|
# Preserve directory structure
|
||||||
|
local rel_path="${module_file#${container_modules_path}/}"
|
||||||
|
local target_dir="${initramfs_modules_dir}/$(dirname "$rel_path")"
|
||||||
|
|
||||||
|
safe_mkdir "$target_dir"
|
||||||
|
safe_execute cp "$module_file" "${initramfs_modules_dir}/${rel_path}"
|
||||||
|
|
||||||
|
log_debug "Copied module: $module from $rel_path"
|
||||||
|
((copied_count++))
|
||||||
|
module_found=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$module_found" == "false" ]]; then
|
||||||
|
log_warn "Module not found in container: $module"
|
||||||
|
((failed_count++))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
log_info "Module copy complete: ${copied_count} copied, ${failed_count} failed"
|
||||||
|
|
||||||
|
# Run depmod in initramfs context if we have the tools
|
||||||
|
if command_exists "depmod" && [[ $copied_count -gt 0 ]]; then
|
||||||
|
log_info "Running depmod for initramfs modules"
|
||||||
|
safe_execute depmod -a -b "$initramfs_dir" "$kernel_version"
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
# Export all functions at the end after they're all defined
|
# Export all functions at the end after they're all defined
|
||||||
export -f initramfs_setup_zinit initramfs_setup_modules initramfs_resolve_module_dependencies
|
export -f initramfs_setup_zinit initramfs_setup_modules initramfs_resolve_module_dependencies
|
||||||
export -f initramfs_install_init_script initramfs_create_module_scripts initramfs_strip_and_upx
|
export -f initramfs_install_init_script initramfs_create_module_scripts initramfs_strip_and_upx
|
||||||
export -f initramfs_create_cpio initramfs_validate initramfs_test_archive
|
export -f initramfs_create_cpio initramfs_validate initramfs_test_archive initramfs_copy_resolved_modules
|
||||||
Reference in New Issue
Block a user