From OSDev Wiki
Jump to: navigation, search

This page is under construction! This page is a work in progress and may thus be incomplete. Its content may be changed in the near future.

GRUB 2 is the GNU Project's next-generation bootloader. It has a more complete feature set than GRUB 0.97 (commonly referred to as "GRUB Legacy"). Still, all things considered, GRUB Legacy is more mature and most of the available documentation is for GRUB Legacy (hence the brief page).



GRUB 2 started its life as the PUPA (note the pun) research project and was rewritten from the ground up. Since then GRUB 2 (actually at time of update 1.97) has grown more stable and even hobby operating systems are starting to make use of the new bootloader instead of GRUB Legacy.


  • Basic scripting support
  • GUI (better bootsplash support, custom colors, custom themes, ...)
  • Memory management
  • Cleaner design
  • Better portability
  • Internationalization
  • Rescue mode

Upgrading from GRUB Legacy

WARNING: These steps have not been tested very well yet. Use at your own risk!

Since GRUB 2 is very different from GRUB Legacy, the directions for getting your kernel up and running are different. GRUB 2 differs from GRUB Legacy in that to implement all but the most basic functionality, the user must load so-called "modules": little bits of code that add components (e.g. a different file system or a VGA font). This section gives you an overview of the process you need to go through when you want to have GRUB 2 load your kernel. It's actually rather simple to create a GRUB2 image (assuming you have GRUB2 either built or installed):

ISO instructions

There have been a lot of tries to make Grub2 work good with ISOs, but mostly failed. The only combination of commands that seems to work is the following.

First create a directory tree called "iso", where you put your kernel (and any other needed files) somewhere. Then in the boot/grub subdirectory create the grub.cfg file which is your configuration.

Now run:

grub-mkrescue -o bootable.iso iso

Be sure that your grub.cfg is syntactically correct. A common mistake is to put the menuentry brace on newline. It must be like:

menuentry "Place your os name here" {

grub-mkrescue depends on program xorriso with version 0.5.6 or higher.

If you cannot get it as binary (possibly from a package named "libisoburn") then get the all-in-one source tarball from GNU xorriso homepage. GNU xorriso can be used where it gets built, without further installation:

 grub-mkrescue --xorriso=/...full.path.../xorriso/xorriso -o bootable.iso iso

Floppy instructions

mkdir tmp
grub-mkimage -p /boot -o tmp/core.img multiboot sh fat # This should work.. I hope :D


Let's go through those grub-mkimage options:

-p By default, GRUB 2 looks in /boot/grub for its configuration file. -p changes this.
-o Like so many other GNU tools, grub-mkimage uses -o to set the output file. By default, it's stdout.
multiboot This module is required to load multiboot-compliant kernels.
biosdisk This module is required for GRUB 2 to be able to boot from a LiveCD.
iso9660/fat Allows GRUB 2 to look on the image for different files.
sh This module allows GRUB to parse the configuration file.

GRUB 2, like GRUB Legacy, needs a configuration file to find your kernel. In GRUB Legacy it's called menu.lst, but in GRUB2, it's called grub.cfg. The syntax for the configuration file is also a bit different.

Here's a sample configuration file (NOTE: This file should be placed into the /boot/grub folder of your disk image, and be named grub.cfg):

set timeout=15
set default=0 # Set the default menu entry
menuentry "OS Name" {
   multiboot /boot/kernel-file   # The multiboot command replaces the kernel command

That's basically it. Copy these files to a disk image, pop it in an emulator, and you're done!

Double check that you put the brace on the same line of "menuentry". It can't be on a new line. This is not C.

USB instructions

Fewer and fewer systems have a floppy disc controller these days, but USB ports are found on all. Modern BIOSes can boot from a USB device, usually by pressing some special key during startup.

Putting GRUB 2 on a bootable USB storage device is a nice way to experiment with your OS on different computers. Here's how you set this up (using Linux):

1. Create a FAT32-formatted USB disk, without partitions:

Warning: the following command uses superuser privileges (sudo). E.g. just typing the wrong character for X could cause severe troubles for your current system

sudo mkfs.vfat -F 32 -n YourLabel -I /dev/sdX
(where sdX is your USB device)

The "-I" option is needed because we are targeting a partition-less device

2. Remove your USB device, and plug it back in. The auto-mounter on your OS should detect it now.

3. Invoke grub-install (on some systems this command is called grub2-install, located under /usr/sbin or /usr/local/sbin)

sudo grub-install --root-directory=/media/YourLabel --no-floppy --recheck --force /dev/sdX

It is important to do this as root (or sudo), else the generated listing available boot devices can be empty. /media/YourLabel is the mount point under Fedora 16, it may be different for other distributions.

4. Create a grub.cfg for your kernel (see above), and copy it to your new bootable USB disk

Disk image instructions

Hobby operating systems don't have to use real devices when running on virtual machines (although it may be, and it usually is faster). Creating bootable GRUB disk image is similar to installing it on USB devices, but here you're working with image itself and partition device at once.

1. Create new disk image file

$ dd if=/dev/zero of=disk.img bs=512 count=131072
131072+0 records in
131072+0 records out
67108864 bytes (67 MB) copied, 0.349436 s, 192 MB/s

2. Create new DOS partition table with bootable entry for your filesystem

$ fdisk disk.img

Add new partition, starting at 1MB (2048th sector). This is more space than GRUB actually needs.

Command (m for help): n
Partition type:
   p   primary (0 primary, 0 extended, 4 free)
   e   extended
Select (default p): p
Partition number (1-4, default 1): 1
First sector (2048-131071, default 2048): 
Using default value 2048
Last sector, +sectors or +size{K,M,G} (2048-131071, default 131071): 
Using default value 131071

Make it bootable

Command (m for help): a 
Partition number (1-4): 1

Write the new partition table to disk

Command (m for help): w
The partition table has been altered!

Syncing disks.

3. Setup two loop devices. One will be used for writing GRUB and its additional codes to MBR, and the second will be used for mounting filesystem of your operating system.

$ sudo losetup /dev/loop0 disk.img
$ sudo losetup /dev/loop1 disk.img -o 1048576

-o option defines offset from start of the file. Number 1048576 is actually 1024^2 = 1MB and that's the start of your partition.

4. Format your partition You can simply use [any supported filesystem] like ext2 or FAT32.

$ sudo mke2fs /dev/loop1
$ sudo mkdosfs -F32 -f 2 /dev/loop1

5. Mount your newly formatted partition

$ sudo mount /dev/loop1 /mnt

Note that if you tried to mount your first loop device which doesn't have any offset set, you would be requested to specify filesystem and even if you did it, you wouldn't get the expected result.

7. Install GRUB using grub-install

sudo grub-install --root-directory=/mnt --no-floppy --modules="normal part_msdos ext2 multiboot biosdev" /dev/loop0

If you mistyped /dev/loop1 (pointing on your partition) instead of /dev/loop0 (pointing on your MBR), you would receive message that grub-install can't use 'embedding' (because there's no space for it) and that it would like to use 'block lists', which are not recomended.

Don't forget to flush the filesystem buffers when manipulating with files on mounted disk image. On a Unix-like system, this can be simply done by executing the sync program in your shell.

HDD Image Instructions for OS X users

It might be useful to create an image file for a HDD; The following instructions help you create a HDD with an MBR partition map. Based on information from <palk> on #osdev, it is slightly more complicated to create a HDD image than you'd expect.

This information might not be applicable to Linux users, who will most probably want to use a loopback device. This is for developers on OSX, which doesn't have a loopback device and has a finicky image mounter.

1. First, create a blank, raw image with DD, with the required size. Here, I'll make a 80MB image -- 163840 sectors of 512 bytes.

dd if=/dev/zero of=disk.img count=163840 bs=512

2. Next, calculate the CHS values for the disk and have them at hand. TODO: Explain this.

   Here, it's a 80MB disk, so the CHS values are 78, 32 and 63 respectively.

3. Fire up FDISK (or your tool of choice) -- I'm using the OSX version here, so commands may differ. The concept is essentially identical.

What will show on your screen (in OSX anyway) is on the left, what you enter is on the right.

fdisk -e disk.img
The signature for this MBR is invalid.
Would you like to initialize the partition table? [y]           Yes
fdisk:*1>                                                       disk
Disk: disk.img	geometry: 650/4/63 [16340 sectors]
Change disk geometry? [n]                                       No
fdisk:*1>                                                       edit 1
Partition id ('0' to disable)  [0 - FF]: [B] (? for help)       0B
Do you wish to edit in CHS mode? [n]                            No
Partition offset [0 - 163840]: [63]                             2047
Partition size [1 - 161793]: [161793]                           <Enter>
fdisk:*1>                                                       write
fdisk:*1>                                                       quit

4. Now that the MBR Partition Table is initialised, you'll want to make a Filesystem on the disk. But first.

   Here, we separate the MBR bit, and the actual FS bit.
dd if=disk.img of=mbr.img bs=512 count=2047
dd if=disk.img of=fs.img bs=512 skip=2047

5. Because we're on OS X, we need to mount the disk image first, without actually mounting it.

hdiutil attach -nomount fs.img

6. Use 'diskutil list' to find out which device your image is, use that below.

7. Now, make a FAT12/16/32 filesystem on the FS.img disk. Remember, use FS.img -- not disk.img

newfs_msdos -F 32 /dev/diskX

8. Now you'll want to unmount it, then recombine the two images, then install GRUB.

hdiutil detach /dev/diskX
cat mbr.img fs.img > disk.img
hdiutil attach disk.img
# note the mount point here (/Volumes/NO NAME, probably)
grub-install --modules="part_msdos biosdisk fat multiboot configfile" --root-directory="/Volumes/NO NAME" disk.img
Installation finished. No error reported.

And there it is! You know have a disk.img, that will have GRUB2 installed, ready to go. It should be mountable in OSX simply by double clicking (or with the mount command). Enjoy!

Additional useful options

Whatever device you are using, you may want to have a PC partition table and create a partition you format in one of the filesystems supported by GRUB. If you do, be sure to add the following option the grub-install arguments:


In general, if GRUB2 happens to fail to do what you want and you suspect that it needs some missing functionality, just try to add a module name you believe has the functionality you need to the --modules argument. The module files generally are in /boot/grub/i386-pc/.


Some versions of GRUB 2 like to put multiboot modules in relatively high physical memory addresses, in contrast to GRUB-legacy which loaded them into low memory. Be careful when making your kernel work with GRUB 2 that it is not making any assumptions about where the multiboot modules will appear.

When your kernel gets control, the machine state is defined as follows: Multiboot machine state. Your code should have minimal dependency on this initial state; for example, define your own GDT instead of relying on the GDT setup by GRUB.


As the GRUB 2 manual puts it:

The primary requirement for GRUB is that it be compliant with the Multiboot Specification.

But the Multiboot header as used by older versions of GRUB 2 (field is present in GRUB 1.99 and newer) did not include the header_length field that is specified in the Multiboot 1.6 specification.

GRUB 2 also supports the old Multiboot 0.6.96 specification. It is possible to include both headers.

Installing GRUB2 on Mac OS X

The installation of GRUB2 on OS X is a little tricky. The latest released version 2.00 (as of 7th of October, 2014) doesn't seem to work with any configuration. The developer team fixed this in the newer revisions.

Important: To build GRUB2 so that it can produce a bootloader for your output target you need to have a compiler for that target. So for example, if you want a bootloader for i386-elf (as suggested in the bare bones) you'll need binutils + a compiler for that target. This is required on Mac OS X because the built-in LLVM doesn't know how to make i386-elf binaries. So you can either build a cross-compiler or create an OS-specific toolchain (recommended) for your target platform. You will need the cross-versions of gcc, objcopy, strip, nm and ranlib in step 4.

1. Clone the developer version of the sources:

git clone git://

(This was tested on revision: 77063f4cb672f423272db7e21ca448cf3de98dcf)

2. A tool named objconv is required, get it from:

Download sources, compile (see website for details) and make available in your PATH.

3. Run "" in the GRUB sources folder

4. Create a seperate build directory, switch to it, and run GRUB's configure script (insert your target-specific tools!):

../grub/configure --disable-werror TARGET_CC=i386-elf-gcc TARGET_OBJCOPY=i386-elf-objcopy \
TARGET_STRIP=i386-elf-strip TARGET_NM=i386-elf-nm TARGET_RANLIB=i386-elf-ranlib --target=i386-elf

5. Run "make" and "make install"

Now you have a working GRUB2 that has the required files to build an image that boots on i386 platforms.

Grub for EFI

This section will tell you how to compile, build and install Grub2 on an EFI system. This have been tested on an MacBook Pro6,1


First you need a x86_64 linux with gcc and binutils. I downloaded a Ubuntu 10.4 LiveCD, booted it in VirtualBox and installed it to disk.

You need to make sure gcc, bison, flex etc are installed. Do this with the apt package manager. apt-get install gcc bison flex is what i did.

You need the grub2 source code. I got that from

Download grub-1.9-rc2.tar.gz and unpack it.

Next thing to do is
./configure --with-platform=efi --target=x86_64

next step is to compile:


Now you should have compiled grub2 efi if everything went ok.

Build Grub EFI binary (bootx64.efi)

grub.efi / bootx64.efi is a bundle of tools including grub itself. You need to make the efi image by selecting what modules you want.

For Grub to be able to read disk partitions you need a module for that. Either you want plain-old bootsector and msdos style partition map or you want GPT (new fancy one) you need to select correct module when bundling grub.efi.

For your grub to be functional you should include as many filesystems as possible and also linux,multiboot,multiboot2 etc so that you can read any type of kernel from any type of filesystem.

So.. Lets build grub.efi / bootx64.efi

Go to "grub-core" folder.

Execute: ../grub-mkimage -d . -o bootx64.efi -O x86_64-efi -p /efi/boot [list of modules without .mod]

where "-p /efi/boot" tells where "grub.cfg" is after booting and it will be loaded from this path on booting device.

A easy way of adding all modules is:

../grub-mkimage -d . -o bootx64.efi -O x86_64-efi -p /efi/boot `find *.mod | xargs | sed -e 's/\.mod//g'`

That will build "bootx64.efi" in the subfolder and this can now be copied to a USB-disk, harddisk etc.

From UEFI specification the EFI bios will try to load & boot from /efi/boot/bootx64.efi on a FAT formated drive. This is for x86_64 plattform.


Add a "grub.cfg" file to /efi/boot/gruf.cfg or wherever you like. Make sure to put it where you told grub to look for its files "-p option".

To use graphical menu you must also provide a font file. I used unicode.pf2 that i found in /usr/share/grub2 or something.

I did like this:

set timeout=30
set default=0
#set debug=all

loadfont /efi/boot/unicode.pf2
#set gfxmode=1024x768
set gfxmode=auto
set gfxpayload=keep
terminal_output gfxterm

background_image -m normal /efi/boot/background.jpg

menuentry "OSKernel" {
set debug=all
multiboot /kernel32.exe
module /null.sys
module /console.sys
module /serial.sys
module /keyboard.sys
module /random.sys
sleep 5 

Some nice to know info is that grub2 (1.99rc2 atleast) parses the video mode information in the multiboot header. It also tries to sattisfy your request. This means that you can request text/video, WxHxD from the multiboot header. Video information about mode, framebuffer address etc should be available in the multiboot info aswell. Sweet isnĀ“t it? :)


I partitioned my usbdisk with MacOSX diskutil, but any partition tool should/would do. I created a small 100mb partition as first partition and created a huge secondary partition for files. I formated the partition to HFS+, but i guess FAT should be more compatible since i dont think other EFI firmwares have HFS+ filesystem support like the Mac..

Anyway i created "/efi/boot/" folder and copied bootx64.efi to /efi/boot/bootx64.efi on my disk. I then created a grub.cfg file alongside with it.

To make OSX find the bootx64.efi image on boot i did;

sudo bless --verbose --folder=/Volumes/EFI --file=/Volumes/EFI/efi/boot/bootx64.efi --setBoot

where /Volumes/EFI is the first partition on my usb disk..

Now i saved my work and rebooted.. Press/hold "option" key during boot will bring up boot menu. I now get an option to boot en EFI DISK. I select this and now Grub2 shows like any other Grub..

Configuration of grub and config file is like any other grub2 syntax.

The "blessing" procedure should not be needed on UEFI compatible EFI versions. These will always look for /efi/boot/bootx64.efi.

See Also


External Links

Personal tools