137 - grub2 tutorial

Introduction

This tutorial is about the grub2 boot loader - i.e. the grub> prompt that you see when you boot from a device which has grub2 installed.

Do not confuse grub2 the bootloader/boot manager with legacy grub, grub4dos or GRUB or GRUB2 (which are linux scripts which can be configured to make various grub2 menus).

I have not found any decent guide on grub2 (a very incomplete official manual is here), so this is an attempt to help others and serve as a reminder to me (with useful links)!

As this site is mainly interested in USB booting, I will assume you want to boot from a USB drive to a grub2 menu.

Getting started

If you are a Windows user, you can install grub2 to the MBR and following sectors of a USB drive using:

RMPrepUSB - BootLoaders - Install grub2 to MBR

If you then try to boot from the USB drive (e.g. using RMPrepUSB - F11), it will boot to the grub rescue> prompt because it will not be able to find the /boot/grub/grub.cfg file or any files under /boot/grub.

For linux users:
  • Open a terminal and type sudo su
  • Type fdisk -l (and note which device is your USB)
  • Type mkdir /mnt/USB && mount /dev/sdx1 /mnt/USB (replacing x with your actual usb device)
  • Type grub-install --force --removable --boot-directory=/mnt/USB/boot /dev/sdx (replacing x with your actual USB device)
  • See also here.
The grub rescue console supports a limited number of commands (set, unset, insmod, ls).

You can type set to see what grub2 environment variables have been already set.

See 'Booting the computer' for details of the boot process.



grub2 uses environment variables. For instance, the current root is changed just by a set root=xxx command (you can also use root=xxx).

grub2 normally continues by loading some 'modules' from the $prefix/boot/grub/<arch>/ directory by default.

A typical Ubuntu OS will have one or more of these module directories
/boot/grub/i386-pc - for MBR-mode x86 modules
/boot/grub/i386-efi - for 32-bit EFI-mode
/boot/grub/x86_64.efi - for 64-bit EFI-mode

To boot to the grub rescue prompt, rename these three folders so they cannot be found.

Find these directories from a Ubuntu ISO and copy them to your USB drive (note: will be case-sensitive if ext filesystem).
e.g. If you are MBR-booting (e.g. using QEMU) it will need the /boot/grub/i386-pc module folder.

Now boot to grub2 again. This time you should see a grub> prompt as it boots to the grub command shell.

This is because it has found and loaded the normal.mod module and probably several other modules so that it can access different file systems.
Type lsmod to see what modules have been loaded.

Tip: If a broken system boots to the grub rescue prompt, ensure the prefix variable is correct and type insmod normal to load the normal module and then type normal to get it to load the full grub2 shell.

With the full 'normal' shell, we have many more commands available, because of the modules that have been loaded.
Hit the <TAB> key to see most of the possible commands (but not all!) now available or l<TAB> to see what commands beginning with l are available.

The pager variable controls screen paging. Type set pager=1 and then help to see what page mode does and then unset pager to turn it off.

The debug variable determines the debug level (try set debug=all).

You can use a help command such as help chainloader to get more information about a command (though often it is inaccurate and incomplete!).

You may find some more useful information about grub2 here.

Modules

Modules can be considered as 'plug-ins'. They add functionality.

A good explanation of modules can be found here.

A list can be found here.

Load a Menu

Typically, grub2 will look for the /boot/grub/grub.cfg file after loading the normal.mod module.

.cfg configuration files use a modified form of linux scripting (which does not seem to be fully documented!).

A Guide to shell script language (very similar to grub2) can be found here and bash script programming here and a syntax guide here.

Note that grub.cfg files often start by loading many modules.
Some modules also add more commands to the environment. For instance, if you load the video gfxterm module, the background_image command is then available.

grub2 menu entries are in the form:

menuentry 'Ubuntu, with Linux 2.6.32-24-generic' --class ubuntu --class gnu-linux --class gnu --class os {
# load ext2 module
insmod ext2

# set the current root to 2nd drive, 6th partition
set root='(hd1,6)'
# search for a volume of this UUID
search --no-floppy --fs-uuid --set 6655ee5e-45d1-4d1c-9a7d-10f30f16e745
# load the linux kernel and include boot parameters
linux /boot/vmlinuz-2.6.32-24-generic root=UUID=6655ee5e-45d1-4d1c-9a7d-10f30f16e745 ro quiet splash
# load the ramdisk image
initrd /boot/initrd.img-2.6.32-24-generic
}

lines can be commented using #
Note that this menu loads the ext2 module in case the linux boot files are on an ext2 formatted volume

The commands most useful to call from grub.cfg are:

command description
search find (hdx,y) value for a filesystem with specific label, UUID, etc
terminal configure a textmode terminal
gfxterm configure a graphical terminal
recordfail save state for next boot
echo write to terminal
test interprets [ … ] expressions
linux sets up Grub data-structures so that later execution of the “boot" command will boot into a specified Linux kernel.
chainloader load and jump to the MBR of a different disk partition

Some commands useful to call from an interactive commandline are:

  • ls, cat, echo, hexdump, parttool, tar, reboot

set menu_num=$1 inside a menuentry will set menu_num to the menu number of that entry.

If the value of a variable contains spaces, you must use 'escaping' using "" or {}, e.g. to write 'abc def' ...
set fred="abc de"
echo ${fred}f
echo "$fred"f

To get a line of input from the user as variable myline (or just use read to pause and get user to press ENTER)
read myline

some other useful commands for menus are:

save_env fred peter - saves the current value of these two variables to the /boot/grub/grubenv special file.
load_env fred doris - loads the stored values of fred and doris from the /boot/grub/grubenv special file.
list_env - lists the variables stored in the /boot/grub/grubenv special file.

set default=2 - sets the default menu item to be highlighted/selected
set timeout=5 - sets 5 second timeout

Some of the other variables used by grub2 are here.

background_image /iso/mywallpaper.jpg - loads a background image, .png and .jpg supported (maybe more if modules are loaded?) - requires the gfxterm module

color_normal=red/blue - command to set foreground/background colours of console text
color_highlight=gray/black - command to set foreground/background colours of menu highlight text (not needed if set menu_color_highlight is used)
set menu_color_highlight=red/blue - variable is used by menu system when it is loaded
set menu_color_normal=gray/black - variable is used by menu system when it is loaded

set gfxmode=1366x768 - set the video mode

configfile /boot/grub/main.cfg - passes control to another config file, don't forget to export any variables if you want them to also be passed on.

set gfxpayload=keep - you may not see anything when linux boots unless this value is correct! try text or auto too. See here.

More complex example grub.cfg is here.

Grub2 Gotchas - see here.

Tip: Checkout the generic_isoboot.cfg file. If you rename this to \boot\grub\grub.cfg and place your ISO files in the \iso folder, it should build a isoboot menu for you!


Scripting

Loosely follows bash shell
Useful functions and notes regular expressions

function pathname { regexp -s 2:"$2" '^(\(.*\))?(/.*)$' "$1"; } # /_ISO/ubuntu 64.iso
function devname { regexp -s "$2" '^(\(.*\)).*$' "$1"; } # (hd0,msdos2)
function pathonly { regexp -s 2:"$2" '^(\(.*\))?(.*/)*' "$1"; } # /_ISO/
function getext { regexp -s 3:"$2" '^(.*/)*(.*)\.(.*)$' "$1"; } # iso
function getfname { regexp -s 2:"$2" '(.*)/+(.*)' "$1"; } # ubuntu 64.iso

usage where $file = (hd0,msdos1)/_ISO/DIR/some file name with spaces.iso
# set isopath to the fullpath without device name
pathname "$file" isopath # make sure double-quotes around $file - set isopath variable to fullpath

2: = get second match value, 3: = 3rd matched value
^ = start at beginning
(\(.*\))? = ( look for (anything) ) ? is zero or more of preceding match
(/.*)$ = look for / followed by any chars up to end of line

(.+/)* = look for 1 or more chars up to / any number of times
(*+)\. = look for 0 or more chars followed by .
(.+)$ = look for all chars till end of line

testing regexp from the grub2 command line
unset fred ; regexp -s 2:"fred" 'test regexp here' "$file" ; echo $fred
# if filename does not contain ubuntu then abort
if ! regexp '(.*)[uU][bB][uU][nN][tT][uU]' "$myfname" ; then continue ; fi



ċ
generic_isoboot.cfg
(6k)
Steve Si,
20 Feb 2017, 04:53
Comments

Search