Blame view
cmd/bmp.c
6.07 KB
83d290c56
|
1 |
// SPDX-License-Identifier: GPL-2.0+ |
059ae173e
|
2 3 |
/* * (C) Copyright 2002 |
b37c7e5e5
|
4 |
* Detlev Zundel, DENX Software Engineering, dzu@denx.de. |
059ae173e
|
5 6 7 8 9 10 11 12 13 |
*/ /* * BMP handling routines */ #include <common.h> #include <bmp_layout.h> #include <command.h> |
0c670fc14
|
14 15 |
#include <dm.h> #include <gzip.h> |
8e8ccfe1a
|
16 |
#include <image.h> |
0c670fc14
|
17 |
#include <lcd.h> |
c29ab9d71
|
18 |
#include <malloc.h> |
72b335e91
|
19 |
#include <mapmem.h> |
ff8fb56b6
|
20 |
#include <splash.h> |
f674f7cfc
|
21 |
#include <video.h> |
0257e77fd
|
22 |
#include <video_link.h> |
0c670fc14
|
23 |
#include <asm/byteorder.h> |
059ae173e
|
24 |
|
059ae173e
|
25 |
static int bmp_info (ulong addr); |
059ae173e
|
26 27 |
/* |
43ef1c381
|
28 29 |
* Allocate and decompress a BMP image using gunzip(). * |
f7ef9d610
|
30 31 32 33 34 35 |
* Returns a pointer to the decompressed image data. This pointer is * aligned to 32-bit-aligned-address + 2. * See doc/README.displaying-bmps for explanation. * * The allocation address is passed to 'alloc_addr' and must be freed * by the caller after use. |
43ef1c381
|
36 37 38 39 40 |
* * Returns NULL if decompression failed, or if the decompressed data * didn't contain a valid BMP signature. */ #ifdef CONFIG_VIDEO_BMP_GZIP |
1c3dbe56f
|
41 42 |
struct bmp_image *gunzip_bmp(unsigned long addr, unsigned long *lenp, void **alloc_addr) |
43ef1c381
|
43 44 45 |
{ void *dst; unsigned long len; |
1c3dbe56f
|
46 |
struct bmp_image *bmp; |
43ef1c381
|
47 48 49 50 |
/* * Decompress bmp image */ |
6d0f6bcf3
|
51 |
len = CONFIG_SYS_VIDEO_LOGO_MAX_SIZE; |
f7ef9d610
|
52 53 |
/* allocate extra 3 bytes for 32-bit-aligned-address + 2 alignment */ dst = malloc(CONFIG_SYS_VIDEO_LOGO_MAX_SIZE + 3); |
43ef1c381
|
54 55 56 57 58 |
if (dst == NULL) { puts("Error: malloc in gunzip failed! "); return NULL; } |
f7ef9d610
|
59 60 61 62 |
bmp = dst; /* align to 32-bit-aligned-address + 2 */ |
77195216f
|
63 |
bmp = (struct bmp_image *)((((uintptr_t)dst + 1) & ~3) + 2); |
f7ef9d610
|
64 |
|
72b335e91
|
65 66 |
if (gunzip(bmp, CONFIG_SYS_VIDEO_LOGO_MAX_SIZE, map_sysmem(addr, 0), &len) != 0) { |
43ef1c381
|
67 68 69 |
free(dst); return NULL; } |
6d0f6bcf3
|
70 |
if (len == CONFIG_SYS_VIDEO_LOGO_MAX_SIZE) |
43ef1c381
|
71 |
puts("Image could be truncated" |
6d0f6bcf3
|
72 73 |
" (increase CONFIG_SYS_VIDEO_LOGO_MAX_SIZE)! "); |
43ef1c381
|
74 |
|
43ef1c381
|
75 76 77 78 79 80 81 82 |
/* * Check for bmp mark 'BM' */ if (!((bmp->header.signature[0] == 'B') && (bmp->header.signature[1] == 'M'))) { free(dst); return NULL; } |
17f79e45e
|
83 84 |
debug("Gzipped BMP image detected! "); |
43ef1c381
|
85 |
|
f7ef9d610
|
86 |
*alloc_addr = dst; |
43ef1c381
|
87 88 89 |
return bmp; } #else |
1c3dbe56f
|
90 91 |
struct bmp_image *gunzip_bmp(unsigned long addr, unsigned long *lenp, void **alloc_addr) |
43ef1c381
|
92 93 94 95 |
{ return NULL; } #endif |
54841ab50
|
96 |
static int do_bmp_info(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) |
9acd4f0e9
|
97 98 |
{ ulong addr; |
43ef1c381
|
99 |
|
9acd4f0e9
|
100 |
switch (argc) { |
bb872dd93
|
101 102 |
case 1: /* use image_load_addr as default address */ addr = image_load_addr; |
9acd4f0e9
|
103 104 105 106 107 |
break; case 2: /* use argument */ addr = simple_strtoul(argv[1], NULL, 16); break; default: |
4c12eeb8b
|
108 |
return CMD_RET_USAGE; |
9acd4f0e9
|
109 110 111 112 |
} return (bmp_info(addr)); } |
54841ab50
|
113 |
static int do_bmp_display(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) |
059ae173e
|
114 115 |
{ ulong addr; |
4b248f3f7
|
116 |
int x = 0, y = 0; |
059ae173e
|
117 |
|
ff8fb56b6
|
118 |
splash_get_pos(&x, &y); |
059ae173e
|
119 |
switch (argc) { |
bb872dd93
|
120 121 |
case 1: /* use image_load_addr as default address */ addr = image_load_addr; |
059ae173e
|
122 |
break; |
9acd4f0e9
|
123 124 |
case 2: /* use argument */ addr = simple_strtoul(argv[1], NULL, 16); |
059ae173e
|
125 |
break; |
9acd4f0e9
|
126 127 |
case 4: addr = simple_strtoul(argv[1], NULL, 16); |
b0fcedb7a
|
128 129 130 131 132 133 134 135 |
if (!strcmp(argv[2], "m")) x = BMP_ALIGN_CENTER; else x = simple_strtoul(argv[2], NULL, 10); if (!strcmp(argv[3], "m")) y = BMP_ALIGN_CENTER; else y = simple_strtoul(argv[3], NULL, 10); |
93e145964
|
136 |
break; |
059ae173e
|
137 |
default: |
4c12eeb8b
|
138 |
return CMD_RET_USAGE; |
059ae173e
|
139 |
} |
9acd4f0e9
|
140 141 142 143 144 145 146 |
return (bmp_display(addr, x, y)); } static cmd_tbl_t cmd_bmp_sub[] = { U_BOOT_CMD_MKENT(info, 3, 0, do_bmp_info, "", ""), U_BOOT_CMD_MKENT(display, 5, 0, do_bmp_display, "", ""), }; |
2e5167cca
|
147 |
#ifdef CONFIG_NEEDS_MANUAL_RELOC |
f1d2b313c
|
148 149 150 151 |
void bmp_reloc(void) { fixup_cmdtable(cmd_bmp_sub, ARRAY_SIZE(cmd_bmp_sub)); } #endif |
9acd4f0e9
|
152 153 154 155 156 157 158 159 160 161 |
/* * Subroutine: do_bmp * * Description: Handler for 'bmp' command.. * * Inputs: argv[1] contains the subcommand * * Return: None * */ |
54841ab50
|
162 |
static int do_bmp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
9acd4f0e9
|
163 164 165 166 167 168 169 170 |
{ cmd_tbl_t *c; /* Strip off leading 'bmp' command argument */ argc--; argv++; c = find_cmd_tbl(argv[0], &cmd_bmp_sub[0], ARRAY_SIZE(cmd_bmp_sub)); |
47e26b1bf
|
171 |
if (c) |
9acd4f0e9
|
172 |
return c->cmd(cmdtp, flag, argc, argv); |
47e26b1bf
|
173 |
else |
4c12eeb8b
|
174 |
return CMD_RET_USAGE; |
059ae173e
|
175 |
} |
0d4983930
|
176 |
U_BOOT_CMD( |
4b248f3f7
|
177 |
bmp, 5, 1, do_bmp, |
2fb2604d5
|
178 |
"manipulate BMP image data", |
4b248f3f7
|
179 180 |
"info <imageAddr> - display image info " |
a89c33db9
|
181 |
"bmp display <imageAddr> [x y] - display image at x,y" |
b0fce99bf
|
182 |
); |
059ae173e
|
183 184 185 186 187 188 189 190 191 192 193 194 |
/* * Subroutine: bmp_info * * Description: Show information about bmp file in memory * * Inputs: addr address of the bmp file * * Return: None * */ static int bmp_info(ulong addr) { |
72b335e91
|
195 |
struct bmp_image *bmp = (struct bmp_image *)map_sysmem(addr, 0); |
f7ef9d610
|
196 |
void *bmp_alloc_addr = NULL; |
43ef1c381
|
197 |
unsigned long len; |
c29ab9d71
|
198 |
|
059ae173e
|
199 |
if (!((bmp->header.signature[0]=='B') && |
43ef1c381
|
200 |
(bmp->header.signature[1]=='M'))) |
f7ef9d610
|
201 |
bmp = gunzip_bmp(addr, &len, &bmp_alloc_addr); |
c29ab9d71
|
202 |
|
43ef1c381
|
203 |
if (bmp == NULL) { |
059ae173e
|
204 205 |
printf("There is no valid bmp file at the given address "); |
43ef1c381
|
206 |
return 1; |
059ae173e
|
207 |
} |
43ef1c381
|
208 |
|
059ae173e
|
209 210 211 212 213 214 215 |
printf("Image size : %d x %d ", le32_to_cpu(bmp->header.width), le32_to_cpu(bmp->header.height)); printf("Bits per pixel: %d ", le16_to_cpu(bmp->header.bit_count)); printf("Compression : %d ", le32_to_cpu(bmp->header.compression)); |
c29ab9d71
|
216 |
|
f7ef9d610
|
217 218 |
if (bmp_alloc_addr) free(bmp_alloc_addr); |
c29ab9d71
|
219 |
|
059ae173e
|
220 221 222 223 224 225 226 227 228 229 230 231 232 |
return(0); } /* * Subroutine: bmp_display * * Description: Display bmp file located in memory * * Inputs: addr address of the bmp file * * Return: None * */ |
de3b49c4d
|
233 |
int bmp_display(ulong addr, int x, int y) |
059ae173e
|
234 |
{ |
b01c7923e
|
235 236 237 |
#ifdef CONFIG_DM_VIDEO struct udevice *dev; #endif |
43ef1c381
|
238 |
int ret; |
72b335e91
|
239 |
struct bmp_image *bmp = map_sysmem(addr, 0); |
f7ef9d610
|
240 |
void *bmp_alloc_addr = NULL; |
43ef1c381
|
241 242 243 244 |
unsigned long len; if (!((bmp->header.signature[0]=='B') && (bmp->header.signature[1]=='M'))) |
f7ef9d610
|
245 |
bmp = gunzip_bmp(addr, &len, &bmp_alloc_addr); |
43ef1c381
|
246 247 248 249 250 251 |
if (!bmp) { printf("There is no valid bmp file at the given address "); return 1; } |
72b335e91
|
252 |
addr = map_to_sysmem(bmp); |
43ef1c381
|
253 |
|
b01c7923e
|
254 |
#ifdef CONFIG_DM_VIDEO |
0257e77fd
|
255 256 257 258 259 260 |
#ifdef CONFIG_VIDEO_LINK dev = video_link_get_video_device(); if (!dev) { ret = -ENODEV; } else { #else |
3f603cbbb
|
261 |
ret = uclass_first_device_err(UCLASS_VIDEO, &dev); |
b01c7923e
|
262 |
if (!ret) { |
0257e77fd
|
263 |
#endif |
3f603cbbb
|
264 |
bool align = false; |
b01c7923e
|
265 |
|
b0fcedb7a
|
266 267 268 269 |
if (CONFIG_IS_ENABLED(SPLASH_SCREEN_ALIGN) || x == BMP_ALIGN_CENTER || y == BMP_ALIGN_CENTER) align = true; |
3f603cbbb
|
270 |
ret = video_bmp_display(dev, addr, x, y, align); |
b01c7923e
|
271 |
} |
b01c7923e
|
272 |
#elif defined(CONFIG_LCD) |
72b335e91
|
273 |
ret = lcd_display_bitmap(addr, x, y); |
281e00a3b
|
274 |
#elif defined(CONFIG_VIDEO) |
72b335e91
|
275 |
ret = video_display_bitmap(addr, x, y); |
281e00a3b
|
276 277 |
#else # error bmp_display() requires CONFIG_LCD or CONFIG_VIDEO |
4b248f3f7
|
278 |
#endif |
43ef1c381
|
279 |
|
f7ef9d610
|
280 281 |
if (bmp_alloc_addr) free(bmp_alloc_addr); |
43ef1c381
|
282 |
|
e517db73a
|
283 |
return ret ? CMD_RET_FAILURE : 0; |
059ae173e
|
284 |
} |