From c6588c5af94e568bddd8111c3fca736f464042cf Mon Sep 17 00:00:00 2001 From: Aaron Durbin Date: Fri, 15 May 2015 13:15:34 -0500 Subject: coreboot: introduce boot_device The boot_device is a region_device that represents the device from which coreboot retrieves and boots its stages. The existing cbfs implementations use the boot_device as the intermediary for accessing the CBFS region. Also, there's currently only support for a read-only view of the boot_device. i.e. one cannot write to the boot_device using this view. However, a writable boot_device could be added in the future. Change-Id: Ic0da796ab161b8025c90631be3423ba6473ad31c Signed-off-by: Aaron Durbin Reviewed-on: http://review.coreboot.org/10216 Tested-by: build bot (Jenkins) Tested-by: Raptor Engineering Automated Test Stand Reviewed-by: Patrick Georgi --- src/soc/samsung/exynos5420/alternate_cbfs.c | 118 +++++++++++++++++++--------- 1 file changed, 81 insertions(+), 37 deletions(-) (limited to 'src/soc/samsung/exynos5420/alternate_cbfs.c') diff --git a/src/soc/samsung/exynos5420/alternate_cbfs.c b/src/soc/samsung/exynos5420/alternate_cbfs.c index b30ed6bff7..9bba748a84 100644 --- a/src/soc/samsung/exynos5420/alternate_cbfs.c +++ b/src/soc/samsung/exynos5420/alternate_cbfs.c @@ -20,6 +20,7 @@ #include #include +#include #include /* This driver serves as a CBFS media source. */ #include #include @@ -46,7 +47,7 @@ * rest of the firmware's lifetime and all subsequent stages (which will not * have __PRE_RAM__ defined) can just directly reference it there. */ -static int usb_cbfs_open(struct cbfs_media *media) +static int usb_cbfs_open(void) { #ifdef __PRE_RAM__ static int first_run = 1; @@ -84,7 +85,7 @@ static int usb_cbfs_open(struct cbfs_media *media) * this seems like a safer approach. It also makes it easy to pass our image * down to payloads. */ -static int sdmmc_cbfs_open(struct cbfs_media *media) +static int sdmmc_cbfs_open(void) { #ifdef __PRE_RAM__ /* @@ -118,66 +119,109 @@ static int sdmmc_cbfs_open(struct cbfs_media *media) return 0; } -static int alternate_cbfs_close(struct cbfs_media *media) { return 0; } +static int exynos_cbfs_open(struct cbfs_media *media) { + return 0; +} + +static int exynos_cbfs_close(struct cbfs_media *media) { + return 0; +} + +static size_t exynos_cbfs_read(struct cbfs_media *media, void *dest, + size_t offset, size_t count) { + const struct region_device *boot_dev; + + boot_dev = media->context; + + if (rdev_readat(boot_dev, dest, offset, count) < 0) + return 0; -static size_t alternate_cbfs_read(struct cbfs_media *media, void *dest, - size_t offset, size_t count) -{ - ASSERT(offset + count < _cbfs_cache_size); - memcpy(dest, _cbfs_cache + offset, count); return count; } -static void *alternate_cbfs_map(struct cbfs_media *media, size_t offset, - size_t count) -{ - ASSERT(offset + count < _cbfs_cache_size); - return _cbfs_cache + offset; +static void *exynos_cbfs_map(struct cbfs_media *media, size_t offset, + size_t count) { + const struct region_device *boot_dev; + void *ptr; + + boot_dev = media->context; + + ptr = rdev_mmap(boot_dev, offset, count); + + if (ptr == NULL) + return (void *)-1; + + return ptr; } -static void *alternate_cbfs_unmap(struct cbfs_media *media, - const void *buffer) { return 0; } +static void *exynos_cbfs_unmap(struct cbfs_media *media, + const void *address) { + const struct region_device *boot_dev; -static int initialize_exynos_sdmmc_cbfs_media(struct cbfs_media *media) -{ - printk(BIOS_DEBUG, "Using Exynos alternate boot mode SDMMC\n"); + boot_dev = media->context; - media->open = sdmmc_cbfs_open; - media->close = alternate_cbfs_close; - media->read = alternate_cbfs_read; - media->map = alternate_cbfs_map; - media->unmap = alternate_cbfs_unmap; + rdev_munmap(boot_dev, (void *)address); - return 0; + return NULL; } -static int initialize_exynos_usb_cbfs_media(struct cbfs_media *media) +int init_default_cbfs_media(struct cbfs_media *media) { - printk(BIOS_DEBUG, "Using Exynos alternate boot mode USB A-A\n"); + boot_device_init(); - media->open = usb_cbfs_open; - media->close = alternate_cbfs_close; - media->read = alternate_cbfs_read; - media->map = alternate_cbfs_map; - media->unmap = alternate_cbfs_unmap; + media->context = (void *)boot_device_ro(); + + if (media->context == NULL) + return -1; + + media->open = exynos_cbfs_open; + media->close = exynos_cbfs_close; + media->read = exynos_cbfs_read; + media->map = exynos_cbfs_map; + media->unmap = exynos_cbfs_unmap; return 0; } -int init_default_cbfs_media(struct cbfs_media *media) +static struct mem_region_device alternate_rdev = MEM_REGION_DEV_INIT(NULL, 0); + +const struct region_device *boot_device_ro(void) { if (*iram_secondary_base == SECONDARY_BASE_BOOT_USB) - return initialize_exynos_usb_cbfs_media(media); + return &alternate_rdev.rdev; + + switch (exynos_power->om_stat & OM_STAT_MASK) { + case OM_STAT_SDMMC: + return &alternate_rdev.rdev; + case OM_STAT_SPI: + return exynos_spi_boot_device(); + default: + printk(BIOS_EMERG, "Exynos OM_STAT value 0x%x not supported!\n", + exynos_power->om_stat); + return NULL; + } +} + +void boot_device_init(void) +{ + mem_region_device_init(&alternate_rdev, _cbfs_cache, _cbfs_cache_size); + + if (*iram_secondary_base == SECONDARY_BASE_BOOT_USB) { + printk(BIOS_DEBUG, "Using Exynos alternate boot mode USB A-A\n"); + usb_cbfs_open(); + return; + } switch (exynos_power->om_stat & OM_STAT_MASK) { case OM_STAT_SDMMC: - return initialize_exynos_sdmmc_cbfs_media(media); + printk(BIOS_DEBUG, "Using Exynos alternate boot mode SDMMC\n"); + sdmmc_cbfs_open(); + break; case OM_STAT_SPI: - return initialize_exynos_spi_cbfs_media(media, - _cbfs_cache, _cbfs_cache_size); + exynos_init_spi_boot_device(); + break; default: printk(BIOS_EMERG, "Exynos OM_STAT value 0x%x not supported!\n", exynos_power->om_stat); - return 1; } } -- cgit v1.2.3