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.
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:
Bootstrapping a new Ubuntu 16.04 system (with a kernel and grub)
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)
Partitioning a disk/file with GPT to boot via UEFI and BIOS
Once this is done, you can list the partitions with gdisk -l test.img:
Listing the partitions we just created
Shell
1
2
3
4
5
6
7
8
9
10
# Now list the partitions
gdisk-ltest.img
GPT fdisk(gdisk)version1.0.1
# ...
Number Start(sector)End(sector)Size Code Name
1204840951024.0KiB EF02 BIOS boot partition
24096208895100.0MiB EF00 EFI System
32088966291452629.9GiB8300Linux root filesystem
After the partitions are created, the EFI and root partition need to be formatted:
Formatting the root partition and the EFI System Partition
Shell
1
2
3
4
5
6
7
8
9
10
# Loop sparse file
LOOPDEV=$(losetup--find--show test.img)
partprobe${LOOPDEV}
# Create filesystems
mkfs.fat-F32${LOOPDEV}p2
mkfs.ext4-F-L"demoroot"${LOOPDEV}p3# << Note the label 'demoroot'
# Get rid of loop device
losetup-d${LOOPDEV}
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 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:
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:
Examples on how to use the mkbiosefi script
Shell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Makes a BIOS/UEFI bootable test.img using "demoroot" as OS partition label
# and create a minimal chroot via debootstrap in the "chroot/" folder to do so.
./mkbiosefi test.imgdemoroot
# Makes a BIOS/UEFI bootable test.img using "demoroot" as OS partition label,
# but re-uses the existing "chroot/" folder (this is faster!)
./mkbiosefi test.imgdemoroot chroot/
# If you want to use your own image file, you may create it beforehand and loop it
truncate-s40Gmy.img
myloop=$(losetup--find--show my.img)
./mkbiosefi$myloopdemo chroot/
# Or use a raw disk, of course
./mkbiosefi/dev/sdX demo chroot/
Here’s the script:
mkbiosefi script that can be used to create a BIOS/UEFI bootable disk/image
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
Vincent Perrier
Is it possible to have a working system on a sparse file with only uefi, without any bios partition? Thanks a lot for your script!
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.
Oscar
mkosi (https://github.com/systemd/mkosi) does the same more or less in a automated manner, but only for UEFI systems.
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.
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
davelister
thanks !
hear https://pastebin.com/wUE25LwT#mkbiosefi is a URL for he script !
Marcin
I have tried to run this solution on Debian9 Stretch (Linux dt 4.9.0-9-amd64 #1 SMP Debian 4.9.168-1+deb9u3 (2019-06-16) x86_64 GNU/Linux) however during boot I get “attempt to read or write outside of partition” from grub. The boot was through BIOS Boot after first part of the article.
Another thing is that I have got error after this part:
# Unmount OS partition
umount $MOUNTDIR/{dev,proc,sys,}
/tmp/demoQOJKO9/sys: target is busy
(In some cases useful info about processes that
use the device is found by lsof(8) or fuser(1).)
there was system process:
lsof /tmp/demoQOJKO9/sys/
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
systemd-l 397 root 7r REG 0,16 4096 2676 /sys/devices/virtual/tty/tty0/active
which had successfully blocked all of the unmounting attempts. I had dd test.img to usb drive and powered off the system.
Could you point which direction to go to as I belive I have tried all of the posibilities?
TalisaU230
Hey… wonderful article. Works splendid. I have one problem btw. I rewrote the scripts to make a Void Linux install. When I boot the Void linux and log in.. take ‘ls /boot’ it only shows the EFI directory not the kernel and initramdisk. This is when I boot using EFI. Do you get the idea whats wrong? Sorry for my bad english.
AlHaddare
Hi its helpful for me as newbee but can you explain more details steps as you mention in your sentences
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.
Cause i like to copy root file system from my ubuntu 20.04.1 live usb to my hdd partition then run your script after step 1
Please…Thank You & Bestregard
MD Titoo
I’m new to Linux and found your page when I was searching EFI to BIOS for Linux image. We have multiple systems that has BIOS and BIOS cannot be updated to support EFI. Can an existing GPT EFI Linux disk be converted to BIOS boot? Any information will be highly apricated.
Thanks.
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
Is it possible to have a working system on a sparse file with only uefi, without any bios partition? Thanks a lot for your script!
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.
mkosi (https://github.com/systemd/mkosi) does the same more or less in a automated manner, but only for UEFI systems.
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.
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
thanks !
hear https://pastebin.com/wUE25LwT#mkbiosefi is a URL for he script !
I have tried to run this solution on Debian9 Stretch (Linux dt 4.9.0-9-amd64 #1 SMP Debian 4.9.168-1+deb9u3 (2019-06-16) x86_64 GNU/Linux) however during boot I get “attempt to read or write outside of partition” from grub. The boot was through BIOS Boot after first part of the article.
Another thing is that I have got error after this part:
# Unmount OS partition
umount $MOUNTDIR/{dev,proc,sys,}
/tmp/demoQOJKO9/sys: target is busy
(In some cases useful info about processes that
use the device is found by lsof(8) or fuser(1).)
there was system process:
lsof /tmp/demoQOJKO9/sys/
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
systemd-l 397 root 7r REG 0,16 4096 2676 /sys/devices/virtual/tty/tty0/active
which had successfully blocked all of the unmounting attempts. I had dd test.img to usb drive and powered off the system.
Could you point which direction to go to as I belive I have tried all of the posibilities?
Hey… wonderful article. Works splendid. I have one problem btw. I rewrote the scripts to make a Void Linux install. When I boot the Void linux and log in.. take ‘ls /boot’ it only shows the EFI directory not the kernel and initramdisk. This is when I boot using EFI. Do you get the idea whats wrong? Sorry for my bad english.
Hi its helpful for me as newbee but can you explain more details steps as you mention in your sentences
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.
Cause i like to copy root file system from my ubuntu 20.04.1 live usb to my hdd partition then run your script after step 1
Please…Thank You & Bestregard
I’m new to Linux and found your page when I was searching EFI to BIOS for Linux image. We have multiple systems that has BIOS and BIOS cannot be updated to support EFI. Can an existing GPT EFI Linux disk be converted to BIOS boot? Any information will be highly apricated.
Thanks.