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