Grub2 on a Multi-Boot EFI System
When I bought my new laptop several years ago, I chose Ubuntu as its first distro even though I usually run Debian. For one thing, Ubuntu has an excellent installer. Second, they seem to do more testing on cutting-edge hardware, so I thought the chances were better that hardware on a brand-new laptop would be supported.
Ubuntu has been working fine for a couple of years, but with 21.10 ("Impish Indri") it took a precipitous downturn. First, it has weird X rendering errors: I often see snow or garbled video obscuring popup menus, especially in Firefox or mupdf. In addition, Chromium doesn't work. Chromium on Ubuntu uses snap rather than being a native package -- that's been true for at least a year, but that's only been a minor annoyance. Sometimes shutdown freezes for 90 seconds because it's "waiting for stop job", which usually turns out to be snap-related, and snap also causes delays during booting.
But as of 21.10, snap doesn't work at all unless you use the full Gnome or KDE desktop. I filed bug 1951491, and a couple other people chimed in with "me too" reports, but it was closed as "Invalid" because they don't support anything besides the full desktop environments).
Anyway, the irritants mounted up until I finally made time to install Debian. I used debootstrap from Ubuntu to install a minimal "testing" system (my article on debootstrap is old and probably outmoded, so read DebootstrapChroot and Debootstrap if you want to learn more).
I hacked up a grub entry for the new system in /etc/grub.d/09_local and booted into it. Why not just let grub automatically detect the new OS and make an entry for it? Because autodetection doesn't work. It pairs root partitions with kernels on the wrong partition, which fails badly when you try to boot, and when I filed bug 1912677, it was initially marked as low importance, because
Running two *Ubuntu installs on the same system is not really supported, as there can only be one grub installed. Same for os-prober really, it doesn't really work correctly for anything other than Windows.
After I expressed incredulity (how many decades have Linux users been multi-booting now?) the importance was changed to Medium, but there's been no further interest in the year since then.
Anyway, that means that on a multiboot system, I need to make my own entries for every OS, and not rely on the os-prober. I create a file in /boot/grub.d with a low number, like 09_local,
menuentry " --------- AUTOGENERATED CRAP BELOW ----------" { echo "(just a separator)" }so I know not to try to boot anything that appears below the line.
That done, I booted into my new Debian install, and spent a few hours installing packages that weren't in the minimal install, and configuring things that weren't automatically configured (for instance, installing service like NetworkManager or pulseaudio doesn't actually enable them; you have to futz with systemd to get those services running).
I now had a system that worked pretty well, and it was time to make it
the default. So I copied that /etc/grub.d/09_local entry from
Ubuntu to Debian, moved the Debian entry up to the top, and ran
update-grub
. Rebooted, and ...
... the old Ubuntu install was still first. update-grub
hadn't worked.
How to Point Grub at a Different Partition
A bit about my system. I'm running off an internal solid-state disk. Ubuntu is installed on /dev/nvme0n1p3, while the new Debian is on /dev/nvme0n1p4.
Searching the web, I quickly figured out that the command I needed wasn't update-grub but grub-install. But with what arguments?
First, the disk. In /dev there are entries for both /dev/nvme0 and /dev/nvme0n1. It turns out /dev/nvme0 is a character device for talking directly to the SSD controller; /dev/nvme0n1 is the block device for the full disk, equivalent to /dev/sda. (I don't know why it's n1; are thereSSDs that have n2, n3, etc.?)
But if you just run something like grub-install /dev/nvme0n1
,
you'll get an error like
# grub-install /dev/nvme0n1 Installing for i386-pc platform. 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.. grub-install: error: will not proceed with blocklists.
That's because by default, Debian (and probably most other distros) installs grub-legacy, the old MBR version of grub, which doesn't handle disks set up for EFI.
The first step is to replace that grub-legacy with a version of grub tailored to EFI, and apparently it also has to be tailored to the current architecture:
apt-get install grub-efi-amd64
The EFI setup that the Ubuntu installer created on my disk created a 241 Mb partition at the beginning of the disk (vme0n1p1) which it mounted on /boot/efi. Inside that EFI position is a whole directory structure, including a directory called /boot/efi/EFI/ubuntu/. Presumably my goal was to get a directory called /boot/efi/EFI/debian and somehow point the boot there.
(I should mention that I am not using SecureBoot. You can check that
with mokutil --sb-state
.)
To make a long story slightly less long, once I'd installed the right version of grub, the right command turned out to be:
grub-install --target=x86_64-efi --efi-directory=/boot/efi
(Some people suggested adding --removable, which apparently is useful for making EFI live installs on USB sticks, but it didn't do what I needed for this internal disk.)
After running that command, sure enough, I had both debian and ubuntu directories inside /boot/efi/EFI.
I ran update-grub again, just to be on the safe side, but I don't know if it was actually needed.
Check Boot Status from a Running System
I was theoretically ready to reboot. But since I didn't know whether that grub-install had done the right thing, I wasn't sure if my system was even bootable. Is there any way to find out from a running system which partition's grub menu is the active one?
One useful command is efibootmgr:
# efibootmgr BootCurrent: 0003 Timeout: 2 seconds BootOrder: 0003,0000,0001,0019,001A,001B,001C,001D,001E,001F,0020,0021,0022,0023,0024,0002 Boot0000* ubuntu Boot0001* Windows Boot Manager Boot0002* Linux-Firmware-Updater Boot0003* debian ... 25 more lines snipped
Note that the BootOrder line starts with 0003; and Boot0003, a few lines down, is debian.
So apparently I had indeed switched to Debian's grub.
It made me curious, though. I actually have two ubuntu partitions, and each of them has a /boot/grub/grub.cfg. How does grub figure out on which filesystem it should look for grub.cfg?
For Ubuntu, the answer seems to be fairly straightforward. /boot/efi/EFI/ubuntu has several .efi files plus a grub.cfg:
# ls /boot/efi/EFI/ubuntu/ BOOTX64.CSV fw fwupdx64.efi grub.cfg grubx64.efi mmx64.efi shimx64.efiThe grub.cfg is a stub that contains:
search.fs_uuid 368bb829-9fea-47da-9f07-ccb23a47506c root set prefix=($root)'/boot/grub' configfile $prefix/grub.cfg
That just happens to be the uuid of the filesystem of the Ubuntu
where I most recently ran update-grub
.
So I guess that's how Ubuntu's grub picks the right partition.
But there's only one file in /boot/efi/EFI/debian: grubx64.efi. So if I have two Debian partitions, how does grub know which partition's /boot/grub/grub.cfg to use?
I spent a lot of time trying to answer that question. I have some theories, but no answers yet; hopefully I'll find out and write about it in a future article.
Oh, and remember how one of my reasons to install Debian was that Chromium doesn't work on Ubuntu? The joke's on me there: turns out Debian has removed Chromium from its repositories, and has no plans of putting it back because it's too much work to keep up with all the security bugs. I guess if I want to test website layout on Blink I'll have to use a python-qt5-webengine browser and hope that gives me a good enough idea of what Chrome users will see.
Nevertheless, I'm going to stick with Debian at least for a while: it boots so much faster, and doesn't seem to have any of the X rendering problems of Ubuntu Impish.
[ 19:53 Dec 28, 2021 More linux | permalink to this entry | ]