vboot_display.c revision 8f7b7055a134d003920b4a67a951d23ad7b1f939
1/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved. 2 * Use of this source code is governed by a BSD-style license that can be 3 * found in the LICENSE file. 4 * 5 * Display functions used in kernel selection. 6 */ 7 8#include "sysincludes.h" 9 10#include "bmpblk_font.h" 11#include "gbb_access.h" 12#include "gbb_header.h" 13#include "region.h" 14#include "utility.h" 15#include "vboot_api.h" 16#include "vboot_common.h" 17#include "vboot_display.h" 18#include "vboot_nvstorage.h" 19 20static uint32_t disp_current_screen = VB_SCREEN_BLANK; 21static uint32_t disp_width = 0, disp_height = 0; 22 23VbError_t VbGetLocalizationCount(VbCommonParams *cparams, uint32_t *count) 24{ 25 BmpBlockHeader hdr; 26 VbError_t ret; 27 28 /* Default to 0 on error */ 29 *count = 0; 30 31 ret = VbGbbReadBmpHeader(cparams, &hdr); 32 if (ret) 33 return ret; 34 35 *count = hdr.number_of_localizations; 36 return VBERROR_SUCCESS; 37} 38 39/* 40 * TODO: We could cache the font info to speed things up, by making the 41 * in-memory font structure distinct from the in-flash version. We'll do that 42 * Real Soon Now. Until then, we just repeat the same linear search every time. 43 */ 44 45VbFont_t *VbInternalizeFontData(FontArrayHeader *fonthdr) 46{ 47 /* Just return the raw data pointer for now. */ 48 return (VbFont_t *)fonthdr; 49} 50 51void VbDoneWithFontForNow(VbFont_t *ptr) 52{ 53 /* Nothing. */ 54} 55 56ImageInfo *VbFindFontGlyph(VbFont_t *font, uint32_t ascii, 57 void **bufferptr, uint32_t *buffersize) 58{ 59 uint8_t *ptr, *firstptr; 60 uint32_t max; 61 uint32_t i; 62 FontArrayEntryHeader *entry; 63 64 ptr = (uint8_t *)font; 65 max = ((FontArrayHeader *)ptr)->num_entries; 66 ptr += sizeof(FontArrayHeader); 67 firstptr = ptr; 68 69 /* 70 * Simple linear search. 71 * 72 * Note: We're assuming glpyhs are uncompressed. That's true because 73 * the bmpblk_font tool doesn't compress anything. The bmpblk_utility 74 * does, but it compresses the entire font blob at once, and we've 75 * already uncompressed that before we got here. 76 */ 77 for(i=0; i<max; i++) { 78 entry = (FontArrayEntryHeader *)ptr; 79 if (entry->ascii == ascii) { 80 *bufferptr = ptr + sizeof(FontArrayEntryHeader); 81 *buffersize = entry->info.original_size; 82 return &(entry->info); 83 } 84 ptr += sizeof(FontArrayEntryHeader)+entry->info.compressed_size; 85 } 86 87 /* 88 * We must return something valid. We'll just use the first glyph in 89 * the font structure (so it should be something distinct). 90 */ 91 entry = (FontArrayEntryHeader *)firstptr; 92 *bufferptr = firstptr + sizeof(FontArrayEntryHeader); 93 *buffersize = entry->info.original_size; 94 return &(entry->info); 95} 96 97void VbRenderTextAtPos(const char *text, int right_to_left, 98 uint32_t x, uint32_t y, VbFont_t *font) 99{ 100 int i; 101 ImageInfo *image_info = 0; 102 void *buffer; 103 uint32_t buffersize; 104 uint32_t cur_x = x, cur_y = y; 105 106 if (!text || !font) { 107 VBDEBUG((" VbRenderTextAtPos: invalid args\n")); 108 return; 109 } 110 111 for (i=0; text[i]; i++) { 112 113 if (text[i] == '\n') { 114 if (!image_info) 115 image_info = VbFindFontGlyph(font, text[i], 116 &buffer, 117 &buffersize); 118 cur_x = x; 119 cur_y += image_info->height; 120 continue; 121 } 122 123 image_info = VbFindFontGlyph(font, text[i], &buffer, 124 &buffersize); 125 126 if (right_to_left) 127 cur_x -= image_info->width; 128 129 if (VBERROR_SUCCESS != VbExDisplayImage(cur_x, cur_y, buffer, 130 buffersize)) { 131 VBDEBUG((" VbRenderTextAtPos: " 132 "can't display ascii 0x%x\n", text[i])); 133 } 134 135 if (!right_to_left) 136 cur_x += image_info->width; 137 } 138} 139 140VbError_t VbDisplayScreenFromGBB(VbCommonParams *cparams, uint32_t screen, 141 VbNvContext *vncptr) 142{ 143 char *fullimage = NULL; 144 BmpBlockHeader hdr; 145 uint32_t screen_index; 146 uint32_t localization = 0; 147 VbError_t retval = VBERROR_UNKNOWN; /* Assume error until proven ok */ 148 uint32_t inoutsize; 149 uint32_t i; 150 VbFont_t *font; 151 const char *text_to_show; 152 int rtol = 0; 153 VbError_t ret; 154 155 ret = VbGbbReadBmpHeader(cparams, &hdr); 156 if (ret) 157 return ret; 158 159 /* 160 * Translate screen ID into index. Note that not all screens are in 161 * the GBB. 162 * 163 * TODO: ensure screen IDs match indices? Having this translation here 164 * is awful. 165 */ 166 switch (screen) { 167 case VB_SCREEN_DEVELOPER_WARNING: 168 screen_index = SCREEN_DEVELOPER_WARNING; 169 break; 170 case VB_SCREEN_RECOVERY_REMOVE: 171 screen_index = SCREEN_RECOVERY_REMOVE; 172 break; 173 case VB_SCREEN_RECOVERY_NO_GOOD: 174 screen_index = SCREEN_RECOVERY_NO_GOOD; 175 break; 176 case VB_SCREEN_RECOVERY_INSERT: 177 screen_index = SCREEN_RECOVERY_INSERT; 178 break; 179 case VB_SCREEN_RECOVERY_TO_DEV: 180 screen_index = SCREEN_RECOVERY_TO_DEV; 181 break; 182 case VB_SCREEN_DEVELOPER_TO_NORM: 183 screen_index = SCREEN_DEVELOPER_TO_NORM; 184 break; 185 case VB_SCREEN_WAIT: 186 screen_index = SCREEN_WAIT; 187 break; 188 case VB_SCREEN_TO_NORM_CONFIRMED: 189 screen_index = SCREEN_TO_NORM_CONFIRMED; 190 break; 191 case VB_SCREEN_BLANK: 192 case VB_SCREEN_DEVELOPER_EGG: 193 default: 194 /* Screens which aren't in the GBB */ 195 VBDEBUG(("VbDisplayScreenFromGBB(): screen %d not in the GBB\n", 196 (int)screen)); 197 retval = VBERROR_INVALID_SCREEN_INDEX; 198 goto VbDisplayScreenFromGBB_exit; 199 } 200 201 if (screen_index >= hdr.number_of_screenlayouts) { 202 VBDEBUG(("VbDisplayScreenFromGBB(): " 203 "screen %d index %d not in the GBB\n", 204 (int)screen, (int)screen_index)); 205 retval = VBERROR_INVALID_SCREEN_INDEX; 206 goto VbDisplayScreenFromGBB_exit; 207 } 208 209 /* Clip localization to number of localizations present in the GBB */ 210 VbNvGet(vncptr, VBNV_LOCALIZATION_INDEX, &localization); 211 if (localization >= hdr.number_of_localizations) { 212 localization = 0; 213 VbNvSet(vncptr, VBNV_LOCALIZATION_INDEX, localization); 214 } 215 216 /* Display all bitmaps for the image */ 217 for (i = 0; i < MAX_IMAGE_IN_LAYOUT; i++) { 218 ScreenLayout layout; 219 ImageInfo image_info; 220 char hwid[256]; 221 222 ret = VbGbbReadImage(cparams, localization, screen_index, 223 i, &layout, &image_info, 224 &fullimage, &inoutsize); 225 if (ret == VBERROR_NO_IMAGE_PRESENT) { 226 continue; 227 } else if (ret) { 228 retval = ret; 229 goto VbDisplayScreenFromGBB_exit; 230 } 231 232 switch(image_info.format) { 233 case FORMAT_BMP: 234 if (i == 0) { 235 /** 236 * In current version GBB bitmaps, first image 237 * is always the background. 238 */ 239 ret = VbExDisplaySetDimension( 240 image_info.width, 241 image_info.height); 242 if (ret) { 243 VBDEBUG(("VbExDisplaySetDimension" 244 "(%d,%d): failed (%#x).\n", 245 image_info.width, 246 image_info.height, ret)); 247 } 248 } 249 250 retval = VbExDisplayImage(layout.images[i].x, 251 layout.images[i].y, 252 fullimage, inoutsize); 253 break; 254 255 case FORMAT_FONT: 256 /* 257 * The uncompressed blob is our font structure. Cache 258 * it as needed. 259 */ 260 font = VbInternalizeFontData( 261 (FontArrayHeader *)fullimage); 262 263 /* TODO: handle text in general here */ 264 if (TAG_HWID == image_info.tag || 265 TAG_HWID_RTOL == image_info.tag) { 266 VbRegionReadHWID(cparams, hwid, sizeof(hwid)); 267 text_to_show = hwid; 268 rtol = (TAG_HWID_RTOL == image_info.tag); 269 } else { 270 text_to_show = ""; 271 rtol = 0; 272 } 273 274 VbRenderTextAtPos(text_to_show, rtol, 275 layout.images[i].x, 276 layout.images[i].y, font); 277 278 VbDoneWithFontForNow(font); 279 break; 280 281 default: 282 VBDEBUG(("VbDisplayScreenFromGBB(): " 283 "unsupported ImageFormat %d\n", 284 image_info.format)); 285 retval = VBERROR_INVALID_GBB; 286 } 287 288 VbExFree(fullimage); 289 290 if (VBERROR_SUCCESS != retval) 291 goto VbDisplayScreenFromGBB_exit; 292 } 293 294 /* Successful if all bitmaps displayed */ 295 retval = VBERROR_SUCCESS; 296 297 VbRegionCheckVersion(cparams); 298 299 VbDisplayScreenFromGBB_exit: 300 VBDEBUG(("leaving VbDisplayScreenFromGBB() with %d\n",retval)); 301 return retval; 302} 303 304VbError_t VbDisplayScreen(VbCommonParams *cparams, uint32_t screen, 305 int force, VbNvContext *vncptr) 306{ 307 VbError_t retval; 308 309 /* Initialize display if necessary */ 310 if (!disp_width) { 311 retval = VbExDisplayInit(&disp_width, &disp_height); 312 if (VBERROR_SUCCESS != retval) 313 return retval; 314 } 315 316 /* If requested screen is the same as the current one, we're done. */ 317 if (disp_current_screen == screen && 0 == force) 318 return VBERROR_SUCCESS; 319 320 /* If the screen is blank, turn off the backlight; else turn it on. */ 321 VbExDisplayBacklight(VB_SCREEN_BLANK == screen ? 0 : 1); 322 323 /* Request the screen */ 324 disp_current_screen = screen; 325 326 /* Look in the GBB first */ 327 if (VBERROR_SUCCESS == VbDisplayScreenFromGBB(cparams, screen, 328 vncptr)) 329 return VBERROR_SUCCESS; 330 331 /* If screen wasn't in the GBB bitmaps, fall back to a default */ 332 return VbExDisplayScreen(screen); 333} 334 335static void Uint8ToString(char *buf, uint8_t val) 336{ 337 const char *trans = "0123456789abcdef"; 338 *buf++ = trans[val >> 4]; 339 *buf = trans[val & 0xF]; 340} 341 342static void FillInSha1Sum(char *outbuf, VbPublicKey *key) 343{ 344 uint8_t *buf = ((uint8_t *)key) + key->key_offset; 345 uint64_t buflen = key->key_size; 346 uint8_t *digest = DigestBuf(buf, buflen, SHA1_DIGEST_ALGORITHM); 347 int i; 348 for (i = 0; i < SHA1_DIGEST_SIZE; i++) { 349 Uint8ToString(outbuf, digest[i]); 350 outbuf += 2; 351 } 352 *outbuf = '\0'; 353 VbExFree(digest); 354} 355 356const char *RecoveryReasonString(uint8_t code) 357{ 358 switch(code) { 359 case VBNV_RECOVERY_NOT_REQUESTED: 360 return "Recovery not requested"; 361 case VBNV_RECOVERY_LEGACY: 362 return "Recovery requested from legacy utility"; 363 case VBNV_RECOVERY_RO_MANUAL: 364 return "recovery button pressed"; 365 case VBNV_RECOVERY_RO_INVALID_RW: 366 return "RW firmware failed signature check"; 367 case VBNV_RECOVERY_RO_S3_RESUME: 368 return "S3 resume failed"; 369 case VBNV_RECOVERY_DEP_RO_TPM_ERROR: 370 return "TPM error in read-only firmware"; 371 case VBNV_RECOVERY_RO_SHARED_DATA: 372 return "Shared data error in read-only firmware"; 373 case VBNV_RECOVERY_RO_TEST_S3: 374 return "Test error from S3Resume()"; 375 case VBNV_RECOVERY_RO_TEST_LFS: 376 return "Test error from LoadFirmwareSetup()"; 377 case VBNV_RECOVERY_RO_TEST_LF: 378 return "Test error from LoadFirmware()"; 379 case VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + VBSD_LF_CHECK_NOT_DONE: 380 return "RW firmware check not done"; 381 case VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + VBSD_LF_CHECK_DEV_MISMATCH: 382 return "RW firmware developer flag mismatch"; 383 case VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + VBSD_LF_CHECK_REC_MISMATCH: 384 return "RW firmware recovery flag mismatch"; 385 case VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + 386 VBSD_LF_CHECK_VERIFY_KEYBLOCK: 387 return "RW firmware unable to verify key block"; 388 case VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + VBSD_LF_CHECK_KEY_ROLLBACK: 389 return "RW firmware key version rollback detected"; 390 case VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + 391 VBSD_LF_CHECK_DATA_KEY_PARSE: 392 return "RW firmware unable to parse data key"; 393 case VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + 394 VBSD_LF_CHECK_VERIFY_PREAMBLE: 395 return "RW firmware unable to verify preamble"; 396 case VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + VBSD_LF_CHECK_FW_ROLLBACK: 397 return "RW firmware version rollback detected"; 398 case VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + VBSD_LF_CHECK_GET_FW_BODY: 399 return "RW firmware unable to get firmware body"; 400 case VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + 401 VBSD_LF_CHECK_HASH_WRONG_SIZE: 402 return "RW firmware hash is wrong size"; 403 case VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + VBSD_LF_CHECK_VERIFY_BODY: 404 return "RW firmware unable to verify firmware body"; 405 case VBNV_RECOVERY_RO_INVALID_RW_CHECK_MIN + VBSD_LF_CHECK_NO_RO_NORMAL: 406 return "RW firmware read-only normal path is not supported"; 407 case VBNV_RECOVERY_RO_FIRMWARE: 408 return "Firmware problem outside of verified boot"; 409 case VBNV_RECOVERY_RO_TPM_REBOOT: 410 return "TPM requires a system reboot (should be transient)"; 411 case VBNV_RECOVERY_EC_SOFTWARE_SYNC: 412 return "EC software sync error"; 413 case VBNV_RECOVERY_EC_UNKNOWN_IMAGE: 414 return "EC software sync unable to determine active EC image"; 415 case VBNV_RECOVERY_DEP_EC_HASH: 416 return "EC software sync error obtaining EC image hash"; 417 case VBNV_RECOVERY_EC_EXPECTED_IMAGE: 418 return "EC software sync error " 419 "obtaining expected EC image from BIOS"; 420 case VBNV_RECOVERY_EC_EXPECTED_HASH: 421 return "EC software sync error " 422 "obtaining expected EC hash from BIOS"; 423 case VBNV_RECOVERY_EC_HASH_MISMATCH: 424 return "EC software sync error " 425 "comparing expected EC hash and image"; 426 case VBNV_RECOVERY_EC_UPDATE: 427 return "EC software sync error updating EC"; 428 case VBNV_RECOVERY_EC_JUMP_RW: 429 return "EC software sync unable to jump to EC-RW"; 430 case VBNV_RECOVERY_EC_PROTECT: 431 return "EC software sync protection error"; 432 case VBNV_RECOVERY_RO_UNSPECIFIED: 433 return "Unspecified/unknown error in RO firmware"; 434 case VBNV_RECOVERY_RW_DEV_SCREEN: 435 return "User requested recovery from dev-mode warning screen"; 436 case VBNV_RECOVERY_RW_NO_OS: 437 return "No OS kernel detected (or kernel rollback attempt?)"; 438 case VBNV_RECOVERY_RW_INVALID_OS: 439 return "OS kernel failed signature check"; 440 case VBNV_RECOVERY_DEP_RW_TPM_ERROR: 441 return "TPM error in rewritable firmware"; 442 case VBNV_RECOVERY_RW_DEV_MISMATCH: 443 return "RW firmware in dev mode, but dev switch is off"; 444 case VBNV_RECOVERY_RW_SHARED_DATA: 445 return "Shared data error in rewritable firmware"; 446 case VBNV_RECOVERY_RW_TEST_LK: 447 return "Test error from LoadKernel()"; 448 case VBNV_RECOVERY_DEP_RW_NO_DISK: 449 return "No bootable disk found"; 450 case VBNV_RECOVERY_TPM_E_FAIL: 451 return "TPM error that was not fixed by reboot"; 452 case VBNV_RECOVERY_RO_TPM_S_ERROR: 453 return "TPM setup error in read-only firmware"; 454 case VBNV_RECOVERY_RO_TPM_W_ERROR: 455 return "TPM write error in read-only firmware"; 456 case VBNV_RECOVERY_RO_TPM_L_ERROR: 457 return "TPM lock error in read-only firmware"; 458 case VBNV_RECOVERY_RO_TPM_U_ERROR: 459 return "TPM update error in read-only firmware"; 460 case VBNV_RECOVERY_RW_TPM_R_ERROR: 461 return "TPM read error in rewritable firmware"; 462 case VBNV_RECOVERY_RW_TPM_W_ERROR: 463 return "TPM write error in rewritable firmware"; 464 case VBNV_RECOVERY_RW_TPM_L_ERROR: 465 return "TPM lock error in rewritable firmware"; 466 case VBNV_RECOVERY_EC_HASH_FAILED: 467 return "EC software sync unable to get EC image hash"; 468 case VBNV_RECOVERY_EC_HASH_SIZE: 469 return "EC software sync invalid image hash size"; 470 case VBNV_RECOVERY_LK_UNSPECIFIED: 471 return "Unspecified error while trying to load kernel"; 472 case VBNV_RECOVERY_RW_NO_DISK: 473 return "No bootable storage device in system"; 474 case VBNV_RECOVERY_RW_NO_KERNEL: 475 return "No bootable kernel found on disk"; 476 case VBNV_RECOVERY_RW_UNSPECIFIED: 477 return "Unspecified/unknown error in RW firmware"; 478 case VBNV_RECOVERY_KE_DM_VERITY: 479 return "DM-verity error"; 480 case VBNV_RECOVERY_KE_UNSPECIFIED: 481 return "Unspecified/unknown error in kernel"; 482 case VBNV_RECOVERY_US_TEST: 483 return "Recovery mode test from user-mode"; 484 case VBNV_RECOVERY_US_UNSPECIFIED: 485 return "Unspecified/unknown error in user-mode"; 486 } 487 return "We have no idea what this means"; 488} 489 490#define DEBUG_INFO_SIZE 512 491 492VbError_t VbDisplayDebugInfo(VbCommonParams *cparams, VbNvContext *vncptr) 493{ 494 VbSharedDataHeader *shared = 495 (VbSharedDataHeader *)cparams->shared_data_blob; 496 GoogleBinaryBlockHeader *gbb = cparams->gbb; 497 char buf[DEBUG_INFO_SIZE] = ""; 498 char sha1sum[SHA1_DIGEST_SIZE * 2 + 1]; 499 char hwid[256]; 500 uint32_t used = 0; 501 VbPublicKey *key; 502 VbError_t ret; 503 uint32_t i; 504 505 /* Redisplay current screen to overwrite any previous debug output */ 506 VbDisplayScreen(cparams, disp_current_screen, 1, vncptr); 507 508 /* Add hardware ID */ 509 VbRegionReadHWID(cparams, hwid, sizeof(hwid)); 510 used += StrnAppend(buf + used, "HWID: ", DEBUG_INFO_SIZE - used); 511 used += StrnAppend(buf + used, hwid, DEBUG_INFO_SIZE - used); 512 513 /* Add recovery reason */ 514 used += StrnAppend(buf + used, 515 "\nrecovery_reason: 0x", DEBUG_INFO_SIZE - used); 516 used += Uint64ToString(buf + used, DEBUG_INFO_SIZE - used, 517 shared->recovery_reason, 16, 2); 518 used += StrnAppend(buf + used, " ", DEBUG_INFO_SIZE - used); 519 used += StrnAppend(buf + used, 520 RecoveryReasonString(shared->recovery_reason), 521 DEBUG_INFO_SIZE - used); 522 523 /* Add VbSharedData flags */ 524 used += StrnAppend(buf + used, "\nVbSD.flags: 0x", DEBUG_INFO_SIZE - used); 525 used += Uint64ToString(buf + used, DEBUG_INFO_SIZE - used, 526 shared->flags, 16, 8); 527 528 /* Add raw contents of VbNvStorage */ 529 used += StrnAppend(buf + used, "\nVbNv.raw:", DEBUG_INFO_SIZE - used); 530 for (i = 0; i < VBNV_BLOCK_SIZE; i++) { 531 used += StrnAppend(buf + used, " ", DEBUG_INFO_SIZE - used); 532 used += Uint64ToString(buf + used, DEBUG_INFO_SIZE - used, 533 vncptr->raw[i], 16, 2); 534 } 535 536 /* Add dev_boot_usb flag */ 537 VbNvGet(vncptr, VBNV_DEV_BOOT_USB, &i); 538 used += StrnAppend(buf + used, "\ndev_boot_usb: ", DEBUG_INFO_SIZE - used); 539 used += Uint64ToString(buf + used, DEBUG_INFO_SIZE - used, i, 10, 0); 540 541 /* Add dev_boot_legacy flag */ 542 VbNvGet(vncptr, VBNV_DEV_BOOT_LEGACY, &i); 543 used += StrnAppend(buf + used, 544 "\ndev_boot_legacy: ", DEBUG_INFO_SIZE - used); 545 used += Uint64ToString(buf + used, DEBUG_INFO_SIZE - used, i, 10, 0); 546 547 /* Add dev_boot_signed_only flag */ 548 VbNvGet(vncptr, VBNV_DEV_BOOT_SIGNED_ONLY, &i); 549 used += StrnAppend(buf + used, "\ndev_boot_signed_only: ", 550 DEBUG_INFO_SIZE - used); 551 used += Uint64ToString(buf + used, DEBUG_INFO_SIZE - used, i, 10, 0); 552 553 /* Add TPM versions */ 554 used += StrnAppend(buf + used, "\nTPM: fwver=0x", DEBUG_INFO_SIZE - used); 555 used += Uint64ToString(buf + used, DEBUG_INFO_SIZE - used, 556 shared->fw_version_tpm, 16, 8); 557 used += StrnAppend(buf + used, " kernver=0x", DEBUG_INFO_SIZE - used); 558 used += Uint64ToString(buf + used, DEBUG_INFO_SIZE - used, 559 shared->kernel_version_tpm, 16, 8); 560 561 /* Add GBB flags */ 562 used += StrnAppend(buf + used, "\ngbb.flags: 0x", DEBUG_INFO_SIZE - used); 563 if (gbb->major_version == GBB_MAJOR_VER && gbb->minor_version >= 1) { 564 used += Uint64ToString(buf + used, DEBUG_INFO_SIZE - used, 565 gbb->flags, 16, 8); 566 } else { 567 used += StrnAppend(buf + used, 568 "0 (default)", DEBUG_INFO_SIZE - used); 569 } 570 571 /* Add sha1sum for Root & Recovery keys */ 572 ret = VbGbbReadRootKey(cparams, &key); 573 if (!ret) { 574 FillInSha1Sum(sha1sum, key); 575 VbExFree(key); 576 used += StrnAppend(buf + used, "\ngbb.rootkey: ", 577 DEBUG_INFO_SIZE - used); 578 used += StrnAppend(buf + used, sha1sum, 579 DEBUG_INFO_SIZE - used); 580 } 581 582 ret = VbGbbReadRecoveryKey(cparams, &key); 583 if (!ret) { 584 FillInSha1Sum(sha1sum, key); 585 VbExFree(key); 586 used += StrnAppend(buf + used, "\ngbb.recovery_key: ", 587 DEBUG_INFO_SIZE - used); 588 used += StrnAppend(buf + used, sha1sum, 589 DEBUG_INFO_SIZE - used); 590 } 591 592 /* If we're in dev-mode, show the kernel subkey that we expect, too. */ 593 if (0 == shared->recovery_reason) { 594 FillInSha1Sum(sha1sum, &shared->kernel_subkey); 595 used += StrnAppend(buf + used, 596 "\nkernel_subkey: ", DEBUG_INFO_SIZE - used); 597 used += StrnAppend(buf + used, sha1sum, DEBUG_INFO_SIZE - used); 598 } 599 600 /* Make sure we finish with a newline */ 601 used += StrnAppend(buf + used, "\n", DEBUG_INFO_SIZE - used); 602 603 /* TODO: add more interesting data: 604 * - Information on current disks */ 605 606 buf[DEBUG_INFO_SIZE - 1] = '\0'; 607 return VbExDisplayDebugInfo(buf); 608} 609 610#define MAGIC_WORD_LEN 5 611#define MAGIC_WORD "xyzzy" 612static uint8_t MagicBuffer[MAGIC_WORD_LEN]; 613 614VbError_t VbCheckDisplayKey(VbCommonParams *cparams, uint32_t key, 615 VbNvContext *vncptr) 616{ 617 int i; 618 619 /* Update key buffer */ 620 for(i = 1; i < MAGIC_WORD_LEN; i++) 621 MagicBuffer[i - 1] = MagicBuffer[i]; 622 /* Save as lower-case ASCII */ 623 MagicBuffer[MAGIC_WORD_LEN - 1] = (key | 0x20) & 0xFF; 624 625 if ('\t' == key) { 626 /* Tab = display debug info */ 627 return VbDisplayDebugInfo(cparams, vncptr); 628 } else if (VB_KEY_LEFT == key || VB_KEY_RIGHT == key || 629 VB_KEY_DOWN == key || VB_KEY_UP == key) { 630 /* Arrow keys = change localization */ 631 uint32_t loc = 0; 632 uint32_t count = 0; 633 634 VbNvGet(vncptr, VBNV_LOCALIZATION_INDEX, &loc); 635 if (VBERROR_SUCCESS != VbGetLocalizationCount(cparams, &count)) 636 loc = 0; /* No localization count (bad GBB?) */ 637 else if (VB_KEY_RIGHT == key || VB_KEY_UP == key) 638 loc = (loc < count - 1 ? loc + 1 : 0); 639 else 640 loc = (loc > 0 ? loc - 1 : count - 1); 641 VBDEBUG(("VbCheckDisplayKey() - change localization to %d\n", 642 (int)loc)); 643 VbNvSet(vncptr, VBNV_LOCALIZATION_INDEX, loc); 644 645#ifdef SAVE_LOCALE_IMMEDIATELY 646 VbNvTeardown(vncptr); /* really only computes checksum */ 647 if (vncptr->raw_changed) 648 VbExNvStorageWrite(vncptr->raw); 649#endif 650 651 /* Force redraw of current screen */ 652 return VbDisplayScreen(cparams, disp_current_screen, 1, vncptr); 653 } 654 655 if (0 == Memcmp(MagicBuffer, MAGIC_WORD, MAGIC_WORD_LEN)) { 656 if (VBEASTEREGG) 657 (void)VbDisplayScreen(cparams, disp_current_screen, 658 1, vncptr); 659 } 660 661 return VBERROR_SUCCESS; 662} 663