Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: host/lib/crossystem.c

Issue 6780008: Refactor crossystem to move x86-specific implementation to its own file. (Closed) Base URL: ssh://gitrw.chromium.org:9222/vboot_reference.git@master
Patch Set: post-pull Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « host/include/host_misc.h ('k') | host/lib/host_misc.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* Copyright (c) 2011 The Chromium OS Authors. All rights reserved. 1 /* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
2 * Use of this source code is governed by a BSD-style license that can be 2 * Use of this source code is governed by a BSD-style license that can be
3 * found in the LICENSE file. 3 * found in the LICENSE file.
4 */ 4 */
5 5
6 #include <stdio.h> 6 #include <stdio.h>
7 #include <string.h> 7 #include <string.h>
8 #include <sys/types.h> 8 #include <sys/types.h>
9 #include <sys/stat.h> 9 #include <sys/stat.h>
10 #include <unistd.h> 10 #include <unistd.h>
11 #include <ctype.h> 11 #include <ctype.h>
12 12
13 #include "host_common.h" 13 #include "host_common.h"
14 14
15 #include "crossystem.h" 15 #include "crossystem.h"
16 #include "crossystem_arch.h"
16 #include "utility.h" 17 #include "utility.h"
17 #include "vboot_common.h" 18 #include "vboot_common.h"
18 #include "vboot_nvstorage.h" 19 #include "vboot_nvstorage.h"
19 #include "vboot_struct.h" 20 #include "vboot_struct.h"
20 21
21 /* ACPI constants from Chrome OS Main Processor Firmware Spec */
22 /* GPIO signal types */
23 #define GPIO_SIGNAL_TYPE_RECOVERY 1
24 #define GPIO_SIGNAL_TYPE_DEV 2
25 #define GPIO_SIGNAL_TYPE_WP 3
26 /* CHSW bitflags */
27 #define CHSW_RECOVERY_BOOT 0x00000002
28 #define CHSW_RECOVERY_EC_BOOT 0x00000004
29 #define CHSW_DEV_BOOT 0x00000020
30 #define CHSW_WP_BOOT 0x00000200
31 /* CMOS reboot field bitflags */
32 #define CMOSRF_RECOVERY 0x80
33 #define CMOSRF_DEBUG_RESET 0x40
34 #define CMOSRF_TRY_B 0x20
35 /* Boot reasons from BINF.0, from early H2C firmware */
36 /* Unknown */
37 #define BINF0_UNKNOWN 0
38 /* Normal boot to Chrome OS */
39 #define BINF0_NORMAL 1
40 /* Developer mode boot (developer mode warning displayed) */
41 #define BINF0_DEVELOPER 2
42 /* Recovery initiated by user, using recovery button */
43 #define BINF0_RECOVERY_BUTTON 3
44 /* Recovery initiated by user pressing a key at developer mode warning
45 * screen */
46 #define BINF0_RECOVERY_DEV_SCREEN_KEY 4
47 /* Recovery caused by BIOS failed signature check (neither rewritable
48 * firmware was valid) */
49 #define BINF0_RECOVERY_RW_FW_BAD 5
50 /* Recovery caused by no OS kernel detected */
51 #define BINF0_RECOVERY_NO_OS 6
52 /* Recovery caused by OS kernel failed signature check */
53 #define BINF0_RECOVERY_BAD_OS 7
54 /* Recovery initiated by OS */
55 #define BINF0_RECOVERY_OS_INITIATED 8
56 /* OS-initiated S3 diagnostic path (debug mode boot) */
57 #define BINF0_S3_DIAGNOSTIC_PATH 9
58 /* S3 resume failed */
59 #define BINF0_S3_RESUME_FAILED 10
60 /* Recovery caused by TPM error */
61 #define BINF0_RECOVERY_TPM_ERROR 11
62 /* Firmware types from BINF.3 */
63 #define BINF3_RECOVERY 0
64 #define BINF3_NORMAL 1
65 #define BINF3_DEVELOPER 2
66
67 /* Base name for ACPI files */
68 #define ACPI_BASE_PATH "/sys/devices/platform/chromeos_acpi"
69 /* Paths for frequently used ACPI files */
70 #define ACPI_BINF_PATH ACPI_BASE_PATH "/BINF"
71 #define ACPI_CHNV_PATH ACPI_BASE_PATH "/CHNV"
72 #define ACPI_CHSW_PATH ACPI_BASE_PATH "/CHSW"
73 #define ACPI_FMAP_PATH ACPI_BASE_PATH "/FMAP"
74 #define ACPI_GPIO_PATH ACPI_BASE_PATH "/GPIO"
75 #define ACPI_VBNV_PATH ACPI_BASE_PATH "/VBNV"
76 #define ACPI_VDAT_PATH ACPI_BASE_PATH "/VDAT"
77
78 /* Base name for GPIO files */
79 #define GPIO_BASE_PATH "/sys/class/gpio"
80 #define GPIO_EXPORT_PATH GPIO_BASE_PATH "/export"
81
82 /* Filename for NVRAM file */
83 #define NVRAM_PATH "/dev/nvram"
84
85 /* Filename for kernel command line */ 22 /* Filename for kernel command line */
86 #define KERNEL_CMDLINE_PATH "/proc/cmdline" 23 #define KERNEL_CMDLINE_PATH "/proc/cmdline"
87 24
88 /* A structure to contain buffer data retrieved from the ACPI. */
89 typedef struct {
90 int buffer_size;
91 uint8_t* buffer;
92 } AcpiBuffer;
93
94
95 /* Fields that GetVdatString() can get */ 25 /* Fields that GetVdatString() can get */
96 typedef enum VdatStringField { 26 typedef enum VdatStringField {
97 VDAT_STRING_TIMERS = 0, /* Timer values */ 27 VDAT_STRING_TIMERS = 0, /* Timer values */
98 VDAT_STRING_LOAD_FIRMWARE_DEBUG, /* LoadFirmware() debug information */ 28 VDAT_STRING_LOAD_FIRMWARE_DEBUG, /* LoadFirmware() debug information */
99 VDAT_STRING_LOAD_KERNEL_DEBUG /* LoadKernel() debug information */ 29 VDAT_STRING_LOAD_KERNEL_DEBUG /* LoadKernel() debug information */
100 } VdatStringField; 30 } VdatStringField;
101 31
102 32
103 /* Fields that GetVdatInt() can get */ 33 /* Fields that GetVdatInt() can get */
104 typedef enum VdatIntField { 34 typedef enum VdatIntField {
105 VDAT_INT_FLAGS = 0, /* Flags */ 35 VDAT_INT_FLAGS = 0, /* Flags */
106 VDAT_INT_FW_VERSION_TPM, /* Current firmware version in TPM */ 36 VDAT_INT_FW_VERSION_TPM, /* Current firmware version in TPM */
107 VDAT_INT_KERNEL_VERSION_TPM, /* Current kernel version in TPM */ 37 VDAT_INT_KERNEL_VERSION_TPM, /* Current kernel version in TPM */
108 VDAT_INT_TRIED_FIRMWARE_B, /* Tried firmware B due to fwb_tries */ 38 VDAT_INT_TRIED_FIRMWARE_B, /* Tried firmware B due to fwb_tries */
109 VDAT_INT_KERNEL_KEY_VERIFIED /* Kernel key verified using 39 VDAT_INT_KERNEL_KEY_VERIFIED /* Kernel key verified using
110 * signature, not just hash */ 40 * signature, not just hash */
111 } VdatIntField; 41 } VdatIntField;
112 42
113 43
114 /* Copy up to dest_size-1 characters from src to dest, ensuring null
115 termination (which strncpy() doesn't do). Returns the destination
116 string. */
117 char* StrCopy(char* dest, const char* src, int dest_size) {
118 strncpy(dest, src, dest_size);
119 dest[dest_size - 1] = '\0';
120 return dest;
121 }
122
123
124 /* Read a string from a file. Passed the destination, dest size, and
125 * filename to read.
126 *
127 * Returns the destination, or NULL if error. */
128 char* ReadFileString(char* dest, int size, const char* filename) {
129 char* got;
130 FILE* f;
131
132 f = fopen(filename, "rt");
133 if (!f)
134 return NULL;
135
136 got = fgets(dest, size, f);
137 fclose(f);
138 return got;
139 }
140
141
142 /* Read an integer from a file.
143 *
144 * Returns the parsed integer, or -1 if error. */
145 int ReadFileInt(const char* filename) {
146 char buf[64];
147 int value;
148 char* e = NULL;
149
150 if (!ReadFileString(buf, sizeof(buf), filename))
151 return -1;
152
153 /* Convert to integer. Allow characters after the int ("123 blah"). */
154 value = strtol(buf, &e, 0);
155 if (e == buf)
156 return -1; /* No characters consumed, so conversion failed */
157
158 return value;
159 }
160
161
162 /* Check if a bit is set in a file which contains an integer.
163 *
164 * Returns 1 if the bit is set, 0 if clear, or -1 if error. */
165 int ReadFileBit(const char* filename, int bitmask) {
166 int value = ReadFileInt(filename);
167 if (value == -1)
168 return -1;
169 else return (value & bitmask ? 1 : 0);
170 }
171
172
173 /* Return true if the FWID starts with the specified string. */ 44 /* Return true if the FWID starts with the specified string. */
174 static int FwidStartsWith(const char *start) { 45 int FwidStartsWith(const char *start) {
175 char fwid[128]; 46 char fwid[128];
176 if (!VbGetSystemPropertyString("fwid", fwid, sizeof(fwid))) 47 if (!VbGetSystemPropertyString("fwid", fwid, sizeof(fwid)))
177 return 0; 48 return 0;
178 49
179 return 0 == strncmp(fwid, start, strlen(start)); 50 return 0 == strncmp(fwid, start, strlen(start));
180 } 51 }
181 52
182 53
183 /* Read a GPIO of the specified signal type (see ACPI GPIO SignalType).
184 *
185 * Returns 1 if the signal is asserted, 0 if not asserted, or -1 if error. */
186 int ReadGpio(int signal_type) {
187 char name[128];
188 int index = 0;
189 int gpio_type;
190 int active_high;
191 int controller_offset;
192 char controller_name[128];
193 int value;
194
195 /* Scan GPIO.* to find a matching signal type */
196 for (index = 0; ; index++) {
197 snprintf(name, sizeof(name), "%s.%d/GPIO.0", ACPI_GPIO_PATH, index);
198 gpio_type = ReadFileInt(name);
199 if (gpio_type == signal_type)
200 break;
201 else if (gpio_type == -1)
202 return -1; /* Ran out of GPIOs before finding a match */
203 }
204
205 /* Read attributes and controller info for the GPIO */
206 snprintf(name, sizeof(name), "%s.%d/GPIO.1", ACPI_GPIO_PATH, index);
207 active_high = ReadFileBit(name, 0x00000001);
208 snprintf(name, sizeof(name), "%s.%d/GPIO.2", ACPI_GPIO_PATH, index);
209 controller_offset = ReadFileInt(name);
210 if (active_high == -1 || controller_offset == -1)
211 return -1; /* Missing needed info */
212
213 /* We only support the NM10 for now */
214 snprintf(name, sizeof(name), "%s.%d/GPIO.3", ACPI_GPIO_PATH, index);
215 if (!ReadFileString(controller_name, sizeof(controller_name), name))
216 return -1;
217 if (0 != strcmp(controller_name, "NM10"))
218 return -1;
219
220 /* Assume the NM10 has offset 192 */
221 /* TODO: should really check gpiochipNNN/label to see if it's the
222 * address we expect for the NM10, and then read the offset from
223 * gpiochipNNN/base. */
224 controller_offset += 192;
225
226 /* Try reading the GPIO value */
227 snprintf(name, sizeof(name), "%s/gpio%d/value",
228 GPIO_BASE_PATH, controller_offset);
229 value = ReadFileInt(name);
230
231 if (value == -1) {
232 /* Try exporting the GPIO */
233 FILE* f = fopen(GPIO_EXPORT_PATH, "wt");
234 if (!f)
235 return -1;
236 fprintf(f, "%d", controller_offset);
237 fclose(f);
238
239 /* Try re-reading the GPIO value */
240 value = ReadFileInt(name);
241 }
242
243 if (value == -1)
244 return -1;
245
246 /* Compare the GPIO value with the active value and return 1 if match. */
247 return (value == active_high ? 1 : 0);
248 }
249
250
251 /* Read the CMOS reboot field in NVRAM.
252 *
253 * Returns 0 if the mask is clear in the field, 1 if set, or -1 if error. */
254 int VbGetCmosRebootField(uint8_t mask) {
255 FILE* f;
256 int chnv, nvbyte;
257
258 /* Get the byte offset from CHNV */
259 chnv = ReadFileInt(ACPI_CHNV_PATH);
260 if (chnv == -1)
261 return -1;
262
263 f = fopen(NVRAM_PATH, "rb");
264 if (!f)
265 return -1;
266
267 if (0 != fseek(f, chnv, SEEK_SET) || EOF == (nvbyte = fgetc(f))) {
268 fclose(f);
269 return -1;
270 }
271
272 fclose(f);
273 return (nvbyte & mask ? 1 : 0);
274 }
275
276
277 /* Write the CMOS reboot field in NVRAM.
278 *
279 * Sets (value=0) or clears (value!=0) the mask in the byte.
280 *
281 * Returns 0 if success, or -1 if error. */
282 int VbSetCmosRebootField(uint8_t mask, int value) {
283 FILE* f;
284 int chnv, nvbyte;
285
286 /* Get the byte offset from CHNV */
287 chnv = ReadFileInt(ACPI_CHNV_PATH);
288 if (chnv == -1)
289 return -1;
290
291 f = fopen(NVRAM_PATH, "w+b");
292 if (!f)
293 return -1;
294
295 /* Read the current value */
296 if (0 != fseek(f, chnv, SEEK_SET) || EOF == (nvbyte = fgetc(f))) {
297 fclose(f);
298 return -1;
299 }
300
301 /* Set/clear the mask */
302 if (value)
303 nvbyte |= mask;
304 else
305 nvbyte &= ~mask;
306
307 /* Write the byte back */
308 if (0 != fseek(f, chnv, SEEK_SET) || EOF == (fputc(nvbyte, f))) {
309 fclose(f);
310 return -1;
311 }
312
313 /* Success */
314 fclose(f);
315 return 0;
316 }
317
318 /*
319 * Get buffer data from ACPI.
320 *
321 * Buffer data is expected to be represented by a file which is a text dump of
322 * the buffer, representing each byte by two hex numbers, space and newline
323 * separated.
324 *
325 * Input - ACPI file name to get data from.
326 *
327 * Output: a pointer to AcpiBuffer structure containing the binary
328 * representation of the data. The caller is responsible for
329 * deallocating the pointer, this will take care of both the structure
330 * and the buffer. Null in case of error.
331 */
332
333 AcpiBuffer* VbGetBuffer(const char* filename)
334 {
335 FILE* f = NULL;
336 char* file_buffer = NULL;
337 AcpiBuffer* acpi_buffer = NULL;
338 AcpiBuffer* return_value = NULL;
339
340 do {
341 struct stat fs;
342 uint8_t* output_ptr;
343 int rv, i, real_size;
344
345 rv = stat(filename, &fs);
346 if (rv || !S_ISREG(fs.st_mode))
347 break;
348
349 f = fopen(filename, "r");
350 if (!f)
351 break;
352
353 file_buffer = Malloc(fs.st_size + 1);
354 if (!file_buffer)
355 break;
356
357 real_size = fread(file_buffer, 1, fs.st_size, f);
358 if (!real_size)
359 break;
360 file_buffer[real_size] = '\0';
361
362 /* Each byte in the output will replace two characters and a space
363 * in the input, so the output size does not exceed input side/3
364 * (a little less if account for newline characters). */
365 acpi_buffer = Malloc(sizeof(AcpiBuffer) + real_size/3);
366 if (!acpi_buffer)
367 break;
368 acpi_buffer->buffer = (uint8_t*)(acpi_buffer + 1);
369 acpi_buffer->buffer_size = 0;
370 output_ptr = acpi_buffer->buffer;
371
372 /* process the file contents */
373 for (i = 0; i < real_size; i++) {
374 char* base, *end;
375
376 base = file_buffer + i;
377
378 if (!isxdigit(*base))
379 continue;
380
381 output_ptr[acpi_buffer->buffer_size++] = strtol(base, &end, 16) & 0xff;
382
383 if ((end - base) != 2)
384 /* Input file format error */
385 break;
386
387 i += 2; /* skip the second character and the following space */
388 }
389
390 if (i == real_size) {
391 /* all is well */
392 return_value = acpi_buffer;
393 acpi_buffer = NULL; /* prevent it from deallocating */
394 }
395 } while(0);
396
397 /* wrap up */
398 if (f)
399 fclose(f);
400
401 if (file_buffer)
402 Free(file_buffer);
403
404 if (acpi_buffer)
405 Free(acpi_buffer);
406
407 return return_value;
408 }
409
410 /* Read an integer property from VbNvStorage.
411 *
412 * Returns the parameter value, or -1 if error. */
413 int VbGetNvStorage(VbNvParam param) { 54 int VbGetNvStorage(VbNvParam param) {
414 FILE* f;
415 VbNvContext vnc; 55 VbNvContext vnc;
416 int offs;
417 uint32_t value; 56 uint32_t value;
418 int retval; 57 int retval;
419 58
420 /* Get the byte offset from VBNV */ 59 /* TODO: locking around NV access */
421 offs = ReadFileInt(ACPI_VBNV_PATH ".0"); 60
422 if (offs == -1) 61 if (0 != VbReadNvStorage(&vnc))
423 return -1; 62 return -1;
424 if (VBNV_BLOCK_SIZE > ReadFileInt(ACPI_VBNV_PATH ".1"))
425 return -1; /* NV storage block is too small */
426
427 /* TODO: locking around NV access */
428 f = fopen(NVRAM_PATH, "rb");
429 if (!f)
430 return -1;
431
432 if (0 != fseek(f, offs, SEEK_SET) ||
433 1 != fread(vnc.raw, VBNV_BLOCK_SIZE, 1, f)) {
434 fclose(f);
435 return -1;
436 }
437
438 fclose(f);
439
440 if (0 != VbNvSetup(&vnc)) 63 if (0 != VbNvSetup(&vnc))
441 return -1; 64 return -1;
442 retval = VbNvGet(&vnc, param, &value); 65 retval = VbNvGet(&vnc, param, &value);
443 if (0 != VbNvTeardown(&vnc)) 66 if (0 != VbNvTeardown(&vnc))
444 return -1; 67 return -1;
445 if (0 != retval) 68 if (0 != retval)
446 return -1; 69 return -1;
447 70
448 /* TODO: If vnc.raw_changed, attempt to reopen NVRAM for write and 71 /* TODO: If vnc.raw_changed, attempt to reopen NVRAM for write and
449 * save the new defaults. If we're able to, log. */ 72 * save the new defaults. If we're able to, log. */
450 /* TODO: release lock */ 73 /* TODO: release lock */
451 74
452 return (int)value; 75 return (int)value;
453 } 76 }
454 77
455 78
456 /* Write an integer property to VbNvStorage.
457 *
458 * Returns 0 if success, -1 if error. */
459 int VbSetNvStorage(VbNvParam param, int value) { 79 int VbSetNvStorage(VbNvParam param, int value) {
460 FILE* f;
461 VbNvContext vnc; 80 VbNvContext vnc;
462 int offs;
463 int retval = -1; 81 int retval = -1;
464 int i; 82 int i;
465 83
466 /* Get the byte offset from VBNV */ 84 if (0 != VbReadNvStorage(&vnc))
467 offs = ReadFileInt(ACPI_VBNV_PATH ".0");
468 if (offs == -1)
469 return -1; 85 return -1;
470 if (VBNV_BLOCK_SIZE > ReadFileInt(ACPI_VBNV_PATH ".1"))
471 return -1; /* NV storage block is too small */
472
473 /* TODO: locking around NV access */
474 f = fopen(NVRAM_PATH, "w+b");
475 if (!f)
476 return -1;
477
478 if (0 != fseek(f, offs, SEEK_SET) ||
479 1 != fread(vnc.raw, VBNV_BLOCK_SIZE, 1, f)) {
480 goto VbSetNvCleanup;
481 }
482 86
483 if (0 != VbNvSetup(&vnc)) 87 if (0 != VbNvSetup(&vnc))
484 goto VbSetNvCleanup; 88 goto VbSetNvCleanup;
485 i = VbNvSet(&vnc, param, (uint32_t)value); 89 i = VbNvSet(&vnc, param, (uint32_t)value);
486 if (0 != VbNvTeardown(&vnc)) 90 if (0 != VbNvTeardown(&vnc))
487 goto VbSetNvCleanup; 91 goto VbSetNvCleanup;
488 if (0 != i) 92 if (0 != i)
489 goto VbSetNvCleanup; 93 goto VbSetNvCleanup;
490 94
491 if (vnc.raw_changed) { 95 if (vnc.raw_changed) {
492 if (0 != fseek(f, offs, SEEK_SET) || 96 if (0 != VbReadNvStorage(&vnc))
493 1 != fwrite(vnc.raw, VBNV_BLOCK_SIZE, 1, f))
494 goto VbSetNvCleanup; 97 goto VbSetNvCleanup;
495 } 98 }
496 99
497 /* Success */ 100 /* Success */
498 retval = 0; 101 retval = 0;
499 102
500 VbSetNvCleanup: 103 VbSetNvCleanup:
501 fclose(f);
502 /* TODO: release lock */ 104 /* TODO: release lock */
503 return retval; 105 return retval;
504 } 106 }
505 107
506 108
507 /* Read the recovery reason. Returns the reason code or -1 if error. */
508 int VbGetRecoveryReason(void) {
509 int value;
510
511 /* Try reading type from BINF.4 */
512 value = ReadFileInt(ACPI_BINF_PATH ".4");
513 if (-1 != value)
514 return value;
515
516 /* Fall back to BINF.0 for legacy systems like Mario. */
517 switch(ReadFileInt(ACPI_BINF_PATH ".0")) {
518 case BINF0_NORMAL:
519 case BINF0_DEVELOPER:
520 return VBNV_RECOVERY_NOT_REQUESTED;
521 case BINF0_RECOVERY_BUTTON:
522 return VBNV_RECOVERY_RO_MANUAL;
523 case BINF0_RECOVERY_DEV_SCREEN_KEY:
524 return VBNV_RECOVERY_RW_DEV_SCREEN;
525 case BINF0_RECOVERY_RW_FW_BAD:
526 case BINF0_RECOVERY_NO_OS:
527 return VBNV_RECOVERY_RW_NO_OS;
528 case BINF0_RECOVERY_BAD_OS:
529 return VBNV_RECOVERY_RW_INVALID_OS;
530 case BINF0_RECOVERY_OS_INITIATED:
531 return VBNV_RECOVERY_LEGACY;
532 default:
533 /* Other values don't map cleanly to firmware type. */
534 return -1;
535 }
536 }
537
538
539 /* Read the active main firmware type into the destination buffer.
540 * Passed the destination and its size. Returns the destination, or
541 * NULL if error. */
542 const char* VbReadMainFwType(char* dest, int size) {
543
544 /* Try reading type from BINF.3 */
545 switch(ReadFileInt(ACPI_BINF_PATH ".3")) {
546 case BINF3_RECOVERY:
547 return StrCopy(dest, "recovery", size);
548 case BINF3_NORMAL:
549 return StrCopy(dest, "normal", size);
550 case BINF3_DEVELOPER:
551 return StrCopy(dest, "developer", size);
552 default:
553 break; /* Fall through to legacy handling */
554 }
555
556 /* Fall back to BINF.0 for legacy systems like Mario. */
557 switch(ReadFileInt(ACPI_BINF_PATH ".0")) {
558 case -1:
559 /* Both BINF.0 and BINF.3 are missing, so this isn't Chrome OS
560 * firmware. */
561 return StrCopy(dest, "nonchrome", size);
562 case BINF0_NORMAL:
563 return StrCopy(dest, "normal", size);
564 case BINF0_DEVELOPER:
565 return StrCopy(dest, "developer", size);
566 case BINF0_RECOVERY_BUTTON:
567 case BINF0_RECOVERY_DEV_SCREEN_KEY:
568 case BINF0_RECOVERY_RW_FW_BAD:
569 case BINF0_RECOVERY_NO_OS:
570 case BINF0_RECOVERY_BAD_OS:
571 case BINF0_RECOVERY_OS_INITIATED:
572 case BINF0_RECOVERY_TPM_ERROR:
573 /* Assorted flavors of recovery boot reason. */
574 return StrCopy(dest, "recovery", size);
575 default:
576 /* Other values don't map cleanly to firmware type. */
577 return NULL;
578 }
579 }
580
581
582 /* Determine whether OS-level debugging should be allowed. Passed the 109 /* Determine whether OS-level debugging should be allowed. Passed the
583 * destination and its size. Returns 1 if yes, 0 if no, -1 if error. */ 110 * destination and its size. Returns 1 if yes, 0 if no, -1 if error. */
584 int VbGetCrosDebug(void) { 111 int VbGetCrosDebug(void) {
585 FILE* f = NULL; 112 FILE* f = NULL;
586 char buf[4096] = ""; 113 char buf[4096] = "";
587 int binf3;
588 char *t, *saveptr; 114 char *t, *saveptr;
589 115
590 /* Try reading firmware type from BINF.3. */ 116 /* Try reading firmware type. */
591 binf3 = ReadFileInt(ACPI_BINF_PATH ".3"); 117 if (VbGetArchPropertyString("mainfw_type", buf, sizeof(buf))) {
592 if (BINF3_RECOVERY == binf3) 118 if (0 == strcmp(buf, "recovery"))
593 return 0; /* Recovery mode never allows debug. */ 119 return 0; /* Recovery mode never allows debug. */
594 else if (BINF3_DEVELOPER == binf3) 120 else if (0 == strcmp(buf, "developer"))
595 return 1; /* Developer firmware always allows debug. */ 121 return 1; /* Developer firmware always allows debug. */
122 }
596 123
597 /* Normal new firmware, older ChromeOS firmware, or non-Chrome firmware. 124 /* Normal new firmware, older ChromeOS firmware, or non-Chrome firmware.
598 * For all these cases, check /proc/cmdline for cros_[no]debug. */ 125 * For all these cases, check /proc/cmdline for cros_[no]debug. */
599 f = fopen(KERNEL_CMDLINE_PATH, "rt"); 126 f = fopen(KERNEL_CMDLINE_PATH, "rt");
600 if (f) { 127 if (f) {
601 if (NULL == fgets(buf, sizeof(buf), f)) 128 if (NULL == fgets(buf, sizeof(buf), f))
602 *buf = 0; 129 *buf = 0;
603 fclose(f); 130 fclose(f);
604 } 131 }
605 for (t = strtok_r(buf, " ", &saveptr); t; t=strtok_r(NULL, " ", &saveptr)) { 132 for (t = strtok_r(buf, " ", &saveptr); t; t=strtok_r(NULL, " ", &saveptr)) {
606 if (0 == strcmp(t, "cros_debug")) 133 if (0 == strcmp(t, "cros_debug"))
607 return 1; 134 return 1;
608 else if (0 == strcmp(t, "cros_nodebug")) 135 else if (0 == strcmp(t, "cros_nodebug"))
609 return 0; 136 return 0;
610 } 137 }
611 138
612 /* Normal new firmware or older Chrome OS firmware allows debug if the 139 /* Normal new firmware or older Chrome OS firmware allows debug if the
613 * dev switch is on. */ 140 * dev switch is on. */
614 if (1 == ReadFileBit(ACPI_CHSW_PATH, CHSW_DEV_BOOT)) 141 if (1 == VbGetSystemPropertyInt("devsw_boot"))
615 return 1; 142 return 1;
616 143
617 /* All other cases disallow debug. */ 144 /* All other cases disallow debug. */
618 return 0; 145 return 0;
619 } 146 }
620 147
621 148
622 char* GetVdatLoadFirmwareDebug(char* dest, int size, 149 char* GetVdatLoadFirmwareDebug(char* dest, int size,
623 const VbSharedDataHeader* sh) { 150 const VbSharedDataHeader* sh) {
624 snprintf(dest, size, 151 snprintf(dest, size,
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
726 /* Warn if data was truncated; we left space for this above. */ 253 /* Warn if data was truncated; we left space for this above. */
727 if (used > size) 254 if (used > size)
728 strcat(dest, TRUNCATED); 255 strcat(dest, TRUNCATED);
729 256
730 return dest; 257 return dest;
731 } 258 }
732 259
733 260
734 char* GetVdatString(char* dest, int size, VdatStringField field) 261 char* GetVdatString(char* dest, int size, VdatStringField field)
735 { 262 {
736 VbSharedDataHeader* sh; 263 VbSharedDataHeader* sh = VbSharedDataRead();
737 AcpiBuffer* ab = VbGetBuffer(ACPI_VDAT_PATH);
738 char* value = dest; 264 char* value = dest;
739 if (!ab) 265
266 if (!sh)
740 return NULL; 267 return NULL;
741 268
742 sh = (VbSharedDataHeader*)ab->buffer;
743
744 switch (field) { 269 switch (field) {
745 case VDAT_STRING_TIMERS: 270 case VDAT_STRING_TIMERS:
746 snprintf(dest, size, 271 snprintf(dest, size,
747 "LFS=%" PRIu64 ",%" PRIu64 272 "LFS=%" PRIu64 ",%" PRIu64
748 " LF=%" PRIu64 ",%" PRIu64 273 " LF=%" PRIu64 ",%" PRIu64
749 " LK=%" PRIu64 ",%" PRIu64, 274 " LK=%" PRIu64 ",%" PRIu64,
750 sh->timer_load_firmware_start_enter, 275 sh->timer_load_firmware_start_enter,
751 sh->timer_load_firmware_start_exit, 276 sh->timer_load_firmware_start_exit,
752 sh->timer_load_firmware_enter, 277 sh->timer_load_firmware_enter,
753 sh->timer_load_firmware_exit, 278 sh->timer_load_firmware_exit,
754 sh->timer_load_kernel_enter, 279 sh->timer_load_kernel_enter,
755 sh->timer_load_kernel_exit); 280 sh->timer_load_kernel_exit);
756 break; 281 break;
757 282
758 case VDAT_STRING_LOAD_FIRMWARE_DEBUG: 283 case VDAT_STRING_LOAD_FIRMWARE_DEBUG:
759 value = GetVdatLoadFirmwareDebug(dest, size, sh); 284 value = GetVdatLoadFirmwareDebug(dest, size, sh);
760 break; 285 break;
761 286
762 case VDAT_STRING_LOAD_KERNEL_DEBUG: 287 case VDAT_STRING_LOAD_KERNEL_DEBUG:
763 value = GetVdatLoadKernelDebug(dest, size, sh); 288 value = GetVdatLoadKernelDebug(dest, size, sh);
764 break; 289 break;
765 290
766 default: 291 default:
767 Free(ab); 292 value = NULL;
768 return NULL; 293 break;
769 } 294 }
770 295
771 Free(ab); 296 Free(sh);
772 return value; 297 return value;
773 } 298 }
774 299
775 300
776 int GetVdatInt(VdatIntField field) { 301 int GetVdatInt(VdatIntField field) {
777 VbSharedDataHeader* sh; 302 VbSharedDataHeader* sh = VbSharedDataRead();
778 AcpiBuffer* ab = VbGetBuffer(ACPI_VDAT_PATH);
779 int value = -1; 303 int value = -1;
780 304
781 if (!ab) 305 if (!sh)
782 return -1; 306 return -1;
783 307
784 sh = (VbSharedDataHeader*)ab->buffer;
785
786 switch (field) { 308 switch (field) {
787 case VDAT_INT_FLAGS: 309 case VDAT_INT_FLAGS:
788 value = (int)sh->flags; 310 value = (int)sh->flags;
789 break; 311 break;
790 case VDAT_INT_FW_VERSION_TPM: 312 case VDAT_INT_FW_VERSION_TPM:
791 value = (int)sh->fw_version_tpm; 313 value = (int)sh->fw_version_tpm;
792 break; 314 break;
793 case VDAT_INT_KERNEL_VERSION_TPM: 315 case VDAT_INT_KERNEL_VERSION_TPM:
794 value = (int)sh->kernel_version_tpm; 316 value = (int)sh->kernel_version_tpm;
795 break; 317 break;
796 case VDAT_INT_TRIED_FIRMWARE_B: 318 case VDAT_INT_TRIED_FIRMWARE_B:
797 value = (sh->flags & VBSD_FWB_TRIED ? 1 : 0); 319 value = (sh->flags & VBSD_FWB_TRIED ? 1 : 0);
798 break; 320 break;
799 case VDAT_INT_KERNEL_KEY_VERIFIED: 321 case VDAT_INT_KERNEL_KEY_VERIFIED:
800 value = (sh->flags & VBSD_KERNEL_KEY_VERIFIED ? 1 : 0); 322 value = (sh->flags & VBSD_KERNEL_KEY_VERIFIED ? 1 : 0);
801 break; 323 break;
802 } 324 }
803 325
804 Free(ab); 326 Free(sh);
805 return value; 327 return value;
806 } 328 }
807 329
808 330
809 /* Read a system property integer.
810 *
811 * Returns the property value, or -1 if error. */
812 int VbGetSystemPropertyInt(const char* name) { 331 int VbGetSystemPropertyInt(const char* name) {
813 int value = -1; 332 int value = -1;
814 333
815 /* Switch positions */ 334 /* Check architecture-dependent properties first */
816 if (!strcasecmp(name,"devsw_cur")) { 335 value = VbGetArchPropertyInt(name);
817 value = ReadGpio(GPIO_SIGNAL_TYPE_DEV); 336 if (-1 != value)
818 } else if (!strcasecmp(name,"devsw_boot")) { 337 return value;
819 value = ReadFileBit(ACPI_CHSW_PATH, CHSW_DEV_BOOT); 338
820 } else if (!strcasecmp(name,"recoverysw_cur")) { 339 /* NV storage values */
821 value = ReadGpio(GPIO_SIGNAL_TYPE_RECOVERY);
822 } else if (!strcasecmp(name,"recoverysw_boot")) {
823 value = ReadFileBit(ACPI_CHSW_PATH, CHSW_RECOVERY_BOOT);
824 } else if (!strcasecmp(name,"recoverysw_ec_boot")) {
825 value = ReadFileBit(ACPI_CHSW_PATH, CHSW_RECOVERY_EC_BOOT);
826 } else if (!strcasecmp(name,"wpsw_cur")) {
827 value = ReadGpio(GPIO_SIGNAL_TYPE_WP);
828 if (-1 != value && FwidStartsWith("Mario."))
829 value = 1 - value; /* Mario reports this backwards */
830 } else if (!strcasecmp(name,"wpsw_boot")) {
831 value = ReadFileBit(ACPI_CHSW_PATH, CHSW_WP_BOOT);
832 if (-1 != value && FwidStartsWith("Mario."))
833 value = 1 - value; /* Mario reports this backwards */
834 }
835 /* Saved memory is at a fixed location for all H2C BIOS. If the CHSW
836 * path exists in sysfs, it's a H2C BIOS. */
837 else if (!strcasecmp(name,"savedmem_base")) {
838 return (-1 == ReadFileInt(ACPI_CHSW_PATH) ? -1 : 0x00F00000);
839 } else if (!strcasecmp(name,"savedmem_size")) {
840 return (-1 == ReadFileInt(ACPI_CHSW_PATH) ? -1 : 0x00100000);
841 }
842 /* NV storage values with no defaults for older BIOS. */
843 else if (!strcasecmp(name,"kern_nv")) { 340 else if (!strcasecmp(name,"kern_nv")) {
844 value = VbGetNvStorage(VBNV_KERNEL_FIELD); 341 value = VbGetNvStorage(VBNV_KERNEL_FIELD);
845 } else if (!strcasecmp(name,"nvram_cleared")) { 342 } else if (!strcasecmp(name,"nvram_cleared")) {
846 value = VbGetNvStorage(VBNV_KERNEL_SETTINGS_RESET); 343 value = VbGetNvStorage(VBNV_KERNEL_SETTINGS_RESET);
847 } else if (!strcasecmp(name,"vbtest_errfunc")) { 344 } else if (!strcasecmp(name,"vbtest_errfunc")) {
848 value = VbGetNvStorage(VBNV_TEST_ERROR_FUNC); 345 value = VbGetNvStorage(VBNV_TEST_ERROR_FUNC);
849 } else if (!strcasecmp(name,"vbtest_errno")) { 346 } else if (!strcasecmp(name,"vbtest_errno")) {
850 value = VbGetNvStorage(VBNV_TEST_ERROR_NUM); 347 value = VbGetNvStorage(VBNV_TEST_ERROR_NUM);
851 } 348 } else if (!strcasecmp(name,"recovery_request")) {
852 /* NV storage values. If unable to get from NV storage, fall back to the
853 * CMOS reboot field used by older BIOS. */
854 else if (!strcasecmp(name,"recovery_request")) {
855 value = VbGetNvStorage(VBNV_RECOVERY_REQUEST); 349 value = VbGetNvStorage(VBNV_RECOVERY_REQUEST);
856 if (-1 == value)
857 value = VbGetCmosRebootField(CMOSRF_RECOVERY);
858 } else if (!strcasecmp(name,"dbg_reset")) { 350 } else if (!strcasecmp(name,"dbg_reset")) {
859 value = VbGetNvStorage(VBNV_DEBUG_RESET_MODE); 351 value = VbGetNvStorage(VBNV_DEBUG_RESET_MODE);
860 if (-1 == value)
861 value = VbGetCmosRebootField(CMOSRF_DEBUG_RESET);
862 } else if (!strcasecmp(name,"fwb_tries")) { 352 } else if (!strcasecmp(name,"fwb_tries")) {
863 value = VbGetNvStorage(VBNV_TRY_B_COUNT); 353 value = VbGetNvStorage(VBNV_TRY_B_COUNT);
864 if (-1 == value)
865 value = VbGetCmosRebootField(CMOSRF_TRY_B);
866 } 354 }
867 /* Other parameters */ 355 /* Other parameters */
868 else if (!strcasecmp(name,"recovery_reason")) { 356 else if (!strcasecmp(name,"cros_debug")) {
869 return VbGetRecoveryReason();
870 } else if (!strcasecmp(name,"fmap_base")) {
871 value = ReadFileInt(ACPI_FMAP_PATH);
872 } else if (!strcasecmp(name,"cros_debug")) {
873 value = VbGetCrosDebug(); 357 value = VbGetCrosDebug();
874 } else if (!strcasecmp(name,"vdat_flags")) { 358 } else if (!strcasecmp(name,"vdat_flags")) {
875 value = GetVdatInt(VDAT_INT_FLAGS); 359 value = GetVdatInt(VDAT_INT_FLAGS);
876 } else if (!strcasecmp(name,"tpm_fwver")) { 360 } else if (!strcasecmp(name,"tpm_fwver")) {
877 value = GetVdatInt(VDAT_INT_FW_VERSION_TPM); 361 value = GetVdatInt(VDAT_INT_FW_VERSION_TPM);
878 } else if (!strcasecmp(name,"tpm_kernver")) { 362 } else if (!strcasecmp(name,"tpm_kernver")) {
879 value = GetVdatInt(VDAT_INT_KERNEL_VERSION_TPM); 363 value = GetVdatInt(VDAT_INT_KERNEL_VERSION_TPM);
880 } else if (!strcasecmp(name,"tried_fwb")) { 364 } else if (!strcasecmp(name,"tried_fwb")) {
881 value = GetVdatInt(VDAT_INT_TRIED_FIRMWARE_B); 365 value = GetVdatInt(VDAT_INT_TRIED_FIRMWARE_B);
882 } 366 }
883 367
884 return value; 368 return value;
885 } 369 }
886 370
887 /* Read a system property string into a destination buffer of the specified 371
888 * size.
889 *
890 * Returns the passed buffer, or NULL if error. */
891 const char* VbGetSystemPropertyString(const char* name, char* dest, int size) { 372 const char* VbGetSystemPropertyString(const char* name, char* dest, int size) {
373 /* Check architecture-dependent properties first */
374 if (VbGetArchPropertyString(name, dest, size))
375 return dest;
892 376
893 if (!strcasecmp(name,"hwid")) { 377 if (!strcasecmp(name,"kernkey_vfy")) {
894 return ReadFileString(dest, size, ACPI_BASE_PATH "/HWID");
895 } else if (!strcasecmp(name,"fwid")) {
896 return ReadFileString(dest, size, ACPI_BASE_PATH "/FWID");
897 } else if (!strcasecmp(name,"ro_fwid")) {
898 return ReadFileString(dest, size, ACPI_BASE_PATH "/FRID");
899 } else if (!strcasecmp(name,"mainfw_act")) {
900 switch(ReadFileInt(ACPI_BINF_PATH ".1")) {
901 case 0:
902 return StrCopy(dest, "recovery", size);
903 case 1:
904 return StrCopy(dest, "A", size);
905 case 2:
906 return StrCopy(dest, "B", size);
907 default:
908 return NULL;
909 }
910 } else if (!strcasecmp(name,"mainfw_type")) {
911 return VbReadMainFwType(dest, size);
912 } else if (!strcasecmp(name,"ecfw_act")) {
913 switch(ReadFileInt(ACPI_BINF_PATH ".2")) {
914 case 0:
915 return StrCopy(dest, "RO", size);
916 case 1:
917 return StrCopy(dest, "RW", size);
918 default:
919 return NULL;
920 }
921 } else if (!strcasecmp(name,"kernkey_vfy")) {
922 switch(GetVdatInt(VDAT_INT_KERNEL_KEY_VERIFIED)) { 378 switch(GetVdatInt(VDAT_INT_KERNEL_KEY_VERIFIED)) {
923 case 0: 379 case 0:
924 return "hash"; 380 return "hash";
925 case 1: 381 case 1:
926 return "sig"; 382 return "sig";
927 default: 383 default:
928 return NULL; 384 return NULL;
929 } 385 }
930 } else if (!strcasecmp(name, "vdat_timers")) { 386 } else if (!strcasecmp(name, "vdat_timers")) {
931 return GetVdatString(dest, size, VDAT_STRING_TIMERS); 387 return GetVdatString(dest, size, VDAT_STRING_TIMERS);
932 } else if (!strcasecmp(name, "vdat_lfdebug")) { 388 } else if (!strcasecmp(name, "vdat_lfdebug")) {
933 return GetVdatString(dest, size, VDAT_STRING_LOAD_FIRMWARE_DEBUG); 389 return GetVdatString(dest, size, VDAT_STRING_LOAD_FIRMWARE_DEBUG);
934 } else if (!strcasecmp(name, "vdat_lkdebug")) { 390 } else if (!strcasecmp(name, "vdat_lkdebug")) {
935 return GetVdatString(dest, size, VDAT_STRING_LOAD_KERNEL_DEBUG); 391 return GetVdatString(dest, size, VDAT_STRING_LOAD_KERNEL_DEBUG);
936 } else 392 }
937 return NULL; 393
394 return NULL;
938 } 395 }
939 396
940 397
941 /* Set a system property integer.
942 *
943 * Returns 0 if success, -1 if error. */
944 int VbSetSystemPropertyInt(const char* name, int value) { 398 int VbSetSystemPropertyInt(const char* name, int value) {
399 /* Check architecture-dependent properties first */
400 if (0 == VbSetArchPropertyInt(name, value))
401 return 0;
945 402
946 /* NV storage values with no defaults for older BIOS. */ 403 /* NV storage values */
947 if (!strcasecmp(name,"nvram_cleared")) { 404 if (!strcasecmp(name,"nvram_cleared")) {
948 /* Can only clear this flag; it's set inside the NV storage library. */ 405 /* Can only clear this flag; it's set inside the NV storage library. */
949 return VbSetNvStorage(VBNV_KERNEL_SETTINGS_RESET, 0); 406 return VbSetNvStorage(VBNV_KERNEL_SETTINGS_RESET, 0);
950 } else if (!strcasecmp(name,"kern_nv")) { 407 } else if (!strcasecmp(name,"kern_nv")) {
951 return VbSetNvStorage(VBNV_KERNEL_FIELD, value); 408 return VbSetNvStorage(VBNV_KERNEL_FIELD, value);
952 } else if (!strcasecmp(name,"vbtest_errfunc")) { 409 } else if (!strcasecmp(name,"vbtest_errfunc")) {
953 return VbSetNvStorage(VBNV_TEST_ERROR_FUNC, value); 410 return VbSetNvStorage(VBNV_TEST_ERROR_FUNC, value);
954 } else if (!strcasecmp(name,"vbtest_errno")) { 411 } else if (!strcasecmp(name,"vbtest_errno")) {
955 return VbSetNvStorage(VBNV_TEST_ERROR_NUM, value); 412 return VbSetNvStorage(VBNV_TEST_ERROR_NUM, value);
956 } 413 } else if (!strcasecmp(name,"recovery_request")) {
957 /* NV storage values. If unable to get from NV storage, fall back to the 414 return VbSetNvStorage(VBNV_RECOVERY_REQUEST, value);
958 * CMOS reboot field used by older BIOS. */
959 else if (!strcasecmp(name,"recovery_request")) {
960 if (0 == VbSetNvStorage(VBNV_RECOVERY_REQUEST, value))
961 return 0;
962 return VbSetCmosRebootField(CMOSRF_RECOVERY, value);
963 } else if (!strcasecmp(name,"dbg_reset")) { 415 } else if (!strcasecmp(name,"dbg_reset")) {
964 if (0 == VbSetNvStorage(VBNV_DEBUG_RESET_MODE, value)) 416 return VbSetNvStorage(VBNV_DEBUG_RESET_MODE, value);
965 return 0;
966 return VbSetCmosRebootField(CMOSRF_DEBUG_RESET, value);
967 } else if (!strcasecmp(name,"fwb_tries")) { 417 } else if (!strcasecmp(name,"fwb_tries")) {
968 if (0 == VbSetNvStorage(VBNV_TRY_B_COUNT, value)) 418 return VbSetNvStorage(VBNV_TRY_B_COUNT, value);
969 return 0;
970 return VbSetCmosRebootField(CMOSRF_TRY_B, value);
971 } 419 }
972 420
973 return -1; 421 return -1;
974 } 422 }
975 423
976 424
977 /* Set a system property string.
978 *
979 * Returns 0 if success, -1 if error. */
980 int VbSetSystemPropertyString(const char* name, const char* value) { 425 int VbSetSystemPropertyString(const char* name, const char* value) {
981 426 /* Chain to architecture-dependent properties */
982 /* TODO: support setting */ 427 return VbSetArchPropertyString(name, value);
983 return -1;
984 } 428 }
OLDNEW
« no previous file with comments | « host/include/host_misc.h ('k') | host/lib/host_misc.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698