summaryrefslogtreecommitdiff
path: root/firmware/lib/vboot_display.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/lib/vboot_display.c')
-rw-r--r--firmware/lib/vboot_display.c233
1 files changed, 162 insertions, 71 deletions
diff --git a/firmware/lib/vboot_display.c b/firmware/lib/vboot_display.c
index 910c60a0..f79dfe13 100644
--- a/firmware/lib/vboot_display.c
+++ b/firmware/lib/vboot_display.c
@@ -8,9 +8,7 @@
#include "sysincludes.h"
#include "bmpblk_font.h"
-#include "gbb_access.h"
#include "gbb_header.h"
-#include "region.h"
#include "utility.h"
#include "vboot_api.h"
#include "vboot_common.h"
@@ -22,20 +20,49 @@ static uint32_t disp_width = 0, disp_height = 0;
VbError_t VbGetLocalizationCount(VbCommonParams *cparams, uint32_t *count)
{
- BmpBlockHeader hdr;
- VbError_t ret;
+ GoogleBinaryBlockHeader *gbb =
+ (GoogleBinaryBlockHeader *)cparams->gbb_data;
+ BmpBlockHeader *hdr;
/* Default to 0 on error */
*count = 0;
- ret = VbGbbReadBmpHeader(cparams, &hdr);
- if (ret)
- return ret;
+ /* Make sure bitmap data is inside the GBB and is non-zero in size */
+ if (0 == gbb->bmpfv_size ||
+ gbb->bmpfv_offset > cparams->gbb_size ||
+ gbb->bmpfv_offset + gbb->bmpfv_size > cparams->gbb_size) {
+ return VBERROR_INVALID_GBB;
+ }
+
+ /* Sanity-check the bitmap block header */
+ hdr = (BmpBlockHeader *)(((uint8_t *)gbb) + gbb->bmpfv_offset);
+ if ((0 != Memcmp(hdr->signature, BMPBLOCK_SIGNATURE,
+ BMPBLOCK_SIGNATURE_SIZE)) ||
+ (hdr->major_version > BMPBLOCK_MAJOR_VERSION) ||
+ ((hdr->major_version == BMPBLOCK_MAJOR_VERSION) &&
+ (hdr->minor_version > BMPBLOCK_MINOR_VERSION))) {
+ return VBERROR_INVALID_BMPFV;
+ }
- *count = hdr.number_of_localizations;
+ *count = hdr->number_of_localizations;
return VBERROR_SUCCESS;
}
+const 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
@@ -137,24 +164,62 @@ void VbRenderTextAtPos(const char *text, int right_to_left,
}
}
+#define OUTBUF_LEN 128
+
VbError_t VbDisplayScreenFromGBB(VbCommonParams *cparams, uint32_t screen,
VbNvContext *vncptr)
{
- char *fullimage = NULL;
- BmpBlockHeader hdr;
+ GoogleBinaryBlockHeader *gbb =
+ (GoogleBinaryBlockHeader *)cparams->gbb_data;
+ static uint8_t *bmpfv;
+ 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 */
uint32_t inoutsize;
+ uint32_t offset;
uint32_t i;
VbFont_t *font;
const char *text_to_show;
int rtol = 0;
- VbError_t ret;
+ char outbuf[OUTBUF_LEN] = "";
+ uint32_t used = 0;
- ret = VbGbbReadBmpHeader(cparams, &hdr);
- if (ret)
- return ret;
+ /* Make sure bitmap data is inside the GBB and is non-zero in size */
+ if (0 == gbb->bmpfv_size ||
+ gbb->bmpfv_offset > cparams->gbb_size ||
+ gbb->bmpfv_offset + gbb->bmpfv_size > cparams->gbb_size) {
+ VBDEBUG(("VbDisplayScreenFromGBB(): "
+ "invalid bmpfv offset/size\n"));
+ return VBERROR_INVALID_GBB;
+ }
+
+ /* Copy bitmap data from GBB into RAM for speed */
+ if (!bmpfv) {
+#ifdef COPY_BMP_DATA
+ bmpfv = (uint8_t *)VbExMalloc(gbb->bmpfv_size);
+ Memcpy(bmpfv, ((uint8_t *)gbb) + gbb->bmpfv_offset,
+ gbb->bmpfv_size);
+#else
+ bmpfv = ((uint8_t *)gbb) + gbb->bmpfv_offset;
+#endif
+ }
+
+ /* Sanity-check the bitmap block header */
+ hdr = (BmpBlockHeader *)bmpfv;
+ if ((0 != Memcmp(hdr->signature, BMPBLOCK_SIGNATURE,
+ BMPBLOCK_SIGNATURE_SIZE)) ||
+ (hdr->major_version > BMPBLOCK_MAJOR_VERSION) ||
+ ((hdr->major_version == BMPBLOCK_MAJOR_VERSION) &&
+ (hdr->minor_version > BMPBLOCK_MINOR_VERSION))) {
+ VBDEBUG(("VbDisplayScreenFromGBB(): "
+ "invalid/too new bitmap header\n"));
+ retval = VBERROR_INVALID_BMPFV;
+ goto VbDisplayScreenFromGBB_exit;
+ }
/*
* Translate screen ID into index. Note that not all screens are in
@@ -198,7 +263,7 @@ VbError_t VbDisplayScreenFromGBB(VbCommonParams *cparams, uint32_t screen,
goto VbDisplayScreenFromGBB_exit;
}
- if (screen_index >= hdr.number_of_screenlayouts) {
+ if (screen_index >= hdr->number_of_screenlayouts) {
VBDEBUG(("VbDisplayScreenFromGBB(): "
"screen %d index %d not in the GBB\n",
(int)screen, (int)screen_index));
@@ -208,31 +273,48 @@ VbError_t VbDisplayScreenFromGBB(VbCommonParams *cparams, uint32_t screen,
/* Clip localization to number of localizations present in the GBB */
VbNvGet(vncptr, VBNV_LOCALIZATION_INDEX, &localization);
- if (localization >= hdr.number_of_localizations) {
+ if (localization >= hdr->number_of_localizations) {
localization = 0;
VbNvSet(vncptr, VBNV_LOCALIZATION_INDEX, localization);
}
+ /*
+ * 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);
+ layout = (ScreenLayout *)(bmpfv + offset);
+
/* Display all bitmaps for the image */
for (i = 0; i < MAX_IMAGE_IN_LAYOUT; i++) {
- ScreenLayout layout;
- ImageInfo image_info;
- char hwid[256];
-
- ret = VbGbbReadImage(cparams, localization, screen_index,
- i, &layout, &image_info,
- &fullimage, &inoutsize);
- if (ret == VBERROR_NO_IMAGE_PRESENT) {
+ if (!layout->images[i].image_info_offset)
continue;
- } else if (ret) {
- retval = ret;
- goto VbDisplayScreenFromGBB_exit;
+
+ offset = layout->images[i].image_info_offset;
+ image_info = (ImageInfo *)(bmpfv + offset);
+ 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,
+ fullimage, &inoutsize);
+ if (VBERROR_SUCCESS != retval) {
+ VbExFree(fullimage);
+ goto VbDisplayScreenFromGBB_exit;
+ }
}
- switch(image_info.format) {
+ switch(image_info->format) {
case FORMAT_BMP:
- retval = VbExDisplayImage(layout.images[i].x,
- layout.images[i].y,
+ retval = VbExDisplayImage(layout->images[i].x,
+ layout->images[i].y,
fullimage, inoutsize);
break;
@@ -241,23 +323,21 @@ VbError_t VbDisplayScreenFromGBB(VbCommonParams *cparams, uint32_t screen,
* The uncompressed blob is our font structure. Cache
* it as needed.
*/
- font = VbInternalizeFontData(
- (FontArrayHeader *)fullimage);
+ font = VbInternalizeFontData(fullimage);
/* TODO: handle text in general here */
- if (TAG_HWID == image_info.tag ||
- TAG_HWID_RTOL == image_info.tag) {
- VbRegionReadHWID(cparams, hwid, sizeof(hwid));
- text_to_show = hwid;
- rtol = (TAG_HWID_RTOL == image_info.tag);
+ 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);
+ layout->images[i].x,
+ layout->images[i].y, font);
VbDoneWithFontForNow(font);
break;
@@ -265,11 +345,12 @@ VbError_t VbDisplayScreenFromGBB(VbCommonParams *cparams, uint32_t screen,
default:
VBDEBUG(("VbDisplayScreenFromGBB(): "
"unsupported ImageFormat %d\n",
- image_info.format));
+ image_info->format));
retval = VBERROR_INVALID_GBB;
}
- VbExFree(fullimage);
+ if (COMPRESS_NONE != image_info->compression)
+ VbExFree(fullimage);
if (VBERROR_SUCCESS != retval)
goto VbDisplayScreenFromGBB_exit;
@@ -278,15 +359,29 @@ VbError_t VbDisplayScreenFromGBB(VbCommonParams *cparams, uint32_t screen,
/* Successful if all bitmaps displayed */
retval = VBERROR_SUCCESS;
- VbRegionCheckVersion(cparams);
+ /*
+ * If GBB flags is nonzero, complain because that's something that the
+ * factory MUST fix before shipping. We only have to do this here,
+ * because it's obvious that something is wrong if we're not displaying
+ * screens from the GBB.
+ */
+ if (gbb->major_version == GBB_MAJOR_VER && gbb->minor_version >= 1 &&
+ (gbb->flags != 0)) {
+ used += StrnAppend(outbuf + used, "gbb.flags is nonzero: 0x",
+ OUTBUF_LEN - used);
+ used += Uint64ToString(outbuf + used, OUTBUF_LEN - used,
+ gbb->flags, 16, 8);
+ used += StrnAppend(outbuf + used, "\n", OUTBUF_LEN - used);
+ (void)VbExDisplayDebugInfo(outbuf);
+ }
VbDisplayScreenFromGBB_exit:
VBDEBUG(("leaving VbDisplayScreenFromGBB() with %d\n",retval));
return retval;
}
-VbError_t VbDisplayScreen(VbCommonParams *cparams, uint32_t screen,
- int force, VbNvContext *vncptr)
+VbError_t VbDisplayScreen(VbCommonParams *cparams, uint32_t screen, int force,
+ VbNvContext *vncptr)
{
VbError_t retval;
@@ -308,8 +403,7 @@ VbError_t VbDisplayScreen(VbCommonParams *cparams, uint32_t screen,
disp_current_screen = screen;
/* Look in the GBB first */
- if (VBERROR_SUCCESS == VbDisplayScreenFromGBB(cparams, screen,
- vncptr))
+ if (VBERROR_SUCCESS == VbDisplayScreenFromGBB(cparams, screen, vncptr))
return VBERROR_SUCCESS;
/* If screen wasn't in the GBB bitmaps, fall back to a default */
@@ -477,22 +571,29 @@ VbError_t VbDisplayDebugInfo(VbCommonParams *cparams, VbNvContext *vncptr)
{
VbSharedDataHeader *shared =
(VbSharedDataHeader *)cparams->shared_data_blob;
- GoogleBinaryBlockHeader *gbb = cparams->gbb;
+ GoogleBinaryBlockHeader *gbb =
+ (GoogleBinaryBlockHeader *)cparams->gbb_data;
char buf[DEBUG_INFO_SIZE] = "";
char sha1sum[SHA1_DIGEST_SIZE * 2 + 1];
- char hwid[256];
uint32_t used = 0;
- VbPublicKey *key;
- VbError_t ret;
uint32_t i;
/* Redisplay current screen to overwrite any previous debug output */
VbDisplayScreen(cparams, disp_current_screen, 1, vncptr);
/* Add hardware ID */
- VbRegionReadHWID(cparams, hwid, sizeof(hwid));
used += StrnAppend(buf + used, "HWID: ", DEBUG_INFO_SIZE - used);
- used += StrnAppend(buf + used, hwid, DEBUG_INFO_SIZE - used);
+ if (0 == gbb->hwid_size ||
+ gbb->hwid_offset > cparams->gbb_size ||
+ gbb->hwid_offset + gbb->hwid_size > cparams->gbb_size) {
+ VBDEBUG(("VbDisplayDebugInfo(): invalid hwid offset/size\n"));
+ used += StrnAppend(buf + used,
+ "(INVALID)", DEBUG_INFO_SIZE - used);
+ } else {
+ used += StrnAppend(buf + used,
+ (char *)((uint8_t *)gbb + gbb->hwid_offset),
+ DEBUG_INFO_SIZE - used);
+ }
/* Add recovery reason */
used += StrnAppend(buf + used,
@@ -553,25 +654,15 @@ VbError_t VbDisplayDebugInfo(VbCommonParams *cparams, VbNvContext *vncptr)
}
/* Add sha1sum for Root & Recovery keys */
- ret = VbGbbReadRootKey(cparams, &key);
- if (!ret) {
- FillInSha1Sum(sha1sum, key);
- VbExFree(key);
- used += StrnAppend(buf + used, "\ngbb.rootkey: ",
- DEBUG_INFO_SIZE - used);
- used += StrnAppend(buf + used, sha1sum,
- DEBUG_INFO_SIZE - used);
- }
-
- ret = VbGbbReadRecoveryKey(cparams, &key);
- if (!ret) {
- FillInSha1Sum(sha1sum, key);
- VbExFree(key);
- used += StrnAppend(buf + used, "\ngbb.recovery_key: ",
- DEBUG_INFO_SIZE - used);
- used += StrnAppend(buf + used, sha1sum,
- DEBUG_INFO_SIZE - used);
- }
+ FillInSha1Sum(sha1sum,
+ (VbPublicKey *)((uint8_t *)gbb + gbb->rootkey_offset));
+ used += StrnAppend(buf + used, "\ngbb.rootkey: ", DEBUG_INFO_SIZE - used);
+ used += StrnAppend(buf + used, sha1sum, DEBUG_INFO_SIZE - used);
+ FillInSha1Sum(sha1sum,
+ (VbPublicKey *)((uint8_t *)gbb + gbb->recovery_key_offset));
+ used += StrnAppend(buf + used,
+ "\ngbb.recovery_key: ", DEBUG_INFO_SIZE - used);
+ used += StrnAppend(buf + used, sha1sum, DEBUG_INFO_SIZE - used);
/* If we're in dev-mode, show the kernel subkey that we expect, too. */
if (0 == shared->recovery_reason) {