EFI boot with multiple alternate boot/OS partitions - possible?
Add Reply
Warner Losh
2018-11-30 16:23:31 UTC
I am working on a project using relatively simple workstation,
basically web browser with custom backend, running page with javascript
communicating with said backend to display status of some processes
(customer's technology aka real world) being supervised. Current
prototype uses UP2 board with 32 GB eMMC, where EFI BIOS is used.
So far so good, everything runs to project manager's satisfaction, just
there is one problem to solve - UPS is not used in order to keep
installation simpler and cost lower, so I need to find a way how to run
everything from read-only mounted file systems, but occasional update
could be requested.
It is manageable when dealing with application/libraries, both from
ports and custom programms, but if OS partition is to be upgraded,
maybe for security reason or the like, power outage in wrong instant
could render whole system unusable. In order to minimise risks with
(partial partition layout from gpart show)
40 409600 1 efi (200M)
409640 3145728 2 freebsd-ufs (1.5G)
3555368 3145728 3 freebsd-ufs (1.5G)
6701096 8388608 4 freebsd-swap (4.0G)
(other partition for application data, cache etc)
with /etc/fstab corresponding part being
# Device Mountpoint FStype Options Dump Pass#
/dev/sdda0p2 / ufs ro 1 1
/dev/sdda0p3 /alt ufs ro 2 2
/dev/sdda0p4 none swap sw 0 0
When upgrade request is being handled, /alt filesystem is being remount
with read-write access, receives whole OS installation, relevant config
files in /etc directory are being copied into /alt/etc directory,
resulting in usable alternate OS copy. This can be verified for
accuracy etc. and system should be switched to use partition 3 for
next boot, something like nextboot command with -k option makes, but
whole partition, not just directory with kernel is switched...
Then partitions' roles are swapped, as /etc/fstab file in now active
secondary partition would be
# Device Mountpoint FStype Options Dump Pass#
/dev/sdda0p2 /alt ufs ro 2 2
/dev/sdda0p3 / ufs ro 1 1
/dev/sdda0p4 none swap sw 0 0
Any ideas/hints would be appreciated, I tried to look into efibootmgr
and efivar man pages, but got no clear idea how they could be used for
my purpose. I do not fully understand some details of EFI boot process,
so if some good material for reading is available, let me know (I did
some googling, but found no definitive answers yet).
efibootmgr is what you want, though if it's under-documented we should fix
that. Assuming that p1 is the ESP, you should be able to do:

efibootmgr -c -l ssd0p1:/efi/freebsd/loader.efi -k
ssd0p3:/boot/kernel/kernel -b 10 -a
efibootmgr -c -l ssd0p1:/efi/freebsd/loader.efi -k
ssd0p2:/boot/kernel/kernel -b 11 -a

this will setup Boot0010 and Boot0011.

You can then set the order either with efibootmgr -o or efibootmgr -n. In
theory you can also use the full unix path for the -k and -l lines if
things are mounted, but I hadn't fixed all the weird edge cases with that
which kept cropping up (I think they are are fixed since I can't recreate
the problems, but I'm not 100% sure).

Extra caveat: This only works for UEFI implementations that have persistent
env vars. And non-broken UEFI BootMgr implementations. Supermicro has a
broken one that one needs to work around in various ugly ways (they won't
fix it, since they think it's a feature, but they are wrong).

Or should I modify my partitions by inserting second efi, so the result
would be like
40 409600 1 efi (200M)
409640 3145728 2 freebsd-ufs (1.5G)
xxxxx68 409600 3 efi (200M)
xxxxx68 3145728 4 freebsd-ufs (1.5G)
xxxxx96 8388608 5 freebsd-swap (4.0G)
and EFI BIOS will see those two efi partitions as two independent
systems allowing me to switch them with some BootOrder vars? I would
like to avoid having two efi partitions, 200 MB basically wasted space
is not too much in today's devices, but as the whole eMMC is 32 GB in
size, it is not negligible, it could be missed sometimes...