After my CentOS 7 upgrade, I rebooted it. It gets stuck and shows a prompt like this:

grub >

It is an annoying start.

Firstly, I tried typing load_env to check the grub env, and it told me "can not find env file from /EFI/redhat/grubenv". I guess I found the root cause.

Since CentOS is recompiled from RHEL, there are 3 directories in /boot/efi/EFI: BOOT, redhat, and centos.

Here is an example file tree:

.
└── EFI
    ├── BOOT
    │   ├── BOOTX64.EFI
    │   └── fbx64.efi
    ├── centos
    │   ├── grub.cfg
    │   └── grubenv
    └── redhat
        ├── BOOT.CSV
        ├── BOOTX64.CSV
        ├── fonts
        │   └── unicode.pf2
        ├── grubx64.efi
        ├── mmx64.efi
        ├── shim.efi
        ├── shimx64.efi
        └── shimx64-redhat.efi

After upgrading the kernel, some scripts may regenerate the grub config file, (please follow this link for more detail.) and finally due to some issues, grub cannot find the files grub.cfg and grubenv in the redhat folder.

If we had BusyBox or LiveCD, things would be very simple. We can boot from that OS, mount the folder, and copy the files to the correct path:

.
└── EFI
    ├── BOOT
    │   ├── BOOTX64.EFI
    │   └── fbx64.efi
    ├── centos
    │   ├── grub.cfg
    │   └── grubenv
    └── redhat
        ├── BOOT.CSV
        ├── BOOTX64.CSV
        ├── fonts
        │   └── unicode.pf2
        ├── grub.cfg  # copied from centos
        ├── grubenv   # copied from centos
        ├── grubx64.efi
        ├── mmx64.efi
        ├── shim.efi
        ├── shimx64.efi
        └── shimx64-redhat.efi

However, I have neither.

Then I try to boot myself from the grub command line.

> linux (hd1,gpt2)/vmlinuz-0-rescue-xxx
> initrd (hd1,gpt2)/initramfs-0-rescue-xxx.img

But it doesn't work.

> linux (hd1,gpt2)/vmlinuz-0-rescue-xxx
error: cant't find command linux

According to this Q&A, I replaced the linux to linuxefi and initrd to initrdefi. And try again:

> linuxefi (hd1,gpt2)/vmlinuz-0-rescue-xxx
> initrdefi (hd1,gpt2)/initramfs-0-rescue-xxx.img

It starts but stops at 'switch root'. This is because we did not pass the root parameter correctly. It should probably be something like /dev/sda1, which is a device label. Since I am using an LVM to manage the devices, this is too complicated for me.

However, I am still in a nice environment with some basic functionality.

I mounted my devices and copied grub.cfg and grubenv to the correct path and then rebooted the system.

It works.

Conclusion

Booting from grub using the keyboard is not easy, as the full correct command is:

load_video
set gfxpayload=keep
insmod gzio
insmod part_gpt
insmod ext2
set root='hd1,gpt2'
search --no-floppy --fs-uuid --set=root --hint-bios=hd1,gpt2 --hint-efi=hd1,gpt2 --hint-baremetal=ahci1,gpt2  xxxx-xxxx-xxxx-xxxx-xxxxxxx
linuxefi /vmlinuz-xxxx root=/dev/mapper/xxxx ro crashkernel=auto spectre_v2=retpoline rd.lvm.lv=xxxx/xxxx rhgb quiet LANG=en_US.UTF-8
initrdefi /initramfs-xxxx.x86_64.img

It's a horrible sequence.

As for us, the easiest way is to just boot a minimal system, correct the problem, then reboot and let it continue to work.

References

Categories: Code

Yu

Ideals are like the stars: we never reach them, but like the mariners of the sea, we chart our course by them.

Leave a Reply

Your email address will not be published. Required fields are marked *