Displaying a Splash Screen with U-Boot

Published on May 30, 2013

Archived Notice

This article has been archived and may contain broken links, photos and out-of-date information. If you have any questions, please Contact Us.

2014-02-22: N.B. Some of this post has flaws

At least with a GCC 4.7 cross compiler and the latest U-Boot sources, it is necessary to align bitmaps on a memory address with an offset of an odd multiple of +2, since the use of a four-byte alignment will cause alignment exceptions at run-time.
  • If you're using an un-compressed bitmap, you should use an address like 0x10000002, and
  • If you're using a gzipped image, you'll also need a patch like this one
Refer to these documents for details:

Original post

We've recently had several customers contact us asking about using splash screens with U-Boot. We added display support to U-Boot a while back as described here and with it we got a nice Tux logo and the version information but didn't have a way to customize it. Now we do and we'll explain how it works in this post.

For the impatient

The process to set it up is the following for boards with SPI-nor flash: U-Boot > ext2load mmc 1 10000000 /water-conservation1024x600.bmp.gz 745898 bytes read in 219 ms (3.2 MiB/s) U-Boot > sf probe SF: Detected SST25VF016B with page size 4 KiB, total 2 MiB U-Boot > sf erase c2000 +${filesize} U-Boot > sf write 10000000 c2000 ${filesize} U-Boot > setenv splashimage 12000000 U-Boot > setenv splashpos m,m U-Boot > setenv splashsize ${filesize} U-Boot > saveenv
  • The image is copied into SPI flash so it is tied to the board and won't change with different boot devices.
  • For splashimage, pick somewhere in the valid range.
  • The variable splashpos is optional and setting it to m,m will center the image.
  • SPI NOR flash is 2 MiB so your max image size is 1302528 bytes, 2 MiB - c2000 bytes.
  • It can handle most bmp formats as well as gzipped versions as show above.
  The process to set up from eMMC/sd card follows: => setenv splashimage ${loadaddr} => setenv loadsplash load mmc 2 ${splashimage} iguana.bmp3.gz => run loadsplash 666379 bytes read in 15 ms (42.4 MiB/s) => setenv splashsize $filesize => setenv splashpos m,m => savee Saving Environment to MMC... Writing to MMC(2)... OK => The file iguana.bmp3.gz can be created from a jpeg by OS2:~$ convert iguana.jpg -colors 256 -depth 8 -compress none iguana.bmp3 OS2:~$ gzip iguana.bmp3 OS2:~$

Background

U-Boot provides the bmp command for working with bitmaps. You can load an image from an SD card and display them like this: U-Boot > ls mmc 1 <DIR> 4096 . <DIR> 4096 .. <DIR> 16384 lost+found ... 1152138 water2.bmp 1843338 water1.bmp 1152138 water-conservation800x480.bmp 1843338 water-conservation1024x600.bmp 1843338 splash.bmp 134538 boundarydevicesx240.bmp 745898 water-conservation1024x600.bmp.gz U-Boot > ext2load mmc 1 10000000 /water-conservation1024x600.bmp.gz 745898 bytes read in 219 ms (3.2 MiB/s) U-Boot > bmp i 10000000 Image size : 1024 x 600 Bits per pixel: 24 Compression : 0 U-Boot > bmp d 10000000 With this capability we could do something like adding the following line to the top of 6x_bootscript (or to the bootcmd environment variable), will cause u-boot to look for a bitmap image named splash.bmp in the root directory of the filesystem from whatever you're booting from. ${fs}load ${dtype} ${disk}:1 10000002 /splash.bmp && bmp d 10000002 ; See this post for more details about the bootscript and bootcmd There are 2 major downsides with this method. One, if there's no boot media attached to the board you get Tux. Two, it's slow and fleeting. You still see Tux and the version info for a second or 2 because it only runs once the bootcmd has been called after the 1 second boot delay and if you continue to boot into Linux or something else which has it's own splash screen or simply clears the screen, you'll only see your image for a second anyway.

SPI NOR and splashimage

We want displaying the splash screen to work regardless of whether there's an SD card or anything else plugged in to boot from and we want it displayed immediately on boot up (without seeing Tux or U-Boot output). The first part can be solved using flash. Our boards have 2 MiB of non-volatile SPI NOR flash, part of which we use to store U-Boot and the environment variables. We can store an image here with U-Boot's sf commands. Assuming you've just loaded an image to RAM at address 10000000 (see above), the process looks like this: U-Boot > sf probe SF: Detected SST25VF016B with page size 4 KiB, total 2 MiB U-Boot > sf erase c2000 +${filesize} U-Boot > sf write 10000000 c2000 ${filesize} U-Boot > sf read 12000000 c2000 ${filesize} U-Boot > bmp d 12000000 The filesize environment variable is automatically set to the size of the file just loaded (in hex which is what we need). Why did we write to SPI location c2000 besides that's where loadsplash expects it? The SPI NOR memory map looks like this: 0..bffff - U-Boot 0xc0000..0xc1fff - environment The free space in flash is from c2000 to the end, so that's where we put the image. The second part, displaying immediately at bootup, is covered by taking advantage of the CONFIG_SPLASH_SCREEN option in U-Boot. When U-Boot is compiled with this enabled, immediately on startup it will look for an environment variable named splashimage and read an address out of it. It'll then try to load and display a bmp image from that location in RAM. Sounds easy enough, but now we have another problem. U-Boot's splash screen feature is expecting the image in RAM and our image is stored in NOR flash. To solve this we've committed some code changes to the staging branch. This key change is an added default environment variable loadsplash: loadsplash=if sf probe ; then sf read ${splashimage} c2000 ${splashsize} ; fi Obviously, when run it will copy an image from c2000 in flash to the location in splashimage, the place where U-Boot will look for it. You can try running it manually using the run command: U-Boot > run loadsplash SF: Detected SST25VF016B with page size 4 KiB, total 2 MiB U-Boot > bmp d ${splashimage} So, at startup, if splashimage and splashsize and loadsplash exist, U-Boot will try to run loadsplash. Splashimage, is as we mentioned the address that U-Boot will look for the splash screen bmp so we load it there and splashsize is the size in hex of the image you copied to SPI NOR. You'll have to set those 2 variables using setenv: U-Boot > setenv splashimage 12000000 U-Boot > setenv splashpos m,m U-Boot > setenv splashsize ${filesize} U-Boot > saveenv After setting these variables appropriately, you're done. Reset and you should see your image displayed instantly.

Conclusion

I admit that it does seem like quite a process going on behind the scenes for something as simple as displaying a splash image but we've aimed for it to be as easy to use (or ignore) as possible from the your perspective