The information that your root filesystem is /dev/sda1
is actually completely useless for GRUB, other than as part of a kernel boot parameter string root=/dev/sda1
which is passed to the Linux kernel as-is.
What GRUB needs to know is which identifier it needs to use for the disk in the system firmware calls when loading its own configuration file, any GRUB modules that are not embedded in GRUB core image, the kernel, and the initramfs file.
In a classic BIOS-based system, the fundamental form of this identifier is hexadecimal byte: 0x80 refers to the first disk detected by the BIOS, 0x81 to the second, etc. GRUB maps these to its own identifiers: (hd0)
is 0x80, (hd1)
is 0x81 and so on.
In an UEFI system, you might be able to run an UEFI shell and use its map
command to see the UEFI partition identifiers in the order firmware detects them: the first partition with a UEFI-recognizable filesystem will be fs0:
, the second fs1:
and so on. Whole disks and raw partition access is via identifiers like blk0:
. These (or their machine-readable UEFI API equivalents) are what an UEFI version of GRUB must use to identify the disk or partition it wants to load something from. GRUB mostly uses its own filesystem drivers, so it maps the blkN:
identifiers of the firmware to (hdN)
.
The search
command
search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1
means that according to the best information available to the grub-mkconfig
command (which can be just a best guess, particularly with BIOS-based systems) the partition that contains the files needed by subsequent commands will most likely be (hd0,msdos1)
at boot time, assuming the hardware configuration won't change after writing the configuration file.
--set=root
tells you that the purpose of this search command is to set GRUB's root
variable to point to whatever partition is the result of this search.
So if you know that the files needed by whatever comes after this search
command are on the first partition of a disk that will always be detected as the first disk by the firmware, then you can replace this search
command with:
set root=(hd0,msdos1)
Note: setting GRUB's root
variable has nothing at all to do with the root filesystem for the Linux kernel. Its only purpose is to define the root path (including the disk/partition) for any subsequent GRUB commands that refer to files on disk using path names.
With a classic BIOS-style boot process, the only thing you can be reasonably sure about is that whatever disk has been selected as bootable in the BIOS settings (and the BIOS is currently trying to boot from, if there are multiple disks listed in the boot order) will be accessible as BIOS disk 0x80... and so for GRUB, it will be (hd0)
.
And, by the way, Debian and Ubuntu "use GRUB" only in the sense that it is the default bootloader. If you wish, you can rip out GRUB and replace it with your favorite bootloader. The only requirement is that you write your own scripts for updating its configuration in the appropriate directories under /etc/kernel/
: for GRUB, these scripts are /etc/kernel/postinst.d/zz-update-grub
and /etc/kernel/postrm.d/zz-update-grub
. These are the only connection between the package management system and GRUB configuration.
Any time a new kernel package is installed or removed, all the scripts in the respective directory will be executed: if you place a script that runs lilo
in the postinst.d
and preinst.d
directories, you can use LILO just about as seamlessly with Ubuntu's updates as GRUB is used by default.
In 2012, I had a system with an early UEFI implementation that had a firmware bug that caused problems for GRUB at that time; I found out that rEFInd could avoid that bug, so I used this to replace Debian's GRUB with rEFInd. Even though the firmware has since then been updated to a fixed version, and GRUB has gained many workarounds for UEFI bugs, I've kept the simple scripts I wrote back then in place as a backup bootloader; the scripts have worked for 8 years.
Modern versions of Debian actually package rEFInd and include similar scripts right in the package. So may other bootloader packages included in the distribution: if there's a package for LILO or Syslinux in Ubuntu, you might try installing it and see if the package includes kernel postinstall/postrm scripts for it. If it does, you might find that it "just works."
If you are in the habit of cloning disks or filesystems, you might want to consider changing the UUIDs of the new clones if they are going to be presented to the computer together with the originals. This question has plenty of advice for that.
In an enterprise environment with SAN-level snapshots with LVM, you must re-uniquify the clones immediately after creating them or else you will be in a world of hurt if the clone and the original are ever presented to the same system (been there, fixed the mess, vgimportclone
is your friend). In any other type of environment, it might still be a good idea.