initramfs+modules: robust copy aliasing, curated stage1 + PHYs, firmware policy via firmware.conf, runtime readiness, build ID; docs sync
Summary of changes (with references):\n\nModules + PHY coverage\n- Curated and normalized stage1 list in [config.modules.conf](config/modules.conf:1):\n - Boot-critical storage, core virtio, common NICs (Intel/Realtek/Broadcom), overlay/fuse, USB HCD/HID.\n - Added PHY drivers required by NIC MACs:\n * realtek (for r8169, etc.)\n * broadcom families: broadcom, bcm7xxx, bcm87xx, bcm_phy_lib, bcm_phy_ptp\n- Robust underscore↔hyphen aliasing during copy so e.g. xhci_pci → xhci-pci.ko, hid_generic → hid-generic.ko:\n - [bash.initramfs_copy_resolved_modules()](scripts/lib/initramfs.sh:990)\n\nFirmware policy and coverage\n- Firmware selection now authoritative via [config/firmware.conf](config/firmware.conf:1); ignore modules.conf firmware hints:\n - [bash.initramfs_setup_modules()](scripts/lib/initramfs.sh:229)\n - Count from firmware.conf for reporting; remove stale required-firmware.list.\n- Expanded NIC firmware set (bnx2, bnx2x, tigon, intel, realtek, rtl_nic, qlogic, e100) in [config.firmware.conf](config/firmware.conf:1).\n- Installer enforces firmware.conf source-of-truth in [bash.alpine_install_firmware()](scripts/lib/alpine.sh:392).\n\nEarly input & build freshness\n- Write a runtime build stamp to /etc/zero-os-build-id for embedded initramfs verification:\n - [bash.initramfs_finalize_customization()](scripts/lib/initramfs.sh:568)\n- Minor init refinements in [config.init](config/init:1) (ensures /home, consistent depmod path).\n\nRebuild helper improvements\n- [scripts/rebuild-after-zinit.sh](scripts/rebuild-after-zinit.sh:1):\n - Added --verify-only; container-aware execution; selective marker clears only.\n - Prints stage status before/after; avoids --rebuild-from; resolves full kernel version for diagnostics.\n\nRemote flist readiness + zinit\n- Init scripts now probe BASE_URL readiness and accept FLISTS_BASE_URL/FLIST_BASE_URL; firmware target is /lib/firmware:\n - [sh.firmware.sh](config/zinit/init/firmware.sh:1)\n - [sh.modules.sh](config/zinit/init/modules.sh:1)\n\nContainer, docs, and utilities\n- Stream container build logs by calling runtime build directly in [bash.docker_build_container()](scripts/lib/docker.sh:56).\n- Docs updated to reflect firmware policy, runtime readiness, rebuild helper, early input, and GRUB USB:\n - [docs.NOTES.md](docs/NOTES.md)\n - [docs.PROMPT.md](docs/PROMPT.md)\n - [docs.review-rfs-integration.md](docs/review-rfs-integration.md)\n- Added GRUB USB creator (referenced in docs): [scripts/make-grub-usb.sh](scripts/make-grub-usb.sh)\n\nCleanup\n- Removed legacy/duplicated config trees under configs/ and config/zinit.old/.\n- Minor newline and ignore fixes: [.gitignore](.gitignore:1)\n\nNet effect\n- Runtime now has correct USB HCDs/HID-generic and NIC+PHY coverage (Realtek/Broadcom), with matching firmware installed in initramfs.\n- Rebuild workflow is minimal and host/container-aware; docs are aligned with implemented behavior.\n
This commit is contained in:
@@ -395,43 +395,35 @@ function alpine_install_firmware() {
|
||||
|
||||
section_header "Installing Required Firmware Packages (Selective)"
|
||||
|
||||
# Use smart firmware selection from module analysis if available
|
||||
# Policy: firmware.conf is the authoritative source for initramfs firmware
|
||||
local firmware_packages=()
|
||||
|
||||
if [[ ! -f "$firmware_conf" ]]; then
|
||||
log_warn "Firmware configuration not found: ${firmware_conf}; skipping firmware installation to initramfs"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Ignore any REQUIRED_FIRMWARE_PACKAGES hints to avoid duplication/mismatch with modules.conf
|
||||
if [[ -n "${REQUIRED_FIRMWARE_PACKAGES:-}" ]]; then
|
||||
log_info "Using intelligent firmware selection based on COPIED modules only"
|
||||
read -ra firmware_packages <<< "$REQUIRED_FIRMWARE_PACKAGES"
|
||||
|
||||
log_info "Required firmware packages (${#firmware_packages[@]}):"
|
||||
for package in "${firmware_packages[@]}"; do
|
||||
log_info " ✓ ${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
|
||||
log_info "Firmware selection: ignoring REQUIRED_FIRMWARE_PACKAGES; using ${firmware_conf} as authoritative source"
|
||||
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
|
||||
|
||||
# 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
|
||||
# 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 to install"
|
||||
|
||||
@@ -56,7 +56,7 @@ function docker_build_container() {
|
||||
fi
|
||||
|
||||
log_info "Building container image: ${tag}"
|
||||
safe_execute ${CONTAINER_RUNTIME} build -t "${tag}" -f "${dockerfile_path}" "${PROJECT_ROOT}"
|
||||
${CONTAINER_RUNTIME} build -t "${tag}" -f "${dockerfile_path}" "${PROJECT_ROOT}"
|
||||
|
||||
log_info "Container image built successfully: ${tag}"
|
||||
}
|
||||
|
||||
@@ -250,16 +250,9 @@ function initramfs_setup_modules() {
|
||||
local stage1_modules=()
|
||||
local stage1_firmware=()
|
||||
|
||||
while IFS=: read -r stage module firmware_line; do
|
||||
while IFS=: read -r stage module _ignored_fw; do
|
||||
if [[ "$stage" == "stage1" && -n "$module" ]]; then
|
||||
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
|
||||
stage1_firmware+=("$firmware")
|
||||
required_firmware+=("$firmware")
|
||||
log_debug "Module $module requires firmware: $firmware"
|
||||
fi
|
||||
fi
|
||||
done < <(grep "^stage1:" "$modules_conf")
|
||||
|
||||
@@ -286,32 +279,32 @@ function initramfs_setup_modules() {
|
||||
local stage2_with_deps=()
|
||||
|
||||
# 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[*]}"
|
||||
# Firmware selection policy: use config/firmware.conf as the authoritative source.
|
||||
# Ignore firmware hints in modules.conf (third column) to avoid duplication/mismatch.
|
||||
if [[ -f "${PROJECT_ROOT}/config/firmware.conf" ]]; then
|
||||
log_info "Firmware selection: using config/firmware.conf (ignoring modules.conf firmware hints)"
|
||||
else
|
||||
log_info "No firmware packages required"
|
||||
export REQUIRED_FIRMWARE_PACKAGES=""
|
||||
log_warn "Firmware selection: config/firmware.conf not found; no firmware will be installed into initramfs"
|
||||
fi
|
||||
# Remove any stale list created by previous versions
|
||||
rm -f "${modules_dir}/required-firmware.list" 2>/dev/null || true
|
||||
# Do NOT export REQUIRED_FIRMWARE_PACKAGES anymore; alpine_install_firmware reads the config file directly.
|
||||
|
||||
# Create module loading scripts
|
||||
initramfs_create_module_scripts "$initramfs_dir" "$kernel_version"
|
||||
|
||||
# Report final counts
|
||||
local stage1_count=${#stage1_with_deps[@]}
|
||||
local firmware_count=${#unique_firmware[@]}
|
||||
# Count firmware entries from authoritative firmware.conf (non-empty, non-comment lines)
|
||||
local firmware_count=0
|
||||
if [[ -f "${PROJECT_ROOT}/config/firmware.conf" ]]; then
|
||||
firmware_count=$(grep -v '^[[:space:]]*#' "${PROJECT_ROOT}/config/firmware.conf" | sed '/^[[:space:]]*$/d' | wc -l | tr -d ' ')
|
||||
fi
|
||||
|
||||
log_info "Module configuration complete:"
|
||||
log_info " Stage1 (critical + deps): ${stage1_count} modules"
|
||||
log_info " Stage2: disabled (only using stage1)"
|
||||
log_info " Required firmware packages: ${firmware_count}"
|
||||
log_info " Firmware packages (from firmware.conf): ${firmware_count}"
|
||||
log_info " Total modules: ${stage1_count}"
|
||||
}
|
||||
|
||||
@@ -631,6 +624,17 @@ EOF
|
||||
log_info "Branding disabled: leaving /etc/motd, /etc/issue and root password unchanged"
|
||||
fi
|
||||
|
||||
# Write a unique build stamp to verify runtime image freshness
|
||||
# Allows confirming that the booted VM uses the latest embedded initramfs
|
||||
local _rand=""
|
||||
if command_exists "openssl"; then _rand=$(openssl rand -hex 6 2>/dev/null || true); fi
|
||||
local _build_id="ZOS-BUILD $(date -u +%Y-%m-%dT%H:%M:%SZ) ${_rand}"
|
||||
# Write via tee to ensure creation + visible logging, avoid shell redirection edge cases
|
||||
safe_mkdir "${initramfs_dir}/etc"
|
||||
printf "%s\n" "${_build_id}" | tee "${initramfs_dir}/etc/zero-os-build-id" >/dev/null
|
||||
safe_execute chmod 644 "${initramfs_dir}/etc/zero-os-build-id"
|
||||
log_info "Build ID: ${_build_id} (written to /etc/zero-os-build-id)"
|
||||
|
||||
# Ensure essential Linux filesystem directories exist (defensive), including /home
|
||||
# Some earlier stages or cleanups may have run in previous builds; enforce presence now.
|
||||
log_info "Ensuring essential directories exist (including /home)"
|
||||
@@ -1069,25 +1073,56 @@ function initramfs_copy_resolved_modules() {
|
||||
|
||||
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)
|
||||
|
||||
|
||||
# Try to find module file with robust underscore/hyphen aliasing
|
||||
# modprobe treats '_' and '-' as equivalent, but our file search must do both.
|
||||
local query="${module}"
|
||||
local module_file=""
|
||||
|
||||
# 1) Exact match (as given)
|
||||
module_file=$(find "$container_modules_path" -name "${query}.ko*" -type f | head -1)
|
||||
|
||||
# 2) Fallback: underscores -> hyphens (e.g., xhci_pci -> xhci-pci)
|
||||
if [[ -z "$module_file" || ! -f "$module_file" ]]; then
|
||||
local alt="${query//_/-}"
|
||||
if [[ "$alt" != "$query" ]]; then
|
||||
module_file=$(find "$container_modules_path" -name "${alt}.ko*" -type f | head -1)
|
||||
if [[ -n "$module_file" && -f "$module_file" ]]; then
|
||||
log_info "Resolved module alias: ${query} -> ${alt} (hyphen)"
|
||||
query="$alt"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# 3) Fallback: hyphens -> underscores (defensive; modinfo sometimes reports hyphen)
|
||||
if [[ -z "$module_file" || ! -f "$module_file" ]]; then
|
||||
local alt2="${query//-/_}"
|
||||
if [[ "$alt2" != "$query" ]]; then
|
||||
local mf2
|
||||
mf2=$(find "$container_modules_path" -name "${alt2}.ko*" -type f | head -1)
|
||||
if [[ -n "$mf2" && -f "$mf2" ]]; then
|
||||
log_info "Resolved module alias: ${query} -> ${alt2} (underscore)"
|
||||
query="$alt2"
|
||||
module_file="$mf2"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
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"
|
||||
|
||||
log_debug "Copied module: ${query} from ${rel_path}"
|
||||
((copied_count++))
|
||||
module_found=true
|
||||
fi
|
||||
|
||||
|
||||
if [[ "$module_found" == "false" ]]; then
|
||||
log_warn "Module not found in container: $module"
|
||||
log_warn "Module not found in container (after alias fallbacks): ${module}"
|
||||
((failed_count++))
|
||||
fi
|
||||
done
|
||||
|
||||
Reference in New Issue
Block a user