(UEFI) Chainloading GRUB from GRUB

22,549

Solution 1

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.

Solution 2

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.

Solution 3

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.

Share:
22,549

Related videos on Youtube

jiggunjer
Author by

jiggunjer

Updated on September 18, 2022

Comments

  • jiggunjer
    jiggunjer over 1 year

    Terminology: ESP = my FAT32 EFI partition.

    I want to:

    • Have a self-contained GRUB install on my ESP that chainloads another GRUB bootloader on my distro root filesystem (/). I currently have several distros without GRUB installed on my partitions. Each is installed completely on their own ext4 /. I want them all to have their own secondary bootloader.
    • Also acceptable is for the primary ESP GRUB to restart/reload with a grub.cfg from the OS. Effectively chainloading itself.

    What I've tried:

    • Examples I've found include booting GRUB legacy from GRUB2 and vice versa but they don't use UEFI and .efi files. The GNU GRUB documentation doesn't even mention UEFI, and the Arch/Ubuntu/Gentoo wikis provide the bare minimal info to set up a basic (non-chainloading) install.

    So far:

    • I've installed GRUB onto my ESP using grub-install and grub-mkconfig.Test boot works. This means my /boot/grub folder is empty, and my ESP doesn't need to be mounted during/after boot.
    • I've tried installing a second grub into /boot/efi/ and /boot/grub/, but the EFI part won't install, grub-install complains the target is not an EFI partition. But since I already have a primary GRUB installed, it shouldn't matter that my secondary GRUB is on the ext4 rootfs right? Grub can read ext4. I tried the --force option too.

    So it seems I need to find some way of convincing the installer that it is OK to install grubx64.efi under /boot/EFI...

    If anyone is curious about how I installed the primary GRUB, it was just a matter of using the right options in grub-install with respect to my ESP.

  • jiggunjer
    jiggunjer about 7 years
    I understand, this is what I was referring to in point 3: "Chainloading itself". I found this method while searching, but was holding off on answering myself as I'd prefer to chainload another .efi that points to its own grub.cfg. I'm looking at grub-mkimage with multiboot or chainloader but so far I haven't been able to create a working secondary .efi or core.img.
  • Bassem Mamar
    Bassem Mamar almost 6 years
    What if you wanted to use the UUID instead of (hd0,gpt7)? How would the grub-mkimage command line look in that case?