Browse Source

lcd: implement a callback for splashimage

On some architectures certain values of splashimage will lead to
a data abort exception.

Document the problem, and implement a callback for splashimage to
reject such values.

Cc: Anatolij Gustschin <agust@denx.de>
Cc: Wolfgang Denk <wd@denx.de>
Signed-off-by: Nikita Kiryanov <nikita@compulab.co.il>
Acked-by: Igor Grinberg <grinberg@compulab.co.il>
Nikita Kiryanov 11 years ago
parent
commit
c088048533
4 changed files with 71 additions and 0 deletions
  1. 11 0
      README
  2. 26 0
      common/lcd.c
  3. 27 0
      doc/README.displaying-bmps
  4. 7 0
      include/env_callback.h

+ 11 - 0
README

@@ -1530,6 +1530,17 @@ CBFS (Coreboot Filesystem) support
 		allows for a "silent" boot where a splash screen is
 		loaded very quickly after power-on.
 
+		CONFIG_SPLASHIMAGE_GUARD
+
+		If this option is set, then U-Boot will prevent the environment
+		variable "splashimage" from being set to a problematic address
+		(see README.displaying-bmps and README.arm-unaligned-accesses).
+		This option is useful for targets where, due to alignment
+		restrictions, an improperly aligned BMP image will cause a data
+		abort. If you think you will not have problems with unaligned
+		accesses (for example because your toolchain prevents them)
+		there is no need to set this option.
+
 		CONFIG_SPLASH_SCREEN_ALIGN
 
 		If this option is set the splash image can be freely positioned

+ 26 - 0
common/lcd.c

@@ -33,6 +33,8 @@
 #include <common.h>
 #include <command.h>
 #include <stdarg.h>
+#include <search.h>
+#include <env_callback.h>
 #include <linux/types.h>
 #include <stdio_dev.h>
 #if defined(CONFIG_POST)
@@ -1099,6 +1101,30 @@ static void *lcd_logo(void)
 #endif /* CONFIG_LCD_LOGO && !CONFIG_LCD_INFO_BELOW_LOGO */
 }
 
+#ifdef CONFIG_SPLASHIMAGE_GUARD
+static int on_splashimage(const char *name, const char *value, enum env_op op,
+	int flags)
+{
+	ulong addr;
+	int aligned;
+
+	if (op == env_op_delete)
+		return 0;
+
+	addr = simple_strtoul(value, NULL, 16);
+	/* See README.displaying-bmps */
+	aligned = (addr % 4 == 2);
+	if (!aligned) {
+		printf("Invalid splashimage value. Value must be 16 bit aligned, but not 32 bit aligned\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+U_BOOT_ENV_CALLBACK(splashimage, on_splashimage);
+#endif
+
 void lcd_position_cursor(unsigned col, unsigned row)
 {
 	console_col = min(col, CONSOLE_COLS - 1);

+ 27 - 0
doc/README.displaying-bmps

@@ -0,0 +1,27 @@
+If you are experiencing hangups/data-aborts when trying to display a BMP image,
+the following might be relevant to your situation...
+
+Some architectures cannot handle unaligned memory accesses, and an attempt to
+perform one will lead to a data abort. On such architectures it is necessary to
+make sure all data is properly aligned, and in many situations simply choosing
+a 32 bit aligned address is enough to ensure proper alignment. This is not
+always the case when dealing with data that has an internal layout such as a
+BMP image:
+
+BMP images have a header that starts with 2 byte-size fields followed by mostly
+32 bit fields. The packed struct that represents this header can be seen below:
+
+typedef struct bmp_header {
+	/* Header */
+	char signature[2];
+	__u32	file_size;
+	__u32	reserved;
+	__u32	data_offset;
+	... etc
+} __attribute__ ((packed)) bmp_header_t;
+
+When placed in an aligned address such as 0x80a00000, char signature offsets
+the __u32 fields into unaligned addresses (in our example 0x80a00002,
+0x80a00006, and so on...). When these fields are accessed by U-Boot, a 32 bit
+access is generated at a non-32-bit-aligned address, causing a data abort.
+The proper alignment for BMP images is therefore: 32-bit-aligned-address + 2.

+ 7 - 0
include/env_callback.h

@@ -41,6 +41,12 @@
 #define SILENT_CALLBACK
 #endif
 
+#ifdef CONFIG_SPLASHIMAGE_GUARD
+#define SPLASHIMAGE_CALLBACK "splashimage:splashimage,"
+#else
+#define SPLASHIMAGE_CALLBACK
+#endif
+
 /*
  * This list of callback bindings is static, but may be overridden by defining
  * a new association in the ".callbacks" environment variable.
@@ -51,6 +57,7 @@
 	"bootfile:bootfile," \
 	"loadaddr:loadaddr," \
 	SILENT_CALLBACK \
+	SPLASHIMAGE_CALLBACK \
 	"stdin:console,stdout:console,stderr:console," \
 	CONFIG_ENV_CALLBACK_LIST_STATIC