409 lines
16 KiB
Markdown
409 lines
16 KiB
Markdown
# 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:
|
|
|
|
```
|
|
<data partition>/hiperiso/logs/<iso-basename>_<UTC-timestamp>/
|
|
```
|
|
|
|
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: phase<TAB>uptime<TAB>iso8601)
|
|
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:
|
|
|
|
```
|
|
<data partition>/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
|
|
```
|