vboot_display.c revision fe510c06204c763e61aa36d2263c3b8b79c79879
10bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
2822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson * Use of this source code is governed by a BSD-style license that can be
3822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson * found in the LICENSE file.
4822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson *
5822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson * Display functions used in kernel selection.
6822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson */
7822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson
80a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson#include "bmpblk_font.h"
9822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson#include "gbb_header.h"
10822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson#include "utility.h"
11822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson#include "vboot_api.h"
12822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson#include "vboot_common.h"
13822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson#include "vboot_display.h"
14822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson#include "vboot_nvstorage.h"
15822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson
16822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardsonstatic uint32_t disp_current_screen = VB_SCREEN_BLANK;
17822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardsonstatic uint32_t disp_width = 0, disp_height = 0;
18822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson
190bf6405a4b4ac1ce569363a45812767777e0f4ebRandall SpanglerVbError_t VbGetLocalizationCount(VbCommonParams *cparams, uint32_t *count)
200bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler{
210bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	GoogleBinaryBlockHeader *gbb =
220bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		(GoogleBinaryBlockHeader *)cparams->gbb_data;
230bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	BmpBlockHeader *hdr;
240bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
250bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Default to 0 on error */
260bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	*count = 0;
270bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
280bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Make sure bitmap data is inside the GBB and is non-zero in size */
290bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	if (0 == gbb->bmpfv_size ||
300bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	    gbb->bmpfv_offset > cparams->gbb_size ||
310bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	    gbb->bmpfv_offset + gbb->bmpfv_size > cparams->gbb_size) {
320bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return VBERROR_INVALID_GBB;
330bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
340bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
350bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Sanity-check the bitmap block header */
360bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	hdr = (BmpBlockHeader *)(((uint8_t *)gbb) + gbb->bmpfv_offset);
370bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	if ((0 != Memcmp(hdr->signature, BMPBLOCK_SIGNATURE,
380bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			 BMPBLOCK_SIGNATURE_SIZE)) ||
390bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	    (hdr->major_version > BMPBLOCK_MAJOR_VERSION) ||
400bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	    ((hdr->major_version == BMPBLOCK_MAJOR_VERSION) &&
410bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	     (hdr->minor_version > BMPBLOCK_MINOR_VERSION))) {
420bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return VBERROR_INVALID_BMPFV;
430bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
440bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
450bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	*count = hdr->number_of_localizations;
460bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	return VBERROR_SUCCESS;
470bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler}
48822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson
490bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spanglerchar *VbHWID(VbCommonParams *cparams)
500bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler{
510bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	GoogleBinaryBlockHeader *gbb =
520bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		(GoogleBinaryBlockHeader *)cparams->gbb_data;
53822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson
540bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	if (0 == gbb->hwid_size ||
550bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	    gbb->hwid_offset > cparams->gbb_size ||
560bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	    gbb->hwid_offset + gbb->hwid_size > cparams->gbb_size) {
570bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		VBDEBUG(("VbHWID(): invalid hwid offset/size\n"));
580bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "{INVALID}";
590bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
60822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson
610bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	return (char *)((uint8_t *)gbb + gbb->hwid_offset);
620a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson}
630a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson
640bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler/*
650bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler * TODO: We could cache the font info to speed things up, by making the
660a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson * in-memory font structure distinct from the in-flash version.  We'll do that
670a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson * Real Soon Now. Until then, we just repeat the same linear search every time.
680a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson */
690a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardsontypedef FontArrayHeader VbFont_t;
700a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson
71fe510c06204c763e61aa36d2263c3b8b79c79879Randall SpanglerVbFont_t *VbInternalizeFontData(FontArrayHeader *fonthdr)
720bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler{
730bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Just return the raw data pointer for now. */
740bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	return (VbFont_t *)fonthdr;
750a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson}
760a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson
77fe510c06204c763e61aa36d2263c3b8b79c79879Randall Spanglervoid VbDoneWithFontForNow(VbFont_t *ptr)
780bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler{
790bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Nothing. */
800a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson}
810a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson
82fe510c06204c763e61aa36d2263c3b8b79c79879Randall SpanglerImageInfo *VbFindFontGlyph(VbFont_t *font, uint32_t ascii,
83fe510c06204c763e61aa36d2263c3b8b79c79879Randall Spangler			   void **bufferptr, uint32_t *buffersize)
840bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler{
850bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	uint8_t *ptr, *firstptr;
860bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	uint32_t max;
870bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	uint32_t i;
880bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	FontArrayEntryHeader *entry;
890bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
900bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	ptr = (uint8_t *)font;
910bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	max = ((FontArrayHeader *)ptr)->num_entries;
920bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	ptr += sizeof(FontArrayHeader);
930bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	firstptr = ptr;
940bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
950bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/*
960bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 * Simple linear search.
970bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 *
980bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 * Note: We're assuming glpyhs are uncompressed. That's true because
990bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 * the bmpblk_font tool doesn't compress anything. The bmpblk_utility
1000bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 * does, but it compresses the entire font blob at once, and we've
1010bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 * already uncompressed that before we got here.
1020bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 */
1030bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	for(i=0; i<max; i++) {
1040bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		entry = (FontArrayEntryHeader *)ptr;
1050bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		if (entry->ascii == ascii) {
1060bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			*bufferptr = ptr + sizeof(FontArrayEntryHeader);
1070bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			*buffersize = entry->info.original_size;
1080bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			return &(entry->info);
1090bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		}
1100bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		ptr += sizeof(FontArrayEntryHeader)+entry->info.compressed_size;
1110bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
1120bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
1130bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/*
1140bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 * We must return something valid. We'll just use the first glyph in
1150bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 * the font structure (so it should be something distinct).
1160bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 */
1170bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	entry = (FontArrayEntryHeader *)firstptr;
1180bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	*bufferptr = firstptr + sizeof(FontArrayEntryHeader);
1190bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	*buffersize = entry->info.original_size;
1200bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	return &(entry->info);
1210a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson}
1220a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson
123fe510c06204c763e61aa36d2263c3b8b79c79879Randall Spanglervoid VbRenderTextAtPos(char *text, int right_to_left,
124fe510c06204c763e61aa36d2263c3b8b79c79879Randall Spangler		       uint32_t x, uint32_t y, VbFont_t *font)
1250bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler{
1260bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	int i;
1270bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	ImageInfo *image_info = 0;
1280bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	void *buffer;
1290bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	uint32_t buffersize;
1300bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	uint32_t cur_x = x, cur_y = y;
1310bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
1320bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	if (!text || !font) {
1330bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		VBDEBUG(("  VbRenderTextAtPos: invalid args\n"));
1340bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return;
1350bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
1360bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
1370bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	for (i=0; text[i]; i++) {
1380bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
1390bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		if (text[i] == '\n') {
1400bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			if (!image_info)
1410bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler				image_info = VbFindFontGlyph(font, text[i],
1420bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler							     &buffer,
1430bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler							     &buffersize);
1440bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			cur_x = x;
1450bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			cur_y += image_info->height;
1460bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			continue;
1470bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		}
1480bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
1490bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		image_info = VbFindFontGlyph(font, text[i], &buffer,
1500bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler					     &buffersize);
1510bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
1520bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		if (right_to_left)
1530bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			cur_x -= image_info->width;
1540bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
1550bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		if (VBERROR_SUCCESS != VbExDisplayImage(cur_x, cur_y, buffer,
1560bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler							buffersize)) {
1570bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			VBDEBUG(("  VbRenderTextAtPos: "
1580bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler				 "can't display ascii 0x%x\n", text[i]));
1590bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		}
1600bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
1610bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		if (!right_to_left)
1620bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			cur_x += image_info->width;
1630bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
1640a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson}
1650a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson
166f2ad05f59ef644af8d6d28d002f89f6c88cde27fBill Richardson#define OUTBUF_LEN 128
167822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson
1680bf6405a4b4ac1ce569363a45812767777e0f4ebRandall SpanglerVbError_t VbDisplayScreenFromGBB(VbCommonParams *cparams, uint32_t screen,
1690bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler                                 VbNvContext *vncptr)
1700bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler{
1710bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	GoogleBinaryBlockHeader *gbb =
1720bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		(GoogleBinaryBlockHeader *)cparams->gbb_data;
1730bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	static uint8_t *bmpfv;
1740bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	void *fullimage = NULL;
1750bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	BmpBlockHeader *hdr;
1760bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	ScreenLayout *layout;
1770bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	ImageInfo *image_info;
1780bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	uint32_t screen_index;
1790bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	uint32_t localization = 0;
1800bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	VbError_t retval = VBERROR_UNKNOWN;   /* Assume error until proven ok */
1810bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	uint32_t inoutsize;
1820bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	uint32_t offset;
1830bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	uint32_t i;
1840bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	VbFont_t *font;
1850bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	char *text_to_show;
1860bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	int rtol = 0;
1870bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	char outbuf[OUTBUF_LEN] = "";
1880bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	uint32_t used = 0;
1890bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
1900bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Make sure bitmap data is inside the GBB and is non-zero in size */
1910bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	if (0 == gbb->bmpfv_size ||
1920bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	    gbb->bmpfv_offset > cparams->gbb_size ||
1930bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	    gbb->bmpfv_offset + gbb->bmpfv_size > cparams->gbb_size) {
1940bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		VBDEBUG(("VbDisplayScreenFromGBB(): "
1950bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			 "invalid bmpfv offset/size\n"));
1960bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return VBERROR_INVALID_GBB;
1970bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
1980bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
1990bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Copy bitmap data from GBB into RAM for speed */
2000bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	if (!bmpfv) {
201c92c81ecf517536d29da3cc75e4ea4d922cb28e2Simon Glass#ifdef COPY_BMP_DATA
2020bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		bmpfv = (uint8_t *)VbExMalloc(gbb->bmpfv_size);
2030bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		Memcpy(bmpfv, ((uint8_t *)gbb) + gbb->bmpfv_offset,
2040bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		       gbb->bmpfv_size);
205c92c81ecf517536d29da3cc75e4ea4d922cb28e2Simon Glass#else
2060bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		bmpfv = ((uint8_t *)gbb) + gbb->bmpfv_offset;
207c92c81ecf517536d29da3cc75e4ea4d922cb28e2Simon Glass#endif
2080bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
2090bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
2100bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Sanity-check the bitmap block header */
2110bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	hdr = (BmpBlockHeader *)bmpfv;
2120bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	if ((0 != Memcmp(hdr->signature, BMPBLOCK_SIGNATURE,
2130bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			 BMPBLOCK_SIGNATURE_SIZE)) ||
2140bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	    (hdr->major_version > BMPBLOCK_MAJOR_VERSION) ||
2150bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	    ((hdr->major_version == BMPBLOCK_MAJOR_VERSION) &&
2160bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	     (hdr->minor_version > BMPBLOCK_MINOR_VERSION))) {
2170bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		VBDEBUG(("VbDisplayScreenFromGBB(): "
2180bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			 "invalid/too new bitmap header\n"));
2190bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		retval = VBERROR_INVALID_BMPFV;
2200bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		goto VbDisplayScreenFromGBB_exit;
2210bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
2220bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
2230bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/*
2240bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 * Translate screen ID into index.  Note that not all screens are in
2250bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 * the GBB.
2260bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 *
2270bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 * TODO: ensure screen IDs match indices?  Having this translation here
2280bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 * is awful.
2290bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 */
2300bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	switch (screen) {
2310bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VB_SCREEN_DEVELOPER_WARNING:
2320bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		screen_index = SCREEN_DEVELOPER_WARNING;
2330bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		break;
2340bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VB_SCREEN_RECOVERY_REMOVE:
2350bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		screen_index = SCREEN_RECOVERY_REMOVE;
2360bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		break;
2370bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VB_SCREEN_RECOVERY_NO_GOOD:
2380bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		screen_index = SCREEN_RECOVERY_NO_GOOD;
2390bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		break;
2400bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VB_SCREEN_RECOVERY_INSERT:
2410bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		screen_index = SCREEN_RECOVERY_INSERT;
2420bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		break;
2430bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VB_SCREEN_RECOVERY_TO_DEV:
2440bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		screen_index = SCREEN_RECOVERY_TO_DEV;
2450bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		break;
2460bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VB_SCREEN_DEVELOPER_TO_NORM:
2470bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		screen_index = SCREEN_DEVELOPER_TO_NORM;
2480bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		break;
2490bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VB_SCREEN_WAIT:
2500bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		screen_index = SCREEN_WAIT;
2510bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		break;
2520bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VB_SCREEN_TO_NORM_CONFIRMED:
2530bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		screen_index = SCREEN_TO_NORM_CONFIRMED;
2540bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		break;
2550bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VB_SCREEN_BLANK:
2560bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VB_SCREEN_DEVELOPER_EGG:
2570bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	default:
2580bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		/* Screens which aren't in the GBB */
2590bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		VBDEBUG(("VbDisplayScreenFromGBB(): screen %d not in the GBB\n",
2600bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			 (int)screen));
2610bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		retval = VBERROR_INVALID_SCREEN_INDEX;
2620bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		goto VbDisplayScreenFromGBB_exit;
2630bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
2640bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
2650bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	if (screen_index >= hdr->number_of_screenlayouts) {
2660bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		VBDEBUG(("VbDisplayScreenFromGBB(): "
2670bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			 "screen %d index %d not in the GBB\n",
2680bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			 (int)screen, (int)screen_index));
2690bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		retval = VBERROR_INVALID_SCREEN_INDEX;
2700bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		goto VbDisplayScreenFromGBB_exit;
2710bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
2720bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
2730bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Clip localization to number of localizations present in the GBB */
2740bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	VbNvGet(vncptr, VBNV_LOCALIZATION_INDEX, &localization);
2750bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	if (localization >= hdr->number_of_localizations) {
2760bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		localization = 0;
2770bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		VbNvSet(vncptr, VBNV_LOCALIZATION_INDEX, localization);
2780bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
2790bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
2800bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/*
2810bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 * Calculate offset of screen layout = start of screen stuff + correct
2820bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 * locale + correct screen.
2830bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 */
2840bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	offset = sizeof(BmpBlockHeader) +
2850bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		localization * hdr->number_of_screenlayouts *
2860bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			sizeof(ScreenLayout) +
2870bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		screen_index * sizeof(ScreenLayout);
2880bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	layout = (ScreenLayout *)(bmpfv + offset);
2890bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
2900bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Display all bitmaps for the image */
2910bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	for (i = 0; i < MAX_IMAGE_IN_LAYOUT; i++) {
2920bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		if (!layout->images[i].image_info_offset)
2930bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			continue;
2940bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
2950bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		offset = layout->images[i].image_info_offset;
2960bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		image_info = (ImageInfo *)(bmpfv + offset);
2970bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		fullimage = bmpfv + offset + sizeof(ImageInfo);
2980bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		inoutsize = image_info->original_size;
2990bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		if (inoutsize &&
3000bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		    image_info->compression != COMPRESS_NONE) {
3010bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			fullimage = VbExMalloc(inoutsize);
3020bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			retval = VbExDecompress(
3030bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler					bmpfv + offset + sizeof(ImageInfo),
3040bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler					image_info->compressed_size,
3050bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler					image_info->compression,
3060bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler					fullimage, &inoutsize);
3070bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			if (VBERROR_SUCCESS != retval) {
3080bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler				VbExFree(fullimage);
3090bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler				goto VbDisplayScreenFromGBB_exit;
3100bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			}
3110bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		}
3120bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
3130bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		switch(image_info->format) {
3140bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		case FORMAT_BMP:
3150bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			retval = VbExDisplayImage(layout->images[i].x,
3160bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler						  layout->images[i].y,
3170bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler						  fullimage, inoutsize);
3180bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			break;
3190bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
3200bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		case FORMAT_FONT:
3210bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			/*
3220bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			 * The uncompressed blob is our font structure. Cache
3230bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			 * it as needed.
3240bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			 */
3250bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			font = VbInternalizeFontData(fullimage);
3260bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
3270bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			/* TODO: handle text in general here */
3280bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			if (TAG_HWID == image_info->tag ||
3290bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			    TAG_HWID_RTOL == image_info->tag) {
3300bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler				text_to_show = VbHWID(cparams);
3310bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler				rtol = (TAG_HWID_RTOL == image_info->tag);
3320bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			} else {
3330bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler				text_to_show = "";
3340bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler				rtol = 0;
3350bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			}
3360bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
3370bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			VbRenderTextAtPos(text_to_show, rtol,
3380bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler					  layout->images[i].x,
3390bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler					  layout->images[i].y, font);
3400bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
3410bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			VbDoneWithFontForNow(font);
3420bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			break;
3430bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
3440bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		default:
3450bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			VBDEBUG(("VbDisplayScreenFromGBB(): "
3460bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler				 "unsupported ImageFormat %d\n",
3470bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler				 image_info->format));
3480bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			retval = VBERROR_INVALID_GBB;
3490bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		}
3500bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
3510bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		if (COMPRESS_NONE != image_info->compression)
3520bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			VbExFree(fullimage);
3530bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
3540bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		if (VBERROR_SUCCESS != retval)
3550bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			goto VbDisplayScreenFromGBB_exit;
3560bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
3570bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
3580bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Successful if all bitmaps displayed */
3590bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	retval = VBERROR_SUCCESS;
3600bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
3610bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/*
3620bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 * If GBB flags is nonzero, complain because that's something that the
3630bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 * factory MUST fix before shipping. We only have to do this here,
3640bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 * because it's obvious that something is wrong if we're not displaying
3650bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 * screens from the GBB.
3660bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 */
3670bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	if (gbb->major_version == GBB_MAJOR_VER && gbb->minor_version >= 1 &&
3680bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	    (gbb->flags != 0)) {
3690bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		used += Strncat(outbuf + used, "gbb.flags is nonzero: 0x",
3700bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler				OUTBUF_LEN - used);
3710bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		used += Uint64ToString(outbuf + used, OUTBUF_LEN - used,
3720bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler				       gbb->flags, 16, 8);
3730bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		used += Strncat(outbuf + used, "\n", OUTBUF_LEN - used);
3740bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		(void)VbExDisplayDebugInfo(outbuf);
3750bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
3760bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
3770bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler VbDisplayScreenFromGBB_exit:
3780bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	VBDEBUG(("leaving VbDisplayScreenFromGBB() with %d\n",retval));
3790bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	return retval;
380822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson}
381822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson
3820bf6405a4b4ac1ce569363a45812767777e0f4ebRandall SpanglerVbError_t VbDisplayScreen(VbCommonParams *cparams, uint32_t screen, int force,
3830bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler                          VbNvContext *vncptr)
3840bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler{
3850bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	VbError_t retval;
386822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson
3870bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Initialize display if necessary */
3880bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	if (!disp_width) {
3890bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		retval = VbExDisplayInit(&disp_width, &disp_height);
3900bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		if (VBERROR_SUCCESS != retval)
3910bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			return retval;
3920bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
393822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson
3940bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* If requested screen is the same as the current one, we're done. */
3950bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	if (disp_current_screen == screen && 0 == force)
3960bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return VBERROR_SUCCESS;
397822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson
3980bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* If the screen is blank, turn off the backlight; else turn it on. */
3990bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	VbExDisplayBacklight(VB_SCREEN_BLANK == screen ? 0 : 1);
400822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson
4010bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Request the screen */
4020bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	disp_current_screen = screen;
403822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson
4040bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Look in the GBB first */
4050bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	if (VBERROR_SUCCESS == VbDisplayScreenFromGBB(cparams, screen, vncptr))
4060bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return VBERROR_SUCCESS;
407822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson
4080bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* If screen wasn't in the GBB bitmaps, fall back to a default */
4090bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	return VbExDisplayScreen(screen);
410822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson}
411822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson
4120bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spanglerstatic void Uint8ToString(char *buf, uint8_t val)
4130bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler{
4140bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	const char *trans = "0123456789abcdef";
4150bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	*buf++ = trans[val >> 4];
4160bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	*buf = trans[val & 0xF];
4175de6b40ca74f4a6724941068a15bb0cf261a2d01Bill Richardson}
4185de6b40ca74f4a6724941068a15bb0cf261a2d01Bill Richardson
4190bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spanglerstatic void FillInSha1Sum(char *outbuf, VbPublicKey *key)
4200bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler{
4210bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	uint8_t *buf = ((uint8_t *)key) + key->key_offset;
4220bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	uint64_t buflen = key->key_size;
4230bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	uint8_t *digest = DigestBuf(buf, buflen, SHA1_DIGEST_ALGORITHM);
4240bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	int i;
4250bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	for (i = 0; i < SHA1_DIGEST_SIZE; i++) {
4260bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		Uint8ToString(outbuf, digest[i]);
4270bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		outbuf += 2;
4280bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
4290bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	*outbuf = '\0';
4300bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	VbExFree(digest);
4315de6b40ca74f4a6724941068a15bb0cf261a2d01Bill Richardson}
4325de6b40ca74f4a6724941068a15bb0cf261a2d01Bill Richardson
4330bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spanglerconst char *RecoveryReasonString(uint8_t code)
4340bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler{
4350bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	switch(code) {
4360bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_NOT_REQUESTED:
4370bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "Recovery not requested";
4380bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_LEGACY:
4390bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "Recovery requested from legacy utility";
4400bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_MANUAL:
4410bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "recovery button pressed";
4420bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_INVALID_RW:
4430bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "RW firmware failed signature check";
4440bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_S3_RESUME:
4450bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "S3 resume failed";
4460bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_DEP_RO_TPM_ERROR:
4470bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "TPM error in read-only firmware";
4480bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_SHARED_DATA:
4490bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "Shared data error in read-only firmware";
4500bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_TEST_S3:
4510bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "Test error from S3Resume()";
4520bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_TEST_LFS:
4530bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "Test error from LoadFirmwareSetup()";
4540bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_TEST_LF:
4550bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "Test error from LoadFirmware()";
4560bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + VBSD_LF_CHECK_NOT_DONE:
4570bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "RW firmware check not done";
4580bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + VBSD_LF_CHECK_DEV_MISMATCH:
4590bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	  return "RW firmware developer flag mismatch";
4600bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + VBSD_LF_CHECK_REC_MISMATCH:
4610bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "RW firmware recovery flag mismatch";
4620bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN +
4630bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		VBSD_LF_CHECK_VERIFY_KEYBLOCK:
4640bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "RW firmware unable to verify key block";
4650bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + VBSD_LF_CHECK_KEY_ROLLBACK:
4660bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "RW firmware key version rollback detected";
4670bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN +
4680bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		VBSD_LF_CHECK_DATA_KEY_PARSE:
4690bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "RW firmware unable to parse data key";
4700bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN +
4710bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		VBSD_LF_CHECK_VERIFY_PREAMBLE:
4720bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "RW firmware unable to verify preamble";
4730bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + VBSD_LF_CHECK_FW_ROLLBACK:
4740bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "RW firmware version rollback detected";
4750bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + VBSD_LF_CHECK_GET_FW_BODY:
4760bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "RW firmware unable to get firmware body";
4770bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN +
4780bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		VBSD_LF_CHECK_HASH_WRONG_SIZE:
4790bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "RW firmware hash is wrong size";
4800bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + VBSD_LF_CHECK_VERIFY_BODY:
4810bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "RW firmware unable to verify firmware body";
4820bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + VBSD_LF_CHECK_NO_RO_NORMAL:
4830bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "RW firmware read-only normal path is not supported";
4840bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_FIRMWARE:
4850bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "Firmware problem outside of verified boot";
4860bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_TPM_REBOOT:
4870bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "TPM requires a system reboot (should be transient)";
4880bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_EC_SOFTWARE_SYNC:
4890bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "EC software sync error";
4900bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_EC_UNKNOWN_IMAGE:
4910bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "EC software sync unable to determine active EC image";
4920bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_DEP_EC_HASH:
4930bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "EC software sync error obtaining EC image hash";
4940bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_EC_EXPECTED_IMAGE:
4950bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "EC software sync error "
4960bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			"obtaining expected EC image from BIOS";
4975ca4ea087a3d67c2a639e8b9254f51f076bf85faRandall Spangler	case VBNV_RECOVERY_EC_EXPECTED_HASH:
4985ca4ea087a3d67c2a639e8b9254f51f076bf85faRandall Spangler		return "EC software sync error "
4995ca4ea087a3d67c2a639e8b9254f51f076bf85faRandall Spangler			"obtaining expected EC hash from BIOS";
5005ca4ea087a3d67c2a639e8b9254f51f076bf85faRandall Spangler	case VBNV_RECOVERY_EC_HASH_MISMATCH:
5015ca4ea087a3d67c2a639e8b9254f51f076bf85faRandall Spangler		return "EC software sync error "
5025ca4ea087a3d67c2a639e8b9254f51f076bf85faRandall Spangler			"comparing expected EC hash and image";
5030bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_EC_UPDATE:
5040bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "EC software sync error updating EC";
5050bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_EC_JUMP_RW:
5060bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "EC software sync unable to jump to EC-RW";
5070bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_EC_PROTECT:
5080bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "EC software sync protection error";
5090bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_UNSPECIFIED:
5100bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "Unspecified/unknown error in RO firmware";
5110bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RW_DEV_SCREEN:
5120bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "User requested recovery from dev-mode warning screen";
5130bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RW_NO_OS:
5140bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "No OS kernel detected (or kernel rollback attempt?)";
5150bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RW_INVALID_OS:
5160bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "OS kernel failed signature check";
5170bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_DEP_RW_TPM_ERROR:
5180bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "TPM error in rewritable firmware";
5190bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RW_DEV_MISMATCH:
5200bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "RW firmware in dev mode, but dev switch is off";
5210bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RW_SHARED_DATA:
5220bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "Shared data error in rewritable firmware";
5230bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RW_TEST_LK:
5240bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "Test error from LoadKernel()";
5250bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_DEP_RW_NO_DISK:
5260bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "No bootable disk found";
5270bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_TPM_E_FAIL:
5280bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "TPM error that was not fixed by reboot";
5290bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_TPM_S_ERROR:
5300bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "TPM setup error in read-only firmware";
5310bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_TPM_W_ERROR:
5320bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "TPM write error in read-only firmware";
5330bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_TPM_L_ERROR:
5340bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "TPM lock error in read-only firmware";
5350bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_TPM_U_ERROR:
5360bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "TPM update error in read-only firmware";
5370bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RW_TPM_R_ERROR:
5380bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "TPM read error in rewritable firmware";
5390bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RW_TPM_W_ERROR:
5400bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "TPM write error in rewritable firmware";
5410bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RW_TPM_L_ERROR:
5420bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "TPM lock error in rewritable firmware";
5430bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_EC_HASH_FAILED:
5440bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "EC software sync unable to get EC image hash";
5450bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_EC_HASH_SIZE:
5460bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "EC software sync invalid image hash size";
5470bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_LK_UNSPECIFIED:
5480bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "Unspecified error while trying to load kernel";
5490bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RW_NO_DISK:
5500bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "No bootable storage device in system";
5510bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RW_NO_KERNEL:
5520bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "No bootable kernel found on disk";
5530bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RW_UNSPECIFIED:
5540bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "Unspecified/unknown error in RW firmware";
5550bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_KE_DM_VERITY:
5560bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "DM-verity error";
5570bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_KE_UNSPECIFIED:
5580bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "Unspecified/unknown error in kernel";
5590bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_US_TEST:
5600bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "Recovery mode test from user-mode";
5610bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_US_UNSPECIFIED:
5620bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "Unspecified/unknown error in user-mode";
5630bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
5640bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	return "We have no idea what this means";
565f2ad05f59ef644af8d6d28d002f89f6c88cde27fBill Richardson}
566f2ad05f59ef644af8d6d28d002f89f6c88cde27fBill Richardson
567822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson#define DEBUG_INFO_SIZE 512
568822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson
5690bf6405a4b4ac1ce569363a45812767777e0f4ebRandall SpanglerVbError_t VbDisplayDebugInfo(VbCommonParams *cparams, VbNvContext *vncptr)
5700bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler{
5710bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	VbSharedDataHeader *shared =
5720bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		(VbSharedDataHeader *)cparams->shared_data_blob;
5730bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	GoogleBinaryBlockHeader *gbb =
5740bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		(GoogleBinaryBlockHeader *)cparams->gbb_data;
5750bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	char buf[DEBUG_INFO_SIZE] = "";
5760bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	char sha1sum[SHA1_DIGEST_SIZE * 2 + 1];
5770bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	uint32_t used = 0;
5780bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	uint32_t i;
5790bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
5800bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Redisplay current screen to overwrite any previous debug output */
5810bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	VbDisplayScreen(cparams, disp_current_screen, 1, vncptr);
5820bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
5830bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Add hardware ID */
5840bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	used += Strncat(buf + used, "HWID: ", DEBUG_INFO_SIZE - used);
5850bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	if (0 == gbb->hwid_size ||
5860bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	    gbb->hwid_offset > cparams->gbb_size ||
5870bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	    gbb->hwid_offset + gbb->hwid_size > cparams->gbb_size) {
5880bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		VBDEBUG(("VbDisplayDebugInfo(): invalid hwid offset/size\n"));
5890bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		used += Strncat(buf + used,
5900bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler				"(INVALID)", DEBUG_INFO_SIZE - used);
591822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson  } else {
5920bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		used += Strncat(buf + used,
5930bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler				(char *)((uint8_t *)gbb + gbb->hwid_offset),
5940bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler				DEBUG_INFO_SIZE - used);
595822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson  }
596822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson
5970bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Add recovery reason */
5980bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	used += Strncat(buf + used,
5990bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			"\nrecovery_reason: 0x", DEBUG_INFO_SIZE - used);
6000bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	used += Uint64ToString(buf + used, DEBUG_INFO_SIZE - used,
6010bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			       shared->recovery_reason, 16, 2);
6020bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	used += Strncat(buf + used, "  ", DEBUG_INFO_SIZE - used);
6030bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	used += Strncat(buf + used,
6040bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			RecoveryReasonString(shared->recovery_reason),
6050bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			DEBUG_INFO_SIZE - used);
6060bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
6070bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Add VbSharedData flags */
6080bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	used += Strncat(buf + used, "\nVbSD.flags: 0x", DEBUG_INFO_SIZE - used);
6090bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	used += Uint64ToString(buf + used, DEBUG_INFO_SIZE - used,
6100bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			       shared->flags, 16, 8);
6110bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
6120bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Add raw contents of VbNvStorage */
6130bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	used += Strncat(buf + used, "\nVbNv.raw:", DEBUG_INFO_SIZE - used);
6140bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	for (i = 0; i < VBNV_BLOCK_SIZE; i++) {
6150bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		used += Strncat(buf + used, " ", DEBUG_INFO_SIZE - used);
6160bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		used += Uint64ToString(buf + used, DEBUG_INFO_SIZE - used,
6170bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler				       vncptr->raw[i], 16, 2);
6180bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
6190bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
6200bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Add dev_boot_usb flag */
6210bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	VbNvGet(vncptr, VBNV_DEV_BOOT_USB, &i);
6220bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	used += Strncat(buf + used, "\ndev_boot_usb: ", DEBUG_INFO_SIZE - used);
6230bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	used += Uint64ToString(buf + used, DEBUG_INFO_SIZE - used, i, 10, 0);
6240bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
6250bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Add dev_boot_legacy flag */
6260bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	VbNvGet(vncptr, VBNV_DEV_BOOT_LEGACY, &i);
6270bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	used += Strncat(buf + used,
6280bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			"\ndev_boot_legacy: ", DEBUG_INFO_SIZE - used);
6290bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	used += Uint64ToString(buf + used, DEBUG_INFO_SIZE - used, i, 10, 0);
6300bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
6310bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Add dev_boot_signed_only flag */
6320bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	VbNvGet(vncptr, VBNV_DEV_BOOT_SIGNED_ONLY, &i);
6330bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	used += Strncat(buf + used, "\ndev_boot_signed_only: ",
6340bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			DEBUG_INFO_SIZE - used);
6350bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	used += Uint64ToString(buf + used, DEBUG_INFO_SIZE - used, i, 10, 0);
6360bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
6370bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Add TPM versions */
6380bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	used += Strncat(buf + used, "\nTPM: fwver=0x", DEBUG_INFO_SIZE - used);
6390bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	used += Uint64ToString(buf + used, DEBUG_INFO_SIZE - used,
6400bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			       shared->fw_version_tpm, 16, 8);
6410bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	used += Strncat(buf + used, " kernver=0x", DEBUG_INFO_SIZE - used);
6420bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	used += Uint64ToString(buf + used, DEBUG_INFO_SIZE - used,
6430bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			       shared->kernel_version_tpm, 16, 8);
6440bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
6450bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Add GBB flags */
6460bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	used += Strncat(buf + used, "\ngbb.flags: 0x", DEBUG_INFO_SIZE - used);
6470bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	if (gbb->major_version == GBB_MAJOR_VER && gbb->minor_version >= 1) {
6480bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		used += Uint64ToString(buf + used, DEBUG_INFO_SIZE - used,
6490bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler				       gbb->flags, 16, 8);
6500bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	} else {
6510bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		used += Strncat(buf + used,
6520bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler				"0 (default)", DEBUG_INFO_SIZE - used);
6530bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
6540bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
6550bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Add sha1sum for Root & Recovery keys */
6560bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	FillInSha1Sum(sha1sum,
6570bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		(VbPublicKey *)((uint8_t *)gbb + gbb->rootkey_offset));
6580bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	used += Strncat(buf + used, "\ngbb.rootkey: ", DEBUG_INFO_SIZE - used);
6590bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	used += Strncat(buf + used, sha1sum, DEBUG_INFO_SIZE - used);
6600bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	FillInSha1Sum(sha1sum,
6610bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		(VbPublicKey *)((uint8_t *)gbb + gbb->recovery_key_offset));
6620bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	used += Strncat(buf + used,
6630bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			"\ngbb.recovery_key: ", DEBUG_INFO_SIZE - used);
6640bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	used += Strncat(buf + used, sha1sum, DEBUG_INFO_SIZE - used);
6650bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
6660bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* If we're in dev-mode, show the kernel subkey that we expect, too. */
6670bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	if (0 == shared->recovery_reason) {
6680bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		FillInSha1Sum(sha1sum, &shared->kernel_subkey);
6690bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		used += Strncat(buf + used,
6700bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler				"\nkernel_subkey: ", DEBUG_INFO_SIZE - used);
6710bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		used += Strncat(buf + used, sha1sum, DEBUG_INFO_SIZE - used);
6720bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
6730bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
6740bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Make sure we finish with a newline */
6750bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	used += Strncat(buf + used, "\n", DEBUG_INFO_SIZE - used);
6760bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
6770bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* TODO: add more interesting data:
6780bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 * - Information on current disks */
6790bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
6800bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	buf[DEBUG_INFO_SIZE - 1] = '\0';
6810bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	return VbExDisplayDebugInfo(buf);
682822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson}
683822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson
684518d4f39b4ab5fa7d516de397795bc146250c51bBill Richardson#define MAGIC_WORD_LEN 5
6850bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler#define MAGIC_WORD "xyzzy"
686518d4f39b4ab5fa7d516de397795bc146250c51bBill Richardsonstatic uint8_t MagicBuffer[MAGIC_WORD_LEN];
687518d4f39b4ab5fa7d516de397795bc146250c51bBill Richardson
6880bf6405a4b4ac1ce569363a45812767777e0f4ebRandall SpanglerVbError_t VbCheckDisplayKey(VbCommonParams *cparams, uint32_t key,
6890bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler                            VbNvContext *vncptr)
6900bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler{
6910bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	int i;
6920bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
6930bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Update key buffer */
6940bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	for(i = 1; i < MAGIC_WORD_LEN; i++)
6950bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		MagicBuffer[i - 1] = MagicBuffer[i];
6960bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Save as lower-case ASCII */
6970bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	MagicBuffer[MAGIC_WORD_LEN - 1] = (key | 0x20) & 0xFF;
6980bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
6990bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	if ('\t' == key) {
7000bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		/* Tab = display debug info */
7010bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return VbDisplayDebugInfo(cparams, vncptr);
7020bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	} else if (VB_KEY_LEFT == key || VB_KEY_RIGHT == key ||
7030bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		   VB_KEY_DOWN == key || VB_KEY_UP == key) {
7040bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		/* Arrow keys = change localization */
7050bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		uint32_t loc = 0;
7060bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		uint32_t count = 0;
7070bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
7080bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		VbNvGet(vncptr, VBNV_LOCALIZATION_INDEX, &loc);
7090bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		if (VBERROR_SUCCESS != VbGetLocalizationCount(cparams, &count))
7100bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			loc = 0;  /* No localization count (bad GBB?) */
7110bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		else if (VB_KEY_RIGHT == key || VB_KEY_UP == key)
7120bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			loc = (loc < count - 1 ? loc + 1 : 0);
7130bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		else
7140bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			loc = (loc > 0 ? loc - 1 : count - 1);
7150bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		VBDEBUG(("VbCheckDisplayKey() - change localization to %d\n",
7160bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			 (int)loc));
7170bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		VbNvSet(vncptr, VBNV_LOCALIZATION_INDEX, loc);
718985e90e26320c73949d5dfbf218773f2cb744598Simon Glass
719be94d55d4f07c5052b04ac3982314e6e588fc361Randall Spangler#ifdef SAVE_LOCALE_IMMEDIATELY
7200bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		VbNvTeardown(vncptr);  /* really only computes checksum */
7210bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		if (vncptr->raw_changed)
7220bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			VbExNvStorageWrite(vncptr->raw);
723985e90e26320c73949d5dfbf218773f2cb744598Simon Glass#endif
724822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson
7250bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		/* Force redraw of current screen */
7260bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return VbDisplayScreen(cparams, disp_current_screen, 1, vncptr);
7270bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
728822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson
7290bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	if (0 == Memcmp(MagicBuffer, MAGIC_WORD, MAGIC_WORD_LEN)) {
7300bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		if (VBEASTEREGG)
7310bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			(void)VbDisplayScreen(cparams, disp_current_screen,
7320bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler					      1, vncptr);
7330bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
734518d4f39b4ab5fa7d516de397795bc146250c51bBill Richardson
735822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson  return VBERROR_SUCCESS;
736822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson}
737