The Linux kernel command-line
Published on July 23, 2012
The Linux kernel has a lot of features that can be controlled at boot time through a feature known as the "Kernel command line". When combined with a U-Boot variable named bootargs, this feature allows you to tell the kernel how to configure various device drivers, where to find the root filesystem and can even be used to pass information to applications on the system.
The next time you boot Linux, I encourage you to pay attention to the start of the kernel's output to the serial port:
Uncompressing Linux... done, booting the kernel.
Initializing cgroup subsys cpuset
Initializing cgroup subsys cpu
Linux version 3.0.15-ga753097 (gcc version 4.4.3 (GCC) )...
CPU: ARMv7 Processor [412fc09a] revision 10 (ARMv7), cr=10c53c7d
CPU: VIPT nonaliasing data cache, VIPT aliasing instruction cache
Machine: Freescale i.MX 6Quad Sabre-Lite Board
Memory policy: ECC disabled, Data cache writealloc
PERCPU: Embedded 7 pages/cpu @c10fa000 s5760 r8192 d14720 u32768
Built 1 zonelists in Zone order, mobility grouping on. Total pages: 198656
Kernel command line: console=ttymxc1,115200 init=/init rw no_console_suspend
androidboot.console=ttymxc1 vmalloc=400M video=mxcfb0:dev=hdmi,1280x720M@60,if=RGB24
video=mxcfb1:dev=lcd,CLAA-WVGA,if=RGB666 fbmem=28M,10M,10M calibration tsdev=tsc2004
video=mxcfb2:dev=ldb,LDB-XGA,if=RGB666
The last four lines above show a rather complicated set of flags and variable assignments used in a boot of Android on the Nitrogen6X board. I'll walk through a number of them below, but first I'd like to talk about how and where these variables are set and handed off to the kernel.
The short answer to that question is U-Boot, but the more precise answer is that the U-Boot boot loader passes the kernel command-line transparently to the Linux kernel using a feature known as atags from a U-Boot variable named bootargs. In general, you won't need to know about atags, but if you mess around at all with U-Boot, you're likely to know a lot about bootargs.
Structure and construction
In lots of previous posts, we've described the anatomy and particulars of boot scripts. One of the primary purposes of those scripts is to construct a proper set of bootargs for the user-space being booted.If you run print at a U-Boot prompt, you're likely to see something like this that defines a default set of bootargs.
U-Boot > print
bootdelay=3
...
bootargs=console=ttymxc1,115200 video=mxcfb0:dev=hdmi,1280x720M@60,if=RGB24
This example just shows a set of default values in bootargs. This is typical of a configuration set by Boundary Devices.
You might also see something like this, which is more typical of Freescale:U-Boot > print
bootargs_base=setenv bootargs console=ttymxc1,115200
...
bootargs_nfs=setenv bootargs ${bootargs} root=/dev/nfs ip=dhcp
nfsroot=${serverip}:${nfsroot},v3,tcp
video=mxcfb0:dev=ldb,LDB-XGA,if=RGB666
enable_wait_mode=off
bootcmd_net=dhcp; run bootargs_base bootargs_nfs;bootm
The notable difference between the two is that the value of the bootargs_base and bootargs_nfs variables are actually a set of commands that set and append to the variable bootargs respectively.Likewise, the bootcmd_net variable contains commands which will run the other two. In typical usage, bootcmd_net will be invoked by the first level bootcmd variable like so:
U-Boot > print
...
bootcmd=run bootcmd_net
Our practices
That's a lot of running, and the primary reason we tend to avoid this is that it's not clear what you're saving. In other words, this mixes code and data, which can cause things to break.Our desire to separate things also stems from our practice of booting to SPI-NOR and not the same device that contains our root filesystem. Most Freescale devices are configured to use a single media (usually SD card) for both.
Since we have separate storage for them, we try and place variables which define the board, such as display configuration or mac addresses into persistent environment variables and leave variables that are tied to the user-space in a boot script which follows the boot media.
Common variables
The following is a table of commonly used bootargs components. Note that these change with kernel releases and updates to the userspace, so we suggest that you ask us or your user-space provider for specifics during each release.Name | Typical values | Description |
---|---|---|
video= | mxcfb0:dev=hdmi,1280x720M@60,if=RGB24 | Used to specify the display resolution on i.MX6. |
root= | /dev/mmcblk0p1 | Used to specify the root filesystem. This is required unless a RAM disk is specified in the U-Boot bootm command. |
rootwait | N/A | This flag should always be present if a root= clause is specified. It tells the kernel to wait for the device to appear before trying to mount it. |
console= | ttymxc1,115200 | Used to specify the Linux kernel console device (to which kernel messages are routed). |
init= | /init | After mounting the root filesystem, the Linux kernel runs a single program to start the system. This is typically either /init or /linuxrc. You can override the default behavior if your userspace requires it by using the init= parameter. Note that this is rarely needed. |