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
80c3ba249abb1dc60f5ebabccf84ff13206440b83Bill Richardson#include "sysincludes.h"
90c3ba249abb1dc60f5ebabccf84ff13206440b83Bill Richardson
100a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson#include "bmpblk_font.h"
11527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass#include "gbb_access.h"
12822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson#include "gbb_header.h"
13527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass#include "region.h"
14822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson#include "utility.h"
15822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson#include "vboot_api.h"
16822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson#include "vboot_common.h"
17822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson#include "vboot_display.h"
18822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson#include "vboot_nvstorage.h"
19822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson
20822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardsonstatic uint32_t disp_current_screen = VB_SCREEN_BLANK;
21822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardsonstatic uint32_t disp_width = 0, disp_height = 0;
22822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson
230bf6405a4b4ac1ce569363a45812767777e0f4ebRandall SpanglerVbError_t VbGetLocalizationCount(VbCommonParams *cparams, uint32_t *count)
240bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler{
25527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass	BmpBlockHeader hdr;
26527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass	VbError_t ret;
270bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
280bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Default to 0 on error */
290bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	*count = 0;
300bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
31527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass	ret = VbGbbReadBmpHeader(cparams, &hdr);
32527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass	if (ret)
33527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass		return ret;
340bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
35527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass	*count = hdr.number_of_localizations;
360bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	return VBERROR_SUCCESS;
370bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler}
38822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson
390bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler/*
400bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler * TODO: We could cache the font info to speed things up, by making the
410a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson * in-memory font structure distinct from the in-flash version.  We'll do that
420a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson * Real Soon Now. Until then, we just repeat the same linear search every time.
430a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson */
440a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson
45fe510c06204c763e61aa36d2263c3b8b79c79879Randall SpanglerVbFont_t *VbInternalizeFontData(FontArrayHeader *fonthdr)
460bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler{
470bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Just return the raw data pointer for now. */
480bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	return (VbFont_t *)fonthdr;
490a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson}
500a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson
51fe510c06204c763e61aa36d2263c3b8b79c79879Randall Spanglervoid VbDoneWithFontForNow(VbFont_t *ptr)
520bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler{
530bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Nothing. */
540a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson}
550a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson
56fe510c06204c763e61aa36d2263c3b8b79c79879Randall SpanglerImageInfo *VbFindFontGlyph(VbFont_t *font, uint32_t ascii,
57fe510c06204c763e61aa36d2263c3b8b79c79879Randall Spangler			   void **bufferptr, uint32_t *buffersize)
580bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler{
590bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	uint8_t *ptr, *firstptr;
600bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	uint32_t max;
610bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	uint32_t i;
620bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	FontArrayEntryHeader *entry;
630bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
640bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	ptr = (uint8_t *)font;
650bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	max = ((FontArrayHeader *)ptr)->num_entries;
660bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	ptr += sizeof(FontArrayHeader);
670bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	firstptr = ptr;
680bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
690bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/*
700bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 * Simple linear search.
710bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 *
720bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 * Note: We're assuming glpyhs are uncompressed. That's true because
730bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 * the bmpblk_font tool doesn't compress anything. The bmpblk_utility
740bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 * does, but it compresses the entire font blob at once, and we've
750bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 * already uncompressed that before we got here.
760bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 */
770bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	for(i=0; i<max; i++) {
780bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		entry = (FontArrayEntryHeader *)ptr;
790bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		if (entry->ascii == ascii) {
800bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			*bufferptr = ptr + sizeof(FontArrayEntryHeader);
810bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			*buffersize = entry->info.original_size;
820bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			return &(entry->info);
830bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		}
840bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		ptr += sizeof(FontArrayEntryHeader)+entry->info.compressed_size;
850bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
860bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
870bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/*
880bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 * We must return something valid. We'll just use the first glyph in
890bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 * the font structure (so it should be something distinct).
900bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 */
910bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	entry = (FontArrayEntryHeader *)firstptr;
920bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	*bufferptr = firstptr + sizeof(FontArrayEntryHeader);
930bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	*buffersize = entry->info.original_size;
940bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	return &(entry->info);
950a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson}
960a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson
979d7d0cbe132e6660885b72d6c46a2bbc982dca25Aaron Durbinvoid VbRenderTextAtPos(const char *text, int right_to_left,
98fe510c06204c763e61aa36d2263c3b8b79c79879Randall Spangler		       uint32_t x, uint32_t y, VbFont_t *font)
990bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler{
1000bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	int i;
1010bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	ImageInfo *image_info = 0;
1020bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	void *buffer;
1030bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	uint32_t buffersize;
1040bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	uint32_t cur_x = x, cur_y = y;
1050bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
1060bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	if (!text || !font) {
1070bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		VBDEBUG(("  VbRenderTextAtPos: invalid args\n"));
1080bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return;
1090bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
1100bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
1110bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	for (i=0; text[i]; i++) {
1120bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
1130bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		if (text[i] == '\n') {
1140bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			if (!image_info)
1150bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler				image_info = VbFindFontGlyph(font, text[i],
1160bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler							     &buffer,
1170bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler							     &buffersize);
1180bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			cur_x = x;
1190bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			cur_y += image_info->height;
1200bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			continue;
1210bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		}
1220bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
1230bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		image_info = VbFindFontGlyph(font, text[i], &buffer,
1240bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler					     &buffersize);
1250bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
1260bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		if (right_to_left)
1270bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			cur_x -= image_info->width;
1280bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
1290bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		if (VBERROR_SUCCESS != VbExDisplayImage(cur_x, cur_y, buffer,
1300bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler							buffersize)) {
1310bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			VBDEBUG(("  VbRenderTextAtPos: "
1320bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler				 "can't display ascii 0x%x\n", text[i]));
1330bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		}
1340bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
1350bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		if (!right_to_left)
1360bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			cur_x += image_info->width;
1370bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
1380a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson}
1390a9977e161ce6ad6b11935dfb05ae840bf758078Bill Richardson
1400bf6405a4b4ac1ce569363a45812767777e0f4ebRandall SpanglerVbError_t VbDisplayScreenFromGBB(VbCommonParams *cparams, uint32_t screen,
1410bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler                                 VbNvContext *vncptr)
1420bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler{
143527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass	char *fullimage = NULL;
144527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass	BmpBlockHeader hdr;
1450bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	uint32_t screen_index;
1460bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	uint32_t localization = 0;
1470bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	VbError_t retval = VBERROR_UNKNOWN;   /* Assume error until proven ok */
1480bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	uint32_t inoutsize;
1490bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	uint32_t i;
1500bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	VbFont_t *font;
1519d7d0cbe132e6660885b72d6c46a2bbc982dca25Aaron Durbin	const char *text_to_show;
1520bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	int rtol = 0;
153527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass	VbError_t ret;
1540bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
155527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass	ret = VbGbbReadBmpHeader(cparams, &hdr);
156527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass	if (ret)
157527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass		return ret;
1580bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
1590bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/*
1600bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 * Translate screen ID into index.  Note that not all screens are in
1610bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 * the GBB.
1620bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 *
1630bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 * TODO: ensure screen IDs match indices?  Having this translation here
1640bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 * is awful.
1650bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 */
1660bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	switch (screen) {
1670bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VB_SCREEN_DEVELOPER_WARNING:
1680bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		screen_index = SCREEN_DEVELOPER_WARNING;
1690bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		break;
1700bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VB_SCREEN_RECOVERY_REMOVE:
1710bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		screen_index = SCREEN_RECOVERY_REMOVE;
1720bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		break;
1730bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VB_SCREEN_RECOVERY_NO_GOOD:
1740bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		screen_index = SCREEN_RECOVERY_NO_GOOD;
1750bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		break;
1760bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VB_SCREEN_RECOVERY_INSERT:
1770bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		screen_index = SCREEN_RECOVERY_INSERT;
1780bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		break;
1790bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VB_SCREEN_RECOVERY_TO_DEV:
1800bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		screen_index = SCREEN_RECOVERY_TO_DEV;
1810bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		break;
1820bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VB_SCREEN_DEVELOPER_TO_NORM:
1830bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		screen_index = SCREEN_DEVELOPER_TO_NORM;
1840bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		break;
1850bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VB_SCREEN_WAIT:
1860bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		screen_index = SCREEN_WAIT;
1870bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		break;
1880bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VB_SCREEN_TO_NORM_CONFIRMED:
1890bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		screen_index = SCREEN_TO_NORM_CONFIRMED;
1900bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		break;
1910bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VB_SCREEN_BLANK:
1920bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VB_SCREEN_DEVELOPER_EGG:
1930bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	default:
1940bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		/* Screens which aren't in the GBB */
1950bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		VBDEBUG(("VbDisplayScreenFromGBB(): screen %d not in the GBB\n",
1960bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			 (int)screen));
1970bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		retval = VBERROR_INVALID_SCREEN_INDEX;
1980bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		goto VbDisplayScreenFromGBB_exit;
1990bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
2000bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
201527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass	if (screen_index >= hdr.number_of_screenlayouts) {
2020bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		VBDEBUG(("VbDisplayScreenFromGBB(): "
2030bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			 "screen %d index %d not in the GBB\n",
2040bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			 (int)screen, (int)screen_index));
2050bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		retval = VBERROR_INVALID_SCREEN_INDEX;
2060bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		goto VbDisplayScreenFromGBB_exit;
2070bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
2080bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
2090bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Clip localization to number of localizations present in the GBB */
2100bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	VbNvGet(vncptr, VBNV_LOCALIZATION_INDEX, &localization);
211527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass	if (localization >= hdr.number_of_localizations) {
2120bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		localization = 0;
2130bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		VbNvSet(vncptr, VBNV_LOCALIZATION_INDEX, localization);
214b64f097891e697eaf3b2794baae934f8b4d82d14Bill Richardson		VbNvSet(vncptr, VBNV_BACKUP_NVRAM_REQUEST, 1);
2150bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
2160bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
2170bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Display all bitmaps for the image */
2180bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	for (i = 0; i < MAX_IMAGE_IN_LAYOUT; i++) {
219527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass		ScreenLayout layout;
220527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass		ImageInfo image_info;
221527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass		char hwid[256];
222527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass
223527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass		ret = VbGbbReadImage(cparams, localization, screen_index,
224527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass				    i, &layout, &image_info,
225527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass				    &fullimage, &inoutsize);
226527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass		if (ret == VBERROR_NO_IMAGE_PRESENT) {
2270bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			continue;
228527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass		} else if (ret) {
229527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass			retval = ret;
230527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass			goto VbDisplayScreenFromGBB_exit;
2310bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		}
2320bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
233527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass		switch(image_info.format) {
2340bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		case FORMAT_BMP:
2355e8f1db9d4a483678c376a0a276b8f774f91d0acHung-Te Lin			if (i == 0) {
2365e8f1db9d4a483678c376a0a276b8f774f91d0acHung-Te Lin				/**
2375e8f1db9d4a483678c376a0a276b8f774f91d0acHung-Te Lin				 * In current version GBB bitmaps, first image
2385e8f1db9d4a483678c376a0a276b8f774f91d0acHung-Te Lin				 * is always the background.
2395e8f1db9d4a483678c376a0a276b8f774f91d0acHung-Te Lin				 */
2405e8f1db9d4a483678c376a0a276b8f774f91d0acHung-Te Lin				ret = VbExDisplaySetDimension(
2415e8f1db9d4a483678c376a0a276b8f774f91d0acHung-Te Lin						image_info.width,
2425e8f1db9d4a483678c376a0a276b8f774f91d0acHung-Te Lin						image_info.height);
2438f7b7055a134d003920b4a67a951d23ad7b1f939Hung-Te Lin				if (ret) {
2445e8f1db9d4a483678c376a0a276b8f774f91d0acHung-Te Lin					VBDEBUG(("VbExDisplaySetDimension"
2458f7b7055a134d003920b4a67a951d23ad7b1f939Hung-Te Lin						 "(%d,%d): failed (%#x).\n",
2465e8f1db9d4a483678c376a0a276b8f774f91d0acHung-Te Lin						 image_info.width,
2478f7b7055a134d003920b4a67a951d23ad7b1f939Hung-Te Lin						 image_info.height, ret));
2485e8f1db9d4a483678c376a0a276b8f774f91d0acHung-Te Lin				}
2495e8f1db9d4a483678c376a0a276b8f774f91d0acHung-Te Lin			}
2505e8f1db9d4a483678c376a0a276b8f774f91d0acHung-Te Lin
251527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass			retval = VbExDisplayImage(layout.images[i].x,
252527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass						  layout.images[i].y,
2530bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler						  fullimage, inoutsize);
2540bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			break;
2550bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
2560bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		case FORMAT_FONT:
2570bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			/*
2580bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			 * The uncompressed blob is our font structure. Cache
2590bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			 * it as needed.
2600bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			 */
261527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass			font = VbInternalizeFontData(
262527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass					(FontArrayHeader *)fullimage);
2630bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
2640bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			/* TODO: handle text in general here */
265527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass			if (TAG_HWID == image_info.tag ||
266527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass			    TAG_HWID_RTOL == image_info.tag) {
267527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass				VbRegionReadHWID(cparams, hwid, sizeof(hwid));
268527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass				text_to_show = hwid;
269527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass				rtol = (TAG_HWID_RTOL == image_info.tag);
2700bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			} else {
2710bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler				text_to_show = "";
2720bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler				rtol = 0;
2730bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			}
2740bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
2750bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			VbRenderTextAtPos(text_to_show, rtol,
276527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass					  layout.images[i].x,
277527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass					  layout.images[i].y, font);
2780bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
2790bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			VbDoneWithFontForNow(font);
2800bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			break;
2810bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
2820bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		default:
2830bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			VBDEBUG(("VbDisplayScreenFromGBB(): "
2840bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler				 "unsupported ImageFormat %d\n",
285527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass				 image_info.format));
2860bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			retval = VBERROR_INVALID_GBB;
2870bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		}
2880bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
289527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass		VbExFree(fullimage);
2900bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
2910bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		if (VBERROR_SUCCESS != retval)
2920bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			goto VbDisplayScreenFromGBB_exit;
2930bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
2940bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
2950bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Successful if all bitmaps displayed */
2960bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	retval = VBERROR_SUCCESS;
2970bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
298527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass	VbRegionCheckVersion(cparams);
2990bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
3000bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler VbDisplayScreenFromGBB_exit:
3010bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	VBDEBUG(("leaving VbDisplayScreenFromGBB() with %d\n",retval));
3020bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	return retval;
303822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson}
304822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson
305527ba810eff4006cf69579f6b96cb4350cb1e189Simon GlassVbError_t VbDisplayScreen(VbCommonParams *cparams, uint32_t screen,
306527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass			  int force, VbNvContext *vncptr)
3070bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler{
3080bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	VbError_t retval;
309822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson
3100bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Initialize display if necessary */
3110bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	if (!disp_width) {
3120bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		retval = VbExDisplayInit(&disp_width, &disp_height);
3130bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		if (VBERROR_SUCCESS != retval)
3140bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			return retval;
3150bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
316822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson
3170bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* If requested screen is the same as the current one, we're done. */
3180bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	if (disp_current_screen == screen && 0 == force)
3190bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return VBERROR_SUCCESS;
320822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson
3210bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* If the screen is blank, turn off the backlight; else turn it on. */
3220bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	VbExDisplayBacklight(VB_SCREEN_BLANK == screen ? 0 : 1);
323822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson
3240bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Request the screen */
3250bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	disp_current_screen = screen;
326822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson
3270bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Look in the GBB first */
328527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass	if (VBERROR_SUCCESS == VbDisplayScreenFromGBB(cparams, screen,
329527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass						      vncptr))
3300bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return VBERROR_SUCCESS;
331822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson
3320bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* If screen wasn't in the GBB bitmaps, fall back to a default */
3330bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	return VbExDisplayScreen(screen);
334822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson}
335822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson
3360bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spanglerstatic void Uint8ToString(char *buf, uint8_t val)
3370bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler{
3380bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	const char *trans = "0123456789abcdef";
3390bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	*buf++ = trans[val >> 4];
3400bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	*buf = trans[val & 0xF];
3415de6b40ca74f4a6724941068a15bb0cf261a2d01Bill Richardson}
3425de6b40ca74f4a6724941068a15bb0cf261a2d01Bill Richardson
3430bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spanglerstatic void FillInSha1Sum(char *outbuf, VbPublicKey *key)
3440bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler{
3450bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	uint8_t *buf = ((uint8_t *)key) + key->key_offset;
3460bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	uint64_t buflen = key->key_size;
3470bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	uint8_t *digest = DigestBuf(buf, buflen, SHA1_DIGEST_ALGORITHM);
3480bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	int i;
3490bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	for (i = 0; i < SHA1_DIGEST_SIZE; i++) {
3500bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		Uint8ToString(outbuf, digest[i]);
3510bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		outbuf += 2;
3520bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
3530bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	*outbuf = '\0';
3540bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	VbExFree(digest);
3555de6b40ca74f4a6724941068a15bb0cf261a2d01Bill Richardson}
3565de6b40ca74f4a6724941068a15bb0cf261a2d01Bill Richardson
3570bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spanglerconst char *RecoveryReasonString(uint8_t code)
3580bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler{
3590bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	switch(code) {
3600bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_NOT_REQUESTED:
3610bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "Recovery not requested";
3620bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_LEGACY:
3630bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "Recovery requested from legacy utility";
3640bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_MANUAL:
3650bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "recovery button pressed";
3660bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_INVALID_RW:
3670bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "RW firmware failed signature check";
3680bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_S3_RESUME:
3690bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "S3 resume failed";
3700bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_DEP_RO_TPM_ERROR:
3710bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "TPM error in read-only firmware";
3720bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_SHARED_DATA:
3730bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "Shared data error in read-only firmware";
3740bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_TEST_S3:
3750bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "Test error from S3Resume()";
3760bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_TEST_LFS:
3770bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "Test error from LoadFirmwareSetup()";
3780bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_TEST_LF:
3790bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "Test error from LoadFirmware()";
3800bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + VBSD_LF_CHECK_NOT_DONE:
3810bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "RW firmware check not done";
3820bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + VBSD_LF_CHECK_DEV_MISMATCH:
3830bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	  return "RW firmware developer flag mismatch";
3840bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + VBSD_LF_CHECK_REC_MISMATCH:
3850bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "RW firmware recovery flag mismatch";
3860bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN +
3870bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		VBSD_LF_CHECK_VERIFY_KEYBLOCK:
3880bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "RW firmware unable to verify key block";
3890bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + VBSD_LF_CHECK_KEY_ROLLBACK:
3900bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "RW firmware key version rollback detected";
3910bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN +
3920bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		VBSD_LF_CHECK_DATA_KEY_PARSE:
3930bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "RW firmware unable to parse data key";
3940bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN +
3950bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		VBSD_LF_CHECK_VERIFY_PREAMBLE:
3960bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "RW firmware unable to verify preamble";
3970bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + VBSD_LF_CHECK_FW_ROLLBACK:
3980bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "RW firmware version rollback detected";
3990bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + VBSD_LF_CHECK_GET_FW_BODY:
4000bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "RW firmware unable to get firmware body";
4010bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN +
4020bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		VBSD_LF_CHECK_HASH_WRONG_SIZE:
4030bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "RW firmware hash is wrong size";
4040bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + VBSD_LF_CHECK_VERIFY_BODY:
4050bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "RW firmware unable to verify firmware body";
4060bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + VBSD_LF_CHECK_NO_RO_NORMAL:
4070bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "RW firmware read-only normal path is not supported";
4080bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_FIRMWARE:
4090bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "Firmware problem outside of verified boot";
4100bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_TPM_REBOOT:
4110bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "TPM requires a system reboot (should be transient)";
4120bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_EC_SOFTWARE_SYNC:
4130bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "EC software sync error";
4140bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_EC_UNKNOWN_IMAGE:
4150bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "EC software sync unable to determine active EC image";
4160bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_DEP_EC_HASH:
4170bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "EC software sync error obtaining EC image hash";
4180bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_EC_EXPECTED_IMAGE:
4190bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "EC software sync error "
4200bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			"obtaining expected EC image from BIOS";
4215ca4ea087a3d67c2a639e8b9254f51f076bf85faRandall Spangler	case VBNV_RECOVERY_EC_EXPECTED_HASH:
4225ca4ea087a3d67c2a639e8b9254f51f076bf85faRandall Spangler		return "EC software sync error "
4235ca4ea087a3d67c2a639e8b9254f51f076bf85faRandall Spangler			"obtaining expected EC hash from BIOS";
4245ca4ea087a3d67c2a639e8b9254f51f076bf85faRandall Spangler	case VBNV_RECOVERY_EC_HASH_MISMATCH:
4255ca4ea087a3d67c2a639e8b9254f51f076bf85faRandall Spangler		return "EC software sync error "
4265ca4ea087a3d67c2a639e8b9254f51f076bf85faRandall Spangler			"comparing expected EC hash and image";
4270bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_EC_UPDATE:
4280bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "EC software sync error updating EC";
4290bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_EC_JUMP_RW:
4300bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "EC software sync unable to jump to EC-RW";
4310bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_EC_PROTECT:
4320bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "EC software sync protection error";
433dc8ec103c0d0d2a4e930153a4b19c43b51d74b5dJulius Werner	case VBNV_RECOVERY_VB2_SECDATA_INIT:
434dc8ec103c0d0d2a4e930153a4b19c43b51d74b5dJulius Werner		return "Secure NVRAM (TPM) initialization error";
435dc8ec103c0d0d2a4e930153a4b19c43b51d74b5dJulius Werner	case VBNV_RECOVERY_VB2_GBB_HEADER:
436dc8ec103c0d0d2a4e930153a4b19c43b51d74b5dJulius Werner		return "Error parsing GBB header";
437dc8ec103c0d0d2a4e930153a4b19c43b51d74b5dJulius Werner	case VBNV_RECOVERY_VB2_TPM_CLEAR_OWNER:
438dc8ec103c0d0d2a4e930153a4b19c43b51d74b5dJulius Werner		return "Error trying to clear TPM owner";
439dc8ec103c0d0d2a4e930153a4b19c43b51d74b5dJulius Werner	case VBNV_RECOVERY_VB2_DEV_SWITCH:
440dc8ec103c0d0d2a4e930153a4b19c43b51d74b5dJulius Werner		return "Error reading or updating developer switch";
441dc8ec103c0d0d2a4e930153a4b19c43b51d74b5dJulius Werner	case VBNV_RECOVERY_VB2_FW_SLOT:
442dc8ec103c0d0d2a4e930153a4b19c43b51d74b5dJulius Werner		return "Error selecting RW firmware slot";
4430bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_UNSPECIFIED:
4440bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "Unspecified/unknown error in RO firmware";
4450bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RW_DEV_SCREEN:
4460bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "User requested recovery from dev-mode warning screen";
4470bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RW_NO_OS:
4480bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "No OS kernel detected (or kernel rollback attempt?)";
4490bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RW_INVALID_OS:
4500bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "OS kernel failed signature check";
4510bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_DEP_RW_TPM_ERROR:
4520bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "TPM error in rewritable firmware";
4530bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RW_DEV_MISMATCH:
4540bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "RW firmware in dev mode, but dev switch is off";
4550bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RW_SHARED_DATA:
4560bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "Shared data error in rewritable firmware";
4570bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RW_TEST_LK:
4580bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "Test error from LoadKernel()";
4590bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_DEP_RW_NO_DISK:
4600bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "No bootable disk found";
4610bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_TPM_E_FAIL:
4620bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "TPM error that was not fixed by reboot";
4630bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_TPM_S_ERROR:
4640bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "TPM setup error in read-only firmware";
4650bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_TPM_W_ERROR:
4660bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "TPM write error in read-only firmware";
4670bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_TPM_L_ERROR:
4680bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "TPM lock error in read-only firmware";
4690bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RO_TPM_U_ERROR:
4700bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "TPM update error in read-only firmware";
4710bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RW_TPM_R_ERROR:
4720bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "TPM read error in rewritable firmware";
4730bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RW_TPM_W_ERROR:
4740bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "TPM write error in rewritable firmware";
4750bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RW_TPM_L_ERROR:
4760bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "TPM lock error in rewritable firmware";
4770bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_EC_HASH_FAILED:
4780bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "EC software sync unable to get EC image hash";
4790bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_EC_HASH_SIZE:
4800bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "EC software sync invalid image hash size";
4810bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_LK_UNSPECIFIED:
4820bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "Unspecified error while trying to load kernel";
4830bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RW_NO_DISK:
4840bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "No bootable storage device in system";
4850bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RW_NO_KERNEL:
4860bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "No bootable kernel found on disk";
4870bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_RW_UNSPECIFIED:
4880bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "Unspecified/unknown error in RW firmware";
4890bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_KE_DM_VERITY:
4900bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "DM-verity error";
4910bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_KE_UNSPECIFIED:
4920bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "Unspecified/unknown error in kernel";
4930bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_US_TEST:
4940bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "Recovery mode test from user-mode";
4950bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	case VBNV_RECOVERY_US_UNSPECIFIED:
4960bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return "Unspecified/unknown error in user-mode";
4970bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
4980bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	return "We have no idea what this means";
499f2ad05f59ef644af8d6d28d002f89f6c88cde27fBill Richardson}
500f2ad05f59ef644af8d6d28d002f89f6c88cde27fBill Richardson
501822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson#define DEBUG_INFO_SIZE 512
502822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson
5030bf6405a4b4ac1ce569363a45812767777e0f4ebRandall SpanglerVbError_t VbDisplayDebugInfo(VbCommonParams *cparams, VbNvContext *vncptr)
5040bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler{
5050bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	VbSharedDataHeader *shared =
5060bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		(VbSharedDataHeader *)cparams->shared_data_blob;
507527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass	GoogleBinaryBlockHeader *gbb = cparams->gbb;
5080bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	char buf[DEBUG_INFO_SIZE] = "";
5090bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	char sha1sum[SHA1_DIGEST_SIZE * 2 + 1];
510527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass	char hwid[256];
5110bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	uint32_t used = 0;
512527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass	VbPublicKey *key;
513527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass	VbError_t ret;
5140bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	uint32_t i;
5150bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
5160bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Redisplay current screen to overwrite any previous debug output */
5170bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	VbDisplayScreen(cparams, disp_current_screen, 1, vncptr);
5180bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
5190bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Add hardware ID */
520527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass	VbRegionReadHWID(cparams, hwid, sizeof(hwid));
5215fed2a667096341160db8643a4a057e328953a1dBill Richardson	used += StrnAppend(buf + used, "HWID: ", DEBUG_INFO_SIZE - used);
522527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass	used += StrnAppend(buf + used, hwid, DEBUG_INFO_SIZE - used);
523822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson
524dc8ec103c0d0d2a4e930153a4b19c43b51d74b5dJulius Werner	/* Add recovery reason and subcode */
525dc8ec103c0d0d2a4e930153a4b19c43b51d74b5dJulius Werner	VbNvGet(vncptr, VBNV_RECOVERY_SUBCODE, &i);
5265fed2a667096341160db8643a4a057e328953a1dBill Richardson	used += StrnAppend(buf + used,
5270bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			"\nrecovery_reason: 0x", DEBUG_INFO_SIZE - used);
5280bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	used += Uint64ToString(buf + used, DEBUG_INFO_SIZE - used,
5290bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			       shared->recovery_reason, 16, 2);
530dc8ec103c0d0d2a4e930153a4b19c43b51d74b5dJulius Werner	used += StrnAppend(buf + used, " / 0x", DEBUG_INFO_SIZE - used);
531dc8ec103c0d0d2a4e930153a4b19c43b51d74b5dJulius Werner	used += Uint64ToString(buf + used, DEBUG_INFO_SIZE - used, i, 16, 2);
5325fed2a667096341160db8643a4a057e328953a1dBill Richardson	used += StrnAppend(buf + used, "  ", DEBUG_INFO_SIZE - used);
5335fed2a667096341160db8643a4a057e328953a1dBill Richardson	used += StrnAppend(buf + used,
5340bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			RecoveryReasonString(shared->recovery_reason),
5350bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			DEBUG_INFO_SIZE - used);
5360bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
5370bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Add VbSharedData flags */
5385fed2a667096341160db8643a4a057e328953a1dBill Richardson	used += StrnAppend(buf + used, "\nVbSD.flags: 0x", DEBUG_INFO_SIZE - used);
5390bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	used += Uint64ToString(buf + used, DEBUG_INFO_SIZE - used,
5400bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			       shared->flags, 16, 8);
5410bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
5420bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Add raw contents of VbNvStorage */
5435fed2a667096341160db8643a4a057e328953a1dBill Richardson	used += StrnAppend(buf + used, "\nVbNv.raw:", DEBUG_INFO_SIZE - used);
5440bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	for (i = 0; i < VBNV_BLOCK_SIZE; i++) {
5455fed2a667096341160db8643a4a057e328953a1dBill Richardson		used += StrnAppend(buf + used, " ", DEBUG_INFO_SIZE - used);
5460bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		used += Uint64ToString(buf + used, DEBUG_INFO_SIZE - used,
5470bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler				       vncptr->raw[i], 16, 2);
5480bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
5490bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
5500bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Add dev_boot_usb flag */
5510bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	VbNvGet(vncptr, VBNV_DEV_BOOT_USB, &i);
5525fed2a667096341160db8643a4a057e328953a1dBill Richardson	used += StrnAppend(buf + used, "\ndev_boot_usb: ", DEBUG_INFO_SIZE - used);
5530bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	used += Uint64ToString(buf + used, DEBUG_INFO_SIZE - used, i, 10, 0);
5540bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
5550bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Add dev_boot_legacy flag */
5560bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	VbNvGet(vncptr, VBNV_DEV_BOOT_LEGACY, &i);
5575fed2a667096341160db8643a4a057e328953a1dBill Richardson	used += StrnAppend(buf + used,
5580bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			"\ndev_boot_legacy: ", DEBUG_INFO_SIZE - used);
5590bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	used += Uint64ToString(buf + used, DEBUG_INFO_SIZE - used, i, 10, 0);
5600bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
5610bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Add dev_boot_signed_only flag */
5620bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	VbNvGet(vncptr, VBNV_DEV_BOOT_SIGNED_ONLY, &i);
5635fed2a667096341160db8643a4a057e328953a1dBill Richardson	used += StrnAppend(buf + used, "\ndev_boot_signed_only: ",
5640bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			DEBUG_INFO_SIZE - used);
5650bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	used += Uint64ToString(buf + used, DEBUG_INFO_SIZE - used, i, 10, 0);
5660bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
5670bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Add TPM versions */
5685fed2a667096341160db8643a4a057e328953a1dBill Richardson	used += StrnAppend(buf + used, "\nTPM: fwver=0x", DEBUG_INFO_SIZE - used);
5690bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	used += Uint64ToString(buf + used, DEBUG_INFO_SIZE - used,
5700bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			       shared->fw_version_tpm, 16, 8);
5715fed2a667096341160db8643a4a057e328953a1dBill Richardson	used += StrnAppend(buf + used, " kernver=0x", DEBUG_INFO_SIZE - used);
5720bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	used += Uint64ToString(buf + used, DEBUG_INFO_SIZE - used,
5730bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			       shared->kernel_version_tpm, 16, 8);
5740bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
5750bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Add GBB flags */
5765fed2a667096341160db8643a4a057e328953a1dBill Richardson	used += StrnAppend(buf + used, "\ngbb.flags: 0x", DEBUG_INFO_SIZE - used);
5770bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	if (gbb->major_version == GBB_MAJOR_VER && gbb->minor_version >= 1) {
5780bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		used += Uint64ToString(buf + used, DEBUG_INFO_SIZE - used,
5790bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler				       gbb->flags, 16, 8);
5800bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	} else {
5815fed2a667096341160db8643a4a057e328953a1dBill Richardson		used += StrnAppend(buf + used,
5820bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler				"0 (default)", DEBUG_INFO_SIZE - used);
5830bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
5840bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
5850bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Add sha1sum for Root & Recovery keys */
586527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass	ret = VbGbbReadRootKey(cparams, &key);
587527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass	if (!ret) {
588527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass		FillInSha1Sum(sha1sum, key);
589527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass		VbExFree(key);
590527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass		used += StrnAppend(buf + used, "\ngbb.rootkey: ",
591527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass				   DEBUG_INFO_SIZE - used);
592527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass		used += StrnAppend(buf + used, sha1sum,
593527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass				   DEBUG_INFO_SIZE - used);
594527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass	}
595527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass
596527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass	ret = VbGbbReadRecoveryKey(cparams, &key);
597527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass	if (!ret) {
598527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass		FillInSha1Sum(sha1sum, key);
599527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass		VbExFree(key);
600527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass		used += StrnAppend(buf + used, "\ngbb.recovery_key: ",
601527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass				   DEBUG_INFO_SIZE - used);
602527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass		used += StrnAppend(buf + used, sha1sum,
603527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass				   DEBUG_INFO_SIZE - used);
604527ba810eff4006cf69579f6b96cb4350cb1e189Simon Glass	}
6050bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
6060bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* If we're in dev-mode, show the kernel subkey that we expect, too. */
6070bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	if (0 == shared->recovery_reason) {
6080bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		FillInSha1Sum(sha1sum, &shared->kernel_subkey);
6095fed2a667096341160db8643a4a057e328953a1dBill Richardson		used += StrnAppend(buf + used,
6100bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler				"\nkernel_subkey: ", DEBUG_INFO_SIZE - used);
6115fed2a667096341160db8643a4a057e328953a1dBill Richardson		used += StrnAppend(buf + used, sha1sum, DEBUG_INFO_SIZE - used);
6120bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
6130bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
6140bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Make sure we finish with a newline */
6155fed2a667096341160db8643a4a057e328953a1dBill Richardson	used += StrnAppend(buf + used, "\n", DEBUG_INFO_SIZE - used);
6160bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
6170bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* TODO: add more interesting data:
6180bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	 * - Information on current disks */
6190bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
6200bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	buf[DEBUG_INFO_SIZE - 1] = '\0';
6210bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	return VbExDisplayDebugInfo(buf);
622822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson}
623822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson
624518d4f39b4ab5fa7d516de397795bc146250c51bBill Richardson#define MAGIC_WORD_LEN 5
6250bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler#define MAGIC_WORD "xyzzy"
626518d4f39b4ab5fa7d516de397795bc146250c51bBill Richardsonstatic uint8_t MagicBuffer[MAGIC_WORD_LEN];
627518d4f39b4ab5fa7d516de397795bc146250c51bBill Richardson
6280bf6405a4b4ac1ce569363a45812767777e0f4ebRandall SpanglerVbError_t VbCheckDisplayKey(VbCommonParams *cparams, uint32_t key,
6290bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler                            VbNvContext *vncptr)
6300bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler{
6310bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	int i;
6320bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
6330bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Update key buffer */
6340bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	for(i = 1; i < MAGIC_WORD_LEN; i++)
6350bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		MagicBuffer[i - 1] = MagicBuffer[i];
6360bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	/* Save as lower-case ASCII */
6370bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	MagicBuffer[MAGIC_WORD_LEN - 1] = (key | 0x20) & 0xFF;
6380bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
6390bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	if ('\t' == key) {
6400bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		/* Tab = display debug info */
6410bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return VbDisplayDebugInfo(cparams, vncptr);
6420bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	} else if (VB_KEY_LEFT == key || VB_KEY_RIGHT == key ||
6430bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		   VB_KEY_DOWN == key || VB_KEY_UP == key) {
6440bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		/* Arrow keys = change localization */
6450bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		uint32_t loc = 0;
6460bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		uint32_t count = 0;
6470bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler
6480bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		VbNvGet(vncptr, VBNV_LOCALIZATION_INDEX, &loc);
6490bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		if (VBERROR_SUCCESS != VbGetLocalizationCount(cparams, &count))
6500bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			loc = 0;  /* No localization count (bad GBB?) */
6510bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		else if (VB_KEY_RIGHT == key || VB_KEY_UP == key)
6520bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			loc = (loc < count - 1 ? loc + 1 : 0);
6530bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		else
6540bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			loc = (loc > 0 ? loc - 1 : count - 1);
6550bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		VBDEBUG(("VbCheckDisplayKey() - change localization to %d\n",
6560bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			 (int)loc));
6570bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		VbNvSet(vncptr, VBNV_LOCALIZATION_INDEX, loc);
658b64f097891e697eaf3b2794baae934f8b4d82d14Bill Richardson		VbNvSet(vncptr, VBNV_BACKUP_NVRAM_REQUEST, 1);
659985e90e26320c73949d5dfbf218773f2cb744598Simon Glass
660be94d55d4f07c5052b04ac3982314e6e588fc361Randall Spangler#ifdef SAVE_LOCALE_IMMEDIATELY
6610bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		VbNvTeardown(vncptr);  /* really only computes checksum */
6620bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		if (vncptr->raw_changed)
6630bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			VbExNvStorageWrite(vncptr->raw);
664985e90e26320c73949d5dfbf218773f2cb744598Simon Glass#endif
665822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson
6660bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		/* Force redraw of current screen */
6670bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		return VbDisplayScreen(cparams, disp_current_screen, 1, vncptr);
6680bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
669822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson
6700bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	if (0 == Memcmp(MagicBuffer, MAGIC_WORD, MAGIC_WORD_LEN)) {
6710bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler		if (VBEASTEREGG)
6720bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler			(void)VbDisplayScreen(cparams, disp_current_screen,
6730bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler					      1, vncptr);
6740bf6405a4b4ac1ce569363a45812767777e0f4ebRandall Spangler	}
675518d4f39b4ab5fa7d516de397795bc146250c51bBill Richardson
676822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson  return VBERROR_SUCCESS;
677822eca680fa9568396f9de79ab91a9e67f3a9aaeBill Richardson}
678