# hiperiso A hypervisor-based ISO boot tool with full bootlogging — like Ventoy, but it boots ISOs inside a **KVM + QEMU** virtual machine and captures the entire boot (serial console, disk I/O, PCI/port I/O traces). The guest OS runs completely unmodified. ``` USB → GRUB2 → minimal Linux kernel (KVM built-in) + initramfs → QEMU (KVM accel) → OVMF UEFI → ISO boots as an emulated CD-ROM ``` ## How it differs from Ventoy Ventoy injects hooks into the booted OS (initrd patching, device-mapper, WIM patching, 60+ distro hooks). hiperiso instead presents the ISO as a native emulated AHCI CD-ROM to a KVM guest, so **no guest modification is needed** and the hypervisor has full visibility into every I/O operation. --- ## Prerequisites ### Build host - A Linux x86_64 machine with VT-x / AMD-V - Build tools: `gcc`, `g++`, `make`, `bc`, `flex`, `bison`, `cpio`, `gzip`, `wget`, `tar` - EDK2 build deps: `nasm`, `iasl` (acpica), `python3` - QEMU build deps: `ninja-build`, `pkg-config`, `libglib2.0-dev`, `libpixman-1-dev` - Kernel build deps: `libelf-dev`, `libssl-dev` - ~6 GB free disk for sources + build trees ### Install host (where you prepare the USB) - `sgdisk` (package `gdisk` / `gptfdisk`) - `dosfstools` (`mkfs.vfat`) - `exfatprogs` (`mkfs.exfat`) **or** `ntfs-3g` (`mkntfs`) - `grub2-efi-amd64` + `grub2-efi-amd64-modules` (provides `grub-install --target=x86_64-efi`) - `util-linux` (`findmnt`, `lsblk`) ### Target machine (the PC you boot from USB) - x86_64 with hardware virtualization (VT-x/AMD-V) **enabled in BIOS/UEFI** - UEFI boot mode (a Legacy/CSM path is planned, not in the MVP) --- ## Build ### 1. One-shot full build ```sh ./scripts/build_all.sh ``` This downloads sources, builds the kernel, QEMU, OVMF, GRUB2, the log tool, packs the initramfs, and assembles a distributable payload in `build/payload/`. Re-run later without re-downloading: ```sh SKIP_DOWNLOAD=1 ./scripts/build_all.sh ``` ### 2. Build individual components Each stage is a standalone script: ```sh ./scripts/download_sources.sh # fetch + extract kernel, qemu, edk2, grub2, busybox cd build/linux && cp ../../host/kernel/hiperiso_defconfig .config && make olddefconfig && make -j"$(nproc)" bzImage cd build/qemu && ../../scripts/configure_qemu.sh && make -j"$(nproc)" qemu-system-x86_64 cd build/edk2 && bash ../../firmware/build_ovmf.sh ``` Or use the provided Makefile: ```sh make all # kernel qemu ovmf grub2 initramfs hiperiso-log make dist # assemble build/payload/ make clean # remove build/ ``` ### 3. Output layout ``` build/payload/ ├── Hiperiso2Disk.sh ├── config/hiperiso.json.example └── EFI/ ├── BOOT/ │ ├── BOOTX64.EFI # GRUB2 (hiperiso module) │ └── grub.cfg └── hiperiso/ ├── vmlinuz # host kernel (KVM built-in) ├── initramfs.cpio.gz # busybox + qemu + init ├── OVMF.fd # guest UEFI firmware (SMM + Secure Boot) ├── hiperiso-log # log analysis tool └── trace/ # trace-*.events (standard/detailed/full) ``` --- ## Install to a USB drive > ⚠️ **This destroys all data on the target device.** Double-check the device name. ```sh lsblk # identify your USB, e.g. /dev/sdX sudo bash build/payload/Hiperiso2Disk.sh -I -g /dev/sdX ``` `Hiperiso2Disk.sh` defaults to MBR. Use `-g` for GPT. The standard Ventoy-style layout is: | # | Type | FS | Size | Contents | |---|--------|--------|--------|--------------------------------------------| | 1 | 0700 | exFAT | rest | Your ISOs + boot logs + config | | 2 | EF00 | FAT16 | 32 MB | ESP: GRUB2, kernel, initramfs, OVMF | Copy your ISOs: ```sh cp my_os.iso /media/$USER/HIPERISO/ISOs/ ``` Options: ```sh sudo bash Hiperiso2Disk.sh -i /dev/sdX # install sudo bash Hiperiso2Disk.sh -I -g /dev/sdX # force reinstall using GPT sudo bash Hiperiso2Disk.sh -i -L MYUSB /dev/sdX # custom data-partition label ``` --- ## Usage 1. Boot the PC from the USB (pick the **UEFI** entry). 2. GRUB2 lists ISOs found under `/ISOs/`. Select one. 3. GRUB2 boots the host kernel; the initramfs detects `/dev/kvm` and launches QEMU with the selected ISO attached as a CD-ROM. 4. The ISO's OS boots **unmodified** inside the VM. 5. On guest shutdown, logs are flushed to the data partition. ### View boot logs Every boot gets its own timestamped session directory so logs are never overwritten: ``` /hiperiso/logs/_/ ``` Mount the data partition on any machine and point the log tool at a session directory: ```sh hiperiso-log analyze /hiperiso/logs/ubuntu-24.04_20260629T101530Z/ hiperiso-log trace /hiperiso/logs/ubuntu-24.04_20260629T101530Z/trace.bin --format json hiperiso-log serial /hiperiso/logs/ubuntu-24.04_20260629T101530Z/serial.log --stages ``` Three files are guaranteed in every session directory, even when the boot fails before QEMU launches: ``` session.json # session manifest (structured metadata for agents) status.json # live status, rewritten at every stage transition env.txt # host environment snapshot (kernel, RAM, CPU, KVM, config) ``` The remaining files appear depending on how far the boot progressed: ``` serial.log # UART text (written by QEMU, Tier 1) trace.bin # QEMU simpletrace (Tier 2+, only when trace_level != none) qemu.cmdline # exact QEMU command line used monitor.sock # QEMU monitor socket (live introspection while guest runs) timing.dat # raw boot phase timing data (TSV: phaseuptimeiso8601) timing.json # structured boot timing with per-phase deltas (agent-friendly) hw/ # hardware inventory directory (see below) network.pcap # network packet capture (only when net_dump is enabled) report.json # generated analysis report (auto-run after QEMU exits) report.txt # human-readable report report.log # raw output from the analyze run analysis.meta # flat KEY=VALUE derived analysis sidecar HEARTBEAT # periodic liveness marker from the flush daemon SESSION_COMPLETE # sentinel, present when the session finished (success or failure) FAILURE.txt # human-readable failure summary (present only on failure) ``` ### Hardware inventory (`hw/`) Every session collects a comprehensive hardware inventory from both the host (initramfs kernel) and the guest (QEMU virtual machine). This data provides ground truth about exactly what hardware the guest OS sees — invaluable for OS development, driver writing, and agentic debugging. #### Host-side data (always present) Collected from `/proc` and `/sys` before QEMU launches. Describes the real hardware the initramfs kernel sees. ``` hw/ ├── host_cpuinfo.txt # full /proc/cpuinfo ├── host_meminfo.txt # full /proc/meminfo ├── host_interrupts.txt # /proc/interrupts ├── host_iomem.txt # /proc/iomem (physical memory map) ├── host_ioports.txt # /proc/ioports ├── host_cmdline.txt # /proc/cmdline ├── host_version.txt # /proc/version ├── host_diskstats.txt # /proc/diskstats ├── host_pci_devices.txt # /proc/bus/pci/devices ├── host_cpu_cache.txt # CPU cache topology (levels, sizes, sharing) ├── host_cpu_topology.txt # CPU core/socket/thread IDs ├── host_numa.txt # NUMA node topology ├── host_iommu.txt # IOMMU groups (VT-d/AMD-Vi) ├── host_kvm.txt # /dev/kvm presence ├── host_block.txt # block device info ├── host_usb.txt # USB device tree (vendor/product IDs) ├── host_dmi.txt # DMI/SMBIOS identifiers (board, BIOS, product) ├── host_efi.txt # EFI firmware info (if UEFI boot) ├── host_dmesg.txt # host kernel boot messages ├── host_kernel_config.gz # kernel .config (if /proc/config.gz available) ├── acpi/ # host ACPI tables (binary: DSDT, FACP, APIC, MCFG...) ├── smbios/ # host DMI/SMBIOS raw tables └── kvm_caps.json # KVM capabilities (module params: nested, ept, vpid...) ``` #### Guest-side data (present if QEMU ran ≥ 3 seconds) Collected via QEMU HMP monitor pipe. Describes the virtual hardware the guest OS sees. Not all files may be present — depends on QEMU version and configuration. ``` hw/ ├── qemu_version.txt # QEMU version string ├── qemu_qtree.txt # full QEMU device tree (buses, devices, properties) ├── qemu_pci.txt # PCI device list as seen by guest ├── qemu_cpuid.txt # CPUID leaves exposed to guest ├── qemu_memmap.txt # guest memory map (hierarchical view) ├── qemu_memmap_flat.txt # guest memory map (flat view, all regions) ├── qemu_ioapic.txt # IO-APIC interrupt routing state ├── qemu_lapic.txt # Local APIC state per vCPU ├── qemu_irq.txt # IRQ statistics (delivery counts) ├── qemu_registers.txt # CPU register snapshot (RAX-R15, RIP, flags, segments) ├── qemu_tlb.txt # TLB entries (TCG mode only) ├── qemu_numa.txt # guest NUMA topology ├── qemu_hpet.txt # HPET timer state ├── qemu_qomtree.txt # QOM object hierarchy ├── qemu_smbios.txt # SMBIOS table (if QEMU supports info smbios) ├── qemu_chardev.txt # QEMU character devices ├── qemu_block.txt # QEMU block devices (CD-ROM, disk, floppy) ├── qemu_net.txt # QEMU network devices ├── qemu_monitor_raw.txt # raw combined monitor output (all sections) └── pci_summary.json # structured PCI device list (bus/dev/fn, vendor/device IDs) ``` Host files are always present. QEMU files appear only if QEMU launched successfully and the guest ran long enough for the monitor commands to execute (3-second delay after QEMU start). ### Boot timing (`timing.json`) Records microsecond-precision timestamps at each boot phase transition using `/proc/uptime` as a monotonic clock. Lets agents and developers identify performance bottlenecks across the full hypervisor boot stack. ```json { "total_duration_s": 15.234, "phases": [ {"phase": "kernel_start", "uptime_s": 0.512, "timestamp_utc": "...", "delta_s": null}, {"phase": "session_created", "uptime_s": 2.341, "timestamp_utc": "...", "delta_s": 1.829}, {"phase": "env_written", "uptime_s": 2.520, "timestamp_utc": "...", "delta_s": 0.179}, {"phase": "kvm_checked", "uptime_s": 2.890, "timestamp_utc": "...", "delta_s": 0.370}, {"phase": "iso_verified", "uptime_s": 2.910, "timestamp_utc": "...", "delta_s": 0.020}, {"phase": "qemu_launching", "uptime_s": 3.001, "timestamp_utc": "...", "delta_s": 0.091}, {"phase": "qemu_started", "uptime_s": 3.102, "timestamp_utc": "...", "delta_s": 0.101}, {"phase": "qemu_exited", "uptime_s": 14.567, "timestamp_utc": "...", "delta_s": 11.465}, {"phase": "qemu_returned", "uptime_s": 14.570, "timestamp_utc": "...", "delta_s": 0.003}, {"phase": "report_done", "uptime_s": 15.200, "timestamp_utc": "...", "delta_s": 0.630}, {"phase": "session_finalized","uptime_s": 15.234, "timestamp_utc": "...", "delta_s": 0.034} ] } ``` `SESSION_COMPLETE` is the signal that the session finished and all logs were flushed. If it is absent, check `status.json` for the last known stage and `HEARTBEAT` to see whether the flush daemon was still alive. For cross-session ingestion, hiperiso also appends one compact JSON object per session to: ``` /hiperiso/logs/index.jsonl ``` The session manifest (`session.json`) is written when the session starts and rewritten at the end as the canonical final manifest. For the live in-progress state, read `status.json`: ```json { "session_id": "ubuntu-24.04_20260629T101530Z", "status": "started", "iso_path": "/ISOs/ubuntu-24.04-desktop-amd64.iso", "iso_basename": "ubuntu-24.04-desktop-amd64.iso", "log_dir": "/hiperiso/logs/ubuntu-24.04_20260629T101530Z", "start_time_utc": "2026-06-29T10:15:30Z", "kvm": "available", "trace_level": "standard", "guest_ram_mb": 2048, "guest_cpus": 2 } ``` The final manifest (rewritten at session end) adds `end_time_utc`, `result`, `qemu_exit_code`, `report_available`, `host` (CPU model, RAM, virt support), `analysis` (boot result, failure domain, error count, timing), and `hw_inventory` (list of collected hardware data files). ### Fallback mode If `/dev/kvm` is absent (virtualization disabled) and `hiperiso_fallback` is not set, hiperiso captures a failure session rather than launching a guest. The session directory still gets `session.json`, `status.json`, and `env.txt`, plus a `FAILURE.txt` explaining what went wrong, and the analysis report is generated. Set `hiperiso_fallback=1` to force TCG software emulation instead: the ISO boots (very slowly) with full logging enabled. --- ## Configuration Edit `/hiperiso/hiperiso.json` on the **data partition** (copied from `config/hiperiso.json.example`). See **[config/README.md](config/README.md)** for every option. Highlights: ```jsonc { "control": { "default_ram": 2048, "default_trace_level": "standard" }, "iso_overrides": { "*./windows11*.iso": { "ram": 4096, "tpm": true, "cpu_features": ["vmx"] } } } ``` Trace tiers: `standard` (serial + disk I/O), `detailed` (+ PCI/port I/O), `full` (+ every MMIO access — very slow, debug only). Network capture: set `"net_dump": true` in `control_ext` or per-ISO in `iso_overrides` to capture all guest network traffic as a pcap file (`network.pcap` in the session directory). Adds a virtio-net-pci device to the guest and a QEMU filter-dump. --- ## Troubleshooting **`/dev/kvm` missing → "Falling back to direct boot mode."** Enable VT-x/AMD-V in the host BIOS/UEFI. hiperiso then uses hypervisor mode with full logging. Disabling Secure Boot on the host may also be required. **Guest boots to OVMF shell or hangs.** - Ensure the ISO is a valid hybrid/UEFI-bootable image. - Try `trace_level: detailed` and inspect `serial.log` for the failure point. - Windows 11 ISOs need `tpm: true` and a `swtpm` socket — see `config/iso_overrides/windows11.json`. **USB not booting.** - Boot in **UEFI mode** (not Legacy/CSM). - Re-run the installer and confirm `EFI/BOOT/BOOTX64.EFI` exists on the ESP. - Some firmums need the USB entry added manually via the boot menu (F12/F8). **`grub-install failed`.** Install `grub2-efi-amd64` and `grub2-efi-amd64-modules` (Debian/Ubuntu) or `grub2-efi-x64` + `grub2-efi-x64-modules` (Fedora/RHEL). **Build: OVMF step fails.** Install `nasm`, `iasl` (acpica-tools), `python3`, and run from inside `build/edk2`. The script builds EDK2 BaseTools first; ensure `make` and a recent GCC (GCC5 toolchain = GCC 5+) are present. **QEMU configure complains about missing deps.** Install `ninja-build`, `libglib2.0-dev`, `libpixman-1-dev`, `pkg-config`. --- ## Project layout ``` hiperiso/ ├── scripts/ # build_all, download_sources, configure_qemu, build_initramfs ├── host/kernel/ # hiperiso_defconfig (minimal KVM kernel) ├── host/initramfs/ # init scripts (separate task) ├── firmware/ # build_ovmf.sh ├── grub2/ # GRUB2 hiperiso module (separate task) ├── logging/ # trace-*.events + hiperiso-log tool (separate task) ├── installer/ # Hiperiso2Disk.sh ├── config/ # hiperiso.json.example + per-ISO overrides ├── Makefile └── INTERFACES.sh # single source of truth for all interfaces ```