]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
059ae173 WD |
2 | /* |
3 | * (C) Copyright 2002 | |
b37c7e5e | 4 | * Detlev Zundel, DENX Software Engineering, [email protected]. |
059ae173 WD |
5 | */ |
6 | ||
7 | /* | |
8 | * BMP handling routines | |
9 | */ | |
10 | ||
11 | #include <common.h> | |
12 | #include <bmp_layout.h> | |
13 | #include <command.h> | |
0c670fc1 SG |
14 | #include <dm.h> |
15 | #include <gzip.h> | |
8e8ccfe1 | 16 | #include <image.h> |
f7ae49fc | 17 | #include <log.h> |
c29ab9d7 | 18 | #include <malloc.h> |
72b335e9 | 19 | #include <mapmem.h> |
ff8fb56b | 20 | #include <splash.h> |
f674f7cf | 21 | #include <video.h> |
0c670fc1 | 22 | #include <asm/byteorder.h> |
059ae173 | 23 | |
059ae173 | 24 | static int bmp_info (ulong addr); |
059ae173 | 25 | |
43ef1c38 HCE |
26 | /* |
27 | * Allocate and decompress a BMP image using gunzip(). | |
28 | * | |
f7ef9d61 PW |
29 | * Returns a pointer to the decompressed image data. This pointer is |
30 | * aligned to 32-bit-aligned-address + 2. | |
31 | * See doc/README.displaying-bmps for explanation. | |
32 | * | |
33 | * The allocation address is passed to 'alloc_addr' and must be freed | |
34 | * by the caller after use. | |
43ef1c38 HCE |
35 | * |
36 | * Returns NULL if decompression failed, or if the decompressed data | |
37 | * didn't contain a valid BMP signature. | |
38 | */ | |
39 | #ifdef CONFIG_VIDEO_BMP_GZIP | |
1c3dbe56 SG |
40 | struct bmp_image *gunzip_bmp(unsigned long addr, unsigned long *lenp, |
41 | void **alloc_addr) | |
43ef1c38 HCE |
42 | { |
43 | void *dst; | |
44 | unsigned long len; | |
1c3dbe56 | 45 | struct bmp_image *bmp; |
43ef1c38 HCE |
46 | |
47 | /* | |
48 | * Decompress bmp image | |
49 | */ | |
e6550033 | 50 | len = CONFIG_VIDEO_LOGO_MAX_SIZE; |
f7ef9d61 | 51 | /* allocate extra 3 bytes for 32-bit-aligned-address + 2 alignment */ |
e6550033 SG |
52 | dst = malloc(CONFIG_VIDEO_LOGO_MAX_SIZE + 3); |
53 | if (!dst) { | |
43ef1c38 HCE |
54 | puts("Error: malloc in gunzip failed!\n"); |
55 | return NULL; | |
56 | } | |
f7ef9d61 | 57 | |
f7ef9d61 | 58 | /* align to 32-bit-aligned-address + 2 */ |
e6550033 | 59 | bmp = dst + 2; |
f7ef9d61 | 60 | |
e6550033 SG |
61 | if (gunzip(bmp, CONFIG_VIDEO_LOGO_MAX_SIZE, map_sysmem(addr, 0), |
62 | &len)) { | |
43ef1c38 HCE |
63 | free(dst); |
64 | return NULL; | |
65 | } | |
e6550033 SG |
66 | if (len == CONFIG_VIDEO_LOGO_MAX_SIZE) |
67 | puts("Image could be truncated (increase CONFIG_VIDEO_LOGO_MAX_SIZE)!\n"); | |
43ef1c38 | 68 | |
43ef1c38 HCE |
69 | /* |
70 | * Check for bmp mark 'BM' | |
71 | */ | |
72 | if (!((bmp->header.signature[0] == 'B') && | |
73 | (bmp->header.signature[1] == 'M'))) { | |
74 | free(dst); | |
75 | return NULL; | |
76 | } | |
77 | ||
17f79e45 | 78 | debug("Gzipped BMP image detected!\n"); |
43ef1c38 | 79 | |
f7ef9d61 | 80 | *alloc_addr = dst; |
43ef1c38 HCE |
81 | return bmp; |
82 | } | |
83 | #else | |
1c3dbe56 SG |
84 | struct bmp_image *gunzip_bmp(unsigned long addr, unsigned long *lenp, |
85 | void **alloc_addr) | |
43ef1c38 HCE |
86 | { |
87 | return NULL; | |
88 | } | |
89 | #endif | |
90 | ||
09140113 SG |
91 | static int do_bmp_info(struct cmd_tbl *cmdtp, int flag, int argc, |
92 | char *const argv[]) | |
9acd4f0e FM |
93 | { |
94 | ulong addr; | |
43ef1c38 | 95 | |
9acd4f0e | 96 | switch (argc) { |
bb872dd9 SG |
97 | case 1: /* use image_load_addr as default address */ |
98 | addr = image_load_addr; | |
9acd4f0e FM |
99 | break; |
100 | case 2: /* use argument */ | |
7e5f460e | 101 | addr = hextoul(argv[1], NULL); |
9acd4f0e FM |
102 | break; |
103 | default: | |
4c12eeb8 | 104 | return CMD_RET_USAGE; |
9acd4f0e FM |
105 | } |
106 | ||
107 | return (bmp_info(addr)); | |
108 | } | |
109 | ||
09140113 SG |
110 | static int do_bmp_display(struct cmd_tbl *cmdtp, int flag, int argc, |
111 | char *const argv[]) | |
059ae173 WD |
112 | { |
113 | ulong addr; | |
4b248f3f | 114 | int x = 0, y = 0; |
059ae173 | 115 | |
ff8fb56b AG |
116 | splash_get_pos(&x, &y); |
117 | ||
059ae173 | 118 | switch (argc) { |
bb872dd9 SG |
119 | case 1: /* use image_load_addr as default address */ |
120 | addr = image_load_addr; | |
059ae173 | 121 | break; |
9acd4f0e | 122 | case 2: /* use argument */ |
7e5f460e | 123 | addr = hextoul(argv[1], NULL); |
059ae173 | 124 | break; |
9acd4f0e | 125 | case 4: |
7e5f460e | 126 | addr = hextoul(argv[1], NULL); |
b0fcedb7 PD |
127 | if (!strcmp(argv[2], "m")) |
128 | x = BMP_ALIGN_CENTER; | |
129 | else | |
0b1284eb | 130 | x = dectoul(argv[2], NULL); |
b0fcedb7 PD |
131 | if (!strcmp(argv[3], "m")) |
132 | y = BMP_ALIGN_CENTER; | |
133 | else | |
0b1284eb | 134 | y = dectoul(argv[3], NULL); |
93e14596 | 135 | break; |
059ae173 | 136 | default: |
4c12eeb8 | 137 | return CMD_RET_USAGE; |
059ae173 WD |
138 | } |
139 | ||
9acd4f0e FM |
140 | return (bmp_display(addr, x, y)); |
141 | } | |
142 | ||
09140113 | 143 | static struct cmd_tbl cmd_bmp_sub[] = { |
9acd4f0e FM |
144 | U_BOOT_CMD_MKENT(info, 3, 0, do_bmp_info, "", ""), |
145 | U_BOOT_CMD_MKENT(display, 5, 0, do_bmp_display, "", ""), | |
146 | }; | |
147 | ||
2e5167cc | 148 | #ifdef CONFIG_NEEDS_MANUAL_RELOC |
f1d2b313 HS |
149 | void bmp_reloc(void) { |
150 | fixup_cmdtable(cmd_bmp_sub, ARRAY_SIZE(cmd_bmp_sub)); | |
151 | } | |
152 | #endif | |
153 | ||
9acd4f0e FM |
154 | /* |
155 | * Subroutine: do_bmp | |
156 | * | |
157 | * Description: Handler for 'bmp' command.. | |
158 | * | |
159 | * Inputs: argv[1] contains the subcommand | |
160 | * | |
161 | * Return: None | |
162 | * | |
163 | */ | |
09140113 | 164 | static int do_bmp(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) |
9acd4f0e | 165 | { |
09140113 | 166 | struct cmd_tbl *c; |
9acd4f0e FM |
167 | |
168 | /* Strip off leading 'bmp' command argument */ | |
169 | argc--; | |
170 | argv++; | |
171 | ||
172 | c = find_cmd_tbl(argv[0], &cmd_bmp_sub[0], ARRAY_SIZE(cmd_bmp_sub)); | |
173 | ||
47e26b1b | 174 | if (c) |
9acd4f0e | 175 | return c->cmd(cmdtp, flag, argc, argv); |
47e26b1b | 176 | else |
4c12eeb8 | 177 | return CMD_RET_USAGE; |
059ae173 WD |
178 | } |
179 | ||
0d498393 | 180 | U_BOOT_CMD( |
4b248f3f | 181 | bmp, 5, 1, do_bmp, |
2fb2604d | 182 | "manipulate BMP image data", |
4b248f3f | 183 | "info <imageAddr> - display image info\n" |
a89c33db | 184 | "bmp display <imageAddr> [x y] - display image at x,y" |
b0fce99b WD |
185 | ); |
186 | ||
059ae173 WD |
187 | /* |
188 | * Subroutine: bmp_info | |
189 | * | |
190 | * Description: Show information about bmp file in memory | |
191 | * | |
192 | * Inputs: addr address of the bmp file | |
193 | * | |
194 | * Return: None | |
195 | * | |
196 | */ | |
197 | static int bmp_info(ulong addr) | |
198 | { | |
72b335e9 | 199 | struct bmp_image *bmp = (struct bmp_image *)map_sysmem(addr, 0); |
f7ef9d61 | 200 | void *bmp_alloc_addr = NULL; |
43ef1c38 | 201 | unsigned long len; |
c29ab9d7 | 202 | |
059ae173 | 203 | if (!((bmp->header.signature[0]=='B') && |
43ef1c38 | 204 | (bmp->header.signature[1]=='M'))) |
f7ef9d61 | 205 | bmp = gunzip_bmp(addr, &len, &bmp_alloc_addr); |
c29ab9d7 | 206 | |
43ef1c38 | 207 | if (bmp == NULL) { |
059ae173 | 208 | printf("There is no valid bmp file at the given address\n"); |
43ef1c38 | 209 | return 1; |
059ae173 | 210 | } |
43ef1c38 | 211 | |
059ae173 WD |
212 | printf("Image size : %d x %d\n", le32_to_cpu(bmp->header.width), |
213 | le32_to_cpu(bmp->header.height)); | |
214 | printf("Bits per pixel: %d\n", le16_to_cpu(bmp->header.bit_count)); | |
215 | printf("Compression : %d\n", le32_to_cpu(bmp->header.compression)); | |
c29ab9d7 | 216 | |
f7ef9d61 PW |
217 | if (bmp_alloc_addr) |
218 | free(bmp_alloc_addr); | |
c29ab9d7 | 219 | |
059ae173 WD |
220 | return(0); |
221 | } | |
222 | ||
de3b49c4 | 223 | int bmp_display(ulong addr, int x, int y) |
059ae173 | 224 | { |
b01c7923 | 225 | struct udevice *dev; |
43ef1c38 | 226 | int ret; |
72b335e9 | 227 | struct bmp_image *bmp = map_sysmem(addr, 0); |
f7ef9d61 | 228 | void *bmp_alloc_addr = NULL; |
43ef1c38 HCE |
229 | unsigned long len; |
230 | ||
231 | if (!((bmp->header.signature[0]=='B') && | |
232 | (bmp->header.signature[1]=='M'))) | |
f7ef9d61 | 233 | bmp = gunzip_bmp(addr, &len, &bmp_alloc_addr); |
43ef1c38 HCE |
234 | |
235 | if (!bmp) { | |
236 | printf("There is no valid bmp file at the given address\n"); | |
237 | return 1; | |
238 | } | |
72b335e9 | 239 | addr = map_to_sysmem(bmp); |
43ef1c38 | 240 | |
3f603cbb | 241 | ret = uclass_first_device_err(UCLASS_VIDEO, &dev); |
b01c7923 | 242 | if (!ret) { |
3f603cbb | 243 | bool align = false; |
b01c7923 | 244 | |
988d19dd | 245 | if (x == BMP_ALIGN_CENTER || y == BMP_ALIGN_CENTER) |
b0fcedb7 PD |
246 | align = true; |
247 | ||
3f603cbb | 248 | ret = video_bmp_display(dev, addr, x, y, align); |
b01c7923 | 249 | } |
43ef1c38 | 250 | |
f7ef9d61 PW |
251 | if (bmp_alloc_addr) |
252 | free(bmp_alloc_addr); | |
43ef1c38 | 253 | |
e517db73 | 254 | return ret ? CMD_RET_FAILURE : 0; |
059ae173 | 255 | } |