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