diff options
author | Aaron Durbin <adurbin@chromium.org> | 2016-08-12 12:48:58 -0500 |
---|---|---|
committer | Martin Roth <martinroth@google.com> | 2016-08-19 18:18:57 +0200 |
commit | b18a6665df2633193b7863e3dd9eca230536405b (patch) | |
tree | 12e13454875b1e8b1d6086850a684d55f9d8f61e | |
parent | 5bb9e93ea68db0ffe156f2df2d69397f21c57095 (diff) | |
download | coreboot-b18a6665df2633193b7863e3dd9eca230536405b.tar.xz |
vboot/vbnv_flash: make I/O connection agnostic
There's no need to be SPI specific w.r.t. how the flash is
connected. Therefore, use the RW boot device to write the
contents of VBNV. The erasable check was dropped because that
information isn't available. All regions should be aligned
accordingly on the platform for the underlying hardware
implementation. And once the VBNV region fills the erase
will fail.
BUG=chrome-os-partner:56151
Change-Id: I07fdc8613e0b3884e132a2f158ffeabeaa6da6ce
Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: https://review.coreboot.org/16206
Tested-by: build bot (Jenkins)
Reviewed-by: Duncan Laurie <dlaurie@chromium.org>
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Reviewed-by: Furquan Shaikh <furquan@google.com>
-rw-r--r-- | src/vboot/Kconfig | 3 | ||||
-rw-r--r-- | src/vboot/vbnv_flash.c | 82 |
2 files changed, 16 insertions, 69 deletions
diff --git a/src/vboot/Kconfig b/src/vboot/Kconfig index 08381677e3..f3df7c524b 100644 --- a/src/vboot/Kconfig +++ b/src/vboot/Kconfig @@ -29,7 +29,7 @@ config VBOOT_VBNV_CMOS config VBOOT_VBNV_CMOS_BACKUP_TO_FLASH bool "Back up Vboot non-volatile storage from CMOS to flash." default n - depends on VBOOT_VBNV_CMOS + depends on VBOOT_VBNV_CMOS && BOOT_DEVICE_SUPPORTS_WRITES help Vboot non-volatile storage data will be backed up from CMOS to flash and restored from flash if the CMOS is invalid due to power loss. @@ -42,6 +42,7 @@ config VBOOT_VBNV_EC config VBOOT_VBNV_FLASH def_bool n + depends on BOOT_DEVICE_SUPPORTS_WRITES help VBNV is stored in flash storage diff --git a/src/vboot/vbnv_flash.c b/src/vboot/vbnv_flash.c index 717ff23819..d061228a2a 100644 --- a/src/vboot/vbnv_flash.c +++ b/src/vboot/vbnv_flash.c @@ -17,7 +17,6 @@ #include <assert.h> #include <commonlib/region.h> #include <console/console.h> -#include <spi_flash.h> #include <string.h> #include <vb2_api.h> #include <vboot_nvstorage.h> @@ -31,17 +30,14 @@ struct vbnv_flash_ctx { /* VBNV flash is initialized */ int initialized; - /* Offset of the current nvdata in SPI flash */ + /* Offset of the current nvdata in flash */ int blob_offset; - /* Offset of the topmost nvdata blob in SPI flash */ + /* Offset of the topmost nvdata blob in flash */ int top_offset; - /* SPI flash handler used when saving data */ - struct spi_flash *flash; - - /* FMAP descriptor of the NVRAM area */ - struct region_device region; + /* Region to store and retrieve the VBNV contents. */ + struct region_device vbnv_dev; /* Cache of the current nvdata */ uint8_t cache[BLOB_SIZE]; @@ -66,13 +62,14 @@ static inline int can_overwrite(uint8_t current, uint8_t new) static int init_vbnv(void) { struct vbnv_flash_ctx *ctx = car_get_var_ptr(&vbnv_flash); + struct region_device *rdev = &ctx->vbnv_dev; uint8_t buf[BLOB_SIZE]; uint8_t empty_blob[BLOB_SIZE]; int offset; int i; - if (vboot_named_region_device("RW_NVRAM", &ctx->region) || - region_device_sz(&ctx->region) < BLOB_SIZE) { + if (vboot_named_region_device_rw("RW_NVRAM", rdev) || + region_device_sz(rdev) < BLOB_SIZE) { printk(BIOS_ERR, "%s: failed to locate NVRAM\n", __func__); return 1; } @@ -82,7 +79,7 @@ static int init_vbnv(void) empty_blob[i] = erase_value(); offset = 0; - ctx->top_offset = region_device_sz(&ctx->region) - BLOB_SIZE; + ctx->top_offset = region_device_sz(rdev) - BLOB_SIZE; /* * after the loop, offset is supposed to point the blob right before @@ -91,7 +88,7 @@ static int init_vbnv(void) * used. */ for (i = 0; i <= ctx->top_offset; i += BLOB_SIZE) { - if (rdev_readat(&ctx->region, buf, i, BLOB_SIZE) < 0) { + if (rdev_readat(rdev, buf, i, BLOB_SIZE) < 0) { printk(BIOS_ERR, "failed to read nvdata\n"); return 1; } @@ -101,7 +98,7 @@ static int init_vbnv(void) } /* reread the nvdata and write it to the cache */ - if (rdev_readat(&ctx->region, ctx->cache, offset, BLOB_SIZE) < 0) { + if (rdev_readat(rdev, ctx->cache, offset, BLOB_SIZE) < 0) { printk(BIOS_ERR, "failed to read nvdata\n"); return 1; } @@ -112,61 +109,12 @@ static int init_vbnv(void) return 0; } -static void vbnv_is_erasable(void) -{ - /* - * We check whether the region is aligned or not in advance to ensure - * we can erase the region when it's all used up. - * - * The region offset & size are determined by fmap.dts yet the check can - * be confidently done only by the spi flash driver. We use the same - * check as the one used by spi_flash_cmd_erase, which happens to be - * common to all the spi flash parts we support. - * - * TODO: Check by calling can_erase implemented by each spi flash driver - */ - struct vbnv_flash_ctx *ctx = car_get_var_ptr(&vbnv_flash); - - assert(!(region_device_offset(&ctx->region) % ctx->flash->sector_size)); - assert(!(region_device_sz(&ctx->region) % ctx->flash->sector_size)); -} - -static int vbnv_flash_probe(void) -{ - struct vbnv_flash_ctx *ctx = car_get_var_ptr(&vbnv_flash); - - if (!ctx->flash) { - ctx->flash = - spi_flash_probe(CONFIG_BOOT_DEVICE_SPI_FLASH_BUS, 0); - if (!ctx->flash) { - printk(BIOS_ERR, "failed to probe spi flash\n"); - return 1; - } - /* - * Called here instead of init_vbnv to reduce impact on boot - * speed. - */ - vbnv_is_erasable(); - } - - /* - * Handle the case where spi_flash_probe returns a CAR_GLOBAL - * in early execution on x86 but then later is moved to RAM. - */ - ctx->flash = car_get_var_ptr(ctx->flash); - - return 0; -} - static int erase_nvram(void) { struct vbnv_flash_ctx *ctx = car_get_var_ptr(&vbnv_flash); + const struct region_device *rdev = &ctx->vbnv_dev; - if (vbnv_flash_probe()) - return 1; - - if (ctx->flash->erase(ctx->flash, region_device_offset(&ctx->region), - region_device_sz(&ctx->region))) { + if (rdev_eraseat(rdev, 0, region_device_sz(rdev)) < 0) { printk(BIOS_ERR, "failed to erase nvram\n"); return 1; } @@ -191,6 +139,7 @@ void save_vbnv_flash(const uint8_t *vbnv_copy) struct vbnv_flash_ctx *ctx = car_get_var_ptr(&vbnv_flash); int new_offset; int i; + const struct region_device *rdev = &ctx->vbnv_dev; if (!ctx->initialized) if (init_vbnv()) @@ -216,10 +165,7 @@ void save_vbnv_flash(const uint8_t *vbnv_copy) } } - if (!vbnv_flash_probe() && - !ctx->flash->write(ctx->flash, - region_device_offset(&ctx->region) + new_offset, - BLOB_SIZE, vbnv_copy)) { + if (rdev_writeat(rdev, vbnv_copy, new_offset, BLOB_SIZE) < 0) { /* write was successful. safely move pointer forward */ ctx->blob_offset = new_offset; memcpy(ctx->cache, vbnv_copy, BLOB_SIZE); |