Welcome! You are about to start on a journey to learn about booting process in different operating systems. For your reference, below is a list of the articles in this series:
- Part 1a: Linux - BIOS and Master Boot Record
- Part 1b: Linux - The Bootloader (this article)
- Part 1c: Linux - The Kernel and Initial Ramdisk
- Part 1d: Linux - Init Process
We continue Linux boot process with the bootloader whose responsibility is to find where the kernel is and decide which kernel parameters should be passed.
The boot program first copies itself to a fixed high-memory address to free up low memory for the operating system. Let’s assume that we are using Legacy Grub (version 0). stage-1 code will find and execute the rest on the code on entire disk.
Since 446 bytes is not big enough to contain a boot loader that supports complex and multiple filesystems, bootloaders are thus split, only stage-1 code resides within the MBR, while the rest is stored in other locations of the disk. This is known as multi-stage bootloader.
This is not very secure because anything can overwrite the code there, but most bootloaders do it, including GRUB installations. Also, this scheme won’t work with a GPT-partitioned disk using the BIOS to boot because the GPT table information resides in the area after the MBR (GPT leaves the traditional MBR alone for backward compatibility). The workaround for GPT is to create a small partition called a BIOS boot partition with a special UUID to give the full boot loader code a place to reside. However, GPT is a part UEFI standard, and is not usually used with BIOS.
The MBR loads the booting code contained first block (the boot block) in a particular partition called active partition. Apart from this partition, every other partition also start with a boot block, hence, the disk can store booting code of many different operating systems.
In legacy Grub, the rest of booting code are stage 1.5 and 2. Stage 1.5 purpose is to load stage-2 code in to memory. Since stage 2 can be located anywhere, The stage 1.5 image contains a few common filesystem drivers, i.e. EXT, XFS, FAT, NTFS, enabling it to directly load stage 2 from any known location, i.e. /boot.
Stage 2 of GRUB code allow it to access Linux filesystems, and it uses that ability to read and load a configuration file that tells which kernel it can boot, where they are on the disk (usually in /boot), and what parameters to pass. Kernels are identifiable as they are all named starting with vmlinuz. In most modern systems, GRUB actually allow users to select from the list of kernels (sometimes with a screen or graphics and often with a countdown) and also to edit boot-time settings.
The reason why BIOS cannot directly access stage 1.5 or 2 is because BIOS is only capable of direct hardware access. It can not mount drives, partitions, or filesystems. Thus, it can only access the drive with cylinder-head-sector (CHS) or Linear Block Addressing (LBA) addressing via the HDD controller. This means that BIOS can only access the first 8GB of the drive.
Once you select a particular kernel, GRUB will load the Linux kernel as an image file into memory RAM, execute it, and pass along any boot-time arguments, you can actually view the kernel parameters from your system’s boot by looking at the file /proc/cmdline, i.e.
$ cat /proc/cmdline BOOT_IMAGE=/boot/vmlinuz-3.2.0-67-generic-pae root=UUID=70ccd6e7-6ae6-44f6-812c-51aab8036d29 ro quiet splash vt.handoff=7
In modern version GRUB 2, the chain booting process is similar to legacy GRUB, although GRUB 2 code is much more complicated, please see this article for more differences. Other hard drive bootloader is Intel’s LILO which does not rely on any specific file system. Instead, they need a block map and low-level addresses, which describe physical sectors, heads, and cylinders, to find the relevant sectors to be loaded.
Other than hard drive, systems that boot from USB, CD-ROM, or the network using SYSLINUX, ISOLINUX or PXELINUX respectively as their boot loader. In the networking booting, the network boot program PXELINUX is used in conjunction with pxe-capable NIC to download bootstrap program with the help of DHCP/TFTP which will load and configure kernel.
Phew, the good news is we are half way through, but still far from the end, from here onwards the kernel will take over the bootloader, so let’s hang for a while…