summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Richardson <wfrichar@chromium.org>2011-08-22 16:03:59 -0700
committerBill Richardson <wfrichar@chromium.org>2011-08-24 09:27:12 -0700
commit0a9977e161ce6ad6b11935dfb05ae840bf758078 (patch)
treeb3ec3bf4e7b17dad7b9c0a6ec9f8b2d1aec75fd7
parentefea801390caff45c2ef6083fde5f253f03bc395 (diff)
downloadvboot-0a9977e161ce6ad6b11935dfb05ae840bf758078.tar.gz
bmpblock v1.2 - render HWID inside vboot_reference
The vboot_api.h doesn't require the BIOS display the ASCII HWID in a graphical form (ARM U-Boot doesn't know how), so we have to do it ourselves. This change makes that possible. Summary of changes: * bmpblk_font.h defines a structure to map ASCII chars to BMPs * bmpblk_font utility generates that font structure * bmpblock format is bumped to version 1.2 - YAML file specifies font to use for $HWID - make_default_yaml updated to emit the new format - README updated to describe the difference BUG=chromium-os:18631 TEST=manual I've tested this on ARM, like so: Inside the chroot, build a U-Boot that uses it: emerge-tegra2_kaen vboot_reference vboot_reference-firmware emerge-tegra2_kaen tegra-bct tegra2-public-firmware-fdts \ chromeos-u-boot chromeos-bootimage Outside chroot, but in src/platform/vboot_reference: make <copy ./build/utility/bmpblk_font and ./build/utility/bmpblk_utility to somewhere in your $PATH> make clean cd scripts/newbitmaps/fonts bmpblk_font --outfile ../images/hwid_fonts.bin outdir/* cd scripts/newbitmaps/images make arm cd out_arm <edit DEFAULT.yaml> bmpblk_utility -z 2 -c DEFAULT.yaml arm_bmpblock.bin <use gbb_utility to replace the bitmaps in the U-Boot image, boot it> The HWID string is displayed. Change-Id: I782004a0f30c57fa1f3bb246e8c59a02c5e9f561 Reviewed-on: http://gerrit.chromium.org/gerrit/6544 Reviewed-by: Bill Richardson <wfrichar@chromium.org> Tested-by: Bill Richardson <wfrichar@chromium.org>
-rw-r--r--firmware/include/bmpblk_header.h3
-rw-r--r--firmware/lib/include/bmpblk_font.h65
-rw-r--r--firmware/lib/vboot_display.c215
-rw-r--r--scripts/newbitmaps/README25
-rwxr-xr-xscripts/newbitmaps/fonts/make_ascii_bmps.py87
-rw-r--r--scripts/newbitmaps/images/DEFAULT.yaml6
-rw-r--r--scripts/newbitmaps/images/Makefile32
-rw-r--r--scripts/newbitmaps/images/hwid_fonts.binbin0 -> 66136 bytes
-rwxr-xr-xscripts/newbitmaps/images/make_default_yaml8
-rwxr-xr-xscripts/newbitmaps/lib/bmpblock.py11
-rw-r--r--utility/Makefile13
-rw-r--r--utility/bmpblk_font.c227
-rw-r--r--utility/bmpblk_util.c33
-rw-r--r--utility/bmpblk_utility.cc105
-rw-r--r--utility/image_types.c71
-rw-r--r--utility/include/bmpblk_utility.h8
-rw-r--r--utility/include/image_types.h25
17 files changed, 798 insertions, 136 deletions
diff --git a/firmware/include/bmpblk_header.h b/firmware/include/bmpblk_header.h
index 9d42123a..c99f0fe3 100644
--- a/firmware/include/bmpblk_header.h
+++ b/firmware/include/bmpblk_header.h
@@ -54,7 +54,7 @@ __pragma(pack(push, 1)) /* Support packing for MSVC. */
#define BMPBLOCK_SIGNATURE_SIZE (4)
#define BMPBLOCK_MAJOR_VERSION (0x0001)
-#define BMPBLOCK_MINOR_VERSION (0x0001)
+#define BMPBLOCK_MINOR_VERSION (0x0002)
#define MAX_IMAGE_IN_LAYOUT (8)
@@ -118,6 +118,7 @@ typedef enum ImageTag {
typedef enum ImageFormat {
FORMAT_INVALID = 0,
FORMAT_BMP,
+ FORMAT_FONT,
} ImageFormat;
/* Constants for ImageInfo.compression */
diff --git a/firmware/lib/include/bmpblk_font.h b/firmware/lib/include/bmpblk_font.h
new file mode 100644
index 00000000..1ffaefda
--- /dev/null
+++ b/firmware/lib/include/bmpblk_font.h
@@ -0,0 +1,65 @@
+/* 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.
+ *
+ * This describes the internal format used to pack a set of character glpyhs so
+ * we can render strings by drawing one character at a time.
+ *
+ * The format is this:
+ *
+ * +-------------------------+
+ * | FontArrayHeader |
+ * +-------------------------+
+ * | FontArrayEntryHeader[0] |
+ * +-------------------------+
+ * | raw image data[0] |
+ * +-------------------------+
+ * | FontArrayEntryHeader[1] |
+ * +-------------------------+
+ * | raw image data[1] |
+ * +-------------------------+
+ * | FontArrayEntryHeader[2] |
+ * +-------------------------+
+ * | raw image data[2] |
+ * +-------------------------+
+ * ...
+ * +-------------------------+
+ * | FontArrayEntryHeader[n] |
+ * +-------------------------+
+ * | raw image data[n] |
+ * +-------------------------+
+ *
+ * The FontArrayHeader describes how many characters will be encoded.
+ * Each character encoding consists of a FontArrayEntryHeader followed
+ * immediately by the raw image data for that character.
+ */
+
+#ifndef VBOOT_REFERENCE_BMPBLK_FONT_H_
+#define VBOOT_REFERENCE_BMPBLK_FONT_H_
+
+#include "bmpblk_header.h"
+
+__pragma(pack(push, 1)) /* Support packing for MSVC. */
+
+#define FONT_SIGNATURE "FONT"
+#define FONT_SIGNATURE_SIZE 4
+
+typedef struct FontArrayHeader {
+ uint8_t signature[FONT_SIGNATURE_SIZE];
+ uint32_t num_entries; /* Number of chars encoded here. */
+} __attribute__((packed)) FontArrayHeader;
+
+typedef struct FontArrayEntryHeader {
+ uint32_t ascii; /* What to show. Could even be UTF? */
+ ImageInfo info; /* Describes the bitmap. */
+ /* The image to use follows immediately, NOT compressed. It's uncompressed
+ * because each glyph is only a few hundred bytes, but they have much in
+ * common (colormaps, for example). When we add the whole font blob to the
+ * bmpblk, it will be compressed as a single item there.
+ */
+} __attribute__((packed)) FontArrayEntryHeader;
+
+
+__pragma(pack(pop)) /* Support packing for MSVC. */
+
+#endif /* VBOOT_REFERENCE_BMPBLK_FONT_H_ */
diff --git a/firmware/lib/vboot_display.c b/firmware/lib/vboot_display.c
index 179bf7ba..9ee9419e 100644
--- a/firmware/lib/vboot_display.c
+++ b/firmware/lib/vboot_display.c
@@ -5,6 +5,7 @@
* Display functions used in kernel selection.
*/
+#include "bmpblk_font.h"
#include "gbb_header.h"
#include "utility.h"
#include "vboot_api.h"
@@ -48,21 +49,131 @@ static VbError_t VbGetLocalizationCount(VbCommonParams* cparams,
+/* Return a fixed string representing the HWID */
+static char *VbHWID(VbCommonParams* cparams) {
+ GoogleBinaryBlockHeader* gbb = (GoogleBinaryBlockHeader*)cparams->gbb_data;
+ if (0 == gbb->hwid_size ||
+ gbb->hwid_offset > cparams->gbb_size ||
+ gbb->hwid_offset + gbb->hwid_size > cparams->gbb_size) {
+ VBDEBUG(("VbHWID(): invalid hwid offset/size\n"));
+ return "{INVALID}";
+ }
+ return (char*)((uint8_t*)gbb + gbb->hwid_offset);
+}
+
+
+/* TODO: We could cache the font info to speed things up, by making the
+ * in-memory font structure distinct from the in-flash version. We'll do that
+ * Real Soon Now. Until then, we just repeat the same linear search every time.
+ */
+typedef FontArrayHeader VbFont_t;
+
+static VbFont_t *VbInternalizeFontData(FontArrayHeader *fonthdr) {
+ /* Just return the raw data pointer for now. */
+ return (VbFont_t *)fonthdr;
+}
+
+static void VbDoneWithFontForNow(VbFont_t *ptr) {
+ /* Nothing. */
+}
+
+static ImageInfo *VbFindFontGlyph(VbFont_t *font, uint32_t ascii,
+ void **bufferptr, uint32_t *buffersize) {
+ uint8_t *ptr, *firstptr;
+ uint32_t max;
+ uint32_t i;
+ FontArrayEntryHeader *entry;
+
+ ptr = (uint8_t *)font;
+ max = ((FontArrayHeader *)ptr)->num_entries;
+ ptr += sizeof(FontArrayHeader);
+ firstptr = ptr;
+
+ /* Simple linear search. */
+ for(i=0; i<max; i++)
+ {
+ entry = (FontArrayEntryHeader *)ptr;
+ if (entry->ascii == ascii) {
+ /* Note: We're assuming the glpyh is uncompressed. That's true
+ * because the bmpblk_font tool doesn't compress anything. The
+ * bmpblk_utility does, but it compresses the entire font blob at once,
+ * and we've already uncompressed that before we got here.
+ */
+ *bufferptr = ptr + sizeof(FontArrayEntryHeader);
+ *buffersize = entry->info.original_size;
+ return &(entry->info);
+ }
+ ptr += sizeof(FontArrayEntryHeader)+entry->info.compressed_size;
+ }
+
+ /* NOTE: We must return something valid. We'll just use the first glyph in the
+ * font structure (so it should be something distinct).
+ */
+ entry = (FontArrayEntryHeader *)firstptr;
+ *bufferptr = firstptr + sizeof(FontArrayEntryHeader);
+ *buffersize = entry->info.original_size;
+ return &(entry->info);
+}
+
+/* Try to display the specified text at a particular position. */
+static void VbRenderTextAtPos(char *text, int right_to_left,
+ uint32_t x, uint32_t y, VbFont_t *font) {
+ int i;
+ ImageInfo *image_info = 0;
+ void *buffer;
+ uint32_t buffersize;
+ uint32_t cur_x = x, cur_y = y;
+
+ if (!text || !font) {
+ VBDEBUG((" VbRenderTextAtPos: invalid args\n"));
+ return;
+ }
+
+ for (i=0; text[i]; i++) {
+
+ if (text[i] == '\n') {
+ if (!image_info)
+ image_info = VbFindFontGlyph(font, text[i], &buffer, &buffersize);
+ cur_x = x;
+ cur_y += image_info->height;
+ continue;
+ }
+
+ image_info = VbFindFontGlyph(font, text[i], &buffer, &buffersize);
+
+ if (right_to_left) {
+ cur_x -= image_info->width;
+ }
+
+ if (VBERROR_SUCCESS != VbExDisplayImage(cur_x, cur_y, buffer, buffersize)) {
+ VBDEBUG((" VbRenderTextAtPos: can't display ascii 0x%x\n", text[i]));
+ }
+
+ if (!right_to_left) {
+ cur_x += image_info->width;
+ }
+ }
+}
+
+
/* Display a screen from the GBB. */
VbError_t VbDisplayScreenFromGBB(VbCommonParams* cparams, uint32_t screen,
VbNvContext *vncptr) {
GoogleBinaryBlockHeader* gbb = (GoogleBinaryBlockHeader*)cparams->gbb_data;
uint8_t* bmpfv = NULL;
- uint8_t* fullimage = NULL;
+ void* fullimage = NULL;
BmpBlockHeader* hdr;
ScreenLayout* layout;
ImageInfo* image_info;
uint32_t screen_index;
uint32_t localization = 0;
- VbError_t retval = VBERROR_UNKNOWN; /* Assume error until proven ok */
+ VbError_t retval = VBERROR_UNKNOWN; /* Assume error until proven ok */
uint32_t inoutsize;
uint32_t offset;
uint32_t i;
+ VbFont_t *font;
+ char *text_to_show;
+ int rtol = 0;
/* Make sure the bitmap data is inside the GBB and is non-zero in size */
if (0 == gbb->bmpfv_size ||
@@ -93,26 +204,26 @@ VbError_t VbDisplayScreenFromGBB(VbCommonParams* cparams, uint32_t screen,
/* TODO: ensure screen IDs match indices? Having this translation
* here is awful. */
switch (screen) {
- case VB_SCREEN_DEVELOPER_WARNING:
- screen_index = 0;
- break;
- case VB_SCREEN_RECOVERY_REMOVE:
- screen_index = 1;
- break;
- case VB_SCREEN_RECOVERY_NO_GOOD:
- screen_index = 2;
- break;
- case VB_SCREEN_RECOVERY_INSERT:
- screen_index = 3;
- break;
- case VB_SCREEN_BLANK:
- case VB_SCREEN_DEVELOPER_EGG:
- default:
- /* Screens which aren't in the GBB */
- VBDEBUG(("VbDisplayScreenFromGBB(): screen %d not in the GBB\n",
- (int)screen));
- retval = VBERROR_INVALID_SCREEN_INDEX;
- goto VbDisplayScreenFromGBB_exit;
+ case VB_SCREEN_DEVELOPER_WARNING:
+ screen_index = 0;
+ break;
+ case VB_SCREEN_RECOVERY_REMOVE:
+ screen_index = 1;
+ break;
+ case VB_SCREEN_RECOVERY_NO_GOOD:
+ screen_index = 2;
+ break;
+ case VB_SCREEN_RECOVERY_INSERT:
+ screen_index = 3;
+ break;
+ case VB_SCREEN_BLANK:
+ case VB_SCREEN_DEVELOPER_EGG:
+ default:
+ /* Screens which aren't in the GBB */
+ VBDEBUG(("VbDisplayScreenFromGBB(): screen %d not in the GBB\n",
+ (int)screen));
+ retval = VBERROR_INVALID_SCREEN_INDEX;
+ goto VbDisplayScreenFromGBB_exit;
}
if (screen_index >= hdr->number_of_screenlayouts) {
VBDEBUG(("VbDisplayScreenFromGBB(): screen %d index %d not in the GBB\n",
@@ -131,10 +242,8 @@ VbError_t VbDisplayScreenFromGBB(VbCommonParams* cparams, uint32_t screen,
/* Calculate offset of screen layout = start of screen stuff +
* correct locale + correct screen. */
offset = sizeof(BmpBlockHeader) +
- localization * hdr->number_of_screenlayouts * sizeof(ScreenLayout) +
- screen_index * sizeof(ScreenLayout);
- VBDEBUG(("VbDisplayScreenFromGBB(): scr_%d_%d at offset 0x%x\n",
- localization, screen_index, offset));
+ localization * hdr->number_of_screenlayouts * sizeof(ScreenLayout) +
+ screen_index * sizeof(ScreenLayout);
layout = (ScreenLayout*)(bmpfv + offset);
/* Display all bitmaps for the image */
@@ -142,15 +251,10 @@ VbError_t VbDisplayScreenFromGBB(VbCommonParams* cparams, uint32_t screen,
if (layout->images[i].image_info_offset) {
offset = layout->images[i].image_info_offset;
image_info = (ImageInfo*)(bmpfv + offset);
- VBDEBUG(("VbDisplayScreenFromGBB: image %d: %dx%d+%d+%d %d/%d"
- "tag %d at 0x%x\n",
- i, image_info->width, image_info->height,
- layout->images[i].x, layout->images[i].y,
- image_info->compressed_size, image_info->original_size,
- image_info->tag, offset));
- if (COMPRESS_NONE != image_info->compression) {
- inoutsize = image_info->original_size;
- fullimage = (uint8_t*)VbExMalloc(inoutsize);
+ fullimage = bmpfv + offset + sizeof(ImageInfo);
+ inoutsize = image_info->original_size;
+ if (inoutsize && image_info->compression != COMPRESS_NONE) {
+ fullimage = VbExMalloc(inoutsize);
retval = VbExDecompress(bmpfv + offset + sizeof(ImageInfo),
image_info->compressed_size,
image_info->compression,
@@ -159,16 +263,45 @@ VbError_t VbDisplayScreenFromGBB(VbCommonParams* cparams, uint32_t screen,
VbExFree(fullimage);
goto VbDisplayScreenFromGBB_exit;
}
+ }
+
+ switch(image_info->format) {
+ case FORMAT_BMP:
retval = VbExDisplayImage(layout->images[i].x, layout->images[i].y,
fullimage, inoutsize);
- VbExFree(fullimage);
- } else {
- retval = VbExDisplayImage(layout->images[i].x, layout->images[i].y,
- bmpfv + offset + sizeof(ImageInfo),
- image_info->original_size);
+ break;
+
+ case FORMAT_FONT:
+ /* The uncompressed blob is our font structure. Cache it as needed. */
+ font = VbInternalizeFontData(fullimage);
+
+ /* TODO: handle text in general here */
+ if (TAG_HWID == image_info->tag || TAG_HWID_RTOL == image_info->tag) {
+ text_to_show = VbHWID(cparams);
+ rtol = (TAG_HWID_RTOL == image_info->tag);
+ } else {
+ text_to_show = "";
+ rtol = 0;
+ }
+
+ VbRenderTextAtPos(text_to_show, rtol,
+ layout->images[i].x, layout->images[i].y, font);
+
+ VbDoneWithFontForNow(font);
+ break;
+
+ default:
+ VBDEBUG(("VbDisplayScreenFromGBB(): unsupported ImageFormat %d\n",
+ image_info->format));
+ retval = VBERROR_INVALID_GBB;
}
+
+ if (COMPRESS_NONE != image_info->compression)
+ VbExFree(fullimage);
+
if (VBERROR_SUCCESS != retval)
goto VbDisplayScreenFromGBB_exit;
+
}
}
@@ -189,8 +322,6 @@ VbError_t VbDisplayScreen(VbCommonParams* cparams, uint32_t screen, int force,
VbNvContext *vncptr) {
VbError_t retval;
- VBDEBUG(("VbDisplayScreen(%d, %d)\n", (int)screen, force));
-
/* Initialize display if necessary */
if (!disp_width) {
retval = VbExDisplayInit(&disp_width, &disp_height);
diff --git a/scripts/newbitmaps/README b/scripts/newbitmaps/README
index 5a23eaf6..728d42f2 100644
--- a/scripts/newbitmaps/README
+++ b/scripts/newbitmaps/README
@@ -49,6 +49,31 @@ last-displayed locale is stored in nvram, so it's sticky across reboots. The
factory process sets the default locale to the appropriate region.
+Version 1.2. Used by any BIOS that uses "vboot_api.h"
+
+The "vboot wrapper" is a refactoring of the vboot_reference library to
+isolate our verified boot stuff from the underlying BIOS. Among other
+things, it places the burden of displaying the ASCII HWID value on the
+vboot_reference library, which means the bmpblock must contain a "font" to
+translate the ASCII characters in the HWID into graphical images. The yaml
+file must now specify a font file for the $HWID (and $HWID.rtol, if used)
+image name. For example:
+
+ bmpblock: 1.2
+ images:
+ $HWID: font.bin # THIS IS NOW REQUIRED WHEN USING $HWID
+ screens:
+ scr_0_0:
+ - [ 0, 0, $HWID]
+ localizations:
+ - [ scr_0_0, scr_0_0, scr_0_0, scr_0_0 ]
+ locale_index:
+ en
+
+The old v1.1 bmpblock will be accepted by the vboot wrapper, but a $HWID
+screen without a corresponding font will be silently ignored.
+
+
Instructions:
diff --git a/scripts/newbitmaps/fonts/make_ascii_bmps.py b/scripts/newbitmaps/fonts/make_ascii_bmps.py
new file mode 100755
index 00000000..df6083e1
--- /dev/null
+++ b/scripts/newbitmaps/fonts/make_ascii_bmps.py
@@ -0,0 +1,87 @@
+#!/usr/bin/python -tt
+# 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.
+
+import optparse
+import os
+import subprocess
+import sys
+import tempfile
+
+chars = '* 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ{}-_'
+
+def main():
+ """Convert a set of text chars into individual BMPs.
+
+ This uses ImageMagick, so don't run it inside the build chroot.
+ Not all characters in the world are supported.
+ """
+
+ parser = optparse.OptionParser()
+ parser.description = ' '.join(main.__doc__.split())
+ parser.add_option("--foreground", default='#9ccaec',
+ dest="fg", action="store", metavar="COLOR",
+ help="foreground color (%default)")
+ parser.add_option("--background", default='#607c91',
+ dest="bg", action="store", metavar="COLOR",
+ help="background color (%default)")
+ parser.add_option("--font", default='Helvetica',
+ dest="font", action="store",
+ help="font to use (%default)")
+ parser.add_option("--size", default='22', metavar="POINTSIZE",
+ dest="size", action="store",
+ help="font size (%default)")
+ parser.add_option('--dir', default='./outdir',
+ dest="outdir", action="store",
+ help="output directory (%default)")
+ (options, args) = parser.parse_args()
+
+
+ if not os.path.isdir(options.outdir):
+ os.mkdir(options.outdir)
+
+ # ARM U-Boot is very picky about its BMPs. They have to have exactly 256
+ # colors in their colormap. Imagemagick generally tries to reduce the
+ # colormap when it can, so we have to play some games to force it not to.
+ # We'll create a gradient file with 256 colors, and then make sure that all
+ # our rendered characters use the same colormap. This makes the resulting
+ # images larger, but it also means they'll work on x86 too. Sigh.
+ (handle, gradient_file) = tempfile.mkstemp(".png")
+ os.close(handle)
+
+ cmd = ('convert', '-size', '256x1',
+ 'gradient:%s-%s' % (options.fg, options.bg),
+ gradient_file)
+ print ' '.join(cmd)
+ subprocess.call(cmd)
+
+
+ count=0
+ for ascii in chars:
+ outfile = os.path.join(options.outdir,
+ "idx%03d_%x.bmp" % (count,ord(ascii)))
+ print outfile
+ cmd = ('convert',
+ '-font', options.font,
+ '-background', options.bg,
+ '-fill', options.fg,
+ '-bordercolor', options.bg,
+ '-border', '0x3',
+ '-gravity', 'Center',
+ '-pointsize', options.size,
+ 'label:%s' % ascii,
+ '-remap', gradient_file,
+ '-compress', 'none',
+ '-alpha', 'off',
+ outfile)
+ print ' '.join(cmd)
+ count += 1
+ subprocess.call(cmd)
+
+ os.unlink(gradient_file)
+
+
+# Start it all off
+if __name__ == '__main__':
+ main()
diff --git a/scripts/newbitmaps/images/DEFAULT.yaml b/scripts/newbitmaps/images/DEFAULT.yaml
index 3aa9677c..fa5269ea 100644
--- a/scripts/newbitmaps/images/DEFAULT.yaml
+++ b/scripts/newbitmaps/images/DEFAULT.yaml
@@ -1,11 +1,11 @@
-bmpblock: 1.1
+bmpblock: 1.2
compression: 1
images:
- # The HWID must change for every BOM
- # $HWID: hwid_unknown.bmp
+ # We must specify a font blob to use to render the HWID
+ $HWID: hwid_fonts.bin
# This URL never changes
url: Url.bmp
diff --git a/scripts/newbitmaps/images/Makefile b/scripts/newbitmaps/images/Makefile
index b026ef56..fe2be482 100644
--- a/scripts/newbitmaps/images/Makefile
+++ b/scripts/newbitmaps/images/Makefile
@@ -14,6 +14,7 @@ TARGETS=x86 arm
BASE_IMAGES=Devmode.bmp Insert.bmp Remove.bmp Yuck.bmp
OTHER_IMAGES=Url.bmp hwid_unknown.bmp
+FONTS=hwid_fonts.bin
default: outside_chroot
@echo "Specify a target to build for:"
@@ -36,6 +37,8 @@ ${TARGETS}:: outside_chroot
# those, so let's just assume 16:9 for future platforms to make things simpler.
_x86_max="800x600!"
_x86_scale="59%x78%"
+_arm_max="800x600!"
+_arm_scale="59%x78%"
x86::
# create output directories
@@ -43,6 +46,8 @@ x86::
for i in localized_images/*; do \
mkdir -p "out_$@/$$i"; \
done
+ # copy stuff we need
+ cp "${FONTS}" "out_$@"
# scale the background pictures exactly
for i in ${BASE_IMAGES}; do \
convert $$i -scale "${_x86_max}" "out_$@/$$i"; \
@@ -58,7 +63,32 @@ x86::
arm::
- echo "Not sure what to do here. Please fix me."
+ # create output directories
+ mkdir -p "out_$@"
+ for i in localized_images/*; do \
+ mkdir -p "out_$@/$$i"; \
+ done
+ # copy stuff we need
+ cp "${FONTS}" "out_$@"
+ convert ${BASE_IMAGES} -append \
+ -colors 256 -unique-colors "out_$@/base_cmap.png"
+ convert localized_images/*/*.bmp -append \
+ -colors 256 -unique-colors "out_$@/loc_cmap.png"
+ # scale the background pictures exactly
+ for i in ${BASE_IMAGES}; do \
+ convert $$i -scale "${_arm_max}" \
+ -remap "out_$@/base_cmap.png" "out_$@/$$i"; \
+ done
+ # scale the localized string images using percentages
+ for i in ${OTHER_IMAGES} localized_images/*/*.bmp; do \
+ convert $$i -scale "${_arm_scale}" \
+ -remap "out_$@/loc_cmap.png" "out_$@/$$i"; \
+ done
+ # produce the new yaml
+ cd "out_$@" && ../make_default_yaml
+ # Note: hand-edit the new DEFAULT.yaml to select the shipping locales,
+ # then use bmpblk_utility to create the binary.
+
clean:
diff --git a/scripts/newbitmaps/images/hwid_fonts.bin b/scripts/newbitmaps/images/hwid_fonts.bin
new file mode 100644
index 00000000..ecdfaef6
--- /dev/null
+++ b/scripts/newbitmaps/images/hwid_fonts.bin
Binary files differ
diff --git a/scripts/newbitmaps/images/make_default_yaml b/scripts/newbitmaps/images/make_default_yaml
index 93178f51..88c540e8 100755
--- a/scripts/newbitmaps/images/make_default_yaml
+++ b/scripts/newbitmaps/images/make_default_yaml
@@ -117,15 +117,15 @@ for hwid_bmp in hwid_unknown.bmp; do
echo "$yaml_file"
# List the images. The major difference is the HWID.
- cat >"$yaml_file" <<EOF1
-bmpblock: 1.1
+ cat >"$yaml_file" <<'EOF1'
+bmpblock: 1.2
compression: 1
images:
- # The HWID must change for every BOM
- # hwid: $hwid_bmp
+ # We must specify a font blob to use to render the HWID
+ $HWID: hwid_fonts.bin
# This URL never changes
url: Url.bmp
diff --git a/scripts/newbitmaps/lib/bmpblock.py b/scripts/newbitmaps/lib/bmpblock.py
index 4d588d76..539159bc 100755
--- a/scripts/newbitmaps/lib/bmpblock.py
+++ b/scripts/newbitmaps/lib/bmpblock.py
@@ -57,10 +57,13 @@ class BmpBlock(object):
# image values should all be filenames (ie, strings)
for val in images.values():
assert val and isinstance(val, types.StringTypes)
- if not "$HWID" in images:
- images["$HWID"] = os.path.join(self.libdir,'current_hwid.bmp')
- if not "$HWID.rtol" in images:
- images["$HWID.rtol"] = os.path.join(self.libdir, 'current_hwid.bmp')
+ # don't worry about fonts. eventually we'll have graphical mocks on host.
+ if "$HWID" in images:
+ print "WARNING: ignoring $HWID font blob"
+ if "$HWID.rtol" in images:
+ print "WARNING: ignoring $HWID.rtol font blob"
+ images["$HWID"] = os.path.join(self.libdir,'current_hwid.bmp')
+ images["$HWID.rtol"] = os.path.join(self.libdir, 'current_hwid.bmp')
screens = thing["screens"]
assert isinstance(screens, dict)
diff --git a/utility/Makefile b/utility/Makefile
index 88c8a5b4..b53ee572 100644
--- a/utility/Makefile
+++ b/utility/Makefile
@@ -39,7 +39,7 @@ TARGET_NAMES = crossystem \
vbutil_what_keys
ifeq ($(MINIMAL),)
-TARGET_NAMES += bmpblk_utility eficompress efidecompress
+TARGET_NAMES += bmpblk_font bmpblk_utility eficompress efidecompress
endif
TARGET_BINS = $(addprefix ${BUILD_ROOT}/,$(TARGET_NAMES))
@@ -65,6 +65,12 @@ ${BUILD_ROOT}/bmpblk_utility.o: bmpblk_utility.cc
${BUILD_ROOT}/bmpblk_util.o: bmpblk_util.c
$(CC) $(CFLAGS) -c $< -o $@
+${BUILD_ROOT}/bmpblk_font.o: bmpblk_font.c
+ $(CC) $(CFLAGS) -c $< -o $@
+
+${BUILD_ROOT}/image_types.o: image_types.c
+ $(CC) $(CFLAGS) -c $< -o $@
+
${BUILD_ROOT}/eficompress.o: eficompress.c
$(CC) $(CFLAGS) -c $< -o $@
@@ -79,10 +85,15 @@ ${BUILD_ROOT}/efidecompress: efidecompress.c
${BUILD_ROOT}/bmpblk_utility: ${BUILD_ROOT}/bmpblk_utility.o \
${BUILD_ROOT}/bmpblk_util.o \
+ ${BUILD_ROOT}/image_types.o \
${BUILD_ROOT}/eficompress.o \
${BUILD_ROOT}/efidecompress.o
$(CXX) -llzma -lyaml $(CFLAGS) $^ -o $@
+${BUILD_ROOT}/bmpblk_font: ${BUILD_ROOT}/bmpblk_font.o \
+ ${BUILD_ROOT}/image_types.o
+ $(CC) $(CFLAGS) $^ -o $@
+
# TODO: rewrite load_firmware_test to support new wrapper API
#${BUILD_ROOT}/load_firmware_test: load_firmware_test.c $(LIBS)
# $(CC) $(CFLAGS) $< -o $@ $(LIBS) -lcrypto
diff --git a/utility/bmpblk_font.c b/utility/bmpblk_font.c
new file mode 100644
index 00000000..493e87f0
--- /dev/null
+++ b/utility/bmpblk_font.c
@@ -0,0 +1,227 @@
+// 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 <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"
+
+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);
+}
diff --git a/utility/bmpblk_util.c b/utility/bmpblk_util.c
index 84a48fb1..49573af9 100644
--- a/utility/bmpblk_util.c
+++ b/utility/bmpblk_util.c
@@ -285,20 +285,23 @@ int dump_bmpblock(const char *infile, int show_as_yaml,
if (img->compressed_size) {
sprintf(image_name, "img_%08x.bmp", offset);
if (img->tag == TAG_HWID) {
- fprintf(yfp, " %s: %s # %dx%d %d/%d tag=%d\n",
+ fprintf(yfp, " %s: %s # %dx%d %d/%d tag=%d fmt=%d\n",
RENDER_HWID, image_name,
img->width, img->height,
- img->compressed_size, img->original_size, img->tag);
+ img->compressed_size, img->original_size,
+ img->tag, img->format);
} else if (img->tag == TAG_HWID_RTOL) {
- fprintf(yfp, " %s: %s # %dx%d %d/%d tag=%d\n",
+ fprintf(yfp, " %s: %s # %dx%d %d/%d tag=%d fmt=%d\n",
RENDER_HWID_RTOL, image_name,
img->width, img->height,
- img->compressed_size, img->original_size, img->tag);
+ img->compressed_size, img->original_size,
+ img->tag, img->format);
} else {
- fprintf(yfp, " img_%08x: %s # %dx%d %d/%d tag=%d\n",
+ fprintf(yfp, " img_%08x: %s # %dx%d %d/%d tag=%d fmt=%d\n",
offset, image_name,
img->width, img->height,
- img->compressed_size, img->original_size, img->tag);
+ img->compressed_size, img->original_size,
+ img->tag, img->format);
}
if (todir) {
sprintf(full_path_name, "%s/%s", todir, image_name);
@@ -388,17 +391,23 @@ int dump_bmpblock(const char *infile, int show_as_yaml,
ImageInfo *iptr =
(ImageInfo *)(ptr + scr->images[i].image_info_offset);
if (iptr->tag == TAG_HWID) {
- fprintf(yfp, " - [%d, %d, %s]\n",
+ fprintf(yfp, " - [%d, %d, %s] # tag=%d fmt=%d c=%d %d/%d\n",
scr->images[i].x, scr->images[i].y,
- RENDER_HWID);
+ RENDER_HWID, iptr->tag, iptr->format, iptr->compression,
+ iptr->compressed_size, iptr->original_size);
} else if (iptr->tag == TAG_HWID_RTOL) {
- fprintf(yfp, " - [%d, %d, %s]\n",
+ fprintf(yfp, " - [%d, %d, %s] # tag=%d fmt=%d c=%d %d/%d\n",
scr->images[i].x, scr->images[i].y,
- RENDER_HWID_RTOL);
+ RENDER_HWID_RTOL, iptr->tag,
+ iptr->format, iptr->compression,
+ iptr->compressed_size, iptr->original_size);
} else {
- fprintf(yfp, " - [%d, %d, img_%08x]\n",
+ fprintf(yfp, " - [%d, %d, img_%08x]"
+ " # tag=%d fmt=%d c=%d %d/%d\n",
scr->images[i].x, scr->images[i].y,
- scr->images[i].image_info_offset);
+ scr->images[i].image_info_offset,
+ iptr->tag, iptr->format, iptr->compression,
+ iptr->compressed_size, iptr->original_size);
}
}
}
diff --git a/utility/bmpblk_utility.cc b/utility/bmpblk_utility.cc
index f4bde7c7..2846746f 100644
--- a/utility/bmpblk_utility.cc
+++ b/utility/bmpblk_utility.cc
@@ -6,6 +6,7 @@
//
#include "bmpblk_utility.h"
+#include "image_types.h"
#include <assert.h>
#include <errno.h>
@@ -22,29 +23,6 @@ extern "C" {
}
-/* BMP header, used to validate image requirements
- * See http://en.wikipedia.org/wiki/BMP_file_format
- */
-typedef struct {
- uint8_t CharB; // must be 'B'
- uint8_t CharM; // must be 'M'
- uint32_t Size;
- uint16_t Reserved[2];
- uint32_t ImageOffset;
- uint32_t HeaderSize;
- uint32_t PixelWidth;
- uint32_t PixelHeight;
- uint16_t Planes; // Must be 1 for x86
- uint16_t BitPerPixel; // 1, 4, 8, or 24 for x86
- uint32_t CompressionType; // 0 (none) for x86, 1 (RLE) for arm
- uint32_t ImageSize;
- uint32_t XPixelsPerMeter;
- uint32_t YPixelsPerMeter;
- uint32_t NumberOfColors;
- uint32_t ImportantColors;
-} __attribute__((packed)) BMP_IMAGE_HEADER;
-
-
static void error(const char *format, ...) {
va_list ap;
va_start(ap, format);
@@ -71,6 +49,10 @@ namespace vboot_reference {
set_compression_ = false;
compression_ = COMPRESS_NONE;
debug_ = debug;
+ render_hwid_ = true;
+ support_font_ = true;
+ got_font_ = false;
+ got_rtol_font_ = false;
}
BmpBlockUtil::~BmpBlockUtil() {
@@ -125,11 +107,12 @@ namespace vboot_reference {
for (StrImageConfigMap::iterator it = config_.images_map.begin();
it != config_.images_map.end();
++it) {
- printf(" \"%s\": filename=\"%s\" offset=0x%x tag=%d\n",
+ printf(" \"%s\": filename=\"%s\" offset=0x%x tag=%d fmt=%d\n",
it->first.c_str(),
it->second.filename.c_str(),
it->second.offset,
- it->second.data.tag);
+ it->second.data.tag,
+ it->second.data.format);
}
printf("%ld screens_map\n", config_.screens_map.size());
for (StrScreenConfigMap::iterator it = config_.screens_map.begin();
@@ -206,11 +189,19 @@ namespace vboot_reference {
error("Syntax error in parsing bmpblock.\n");
}
string gotversion = (char*)event.data.scalar.value;
- if (gotversion == "1.1") {
+ if (gotversion == "1.2") {
render_hwid_ = true;
+ support_font_ = true;
+ } else if (gotversion == "1.1") {
+ minor_version_ = 1;
+ render_hwid_ = true;
+ support_font_ = false;
+ fprintf(stderr, "WARNING: using old format: %s\n", gotversion.c_str());
} else if (gotversion == "1.0") {
minor_version_ = 0;
render_hwid_ = false;
+ support_font_ = false;
+ fprintf(stderr, "WARNING: using old format: %s\n", gotversion.c_str());
} else {
error("Unsupported version specified in config file (%s)\n",
gotversion.c_str());
@@ -254,6 +245,12 @@ namespace vboot_reference {
config_.image_names.push_back(image_name);
config_.images_map[image_name] = ImageConfig();
config_.images_map[image_name].filename = image_filename;
+ if (image_name == RENDER_HWID) {
+ got_font_ = true;
+ }
+ if (image_name == RENDER_HWID_RTOL) {
+ got_rtol_font_ = true;
+ }
break;
case YAML_MAPPING_END_EVENT:
yaml_event_delete(&event);
@@ -286,17 +283,22 @@ namespace vboot_reference {
case 2:
screen.image_names[index1] = (char*)event.data.scalar.value;
// Detect the special case where we're rendering the HWID string
- // instead of displaying a bitmap. The image name shouldn't
- // exist in the list of images, but we will still need an
+ // instead of displaying a bitmap. The image name may not
+ // exist in the list of images (v1.1), but we will still need an
// ImageInfo struct to remember where to draw the text.
- // Note that if the image name DOES exist, we still will won't
- // display it (yet). Future versions may use that image to hold the
- // font glpyhs, which is why we pass it around now.
+ // Note that v1.2 requires that the image name DOES exist, because
+ // the corresponding file is used to hold the font glpyhs.
if (render_hwid_) {
if (screen.image_names[index1] == RENDER_HWID) {
config_.images_map[RENDER_HWID].data.tag = TAG_HWID;
+ if (support_font_ && !got_font_)
+ error("Font required in 'image:' section for %s\n",
+ RENDER_HWID);
} else if (screen.image_names[index1] == RENDER_HWID_RTOL) {
config_.images_map[RENDER_HWID_RTOL].data.tag = TAG_HWID_RTOL;
+ if (support_font_ && !got_rtol_font_)
+ error("Font required in 'image:' section for %s\n",
+ RENDER_HWID_RTOL);
}
}
break;
@@ -406,13 +408,10 @@ namespace vboot_reference {
const string &content = read_image_file(it->second.filename.c_str());
it->second.raw_content = content;
it->second.data.original_size = content.size();
- it->second.data.format = get_image_format(content);
- switch (it->second.data.format) {
- case FORMAT_BMP:
- it->second.data.width = get_bmp_image_width(it->second.raw_content);
- it->second.data.height = get_bmp_image_height(it->second.raw_content);
- break;
- default:
+ it->second.data.format =
+ identify_image_type(content.c_str(),
+ (uint32_t)content.size(), &it->second.data);
+ if (FORMAT_INVALID == it->second.data.format) {
error("Unsupported image format in %s\n", it->second.filename.c_str());
}
switch(compression_) {
@@ -503,31 +502,6 @@ namespace vboot_reference {
return content;
}
- ImageFormat BmpBlockUtil::get_image_format(const string content) {
- if (content.size() < sizeof(BMP_IMAGE_HEADER))
- return FORMAT_INVALID;
- const BMP_IMAGE_HEADER *hdr = (const BMP_IMAGE_HEADER *)content.c_str();
-
- if (hdr->CharB != 'B' || hdr->CharM != 'M' ||
- hdr->Planes != 1 ||
- (hdr->CompressionType != 0 && hdr->CompressionType != 1) ||
- (hdr->BitPerPixel != 1 && hdr->BitPerPixel != 4 &&
- hdr->BitPerPixel != 8 && hdr->BitPerPixel != 24))
- return FORMAT_INVALID;
-
- return FORMAT_BMP;
- }
-
- uint32_t BmpBlockUtil::get_bmp_image_width(const string content) {
- const BMP_IMAGE_HEADER *hdr = (const BMP_IMAGE_HEADER *)content.c_str();
- return hdr->PixelWidth;
- }
-
- uint32_t BmpBlockUtil::get_bmp_image_height(const string content) {
- const BMP_IMAGE_HEADER *hdr = (const BMP_IMAGE_HEADER *)content.c_str();
- return hdr->PixelHeight;
- }
-
void BmpBlockUtil::fill_bmpblock_header() {
memset(&config_.header, '\0', sizeof(config_.header));
memcpy(&config_.header.signature, BMPBLOCK_SIGNATURE,
@@ -557,11 +531,12 @@ namespace vboot_reference {
++it) {
it->second.offset = current_offset;
if (debug_)
- printf(" \"%s\": filename=\"%s\" offset=0x%x tag=%d\n",
+ printf(" \"%s\": filename=\"%s\" offset=0x%x tag=%d fmt=%d\n",
it->first.c_str(),
it->second.filename.c_str(),
it->second.offset,
- it->second.data.tag);
+ it->second.data.tag,
+ it->second.data.format);
current_offset += sizeof(ImageInfo) +
it->second.data.compressed_size;
/* Make it 4-byte aligned. */
diff --git a/utility/image_types.c b/utility/image_types.c
new file mode 100644
index 00000000..2cc27b32
--- /dev/null
+++ b/utility/image_types.c
@@ -0,0 +1,71 @@
+// Copyright (c) 2010 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 <stdint.h>
+#include <string.h>
+
+#include "bmpblk_header.h"
+#include "bmpblk_font.h"
+#include "image_types.h"
+
+/* BMP header, used to validate image requirements
+ * See http://en.wikipedia.org/wiki/BMP_file_format
+ */
+typedef struct {
+ uint8_t CharB; // must be 'B'
+ uint8_t CharM; // must be 'M'
+ uint32_t Size;
+ uint16_t Reserved[2];
+ uint32_t ImageOffset;
+ uint32_t HeaderSize;
+ uint32_t PixelWidth;
+ uint32_t PixelHeight;
+ uint16_t Planes; // Must be 1 for x86
+ uint16_t BitPerPixel; // 1, 4, 8, or 24 for x86
+ uint32_t CompressionType; // 0 (none) for x86, 1 (RLE) for arm
+ uint32_t ImageSize;
+ uint32_t XPixelsPerMeter;
+ uint32_t YPixelsPerMeter;
+ uint32_t NumberOfColors;
+ uint32_t ImportantColors;
+} __attribute__((packed)) BMP_IMAGE_HEADER;
+
+
+ImageFormat identify_image_type(const void *buf, uint32_t bufsize,
+ ImageInfo *info) {
+
+ if (info)
+ info->format = FORMAT_INVALID;
+
+ if (bufsize < sizeof(BMP_IMAGE_HEADER) &&
+ bufsize < sizeof(FontArrayHeader)) {
+ return FORMAT_INVALID;
+ }
+
+ const BMP_IMAGE_HEADER *bhdr = buf;
+ if (bhdr->CharB == 'B' && bhdr->CharM == 'M' &&
+ bhdr->Planes == 1 &&
+ (bhdr->CompressionType == 0 || bhdr->CompressionType == 1) &&
+ (bhdr->BitPerPixel == 1 || bhdr->BitPerPixel == 4 ||
+ bhdr->BitPerPixel == 8 || bhdr->BitPerPixel == 24)) {
+ if (info) {
+ info->format = FORMAT_BMP;
+ info->width = bhdr->PixelWidth;
+ info->height = bhdr->PixelHeight;
+ }
+ return FORMAT_BMP;
+ }
+
+ const FontArrayHeader *fhdr = buf;
+ if (0 == memcmp(&fhdr->signature, FONT_SIGNATURE, FONT_SIGNATURE_SIZE) &&
+ fhdr->num_entries > 0) {
+ if (info)
+ info->format = FORMAT_FONT;
+ return FORMAT_FONT;
+ }
+
+ return FORMAT_BMP;
+}
+
+
diff --git a/utility/include/bmpblk_utility.h b/utility/include/bmpblk_utility.h
index 5b70ce2d..fec2b02f 100644
--- a/utility/include/bmpblk_utility.h
+++ b/utility/include/bmpblk_utility.h
@@ -7,6 +7,8 @@
#define VBOOT_REFERENCE_BMPBLK_UTILITY_H_
#include "bmpblk_header.h"
+#include "bmpblk_font.h"
+#include "image_types.h"
#include <yaml.h>
@@ -93,9 +95,6 @@ class BmpBlockUtil {
/* Useful functions */
const string read_image_file(const char *filename);
- ImageFormat get_image_format(const string content);
- uint32_t get_bmp_image_width(const string content);
- uint32_t get_bmp_image_height(const string content);
/* Verbosity flags */
bool debug_;
@@ -106,6 +105,9 @@ class BmpBlockUtil {
/* Flags for version-specific features */
bool render_hwid_;
+ bool support_font_;
+ bool got_font_;
+ bool got_rtol_font_;
/* Internal variable for storing the config of BmpBlock. */
BmpBlockConfig config_;
diff --git a/utility/include/image_types.h b/utility/include/image_types.h
new file mode 100644
index 00000000..f85a9a98
--- /dev/null
+++ b/utility/include/image_types.h
@@ -0,0 +1,25 @@
+/* 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.
+ */
+
+#ifndef VBOOT_REFERENCE_IMAGE_TYPES_H_
+#define VBOOT_REFERENCE_IMAGE_TYPES_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <stdint.h>
+#include "bmpblk_header.h"
+
+/* Identify the data. Fill in known values if info is not NULL */
+ImageFormat identify_image_type(const void *buf, uint32_t bufsize,
+ ImageInfo *info);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* VBOOT_REFERENCE_IMAGE_TYPES_H_ */
+