My name is Philipp C. Heckel and I write about nerdy things.
This site moved here recently from blog.philippheckel.com!

Creating a BIOS/GPT and UEFI/GPT Grub-bootable Linux system


Linux

Creating a BIOS/GPT and UEFI/GPT Grub-bootable Linux system


Good old Master Boot Record (MBR) unfortunately cannot address anything beyond 2TB, so partitioning large disks and making them bootable is impossible using MBR. The GUID Partition Table (GPT) solves this problem: It supports disks up to 16EB. However, installing grub does not work without a special BIOS boot partition. If you also want to support booting the same system via UEFI, another partition, the EFI System Partition (ESP), is necessary.

This should post shows you how to partition a disk with GPT and make a bootable Linux system via BIOS/Legacy and UEFI.


Content


Requirements & Assumptions

For this post, I’ll assume that you are running everything on a Debian-based system, and all commands shown must be run as root.

1. Create a minimal Linux (optional)

For this example, we’ll use a small Linux install that we can create with the following commands. This will bootstrap (debootstrap) a minimal Ubuntu 16.04 system to the chroot/ folder which we will later use to boot our system. To create a bootable system, we need a kernel and the bootloader modules and files, so let’s install linux-image-generic and grub-pc:

Alternatively, you can of course use any Linux root file system, provided that it has a kernel and grub. You could, for instance, just copy your own root file system to the chroot/ folder.

2. Creating a GPT with a BIOS boot partition and an EFI System Partition

Now that we have the Linux root file system in the chroot/ folder, we’ll create a sparse file that represents our disk. You may of course do all this with a proper HDD/SSD, i.e. with /dev/sdX, but for testing things using a raw disk file is much easier. The following snippet will create 3 partitions:

  • A 1 MB BIOS boot partition (of type ef02) that Grub will use to store its core image.
  • A 100 MB EFI System Partition (of type ef00) formatted as FAT32 in which we will store the EFI boot image
  • And a partition for our root file system (in our example formatted with ext4)

Once this is done, you can list the partitions with gdisk -l test.img:

After the partitions are created, the EFI and root partition need to be formatted:

Note that I named the root partition demoroot (the ext4 label). This will be important later in the Grub configuration.

3. Copying the root file system, installing grub into the BIOS partition

Now that the partition to be used for our root file system is formatted, let’s copy our chroot/ directory to it and then install grub to the disk with grub-install. Because the disk is GPT formatted, grub will use the BIOS partition to install its core image:

After this, you should be able to boot the system via BIOS from the root GPT partition. I always do that via KVM like this:

4. Preparing the EFI partition

After you’ve verified that you can boot via BIOS, let’s make sure that we can also boot on UEFI systems. We formatted the EFI partition earlier. All that’s remaining is to create/copy the bootx64.efi image file and a valid grub.cfg to it.

Grub can create the EFI image via the grub-mkimage command using the Grub modules in /usr/lib/grub/x86_64-efi (part of the grub-efi-amd64-bin package). In order to avoid having to load anything from the file system, we include all the modules in the image. If you are not booted via EFI, you may need to install the grub-efi-amd64-bin package.

The Grub config file in the EFI partition grub.cfg is rather simple: It uses search --label demoroot to look for the root partition and then simply includes the actual grub config file via configfile ....

Let’s mount the EFI partition again, create the image and the grub config:

After that, the EFI partition should contain the two files /EFI/BOOT/bootx64.efi and /EFI/BOOT/grub.cfg. You can verify that like this:

That’s it. You should now be able to boot this image via UEFI. I always test this with KVM and OVMF:

5. One script to do it all

If you are an impatient man/woman, then you may just want to run the following script to do all of this in one go. You’ll of course have to adjust it to your needs for production use.

The script can be called in two ways:

Here’s the script:

6 Comments

  1. Mark Lomas

    Hey Philipp,

    This is a great article, I found it super useful. Thanks :-)

    FYI, I had to apt-get the ‘udev’ package because partprobe complained about ‘udevadm’ being missing and I needed to apt-get ‘parted’ so that partprobe was installed. I also added ‘–arch=amd64’ to debootstrap because I wanted a 64bit distro, it seemed to default to ‘i386’ which I assumed mean’t 32bit.

    My next step is to investigate the ‘live_boot’ package to see if I can turn the distro into one that can install itself somewhere when booted and I’d like to find a way to squeeze the image size down from 30GB to something much smaller. Any ideas?

    Thanks once again for the article,

    Best regards
    Mark



  2. Philipp C. Heckel

    The BIOS partition is used by grub only for BIOS boot. If you want UEFI only all you need is the EFI partition. The EFI grub.cfg references the grub.cfg on the root partition, not the boot partition, so you should be good there. You’d have to adjust the script not to create a BIOS partition, obviously.



  3. ewe2

    You probably need to install grml-debootstrap to simplify a lot of this, for Debian Stretch I had to change a lot and it’s a lot easier to have grml-debootstrap generate the correct locales for instance.


  4. Gil Montag

    Hi
    1. Will this technique be good also for buildroot generated rootfs and kernel?
    2. I tried the method and the uefi boot didn’t work for me. It reverted to normal boot after few error messages of not being able to uefi boot from cdrom and floppy…???
    Thanks
    Gil


Leave a comment

I'd very much like to hear what you think of this post. Feel free to leave a comment. I usually respond within a day or two, sometimes even faster. I will not share or publish your e-mail address anywhere.