Passing command line arguments to the Linux kernel allows for very
flexible and efficient configuration which is especially important in
Embedded Systems. It is somewhat strange that these features are
nearly undocumented everywhere else. One reason for that is
certainly the very limited capabilities of other boot loaders.
It is especially U-Boot's capability to easily define, store, and
use environment variables that makes it such a powerful tool in this
area. In the examples above we have already seen how we can use for
instance the
root
and
ip
boot
arguments to pass information about the root filesystem or network
configuration. The
ip
argument is not only useful
in configurations with root filesystem over NFS; if the Linux kernel
has the
CONFIG_IP_PNP
configuration enabled (IP
kernel level autoconfiguration), this can be used to enable automatic
configuration of IP addresses of devices and of the routing table
during kernel boot, based on either information supplied on the
kernel command line or by
BOOTP or RARP protocols.
The advantage of this mechanism is that you don't have to spend
precious system memory (RAM and flash) for network configuration
tools like
ifconfig
or
route
-
especially in Embedded Systems where you seldom have to change the
network configuration while the system is running.
We can use U-Boot environment variables to store all necessary
configuration parameters:
=> setenv ipaddr 192.168.100.6
=> setenv serverip 192.168.1.1
=> setenv netmask 255.255.0.0
=> setenv hostname canyonlands
=> setenv rootpath /opt/eldk-4.2/ppc_4xx
=> saveenv
Then you can use these variables to build the boot arguments to be
passed to the Linux kernel:
=> setenv nfsargs 'root=/dev/nfs rw nfsroot=${serverip}:${rootpath}'
Note how apostrophes are used to delay the substitution of the
referenced environment variables. This way, the current values of
these variables get inserted
when assigning values to the
"bootargs"
variable itself later,
i. e. when it gets assembled from the given parts
before passing it to the kernel.
This allows us to simply
redefine any of the variables (say, the value of
"ipaddr"
if it has to be
changed), and the changes will automatically propagate to the Linux
kernel.
Note: You cannot use this method
directly to define for example the
"bootargs"
environment variable, as the implicit usage of this variable by
the
"bootm"
command will
not trigger variable expansion - this happens
only when using the
"setenv"
command.
In the next step, this can be used for a flexible method to define
the
"bootargs"
environment variable by using a
function-like approach to build the boot arguments step by step:
=> setenv ramargs setenv bootargs root=/dev/ram rw
=> setenv nfsargs 'setenv bootargs root=/dev/nfs rw nfsroot=${serverip}:${rootpath}'
=> setenv addip 'setenv bootargs ${bootargs} ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}::off'
=> setenv ram_root 'run ramargs addip;bootm ${kernel_addr} ${ramdisk_addr} ${fdt_addr}'
=> setenv nfs_root 'run nfsargs addip;bootm ${kernel_addr} - ${fdt_addr}'
In this setup we define two variables,
ram_root
and
nfs_root
, to boot with root filesystem from a
ramdisk image or over NFS, respecively. The variables can be executed
using U-Boot's
run
command. These variables make use of the
run
command itself:
- First, either
run ramargs
or run nfsargs
is used to
initialize the bootargs
environment variable as needed to boot
with ramdisk image or with root over NFS.
- Then, in both cases,
run addip
is used to append the ip
parameter to use the Linux kernel IP autoconfiguration mechanism
for configuration of the network settings.
- Finally, the
bootm
command is used with three resp. two address arguments
%ENDIF0% to boot the Linux kernel image with resp. without a
ramdisk image. (We assume here that the variables kernel_addr
, ramdisk_addr
and fdt_addr
%ENDIF0% have already been set.)
This method can be easily extended to add more customization options
when needed.
If you have used U-Boot's network commands before (and/or read the
documentation), you will probably have recognized that the names of
the U-Boot environment variables we used in the examples above are
exactly the same as those used with the U-Boot commands to boot over a
network using
DHCP or
BOOTP. That means that, instead of manually setting
network configuration parameters like IP address, etc., these variables
will be set automatically to the values retrieved with the network
boot protocols. This is explained in detail in the sections about the
respective U-Boot commands.