LEG/Engineering/Kernel/GRUBonUBOOT - Linaro Wiki



Prerequisites for U-Boot Support

A compliant U-Boot must be configured with

  • EFI/GPT partition table support
  • MSDOS partition table support
  • EXT2 filesystem support

Prerequisites for build environment

You should have the following build dependencies installed

  • autoconf
  • autogen
  • automake
  • bison
  • flex
  • gcc
  • (optional) libdevmapper header
  • (optional) freetype2 library
  • (optional) FUSE library

Prerequisites for grub-install

Building and installing Grub for U-Boot

Download the source code from launchpad:

 1 $ bzr branch lp:~leif-lindholm/linaro-grub/arm-uboot

Since this is a raw source checkout, you need to first prepare the build system:

 1 $ cd arm-uboot
 2 $ ./

Configure, build natively and install (uboot is the default platform for the ARM target, /usr/local is the default prefix):

 1 $ ./configure --with-platform=uboot
 2 $ make -j`getconf _NPROCESSORS_ONLN`
 3 $ sudo make install

This will install tools to /usr/local/bin and /usr/local/sbin, with GRUB kernel and modules under /usr/local/lib - it is still not "installed" as a bootloader.

Note: Cross compilation is not recommended, but if you do need to cross compile for ARM target, you need to pass --build and --host configure options. e.g.

 1 $ ./configure --build=x86_64-linux-gnu --host=arm-linux-gnueabihf --with-platform=uboot

Setting up GRUB as a bootloader under U-Boot

First, install GRUB into your filesystem:

 1 $ sudo grub-install /boot

grub-install (above) calls grub-mkimage, which generates an image with a U-Boot header on it, masquerading as a Linux kernel. This file ends up in <installdir>/grub/arm-uboot/core.img. grub-install also extracts the UUID of the /boot partition if it is an ext filesystem and passes this as an embedded configuration file to grub-mkimage to notify it where the GRUB root partition is. If /boot is not on an ext filesystem, GRUB will read the U-Boot environment variable grub_bootdev to find this (for example fd0,msdos1).

grub-mkconfig cannot necessarily be trusted to do the right thing yet, but however you generate it, GRUB will look for /grub/grub.cfg in its root partition.

GRUB (core.img) is then somehow (through a boot.scr, uboot.env or manually) loaded as a normal image in U-Boot and executed with bootm.

Running GRUB on U-Boot on Versatile Express

Note: These instructions have been tested on the 4x-Cortex-A9 core tile, but should work for others too.

U-Boot requirements

The u-boot-linaro-stable default configuration does not include EXT2 filesystem support. Since this is a requirement, you need to rebuild it with CONFIG_CMD_EXT2 added in u-boot-linaro-stable/include/configs/vexpress_common.h. It might also be a good idea to add CONFIG_EFI_PARTITION in the same file while you're at it :)

Kernel requirements

The only real requirement on the kernel is that:

  • It is built as a simple zImage (none of that uImage wizardry!),
  • it is built with Flattened Device Tree (FDT) support and
  • that it does not simply append that device tree to the kernel image.

Since, for the moment, the kernel source tree is also the repository for the device tree descriptor sources, .dtb files are generated in linux/arch/arm/boot/ (linux/arch/arm/boot/dts from 3.8? onwards) for the platform(s) enabled in your configuration.

Initialise an SD card

Using your partitioning format of choice, prepare an SD card (not SDHC) as follows:

  • Create an ext2 partition to be your /boot, at least 128MB in size

  • Create an ext (2, 3 or 4) to be your /, as large as fits

    • Alternatively, put your / on a different device, supported by your kernel, but not GRUB.

  • Initialize the filesystems
  • Copy kernel and .dtb. files into the /boot filesystem.

Installing GRUB on the SD card

 1 # mount /dev/sdb1 /mnt
 2 # grub-install --boot-directory=/mnt

Creating a simple config file

You can use a configuration file If no configuration file is present, GRUB will fall boot straight to its command prompt.

All paths in the configuration file are relative to the root of the filesystem GRUB is installed on (/boot).

Here is a minimalistic configuration file that Linux kernel commandline parameters are anything passed as parameters to the linux command beyond the first one (which is the actual image). The images here are not uImage/uInitrd like used by U-Boot, but just the raw ramdisk and zImage.

 1 # cat /boot/grub/grub.cfg
 2 # This is a comment
 3 echo "Hello from grub.cfg"
 5 menuentry 'Test menu entry' {
 6         devicetree /vexpress-v2p-ca9.dtb
 7         initrd /initrd
 8         linux /zImage console=ttyAMA0,38400n8 rootwait clcd=xvga mmci.fmax=4000000 root=/dev/mmcblk0p2 ext4 ro
 9 }

You can also use the parameter timeout <seconds> to make GRUB automatically boot the first option after <number> seconds.

Booting the Versatile Express

From within U-Boot:

 1 Now running in RAM - U-Boot at: 7ff89000
 2 Flash: 128 MiB
 3 MMC:   MMC: 0
 4 In:    serial
 5 Out:   serial
 6 Err:   serial
 7 Net:   smc911x-0
 8 Hit any key to stop autoboot:  0 
 9 VExpress# mmc rescan
 10 VExpress# ext2load mmc 0:1 $loadaddr /grub/arm-uboot/core.img
 11 Loading file "/grub/arm-uboot/core.img" from mmc device 0:1 (Linux filesystem)
 12 49320 bytes read
 13 VExpress# bootm

The boot process will "freeze" for several seconds after displaying the Welcome to GRUB! message, while GRUB automatically loads available modules from the SD card filesystem.

The current GRUB on U-Boot port is statically linked and relies on there being writeable RAM available at physical address 0. This prevents it from working on certain platforms, such as the Samsung Arndale and TI Pandaboard.


The following has actually been reported to me to get GRUB working on Samsung Arndale.

There are 3 locations in the GRUB sources that need to be modified:

  • grub-core/Makefile.core.def

    • Change the link address in arm_uboot_ldflags.

  • include/grub/offsets.h

    • Change GRUB_KERNEL_ARM_UBOOT_LINK_ADDR to the appropriate value.

  • utils/

    • Towards the end of the file, there is a line starting with mkimage -T kernel -A ARM -O Linux .... Change both addresses on this line (parameters to -a and -e flags, specifically) to the appropriate value.

The proper solution

The proper solution would mean extending the port so as to make grub-mkimage output a fully relocateable ELF image instead, and then let U-Boot's ELF loader sort out getting it to where it needs to be. There is an image type in there called IMAGE_LOONGSON_ELF that could be used as a template.