#!/bin/sh set -e # Output directory (current working directory by default) OUTPUT_DIR="${1:-$(pwd)}" WORK_DIR="$OUTPUT_DIR/initramfs"
echo "Building initramfs in $OUTPUT_DIR..." # Detect architecture ARCH=$(uname -m) case "$ARCH" in x86_64) LD_ARCH="ld-linux-x86-64.so.2" ;; i386|i686) LD_ARCH="ld-linux.so.2" ;; aarch64) LD_ARCH="ld-linux-aarch64.so.1" ;; arm*) LD_ARCH="ld-linux-arm" ;; *) LD_ARCH="ld-linux" ;; esac # Find library path dynamically find_lib() { local libname="$1" # Search in common library locations for dir in /lib /lib64 /usr/lib /usr/lib64 /lib32; do if [ -f "$dir/$libname" ]; then echo "$dir/$libname" return 0 fi done # Use ldconfig to find library if command -v ldconfig >/dev/null 2>&1; then result=$(ldconfig -p 2>/dev/null | grep "$libname" | head -1 | awk '{print $NF}') if [ -n "$result" ]; then echo "$result" return 0 fi fi return 1 } # Copy a binary and all its required libraries copy_binary() { local src="$1" local dest_dir="$2" local bin_name=$(basename "$src")
# Resolve symlinks to get real binary if [ -L "$src" ]; then real_bin=$(readlink -f "$src" 2>/dev/null || echo "$src") else real_bin="$src" fi
mkdir -p "$dest_dir"
# Copy the binary cp "$real_bin" "$dest_dir/$bin_name"
# Copy libraries needed by this binary using ldd if command -v ldd >/dev/null 2>&1; then ldd "$real_bin" 2>/dev/null | grep -E '=>' | awk '{print $3}' | while read -r lib; do # Handle virtual libraries [ -z "$lib" ] && continue [ ! -f "$lib" ] && continue
lib_name=$(basename "$lib")
# Determine destination based on path case "$lib" in */lib64/*) mkdir -p "$dest_dir/lib64" lib_dest="$dest_dir/lib64" ;; */lib32/*) mkdir -p "$dest_dir/lib" lib_dest="$dest_dir/lib" ;; *) mkdir -p "$dest_dir/lib" lib_dest="$dest_dir/lib" ;; esac
# Avoid duplicate copies if [ ! -f "$lib_dest/$lib_name" ]; then cp "$lib" "$lib_dest/$lib_name" fi done fi } # Resolve command path resolve_cmd() { local cmd="$1" # Try command -v first, fall back to which if command -v "$cmd" >/dev/null 2>&1; then command -v "$cmd" elif command -v which >/dev/null 2>&1; then which "$cmd" 2>/dev/null fi } # 1. Create directory structure mkdir -p "$WORK_DIR"/bin "$WORK_DIR"/sbin "$WORK_DIR"/etc "$WORK_DIR"/proc mkdir -p "$WORK_DIR"/sys "$WORK_DIR"/dev "$WORK_DIR"/lib "$WORK_DIR"/lib64 "$WORK_DIR"/run # 2. List of required binaries (name:path format, one per line) # Format: name|path|destdir BINARIES=" bash|/bin/bash|bin sh|/bin/sh|bin ls|/usr/bin/ls|bin cat|/usr/bin/cat|bin echo|/usr/bin/echo|bin mkdir|/usr/bin/mkdir|bin switch_root|/usr/sbin/switch_root|sbin switch_root|/sbin/switch_root|sbin mount|/usr/bin/mount|bin umount|/usr/bin/umount|bin sleep|/usr/bin/sleep|bin " # 3. Copy binaries echo "$BINARIES" | while IFS='|' read -r name path destdir; do [ -z "$name" ] && continue resolved=$(resolve_cmd "$name")
if [ -n "$resolved" ] && [ -f "$resolved" ]; then echo "Copying $name from $resolved" copy_binary "$resolved" "$WORK_DIR/$destdir" else echo "Warning: $name not found, skipping" fi done # 4. Copy the dynamic linker copy_ld() { for pattern in /lib64/ld-linux*.so.* /lib/ld-linux*.so.* /lib/*/ld-linux*.so.*; do case "$pattern" in *\*) continue ;; esac if [ -f "$pattern" ]; then ld_name=$(basename "$pattern") mkdir -p "$WORK_DIR/lib64" cp "$pattern" "$WORK_DIR/lib64/$ld_name" # Create versioned symlink if [ -L "$pattern" ]; then target=$(readlink "$pattern") case "$target" in ld-*.so.*) ln -sf "$target" "$WORK_DIR/lib64/${target%.so.*}.so" 2>/dev/null || true ;; esac fi return 0 fi done return 1 } copy_ld # 5. Create init script cat > "$WORK_DIR/init" << 'INITEOF' #!/bin/sh echo "initramfs booting..." mount -t proc none /proc mount -t sysfs none /sys mount -t devtmpfs none /dev echo "Welcome to LKVM!" exec /bin/sh INITEOF chmod +x "$WORK_DIR/init" # 6. Package initramfs cd "$WORK_DIR" if command -v cpio >/dev/null 2>&1; then find . -print0 | cpio -o -H newc --null | gzip > "$OUTPUT_DIR/initramfs.cpio.gz" else echo "Error: cpio not found" exit 1 fi
if [ -f "$OUTPUT_DIR/initramfs.cpio.gz" ]; then size=$(ls -lh "$OUTPUT_DIR/initramfs.cpio.gz" | awk '{print $5}') echo "Done! initramfs.cpio.gz created: $size" else echo "Error: Failed to create initramfs.cpio.gz" exit 1 fi