1.18. Booting Linux¶
1.18.1. Introduction¶
The lowlevel boot command in barebox is bootm - boot an application image. This command can be used directly, but there is also a boot - boot from script, device, … command which offers additional features like a boot sequence which tries to boot different entries until one succeeds.
1.18.2. The bootm command¶
The bootm - boot an application image command is the lowlevel boot command. Depending on the architecture the bootm command handles different image types. On ARM the following images are supported:
ARM Linux zImage
ARM64 Linux Image, plain or compressed
U-Boot uImage
barebox images
FIT images, containing a zImage or Image
The images can either be passed directly to the bootm command as argument or
in the global.bootm.image
variable:
bootm /path/to/zImage
# same as:
global.bootm.image=/path/to/zImage
bootm
When barebox has an internal devicetree it is passed to the kernel. You can
specify an alternative devicetree with the -o DTS
option or the global.bootm.oftree
variable:
bootm -o /path/to/dtb /path/to/zImage
# same as:
global.bootm.oftree=/path/to/dtb
global.bootm.image=/path/to/zImage
bootm
FIT image configurations will be matched by comparing the compatible
property
inside the configuration node with the barebox live tree’s /compatible
.
It’s also possible to select a specific configuration explicitly:
global.bootm.image=/dev/mmc0.fit@conf-imx8mm-evk.dtb
NOTE: it may happen that barebox is probed from the devicetree, but you have
want to start a Kernel without passing a devicetree. In this case set the
global.bootm.boot_atag
variable to true
.
1.18.2.1. Passing Kernel Arguments¶
The simple method to pass bootargs to the kernel is with
CONFIG_FLEXIBLE_BOOTARGS
disabled: in this case the bootm command
takes the bootargs from the bootargs
environment variable.
With CONFIG_FLEXIBLE_BOOTARGS
enabled, the bootargs are composed
from different global device variables. All variables beginning
with global.linux.bootargs.
will be concatenated to the bootargs:
global linux.bootargs.base="console=ttyO0,115200"
global linux.bootargs.debug="earlyprintk ignore_loglevel"
bootm zImage
...
Kernel command line: console=ttymxc0,115200n8 earlyprintk ignore_loglevel
Additionally all variables starting with global.linux.mtdparts.
are concatenated
to a mtdparts=
parameter to the kernel. This makes it possible to consistently
partition devices with the addpart - add a partition description to a device command and pass the same string as used
with addpart to the Kernel:
norparts="512k(bootloader),512k(env),4M(kernel),-(root)"
nandparts="1M(bootloader),1M(env),4M(kernel),-(root)"
global linux.mtdparts.nor0="physmap-flash.0:$norparts"
global linux.mtdparts.nand0="mxc_nand:$nandparts"
addpart /dev/nor0 $norparts
addpart /dev/nand0 $nandparts
...
bootm zImage
...
Kernel command line: mtdparts=physmap-flash.0:512k(bootloader),512k(env),4M(kernel),-(root);
mxc_nand:1M(bootloader),1M(env),4M(kernel),-(root)
1.18.2.2. Creating root= options for the Kernel¶
It’s a common case that the Linux Kernel is loaded from a filesystem
that later becomes the root filesystem for the Kernel. For several
filesystems barebox can automatically append a suitable root= option
to the Kernel command line. This is done when global.bootm.appendroot
is true. How the root= option is appended depends on the device type
and filesystem the kernel is booted from. For disk like devices (SD/MMC,
ATA) the partition UUID will be used, the root= option will be something
like root=PARTUUID=deadbeef-1
. For UBIFS fileystems it will be
root=ubi0:volname ubi.mtd=mtdpartname rootfstype=ubifs
. NFS
filesystems will result in root=/dev/nfs nfsroot=ip:/path/to/nfsroot,v3,tcp
.
The v3,tcp
part is configurable in global.linux.rootnfsopts
.
1.18.3. The boot command¶
The boot - boot from script, device, … command offers additional convenience for the bootm - boot an application image
command. It works with Boot entries and Boot Loader Specification entries. Boot entries
are located under /env/boot/ and are scripts which setup the bootm variables so that the
boot
command can run bootm
without further arguments.
1.18.3.1. Boot entries¶
A simple boot entry in /env/boot/mmc
could look like this:
#!/bin/sh
global.bootm.image=/mnt/mmc1/zImage
global.bootm.oftree=/env/oftree
global linux.bootargs.dyn.root="root=PARTUUID=deadbeef:01"
This takes the kernel from /mnt/mmc1/zImage
(which could be an
Automount path registered earlier). The devicetree will be used from
/env/oftree
. The Kernel gets the command line
root=PARTUUID=deadbeef:01
. Note the .dyn
in the bootargs variable name.
boot entries should always add Kernel command line parameters to variables with
.dyn
in it. These will be cleared before booting different boot entries.
This is done so that following boot entries do not leak command line
parameters from the previous boot entries.
This entry can be booted with boot mmc
. It can also be made the default by
setting the global.boot.default
variable to mmc
and then calling
boot
without arguments.
1.18.3.2. Boot Loader Specification¶
barebox supports booting according to the Boot Loader Specification (sometimes also known as Bootloader Spec, bootspec or blspec).
It follows another philosophy than the Boot entries. With Boot Entries booting is completely configured in the bootloader. Bootloader Spec Entries on the other hand are part of the boot medium. This gives a boot medium the possibility to describe where a kernel is located and which parameters are needed to boot it.
All Bootloader Spec Entries are located in a partition on the boot medium under
/loader/entries/*.conf
. According to the Bootloader Spec, a boot medium has
to use a dedicated partition for boot entries. barebox is less strict, it
accepts Bootloader Spec Entries on every partition that barebox can read.
A Bootloader Spec Entry consists of key value pairs:
/loader/entries/6a9857a393724b7a981ebb5b8495b9ea-3.8.0-2.fc19.x86_64.conf:
title Fedora 19 (Rawhide)
version 3.8.0-2.fc19.x86_64
machine-id 6a9857a393724b7a981ebb5b8495b9ea
options root=UUID=6d3376e4-fc93-4509-95ec-a21d68011da2
linux /6a9857a393724b7a981ebb5b8495b9ea/3.8.0-2.fc19.x86_64/linux
initrd /6a9857a393724b7a981ebb5b8495b9ea/3.8.0-2.fc19.x86_64/initrd
All paths are absolute paths in the partition. Bootloader Spec Entries can
be created manually, but there also is the scripts/kernel-install
tool to
create/list/modify entries directly on a MMC/SD card or other media. To use
it, create an SD card / USB memory stick with a /boot
partition with type 0xea
.
The partition can be formatted with FAT or EXT4 filesystem. If you wish to write
to it from barebox later you must use FAT. The following creates a Bootloader
Spec Entry on a SD card:
scripts/kernel-install --device=/dev/mmcblk0 -a \
--machine-id=11ab7c89d02c4f66a4e2474ea25b2b84 --kernel-version="3.15" \
--kernel=/home/sha/linux/arch/arm/boot/zImage --add-root-option \
--root=/dev/mmcblk0p1 -o "console=ttymxc0,115200"
The entry can be listed with the -l
option:
scripts/kernel-install --device=/dev/mmcblk0 -l
Entry 0:
title: Linux-3.15
version: 3.15
machine_id: 11ab7c89d02c4f66a4e2474ea25b2b84
options: console=ttymxc0,115200 root=PARTUUID=0007CB20-01
linux: 11ab7c89d02c4f66a4e2474ea25b2b84.15/linux
When the SD card shows up as mmc1
in barebox, this entry can be booted with
boot mmc1
or by setting global.boot.default
to mmc1
.
A bootloader spec entry can also reside on an NFS server, in which case an RFC 2224-compatible NFS URI must be passed to the boot command:
boot nfs://nfshost[:port]//path/
Additional notes about keys in the bootloader spec entries:
machine-id
This key is optional. If the
global.boot.machine_id
variable is set to a non-empty value, barebox will only boot the Bootloader Spec Entry whosemachine-id
key matches theglobal.boot.machine_id
variable. All other Bootloader Spec entries will be ignored.linux-appendroot
This boolean option is understood by Barebox although it is not part of the original specification. If set to
true
, barebox will automatically append aroot=
string to the Linux commandline based on the device where the entry is found on. This makes it possible to use the same rootfs image on different devices without having to specify a differentroot=
option each time.
1.18.4. Network boot¶
With the following steps, barebox can start the kernel and root filesystem over the network, a standard development case.
See Networking for informations how to configure your network interfaces.
Note that barebox will pass the same IP settings to the kernel, i.e. it passes
ip=$ipaddr:$serverip:$gateway:$netmask::<linuxdevname>:
for a static IP setup
and ip=dhcp
for a dynamic DHCP setup. <linuxdevname>
is a configurable value.
set nv.dev.<ethdev>.linuxdevname
to the name the device has in Linux.
By default, barebox uses the variables global.user
and global.hostname
to retrieve its kernel image over TFTP, which makes it possible to use multiple
boards for multiple users with one single server.
You can adjust those variables using nvvars with these commands:
nv user=sha
nv hostname=efikasb
Copy the kernel (and devicetree if needed) to the root directory of your TFTP server, and name them accordingly; for example:
cp zImage /tftpboot/sha-linux-efikasb
cp myboard.dtb /tftpboot/sha-oftree-efikasb
(In this example, the directory /tftpboot
represents the root directory of
the TFTP server.
That directory depends on the configuration of your TFTP server, some servers
may also use /srv/tftp
instead.)
barebox will pass nfsroot=/home/${global.user}/nfsroot/${global.hostname}
to
the kernel.
This causes the kernel to mount its root filesystem from a NFS server, which is
detected through the DHCP reply.
To choose a different server, simply prepend its IP address to the mount path,
e.g. nfsroot=192.168.23.5:/home/...
.
In any case, make sure that the specified mountpoint is exported by your NFS
server.
For more information about booting with nfsroot
, see
Documentation/admin-guide/nfs/nfsroot.rst
in the Linux kernel documentation.
If the preconfigured paths or names are not suitable, they can be adjusted in
/env/boot/net
:
#!/bin/sh
path="/mnt/tftp"
global.bootm.image="${path}/${global.user}-linux-${global.hostname}"
oftree="${path}/${global.user}-oftree-${global.hostname}"
if [ -f "${oftree}" ]; then
global.bootm.oftree="$oftree"
fi
nfsroot="/home/${global.user}/nfsroot/${global.hostname}"
ip_route_get -b ${global.net.server} global.linux.bootargs.dyn.ip
global.linux.bootargs.dyn.root="root=/dev/nfs nfsroot=$nfsroot,v3,tcp"
boot net
will then retrieve the kernel (and also the device tree and
initramfs, if used) over TFTP and boot it.