diff --git a/bootloader/bootloader-display.c b/bootloader/bootloader-display.c
index 2c1e34fd81319f7761eb577d12a0afff7962b0cb..1fe0cae0ffee19dcf226db64248af754e3c87ac7 100644
--- a/bootloader/bootloader-display.c
+++ b/bootloader/bootloader-display.c
@@ -1,14 +1,42 @@
 #include "bootloader.h"
+/* Autogenerated */
+#include "splash-screen.h"
 
 #include "GUI_Paint.h"
 #include "display.h"
 
+/*
+ * "Decompress" splash-screen image.  The algorithm works as follows:
+ *
+ * Each byte encodes up to 127 pixels in either white or black.  The most
+ * significant bit determines the color, the remaining 7 bits determine the
+ * amount.
+ */
+static void bootloader_display_splash(void)
+{
+	int idx = 0;
+
+	for (int i = 0; i < sizeof(splash); i++) {
+		uint16_t color = (splash[i] & 0x80) ? 0xffff : 0x0000;
+		uint8_t length = splash[i] & 0x7f;
+
+		for (int j = 0; j < length; j++) {
+			uint16_t x = idx % 160;
+			uint16_t y = idx / 160;
+			Paint_SetPixel(x, y, color);
+			idx++;
+		}
+	}
+
+	LCD_Update();
+}
+
 /*
  * Initialize the display.
  */
 void bootloader_display_init(void)
 {
-	;
+	bootloader_display_splash();
 }
 
 /*
diff --git a/bootloader/main.c b/bootloader/main.c
index 1a5f08e0da2fc7a2b3867c8c0fec072ba2a67e50..d3577542ede90d0840f6606be5df36764903c333 100644
--- a/bootloader/main.c
+++ b/bootloader/main.c
@@ -205,10 +205,11 @@ int main(void)
 	 */
 	pmic_set_button_callback(pmic_button);
 
-	bootloader_display_header();
+	bootloader_display_init();
 
 	// If the button is pressed, we go into MSC mode.
 	if (PB_Get(3)) {
+		bootloader_display_header();
 		bootloader_display_line(2, "USB activated.", 0xffff);
 		bootloader_display_line(3, "Ready.", 0xffff);
 		run_usbmsc();
@@ -224,36 +225,42 @@ int main(void)
 		int res = check_integrity();
 		if (res == -ENOENT) {
 			printf("card10.bin not found!\n");
-			bootloader_display_line(
-				2, "card10.bin not found", 0xffff
-			);
 		} else if (res == -EINVAL) {
 			printf("card10.bin CRC is invalid!\n");
+			bootloader_display_header();
 			bootloader_display_line(
 				2, "Integrity check failed", 0xffff
 			);
+
+			bootloader_display_line(4, "Trying to boot", 0xffff);
 		} else if (res == 0) {
 			printf("Found valid application image\n");
 			if (is_update_needed()) {
 				printf("Trying to update firmware from external flash\n");
+				bootloader_display_header();
 				bootloader_display_line(
-					4, "Updating ...", 0xffff
+					3, "Updating ...", 0xffff
 				);
 				erase_partition();
 				flash_partition();
+				bootloader_display_line(
+					4, "Trying to boot", 0xffff
+				);
 			} else {
 				printf("No update needed\n");
 			}
 		}
 	} else {
+		bootloader_display_header();
 		bootloader_display_line(
 			2, "Failed to mount filesystem", 0xffff
 		);
 		printf("Failed to mount the external flash\n");
+
+		bootloader_display_line(4, "Trying to boot", 0xffff);
 	}
 
 	printf("Trying to boot\n");
-	bootloader_display_line(4, "Trying to boot", 0xffff);
 
 	boot((uintptr_t *)PARTITION_START);
 
diff --git a/bootloader/meson.build b/bootloader/meson.build
index 9a863cdfa8de1bb99c79bad8f783b4cd29a9e239..23c387943125a45c20b40b685edb22fc5f2936dc 100644
--- a/bootloader/meson.build
+++ b/bootloader/meson.build
@@ -1,5 +1,18 @@
 name = 'bootloader'
 
+splash_screen = custom_target(
+  'splash-screen.h',
+  output: 'splash-screen.h',
+  input: 'splash-screen.png',
+  command: [
+    python3,
+    meson.current_source_dir() + '../tools/bootloader-image.py',
+    '-n', 'splash',
+    '@INPUT@',
+    '@OUTPUT@',
+  ],
+)
+
 executable(
   name + '.elf',
   'main.c',
@@ -7,6 +20,7 @@ executable(
   'bootloader-display.c',
   'bootloader-usb.c',
   'crc16-ccitt.c',
+  splash_screen,
   dependencies: [
     libcard10,
     max32665_startup_boot,
diff --git a/bootloader/splash-screen.png b/bootloader/splash-screen.png
new file mode 100644
index 0000000000000000000000000000000000000000..02a632049624f5b96e54ac2d4c7d408fd41ae796
Binary files /dev/null and b/bootloader/splash-screen.png differ
diff --git a/tools/bootloader-image.py b/tools/bootloader-image.py
new file mode 100755
index 0000000000000000000000000000000000000000..f2ce2bf8b974578217b3f6d4ebc9a3bb080fed3a
--- /dev/null
+++ b/tools/bootloader-image.py
@@ -0,0 +1,83 @@
+#!/usr/bin/env python3
+import argparse
+import os
+from PIL import Image
+
+
+def main() -> None:
+    parser = argparse.ArgumentParser(
+        description="""\
+\"Compress\" an image for the boot-splash.
+The boot-splash is a two-color image."""
+    )
+
+    parser.add_argument("image", help="Boot-splash image")
+    parser.add_argument("-n", "--name", help="Name of the data-block")
+    parser.add_argument("output", help="Output file name")
+
+    args = parser.parse_args()
+
+    im = Image.open(args.image)
+
+    assert im.size[0] == 160, "Image must be 160 pixels wide"
+    assert im.size[1] == 80, "Image must be 80 pixels high)"
+
+    if args.name is not None:
+        name = args.name
+    else:
+        name = os.path.splitext(os.path.basename(args.image))[0].replace("-", "_")
+
+    with open(args.output, "w") as f:
+        tmp = """\
+#include <stdint.h>
+
+/*
+ * This is the splash-screen image, compressed using a very primitive algorithm:
+ *
+ * Each byte encodes up to 127 pixels in either white or black.  The most
+ * significant bit determines the color, the remaining 7 bits determine the
+ * amount.
+ */
+const uint8_t {name}[] = {{
+"""
+        f.write(tmp.format(name=name))
+
+        total = 0
+        start = 0
+        previous_white = False
+        for i in range(160 * 80):
+            x = i % 160
+            y = i // 160
+            white = im.getpixel((x, y))[0] > 0
+
+            if white != previous_white or i - start == 127:
+                length = i - start
+                assert length < 128, "Internal error"
+                value = (length & 0x7F) | (0x80 if previous_white else 0x00)
+
+                tmp = """\
+    /* {length} pixels in {color} */
+    0x{value:x},
+"""
+                f.write(
+                    tmp.format(
+                        length=length,
+                        color="white" if previous_white else "black",
+                        value=value,
+                    )
+                )
+
+                previous_white = white
+                start = i
+                total += length
+
+        tmp = """\
+}};
+"""
+        f.write(tmp.format())
+
+        assert total < (160 * 80), "Internal error"
+
+
+if __name__ == "__main__":
+    main()