diff options
author | Vadim Bendebury <vbendeb@chromium.org> | 2011-11-03 14:00:57 -0700 |
---|---|---|
committer | Vadim Bendebury <vbendeb@chromium.org> | 2011-11-04 09:51:55 -0700 |
commit | b09086595e7844d068994476bd64737dc37a072b (patch) | |
tree | bc0f92ec1d18bb96ce7edf49a0784c00873b122e /lib | |
parent | 103dcae4b23ba2a3a33447af20342ca9fb4b55ce (diff) |
Introduce ability to use hardware SPI mapping for read accesses.
On X86 systems the hardware maps the bootprom SPI flash chip into the
top of memory address range. This could be used for accessing all
information in the SPI flash.
The vboot-reference code requires access to FMAP sections containing
cryptographic information, and as of today, u-boot reads the whole
sections, which are 64 KB in size, even though the actual areas
accessed by vboot-reference are much smaller.
A much faster way of accessing this information would be just passing
around pointers to the appropriate memory areas. This would eliminate
one copy, and also would make sure that only the areas actually
accessed get fetched from SPI flash.
This patch provides this ability trying to keep code changes to a
minimum.
New feature is enabled by defining CONFIG_HARDWARE_MAPPED_SPI. The
firmware storage API for file reads changes when the new configuration
option is set: a pointer to pointer to buffer is passed to the
read_spi() function instead of a pointer to buffer. When the new
feature is enabled the read_spi() function sets the pointer value to
point to the requested data instead of copying the data into the
buffer.
A new data type is introduced (read_buf_type), which is set to be a
(void *) if the new feature is not enabled, or (void **) otherwise.
This type is used as the buffer pointer in the spi_read() function.
Code allocating/freeing buffers used to keep data read from SPI flash
is now conditionally compiled.
Call sites for the spi_read() function are modified to adjust the
buffer pointer parameter (pass the address of the parameter instead of
the parameter, when the new feature is enabled).
gbb field access functions can be aliased to gbb_init(), as they all
in fact do the same - read a certain section of the gbb area.
This change does not benefit the ARM implementations, and makes the
code more complicated that it should be. Some u-boot rearchitecture
along with vboot_reference API enhancements could address this. A
tracking issue
(http://code.google.com/p/chromium-os/issues/detail?id=22528) has been
opened for that.
BUG=chrome-os-partner:6585, chromium-os:22528
TEST=manual
. build a new stumpy firmware image
. boot the stumpy, observe it start up chromeos.
. assess the boot timing using the cbmem.py utility (this
modification shaves in excess of 100ms off the boot time).
. disable the new feature, build a stumpy image, observe that is
still boots chromeOs.
. run emerge-terga2_kaen chromeos-u-boot to confirem that ARM
version builds cleanly.
Change-Id: I4e6ab530d24f5771b5a86a48d3f3135101b469a6
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/11152
Diffstat (limited to 'lib')
-rw-r--r-- | lib/chromeos/firmware_storage_spi.c | 46 | ||||
-rw-r--r-- | lib/chromeos/gbb.c | 12 | ||||
-rw-r--r-- | lib/vbexport/load_firmware.c | 3 |
3 files changed, 57 insertions, 4 deletions
diff --git a/lib/chromeos/firmware_storage_spi.c b/lib/chromeos/firmware_storage_spi.c index 26e01046db3..a2d80b585b0 100644 --- a/lib/chromeos/firmware_storage_spi.c +++ b/lib/chromeos/firmware_storage_spi.c @@ -47,19 +47,61 @@ static int border_check(struct spi_flash *flash, uint32_t offset, return 0; } +#ifdef CONFIG_HARDWARE_MAPPED_SPI + +#include <libfdt.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* + * When using hardware mapped SPI the offset passed to the file_read() + * function should be added to the base address of the SPI flash in the CPI + * memory. set_spi_flash_base() retrieves the flash chip base address from the + * flash map device tree section. + */ +static uint32_t spi_flash_base_addr; + +void set_spi_flash_base(void) +{ + int fmap_offset; + uint32_t *property; + int length; + const void *blob = gd->blob; + + fmap_offset = fdt_node_offset_by_compatible(blob, -1, + "chromeos,flashmap"); + if (fmap_offset < 0) { + VBDEBUG(PREFIX "chromeos,flashmap node is missing\n"); + return; + } + property = (uint32_t *)fdt_getprop(blob, fmap_offset, "reg", &length); + if (!property) { + VBDEBUG(PREFIX "reg property missing in flashmap!'\n"); + return; + } + spi_flash_base_addr = fdt32_to_cpu(property[0]); +} + +#endif + static int read_spi(firmware_storage_t *file, uint32_t offset, uint32_t count, - void *buf) + read_buf_type buf) { struct spi_flash *flash = file->context; if (border_check(flash, offset, count)) return -1; +#ifndef CONFIG_HARDWARE_MAPPED_SPI if (flash->read(flash, offset, count, buf)) { VBDEBUG(PREFIX "SPI read fail\n"); return -1; } - +#else + if (!spi_flash_base_addr) + set_spi_flash_base(); + *buf = (void *) (spi_flash_base_addr + offset); +#endif return 0; } diff --git a/lib/chromeos/gbb.c b/lib/chromeos/gbb.c index efadcd3037d..25d57413185 100644 --- a/lib/chromeos/gbb.c +++ b/lib/chromeos/gbb.c @@ -16,8 +16,9 @@ #define PREFIX "gbb: " -int gbb_init(void *gbb, firmware_storage_t *file, uint32_t gbb_offset) +int gbb_init(read_buf_type gbb, firmware_storage_t *file, uint32_t gbb_offset) { +#ifndef CONFIG_HARDWARE_MAPPED_SPI GoogleBinaryBlockHeader *gbbh = (GoogleBinaryBlockHeader *)gbb; if (file->read(file, gbb_offset, sizeof(*gbbh), gbbh)) { @@ -38,10 +39,18 @@ int gbb_init(void *gbb, firmware_storage_t *file, uint32_t gbb_offset) VBDEBUG(PREFIX "failed to read root key\n"); return 1; } +#else + if (file->read(file, gbb_offset, + sizeof(GoogleBinaryBlockHeader), gbb)) { + VBDEBUG(PREFIX "failed to read GBB header\n"); + return 1; + } +#endif return 0; } +#ifndef CONFIG_HARDWARE_MAPPED_SPI int gbb_read_bmp_block(void *gbb, firmware_storage_t *file, uint32_t gbb_offset) { GoogleBinaryBlockHeader *gbbh = (GoogleBinaryBlockHeader *)gbb; @@ -70,6 +79,7 @@ int gbb_read_recovery_key(void *gbb, return 0; } +#endif int gbb_check_integrity(uint8_t *gbb) { diff --git a/lib/vbexport/load_firmware.c b/lib/vbexport/load_firmware.c index 847418293e1..49b0215351a 100644 --- a/lib/vbexport/load_firmware.c +++ b/lib/vbexport/load_firmware.c @@ -49,7 +49,8 @@ VbError_t VbExHashFirmwareBody(VbCommonParams* cparams, uint32_t firmware_index) */ s->fw[i].size = firmware_body_size((uintptr_t)s->fw[i].vblock); - if (file->read(file, s->fw[i].offset, s->fw[i].size, s->fw[i].cache)) { + if (file->read(file, s->fw[i].offset, + s->fw[i].size, BT_EXTRA(s->fw[i].cache))) { VBDEBUG(PREFIX "fail to read firmware: %d\n", firmware_index); return 1; } |