U-Boot on i.MX6

There are a lot of posts in this blog that describe the state of U-Boot for our i.MX6 boards, but most of them describe the history. They were designed to help the early adopters make transitions as we switched from the Freescale U-Boot 2009.08 to main-line and added display support.

Things have stabilized, and in this post, we’ll recap the current state of affairs to provide the new user a quick Getting started guide.

Here are some things you should know about the U-Boot that we ship with our i.MX6 boards:

Our boards boot to a serial EEPROM. The i.MX6 processor has a set of internal fuses that control the boot device, and we program these for SPI-NOR. There are a variety of ways to over-ride this, but we don’t recommend them except for very specific needs.

The primary U-Boot console is the serial port on a DB-9 labelled console. It’s configured for direct connection to common USB serial adapters (i.e. as DCE). The baud rate is 115200. 8 data bits, no parity, no flow control. If you hit the any key right after power-on, you’ll abort the automatic boot process and get a U-Boot prompt on the serial port.

U-Boot images have support for USB keyboard. See this post for details. If you boot without a working 6x_bootscript on SD card or SATA, you’ll get a prompt on the display and USB keyboard in addition to the serial port.

Our images will boot from either SD card slot or SATA. The default bootcmd string is set to iterate through all of the boot media on your board, looking for the file 6x_bootscript in partition 1. If found, the script will be run (and won’t return if successful). Note that some userspaces may require the use of a certain boot media. Consult the corresponding documentation for details.

U-Boot images include the USB Mass Storage Gadget. This allows the board to present a block device (such as an SD card) to the host as a mass storage device via the USB OTG port.

If you power-on a device with one of our displays connected, you should get an on-screen image. Display support has been in U-Boot for a while now, and you should see a display without any SD card present.

Our default bootcmd is set to run 6x_bootscript. To elaborate, we leave the precise boot instructions to the userspace image itself, since different distributions package things differently and require at least different kernel command-lines. We accomplish this by having a bootcmd which simply loads a distribution-specific startup script (6x_bootscript) from the first partition of either SD card or SATA drive.

Linux kernel 3.10.31 introduces incompatible naming of SD card devices. As detailed in this post, the root= clause in the kernel command line may need to be altered to accommodate these changes. The new sdphys variable in our boot scripts can be used to select the old or new numbering scheme.

We provide sample boot scripts for Android and typical non-Android use. You can find these in the directory corresponding to your board in files named 6x_bootscript*. These are just samples though. You will likely need to tailor them for your use in production, because

The default boot scripts try to detect your display. There are some notes in this post but from a high-level, suffice it to say that these boot scripts try to provide an easy out-of-the-box experience.

Boot scripts are compiled text files consisting of a series of U-Boot commands. The language supports the use of conditionals, so you can test for the presence of files, environment variables, and the like.

Don’t assume that you need to re-compile and re-install U-Boot to match your userspace. We routinely boot Linaro, Buildroot, LTIB, Ubuntu, Debian, Timesys, Android, QNX, and Windows Embedded Compact 7 operating systems without re-programming U-Boot. You should only need to re-install U-boot to take advantage of a new feature or to fix a bug. The U in U-Boot stands for Universal and it comes pretty darn close. Many userspace builders will build a U-Boot image for you, but that’s primarily because other platforms are configured for boot to raw SD card and require it. Our boards don’t.

Use the 6x_upgrade script and the upgradeu environment variable if you do need an upgrade. You can copy 6x_upgrade and u-boot.imx to an SD card, and upgrade like this:

U-Boot packages – The example of upgradeu above works when you’re compiling U-Boot yourself, as it makes reference to u-boot.imx. If you’re using our production binary package, you’ll either need to re-name one of the files in the package to u-boot.imx or over-ride the boot file like so:

Refer to this post for information about the various files and the naming conventions.

If you’re booting to SD card or SATA, you shouldn’t need to set any environment variables before booting. Our sample boot scripts configure most things automatically, and you should generally do the same. If you need to customize the boot environment (usually the bootargs variable), you’ll generally want to hack the boot script instead. This is easier to copy to other machines, and fits nicely into a source repository.

If you’re booting over NFS during development, you should hack your environment variables. See the notes below for typical usage.

Restore your factory defaults with clearenv.

U-Boot > run clearenv

Or better yet, use env default -f -a. We only learned of this nice feature recently, and will likely discard clearenv in the future.

U-Boot > env default -f -a

Our U-Boot source code is on Github. We aim to have all of the code for our standard products in main-line U-Boot, but generally have at least a few patches in flight.

Our production branch contains the version that we’re currently shipping for new orders and is typically the most stable and recommended branch.

Our staging branch contains the version that we’re prepping for the next release. It may have some bugs, but also may have some new features of interest.

Boot flow

The process of booting an i.MX6 involves multiple steps:

At power-on or reset, the processor starts executing code from on-chip ROM. This code reads the Boot Mode switches, and if they’re in the normal position (Boot from fuses), goes on to read the fuses to find out which media to search for a bootable image. In our case, it will see that we have the fuses programmed for serial EEPROM, and should find a U-Boot image at offset 0x400 in that device.

The code in on-chip ROM will read the U-Boot preamble, configuring registers for DDR, then copy U-Boot into DDR and begin U-Boot execution.

U-Boot will wait for bootdelay seconds for a user to abort the boot with a keystroke on the console (the serial port).

If no keystroke is present, U-Boot will execute a set of commands stored in the environment variable bootcmd.

As mentioned above, our default bootcmd is configured to iterate through all bootable media (SATA and both SD cards), looking for 6x_bootscript. If found, the commands inside are executed.
In the normal case, these commands will never return because an O/S will be launched.

Unbricking

If step 1 above sees the Boot mode pins in the Serial Boot position, or doesn’t find a valid image in the serial EEPROM, the code in the on-chip ROM will enter serial download mode.

This mode allows a user to download a valid boot image over the USB OTG port, providing a robust means of recovery.

If you connect the USB OTG port to a Linux-based machine (including i.MX6 devices), you can see this in the output of lsusb:

We selected nitrogen6q_config, which is the standard configuration for our most popular boards, the Nitrogen6X and SABRE Lite. If you’re compiling for another board or have a non-standard memory configuration, please refer to the table in this post.

A number of custom boards aren’t suitable for up-streaming though, and we do generally have additions in our repository that either aren’t worth the noise of pushing up-stream (notably boot script updates) or have not yet made their way through the approval process into the main-line U-Boot code base.

We try to update our repository with the latest from up-stream as quickly as possible after each release cycle, so you’ll have access to all of the efforts by others in the community. This process largely entails moving or re-basing our branch onto the latest version from Denx, but we do usually take steps to reduce the patch set (and clean things up) during those efforts, so we lose a little of the history.

Because many of our customers (especially customers using Nitrogen6X-SOM) create their own branches based on our versions, we’ll keep each of of our branches indefinitely,
but they might be re-named. Please shoot us an e-mail if you do this.

Our production branch will move with each official release from us. If you’re trying to decide what branch to build, this is always the one you want. It should represent the most stable, most full-featured code base at any time. As a consequence, the branch name is also unstable. In other words, it will move over time as we jump from one version of U-Boot to the next.

To provide more stable branch names, we’ll also create branches named vYYYY.MM-yyyymmdd each time we complete a re-base. The YYYY.MM will represent the U-Boot version number and yyyymmdd will represent the date on which we re-based. If you need a stable branch name, as the Yocto Project does, you’ll want to use these instead of production. Additional patches may be added to a vYYYY.MM-yyyymmdd branch, but the history won’t be lost.

Basics of launching Linux

In order to boot Linux using U-Boot, you usually need only two things:

A working kernel, and

A filesystem containing init

But you’ll generally need a third:

A set of kernel parameters passed via the bootargs environment variable in U-Boot.

The kernel image is typically stored in a file named uImage and is most commonly stored in the /boot directory of a filesystem, but these are guidelines, not rules. The only important thing is that U-Boot is able to load the kernel into RAM.

The filesystem used at startup (generally referred to as the root filesystem) could be a typical ext2, ext3, ext4 filesystem on SD card or SATA, an accessible NFS share, or a RAM disk image. The only important piece is that you can tell the kernel how to find it at startup time.

Kernel startup is almost always invoked using the bootm command under U-Boot. The first parameter to bootm is the address of a kernel as shown in this example:

This simple example shows how to load /boot/uImage into memory address 0x10800000 and launch it.

But wait. We haven’t provided a filesystem reference in this example.

When you invoke bootm using a single parameter, you’ll need to specify the root filesystem indirectly through the bootargs environment variable as shown below.
This example tells the kernel to wait for the root filesystem to become available, and that the root filesystem is the partition /dev/mmcblk0p1 (the first partition of the first SD card enumerated on the system).

This is precisely what’s done in the default boot script board/boundary/nitrogen6x/6x_bootscript.txt.

To boot a RAM disk for the root filesystem, you add a second parameter to the bootm command with the load address of the RAM disk and omit the root= clause from bootargs. The following example illustrates this:

RAM disks are used in the default Android boot script (board/boundary/nitrogen6x/6x_bootscript_android.txt), but are also useful for other distributions. We used one to put together this image for exposing storage across USB.

Note that there is a third parameter for bootm that’s required for use of the main-line Linux kernel. It supplies something called a device tree, which is used to make the kernel a bit more generic. If you’re working with main-line, it’s likely that you have access to this, so we won’t go into the details here.

How to boot over NFS

Booting over NFS is a straightforward extension of this that simply replaces the root= clause in bootargs with root=/dev/nfs. It does require a couple of additional parameters to the kernel, though:

parameter

typical value

nfsroot

hostip:/path/to/rootfs,options

ip

dhcp

The first parameter, nfsroot= tells the kernel where to find a root filesystem and what options to pass to the NFS mount process. A typical value for the entire clause might benfsroot=192.168.0.42:/home/user/imx-android,v3,tcp.

The second parameter, ip= is needed because the kernel needs to have an IP address in order to access the network. An IP address is normally done as a part of the userspace startup, but in the case of an NFS root, we can’t wait for that because of the chicken-and-egg problem.

Note that this example doesn’t completely boot over the network, though. The kernel is still loaded from an ext2/3/4 filesystem on partition 1 of the SD card. This brings up the next question:

Loading a file over TFTP

U-Boot contains a number of networking commands, and support for a number of protocols.

The most common are the dhcp and tftp commands, and we generally use the dhcp command to acquire an IP address and transfer a file in a single command like so:

U-Boot > dhcp 10800000 192.168.0.62:uImage

This command will acquire an IP address using DHCP, then request a file named uImage and load it into memory address 0x10800000.

When used in conjunction with the NFS boot arguments, this provides a single, relatively command line to be used for booting:

U-Boot > dhcp 10800000 192.168.0.62:uImage && bootm 10800000

You may now be understanding why I mentioned the saving of environment variables when booting NFS. There are a number of parameters to provide, including

the IP address of the TFTP server, and

the IP address and path to the NFS filesystem

If you’re going to save all of these, you might as well just over-write the bootargs variable entirely, and the bootcmd variable while you’re at it.

You can always run clearenv when you’re done.

Important clauses for bootargs:

To recap and expand on the notes above, here are a set of known variables that you might want to set in bootargs under U-Boot:

name

typical value

Notes

console

ttymxc1,115200

This tells the kernel to send kernel messages to /dev/ttymxc1, the serial console port. You almost always want this set during development, though you might consider turning it off in production, since it can slow the boot process.

enable_wait_mode

false

This variable controls the behavior of the idle loop in the Linux kernel and you may see system stalls without this value set.

root=

/dev/mmcblk0p1

/dev/sda1

See notes above

video=

mxcfb0:dev=hdmi,1280x720M@60,if=RGB24

mxcfb0:dev=ldb,LDB-XGA,if=RGB666

mxcfb0:dev=ldb,1024x600M@60,if=RGB666

mxcfb0:dev=lcd,CLAA-WVGA,if=RGB666

Defines the display(s). These should be numbered starting at mxcfb0 through mxcfb2 and will translate into a number of device nodes as described in this post.

consoleblank

0

This variable controls the amount of idle time before the console device goes to sleep. Use consoleblank=0 to disable blanking on idle.

vmalloc

400M

This controls the amount of memory available to the kernel for dynamic allocation. You’ll normally want this to be 400M or so on a system running a graphical U/I with accelerated video and graphics.

Booting Yocto

Thanks largely to the efforts of the team at O.S. Systems, the current builds of Yocto using the meta-fsl repositories have a custom boot script that specifies partition 2 for the root filesystem instead of partition 1.

Their efforts show the right thing to do: have the boot script built as a part of the userspace, but not U-Boot itself.

Booting Windows Embedded Compact 7

Coming soon

Booting QNX

Details coming soon, but the general process involves the use of the gocommand:

Did you change the bootscript filename in recent U-Boot ? (/6q_bootscript vs /6x_bootscript)
Do I have to update U-Boot if I want to use Yocto on the Sabrelite.
The current U-Boot on my board is “U-Boot 2009.08 (Aug 16 2012 – 10:06:42)”

I downloaded the file “u-boot-2013-6-19.tar.gz”.
Which file is the U-Boot for the Sabrelite. Do I have to rename one of the file to “u-boot.imx” and copy it to the SD card ?

Yes we changed the boot script from 6q_bootscript to 6x_bootscript when we switched to main-line U-Boot. See this post for background about why (essentially incompatibilities in some commands).

No, it wasn’t recent (November of 2012).

No, it’s technically not necessary to switch U-Boot versions to run any O/S unless you’re using the main-line kernel, which needs device-tree support. That said, you should upgrade because we’ve fixed some critical bugs, and we recommend switching to the main-line based U-Boot (2013.x) if you want to run any of our images or things like Yocto, because we’re really only providing boot scripts for that platform.

Is it possible to use the unused memory of the spi-nor on the sabrelite as scratchpad memory? Would you be able to provide a memory map of this device including the unused portion? I’d like to experiment with freescale’s kernel level spi driver for reading and writing to this scratchpad memory. Thanks!

I have followed “How to Build” section above, but when I “make all” , it pop up error messages as below listings. Can you comment this problem for me? Note: the ARCH=arm and CROSS_COMPILE=arm-none-linux-gnueabi- have been exported.

My linux machine (ubuntu and LTIB) was working every demo on Nitrogen6x board, e.g. build u-boot-2009-8 and rebuilding Boundary’s kernel/modules. Everything was good. Since I tried to build Yocto image for Qt. I found something broken that I could not go back to re-build any demo on LTIB. I tried to build u-boot.imx, it pop up the error “/bin/bash: arm-linux-gcc: command not found”.

I tried to re-bould u-boot-2009.8 and got the same error. Eventhough I cannot build kernel and modules now. I hope someone may help me to figure out what was happened in my senario.

I need to modify the pin definitions in the file, nitrogen6x.c under u-boot-imx6, to meet our application. But it failed to compile. e.g.
Original is from:
MX6_PAD_EIM_D16__ECSPI1_SCLK | MUX_PAD_CTRL(SPI_PAD_CTRL),
Need to be changed to:
MX6_PAD_CSIO_DAT4__ECSPI1_SCLK | MUX_PAD_CTRL(SPI_PAD_CTRL),

I tried to locate the header file like, nitrogen6x.h. But I could not find it. I wonder if you know where or which file has the definitions of those pins?

Hi all,
I am having sabrelite board.I have upgraded uboot on it to support android jelly bean.
I am having questions regarding fastboot. when i connect board to linux pc using usb & run fastboot command. It only shows .
As i am new to android I am having some simple questions like

How can i solve this?
Is it necessary to have fastboot compatible bootloader on board?
Is host(pc) need to have specific driver for each board?

hi all ,
when i start my kit it starts ok and runs the u-boot after that i made debugging on it with test example that run on ram at add 0x900000 and it’s debug ok .
when i reset the kit it doesn’t boot and when i make debugging with another example it return cable not found or

I’m having a problem compiling U-Boot for a Nitorgen6x board. I downloaded the code with the following command:

git clone git://git.denx.de/u-boot-imx.git

Then I tried to compile with the following two commands:

make nitrogen6q_config
make

On a Red Hat machine I get File format not recognized errors. If I enter make I get beyond the error and on to another. The last error I get is “strip:proftool: File format not recognized”. I cannot get past this error. On an Ubuntu machine the linker gets undefined references for all the function calls to functions defined in common/iomux.c, then the linker gets a segmentation fault. The cause of the former is that arch/arm/imx-common.c, rather than common/iomux.c, is included and that doesn’t have the missing needed functions defined.

Ahah!… I’ve seen this before with the Timesys package. They seem to put the cross-compiler version ahead of the native version. If you swap around your path on the Red-Hat machine, such that /usr/bin comes before /opt/armv71-timeys…, you should be able to build successfully.

I’m stumped by why your Ubuntu machine isn’t working. Can you run strip tools/proftool by hand?

Voilà, I was able to compile on the Red Hat machine. Thanks. As to the Ubuntu machine, I should be compiling on the Red Hat machine. I only switched to the Ubuntu machine when I couldn’t compile on the Red Hat machine. So now I’m back on the Red Hat machine, and I won’t worry about compiling on the Ubuntu machine. Now I have one more question. Since I’m fairly new with U-Boot, how exactly do I get the code from your git repository?

Unfortunately, I know exactly what the problem is (since we’ve hit this before). The 6x_upgrade script originally only erased 0x50000 bytes, and U-Boot grew bigger than that. Note that the offset above is 0x50000-0x400 bytes into the image.

Please use the boot script that’s part of the latest production package:

I think you may be looking in the wrong place. The bug (and patches) mentioned don’t appear to have any effect, since a value of 2 in CCGR3 bits 0 and 1 appears to have the same function as 01 and 03. You can test this by hand using the mm command to access the register:

U-Boot > mm 0x020C4074
020c4074: 3ff0300e ? 0x3ff0300d

I just ran the command above with a 10.1″ LVDS panel and things worked with either setting.

I’ve given up trying to get the LVDS display to work in U-Boot for now and have moved on to Linux. But now, U-Boot has stopped booting Linux. I get the message, “6x_bootscript not found”, but when I do an ls mmc 0, it’s there.

I’m having an issue loading a u-boot binary that I compiled onto my 6x (I want to have a 2G version of production). I keep getting a “Read verification error”. Trying out the binary – gives, no surprise, a bricked board. The issue though seems to be with the ‘upgradeu’ command not writing to the flash correctly. I’m not sure how to debug this…. Here’s the output I get:

Sorry I should have read all the comments better – this was already answered… I used the 6x_upgrade from production and it worked. I suspected that not enough flash was being erased. I got my version 6x_upgrade from the Ubuntu 4.0.0 build – the tar.gz file linked to on this page: http://boundarydevices.com/freescale-ubuntu-image-with-4-0-0-kernel/. Updating this build with the production 6x_upgrade would be good.

I just tried to upgrade my u-boot to the production version ‘u-boot-production.tar.gz’…

My board is a ‘saber lite’ quad core, so the most appropriate image seemed to be ‘u-boot.mx6qsabrelite’. I followed the instructions, which seemed to work successfully. But on rebooting, I didn’t see all the usual default environment settings, such as the upgradeu command… even after resetting to defaults. So I am not bricked, but I don’t seem to have the standard environment for booting these boards.

I also just noticed a comment above stating:
The file u-boot.nitrogen6q is the U-Boot for stock (1GB) SABRE Lite and Nitrogen6X boards.

Did I use the wrong image? If so, what is the u-boot.mx6qsabrelite for? I assume I now need to do something like:
mmc dev 1
fatload mmc 1:1 10008000 /6q_upgrade && source 10008000
to install a different u-boot. Is that right? I can see the files with ‘fatls mmc 1:1′ so at least I seem to be reading the micro sd card ok.

I assume I can use the files from ‘6xupgrade’ from ‘6x_downgrade-20121109.zip’ to return to the original u-boot (6q_) image my board shipped with. But the 6q_script that came with ‘6q_upgrade-20121109.zip’ wont be usable from where I am.

Which script should I use to go from a 6x_.. u-boot to another 6x_… u-boot? the one which came with the 6x_downgrade, or the one that came with the production set? The former is 2012 bytes, and the latter is 1401, so there seems to be a significant difference.

Its a great little board, and the support is excellent judging by how quickly you responded. But I am still finding all the image choices quite confusing.

Closest I have been to a stable system so far was the oneiric-imx6-20120626.gz image which I started with because I could use it without tackling a u-boot upgrade. I was stable, but I never got the display to work, and I read that the can bus I was having trouble with wouldnt work till I upgraded.

I next tried oneiric-imx6-20130307.tar.gz after getting up the courage to run 6q_upgrade-20121109.zip,
but I kept getting kernel panics whenever I did anything which caused a lot of writes to the micro sd. I read something about some timing fixes is the latest u-boot, and the description of being ‘production’ made it sound worth another go at bootloader upgrade. The only other idea I had of why the newer image wasn’t stable for me was that the SD card I am using has some compatability issue. It is slower than the one with my older system on it (only class 4), but it seems to work ok on the host system that wrote the image.

I was thinking of trying one of the newer images, but they look a lot smaller, and I am behind a firewall which doesn’t let me use apt, so I have been having to manually locate and download .deb files and any related dependencies, which is tedious.

Anyway, if you have any suggestions of what might be going wrong, or the best image to start with, please let me know. I’ll do some testing to see if the u-boot upgrade makes any difference (although I think it is a long shot).

Thanks for the feedback. As I think you’ve figured out, we struggle with the question of userspaces (images).

Every one of the projects behind a userspace is much bigger than our primary role of kernel and boot loader (the hardware-specific bits).

For desktop-oriented systems (i.e. native build environments), we recommend either the Linaro Ubuntu or Debian images as a starting point. The Freescale Oneiric images are quite old by now, and won’t get proper package updates.

Some users have also reported good results with ArchLinuxArm, but we don’t have any experience in that area.

The release u-boot did seem to make a difference! It took a number of attempts to get it to boot (kept getting stuck at ‘Freeing init memory: 200K’, but once it did boot, it has been stable and I havn’t seen any of the kernel crashes I was getting before. The display even came up!!

I purchased a sabre-lite board. Boots ok. On the hdmi — there is the timesys demo.
On the serial console I can see quite a bit.
I need to disable the demo and make the hdmi/usb kbd the console.
How do I do this?

Hey, I was wondering if you would be able to tell me how I would find out if I need to upgrade u-boot. I am currently using a utilite pro with: (see below) I do not want Ubuntu on the SSD I would rather have Kali or Debian Linux. But, I recently have had some issues with nand and booting. Went in and fixed the env to be able to boot to sdcard. Before I get an OS installed I would like to make sure that I have the latest boot files needed to utilize the most from the imx6 and board. All help welcome. =)

I’m a fresh to the linux,and now I have a sabrelite board.I want to install ubuntu into the SD card on it,but I am not sure which are the correct steps to follow. firstly,I build the u-boot and get the u-boot.imx,and then I just adjust the “two DIP switches ” on at the Sabre Lite to “10 – Internal”,and I can see
~/$ lsusb
Bus 001 Device 009: ID 15a2:0054 Freescale Semiconductor, Inc. i.MX6Q SystemOnChip in RecoveryMode
like this,but if I adjustthe “two DIP switches ” to “01 – USB” ,I can see nothing ,is that the correct status?

is that mean I have load the uboot to sabrelite?(I haven’t put an SD card to sabrelite),and the I run the minicom,but can not see U-Boot launch from minicom like below:
hb@hb-virtual-machine:~/imx_usb_loader$ sudo minicom

Welcome to minicom 2.5

OPTIONS: I18n
Compiled on May 2 2011, 00:39:27.
Port /dev/tty8

Press CTRL-A Z for help on special keys

I have no idea about the problems,please give me a favor,and what should I do next in order to load ubuntu on sabrelite.

1. I’m using Sabre Lite rev-2 board. I cross compiled the U-boot production branch for nitrogen6q and got .bin and .imx files. Failed to load the file through Mfg tool. But able to load the .bin file which is in MFG\Profiles\MX6Q Linux Update\OS Firmware u-boot-mx6q-sabrelite.bin. Below is the error I’m getting in Mfg tool log file,

Both the files are not working. After loading the .imx file, PC was not able find the board under HID device. Now I’m trying to earse the NOR Flash through SPI.
Why the same files are not working while loading through U-boot?
If it is working, then I’ll try to load the cross compiled U-boot production branch.

3. After loading the U-boot 2009.08 through Mfg tool, I placed the .imx / .bin file & 6x_upgrade script in SD card and tried to upgrade using “run upgradeu” comment. Board was not able to read the SD card which is in FAT file system, getting error as “not able to find ext2″. Is there any option to read the FAT file system for upgradation.