3

I have had four hard days with trying to install OpenZFS 2.0.0 on a vanilla debian buster and to boot from it. To make a long story short, OpenZFS 2.0.0 runs, and buster boots from it, but only with a little bit of manual help:

After each reboot, grub goes to the command line. Obviously, it does not execute grub.cfg. If I manually execute grub.cfg, the system boots.

Please note that I have read a zillion of other threads and Q & A which all were dealing with grub being at the command line after reboot. However, I have not found a question similar to mine - I believe I have tracked down the problem so far that my question is very specific:

When I issue set at grub's command prompt, there is (among others, of course) the following line:

prefix=(hd0,gpt2)/EFI/debian

I am not a Linux expert, let alone a grub expert. So I might be wrong, but I believe that this is the culprit, because the bootloaders (grubx64.efi and shimx64.efi, respectively) along with the configuration file (grub.cfg) actually are in (hd0,gpt2)/EFI/debian-hdd1 (please note the trailing -hdd1, which the value of prefix lacks), not in (hd0,gpt2)/EFI/debian.

Consequently, when I issue normal at the command line, nothing happens (well, the screen seems to refresh, but nothing else). But when I first type

set prefix=(hd0,gpt2)/EFI/debian-hdd1

and then type normal, the normal grub boot menu appears.

This makes me assume that the prefix variable is wrong in this special situation. Obviously, when reaching the command prompt, grub has not executed any script yet. Therefore, value of prefix must be a default value.

Question:

Where does grub get this default value from? Is it a compile-time option, or can I set it somewhere? That is, how can I set the default value of grub variables, notably prefix (i.e. the value these variables have when no script has been run yet)?

Off-topic side note:

I am aware that I probably could solve the problem by installing grub.cfg in .../debian instead of .../debian-hdd1. I haven't tried that for two reasons yet:

  1. I really would like to learn how to change grub's default value of prefix (call it curiosity or pedantry).

  2. I am installing grub by grub-install, which obviously uses the UEFI boot entry name (set by giving the option --bootloader-id=debian-hdd1) as the directory name it creates.

    I need a boot entry name of that form because the rpool the system starts from consists of a mirror of two disks, and if one of them fails, I'd like to be able to boot from the other one. Therefore, I need to be able to distinguish the two disks in the UEFI BIOS setup.

4
  • Lets see details, use ppa version with your live installer (2nd option) or any working install, not Boot-Repair ISO: Please copy & paste the pastebin link to the Boot-info summary report ( do not post report), do not run the auto fix till reviewed. help.ubuntu.com/community/Boot-Repair I normally use Ubuntu, but installed Debian once to see difference in grub. With Ubuntu it has a tiny 3 line grub.cfg configfile entry to boot full grub in the / (/boot folder). With Debian then, it seemed it embedded the loading of the install's grub.cfg into the .efi boot file.
    – oldfred
    Dec 22, 2020 at 23:57
  • Does this help? GRUB Rescue - setting boot and prefix again and again (adjust to your actual devices) Dec 23, 2020 at 0:00
  • @EduardoTrápani Thanks for the link. Unfortunately, the solutions shown there did not help - you can't imagine how often I have re-installed grub and tried several other things. However, while I still haven't found an answer to my question, I have a solution to the problem - see my own answer.
    – Binarus
    Dec 23, 2020 at 10:32
  • @oldfred Thanks for the hints. Unfortunately, I am on debian, not Ubuntu. In debian, the chain is the same as in Ubuntu: A three-line grub.cfg in the EFI partition which actually starts /boot/grub/grub.cfg. The problem is that the first grub.cfg (in the EFI partition) does not get executed, obviously because grub's default value for prefix is wrong for this situation. I still don't know how to change that default value (probably it is a compile-time option), but I have found a solution to my problem - see my own answer.
    – Binarus
    Dec 23, 2020 at 10:37

3 Answers 3

3

Yes we can

I found a solution how we can change the prefix permanently. However, it has the following caveats: We have to change it directly inside the grubx64.efi binary file, and we have to keep the file the same length. And how much space you are given may depend on your distribution. Read along for further explanation.

Disclaimers

  • If you want to do this you will have to turn off secure boot as the hash will have changed and the binary will be rejected. Not sure if this can be fixed by installing your own hashes (search for MOK).
  • Always make backups of the files you are changing. If you do as I did, you will be able to reverse your changes with a bootable USB stick. If you do not have another system at hand, then please create a bootable USB now and test if you can boot into it.

First the Problem:

Basically, this whole issue is a limitation of Secure Boot. For Secure Boot to accept the grubx64.efi file, it must be signed by an accepted authority. Therefore, this grub executable is signed and prebaked. The current standard to set this prefix seems to be /EFI/$(lsb_release -i -s). This of course also means that - no matter which loader path (for example efibootmgr--loader \\EFI\\other\\SSHIMX64.efi) - you specify when creating a new boot option, it will have no effect on the prefix variable in the grub bootloader.

The solution:

Let's assume our distro is ubuntu and we would like to rename that to longubuntu for some reason, we can do so following these steps:

# List contents of EFI directory
find /boot/efi/EFI;
# Rename the directory
mv /boot/efi/EFI/ubuntu /boot/efi/EFI/longubuntu;
# List contents of EFI/longubuntu for easy access
find /boot/efi/EFI/longubuntu;
# Always make a copy of the original
cp /boot/efi/EFI/longubuntu/BOOTX64.CSV /boot/efi/EFI/longubuntu/BOOTX64.CSV.bak
# Inside the .csv-file change 'ubuntu' to 'longubuntu'
nano /boot/efi/EFI/longubuntu/BOOTX64.CSV

Before proceeding:

Check that there are enough nul-characters available in the binary file. It is important to keep the overall length the same. If you don't do that, it will throw an error - if this happens to you, then copy back the original grubx64.efi and try again. When inspecting my grubx64.efi-binary with VS Code I do have enough available to change the prefix to my hearts content:
Many nul-characters directly behind /EFI/ubuntu

Now to the fun and critical part:

As I already said, we need to make sure that we keep the binary file the same length. We can so by either padding the new prefix with nul-chars (\0) or by padding the text to replace with nul-chars.

So if you want to specify a longer prefix (as in my case), you can do so with:

# Parameter -pi.bak will create a backup for you
perl -pi.perlbak -e 's/EFI\/ubuntu\0\0\0\0/EFI\/longubuntu/g' /boot/efi/EFI/longubuntu/grubx64.efi

If you choose a shorter prefix (for example bent), then pad the new value with \0:

# Parameter -pi.bak will create a backup for you
perl -pi.perlbak -e 's/EFI\/ubuntu/EFI\/bent\0\0/g' /boot/efi/EFI/longubuntu/grubx64.efi

You can check the results of your operation with, which will print the line containing the prefix.

$~: grep -a 'EFI\/longubuntu' /boot/efi/EFI/longubuntu/grubx64.efi

Which prints:
Grep will print the new prefix.

Do not forget to add a new boot option!

I will use efibootmgr. With efibootmgr we can delete the old boot option and add a new one.

# Print current boot options
:~# efibootmgr -v
BootCurrent: 0000
Timeout: 1 seconds
BootOrder: 0000
Boot0000* ubuntu        HD(1,GPT,28bd5547-5802-4f9c-97da-22ddd968dea6,0x800,0x100000)/File(\EFI\UBUNTU\SHIMX64.EFI)
# Delete current
:~# efibootmgr -b 0 -B
# List disks
:~# lsblk
NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
[...]
nvme0n1     259:0    0 238.5G  0 disk
├─nvme0n1p1 259:1    0   512M  0 part /boot/efi
└─nvme0n1p2 259:2    0   238G  0 part /
# Create new boot option
:~# efibootmgr --create --disk /dev/nvme0n1 --part 1 --label "Long Ubuntu Name" --loader \\EFI\\longubuntu\\shimx64.efi

Enjoy:

When you reboot now. You should still boot into your distribution as before.
If not, then boot into the USB stick and mount the EFI-partition. Then undo the changes or copy back the original file. On my device, I mount the EFI-partition like so:

:~# lsblk
NAME        MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT
[...]
nvme0n1     259:0    0 238.5G  0 disk
├─nvme0n1p1 259:1    0   512M  0 part /boot/efi
└─nvme0n1p2 259:2    0   238G  0 part /
:~# mkdir -p /media/efi; mount /dev/nvme0n1p1 /media/efi
1
  • 2
    Thanks for the long and detailed answer, +1 and welcome.
    – Binarus
    Nov 8, 2023 at 22:55
2

When you run grub-install it creates /boot/grub/x86_64-efi/grubx64.efi that references /boot/grub/grub.cfg

The problem then is that instead of copying this one to /EFI/$GRUB_DISTRIBUTOR/grubx64.efi, it copies /usr/lib/grub/x86_64-efi/monolithic/grubx64.efi or /usr/lib/grub/x86_64-efi-signed/grubx64.efi.signed.

They are prebuilt binaries in the deb packages and reference /EFI/ubuntu/grub.cfg.

I understand that it's necessary if you want to have a signed grubx64.efi, but we should be able to have correct implementation if we don't care about secure boot.

I can find a setting that say which grubx64.efi to take. Maybe it's handleded by alternatives, I will check that.

But the simplest solution I found is to just manually copy /boot/grub/x86_64-efi/grubx64.efi to /EFI/$GRUB_DISTRIBUTOR/grubx64.efi then install reFind that will automatically scan EFI folders and create a graphical menu entry.

You can also create menu entries in /EFI/ubuntu/grub.cfg like

set timeout=5
set default=0

menuentry '@gorilla configfile' {
        search.fs_uuid c9708fd5-155c-4459-abbe-3a08930cfd05 root lvmid/GkCLQl-oP2y-Op1F-o5Tc-TT8P-0tjW-iV2yTe/SlCPLV-S3jd-
        set prefix=($root)'/@gorilla/boot/grub'
        configfile $prefix/grub.cfg
}

menuentry '@gorilla chainload' {
        search.fs_uuid c9708fd5-155c-4459-abbe-3a08930cfd05 root lvmid/GkCLQl-oP2y-Op1F-o5Tc-TT8P-0tjW-iV2yTe/SlCPLV-S3jd-
        set prefix=($root)'/@gorilla/boot/grub'
        chainloader $prefix/x86_64-efi/core.efi
}

I had issue once with grub-bios when an old grub binary couldn't load the more recent config in /boot/grub/grub.cfg so I think it's better to chainload core.efi to not have that issue ever, instead of using the configfile.

2
  • Thanks for providing an alternative solution, and +1. I haven't tested it, though, because my own solution works without a problem since quite a while, and I won't touch the boot loader on a production system just for tests. But your solution is surely useful for other people, and perhaps also for me when I set up the next system.
    – Binarus
    May 24, 2021 at 8:32
  • @Binarus I did it first with "efibootmgr -c -d /dev/sda -p 2 -w -L debian-hdd1 -l '\EFI\@gorilla\core.efi'" then I figured the chainload way. I am not sure exactly how it is for debian, if the issue are the same than ubuntu. But there is something they didn't though about for multiboot case.
    – mirak
    May 24, 2021 at 10:16
1

I still can't answer my question, that is, I still don't know how to change the default value for prefix in grub-efi. However, I have found a solution to my problem - efibootmgr came to rescue, which I didn't know very well until now.

I first left away the option --bootloader-id= when doing grub-install, which turned out to have the same effect as --bootloader-id=debian: The bootloader files now were in EFI\debian instead of EFI\debian-hdd1.

Of course, the boot menu entry in the UEFI BIOS setup now was also debian, which I have to avoid. Fortunately, after having read the man page, it became clear that efibootmgr was the right tool to resolve the situation.

First, I deleted the UEFI BIOS boot menu entry with the wrong name:

efibootmgr -b 0001 -B

Then I created a new UEFI BIOS boot menu entry with the correct name:

efibootmgr -c -d /dev/sda -p 2 -w -L debian-hdd1 -l '\EFI\debian\shimx64.efi'

Please note that this command does not touch the actual boot loader installations, neither the one in the EFI partition nor the one in /boot/grub. Instead, it really just creates a boot menu entry in the UEFI firmware.

That is exactly what I need. Actually, I don't care whether the EFI bootloader is in EFI\debian or EFI\something-else. However, I do care about the name of that boot loader's entry in the UEFI setup, and my question arose because until then I considered the --bootloader-id to grub-install the only comfortable way to name the bootloader entry in the UEFI setup correctly.

The system now boots without any issue, because the initial grub.cfg now is in EFI\debian, and thus grub can find it.

5
  • 1
    I tried the same with Ubuntu for several versions back, and thought issue was only Ubuntu. When I created a new /etc/default/grub entry GRUB_DISTRIBUTOR=kubuntu, and reinstall grub I get a new UEFI entry "kubuntu". But it uses /EFI/ubuntu/grub.cfg to boot. It used to not even add a grub into /EFI/kubuntu and now does, but only working grub.cfg is /EFI/ubuntu. Or not just Ubuntu issue. Both Ubuntu & Debian have hard coded location of grub.cfg somewhere in grubx64.efi or shimx64.efi.
    – oldfred
    Dec 23, 2020 at 15:50
  • @oldfred Thank you very much for your report - +1. Both Ubuntu & Debian have hard coded location of grub.cfg somewhere in grubx64.efi or shimx64.efi. I have come to the same conclusion, and the solution I found seems to be the only remedy (unless I wanted to compile grub myself, and I didn't look yet into the very promising grub-mkimage and its -c option). Also thanks for pointing out GRUB_DISTRIBUTOR - I didn't know about it yet.
    – Binarus
    Dec 23, 2020 at 17:00
  • 1
    You might try changing the grub distributor. When I looked at Ubuntu's grub code it changed many settings from the grub distributor to just "ubuntu'. There seemed to be both an efi distributor setting and it looks like grub sets that from grub distributor. But Ubuntu uses just "ubuntu". I have second installs of Ubuntu and looked at /EFI/kubuntu/grub.cfg and /EFI/ubuntu/grub.cfg. And I often had to manually edit /EFI/ubuntu/grub.cfg to boot my main default install, rather than a new test install.
    – oldfred
    Dec 23, 2020 at 18:17
  • @oldfred Thanks again. But to be honest, I am happy with the solution I outlined. It is straightforward, and I don't need to fight against my distribution that way. Therefore, I think I won't touch grub and recompile it in the next time. Plus, in the past days, I've had enough of compiling and solving difficult problems (after making my vanilla debian boot from OpenZFS 2.0.0 ...) :-).
    – Binarus
    Dec 23, 2020 at 18:45
  • That's fine, I may just install Debian again and experiment with different distributor settings to see if like Ubuntu or if it works when grub distributor is different to set efi distributor setting in grub. Never compiled grub, but just reviewed code a bit.
    – oldfred
    Dec 23, 2020 at 20:23

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .