Commit f7ef9d610cb28d31c106792f18b58424e39275c7

Authored by Piotr Wilczek
Committed by Anatolij Gustschin
1 parent 5af7d0f090

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

... ... @@ -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 }
... ... @@ -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 /**