crossystem.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883
  1. /* Copyright (c) 2012 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. #include <stddef.h>
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include <sys/types.h>
  9. #include <sys/stat.h>
  10. #include <unistd.h>
  11. #include <ctype.h>
  12. #include <sys/types.h>
  13. #include <sys/stat.h>
  14. #include <sys/wait.h>
  15. #include <fcntl.h>
  16. #include <unistd.h>
  17. #include "host_common.h"
  18. #include "crossystem.h"
  19. #include "crossystem_arch.h"
  20. #include "crossystem_vbnv.h"
  21. #include "utility.h"
  22. #include "vboot_common.h"
  23. #include "vboot_nvstorage.h"
  24. #include "vboot_struct.h"
  25. /* Filename for kernel command line */
  26. #define KERNEL_CMDLINE_PATH "/proc/cmdline"
  27. #define MOSYS_CROS_PATH "/usr/sbin/mosys"
  28. #define MOSYS_ANDROID_PATH "/system/bin/mosys"
  29. /* Fields that GetVdatString() can get */
  30. typedef enum VdatStringField {
  31. VDAT_STRING_TIMERS = 0, /* Timer values */
  32. VDAT_STRING_LOAD_FIRMWARE_DEBUG, /* LoadFirmware() debug information */
  33. VDAT_STRING_LOAD_KERNEL_DEBUG, /* LoadKernel() debug information */
  34. VDAT_STRING_MAINFW_ACT /* Active main firmware */
  35. } VdatStringField;
  36. /* Fields that GetVdatInt() can get */
  37. typedef enum VdatIntField {
  38. VDAT_INT_FLAGS = 0, /* Flags */
  39. VDAT_INT_HEADER_VERSION, /* Header version for VbSharedData */
  40. VDAT_INT_DEVSW_BOOT, /* Dev switch position at boot */
  41. VDAT_INT_DEVSW_VIRTUAL, /* Dev switch is virtual */
  42. VDAT_INT_RECSW_BOOT, /* Recovery switch position at boot */
  43. VDAT_INT_HW_WPSW_BOOT, /* Hardware WP switch position at boot */
  44. VDAT_INT_SW_WPSW_BOOT, /* Flash chip's WP setting at boot */
  45. VDAT_INT_FW_VERSION_TPM, /* Current firmware version in TPM */
  46. VDAT_INT_KERNEL_VERSION_TPM, /* Current kernel version in TPM */
  47. VDAT_INT_TRIED_FIRMWARE_B, /* Tried firmware B due to fwb_tries */
  48. VDAT_INT_KERNEL_KEY_VERIFIED, /* Kernel key verified using
  49. * signature, not just hash */
  50. VDAT_INT_RECOVERY_REASON, /* Recovery reason for current boot */
  51. VDAT_INT_FW_BOOT2 /* Firmware selection by vboot2 */
  52. } VdatIntField;
  53. /* Description of build options that may be specified on the
  54. * kernel command line. */
  55. typedef enum VbBuildOption {
  56. VB_BUILD_OPTION_UNKNOWN,
  57. VB_BUILD_OPTION_DEBUG,
  58. VB_BUILD_OPTION_NODEBUG
  59. } VbBuildOption;
  60. static const char *fw_results[] = {"unknown", "trying", "success", "failure"};
  61. static const char *default_boot[] = {"disk", "usb", "legacy"};
  62. /* Masks for kern_nv usage by kernel. */
  63. #define KERN_NV_FWUPDATE_TRIES_MASK 0x0000000F
  64. #define KERN_NV_BLOCK_DEVMODE_FLAG 0x00000010
  65. #define KERN_NV_TPM_ATTACK_FLAG 0x00000020
  66. /* If you want to use the remaining currently-unused bits in kern_nv
  67. * for something kernel-y, define a new field (the way we did for
  68. * fwupdate_tries). Don't just modify kern_nv directly, because that
  69. * makes it too easy to accidentally corrupt other sub-fields. */
  70. #define KERN_NV_CURRENTLY_UNUSED 0xFFFFFFC0
  71. /* Return true if the FWID starts with the specified string. */
  72. int FwidStartsWith(const char *start)
  73. {
  74. char fwid[VB_MAX_STRING_PROPERTY];
  75. if (!VbGetSystemPropertyString("fwid", fwid, sizeof(fwid)))
  76. return 0;
  77. return 0 == strncmp(fwid, start, strlen(start));
  78. }
  79. static int vnc_read;
  80. int VbGetNvStorage(VbNvParam param)
  81. {
  82. uint32_t value;
  83. int retval;
  84. static VbNvContext cached_vnc;
  85. /* TODO: locking around NV access */
  86. if (!vnc_read) {
  87. if (0 != VbReadNvStorage(&cached_vnc))
  88. return -1;
  89. vnc_read = 1;
  90. }
  91. if (0 != VbNvSetup(&cached_vnc))
  92. return -1;
  93. retval = VbNvGet(&cached_vnc, param, &value);
  94. if (0 != VbNvTeardown(&cached_vnc))
  95. return -1;
  96. if (0 != retval)
  97. return -1;
  98. /* TODO: If vnc.raw_changed, attempt to reopen NVRAM for write and
  99. * save the new defaults. If we're able to, log. */
  100. /* TODO: release lock */
  101. return (int)value;
  102. }
  103. int VbSetNvStorage(VbNvParam param, int value)
  104. {
  105. VbNvContext vnc;
  106. int retval = -1;
  107. int i;
  108. if (0 != VbReadNvStorage(&vnc))
  109. return -1;
  110. if (0 != VbNvSetup(&vnc))
  111. goto VbSetNvCleanup;
  112. i = VbNvSet(&vnc, param, (uint32_t)value);
  113. if (0 != VbNvTeardown(&vnc))
  114. goto VbSetNvCleanup;
  115. if (0 != i)
  116. goto VbSetNvCleanup;
  117. if (vnc.raw_changed) {
  118. vnc_read = 0;
  119. if (0 != VbWriteNvStorage(&vnc))
  120. goto VbSetNvCleanup;
  121. }
  122. /* Success */
  123. retval = 0;
  124. VbSetNvCleanup:
  125. /* TODO: release lock */
  126. return retval;
  127. }
  128. /*
  129. * Set a param value, and try to flag it for persistent backup.
  130. * It's okay if backup isn't supported. It's best-effort only.
  131. */
  132. static int VbSetNvStorage_WithBackup(VbNvParam param, int value)
  133. {
  134. int retval;
  135. retval = VbSetNvStorage(param, value);
  136. if (!retval)
  137. VbSetNvStorage(VBNV_BACKUP_NVRAM_REQUEST, 1);
  138. return retval;
  139. }
  140. /* Find what build/debug status is specified on the kernel command
  141. * line, if any. */
  142. static VbBuildOption VbScanBuildOption(void)
  143. {
  144. FILE* f = NULL;
  145. char buf[4096] = "";
  146. char *t, *saveptr;
  147. const char *delimiters = " \r\n";
  148. f = fopen(KERNEL_CMDLINE_PATH, "r");
  149. if (NULL != f) {
  150. if (NULL == fgets(buf, sizeof(buf), f))
  151. buf[0] = 0;
  152. fclose(f);
  153. }
  154. for (t = strtok_r(buf, delimiters, &saveptr); t;
  155. t = strtok_r(NULL, delimiters, &saveptr)) {
  156. if (0 == strcmp(t, "cros_debug"))
  157. return VB_BUILD_OPTION_DEBUG;
  158. else if (0 == strcmp(t, "cros_nodebug"))
  159. return VB_BUILD_OPTION_NODEBUG;
  160. }
  161. return VB_BUILD_OPTION_UNKNOWN;
  162. }
  163. /* Determine whether the running OS image was built for debugging.
  164. * Returns 1 if yes, 0 if no or indeterminate. */
  165. int VbGetDebugBuild(void)
  166. {
  167. return VB_BUILD_OPTION_DEBUG == VbScanBuildOption();
  168. }
  169. /* Determine whether OS-level debugging should be allowed.
  170. * Returns 1 if yes, 0 if no or indeterminate. */
  171. int VbGetCrosDebug(void)
  172. {
  173. /* If the currently running system specifies its debug status, use
  174. * that in preference to other indicators. */
  175. VbBuildOption option = VbScanBuildOption();
  176. if (VB_BUILD_OPTION_DEBUG == option) {
  177. return 1;
  178. } else if (VB_BUILD_OPTION_NODEBUG == option) {
  179. return 0;
  180. }
  181. /* Command line is silent; allow debug if the dev switch is on. */
  182. if (1 == VbGetSystemPropertyInt("devsw_boot"))
  183. return 1;
  184. /* All other cases disallow debug. */
  185. return 0;
  186. }
  187. char *GetVdatLoadFirmwareDebug(char *dest, int size,
  188. const VbSharedDataHeader *sh)
  189. {
  190. snprintf(dest, size,
  191. "Check A result=%d\n"
  192. "Check B result=%d\n"
  193. "Firmware index booted=0x%02x\n"
  194. "TPM combined version at start=0x%08x\n"
  195. "Lowest combined version from firmware=0x%08x\n",
  196. sh->check_fw_a_result,
  197. sh->check_fw_b_result,
  198. sh->firmware_index,
  199. sh->fw_version_tpm_start,
  200. sh->fw_version_lowest);
  201. return dest;
  202. }
  203. #define TRUNCATED "\n(truncated)\n"
  204. char *GetVdatLoadKernelDebug(char *dest, int size,
  205. const VbSharedDataHeader *sh)
  206. {
  207. int used = 0;
  208. int first_call_tracked = 0;
  209. int call;
  210. /* Make sure we have space for truncation warning */
  211. if (size < strlen(TRUNCATED) + 1)
  212. return NULL;
  213. size -= strlen(TRUNCATED) + 1;
  214. used += snprintf(
  215. dest + used, size - used,
  216. "Calls to LoadKernel()=%d\n",
  217. sh->lk_call_count);
  218. if (used > size)
  219. goto LoadKernelDebugExit;
  220. /* Report on the last calls */
  221. if (sh->lk_call_count > VBSD_MAX_KERNEL_CALLS)
  222. first_call_tracked = sh->lk_call_count - VBSD_MAX_KERNEL_CALLS;
  223. for (call = first_call_tracked; call < sh->lk_call_count; call++) {
  224. const VbSharedDataKernelCall* shc = sh->lk_calls +
  225. (call & (VBSD_MAX_KERNEL_CALLS - 1));
  226. int first_part_tracked = 0;
  227. int part;
  228. used += snprintf(dest + used, size - used,
  229. "Call %d:\n"
  230. " Boot flags=0x%02x\n"
  231. " Boot mode=%d\n"
  232. " Test error=%d\n"
  233. " Return code=%d\n"
  234. " Debug flags=0x%02x\n"
  235. " Drive sectors=%" PRIu64 "\n"
  236. " Sector size=%d\n"
  237. " Check result=%d\n"
  238. " Kernel partitions found=%d\n",
  239. call + 1,
  240. shc->boot_flags,
  241. shc->boot_mode,
  242. shc->test_error_num,
  243. shc->return_code,
  244. shc->flags,
  245. shc->sector_count,
  246. shc->sector_size,
  247. shc->check_result,
  248. shc->kernel_parts_found);
  249. if (used > size)
  250. goto LoadKernelDebugExit;
  251. /* If we found too many partitions, only prints ones where the
  252. * structure has info. */
  253. if (shc->kernel_parts_found > VBSD_MAX_KERNEL_PARTS)
  254. first_part_tracked = shc->kernel_parts_found -
  255. VBSD_MAX_KERNEL_PARTS;
  256. /* Report on the partitions checked */
  257. for (part = first_part_tracked; part < shc->kernel_parts_found;
  258. part++) {
  259. const VbSharedDataKernelPart* shp = shc->parts +
  260. (part & (VBSD_MAX_KERNEL_PARTS - 1));
  261. used += snprintf(dest + used, size - used,
  262. " Kernel %d:\n"
  263. " GPT index=%d\n"
  264. " Start sector=%" PRIu64 "\n"
  265. " Sector count=%" PRIu64 "\n"
  266. " Combined version=0x%08x\n"
  267. " Check result=%d\n"
  268. " Debug flags=0x%02x\n",
  269. part + 1,
  270. shp->gpt_index,
  271. shp->sector_start,
  272. shp->sector_count,
  273. shp->combined_version,
  274. shp->check_result,
  275. shp->flags);
  276. if (used > size)
  277. goto LoadKernelDebugExit;
  278. }
  279. }
  280. LoadKernelDebugExit:
  281. /* Warn if data was truncated; we left space for this above. */
  282. if (used > size)
  283. strcat(dest, TRUNCATED);
  284. return dest;
  285. }
  286. char *GetVdatString(char *dest, int size, VdatStringField field)
  287. {
  288. VbSharedDataHeader *sh = VbSharedDataRead();
  289. char *value = dest;
  290. if (!sh)
  291. return NULL;
  292. switch (field) {
  293. case VDAT_STRING_TIMERS:
  294. snprintf(dest, size,
  295. "LFS=%" PRIu64 ",%" PRIu64
  296. " LF=%" PRIu64 ",%" PRIu64
  297. " LK=%" PRIu64 ",%" PRIu64,
  298. sh->timer_vb_init_enter,
  299. sh->timer_vb_init_exit,
  300. sh->timer_vb_select_firmware_enter,
  301. sh->timer_vb_select_firmware_exit,
  302. sh->timer_vb_select_and_load_kernel_enter,
  303. sh->timer_vb_select_and_load_kernel_exit);
  304. break;
  305. case VDAT_STRING_LOAD_FIRMWARE_DEBUG:
  306. value = GetVdatLoadFirmwareDebug(dest, size, sh);
  307. break;
  308. case VDAT_STRING_LOAD_KERNEL_DEBUG:
  309. value = GetVdatLoadKernelDebug(dest, size, sh);
  310. break;
  311. case VDAT_STRING_MAINFW_ACT:
  312. switch(sh->firmware_index) {
  313. case 0:
  314. StrCopy(dest, "A", size);
  315. break;
  316. case 1:
  317. StrCopy(dest, "B", size);
  318. break;
  319. case 0xFF:
  320. StrCopy(dest, "recovery", size);
  321. break;
  322. default:
  323. value = NULL;
  324. }
  325. break;
  326. default:
  327. value = NULL;
  328. break;
  329. }
  330. free(sh);
  331. return value;
  332. }
  333. int GetVdatInt(VdatIntField field)
  334. {
  335. VbSharedDataHeader* sh = VbSharedDataRead();
  336. int value = -1;
  337. if (!sh)
  338. return -1;
  339. /* Fields supported in version 1 */
  340. switch (field) {
  341. case VDAT_INT_FLAGS:
  342. value = (int)sh->flags;
  343. break;
  344. case VDAT_INT_HEADER_VERSION:
  345. value = sh->struct_version;
  346. break;
  347. case VDAT_INT_TRIED_FIRMWARE_B:
  348. value = (sh->flags & VBSD_FWB_TRIED ? 1 : 0);
  349. break;
  350. case VDAT_INT_KERNEL_KEY_VERIFIED:
  351. value = (sh->flags & VBSD_KERNEL_KEY_VERIFIED ? 1 : 0);
  352. break;
  353. case VDAT_INT_FW_VERSION_TPM:
  354. value = (int)sh->fw_version_tpm;
  355. break;
  356. case VDAT_INT_KERNEL_VERSION_TPM:
  357. value = (int)sh->kernel_version_tpm;
  358. break;
  359. case VDAT_INT_FW_BOOT2:
  360. value = (sh->flags & VBSD_BOOT_FIRMWARE_VBOOT2 ? 1 : 0);
  361. default:
  362. break;
  363. }
  364. /* Fields added in struct version 2 */
  365. if (sh->struct_version >= 2) {
  366. switch(field) {
  367. case VDAT_INT_DEVSW_BOOT:
  368. value = (sh->flags &
  369. VBSD_BOOT_DEV_SWITCH_ON ? 1 : 0);
  370. break;
  371. case VDAT_INT_DEVSW_VIRTUAL:
  372. value = (sh->flags &
  373. VBSD_HONOR_VIRT_DEV_SWITCH ? 1 : 0);
  374. break;
  375. case VDAT_INT_RECSW_BOOT:
  376. value = (sh->flags &
  377. VBSD_BOOT_REC_SWITCH_ON ? 1 : 0);
  378. break;
  379. case VDAT_INT_HW_WPSW_BOOT:
  380. value = (sh->flags &
  381. VBSD_BOOT_FIRMWARE_WP_ENABLED ? 1 : 0);
  382. break;
  383. case VDAT_INT_SW_WPSW_BOOT:
  384. value = (sh->flags &
  385. VBSD_BOOT_FIRMWARE_SW_WP_ENABLED ?
  386. 1 : 0);
  387. break;
  388. case VDAT_INT_RECOVERY_REASON:
  389. value = sh->recovery_reason;
  390. break;
  391. default:
  392. break;
  393. }
  394. }
  395. free(sh);
  396. return value;
  397. }
  398. /* Return version of VbSharedData struct or -1 if not found. */
  399. int VbSharedDataVersion(void)
  400. {
  401. return GetVdatInt(VDAT_INT_HEADER_VERSION);
  402. }
  403. int VbGetSystemPropertyInt(const char *name)
  404. {
  405. int value = -1;
  406. /* Check architecture-dependent properties first */
  407. value = VbGetArchPropertyInt(name);
  408. if (-1 != value)
  409. return value;
  410. /* NV storage values */
  411. else if (!strcasecmp(name,"kern_nv")) {
  412. value = VbGetNvStorage(VBNV_KERNEL_FIELD);
  413. } else if (!strcasecmp(name,"nvram_cleared")) {
  414. value = VbGetNvStorage(VBNV_KERNEL_SETTINGS_RESET);
  415. } else if (!strcasecmp(name,"recovery_request")) {
  416. value = VbGetNvStorage(VBNV_RECOVERY_REQUEST);
  417. } else if (!strcasecmp(name,"dbg_reset")) {
  418. value = VbGetNvStorage(VBNV_DEBUG_RESET_MODE);
  419. } else if (!strcasecmp(name,"disable_dev_request")) {
  420. value = VbGetNvStorage(VBNV_DISABLE_DEV_REQUEST);
  421. } else if (!strcasecmp(name,"clear_tpm_owner_request")) {
  422. value = VbGetNvStorage(VBNV_CLEAR_TPM_OWNER_REQUEST);
  423. } else if (!strcasecmp(name,"clear_tpm_owner_done")) {
  424. value = VbGetNvStorage(VBNV_CLEAR_TPM_OWNER_DONE);
  425. } else if (!strcasecmp(name,"tpm_rebooted")) {
  426. value = VbGetNvStorage(VBNV_TPM_REQUESTED_REBOOT);
  427. } else if (!strcasecmp(name,"fwb_tries")) {
  428. value = VbGetNvStorage(VBNV_TRY_B_COUNT);
  429. } else if (!strcasecmp(name,"fw_vboot2")) {
  430. value = GetVdatInt(VDAT_INT_FW_BOOT2);
  431. } else if (!strcasecmp(name,"fw_try_count")) {
  432. value = VbGetNvStorage(VBNV_FW_TRY_COUNT);
  433. } else if (!strcasecmp(name,"fwupdate_tries")) {
  434. value = VbGetNvStorage(VBNV_KERNEL_FIELD);
  435. if (value != -1)
  436. value &= KERN_NV_FWUPDATE_TRIES_MASK;
  437. } else if (!strcasecmp(name,"block_devmode")) {
  438. value = VbGetNvStorage(VBNV_KERNEL_FIELD);
  439. if (value != -1) {
  440. value &= KERN_NV_BLOCK_DEVMODE_FLAG;
  441. value = !!value;
  442. }
  443. } else if (!strcasecmp(name,"tpm_attack")) {
  444. value = VbGetNvStorage(VBNV_KERNEL_FIELD);
  445. if (value != -1) {
  446. value &= KERN_NV_TPM_ATTACK_FLAG;
  447. value = !!value;
  448. }
  449. } else if (!strcasecmp(name,"loc_idx")) {
  450. value = VbGetNvStorage(VBNV_LOCALIZATION_INDEX);
  451. } else if (!strcasecmp(name,"backup_nvram_request")) {
  452. value = VbGetNvStorage(VBNV_BACKUP_NVRAM_REQUEST);
  453. } else if (!strcasecmp(name,"dev_boot_usb")) {
  454. value = VbGetNvStorage(VBNV_DEV_BOOT_USB);
  455. } else if (!strcasecmp(name,"dev_boot_legacy")) {
  456. value = VbGetNvStorage(VBNV_DEV_BOOT_LEGACY);
  457. } else if (!strcasecmp(name,"dev_boot_signed_only")) {
  458. value = VbGetNvStorage(VBNV_DEV_BOOT_SIGNED_ONLY);
  459. } else if (!strcasecmp(name,"dev_boot_fastboot_full_cap")) {
  460. value = VbGetNvStorage(VBNV_DEV_BOOT_FASTBOOT_FULL_CAP);
  461. } else if (!strcasecmp(name,"oprom_needed")) {
  462. value = VbGetNvStorage(VBNV_OPROM_NEEDED);
  463. } else if (!strcasecmp(name,"recovery_subcode")) {
  464. value = VbGetNvStorage(VBNV_RECOVERY_SUBCODE);
  465. } else if (!strcasecmp(name,"wipeout_request")) {
  466. value = VbGetNvStorage(VBNV_FW_REQ_WIPEOUT);
  467. }
  468. /* Other parameters */
  469. else if (!strcasecmp(name,"cros_debug")) {
  470. value = VbGetCrosDebug();
  471. } else if (!strcasecmp(name,"debug_build")) {
  472. value = VbGetDebugBuild();
  473. } else if (!strcasecmp(name,"devsw_boot")) {
  474. value = GetVdatInt(VDAT_INT_DEVSW_BOOT);
  475. } else if (!strcasecmp(name,"devsw_virtual")) {
  476. value = GetVdatInt(VDAT_INT_DEVSW_VIRTUAL);
  477. } else if (!strcasecmp(name, "recoverysw_boot")) {
  478. value = GetVdatInt(VDAT_INT_RECSW_BOOT);
  479. } else if (!strcasecmp(name, "wpsw_boot")) {
  480. value = GetVdatInt(VDAT_INT_HW_WPSW_BOOT);
  481. } else if (!strcasecmp(name, "sw_wpsw_boot")) {
  482. value = GetVdatInt(VDAT_INT_SW_WPSW_BOOT);
  483. } else if (!strcasecmp(name,"vdat_flags")) {
  484. value = GetVdatInt(VDAT_INT_FLAGS);
  485. } else if (!strcasecmp(name,"tpm_fwver")) {
  486. value = GetVdatInt(VDAT_INT_FW_VERSION_TPM);
  487. } else if (!strcasecmp(name,"tpm_kernver")) {
  488. value = GetVdatInt(VDAT_INT_KERNEL_VERSION_TPM);
  489. } else if (!strcasecmp(name,"tried_fwb")) {
  490. value = GetVdatInt(VDAT_INT_TRIED_FIRMWARE_B);
  491. } else if (!strcasecmp(name,"recovery_reason")) {
  492. value = GetVdatInt(VDAT_INT_RECOVERY_REASON);
  493. } else if (!strcasecmp(name, "fastboot_unlock_in_fw")) {
  494. value = VbGetNvStorage(VBNV_FASTBOOT_UNLOCK_IN_FW);
  495. } else if (!strcasecmp(name, "boot_on_ac_detect")) {
  496. value = VbGetNvStorage(VBNV_BOOT_ON_AC_DETECT);
  497. } else if (!strcasecmp(name, "try_ro_sync")) {
  498. value = VbGetNvStorage(VBNV_TRY_RO_SYNC);
  499. } else if (!strcasecmp(name, "battery_cutoff_request")) {
  500. value = VbGetNvStorage(VBNV_BATTERY_CUTOFF_REQUEST);
  501. } else if (!strcasecmp(name, "inside_vm")) {
  502. /* Detect if the host is a VM. If there is no HWID and the
  503. * firmware type is "nonchrome", then assume it is a VM. If
  504. * HWID is present, it is a baremetal Chrome OS machine. Other
  505. * cases are errors. */
  506. char hwid[VB_MAX_STRING_PROPERTY];
  507. if (!VbGetSystemPropertyString("hwid", hwid, sizeof(hwid))) {
  508. char fwtype_buf[VB_MAX_STRING_PROPERTY];
  509. const char *fwtype = VbGetSystemPropertyString(
  510. "mainfw_type", fwtype_buf, sizeof(fwtype_buf));
  511. if (fwtype && !strcasecmp(fwtype, "nonchrome")) {
  512. value = 1;
  513. }
  514. } else {
  515. value = 0;
  516. }
  517. }
  518. return value;
  519. }
  520. const char *VbGetSystemPropertyString(const char *name, char *dest,
  521. size_t size)
  522. {
  523. /* Check architecture-dependent properties first */
  524. if (VbGetArchPropertyString(name, dest, size))
  525. return dest;
  526. if (!strcasecmp(name,"kernkey_vfy")) {
  527. switch(GetVdatInt(VDAT_INT_KERNEL_KEY_VERIFIED)) {
  528. case 0:
  529. return "hash";
  530. case 1:
  531. return "sig";
  532. default:
  533. return NULL;
  534. }
  535. } else if (!strcasecmp(name, "mainfw_act")) {
  536. return GetVdatString(dest, size, VDAT_STRING_MAINFW_ACT);
  537. } else if (!strcasecmp(name, "vdat_timers")) {
  538. return GetVdatString(dest, size, VDAT_STRING_TIMERS);
  539. } else if (!strcasecmp(name, "vdat_lfdebug")) {
  540. return GetVdatString(dest, size,
  541. VDAT_STRING_LOAD_FIRMWARE_DEBUG);
  542. } else if (!strcasecmp(name, "vdat_lkdebug")) {
  543. return GetVdatString(dest, size, VDAT_STRING_LOAD_KERNEL_DEBUG);
  544. } else if (!strcasecmp(name, "fw_try_next")) {
  545. return VbGetNvStorage(VBNV_FW_TRY_NEXT) ? "B" : "A";
  546. } else if (!strcasecmp(name, "fw_tried")) {
  547. return VbGetNvStorage(VBNV_FW_TRIED) ? "B" : "A";
  548. } else if (!strcasecmp(name, "fw_result")) {
  549. int v = VbGetNvStorage(VBNV_FW_RESULT);
  550. if (v < ARRAY_SIZE(fw_results))
  551. return fw_results[v];
  552. else
  553. return "unknown";
  554. } else if (!strcasecmp(name, "fw_prev_tried")) {
  555. return VbGetNvStorage(VBNV_FW_PREV_TRIED) ? "B" : "A";
  556. } else if (!strcasecmp(name, "fw_prev_result")) {
  557. int v = VbGetNvStorage(VBNV_FW_PREV_RESULT);
  558. if (v < ARRAY_SIZE(fw_results))
  559. return fw_results[v];
  560. else
  561. return "unknown";
  562. } else if (!strcasecmp(name,"dev_default_boot")) {
  563. int v = VbGetNvStorage(VBNV_DEV_DEFAULT_BOOT);
  564. if (v < ARRAY_SIZE(default_boot))
  565. return default_boot[v];
  566. else
  567. return "unknown";
  568. }
  569. return NULL;
  570. }
  571. int VbSetSystemPropertyInt(const char *name, int value)
  572. {
  573. /* Check architecture-dependent properties first */
  574. if (0 == VbSetArchPropertyInt(name, value))
  575. return 0;
  576. /* NV storage values */
  577. if (!strcasecmp(name,"nvram_cleared")) {
  578. /* Can only clear this flag; it's set inside the NV storage
  579. * library. */
  580. return VbSetNvStorage(VBNV_KERNEL_SETTINGS_RESET, 0);
  581. } else if (!strcasecmp(name,"recovery_request")) {
  582. return VbSetNvStorage(VBNV_RECOVERY_REQUEST, value);
  583. } else if (!strcasecmp(name,"recovery_subcode")) {
  584. return VbSetNvStorage(VBNV_RECOVERY_SUBCODE, value);
  585. } else if (!strcasecmp(name,"dbg_reset")) {
  586. return VbSetNvStorage(VBNV_DEBUG_RESET_MODE, value);
  587. } else if (!strcasecmp(name,"disable_dev_request")) {
  588. return VbSetNvStorage(VBNV_DISABLE_DEV_REQUEST, value);
  589. } else if (!strcasecmp(name,"clear_tpm_owner_request")) {
  590. return VbSetNvStorage(VBNV_CLEAR_TPM_OWNER_REQUEST, value);
  591. } else if (!strcasecmp(name,"clear_tpm_owner_done")) {
  592. /* Can only clear this flag; it's set by firmware. */
  593. return VbSetNvStorage(VBNV_CLEAR_TPM_OWNER_DONE, 0);
  594. } else if (!strcasecmp(name,"fwb_tries")) {
  595. return VbSetNvStorage(VBNV_TRY_B_COUNT, value);
  596. } else if (!strcasecmp(name,"fw_try_count")) {
  597. return VbSetNvStorage(VBNV_FW_TRY_COUNT, value);
  598. } else if (!strcasecmp(name,"oprom_needed")) {
  599. return VbSetNvStorage(VBNV_OPROM_NEEDED, value);
  600. } else if (!strcasecmp(name,"wipeout_request")) {
  601. /* Can only clear this flag, set only by firmware. */
  602. return VbSetNvStorage(VBNV_FW_REQ_WIPEOUT, 0);
  603. } else if (!strcasecmp(name,"backup_nvram_request")) {
  604. /* Best-effort only, since it requires firmware and TPM
  605. * support. */
  606. return VbSetNvStorage(VBNV_BACKUP_NVRAM_REQUEST, value);
  607. } else if (!strcasecmp(name,"fwupdate_tries")) {
  608. int kern_nv = VbGetNvStorage(VBNV_KERNEL_FIELD);
  609. if (kern_nv == -1)
  610. return -1;
  611. kern_nv &= ~KERN_NV_FWUPDATE_TRIES_MASK;
  612. kern_nv |= (value & KERN_NV_FWUPDATE_TRIES_MASK);
  613. return VbSetNvStorage_WithBackup(VBNV_KERNEL_FIELD, kern_nv);
  614. } else if (!strcasecmp(name,"block_devmode")) {
  615. int kern_nv = VbGetNvStorage(VBNV_KERNEL_FIELD);
  616. if (kern_nv == -1)
  617. return -1;
  618. kern_nv &= ~KERN_NV_BLOCK_DEVMODE_FLAG;
  619. if (value)
  620. kern_nv |= KERN_NV_BLOCK_DEVMODE_FLAG;
  621. return VbSetNvStorage_WithBackup(VBNV_KERNEL_FIELD, kern_nv);
  622. } else if (!strcasecmp(name,"tpm_attack")) {
  623. /* This value should only be read and cleared, but we allow
  624. * setting it to 1 for testing. */
  625. int kern_nv = VbGetNvStorage(VBNV_KERNEL_FIELD);
  626. if (kern_nv == -1)
  627. return -1;
  628. kern_nv &= ~KERN_NV_TPM_ATTACK_FLAG;
  629. if (value)
  630. kern_nv |= KERN_NV_TPM_ATTACK_FLAG;
  631. return VbSetNvStorage_WithBackup(VBNV_KERNEL_FIELD, kern_nv);
  632. } else if (!strcasecmp(name,"loc_idx")) {
  633. return VbSetNvStorage_WithBackup(VBNV_LOCALIZATION_INDEX,
  634. value);
  635. } else if (!strcasecmp(name,"dev_boot_usb")) {
  636. return VbSetNvStorage_WithBackup(VBNV_DEV_BOOT_USB, value);
  637. } else if (!strcasecmp(name,"dev_boot_legacy")) {
  638. return VbSetNvStorage_WithBackup(VBNV_DEV_BOOT_LEGACY, value);
  639. } else if (!strcasecmp(name,"dev_boot_signed_only")) {
  640. return VbSetNvStorage_WithBackup(VBNV_DEV_BOOT_SIGNED_ONLY,
  641. value);
  642. } else if (!strcasecmp(name,"dev_boot_fastboot_full_cap")) {
  643. return VbSetNvStorage_WithBackup(
  644. VBNV_DEV_BOOT_FASTBOOT_FULL_CAP, value);
  645. } else if (!strcasecmp(name, "fastboot_unlock_in_fw")) {
  646. return VbSetNvStorage_WithBackup(VBNV_FASTBOOT_UNLOCK_IN_FW,
  647. value);
  648. } else if (!strcasecmp(name, "boot_on_ac_detect")) {
  649. return VbSetNvStorage_WithBackup(VBNV_BOOT_ON_AC_DETECT, value);
  650. } else if (!strcasecmp(name, "try_ro_sync")) {
  651. return VbSetNvStorage_WithBackup(VBNV_TRY_RO_SYNC, value);
  652. } else if (!strcasecmp(name, "battery_cutoff_request")) {
  653. return VbSetNvStorage(VBNV_BATTERY_CUTOFF_REQUEST, value);
  654. }
  655. return -1;
  656. }
  657. int VbSetSystemPropertyString(const char* name, const char* value)
  658. {
  659. /* Chain to architecture-dependent properties */
  660. if (0 == VbSetArchPropertyString(name, value))
  661. return 0;
  662. if (!strcasecmp(name, "fw_try_next")) {
  663. if (!strcasecmp(value, "A"))
  664. return VbSetNvStorage(VBNV_FW_TRY_NEXT, 0);
  665. else if (!strcasecmp(value, "B"))
  666. return VbSetNvStorage(VBNV_FW_TRY_NEXT, 1);
  667. else
  668. return -1;
  669. } else if (!strcasecmp(name, "fw_result")) {
  670. int i;
  671. for (i = 0; i < ARRAY_SIZE(fw_results); i++) {
  672. if (!strcasecmp(value, fw_results[i]))
  673. return VbSetNvStorage(VBNV_FW_RESULT, i);
  674. }
  675. return -1;
  676. } else if (!strcasecmp(name, "dev_default_boot")) {
  677. int i;
  678. for (i = 0; i < ARRAY_SIZE(default_boot); i++) {
  679. if (!strcasecmp(value, default_boot[i]))
  680. return VbSetNvStorage(VBNV_DEV_DEFAULT_BOOT, i);
  681. }
  682. return -1;
  683. }
  684. return -1;
  685. }
  686. static int InAndroid(void)
  687. {
  688. int fd;
  689. struct stat s;
  690. int retval = 0;
  691. /*
  692. * In Android, mosys utility located in /system/bin check if file
  693. * exists. Using fstat because for some reason, stat() was seg
  694. * faulting in Android
  695. */
  696. fd = open(MOSYS_ANDROID_PATH, O_RDONLY);
  697. if (fd != -1) {
  698. if (fstat(fd, &s) == 0)
  699. retval = 1;
  700. close(fd);
  701. }
  702. return retval;
  703. }
  704. static int ExecuteMosys(char * const argv[], char *buf, size_t bufsize)
  705. {
  706. int status, mosys_to_crossystem[2];
  707. pid_t pid;
  708. ssize_t n;
  709. if (pipe(mosys_to_crossystem) < 0) {
  710. fprintf(stderr, "pipe() error\n");
  711. return -1;
  712. }
  713. if ((pid = fork()) < 0) {
  714. fprintf(stderr, "fork() error\n");
  715. close(mosys_to_crossystem[0]);
  716. close(mosys_to_crossystem[1]);
  717. return -1;
  718. } else if (!pid) { /* Child */
  719. close(mosys_to_crossystem[0]);
  720. /* Redirect pipe's write-end to mosys' stdout */
  721. if (STDOUT_FILENO != mosys_to_crossystem[1]) {
  722. if (dup2(mosys_to_crossystem[1], STDOUT_FILENO)
  723. != STDOUT_FILENO) {
  724. fprintf(stderr, "stdout dup2() failed (mosys)\n");
  725. close(mosys_to_crossystem[1]);
  726. exit(1);
  727. }
  728. }
  729. /* Execute mosys */
  730. execv(InAndroid() ? MOSYS_ANDROID_PATH : MOSYS_CROS_PATH, argv);
  731. /* We shouldn't be here; exit now! */
  732. fprintf(stderr, "execv() of mosys failed\n");
  733. close(mosys_to_crossystem[1]);
  734. exit(1);
  735. } else { /* Parent */
  736. close(mosys_to_crossystem[1]);
  737. if (bufsize) {
  738. bufsize--; /* Reserve 1 byte for '\0' */
  739. while ((n = read(mosys_to_crossystem[0],
  740. buf, bufsize)) > 0) {
  741. buf += n;
  742. bufsize -= n;
  743. }
  744. *buf = '\0';
  745. } else {
  746. n = 0;
  747. }
  748. close(mosys_to_crossystem[0]);
  749. if (n < 0)
  750. fprintf(stderr, "read() error on output from mosys\n");
  751. if (waitpid(pid, &status, 0) < 0 || status) {
  752. fprintf(stderr, "waitpid() or mosys error\n");
  753. return -1;
  754. }
  755. if (n < 0)
  756. return -1;
  757. }
  758. return 0;
  759. }
  760. int VbReadNvStorage_mosys(VbNvContext *vnc)
  761. {
  762. char hexstring[VBNV_BLOCK_SIZE * 2 + 32]; /* Reserve extra 32 bytes */
  763. char * const argv[] = {
  764. InAndroid() ? MOSYS_ANDROID_PATH : MOSYS_CROS_PATH,
  765. "nvram", "vboot", "read", NULL
  766. };
  767. char hexdigit[3];
  768. int i;
  769. if (ExecuteMosys(argv, hexstring, sizeof(hexstring)))
  770. return -1;
  771. hexdigit[2] = '\0';
  772. for (i = 0; i < VBNV_BLOCK_SIZE; i++) {
  773. hexdigit[0] = hexstring[i * 2];
  774. hexdigit[1] = hexstring[i * 2 + 1];
  775. vnc->raw[i] = strtol(hexdigit, NULL, 16);
  776. }
  777. return 0;
  778. }
  779. int VbWriteNvStorage_mosys(VbNvContext* vnc)
  780. {
  781. char hexstring[VBNV_BLOCK_SIZE * 2 + 1];
  782. char * const argv[] = {
  783. InAndroid() ? MOSYS_ANDROID_PATH : MOSYS_CROS_PATH,
  784. "nvram", "vboot", "write", hexstring, NULL
  785. };
  786. int i;
  787. for (i = 0; i < VBNV_BLOCK_SIZE; i++)
  788. snprintf(hexstring + i * 2, 3, "%02x", vnc->raw[i]);
  789. hexstring[sizeof(hexstring) - 1] = '\0';
  790. if (ExecuteMosys(argv, NULL, 0))
  791. return -1;
  792. return 0;
  793. }