how to create EFI-compatible rhel installation usb
pre
RedHat provides several ISO images that let you install a system. They are DD compatible and one can flash an ISO into USB drive by using either DD or Fedora Media Writer.
If you are lucky enough you may boot this USB in a BIOS-legacy mode, but not in the EFI mode. The installation also continues in BIOS-legacy and doesn't create any EFI-compatible partitions. No secure boot at all.
For those who care about UEFI in their system there are no structured information on RedHat docs.
see into an image
An official ISO has a both isolinux bootloader (bios-mode) and grub (efi-mode). The latter one disappear when you DD the image to USB drive. It may be just because of some misconfiguration during the ISO creating process. I tried to repack an ISO but had no luck about EFI mode.
efi-mode easy way
EFI boot was desinged to be very simple. There are no hidden magic stuff (almost) behind the bootloader. EFI-enabled partitions is just a VFAT-formatted partition with a custom PART-GUID. There are some limitations about the size and some others between different platforms, but let's keep it simple for now.
EFI partitions has type code EF00
and PART-GUID C12A7328-F81F-11D2-BA4B-00A0C93EC93B
.
GPT fdisk (gdisk) version 1.0.9
Partition table scan:
MBR: protective
BSD: not present
APM: not present
GPT: present
Found valid GPT with protective MBR; using GPT.
Command (? for help): p
Disk disk.raw: 3104768 sectors, 1.5 GiB
Sector size (logical): 512 bytes
Disk identifier (GUID): 2A2619EB-3FA6-4C34-A716-1DCA94AD43B7
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 33
First usable sector is 34, last usable sector is 3104734
Partitions will be aligned on 2048-sector boundaries
Total free space is 4029 sectors (2.0 MiB)
Number Start (sector) End (sector) Size Code Name
1 2048 3102719 1.5 GiB EF00 EFI system partition
Command (? for help): x
Expert command (? for help): i
Using 1
Partition GUID code: C12A7328-F81F-11D2-BA4B-00A0C93EC93B (EFI system partition)
Partition unique GUID: 2A1143B9-AFE9-48CE-8B47-21535F031770
First sector: 2048 (at 1024.0 KiB)
Last sector: 3102719 (at 1.5 GiB)
Partition size: 3100672 sectors (1.5 GiB)
Attribute flags: 0000000000000000
Partition name: 'EFI system partition'
gdisk util makes everything simple. To prepare an EFI-compatible partition you need to set the type to EF00
during the creating process, then PART-GUID will be filled automatically:
Command (? for help): n
Partition number (1-128, default 1):
First sector (34-3104734, default = 2048) or {+-}size{KMGTP}:
Last sector (2048-3104734, default = 3102719) or {+-}size{KMGTP}:
Current type is 8300 (Linux filesystem)
Hex code or GUID (L to show codes, Enter = 8300): ef00
Changed type of partition to 'EFI system partition'
almost it
Let's mount everything we need to make it work. First, locate an RedHat installation ISO, e.g. rhel-baseos-9.0-x86_64-boot.iso
. Then locate a newly created EFI partition, e.g. /dev/sdc1
.
$ realpath rhel-baseos-9.0-x86_64-boot.iso
/home/mainnika/rhel-baseos-9.0-x86_64-boot.iso
$ stat /dev/sdc1
File: /dev/sdc1
EFI partition needs to be formatted first, please notice a label
argument -n RHEL9
. This is necessary for the bootloader to find a boot root partition by label.
# sudo mkfs.fat -F 32 -n RHEL9 /dev/sdc1
mkfs.fat 4.2 (2021-01-31)
Now mount everything. Be aware of ephemeral directory I use in exmaples, do not copy them blindly.
# mktemp -d --suffix=-iso-mount
/tmp/tmp.SR9TpfSV5U-iso-mount
# mktemp -d --suffix=-efi-mount
/tmp/tmp.A7IJSAwhHy-efi-mount
# mount -o loop /home/mainnika/rhel-baseos-9.0-x86_64-boot.iso /tmp/tmp.SR9TpfSV5U-iso-mount
mount: /tmp/tmp.SR9TpfSV5U-iso-mount: WARNING: source write-protected, mounted read-only.
# mount /dev/sdc1 /tmp/tmp.A7IJSAwhHy-efi-mount
# mount
/home/mainnika/rhel-baseos-9.0-x86_64-boot.iso on /tmp/tmp.SR9TpfSV5U-iso-mount type iso9660
/dev/sdc1 on /tmp/tmp.A7IJSAwhHy-efi-mount type vfat
Prepare/copy EFI bootloader. The EFI bootloader is just a EFI
folder located in root.
# cp -r /tmp/tmp.SR9TpfSV5U-iso-mount/EFI /tmp/tmp.A7IJSAwhHy-efi-mount
For some weird reason there is an invalid bootloader in EFI folder, BOOTX64.EFI
. Let's replace it with grub which is right there as well and remove some of leftovers.
# mv /tmp/tmp.A7IJSAwhHy-efi-mount/EFI/BOOT/grubx64.efi /tmp/tmp.A7IJSAwhHy-efi-mount/EFI/BOOT/BOOTX64.EFI
# rm /tmp/tmp.A7IJSAwhHy-efi-mount/EFI/BOOT/mmx64.efi
The most important step is to change a grub.cfg
and let him use right paths and kernel. You might see here the label
we've used during formatting.
# sed -i 's/RHEL-9-0-0-BaseOS-x86_64/RHEL9/g' /tmp/tmp.A7IJSAwhHy-efi-mount/EFI/BOOT/grub.cfg
# sed -i 's/images\/pxeboot/isolinux/g' /tmp/tmp.A7IJSAwhHy-efi-mount/EFI/BOOT/grub.cfg
The last step is to copy installation files from ISO media to EFI partition.
# cp -r /tmp/tmp.SR9TpfSV5U-iso-mount/{images,isolinux} /tmp/tmp.A7IJSAwhHy-efi-mount
that's it
Examine a filesystem tree for the EFI partition.
# tree /tmp/tmp.A7IJSAwhHy-efi-mount/
/tmp/tmp.A7IJSAwhHy-efi-mount/
├── EFI
│ └── BOOT
│ ├── BOOTX64.EFI
│ ├── fonts
│ │ └── unicode.pf2
│ └── grub.cfg
├── images
│ ├── efiboot.img
│ └── install.img
└── isolinux
├── boot.cat
├── boot.msg
├── grub.conf
├── initrd.img
├── isolinux.bin
├── isolinux.cfg
├── ldlinux.c32
├── libcom32.c32
├── libutil.c32
├── memtest
├── splash.png
├── vesamenu.c32
└── vmlinuz
Unmount everything and eject USB drive,
# umount /tmp/tmp.SR9TpfSV5U-iso-mount /tmp/tmp.A7IJSAwhHy-efi-mount
# sync
# eject /dev/sdc
then boot it!