vboot: ec_sync: Switch to new CBFS API

This patch changes the vboot EC sync code to use the new CBFS API. As a
consequence, we have to map the whole EC image file at once (because the
new API doesn't support partial mapping). This should be fine on the
only platform that uses this code (Google_Volteer/_Dedede family)
because they are x86 devices that support direct mapping from flash, but
the code was originally written to more carefully map the file in
smaller steps to be theoretically able to support Arm devices.

EC sync in romstage for devices without memory-mapped flash would be
hard to combine with CBFS verification because there's not enough SRAM
to ever hold the whole file in memory at once, but we can't validate the
file hash until we have loaded the whole file and for performance (or
TOCTOU-safety, if applicable) reasons we wouldn't want to load anything
more than once. The "good" solution for this would be to introduce a
CBFS streaming API can slowly feed chunks of the file into a callback
but in the end still return a "hash valid/invalid" result to the caller.
If use cases like this become pressing in the future, we may have to
implement such an API.

However, for now this code is the only part of coreboot with constraints
like that, it was only ever used on platforms that do support
memory-mapped flash, and due to the new EC-EFS2 model used on more
recent Chrome OS devices we don't currently anticipate this to ever be
needed again. Therefore this patch goes the easier way of just papering
over the problem and punting the work of implementing a more generic
solution until we actually have a real need for it.

Signed-off-by: Julius Werner <jwerner@chromium.org>
Change-Id: I7e263272aef3463f3b2924887d96de9b2607f5e5
Reviewed-on: https://review.coreboot.org/c/coreboot/+/52280
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Julius Werner 2021-04-12 16:28:37 -07:00
parent c074f61d8f
commit b3182fbb00
1 changed files with 21 additions and 27 deletions

View File

@ -240,11 +240,10 @@ static enum ec_flash_region vboot_to_ec_region(enum vb2_firmware_selection selec
} }
/* /*
* Read the EC's burst size bytes at a time from CBFS, and then send * Send an image to the EC in burst-sized chunks.
* the chunk to the EC for it to write into its flash.
*/ */
static vb2_error_t ec_flash_write(struct region_device *image_region, static vb2_error_t ec_flash_write(void *image, uint32_t region_offset,
uint32_t region_offset, int image_size) int image_size)
{ {
struct ec_response_get_protocol_info resp_proto; struct ec_response_get_protocol_info resp_proto;
struct ec_response_flash_info resp_flash; struct ec_response_flash_info resp_flash;
@ -295,24 +294,17 @@ static vb2_error_t ec_flash_write(struct region_device *image_region,
/* Fill up the buffer */ /* Fill up the buffer */
end = region_offset + image_size; end = region_offset + image_size;
file_buf = image;
for (off = region_offset; off < end; off += burst) { for (off = region_offset; off < end; off += burst) {
uint32_t todo = MIN(end - off, burst); uint32_t todo = MIN(end - off, burst);
uint32_t xfer_size = todo + sizeof(*params); uint32_t xfer_size = todo + sizeof(*params);
/* Map 'todo' bytes into memory */
file_buf = rdev_mmap(image_region, off - region_offset, todo);
if (file_buf == NULL)
return VB2_ERROR_UNKNOWN;
params->offset = off; params->offset = off;
params->size = todo; params->size = todo;
/* Read todo bytes into the buffer */ /* Read todo bytes into the buffer */
memcpy(params + 1, file_buf, todo); memcpy(params + 1, file_buf, todo);
if (rdev_munmap(image_region, file_buf))
return VB2_ERROR_UNKNOWN;
/* Make sure to add back in the size of the parameters */ /* Make sure to add back in the size of the parameters */
if (google_chromeec_flash_write_block( if (google_chromeec_flash_write_block(
(const uint8_t *)params, xfer_size)) { (const uint8_t *)params, xfer_size)) {
@ -320,6 +312,8 @@ static vb2_error_t ec_flash_write(struct region_device *image_region,
"relative offset %u!\n", off - region_offset); "relative offset %u!\n", off - region_offset);
return VB2_ERROR_UNKNOWN; return VB2_ERROR_UNKNOWN;
} }
file_buf += todo;
} }
return VB2_SUCCESS; return VB2_SUCCESS;
@ -333,10 +327,8 @@ static vb2_error_t ec_update_image(enum vb2_firmware_selection select)
uint32_t region_offset, region_size; uint32_t region_offset, region_size;
enum ec_flash_region region; enum ec_flash_region region;
vb2_error_t rv; vb2_error_t rv;
void *image;
size_t image_size; size_t image_size;
struct cbfsf fh;
const char *filename;
struct region_device image_region;
/* Un-protect the flash region */ /* Un-protect the flash region */
rv = ec_protect_flash(select, 0); rv = ec_protect_flash(select, 0);
@ -351,32 +343,34 @@ static vb2_error_t ec_update_image(enum vb2_firmware_selection select)
&region_size)) &region_size))
return VB2_ERROR_UNKNOWN; return VB2_ERROR_UNKNOWN;
/* Locate the CBFS file */ /* Map the CBFS file */
filename = EC_IMAGE_FILENAME(select); image = cbfs_map(EC_IMAGE_FILENAME(select), &image_size);
if (cbfs_boot_locate(&fh, filename, NULL)) if (!image)
return VB2_ERROR_UNKNOWN; return VB2_ERROR_UNKNOWN;
/* Get the file size and the region struct */ rv = VB2_ERROR_UNKNOWN;
image_size = region_device_sz(&fh.data);
cbfs_file_data(&image_region, &fh);
/* Bail if the image is too large */ /* Bail if the image is too large */
if (image_size > region_size) if (image_size > region_size)
return VB2_ERROR_INVALID_PARAMETER; goto unmap;
/* Erase the region */ /* Erase the region */
if (google_chromeec_flash_erase(region_offset, region_size)) if (google_chromeec_flash_erase(region_offset, region_size))
return VB2_ERROR_UNKNOWN; goto unmap;
/* Write the image into the region */ /* Write the image into the region */
if (ec_flash_write(&image_region, region_offset, image_size)) if (ec_flash_write(image, region_offset, image_size))
return VB2_ERROR_UNKNOWN; goto unmap;
/* Verify the image */ /* Verify the image */
if (google_chromeec_efs_verify(region)) if (google_chromeec_efs_verify(region))
return VB2_ERROR_UNKNOWN; goto unmap;
return VB2_SUCCESS; rv = VB2_SUCCESS;
unmap:
cbfs_unmap(image);
return rv;
} }
static vb2_error_t ec_get_expected_hash(enum vb2_firmware_selection select, static vb2_error_t ec_get_expected_hash(enum vb2_firmware_selection select,