Installing Home Assistant OS on legacy BIOS hardware (no UEFI) — fixing “no BIOS Boot Partition” / GRUB won’t embed
TL;DR: If you’re trying to install the generic x86-64 HAOS image on an old machine with a conventional BIOS and no UEFI support at all, grub-install will likely fail to embed properly on HAOS’s GPT disk layout, because there’s no dedicated BIOS Boot Partition for it to use. The fix is to manually create one. Full steps below.
The problem
HAOS’s official generic x86-64 image is built assuming UEFI boot. If your hardware only has a legacy BIOS (no UEFI at all), the stock image won’t boot as-is.
There’s a known community workaround — install a small legacy GRUB “bridge” that chainloads into HAOS’s own real, unmodified grub.cfg, letting HAOS’s normal A/B slot boot logic run as intended. This works well on some older boards. On others, you’ll hit this when running grub-install:
grub-install: warning: this GPT partition label contains no BIOS Boot Partition; embedding won't be possible.
grub-install: warning: Embedding is not possible. GRUB can only be installed in this setup by using blocklists. However, blocklists are UNRELIABLE and their use is discouraged.
It’ll still say “Installation finished. No error reported,” which is misleading — booting afterward typically hangs at “Attempting to boot from hard disk” with no further progress, or fails in some other unreliable way, because GRUB fell back to hardcoding raw disk sector addresses (“blocklists”) instead of properly embedding itself. Blocklists break if literally anything shifts on disk afterward.
Why this happens
Legacy BIOS firmware only knows how to execute a tiny 512-byte boot sector — nowhere near enough space for a real bootloader. GRUB solves this in two stages: a minimal boot.img that fits in that sector, which loads a larger core.img containing the real bootloader logic.
On old MBR-partitioned disks, there was historically a small gap of unused space right after the boot sector where core.img could be tucked away for free. GPT disks (which HAOS uses) reserve that same region for the GPT header/partition table itself, so that free hiding spot no longer exists. GRUB’s answer for GPT disks is a dedicated tiny partition (1–8MB), flagged specifically as a BIOS Boot Partition, whose only job is holding core.img.
If your target disk’s GPT layout doesn’t have one (which HAOS’s stock image doesn’t, since it’s designed around UEFI, not this legacy trick), grub-install has nowhere safe to embed into and silently degrades to the unreliable blocklist method instead.
The fix
Create the missing BIOS Boot Partition yourself before running grub-install.
Prerequisites
- A Linux live USB (Ubuntu/Debian) with
parted,grub2 - The HAOS generic x86-64
.imgfile, decompressed - Your target disk device confirmed (this is destructive — check
lsblkcarefully)
1. Wipe the target disk
lsblk # confirm target device, e.g. /dev/sdb
sudo umount /dev/sdb* 2>/dev/null
sudo wipefs -a /dev/sdb
2. Write the HAOS image
sudo dd if=/path/to/haos_generic-x86-64-XX.X.img of=/dev/sdb bs=4M status=progress conv=fsync
sync
sudo partprobe /dev/sdb
lsblk # confirm sdb1–sdb8, standard HAOS layout
3. Resize the data partition and add the bridge + BIOS Boot partitions
sudo parted /dev/sdb
Inside parted, check free space first:
unit MiB print free
Resize the data partition (partition 8) to your preferred size, leaving room after it. Example assumes it currently starts at 697MiB and you want it to be 32GB total:
resizepart 8 33465MiB
mkpart primary ext4 33465MiB 33475MiB
mkpart primary 33475MiB 33483MiB
print
Note the number of that last 8MB partition (call it N), then:
set N bios_grub on
print
quit
4. Format the bridge partition
sudo mkfs.ext4 /dev/sdb9
(adjust the partition number if it landed differently)
5. Fix a known grubenv path bug in HAOS’s own grub.cfg
Separately from the BIOS Boot Partition issue, HAOS’s real grub.cfg assumes GRUB already knows where its own environment file lives — true under normal UEFI boot, but not when chainloaded from a separate legacy GRUB install. Fix it:
sudo mkdir -p /mnt/haos_boot
sudo mount /dev/sdb1 /mnt/haos_boot
sudo sed -i 's|^load_env$|load_env --file (hd0,gpt1)/efi/boot/grubenv|' /mnt/haos_boot/efi/boot/grub.cfg
sudo sed -i 's|^save_env A_TRY A_OK B_TRY B_OK ORDER MACHINE_ID$|save_env --file (hd0,gpt1)/efi/boot/grubenv A_TRY A_OK B_TRY B_OK ORDER MACHINE_ID|' /mnt/haos_boot/efi/boot/grub.cfg
grep -n "load_env\|save_env" /mnt/haos_boot/efi/boot/grub.cfg # verify both lines updated
sudo umount /mnt/haos_boot
6. Install GRUB — should now embed cleanly
sudo mkdir -p /mnt/elite_grub
sudo mount /dev/sdb9 /mnt/elite_grub
sudo apt install grub2
sudo grub-install --compress=xz --root-directory=/mnt/elite_grub /dev/sdb --force
Confirm the output does not contain “no BIOS Boot Partition” / “falling back to blocklists.” If it still does, double-check the bios_grub flag actually landed on the partition you think it did (sudo parted /dev/sdb print).
7. Write the bridge grub.cfg
This is deliberately bare — it does no work itself, it just chainloads HAOS’s own real grub.cfg, letting HAOS’s own A/B slot logic run unmodified:
cat <<! | sudo dd of=/mnt/elite_grub/boot/grub/grub.cfg
set root=(hd0,1)
configfile /efi/boot/grub.cfg
!
8. Unmount and boot
sync
sudo umount /mnt/elite_grub
Move the drive to the target machine and boot.
Summary
If you hit “no BIOS Boot Partition; embedding won’t be possible” while trying to install HAOS (or really, any GRUB legacy-BIOS setup) on a GPT disk — the fix is a dedicated ~8MB partition flagged bios_grub. It’s a one-time gotcha specific to GPT + legacy BIOS combinations, not a HAOS bug, and not something you’re doing wrong. Once GRUB has somewhere proper to embed itself, everything else (the bridge partition, the grubenv path fix, chainloading into HAOS’s real config) falls into place normally.