[<< | Prev | Index | Next | >>]

Sunday, November 04, 2018

UEFI Boot Process / Making a Bootable Hot Backup

[technical, linux/ubuntu]

[WARNING: All of this is untested at this time. I'll try to remember to remove this warning once I successfully migrate to my new disk...]

I've been trying to back up my linux system (root/boot partitions) so I can restore it on disk failure (mine is failing) without having to re-install and re-configure/re-tune everything from scratch. You would think this would be a standard thing--like the most common thing--but I couldn't find it described well anywhere. Ideally, it would be a directly bootable backup, so if my main disk fails, I just reboot off my backup disk and I'm instantly up and running again. I installed an sdcard for this purpose, worked out how to do it, and then learned my particular laptop (thinkpad carbon X1 6th gen) can't boot from the sdcard, ever. Bummer. But at least I can just install a new disk, boot from any live CD, restore my system from the sdcard, and go. (And I'll make sure my next laptop can boot from the sdcard.)

Still, for either approach, I had to work out how to build a bootable system backup, and as a prerequisite how a UEFI systems boots, both of which I'll describe here since they can be explained in a few lines rather than the multi-volume tomes you will find elsewhere.

Everything here applies to systems running UEFI (as opposed to the now antiquated BIOS) firmware only.

The UEFI boot process (typical case, booting from local disk):

- You turn the machine on, it does its diagnostics and whatnot and then runs the UEFI boot manager (firmware).

- The boot manager loads an ordered list of boot entries from non-volatile ram (nvram--memory in the computer which persiststs between reboots).

- Each boot entry specifies a location (a disk, partition, and partition-relative file path) to look for a program to run (your boot loader, in a specified executable format: .efi), as well as human-friendly label like "ubuntu". You can change the order and labels, and add/remove entries, with efibootmgr in linux.

- Bootable disks must use GPT style partitioning, and the file to boot must reside in a FAT (usually FAT32) formated partition with "boot" and "esp" flags set. (Generally it is the first partition on the disk, which I don't think is technically required but it's possible some firmware may assume it.)

- The boot manager runs (boots) the first valid entry it finds.

- If it can't find anything else (or sooner, depending on your boot list order in nvram) it will look for any EFI partition with an "\EFI\BOOT\BOOTX64.EFI" file (for x86_64 type CPUs) and run that as a fallback, which is how removable boot media is able to work, and is also the only easy way to build a boot disk on one machine and boot it on another.

That's basically it. (Note there's no magic boot code hidden in the begining of the disk or anything like that, contrast the old BIOS/MBR style of booting. With UEFI, the "magic" is that you need to use GPT/FAT so it can find your boot files.)

So, to make a disk bootable, you need to:

- Partition and format it with an EFI partition (FAT32; flags=esp,boot; size > ~100MB should be plenty for a linux-only machine -- mine has a mere 16M used).

- Copy and configure your bootloader files to an appropriate folder in that partition (e.g. "\EFI\ubuntu").

- Tell the nvram where to find it (path) and what to call it (label). By default when you add an entry with efibootmgr, it becomes first in line.

For a linux system, the bootloader needs to be configured to find and mount your main system partition, launch the appropriate kernel, and whatnot. Re-stating the above sequence in practical terms for linux, in the context of copying a reference system and making it bootable again:

First partition and mount the disk, and restore the bulk of your system:

- Partition (and format) your target disk with an EFI partition per above, and at least a system (root) partition (ext4 or whatever).

- Mount the latter somewhere like /mnt/newroot and the former under that at boot/efi as in /mnt/newroot/boot/efi

- Restore/copy your reference system to the new system partition. E.g. "rsync -axAHXvi / /mnt/newroot" for a hot backup, or "rsync -axAHXvi /mnt/bak/ /mnt/newroot" to recover from a previous archive. (Note the -x will not cross partition boundaries so will not touch the efi partition.)

Next, cajole grub into making your new disk bootable:

- "mount --bind" various special dirs like /dev, /proc, etc., into the target, e.g. "mount --bind /dev /mnt/newroot/dev"

- chroot to your new disk, e.g. "chroot /mnt/newroot" (which should now have operational /dev and such).

- run grub-install (typically with no parameters), which will load up /boot/efi and /boot/grub with all the necessary stuff, AND will update your nvram to boot off that disk in the future. (Use "--no-nvram" to make it skip that last step if, for instance, you are setting up a disk to boot on a different computer.)

- run update-grub (again, no parameters), which will (only) make a new /boot/grub/grub.cfg file, which tells grub what kernels are available and where to find them.

Finally, update any other system files which might reference your disk's UUID (now changed). Mainly:

- Update /etc/fstab (nee /mnt/newroot/etc/fstab) to refer to the new disk (run "blkid" to see UUIDs of your partitions).

I've made a python script that automates all of that including the initial partitioning and fstab update. I can make that available on request (but won't bother lacking demand). [Update 2020-07-28: Here is the source if you want to try it, but beware it is still largely untested. Let me know if you find any issues with it or can suggest any improvements, or if you test it and find it does or doesn't work: bootback.2020-07-28.tgz]


- In theory one could just copy over the EFI partition directly rather than re-building it, and not have to worry about grub-install or update-grub (or, consequently, the mount --bind's and chroot), but empirically it appears a few files change (different disk UUIDs, and what else?) in both the EFI partition (grub.cfg) and /boot/grub (grub.cfg, x86_64-efi/{core.efi,grub.efi,load.cfg}) so it's probably safer, and possibly necessary, to rebuild it. This is fairly harmless since you're still keeping your main system install and partition intact, so not losing any system config, installed packages, logs, and whatnot. Still, it's unfortunate to have to do this every time you backup your system (in the directly-bootable backup case) so if anybody knows a way to safely avoid at least the grub-install, let me know.

- To make a directly-bootable backup drive, which I haven't tested since I can't on my machine, I would think you would want to do the grub-install with the --no-nvram flag (otherwise next time you reboot you'll be running on your backup disk!), and then (just once when you first set up the backup drive) use efibootmgr to add a new entry with label "hotbackup" or such, taking care to list it below your main OS. In theory if your main disk dies, it should boot automatically to your backup on restart.

[<< | Prev | Index | Next | >>]

Simon Funk / simonfunk@gmail.com