| OLD | NEW |
| 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 Loading... |
| 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 } |
| OLD | NEW |