Search by Tags

U-Boot

 
Compare with Revision

Subscribe for this article updates

Introduction

U-Boot is an open-source bootloader commonly used in embedded devices. It has its origins in a very simple bootloader designed for the PowerPC architecture which was publicly released in 2000 under the name of PPCBoot. Shortly thereafter it was renamed to U-Boot (short for Das Universal Boot) to reflect its evolution into a multiarchitectural bootloader. Today, U-Boot is a fully-fledged bootloader supporting more than a dozen architectures, several filesystems and a handful of interfaces. It features a console interface through the serial port with low level commands and environment variables that provide high flexibility when configuring the boot process. The most remarkable achievement, however, is its good driver assortment, which has established it as the preferred bootloader for most embedded platforms. Toradex also uses U-Boot as the bootloader for its images. You can find the code in our repositories.

This article explains how to manage the console and the environment variables in a running U-Boot so that you are able to troubleshoot, modify or set up your own booting configuration. To learn how to build your own U-Boot version, please refer to Build U-Boot and Linux Kernel from Source Code.

Requirements

In order to access the U-Boot console you obviously need a running U-Boot in your module. A running U-Boot is automatically available if you have:

The U-Boot Console

When U-Boot is running in RAM, it sends its output through the primary Full Function (FF) UART (usually UART_A). The Colibri and Apalis evaluation boards route this UART through a USB to Serial converter to a USB B connector or through a TTL to RS232 converter to a DB9 connector (see Colibri Evaluation Board, Apalis Evaluation Board). The Iris Board routes this UART through a TTL to RS232 converter to a header (see Serial Adapter Cable on Iris). While U-Boot's console output is also visible on the parallel RGB display (and with the carrier boards RAMDAC on VGA) a USB keyboard directly connected to the module does not work as of yet.

In order to visualize the serial output from a host machine, a serial port reader program such as minicom or PuTTy is commonly set to read the corresponding USB serial port (e.g. in Linux /dev/ttyUSB*). For detailed information on how to set up and configure the serial port on your host machine see our Getting Started guides.

Once you can read the output from your host machine, the U-Boot Console can be easily accessed by pressing any button before the autoboot sequence starts. By default U-Boot waits up to 3 seconds before starting the autoboot sequence. The following is an extract of what the console shows when U-Boot is initialized and autoboot is prevented by entering into the console.

U-Boot 2016.11-2.8.4+g07edca0bb8 (Oct 05 2018 - 16:21:45 +0000)

CPU:   Freescale i.MX6DL rev1.3 at 792 MHz
Reset cause: POR
I2C:   ready
DRAM:  512 MiB
...
Model: Toradex Colibri iMX6 DualLite 512MB V1.1A, Serial# 05130147
Net:   using PHY at 0
FEC [PRIME]
Hit any key to stop autoboot:  3
Colibri iMX6 # 

Environment Variables

Environment variables are key-value pairs of strings that are used by U-Boot as configuration or to execute commands. To list all currently set variables, issue the command printenv in the U-Boot console.

Colibri iMX6 # printenv
arch=arm
baudrate=115200
board=colibri_imx6
...
boot_targets=mmc1 mmc0 usb0 dhcp 
bootcmd=run emmcboot; echo; echo emmcboot failed; run distro_bootcmd; usb start; setenv stdout serial,vga; setenv stdin serial,usbkbd
bootcmd_dhcp=if dhcp ${scriptaddr} ${boot_script_dhcp}; then source ${scriptaddr}; fi;
...
ver=U-Boot 2016.11-2.8.4+g07edca0bb8 (Oct 05 2018 - 16:21:45 +0000)
vidargs=video=mxcfb0:dev=lcd,640x480M@60,if=RGB666 video=mxcfb1:off fbmem=8M
x-test=atest

As you can observe, some variables such as arch or vidargs contain information needed for configuration. Others such as bootcmd also contain commands (run, echo, etc) that can be run. To print the value of a single variable, use printenv <variable>.

Creating and Modifying Variables

Creating a new variable or changing an existing one is done using the setenv command.

Colibri iMX6 # setenv myvar myvalue
Colibri iMX6 # printenv myvar
myvar=myvalue

You can expand the value of a variable inside the definition of another variable by prepending $ to it.

Colibri iMX6 # setenv myvar2 $myvar
Colibri iMX6 # printenv myvar2
myvar2=myvalue

You must enclose the value of the variable with ' ' if you don't want to expand other variables or if multiple statements are given.

Colibri iMX6 # setenv defargs 'video=tegrafb vmalloc=248M usb_high_speed=1'

Saving the Environment

Using setenv to create or modify varibles will only add or change their values in RAM. If you want to make changes permanent they need to be stored in flash with the saveenv command:

Colibri iMX6 # saveenv   
Saving Environment to MMC...
Writing to MMC(0)... done

If you now reboot your system, the variables myvar and myvar2 will be defined in U-Boot.

Resetting the Environment to the Defaults

If you want to discard any changes you made to the environment with saveenv, you can always return to the default values with env default -a.

Colibri iMX6 # env default -a
## Resetting to default environment
Colibri iMX6 # saveenv        
Saving Environment to MMC...
Writing to MMC(0)... done

Executing the commands in a variable

Variables may contain commands that are executable by U-Boot such as echo, ls or reset. To list the available commands type help in the console. To execute a variable containing commands, use run <variable>.

Colibri iMX6 # setenv myvar 'setenv myvar2 myvalue2'
Colibri iMX6 # printenv myvar2
## Error: "myvar2" not defined
Colibri iMX6 # run myvar
Colibri iMX6 # printenv myvar2
myvar2=myvalue2

The best example of variable execution happens on autoboot. Autoboot basically executes the boot command, which essentially calls run bootcmd. bootcmd is a variable that contains other commands and other variables that contain further commands in a way that resembles the execution of a shell script.