123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- // Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include <errno.h>
- #include <fcntl.h>
- #include <getopt.h>
- #include <limits.h>
- #include <stdarg.h>
- #include <stdint.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/mman.h>
- #include <sys/stat.h>
- #include <sys/types.h>
- #include <unistd.h>
- #include "bmpblk_font.h"
- #include "image_types.h"
- #include "vboot_api.h"
- static char *progname;
- static void error(const char *fmt, ...)
- {
- va_list args;
- va_start( args, fmt );
- fprintf(stderr, "%s: ", progname);
- vfprintf( stderr, fmt, args );
- va_end( args );
- }
- #define fatal(args...) do { error(args); exit(1); } while(0)
- /* Command line options */
- enum {
- OPT_OUTFILE = 1000,
- };
- #define DEFAULT_OUTFILE "font.bin"
- static struct option long_opts[] = {
- {"outfile", 1, 0, OPT_OUTFILE },
- {NULL, 0, 0, 0}
- };
- /* Print help and return error */
- static void HelpAndDie(void) {
- fprintf(stderr,
- "\n"
- "%s - Create a vboot fontfile from a set of BMP files.\n"
- "\n"
- "Usage: %s [OPTIONS] BMPFILE [BMPFILE...]\n"
- "\n"
- "Each BMP file must match *_HEX.bmp, where HEX is the hexadecimal\n"
- "representation of the character that the file displays. The images\n"
- "will be encoded in the given order. Typically the first image is\n"
- "reused to represent any missing characters.\n"
- "\n"
- "OPTIONS are:\n"
- " --outfile <filename> Output file (default is %s)\n"
- "\n", progname, progname, DEFAULT_OUTFILE);
- exit(1);
- }
- //////////////////////////////////////////////////////////////////////////////
- // Returns pointer to buffer containing entire file, sets length.
- static void *read_entire_file(const char *filename, size_t *length) {
- int fd;
- struct stat sbuf;
- void *ptr;
- *length = 0; // just in case
- if (0 != stat(filename, &sbuf)) {
- error("Unable to stat %s: %s\n", filename, strerror(errno));
- return 0;
- }
- if (!sbuf.st_size) {
- error("File %s is empty\n", filename);
- return 0;
- }
- fd = open(filename, O_RDONLY);
- if (fd < 0) {
- error("Unable to open %s: %s\n", filename, strerror(errno));
- return 0;
- }
- ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
- if (MAP_FAILED == ptr) {
- error("Unable to mmap %s: %s\n", filename, strerror(errno));
- close(fd);
- return 0;
- }
- *length = sbuf.st_size;
- close(fd);
- return ptr;
- }
- // Reclaims buffer from read_entire_file().
- static void discard_file(void *ptr, size_t length) {
- munmap(ptr, length);
- }
- //////////////////////////////////////////////////////////////////////////////
- int main(int argc, char* argv[]) {
- char* outfile = DEFAULT_OUTFILE;
- int numimages = 0;
- int parse_error = 0;
- int i;
- FILE *ofp;
- FontArrayHeader header;
- FontArrayEntryHeader entry;
- progname = strrchr(argv[0], '/');
- if (progname)
- progname++;
- else
- progname = argv[0];
- while ((i = getopt_long(argc, argv, "", long_opts, NULL)) != -1) {
- switch (i) {
- case OPT_OUTFILE:
- outfile = optarg;
- break;
- default:
- /* Unhandled option */
- printf("Unknown option\n");
- parse_error = 1;
- break;
- }
- }
- numimages = argc - optind;
- if (parse_error || numimages < 1)
- HelpAndDie();
- printf("outfile is %s\n", outfile);
- printf("numimages is %d\n", numimages);
- ofp = fopen(outfile, "wb");
- if (!ofp)
- fatal("Unable to open %s: %s\n", outfile, strerror(errno));
- memcpy(&header.signature, FONT_SIGNATURE, FONT_SIGNATURE_SIZE);
- header.num_entries = numimages;
- if (1 != fwrite(&header, sizeof(header), 1, ofp)) {
- error("Can't write header to %s: %s\n", outfile, strerror(errno));
- goto bad1;
- }
- for(i=0; i<numimages; i++) {
- char *imgfile = argv[optind+i];
- char *s;
- uint32_t ascii;
- void *imgdata = 0;
- size_t imgsize, filesize, diff;
- s = strrchr(imgfile, '_');
- if (!s || 1 != sscanf(s, "_%x.bmp", &ascii)) { // This is not foolproof.
- error("Unable to parse the character from filename %s\n", imgfile);
- goto bad1;
- }
- imgdata = read_entire_file(imgfile, &imgsize);
- if (!imgdata)
- goto bad1;
- if (FORMAT_BMP != identify_image_type(imgdata, imgsize, &entry.info)) {
- error("%s does not contain a valid BMP image\n", imgfile);
- goto bad1;
- }
- // Pad the image to align it on a 4-byte boundary.
- filesize = imgsize;
- if (imgsize % 4)
- filesize = ((imgsize + 4) / 4) * 4;
- diff = filesize - imgsize;
- entry.ascii = ascii;
- entry.info.tag = TAG_NONE;
- entry.info.compression = COMPRESS_NONE; // we'll compress it all later
- entry.info.original_size = filesize;
- entry.info.compressed_size = filesize;
- printf("%s => 0x%x %dx%d\n", imgfile, entry.ascii,
- entry.info.width, entry.info.height);
- if (1 != fwrite(&entry, sizeof(entry), 1, ofp)) {
- error("Can't write entry to %s: %s\n", outfile, strerror(errno));
- goto bad1;
- }
- if (1 != fwrite(imgdata, imgsize, 1, ofp)) {
- error("Can't write image to %s: %s\n", outfile, strerror(errno));
- goto bad1;
- }
- if (diff && 1 != fwrite("\0\0\0\0\0\0\0\0", diff, 1, ofp)) {
- error("Can't write padding to %s: %s\n", outfile, strerror(errno));
- goto bad1;
- }
- discard_file(imgdata, imgsize);
- }
- fclose(ofp);
- return 0;
- bad1:
- fclose(ofp);
- error("Aborting\n");
- (void) unlink(outfile);
- exit(1);
- }
|