1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 /* Vboot/crossystem interface */ 17 18 #define LOG_TAG "fwtool" 19 20 #include <endian.h> 21 #include <errno.h> 22 #include <stdint.h> 23 #include <stdlib.h> 24 #include <string.h> 25 #include <unistd.h> 26 27 #include "ec_commands.h" 28 #include "flash_device.h" 29 #include "fmap.h" 30 #include "update_log.h" 31 #include "vboot_struct.h" 32 #include "gbb_header.h" 33 34 /* ---- VBoot information passed by the firmware through the device-tree ---- */ 35 36 /* Base name for firmware FDT files */ 37 #define FDT_BASE_PATH "/proc/device-tree/firmware/chromeos" 38 39 char *fdt_read_string(const char *prop) 40 { 41 char filename[PATH_MAX]; 42 FILE *file; 43 size_t size; 44 char *data; 45 46 snprintf(filename, sizeof(filename), FDT_BASE_PATH "/%s", prop); 47 file = fopen(filename, "r"); 48 if (!file) { 49 ALOGD("Unable to open FDT property %s\n", prop); 50 return NULL; 51 } 52 fseek(file, 0, SEEK_END); 53 size = ftell(file); 54 data = malloc(size + 1); 55 if (!data) { 56 goto out_close; 57 } 58 data[size] = '\0'; 59 60 rewind(file); 61 if (fread(data, 1, size, file) != size) { 62 ALOGD("Unable to read FDT property %s\n", prop); 63 goto out_free; 64 } 65 fclose(file); 66 67 return data; 68 69 out_free: 70 free(data); 71 72 out_close: 73 fclose(file); 74 return NULL; 75 } 76 77 uint32_t fdt_read_u32(const char *prop) 78 { 79 char filename[PATH_MAX]; 80 FILE *file; 81 int data = 0; 82 83 snprintf(filename, sizeof(filename), FDT_BASE_PATH "/%s", prop); 84 file = fopen(filename, "r"); 85 if (!file) { 86 ALOGD("Unable to open FDT property %s\n", prop); 87 return -1U; 88 } 89 if (fread(&data, 1, sizeof(data), file) != sizeof(data)) { 90 ALOGD("Unable to read FDT property %s\n", prop); 91 fclose(file); 92 return -1U; 93 } 94 fclose(file); 95 96 return ntohl(data); /* FDT is network byte order */ 97 } 98 99 char vboot_get_mainfw_act(void) 100 { 101 VbSharedDataHeader *shd = (void *)fdt_read_string("vboot-shared-data"); 102 char v; 103 104 if (!shd || shd->magic != VB_SHARED_DATA_MAGIC) { 105 ALOGD("Cannot retrieve VBoot shared data\n"); 106 if (shd) 107 free(shd); 108 return 'E'; /* Error */ 109 } 110 111 switch(shd->firmware_index) { 112 case 0: 113 v = 'A'; /* RW_A in use */ 114 break; 115 case 1: 116 v = 'B'; /* RW_B in use */ 117 break; 118 case 0xFF: 119 v = 'R'; /* Recovery/RO in use */ 120 break; 121 default: 122 ALOGD("Invalid firmware index : %02x\n", shd->firmware_index); 123 v = 'E'; /* Error */ 124 } 125 126 free(shd); 127 return v; 128 } 129 130 /* ---- Flash Maps handling ---- */ 131 132 off_t fmap_scan_offset(struct flash_device *dev, off_t end) 133 { 134 struct fmap h; 135 uint32_t off = end - (end % 64); /* start on a 64-byte boundary */ 136 int res; 137 138 /* 139 * Try to find the FMAP signature at 64-byte boundaries 140 * starting from the end. 141 */ 142 do { 143 off -= 64; 144 res = flash_read(dev, off, &h, sizeof(h.signature)); 145 if (res) 146 break; 147 if (!memcmp(&h.signature, FMAP_SIGNATURE, sizeof(h.signature))) 148 break; 149 } while (off); 150 151 return off; 152 } 153 154 struct fmap *fmap_load(struct flash_device *dev, off_t offset) 155 { 156 struct fmap hdr; 157 struct fmap *fmap; 158 size_t size; 159 int res; 160 161 ALOGD("Searching FMAP @0x%08lx\n", offset); 162 res = flash_read(dev, offset, &hdr, sizeof(hdr)); 163 if (res) { 164 ALOGD("Cannot read FMAP header\n"); 165 return NULL; 166 } 167 168 if (memcmp(&hdr.signature, FMAP_SIGNATURE, sizeof(hdr.signature))) { 169 ALOGD("Cannot find FMAP\n"); 170 return NULL; 171 } 172 173 size = sizeof(struct fmap) + hdr.nareas * sizeof(struct fmap_area); 174 fmap = malloc(size); 175 176 res = flash_read(dev, offset, fmap, size); 177 if (res) { 178 ALOGD("Cannot read FMAP\n"); 179 free(fmap); 180 return NULL; 181 } 182 183 return fmap; 184 } 185 186 int fmap_get_section_offset(struct flash_device *dev, const char *name, 187 off_t *offset) 188 { 189 int i; 190 struct fmap *fmap = flash_get_fmap(dev); 191 if (!fmap) 192 return -1; 193 194 if (name) { 195 for (i = 0; i < fmap->nareas; i++) 196 if (!strcmp(name, (const char*)fmap->areas[i].name)) 197 break; 198 199 if (i == fmap->nareas) { 200 ALOGD("Cannot find section '%s'\n", name); 201 return -1; 202 } 203 204 *offset = fmap->areas[i].offset; 205 } else { 206 *offset = 0; 207 } 208 209 return 0; 210 } 211 212 void *fmap_read_section(struct flash_device *dev, 213 const char *name, size_t *size, off_t *offset) 214 { 215 int i, r; 216 struct fmap *fmap = flash_get_fmap(dev); 217 void *data; 218 off_t start_offset; 219 220 if (!fmap) 221 return NULL; 222 223 if (name) { 224 for (i = 0; i < fmap->nareas; i++) 225 if (!strcmp(name, (const char*)fmap->areas[i].name)) 226 break; 227 if (i == fmap->nareas) { 228 ALOGD("Cannot find section '%s'\n", name); 229 return NULL; 230 } 231 *size = fmap->areas[i].size; 232 start_offset = fmap->areas[i].offset; 233 } else { 234 *size = flash_get_size(dev); 235 start_offset = 0; 236 } 237 238 data = malloc(*size); 239 if (!data) 240 return NULL; 241 242 r = flash_read(dev, start_offset, data, *size); 243 if (r) { 244 ALOGD("Cannot read section '%s'\n", name); 245 free(data); 246 return NULL; 247 } 248 if (offset) 249 *offset = start_offset; 250 251 return data; 252 } 253 254 /* ---- Google Binary Block (GBB) ---- */ 255 256 uint8_t *gbb_get_rootkey(struct flash_device *dev, size_t *size) 257 { 258 size_t gbb_size; 259 uint8_t *gbb = flash_get_gbb(dev, &gbb_size); 260 GoogleBinaryBlockHeader *hdr = (void *)gbb; 261 262 if (!gbb || memcmp(hdr->signature, GBB_SIGNATURE, GBB_SIGNATURE_SIZE) || 263 gbb_size < sizeof(*hdr)) 264 return NULL; 265 266 if (hdr->rootkey_offset + hdr->rootkey_size > gbb_size) 267 return NULL; 268 269 if (size) 270 *size = hdr->rootkey_size; 271 272 return gbb + hdr->rootkey_offset; 273 } 274 275 /* ---- VBoot NVRAM (stored in SPI flash) ---- */ 276 277 /* bits definition in NVRAM */ 278 279 enum { 280 VB_HEADER_OFFSET = 0, 281 VB_BOOT_OFFSET = 1, 282 VB_RECOVERY_OFFSET = 2, 283 VB_LOCALIZATION_OFFSET = 3, 284 VB_DEV_OFFSET = 4, 285 VB_TPM_OFFSET = 5, 286 VB_RECVOERY_SUBCODE_OFFSET = 6, 287 VB_BOOT2_OFFSET = 7, 288 VB_MISC_OFFSET = 8, 289 VB_KERNEL_OFFSET = 11, 290 VB_CRC_OFFSET = 15, 291 VB_NVDATA_SIZE = 16 292 }; 293 294 #define VB_DEFAULT_MASK 0x01 295 296 /* HEADER_OFFSET */ 297 #define VB_HEADER_WIPEOUT_SHIFT 3 298 #define VB_HEADER_KERNEL_SETTINGS_RESET_SHIFT 4 299 #define VB_HEADER_FW_SETTINGS_RESET_SHIFT 5 300 #define VB_HEADER_SIGNATURE_SHIFT 6 301 302 /* BOOT_OFFSET */ 303 #define VB_BOOT_TRY_COUNT_MASK 0xf 304 #define VB_BOOT_TRY_COUNT_SHIFT 0 305 #define VB_BOOT_BACKUP_NVRAM_SHIFT 4 306 #define VB_BOOT_OPROM_NEEDED_SHIFT 5 307 #define VB_BOOT_DISABLE_DEV_SHIFT 6 308 #define VB_BOOT_DEBUG_RESET_SHIFT 7 309 310 /* RECOVERY_OFFSET */ 311 #define VB_RECOVERY_REASON_SHIFT 0 312 #define VB_RECOVERY_REASON_MASK 0xff 313 314 /* BOOT2_OFFSET */ 315 #define VB_BOOT2_RESULT_MASK 0x3 316 #define VB_BOOT2_RESULT_SHIFT 0 317 #define VB_BOOT2_TRIED_SHIFT 2 318 #define VB_BOOT2_TRY_NEXT_SHIFT 3 319 #define VB_BOOT2_PREV_RESULT_MASK 0x3 320 #define VB_BOOT2_PREV_RESULT_SHIFT 4 321 #define VB_BOOT2_PREV_TRIED_SHIFT 6 322 323 /* DEV_OFFSET */ 324 #define VB_DEV_FLAG_USB_SHIFT 0 325 #define VB_DEV_FLAG_SIGNED_ONLY_SHIFT 1 326 #define VB_DEV_FLAG_LEGACY_SHIFT 2 327 #define VB_DEV_FLAG_FASTBOOT_FULL_CAP_SHIFT 3 328 329 /* TPM_OFFSET */ 330 #define VB_TPM_CLEAR_OWNER_REQUEST_SHIFT 0 331 #define VB_TPM_CLEAR_OWNER_DONE_SHIFT 1 332 333 /* MISC_OFFSET */ 334 #define VB_MISC_UNLOCK_FASTBOOT_SHIFT 0 335 #define VB_MISC_BOOT_ON_AC_DETECT_SHIFT 1 336 337 typedef enum { 338 VBNV_DEFAULT_FLAG = 0x00, 339 VBNV_WRITABLE = 0x01, 340 } vbnv_param_flags_t; 341 342 typedef struct vbnv_param { 343 char *name; 344 vbnv_param_flags_t flags; 345 int offset; 346 int shift; 347 int mask; 348 } vbnv_param_t; 349 350 static const vbnv_param_t param_table[] = { 351 {"try_count", VBNV_WRITABLE, VB_BOOT_OFFSET, VB_BOOT_TRY_COUNT_SHIFT, 352 VB_BOOT_TRY_COUNT_MASK}, 353 {"backup_nvram", VBNV_WRITABLE, VB_BOOT_OFFSET, 354 VB_BOOT_BACKUP_NVRAM_SHIFT, VB_DEFAULT_MASK}, 355 {"oprom_needed", VBNV_WRITABLE, VB_BOOT_OFFSET, 356 VB_BOOT_OPROM_NEEDED_SHIFT, VB_DEFAULT_MASK}, 357 {"disable_dev", VBNV_WRITABLE, VB_BOOT_OFFSET, 358 VB_BOOT_DISABLE_DEV_SHIFT, VB_DEFAULT_MASK}, 359 {"debug_reset", VBNV_WRITABLE, VB_BOOT_OFFSET, 360 VB_BOOT_DEBUG_RESET_SHIFT, VB_DEFAULT_MASK}, 361 {"boot_result", VBNV_WRITABLE, VB_BOOT2_OFFSET, VB_BOOT2_RESULT_SHIFT, 362 VB_BOOT2_RESULT_MASK}, 363 {"fw_tried", VBNV_DEFAULT_FLAG, VB_BOOT2_OFFSET, VB_BOOT2_TRIED_SHIFT, 364 VB_DEFAULT_MASK}, 365 {"fw_try_next", VBNV_WRITABLE, VB_BOOT2_OFFSET, VB_BOOT2_TRY_NEXT_SHIFT, 366 VB_DEFAULT_MASK}, 367 {"fw_prev_result", VBNV_DEFAULT_FLAG, VB_BOOT2_OFFSET, 368 VB_BOOT2_PREV_RESULT_SHIFT, VB_BOOT2_PREV_RESULT_MASK}, 369 {"prev_tried", VBNV_DEFAULT_FLAG, VB_BOOT2_OFFSET, 370 VB_BOOT2_PREV_TRIED_SHIFT, VB_DEFAULT_MASK}, 371 {"dev_boot_usb", VBNV_WRITABLE, VB_DEV_OFFSET, VB_DEV_FLAG_USB_SHIFT, 372 VB_DEFAULT_MASK}, 373 {"dev_boot_signed_only", VBNV_WRITABLE, VB_DEV_OFFSET, 374 VB_DEV_FLAG_SIGNED_ONLY_SHIFT, VB_DEFAULT_MASK}, 375 {"dev_boot_legacy", VBNV_WRITABLE, VB_DEV_OFFSET, 376 VB_DEV_FLAG_LEGACY_SHIFT, VB_DEFAULT_MASK}, 377 {"dev_boot_fastboot_full_cap", VBNV_WRITABLE, VB_DEV_OFFSET, 378 VB_DEV_FLAG_FASTBOOT_FULL_CAP_SHIFT, VB_DEFAULT_MASK}, 379 {"tpm_clear_owner_request", VBNV_WRITABLE, VB_TPM_OFFSET, 380 VB_TPM_CLEAR_OWNER_REQUEST_SHIFT, VB_DEFAULT_MASK}, 381 {"tpm_clear_owner_done", VBNV_WRITABLE, VB_TPM_OFFSET, 382 VB_TPM_CLEAR_OWNER_DONE_SHIFT, VB_DEFAULT_MASK}, 383 {"unlock_fastboot", VBNV_WRITABLE, VB_MISC_OFFSET, 384 VB_MISC_UNLOCK_FASTBOOT_SHIFT, VB_DEFAULT_MASK}, 385 {"boot_on_ac_detect", VBNV_WRITABLE, VB_MISC_OFFSET, 386 VB_MISC_BOOT_ON_AC_DETECT_SHIFT, VB_DEFAULT_MASK}, 387 {"recovery_reason", VBNV_WRITABLE, VB_RECOVERY_OFFSET, 388 VB_RECOVERY_REASON_SHIFT, VB_RECOVERY_REASON_MASK}, 389 }; 390 391 static uint8_t crc8(const uint8_t *data, int len) 392 { 393 uint32_t crc = 0; 394 int i, j; 395 396 for (j = len; j; j--, data++) { 397 crc ^= (*data << 8); 398 for(i = 8; i; i--) { 399 if (crc & 0x8000) 400 crc ^= (0x1070 << 3); 401 crc <<= 1; 402 } 403 } 404 405 return (uint8_t)(crc >> 8); 406 } 407 408 static inline int can_overwrite(uint8_t current, uint8_t new) 409 { 410 return (current & new) == new; 411 } 412 413 int vbnv_readwrite(struct flash_device *spi, const vbnv_param_t *param, 414 uint8_t *value, int write) 415 { 416 int i; 417 int res; 418 size_t size; 419 off_t offset; 420 uint8_t *block, *nvram, *end, *curr; 421 uint8_t dummy[VB_NVDATA_SIZE]; 422 423 int off = param->offset; 424 uint8_t mask = param->mask << param->shift; 425 426 if (off >= VB_NVDATA_SIZE) { 427 ALOGW("ERROR: Incorrect offset %d for NvStorage\n", off); 428 return -EIO; 429 } 430 431 /* Read NVRAM. */ 432 nvram = fmap_read_section(spi, "RW_NVRAM", &size, &offset); 433 /* 434 * Ensure NVRAM is found, size is at least 1 block and total size is 435 * multiple of VB_NVDATA_SIZE. 436 */ 437 if ((nvram == NULL) || (size < VB_NVDATA_SIZE) || 438 (size % VB_NVDATA_SIZE)) { 439 ALOGW("ERROR: NVRAM not found\n"); 440 return -EIO; 441 } 442 443 /* Create an empty dummy block to compare. */ 444 memset(dummy, 0xFF, sizeof(dummy)); 445 446 /* 447 * Loop until the last used block in NVRAM. 448 * 1. All blocks will not be empty since we just booted up fine. 449 * 2. If all blocks are used, select the last block. 450 */ 451 block = nvram; 452 end = block + size; 453 for (curr = block; curr < end; curr += VB_NVDATA_SIZE) { 454 if (memcmp(curr, dummy, VB_NVDATA_SIZE) == 0) 455 break; 456 block = curr; 457 } 458 459 if (write) { 460 uint8_t flag_value = (*value & param->mask) << param->shift; 461 462 /* Copy last used block to make modifications. */ 463 memcpy(dummy, block, VB_NVDATA_SIZE); 464 465 dummy[off] = (dummy[off] & ~mask) | (flag_value & mask); 466 dummy[VB_CRC_OFFSET] = crc8(dummy, VB_CRC_OFFSET); 467 468 /* Check if new block can be overwritten */ 469 for (i = 0; i < VB_NVDATA_SIZE; i++) { 470 if (!can_overwrite(block[i], dummy[i])) { 471 if (curr != end) 472 offset += (curr - nvram); 473 else if (flash_erase(spi, offset, size)) { 474 ALOGW("ERROR: Cannot erase flash\n"); 475 return -EIO; 476 } 477 break; 478 } 479 } 480 481 /* Block can be overwritten. */ 482 if (i == VB_NVDATA_SIZE) 483 offset += (block - nvram); 484 485 ALOGI("Writing new entry into NVRAM @ 0x%lx\n", offset); 486 487 /* Write new entry into NVRAM. */ 488 if (flash_write(spi, offset, dummy, VB_NVDATA_SIZE)) { 489 ALOGW("ERROR: Cannot update NVRAM\n"); 490 return -EIO; 491 } 492 493 ALOGD("NVRAM updated.\n"); 494 } else { 495 *value = (block[off] & mask) >> param->shift; 496 } 497 498 return 0; 499 } 500 501 #define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0])) 502 int vbnv_set_flag(struct flash_device *spi, const char *param, uint8_t value) 503 { 504 size_t i; 505 for (i = 0; i < ARRAY_SIZE(param_table); i++) { 506 if (!strcmp(param, param_table[i].name)) { 507 if (param_table[i].flags & VBNV_WRITABLE) 508 return vbnv_readwrite(spi, ¶m_table[i], 509 &value, 1); 510 511 fprintf(stderr, "ERROR: Cannot write this flag.\n"); 512 return -EIO; 513 } 514 } 515 fprintf(stderr, "Error: Unknown param\n"); 516 return -EIO; 517 } 518 519 int vbnv_get_flag(struct flash_device *spi, const char *param, uint8_t *value) 520 { 521 size_t i; 522 for (i = 0; i < ARRAY_SIZE(param_table); i++) { 523 if (!strcmp(param, param_table[i].name)) 524 return vbnv_readwrite(spi, ¶m_table[i], value, 0); 525 } 526 fprintf(stderr, "Error: Unknown param\n"); 527 return -EIO; 528 } 529 530 void vbnv_usage(int write) 531 { 532 size_t i; 533 for (i = 0; i < ARRAY_SIZE(param_table); i++) 534 if ((write == 0) || (write && 535 (param_table[i].flags & VBNV_WRITABLE))) 536 printf(" %s\n", param_table[i].name); 537 } 538 539 /* ---- Vital Product Data handling ---- */ 540