123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883 |
- /* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #include <stddef.h>
- #include <stdio.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <unistd.h>
- #include <ctype.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/wait.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include "host_common.h"
- #include "crossystem.h"
- #include "crossystem_arch.h"
- #include "crossystem_vbnv.h"
- #include "utility.h"
- #include "vboot_common.h"
- #include "vboot_nvstorage.h"
- #include "vboot_struct.h"
- /* Filename for kernel command line */
- #define KERNEL_CMDLINE_PATH "/proc/cmdline"
- #define MOSYS_CROS_PATH "/usr/sbin/mosys"
- #define MOSYS_ANDROID_PATH "/system/bin/mosys"
- /* Fields that GetVdatString() can get */
- typedef enum VdatStringField {
- VDAT_STRING_TIMERS = 0, /* Timer values */
- VDAT_STRING_LOAD_FIRMWARE_DEBUG, /* LoadFirmware() debug information */
- VDAT_STRING_LOAD_KERNEL_DEBUG, /* LoadKernel() debug information */
- VDAT_STRING_MAINFW_ACT /* Active main firmware */
- } VdatStringField;
- /* Fields that GetVdatInt() can get */
- typedef enum VdatIntField {
- VDAT_INT_FLAGS = 0, /* Flags */
- VDAT_INT_HEADER_VERSION, /* Header version for VbSharedData */
- VDAT_INT_DEVSW_BOOT, /* Dev switch position at boot */
- VDAT_INT_DEVSW_VIRTUAL, /* Dev switch is virtual */
- VDAT_INT_RECSW_BOOT, /* Recovery switch position at boot */
- VDAT_INT_HW_WPSW_BOOT, /* Hardware WP switch position at boot */
- VDAT_INT_SW_WPSW_BOOT, /* Flash chip's WP setting at boot */
- VDAT_INT_FW_VERSION_TPM, /* Current firmware version in TPM */
- VDAT_INT_KERNEL_VERSION_TPM, /* Current kernel version in TPM */
- VDAT_INT_TRIED_FIRMWARE_B, /* Tried firmware B due to fwb_tries */
- VDAT_INT_KERNEL_KEY_VERIFIED, /* Kernel key verified using
- * signature, not just hash */
- VDAT_INT_RECOVERY_REASON, /* Recovery reason for current boot */
- VDAT_INT_FW_BOOT2 /* Firmware selection by vboot2 */
- } VdatIntField;
- /* Description of build options that may be specified on the
- * kernel command line. */
- typedef enum VbBuildOption {
- VB_BUILD_OPTION_UNKNOWN,
- VB_BUILD_OPTION_DEBUG,
- VB_BUILD_OPTION_NODEBUG
- } VbBuildOption;
- static const char *fw_results[] = {"unknown", "trying", "success", "failure"};
- static const char *default_boot[] = {"disk", "usb", "legacy"};
- /* Masks for kern_nv usage by kernel. */
- #define KERN_NV_FWUPDATE_TRIES_MASK 0x0000000F
- #define KERN_NV_BLOCK_DEVMODE_FLAG 0x00000010
- #define KERN_NV_TPM_ATTACK_FLAG 0x00000020
- /* If you want to use the remaining currently-unused bits in kern_nv
- * for something kernel-y, define a new field (the way we did for
- * fwupdate_tries). Don't just modify kern_nv directly, because that
- * makes it too easy to accidentally corrupt other sub-fields. */
- #define KERN_NV_CURRENTLY_UNUSED 0xFFFFFFC0
- /* Return true if the FWID starts with the specified string. */
- int FwidStartsWith(const char *start)
- {
- char fwid[VB_MAX_STRING_PROPERTY];
- if (!VbGetSystemPropertyString("fwid", fwid, sizeof(fwid)))
- return 0;
- return 0 == strncmp(fwid, start, strlen(start));
- }
- static int vnc_read;
- int VbGetNvStorage(VbNvParam param)
- {
- uint32_t value;
- int retval;
- static VbNvContext cached_vnc;
- /* TODO: locking around NV access */
- if (!vnc_read) {
- if (0 != VbReadNvStorage(&cached_vnc))
- return -1;
- vnc_read = 1;
- }
- if (0 != VbNvSetup(&cached_vnc))
- return -1;
- retval = VbNvGet(&cached_vnc, param, &value);
- if (0 != VbNvTeardown(&cached_vnc))
- return -1;
- if (0 != retval)
- return -1;
- /* TODO: If vnc.raw_changed, attempt to reopen NVRAM for write and
- * save the new defaults. If we're able to, log. */
- /* TODO: release lock */
- return (int)value;
- }
- int VbSetNvStorage(VbNvParam param, int value)
- {
- VbNvContext vnc;
- int retval = -1;
- int i;
- if (0 != VbReadNvStorage(&vnc))
- return -1;
- if (0 != VbNvSetup(&vnc))
- goto VbSetNvCleanup;
- i = VbNvSet(&vnc, param, (uint32_t)value);
- if (0 != VbNvTeardown(&vnc))
- goto VbSetNvCleanup;
- if (0 != i)
- goto VbSetNvCleanup;
- if (vnc.raw_changed) {
- vnc_read = 0;
- if (0 != VbWriteNvStorage(&vnc))
- goto VbSetNvCleanup;
- }
- /* Success */
- retval = 0;
- VbSetNvCleanup:
- /* TODO: release lock */
- return retval;
- }
- /*
- * Set a param value, and try to flag it for persistent backup.
- * It's okay if backup isn't supported. It's best-effort only.
- */
- static int VbSetNvStorage_WithBackup(VbNvParam param, int value)
- {
- int retval;
- retval = VbSetNvStorage(param, value);
- if (!retval)
- VbSetNvStorage(VBNV_BACKUP_NVRAM_REQUEST, 1);
- return retval;
- }
- /* Find what build/debug status is specified on the kernel command
- * line, if any. */
- static VbBuildOption VbScanBuildOption(void)
- {
- FILE* f = NULL;
- char buf[4096] = "";
- char *t, *saveptr;
- const char *delimiters = " \r\n";
- f = fopen(KERNEL_CMDLINE_PATH, "r");
- if (NULL != f) {
- if (NULL == fgets(buf, sizeof(buf), f))
- buf[0] = 0;
- fclose(f);
- }
- for (t = strtok_r(buf, delimiters, &saveptr); t;
- t = strtok_r(NULL, delimiters, &saveptr)) {
- if (0 == strcmp(t, "cros_debug"))
- return VB_BUILD_OPTION_DEBUG;
- else if (0 == strcmp(t, "cros_nodebug"))
- return VB_BUILD_OPTION_NODEBUG;
- }
- return VB_BUILD_OPTION_UNKNOWN;
- }
- /* Determine whether the running OS image was built for debugging.
- * Returns 1 if yes, 0 if no or indeterminate. */
- int VbGetDebugBuild(void)
- {
- return VB_BUILD_OPTION_DEBUG == VbScanBuildOption();
- }
- /* Determine whether OS-level debugging should be allowed.
- * Returns 1 if yes, 0 if no or indeterminate. */
- int VbGetCrosDebug(void)
- {
- /* If the currently running system specifies its debug status, use
- * that in preference to other indicators. */
- VbBuildOption option = VbScanBuildOption();
- if (VB_BUILD_OPTION_DEBUG == option) {
- return 1;
- } else if (VB_BUILD_OPTION_NODEBUG == option) {
- return 0;
- }
- /* Command line is silent; allow debug if the dev switch is on. */
- if (1 == VbGetSystemPropertyInt("devsw_boot"))
- return 1;
- /* All other cases disallow debug. */
- return 0;
- }
- char *GetVdatLoadFirmwareDebug(char *dest, int size,
- const VbSharedDataHeader *sh)
- {
- snprintf(dest, size,
- "Check A result=%d\n"
- "Check B result=%d\n"
- "Firmware index booted=0x%02x\n"
- "TPM combined version at start=0x%08x\n"
- "Lowest combined version from firmware=0x%08x\n",
- sh->check_fw_a_result,
- sh->check_fw_b_result,
- sh->firmware_index,
- sh->fw_version_tpm_start,
- sh->fw_version_lowest);
- return dest;
- }
- #define TRUNCATED "\n(truncated)\n"
- char *GetVdatLoadKernelDebug(char *dest, int size,
- const VbSharedDataHeader *sh)
- {
- int used = 0;
- int first_call_tracked = 0;
- int call;
- /* Make sure we have space for truncation warning */
- if (size < strlen(TRUNCATED) + 1)
- return NULL;
- size -= strlen(TRUNCATED) + 1;
- used += snprintf(
- dest + used, size - used,
- "Calls to LoadKernel()=%d\n",
- sh->lk_call_count);
- if (used > size)
- goto LoadKernelDebugExit;
- /* Report on the last calls */
- if (sh->lk_call_count > VBSD_MAX_KERNEL_CALLS)
- first_call_tracked = sh->lk_call_count - VBSD_MAX_KERNEL_CALLS;
- for (call = first_call_tracked; call < sh->lk_call_count; call++) {
- const VbSharedDataKernelCall* shc = sh->lk_calls +
- (call & (VBSD_MAX_KERNEL_CALLS - 1));
- int first_part_tracked = 0;
- int part;
- used += snprintf(dest + used, size - used,
- "Call %d:\n"
- " Boot flags=0x%02x\n"
- " Boot mode=%d\n"
- " Test error=%d\n"
- " Return code=%d\n"
- " Debug flags=0x%02x\n"
- " Drive sectors=%" PRIu64 "\n"
- " Sector size=%d\n"
- " Check result=%d\n"
- " Kernel partitions found=%d\n",
- call + 1,
- shc->boot_flags,
- shc->boot_mode,
- shc->test_error_num,
- shc->return_code,
- shc->flags,
- shc->sector_count,
- shc->sector_size,
- shc->check_result,
- shc->kernel_parts_found);
- if (used > size)
- goto LoadKernelDebugExit;
- /* If we found too many partitions, only prints ones where the
- * structure has info. */
- if (shc->kernel_parts_found > VBSD_MAX_KERNEL_PARTS)
- first_part_tracked = shc->kernel_parts_found -
- VBSD_MAX_KERNEL_PARTS;
- /* Report on the partitions checked */
- for (part = first_part_tracked; part < shc->kernel_parts_found;
- part++) {
- const VbSharedDataKernelPart* shp = shc->parts +
- (part & (VBSD_MAX_KERNEL_PARTS - 1));
- used += snprintf(dest + used, size - used,
- " Kernel %d:\n"
- " GPT index=%d\n"
- " Start sector=%" PRIu64 "\n"
- " Sector count=%" PRIu64 "\n"
- " Combined version=0x%08x\n"
- " Check result=%d\n"
- " Debug flags=0x%02x\n",
- part + 1,
- shp->gpt_index,
- shp->sector_start,
- shp->sector_count,
- shp->combined_version,
- shp->check_result,
- shp->flags);
- if (used > size)
- goto LoadKernelDebugExit;
- }
- }
- LoadKernelDebugExit:
- /* Warn if data was truncated; we left space for this above. */
- if (used > size)
- strcat(dest, TRUNCATED);
- return dest;
- }
- char *GetVdatString(char *dest, int size, VdatStringField field)
- {
- VbSharedDataHeader *sh = VbSharedDataRead();
- char *value = dest;
- if (!sh)
- return NULL;
- switch (field) {
- case VDAT_STRING_TIMERS:
- snprintf(dest, size,
- "LFS=%" PRIu64 ",%" PRIu64
- " LF=%" PRIu64 ",%" PRIu64
- " LK=%" PRIu64 ",%" PRIu64,
- sh->timer_vb_init_enter,
- sh->timer_vb_init_exit,
- sh->timer_vb_select_firmware_enter,
- sh->timer_vb_select_firmware_exit,
- sh->timer_vb_select_and_load_kernel_enter,
- sh->timer_vb_select_and_load_kernel_exit);
- break;
- case VDAT_STRING_LOAD_FIRMWARE_DEBUG:
- value = GetVdatLoadFirmwareDebug(dest, size, sh);
- break;
- case VDAT_STRING_LOAD_KERNEL_DEBUG:
- value = GetVdatLoadKernelDebug(dest, size, sh);
- break;
- case VDAT_STRING_MAINFW_ACT:
- switch(sh->firmware_index) {
- case 0:
- StrCopy(dest, "A", size);
- break;
- case 1:
- StrCopy(dest, "B", size);
- break;
- case 0xFF:
- StrCopy(dest, "recovery", size);
- break;
- default:
- value = NULL;
- }
- break;
- default:
- value = NULL;
- break;
- }
- free(sh);
- return value;
- }
- int GetVdatInt(VdatIntField field)
- {
- VbSharedDataHeader* sh = VbSharedDataRead();
- int value = -1;
- if (!sh)
- return -1;
- /* Fields supported in version 1 */
- switch (field) {
- case VDAT_INT_FLAGS:
- value = (int)sh->flags;
- break;
- case VDAT_INT_HEADER_VERSION:
- value = sh->struct_version;
- break;
- case VDAT_INT_TRIED_FIRMWARE_B:
- value = (sh->flags & VBSD_FWB_TRIED ? 1 : 0);
- break;
- case VDAT_INT_KERNEL_KEY_VERIFIED:
- value = (sh->flags & VBSD_KERNEL_KEY_VERIFIED ? 1 : 0);
- break;
- case VDAT_INT_FW_VERSION_TPM:
- value = (int)sh->fw_version_tpm;
- break;
- case VDAT_INT_KERNEL_VERSION_TPM:
- value = (int)sh->kernel_version_tpm;
- break;
- case VDAT_INT_FW_BOOT2:
- value = (sh->flags & VBSD_BOOT_FIRMWARE_VBOOT2 ? 1 : 0);
- default:
- break;
- }
- /* Fields added in struct version 2 */
- if (sh->struct_version >= 2) {
- switch(field) {
- case VDAT_INT_DEVSW_BOOT:
- value = (sh->flags &
- VBSD_BOOT_DEV_SWITCH_ON ? 1 : 0);
- break;
- case VDAT_INT_DEVSW_VIRTUAL:
- value = (sh->flags &
- VBSD_HONOR_VIRT_DEV_SWITCH ? 1 : 0);
- break;
- case VDAT_INT_RECSW_BOOT:
- value = (sh->flags &
- VBSD_BOOT_REC_SWITCH_ON ? 1 : 0);
- break;
- case VDAT_INT_HW_WPSW_BOOT:
- value = (sh->flags &
- VBSD_BOOT_FIRMWARE_WP_ENABLED ? 1 : 0);
- break;
- case VDAT_INT_SW_WPSW_BOOT:
- value = (sh->flags &
- VBSD_BOOT_FIRMWARE_SW_WP_ENABLED ?
- 1 : 0);
- break;
- case VDAT_INT_RECOVERY_REASON:
- value = sh->recovery_reason;
- break;
- default:
- break;
- }
- }
- free(sh);
- return value;
- }
- /* Return version of VbSharedData struct or -1 if not found. */
- int VbSharedDataVersion(void)
- {
- return GetVdatInt(VDAT_INT_HEADER_VERSION);
- }
- int VbGetSystemPropertyInt(const char *name)
- {
- int value = -1;
- /* Check architecture-dependent properties first */
- value = VbGetArchPropertyInt(name);
- if (-1 != value)
- return value;
- /* NV storage values */
- else if (!strcasecmp(name,"kern_nv")) {
- value = VbGetNvStorage(VBNV_KERNEL_FIELD);
- } else if (!strcasecmp(name,"nvram_cleared")) {
- value = VbGetNvStorage(VBNV_KERNEL_SETTINGS_RESET);
- } else if (!strcasecmp(name,"recovery_request")) {
- value = VbGetNvStorage(VBNV_RECOVERY_REQUEST);
- } else if (!strcasecmp(name,"dbg_reset")) {
- value = VbGetNvStorage(VBNV_DEBUG_RESET_MODE);
- } else if (!strcasecmp(name,"disable_dev_request")) {
- value = VbGetNvStorage(VBNV_DISABLE_DEV_REQUEST);
- } else if (!strcasecmp(name,"clear_tpm_owner_request")) {
- value = VbGetNvStorage(VBNV_CLEAR_TPM_OWNER_REQUEST);
- } else if (!strcasecmp(name,"clear_tpm_owner_done")) {
- value = VbGetNvStorage(VBNV_CLEAR_TPM_OWNER_DONE);
- } else if (!strcasecmp(name,"tpm_rebooted")) {
- value = VbGetNvStorage(VBNV_TPM_REQUESTED_REBOOT);
- } else if (!strcasecmp(name,"fwb_tries")) {
- value = VbGetNvStorage(VBNV_TRY_B_COUNT);
- } else if (!strcasecmp(name,"fw_vboot2")) {
- value = GetVdatInt(VDAT_INT_FW_BOOT2);
- } else if (!strcasecmp(name,"fw_try_count")) {
- value = VbGetNvStorage(VBNV_FW_TRY_COUNT);
- } else if (!strcasecmp(name,"fwupdate_tries")) {
- value = VbGetNvStorage(VBNV_KERNEL_FIELD);
- if (value != -1)
- value &= KERN_NV_FWUPDATE_TRIES_MASK;
- } else if (!strcasecmp(name,"block_devmode")) {
- value = VbGetNvStorage(VBNV_KERNEL_FIELD);
- if (value != -1) {
- value &= KERN_NV_BLOCK_DEVMODE_FLAG;
- value = !!value;
- }
- } else if (!strcasecmp(name,"tpm_attack")) {
- value = VbGetNvStorage(VBNV_KERNEL_FIELD);
- if (value != -1) {
- value &= KERN_NV_TPM_ATTACK_FLAG;
- value = !!value;
- }
- } else if (!strcasecmp(name,"loc_idx")) {
- value = VbGetNvStorage(VBNV_LOCALIZATION_INDEX);
- } else if (!strcasecmp(name,"backup_nvram_request")) {
- value = VbGetNvStorage(VBNV_BACKUP_NVRAM_REQUEST);
- } else if (!strcasecmp(name,"dev_boot_usb")) {
- value = VbGetNvStorage(VBNV_DEV_BOOT_USB);
- } else if (!strcasecmp(name,"dev_boot_legacy")) {
- value = VbGetNvStorage(VBNV_DEV_BOOT_LEGACY);
- } else if (!strcasecmp(name,"dev_boot_signed_only")) {
- value = VbGetNvStorage(VBNV_DEV_BOOT_SIGNED_ONLY);
- } else if (!strcasecmp(name,"dev_boot_fastboot_full_cap")) {
- value = VbGetNvStorage(VBNV_DEV_BOOT_FASTBOOT_FULL_CAP);
- } else if (!strcasecmp(name,"oprom_needed")) {
- value = VbGetNvStorage(VBNV_OPROM_NEEDED);
- } else if (!strcasecmp(name,"recovery_subcode")) {
- value = VbGetNvStorage(VBNV_RECOVERY_SUBCODE);
- } else if (!strcasecmp(name,"wipeout_request")) {
- value = VbGetNvStorage(VBNV_FW_REQ_WIPEOUT);
- }
- /* Other parameters */
- else if (!strcasecmp(name,"cros_debug")) {
- value = VbGetCrosDebug();
- } else if (!strcasecmp(name,"debug_build")) {
- value = VbGetDebugBuild();
- } else if (!strcasecmp(name,"devsw_boot")) {
- value = GetVdatInt(VDAT_INT_DEVSW_BOOT);
- } else if (!strcasecmp(name,"devsw_virtual")) {
- value = GetVdatInt(VDAT_INT_DEVSW_VIRTUAL);
- } else if (!strcasecmp(name, "recoverysw_boot")) {
- value = GetVdatInt(VDAT_INT_RECSW_BOOT);
- } else if (!strcasecmp(name, "wpsw_boot")) {
- value = GetVdatInt(VDAT_INT_HW_WPSW_BOOT);
- } else if (!strcasecmp(name, "sw_wpsw_boot")) {
- value = GetVdatInt(VDAT_INT_SW_WPSW_BOOT);
- } else if (!strcasecmp(name,"vdat_flags")) {
- value = GetVdatInt(VDAT_INT_FLAGS);
- } else if (!strcasecmp(name,"tpm_fwver")) {
- value = GetVdatInt(VDAT_INT_FW_VERSION_TPM);
- } else if (!strcasecmp(name,"tpm_kernver")) {
- value = GetVdatInt(VDAT_INT_KERNEL_VERSION_TPM);
- } else if (!strcasecmp(name,"tried_fwb")) {
- value = GetVdatInt(VDAT_INT_TRIED_FIRMWARE_B);
- } else if (!strcasecmp(name,"recovery_reason")) {
- value = GetVdatInt(VDAT_INT_RECOVERY_REASON);
- } else if (!strcasecmp(name, "fastboot_unlock_in_fw")) {
- value = VbGetNvStorage(VBNV_FASTBOOT_UNLOCK_IN_FW);
- } else if (!strcasecmp(name, "boot_on_ac_detect")) {
- value = VbGetNvStorage(VBNV_BOOT_ON_AC_DETECT);
- } else if (!strcasecmp(name, "try_ro_sync")) {
- value = VbGetNvStorage(VBNV_TRY_RO_SYNC);
- } else if (!strcasecmp(name, "battery_cutoff_request")) {
- value = VbGetNvStorage(VBNV_BATTERY_CUTOFF_REQUEST);
- } else if (!strcasecmp(name, "inside_vm")) {
- /* Detect if the host is a VM. If there is no HWID and the
- * firmware type is "nonchrome", then assume it is a VM. If
- * HWID is present, it is a baremetal Chrome OS machine. Other
- * cases are errors. */
- char hwid[VB_MAX_STRING_PROPERTY];
- if (!VbGetSystemPropertyString("hwid", hwid, sizeof(hwid))) {
- char fwtype_buf[VB_MAX_STRING_PROPERTY];
- const char *fwtype = VbGetSystemPropertyString(
- "mainfw_type", fwtype_buf, sizeof(fwtype_buf));
- if (fwtype && !strcasecmp(fwtype, "nonchrome")) {
- value = 1;
- }
- } else {
- value = 0;
- }
- }
- return value;
- }
- const char *VbGetSystemPropertyString(const char *name, char *dest,
- size_t size)
- {
- /* Check architecture-dependent properties first */
- if (VbGetArchPropertyString(name, dest, size))
- return dest;
- if (!strcasecmp(name,"kernkey_vfy")) {
- switch(GetVdatInt(VDAT_INT_KERNEL_KEY_VERIFIED)) {
- case 0:
- return "hash";
- case 1:
- return "sig";
- default:
- return NULL;
- }
- } else if (!strcasecmp(name, "mainfw_act")) {
- return GetVdatString(dest, size, VDAT_STRING_MAINFW_ACT);
- } else if (!strcasecmp(name, "vdat_timers")) {
- return GetVdatString(dest, size, VDAT_STRING_TIMERS);
- } else if (!strcasecmp(name, "vdat_lfdebug")) {
- return GetVdatString(dest, size,
- VDAT_STRING_LOAD_FIRMWARE_DEBUG);
- } else if (!strcasecmp(name, "vdat_lkdebug")) {
- return GetVdatString(dest, size, VDAT_STRING_LOAD_KERNEL_DEBUG);
- } else if (!strcasecmp(name, "fw_try_next")) {
- return VbGetNvStorage(VBNV_FW_TRY_NEXT) ? "B" : "A";
- } else if (!strcasecmp(name, "fw_tried")) {
- return VbGetNvStorage(VBNV_FW_TRIED) ? "B" : "A";
- } else if (!strcasecmp(name, "fw_result")) {
- int v = VbGetNvStorage(VBNV_FW_RESULT);
- if (v < ARRAY_SIZE(fw_results))
- return fw_results[v];
- else
- return "unknown";
- } else if (!strcasecmp(name, "fw_prev_tried")) {
- return VbGetNvStorage(VBNV_FW_PREV_TRIED) ? "B" : "A";
- } else if (!strcasecmp(name, "fw_prev_result")) {
- int v = VbGetNvStorage(VBNV_FW_PREV_RESULT);
- if (v < ARRAY_SIZE(fw_results))
- return fw_results[v];
- else
- return "unknown";
- } else if (!strcasecmp(name,"dev_default_boot")) {
- int v = VbGetNvStorage(VBNV_DEV_DEFAULT_BOOT);
- if (v < ARRAY_SIZE(default_boot))
- return default_boot[v];
- else
- return "unknown";
- }
- return NULL;
- }
- int VbSetSystemPropertyInt(const char *name, int value)
- {
- /* Check architecture-dependent properties first */
- if (0 == VbSetArchPropertyInt(name, value))
- return 0;
- /* NV storage values */
- if (!strcasecmp(name,"nvram_cleared")) {
- /* Can only clear this flag; it's set inside the NV storage
- * library. */
- return VbSetNvStorage(VBNV_KERNEL_SETTINGS_RESET, 0);
- } else if (!strcasecmp(name,"recovery_request")) {
- return VbSetNvStorage(VBNV_RECOVERY_REQUEST, value);
- } else if (!strcasecmp(name,"recovery_subcode")) {
- return VbSetNvStorage(VBNV_RECOVERY_SUBCODE, value);
- } else if (!strcasecmp(name,"dbg_reset")) {
- return VbSetNvStorage(VBNV_DEBUG_RESET_MODE, value);
- } else if (!strcasecmp(name,"disable_dev_request")) {
- return VbSetNvStorage(VBNV_DISABLE_DEV_REQUEST, value);
- } else if (!strcasecmp(name,"clear_tpm_owner_request")) {
- return VbSetNvStorage(VBNV_CLEAR_TPM_OWNER_REQUEST, value);
- } else if (!strcasecmp(name,"clear_tpm_owner_done")) {
- /* Can only clear this flag; it's set by firmware. */
- return VbSetNvStorage(VBNV_CLEAR_TPM_OWNER_DONE, 0);
- } else if (!strcasecmp(name,"fwb_tries")) {
- return VbSetNvStorage(VBNV_TRY_B_COUNT, value);
- } else if (!strcasecmp(name,"fw_try_count")) {
- return VbSetNvStorage(VBNV_FW_TRY_COUNT, value);
- } else if (!strcasecmp(name,"oprom_needed")) {
- return VbSetNvStorage(VBNV_OPROM_NEEDED, value);
- } else if (!strcasecmp(name,"wipeout_request")) {
- /* Can only clear this flag, set only by firmware. */
- return VbSetNvStorage(VBNV_FW_REQ_WIPEOUT, 0);
- } else if (!strcasecmp(name,"backup_nvram_request")) {
- /* Best-effort only, since it requires firmware and TPM
- * support. */
- return VbSetNvStorage(VBNV_BACKUP_NVRAM_REQUEST, value);
- } else if (!strcasecmp(name,"fwupdate_tries")) {
- int kern_nv = VbGetNvStorage(VBNV_KERNEL_FIELD);
- if (kern_nv == -1)
- return -1;
- kern_nv &= ~KERN_NV_FWUPDATE_TRIES_MASK;
- kern_nv |= (value & KERN_NV_FWUPDATE_TRIES_MASK);
- return VbSetNvStorage_WithBackup(VBNV_KERNEL_FIELD, kern_nv);
- } else if (!strcasecmp(name,"block_devmode")) {
- int kern_nv = VbGetNvStorage(VBNV_KERNEL_FIELD);
- if (kern_nv == -1)
- return -1;
- kern_nv &= ~KERN_NV_BLOCK_DEVMODE_FLAG;
- if (value)
- kern_nv |= KERN_NV_BLOCK_DEVMODE_FLAG;
- return VbSetNvStorage_WithBackup(VBNV_KERNEL_FIELD, kern_nv);
- } else if (!strcasecmp(name,"tpm_attack")) {
- /* This value should only be read and cleared, but we allow
- * setting it to 1 for testing. */
- int kern_nv = VbGetNvStorage(VBNV_KERNEL_FIELD);
- if (kern_nv == -1)
- return -1;
- kern_nv &= ~KERN_NV_TPM_ATTACK_FLAG;
- if (value)
- kern_nv |= KERN_NV_TPM_ATTACK_FLAG;
- return VbSetNvStorage_WithBackup(VBNV_KERNEL_FIELD, kern_nv);
- } else if (!strcasecmp(name,"loc_idx")) {
- return VbSetNvStorage_WithBackup(VBNV_LOCALIZATION_INDEX,
- value);
- } else if (!strcasecmp(name,"dev_boot_usb")) {
- return VbSetNvStorage_WithBackup(VBNV_DEV_BOOT_USB, value);
- } else if (!strcasecmp(name,"dev_boot_legacy")) {
- return VbSetNvStorage_WithBackup(VBNV_DEV_BOOT_LEGACY, value);
- } else if (!strcasecmp(name,"dev_boot_signed_only")) {
- return VbSetNvStorage_WithBackup(VBNV_DEV_BOOT_SIGNED_ONLY,
- value);
- } else if (!strcasecmp(name,"dev_boot_fastboot_full_cap")) {
- return VbSetNvStorage_WithBackup(
- VBNV_DEV_BOOT_FASTBOOT_FULL_CAP, value);
- } else if (!strcasecmp(name, "fastboot_unlock_in_fw")) {
- return VbSetNvStorage_WithBackup(VBNV_FASTBOOT_UNLOCK_IN_FW,
- value);
- } else if (!strcasecmp(name, "boot_on_ac_detect")) {
- return VbSetNvStorage_WithBackup(VBNV_BOOT_ON_AC_DETECT, value);
- } else if (!strcasecmp(name, "try_ro_sync")) {
- return VbSetNvStorage_WithBackup(VBNV_TRY_RO_SYNC, value);
- } else if (!strcasecmp(name, "battery_cutoff_request")) {
- return VbSetNvStorage(VBNV_BATTERY_CUTOFF_REQUEST, value);
- }
- return -1;
- }
- int VbSetSystemPropertyString(const char* name, const char* value)
- {
- /* Chain to architecture-dependent properties */
- if (0 == VbSetArchPropertyString(name, value))
- return 0;
- if (!strcasecmp(name, "fw_try_next")) {
- if (!strcasecmp(value, "A"))
- return VbSetNvStorage(VBNV_FW_TRY_NEXT, 0);
- else if (!strcasecmp(value, "B"))
- return VbSetNvStorage(VBNV_FW_TRY_NEXT, 1);
- else
- return -1;
- } else if (!strcasecmp(name, "fw_result")) {
- int i;
- for (i = 0; i < ARRAY_SIZE(fw_results); i++) {
- if (!strcasecmp(value, fw_results[i]))
- return VbSetNvStorage(VBNV_FW_RESULT, i);
- }
- return -1;
- } else if (!strcasecmp(name, "dev_default_boot")) {
- int i;
- for (i = 0; i < ARRAY_SIZE(default_boot); i++) {
- if (!strcasecmp(value, default_boot[i]))
- return VbSetNvStorage(VBNV_DEV_DEFAULT_BOOT, i);
- }
- return -1;
- }
- return -1;
- }
- static int InAndroid(void)
- {
- int fd;
- struct stat s;
- int retval = 0;
- /*
- * In Android, mosys utility located in /system/bin check if file
- * exists. Using fstat because for some reason, stat() was seg
- * faulting in Android
- */
- fd = open(MOSYS_ANDROID_PATH, O_RDONLY);
- if (fd != -1) {
- if (fstat(fd, &s) == 0)
- retval = 1;
- close(fd);
- }
- return retval;
- }
- static int ExecuteMosys(char * const argv[], char *buf, size_t bufsize)
- {
- int status, mosys_to_crossystem[2];
- pid_t pid;
- ssize_t n;
- if (pipe(mosys_to_crossystem) < 0) {
- fprintf(stderr, "pipe() error\n");
- return -1;
- }
- if ((pid = fork()) < 0) {
- fprintf(stderr, "fork() error\n");
- close(mosys_to_crossystem[0]);
- close(mosys_to_crossystem[1]);
- return -1;
- } else if (!pid) { /* Child */
- close(mosys_to_crossystem[0]);
- /* Redirect pipe's write-end to mosys' stdout */
- if (STDOUT_FILENO != mosys_to_crossystem[1]) {
- if (dup2(mosys_to_crossystem[1], STDOUT_FILENO)
- != STDOUT_FILENO) {
- fprintf(stderr, "stdout dup2() failed (mosys)\n");
- close(mosys_to_crossystem[1]);
- exit(1);
- }
- }
- /* Execute mosys */
- execv(InAndroid() ? MOSYS_ANDROID_PATH : MOSYS_CROS_PATH, argv);
- /* We shouldn't be here; exit now! */
- fprintf(stderr, "execv() of mosys failed\n");
- close(mosys_to_crossystem[1]);
- exit(1);
- } else { /* Parent */
- close(mosys_to_crossystem[1]);
- if (bufsize) {
- bufsize--; /* Reserve 1 byte for '\0' */
- while ((n = read(mosys_to_crossystem[0],
- buf, bufsize)) > 0) {
- buf += n;
- bufsize -= n;
- }
- *buf = '\0';
- } else {
- n = 0;
- }
- close(mosys_to_crossystem[0]);
- if (n < 0)
- fprintf(stderr, "read() error on output from mosys\n");
- if (waitpid(pid, &status, 0) < 0 || status) {
- fprintf(stderr, "waitpid() or mosys error\n");
- return -1;
- }
- if (n < 0)
- return -1;
- }
- return 0;
- }
- int VbReadNvStorage_mosys(VbNvContext *vnc)
- {
- char hexstring[VBNV_BLOCK_SIZE * 2 + 32]; /* Reserve extra 32 bytes */
- char * const argv[] = {
- InAndroid() ? MOSYS_ANDROID_PATH : MOSYS_CROS_PATH,
- "nvram", "vboot", "read", NULL
- };
- char hexdigit[3];
- int i;
- if (ExecuteMosys(argv, hexstring, sizeof(hexstring)))
- return -1;
- hexdigit[2] = '\0';
- for (i = 0; i < VBNV_BLOCK_SIZE; i++) {
- hexdigit[0] = hexstring[i * 2];
- hexdigit[1] = hexstring[i * 2 + 1];
- vnc->raw[i] = strtol(hexdigit, NULL, 16);
- }
- return 0;
- }
- int VbWriteNvStorage_mosys(VbNvContext* vnc)
- {
- char hexstring[VBNV_BLOCK_SIZE * 2 + 1];
- char * const argv[] = {
- InAndroid() ? MOSYS_ANDROID_PATH : MOSYS_CROS_PATH,
- "nvram", "vboot", "write", hexstring, NULL
- };
- int i;
- for (i = 0; i < VBNV_BLOCK_SIZE; i++)
- snprintf(hexstring + i * 2, 3, "%02x", vnc->raw[i]);
- hexstring[sizeof(hexstring) - 1] = '\0';
- if (ExecuteMosys(argv, NULL, 0))
- return -1;
- return 0;
- }
|