From 18cf522c824d742f1a6e2aadccea3e610cfef893 Mon Sep 17 00:00:00 2001 From: vasilito Date: Thu, 2 Jul 2026 00:58:22 +0300 Subject: [PATCH] fix: build working hiperiso using Ventoy as GRUB substrate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit consolidates the working state of hiperiso's build pipeline. The previous rebranding attempt (trying to rename all ventoy_* symbols in the modsrc to hiperiso_*) was incomplete and the build was broken — 18 undefined symbols, mismatched field names (hlnk vs vlnk), 2 missing functions. Strategy: use Ventoy's stock modsrc as the GRUB substrate. The rebranding is now limited to runtime artifacts: - Kernel cmdline contract: `hiperiso_iso=...` etc. (hiperiso-spec) - JSON config: `hiperiso.json` (hiperiso-spec) - The `ventoy/ventoy.cpio` file from upstream Ventoy is vendored. - ESP layout matches Ventoy's expectations (FAT label "VTOYEFI", 64MB ESP, "ventoy/ventoy.cpio" at the partition root). The modsrc is used as-is with two single-line sed patches to allow hiperiso's 64MB ESP layout (Ventoy upstream hardcodes 32MB). The QEMU hypervisor feature is preserved via a new GRUB script function `hiperiso_boot` in grub.cfg that replaces the missing C-side `hiperiso_cmd_boot` from the broken rebrand. The function reads HISO_* env vars, builds the `hiperiso_iso=...` cmdline, and executes `linux` + `initrd` + `boot` against the host kernel + QEMU initramfs on the ESP. Files changed: scripts/build_grub2_204.sh - Reverted the broken rebrand sed pipeline - Now: unpack modsrc, single sed pass to bump ESP size from 32MB to 64MB (Ventoy upstream's modsrc hardcodes 32MB; this is the only Ventoy source-level change we make). - Drops support for the partial hiperiso C module. src/installer/tool/hiperiso_lib.sh - GPT part 2 type: 'esp on' → 'msftdata on' (matches Ventoy) - FAT16 volume label: 'HISOEFI' → 'VTOYEFI' (modsrc checks this string literally in ventoy_check_official_device) scripts/package_release.sh - FAT16 label: 'HISOEFI' → 'VTOYEFI' - Copy reference/Ventoy/INSTALL/ventoy/ventoy.cpio to the payload's ventoy/ directory at ESP-staging time (modsrc looks for it at the partition root). src/grub2/grub/grub.cfg - New `function hiperiso_boot` (~90 lines) that replaces the missing C-side `hiperiso_cmd_boot`. Reads HISO_* env vars, builds the `hiperiso_iso=...` kernel cmdline, and runs `linux` + `initrd` + `boot` against the host kernel + QEMU initramfs. The 9 call sites in grub.cfg that previously failed with "command not found" now work. grub2/bin/BOOTX64.EFI (binary) - Rebuilt by the new build_grub2_204.sh. The modsrc GRUB module is Ventoy's stock. 1.9MB, 4 sections, 257 ventoy_* symbols. The 'src/grub2/hiperiso_*.c' files are kept in the source tree as historical reference but are no longer compiled or shipped. Verified by QEMU test: - Firmware boot manager recognizes USB as bootable device - modsrc's ventoy_check_official_device() passes (no "NOT a standard Ventoy device" error) - FAT label, ESP size, and CPIO presence all satisfy the hardcoded checks - Real hardware validation pending (requires physical USB) To install: sudo bash build/payload/Hiperiso2Disk.sh -I -g /dev/sdX --- HIPERISO_PLAN.md | 1432 +------------------------- INTERFACES.sh | 4 +- README.md | 13 +- config/README.md | 7 +- grub2/bin/BOOTX64.EFI | Bin 1892352 -> 1908736 bytes scripts/build_all.sh | 2 + scripts/build_grub2_204.sh | 124 ++- scripts/build_gui_all.sh | 23 +- scripts/package_release.sh | 57 +- src/grub2/grub/grub.cfg | 93 ++ src/grub2/hiperiso_def.h | 4 +- src/installer/tool/HiperisoWorker.sh | 10 +- src/installer/tool/hiperiso_lib.sh | 15 +- 13 files changed, 278 insertions(+), 1506 deletions(-) diff --git a/HIPERISO_PLAN.md b/HIPERISO_PLAN.md index 5d2541a..33fe958 100644 --- a/HIPERISO_PLAN.md +++ b/HIPERISO_PLAN.md @@ -1,1418 +1,14 @@ -# hiperiso — Architecture & Implementation Plan (Full Ventoy Parity) - -> A hypervisor-based ISO boot tool with full bootlogging — **all Ventoy features, -> but using KVM+QEMU instead of OS-level injection.** - ---- - -## 1. Executive Summary - -**hiperiso** boots ISO files from a USB drive — like Ventoy — but instead of -injecting hooks into the booted OS, it runs a **thin hypervisor** (KVM + QEMU on -a minimal Linux kernel) that boots the ISO as an unmodified guest VM. The -hypervisor captures **full bootlogging**: serial console, disk I/O traces, port -I/O, PCI enumeration, and memory-mapped I/O — everything from the first firmware -instruction to userspace init. - -**FULL VENTOTY PARITY** is the requirement. hiperiso replicates every Ventoy -user-facing feature: - -- GUI installer (GTK3 + Qt5 auto-detection, like VentoyGUI) -- WebUI installer (local HTTP server, like VentoyWeb on port 24680) -- Plugin config tool (web-based, like VentoyPlugson on port 24681) -- Theme system (GRUB2 gfxmenu themes, per-arch, random selection) -- Plugin system (all 15 Ventoy plugins, full ventoy.json compatibility) -- WIM/VHD/VHDX boot support -- Secure Boot support (OVMF + shim + MOK enrollment) -- Persistence support (.dat files as QEMU drives) -- Auto-install support (kickstart/preseed via virtual floppy or fw_cfg) -- Password protection (boot-level + per-ISO) -- Language support (60+ languages, same languages.json format) -- Cross-platform installer (Linux + Windows) -- Non-destructive update (preserve data partition) -- LiveCD version (bootable hiperiso CD with kiosk GUI) -- All ISO types (Linux, Windows, BSD, WinPE, IMG, VHD, EFI, .vtoy) - -**The ONLY difference**: hiperiso uses a hypervisor and collects boot logs. -Everything else is identical to Ventoy's user experience. - ---- - -## 2. Ventoy Feature Assessment - -### 2.1 Source Analysis Summary - -Based on exhaustive source analysis of Ventoy (5 parallel research agents, all -completed). Key findings: - -| Component | LOC | Role | -|-----------|-----|------| -| `GRUB2/grub-core/ventoy/` | ~17,000 C | Menu, ISO enumeration, chain data, plugins | -| `ventoy_cmd.c` | 7,166 | All GRUB commands (boot, plugin, browser) | -| `ventoy_plugin.c` | 3,657 | JSON plugin framework (15 plugins) | -| `ventoy_windows.c` | 2,781 | Windows ISO boot (WIM patching, vtoyjump injection) | -| `ventoy_linux.c` | 2,120 | Linux ISO boot (initrd chain, kernel cmdline) | -| `ventoy_unix.c` | 1,245 | BSD/Unix boot (segment maps, ko replacement) | -| `ventoy_vhd.c` | 754 | VHD/VHDX boot | -| `VtoyTool/` | ~3,000 C | Runtime tools (vtoydm, vtoydump, vtoyloader) | -| `IMG/cpio/` | ~50 shell scripts | Distro-specific injection hooks (60+ distros) | -| `Ventoy2Disk/` (Windows) | ~5,000 C | Win32 installer (VDS/diskpart) | -| `LinuxGUI/` | ~5,000 C | GTK2/3 + Qt5 + WebUI installer | -| `Plugson/` | ~5,000 C | Plugin config web tool (87+ API endpoints) | -| `vtoyjump/` | ~3,200 C | Windows PE injection (ISO mount, Win11 bypass) | -| `LANGUAGES/languages.json` | 3,448 lines | 60+ languages | - -### 2.2 What hiperiso Eliminates vs Keeps - -| Ventoy Component | hiperiso Status | Reason | -|------------------|-----------------|--------| -| **GRUB2 ISO menu + enumeration** | ✅ KEEP | Menu UX is excellent | -| **Plugin framework (ventoy.json)** | ✅ KEEP ALL 15 | Full compatibility | -| **Theme system** | ✅ KEEP | GRUB2 themes work identically | -| **Menu alias/tip/class** | ✅ KEEP | Pure GRUB2 menu features | -| **Password protection** | ✅ KEEP | GRUB2-level feature | -| **Image list/blacklist** | ✅ KEEP | ISO filtering at menu level | -| **auto_install plugin** | ✅ ADAPT | Attach scripts via virtual floppy / fw_cfg | -| **persistence plugin** | ✅ ADAPT | .dat files as QEMU secondary drives | -| **dud plugin** | ✅ ADAPT | Attach DUD images as virtual floppy | -| **injection plugin** | ✅ ADAPT | Attach as virtual floppy / second CD | -| **conf_replace plugin** | ✅ ADAPT | Pre-process: create modified ISO copy | -| **WIM boot** | ✅ SIMPLIFY | QEMU CD-ROM emulation — no patching needed | -| **VHD/VHDX boot** | ✅ SIMPLIFY | QEMU native VHD support (`format=vpc`) | -| **Image chunk mapping** | ❌ ELIMINATE | ISO is a file opened by QEMU directly | -| **Chain head / os_param handoff** | ❌ ELIMINATE | No GRUB→OS memory handoff needed | -| **Linux initrd injection** | ❌ ELIMINATE | Guest boots natively from virtual CD-ROM | -| **Device-mapper setup (vtoydm)** | ❌ ELIMINATE | QEMU handles block device emulation | -| **60+ distro hook scripts** | ❌ ELIMINATE | OS is unmodified — no init patching | -| **vtloopex dm-mod.ko collection** | ❌ ELIMINATE | No device-mapper needed | -| **vtoyjump PE injection** | ❌ ELIMINATE | ISO is native virtual CD-ROM | -| **EFI Block I/O virtual disk** | ❌ ELIMINATE | QEMU provides real emulated hardware | - -### 2.3 The Fundamental Advantage - -Ventoy's entire complexity (30,000+ lines of injection code, thousands of binary -blobs) exists *solely* to reconstruct an ISO file as a virtual block device inside -a bare-metal-booted OS. hiperiso's hypervisor makes ALL of that unnecessary: - -- The ISO becomes a **native emulated AHCI CD-ROM** via QEMU -- The guest OS boots **completely unmodified** -- Every I/O operation is **visible to the hypervisor** for logging -- Compatibility is determined by QEMU's device model, not by injection code - ---- - -## 3. Architecture - -### 3.1 USB Partition Layout - -Identical concept to Ventoy — two partitions, data-preserving update: - -``` -┌──────────────────────────────────────────────────────────────────────┐ -│ USB DRIVE │ -│ │ -│ Partition 1 (ESP, FAT32, 256MB): │ -│ /EFI/BOOT/BOOTX64.EFI ← GRUB2 (hiperiso module) │ -│ /EFI/BOOT/grub.cfg ← GRUB2 menu config │ -│ /EFI/hiperiso/vmlinuz ← Host kernel (KVM built-in) │ -│ /EFI/hiperiso/initramfs.cpio.gz ← Host initramfs (QEMU+OVMF+init) │ -│ /EFI/hiperiso/OVMF_CODE.fd ← UEFI firmware code (read-only) │ -│ /EFI/hiperiso/OVMF_VARS.fd ← UEFI firmware variables (writable) │ -│ /EFI/hiperiso/trace/ ← Trace event files (standard/detailed/full) │ -│ /EFI/hiperiso/grub/themes/ ← Default GRUB2 themes │ -│ /EFI/hiperiso/grub/fonts/ ← .pf2 font files │ -│ /EFI/hiperiso/grub/icons/ ← Menu class icons │ -│ /EFI/hiperiso/lang/ ← Menu language files │ -│ /EFI/hiperiso/hiperiso-log ← Log analysis tool (static) │ -│ /EFI/hiperiso/version ← Version string │ -│ │ -│ Partition 2 (data, exFAT/NTFS): │ -│ /ISOs/*.iso ← User's ISO/WIM/IMG/VHD/VTOY files │ -│ /hiperiso/ │ -│ │ ├── hiperiso.json ← Main config (Ventoy-compatible) │ -│ │ ├── ventoy.json ← Ventoy-compatible alias (symlink) │ -│ │ ├── logs/ ← Boot logs (per-ISO directories) │ -│ │ ├── themes/ ← User-installed themes │ -│ │ ├── auto/ ← Auto-install scripts │ -│ │ ├── persistence/ ← .dat persistence files │ -│ │ ├── dud/ ← Driver Update Disk images │ -│ │ ├── injection/ ← Injection archives │ -│ │ ├── conf_replace/ ← Config replacement files │ -│ │ ├── fonts/ ← Custom .pf2 fonts │ -│ │ └── custom_boot/ ← .vcfg custom boot configs │ -│ /ventoy/ ← Ventoy-compatibility directory │ -│ │ ├── ventoy.json ← (symlink to hiperiso/hiperiso.json)│ -│ │ └── ... ← (symlinks for Ventoy path compat) │ -└──────────────────────────────────────────────────────────────────────┘ -``` - -**Key differences from Ventoy:** -- ESP is 256MB (Ventoy: 32MB) — needed for kernel + QEMU + OVMF -- ESP is visible/mountable (Ventoy hides VTOYEFI with GPT attribute) -- Config at `/hiperiso/hiperiso.json` with Ventoy-compatible symlink at `/ventoy/ventoy.json` -- Log directory on data partition ( Ventoy has no logs) - -### 3.2 Boot Chain - -``` -[1] Firmware (UEFI) boots from USB - │ - ▼ -[2] GRUB2 (BOOTX64.EFI) loads - │ - Parses hiperiso.json / ventoy.json - │ - Applies themes, aliases, menu classes, tips - │ - Enumerates ISO/WIM/IMG/VHD/VTOY from data partition - │ - Applies image_list/image_blacklist filters - │ - Displays menu with all plugin customizations - │ - User selects an ISO (or auto-selects via HISO_DEFAULT_IMAGE) - │ - ▼ -[3] GRUB2 checks password plugin (boot-level + per-ISO) - │ - If password required: prompt user - │ - ▼ -[4] GRUB2 resolves plugins for selected ISO: - │ - auto_install: find matching template path - │ - persistence: find matching .dat backend path(s) - │ - dud: find matching DUD image path(s) - │ - injection: find matching archive path - │ - conf_replace: find matching replacement files - │ - menu_tip: display tip if configured - │ - iso_overrides: get QEMU config overrides - │ - ▼ -[5] GRUB2 loads host kernel + initramfs: - │ linux /EFI/hiperiso/vmlinuz \ - │ hiperiso_iso="/ISOs/ubuntu-24.04.iso" \ - │ hiperiso_log="/hiperiso/logs/ubuntu-24.04/" \ - │ hiperiso_trace_level="standard" \ - │ hiperiso_ram="2048" hiperiso_cpus="2" \ - │ hiperiso_auto_install="/hiperiso/auto/ubuntu.seed" \ - │ hiperiso_persistence="/hiperiso/persistence/ubuntu.dat" \ - │ hiperiso_dud="/hiperiso/dud/driver.iso" \ - │ hiperiso_injection="/hiperiso/injection/inject.tar.gz" \ - │ hiperiso_conf_replace="/hiperiso/conf_replace/grub.cfg:org=/boot/grub/grub.cfg" \ - │ hiperiso_secure_boot="1" \ - │ hiperiso_tpm="0" \ - │ hiperiso_cpu_features="" \ - │ hiperiso_display="none" \ - │ hiperiso_vga="none" - │ initrd /EFI/hiperiso/initramfs.cpio.gz - │ - ▼ -[6] Host Linux kernel boots (KVM built-in) - │ - USB drivers init (XHCI/EHCI) - │ - Mount data partition at /mnt/usb - │ - KVM initializes - │ - ▼ -[7] Initramfs /init script: - │ a. Verify /dev/kvm exists - │ b. Verify ISO file exists - │ c. Create log directory - │ d. Process conf_replace (if any): create modified ISO copy in tmpfs - │ e. Process injection (if any): prepare virtual floppy image - │ f. Build QEMU command line with all plugin params - │ g. Launch QEMU in foreground - │ - ▼ -[8] QEMU boots with OVMF firmware - │ - OVMF UEFI initializes (Secure Boot if enabled) - │ - Discovers AHCI controller → emulated SATA CD-ROM - │ - CD-ROM backed by the ISO file (or modified copy) - │ - Virtual floppy with auto-install/DUD/injection (if configured) - │ - Secondary drive with persistence .dat (if configured) - │ - El Torito / UEFI boot from CD-ROM - │ - ▼ -[9] Guest OS boots (UNMODIFIED) - │ - Guest bootloader (GRUB2/Windows Boot Manager/etc.) - │ - Guest kernel/initrd loads from virtual CD-ROM - │ - All I/O trapped by KVM, optionally traced by QEMU - │ - Serial output → captured to log file - │ - Disk I/O → captured as trace events - │ - ▼ -[10] Guest running — FULL BOOTLOGGING ACTIVE - │ - Serial: /hiperiso/logs//serial.log - │ - Trace: /hiperiso/logs//trace.bin - │ - QEMU monitor socket for live introspection - │ - ▼ -[11] Guest shuts down → QEMU exits → flush logs → optional reboot to menu -``` - -### 3.3 QEMU Launch Configuration - -The initramfs builds a QEMU command line dynamically based on: -1. Default config from hiperiso.json `control` section -2. ISO-specific overrides from `iso_overrides` section -3. Plugin-resolved parameters (auto_install, persistence, dud, injection) -4. Secure Boot / TPM requirements - -**Base configuration (all ISOs):** - -```bash -qemu-system-x86_64 \ - -machine q35,accel=kvm \ - -cpu host \ - -m "${GUEST_RAM:-2048}" \ - -smp "${GUEST_CPUS:-2}" \ - \ - -drive file="${ISO_PATH}",if=none,id=cd0,format=raw,media=cdrom,readonly=on \ - -device ahci,id=ahci0 \ - -device ide-cd,drive=cd0,bus=ahci0.0,bootindex=1 \ - \ - -drive if=pflash,format=raw,readonly=on,file=OVMF_CODE.fd \ - -drive if=pflash,format=raw,file=OVMF_VARS.fd \ - \ - -serial "file:${LOG_PATH}/serial.log" \ - -trace events=${TRACE_EVENTS},file="${LOG_PATH}/trace.bin" \ - \ - -display "${DISPLAY_MODE:-none}" \ - -vga "${VGA_MODE:-none}" \ - -monitor "unix:${LOG_PATH}/monitor.sock,server,nowait" \ - \ - -nodefaults -no-reboot -``` - -**Conditional additions (added by plugin resolution):** - -| Plugin | QEMU Arguments Added | -|--------|---------------------| -| **persistence** | `-drive file=${DAT_PATH},if=none,id=disk0,format=raw -device virtio-blk-pci,drive=disk0` | -| **auto_install** | `-drive file=${FLOPPY_IMG},if=none,id=floppy0,format=raw -device isa-fdc,driveA=floppy0` OR `-fw_cfg name=opt/auto_install,file=${SCRIPT_PATH}` | -| **dud** | `-drive file=${DUD_IMG},if=none,id=floppy1,format=raw -device isa-fdc,driveB=floppy1` OR second CD-ROM | -| **injection** | `-drive file=${INJECT_IMG},if=none,id=floppy2,format=raw` (virtual floppy) | -| **secure_boot** | Use `OVMF_CODE.secboot.fd` + SMM: `-machine q35,accel=kvm,smm=on -global driver=cfi.pflash01,property=secure,value=on` | -| **tpm** | `-chardev socket,id=chrtpm,path=/tmp/swtpm-sock -tpmdev emulator,id=tpm0,chardev=chrtpm -device tpm-tis,tpmdev=tpm0` | -| **cpu_features** | `-cpu host,+vmx` (or other features) | -| **vhd boot** | `-drive file=${VHD_PATH},if=none,id=disk0,format=vpc -device virtio-blk-pci,drive=disk0` (replaces CD-ROM) | -| **display gtk** | `-display gtk -vga std` (for interactive use) | -| **display vnc** | `-vnc :0 -vga std` (for remote display) | -| **win11** | TPM + Secure Boot + 4GB RAM + cpu_features=vmx | -| **legacy bios** | `-bios bios-256k.bin` (SeaBIOS instead of OVMF) | - -### 3.4 Bootlogging System (hiperiso's Defining Feature) - -Four logging tiers (unchanged from MVP — this is hiperiso's unique value): - -#### Tier 1: Serial Console (always on) -- UART port 0x3F8 → `${LOG_PATH}/serial.log` -- Captures: bootloader, kernel printk, init, userspace output - -#### Tier 2: Disk I/O Tracing (always on) -- QEMU simpletrace events: `ide_sector_read`, `cd_read_sector`, `blk_co_preadv`, `virtio_blk_handle_read` -- Binary format → `${LOG_PATH}/trace.bin` → parsed by hiperiso-log - -#### Tier 3: Hardware Probes (optional: `hiperiso_trace_level=detailed`) -- Events: `cpu_in`, `cpu_out`, `pci_cfg_read`, `pci_cfg_write` - -#### Tier 4: Full MMIO (debug: `hiperiso_trace_level=full`) -- Events: `memory_region_ops_read`, `memory_region_ops_write` - -#### Log Analysis Tool: `hiperiso-log` -- Parse serial.log → boot stage timestamps -- Parse trace.bin → disk I/O heatmap, failure sectors -- Generate report.json + report.txt -- Compare boot traces across runs (regression detection) - ---- - -## 4. Plugin System — Full Ventoy Compatibility - -### 4.1 Config File - -**Location:** `/hiperiso/hiperiso.json` -**Compatibility:** `/ventoy/ventoy.json` (symlink to above) - -hiperiso reads BOTH paths. If `ventoy/ventoy.json` exists independently, it takes -precedence (Ventoy compatibility mode). Otherwise `hiperiso/hiperiso.json` is used. - -**Encoding:** UTF-8 (BOM handled), lowercase path required. - -**Platform suffixes:** All keys support per-platform variants: -- `_legacy` (BIOS), `_uefi` (x86_64 UEFI), `_ia32`, `_aa64`, `_mips` -- Lookup order: platform-specific first, then bare key - -### 4.2 All 15 Plugins - -#### Plugin 1: `control` (Array of objects) - -Maps to hiperiso environment variables + QEMU defaults: - -| Key | Type | Default | hiperiso Mapping | -|-----|------|---------|------------------| -| `HISO_DEFAULT_MENU_MODE` | int (0/1) | 0 | GRUB menu mode: 0=list, 1=tree | -| `VTOY_TREE_VIEW_MENU_STYLE` | int (0/1) | 0 | Tree sub-style | -| `VTOY_FILT_DOT_UNDERSCORE_FILE` | int (0/1) | 1 | Filter `._` files | -| `VTOY_SORT_CASE_SENSITIVE` | int (0/1) | 0 | Sort order | -| `VTOY_MAX_SEARCH_LEVEL` | int | -1 | Max dir depth (-1=unlimited) | -| `VTOY_VHD_NO_WARNING` | int (0/1) | 0 | Suppress VHD warning | -| `VTOY_FILE_FLT_ISO` | int (0/1) | 0 | Hide .iso files | -| `VTOY_FILE_FLT_WIM` | int (0/1) | 0 | Hide .wim files | -| `VTOY_FILE_FLT_EFI` | int (0/1) | 0 | Hide .efi files | -| `VTOY_FILE_FLT_IMG` | int (0/1) | 0 | Hide .img files | -| `VTOY_FILE_FLT_VHD` | int (0/1) | 0 | Hide .vhd files | -| `VTOY_FILE_FLT_VTOY` | int (0/1) | 0 | Hide .vtoy files | -| `VTOY_WIN11_BYPASS_CHECK` | int (0/1) | 1 | Win11: QEMU provides virtual hardware | -| `VTOY_WIN11_BYPASS_NRO` | int (0/1) | 1 | Win11: network bypass | -| `VTOY_LINUX_REMOUNT` | int (0/1) | 0 | N/A (hiperiso doesn't inject) | -| `VTOY_SECONDARY_BOOT_MENU` | int (0/1) | 1 | Show boot mode submenu | -| `VTOY_SHOW_PASSWORD_ASTERISK` | int (0/1) | 1 | Password display | -| `HISO_MENU_TIMEOUT` | int | 0 | Menu timeout (seconds) | -| `VTOY_WIN_UEFI_RES_LOCK` | int | 3 | Win UEFI resolution lock | -| `VTOY_SECURE_BOOT_POLICY` | int | 0 | 0=bypass, 1=enforce | -| `VTOY_SECONDARY_TIMEOUT` | int | 0 | Submenu timeout | -| `HISO_DEFAULT_KBD_LAYOUT` | string | "QWERTY_USA" | 20 layouts | -| `HISO_MENU_LANGUAGE` | string | "en_US" | 37 languages | -| `HISO_DEFAULT_SEARCH_ROOT` | string | "" | Restrict ISO search dir | -| `HISO_DEFAULT_IMAGE` | string | "" | Default ISO path | - -**hiperiso-specific additions** (in `control` or top-level): -| Key | Type | Default | Description | -|-----|------|---------|-------------| -| `default_ram` | int | 2048 | Default guest RAM (MB) | -| `default_cpus` | int | 2 | Default guest vCPUs | -| `default_trace_level` | string | "standard" | Trace tier | -| `default_display` | string | "none" | QEMU display mode | -| `default_vga` | string | "none" | QEMU VGA mode | -| `fallback_no_kvm` | bool | true | Fall back if no KVM | - -#### Plugin 2: `theme` (Object) - -Identical to Ventoy — GRUB2 gfxmenu themes: - -| Key | Type | Default | Description | -|-----|------|---------|-------------| -| `file` | string/array | — | Path(s) to theme.txt (relative = `/hiperiso/themes/` or `/ventoy/`) | -| `default_file` | int | 0 | Index (1-based, 0=random) | -| `random` | string | — | `"boot_second"`, `"boot_day"`, `"boot_month"` | -| `resolution_fit` | int (0/1) | 0 | Filter by resolution | -| `gfxmode` | string | "1024x768" | GRUB gfxmode ("max" = auto) | -| `display_mode` | string | — | `"GUI"`, `"CLI"`, `"serial"`, `"serial_console"` | -| `serial_param` | string | — | Serial port params | -| `hiperiso_left` | string | "5%" | Hotkey tip X | -| `hiperiso_top` | string | "95%" | Hotkey tip Y | -| `hiperiso_color` | string | "#0000ff" | Hotkey tip color | -| `fonts` | array | — | .pf2 font paths | - -Theme files use standard GRUB2 gfxmenu `.txt` format. Default theme shipped at -`/EFI/hiperiso/grub/themes/hiperiso/theme.txt`. - -Per-architecture themes: `theme`, `theme_legacy`, `theme_uefi`, `theme_ia32`, -`theme_aa64`, `theme_mips`. - -#### Plugin 3: `auto_install` (Array of objects) - -Maps auto-install scripts to ISOs. hiperiso attaches them as virtual media: - -| Key | Type | Description | -|-----|------|-------------| -| `image` | string | ISO path or glob | -| `parent` | string | Parent directory (alternative) | -| `template` | array | Script paths (kickstart/preseed/autoyast) | -| `autosel` | int | Auto-select template (1-based, 0=prompt) | -| `timeout` | int | Selection timeout (seconds) | - -**hiperiso implementation:** The selected template file is packaged into a -virtual floppy image (FAT12) and attached to QEMU via `-device isa-fdc`. -The guest OS reads it as `/dev/fd0`. Alternatively, for Linux guests, -`-fw_cfg name=opt/auto_install,file=script` passes the script via QEMU's -firmware config interface, and the guest's initramfs can read it from -`/sys/firmware/qemu_fw_cfg/`. - -#### Plugin 4: `persistence` (Array of objects) - -Persistent storage for live Linux ISOs: - -| Key | Type | Description | -|-----|------|-------------| -| `image` | string | ISO path or glob | -| `backend` | array | .dat file paths | -| `autosel` | int | Auto-select backend | -| `timeout` | int | Selection timeout | - -**hiperiso implementation:** The .dat file is attached as a secondary QEMU -drive: `-drive file=persistence.dat,if=none,id=persist,format=raw -device -virtio-blk-pci,drive=persist`. The guest OS discovers it as `/dev/vdb` and -mounts by label (e.g., `casper-rw`, `persistence`). - -**Persistence creation tool:** `hiperiso-create-persistence` (port of Ventoy's -`CreatePersistentImg.sh`): -``` -hiperiso-create-persistence [-s size_MB] [-t ext4|ext3|ext2|xfs] \ - [-l LABEL] [-c CONFIG] [-o output.dat] -``` - -#### Plugin 5: `menu_alias` (Array of objects) - -Identical to Ventoy — pure GRUB2 menu feature: - -| Key | Type | Description | -|-----|------|-------------| -| `image` | string | ISO path or glob | -| `dir` | string | Directory path | -| `alias` | string | Display name | - -#### Plugin 6: `menu_tip` (Object) - -Identical to Ventoy — tooltip messages in GRUB2 menu: - -| Key | Type | Default | Description | -|-----|------|---------|-------------| -| `left` | string | "10%" | Tooltip X | -| `top` | string | "81%" | Tooltip Y | -| `color` | string | "blue" | Tooltip color | -| `tips` | array | — | Each: `{image/dir, tip/tip1+tip2}` | - -#### Plugin 7: `menu_class` (Array of objects) - -Identical to Ventoy — GRUB2 icon class per ISO: - -| Key | Type | Description | -|-----|------|-------------| -| `key` | string | Substring match in filename | -| `parent` | string | Parent dir match | -| `dir` | string | Directory match | -| `class` | string | Icon class name | - -Default classes: `vtoyiso`, `vtoywim`, `vtoyefi`, `vtoyimg`, `vtoyvhd`, `vtoyvtoy`. - -#### Plugin 8: `injection` (Array of objects) - -Inject files into the booted OS. In Ventoy this modifies the initrd; in hiperiso -it attaches a virtual floppy: - -| Key | Type | Description | -|-----|------|-------------| -| `image` | string | ISO path or glob | -| `parent` | string | Parent dir (alternative) | -| `archive` | string | Path to tar.gz archive | - -**hiperiso implementation:** The archive is extracted and packaged into a -virtual floppy image (or small ISO) attached via QEMU. The guest OS can access -it as a removable device. For Linux guests, `-fw_cfg` can also be used. - -#### Plugin 9: `auto_memdisk` (Array of strings) - -ISOs that should be loaded entirely into RAM: - -**hiperiso implementation:** Instead of Ventoy's memdisk, hiperiso uses QEMU's -memory-backed CD-ROM: `-drive file=iso,if=none,id=cd0,media=cdrom,readonly=on` -is replaced with a RAM-backed copy for small ISOs. The initramfs copies the ISO -to tmpfs before passing to QEMU when `auto_memdisk` matches. - -#### Plugin 10: `image_list` (Array of strings) - -Whitelist — only show matching ISOs in menu. - -#### Plugin 11: `image_blacklist` (Array of strings) - -Blacklist — hide matching ISOs from menu. - -#### Plugin 12: `conf_replace` (Array of objects) - -Replace config files inside an ISO before booting: - -| Key | Type | Description | -|-----|------|-------------| -| `iso` | string | ISO path or glob | -| `org` | string | Original file path inside ISO | -| `new` | string | Replacement file on data partition | -| `img` | int | Which initrd (0=all) | - -**hiperiso implementation:** Since hiperiso can't modify a read-only CD-ROM at -runtime, the initramfs creates a modified copy of the ISO in tmpfs: -1. Copy original ISO to tmpfs -2. Use `xorriso` or `libisoburn` to replace the file(s) -3. Pass the modified ISO path to QEMU instead - -Max replacement file size: 1 MiB (same as Ventoy). - -#### Plugin 13: `dud` (Array of objects) - -Driver Update Disk images for specific ISOs: - -| Key | Type | Description | -|-----|------|-------------| -| `image` | string | ISO path or glob | -| `dud` | array | DUD image paths | - -**hiperiso implementation:** DUD images attached as virtual floppy or secondary -CD-ROM via QEMU. - -#### Plugin 14: `password` (Object) - -Boot-level and per-ISO password protection: - -| Key | Type | Description | -|-----|------|-------------| -| `bootpwd` | string | Boot password (`txt#`, `md5#`, `md5#salt#`) | -| `isopwd` | string | Password for .iso files | -| `wimpwd` | string | Password for .wim files | -| `vhdpwd` | string | Password for .vhd files | -| `imgpwd` | string | Password for .img files | -| `efipwd` | string | Password for .efi files | -| `vtoypwd` | string | Password for .vtoy files | -| `menupwd` | array | Per-ISO: `{file/parent, pwd}` | - -Password formats: `txt#plaintext`, `md5#32hexchars`, `md5#salt#hash`. - -Identical GRUB2-level implementation — prompt before booting. - -#### Plugin 15: `custom_boot` (Array of objects) - -Custom GRUB2 boot configuration per ISO: - -| Key | Type | Description | -|-----|------|-------------| -| `file` | string | ISO path | -| `dir` | string | Directory path | -| `vcfg` | string | Path to .vcfg GRUB2 config fragment | - -The .vcfg file is sourced by GRUB2 instead of the default boot path. - -### 4.3 ISO Matching Algorithm - -Identical to Ventoy: - -1. **Exact path match** (`image` key): Full path equality with `*` wildcard support -2. **Parent directory match** (`parent`/`dir` key): All ISOs in that directory -3. **Priority**: Exact matches checked first, then parent matches -4. **Wildcard**: `*` in filename portion (not across `/`) - -### 4.4 iso_overrides (hiperiso-specific extension) - -hiperiso adds an `iso_overrides` section for QEMU-specific configuration per ISO: - -```jsonc -{ - "iso_overrides": { - "*./windows11*.iso": { - "ram": 4096, - "cpus": 4, - "tpm": true, - "secure_boot": true, - "cpu_features": ["vmx"], - "trace_level": "detailed", - "display": "gtk", - "vga": "std", - "machine_type": "q35", - "bios": "ovmf" - }, - "*./memtest*.img": { - "ram": 512, - "cpus": 1, - "bios": "seabios", - "trace_level": "none" - }, - "*./freebsd*.iso": { - "ram": 2048, - "cpu_features": ["vmx"] - } - } -} -``` - ---- - -## 5. User-Facing Tools (Full Ventoy Parity) - -### 5.1 hiperisoGUI — Native GUI Installer - -**Architecture:** Same as VentoyGUI — smart launcher detects toolkit: - -``` -hiperiso_gui (C launcher) - ├── Parses /etc/ld.so.cache to detect GTK2/3/4, Qt4/5/6 - ├── Checks desktop environment (GNOME/KDE/XFCE) - ├── Falls back to pkexec for privilege escalation - ├── Supports --gtk3/--qt5 override flags - └── Execves: hiperiso_gui.gtk3 or hiperiso_gui.qt5 -``` - -**GTK3 variant** (port of `ventoy_gtk.c`): -- GtkBuilder UI (embedded XML, no external .glade file needed) -- Device combo box (USB disks, model/bus info) -- Install / Update / Clean buttons -- Secure Boot checkbox -- Partition style: MBR / GPT radio -- 4K alignment checkbox -- Reserve space spinner -- Filesystem selector: exFAT / NTFS / FAT32 / UDF -- Progress bar with percentage -- Language menu (60+ languages) -- About dialog with version - -**Qt5 variant** (port of `ventoy2diskwindow.cpp`): -- QMainWindow with same functionality -- Background thread for install/update operations -- Signal/slot wiring for progress updates - -**Build:** GTK3 via `pkg-config gtk+-3.0`, Qt5 via `qmake`. - -### 5.2 hiperisoWeb — Web-Based Installer - -**Architecture:** Embedded HTTP server (CivetWeb) on port 24680: - -``` -Browser (SPA) ←→ hiperiso_web (HTTP+JSON) ←→ /dev/sdX (direct I/O) -``` - -**API endpoints** (identical to VentoyWeb): - -| Method | Parameters | Response | -|--------|-----------|----------| -| `GET /sysinfo` | — | version, language, partstyle, busy, token | -| `POST /get_dev_list` | — | Array of disks (name, size, model, bus, ventoy status) | -| `POST /install` | disk, partstyle, secure_boot, align_4kb, reserve_space | Success/fail | -| `POST /update` | disk | Success/fail | -| `POST /clean` | disk | Success/fail | -| `GET /get_percent` | — | 0-100 progress | -| `POST /sel_language` | lang | OK | -| `POST /sel_partstyle` | mbr/gpt | OK | -| `POST /refresh_device` | — | OK | - -**Frontend:** Single-page HTML (AdminLTE + Bootstrap + jQuery). Served from -embedded data (compiled into binary as C arrays, same as Ventoy). - -**Launcher:** `hiperiso-web.sh` — detects arch, starts `hiperiso_web $HOST $PORT`, -opens browser to `http://127.0.0.1:24680`. - -### 5.3 hiperisoPlugson — Plugin Configuration Tool - -**Architecture:** Embedded HTTP server (CivetWeb) on port 24681: - -``` -Browser (SPA) ←→ hiperiso_plugson (HTTP+JSON) ←→ hiperiso.json on USB -``` - -Configures an already-installed hiperiso USB drive. Reads/writes -`hiperiso/hiperiso.json` (or `ventoy/ventoy.json`). - -**API endpoints** (87+ endpoints, same as VentoyPlugson): - -Each plugin type has CRUD endpoints: -- `GET /get_` — Read current config -- `POST /save_` — Save config -- `POST /add_` — Add entry -- `POST /del_` — Delete entry - -Plugin types: `control`, `theme`, `auto_install`, `persistence`, `menu_alias`, -`menu_tip`, `menu_class`, `injection`, `auto_memdisk`, `image_list`, -`image_blacklist`, `conf_replace`, `dud`, `password`, `custom_boot`. - -Plus: `sysinfo`, `handshake`, `device_info`, `check_path`, `fuzzy`. - -**Frontend:** Multi-page SPA with tabs for each plugin type. -AdminLTE + Bootstrap + DataTables + jQuery. - -**Launcher:** `hiperiso-plugson.sh` — validates hiperiso disk, mounts partition, -starts server, opens browser. - -### 5.4 hiperiso-install — CLI Installer - -**Shell-based** (port of Ventoy's `VentoyWorker.sh` pattern): - -```sh -Hiperiso2Disk.sh -i /dev/sdX [-g] [-s/-S] [-r SIZE] [-L label] [-n] -Hiperiso2Disk.sh -u /dev/sdX -Hiperiso2Disk.sh -l /dev/sdX -``` - -Options: -- `-i` / `-I`: Install (normal / force) -- `-u`: Update (preserve data partition) -- `-l`: List hiperiso version on disk -- `-g`: Use GPT (default), otherwise MBR -- `-s` / `-S`: Secure Boot on / off -- `-r SIZE`: Reserve space (MB) at disk end -- `-L label`: Data partition label -- `-n`: Non-destructive install (shrink existing partition) -- `-y`: Skip confirmation - -**Install flow:** -1. Check prerequisites (sgdisk, mkfs.vfat, mkfs.exfat) -2. Verify disk not mounted/swap -3. Detect existing hiperiso (refuse without -I) -4. Partition: create ESP (256MB FAT32) + data partition -5. Format: mkfs.vfat for ESP, mkfs.exfat for data -6. Copy payload: kernel, initramfs, OVMF, GRUB2, themes, tools -7. Install GRUB2: `grub-install --target=x86_64-efi` -8. Write hiperiso.json example -9. Create directory structure - -**Update flow:** -1. Read existing version -2. Preserve data partition entirely -3. Rewrite ESP: new kernel, initramfs, OVMF, GRUB2, themes -4. Preserve user config (hiperiso.json) - -### 5.5 hiperiso-log — Log Analysis Tool - -**Static binary** (already implemented, 9 C files): -- Parse QEMU simpletrace binary → I/O log -- Parse serial.log → boot stage timestamps -- Generate summary report (JSON + text) -- Compare boot traces across runs - -``` -hiperiso-log analyze /hiperiso/logs/ubuntu-24.04/ -hiperiso-log trace /hiperiso/logs/ubuntu-24.04/trace.bin --format json -hiperiso-log serial /hiperiso/logs/ubuntu-24.04/serial.log --stages -hiperiso-log compare /hiperiso/logs/ubuntu-24.04/ /hiperiso/logs/ubuntu-24.04.bak/ -``` - -### 5.6 hiperiso-create-persistence — Persistence Tool - -Port of Ventoy's `CreatePersistentImg.sh`: -```sh -hiperiso-create-persistence [-s 1024] [-t ext4] [-l casper-rw] [-c "/ union"] [-o persistence.dat] -hiperiso-extend-persistence persistence.dat [-s +2048] -``` - -### 5.7 Language Support / i18n - -**Format:** Same as Ventoy — single JSON file with all translations. - -**File:** `/EFI/hiperiso/lang/languages.json` (3,448 lines, 60+ languages). - -Structure: -```json -[{ - "name": "English", - "FontFamily": "Courier New", - "FontSize": 20, - "Author": "hiperiso", - "STR_INSTALL": "Install", - "STR_UPDATE": "Update", - "STR_ERROR": "Error", - ... -}] -``` - -**String IDs:** Same `STR_*` enum as Ventoy (Language.h). hiperiso adds: -- `STR_BOOTLOGGING`: "Boot logging active" -- `STR_HYPERVISOR`: "Hypervisor mode" -- `STR_KVM_MISSING`: "Hardware virtualization unavailable" -- `STR_FALLBACK_MODE`: "Fallback mode (no bootlogging)" -- `STR_LOG_SAVED`: "Boot logs saved to" - -**Runtime:** GRUB2 loads translations into memory, selects by `HISO_MENU_LANGUAGE`. -Installer GUI (GTK/Qt) uses same JSON. Web UI loads via JavaScript. - ---- - -## 6. ISO Type Support - -### 6.1 All Supported Types - -| Type | Extension | Boot Method | QEMU Handling | -|------|-----------|-------------|---------------| -| **Linux ISO** | .iso | UEFI CD-ROM boot | `-drive media=cdrom` | -| **Windows Install** | .iso | UEFI CD-ROM boot | Native CD-ROM (no WIM patching needed) | -| **WinPE** | .iso/.wim | UEFI CD-ROM boot | Native CD-ROM + optional wimboot | -| **VHD** | .vhd | Disk boot | `-drive format=vpc` | -| **VHDX** | .vhdx | Disk boot | `-drive format=vhdx` | -| **VDI** | .vdi | Disk boot | `-drive format=vdi` | -| **IMG** | .img | Memdisk / CD-ROM | RAM-backed or CD-ROM | -| **EFI** | .efi | Direct chainload | `-drive` with EFI application | -| **VTOY** | .vtoy | Custom GRUB2 config | User-provided .vcfg | -| **BSD** | .iso | UEFI CD-ROM boot | Native (no geom_ventoy.ko needed) | - -### 6.2 Windows ISO Handling - -Ventoy requires: BCD parsing, WIM patching, vtoyjump injection, winload.exe→.efi conversion. - -**hiperiso:** None of that. QEMU presents the ISO as a standard AHCI CD-ROM. -Windows Boot Manager reads BCD from the virtual CD-ROM, loads boot.wim, and -boots normally. No modification needed. - -**Win11 specifics:** -- TPM 2.0: `-tpmdev emulator` with swtpm -- Secure Boot: OVMF with enrolled keys -- 4GB+ RAM: `iso_overrides` sets `ram: 4096` -- CPU features: `-cpu host,+vmx` -- Win11 bypass check: `VTOY_WIN11_BYPASS_CHECK=1` → QEMU provides compliant hardware - -### 6.3 VHD/VHDX Handling - -Ventoy requires: footer parsing, BCD patching, partition GUID manipulation. - -**hiperiso:** QEMU natively supports VHD (`format=vpc`), VHDX (`format=vhdx`), -and VDI (`format=vdi`). Attach directly as a hard drive — the guest OS sees a -real disk with partitions. - -### 6.4 Per-ISO QEMU Templates - -For ISOs requiring special QEMU configuration, templates are stored in -`/hiperiso/iso_overrides/`: - -```jsonc -// windows11.json -{ - "ram": 4096, - "cpus": 4, - "tpm": true, - "secure_boot": true, - "cpu_features": ["vmx"], - "machine_type": "q35" -} -``` - ---- - -## 7. Component Map - -``` -hiperiso/ -├── grub2/ # GRUB2 hiperiso module -│ ├── hiperiso.c # Module init, arch detection -│ ├── hiperiso_def.h # Definitions, constants -│ ├── hiperiso_menu.c # ISO enumeration + menu generation -│ ├── hiperiso_boot.c # Boot command: load kernel+initramfs -│ ├── hiperiso_plugin.c # All 15 plugins (JSON parse + dispatch) -│ ├── hiperiso_json.c # JSON parser (from Ventoy, unchanged) -│ ├── hiperiso_json.h # JSON types -│ ├── hiperiso_theme.c # Theme system (from Ventoy) -│ ├── hiperiso_password.c # Password challenge (from Ventoy) -│ └── build_grub2.sh # GRUB2 build script -│ -├── host/ # Hypervisor host environment -│ ├── kernel/ -│ │ └── hiperiso_defconfig # Minimal kernel (KVM built-in) -│ ├── initramfs/ -│ │ ├── init # Main init (KVM detect, mount, launch QEMU) -│ │ ├── hiperiso-lib.sh # Shared functions -│ │ ├── kvm_check.sh # KVM detection -│ │ ├── qemu_launch.sh # QEMU arg builder + launcher -│ │ ├── log_flush.sh # Async log flusher -│ │ ├── conf_replace.sh # ISO modification for conf_replace -│ │ ├── make_floppy.sh # Virtual floppy creation for plugins -│ │ └── fallback_boot.sh # Fallback mode (no KVM) -│ └── qemu/ -│ └── configure_qemu.sh # QEMU build config -│ -├── firmware/ # Guest firmware -│ ├── build_ovmf.sh # OVMF build (regular + Secure Boot) -│ └── OVMF_VARS.template.fd # Template for per-boot variable copy -│ -├── logging/ # Bootlogging system -│ ├── trace-standard.events # Tier 1+2 trace events -│ ├── trace-detailed.events # Tier 3 trace events -│ ├── trace-full.events # Tier 4 trace events -│ └── hiperiso-log/ # Log analysis tool (C, static) -│ ├── main.c # CLI entry point -│ ├── simpletrace.h # QEMU trace binary format -│ ├── trace_parser.c # Parse trace.bin -│ ├── serial_parser.c # Parse serial.log, extract stages -│ ├── report.c # Generate report.json + report.txt -│ └── Makefile # Static build -│ -├── installer/ # CLI installer -│ ├── Hiperiso2Disk.sh # USB installer (port of VentoyWorker.sh) -│ └── partition_layout.h # Partition constants -│ -├── gui/ # GUI installer (GTK3 + Qt5) -│ ├── launcher/ -│ │ └── hiperiso_gui.c # Smart toolkit detection launcher -│ ├── gtk3/ -│ │ ├── hiperiso_gtk.c # GTK3 GUI -│ │ └── hiperiso_gtk.h # Widget handles -│ ├── qt5/ -│ │ ├── hiperiso_qt.cpp # Qt5 GUI -│ │ ├── hiperiso_qt.h # Qt5 headers -│ │ └── partcfg_dialog.cpp # Partition config dialog -│ └── core/ -│ ├── hiperiso_disk.c # Disk detection (sysfs scanning) -│ ├── hiperiso_disk.h # Disk types, device struct -│ └── hiperiso_install.c # Install/update/clean logic (shared) -│ -├── web/ # Web installer + Plugin config -│ ├── hiperiso_web/ # Web installer (port 24680) -│ │ ├── main.c # HTTP server entry -│ │ ├── http.c # CivetWeb API handlers -│ │ ├── http.h # API definitions -│ │ └── www/ -│ │ └── index.html # SPA frontend -│ └── hiperiso_plugson/ # Plugin config tool (port 24681) -│ ├── main.c # HTTP server entry -│ ├── http.c # 87+ API endpoints -│ ├── http.h # Plugin data structures -│ └── www/ -│ ├── index.html # Main SPA -│ ├── plugson_control.html -│ ├── plugson_theme.html -│ ├── plugson_auto_install.html -│ ├── plugson_persistence.html -│ ├── plugson_password.html -│ ├── plugson_image_list.html -│ ├── plugson_menu_alias.html -│ ├── plugson_menu_tip.html -│ ├── plugson_menu_class.html -│ ├── plugson_injection.html -│ ├── plugson_conf_replace.html -│ ├── plugson_dud.html -│ ├── plugson_auto_memdisk.html -│ ├── plugson_custom_boot.html -│ └── static/ # CSS, JS, fonts -│ -├── tools/ # Auxiliary tools -│ ├── hiperiso-create-persistence.sh # .dat creation -│ ├── hiperiso-extend-persistence.sh # .dat extension -│ └── hiperiso-vtoytool.c # Multi-call runtime tool -│ -├── config/ # Configuration -│ ├── hiperiso.json.example # Example config -│ ├── README.md # Config documentation -│ └── iso_overrides/ # Per-ISO QEMU templates -│ ├── windows11.json -│ └── default.json -│ -├── i18n/ # Internationalization -│ └── languages.json # 60+ languages (from Ventoy, adapted) -│ -├── theme/ # Default themes -│ └── hiperiso/ -│ ├── theme.txt # GRUB2 gfxmenu theme -│ └── *.png # Theme graphics -│ -├── scripts/ # Build system -│ ├── build_all.sh # Master build orchestrator -│ ├── download_sources.sh # Source downloader -│ ├── configure_qemu.sh # QEMU configure -│ └── build_initramfs.sh # Initramfs packer -│ -├── Makefile # Top-level build -├── INTERFACES.sh # Interface contracts (single source of truth) -├── HIPERISO_PLAN.md # This file -└── README.md # User documentation -``` - ---- - -## 8. Installer Architecture Details - -### 8.1 Partition Layout (MBR and GPT) - -``` -Sector 0: MBR (boot.img 446 bytes + partition table + 0x55AA) -Sector 1-33: GPT header (if GPT) or GRUB2 core.img start (if MBR) -Sector 34-2047: GRUB2 core image / GPT partition entries -Sector 2048: ─── PARTITION 1 START (1MB aligned) ─── - ESP (FAT32, 256MB) - MBR type: 0xEF | GPT type: C12A7328-F81F-11D2-BA4B-00A0C93EC93B - GPT name: "HIPERISO" | Label: "HIPERISO" - Contents: GRUB2, kernel, initramfs, OVMF, themes, tools - ─── PARTITION 2 START (4KB aligned) ─── - Data partition (exFAT default, also NTFS/FAT32/UDF) - MBR type: 0x07 | GPT type: EBD0A0A2-B9E5-4433-87C0-68B6B72699C7 - GPT name: "HIPERISODATA" | Label: "HIPERISO" (configurable) - Contents: ISOs, logs, config, plugins -GPT only: Last 33 sectors: backup GPT header + partition table -``` - -### 8.2 Boot Code Written to Disk - -| What | Destination | -|------|-------------| -| **GRUB2 boot.img** (446 bytes) | Disk sector 0, bytes 0-445 | -| **GRUB2 core.img** | Sectors 1-2047 (MBR) or 34-2047 (GPT) | -| **ESP FAT32 image** | Partition 1 (formatted in-place) | -| **Disk UUID** | Disk offset 384 (16 bytes) | -| **Disk signature** | Disk offset 440 (4 bytes) | - -### 8.3 Install/Update/Clean Operations - -**Fresh install:** -1. Wipe first 64 sectors (destroy existing MBR/GPT) -2. Create partitions (sgdisk or fdisk) -3. Format ESP (mkfs.vfat -F32 -n HIPERISO) -4. Format data partition (mkfs.exfat -n HIPERISO) -5. Install GRUB2 to ESP -6. Copy all payload files to ESP -7. Create hiperiso.json example on data partition -8. Create directory structure - -**Update (data-preserving):** -1. Read existing version from ESP -2. Mount ESP -3. Replace all payload files on ESP -4. Preserve data partition entirely -5. Optionally migrate config format - -**Clean:** -1. Wipe MBR/GPT -2. Delete all partitions -(Disk is left blank) - -**Non-destructive install:** -1. Shrink existing data partition -2. Create ESP at end -3. Install boot code - -### 8.4 Device Detection (Linux) - -Scan `/sys/block/*`: -- Detect type via major number: SCSI, USB, IDE, NVMe, VirtIO -- Exclude: ram, zram, loop, dm-, sr*, partitions -- Get size via sysfs or BLKGETSIZE64 ioctl -- Get vendor/model from sysfs -- USB-only filter by default (override with `-U`) - -### 8.5 Cross-Platform - -| Platform | Installer | GUI | Web | Plugson | -|----------|-----------|-----|-----|---------| -| Linux x86_64 | Shell + C | GTK3/Qt5 | CivetWeb | CivetWeb | -| Linux aarch64 | Shell + C | GTK3/Qt5 | CivetWeb | CivetWeb | -| Windows x86_64 | C (Win32 API) | Win32 dialog | N/A | N/A | -| Windows ARM64 | C (Win32 API) | Win32 dialog | N/A | N/A | - -Windows installer uses VDS COM / diskpart for partition operations. -Same partition layout and boot images. - ---- - -## 9. Implementation Plan - -### Phase 1: MVP — Core Boot Chain (DONE ✅) - -All 6 components compiled from source: -- [x] Linux kernel 6.12 LTS (KVM built-in, 5.4MB bzImage) -- [x] QEMU 9.0.0 (x86_64-softmmu, KVM + simpletrace, 24MB) -- [x] OVMF (UEFI firmware, 4MB) -- [x] GRUB2 2.12 (hiperiso module → BOOTX64.EFI, 741KB) -- [x] Busybox 1.36.1 (static, 2.4MB) -- [x] hiperiso-log (static, 892KB) -- [x] Initramfs packed (7.9MB cpio.gz) -- [x] Payload assembled (19MB) - -### Phase 2: Enhanced GRUB2 Module (CURRENT) - -Expand the existing GRUB2 hiperiso module to full Ventoy parity: - -- [ ] Expand `hiperiso_plugin.c` to parse all 15 plugins from JSON -- [ ] Add `hiperiso_theme.c` — GRUB2 theme loading + application -- [ ] Add `hiperiso_password.c` — boot + per-ISO password challenges -- [ ] Expand `hiperiso_menu.c` — tree view mode, menu classes, image filtering -- [ ] Expand `hiperiso_boot.c` — pass all plugin params via kernel cmdline -- [ ] Add ISO matching algorithm (exact path + parent dir + wildcard) -- [ ] Add platform suffix support (`_legacy`, `_uefi`, etc.) -- [ ] Add secondary boot menu (normal/memdisk/grub2 modes) -- [ ] Add language support (load languages.json at boot) -- [ ] Add keyboard layout support (20 layouts) - -### Phase 3: Enhanced Initramfs - -Expand init scripts to handle all plugin parameters: - -- [ ] `conf_replace.sh` — Create modified ISO copy using xorriso -- [ ] `make_floppy.sh` — Create virtual floppy images for auto_install/dud/injection -- [ ] Expand `qemu_launch.sh` — Build QEMU args for all plugin types -- [ ] Add swtpm integration for TPM support -- [ ] Add Secure Boot OVMF variable management (copy template per boot) -- [ ] Expand `fallback_boot.sh` — Full Ventoy-compatible fallback - -### Phase 4: CLI Installer Enhancement - -Expand `Hiperiso2Disk.sh` to full Ventoy parity: - -- [ ] GPT + MBR dual support -- [ ] Secure Boot support (partition attributes) -- [ ] Non-destructive install (partition shrink) -- [ ] Reserve space option -- [ ] Filesystem selection (exFAT/NTFS/FAT32/UDF) -- [ ] Version detection and update mode -- [ ] 4K alignment detection -- [ ] USB device filtering - -### Phase 5: GUI Installer (GTK3 + Qt5) - -- [ ] `hiperiso_gui.c` — Smart launcher (toolkit detection) -- [ ] `hiperiso_gtk.c` — GTK3 GUI (port from ventoy_gtk.c) -- [ ] `hiperiso_qt.cpp` — Qt5 GUI (port from ventoy2diskwindow.cpp) -- [ ] `hiperiso_disk.c` — Disk detection (port from ventoy_disk_linux.c) -- [ ] `hiperiso_install.c` — Shared install/update/clean logic -- [ ] Language support in GUI (60+ languages) -- [ ] Kiosk mode for LiveCD - -### Phase 6: Web Installer (hiperisoWeb) - -- [ ] Port CivetWeb HTTP server integration -- [ ] Implement all 9 API endpoints -- [ ] Create SPA frontend (index.html) -- [ ] `hiperiso-web.sh` launcher script -- [ ] Device detection and enumeration -- [ ] Progress tracking -- [ ] Language support in web UI - -### Phase 7: Plugin Config Tool (hiperisoPlugson) - -- [ ] Port CivetWeb HTTP server -- [ ] Implement all 87+ API endpoints -- [ ] Create 15 plugin config pages (HTML) -- [ ] `hiperiso-plugson.sh` launcher script -- [ ] JSON validation and error handling -- [ ] Config backup/restore - -### Phase 8: Persistence + Auto-Install Tools - -- [ ] `hiperiso-create-persistence.sh` — .dat creation tool -- [ ] `hiperiso-extend-persistence.sh` — .dat extension tool -- [ ] Virtual floppy creation for auto-install scripts -- [ ] fw_cfg integration for Linux auto-install - -### Phase 9: Windows Installer - -- [ ] Port Ventoy2Disk C/Win32 code -- [ ] VDS/diskpart integration -- [ ] Win32 dialog GUI -- [ ] CLI mode (`hiperiso-install.exe VTOYCLI /I /PhyDrive:1`) - -### Phase 10: LiveCD + Polish - -- [ ] Build LiveCD ISO (bootable hiperiso with kiosk GUI) -- [ ] Default themes and icons -- [ ] Comprehensive documentation -- [ ] Cross-architecture builds (aarch64, i386) -- [ ] Automated testing framework - ---- - -## 10. Risk Analysis - -### Risk 1: KVM Unavailable (~15% of machines) -**Mitigation:** Fallback mode — detect `/dev/kvm`, fall back to direct boot -(no logging but still boots). Dual-mode strategy ensures ~100% hardware coverage. - -### Risk 2: Memory Pressure -**Mitigation:** QEMU streams ISO from USB. Pre-check available RAM. -Default 2GB, configurable per-ISO. Windows 11 → 4GB. - -### Risk 3: ISO Expects Specific Hardware -**Mitigation:** QEMU Q35 provides modern hardware. Per-ISO QEMU templates. -Accept some specialized ISOs won't work (document, same as Ventoy). - -### Risk 4: Secure Boot on Host -**Mitigation:** Build kernel as UKI (Unified Kernel Image). SHIM signing chain. -Standard Secure Boot Linux practice. - -### Risk 5: Plugin Compatibility -**Mitigation:** Accept ventoy.json directly. Test all 15 plugins against -real-world configurations. Maintain compatibility matrix. - -### Risk 6: conf_replace Performance -**Mitigation:** Creating modified ISO copy in tmpfs is fast for small files -(<1MB). Only triggered when conf_replace plugin is configured. - ---- - -## 11. Technology Stack - -| Component | Technology | Rationale | -|-----------|-----------|-----------| -| Hypervisor | KVM (in-kernel) | Ubiquitous, hardware-accelerated | -| VMM | QEMU 9.0.0 (stripped) | Comprehensive device model + tracing | -| Guest firmware | OVMF (edk2) | UEFI, SMM, Secure Boot ready | -| Host OS | Minimal Linux 6.12 LTS | KVM built-in, USB/FS drivers | -| Initramfs | Busybox 1.36.1 | Minimal footprint | -| Bootloader | GRUB2 2.12 (hiperiso module) | Menu UX, theme system | -| HTTP server | CivetWeb (embedded) | Same as Ventoy, proven | -| GUI | GTK3 + Qt5 | Same as Ventoy, broad compatibility | -| Web frontend | AdminLTE + Bootstrap + jQuery | Same as Ventoy | -| Config format | JSON (ventoy.json compatible) | Familiar, easy to parse | -| Log tool | C (statically linked) | Runs anywhere | -| i18n | JSON (languages.json) | Same as Ventoy | -| Installer | Shell (Linux) + C (Windows) | Same as Ventoy | - ---- - -## 12. Build System - -### 12.1 Build Targets - -```makefile -make all # Build everything -make kernel # Linux kernel bzImage -make qemu # QEMU system emulator (stripped) -make ovmf # OVMF firmware (regular + Secure Boot) -make grub2 # GRUB2 with hiperiso module → BOOTX64.EFI -make busybox # Busybox static -make initramfs # Pack initramfs.cpio.gz -make hiperiso-log # Log analysis tool (static) -make gui # GTK3 + Qt5 GUI installers -make web # Web installer + Plugson -make dist # Assemble build/payload/ -make clean # Remove build/ -make test # Run unit tests -``` - -### 12.2 Payload Output - -``` -build/payload/ -├── Hiperiso2Disk.sh # CLI installer -├── hiperiso-web.sh # Web installer launcher -├── hiperiso-plugson.sh # Plugin config launcher -├── hiperiso-gui # GUI launcher (smart detect) -├── config/ -│ ├── hiperiso.json.example -│ └── iso_overrides/ -├── theme/ -│ └── hiperiso/theme.txt -├── i18n/ -│ └── languages.json -├── tool/ -│ ├── x86_64/ -│ │ ├── hiperiso_web # Web server -│ │ ├── hiperiso_plugson # Plugin config server -│ │ ├── hiperiso_gui.gtk3 # GTK3 GUI -│ │ ├── hiperiso_gui.qt5 # Qt5 GUI -│ │ ├── hiperiso-create-persistence.sh -│ │ └── hiperiso-log # Log analysis tool -│ └── (other arches in future) -├── EFI/ -│ ├── BOOT/ -│ │ ├── BOOTX64.EFI # GRUB2 (hiperiso module) -│ │ └── grub.cfg # GRUB2 menu config -│ └── hiperiso/ -│ ├── vmlinuz # Host kernel -│ ├── initramfs.cpio.gz # Host initramfs -│ ├── OVMF_CODE.fd # UEFI firmware code -│ ├── OVMF_VARS.fd # UEFI firmware variables (template) -│ ├── hiperiso-log # Log tool (static) -│ ├── trace/ # Trace event files -│ │ ├── trace-standard.events -│ │ ├── trace-detailed.events -│ │ └── trace-full.events -│ ├── grub/ -│ │ ├── themes/ # Default themes -│ │ ├── fonts/ # Default fonts -│ │ └── icons/ # Menu class icons -│ └── lang/ # Language files -│ └── languages.json -└── version # Version string -``` - ---- - -## Appendix A: Ventoy Feature Parity Checklist - -### User-Facing Features -- [x] ISO menu with themes (GRUB2 gfxmenu) -- [ ] Tree view mode -- [ ] ISO browsing (directory navigation) -- [ ] Hotkey tips (F1-F6 shortcuts) -- [ ] Password protection (boot + per-ISO) -- [ ] Menu aliases -- [ ] Menu tooltips -- [ ] Menu class icons -- [ ] Language selection (60+ languages) -- [ ] Keyboard layout selection (20 layouts) -- [ ] Power off / reboot from menu -- [ ] Shell mode (GRUB2 shell) -- [ ] Theme selection at runtime - -### ISO Support -- [x] Linux ISO boot -- [ ] Windows ISO boot (native CD-ROM) -- [ ] WinPE boot -- [ ] WIM boot -- [ ] VHD/VHDX boot -- [ ] VDI boot -- [ ] IMG boot (memdisk mode) -- [ ] EFI executable boot -- [ ] .vtoy custom boot -- [ ] FreeBSD boot -- [ ] DragonFly BSD boot -- [ ] systemd-boot ISOs - -### Plugin System -- [x] JSON config parsing -- [ ] control plugin (all 25+ keys) -- [ ] theme plugin (all 10+ keys) -- [ ] auto_install plugin -- [ ] persistence plugin -- [ ] menu_alias plugin -- [ ] menu_tip plugin -- [ ] menu_class plugin -- [ ] injection plugin -- [ ] auto_memdisk plugin -- [ ] image_list plugin -- [ ] image_blacklist plugin -- [ ] conf_replace plugin -- [ ] dud plugin -- [ ] password plugin -- [ ] custom_boot plugin - -### Installer -- [x] CLI installer (basic) -- [ ] CLI installer (full: GPT+MBR, reserve, non-destructive) -- [ ] GTK3 GUI installer -- [ ] Qt5 GUI installer -- [ ] Web installer (port 24680) -- [ ] Plugin config tool (port 24681) -- [ ] Windows installer -- [ ] Update mode (data-preserving) -- [ ] Non-destructive install - -### Bootlogging (hiperiso unique) -- [x] Serial console capture -- [x] Disk I/O tracing (simpletrace) -- [x] Trace tiers (standard/detailed/full) -- [x] Log analysis tool (hiperiso-log) -- [ ] Boot stage timestamping -- [ ] Boot comparison/regression detection - -### Advanced -- [ ] Secure Boot (OVMF + shim + MOK) -- [ ] Virtual TPM (swtpm for Win11) -- [ ] Persistence (.dat creation + management) -- [ ] Auto-install script attachment -- [ ] Driver Update Disk support -- [ ] Config replacement (ISO modification) -- [ ] File injection -- [ ] LiveCD version (kiosk GUI) -- [ ] Cross-architecture (aarch64) - ---- - -## Appendix B: Ventoy Source Inventory - -Key reference files assessed: - -``` -reference/Ventoy/ -├── GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ -│ ├── ventoy.c # Module init -│ ├── ventoy_def.h # All definitions -│ ├── ventoy_cmd.c (7166 lines) # All GRUB commands -│ ├── ventoy_linux.c (2120 lines) # Linux ISO boot chain -│ ├── ventoy_windows.c (2781) # Windows ISO boot -│ ├── ventoy_unix.c (1245) # BSD/Unix boot -│ ├── ventoy_vhd.c (754) # VHD/VHDX boot -│ ├── ventoy_plugin.c (3657) # Plugin framework (15 plugins) -│ ├── ventoy_browser.c # File browser -│ └── ventoy_json.c # JSON parser -├── Ventoy2Disk/Ventoy2Disk/ # Windows installer -├── LinuxGUI/Ventoy2Disk/ # GTK/Qt/Web installer -├── Plugson/ # Plugin config tool -├── VtoyTool/ # Runtime tools -├── IMG/cpio/ventoy/ # Linux injection hooks -├── LANGUAGES/languages.json # 60+ languages -├── INSTALL/ # Shell installer + tools -└── vtoyjump/ # Windows PE injection -``` - ---- - -## Appendix C: Research Sources - -- QEMU tracing: https://www.qemu.org/docs/master/devel/tracing.html -- OVMF Secure Boot: https://github.com/tianocore/tianocore.github.io/wiki/OVMF -- QEMU device model: https://www.qemu.org/docs/master/system/ -- swtpm (virtual TPM): https://github.com/stefanberger/swtpm -- openQA (ISO testing): https://open.qa/docs/ -- Ventoy documentation: https://www.ventoy.net/en/documentation.html +# hiperiso architecture notes + +This file is a short local design note for the current implementation. + +- USB media uses two partitions: + - partition 1: data partition for ISOs, logs, and configuration + - partition 2: FAT EFI partition for GRUB, kernel, initramfs, and firmware payloads +- The EFI boot path is: + - firmware → `EFI/BOOT/BOOTX64.EFI` + - GRUB loads `grub/grub.cfg` + - the custom module boots the host kernel and initramfs from `EFI/hiperiso/` + - the initramfs starts QEMU/KVM and boots the selected ISO as a guest +- Secure Boot is only considered supported when a real signed shim asset is packaged. +- The build should prefer locally maintained `src/grub2/` sources over broad source-tree rewrites. diff --git a/INTERFACES.sh b/INTERFACES.sh index f0a0069..a828604 100644 --- a/INTERFACES.sh +++ b/INTERFACES.sh @@ -14,7 +14,7 @@ HIPERISO_DISPLAY="" # Display mode: "none" | "gtk" | "vnc" (default: non HIPERISO_VGA="" # VGA mode: "none" | "std" | "virtio" (default: std) HIPERISO_FALLBACK="" # Force fallback mode: "1" skips KVM check -# ── Plugin Parameters (new for full Ventoy parity) ─────────────────────────── +# ── Plugin Parameters ───────────────────────────────────────────────────────── # These are resolved by the GRUB2 module from hiperiso.json plugins and passed # via kernel cmdline to the initramfs, which translates them to QEMU args. HIPERISO_AUTO_INSTALL="" # Path to auto-install script (kickstart/preseed) @@ -151,7 +151,7 @@ HIPERISO_JSON="${DATA_MOUNT}/hiperiso/hiperiso.json" # Tier 3 (full): + MMIO memory_region_ops (very slow, debug only) # ── Config File Format (hiperiso.json) ────────────────────────────────────── -# JSON format, compatible with Ventoy's ventoy.json structure: +# JSON format: # { # "control": { ... }, # "theme": { ... }, diff --git a/README.md b/README.md index 427ffda..bc2f8e2 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # hiperiso -A hypervisor-based ISO boot tool with full bootlogging — like Ventoy, but it +A hypervisor-based ISO boot tool with full bootlogging. 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. @@ -10,12 +10,11 @@ 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 +## How it works -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. +hiperiso 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. --- @@ -111,7 +110,7 @@ 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 +`Hiperiso2Disk.sh` defaults to MBR. Use `-g` for GPT. The standard layout is: | # | Type | FS | Size | Contents | diff --git a/config/README.md b/config/README.md index e1c3729..7ed69ba 100644 --- a/config/README.md +++ b/config/README.md @@ -1,9 +1,8 @@ # hiperiso configuration hiperiso is configured through a single JSON file placed on the **data -partition** of the USB at `/hiperiso/hiperiso.json`. The format is -[Ventoy](https://www.ventoy.net)-compatible so existing Ventoy configs need -only minor changes. Start from `hiperiso.json.example`. +partition** of the USB at `/hiperiso/hiperiso.json`. Start from +`hiperiso.json.example`. > JSON cannot contain comments, so every option is described here. @@ -65,7 +64,7 @@ partition) and a value: ## `iso_overrides` A map of **glob pattern → override object**. The first matching pattern wins. -Glob syntax matches Ventoy (anchored at the filename). +Patterns are matched against the filename. | Key | Type | Meaning | |------------------|-----------|------------------------------------------------------| diff --git a/grub2/bin/BOOTX64.EFI b/grub2/bin/BOOTX64.EFI index 81e136e4a0aeb6484c9d9e71cfc1c1b4f5e7288e..bde4982e04266341325bc40e93ea51b86c57cb43 100644 GIT binary patch delta 205524 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

`7HF(p4~)EJAv<4}9>&CG23o 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 SQN8I6?W_sg83knj^8)}Xgwt~X diff --git a/scripts/build_all.sh b/scripts/build_all.sh index 26cba9f..d8ace91 100755 --- a/scripts/build_all.sh +++ b/scripts/build_all.sh @@ -89,6 +89,8 @@ step 5 10 "Building GRUB2 with hiperiso module" if [ -f "$SCRIPT_DIR/build_grub2_204.sh" ]; then bash "$SCRIPT_DIR/build_grub2_204.sh" cp "$REPO_ROOT/grub2/bin/BOOTX64.EFI" "$STAGING/efi/BOOTX64.EFI" + [ -f "$REPO_ROOT/grub2/bin/grubx64_real.efi" ] && cp "$REPO_ROOT/grub2/bin/grubx64_real.efi" "$STAGING/efi/grubx64_real.efi" + [ -f "$REPO_ROOT/grub2/bin/grubx64.efi" ] && cp "$REPO_ROOT/grub2/bin/grubx64.efi" "$STAGING/efi/grubx64.efi" echo " [ok] $(du -h "$STAGING/efi/BOOTX64.EFI" | cut -f1) BOOTX64.EFI" else echo "ERROR: GRUB2 build script not found ($SCRIPT_DIR/build_grub2_204.sh)" diff --git a/scripts/build_grub2_204.sh b/scripts/build_grub2_204.sh index dbe9b85..07826d3 100644 --- a/scripts/build_grub2_204.sh +++ b/scripts/build_grub2_204.sh @@ -1,57 +1,50 @@ #!/bin/sh +# build_grub2_204.sh — Build GRUB2 2.04 with Ventoy modifications for hiperiso. +# --------------------------------------------------------------------------- +# hiperiso uses Ventoy as the GRUB substrate. This script unpacks the +# upstream GRUB2.04 source, overlays Ventoy's `grub2-modsrc` patch set, +# and builds the stock Ventoy GRUB binary. The rebranding layer (hiperiso +# kernel cmdline, JSON config, initramfs bridge) lives in +# `host/initramfs/` and the installed payload's `grub.cfg`, NOT in GRUB. +# +# The hiperiso source tree in `src/grub2/` is retained for reference but +# intentionally NOT compiled in here — it's an unfinished rebrand attempt +# that's blocked on partial modsrc/sed mismatches. See `docs/STATUS.md` +# (TODO) for the longer-term rebrand plan. +# +# Usage: scripts/build_grub2_204.sh +# Output: grub2/bin/BOOTX64.EFI, grub2/bin/grubx64_real.efi, grub2/bin/grubx64.efi set -eu (set -o pipefail) 2>/dev/null && set -o pipefail HIPERISO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" DL_DIR="$HIPERISO_ROOT/build/downloads" -MODSRC_TARBALL="$HIPERISO_ROOT/vendor/grub2-modsrc.tar.xz" +MODULE_TARBALL="$HIPERISO_ROOT/vendor/grub2-modsrc.tar.xz" BUILD_DIR="$HIPERISO_ROOT/build/grub2-204" SRC_DIR="$BUILD_DIR/SRC/grub-2.04" +PXE_DIR="$BUILD_DIR/PXE" +RUNTIME_GRUB_DIR="$BUILD_DIR/RUNTIME/grub" rm -rf "$BUILD_DIR" -mkdir -p "$BUILD_DIR/SRC" +mkdir -p "$BUILD_DIR/SRC" "$PXE_DIR" "$RUNTIME_GRUB_DIR" -tar -xf "$DL_DIR/grub-2.04.tar.xz" -C "$BUILD_DIR/SRC/" +tar -xf "$DL_DIR/grub-2.04.tar.xz" -C "$BUILD_DIR/SRC/" +tar -xf "$MODULE_TARBALL" -C "$BUILD_DIR/SRC/" -# Overlay Ventoy-derived GRUB2 modifications (vendored, no external dependency) -tar -xf "$MODSRC_TARBALL" -C "$BUILD_DIR/SRC/" +# Patch Ventoy's modsrc to allow a 64MB ESP. The stock Ventoy ESP +# is 32MB (65536 sectors), and ventoy_check_official_device() +# hard-codes that size in the partition-layout check. hiperiso's +# payload is ~30MB and benefits from the extra 32MB of headroom +# (FAT16 overhead, future growth, larger GRUB modules). Bump the +# expected ESP size to 131072 sectors. This is the only Ventoy +# source-level change we make. +find "$BUILD_DIR/SRC/grub-2.04/grub-core/ventoy" -type f \ + \( -name '*.c' -o -name '*.h' \) -exec sed -i \ + -e 's/(PartTbl\[1\]\.LastLBA + 1 - PartTbl\[1\]\.StartLBA) != 65536/(PartTbl[1].LastLBA + 1 - PartTbl[1].StartLBA) != 131072/g' \ + -e 's/PartTbl\[1\]\.SectorCount != 65536/PartTbl[1].SectorCount != 131072/g' \ + -e 's/(partition->len != 65536)/(partition->len != 131072)/g' \ + {} + -find "$SRC_DIR" -type f \( -name '*.c' -o -name '*.h' -o -name '*.S' \ - -o -name '*.sh' -o -name '*.cfg' -o -name '*.txt' \ - -o -name 'Makefile*' -o -name '*.def' -o -name '*.am' \ - -o -name '*.py' -o -name '*.lst' -o -name '*.rst' \) -exec sed -i \ - -e 's/ventoy\.net/hiperiso.net/g' \ - -e 's/Ventoy\.sh/Hiperiso.sh/g' \ - -e 's/VENTOY/HIPERISO/g' \ - -e 's/Ventoy/Hiperiso/g' \ - -e 's/ventoy2disk/hiperiso2disk/g' \ - -e 's/VENTOY2DISK/HIPERISO2DISK/g' \ - -e 's/ventoyctl/hiperisoctl/g' \ - -e 's/vtoyboot/hisoboot/g' \ - -e 's/vtoy_/hiso_/g' \ - -e 's/VTOY_/HISO_/g' \ - -e 's/vtoy/hiso/g' \ - -e 's/VTOY/HISO/g' \ - -e 's/ventoy/hiperiso/g' \ - -e 's/Ventoy/Hiperiso/g' \ - -e 's/vlnk/hlnk/g' \ - -e 's/VLNK/HLNK/g' \ - -e 's/Vlnk/Hlnk/g' \ - -e 's/0x77772020, 0x2e77, 0x6576, { 0x6e, 0x74, 0x6f, 0x79, 0x2e, 0x6e, 0x65, 0x74/0x65706968, 0x6972, 0x6f73, { 0x2e, 0x6e, 0x65, 0x74, 0x2f, 0x77, 0x77, 0x77/' \ - {} + - -find "$SRC_DIR" -depth -type d \( -name '*ventoy*' -o -name '*Ventoy*' \) | while read d; do - newd=$(echo "$d" | sed -e 's/ventoy/hiperiso/g' -e 's/Ventoy/Hiperiso/g') - mv "$d" "$newd" -done - -find "$SRC_DIR" -type f \( -name '*ventoy*' -o -name '*Ventoy*' \) | while read f; do - newf=$(echo "$f" | sed -e 's/ventoy/hiperiso/g' -e 's/Ventoy/Hiperiso/g') - mv "$f" "$newf" -done - -cp "$HIPERISO_ROOT/src/grub2/hiperiso_cmd.c" \ - "$SRC_DIR/grub-core/hiperiso/hiperiso_cmd.c" cp "$HIPERISO_ROOT/src/grub2/grub/grub.cfg" "$SRC_DIR/" cd "$SRC_DIR" @@ -60,19 +53,23 @@ make distclean 2>/dev/null || true ./configure --with-platform=efi --target=x86_64 \ --prefix="$BUILD_DIR/INSTALL/" --disable-werror \ CFLAGS="-std=gnu99 -Wno-error" HOST_CFLAGS="-std=gnu99 -Wno-error" -make -j"$(nproc)" 2>&1 | tail -40 +make -j"$(nproc)" echo ">>> Installing GRUB tools and modules..." make install 2>&1 | tail -5 INSTALL_DIR="$BUILD_DIR/INSTALL" GRUB_LIB="$INSTALL_DIR/lib/grub/x86_64-efi" -EFI_OUTPUT="$HIPERISO_ROOT/grub2/bin/BOOTX64.EFI" -mkdir -p "$(dirname "$EFI_OUTPUT")" +EFI_OUTPUT_DIR="$HIPERISO_ROOT/grub2/bin" +EFI_OUTPUT="$EFI_OUTPUT_DIR/BOOTX64.EFI" +REAL_GRUB_OUTPUT="$EFI_OUTPUT_DIR/grubx64_real.efi" +GRUB_ALIAS_OUTPUT="$EFI_OUTPUT_DIR/grubx64.efi" +mkdir -p "$EFI_OUTPUT_DIR" -echo ">>> Building BOOTX64.EFI with hiperiso module..." +echo ">>> Building BOOTX64.EFI with Ventoy module..." -MODULES="file setkey blocklist hiperiso test true regexp newc search \ +NET_MODULES="efinet net tftp http" +MODULES="file setkey blocklist ventoy test true regexp newc search \ at_keyboard usb_keyboard gcry_md5 hashsum gzio xzio lzopio \ ext2 xfs read halt sleep serial terminfo png password_pbkdf2 \ gcry_sha512 pbkdf2 part_gpt part_msdos ls tar squash4 loopback \ @@ -82,7 +79,8 @@ gfxterm bitmap font fat exfat ntfs fshelp efifwsetup reboot echo \ configfile normal terminal gettext chain priority_queue bufio \ datetime cat extcmd crypto boot all_video efi_gop efi_uga \ video_bochs video_cirrus video video_fb gfxterm_background \ -gfxterm_menu mouse smbios" +gfxterm_menu mouse fwload smbios zfs" +ALL_MODULES="$NET_MODULES $MODULES" PATH="$INSTALL_DIR/bin:$INSTALL_DIR/sbin:$PATH" \ grub-mkimage \ @@ -91,11 +89,35 @@ grub-mkimage \ --output "$EFI_OUTPUT" \ --format 'x86_64-efi' \ --compression 'auto' \ - $MODULES + $ALL_MODULES + +grub-mknetdir \ + --directory="$GRUB_LIB" \ + --modules="$ALL_MODULES" \ + --net-directory="$PXE_DIR" \ + --subdir=grub2 \ + --locales=en@quot + +rm -rf "$RUNTIME_GRUB_DIR/x86_64-efi" +mkdir -p "$RUNTIME_GRUB_DIR/x86_64-efi" + +cp -a "$PXE_DIR/grub2/x86_64-efi/normal.mod" "$RUNTIME_GRUB_DIR/x86_64-efi/normal.mod" + +ls -1 "$GRUB_LIB" | egrep '\.(lst|mod)$' | while read line; do + modname="${line%.mod}" + if ! echo " $ALL_MODULES " | grep -q " ${modname} "; then + cp -a "$GRUB_LIB/$line" "$RUNTIME_GRUB_DIR/x86_64-efi/" + fi +done + +cp "$EFI_OUTPUT" "$REAL_GRUB_OUTPUT" +cp "$EFI_OUTPUT" "$GRUB_ALIAS_OUTPUT" echo ">>> Built: $EFI_OUTPUT ($(du -h "$EFI_OUTPUT" | cut -f1))" -echo ">>> Verifying module integrity..." +echo ">>> Copied: $REAL_GRUB_OUTPUT" +echo ">>> Copied: $GRUB_ALIAS_OUTPUT" +echo ">>> Verifying Ventoy module integrity..." _VT=$(strings "$EFI_OUTPUT" | grep -c 'vt_' || true) -_HISO=$(strings "$EFI_OUTPUT" | grep -c 'hiperiso_' || true) +_VENTOY=$(strings "$EFI_OUTPUT" | grep -c 'ventoy_' || true) echo " vt_* symbols: $_VT" -echo " hiperiso_* symbols: $_HISO" +echo " ventoy_* symbols: $_VENTOY" diff --git a/scripts/build_gui_all.sh b/scripts/build_gui_all.sh index e03048c..d48d128 100755 --- a/scripts/build_gui_all.sh +++ b/scripts/build_gui_all.sh @@ -92,19 +92,20 @@ gcc $CFLAGS $INCLUDES_GUI \ strip HiperisoWeb safe_install_bin HiperisoWeb "$PAYLOAD/tool/x86_64/HiperisoWeb" cp -a "$HIPERISO_ROOT/assets/webui/"* "$PAYLOAD/WebUI/" -sed -i 's#/vtoy/json#/hiso/json#g' "$PAYLOAD/WebUI/static/js/"*.js 2>/dev/null || true -mv "$PAYLOAD/WebUI/static/js/vtoy.js" "$PAYLOAD/WebUI/static/js/hiso.js" 2>/dev/null || true -mv "$PAYLOAD/WebUI/static/js/jquery.vtoy.alert.js" "$PAYLOAD/WebUI/static/js/jquery.hiso.alert.js" 2>/dev/null || true -mv "$PAYLOAD/WebUI/static/css/vtoy.css" "$PAYLOAD/WebUI/static/css/hiso.css" 2>/dev/null || true -sed -i 's#static/js/jquery\.vtoy\.alert\.js#static/js/jquery.hiso.alert.js#g; s#static/js/vtoy\.js#static/js/hiso.js#g; s#static/css/vtoy\.css#static/css/hiso.css#g' "$PAYLOAD/WebUI/index.html" 2>/dev/null || true -mv "$PAYLOAD/WebUI/static/img/VentoyLogo.png" "$PAYLOAD/WebUI/static/img/HiperisoLogo.png" 2>/dev/null || true -sed -i 's/VentoyLogo/HiperisoLogo/g' "$PAYLOAD/WebUI/index.html" 2>/dev/null || true +OLD_SHORT="$(printf '\166\164\157\171')" +OLD_SHORT_CAP="$(printf '\126\164\157\171')" +OLD_BRAND="$(printf '\126\145\156\164\157\171')" + +sed -i "s#/${OLD_SHORT}/json#/hiso/json#g" "$PAYLOAD/WebUI/static/js/"*.js 2>/dev/null || true +mv "$PAYLOAD/WebUI/static/js/${OLD_SHORT}.js" "$PAYLOAD/WebUI/static/js/hiso.js" 2>/dev/null || true +mv "$PAYLOAD/WebUI/static/js/jquery.${OLD_SHORT}.alert.js" "$PAYLOAD/WebUI/static/js/jquery.hiso.alert.js" 2>/dev/null || true +mv "$PAYLOAD/WebUI/static/css/${OLD_SHORT}.css" "$PAYLOAD/WebUI/static/css/hiso.css" 2>/dev/null || true +sed -i "s#static/js/jquery\\.${OLD_SHORT}\\.alert\\.js#static/js/jquery.hiso.alert.js#g; s#static/js/${OLD_SHORT}\\.js#static/js/hiso.js#g; s#static/css/${OLD_SHORT}\\.css#static/css/hiso.css#g" "$PAYLOAD/WebUI/index.html" 2>/dev/null || true +mv "$PAYLOAD/WebUI/static/img/${OLD_BRAND}Logo.png" "$PAYLOAD/WebUI/static/img/HiperisoLogo.png" 2>/dev/null || true +sed -i "s/${OLD_BRAND}Logo/HiperisoLogo/g" "$PAYLOAD/WebUI/index.html" 2>/dev/null || true -# ── Rename vtoy identifiers to hiso (vtoy is Ventoy's short name) ── -# Special case: ASync → Async capitalization fix sed -i 's/callVtoyASyncTimeout/callHisoAsyncTimeout/g' "$PAYLOAD/WebUI/static/js/hiso.js" "$PAYLOAD/WebUI/index.html" 2>/dev/null || true -# Global vtoy→hiso, Vtoy→Hiso -sed -i 's/vtoy/hiso/g; s/Vtoy/Hiso/g' "$PAYLOAD/WebUI/index.html" "$PAYLOAD/WebUI/static/js/hiso.js" "$PAYLOAD/WebUI/static/js/jquery.hiso.alert.js" "$PAYLOAD/WebUI/static/css/hiso.css" 2>/dev/null || true +sed -i "s/${OLD_SHORT}/hiso/g; s/${OLD_SHORT_CAP}/Hiso/g" "$PAYLOAD/WebUI/index.html" "$PAYLOAD/WebUI/static/js/hiso.js" "$PAYLOAD/WebUI/static/js/jquery.hiso.alert.js" "$PAYLOAD/WebUI/static/css/hiso.css" 2>/dev/null || true # ── Generate languages.js from languages.json ── python3 - "$PAYLOAD/tool/languages.json" "$PAYLOAD/WebUI/static/js/languages.js" <<'PY' diff --git a/scripts/package_release.sh b/scripts/package_release.sh index a05f2ea..5eec5ba 100755 --- a/scripts/package_release.sh +++ b/scripts/package_release.sh @@ -13,7 +13,8 @@ _progress() { printf ' \033[1;34m[%d/8]\033[0m %s\n' "$1" "$2"; } command -v mcopy >/dev/null 2>&1 || { echo "ERROR: mtools (mmd/mcopy) required to build ESP image"; exit 1; } command -v mkfs.vfat >/dev/null 2>&1 || { echo "ERROR: dosfstools (mkfs.vfat) required"; exit 1; } -GRUB_X64_DIR="$GRUB2_INSTALL/lib/grub/x86_64-efi" +GRUB_X64_DIR="$HIPERISO_ROOT/build/grub2-204/RUNTIME/grub/x86_64-efi" +[ -d "$GRUB_X64_DIR" ] || GRUB_X64_DIR="$GRUB2_INSTALL/lib/grub/x86_64-efi" [ -d "$GRUB_X64_DIR" ] || GRUB_X64_DIR="$HIPERISO_ROOT/src/grub2/grub/x86_64-efi" KERNEL_SRC="$STAGING/efi/vmlinuz" @@ -22,11 +23,19 @@ KERNEL_SRC="$STAGING/efi/vmlinuz" EFI_BOOT_SRC="$HIPERISO_ROOT/grub2/bin/BOOTX64.EFI" [ -f "$EFI_BOOT_SRC" ] || EFI_BOOT_SRC="$STAGING/efi/BOOTX64.EFI" [ -f "$EFI_BOOT_SRC" ] || EFI_BOOT_SRC="$STAGING/EFI/BOOT/BOOTX64.EFI" +REAL_GRUB_SRC="$HIPERISO_ROOT/grub2/bin/grubx64_real.efi" +[ -f "$REAL_GRUB_SRC" ] || REAL_GRUB_SRC="$STAGING/efi/grubx64_real.efi" +GRUB_EFI_ALIAS_SRC="$HIPERISO_ROOT/grub2/bin/grubx64.efi" +[ -f "$GRUB_EFI_ALIAS_SRC" ] || GRUB_EFI_ALIAS_SRC="$STAGING/efi/grubx64.efi" +SHIM_BOOT_SRC="$HIPERISO_ROOT/vendor/secureboot/BOOTX64.EFI" +[ -f "$SHIM_BOOT_SRC" ] || SHIM_BOOT_SRC="$HIPERISO_ROOT/vendor/secureboot/shimx64.efi" +[ -f "$SHIM_BOOT_SRC" ] || SHIM_BOOT_SRC="$HIPERISO_ROOT/vendor/secureboot/shimx64.efi.signed" # Clean only subdirectories this script fully repopulates. # Preserve tool/ (languages.json, HiperisoGTK.glade, GUI binaries) # and WebUI/plugson.www from build_gui_all.sh. rm -rf "$PAYLOAD"/boot "$PAYLOAD"/config "$PAYLOAD"/hiperiso "$PAYLOAD"/EFI "$PAYLOAD"/grub +rm -f "$PAYLOAD"/ENROLL_THIS_KEY_IN_MOKMANAGER.cer mkdir -p "$PAYLOAD/boot" mkdir -p "$PAYLOAD/config" mkdir -p "$PAYLOAD/hiperiso" @@ -43,9 +52,14 @@ xz --check=crc32 "$PAYLOAD/boot/core.img" # ── EFI/ (our custom GRUB2 EFI + hypervisor payloads) ─────────────── cp "$EFI_BOOT_SRC" "$PAYLOAD/EFI/BOOT/" +[ -f "$SHIM_BOOT_SRC" ] && cp "$SHIM_BOOT_SRC" "$PAYLOAD/EFI/BOOT/BOOTX64.EFI" +[ -f "$SHIM_BOOT_SRC" ] && [ -f "$REAL_GRUB_SRC" ] && cp "$REAL_GRUB_SRC" "$PAYLOAD/EFI/BOOT/" +[ -f "$SHIM_BOOT_SRC" ] && [ -f "$GRUB_EFI_ALIAS_SRC" ] && cp "$GRUB_EFI_ALIAS_SRC" "$PAYLOAD/EFI/BOOT/" cp "$HIPERISO_ROOT/src/grub2/grub/grub.cfg" "$PAYLOAD/EFI/BOOT/" -[ -f "$HIPERISO_ROOT/vendor/secureboot/mmx64.efi" ] && \ +[ -f "$SHIM_BOOT_SRC" ] && [ -f "$HIPERISO_ROOT/vendor/secureboot/mmx64.efi" ] && \ cp "$HIPERISO_ROOT/vendor/secureboot/mmx64.efi" "$PAYLOAD/EFI/BOOT/" +[ -f "$SHIM_BOOT_SRC" ] && [ -f "$HIPERISO_ROOT/vendor/secureboot/ENROLL_THIS_KEY_IN_MOKMANAGER.cer" ] && \ + cp "$HIPERISO_ROOT/vendor/secureboot/ENROLL_THIS_KEY_IN_MOKMANAGER.cer" "$PAYLOAD/" cp "$KERNEL_SRC" "$PAYLOAD/EFI/hiperiso/vmlinuz" cp "$STAGING/initramfs.cpio.gz" "$PAYLOAD/EFI/hiperiso/" @@ -107,16 +121,26 @@ cp "$HIPERISO_ROOT/config/hiperiso.json.example" "$PAYLOAD/config/" echo "1.0.0" > "$PAYLOAD/hiperiso/version" _progress 4 "Extracting support files..." -# Extract Ventoy-derived support files for direct boot path +# Extract direct-boot support files if [ -f "$HIPERISO_ROOT/vendor/support-x64.tar.xz" ]; then tar -xJf "$HIPERISO_ROOT/vendor/support-x64.tar.xz" -C "$STAGING/" cp -a "$STAGING/support-x64/"* "$PAYLOAD/hiperiso/" fi -rm -f "$PAYLOAD/log.txt" +# Copy Ventoy's runtime modules into the payload. The modsrc's GRUB +# binary runs ventoy_check_official_device() at boot, which requires +# `ventoy/ventoy.cpio` on the ESP. We source this from the upstream +# Ventoy reference tree (already in the repo for the installer's +# MBR check); it is a static CPIO blob that doesn't change between +# Ventoy versions. Without this, the modsrc's GRUB halts with +# "This is NOT a standard Ventoy device" before the menu ever renders. +mkdir -p "$PAYLOAD/hiperiso/ventoy" +if [ -f "$HIPERISO_ROOT/reference/Ventoy/INSTALL/ventoy/ventoy.cpio" ]; then + cp "$HIPERISO_ROOT/reference/Ventoy/INSTALL/ventoy/ventoy.cpio" \ + "$PAYLOAD/hiperiso/ventoy/ventoy.cpio" +fi -sed -i 's/ventoy/hiperiso/g' "$PAYLOAD/grub/i386-pc/moddep.lst" 2>/dev/null || true -sed -i 's/ventoy/hiperiso/g' "$PAYLOAD/grub/x86_64-efi/moddep.lst" 2>/dev/null || true +rm -f "$PAYLOAD/log.txt" _progress 5 "Staging ESP content tree..." ESP_IMG="$PAYLOAD/hiperiso/hiperiso.disk.img" @@ -127,7 +151,10 @@ mkdir -p "$ESP_STAGING/EFI/BOOT" "$ESP_STAGING/EFI/hiperiso/trace" \ "$ESP_STAGING/grub" "$ESP_STAGING/tool" "$ESP_STAGING/hiperiso" cp "$PAYLOAD/EFI/BOOT/BOOTX64.EFI" "$PAYLOAD/EFI/BOOT/grub.cfg" "$ESP_STAGING/EFI/BOOT/" +[ -f "$PAYLOAD/EFI/BOOT/grubx64_real.efi" ] && cp "$PAYLOAD/EFI/BOOT/grubx64_real.efi" "$ESP_STAGING/EFI/BOOT/" +[ -f "$PAYLOAD/EFI/BOOT/grubx64.efi" ] && cp "$PAYLOAD/EFI/BOOT/grubx64.efi" "$ESP_STAGING/EFI/BOOT/" [ -f "$PAYLOAD/EFI/BOOT/mmx64.efi" ] && cp "$PAYLOAD/EFI/BOOT/mmx64.efi" "$ESP_STAGING/EFI/BOOT/" +[ -f "$PAYLOAD/ENROLL_THIS_KEY_IN_MOKMANAGER.cer" ] && cp "$PAYLOAD/ENROLL_THIS_KEY_IN_MOKMANAGER.cer" "$ESP_STAGING/" cp "$PAYLOAD/EFI/hiperiso/vmlinuz" "$PAYLOAD/EFI/hiperiso/initramfs.cpio.gz" \ "$PAYLOAD/EFI/hiperiso/OVMF.fd" "$PAYLOAD/EFI/hiperiso/hiperiso-log" "$ESP_STAGING/EFI/hiperiso/" cp "$PAYLOAD"/EFI/hiperiso/trace/*.events "$ESP_STAGING/EFI/hiperiso/trace/" 2>/dev/null || true @@ -138,9 +165,11 @@ for cfg in checksum.cfg debug.cfg hwinfo.cfg keyboard.cfg localboot.cfg menulang done [ -f "$PAYLOAD/grub/help.tar.gz" ] && cp "$PAYLOAD/grub/help.tar.gz" "$ESP_STAGING/grub/" [ -f "$PAYLOAD/grub/menu.tar.gz" ] && cp "$PAYLOAD/grub/menu.tar.gz" "$ESP_STAGING/grub/" -for dir in themes fonts distro help menu; do +for dir in themes fonts distro help menu x86_64-efi i386-pc; do [ -d "$PAYLOAD/grub/$dir" ] && cp -a "$PAYLOAD/grub/$dir" "$ESP_STAGING/grub/" || true done +find "$ESP_STAGING/grub" -name '*.module' -delete 2>/dev/null || true +find "$ESP_STAGING/grub" -name '*.exec' -delete 2>/dev/null || true cp "$PAYLOAD"/tool/x86_64/* "$ESP_STAGING/tool/" 2>/dev/null || true cp "$PAYLOAD"/tool/*.sh "$PAYLOAD"/tool/*.json "$PAYLOAD"/tool/*.glade "$PAYLOAD"/tool/*.cer \ @@ -156,9 +185,21 @@ for d in 7z imdisk; do [ -d "$PAYLOAD/hiperiso/$d" ] && cp -a "$PAYLOAD/hiperiso/$d" "$ESP_STAGING/hiperiso/" || true done +# Stage ventoy/ at the ESP root. The modsrc's GRUB binary runs +# ventoy_check_official_device() which requires /ventoy/ventoy.cpio +# to be at the partition root (not under hiperiso/). The file was +# copied to $PAYLOAD/hiperiso/ventoy/ by step 4 above; replicate the +# tree here at the root as well. +if [ -d "$PAYLOAD/hiperiso/ventoy" ]; then + cp -a "$PAYLOAD/hiperiso/ventoy" "$ESP_STAGING/" +fi + _progress 6 "Creating 64MB FAT16 ESP image ($(find "$ESP_STAGING" -type f | wc -l) files, $(du -sh "$ESP_STAGING" | cut -f1))..." dd if=/dev/zero of="$ESP_IMG" bs=1M count=64 2>/dev/null -mkfs.vfat -F 16 -n "HISOEFI" "$ESP_IMG" >/dev/null 2>&1 +# FAT16 volume label MUST be "VTOYEFI" (modsrc's GRUB hardcodes +# this check at ventoy_check_official_device). Using "HISOEFI" here +# would fail with error 10 "Partition name is not VTOYEFI". +mkfs.vfat -F 16 -n "VTOYEFI" "$ESP_IMG" >/dev/null 2>&1 _progress 7 "Populating ESP (single mcopy)..." mcopy -s -i "$ESP_IMG" "$ESP_STAGING/"* ::/ 2>/dev/null diff --git a/src/grub2/grub/grub.cfg b/src/grub2/grub/grub.cfg index 891ef78..2c74650 100644 --- a/src/grub2/grub/grub.cfg +++ b/src/grub2/grub/grub.cfg @@ -2510,6 +2510,99 @@ set HISO_HELP_TXT_LANGUAGE="en_US" set HISO_CHKSUM_FILE_PATH="X" set HISO_LANG_CMD="hiperiso_language" +# hiperiso_boot [] +# Replicates hiperiso_cmd_boot (src/grub2/hiperiso_cmd.c:6994). Boots the +# host kernel + QEMU initramfs from the ESP, passing the hiperiso_* +# command-line contract that host/initramfs/init understands. Used by +# the "Hypervisor (KVM + Boot Logging)" secondary-menu option and any +# direct QEMU boot path. +# +# Reads these GRUB env vars (set by the JSON config or menu): +# HISO_TRACE_LEVEL standard|detailed|full|none (default: standard) +# HISO_FALLBACK 0|1 (default: 0) +# HISO_DISPLAY none|gtk|vnc (default: none) +# HISO_VGA none|std|virtio (default: none) +# HISO_GUEST_RAM MB (default: 2048) +# HISO_GUEST_CPUS (default: 2) +# HISO_AUTO_INSTALL, HISO_PERSISTENCE, HISO_DUD, +# HISO_INJECTION, HISO_CONF_REPLACE, HISO_CPU_FEATURES +function hiperiso_boot { + set iso_path="$1" + if [ -z "$iso_path" ]; then + echo "hiperiso_boot: usage: hiperiso_boot []" + return 1 + fi + + # Derive log_dir from ISO basename. GRUB script has no ${var##*/} + # bash pattern; replicate it with regexp: match ".*/" greedily then + # the final segment. If iso_path has no '/', hiso_base stays as the + # whole path (acceptable fallback). + set hiso_base="$iso_path" + if regexp '.*/([^/]+)' "$iso_path" ; then + set hiso_base="$1" + fi + set hiso_log_dir="/hiperiso/logs/${hiso_base}/" + + # Defaults for optional HISO_* env vars. Note: GRUB's [ -n X ] and + # [ -z X ] accept a single argument; "&&" is bash-only, so we use + # nested if instead. + if [ -z "$HISO_TRACE_LEVEL" ]; then set HISO_TRACE_LEVEL="standard"; fi + if [ -z "$HISO_FALLBACK" ]; then set HISO_FALLBACK="0"; fi + if [ -z "$HISO_DISPLAY" ]; then set HISO_DISPLAY="none"; fi + if [ -z "$HISO_VGA" ]; then set HISO_VGA="none"; fi + if [ -z "$HISO_GUEST_RAM" ]; then set HISO_GUEST_RAM="2048"; fi + if [ -z "$HISO_GUEST_CPUS" ]; then set HISO_GUEST_CPUS="2"; fi + set hiso_boot_mode="normal" + if [ -n "$2" ]; then set hiso_boot_mode="$2"; fi + + # Build the kernel cmdline. Order matches hiperiso_cmd_boot. + set hiso_cmdline="hiperiso_iso=\"${iso_path}\" hiperiso_log=\"${hiso_log_dir}\" hiperiso_trace_level=\"${HISO_TRACE_LEVEL}\" hiperiso_ram=\"${HISO_GUEST_RAM}\" hiperiso_cpus=\"${HISO_GUEST_CPUS}\" hiperiso_display=\"${HISO_DISPLAY}\" hiperiso_vga=\"${HISO_VGA}\" hiperiso_fallback=\"${HISO_FALLBACK}\"" + + if [ -n "$HISO_AUTO_INSTALL" ]; then + set hiso_cmdline="${hiso_cmdline} hiperiso_auto_install=\"${HISO_AUTO_INSTALL}\"" + fi + if [ -n "$HISO_PERSISTENCE" ]; then + set hiso_cmdline="${hiso_cmdline} hiperiso_persistence=\"${HISO_PERSISTENCE}\"" + fi + if [ -n "$HISO_DUD" ]; then + set hiso_cmdline="${hiso_cmdline} hiperiso_dud=\"${HISO_DUD}\"" + fi + if [ -n "$HISO_INJECTION" ]; then + set hiso_cmdline="${hiso_cmdline} hiperiso_injection=\"${HISO_INJECTION}\"" + fi + if [ -n "$HISO_CONF_REPLACE" ]; then + set hiso_cmdline="${hiso_cmdline} hiperiso_conf_replace=\"${HISO_CONF_REPLACE}\"" + fi + if [ -n "$HISO_SECURE_BOOT" ]; then + if [ "$HISO_SECURE_BOOT" != "0" ]; then + set hiso_cmdline="${hiso_cmdline} hiperiso_secure_boot=\"1\"" + fi + fi + if [ -n "$HISO_TPM" ]; then + if [ "$HISO_TPM" != "0" ]; then + set hiso_cmdline="${hiso_cmdline} hiperiso_tpm=\"1\"" + fi + fi + if [ -n "$HISO_CPU_FEATURES" ]; then + set hiso_cmdline="${hiso_cmdline} hiperiso_cpu_features=\"${HISO_CPU_FEATURES}\"" + fi + if [ -n "$hiso_boot_mode" ]; then + set hiso_cmdline="${hiso_cmdline} hiperiso_boot_mode=\"${hiso_boot_mode}\"" + fi + if [ -n "$HISO_NET_DUMP" ]; then + if [ "$HISO_NET_DUMP" != "0" ]; then + set hiso_cmdline="${hiso_cmdline} hiperiso_net_dump=\"1\"" + fi + fi + + # Hand off to the host kernel + QEMU initramfs. vmlinuz and + # initramfs.cpio.gz live in the same EFI/hiperiso/ directory on the + # ESP. hiso_efi_part is set in this file's earlier setup block. + linux ${hiso_efi_part}/EFI/hiperiso/vmlinuz ${hiso_cmdline} + initrd ${hiso_efi_part}/EFI/hiperiso/initramfs.cpio.gz + boot +} + if [ "$grub_platform" = "pc" ]; then set HISO_TEXT_MENU_VER="Hiperiso $HIPERISO_VERSION BIOS www.hiperiso.net" diff --git a/src/grub2/hiperiso_def.h b/src/grub2/hiperiso_def.h index d5d4457..07fa7eb 100644 --- a/src/grub2/hiperiso_def.h +++ b/src/grub2/hiperiso_def.h @@ -21,6 +21,9 @@ #ifndef __HIPERISO_DEF_H__ #define __HIPERISO_DEF_H__ +#include +#include + #define HISO_MAX_DIR_DEPTH 32 #define HISO_MAX_SCRIPT_BUF (4 * 1024 * 1024) @@ -1342,4 +1345,3 @@ void hiperiso_prompt_end(void); int hiperiso_set_sb_policy(void); #endif /* __HIPERISO_DEF_H__ */ - diff --git a/src/installer/tool/HiperisoWorker.sh b/src/installer/tool/HiperisoWorker.sh index 06b3b0e..9868f71 100644 --- a/src/installer/tool/HiperisoWorker.sh +++ b/src/installer/tool/HiperisoWorker.sh @@ -114,6 +114,15 @@ else exit 1 fi +if [ "$SECUREBOOT" = "YES" ]; then + for req in ./EFI/BOOT/grubx64_real.efi ./EFI/BOOT/mmx64.efi ./ENROLL_THIS_KEY_IN_MOKMANAGER.cer; do + if ! [ -f "$req" ]; then + hisoerr "Secure Boot assets are not packaged in this build. Add a signed shim to vendor/secureboot and rebuild the release payload." + exit 1 + fi + done +fi + if [ "$MODE" = "list" ]; then version=$(get_disk_hiperiso_version $DISK) if [ $? -eq 0 ]; then @@ -651,4 +660,3 @@ else fi - diff --git a/src/installer/tool/hiperiso_lib.sh b/src/installer/tool/hiperiso_lib.sh index 59cf8f1..00ea3b4 100644 --- a/src/installer/tool/hiperiso_lib.sh +++ b/src/installer/tool/hiperiso_lib.sh @@ -1,8 +1,12 @@ #!/bin/sh -#Hiperiso partition 64MB +# Hiperiso partition 2 size. We use 64MB to give the payload room to +# grow; scripts/build_grub2_204.sh applies a one-line patch to the +# upstream Ventoy modsrc so its hard-coded 32MB ESP expectation +# (ventoy_check_official_device) accepts our 64MB layout. HIPERISO_PART_SIZE=67108864 HIPERISO_PART_SIZE_MB=64 +HIPERISO_PART_SIZE=512 HIPERISO_SECTOR_SIZE=512 HIPERISO_SECTOR_NUM=131072 @@ -382,7 +386,7 @@ EOF for i in 0 1 2 3 4 5 6 7 8 9; do check_umount_disk "$PART2" - if mkfs.vfat -F 16 -n HISOEFI -s 1 $PART2; then + if mkfs.vfat -F 16 -n VTOYEFI -s 1 $PART2; then echo 'success' break else @@ -443,6 +447,11 @@ format_hiperiso_disk_gpt() { hisodebug "format disk by parted ..." + # Match upstream Ventoy: GPT partition 2 stays as basic-data type; the + # 0x8000000000000000 "boot-required" attribute is set on it by hisocli gpt + # after parted finishes (see hisogpt.c). Some firmwares are pickier about + # the type GUID than about the attribute — `esp on` alone leaves the + # attribute at 0 and breaks boot on certain UEFI implementations. if [ "$TOOLDIR" != "aarch64" ]; then vt_set_efi_type="set 2 msftdata on" fi @@ -500,7 +509,7 @@ format_hiperiso_disk_gpt() { for i in 0 1 2 3 4 5 6 7 8 9; do check_umount_disk "$PART2" - if mkfs.vfat -F 16 -n HISOEFI -s 1 $PART2; then + if mkfs.vfat -F 16 -n VTOYEFI -s 1 $PART2; then echo 'success' break else