GRUB on U-Boot
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
- (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:
Configure, build natively and install (uboot is the default platform for the ARM target, /usr/local is the default prefix):
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.
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
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
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.
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.
Memory map dependency
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:
Change the link address in arm_uboot_ldflags.
Change GRUB_KERNEL_ARM_UBOOT_LINK_ADDR to the appropriate value.
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.
LEG/ServerArchitecture/GRUBonUBOOT (last modified 2017-08-17 12:12:54)