mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-10 17:41:54 +00:00
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>
This commit is contained in:
@@ -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 */
|
||||
|
||||
65
firmware/lib/include/bmpblk_font.h
Normal file
65
firmware/lib/include/bmpblk_font.h
Normal file
@@ -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_ */
|
||||
@@ -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);
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
87
scripts/newbitmaps/fonts/make_ascii_bmps.py
Executable file
87
scripts/newbitmaps/fonts/make_ascii_bmps.py
Executable file
@@ -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()
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
BIN
scripts/newbitmaps/images/hwid_fonts.bin
Normal file
BIN
scripts/newbitmaps/images/hwid_fonts.bin
Normal file
Binary file not shown.
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
227
utility/bmpblk_font.c
Normal file
227
utility/bmpblk_font.c
Normal file
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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. */
|
||||
|
||||
71
utility/image_types.c
Normal file
71
utility/image_types.c
Normal file
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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_;
|
||||
|
||||
25
utility/include/image_types.h
Normal file
25
utility/include/image_types.h
Normal file
@@ -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_ */
|
||||
|
||||
Reference in New Issue
Block a user