There are many guides on the internet for creating a custom splash screen on Linux, but most for Raspbian are based on SysV init, and don't interface well with systemd, which is now used by Raspbian. Those that do support systemd make use of Plymouth, which I had extreme difficult installing. Thus I have written up this guide on directly porting the simple init-style splash screens to systemd, for a quick and easy solution to splash screens on the Raspberry Pi.
Thanks to Mike Kazantsev at fraggod.net, whose work this guide heavily draws upon.
Totally worth it.
Clean up the boot process
Firstly, we want to remove as much of the text as possible from the boot-up process, to allow for a clean transition.
Disable the Raspberry Pi ‘color test’ by adding the line
disable_splash=1 to /boot/config.txt.
Disable the Raspberry Pi logo in the corner of the screen by adding
logo.nologo to /boot/cmdline.txt.
Disable the various bits of output from the kernel and friends by adding
consoleblank=0 loglevel=1 quiet to /boot/cmdline.txt.
Disable the login prompt by running
systemctl disable getty@tty1 as root.
Set up the splash screen
Design your splash screen image and place it somewhere easily readable.
Install fbi, the framebuffer image viewer, by running
apt install fbi as root.
Create the file /etc/systemd/system/splashscreen.service with the following content:
[Unit] Description=Splash screen DefaultDependencies=no After=local-fs.target [Service] ExecStart=/usr/bin/fbi -d /dev/fb0 --noverbose -a /opt/splash.png StandardInput=tty StandardOutput=tty [Install] WantedBy=sysinit.target
/opt/splash.png with the path to the splash screen image as appropriate.
-d /dev/fb0 option will tell fbi which framebuffer to display the image on.
--noverbose will suppress the fbi ‘status bar’ at the bottom of the screen.
-a will allow fbi to automatically select the correct zoom level for the image. If your image is already at the correct resolution for the display, you may omit this option.
fbi expects access to a tty, so the
StandardOutput options will allow for this. You may also be able to omit these options and instead pass the
-T flag to fbi, specifying the number of the tty you wish to use.
DefaultDependencies option will override systemd's default behaviour of launching the service late in the boot process (as most ordinary services require access to resources), and the
WantedBy option will cause fbi to be loaded early in the boot process, though not before the file system (and hence image) are ready, through the
Enable the service to be run at boot by running
systemctl enable splashscreen as root.
You may now be able to test the splashscreen by running
systemctl start splashscreen as root, or simply reboot the Pi.
Remove black borders
You may run in to the issue where there appears to be a black border drawn around the splash screen. This is in fact a hardware-level black border around the entire framebuffer, and can be disabled by adding
disable_overscan=1 to /boot/config.txt.
Animated splash screens
In my case, the above process worked fine, but because I had set the system up to automatically boot into Kodi, and Kodi turns the screen black for a brief period before redisplaying the splash screen itself, this created a jarring effect. My solution was to replace the first splash screen with a simple loading screen on a black background, to create a smoother, more genuine feel to the transition. But where's the fun in a static loading screen? Why not a loading spinner!
fbi doesn't support animations, so we will make use of the specialised, highly underrated tool bannerd, which is unfortunately not available in repositories and so must be compiled from source. Thankfully, this appears to be quite straightforward:
git clone https://github.com/alukichev/bannerd.git cd bannerd make
Then copy the newly created bannerd binary to an easily readable location, say /usr/local/bin/bannerd, and ensure it is executable.
Now, we need to get the splash animation into a sequence of BMP files. For example:
ffmpeg -i original_animation.gif %04d.bmp
My particular GIF, though, had an alpha channel, and was designed to be overlaid on a black background, whereas ffmpeg assumed a white background when converting to BMP, so the process was slightly more convoluted:
ffmpeg -i original_animation.gif %04d.png # Preserve alpha channel mogrify -background black -flatten -format bmp *.png
Copy the BMP files to an easily accessible location, preferably in their own folder for convenience.
Now, the systemd service from earlier can be easily adapted by changing the ExecStart line:
ExecStart=/bin/sh -c '/usr/local/bin/bannerd -vD /path/to/frames/*.bmp'
The invocation of sh is necessary to expand the glob.
As before, you can test the splash screen by running
systemctl start splashscreen or rebooting.