(UEFI) Chainloading GRUB from GRUB
There's another way: you can create a menu entry that tells GRUB to load another secondary grub.cfg, such as one from another Linux distro.
For example, I started with Gentoo Linux from which I installed GRUB2 into the MBR (the machine is too old for EFI).
I then installed NixOS, which I configured to generate grub.cfg in it's own /boot (separate from Gentoo's /boot) but without installing GRUB.
To clarify, grub-install
was executed from Gentoo but not from NixOS.
Next, to be able to boot NixOS, I added this to /etc/grub.d/40_custom in Gentoo:
#!/bin/sh
exec tail -n +3 $0
# This file provides an easy way to add custom menu entries. Simply type the
# menu entries you want to add after this comment. Be careful not to change
# the 'exec tail' line above.
menuentry 'NixOS' --class gnu-linux --class gnu --class os $menuentry_id_option 'nixos-0aca58bc-8fdb-4a07-aa2f-56406bcf19b7' {
set root='hd0,msdos4'
configfile /nixos/root/boot/grub/grub.cfg
}
The key is the configfile /nixos/root/boot/grub/grub.cfg
line. It tells GRUB to load another grub.cfg. I then ran grub-mkconfig
from Gentoo to apply the changes.
Now, when I boot and select NixOS the entire GRUB interface refreshes to reflect the NixOS grub.cfg, from which I can boot the OS. Unlike chainloading, this configuration utilizes a single installation of GRUB; it simply uses a second configuration.
I've found out how to manually install the .efi
on each of my /
's. Referring to the secondary GRUB chainloader from the primary config is simple:
menuentry "GRUB chainloader" {
#Load grub on partition 7 of a gpt formatted drive.
#It will reference its own modules and config.
chainloader (hd0,gpt7)/path/to/bootloader/on/myOS/core.efi
}
To create this secondary .efi
I used grub-mkimage
because grub-install
didn't let me write to a non-FAT filesystem. The syntax is very picky and it doesn't give errors if you use a wrong path, so check the arguments carefully:
grub-mkimage -o /path/to/mounted/targetOS/efidir/core.efi --format=x86_64-efi '--prefix=(hd0,gpt7)/boot/grub' ext2 part_gpt
I tried leaving out the GPT or ext2 filesystem modules but that didn't work, those two modules were the absolute minimum requirement for my system (ext2 works for ext2/3/4).
The prefix directory is where the secondary bootloader will look for its modules folder and config file. So I have manually created a /boot/grub/
for each OS that includes a x86_64-efi/
folder (copied from /usr/lib/grub)
and a grub.cfg
I can modify using grub-mkconfig
with OS-probing disabled (or just manually edit it).
I originally installed each OS without GRUB. This method allowed me to install secondary GRUB bootloaders on all operating systems using a first OS or LiveCD with GRUB. I can change the boot configuration of each OS independently, no risks for contamination because the ESP is never mounted.
I am trying to do a similar thing for i386-pc grub, and chainloader of the the core.img file would not work, giving "error: invalid signature"
But I had learned that the grub core.img file is multiboot compliant, so I was able to boot core.img like:
multiboot (hd0,7)/core.img
boot
and successfully get the new grub, it's modules and initial configuration.
I suppose your chainloader command fails on an efi for a non-efi grub, so this failrue can be detected and fall-back to multiboot on core.img before the boot command.