| 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;
|
| -}
|
|
|