Home | History | Annotate | Download | only in updater
      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, &param_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, &param_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