A Simple Menu-based Boot Manager using Kexec (BootMenu)
In PC platforms, there are many capable and versatile boot loaders like syslinux, Grub, Grub2, Grub4dos, and many others. One of the features that many of these bootloaders share is the ability to pre-configure many different settings for booting the PC, including this kernel and which operating systems to boot. These settings is then made available for selection to the user when the PC is started, either through commands or through a menu system.
In the ARM platforms, the situation is a bit different. U-Boot, the most popular bootloader, does support multiple-configuration booting but lacks a menu-system or otherwise easy selection of different boot configurations. In addition, U-Boot usually runs before the display is initialised, thus the only way a user can interact with it is using the serial console attached to a serial terminal (usually another computer). For many devices to get the serial console running, one has to open the device's case and attach a special serial cable (containing serial-to-USB board) to an obscure point on the device's motherboard ... not a prospect that many are prepared for.
The reason for discrepancy is simple. PC, from day one, as designed as a general purpose machine, thus it is designed to be versatile. ARM, however, (apart from its original incarnation in RiscOS machines), are used more of an embedded platform; or single purpose device. Thus once installed, there is no need to choose or edit the configuration of the bootloader and the OS again until the next firmware update; the flexibility of the bootloader is only needed during system design (in which serial console is acceptable).
However as more and more ARM devices are coming to take their part in the general purpose computing, there is a need to have a flexible boot manager that provides facilities to hold multiple configuration of the system as well as some sort of mechanism to allow the user to choose one of these configurations at boot time, when needed.
BootMenu is a simple text-based (suitable for Linux console) boot manager
providing menu-based user interface that reads a configuration file containing
various boot settings, and presents them to the user as a menu.
The user can then choose the boot settings that he/she prefers
(using UP/DOWN keys), and then boot them (by pressing ENTER),
or edit the entire configuration file (by pressing TAB or E). In addition,
the user can drop to PID 1 shell, reboot, shutdown, or exec
various keys and/or as setup in configuration file.
BootMenu is implemented as a shell script, and it requires busybox
(the usual applets such as mount, umount, awk, sed, ash, vi, etc), kexec-tools,
and evtest (for input). It is designed for inclusion in initramfs, and to be
executed as the PID 1
init by adding kernel command line
(assuming you put BootMenu in
BootMenu starts up by looking for its configuration file,
It does this by scanning the root directory of all block devices that it can
find and mount (some block devices are excluded, see the script itself for
details). The first one will be used and the search stops; this config file
is then copied to a temporary location.
bootmenu=dev can be passed on the kernel command line to
force BootMenu to only look at specifid device for its configuration file
bootmenu=mmcblk0p1). If no configuration file is found, BootMenu
will attempt to execute
/init (this is what the kernel would do if
rdinit parameter was not used) to start the system directly. Failure
to do exec
/init will result in kernel panic.
In addition, BootMenu also honours
waitdev parameter (which is used
by FatdogArm and Fatdog64 to delay boot process so that slow
devices have time to initialisation process and make themselves known to
Once the configuration is loaded, BootMenu will enter an event loop to
allow the user to choose the configurations and perhaps edit the configuration
vi. Configuration file that gets edited is the temporary copy
of the configuration file, never the original, thus changes are not
permanent. If you want to make permanent changes you will have to edit the
file yourself when the operating system is already up (or do it on another
If a configuration is chosen, BootMenu will attempt to load the kernel
(and initrd/initramfs, if any) and launch if if the kernel is found. Otherwise
it will return an error and stays in the event loop. It will stay on event
loop until a valid kernel can be loaded, or until the user chooses one of the
shutdown / exit-to-shell / run
BootMenu configuration file
BootMenu menu configuration file is a simple text file, to be located at the root directory of a filesystem that can be found by BootMenu. The format is similar to syslinux/Grub but not identical.
The configuration file consist of two parts:
- global settings
- boot stanza
All configuration items must start at the beginning of line (no spaces or tabs allowed), otherwise they are ignored. Blank lines are ignored, and a line preceded by a hash (#) symbol is a comment and will be ignored too.
A configuration file must contain at least one boot stanza, otherwise the file is considered invalid.
Global settings are settings that will affect BootMenu as a whole. Currently there are two settings:
Followed by a number, this sets the boot stanza entry that will be booted off by default, if the user doesn't choose anything (autoboot). The entry numbering starts from 1 (one). If this is not specified BootMenu will boot the first entry (ie., it is the same as setting
Followed a number, this sets the number of seconds before BootMenu will automatically boot the default entry. If not specified, the delay is 10 (ten) seconds. You can disable autoboot entirely by specifying 0 (zero) as the delay value.
Boot stanza are settings that define a particular boot configuration.
You can have multiple stanzas in the configuration file, each stanza defines
a particular boot settings (combination of kernel, initrd, kernel parameters,
etc). Each stanza is delimited by its
title line; a new
a new stanza and closes the preceding one.
A boot stanza can contain the following keywords:
titlecan be followed by a short string; this string will be displayed in the menu. It also marks the beginning of a new stanza.
rootis followed by a Linux block device name (without
mmcblk0p1, which specifies the block device that holds the kernel.
kernelis followed by a path (within the
rootblock device) to the new kernel that is to be loaded . E.g.
initrdis followed by a path (within the
rootblock device) to the initrd/initramfs to be loaded. Initrd is optional; if it is not given no initrd will be used.
appendis followed by kernel command line parameters to pass to the new kernel. Append is optional, if it is not given then nothing will be passed to the kernel (and therefore the kernel must be compiled with the right boot parameters, otherwise it won't work).
dtbis followed by a path (within the
rootblock device) to the compiled device tree blobs to load and passed to the new kernel. Dtb is optional, if not given BootMenu assumes that the kernel will boot using --atags instead.
commentis followed by a string which will be displayed at the bottom of the menu screen. You can put longer string here (the menu system reserves two lines to display the comment) but all of them must be on one line. If not given, the comment line will be left blank.
initwill launch /init, thus booting the system as if bootmenu is never used (just like pressing 'I' key). If this entry is used, then
kernelis not needed.
rebootwill reboot the system (just like pressing 'R' key). If this entry is used, then
kernelis not needed.
poweroffwill power-off (shutdown) the system (just like pressing 'P' key). If this entry is used, then
kernelis not needed.
shellwill end bootmenu and run a PID 1 shell instead (just like pressing Esc key). If this entry is used, then
kernelis not needed.
You can get BootMenu from here. You can get a sample configuration file from here.
- BootMenu uses the Linux kernel itself as the bootloader.
For this to work, the kernel that runs BootMenu (ie, the first kernel
that boots up) needs to compiled with support for
kexec system call.
The other kernels that would be loaded by BootMenu does not need
- BootMenu operates by hot-loading a new kernel on top of the existing
(the currently-running) one. This assumes that all the devices can be
re-initialised by the new kernel. This is not generally true, and on
some platforms devices can only be initialised once and then locked out
until subsequent hardware reset.
BootMenu will not work on these platforms simply because the new
kernel will not know what to do with these locked-out devices.
- BootMenu doesn't currently recognise touch gestures. To use BootMenu
in a tablet platform, the platform must provide some sort of hardware
buttons (and the BootMenu script needs to be modified to recognise
- Other menu-based Boot Managers using kexec system call
When the idea first came to me, I did a google search in case there was something that I can re-use. And indeed, there are existing implementations:
But none of those meet my needs. Petitboot is client-server design and needs a server to work, so that is immediately out. Kexecboot is pretty, with icons and configurable menus too, but it is missing a few functions and have others that I don't need. I can't recall why I didn't go with kexec-loader.
Thus BootMenu was born. BootMenu is a simpler implementation of the same idea in shell script, using only busybox, kexec-tools, and evtest (for input), and should be very easy to adapt for other platforms (e.g. tablets, which has different key mapping from standard PC keyboards, etc).