vboot_display.c 23 KB

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