Bootstrapping Linux on X86 BIOS

It has come to my attention that properly setting up partition tables and installing a bootloader on the old BIOS boot firmware has become sort of a lost art due to automation and people have forgotten how to do this manually. This guide will help to explain how booting Linux from BIOS works and how to set it up.

How the whole thing works

Partitioning

The first thing you need is a partition table of the MSDOS type. Not a GPT type. While it is possible to use GPT in some BIOS implementations it is by no means guaranteed. To setup a partition table I will use GNU Parted

# parted -a optimal /dev/sda
mklabel msdos

Next, we will change our unit to Mebibytes and setup our partitions. The first few MiBs should be reserved for grub to use and to make sure grub doesn't overwrite into another partition. We will reserve 2 MiBs starting at a 1MiB offset from zero for the Grub2 bootloader, then set a flag allowing grub2 to recognize it.

unit mib
mkpart primary 1 3
set 1 bios_grub on

Next we will setup the /boot partition starting after grub's partition. I usually make them only 255 MiBs big. It really does not have to be that large. This will only store the kernel, initial ramdisk, cpu micropre and grub's configuration file.

mkpart primary 3 131

Now create your swap partition and root filesystem. Note that if you want to be able to hibernate the system, your swap needs to be at least as big as your system memory. On Linux you also need to set a partition flag for the swap partition. Also note that '-1' in parted is a macro 'rest of the disk'. Type 'quit' to exit Parted when finished

mkpart primary 131 1155
set 3 swap on
mkpart 1155 -1

Creating the Filesystems

The /boot filesystem should be of a relatively simple filesystem because the bootloader will need to implement it. ext2 is suitable for this purpose as it is is simple and compact to implement and supports POSIX ownership. If your partitions don't show up under devfs you can instruct the kernel to rescan a disk with the 'partprobe' command.

I will use ext4 for the root filesystem, but you can use whatever filesystem is best for you for the root filesystem that the Linux kernel supports

# partprobe /dev/sda
# mkfs.ext2 /dev/sda2
# mkswap /dev/sda3
# mkfs.ext4 /dev/sda4

Mounting your filesystems

Now that we have prepared the disk we can mount them and prepare to install an operating system. I will mount them under the /mnt directory. Make sure to mount the root filesystem first and since this is a brand new system I will create the /boot directory as well

# mount /dev/sda4 /mnt
# mkdir /mnt/boot
# mount /dev/sda2 /mnt/boot

Preparing a chroot

At this point you would bootstrap your operating system but that is outside the scope of this article and distribution specific. Please consult your Linux vendor's installation manual for this. I will skip over that for now and go right to the preparing a chroot for installing grub.

to run the grub-mkconfig config generation tool you will need to mount devfs, procfs, and sysfs in your chroot.

Grub needs to be installed directly to the disk's Master Boot Record, witch is the first few bytes of the actual disk not the partition table. Ounce that is done you will need to have grub automatically generate a config file and place it in /boot/grub/grub.cfg (relative to the chroot). Not that in Redhat/CentOS systems they are a special case and the config needs to be placed in /boot/grub2/grub.cfg instead so adjust accordingly.

# mount -t proc /mnt/proc
# mount --rbind /sys /mnt/sys
# mount --rbind /dev /mnt/dev

Also note that if using Redhat's systemd software you will need to perform extra mounting commands to appease Lennart Poettering.

# mount --make-rslave /mnt/sys
# mount --make-rslave /mnt/dev

Finnaly, we can chroot in!

chroot /mnt /bin/bash
source /etc/profile
export PS1="(chroot) ${PS1}"

Install & configure Grub bootloader

Note that on Redhat/CentOS systems the grub configuration needs to be insalled into /boot/grub2/grub.cfg instead of /boot/grub/grub.cfg so change accordingly

# grub-install /dev/sda
# grub-mkconfig -o /boot/grub/grub.cfg
# sync

Finishing up

Now just exit the chroot, umount your drives, and sync your disks

# exit
# umount /mnt/boot
# umount /mnt
# sync
# reboot

Valid XHTML 1.1