GRUB 2.0 is an open-source bootloader that can directly or indirectly load a variety of operating systems. (See Legacy Grub for information on the earlier version of GRUB.)
When GRUB is being loaded by BIOS, it consists of two parts:
The code in the GRUB boot sector loads the first sector of the main body of GRUB, known as core.img. (core.img may be stored in one of three places: (1) in the space between MBR and the beginning of the first partition, (2) in a separate partition, or (3) in the /boot/grub directory within the file system.) Again this is only true if the system is being booted via GRUB.
core.img or grub64.efi contains the basic functionality of GRUB, including file-system code for whichever type of file system is used by GRUB for the /boot/grub directory. This may reside in the root file system partition or maybe be a mount point for a separate partition. In the case of UEFI, then grub64.efi must reside in a FAT file system and is therefore almost always a separate partition.) Using this file-system code, GRUB locates and loads dynamic modules for the remaining GRUB functionality. These dynamic modules have a filename extension of ".mod" and are in standard ELF object-file format. They contain 32-bit code (even for a 64-bit OS).
GRUB plus dynamic modules consist of a number of components:
The command language used by GRUB is very similar to the language read by shells such as BASH. It differs in two primary ways:
To summarize the process of loading GRUB:
Thus grub.cfg can configure GRUB to run in one of two ways:
in a UEFI system the GRUB usually includes a menu option to run the UEFI shell. If this menu option is selected, GRUB calls a UEFI function to run the shell. If the user enters the shell "exit" command, the the shell exits and control returns to GRUB. (Don't confuse the UEFI shell with the GRUB command processor.)
GRUB can load the following types of systems:
Here is a typical menu entry for loading a Linux system:
menuentry 'Ubuntu, with Linux 3.2.0-32-generic-pae' --class ubuntu ---class gnu-linux \ --class gnu --class os { recordfail gfxmode $linux_gfx_mode insmod gzio insmod part_msdos insmod ext2 set root='(hd0,msdos1)' search --no-floppy --fs-uuid --set=root 42ac3bc5-54ff-4a57-856e-69d11ad656d7 linux /boot/vmlinuz-3.2.0-32-generic-pae \ root=UUID=42ac3bc5-54ff-4a57-856e-69d11ad656d7 ro quiet splash $vt_handoff initrd /boot/initrd.img-3.2.0-32-generic-pae }
Note: I added the backslash (\) characters for readability; they are not in the original file, and I'm not sure they're valid in a real grub.cfg file.
The above commands may be explicitely stored in grub.cfg file. However, as GRUB functionality has increased, it is now possible to have these commands generated automatically at boot time based on scanning the /boot directory.
The purpose of each of the sample commands shown above is as follows:
The recordfail command causes GRUB to make note of boot failures for recovery purposes.
The gfxmode command specifies a graphics mode for the boot loader to run in. (Note that the text display in the menus is character-mode data, but GRUB can display a background image if the underlying video interface supports it.)
The insmod commands load additional code into GRUB from the specified files. In the first example, "insmode gzio" would load the file /boot/grub/gzio.mod into GRUB.
The set command sets a value for the "root" variable that specifies the drive from which we are booting.
The search command locates the partition that contains the operating system. The search uses a UUID (Universally Unique IDentifier), in this case, 42ac3bc5-54ff-4a57-856e-69d11ad656d7, which was associated with the partition when it was created.
The linux command loads the kernel into memory. The first word following "linux" specifies the filename of the file containing the kernel. All words following the filename are parameters that are passed to the kernel when it is started.
The initrd command specifies an "initialization RAM disk" (thus the name initrd). This file contains a simple file-system structure and a series of files to be loaded by the kernel. These files consist of drivers and other dynamic modules that must be loaded by the kernel early in the boot process. Because the file-system module as well as disk drivers might be loaded as dynamic modules, the kernel cannot use either file system or disk driver to load these components. The kernal has a built-in simple-minded file system for the express purpose of reading this RAM disk.
Thus, GRUB loads the initrd file system into memory, and will pass its address to the kernel. The kernel will then load the "real" file system code as well as a disk driver from that initrd file system.
Once the kernel and initrd are read into memory, GRUB transfers control to the kernel. GRUB passes to the kernel the addresses of (1) the command-line string and (2) the initrd file system.
NOTE: For some distros (such as Ubuntu) you will find the above commands in the grub.cfg file. For other distros (e.g. Fedora) the actual boot commands are not in boot.cfg. Rather they are dynamcially built by the blscfg command at boot time. The blscfg command reads configuration files from the /boot/loader directory, one config file for each Linux kernel version to be shown in the menu.
Both techniques (either coding the commands in the grub.cfg file or specifying the kernels in separate config files) are designed to make it easy for the package manager to add or delete kernels as needed. In the former case, the list of kernels are updated by the package manager; in the latter case the list is generated by GRUB.
Next: The Kernel