Beispiel #1
0
/* returns the size of data in a VPD 2.0 formatted fmap region, or 0 */
static int32_t get_vpd_size(const char *fmap_name, int32_t *base)
{
	struct google_vpd_info info;
	struct region_device vpd;
	int32_t size;

	if (fmap_locate_area_as_rdev(fmap_name, &vpd)) {
		printk(BIOS_ERR, "%s: No %s FMAP section.\n", __func__,
			fmap_name);
		return 0;
	}

	size = region_device_sz(&vpd);

	if ((size < GOOGLE_VPD_2_0_OFFSET + sizeof(info)) ||
	    rdev_chain(&vpd, &vpd, GOOGLE_VPD_2_0_OFFSET,
			size - GOOGLE_VPD_2_0_OFFSET)) {
		printk(BIOS_ERR, "%s: Too small (%d) for Google VPD 2.0.\n",
		       __func__, size);
		return 0;
	}

	/* Try if we can find a google_vpd_info, otherwise read whole VPD. */
	if (rdev_readat(&vpd, &info, *base, sizeof(info)) == sizeof(info) &&
	    memcmp(info.header.magic, VPD_INFO_MAGIC, sizeof(info.header.magic))
	    == 0 && size >= info.size + sizeof(info)) {
		*base += sizeof(info);
		size = info.size;
	} else {
		size -= GOOGLE_VPD_2_0_OFFSET;
	}

	return size;
}
Beispiel #2
0
void fsps_load(bool s3wake)
{
	struct fsp_header *hdr = &fsps_hdr;
	struct cbfsf file_desc;
	struct region_device rdev;
	const char *name = CONFIG_FSP_S_CBFS;
	void *dest;
	size_t size;
	struct prog fsps = PROG_INIT(PROG_REFCODE, name);
	static int load_done;

	if (load_done)
		return;

	if (s3wake && !IS_ENABLED(CONFIG_NO_STAGE_CACHE)) {
		printk(BIOS_DEBUG, "Loading FSPS from stage_cache\n");
		stage_cache_load_stage(STAGE_REFCODE, &fsps);
		if (fsp_validate_component(hdr, prog_rdev(&fsps)) != CB_SUCCESS)
			die("On resume fsps header is invalid\n");
		load_done = 1;
		return;
	}

	if (cbfs_boot_locate(&file_desc, name, NULL)) {
		printk(BIOS_ERR, "Could not locate %s in CBFS\n", name);
		die("FSPS not available!\n");
	}

	cbfs_file_data(&rdev, &file_desc);

	/* Load and relocate into CBMEM. */
	size = region_device_sz(&rdev);
	dest = cbmem_add(CBMEM_ID_REFCODE, size);

	if (dest == NULL)
		die("Could not add FSPS to CBMEM!\n");

	if (rdev_readat(&rdev, dest, 0, size) < 0)
		die("Failed to read FSPS!\n");

	if (fsp_component_relocate((uintptr_t)dest, dest, size) < 0)
		die("Unable to relocate FSPS!\n");

	/* Create new region device in memory after relocation. */
	rdev_chain(&rdev, &addrspace_32bit.rdev, (uintptr_t)dest, size);

	if (fsp_validate_component(hdr, &rdev) != CB_SUCCESS)
		die("Invalid FSPS header!\n");

	prog_set_area(&fsps, dest, size);

	stage_cache_add(STAGE_REFCODE, &fsps);

	/* Signal that FSP component has been loaded. */
	prog_segment_loaded(hdr->image_base, hdr->image_size, SEG_FINAL);
	load_done = 1;
}
Beispiel #3
0
/* returns the size of data in a VPD 2.0 formatted fmap region, or 0 */
static int32_t get_vpd_size(const char *fmap_name, int32_t *base)
{
	struct google_vpd_info info;
	struct region_device vpd;
	int32_t size;

	if (fmap_locate_area_as_rdev(fmap_name, &vpd)) {
		printk(BIOS_ERR, "%s: No %s FMAP section.\n", __func__,
			fmap_name);
		return 0;
	}

	size = region_device_sz(&vpd);

	if ((size < GOOGLE_VPD_2_0_OFFSET + sizeof(info)) ||
	    rdev_chain(&vpd, &vpd, GOOGLE_VPD_2_0_OFFSET,
			size - GOOGLE_VPD_2_0_OFFSET)) {
		printk(BIOS_ERR, "%s: Too small (%d) for Google VPD 2.0.\n",
		       __func__, size);
		return 0;
	}

	/* Try if we can find a google_vpd_info, otherwise read whole VPD. */
	if (rdev_readat(&vpd, &info, *base, sizeof(info)) != sizeof(info)) {
		printk(BIOS_ERR, "ERROR: Failed to read %s header.\n",
		       fmap_name);
		return 0;
	}

	if (memcmp(info.header.magic, VPD_INFO_MAGIC, sizeof(info.header.magic))
	    == 0 && size >= info.size + sizeof(info)) {
		*base += sizeof(info);
		size = info.size;
	} else if (info.header.tlv.type == VPD_TYPE_TERMINATOR ||
		   info.header.tlv.type == VPD_TYPE_IMPLICIT_TERMINATOR) {
		printk(BIOS_WARNING, "WARNING: %s is uninitialized or empty.\n",
		       fmap_name);
		size = 0;
	} else {
		size -= GOOGLE_VPD_2_0_OFFSET;
	}

	return size;
}
Beispiel #4
0
enum fsp_status fsp_silicon_init(void)
{
	struct fsp_header *hdr = &fsps_hdr;
	struct cbfsf file_desc;
	struct region_device rdev;
	const char *name = CONFIG_FSP_S_CBFS;
	void *dest;
	size_t size;

	if (cbfs_boot_locate(&file_desc, name, NULL)) {
		printk(BIOS_ERR, "Could not locate %s in CBFS\n", name);
		return FSP_NOT_FOUND;
	}

	cbfs_file_data(&rdev, &file_desc);

	/* Load and relocate into CBMEM. */
	size = region_device_sz(&rdev);
	dest = cbmem_add(CBMEM_ID_REFCODE, size);

	if (dest == NULL) {
		printk(BIOS_ERR, "Could not add FSPS to CBMEM.\n");
		return FSP_NOT_FOUND;
	}

	if (rdev_readat(&rdev, dest, 0, size) < 0)
		return FSP_NOT_FOUND;

	if (fsp_component_relocate((uintptr_t)dest, dest, size) < 0) {
		printk(BIOS_ERR, "Unable to relocate FSPS.\n");
		return FSP_NOT_FOUND;
	}

	/* Create new region device in memory after relocation. */
	rdev_chain(&rdev, &addrspace_32bit.rdev, (uintptr_t)dest, size);

	if (fsp_validate_component(hdr, &rdev) != CB_SUCCESS)
		return FSP_NOT_FOUND;

	/* Signal that FSP component has been loaded. */
	prog_segment_loaded(hdr->image_base, hdr->image_size, SEG_FINAL);

	return do_silicon_init(hdr);
}
Beispiel #5
0
int cbfs_boot_locate(struct cbfsf *fh, const char *name, uint32_t *type)
{
	struct region_device rdev;
	const struct region_device *boot_dev;
	struct cbfs_props props;

	if (cbfs_boot_region_properties(&props))
		return -1;

	/* All boot CBFS operations are performed using the RO devie. */
	boot_dev = boot_device_ro();

	if (boot_dev == NULL)
		return -1;

	if (rdev_chain(&rdev, boot_dev, props.offset, props.size))
		return -1;

	return cbfs_locate(fh, &rdev, name, type);
}
Beispiel #6
0
static void cbmem_add_cros_vpd(int is_recovery)
{
	struct region_device vpd;
	struct vpd_cbmem *cbmem;
	int32_t ro_vpd_base = 0, rw_vpd_base = 0;
	int32_t ro_vpd_size, rw_vpd_size;

	timestamp_add_now(TS_START_COPYVPD);

	ro_vpd_size = get_vpd_size("RO_VPD", &ro_vpd_base);
	rw_vpd_size = get_vpd_size("RW_VPD", &rw_vpd_base);

	/* no VPD at all? nothing to do then */
	if ((ro_vpd_size == 0) && (rw_vpd_size == 0))
		return;

	cbmem = cbmem_add(CBMEM_ID_VPD, sizeof(*cbmem) + ro_vpd_size +
		rw_vpd_size);
	if (!cbmem) {
		printk(BIOS_ERR, "%s: Failed to allocate CBMEM (%u+%u).\n",
			__func__, ro_vpd_size, rw_vpd_size);
		return;
	}

	cbmem->magic = CROSVPD_CBMEM_MAGIC;
	cbmem->version = CROSVPD_CBMEM_VERSION;
	cbmem->ro_size = 0;
	cbmem->rw_size = 0;

	if (ro_vpd_size) {
		if (fmap_locate_area_as_rdev("RO_VPD", &vpd)) {
			/* shouldn't happen, but let's be extra defensive */
			printk(BIOS_ERR, "%s: No RO_VPD FMAP section.\n",
				__func__);
			return;
		}
		rdev_chain(&vpd, &vpd, GOOGLE_VPD_2_0_OFFSET,
			region_device_sz(&vpd) - GOOGLE_VPD_2_0_OFFSET);


		if (rdev_readat(&vpd, cbmem->blob, ro_vpd_base, ro_vpd_size) ==
			ro_vpd_size) {
			cbmem->ro_size = ro_vpd_size;
		} else {
			printk(BIOS_ERR,
				"%s: Reading RO_VPD FMAP section failed.\n",
				__func__);
			ro_vpd_size = 0;
		}
		timestamp_add_now(TS_END_COPYVPD_RO);
	}

	if (rw_vpd_size) {
		if (fmap_locate_area_as_rdev("RW_VPD", &vpd)) {
			/* shouldn't happen, but let's be extra defensive */
			printk(BIOS_ERR, "%s: No RW_VPD FMAP section.\n",
				__func__);
			return;
		}
		rdev_chain(&vpd, &vpd, GOOGLE_VPD_2_0_OFFSET,
			region_device_sz(&vpd) - GOOGLE_VPD_2_0_OFFSET);

		if (rdev_readat(&vpd, cbmem->blob + ro_vpd_size, rw_vpd_base,
			rw_vpd_size) == rw_vpd_size) {
			cbmem->rw_size = rw_vpd_size;
		} else {
			printk(BIOS_ERR,
				"%s: Reading RW_VPD FMAP section failed.\n",
				__func__);
		}
		timestamp_add_now(TS_END_COPYVPD_RW);
	}
}
Beispiel #7
0
static int hash_body(struct vb2_context *ctx, struct region_device *fw_main)
{
	uint64_t load_ts;
	uint32_t expected_size;
	uint8_t block[TODO_BLOCK_SIZE];
	uint8_t hash_digest[VBOOT_MAX_HASH_SIZE];
	const size_t hash_digest_sz = sizeof(hash_digest);
	size_t block_size = sizeof(block);
	size_t offset;
	int rv;

	/* Clear the full digest so that any hash digests less than the
	 * max have trailing zeros. */
	memset(hash_digest, 0, hash_digest_sz);

	/*
	 * Since loading the firmware and calculating its hash is intertwined,
	 * we use this little trick to measure them separately and pretend it
	 * was first loaded and then hashed in one piece with the timestamps.
	 * (This split won't make sense with memory-mapped media like on x86.)
	 */
	load_ts = timestamp_get();
	timestamp_add(TS_START_HASH_BODY, load_ts);

	expected_size = region_device_sz(fw_main);
	offset = 0;

	/* Start the body hash */
	rv = vb2api_init_hash(ctx, VB2_HASH_TAG_FW_BODY, &expected_size);
	if (rv)
		return rv;

	/*
	 * Honor vboot's RW slot size. The expected size is pulled out of
	 * the preamble and obtained through vb2api_init_hash() above. By
	 * creating sub region the RW slot portion of the boot media is
	 * limited.
	 */
	if (rdev_chain(fw_main, fw_main, 0, expected_size)) {
		printk(BIOS_ERR, "Unable to restrict CBFS size.\n");
		return VB2_ERROR_UNKNOWN;
	}

	/* Extend over the body */
	while (expected_size) {
		uint64_t temp_ts;
		if (block_size > expected_size)
			block_size = expected_size;

		temp_ts = timestamp_get();
		if (rdev_readat(fw_main, block, offset, block_size) < 0)
			return VB2_ERROR_UNKNOWN;
		load_ts += timestamp_get() - temp_ts;

		rv = vb2api_extend_hash(ctx, block, block_size);
		if (rv)
			return rv;

		expected_size -= block_size;
		offset += block_size;
	}

	timestamp_add(TS_DONE_LOADING, load_ts);
	timestamp_add_now(TS_DONE_HASHING);

	/* Check the result (with RSA signature verification) */
	rv = vb2api_check_hash_get_digest(ctx, hash_digest, hash_digest_sz);
	if (rv)
		return rv;

	timestamp_add_now(TS_END_HASH_BODY);

	if (handle_digest_result(hash_digest, hash_digest_sz))
		return VB2_ERROR_UNKNOWN;

	return VB2_SUCCESS;
}