A bootloader is a small program that loads up code required for operating system startup. This mainly includes the location of the operating system kernel and the options which should be used to load the kernel. GRUB is an acronym for “GRand Unified Bootloader”. It works with the BIOS (Basic Input Output System) firmware and supports multiple boot options, such as various Linux boot modes, and other operating systems like Windows, BSD, and so on. We are slowly seeing a migration from the legacy BIOS system towards firmware that is based on the UEFI (Unified Extensible Firmware Interface). It was originally developed by Intel and used for their Itanium systems. This provided a new way to boot the operating system moving away from the BIOS and MBR. With this, we can also implement a secure boot mechanism by performing cryptographic signing of the bootloader. UEFI requires EFI system partition which is usually Fat32. UEFI is not limited to reading the 446 byte bootstrap code in the MBR. The GRUB2 and Syslinux bootloaders support both BIOS and UEFI whereas the legacy GRUB bootloader and LILO only support BIOS. The GRUB bootloader is deployed with Centos 6, RHEL 6 and SLES 11 operating systems.

In this article, we intend to provide a basic introduction to the GRUB bootloader.


GRUB configuration file:
The GRUB configuration file is /boot/grub/menu.lst. Given below is a sample menu.lst file from a Centos 6 system.

[root@linuxnix ~]# cat /boot/grub/menu.lst
# grub.conf generated by anaconda
# Note that you do not have to rerun grub after making changes to this file
# NOTICE: You have a /boot partition. This means that
# all kernel and initrd paths are relative to /boot/, eg.
# root (hd0,0)
# kernel /vmlinuz-version ro root=/dev/mapper/vg_linuxnix-lv_root
# initrd /initrd-[generic-]version.img
title CentOS (2.6.32-696.20.1.el6.x86_64)
root (hd0,0)
kernel /vmlinuz-2.6.32-696.20.1.el6.x86_64 ro root=/dev/mapper/vg_linuxnix-lv_root rd_LVM_LV=vg_linuxnix/lv_swap rd_NO_LUKS LANG=en_US.UTF-8 rd_LVM_LV=vg_linuxnix/lv_root rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=auto KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet
initrd /initramfs-2.6.32-696.20.1.el6.x86_64.img
title CentOS 6 (2.6.32-642.el6.x86_64)
root (hd0,0)
kernel /vmlinuz-2.6.32-642.el6.x86_64 ro root=/dev/mapper/vg_linuxnix-lv_root rd_LVM_LV=vg_linuxnix/lv_swap rd_NO_LUKS LANG=en_US.UTF-8 rd_LVM_LV=vg_linuxnix/lv_root rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=auto KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet
initrd /initramfs-2.6.32-642.el6.x86_64.img

The menu.lst file is soft linked to /boot/grub/grub.conf file and requires root privileges to access.

[root@linuxnix ~]# ls -l /boot/grub/menu.lst
lrwxrwxrwx. 1 root root 11 Jun 16 2017 /boot/grub/menu.lst -> ./grub.conf
[root@linuxnix ~]# ls -l /boot/grub/grub.conf
-rw-------. 1 root root 1184 Feb 15 09:01 /boot/grub/grub.conf
[root@linuxnix ~]#

We’ll now explain the various stanzas of the file.

First, we have the default settings:

  • The default keyword indicates which subsequent menu entry is to be booted i.e it determines which operating system kernel will be used to boot the system.
  • The value of default is zero by default. This implies that the most recent menu entry i.e. the first menu entry should be used to boot the operating system.
  • The first menu entry is generally the latest kernel version.
  • The timeout keyword contains a value in seconds. This specifies the time interval after which the default menu entry will be booted if no particular menu entry is selected.
  • The splashimage contains a path to an image that may be displayed during boot.
  • The hiddenmenu keyword indicates that we need to hit the ESC key to view the boot menu. It will not be displayed by default during system boot.


The next section comprises of the first stanza i.e. the menu entry 0.

title CentOS (2.6.32-696.20.1.el6.x86_64)
root (hd0,0)
kernel /vmlinuz-2.6.32-696.20.1.el6.x86_64 ro root=/dev/mapper/vg_linuxnix-lv_root rd_LVM_LV=vg_linuxnix/lv_swap rd_NO_LUKS LANG=en_US.UTF-8 rd_LVM_LV=vg_linuxnix/lv_root rd_NO_MD SYSFONT=latarcyrheb-sun16 crashkernel=auto KEYBOARDTYPE=pc KEYTABLE=us rd_NO_DM rhgb quiet
initrd /initramfs-2.6.32-696.20.1.el6.x86_64.img

The title indicates the kernel version which is represented by the menu entry. The stanza contains the three critical entries root, kernel, and initrd. If any of these entries are missing for a stanza then we can’t boot the system from that particular menu entry.

  • The root entry points to the location of the GRUB root file system.
  • The kernel section defines the location of the kernel relative to the GRUB root file system i.e. /vmlinuz-2.6.32-696.20.1.el6.x86_64 is actually /boot/vmlinuz-2.6.32-642.el6.x86_64. This also provides options to be used while loading the kernel.
  • The initrd section contains the location of the initial RAM disk file system to be used in conjunction with the kernel to be loaded.


The GRUB shell:
The GRUB bootloader provides a minimal shell where we may run some diagnostic commands. The GRUB shell allows us to execute commands as if they were running within GRUB. We can access this from a running system or from within the GRUB menu. To enter the GRUB shell from a running system, just type grub on the command prompt.

[root@linuxnix ~]# grub
Probing devices to guess BIOS drives. This may take a long time.
Unknown partition table signature

GNU GRUB version 0.97 (640K lower / 3072K upper memory)

[ Minimal BASH-like line editing is supported. For the first word, TAB
lists possible command completions. Anywhere else TAB lists the possible
completions of a device/filename.]

This now drops us into the GRUB shell. To view a list of available commands, type help on the grub prompt as shown below.

grub> help
blocklist FILE boot
cat FILE chainloader [--force] FILE
clear color NORMAL [HIGHLIGHT]
configfile FILE device DRIVE DEVICE
displayapm displaymem
halt [--no-apm] help [--all] [PATTERN ...]
hide PARTITION initrd FILE [ARG ...]
kernel [--no-mem-option] [--type=TYPE] makeactive
map TO_DRIVE FROM_DRIVE md5crypt
module FILE [ARG ...] modulenounzip FILE [ARG ...]
pager [FLAG] partnew PART TYPE START LEN
parttype PART TYPE quit
reboot root [DEVICE [HDBIAS]]
rootnoverify [DEVICE [HDBIAS]] serial [--unit=UNIT] [--port=PORT] [--
setkey [TO_KEY FROM_KEY] setup [--prefix=DIR] [--stage2=STAGE2_
grub will attempt to avoid printing an terminal [--dumb] [--no-echo] [--no-ed
terminfo [--name=NAME --cursor-address testvbe MODE
unhide PARTITION uppermem KBYTES
vbeprobe [MODE]


GRUB root:

This may well be different from the real root file system. The GRUB root is the root of the boot file system. This is generally the /boot directory is partitioned separately or it may be the real root file system. We can use the find command within the grub shell to look for a file named stage1 located in the GRUB root file system. The stage1 file is the master boot record.

grub> find /boot/grub/stage1
find /boot/grub/stage1

Error 15: File not found

[root@linuxnix ~]# ls -l /boot/grub/stage1
-rw-r--r--. 1 root root 512 Jun 16 2017 /boot/grub/stage1
[root@linuxnix ~]#

The error shown in the output above is unfortunately common with systems having booting problems. If this error occurs during system boot then that indicates that GRUB is unable to find a critical component without which the system cannot boot. You’ll need to do some troubleshooting to recover the component or file in question and the boot process will likely not continue if you receive this error.

Let’s run the command again this time omitting the /boot from the file name.

grub> find /grub/stage1
find /grub/stage1

This time the command works correctly and we get the output as (hd0,0). This indicates that the stage1 file resides in the first partition of the first disk on the system which is /dev/sda1 in our case. We had to omit the /boot directory from the location because, for grub, the file will reside in the /grub directory relative to the GRUB root file system which in this case is /boot.


How does GRUB work?
When a computer boots, the BIOS transfers control to the first boot device which is generally a hard disk for modern computer systems. The first sector on a hard is called the Master Boot Record (MBR). This sector is only 512 bytes long and contains a small piece of code (446 bytes) called the primary boot loader and the partition table (64 bytes) describing the primary and extended partitions. By default, MBR code looks for the partition marked active and once such a partition is found, it loads its boot sector into memory and passes control to it. Following this, the GRUB bootloader replaces the MBR with its own code in memory.

GRUB works in three stages and given below is a description of each of them:

  • The Stage 1 or primary boot loader is read into memory by the BIOS from the MBR. The primary boot loader exists on less than 512 bytes of disk space within the MBR and is capable of loading either the Stage 1.5 or Stage 2 boot loader.
  • The Stage 1.5 boot loader is read into memory by the Stage 1 boot loader, if necessary. Some hardware requires an intermediate step to get to the Stage 2 boot loader. This is sometimes true when the /boot/ partition is above the 1024 cylinder head of the hard drive or when using LBA mode. The Stage 1.5 boot loader is found either on the /boot/partition or on a small part of the MBR and the /boot/ partition.
  • The Stage 2 or secondary boot loader is read into memory. The secondary boot loader displays the GRUB menu and command environment. This interface allows selection of the kernel or operating system to boot, pass arguments to the kernel, or look at system parameters.
  • The secondary boot loader reads the operating system or kernel and initrd into memory. Once GRUB determines which operating system to start, it loads it into memory and transfers control of the machine to that operating system.



In this article, we described what is GRUB and how it works and we explained the different sections of the GRUB configuration file. We hope that you’ve found this explanation helpful in understanding the Linux boot process and we look forward towards your feedback.

The following two tabs change content below.

Sahil Suri

He started his career in IT in 2011 as a system administrator. He has since worked with HP-UX, Solaris and Linux operating systems along with exposure to high availability and virtualization solutions. He has a keen interest in shell, Python and Perl scripting and is learning the ropes on AWS cloud, DevOps tools, and methodologies. He enjoys sharing the knowledge he's gained over the years with the rest of the community.