Bootable Linux USB, GRUB, multiboot, some basic topics

This post is not a tutorial of any kind and for sure its not comprehensive guide. It is my private note about basics of creating bootable USB sticks or DVDs, kind of STARTPOINT if I forgot in GNU environment.
Not so long ago I had urgent need of installing some particular Linux distro from stick. So I quickly downloaded image, verified sums, copied files as I was instructed in distribution documentation and… not worked.
Im sure I had to miss some important details, not blaming documentation.
Certainly I could use Windows machine with Rufus or uNetbootin but it was not a way to go for me.
I was attempting to create by hand multiboot USB with Debian 10, Ubuntu 18 and Fedora 30 using Ubuntu or Fedora as machine to prepare sick.
Decided to do some small research to better understand subject. Here is the summary.

How can I prepare USB with GNU linux system?

First of all USB must be FAT32 filesystem, partition with boot flag set and GPT partition table that is one that uses UUIDs for devices identification. How to prepare such?
I have used tools like parted, gparted, mkfs.vfat, grub-efi-amd64-bin (ubuntu) or grub2-efi-x64-modules (Fedora 30), grub-mkimage (ubuntu) grub2-mkimage (Fedora 30). Some of the software was already preinstalled on both systems in neither of system it required to adding any extra repositories.

When computer “starts” so called boot menu is available – to enter it we usually press some key that is mentioned at startup screen (not the system splash, rather BIOS-like screen).
From this menu we can navigate through bootable devices that is ones that have partitions with boot flag. When we select one usually system boots operating system or memtest program is launched or some extra options are available.
Under the hood bootloader program is loaded into memory – its first initial program whose task is to load kernel and boot operating system.
Modern computers with UEFI boot seems to search for bootloader binary in location /EFI/BOOT/boot{$arch}.efi of boot partitions that they boot from. Where $arch is name of target machine processor architecture like i386, x86_64 etc. I used popular bootloader GRUB (Grand Unified Bootloader). Menu entries are created through configuration file.
What is interesting, we can download operating system iso, mount it and browse – usually we will find such folder /EFI/BOOT with configuration files to look for examples.
Besides bootloader and its configuration we must provide system files for example as ISO with initial linux kernel and ram disk images (it is always provided with distribution).

Ubuntu 18.04.03 kernel image and ramdisk filesystem in iso.

1. Filesystem and partitions on USB stick

First install tools:


#ubuntu
sudo apt-get -y update && sudo apt-get -y install parted gparted grub-efi-amd64-bin 

#Fedora
sudo dnf install grub2-efi-x64-modules parted gparted

gparted

We can prepare filesystem and partitions on stick with gparted that is graphical interface to parted tool. Its also worth to use df tool before to check what devices do we have mounted in system after inserting stick to usb port. Command sudo fdisk -l will give us some helpful output too – run them before going further. Gparted can be started from cli but only as sudo user.

Output of sudo df command – currently not showing USB mounted.
Output of sudo fdisk -l – we can see our USB parameters.

$ sudo gparted

We should find USB in menu Devices – I did it by matching size and name to output of df command. Than we need to unmount this filesystem – we can find suitable button in menu Partitions. After unmounting we should create new GPT Partition table and create one FAT32 partition – all options are easy to find and select as checkboxes in menus Device and Partitions when we click suitable buttons that are legibly described.
After creating partition table and partition last thing to do here is to set boot flag – it is a must to do it.

Creating new partition table – we can choose GPT. Select from Device menu.
Creating new partition with FAT32 filesystem – menu Partitions.
Gparted – setting up flags, boot flag must be set.

parted

If somehow we can’t use gparted we can use CLI tools to achieve same effect. First we must create new partition table using sudo fdisk /dev/{your_drive_name}. Fdisk command will go into interactive mode now. But as usually before we start we must unmount drive if its mounted.
Than we should delete all partitions and create new empty GPT partition table and add new partition – shortcuts d, n and g. Fdisk will guide us through this process.

sudo umount /dev/{YOUR_DEVICE_PARTITION}
sudo fdisk /dev/{YOUR_DEVICE_PARTITION}
Interactive mode of sudo df command with help displayed.

After creating new partition table we are going to create FAT32 filesystem on our brand new and shining partition (remember number that we gave to the partition in last step – we will use driv name and that number as our target partition to format, so partition 1 on /dev/sdc is /dev/sdc1).

Remember to use correct drive/partition names – for me it was /dev/sdb1 but it might vary.

Last thing to do is to set boot flag on our new partition and we are ready to go – USB stick should be ready.

sudo parted /dev/{DEVICE} set 1 boot on
And if we use gparted to check effect we should have exactly the same parameters set on USB as if we use gparted tool.

Checking effects…..

2. Preparing bootloader binary

To generate bootloader binary (in our case GRUB2 – Grand Unified Bootloader) we are going to use grub2-mkimage (Fedora) or grub-mkimage (Ubuntu). What we have to do is also install packages required to do this, especially libraries for amd64_efi.


#ubuntu
sudo apt-get install grub-efi-amd64-bin

#Fedora
sudo dnf install grub2-efi-x64-modules

Having those installed we can move further and generate GRUB binary itself. The command for Fedora and Ubuntu is exactly the same.


grub-mkimage -o bootx64.efi -p /efi/boot -O x86_64-efi \
 fat iso9660 part_gpt part_msdos \
 normal boot linux configfile loopback chain \
 efifwsetup efi_gop efi_uga \
 ls search search_label search_fs_uuid search_fs_file \
 gfxterm gfxterm_background gfxterm_menu test all_video loadenv \
 exfat ext2 ntfs btrfs hfsplus udf

Where -o stands for output file, -O is desired target machine cpu architecture and -p is prefix directory, rest are modules that will be included into binary. To list all available modules search for grub-efi-amd64-bin installation folder and file modules.lst in system. If the file is not available – simply look into architectural package install directory and check what modules are placed there in *.mod files. For short list what is what you can search internet or start reading here .
Binary should be now generated.

3. Creating GRUB configuration file

Before creating configuration file lets download and verify Ubuntu image (this one is particularly easy to boot) and copy it to exactly the same directory as we are going to copy our bootloader binary, that is /EFI/BOOT.
So we should put our generated GRUB binary and Ubuntu ISO to one folder. After that lets create empty file named grub.cfg in the same folder.

Before going further its worth to have a quick look at grub manual and few commands like loopback, linux, initrd. Lets look at example config file with one entry.


set timeout=3
set color_highlight=black/light-magenta

menuentry 'Ubuntu from ISO' {
        set isofile="/EFI/BOOT/ubuntu-18.04.03.iso"
        loopback loop $isofile
        linux (loop)/casper/vmlinuz boot=casper iso-scan/filename=$isofile noprompt noeject quiet splash persistent --
        initrd (loop)/casper/initrd
}

As we know that we have to search for linux kernel initial image and ramdisk on ISO we can easily create such configuration. We can easily put more iso images on our stick and add more menu entries to create multiboot stick.

4. Summary

This article is not a tutorial, nor a guide. I wont guarantee that everything will work at the first time. This article is more like road sign where to start and where to dig. I can guarantee that it will give you some ideas and insights in mentioned subjects, enough to start on your own. Some systems may be quite problematic to boot – I have tried to boot Ubuntu, Debian, Fedora and Suse this way. Debian based systems are relatively easy. Fedora had some problems booting and Suse was terrible.

Also if you fail in creating multiboot you can always prepare the stick and simply put original ISO image directly to it so it will run on predefined GRUB configuration – that way seems to be easier. If you are looking for configuration examples its worth a while to download some OS ISO and check how does GRUB configuration files look like.

Some useful links:
Arch Linux Multiboot
Multiboot Specification 0.6.96

If you find something that is wrong or can be written better in this article please contact me using Contact Tab here on my blog.



« »