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