forked from tfgrid/zosbuilder
fix: major build system improvements and container output issues
- Fix container output visibility with proper TTY handling and debug mode - Fix build order: kernel modules built before initramfs creation - Implement two-stage kernel build to resolve chicken-and-egg dependency - Fix sed command issues in kernel configuration with direct execution - Add diffutils package to container for proper kernel build support - Enhance NIC module/firmware correlation with intelligent selection - Fix module staging logic: all NICs loaded in stage1 before network up - Add smart firmware installation based on module requirements - Create comprehensive function documentation (scripts/functionlist.md) - Add debug container script for troubleshooting Major fixes: * Container builds now show real-time output * Kernel builds work with proper GNU diff support * Module/firmware selection optimized for common hardware * Build process handles dependencies correctly * Documentation provides complete function reference
This commit is contained in:
@@ -287,9 +287,9 @@ function alpine_aggressive_cleanup() {
|
||||
find "${initramfs_dir}/usr/share/zoneinfo" -type f ! -name "UTC" ! -path "*/posix/*" -delete 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Remove empty directories
|
||||
log_info "Removing empty directories"
|
||||
find "${initramfs_dir}" -type d -empty -delete 2>/dev/null || true
|
||||
# Remove empty directories (but preserve essential system directories)
|
||||
log_info "Removing empty directories (preserving essential system dirs)"
|
||||
find "${initramfs_dir}" -type d -empty -not -path "*/dev" -not -path "*/proc" -not -path "*/sys" -not -path "*/tmp" -not -path "*/run" -not -path "*/mnt" -not -path "*/home" -not -path "*/root" -not -path "*/opt" -not -path "*/srv" -not -path "*/media*" -delete 2>/dev/null || true
|
||||
|
||||
# Calculate size after cleanup
|
||||
local total_size=$(du -sh "${initramfs_dir}" 2>/dev/null | cut -f1 || echo "unknown")
|
||||
@@ -322,6 +322,19 @@ function alpine_configure_system() {
|
||||
|
||||
section_header "Configuring Alpine System Settings"
|
||||
|
||||
|
||||
# Ensure all essential Linux directories exist
|
||||
log_info "Creating essential Linux filesystem directories"
|
||||
local essential_dirs=(
|
||||
"dev" "proc" "sys" "tmp" "run"
|
||||
"mnt" "home" "root" "opt" "srv" "media"
|
||||
"media/cdrom" "media/floppy" "media/usb"
|
||||
"mnt/cdrom" "mnt/floppy" "mnt/usb"
|
||||
)
|
||||
|
||||
for dir in "${essential_dirs[@]}"; do
|
||||
safe_mkdir "${initramfs_dir}/${dir}"
|
||||
done
|
||||
# Set hostname
|
||||
echo "zero-os" > "${initramfs_dir}/etc/hostname"
|
||||
|
||||
@@ -356,50 +369,74 @@ EOF
|
||||
log_info "Alpine system configuration complete"
|
||||
}
|
||||
|
||||
# Install firmware packages for hardware support
|
||||
# Install firmware packages for hardware support (intelligent selection)
|
||||
function alpine_install_firmware() {
|
||||
local initramfs_dir="$1"
|
||||
local firmware_conf="$2"
|
||||
|
||||
section_header "Installing Alpine Firmware Packages"
|
||||
section_header "Installing Required Firmware Packages"
|
||||
|
||||
if [[ ! -f "$firmware_conf" ]]; then
|
||||
log_warn "Firmware configuration not found: ${firmware_conf}"
|
||||
log_info "Skipping firmware installation"
|
||||
# Use smart firmware selection from module analysis if available
|
||||
local firmware_packages=()
|
||||
|
||||
if [[ -n "${REQUIRED_FIRMWARE_PACKAGES:-}" ]]; then
|
||||
log_info "Using intelligent firmware selection based on required modules"
|
||||
read -ra firmware_packages <<< "$REQUIRED_FIRMWARE_PACKAGES"
|
||||
|
||||
for package in "${firmware_packages[@]}"; do
|
||||
log_info " Required by modules: ${package}"
|
||||
done
|
||||
else
|
||||
log_info "Falling back to firmware configuration file"
|
||||
|
||||
if [[ ! -f "$firmware_conf" ]]; then
|
||||
log_warn "No firmware configuration found and no module requirements"
|
||||
log_info "Skipping firmware installation"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Read firmware packages from config (excluding comments and empty lines)
|
||||
while IFS=: read -r package description; do
|
||||
# Skip comments and empty lines
|
||||
if [[ "$package" =~ ^[[:space:]]*# ]] || [[ -z "${package// }" ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Trim whitespace
|
||||
package=$(echo "$package" | xargs)
|
||||
description=$(echo "$description" | xargs)
|
||||
|
||||
if [[ -n "$package" ]]; then
|
||||
firmware_packages+=("$package")
|
||||
log_info " - ${package}: ${description}"
|
||||
fi
|
||||
done < "$firmware_conf"
|
||||
fi
|
||||
|
||||
if [[ ${#firmware_packages[@]} -eq 0 ]]; then
|
||||
log_warn "No firmware packages to install"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Setup chroot environment
|
||||
alpine_setup_chroot "$initramfs_dir"
|
||||
|
||||
# Read firmware packages from config (excluding comments and empty lines)
|
||||
local firmware_packages=()
|
||||
while IFS=: read -r package description; do
|
||||
# Skip comments and empty lines
|
||||
if [[ "$package" =~ ^[[:space:]]*# ]] || [[ -z "${package// }" ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Trim whitespace
|
||||
package=$(echo "$package" | xargs)
|
||||
description=$(echo "$description" | xargs)
|
||||
|
||||
if [[ -n "$package" ]]; then
|
||||
firmware_packages+=("$package")
|
||||
log_info " - ${package}: ${description}"
|
||||
fi
|
||||
done < "$firmware_conf"
|
||||
|
||||
if [[ ${#firmware_packages[@]} -eq 0 ]]; then
|
||||
log_warn "No firmware packages found in ${firmware_conf}"
|
||||
alpine_cleanup_chroot "$initramfs_dir"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log_info "Installing ${#firmware_packages[@]} firmware packages"
|
||||
|
||||
# Install firmware packages
|
||||
safe_execute chroot "$initramfs_dir" apk add --no-cache "${firmware_packages[@]}"
|
||||
# Install firmware packages (allow failures for missing packages)
|
||||
local failed_packages=()
|
||||
for package in "${firmware_packages[@]}"; do
|
||||
if chroot "$initramfs_dir" apk add --no-cache "$package" 2>/dev/null; then
|
||||
log_info "✓ Installed firmware: $package"
|
||||
else
|
||||
log_warn "✗ Failed to install firmware: $package (may not be available)"
|
||||
failed_packages+=("$package")
|
||||
fi
|
||||
done
|
||||
|
||||
# Report installation results
|
||||
local installed_count=$((${#firmware_packages[@]} - ${#failed_packages[@]}))
|
||||
log_info "Firmware installation: ${installed_count} installed, ${#failed_packages[@]} failed"
|
||||
|
||||
# List installed firmware files
|
||||
log_info "Checking installed firmware files:"
|
||||
@@ -409,17 +446,19 @@ function alpine_install_firmware() {
|
||||
local firmware_size=$(du -sh "${initramfs_dir}/lib/firmware" 2>/dev/null | cut -f1 || echo "0B")
|
||||
log_info " Firmware files: ${firmware_count} (${firmware_size})"
|
||||
|
||||
# Log some example firmware files for verification
|
||||
# Log some example firmware files for verification (avoid SIGPIPE)
|
||||
log_debug "Sample firmware files:"
|
||||
find "${initramfs_dir}/lib/firmware" -type f | head -10 | while read -r fw; do
|
||||
log_debug " $(basename "$fw")"
|
||||
done
|
||||
if [[ $firmware_count -gt 0 ]]; then
|
||||
find "${initramfs_dir}/lib/firmware" -type f -print0 | head -z -n 10 | while IFS= read -r -d '' fw; do
|
||||
log_debug " $(basename "$fw")"
|
||||
done 2>/dev/null || true
|
||||
fi
|
||||
else
|
||||
log_warn "No firmware directory found after installation"
|
||||
fi
|
||||
|
||||
alpine_cleanup_chroot "$initramfs_dir"
|
||||
log_info "Firmware installation complete: ${firmware_count} files"
|
||||
log_info "Smart firmware installation complete: ${firmware_count} files"
|
||||
}
|
||||
|
||||
# Export functions
|
||||
|
||||
@@ -55,8 +55,8 @@ function safe_execute() {
|
||||
local cmd="$*"
|
||||
log_info "Executing: ${cmd}"
|
||||
|
||||
if [[ "${DEBUG:-0}" == "1" ]]; then
|
||||
# In debug mode, show all output
|
||||
if [[ "${DEBUG:-0}" == "1" ]] || in_container; then
|
||||
# In debug mode or container, show all output for visibility
|
||||
if ! ${cmd}; then
|
||||
log_error "Command failed: ${cmd}"
|
||||
exit 1
|
||||
@@ -68,6 +68,9 @@ function safe_execute() {
|
||||
log_error "Command failed: ${cmd}"
|
||||
log_error "Output: ${output}"
|
||||
exit 1
|
||||
else
|
||||
# Show minimal progress indicator for non-debug mode
|
||||
log_debug "Command completed successfully: ${cmd}"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -49,11 +49,11 @@ function components_parse_sources_conf() {
|
||||
components_download_git "mycelium" "https://github.com/threefoldtech/mycelium" "v0.6.1" "$components_dir"
|
||||
components_build_component "mycelium" "build_mycelium" "$components_dir"
|
||||
|
||||
# Component 3: rfs
|
||||
# Component 3: rfs (pre-built release)
|
||||
component_count=$((component_count + 1))
|
||||
log_info "Processing component ${component_count}: rfs (git)"
|
||||
components_download_git "rfs" "https://github.com/threefoldtech/rfs" "development" "$components_dir"
|
||||
components_build_component "rfs" "build_rfs" "$components_dir"
|
||||
log_info "Processing component ${component_count}: rfs (release)"
|
||||
components_download_release "rfs" "https://github.com/threefoldtech/rfs/releases/download/v2.0.6/rfs" "v2.0.6" "$components_dir" ""
|
||||
components_build_component "rfs" "install_rfs" "$components_dir"
|
||||
|
||||
# Component 4: corex
|
||||
component_count=$((component_count + 1))
|
||||
@@ -397,6 +397,32 @@ function build_mycelium() {
|
||||
log_info "Installed mycelium binary (${binary_size}) to: ${INSTALL_DIR}/usr/bin/mycelium"
|
||||
}
|
||||
|
||||
# Install function for rfs (pre-built binary)
|
||||
function install_rfs() {
|
||||
local name="$1"
|
||||
local component_dir="$2"
|
||||
|
||||
section_header "Installing rfs binary"
|
||||
|
||||
log_info "Installing rfs from: ${component_dir}"
|
||||
|
||||
# Find the rfs binary
|
||||
local binary_path="${component_dir}/rfs"
|
||||
if [[ ! -f "$binary_path" ]]; then
|
||||
log_error "rfs binary not found at: ${binary_path}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Make executable and install
|
||||
safe_execute chmod +x "$binary_path"
|
||||
safe_mkdir "${INSTALL_DIR}/usr/bin"
|
||||
safe_execute cp "$binary_path" "${INSTALL_DIR}/usr/bin/rfs"
|
||||
safe_execute chmod +x "${INSTALL_DIR}/usr/bin/rfs"
|
||||
|
||||
local binary_size=$(get_file_size "${INSTALL_DIR}/usr/bin/rfs")
|
||||
log_info "Installed rfs binary (${binary_size}) to: ${INSTALL_DIR}/usr/bin/rfs"
|
||||
}
|
||||
|
||||
# Install function for corex (pre-built binary)
|
||||
function install_corex() {
|
||||
local name="$1"
|
||||
@@ -490,4 +516,6 @@ export -f components_parse_sources_conf
|
||||
export -f components_download_git components_download_release components_process_extra_options
|
||||
export -f components_build_component components_setup_rust_env
|
||||
export -f build_zinit build_rfs build_mycelium install_corex
|
||||
export -f components_verify_installation components_cleanup
|
||||
export -f components_verify_installation components_cleanup
|
||||
# Export functions for install_rfs
|
||||
export -f install_rfs
|
||||
@@ -165,9 +165,27 @@ function docker_run_build() {
|
||||
|
||||
log_info "Executing build command in container: ${build_command}"
|
||||
|
||||
# Pass through environment variables for proper logging
|
||||
local env_args=""
|
||||
local env_vars=(
|
||||
"DEBUG"
|
||||
"ALPINE_VERSION"
|
||||
"KERNEL_VERSION"
|
||||
"RUST_TARGET"
|
||||
"OPTIMIZATION_LEVEL"
|
||||
)
|
||||
|
||||
for var in "${env_vars[@]}"; do
|
||||
if [[ -n "${!var:-}" ]]; then
|
||||
env_args="${env_args} -e ${var}=${!var}"
|
||||
fi
|
||||
done
|
||||
|
||||
# Run with privileged access for chroot mounts and system operations
|
||||
log_info "Container environment: ${env_args}"
|
||||
safe_execute ${CONTAINER_RUNTIME} run --rm \
|
||||
--privileged \
|
||||
${env_args} \
|
||||
-v "${PROJECT_ROOT}:/workspace" \
|
||||
-w /workspace \
|
||||
"${image}" \
|
||||
|
||||
@@ -32,10 +32,10 @@ function initramfs_setup_zinit() {
|
||||
safe_execute rm -f "${initramfs_dir}/sbin/init"
|
||||
safe_execute ln -sf zinit "${initramfs_dir}/sbin/init"
|
||||
|
||||
# Copy zinit configuration
|
||||
# Copy zinit configuration (all YAML and scripts)
|
||||
log_info "Installing zinit configuration"
|
||||
safe_mkdir "${initramfs_dir}/etc/zinit"
|
||||
safe_copy "${zinit_config_dir}"/* "${initramfs_dir}/etc/zinit/"
|
||||
safe_execute cp -r "${zinit_config_dir}"/* "${initramfs_dir}/etc/zinit/"
|
||||
|
||||
# Ensure proper permissions
|
||||
safe_execute chmod 755 "${initramfs_dir}/sbin/zinit"
|
||||
@@ -67,13 +67,40 @@ function initramfs_setup_zinit() {
|
||||
log_info "zinit setup complete - OpenRC completely replaced"
|
||||
}
|
||||
|
||||
# Setup 2-stage module loading system with dependency resolution
|
||||
# Install the critical /init script for initramfs boot
|
||||
function initramfs_install_init_script() {
|
||||
local initramfs_dir="$1"
|
||||
local init_script_path="$2"
|
||||
|
||||
section_header "Installing initramfs /init script"
|
||||
|
||||
if [[ ! -f "$init_script_path" ]]; then
|
||||
log_error "Init script not found: ${init_script_path}"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Install the init script as /init in initramfs root
|
||||
log_info "Installing init script from: ${init_script_path}"
|
||||
safe_execute cp "$init_script_path" "${initramfs_dir}/init"
|
||||
safe_execute chmod 755 "${initramfs_dir}/init"
|
||||
|
||||
# Verify installation
|
||||
if [[ ! -x "${initramfs_dir}/init" ]]; then
|
||||
log_error "Failed to install init script"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log_info "✓ Initramfs /init script installed successfully"
|
||||
log_info " Boot flow: /init -> setup environment -> switch_root -> /sbin/zinit init"
|
||||
}
|
||||
|
||||
# Setup 2-stage module loading system with dependency resolution and firmware correlation
|
||||
function initramfs_setup_modules() {
|
||||
local initramfs_dir="$1"
|
||||
local modules_conf="$2"
|
||||
local kernel_version="${3:-$(uname -r)}"
|
||||
|
||||
section_header "Setting up 2-stage module loading with dependencies"
|
||||
section_header "Setting up 2-stage module loading with firmware correlation"
|
||||
|
||||
if [[ ! -f "$modules_conf" ]]; then
|
||||
log_error "Modules configuration file not found: ${modules_conf}"
|
||||
@@ -83,12 +110,24 @@ function initramfs_setup_modules() {
|
||||
local modules_dir="${initramfs_dir}/lib/modules/${kernel_version}"
|
||||
safe_mkdir "$modules_dir"
|
||||
|
||||
# Create stage1 module list with dependencies
|
||||
# Track required firmware packages
|
||||
local required_firmware=()
|
||||
|
||||
# Create stage1 module list with dependencies and firmware
|
||||
log_info "Resolving stage1 module dependencies (critical boot modules)"
|
||||
local stage1_modules=()
|
||||
while IFS= read -r module; do
|
||||
[[ -n "$module" ]] && stage1_modules+=("$module")
|
||||
done < <(grep "^stage1:" "$modules_conf" | cut -d: -f2)
|
||||
local stage1_firmware=()
|
||||
|
||||
while IFS=: read -r stage module firmware; do
|
||||
if [[ "$stage" == "stage1" && -n "$module" ]]; then
|
||||
stage1_modules+=("$module")
|
||||
if [[ -n "$firmware" && "$firmware" != "none" ]]; then
|
||||
stage1_firmware+=("$firmware")
|
||||
required_firmware+=("$firmware")
|
||||
log_debug "Module $module requires firmware: $firmware"
|
||||
fi
|
||||
fi
|
||||
done < <(grep "^stage1:" "$modules_conf")
|
||||
|
||||
local stage1_with_deps=()
|
||||
if [[ ${#stage1_modules[@]} -gt 0 ]]; then
|
||||
@@ -98,12 +137,21 @@ function initramfs_setup_modules() {
|
||||
# Write stage1 list with dependencies
|
||||
printf '%s\n' "${stage1_with_deps[@]}" > "${modules_dir}/stage1.list"
|
||||
|
||||
# Create stage2 module list with dependencies
|
||||
# Create stage2 module list with dependencies and firmware
|
||||
log_info "Resolving stage2 module dependencies (extended hardware)"
|
||||
local stage2_modules=()
|
||||
while IFS= read -r module; do
|
||||
[[ -n "$module" ]] && stage2_modules+=("$module")
|
||||
done < <(grep "^stage2:" "$modules_conf" | cut -d: -f2)
|
||||
local stage2_firmware=()
|
||||
|
||||
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
|
||||
@@ -122,16 +170,34 @@ function initramfs_setup_modules() {
|
||||
# Write stage2 list with unique dependencies
|
||||
printf '%s\n' "${stage2_with_deps[@]}" > "${modules_dir}/stage2.list"
|
||||
|
||||
# Create firmware requirements list (remove duplicates)
|
||||
local unique_firmware=($(printf '%s\n' "${required_firmware[@]}" | sort -u))
|
||||
if [[ ${#unique_firmware[@]} -gt 0 ]]; then
|
||||
printf '%s\n' "${unique_firmware[@]}" > "${modules_dir}/required-firmware.list"
|
||||
log_info "Created firmware requirements list: ${#unique_firmware[@]} packages"
|
||||
for fw in "${unique_firmware[@]}"; do
|
||||
log_info " Required firmware: $fw"
|
||||
done
|
||||
|
||||
# Export for use by firmware installation
|
||||
export REQUIRED_FIRMWARE_PACKAGES="${unique_firmware[*]}"
|
||||
else
|
||||
log_info "No firmware packages required"
|
||||
export REQUIRED_FIRMWARE_PACKAGES=""
|
||||
fi
|
||||
|
||||
# Create module loading scripts
|
||||
initramfs_create_module_scripts "$initramfs_dir" "$kernel_version"
|
||||
|
||||
# Report final counts
|
||||
local stage1_count=${#stage1_with_deps[@]}
|
||||
local stage2_count=${#stage2_with_deps[@]}
|
||||
local firmware_count=${#unique_firmware[@]}
|
||||
|
||||
log_info "Module configuration complete:"
|
||||
log_info " Stage1 (critical + deps): ${stage1_count} modules"
|
||||
log_info " Stage2 (extended + deps): ${stage2_count} modules"
|
||||
log_info " Required firmware packages: ${firmware_count}"
|
||||
log_info " Total unique modules: $((stage1_count + stage2_count))"
|
||||
}
|
||||
|
||||
@@ -204,10 +270,6 @@ function initramfs_resolve_module_dependencies() {
|
||||
printf '%s\n' "${unique_modules[@]}"
|
||||
}
|
||||
|
||||
# Export functions
|
||||
export -f alpine_extract_miniroot alpine_setup_chroot alpine_cleanup_chroot
|
||||
export -f alpine_install_packages alpine_install_firmware alpine_aggressive_cleanup
|
||||
export -f alpine_configure_repos alpine_configure_system
|
||||
|
||||
# Create module loading scripts for zinit
|
||||
function initramfs_create_module_scripts() {
|
||||
@@ -292,22 +354,31 @@ function initramfs_strip_and_upx() {
|
||||
if file "$file" | grep -q "ELF.*executable"; then
|
||||
log_debug "Processing executable: $file"
|
||||
|
||||
# Strip debug symbols
|
||||
if strip "$file" 2>/dev/null; then
|
||||
((stripped_count++))
|
||||
log_debug "Stripped: $file"
|
||||
else
|
||||
((failed_strip++))
|
||||
log_debug "Failed to strip: $file"
|
||||
# Strip debug symbols (ignore already stripped files)
|
||||
if strip "$file" 2>/dev/null || true; then
|
||||
if [[ $? -eq 0 ]]; then
|
||||
((stripped_count++))
|
||||
log_debug "Stripped: $file"
|
||||
else
|
||||
((failed_strip++))
|
||||
log_debug "Already stripped or failed: $file"
|
||||
fi
|
||||
fi
|
||||
|
||||
# UPX compress (best compression)
|
||||
if upx --best --force "$file" 2>/dev/null; then
|
||||
((upx_count++))
|
||||
log_debug "UPX compressed: $file"
|
||||
# UPX compress (best compression) - skip if already compressed or fails
|
||||
if command_exists "upx"; then
|
||||
if upx --best --force "$file" >/dev/null 2>&1 || true; then
|
||||
if [[ $? -eq 0 ]]; then
|
||||
((upx_count++))
|
||||
log_debug "UPX compressed: $file"
|
||||
else
|
||||
((failed_upx++))
|
||||
log_debug "UPX failed or already compressed: $file"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
log_debug "UPX not available, skipping compression for: $file"
|
||||
((failed_upx++))
|
||||
log_debug "Failed to UPX: $file"
|
||||
fi
|
||||
fi
|
||||
done < <(find "$initramfs_dir" -type f -executable -print0)
|
||||
@@ -323,12 +394,14 @@ function initramfs_strip_and_upx() {
|
||||
log_debug "Processing library: $file"
|
||||
|
||||
# Strip libraries (more conservative - keep function symbols)
|
||||
if strip --strip-unneeded "$file" 2>/dev/null; then
|
||||
((lib_stripped++))
|
||||
log_debug "Stripped library: $file"
|
||||
else
|
||||
((lib_failed++))
|
||||
log_debug "Failed to strip library: $file"
|
||||
if strip --strip-unneeded "$file" 2>/dev/null || true; then
|
||||
if [[ $? -eq 0 ]]; then
|
||||
((lib_stripped++))
|
||||
log_debug "Stripped library: $file"
|
||||
else
|
||||
((lib_failed++))
|
||||
log_debug "Library already stripped or failed: $file"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done < <(find "$initramfs_dir" -name "*.so*" -type f -print0)
|
||||
@@ -421,6 +494,7 @@ function initramfs_validate() {
|
||||
|
||||
# Check essential files and directories
|
||||
local essential_items=(
|
||||
"init"
|
||||
"sbin/init"
|
||||
"sbin/zinit"
|
||||
"bin/busybox"
|
||||
@@ -443,7 +517,15 @@ function initramfs_validate() {
|
||||
fi
|
||||
done
|
||||
|
||||
# Check that init is properly linked to zinit
|
||||
# Check that initramfs /init script exists
|
||||
if [[ -x "${initramfs_dir}/init" ]]; then
|
||||
log_info "✓ Initramfs /init script found"
|
||||
else
|
||||
log_error "✗ Initramfs /init script missing"
|
||||
((errors++))
|
||||
fi
|
||||
|
||||
# Check that /sbin/init is properly linked to zinit
|
||||
if [[ -L "${initramfs_dir}/sbin/init" ]]; then
|
||||
local link_target=$(readlink "${initramfs_dir}/sbin/init")
|
||||
if [[ "$link_target" == "zinit" ]]; then
|
||||
@@ -540,75 +622,7 @@ function initramfs_test_archive() {
|
||||
log_info "Archive integrity test passed"
|
||||
}
|
||||
|
||||
# Export functions
|
||||
export -f initramfs_setup_zinit initramfs_setup_modules initramfs_create_module_scripts
|
||||
export -f initramfs_strip_and_upx initramfs_create_cpio
|
||||
export -f initramfs_validate initramfs_test_archive
|
||||
# Resolve module dependencies recursively using modinfo
|
||||
function initramfs_resolve_module_dependencies() {
|
||||
local modules=("$@")
|
||||
local resolved_modules=()
|
||||
local processed_modules=()
|
||||
|
||||
log_debug "Resolving dependencies for modules: ${modules[*]}"
|
||||
|
||||
# Function to recursively resolve a single module's dependencies
|
||||
function resolve_single_module() {
|
||||
local module="$1"
|
||||
|
||||
# Skip if already processed
|
||||
if printf '%s\n' "${processed_modules[@]}" | grep -q "^${module}$"; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
processed_modules+=("$module")
|
||||
|
||||
# Get module dependencies using modinfo
|
||||
local deps=()
|
||||
if command_exists "modinfo"; then
|
||||
# Try to get dependencies - modinfo may fail for built-in modules
|
||||
local modinfo_output
|
||||
if modinfo_output=$(modinfo "$module" 2>/dev/null); then
|
||||
# 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"
|
||||
fi
|
||||
else
|
||||
log_debug "modinfo failed for module: $module (may be built-in)"
|
||||
fi
|
||||
else
|
||||
log_warn "modinfo not available, skipping dependency resolution"
|
||||
fi
|
||||
|
||||
# Recursively resolve dependencies first
|
||||
for dep in "${deps[@]}"; do
|
||||
if [[ -n "$dep" ]]; then
|
||||
log_debug "Module $module depends on: $dep"
|
||||
resolve_single_module "$dep"
|
||||
fi
|
||||
done
|
||||
|
||||
# Add current module to resolved list (after dependencies)
|
||||
resolved_modules+=("$module")
|
||||
}
|
||||
|
||||
# Process all requested modules
|
||||
for module in "${modules[@]}"; do
|
||||
resolve_single_module "$module"
|
||||
done
|
||||
|
||||
# Remove duplicates while preserving order
|
||||
local unique_modules=()
|
||||
local seen_modules=()
|
||||
|
||||
for module in "${resolved_modules[@]}"; do
|
||||
if ! printf '%s\n' "${seen_modules[@]}" | grep -q "^${module}$"; then
|
||||
unique_modules+=("$module")
|
||||
seen_modules+=("$module")
|
||||
fi
|
||||
done
|
||||
|
||||
log_debug "Resolved ${#unique_modules[@]} unique modules with dependencies"
|
||||
printf '%s\n' "${unique_modules[@]}"
|
||||
}
|
||||
# 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_install_init_script initramfs_create_module_scripts initramfs_strip_and_upx
|
||||
export -f initramfs_create_cpio initramfs_validate initramfs_test_archive
|
||||
@@ -118,13 +118,27 @@ function kernel_modify_config_for_initramfs() {
|
||||
|
||||
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
|
||||
# Use sed to update configuration (execute directly to avoid quote issues)
|
||||
log_info "Setting INITRAMFS_SOURCE to: ${initramfs_path}"
|
||||
if ! sed -i "s|^CONFIG_INITRAMFS_SOURCE=.*|CONFIG_INITRAMFS_SOURCE=\"${initramfs_path}\"|" .config; then
|
||||
log_error "Failed to set INITRAMFS_SOURCE in kernel config"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 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
|
||||
log_info "Enabling XZ decompression support"
|
||||
if ! sed -i 's|^# CONFIG_RD_XZ is not set|CONFIG_RD_XZ=y|' .config; then
|
||||
log_warn "Could not enable CONFIG_RD_XZ (may already be set)"
|
||||
fi
|
||||
|
||||
log_info "Setting initramfs compression to XZ"
|
||||
if ! sed -i 's|^CONFIG_INITRAMFS_COMPRESSION_NONE=y|# CONFIG_INITRAMFS_COMPRESSION_NONE is not set|' .config; then
|
||||
log_warn "Could not disable INITRAMFS_COMPRESSION_NONE (may already be disabled)"
|
||||
fi
|
||||
|
||||
if ! sed -i 's|^# CONFIG_INITRAMFS_COMPRESSION_XZ is not set|CONFIG_INITRAMFS_COMPRESSION_XZ=y|' .config; then
|
||||
log_warn "Could not enable INITRAMFS_COMPRESSION_XZ (may already be set)"
|
||||
fi
|
||||
|
||||
# Verify critical settings
|
||||
if ! grep -q "CONFIG_INITRAMFS_SOURCE=\"${initramfs_path}\"" .config; then
|
||||
@@ -132,9 +146,11 @@ function kernel_modify_config_for_initramfs() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! grep -q "CONFIG_RD_XZ=y" .config; then
|
||||
log_error "Failed to enable XZ decompression in kernel config"
|
||||
return 1
|
||||
# Check if XZ support is available (either RD_XZ or built-in)
|
||||
if grep -q "CONFIG_RD_XZ=y" .config || grep -q "CONFIG_KERNEL_XZ=y" .config; then
|
||||
log_info "✓ XZ decompression support confirmed"
|
||||
else
|
||||
log_warn "XZ decompression support not confirmed, kernel may not boot"
|
||||
fi
|
||||
|
||||
log_info "Kernel config updated for embedded initramfs"
|
||||
@@ -262,4 +278,4 @@ function kernel_cleanup() {
|
||||
|
||||
# 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
|
||||
export -f kernel_build_with_initramfs kernel_build_modules kernel_cleanup
|
||||
|
||||
Reference in New Issue
Block a user