Home | History | Annotate | Download | only in utility
      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  * Chrome OS firmware/system interface utility
      6  */
      7 
      8 #include <stdio.h>
      9 #include <stdlib.h>
     10 #include <string.h>
     11 
     12 #include "crossystem.h"
     13 
     14 /*
     15  * Call arch specific init, if provided, otherwise use the 'weak' stub.
     16  */
     17 int __VbArchInit(void) { return 0; }
     18 int VbArchInit(void) __attribute__((weak, alias("__VbArchInit")));
     19 /* Flags for Param */
     20 #define IS_STRING      0x01  /* String (not present = integer) */
     21 #define CAN_WRITE      0x02  /* Writable (not present = read-only */
     22 #define NO_PRINT_ALL   0x04  /* Don't print contents of parameter when
     23                               * doing a print-all */
     24 
     25 typedef struct Param {
     26   const char* name;  /* Parameter name */
     27   int flags;         /* Flags (see above) */
     28   const char* desc;  /* Human-readable description */
     29   const char* format; /* Format string, if non-NULL and 0==is_string*/
     30 } Param;
     31 
     32 /* List of parameters, terminated with a param with NULL name */
     33 const Param sys_param_list[] = {
     34   {"arch", IS_STRING, "Platform architecture"},
     35   {"backup_nvram_request", CAN_WRITE,
     36    "Backup the nvram somewhere at the next boot. Cleared on success."},
     37   {"block_devmode", CAN_WRITE, "Block all use of developer mode"},
     38   {"clear_tpm_owner_request", CAN_WRITE, "Clear TPM owner on next boot"},
     39   {"clear_tpm_owner_done", CAN_WRITE, "Clear TPM owner done"},
     40   {"cros_debug", 0, "OS should allow debug features"},
     41   {"dbg_reset", CAN_WRITE, "Debug reset mode request (writable)"},
     42   {"ddr_type", IS_STRING, "Type of DDR RAM"},
     43   {"debug_build", 0, "OS image built for debug features"},
     44   {"dev_boot_usb", CAN_WRITE,
     45    "Enable developer mode boot from USB/SD (writable)"},
     46   {"dev_boot_legacy", CAN_WRITE,
     47    "Enable developer mode boot Legacy OSes (writable)"},
     48   {"dev_boot_signed_only", CAN_WRITE,
     49    "Enable developer mode boot only from official kernels (writable)"},
     50   {"devsw_boot", 0, "Developer switch position at boot"},
     51   {"devsw_cur",  0, "Developer switch current position"},
     52   {"disable_dev_request", CAN_WRITE, "Disable virtual dev-mode on next boot"},
     53   {"ecfw_act", IS_STRING, "Active EC firmware"},
     54   {"fmap_base", 0, "Main firmware flashmap physical address", "0x%08x"},
     55   {"fwb_tries", CAN_WRITE, "Try firmware B count (writable)"},
     56   {"fw_vboot2", 0, "1 if firmware was selected by vboot2 or 0 otherwise"},
     57   {"fwid", IS_STRING, "Active firmware ID"},
     58   {"fwupdate_tries", CAN_WRITE,
     59    "Times to try OS firmware update (writable, inside kern_nv)"},
     60   {"fw_tried", IS_STRING, "Firmware tried this boot (vboot2)"},
     61   {"fw_try_count", CAN_WRITE, "Number of times to try fw_try_next (writable)"},
     62   {"fw_try_next", IS_STRING|CAN_WRITE,
     63    "Firmware to try next (vboot2,writable)"},
     64   {"fw_result", IS_STRING|CAN_WRITE,
     65    "Firmware result this boot (vboot2,writable)"},
     66   {"fw_prev_tried", IS_STRING, "Firmware tried on previous boot (vboot2)"},
     67   {"fw_prev_result", IS_STRING, "Firmware result of previous boot (vboot2)"},
     68   {"hwid", IS_STRING, "Hardware ID"},
     69   {"kern_nv", 0, "Non-volatile field for kernel use", "0x%08x"},
     70   {"kernkey_vfy", IS_STRING, "Type of verification done on kernel key block"},
     71   {"loc_idx", CAN_WRITE, "Localization index for firmware screens (writable)"},
     72   {"mainfw_act", IS_STRING, "Active main firmware"},
     73   {"mainfw_type", IS_STRING, "Active main firmware type"},
     74   {"nvram_cleared", CAN_WRITE, "Have NV settings been lost?  Write 0 to clear"},
     75   {"oprom_needed", CAN_WRITE, "Should we load the VGA Option ROM at boot?"},
     76   {"platform_family", IS_STRING, "Platform family type"},
     77   {"recovery_reason", 0, "Recovery mode reason for current boot"},
     78   {"recovery_request", CAN_WRITE, "Recovery mode request (writable)"},
     79   {"recovery_subcode", CAN_WRITE, "Recovery reason subcode (writable)"},
     80   {"recoverysw_boot", 0, "Recovery switch position at boot"},
     81   {"recoverysw_cur", 0, "Recovery switch current position"},
     82   {"recoverysw_ec_boot", 0, "Recovery switch position at EC boot"},
     83   {"ro_fwid", IS_STRING, "Read-only firmware ID"},
     84   {"savedmem_base", 0, "RAM debug data area physical address", "0x%08x"},
     85   {"savedmem_size", 0, "RAM debug data area size in bytes"},
     86   {"sw_wpsw_boot", 0,
     87    "Firmware write protect software setting enabled at boot"},
     88   {"tpm_fwver", 0, "Firmware version stored in TPM", "0x%08x"},
     89   {"tpm_kernver", 0, "Kernel version stored in TPM", "0x%08x"},
     90   {"tried_fwb", 0, "Tried firmware B before A this boot"},
     91   {"vdat_flags", 0, "Flags from VbSharedData", "0x%08x"},
     92   {"vdat_lfdebug", IS_STRING|NO_PRINT_ALL,
     93    "LoadFirmware() debug data (not in print-all)"},
     94   {"vdat_lkdebug", IS_STRING|NO_PRINT_ALL,
     95    "LoadKernel() debug data (not in print-all)"},
     96   {"vdat_timers", IS_STRING, "Timer values from VbSharedData"},
     97   {"wpsw_boot", 0, "Firmware write protect hardware switch position at boot"},
     98   {"wpsw_cur", 0, "Firmware write protect hardware switch current position"},
     99   /* Terminate with null name */
    100   {NULL, 0, NULL}
    101 };
    102 
    103 
    104 /* Print help */
    105 void PrintHelp(const char *progname) {
    106   const Param *p;
    107 
    108   printf("\nUsage:\n"
    109          "  %s [--all]\n"
    110          "    Prints all parameters with descriptions and current values.\n"
    111          "    If --all is specified, prints even normally hidden fields.\n"
    112          "  %s [param1 [param2 [...]]]\n"
    113          "    Prints the current value(s) of the parameter(s).\n"
    114          "  %s [param1=value1] [param2=value2 [...]]]\n"
    115          "    Sets the parameter(s) to the specified value(s).\n"
    116          "  %s [param1?value1] [param2?value2 [...]]]\n"
    117          "    Checks if the parameter(s) all contain the specified value(s).\n"
    118          "Stops at the first error."
    119          "\n"
    120          "Valid parameters:\n", progname, progname, progname, progname);
    121   for (p = sys_param_list; p->name; p++)
    122     printf("  %-22s  %s\n", p->name, p->desc);
    123 }
    124 
    125 
    126 /* Find the parameter in the list.
    127  *
    128  * Returns the parameter, or NULL if no match. */
    129 const Param* FindParam(const char* name) {
    130   const Param* p;
    131   if (!name)
    132     return NULL;
    133   for (p = sys_param_list; p->name; p++) {
    134     if (!strcasecmp(p->name, name))
    135       return p;
    136   }
    137   return NULL;
    138 }
    139 
    140 
    141 /* Set the specified parameter.
    142  *
    143  * Returns 0 if success, non-zero if error. */
    144 int SetParam(const Param* p, const char* value) {
    145   if (!(p->flags & CAN_WRITE))
    146     return 1;  /* Parameter is read-only */
    147 
    148   if (p->flags & IS_STRING) {
    149     return (0 == VbSetSystemPropertyString(p->name, value) ? 0 : 1);
    150   } else {
    151     char* e;
    152     int i = (int)strtol(value, &e, 0);
    153     if (!*value || (e && *e))
    154       return 1;
    155     return (0 == VbSetSystemPropertyInt(p->name, i) ? 0 : 1);
    156   }
    157 }
    158 
    159 
    160 /* Compares the parameter with the expected value.
    161  *
    162  * Returns 0 if success (match), non-zero if error (mismatch). */
    163 int CheckParam(const Param* p, char* expect) {
    164   if (p->flags & IS_STRING) {
    165     char buf[VB_MAX_STRING_PROPERTY];
    166     const char* v = VbGetSystemPropertyString(p->name, buf, sizeof(buf));
    167     if (!v || 0 != strcmp(v, expect))
    168       return 1;
    169   } else {
    170     char* e;
    171     int i = (int)strtol(expect, &e, 0);
    172     int v = VbGetSystemPropertyInt(p->name);
    173     if (!*expect || (e && *e))
    174       return 1;
    175     if (v == -1 || i != v)
    176       return 1;
    177   }
    178   return 0;
    179 }
    180 
    181 
    182 /* Print the specified parameter.
    183  *
    184  * Returns 0 if success, non-zero if error. */
    185 int PrintParam(const Param* p) {
    186   if (p->flags & IS_STRING) {
    187     char buf[VB_MAX_STRING_PROPERTY];
    188     const char* v = VbGetSystemPropertyString(p->name, buf, sizeof(buf));
    189     if (!v)
    190       return 1;
    191     printf("%s", v);
    192   } else {
    193     int v = VbGetSystemPropertyInt(p->name);
    194     if (v == -1)
    195       return 1;
    196     printf(p->format ? p->format : "%d", v);
    197   }
    198   return 0;
    199 }
    200 
    201 
    202 /* Print all parameters with descriptions.  If force_all!=0, prints even
    203  * parameters that specify the NO_PRINT_ALL flag.
    204  *
    205  * Returns 0 if success, non-zero if error. */
    206 int PrintAllParams(int force_all) {
    207   const Param* p;
    208   int retval = 0;
    209   char buf[VB_MAX_STRING_PROPERTY];
    210   const char* value;
    211 
    212   for (p = sys_param_list; p->name; p++) {
    213     if (0 == force_all && (p->flags & NO_PRINT_ALL))
    214       continue;
    215     if (p->flags & IS_STRING) {
    216       value = VbGetSystemPropertyString(p->name, buf, sizeof(buf));
    217     } else {
    218       int v = VbGetSystemPropertyInt(p->name);
    219       if (v == -1)
    220         value = NULL;
    221       else {
    222         snprintf(buf, sizeof(buf), p->format ? p->format : "%d", v);
    223         value = buf;
    224       }
    225     }
    226     printf("%-22s = %-30s # %s\n",
    227            p->name, (value ? value : "(error)"), p->desc);
    228   }
    229   return retval;
    230 }
    231 
    232 
    233 int main(int argc, char* argv[]) {
    234   int retval = 0;
    235   int i;
    236 
    237   char* progname = strrchr(argv[0], '/');
    238   if (progname)
    239     progname++;
    240   else
    241     progname = argv[0];
    242 
    243   if (VbArchInit()) {
    244     fprintf(stderr, "Failed to initialize\n");
    245     return -1;
    246   }
    247 
    248   /* If no args specified, print all params */
    249   if (argc == 1)
    250     return PrintAllParams(0);
    251   /* --all or -a prints all params including normally hidden ones */
    252   if (!strcasecmp(argv[1], "--all") || !strcmp(argv[1], "-a"))
    253     return PrintAllParams(1);
    254 
    255   /* Print help if needed */
    256   if (!strcasecmp(argv[1], "-h") || !strcmp(argv[1], "-?")) {
    257     PrintHelp(progname);
    258     return 0;
    259   }
    260 
    261   /* Otherwise, loop through params and get/set them */
    262   for (i = 1; i < argc && retval == 0; i++) {
    263     char* has_set = strchr(argv[i], '=');
    264     char* has_expect = strchr(argv[i], '?');
    265     char* name = strtok(argv[i], "=?");
    266     char* value = strtok(NULL, "=?");
    267     const Param* p;
    268 
    269     /* Make sure args are well-formed. '' or '=foo' or '?foo' not allowed. */
    270     if (!name || has_set == argv[i] || has_expect == argv[i]) {
    271       fprintf(stderr, "Poorly formed parameter\n");
    272       PrintHelp(progname);
    273       return 1;
    274     }
    275     if (!value)
    276       value=""; /* Allow setting/checking an empty string ('foo=' or 'foo?') */
    277     if (has_set && has_expect) {
    278       fprintf(stderr, "Use either = or ? in a parameter, but not both.\n");
    279       PrintHelp(progname);
    280       return 1;
    281     }
    282 
    283     /* Find the parameter */
    284     p = FindParam(name);
    285     if (!p) {
    286       fprintf(stderr, "Invalid parameter name: %s\n", name);
    287       PrintHelp(progname);
    288       return 1;
    289     }
    290 
    291     if (i > 1)
    292       printf(" ");  /* Output params space-delimited */
    293     if (has_set)
    294       retval = SetParam(p, value);
    295     else if (has_expect)
    296       retval = CheckParam(p, value);
    297     else
    298       retval = PrintParam(p);
    299   }
    300 
    301   return retval;
    302 }
    303