Commit f7ef9d610cb28d31c106792f18b58424e39275c7
Committed by
Anatolij Gustschin
1 parent
5af7d0f090
Exists in
master
and in
53 other branches
lcd: align bmp header when uncopmressing image
When compressed image is loaded, it must be decompressed to an aligned address + 2 to avoid unaligned access exception on some ARM platforms. Signed-off-by: Piotr Wilczek <p.wilczek@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> CC: Anatolij Gustschin <agust@denx.de> CC: Wolfgang Denk <wd@denx.de> Signed-off-by: Anatolij Gustschin <agust@denx.de>
Showing 2 changed files with 30 additions and 15 deletions Side-by-side Diff
common/cmd_bmp.c
... | ... | @@ -38,14 +38,19 @@ |
38 | 38 | /* |
39 | 39 | * Allocate and decompress a BMP image using gunzip(). |
40 | 40 | * |
41 | - * Returns a pointer to the decompressed image data. Must be freed by | |
42 | - * the caller after use. | |
41 | + * Returns a pointer to the decompressed image data. This pointer is | |
42 | + * aligned to 32-bit-aligned-address + 2. | |
43 | + * See doc/README.displaying-bmps for explanation. | |
43 | 44 | * |
45 | + * The allocation address is passed to 'alloc_addr' and must be freed | |
46 | + * by the caller after use. | |
47 | + * | |
44 | 48 | * Returns NULL if decompression failed, or if the decompressed data |
45 | 49 | * didn't contain a valid BMP signature. |
46 | 50 | */ |
47 | 51 | #ifdef CONFIG_VIDEO_BMP_GZIP |
48 | -bmp_image_t *gunzip_bmp(unsigned long addr, unsigned long *lenp) | |
52 | +bmp_image_t *gunzip_bmp(unsigned long addr, unsigned long *lenp, | |
53 | + void **alloc_addr) | |
49 | 54 | { |
50 | 55 | void *dst; |
51 | 56 | unsigned long len; |
52 | 57 | |
... | ... | @@ -55,12 +60,19 @@ |
55 | 60 | * Decompress bmp image |
56 | 61 | */ |
57 | 62 | len = CONFIG_SYS_VIDEO_LOGO_MAX_SIZE; |
58 | - dst = malloc(CONFIG_SYS_VIDEO_LOGO_MAX_SIZE); | |
63 | + /* allocate extra 3 bytes for 32-bit-aligned-address + 2 alignment */ | |
64 | + dst = malloc(CONFIG_SYS_VIDEO_LOGO_MAX_SIZE + 3); | |
59 | 65 | if (dst == NULL) { |
60 | 66 | puts("Error: malloc in gunzip failed!\n"); |
61 | 67 | return NULL; |
62 | 68 | } |
63 | - if (gunzip(dst, CONFIG_SYS_VIDEO_LOGO_MAX_SIZE, (uchar *)addr, &len) != 0) { | |
69 | + | |
70 | + bmp = dst; | |
71 | + | |
72 | + /* align to 32-bit-aligned-address + 2 */ | |
73 | + bmp = (bmp_image_t *)((((unsigned int)dst + 1) & ~3) + 2); | |
74 | + | |
75 | + if (gunzip(bmp, CONFIG_SYS_VIDEO_LOGO_MAX_SIZE, (uchar *)addr, &len) != 0) { | |
64 | 76 | free(dst); |
65 | 77 | return NULL; |
66 | 78 | } |
... | ... | @@ -68,8 +80,6 @@ |
68 | 80 | puts("Image could be truncated" |
69 | 81 | " (increase CONFIG_SYS_VIDEO_LOGO_MAX_SIZE)!\n"); |
70 | 82 | |
71 | - bmp = dst; | |
72 | - | |
73 | 83 | /* |
74 | 84 | * Check for bmp mark 'BM' |
75 | 85 | */ |
76 | 86 | |
... | ... | @@ -81,10 +91,12 @@ |
81 | 91 | |
82 | 92 | debug("Gzipped BMP image detected!\n"); |
83 | 93 | |
94 | + *alloc_addr = dst; | |
84 | 95 | return bmp; |
85 | 96 | } |
86 | 97 | #else |
87 | -bmp_image_t *gunzip_bmp(unsigned long addr, unsigned long *lenp) | |
98 | +bmp_image_t *gunzip_bmp(unsigned long addr, unsigned long *lenp, | |
99 | + void **alloc_addr) | |
88 | 100 | { |
89 | 101 | return NULL; |
90 | 102 | } |
91 | 103 | |
... | ... | @@ -189,11 +201,12 @@ |
189 | 201 | static int bmp_info(ulong addr) |
190 | 202 | { |
191 | 203 | bmp_image_t *bmp=(bmp_image_t *)addr; |
204 | + void *bmp_alloc_addr = NULL; | |
192 | 205 | unsigned long len; |
193 | 206 | |
194 | 207 | if (!((bmp->header.signature[0]=='B') && |
195 | 208 | (bmp->header.signature[1]=='M'))) |
196 | - bmp = gunzip_bmp(addr, &len); | |
209 | + bmp = gunzip_bmp(addr, &len, &bmp_alloc_addr); | |
197 | 210 | |
198 | 211 | if (bmp == NULL) { |
199 | 212 | printf("There is no valid bmp file at the given address\n"); |
... | ... | @@ -205,8 +218,8 @@ |
205 | 218 | printf("Bits per pixel: %d\n", le16_to_cpu(bmp->header.bit_count)); |
206 | 219 | printf("Compression : %d\n", le32_to_cpu(bmp->header.compression)); |
207 | 220 | |
208 | - if ((unsigned long)bmp != addr) | |
209 | - free(bmp); | |
221 | + if (bmp_alloc_addr) | |
222 | + free(bmp_alloc_addr); | |
210 | 223 | |
211 | 224 | return(0); |
212 | 225 | } |
213 | 226 | |
... | ... | @@ -225,11 +238,12 @@ |
225 | 238 | { |
226 | 239 | int ret; |
227 | 240 | bmp_image_t *bmp = (bmp_image_t *)addr; |
241 | + void *bmp_alloc_addr = NULL; | |
228 | 242 | unsigned long len; |
229 | 243 | |
230 | 244 | if (!((bmp->header.signature[0]=='B') && |
231 | 245 | (bmp->header.signature[1]=='M'))) |
232 | - bmp = gunzip_bmp(addr, &len); | |
246 | + bmp = gunzip_bmp(addr, &len, &bmp_alloc_addr); | |
233 | 247 | |
234 | 248 | if (!bmp) { |
235 | 249 | printf("There is no valid bmp file at the given address\n"); |
... | ... | @@ -244,8 +258,8 @@ |
244 | 258 | # error bmp_display() requires CONFIG_LCD or CONFIG_VIDEO |
245 | 259 | #endif |
246 | 260 | |
247 | - if ((unsigned long)bmp != addr) | |
248 | - free(bmp); | |
261 | + if (bmp_alloc_addr) | |
262 | + free(bmp_alloc_addr); | |
249 | 263 | |
250 | 264 | return ret; |
251 | 265 | } |
include/lcd.h
... | ... | @@ -46,7 +46,8 @@ |
46 | 46 | int lcd_getfgcolor(void); |
47 | 47 | |
48 | 48 | /* gunzip_bmp used if CONFIG_VIDEO_BMP_GZIP */ |
49 | -struct bmp_image *gunzip_bmp(unsigned long addr, unsigned long *lenp); | |
49 | +struct bmp_image *gunzip_bmp(unsigned long addr, unsigned long *lenp, | |
50 | + void **alloc_addr); | |
50 | 51 | int bmp_display(ulong addr, int x, int y); |
51 | 52 | |
52 | 53 | /** |