Jeff's loader
Jeff Mock
jeff@mock.com
(c) 2002
version 0.1.0
This is a linux bootloader for embedded X86 PC architecture systems. The
bootloader is intended to be small, easy to understand, and easy
to adapt to the special requirements of embedded systems without
becoming an expert on bootloaders.
The bootloader is not nearly as sophisticated as grub or lilo. There
are many things it does not know how to do:
Boot from from ext2 partitions
Serial port consoles
Support for raid configurations
Boot from extended partitions
Boot from anything other than the first IDE device (/dev/hda)
Present sophisticated menus for the user
Load old kernels
It has a few nice features
Mostly written in C
Boot from cramfs root partition
Change to VESA video mode and present splash screen before
kernel is loaded.
Utility script to build disk image for embedded system without
root priveledges or using fdisk, lilo, etc.
Program structure:
The loader image jlo consists of two pieces. The first
piece is made from mbr.S, a 512-byte boot sector containing
a partition table and a small program to load the secondary
bootstrap. The MBR has a table of sectors to load the secondary
bootstrap. A utility program might modify this table to
suit a boot environment, but the table is by default loaded to
read the secondary bootstrap starting from the second sector
on the disk.
The secondary bootstrap is a C program that is hopefully
easy to modify for particular applications without becoming
an expert is in the subtleties of booting.
The secondary bootstrap is about 6k bytes.
It is a 16-bit real-mode C program. It initializes
the display to a VESA graphics mode, loads a splash screen
and then loads a linux kernel from the first partition in
the partition table marked active.
User Interface
The loader has a very simple user interface. By default
it loads and starts the kernel with no user interaction.
There are a few things you can do to change this process
during development.
If you hold the shift-key down during booting, the MBR
will bail and return to the BIOS. On many motherboards
(like VIA mini-ITX) this will drop into the PXE ROM
for network booting, often very useful for embedded development.
If you hold down the ctrl-key during booting, the boot
process will proceed as usual but the console is left in
text mode, the splash screen is not displayed, and the video
mode parameter passed to the kernel leaves the console
in text mode. This lets you see jlo and linux booting
messages for debug.
If you hold down the atl-key during booting the loader
will present a very simple user interface to manually
select a partition for booting.
Installing
After running make you hopefully wind up with a file called jlo.
This is the MBR and secondary loader together. This should be
put on the first sectors of the boot device. For development I
am using a VIA mini-ITX motherboard with a compact flash adapter.
My boot device is a compact flash card that appears as /dev/hda on
the target machine.
After putting the bootloader on the device, the partition table
needs to be configured to make some partitions.
After creating the partition table a cramfs filesystem needs to be
put on one of the partitions.
A perl program is included for building an image for a boot device.
mkimage needs to know the disk geometry of the boot device.
By default it uses the geometry for a generic 8MB compact flash card.
This is probably not what you want.
You run mkimage something like:
% ./mkimage --sectors=32 --heads=2 --cylinders=248 --p1=myfs
--image=cf.img
This will create a file called cf.img that is an image of an
8MB flash card containing the bootloader and a partition containing
the file myfs. myfs should be an image file of a cramfs
filesystem.
Create the myfs image of the cramfs filesystem using mkcramfs.
To make a bootable cramfs image use the "-i" option to mkcramfs
to insert a kernel image into the cramfs filesystem. Something
like:
% mkcramfs -i bzImage root myfs
The file bzImage should not be under "root", this is a waste of
space. The kernel is inserted at the beginning the filesystem
image and is not part of the filesystem.
Once the image of the device is made you can use dd to copy
it to an actual device for booting:
% dd if=cf.img of=/dev/xxx bs=512
A host program called writecf is also included to make writing
the file image more efficient. writecf only writes used sectors
rather than writing all of the sectors like dd. This speeds
up writing large flash cards quite a lot.
The utilities bootpart.c and update might useful for the target
machine. The idea is to keep two cramfs partitions on the boot
device, one for booting and the other for updates. The update script
downloads a new image, copies it into the unused partition, verifies
the partition and then changes the default boot partition to the new
partition only after the download has been verified. This limits
the exposure for failure during a software upgrade to a very small
window when the active parititon of the boot sector is written.
If these utilities are used, the original device image should be
created using the --p1-size and --p2-size options to make sure
the partitions are large enough to hold future updates even if the
initial filesystem is smaller.
Splash Screens
An optional splash screen is stored in the boot partition along
with the kernel. There are two ways to go. If the file inserted
into the cramfs partition is a bzImage kernel file then the
system will boot without changing the video mode just like lilo.
The other way to go is to create a run-length encoded image to use
as a splash screen while the kernel is being loaded. The perl
script mkrle takes a PNG image and turns it into a splash format.
There are a few extra options to mkrle to set the background color
and screen offset for the image if the image is less than full
screen. By default jlo will center a smaller image on the screen
with a black background if the options aren't set.
One day mkrle might have a few different methods for RLE
encoding the image, but right now it just knows one format. RLE64.
This format places some constraints on the source image. The
image must contain no more than 64 different colors, the format
builds a 64-entry color map table and will barf if the image
contains too many colors. Photoshop does a nice job dithering down
to 64 different colors. Run mkrle something like:
% ./mkrle --png=splash.png --mode=0x111 --out=img.rle --bg
In the above example, the image will be centered on the screen
since --xoff and --yoff weren't specified. If the image is smaller
than fullscreen the --bg option sets the background color the same as
the color of the pixel in the upper left corner of the image. If
you want to specify the background color manually use the --r, --g,
and --b options to mkrle. The --mode option to mkrle sets the
VESA graphics mode. In this example 0x111 is 640x480x16 with the
pixels organized as 5-6-5 RGB.
Once you create the splash RLE image, the splash image needs to
be combined with the kernel something like:
% cat img.rle bzImage > bootfile
% mkcramfs -i bootfile (...)
When the combined splash/kernel is inserted into the cramfs
image jlo will put up the splash screen in the desired video
mode and then load the kernel. If the enclosed kernel patch
is applied, the kernel will smoothly transition to to create
a /dev/fb0 device in vesafb mode with this video mode without
any annoying flashing or glitches.
Command line options to kernel
jlo builds a simple command line for the kernel. It sends the
"auto" option, sets the root device with root=/dev/hdaN, passes the
video mode used by the splash screen with video=0xnnn option.
If the application needs more command line options these can be
passed in the header of the splash screen image. mkrle has an
option to append options to kernel command line. Use it something
like:
# mkrle --png=splash.png --out-img.rle --cmd="vesa=ypan"
If you want to pass command line options or set the video mode from
the bootloader, you must included a splash screen. This information
is stored in the header of the splash screen image prepended to the
kernel.
Tools
Building jlo requires bcc, as86, and ld86. These are
16-bit real-mode x86 tools. These are included in most
big modern linux distributions, but you can get the
latest dev86 tools from:
http://www.cix.co.uk/~mayday/dev86/
At this writing, jlo is built using 0.16.0 of dev86.
Kernel patch
You don't need to patch the kernel, but the following patch
improves the boot process with a splash screen. With the patch
the kernel checks to see if the video mode has already been
set before setting the video mode. This way the there is no
screen flashing between the boot loader splash screen and
linux booting. The patch is against 2.4.20 in the file
patch.linux.