Displaying a Splash Screen with U-Boot
Published on May 30, 2013
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
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.
=> 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.