Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(33)

Unified Diff: utility/bmpblk_util.c

Issue 6508006: Enable EFIv1 compression in bmpbklk_utility. (Closed) Base URL: http://git.chromium.org/git/vboot_reference.git@master
Patch Set: Added tests, updated copyrights, moved bmpblk_util.h as suggested. Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « utility/Makefile ('k') | utility/bmpblk_utility.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: utility/bmpblk_util.c
diff --git a/utility/bmpblk_util.c b/utility/bmpblk_util.c
index d7b9cbf80abbf62706193868bb03466557108e11..214beda4b0040d2b2a1b6b88c283665e3b47c2d4 100644
--- a/utility/bmpblk_util.c
+++ b/utility/bmpblk_util.c
@@ -4,6 +4,7 @@
#include <errno.h>
#include <fcntl.h>
+#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
@@ -12,6 +13,7 @@
#include <unistd.h>
#include "bmpblk_util.h"
+#include "eficompress.h"
// Returns pointer to buffer containing entire file, sets length.
@@ -58,14 +60,105 @@ static void discard_file(void *ptr, size_t length) {
munmap(ptr, length);
}
+//////////////////////////////////////////////////////////////////////////////
-// Show what's inside
-int display_bmpblock(const char *infile) {
- char *ptr;
+static int require_dir(const char *dirname) {
+ struct stat sbuf;
+
+ if (0 == stat(dirname, &sbuf)) {
+ // Something's there. Is it a directory?
+ if (S_ISDIR(sbuf.st_mode)) {
+ return 0;
+ }
+ fprintf(stderr, "%s already exists and is not a directory\n", dirname);
+ return 1;
+ }
+
+ // dirname doesn't exist. Try to create it.
+ if (ENOENT == errno) {
+ if (0 != mkdir(dirname, 0777)) {
+ fprintf(stderr, "Unable to create directory %s: %s\n",
+ dirname, strerror(errno));
+ return 1;
+ }
+ return 0;
+ }
+
+ fprintf(stderr, "Unable to stat %s: %s\n", dirname, strerror(errno));
+ return 1;
+}
+
+
+
+static void *do_efi_decompress(ImageInfo *img) {
+ void *ibuf;
+ void *sbuf;
+ void *obuf;
+ uint32_t isize;
+ uint32_t ssize;
+ uint32_t osize;
+ EFI_STATUS r;
+
+ ibuf = ((void *)img) + sizeof(ImageInfo);
+ isize = img->compressed_size;
+
+ r = EfiGetInfo(ibuf, isize, &osize, &ssize);
+ if (EFI_SUCCESS != r) {
+ fprintf(stderr, "EfiGetInfo() failed with code %d\n",
+ r);
+ return 0;
+ }
+
+ sbuf = malloc(ssize);
+ if (!sbuf) {
+ fprintf(stderr, "Can't allocate %d bytes: %s\n",
+ ssize,
+ strerror(errno));
+ return 0;
+ }
+
+ obuf = malloc(osize);
+ if (!obuf) {
+ fprintf(stderr, "Can't allocate %d bytes: %s\n",
+ osize,
+ strerror(errno));
+ free(sbuf);
+ return 0;
+ }
+
+ r = EfiDecompress(ibuf, isize, obuf, osize, sbuf, ssize);
+ if (r != EFI_SUCCESS) {
+ fprintf(stderr, "EfiDecompress failed with code %d\n", r);
+ free(obuf);
+ free(sbuf);
+ return 0;
+ }
+
+ free(sbuf);
+ return obuf;
+}
+
+
+// Show what's inside. If todir is NULL, just print. Otherwise unpack.
+int dump_bmpblock(const char *infile, int show_as_yaml,
+ const char *todir, int overwrite) {
+ void *ptr, *data_ptr;
size_t length = 0;
BmpBlockHeader *hdr;
+ ImageInfo *img;
+ ScreenLayout *scr;
+ int loc_num;
+ int screen_num;
+ int i;
+ int offset;
+ int free_data;
+ char image_name[80];
+ char full_path_name[PATH_MAX];
+ int yfd, bfd;
+ FILE *yfp = stdout;
+ FILE *bfp = stdout;
- ptr = (char *)read_entire_file(infile, &length);
+ ptr = (void *)read_entire_file(infile, &length);
if (!ptr)
return 1;
@@ -81,21 +174,163 @@ int display_bmpblock(const char *infile) {
return 1;
}
+ if (todir) {
+ // Unpacking everything. Create the output directory if needed.
+ if (0 != require_dir(todir)) {
+ discard_file(ptr, length);
+ return 1;
+ }
+
+ // Open yaml output.
+ show_as_yaml = 1;
+
+ sprintf(full_path_name, "%s/%s", todir, "config.yaml");
+ yfd = open(full_path_name,
+ O_WRONLY | O_CREAT | O_TRUNC | (overwrite ? 0 : O_EXCL),
+ 0666);
+ if (yfd < 0) {
+ fprintf(stderr, "Unable to open %s: %s\n", full_path_name,
+ strerror(errno));
+ discard_file(ptr, length);
+ return 1;
+ }
+
+ yfp = fdopen(yfd, "wb");
+ if (!yfp) {
+ fprintf(stderr, "Unable to fdopen %s: %s\n", full_path_name,
+ strerror(errno));
+ close(yfd);
+ discard_file(ptr, length);
+ return 1;
+ }
+ }
+
hdr = (BmpBlockHeader *)ptr;
- printf("%s:\n", infile);
- printf(" version %d.%d\n", hdr->major_version, hdr->minor_version);
- printf(" %d screens\n", hdr->number_of_screenlayouts);
- printf(" %d localizations\n", hdr->number_of_localizations);
- printf(" %d discrete images\n", hdr->number_of_imageinfos);
+
+ if (!show_as_yaml) {
+ printf("%s:\n", infile);
+ printf(" version %d.%d\n", hdr->major_version, hdr->minor_version);
+ printf(" %d screens\n", hdr->number_of_screenlayouts);
+ printf(" %d localizations\n", hdr->number_of_localizations);
+ printf(" %d discrete images\n", hdr->number_of_imageinfos);
+ discard_file(ptr, length);
+ return 0;
+ }
+
+ // Write out yaml
+ fprintf(yfp, "bmpblock: %d.%d\n", hdr->major_version, hdr->minor_version);
+ fprintf(yfp, "images:\n");
+ offset = sizeof(BmpBlockHeader) +
+ (sizeof(ScreenLayout) *
+ hdr->number_of_localizations *
+ hdr->number_of_screenlayouts);
+ for(i=0; i<hdr->number_of_imageinfos; i++) {
+ img = (ImageInfo *)(ptr + offset);
+ sprintf(image_name, "img_%08x.bmp", offset);
+ fprintf(yfp, " img_%08x: %s # %dx%d %d/%d\n", offset, image_name,
+ img->width, img->height,
+ img->compressed_size, img->original_size);
+ if (todir) {
+ sprintf(full_path_name, "%s/%s", todir, image_name);
+ bfd = open(full_path_name,
+ O_WRONLY | O_CREAT | O_TRUNC | (overwrite ? 0 : O_EXCL),
+ 0666);
+ if (bfd < 0) {
+ fprintf(stderr, "Unable to open %s: %s\n", full_path_name,
+ strerror(errno));
+ fclose(yfp);
+ discard_file(ptr, length);
+ return 1;
+ }
+ bfp = fdopen(bfd, "wb");
+ if (!bfp) {
+ fprintf(stderr, "Unable to fdopen %s: %s\n", full_path_name,
+ strerror(errno));
+ close(bfd);
+ fclose(yfp);
+ discard_file(ptr, length);
+ return 1;
+ }
+ switch(img->compression) {
+ case COMPRESS_NONE:
+ data_ptr = ptr + offset + sizeof(ImageInfo);
+ free_data = 0;
+ break;
+ case COMPRESS_EFIv1:
+ data_ptr = do_efi_decompress(img);
+ if (!data_ptr) {
+ fclose(bfp);
+ fclose(yfp);
+ discard_file(ptr, length);
+ return 1;
+ }
+ free_data = 1;
+ break;
+ default:
+ fprintf(stderr, "Unsupported compression method encountered.\n");
+ fclose(bfp);
+ fclose(yfp);
+ discard_file(ptr, length);
+ return 1;
+ }
+ if (1 != fwrite(data_ptr, img->original_size, 1, bfp)) {
+ fprintf(stderr, "Unable to write %s: %s\n", full_path_name,
+ strerror(errno));
+ fclose(bfp);
+ fclose(yfp);
+ discard_file(ptr, length);
+ return 1;
+ }
+ fclose(bfp);
+ if (free_data)
+ free(data_ptr);
+ }
+ offset += sizeof(ImageInfo);
+ offset += img->compressed_size;
+ // 4-byte aligned
+ if ((offset & 3) > 0)
+ offset = (offset & ~3) + 4;
+ }
+ fprintf(yfp, "screens:\n");
+ for(loc_num = 0;
+ loc_num < hdr->number_of_localizations;
+ loc_num++) {
+ for(screen_num = 0;
+ screen_num < hdr->number_of_screenlayouts;
+ screen_num++) {
+ fprintf(yfp, " scr_%d_%d:\n", loc_num, screen_num);
+ i = loc_num * hdr->number_of_screenlayouts + screen_num;
+ offset = sizeof(BmpBlockHeader) + i * sizeof(ScreenLayout);
+ scr = (ScreenLayout *)(ptr + offset);
+ for(i=0; i<MAX_IMAGE_IN_LAYOUT; i++) {
+ if (scr->images[i].image_info_offset) {
+ fprintf(yfp, " - [%d, %d, img_%08x]\n",
+ scr->images[i].x, scr->images[i].y,
+ scr->images[i].image_info_offset);
+ }
+ }
+ }
+ }
+ fprintf(yfp, "localizations:\n");
+ for(loc_num = 0;
+ loc_num < hdr->number_of_localizations;
+ loc_num++) {
+ fprintf(yfp, " - [");
+ for(screen_num = 0;
+ screen_num < hdr->number_of_screenlayouts;
+ screen_num++) {
+ fprintf(yfp, " scr_%d_%d", loc_num, screen_num);
+ if (screen_num != hdr->number_of_screenlayouts - 1)
+ fprintf(yfp, ",");
+ }
+ fprintf(yfp, " ]\n");
+ }
+
+ if (todir)
+ fclose(yfp);
discard_file(ptr, length);
return 0;
}
-int extract_bmpblock(const char *infile, const char *dirname, int force) {
- printf("extract parts from %s into %s %s overwriting\n",
- infile, dirname, force ? "with" : "without");
- printf("NOT YET IMPLEMENTED\n");
- return 0;
-}
« no previous file with comments | « utility/Makefile ('k') | utility/bmpblk_utility.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698