- add recursive module dependencies based on porper tools (modinfo)
- fix zinit boot sequences
- /dev/shm mount for alpine-built haveged
- mycelium
- rfs copy fixes
- better sequencing overall (god I miss 'before:'
268 lines
7.2 KiB
Bash
Executable File
268 lines
7.2 KiB
Bash
Executable File
#!/bin/bash
|
|
# resolve-module-dependencies.sh - Automatically resolve kernel module dependencies using modinfo
|
|
# This script builds a complete dependency tree for specified kernel modules
|
|
|
|
set -e
|
|
|
|
# Configuration
|
|
KERNEL_BUILD_DIR=""
|
|
MODULES_DIR=""
|
|
KERNEL_VERSION=""
|
|
VERBOSE=${VERBOSE:-0}
|
|
|
|
# Global arrays for tracking
|
|
declare -A RESOLVED_MODULES=() # Track resolved modules to avoid duplicates
|
|
declare -A PROCESSING_MODULES=() # Track modules being processed to detect cycles
|
|
declare -a DEPENDENCY_ORDER=() # Final ordered list of modules
|
|
|
|
usage() {
|
|
echo "Usage: $0 [OPTIONS] MODULE [MODULE...]"
|
|
echo ""
|
|
echo "Resolve kernel module dependencies using modinfo and copy to initramfs"
|
|
echo ""
|
|
echo "Options:"
|
|
echo " -k DIR Kernel build directory (e.g., /build/kernel/linux-6.12.41)"
|
|
echo " -m DIR Target modules directory (e.g., /build/initramfs/lib/modules/6.12.41-Zero-OS)"
|
|
echo " -v VER Kernel version (e.g., 6.12.41-Zero-OS)"
|
|
echo " -V Verbose output"
|
|
echo " -h Show this help"
|
|
echo ""
|
|
echo "Examples:"
|
|
echo " $0 -k /build/kernel/linux-6.12.41 -m /build/initramfs/lib/modules/6.12.41-Zero-OS -v 6.12.41-Zero-OS tun e1000e"
|
|
echo " $0 -k /build/kernel/linux-6.12.41 -m /build/initramfs/lib/modules/6.12.41-Zero-OS -v 6.12.41-Zero-OS mycelium-modules.list"
|
|
}
|
|
|
|
log() {
|
|
if [ "$VERBOSE" -eq 1 ]; then
|
|
echo "[INFO] $*" >&2
|
|
fi
|
|
}
|
|
|
|
warn() {
|
|
echo "[WARN] $*" >&2
|
|
}
|
|
|
|
error() {
|
|
echo "[ERROR] $*" >&2
|
|
exit 1
|
|
}
|
|
|
|
# Find a kernel module file in the build directory
|
|
find_module() {
|
|
local module_name="$1"
|
|
|
|
# Try with .ko extension
|
|
local ko_file=$(find "$KERNEL_BUILD_DIR" -name "${module_name}.ko" -type f 2>/dev/null | head -1)
|
|
if [ -n "$ko_file" ]; then
|
|
echo "$ko_file"
|
|
return 0
|
|
fi
|
|
|
|
# Try without extension (in case it was passed with .ko)
|
|
local base_name="${module_name%.ko}"
|
|
ko_file=$(find "$KERNEL_BUILD_DIR" -name "${base_name}.ko" -type f 2>/dev/null | head -1)
|
|
if [ -n "$ko_file" ]; then
|
|
echo "$ko_file"
|
|
return 0
|
|
fi
|
|
|
|
return 1
|
|
}
|
|
|
|
# Get dependencies for a module using modinfo
|
|
get_module_dependencies() {
|
|
local module_file="$1"
|
|
local module_name=$(basename "$module_file" .ko)
|
|
|
|
if [ ! -f "$module_file" ]; then
|
|
warn "Module file not found: $module_file"
|
|
return 1
|
|
fi
|
|
|
|
# Use modinfo to get dependencies
|
|
local deps=$(modinfo -F depends "$module_file" 2>/dev/null | tr ',' ' ')
|
|
|
|
if [ -n "$deps" ]; then
|
|
log "Dependencies for $module_name: $deps"
|
|
echo "$deps"
|
|
else
|
|
log "No dependencies for $module_name"
|
|
fi
|
|
}
|
|
|
|
# Recursively resolve module dependencies
|
|
resolve_dependencies() {
|
|
local module_name="$1"
|
|
local depth="$2"
|
|
local indent=""
|
|
|
|
# Create indentation for visual tree
|
|
for i in $(seq 1 $depth); do
|
|
indent=" $indent"
|
|
done
|
|
|
|
log "${indent}Resolving: $module_name (depth: $depth)"
|
|
|
|
# Check if we're already processing this module (circular dependency)
|
|
if [ "${PROCESSING_MODULES[$module_name]}" = "1" ]; then
|
|
warn "${indent}Circular dependency detected for: $module_name"
|
|
return 0
|
|
fi
|
|
|
|
# Check if already resolved
|
|
if [ "${RESOLVED_MODULES[$module_name]}" = "1" ]; then
|
|
log "${indent}Already resolved: $module_name"
|
|
return 0
|
|
fi
|
|
|
|
# Mark as being processed
|
|
PROCESSING_MODULES[$module_name]=1
|
|
|
|
# Find the module file
|
|
local module_file=$(find_module "$module_name")
|
|
if [ -z "$module_file" ]; then
|
|
warn "${indent}Module not found: $module_name"
|
|
unset PROCESSING_MODULES[$module_name]
|
|
return 1
|
|
fi
|
|
|
|
# Get dependencies
|
|
local deps=$(get_module_dependencies "$module_file")
|
|
|
|
# Recursively resolve dependencies first
|
|
for dep in $deps; do
|
|
if [ -n "$dep" ]; then
|
|
resolve_dependencies "$dep" $((depth + 1))
|
|
fi
|
|
done
|
|
|
|
# Mark as resolved and add to ordered list
|
|
RESOLVED_MODULES[$module_name]=1
|
|
DEPENDENCY_ORDER+=("$module_name")
|
|
log "${indent}Resolved: $module_name"
|
|
|
|
# Remove from processing list
|
|
unset PROCESSING_MODULES[$module_name]
|
|
}
|
|
|
|
# Copy module to target directory
|
|
copy_module() {
|
|
local module_name="$1"
|
|
local module_file=$(find_module "$module_name")
|
|
|
|
if [ -z "$module_file" ]; then
|
|
warn "Cannot copy module, file not found: $module_name"
|
|
return 1
|
|
fi
|
|
|
|
# Determine target subdirectory based on module path
|
|
local rel_path=$(echo "$module_file" | sed "s|^$KERNEL_BUILD_DIR/||")
|
|
local target_dir="$MODULES_DIR/$(dirname "$rel_path")"
|
|
local target_file="$target_dir/$(basename "$module_file")"
|
|
|
|
# Create target directory
|
|
mkdir -p "$target_dir"
|
|
|
|
# Copy module
|
|
cp "$module_file" "$target_file"
|
|
log "Copied: $module_name -> $target_file"
|
|
}
|
|
|
|
# Parse command line arguments
|
|
while getopts "k:m:v:Vh" opt; do
|
|
case $opt in
|
|
k) KERNEL_BUILD_DIR="$OPTARG" ;;
|
|
m) MODULES_DIR="$OPTARG" ;;
|
|
v) KERNEL_VERSION="$OPTARG" ;;
|
|
V) VERBOSE=1 ;;
|
|
h) usage; exit 0 ;;
|
|
*) usage; exit 1 ;;
|
|
esac
|
|
done
|
|
|
|
shift $((OPTIND-1))
|
|
|
|
# Validate required parameters
|
|
if [ -z "$KERNEL_BUILD_DIR" ] || [ -z "$MODULES_DIR" ] || [ -z "$KERNEL_VERSION" ]; then
|
|
error "Missing required parameters. Use -h for help."
|
|
fi
|
|
|
|
if [ ! -d "$KERNEL_BUILD_DIR" ]; then
|
|
error "Kernel build directory not found: $KERNEL_BUILD_DIR"
|
|
fi
|
|
|
|
if [ $# -eq 0 ]; then
|
|
error "No modules specified. Use -h for help."
|
|
fi
|
|
|
|
# Parse module list (can be individual modules or a file containing module names)
|
|
REQUIRED_MODULES=()
|
|
for arg in "$@"; do
|
|
if [ -f "$arg" ]; then
|
|
# Read modules from file
|
|
log "Reading modules from file: $arg"
|
|
while IFS= read -r line; do
|
|
# Skip empty lines and comments
|
|
line=$(echo "$line" | sed 's/#.*//' | xargs)
|
|
if [ -n "$line" ]; then
|
|
REQUIRED_MODULES+=("$line")
|
|
fi
|
|
done < "$arg"
|
|
else
|
|
# Individual module name
|
|
REQUIRED_MODULES+=("$arg")
|
|
fi
|
|
done
|
|
|
|
if [ ${#REQUIRED_MODULES[@]} -eq 0 ]; then
|
|
error "No valid modules found to process"
|
|
fi
|
|
|
|
log "Processing ${#REQUIRED_MODULES[@]} required modules: ${REQUIRED_MODULES[*]}"
|
|
|
|
# Resolve dependencies for all required modules
|
|
echo "Resolving dependencies for: ${REQUIRED_MODULES[*]}"
|
|
for module in "${REQUIRED_MODULES[@]}"; do
|
|
echo "Processing: $module"
|
|
resolve_dependencies "$module" 0
|
|
done
|
|
|
|
# Report results
|
|
echo ""
|
|
echo "Dependency resolution complete!"
|
|
echo "Total modules required: ${#DEPENDENCY_ORDER[@]}"
|
|
echo ""
|
|
echo "Dependency order:"
|
|
for i in "${!DEPENDENCY_ORDER[@]}"; do
|
|
printf "%3d. %s\n" $((i+1)) "${DEPENDENCY_ORDER[$i]}"
|
|
done
|
|
|
|
# Copy all modules
|
|
echo ""
|
|
echo "Copying modules to: $MODULES_DIR"
|
|
mkdir -p "$MODULES_DIR"
|
|
|
|
COPIED_COUNT=0
|
|
FAILED_COUNT=0
|
|
|
|
for module in "${DEPENDENCY_ORDER[@]}"; do
|
|
if copy_module "$module"; then
|
|
((COPIED_COUNT++))
|
|
else
|
|
((FAILED_COUNT++))
|
|
fi
|
|
done
|
|
|
|
# Summary
|
|
echo ""
|
|
echo "Module installation summary:"
|
|
echo " Successfully copied: $COPIED_COUNT modules"
|
|
echo " Failed to copy: $FAILED_COUNT modules"
|
|
echo " Target directory: $MODULES_DIR"
|
|
|
|
if [ $FAILED_COUNT -gt 0 ]; then
|
|
exit 1
|
|
fi
|
|
|
|
echo ""
|
|
echo "All modules installed successfully!" |