Skip to content

ADR 007: Dual-firmware partman recipe (UEFI + BIOS legacy on GPT)

Synced read-only from /home/synnet/mirrors/synvirt-product/docs/decisions/007-dual-firmware-partman-recipe.md. Edit at the source, not here.

ADR 007: Dual-firmware partman recipe (UEFI + BIOS legacy on GPT)

Section titled “ADR 007: Dual-firmware partman recipe (UEFI + BIOS legacy on GPT)”

Accepted

The SynVirt 0.1.x ISO originally shipped a partman-auto recipe with two silent defects:

  1. The ESP partition declared method{ efi } but with filesystem free (unallocated space). partman treated the partition as unassigned and never formatted it.
  2. The root partition used $primary{ } (a flag valid only for MBR) in combination with $iflabel{ gpt } on the ESP. Under UEFI firmware, partman forces GPT, and this combination silently suppresses the registration of mountpoint{ / } on the root partition.

Consequences observed in the field:

  • On test runtimes with BIOS legacy + MBR, the installer tolerated the error and completed a working install.

  • On test runtimes with strict UEFI firmware + SCSI disk (where partman forces GPT), the installer failed with:

    "No se definio un sistema de ficheros raiz"

Additionally, the recipe did not include a biosgrub partition, which blocked legacy BIOS boot from a GPT disk (an edge case on older physical hardware or VMs configured with BIOS firmware despite GPT labeling).

The product is designed to install on any firmware / disk combination that Debian 13 Trixie supports. The installer must be 100 % unattended (preseed), and the only wizard the operator interacts with is the Ratatui TUI on first boot.

  1. Rewrite the synvirt recipe in iso-builder/preseed/synvirt.preseed with three partitions on GPT:
    • biosgrub, 1 MB (method{ biosgrub })
    • ESP, 512 MB fat32 (method{ efi })
    • /, ext4 (the rest of the disk)
  2. Remove $primary{ } (MBR-only) and set $iflabel{ gpt } on all three partitions to force a consistent GPT layout.
  3. Keep the early_command that resolves the first disk via list-devices disk, so the recipe supports /dev/sda, /dev/vda, /dev/nvme0n1, /dev/hda without changes to the preseed.
  4. Add -isohybrid-mbr /usr/lib/ISOLINUX/isohdpfx.bin to the xorriso invocation, producing a hybrid-MBR ISO that also boots from USB under BIOS legacy.
  5. Copy the preseed to the ISO at /preseed/synvirt.preseed and reference it as preseed/file=/cdrom/preseed/synvirt.preseed in both the BIOS (isolinux) and UEFI (GRUB) kernel command lines. Preseed injection via initrd prepend is kept as a safety net.
  • A single recipe that works on both BIOS and UEFI avoids maintaining two ISOs or two preseeds. This simplifies QA.
  • The biosgrub partition is 1 MB and harmless under UEFI (it is never mounted). Its presence lets grub-pc install stage 1.5 on a GPT disk when the firmware is BIOS.
  • method{ efi } with filesystem fat32 is the documented correct form in /usr/lib/partman/recipes-amd64/*. Replacing free with fat32 fixes the bug without altering the intended semantics.
  • Removing $primary{ } is the most important correction: it is the root cause of the “no root filesystem defined” failure observed under strict UEFI firmware.
  • isohdpfx.bin ships with the isolinux package (already verified in build.sh). Adding -isohybrid-mbr costs 0 KB in the resulting ISO.

Positive:

  • The ISO boots on any firmware/disk combination Debian 13 supports: BIOS legacy or UEFI, SATA / SCSI / VirtIO / NVMe, on physical hardware or in any virtualization runtime, including as a USB image written with dd.
  • early_command + the fallback disk list cover the common device-naming schemes without manual intervention.
  • Zero maintenance burden for BIOS-only vs UEFI-only variants.

Negative:

  • The target disk needs a minimum of ~11 GB (1 MB biosgrub + 538 MB ESP
    • 10 GB root). Still well below the product’s recommended 60 GB for a Standalone deployment.
  • The biosgrub partition “wastes” 1 MB on UEFI systems that will never use it. Negligible.
  1. Detect firmware in early_command and emit different recipes: complex, fragile, doubles the QA surface.
  2. Use method{ biosgrub } conditionally with $bootable{ } on the ESP: not supported by partman-auto; biosgrub must be its own partition.
  3. Distribute two ISOs (SynVirt-bios.iso and SynVirt-uefi.iso): duplicates builds and confuses end users.
  4. Migrate to ZFS-on-root via preseed immediately: incompatible with the stock Debian installer, requires a custom d-i build. Staged for Hito 3 (see ADR 003 and Issue 001).