Files
hiperiso/host/initramfs/init
T
vasilito 4325590686 Add host kernel config and initramfs scripts with P0-P3 hardware inventory
Includes: init (PID 1), hiperiso-lib.sh, qemu_launch.sh, hw_collect.sh,

kvm_check.sh, fallback_boot.sh, log_flush.sh, conf_replace.sh, make_floppy.sh.

13-phase boot timing, 18 QEMU HMP commands, network pcap capture.
2026-06-30 14:30:39 +03:00

271 lines
9.2 KiB
Bash
Executable File

#!/bin/sh
# ============================================================
# init -- PID 1 for the hiperiso hypervisor host initramfs
#
# Boots a selected ISO as a KVM guest with full bootlogging.
# Kernel cmdline parameters (see INTERFACES.sh):
# hiperiso_iso="/ISOs/ubuntu.iso"
# hiperiso_log="/hiperiso/logs/ubuntu/"
# hiperiso_trace_level="standard|detailed|full|none"
# hiperiso_ram=2048 hiperiso_cpus=2
# hiperiso_display="none|gtk|vnc"
# hiperiso_vga="std|none|virtio"
# hiperiso_fallback="1"
# ============================================================
PATH="/usr/bin:/bin:/usr/sbin:/sbin"
export PATH
# ── Step 1: Mount essential virtual filesystems ──────────────
mkdir -p /proc /sys /dev /tmp /run
mount -t proc proc /proc 2>/dev/null
mount -t sysfs sysfs /sys 2>/dev/null
mount -t devtmpfs devtmpfs /dev 2>/dev/null || mount -t tmpfs tmpfs /dev 2>/dev/null
mount -t tmpfs tmpfs /tmp 2>/dev/null
mount -t tmpfs tmpfs /run 2>/dev/null
. /hiperiso-lib.sh
_INIT_UPTIME=$(cut -d' ' -f1 /proc/uptime 2>/dev/null)
printf '\n'
printf '======================================================\n'
printf ' hiperiso hypervisor host -- KVM ISO boot logger \n'
printf '======================================================\n'
printf '\n'
# ── Step 2: Parse kernel command line ────────────────────────
hiperiso_parse_cmdline
if [ -z "$HIPERISO_ISO_PATH" ]; then
printf '[hiperiso] FATAL: hiperiso_iso= not set on kernel command line\n'
printf '[hiperiso] Dropping to recovery shell\n'
exec /bin/sh
fi
hiperiso_log "ISO path: $HIPERISO_ISO_PATH"
hiperiso_log "Log dir: $HIPERISO_LOG_DIR"
hiperiso_log "Trace: ${HIPERISO_TRACE_LEVEL:-standard}"
hiperiso_log "RAM: ${HIPERISO_GUEST_RAM:-2048} MB"
hiperiso_log "CPUs: ${HIPERISO_GUEST_CPUS:-2}"
# ── Step 3: Find and mount the USB data partition ────────────
DATA_PART=$(hiperiso_find_usb_partition)
if [ -z "$DATA_PART" ]; then
hiperiso_log "FATAL: Could not find hiperiso USB data partition"
hiperiso_log "Scanned: blkid label, /dev/sd[abcd]2, sysfs"
exec /bin/sh
fi
hiperiso_log "Data partition: $DATA_PART"
mkdir -p "$DATA_MOUNT"
_mounted=0
for _fstype in exfat ntfs3 ntfs vfat ext4 ext3 ext2; do
if mount -t "$_fstype" "$DATA_PART" "$DATA_MOUNT" 2>/dev/null; then
hiperiso_log "Mounted $DATA_PART at $DATA_MOUNT (type: $_fstype)"
_mounted=1
break
fi
done
if [ "$_mounted" -eq 0 ]; then
if mount "$DATA_PART" "$DATA_MOUNT" 2>/dev/null; then
hiperiso_log "Mounted $DATA_PART at $DATA_MOUNT (auto-detected)"
_mounted=1
fi
fi
if [ "$_mounted" -eq 0 ]; then
hiperiso_log "FATAL: Failed to mount $DATA_PART"
exec /bin/sh
fi
# ── Step 4: Mount the EFI System Partition (for OVMF) ────────
ESP_PART=$(printf '%s' "$DATA_PART" | sed 's/1$/2/')
if [ ! -e "$ESP_PART" ]; then
for _d in /dev/sda2 /dev/sdb2 /dev/sdc2 /dev/sdd2 /dev/sde2 /dev/sdf2 /dev/nvme0n1p2 /dev/nvme1n1p2 /dev/mmcblk0p2; do
if [ -e "$_d" ]; then
ESP_PART="$_d"
break
fi
done
fi
mkdir -p "$EFI_MOUNT"
if mount -t vfat "$ESP_PART" "$EFI_MOUNT" 2>/dev/null; then
hiperiso_log "Mounted ESP $ESP_PART at $EFI_MOUNT"
else
hiperiso_log "WARNING: Could not mount ESP $ESP_PART -- OVMF may be unavailable"
fi
# ── Step 5: Resolve absolute paths and create log dir ────────
# Derive a unique per-session directory with UTC timestamp so
# every boot gets its own log set (no overwriting).
HIPERISO_LOG_DIR=$(hiperiso_derive_session_dir "$HIPERISO_LOG_DIR")
export HIPERISO_LOG_DIR
LOG_DIR="${DATA_MOUNT}${HIPERISO_LOG_DIR}"
ISO_PATH="${DATA_MOUNT}${HIPERISO_ISO_PATH}"
OVMF_FULL_PATH="${EFI_MOUNT}${OVMF_PATH}"
# Collision-safe: if session dir already exists (e.g. same-second boot),
# append an incrementing suffix so logs are never overwritten.
if [ -d "$LOG_DIR" ]; then
_i=2
while [ -d "${LOG_DIR%/}_${_i}" ]; do
_i=$((_i + 1))
done
LOG_DIR="${LOG_DIR%/}_${_i}/"
HIPERISO_LOG_DIR="${HIPERISO_LOG_DIR%/}_${_i}/"
fi
mkdir -p "$LOG_DIR"
export LOG_DIR ISO_PATH OVMF_FULL_PATH EFI_MOUNT DATA_MOUNT
# ── Record early timing marks retroactively ──────────────────
# These phases elapsed before LOG_DIR existed; capture them now
# using the uptime values saved at each checkpoint.
printf 'kernel_start\t%s\t%s\n' "${_INIT_UPTIME:-0}" "$(hiperiso_utc_iso)" >> "${LOG_DIR}/timing.dat"
hiperiso_timing_mark "session_created"
hiperiso_log "Session dir: $HIPERISO_LOG_DIR"
# ── Step 6: Write session metadata and environment snapshot ──
hiperiso_write_session_meta "started"
hiperiso_write_status "running" "mounted"
hiperiso_write_env
hiperiso_timing_mark "env_written"
# ── Step 7: KVM detection ────────────────────────────────────
KVM_RESULT=$(/kvm_check.sh)
printf 'KVM_CHECK_RESULT=%s\n' "$KVM_RESULT" >> "${LOG_DIR}/env.txt"
case "$KVM_RESULT" in
KVM_OK)
hiperiso_log "KVM available -- proceeding with hypervisor boot"
export KVM_AVAILABLE=1
export KVM_STATUS="available"
hiperiso_write_status "running" "kvm_ok"
;;
KVM_FAIL:*)
hiperiso_log "KVM check failed: ${KVM_RESULT#KVM_FAIL:}"
export KVM_AVAILABLE=0
export KVM_STATUS="unavailable"
if [ "$HIPERISO_FALLBACK" != "1" ]; then
hiperiso_write_status "failed" "fallback_no_kvm"
/fallback_boot.sh
exec /bin/sh
fi
hiperiso_log "Fallback forced -- continuing with TCG emulation"
hiperiso_write_status "running" "tcg_emulation"
;;
esac
hiperiso_timing_mark "kvm_checked"
# ── Step 8: Verify ISO exists ────────────────────────────────
if [ ! -f "$ISO_PATH" ]; then
hiperiso_log "FATAL: ISO file not found: $ISO_PATH"
hiperiso_log "Contents of $DATA_MOUNT:"
ls -la "$DATA_MOUNT" 2>/dev/null >> "${LOG_DIR}/env.txt"
hiperiso_write_status "failed" "iso_not_found"
hiperiso_run_report
hiperiso_finalize_session "failed" "" "iso_not_found"
exec /bin/sh
fi
hiperiso_log "ISO found: $ISO_PATH"
hiperiso_timing_mark "iso_verified"
# ── Step 8b: Run conf_replace plugin (if configured) ─────────
_modified_iso=$(sh /conf_replace.sh 2>"${LOG_DIR}/conf_replace.log" || true)
if [ -n "$_modified_iso" ] && [ -f "$_modified_iso" ]; then
ISO_PATH="$_modified_iso"
export ISO_PATH
hiperiso_log "Using modified ISO: $ISO_PATH"
fi
# ── Step 9: Start log flush daemon ───────────────────────────
rm -f /tmp/hiperiso_done
/log_flush.sh "$LOG_DIR" &
LOG_FLUSH_PID=$!
hiperiso_log "Log flush daemon started (PID $LOG_FLUSH_PID)"
hiperiso_write_status "running" "launching_qemu"
hiperiso_timing_mark "qemu_launching"
# ── Step 10: Launch QEMU ─────────────────────────────────────
/qemu_launch.sh
QEMU_EXIT_CODE=$?
# ── Step 11: Flush remaining logs ────────────────────────────
touch /tmp/hiperiso_done
hiperiso_timing_mark "qemu_returned"
_wait=0
while kill -0 "$LOG_FLUSH_PID" 2>/dev/null; do
_wait=$((_wait + 1))
if [ "$_wait" -gt 10 ]; then
kill "$LOG_FLUSH_PID" 2>/dev/null
break
fi
sleep 1
done
sync
printf 'QEMU_EXIT_CODE=%s\n' "$QEMU_EXIT_CODE" >> "${LOG_DIR}/env.txt"
hiperiso_write_status "running" "qemu_exited" "$QEMU_EXIT_CODE"
if [ "$QEMU_EXIT_CODE" -eq 0 ]; then
_session_status="complete"
_session_stage="session_complete"
else
_session_status="failed"
_session_stage="qemu_error"
fi
hiperiso_run_report
hiperiso_timing_mark "report_done"
hiperiso_finalize_session "$_session_status" "$QEMU_EXIT_CODE" "$_session_stage"
hiperiso_timing_mark "session_finalized"
hiperiso_timing_write_json
# ── Step 12: Print session summary ───────────────────────────
printf '\n'
printf '======================================================\n'
printf ' hiperiso boot session complete \n'
printf '======================================================\n'
printf ' ISO: %s\n' "$HIPERISO_ISO_PATH"
printf ' Session: %s\n' "$(hiperiso_session_id)"
printf ' QEMU exit: %s\n' "$QEMU_EXIT_CODE"
printf ' Logs: %s\n' "$LOG_DIR"
printf '======================================================\n'
printf '\n'
printf 'Log files:\n'
ls -la "$LOG_DIR" 2>/dev/null
printf '\n'
# ── Step 13: Offer reboot ────────────────────────────────────
printf 'Press ENTER to reboot, or type "shell" for recovery: '
read -r _response
case "$_response" in
shell|sh)
printf '\nDropping to recovery shell...\n'
exec /bin/sh
;;
esac
printf '\nRebooting...\n'
sync
if command -v reboot >/dev/null 2>&1; then
reboot -f
else
printf 'b' > /proc/sysrq-trigger 2>/dev/null
fi
# Kernel will panic if PID 1 exits -- but reboot should have fired
exec /bin/sh