OLD | NEW |
---|---|
1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <errno.h> | 5 #include <errno.h> |
6 #include <fcntl.h> | 6 #include <fcntl.h> |
7 #include <limits.h> | |
7 #include <stdio.h> | 8 #include <stdio.h> |
8 #include <string.h> | 9 #include <string.h> |
9 #include <sys/mman.h> | 10 #include <sys/mman.h> |
10 #include <sys/stat.h> | 11 #include <sys/stat.h> |
11 #include <sys/types.h> | 12 #include <sys/types.h> |
12 #include <unistd.h> | 13 #include <unistd.h> |
13 | 14 |
14 #include "bmpblk_util.h" | 15 #include "bmpblk_util.h" |
16 #include "eficompress.h" | |
15 | 17 |
16 | 18 |
17 // Returns pointer to buffer containing entire file, sets length. | 19 // Returns pointer to buffer containing entire file, sets length. |
18 static void *read_entire_file(const char *filename, size_t *length) { | 20 static void *read_entire_file(const char *filename, size_t *length) { |
19 int fd; | 21 int fd; |
20 struct stat sbuf; | 22 struct stat sbuf; |
21 void *ptr; | 23 void *ptr; |
22 | 24 |
23 *length = 0; // just in case | 25 *length = 0; // just in case |
24 | 26 |
(...skipping 26 matching lines...) Expand all Loading... | |
51 | 53 |
52 return ptr; | 54 return ptr; |
53 } | 55 } |
54 | 56 |
55 | 57 |
56 // Reclaims buffer from read_entire_file(). | 58 // Reclaims buffer from read_entire_file(). |
57 static void discard_file(void *ptr, size_t length) { | 59 static void discard_file(void *ptr, size_t length) { |
58 munmap(ptr, length); | 60 munmap(ptr, length); |
59 } | 61 } |
60 | 62 |
63 ////////////////////////////////////////////////////////////////////////////// | |
61 | 64 |
62 // Show what's inside | 65 static int require_dir(const char *dirname) { |
Randall Spangler
2011/02/11 23:44:02
Could move this to host/lib so we can share it wit
| |
63 int display_bmpblock(const char *infile) { | 66 struct stat sbuf; |
64 char *ptr; | 67 |
68 if (0 == stat(dirname, &sbuf)) { | |
69 // Something's there. Is it a directory? | |
70 if (S_ISDIR(sbuf.st_mode)) { | |
71 return 0; | |
72 } | |
73 fprintf(stderr, "%s already exists and is not a directory\n", dirname); | |
74 return 1; | |
75 } | |
76 | |
77 // dirname doesn't exist. Try to create it. | |
78 if (ENOENT == errno) { | |
79 if (0 != mkdir(dirname, 0777)) { | |
80 fprintf(stderr, "Unable to create directory %s: %s\n", | |
81 dirname, strerror(errno)); | |
82 return 1; | |
83 } | |
84 return 0; | |
85 } | |
86 | |
87 fprintf(stderr, "Unable to stat %s: %s\n", dirname, strerror(errno)); | |
88 return 1; | |
89 } | |
90 | |
91 | |
92 | |
93 static void *do_efi_decompress(ImageInfo *img) { | |
94 void *ibuf; | |
95 void *sbuf; | |
96 void *obuf; | |
97 uint32_t isize; | |
98 uint32_t ssize; | |
99 uint32_t osize; | |
100 EFI_STATUS r; | |
101 | |
102 ibuf = ((void *)img) + sizeof(ImageInfo); | |
103 isize = img->compressed_size; | |
104 | |
105 r = EfiGetInfo(ibuf, isize, &osize, &ssize); | |
106 if (EFI_SUCCESS != r) { | |
107 fprintf(stderr, "EfiGetInfo() failed with code %d\n", | |
108 r); | |
109 return 0; | |
110 } | |
111 | |
112 sbuf = malloc(ssize); | |
113 if (!sbuf) { | |
114 fprintf(stderr, "Can't allocate %d bytes: %s\n", | |
115 ssize, | |
116 strerror(errno)); | |
117 return 0; | |
118 } | |
119 | |
120 obuf = malloc(osize); | |
121 if (!obuf) { | |
122 fprintf(stderr, "Can't allocate %d bytes: %s\n", | |
123 osize, | |
124 strerror(errno)); | |
125 free(sbuf); | |
126 return 0; | |
127 } | |
128 | |
129 r = EfiDecompress(ibuf, isize, obuf, osize, sbuf, ssize); | |
130 if (r != EFI_SUCCESS) { | |
131 fprintf(stderr, "EfiDecompress failed with code %d\n", r); | |
132 free(obuf); | |
133 free(sbuf); | |
134 return 0; | |
135 } | |
136 | |
137 free(sbuf); | |
138 return obuf; | |
139 } | |
140 | |
141 | |
142 // Show what's inside. If todir is NULL, just print. Otherwise unpack. | |
143 int dump_bmpblock(const char *infile, int show_as_yaml, | |
144 const char *todir, int overwrite) { | |
145 void *ptr, *data_ptr; | |
65 size_t length = 0; | 146 size_t length = 0; |
66 BmpBlockHeader *hdr; | 147 BmpBlockHeader *hdr; |
148 ImageInfo *img; | |
149 ScreenLayout *scr; | |
150 int loc_num; | |
151 int screen_num; | |
152 int i; | |
153 int offset; | |
154 int free_data; | |
155 char image_name[80]; | |
156 char full_path_name[PATH_MAX]; | |
157 int yfd, bfd; | |
158 FILE *yfp = stdout; | |
159 FILE *bfp = stdout; | |
67 | 160 |
68 ptr = (char *)read_entire_file(infile, &length); | 161 ptr = (void *)read_entire_file(infile, &length); |
69 if (!ptr) | 162 if (!ptr) |
70 return 1; | 163 return 1; |
71 | 164 |
72 if (length < sizeof(BmpBlockHeader)) { | 165 if (length < sizeof(BmpBlockHeader)) { |
73 fprintf(stderr, "File %s is too small to be a BMPBLOCK\n", infile); | 166 fprintf(stderr, "File %s is too small to be a BMPBLOCK\n", infile); |
74 discard_file(ptr, length); | 167 discard_file(ptr, length); |
75 return 1; | 168 return 1; |
76 } | 169 } |
77 | 170 |
78 if (0 != memcmp(ptr, BMPBLOCK_SIGNATURE, BMPBLOCK_SIGNATURE_SIZE)) { | 171 if (0 != memcmp(ptr, BMPBLOCK_SIGNATURE, BMPBLOCK_SIGNATURE_SIZE)) { |
79 fprintf(stderr, "File %s is not a BMPBLOCK\n", infile); | 172 fprintf(stderr, "File %s is not a BMPBLOCK\n", infile); |
80 discard_file(ptr, length); | 173 discard_file(ptr, length); |
81 return 1; | 174 return 1; |
82 } | 175 } |
83 | 176 |
177 if (todir) { | |
178 // Unpacking everything. Create the output directory if needed. | |
179 if (0 != require_dir(todir)) { | |
180 discard_file(ptr, length); | |
181 return 1; | |
182 } | |
183 | |
184 // Open yaml output. | |
185 show_as_yaml = 1; | |
186 | |
187 sprintf(full_path_name, "%s/%s", todir, "config.yaml"); | |
188 yfd = open(full_path_name, | |
189 O_WRONLY | O_CREAT | O_TRUNC | (overwrite ? 0 : O_EXCL), | |
190 0666); | |
191 if (yfd < 0) { | |
192 fprintf(stderr, "Unable to open %s: %s\n", full_path_name, | |
193 strerror(errno)); | |
194 discard_file(ptr, length); | |
195 return 1; | |
196 } | |
197 | |
198 yfp = fdopen(yfd, "wb"); | |
199 if (!yfp) { | |
200 fprintf(stderr, "Unable to fdopen %s: %s\n", full_path_name, | |
201 strerror(errno)); | |
202 close(yfd); | |
203 discard_file(ptr, length); | |
204 return 1; | |
205 } | |
206 } | |
207 | |
84 hdr = (BmpBlockHeader *)ptr; | 208 hdr = (BmpBlockHeader *)ptr; |
85 printf("%s:\n", infile); | 209 |
86 printf(" version %d.%d\n", hdr->major_version, hdr->minor_version); | 210 if (!show_as_yaml) { |
87 printf(" %d screens\n", hdr->number_of_screenlayouts); | 211 printf("%s:\n", infile); |
88 printf(" %d localizations\n", hdr->number_of_localizations); | 212 printf(" version %d.%d\n", hdr->major_version, hdr->minor_version); |
89 printf(" %d discrete images\n", hdr->number_of_imageinfos); | 213 printf(" %d screens\n", hdr->number_of_screenlayouts); |
214 printf(" %d localizations\n", hdr->number_of_localizations); | |
215 printf(" %d discrete images\n", hdr->number_of_imageinfos); | |
216 discard_file(ptr, length); | |
217 return 0; | |
218 } | |
219 | |
220 // Write out yaml | |
221 fprintf(yfp, "bmpblock: %d.%d\n", hdr->major_version, hdr->minor_version); | |
222 fprintf(yfp, "images:\n"); | |
223 offset = sizeof(BmpBlockHeader) + | |
224 (sizeof(ScreenLayout) * | |
225 hdr->number_of_localizations * | |
226 hdr->number_of_screenlayouts); | |
227 for(i=0; i<hdr->number_of_imageinfos; i++) { | |
228 img = (ImageInfo *)(ptr + offset); | |
229 sprintf(image_name, "img_%08x.bmp", offset); | |
230 fprintf(yfp, " img_%08x: %s # %dx%d %d/%d\n", offset, image_name, | |
231 img->width, img->height, | |
232 img->compressed_size, img->original_size); | |
233 if (todir) { | |
234 sprintf(full_path_name, "%s/%s", todir, image_name); | |
235 bfd = open(full_path_name, | |
236 O_WRONLY | O_CREAT | O_TRUNC | (overwrite ? 0 : O_EXCL), | |
237 0666); | |
238 if (bfd < 0) { | |
239 fprintf(stderr, "Unable to open %s: %s\n", full_path_name, | |
240 strerror(errno)); | |
241 fclose(yfp); | |
242 discard_file(ptr, length); | |
243 return 1; | |
244 } | |
245 bfp = fdopen(bfd, "wb"); | |
246 if (!bfp) { | |
247 fprintf(stderr, "Unable to fdopen %s: %s\n", full_path_name, | |
248 strerror(errno)); | |
249 close(bfd); | |
250 fclose(yfp); | |
251 discard_file(ptr, length); | |
252 return 1; | |
253 } | |
254 switch(img->compression) { | |
255 case COMPRESS_NONE: | |
256 data_ptr = ptr + offset + sizeof(ImageInfo); | |
257 free_data = 0; | |
258 break; | |
259 case COMPRESS_EFIv1: | |
260 data_ptr = do_efi_decompress(img); | |
261 if (!data_ptr) { | |
262 fclose(bfp); | |
263 fclose(yfp); | |
264 discard_file(ptr, length); | |
265 return 1; | |
266 } | |
267 free_data = 1; | |
268 break; | |
269 default: | |
270 fprintf(stderr, "Unsupported compression method encountered.\n"); | |
271 fclose(bfp); | |
272 fclose(yfp); | |
273 discard_file(ptr, length); | |
274 return 1; | |
275 } | |
276 if (1 != fwrite(data_ptr, img->original_size, 1, bfp)) { | |
277 fprintf(stderr, "Unable to write %s: %s\n", full_path_name, | |
278 strerror(errno)); | |
279 fclose(bfp); | |
280 fclose(yfp); | |
281 discard_file(ptr, length); | |
282 return 1; | |
283 } | |
284 fclose(bfp); | |
285 if (free_data) | |
286 free(data_ptr); | |
287 } | |
288 offset += sizeof(ImageInfo); | |
289 offset += img->compressed_size; | |
290 // 4-byte aligned | |
291 if ((offset & 3) > 0) | |
292 offset = (offset & ~3) + 4; | |
293 } | |
294 fprintf(yfp, "screens:\n"); | |
295 for(loc_num = 0; | |
296 loc_num < hdr->number_of_localizations; | |
297 loc_num++) { | |
298 for(screen_num = 0; | |
299 screen_num < hdr->number_of_screenlayouts; | |
300 screen_num++) { | |
301 fprintf(yfp, " scr_%d_%d:\n", loc_num, screen_num); | |
302 i = loc_num * hdr->number_of_screenlayouts + screen_num; | |
303 offset = sizeof(BmpBlockHeader) + i * sizeof(ScreenLayout); | |
304 scr = (ScreenLayout *)(ptr + offset); | |
305 for(i=0; i<MAX_IMAGE_IN_LAYOUT; i++) { | |
306 if (scr->images[i].image_info_offset) { | |
307 fprintf(yfp, " - [%d, %d, img_%08x]\n", | |
308 scr->images[i].x, scr->images[i].y, | |
309 scr->images[i].image_info_offset); | |
310 } | |
311 } | |
312 } | |
313 } | |
314 fprintf(yfp, "localizations:\n"); | |
315 for(loc_num = 0; | |
316 loc_num < hdr->number_of_localizations; | |
317 loc_num++) { | |
318 fprintf(yfp, " - ["); | |
319 for(screen_num = 0; | |
320 screen_num < hdr->number_of_screenlayouts; | |
321 screen_num++) { | |
322 fprintf(yfp, " scr_%d_%d", loc_num, screen_num); | |
323 if (screen_num != hdr->number_of_screenlayouts - 1) | |
324 fprintf(yfp, ","); | |
325 } | |
326 fprintf(yfp, " ]\n"); | |
327 } | |
328 | |
329 if (todir) | |
330 fclose(yfp); | |
90 | 331 |
91 discard_file(ptr, length); | 332 discard_file(ptr, length); |
92 | 333 |
93 return 0; | 334 return 0; |
94 } | 335 } |
95 | 336 |
96 int extract_bmpblock(const char *infile, const char *dirname, int force) { | |
97 printf("extract parts from %s into %s %s overwriting\n", | |
98 infile, dirname, force ? "with" : "without"); | |
99 printf("NOT YET IMPLEMENTED\n"); | |
100 return 0; | |
101 } | |
OLD | NEW |