Aaron Durbin (adurbin@google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9134
-gerrit
commit 453aec3b70fb70f63fbeb7ac63374add552bf435 Author: Aaron Durbin adurbin@chromium.org Date: Fri Mar 27 00:23:49 2015 -0500
cbfs: add new API
Note: this change purposefully ignores the chromeos code.
Change-Id: I339b84fce95f03d1dbb63a0f54a26be5eb07f7c8 Signed-off-by: Aaron Durbin adurbin@chromium.org --- src/arch/riscv/rom_media.c | 92 +++------ src/arch/x86/lib/Makefile.inc | 6 +- src/arch/x86/lib/mmap_boot.c | 76 +++++++ src/arch/x86/lib/rom_media.c | 101 ---------- src/cpu/allwinner/a10/bootblock_media.c | 6 +- src/cpu/amd/microcode/microcode.c | 4 +- src/cpu/intel/microcode/microcode.c | 18 +- src/cpu/ti/am335x/bootblock_media.c | 57 +----- src/cpu/ti/am335x/nand.c | 8 +- src/cpu/via/nano/update_ucode.c | 5 +- src/device/dram/spd_cache.c | 4 +- src/device/oprom/realmode/x86.c | 14 +- src/device/oprom/yabel/vbe.c | 7 +- src/device/pci_rom.c | 8 +- src/drivers/intel/fsp/fastboot_cache.c | 7 +- src/drivers/pc80/mc146818rtc.c | 8 +- src/include/boot_device.h | 30 +++ src/include/cbfs.h | 85 +++++++- src/include/cbfs_core.h | 128 ------------ src/include/cbfs_declarations.h | 82 -------- src/include/rmodule.h | 4 +- src/lib/Makefile.inc | 17 +- src/lib/cbfs.c | 272 +++++++++++++++++++++++++ src/lib/cbfs_boot_props.c | 57 ++++++ src/lib/cbfs_core.c | 287 --------------------------- src/lib/cbfs_core.h | 52 ----- src/lib/cbfs_gpl.c | 206 ------------------- src/lib/cbfs_spi.c | 85 +++----- src/lib/coreboot_table.c | 4 +- src/lib/loaders/cbfs_payload_loader.c | 5 +- src/lib/loaders/cbfs_ramstage_loader.c | 3 +- src/lib/loaders/load_and_run_romstage.c | 2 +- src/lib/rmodule.c | 48 +++-- src/mainboard/emulation/qemu-armv7/media.c | 54 +---- src/mainboard/google/bolt/romstage.c | 4 +- src/mainboard/google/butterfly/mainboard.c | 4 +- src/mainboard/google/falco/romstage.c | 4 +- src/mainboard/google/link/romstage.c | 4 +- src/mainboard/google/panther/lan.c | 4 +- src/mainboard/google/peach_pit/romstage.c | 17 +- src/mainboard/google/peppy/romstage.c | 4 +- src/mainboard/google/rambi/romstage.c | 9 +- src/mainboard/google/samus/spd/spd.c | 13 +- src/mainboard/google/slippy/romstage.c | 4 +- src/mainboard/samsung/lumpy/romstage.c | 4 +- src/mainboard/siemens/mc_tcu3/modhwinfo.c | 6 +- src/northbridge/amd/agesa/common/common.c | 3 +- src/northbridge/amd/agesa/def_callouts.c | 4 +- src/northbridge/amd/pi/def_callouts.c | 4 +- src/northbridge/intel/haswell/mrccache.c | 7 +- src/northbridge/intel/haswell/raminit.c | 4 +- src/northbridge/intel/i82830/vga.c | 3 +- src/northbridge/intel/sandybridge/mrccache.c | 7 +- src/northbridge/intel/sandybridge/raminit.c | 3 +- src/soc/intel/baytrail/romstage/raminit.c | 3 +- src/soc/intel/broadwell/romstage/raminit.c | 3 +- src/soc/nvidia/tegra124/Makefile.inc | 4 - src/soc/nvidia/tegra124/cbfs.c | 30 --- src/soc/nvidia/tegra124/spi.c | 107 ++++------ src/soc/nvidia/tegra124/spi.h | 5 - src/soc/nvidia/tegra132/Makefile.inc | 3 - src/soc/nvidia/tegra132/cbfs.c | 30 --- src/soc/nvidia/tegra132/ccplex.c | 15 +- src/soc/nvidia/tegra132/spi.c | 107 ++++------ src/soc/nvidia/tegra132/spi.h | 5 - src/soc/rockchip/rk3288/Makefile.inc | 3 - src/soc/rockchip/rk3288/media.c | 36 ---- src/soc/rockchip/rk3288/spi.c | 75 +++---- src/soc/rockchip/rk3288/spi.h | 5 - src/soc/samsung/exynos5250/alternate_cbfs.c | 79 +++----- src/soc/samsung/exynos5250/spi.c | 78 +++----- src/soc/samsung/exynos5250/spi.h | 6 +- src/soc/samsung/exynos5420/alternate_cbfs.c | 79 +++----- src/soc/samsung/exynos5420/spi.c | 74 ++----- src/soc/samsung/exynos5420/spi.h | 6 +- 75 files changed, 963 insertions(+), 1744 deletions(-)
diff --git a/src/arch/riscv/rom_media.c b/src/arch/riscv/rom_media.c index 8e858cb..f810c2a 100644 --- a/src/arch/riscv/rom_media.c +++ b/src/arch/riscv/rom_media.c @@ -1,7 +1,7 @@ /* * This file is part of the coreboot project. * - * Copyright (C) 2013 The Chromium OS Authors. All rights reserved. + * Copyright 2015 Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -18,75 +18,31 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301 USA */ +#include <boot_device.h> #include <cbfs.h> -#include <string.h> +#include <endian.h> +#include <region.h>
-#ifdef LIBPAYLOAD -# define printk(x...) -# define init_default_cbfs_media libpayload_init_default_cbfs_media - extern int libpayload_init_default_cbfs_media(struct cbfs_media *media); -#else -# include <console/console.h> -#endif - -// Implementation of memory-mapped ROM media source on X86. - -static int rom_media_open(struct cbfs_media *media) { - return 0; -} - -static void *rom_media_map(struct cbfs_media *media, size_t offset, size_t count) { - void *ptr; - printk(BIOS_INFO, "%s: media %p, offset %lx, size %ld.\n", __func__, media, offset, count); - - ptr = (void*)offset; - return ptr; -} - -static void *rom_media_unmap(struct cbfs_media *media, const void *address) { - return NULL; -} - -static size_t rom_media_read(struct cbfs_media *media, void *dest, size_t offset, - size_t count) { - void *ptr = rom_media_map(media, offset, count); - memcpy(dest, ptr, count); - rom_media_unmap(media, ptr); - return count; -} - -static int rom_media_close(struct cbfs_media *media) { - return 0; -} +/* + * RISC-V emulation mainboard info and hexdump: + * CONFIG_CBFS_HEADER_ROM_OFFSET 0x10000 + * CONFIG_CBFS_ROM_OFFSET 0x10040 + * CONFIG_ROM_SIZE 0x400000 + * CONFIG_BOOTBLOCK_ROM_OFFSET 0x0 + * + *00010000 4f 52 42 43 31 31 31 32 00 40 00 00 00 00 64 e8 |ORBC1112.@....d.| + *00010010 00 00 00 40 00 01 00 40 c0 01 d0 de ff ff ff ff |...@...@........| + *00010020 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| + *00010030 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| + *00010040 4c 41 52 43 48 49 56 45 00 00 3d 20 00 00 00 10 |LARCHIVE..= ....| + *00010050 00 00 00 00 00 00 00 38 66 61 6c 6c 62 61 63 6b |.......8fallback| + *00010060 2f 72 6f 6d 73 74 61 67 65 00 00 00 00 00 00 00 |/romstage.......| + */
-static int init_rom_media_cbfs(struct cbfs_media *media) { - //extern unsigned long _cbfs_master_header; - // On X86, we always keep a reference of pointer to CBFS header in - // 0xfffffffc, and the pointer is still a memory-mapped address. - // Since the CBFS core always use ROM offset, we need to figure out - // header->romsize even before media is initialized. - struct cbfs_header *header = (struct cbfs_header*) CONFIG_CBFS_HEADER_ROM_OFFSET; //&_cbfs_master_header; - if (CBFS_HEADER_MAGIC != ntohl(header->magic)) { - printk(BIOS_ERR, "Invalid CBFS master header at %p\n", header); - printk(BIOS_ERR, "Expected %08lx and got %08lx\n", (unsigned long) CBFS_HEADER_MAGIC, (unsigned long) ntohl(header->magic)); - return -1; - } else { - uint32_t romsize = ntohl(header->romsize); - media->context = (void*)(uintptr_t)romsize; -#if defined(CONFIG_ROM_SIZE) - if (CONFIG_ROM_SIZE != romsize) - printk(BIOS_INFO, "Warning: rom size unmatch (%d/%d)\n", - CONFIG_ROM_SIZE, romsize); -#endif - } - media->open = rom_media_open; - media->close = rom_media_close; - media->map = rom_media_map; - media->unmap = rom_media_unmap; - media->read = rom_media_read; - return 0; -} +static const struct mem_region_device boot_dev = + MEM_REGION_DEV_INIT(NULL, CONFIG_ROM_SIZE);
-int init_default_cbfs_media(struct cbfs_media *media) { - return init_rom_media_cbfs(media); +const struct region_device *boot_device_ro(void) +{ + return &boot_dev.rdev; } diff --git a/src/arch/x86/lib/Makefile.inc b/src/arch/x86/lib/Makefile.inc index c7e8b62..0d88a6d 100644 --- a/src/arch/x86/lib/Makefile.inc +++ b/src/arch/x86/lib/Makefile.inc @@ -5,7 +5,7 @@ romstage-y += cbfs_and_run.c romstage-y += memset.c romstage-y += memcpy.c romstage-y += memmove.c -romstage-y += rom_media.c +romstage-y += mmap_boot.c
endif # CONFIG_ARCH_ROMSTAGE_X86_32
@@ -21,7 +21,7 @@ ramstage-y += memset.c ramstage-y += memcpy.c ramstage-y += memmove.c ramstage-y += ebda.c -ramstage-y += rom_media.c +ramstage-y += mmap_boot.c ramstage-$(CONFIG_COOP_MULTITASKING) += thread.c ramstage-$(CONFIG_COOP_MULTITASKING) += thread_switch.S ramstage-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c @@ -31,7 +31,7 @@ romstage-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c smm-y += memset.c smm-y += memcpy.c smm-y += memmove.c -smm-y += rom_media.c +smm-y += mmap_boot.c
rmodules_x86_32-y += memset.c rmodules_x86_32-y += memcpy.c diff --git a/src/arch/x86/lib/mmap_boot.c b/src/arch/x86/lib/mmap_boot.c new file mode 100644 index 0000000..7da4faf --- /dev/null +++ b/src/arch/x86/lib/mmap_boot.c @@ -0,0 +1,76 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2015 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <stdint.h> +#include <stdlib.h> +#include <boot_device.h> +#include <console/console.h> +#include <cbfs.h> +#include <endian.h> +#include <region.h> + +/* The ROM is memory mapped just below 4GiB. Form a pointer for the base. */ +#define rom_base ((void *)(uintptr_t)(-(int32_t)CONFIG_ROM_SIZE)) + +static const struct mem_region_device boot_dev = + MEM_REGION_DEV_INIT(rom_base, CONFIG_ROM_SIZE); + +const struct region_device *boot_device_ro(void) +{ + return &boot_dev.rdev; +} + +int cbfs_boot_region_properties(struct cbfs_props *props) +{ + struct cbfs_header header; + int32_t offset; + const struct region_device *bdev; + + bdev = boot_device_ro(); + + rdev_readat(bdev, &offset, CONFIG_ROM_SIZE - 4, sizeof(offset)); + + /* The offset is relative to the end of the media. */ + offset += CONFIG_ROM_SIZE; + + rdev_readat(bdev, &header , offset, sizeof(header)); + + header.magic = ntohl(header.magic); + header.romsize = ntohl(header.romsize); + header.bootblocksize = ntohl(header.bootblocksize); + header.align = ntohl(header.align); + header.offset = ntohl(header.offset); + + if (header.magic != CBFS_HEADER_MAGIC) + return -1; + + props->align = header.align; + props->offset = header.offset; + if (CONFIG_ROM_SIZE != header.romsize) + props->size = CONFIG_ROM_SIZE; + else + props->size = header.romsize; + props->size -= props->offset; + props->size -= header.bootblocksize; + props->size = ALIGN_DOWN(props->size, props->align); + + printk(BIOS_DEBUG, "CBFS @ %zx size %zx\n", props->offset, props->size); + + return 0; +} diff --git a/src/arch/x86/lib/rom_media.c b/src/arch/x86/lib/rom_media.c deleted file mode 100644 index ed2122c..0000000 --- a/src/arch/x86/lib/rom_media.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2013 The Chromium OS Authors. All rights reserved. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; version 2 of - * the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, - * MA 02110-1301 USA - */ -#include <cbfs.h> -#include <string.h> - -#ifdef LIBPAYLOAD -# define printk(x...) -# define init_default_cbfs_media libpayload_init_default_cbfs_media - extern int libpayload_init_default_cbfs_media(struct cbfs_media *media); -#else -# include <console/console.h> -#endif - -// Implementation of memory-mapped ROM media source on X86. - -static int x86_rom_open(struct cbfs_media *media) { - return 0; -} - -static void *x86_rom_map(struct cbfs_media *media, size_t offset, size_t count) { - void *ptr; - // Some address (ex, pointer to master header) may be given in memory - // mapped location. To workaround that, we handle >0xf0000000 as real - // memory pointer. - - if ((uint32_t)offset > (uint32_t)0xf0000000) - ptr = (void*)offset; - else - ptr = (void*)(0 - (uint32_t)media->context + offset); - return ptr; -} - -static void *x86_rom_unmap(struct cbfs_media *media, const void *address) { - return NULL; -} - -static size_t x86_rom_read(struct cbfs_media *media, void *dest, size_t offset, - size_t count) { - void *ptr = x86_rom_map(media, offset, count); - memcpy(dest, ptr, count); - x86_rom_unmap(media, ptr); - return count; -} - -static int x86_rom_close(struct cbfs_media *media) { - return 0; -} - -int init_x86rom_cbfs_media(struct cbfs_media *media); -int init_x86rom_cbfs_media(struct cbfs_media *media) { - // On X86, we always keep a reference of pointer to CBFS header in - // 0xfffffffc, and the pointer is still a memory-mapped address. - // Since the CBFS core always use ROM offset, we need to figure out - // header->romsize even before media is initialized. - struct cbfs_header *header = (struct cbfs_header*) - *(uint32_t*)(0xfffffffc); - if (CBFS_HEADER_MAGIC != ntohl(header->magic)) { -#if defined(CONFIG_ROM_SIZE) - printk(BIOS_ERR, "Invalid CBFS master header at %p\n", header); - media->context = (void*)CONFIG_ROM_SIZE; -#else - return -1; -#endif - } else { - uint32_t romsize = ntohl(header->romsize); - media->context = (void*)romsize; -#if defined(CONFIG_ROM_SIZE) - if (CONFIG_ROM_SIZE != romsize) - printk(BIOS_INFO, "Warning: rom size unmatch (%d/%d)\n", - CONFIG_ROM_SIZE, romsize); -#endif - } - media->open = x86_rom_open; - media->close = x86_rom_close; - media->map = x86_rom_map; - media->unmap = x86_rom_unmap; - media->read = x86_rom_read; - return 0; -} - -int init_default_cbfs_media(struct cbfs_media *media) { - return init_x86rom_cbfs_media(media); -} diff --git a/src/cpu/allwinner/a10/bootblock_media.c b/src/cpu/allwinner/a10/bootblock_media.c index a5863b6..17c6039 100644 --- a/src/cpu/allwinner/a10/bootblock_media.c +++ b/src/cpu/allwinner/a10/bootblock_media.c @@ -4,11 +4,11 @@ * Copyright (C) 2013 Alexandru Gagniuc mr.nuke.me@gmail.com * Subject to the GNU GPL v2, or (at your option) any later version. */ -#include <cbfs.h> +#include <boot_device.h> #include <console/console.h>
-int init_default_cbfs_media(struct cbfs_media *media) +const struct region_device *boot_device_ro(void) { printk(BIOS_ERR, "Oh my! I don't know how to access CBFS yet."); - return 0; + return NULL; } diff --git a/src/cpu/amd/microcode/microcode.c b/src/cpu/amd/microcode/microcode.c index 938f5f6..d5bf756 100644 --- a/src/cpu/amd/microcode/microcode.c +++ b/src/cpu/amd/microcode/microcode.c @@ -105,8 +105,8 @@ void amd_update_microcode_from_cbfs(u32 equivalent_processor_rev_id) return; }
- ucode = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, MICROCODE_CBFS_FILE, - CBFS_TYPE_MICROCODE, &ucode_len); + ucode = cbfs_boot_map_with_leak(MICROCODE_CBFS_FILE, + CBFS_TYPE_MICROCODE, &ucode_len); if (!ucode) { UCODE_DEBUG("microcode file not found. Skipping updates.\n"); return; diff --git a/src/cpu/intel/microcode/microcode.c b/src/cpu/intel/microcode/microcode.c index 947dfd7..c4d2cd0 100644 --- a/src/cpu/intel/microcode/microcode.c +++ b/src/cpu/intel/microcode/microcode.c @@ -109,25 +109,29 @@ void intel_microcode_load_unlocked(const void *microcode_patch)
const void *intel_microcode_find(void) { - struct cbfs_file *microcode_file; const struct microcode *ucode_updates; - u32 eax, microcode_len; + size_t microcode_len; + u32 eax; u32 pf, rev, sig, update_size; unsigned int x86_model, x86_family; msr_t msr;
#ifdef __PRE_RAM__ - microcode_file = walkcbfs_head((char *) MICROCODE_CBFS_FILE); -#else - microcode_file = cbfs_get_file(CBFS_DEFAULT_MEDIA, - MICROCODE_CBFS_FILE); -#endif + struct cbfs_file *microcode_file;
+ microcode_file = walkcbfs_head((char *) MICROCODE_CBFS_FILE); if (!microcode_file) return NULL;
ucode_updates = CBFS_SUBHEADER(microcode_file); microcode_len = ntohl(microcode_file->len); +#else + ucode_updates = cbfs_boot_map_with_leak(MICROCODE_CBFS_FILE, + CBFS_TYPE_MICROCODE, + µcode_len); + if (ucode_updates == NULL) + return NULL; +#endif
/* CPUID sets MSR 0x8B iff a microcode update has been loaded. */ msr.lo = 0; diff --git a/src/cpu/ti/am335x/bootblock_media.c b/src/cpu/ti/am335x/bootblock_media.c index 553fe42..bd7f070 100644 --- a/src/cpu/ti/am335x/bootblock_media.c +++ b/src/cpu/ti/am335x/bootblock_media.c @@ -17,56 +17,15 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
-#include <cbfs.h> -#include <console/console.h> -#include <string.h> +#include <boot_device.h> +#include <region.h>
-static int dummy_open(struct cbfs_media *media) -{ - return 0; -} - -static int dummy_close(struct cbfs_media *media) -{ - return 0; -} +/* FIXME: No idea how big the internal SRAM actually is. */ +static const struct mem_region_device boot_dev = + MEM_REGION_DEV_INIT((void *)(uintptr_t)CONFIG_BOOTBLOCK_BASE, + CONFIG_ROM_SIZE);
-static void * on_chip_memory_map(struct cbfs_media *media, size_t offset, - size_t count) +const struct region_device *boot_device_ro(void) { - return (void *)((uintptr_t)CONFIG_BOOTBLOCK_BASE + offset); -} - -static void * dummy_unmap(struct cbfs_media *media, const void *address) -{ - return NULL; -} - -static size_t on_chip_memory_read(struct cbfs_media *media, void *dest, - size_t offset, size_t count) -{ - void *ptr = media->map(media, offset, count); - memcpy(dest, ptr, count); - media->unmap(media, ptr); - return count; -} - -int init_default_cbfs_media(struct cbfs_media *media) -{ - struct cbfs_header *header = - (struct cbfs_header *)((uintptr_t)CONFIG_BOOTBLOCK_BASE + - CONFIG_CBFS_HEADER_ROM_OFFSET); - - if (CBFS_HEADER_MAGIC != ntohl(header->magic)) { - printk(BIOS_ERR, "Invalid CBFS master header at %p\n", header); - return -1; - } - - media->open = dummy_open; - media->close = dummy_close; - media->map = on_chip_memory_map; - media->unmap = dummy_unmap; - media->read = on_chip_memory_read; - - return 0; + return &boot_dev.rdev; } diff --git a/src/cpu/ti/am335x/nand.c b/src/cpu/ti/am335x/nand.c index ddab389..73dedbb 100644 --- a/src/cpu/ti/am335x/nand.c +++ b/src/cpu/ti/am335x/nand.c @@ -17,10 +17,10 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
-#include <cbfs.h> +#include <boot_device.h>
-int init_default_cbfs_media(struct cbfs_media *media) +const struct region_device *boot_device_ro(void) { - /* FIXME: add support for reading coreboot from NAND */ - return 0; + /* FIXME: add support for reading coreboot from NAND */ + return NULL; } diff --git a/src/cpu/via/nano/update_ucode.c b/src/cpu/via/nano/update_ucode.c index aa0adeb..a69a291 100644 --- a/src/cpu/via/nano/update_ucode.c +++ b/src/cpu/via/nano/update_ucode.c @@ -110,9 +110,8 @@ unsigned int nano_update_ucode(void) u32 *ucode_data; size_t ucode_len;
- ucode_data = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, - "cpu_microcode_blob.bin", - CBFS_TYPE_MICROCODE, &ucode_len); + ucode_data = cbfs_boot_map_with_leak("cpu_microcode_blob.bin", + CBFS_TYPE_MICROCODE, &ucode_len); /* Oops, did you forget to include the microcode ? */ if(ucode_data == NULL) { printk(BIOS_ALERT, "WARNING: No microcode file found in CBFS. " diff --git a/src/device/dram/spd_cache.c b/src/device/dram/spd_cache.c index 8abb791..fcb1391 100644 --- a/src/device/dram/spd_cache.c +++ b/src/device/dram/spd_cache.c @@ -36,8 +36,8 @@ int read_spd_from_cbfs(u8 *buf, int idx) size_t min_len = (idx + 1) * SPD_SIZE;
printk(BIOS_DEBUG, "read SPD\n"); - spd_file = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "spd.bin", - CBFS_TYPE_SPD, &spd_file_len); + spd_file = cbfs_boot_map_with_leak("spd.bin", CBFS_TYPE_SPD, + &spd_file_len); if (!spd_file) printk(BIOS_EMERG, "file [spd.bin] not found in CBFS"); if (spd_file_len < min_len) diff --git a/src/device/oprom/realmode/x86.c b/src/device/oprom/realmode/x86.c index 919fd6d..7f8c166 100644 --- a/src/device/oprom/realmode/x86.c +++ b/src/device/oprom/realmode/x86.c @@ -273,10 +273,9 @@ void vbe_set_graphics(void) vbe_set_mode(&mode_info); #if CONFIG_BOOTSPLASH struct jpeg_decdata *decdata; - unsigned char *jpeg = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, - "bootsplash.jpg", - CBFS_TYPE_BOOTSPLASH, - NULL); + unsigned char *jpeg = cbfs_boot_map_with_leak("bootsplash.jpg", + CBFS_TYPE_BOOTSPLASH, + NULL); if (!jpeg) { printk(BIOS_DEBUG, "VBE: No bootsplash found.\n"); return; @@ -379,6 +378,9 @@ static u32 VSA_vrRead(u16 classIndex)
void do_vsmbios(void) { + struct prog vsa = { + .name = "vsa", + }; printk(BIOS_DEBUG, "Preparing for VSA...\n");
/* Set up C interrupt handlers */ @@ -390,8 +392,8 @@ void do_vsmbios(void) /* Make sure the code is placed. */ setup_realmode_code();
- if ((unsigned int)cbfs_load_stage(CBFS_DEFAULT_MEDIA, "vsa") != - VSA2_ENTRY_POINT) { + if (cbfs_boot_load_stage(&vsa) || + (uintptr_t)prog_entry(&vsa) != VSA2_ENTRY_POINT) { printk(BIOS_ERR, "Failed to load VSA.\n"); return; } diff --git a/src/device/oprom/yabel/vbe.c b/src/device/oprom/yabel/vbe.c index 6354afe..322bc6c 100644 --- a/src/device/oprom/yabel/vbe.c +++ b/src/device/oprom/yabel/vbe.c @@ -724,10 +724,9 @@ void vbe_set_graphics(void) * cares. */ // int imagesize = 1024*768*2;
- unsigned char *jpeg = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, - "bootsplash.jpg", - CBFS_TYPE_BOOTSPLASH, - NULL); + unsigned char *jpeg = cbfs_boot_map_with_leak("bootsplash.jpg", + CBFS_TYPE_BOOTSPLASH, + NULL); if (!jpeg) { DEBUG_PRINTF_VBE("Could not find bootsplash.jpg\n"); return; diff --git a/src/device/pci_rom.c b/src/device/pci_rom.c index dbc05ac..dd70770 100644 --- a/src/device/pci_rom.c +++ b/src/device/pci_rom.c @@ -38,8 +38,7 @@ struct rom_header *pci_rom_probe(struct device *dev) struct pci_data *rom_data;
/* If it's in FLASH, then don't check device for ROM. */ - rom_header = cbfs_load_optionrom(CBFS_DEFAULT_MEDIA, dev->vendor, - dev->device, NULL); + rom_header = cbfs_boot_map_optionrom(dev->vendor, dev->device);
u32 vendev = (dev->vendor << 16) | dev->device; u32 mapped_vendev = vendev; @@ -48,10 +47,9 @@ struct rom_header *pci_rom_probe(struct device *dev)
if (!rom_header) { if (vendev != mapped_vendev) { - rom_header = cbfs_load_optionrom( - CBFS_DEFAULT_MEDIA, + rom_header = cbfs_boot_map_optionrom( mapped_vendev >> 16, - mapped_vendev & 0xffff, NULL); + mapped_vendev & 0xffff); } }
diff --git a/src/drivers/intel/fsp/fastboot_cache.c b/src/drivers/intel/fsp/fastboot_cache.c index bcf39ab..0377ba8 100644 --- a/src/drivers/intel/fsp/fastboot_cache.c +++ b/src/drivers/intel/fsp/fastboot_cache.c @@ -63,10 +63,9 @@ static int is_mrc_cache(struct mrc_data_container *mrc_cache) static u32 get_mrc_cache_region(struct mrc_data_container **mrc_region_ptr) { size_t region_size; - *mrc_region_ptr = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, - "mrc.cache", - CBFS_TYPE_MRC_CACHE, - ®ion_size); + *mrc_region_ptr = cbfs_boot_map_with_leak("mrc.cache", + CBFS_TYPE_MRC_CACHE, + ®ion_size);
return region_size; } diff --git a/src/drivers/pc80/mc146818rtc.c b/src/drivers/pc80/mc146818rtc.c index 4f034a2..fe2e1f3 100644 --- a/src/drivers/pc80/mc146818rtc.c +++ b/src/drivers/pc80/mc146818rtc.c @@ -212,8 +212,8 @@ enum cb_err get_option(void *dest, const char *name) namelen = strnlen(name, CMOS_MAX_NAME_LENGTH);
/* find the requested entry record */ - ct = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "cmos_layout.bin", - CBFS_COMPONENT_CMOS_LAYOUT, NULL); + ct = cbfs_boot_map_with_leak("cmos_layout.bin", + CBFS_COMPONENT_CMOS_LAYOUT, NULL); if (!ct) { printk(BIOS_ERR, "RTC: cmos_layout.bin could not be found. " "Options are disabled\n"); @@ -295,8 +295,8 @@ enum cb_err set_option(const char *name, void *value) namelen = strnlen(name, CMOS_MAX_NAME_LENGTH);
/* find the requested entry record */ - ct = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "cmos_layout.bin", - CBFS_COMPONENT_CMOS_LAYOUT, NULL); + ct = cbfs_boot_map_with_leak("cmos_layout.bin", + CBFS_COMPONENT_CMOS_LAYOUT, NULL); if (!ct) { printk(BIOS_ERR, "cmos_layout.bin could not be found. " "Options are disabled\n"); diff --git a/src/include/boot_device.h b/src/include/boot_device.h new file mode 100644 index 0000000..7d4c0b6 --- /dev/null +++ b/src/include/boot_device.h @@ -0,0 +1,30 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2015 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _BOOT_DEVICE_H_ +#define _BOOT_DEVICE_H_ + +#include <region.h> + +/* Return the region_device for the read-only boot device. */ +const struct region_device *boot_device_ro(void); +/* Initialize the boot device. */ +void boot_device_init(void); + +#endif /* _BOOT_DEVICE_H_ */ diff --git a/src/include/cbfs.h b/src/include/cbfs.h index 315684e..625ec91 100644 --- a/src/include/cbfs.h +++ b/src/include/cbfs.h @@ -20,6 +20,89 @@ #ifndef _CBFS_H_ #define _CBFS_H_
-#include <cbfs_declarations.h> +#include <cbfs_serialized.h> +#include <program_loading.h> +#include <region.h> + +/* + * CBFS operations consist of the following concepts: + * - region_device for the boot media + * - cbfsd which is a descriptor for representing a cbfs instance + * - cbfsf which is a file handle for manipulating cbfs files + */ + +/* Descriptor for cbfs lookup operations. */ +struct cbfsd; +/* File handle representing a cbfs file. */ +struct cbfsf; + +/********************************************** + * Perform CBFS operations on the boot device.* + **********************************************/ + +/* Return mapping of option rom found in boot device. NULL on error. */ +void *cbfs_boot_map_optionrom(uint16_t vendor, uint16_t device); +/* Load stage into memory filling in prog. Return 0 on success. < 0 on error. */ +int cbfs_boot_load_stage(struct prog *prog); +/* Locate file by name and optional type. Return < 0 on error. 0 on success. */ +int cbfs_boot_locate(struct cbfsf *fh, const char *name, uint32_t *type); +/* Map file into memory leaking the mapping. Only should be used when + * leaking mappings are a no-op. Returns NULL on error, else returns + * the mapping and sets the size of the file. */ +void *cbfs_boot_map_with_leak(const char *name, uint32_t type, size_t *size); + +/************************************************* + * Perform CBFS operations on the provided file. * + *************************************************/ + +/* Map file into memory. Return NULL on error. */ +void *cbfs_file_mmap(const struct cbfsf *fh, size_t offset, size_t size); +/* Unmap previously mapped file. Returns < 0 on error. 0 on success. */ +int cbfs_file_munmap(const struct cbfsf *fh, void *mapping); +/* Read size bytes into b at offset in file. Returns < 0 on error else it + * returns the number of bytes read. */ +ssize_t cbfs_file_readat(const struct cbfsf *fh, void *b, size_t offset, + size_t size); +/* Load stage into memory filling in prog. Return 0 on success. < 0 on error. */ +int cbfs_file_stage_load(const struct cbfsf *fh, struct prog *prog); + +/******************************************************* + * Perform CBFS operations on the provided descriptor. * + *******************************************************/ + +/* Locate file by name and optional type. Return < 0 on error. 0 on success. */ +int cbfs_locate(const struct cbfsd *cbfs, struct cbfsf *fh, const char *name, + uint32_t *type); + +/***************************************************************** + * Support structures and functions. Used by implementers of API * + *****************************************************************/ + +struct cbfsd { + const struct region_device *rdev; + size_t align; +}; + +struct cbfsf { + struct region_device rdev; +}; + +static inline size_t cbfs_file_size(const struct cbfsf *fh) +{ + return region_sz(&fh->rdev.region); +} + +/* The cbfs_props struct describes the properties associated with a CBFS. */ +struct cbfs_props { + /* Each file is aligned . */ + size_t align; + /* CBFS starts at the following offset within the boot region. */ + size_t offset; + /* CBFS size. */ + size_t size; +}; + +/* Returns < 0 on error otherwise props are filled out accordingly. */ +int cbfs_boot_region_properties(struct cbfs_props *props);
#endif diff --git a/src/include/cbfs_core.h b/src/include/cbfs_core.h deleted file mode 100644 index c71cc26..0000000 --- a/src/include/cbfs_core.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2008 Jordan Crouse jordan@cosmicpenguin.net - * Copyright (C) 2012 Google, Inc. - * Copyright (C) 2013 The Chromium OS Authors. All rights reserved. - * - * This file is dual-licensed. You can choose between: - * - The GNU GPL, version 2, as published by the Free Software Foundation - * - The revised BSD license (without advertising clause) - * - * --------------------------------------------------------------------------- - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA - * --------------------------------------------------------------------------- - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * --------------------------------------------------------------------------- - */ - -#ifndef _CBFS_CORE_H_ -#define _CBFS_CORE_H_ - -#include <endian.h> -#include <stddef.h> -#include <stdint.h> -#include <cbfs_serialized.h> - -#define CBFS_HEADER_INVALID_ADDRESS ((void*)(0xffffffff)) - -#define CBFS_NAME(_c) (((char *) (_c)) + sizeof(struct cbfs_file)) -#define CBFS_SUBHEADER(_p) ( (void *) ((((uint8_t *) (_p)) + ntohl((_p)->offset))) ) - -/* - * ROMCC does not understand uint64_t, so we hide future definitions as they are - * unlikely to be ever needed from ROMCC - */ -#ifndef __ROMCC__ - -#define CBFS_MEDIA_INVALID_MAP_ADDRESS ((void*)(0xffffffff)) -#define CBFS_DEFAULT_MEDIA ((void*)(0x0)) - -/* Media for CBFS to load files. */ -struct cbfs_media { - - /* implementation dependent context, to hold resource references */ - void *context; - - /* opens media and returns 0 on success, -1 on failure */ - int (*open)(struct cbfs_media *media); - - /* returns number of bytes read from media into dest, starting from - * offset for count of bytes */ - size_t (*read)(struct cbfs_media *media, void *dest, size_t offset, - size_t count); - - /* returns a pointer to memory with count of bytes from media source - * starting from offset, or CBFS_MEDIA_INVALID_MAP_ADDRESS on failure. - * Note: mapped data can't be free unless unmap is called, even if you - * do close first. */ - void * (*map)(struct cbfs_media *media, size_t offset, size_t count); - - /* returns NULL and releases the memory by address, which was allocated - * by map */ - void * (*unmap)(struct cbfs_media *media, const void *address); - - /* closes media and returns 0 on success, -1 on failure. */ - int (*close)(struct cbfs_media *media); -}; - -/* - * Locate file by name and fill in cbfs_file in host byte order. Returns - * < 0 on error, else the offset of the file data. - */ -ssize_t cbfs_locate_file(struct cbfs_media *media, struct cbfs_file *file, - const char *name); - -/* Read count bytes at offset into dest. Return number of bytes read. */ -size_t cbfs_read(struct cbfs_media *media, void *dest, size_t offset, - size_t count); - -/* returns pointer to a file entry inside CBFS or NULL */ -struct cbfs_file *cbfs_get_file(struct cbfs_media *media, const char *name); - -/* returns pointer to file content inside CBFS after if type is correct */ -void *cbfs_get_file_content(struct cbfs_media *media, const char *name, - int type, size_t *sz); - -/* returns decompressed size on success, 0 on failure */ -int cbfs_decompress(int algo, void *src, void *dst, int len); - -/* returns a pointer to CBFS master header, or CBFS_HEADER_INVALID_ADDRESS - * on failure */ -const struct cbfs_header *cbfs_get_header(struct cbfs_media *media); - -#endif /* __ROMCC__ */ - -#endif diff --git a/src/include/cbfs_declarations.h b/src/include/cbfs_declarations.h deleted file mode 100644 index 2ac9c08..0000000 --- a/src/include/cbfs_declarations.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2008 Jordan Crouse jordan@cosmicpenguin.net - * Copyright (C) 2013-2015 Google, Inc. - * - * This file is dual-licensed. You can choose between: - * - The GNU GPL, version 2, as published by the Free Software Foundation - * - The revised BSD license (without advertising clause) - * - * --------------------------------------------------------------------------- - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA - * --------------------------------------------------------------------------- - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * --------------------------------------------------------------------------- - */ - -#ifndef _CBFS_DECLARATIONS_H_ -#define _CBFS_DECLARATIONS_H_ - -#include <cbfs_core.h> - -int init_backing_media(struct cbfs_media **media, struct cbfs_media *backing); -void *cbfs_load_optionrom(struct cbfs_media *media, uint16_t vendor, - uint16_t device, void * dest); -void *cbfs_load_stage(struct cbfs_media *media, const char *name); -void *cbfs_load_stage_by_offset(struct cbfs_media *media, ssize_t offset); -/* Load a stage from a prog structure. Returns < 0 on error. 0 on success. */ -struct prog; -int cbfs_load_prog_stage(struct cbfs_media *media, struct prog *prog); - -/* Simple buffer for streaming media. */ -struct cbfs_simple_buffer { - char *buffer; - size_t allocated; - size_t size; - size_t last_allocate; -}; - -void *cbfs_simple_buffer_map(struct cbfs_simple_buffer *buffer, - struct cbfs_media *media, - size_t offset, size_t count); - -void *cbfs_simple_buffer_unmap(struct cbfs_simple_buffer *buffer, - const void *address); - -/* Defined in individual arch / board implementation. */ -int init_default_cbfs_media(struct cbfs_media *media); - -#endif diff --git a/src/include/rmodule.h b/src/include/rmodule.h index 242ed91..5dc795c 100644 --- a/src/include/rmodule.h +++ b/src/include/rmodule.h @@ -54,7 +54,7 @@ int rmodule_calc_region(unsigned int region_alignment, size_t rmodule_size, /* Support for loading rmodule stages. This API is only available when * using dynamic cbmem because it uses the dynamic cbmem API to obtain * the backing store region for the stage. */ -struct cbfs_stage; +struct cbfsf; struct prog;
struct rmod_stage_load { @@ -63,7 +63,7 @@ struct rmod_stage_load { };
/* Both of the following functions return 0 on success, -1 on error. */ -int rmodule_stage_load(struct rmod_stage_load *rsl, struct cbfs_stage *stage); +int rmodule_stage_load(struct rmod_stage_load *rsl, struct cbfsf *fh); int rmodule_stage_load_from_cbfs(struct rmod_stage_load *rsl);
struct rmodule { diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc index 0bc914b..bbab500 100644 --- a/src/lib/Makefile.inc +++ b/src/lib/Makefile.inc @@ -19,7 +19,8 @@ subdirs-y += loaders
bootblock-y += prog_ops.c -bootblock-y += cbfs_gpl.c cbfs_core.c +bootblock-y += cbfs.c +bootblock-y += cbfs_boot_props.c bootblock-$(CONFIG_COMMON_CBFS_SPI_WRAPPER) += cbfs_spi.c
bootblock-$(CONFIG_CONSOLE_CBMEM) += cbmem_console.c @@ -30,7 +31,8 @@ bootblock-y += region.c
verstage-y += prog_ops.c verstage-y += delay.c -verstage-y += cbfs_gpl.c +verstage-y += cbfs.c +verstage-y += cbfs_boot_props.c verstage-y += memcmp.c verstage-y += region.c verstage-$(CONFIG_CONSOLE_CBMEM) += cbmem_console.c @@ -46,7 +48,8 @@ $(foreach arch,$(ARCH_SUPPORTED),\ $(eval rmodules_$(arch)-y += memcmp.c))
romstage-$(CONFIG_I2C_TPM) += delay.c -romstage-y += cbfs_gpl.c cbfs_core.c +romstage-y += cbfs.c +romstage-y += cbfs_boot_props.c romstage-$(CONFIG_COMMON_CBFS_SPI_WRAPPER) += cbfs_spi.c romstage-$(CONFIG_COMPRESS_RAMSTAGE) += lzma.c lzmadecode.c romstage-$(CONFIG_PRIMITIVE_MEMTEST) += primitive_memtest.c @@ -76,7 +79,8 @@ smm-$(CONFIG_SMM_TSEG) += malloc.c ramstage-y += delay.c ramstage-y += fallback_boot.c ramstage-y += compute_ip_checksum.c -ramstage-y += cbfs_gpl.c cbfs_core.c +ramstage-y += cbfs.c +ramstage-y += cbfs_boot_props.c ramstage-$(CONFIG_COMMON_CBFS_SPI_WRAPPER) += cbfs_spi.c ramstage-y += lzma.c lzmadecode.c ramstage-y += stack.c @@ -122,7 +126,10 @@ ramstage-y += mem_pool.c romstage-y += region.c ramstage-y += region.c
-smm-y += cbfs_gpl.c cbfs_core.c memcmp.c +smm-y += cbfs.c memcmp.c +smm-y += region.c +smm-y += region.c +smm-y += mem_pool.c smm-$(CONFIG_COMPILER_GCC) += gcc.c
bootblock-y += version.c diff --git a/src/lib/cbfs.c b/src/lib/cbfs.c new file mode 100644 index 0000000..61a94c7 --- /dev/null +++ b/src/lib/cbfs.c @@ -0,0 +1,272 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2011 secunet Security Networks AG + * Copyright 2015 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <assert.h> +#include <string.h> +#include <stdlib.h> +#include <boot_device.h> +#include <cbfs.h> +#include <endian.h> +#include <lib.h> +#include <rules.h> + +#define ERROR(x...) printk(BIOS_ERR, "CBFS: " x) +#define LOG(x...) printk(BIOS_INFO, "CBFS: " x) +#if IS_ENABLED(CONFIG_DEBUG_CBFS) +#define DEBUG(x...) printk(BIOS_SPEW, "CBFS: " x) +#else +#define DEBUG(x...) +#endif + +void __attribute__((weak)) boot_device_init(void) +{ + /* Default empty implementation to reduce scattered empty functions. */ +} + +int cbfs_boot_locate(struct cbfsf *fh, const char *name, uint32_t *type) +{ + struct cbfsd cbfs; + struct region_device rdev; + const struct region_device *boot_dev; + struct cbfs_props props; + + boot_device_init(); + + 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; + + cbfs.rdev = &rdev; + cbfs.align = props.align; + + return cbfs_locate(&cbfs, fh, name, type); +} + +void *cbfs_boot_map_with_leak(const char *name, uint32_t type, size_t *size) +{ + struct cbfsf fh; + size_t fsize; + + if (cbfs_boot_locate(&fh, name, &type)) + return NULL; + + fsize = cbfs_file_size(&fh); + + if (size != NULL) + *size = fsize; + + return cbfs_file_mmap(&fh, 0, fsize); +} + +void *cbfs_file_mmap(const struct cbfsf *fh, size_t offset, size_t size) +{ + return rdev_mmap(&fh->rdev, offset, size); +} + +int cbfs_file_munmap(const struct cbfsf *fh, void *mapping) +{ + return rdev_munmap(&fh->rdev, mapping); +} + +ssize_t cbfs_file_readat(const struct cbfsf *fh, void *b, size_t offset, + size_t size) +{ + return rdev_readat(&fh->rdev, b, offset, size); +} + +int cbfs_locate(const struct cbfsd *cbfs, struct cbfsf *fh, const char *name, + uint32_t *type) +{ + size_t offset; + const struct region_device *rd; + size_t align; + + offset = 0; + rd = cbfs->rdev; + align = cbfs->align; + + LOG("Locating '%s'\n", name); + + /* Try to scan the entire cbfs region looking for file name. */ + while (1) { + struct cbfs_file file; + const size_t fsz = sizeof(file); + char *fname; + int name_match; + size_t datasz; + + LOG("Checking offset %zx\n", offset); + + /* Can't read file. Nothing else to do but bail out. */ + if (rdev_readat(rd, &file, offset, fsz) != fsz) + break; + + if (memcmp(file.magic, CBFS_FILE_MAGIC, sizeof(file.magic))) { + offset++; + offset = ALIGN_UP(offset, align); + continue; + } + + file.len = ntohl(file.len); + file.type = ntohl(file.type); + file.offset = ntohl(file.offset); + + /* See if names match. */ + fname = rdev_mmap(rd, offset + fsz, file.offset - fsz); + + if (fname == NULL) + break; + + name_match = !strcmp(fname, name); + rdev_munmap(rd, fname); + + if (!name_match) { + DEBUG(" Unmatched '%s' at %zx\n", fname, offset); + offset += file.offset + file.len; + offset = ALIGN_UP(offset, align); + continue; + } + + if (type != NULL && *type != file.type) { + DEBUG(" Unmatched type %x at %zx\n", file.type, offset); + offset += file.offset + file.len; + offset = ALIGN_UP(offset, align); + continue; + } + + LOG("Found @ offset %zx size %x\n", offset, file.len); + /* File and type match. Create a chained region_device to + * represent the cbfs file. */ + offset += file.offset; + datasz = file.len; + if (rdev_chain(&fh->rdev, rd, offset, datasz)) + break; + + /* Success. */ + return 0; + } + + return -1; +} + +#if !ENV_SMM +static size_t inflate(void *src, void *dst) +{ +#if defined(__BOOT_BLOCK__) + return 0; +#endif +#if (defined(__PRE_RAM__) && !IS_ENABLED(CONFIG_COMPRESS_RAMSTAGE)) + return 0; +#endif + return ulzma(src, dst); +} + +static inline int tohex4(unsigned int c) +{ + return (c <= 9) ? (c + '0') : (c - 10 + 'a'); +} + +static void tohex16(unsigned int val, char* dest) +{ + dest[0] = tohex4(val>>12); + dest[1] = tohex4((val>>8) & 0xf); + dest[2] = tohex4((val>>4) & 0xf); + dest[3] = tohex4(val & 0xf); +} + +void *cbfs_boot_map_optionrom(uint16_t vendor, uint16_t device) +{ + char name[17] = "pciXXXX,XXXX.rom"; + + tohex16(vendor, name+3); + tohex16(device, name+8); + + return cbfs_boot_map_with_leak(name, CBFS_TYPE_OPTIONROM, NULL); +} + +int cbfs_boot_load_stage(struct prog *stage) +{ + struct cbfsf fh; + uint32_t type = CBFS_TYPE_STAGE; + + if (cbfs_boot_locate(&fh, stage->name, &type)) + return -1; + + return cbfs_file_stage_load(&fh, stage); +} + +int cbfs_file_stage_load(const struct cbfsf *fh, struct prog *pstage) +{ + struct cbfs_stage stage; + uint8_t *load; + void *entry; + size_t fsize; + size_t foffset; + + if (cbfs_file_readat(fh, &stage, 0, sizeof(stage)) != sizeof(stage)) + return 0; + + fsize = cbfs_file_size(fh); + fsize -= sizeof(stage); + foffset = 0; + foffset += sizeof(stage); + + assert(fsize == stage.len); + + /* Note: cbfs_stage fields are currently in the endianness of the + * running processor. */ + load = (void *)(uintptr_t)stage.load; + entry = (void *)(uintptr_t)stage.entry; + + if (stage.compression == CBFS_COMPRESS_NONE) { + if (cbfs_file_readat(fh, load, foffset, fsize) != fsize) + return -1; + } else if (stage.compression == CBFS_COMPRESS_LZMA) { + void *map = cbfs_file_mmap(fh, foffset, fsize); + + if (map == NULL) + return -1; + + fsize = inflate(map, load); + + cbfs_file_munmap(fh, map); + + if (!fsize) + return -1; + } else + return -1; + + /* Clear area not covered by file. */ + memset(&load[fsize], 0, stage.memlen - fsize); + + prog_set_area(pstage, load, stage.memlen); + prog_set_entry(pstage, entry, NULL); + + return 0; +} +#endif /* !ENV_SMM */ diff --git a/src/lib/cbfs_boot_props.c b/src/lib/cbfs_boot_props.c new file mode 100644 index 0000000..dfffed3 --- /dev/null +++ b/src/lib/cbfs_boot_props.c @@ -0,0 +1,57 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2015 Google Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <boot_device.h> +#include <cbfs.h> +#include <console/console.h> +#include <endian.h> +#include <region.h> + +/* This function is marked as weak to allow a particular platform to + * override the logic. This implementation should work for most devices. */ +int __attribute__((weak)) cbfs_boot_region_properties(struct cbfs_props *props) +{ + struct cbfs_header header; + const struct region_device *bdev; + + bdev = boot_device_ro(); + + if (bdev == NULL) + return -1; + + rdev_readat(bdev, &header, CONFIG_CBFS_HEADER_ROM_OFFSET, + sizeof(header)); + + header.magic = ntohl(header.magic); + header.romsize = ntohl(header.romsize); + header.align = ntohl(header.align); + header.offset = ntohl(header.offset); + + if (header.magic != CBFS_HEADER_MAGIC) + return -1; + + props->align = header.align; + props->offset = header.offset; + props->size = header.romsize; + props->size -= props->offset; + + printk(BIOS_SPEW, "CBFS @ %zx size %zx\n", props->offset, props->size); + + return 0; +} diff --git a/src/lib/cbfs_core.c b/src/lib/cbfs_core.c deleted file mode 100644 index acd434f..0000000 --- a/src/lib/cbfs_core.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2011 secunet Security Networks AG - * Copyright (C) 2013 The Chromium OS Authors. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* The CBFS core requires a couple of #defines or functions to adapt it to the - * target environment: - * - * CBFS_CORE_WITH_LZMA (must be #define) - * if defined, ulzma() must exist for decompression of data streams - * - * CBFS_HEADER_ROM_ADDRESS - * ROM address (offset) of CBFS header. Underlying CBFS media may interpret - * it in other way so we call this "address". - * - * ERROR(x...) - * print an error message x (in printf format) - * - * LOG(x...) - * print a message x (in printf format) - * - * DEBUG(x...) - * print a debug message x (in printf format) - * - */ - -#include <cbfs.h> -#include <string.h> - -#include "cbfs_core.h" - -/* returns a pointer to CBFS master header, or CBFS_HEADER_INVALID_ADDRESS - * on failure */ -const struct cbfs_header *cbfs_get_header(struct cbfs_media *media) -{ - const struct cbfs_header *header; - struct cbfs_media default_media; - - if (media == CBFS_DEFAULT_MEDIA) { - media = &default_media; - if (init_default_cbfs_media(media) != 0) { - ERROR("Failed to initialize default media.\n"); - return CBFS_HEADER_INVALID_ADDRESS; - } - } - - media->open(media); - DEBUG("CBFS_HEADER_ROM_ADDRESS: 0x%x/0x%x\n", CBFS_HEADER_ROM_ADDRESS, - CONFIG_ROM_SIZE); - header = media->map(media, CBFS_HEADER_ROM_ADDRESS, sizeof(*header)); - media->close(media); - - if (header == CBFS_MEDIA_INVALID_MAP_ADDRESS) { - ERROR("Failed to load CBFS header from 0x%x\n", - CBFS_HEADER_ROM_ADDRESS); - return CBFS_HEADER_INVALID_ADDRESS; - } - - if (CBFS_HEADER_MAGIC != ntohl(header->magic)) { - ERROR("Could not find valid CBFS master header at %x: " - "%x vs %x.\n", CBFS_HEADER_ROM_ADDRESS, CBFS_HEADER_MAGIC, - ntohl(header->magic)); - if (header->magic == 0xffffffff) { - ERROR("Maybe ROM is not mapped properly?\n"); - } - return CBFS_HEADER_INVALID_ADDRESS; - } - return header; -} - - -int init_backing_media(struct cbfs_media **media, struct cbfs_media *backing) -{ - if (*media == CBFS_DEFAULT_MEDIA) { - *media = backing; - if (init_default_cbfs_media(*media) != 0) { - ERROR("Failed to initialize default media.\n"); - return -1; - } - } - return 0; -} - -/* public API starts here*/ -ssize_t cbfs_locate_file(struct cbfs_media *media, struct cbfs_file *file, - const char *name) -{ - const char *file_name; - uint32_t offset, align, romsize, name_len; - const struct cbfs_header *header; - struct cbfs_media default_media; - - if (init_backing_media(&media, &default_media)) - return -1; - - if (CBFS_HEADER_INVALID_ADDRESS == (header = cbfs_get_header(media))) - return -1; - - // Logical offset (for source media) of first file. - offset = ntohl(header->offset); - align = ntohl(header->align); - romsize = ntohl(header->romsize); - - // TODO Add a "size" in CBFS header for a platform independent way to - // determine the end of CBFS data. -#if defined(CONFIG_ARCH_X86) && CONFIG_ARCH_X86 - // resolve actual length of ROM used for CBFS components - // the bootblock size was not taken into account - romsize -= ntohl(header->bootblocksize); - - // fine tune the length to handle alignment positioning. - // using (bootblock size) % align, to derive the - // number of bytes the bootblock is off from the alignment size. - if ((ntohl(header->bootblocksize) % align)) - romsize -= (align - (ntohl(header->bootblocksize) % align)); - else - romsize -= 1; -#endif - - DEBUG("CBFS location: 0x%x~0x%x, align: %d\n", offset, romsize, align); - DEBUG("Looking for '%s' starting from 0x%x.\n", name, offset); - - media->open(media); - while (offset < romsize && - media->read(media, file, offset, sizeof(*file)) == sizeof(*file)) { - if (memcmp(CBFS_FILE_MAGIC, file->magic, - sizeof(file->magic)) != 0) { - uint32_t new_align = align; - if (offset % align) - new_align += align - (offset % align); - LOG("WARNING: No file header found at 0x%x - " - "try next aligned address: 0x%x.\n", offset, - offset + new_align); - offset += new_align; - continue; - } - - file->len = ntohl(file->len); - file->type= ntohl(file->type); - file->offset = ntohl(file->offset); - - name_len = file->offset - sizeof(*file); - DEBUG(" - load entry 0x%x file name (%d bytes)...\n", offset, - name_len); - - // load file name (arbitrary length). - file_name = (const char *)media->map( - media, offset + sizeof(*file), name_len); - if (file_name == CBFS_MEDIA_INVALID_MAP_ADDRESS) { - ERROR("ERROR: Failed to get filename: 0x%x.\n", offset); - } else if (strcmp(file_name, name) == 0) { - DEBUG("Found file (offset=0x%x, len=%d).\n", - offset + file->offset, file->len); - media->unmap(media, file_name); - return offset + file->offset; - } else { - DEBUG(" (unmatched file @0x%x: %s)\n", offset, - file_name); - media->unmap(media, file_name); - } - - // Move to next file. - offset += file->len + file->offset; - if (offset % align) - offset += align - (offset % align); - } - media->close(media); - LOG("WARNING: '%s' not found.\n", name); - return -1; -} - -size_t cbfs_read(struct cbfs_media *media, void *dest, size_t offset, - size_t count) -{ - struct cbfs_media default_media; - size_t nread; - - if (init_backing_media(&media, &default_media)) - return 0; - - media->open(media); - nread = media->read(media, dest, offset, count); - media->close(media); - - return nread; -} - -struct cbfs_file *cbfs_get_file(struct cbfs_media *media, const char *name) -{ - struct cbfs_media default_media; - struct cbfs_file file, *file_ptr; - ssize_t offset; - - if (init_backing_media(&media, &default_media)) - return NULL; - - offset = cbfs_locate_file(media, &file, name); - if (offset < 0) - return NULL; - - /* Map both the metadata and the file contents. */ - media->open(media); - offset -= file.offset; - file_ptr = media->map(media, offset, file.offset + file.len); - media->close(media); - - if (file_ptr == CBFS_MEDIA_INVALID_MAP_ADDRESS) { - ERROR("ERROR: Mapping %s failed.\n", name); - return NULL; - } - - return file_ptr; -} - -void *cbfs_get_file_content(struct cbfs_media *media, const char *name, - int type, size_t *sz) -{ - struct cbfs_file *file = cbfs_get_file(media, name); - - if (sz) - *sz = 0; - - if (file == NULL) { - ERROR("Could not find file '%s'.\n", name); - return NULL; - } - - if (ntohl(file->type) != type) { - ERROR("File '%s' is of type %x, but we requested %x.\n", name, - ntohl(file->type), type); - return NULL; - } - - if (sz) - *sz = ntohl(file->len); - - return (void *)CBFS_SUBHEADER(file); -} - -int cbfs_decompress(int algo, void *src, void *dst, int len) -{ - switch (algo) { - case CBFS_COMPRESS_NONE: - /* Reads need to be aligned at 4 bytes to avoid - poor flash performance. */ - while (len && ((uintptr_t)src & 3)) { - *(u8*)dst++ = *(u8*)src++; - len--; - } - memmove(dst, src, len); - return len; -#ifdef CBFS_CORE_WITH_LZMA - case CBFS_COMPRESS_LZMA: - return ulzma(src, dst); -#endif - default: - ERROR("tried to decompress %d bytes with algorithm #%x," - "but that algorithm id is unsupported.\n", len, - algo); - return 0; - } -} diff --git a/src/lib/cbfs_core.h b/src/lib/cbfs_core.h deleted file mode 100644 index c1eecd2..0000000 --- a/src/lib/cbfs_core.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef __LIB_CBFS_CORE -#define __LIB_CBFS_CORE - -#include <cbfs.h> -#include <string.h> - -#ifdef LIBPAYLOAD -# include <libpayload-config.h> -# ifdef CONFIG_LZMA -# include <lzma.h> -# define CBFS_CORE_WITH_LZMA -# endif -# define CBFS_MINI_BUILD -#elif defined(__SMM__) -# define CBFS_MINI_BUILD -#elif defined(__BOOT_BLOCK__) - /* No LZMA in boot block. */ -#elif defined(__PRE_RAM__) && !CONFIG_COMPRESS_RAMSTAGE - /* No LZMA in romstage if ramstage is not compressed. */ -#else -# define CBFS_CORE_WITH_LZMA -# include <lib.h> -#endif - -#include <cbfs.h> -#include <string.h> -#include <cbmem.h> - -#ifdef LIBPAYLOAD -# include <stdio.h> -# define DEBUG(x...) -# define LOG(x...) printf(x) -# define ERROR(x...) printf(x) -#else -# include <console/console.h> -# define ERROR(x...) printk(BIOS_ERR, "CBFS: " x) -# define LOG(x...) printk(BIOS_INFO, "CBFS: " x) -# if CONFIG_DEBUG_CBFS -# define DEBUG(x...) printk(BIOS_SPEW, "CBFS: " x) -# else -# define DEBUG(x...) -# endif -#endif - -#if defined(CONFIG_CBFS_HEADER_ROM_OFFSET) && (CONFIG_CBFS_HEADER_ROM_OFFSET) -# define CBFS_HEADER_ROM_ADDRESS (CONFIG_CBFS_HEADER_ROM_OFFSET) -#else -// Indirect address: only works on 32bit top-aligned systems. -# define CBFS_HEADER_ROM_ADDRESS (*(uint32_t *)0xfffffffc) -#endif - -#endif /* __LIB_CBFS_CORE */ diff --git a/src/lib/cbfs_gpl.c b/src/lib/cbfs_gpl.c deleted file mode 100644 index 0fddb53..0000000 --- a/src/lib/cbfs_gpl.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2008, Jordan Crouse jordan@cosmicpenguin.net - * Copyright (C) 2013 The Chromium OS Authors. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA - */ - - -#include <program_loading.h> -#include "cbfs_core.h" - -#ifndef __SMM__ -static inline int tohex4(unsigned int c) -{ - return (c <= 9) ? (c + '0') : (c - 10 + 'a'); -} - -static void tohex16(unsigned int val, char* dest) -{ - dest[0] = tohex4(val>>12); - dest[1] = tohex4((val>>8) & 0xf); - dest[2] = tohex4((val>>4) & 0xf); - dest[3] = tohex4(val & 0xf); -} - -void *cbfs_load_optionrom(struct cbfs_media *media, uint16_t vendor, - uint16_t device, void *dest) -{ - char name[17] = "pciXXXX,XXXX.rom"; - struct cbfs_optionrom *orom; - uint8_t *src; - - tohex16(vendor, name+3); - tohex16(device, name+8); - - orom = (struct cbfs_optionrom *) - cbfs_get_file_content(media, name, CBFS_TYPE_OPTIONROM, NULL); - - if (orom == NULL) - return NULL; - - /* They might have specified a dest address. If so, we can decompress. - * If not, there's not much hope of decompressing or relocating the rom. - * in the common case, the expansion rom is uncompressed, we - * pass 0 in for the dest, and all we have to do is find the rom and - * return a pointer to it. - */ - - /* BUG: the cbfstool is (not yet) including a cbfs_optionrom header */ - src = (uint8_t *)orom; // + sizeof(struct cbfs_optionrom); - - if (! dest) - return src; - - if (!cbfs_decompress(ntohl(orom->compression), - src, - dest, - ntohl(orom->len))) - return NULL; - - return dest; -} - -static int cbfs_load_prog_stage_by_offset(struct cbfs_media *media, - struct prog *prog, ssize_t offset) -{ - struct cbfs_stage stage; - struct cbfs_media backing_store; - - if (init_backing_media(&media, &backing_store)) - return -1; - - if (cbfs_read(media, &stage, offset, sizeof(stage)) != sizeof(stage)) { - ERROR("ERROR: failed to read stage header\n"); - return -1; - } - - LOG("loading stage @ 0x%llx (%d bytes), entry @ 0x%llx\n", - stage.load, stage.memlen, stage.entry); - - /* Stages rely the below clearing so that the bss is initialized. */ - memset((void *)(uintptr_t)stage.load, 0, stage.memlen); - - if (stage.compression == CBFS_COMPRESS_NONE) { - if (cbfs_read(media, (void *)(uintptr_t)stage.load, - offset + sizeof(stage), stage.len) != stage.len) { - ERROR("ERROR: Reading stage failed.\n"); - return -1; - } - } else { - void *data = media->map(media, offset + sizeof(stage), - stage.len); - if (data == CBFS_MEDIA_INVALID_MAP_ADDRESS) { - ERROR("ERROR: Mapping stage failed.\n"); - return -1; - } - if (!cbfs_decompress(stage.compression, data, - (void *)(uintptr_t)stage.load, stage.len)) - return -1; - media->unmap(media, data); - } - - arch_segment_loaded(stage.load, stage.memlen, SEG_FINAL); - DEBUG("stage loaded\n"); - - prog_set_area(prog, (void *)(uintptr_t)stage.load, stage.memlen); - prog_set_entry(prog, (void *)(uintptr_t)stage.entry, NULL); - - return 0; -} - -int cbfs_load_prog_stage(struct cbfs_media *media, struct prog *prog) -{ - struct cbfs_file file; - ssize_t offset; - struct cbfs_media backing_store; - - if (init_backing_media(&media, &backing_store)) - return -1; - - offset = cbfs_locate_file(media, &file, prog->name); - if (offset < 0 || file.type != CBFS_TYPE_STAGE) - return -1; - - if (cbfs_load_prog_stage_by_offset(media, prog, offset) < 0) - return -1; - - return 0; -} - -void *cbfs_load_stage_by_offset(struct cbfs_media *media, ssize_t offset) -{ - struct prog prog = { - .name = NULL, - }; - - if (cbfs_load_prog_stage_by_offset(media, &prog, offset) < 0) - return (void *)-1; - - return prog_entry(&prog); -} - -void *cbfs_load_stage(struct cbfs_media *media, const char *name) -{ - struct prog prog = { - .name = name, - }; - - if (cbfs_load_prog_stage(media, &prog) < 0) - return (void *)-1; - - return prog_entry(&prog); -} - -/* Simple buffer */ - -void *cbfs_simple_buffer_map(struct cbfs_simple_buffer *buffer, - struct cbfs_media *media, - size_t offset, size_t count) { - void *address = buffer->buffer + buffer->allocated; - DEBUG("simple_buffer_map(offset=%zd, count=%zd): " - "allocated=%zd, size=%zd, last_allocate=%zd\n", - offset, count, buffer->allocated, buffer->size, - buffer->last_allocate); - if (buffer->allocated + count >= buffer->size) - return CBFS_MEDIA_INVALID_MAP_ADDRESS; - if (media->read(media, address, offset, count) != count) { - ERROR("simple_buffer: fail to read %zd bytes from 0x%zx\n", - count, offset); - return CBFS_MEDIA_INVALID_MAP_ADDRESS; - } - buffer->allocated += count; - buffer->last_allocate = count; - return address; -} - -void *cbfs_simple_buffer_unmap(struct cbfs_simple_buffer *buffer, - const void *address) { - // TODO Add simple buffer management so we can free more than last - // allocated one. - DEBUG("simple_buffer_unmap(address=0x%p): " - "allocated=%zd, size=%zd, last_allocate=%zd\n", - address, buffer->allocated, buffer->size, - buffer->last_allocate); - if ((buffer->buffer + buffer->allocated - buffer->last_allocate) == - address) { - buffer->allocated -= buffer->last_allocate; - buffer->last_allocate = 0; - } - return NULL; -} - -#endif diff --git a/src/lib/cbfs_spi.c b/src/lib/cbfs_spi.c index 2b3728e..915a28e 100644 --- a/src/lib/cbfs_spi.c +++ b/src/lib/cbfs_spi.c @@ -23,77 +23,48 @@ * SPI. */
+#include <boot_device.h> #include <cbfs.h> +#include <region.h> #include <spi_flash.h>
-/* SPI flash as CBFS media. */ -struct cbfs_spi_context { - struct spi_flash *spi_flash_info; - struct cbfs_simple_buffer buffer; -}; - -static struct cbfs_spi_context spi_context; - -static int cbfs_media_open(struct cbfs_media *media) -{ - return 0; -} +static struct spi_flash *spi_flash_info;
-static int cbfs_media_close(struct cbfs_media *media) +static ssize_t spi_readat(const struct region_device *rd, void *b, + size_t offset, size_t size) { - return 0; + if (spi_flash_info->read(spi_flash_info, offset, size, b)) + return -1; + return size; }
-static size_t cbfs_media_read(struct cbfs_media *media, - void *dest, size_t offset, - size_t count) -{ - struct cbfs_spi_context *context = media->context; +static const struct region_device_ops spi_ops = { + .mmap = mmap_helper_rdev_mmap, + .munmap = mmap_helper_rdev_munmap, + .readat = spi_readat, +};
- return context->spi_flash_info->read - (context->spi_flash_info, offset, count, dest) ? 0 : count; -} +static struct mmap_helper_region_device mdev = + MMAP_HELPER_REGION_INIT(&spi_ops, 0, CONFIG_ROM_SIZE, + (void *)(uintptr_t)CONFIG_CBFS_CACHE_ADDRESS, + CONFIG_CBFS_CACHE_SIZE);
-static void *cbfs_media_map(struct cbfs_media *media, - size_t offset, size_t count) +void boot_device_init(void) { - struct cbfs_spi_context *context = media->context; + int bus = CONFIG_BOOT_MEDIA_SPI_BUS; + int cs = 0;
- return cbfs_simple_buffer_map(&context->buffer, media, offset, count); -} + if (spi_flash_info == NULL) + return;
-static void *cbfs_media_unmap(struct cbfs_media *media, - const void *address) -{ - struct cbfs_spi_context *context = media->context; - - return cbfs_simple_buffer_unmap(&context->buffer, address); + spi_flash_info = spi_flash_probe(bus, cs); }
-static int init_cbfs_media_context(void) -{ - if (!spi_context.spi_flash_info) { - - spi_context.spi_flash_info = spi_flash_probe - (CONFIG_BOOT_MEDIA_SPI_BUS, 0); - - if (!spi_context.spi_flash_info) - return -1; - - spi_context.buffer.buffer = (void *)CONFIG_CBFS_CACHE_ADDRESS; - spi_context.buffer.size = CONFIG_CBFS_CACHE_SIZE; - } - return 0; - -} -int init_default_cbfs_media(struct cbfs_media *media) +/* Return the CBFS boot device. */ +const struct region_device *boot_device_ro(void) { - media->context = &spi_context; - media->open = cbfs_media_open; - media->close = cbfs_media_close; - media->read = cbfs_media_read; - media->map = cbfs_media_map; - media->unmap = cbfs_media_unmap; + if (spi_flash_info == NULL) + return NULL;
- return init_cbfs_media_context(); + return &mdev.rdev; } diff --git a/src/lib/coreboot_table.c b/src/lib/coreboot_table.c index 4126e82..9e65d39 100644 --- a/src/lib/coreboot_table.c +++ b/src/lib/coreboot_table.c @@ -380,8 +380,8 @@ unsigned long write_coreboot_table(
#if CONFIG_USE_OPTION_TABLE { - struct cmos_option_table *option_table = cbfs_get_file_content( - CBFS_DEFAULT_MEDIA, "cmos_layout.bin", + struct cmos_option_table *option_table = + cbfs_boot_map_with_leak("cmos_layout.bin", CBFS_COMPONENT_CMOS_LAYOUT, NULL); if (option_table) { struct lb_record *rec_dest = lb_new_record(head); diff --git a/src/lib/loaders/cbfs_payload_loader.c b/src/lib/loaders/cbfs_payload_loader.c index 3928613..fffb558 100644 --- a/src/lib/loaders/cbfs_payload_loader.c +++ b/src/lib/loaders/cbfs_payload_loader.c @@ -24,10 +24,9 @@ static int cbfs_locate_payload(struct prog *payload) { void *buffer; size_t size; - const int type = CBFS_TYPE_PAYLOAD; + const uint32_t type = CBFS_TYPE_PAYLOAD;
- buffer = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, payload->name, - type, &size); + buffer = cbfs_boot_map_with_leak(payload->name, type, &size);
if (buffer == NULL) return -1; diff --git a/src/lib/loaders/cbfs_ramstage_loader.c b/src/lib/loaders/cbfs_ramstage_loader.c index c460653..bbbf695 100644 --- a/src/lib/loaders/cbfs_ramstage_loader.c +++ b/src/lib/loaders/cbfs_ramstage_loader.c @@ -44,8 +44,7 @@ static int cbfs_load_ramstage(struct prog *ramstage)
static int cbfs_load_ramstage(struct prog *ramstage) { - return cbfs_load_prog_stage(CBFS_DEFAULT_MEDIA, ramstage); - + return cbfs_boot_load_stage(ramstage); }
#endif /* CONFIG_RELOCATABLE_RAMSTAGE */ diff --git a/src/lib/loaders/load_and_run_romstage.c b/src/lib/loaders/load_and_run_romstage.c index 8467e90..381bc02 100644 --- a/src/lib/loaders/load_and_run_romstage.c +++ b/src/lib/loaders/load_and_run_romstage.c @@ -32,7 +32,7 @@ void run_romstage(void) .type = PROG_ROMSTAGE, };
- if (cbfs_load_prog_stage(CBFS_DEFAULT_MEDIA, &romstage) < 0) { + if (cbfs_boot_load_stage(&romstage) < 0) { if (IS_ENABLED(CONFIG_BOOTBLOCK_CONSOLE)) die("Couldn't load romstage.\n"); halt(); diff --git a/src/lib/rmodule.c b/src/lib/rmodule.c index d7dc969..0534cd7 100644 --- a/src/lib/rmodule.c +++ b/src/lib/rmodule.c @@ -22,6 +22,7 @@ #include <stdint.h> #include <stdlib.h> #include <string.h> +#include <lib.h> #include <console/console.h> #include <program_loading.h> #include <rmodule.h> @@ -252,7 +253,7 @@ int rmodule_calc_region(unsigned int region_alignment, size_t rmodule_size, return region_alignment - sizeof(struct rmodule_header); }
-int rmodule_stage_load(struct rmod_stage_load *rsl, struct cbfs_stage *stage) +int rmodule_stage_load(struct rmod_stage_load *rsl, struct cbfsf *fh) { struct rmodule rmod_stage; size_t region_size; @@ -260,13 +261,18 @@ int rmodule_stage_load(struct rmod_stage_load *rsl, struct cbfs_stage *stage) int rmodule_offset; int load_offset; const struct cbmem_entry *cbmem_entry; + struct cbfs_stage stage; + void *rmod_loc;
- if (stage == NULL || rsl->prog == NULL || rsl->prog->name == NULL) + if (fh == NULL || rsl->prog == NULL || rsl->prog->name == NULL) + return -1; + + if (cbfs_file_readat(fh, &stage, 0, sizeof(stage)) != sizeof(stage)) return -1;
rmodule_offset = rmodule_calc_region(DYN_CBMEM_ALIGN_SIZE, - stage->memlen, ®ion_size, &load_offset); + stage.memlen, ®ion_size, &load_offset);
cbmem_entry = cbmem_entry_add(rsl->cbmem_id, region_size);
@@ -275,14 +281,32 @@ int rmodule_stage_load(struct rmod_stage_load *rsl, struct cbfs_stage *stage)
stage_region = cbmem_entry_start(cbmem_entry);
+ rmod_loc = &stage_region[rmodule_offset]; + printk(BIOS_INFO, "Decompressing stage %s @ 0x%p (%d bytes)\n", - rsl->prog->name, &stage_region[rmodule_offset], stage->memlen); + rsl->prog->name, rmod_loc, stage.memlen); + + if (stage.compression == CBFS_COMPRESS_NONE) { + if (cbfs_file_readat(fh, rmod_loc, sizeof(stage), stage.len) != + stage.len) + return -1; + } else if (stage.compression == CBFS_COMPRESS_LZMA) { + size_t fsize; + void *map = cbfs_file_mmap(fh, 0, stage.len);
- if (!cbfs_decompress(stage->compression, &stage[1], - &stage_region[rmodule_offset], stage->len)) + if (map == NULL) + return -1; + + fsize = ulzma(map, rmod_loc); + + cbfs_file_munmap(fh, map); + + if (!fsize) + return -1; + } else return -1;
- if (rmodule_parse(&stage_region[rmodule_offset], &rmod_stage)) + if (rmodule_parse(rmod_loc, &rmod_stage)) return -1;
if (rmodule_load(&stage_region[load_offset], &rmod_stage)) @@ -296,13 +320,11 @@ int rmodule_stage_load(struct rmod_stage_load *rsl, struct cbfs_stage *stage)
int rmodule_stage_load_from_cbfs(struct rmod_stage_load *rsl) { - struct cbfs_stage *stage; - - stage = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, - rsl->prog->name, CBFS_TYPE_STAGE, NULL); + struct cbfsf fh; + uint32_t type = CBFS_TYPE_STAGE;
- if (stage == NULL) + if (cbfs_boot_locate(&fh, rsl->prog->name, &type)) return -1;
- return rmodule_stage_load(rsl, stage); + return rmodule_stage_load(rsl, &fh); } diff --git a/src/mainboard/emulation/qemu-armv7/media.c b/src/mainboard/emulation/qemu-armv7/media.c index 1168881..0e86277 100644 --- a/src/mainboard/emulation/qemu-armv7/media.c +++ b/src/mainboard/emulation/qemu-armv7/media.c @@ -12,54 +12,14 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ -#include <cbfs.h> -#include <string.h> -#include <console/console.h> +#include <boot_device.h>
-/* Simple memory-mapped ROM emulation. */ +/* FIXME: No idea how big the internal SRAM actually is. */ +static const struct mem_region_device boot_dev = + MEM_REGION_DEV_INIT((void *)(uintptr_t)CONFIG_BOOTBLOCK_BASE, + CONFIG_ROM_SIZE);
-static int emu_rom_open(struct cbfs_media *media) +const struct region_device *boot_device_ro(void) { - return 0; -} - -static void *emu_rom_map(struct cbfs_media *media, size_t offset, size_t count) -{ - return (void*)(offset + CONFIG_BOOTBLOCK_BASE); -} - -static void *emu_rom_unmap(struct cbfs_media *media, const void *address) -{ - return NULL; -} - -static size_t emu_rom_read(struct cbfs_media *media, void *dest, size_t offset, - size_t count) -{ - void *ptr = emu_rom_map(media, offset, count); - memcpy(dest, ptr, count); - emu_rom_unmap(media, ptr); - return count; -} - -static int emu_rom_close(struct cbfs_media *media) -{ - return 0; -} - -int init_emu_rom_cbfs_media(struct cbfs_media *media); - -int init_emu_rom_cbfs_media(struct cbfs_media *media) -{ - media->open = emu_rom_open; - media->close = emu_rom_close; - media->map = emu_rom_map; - media->unmap = emu_rom_unmap; - media->read = emu_rom_read; - return 0; -} - -int init_default_cbfs_media(struct cbfs_media *media) -{ - return init_emu_rom_cbfs_media(media); + return &boot_dev.rdev; } diff --git a/src/mainboard/google/bolt/romstage.c b/src/mainboard/google/bolt/romstage.c index bead56f..e80aedf 100644 --- a/src/mainboard/google/bolt/romstage.c +++ b/src/mainboard/google/bolt/romstage.c @@ -78,8 +78,8 @@ static void copy_spd(struct pei_data *peid) int spd_index = 0; /* No GPIO selection, force index 0 for now */
printk(BIOS_DEBUG, "SPD index %d\n", spd_index); - spd_file = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "spd.bin", - CBFS_TYPE_SPD, &spd_file_len); + spd_file = cbfs_boot_map_with_leak("spd.bin", CBFS_TYPE_SPD, + &spd_file_len); if (!spd_file) die("SPD data not found.");
diff --git a/src/mainboard/google/butterfly/mainboard.c b/src/mainboard/google/butterfly/mainboard.c index 655fc2f..5420f72 100644 --- a/src/mainboard/google/butterfly/mainboard.c +++ b/src/mainboard/google/butterfly/mainboard.c @@ -205,8 +205,8 @@ static void mainboard_init(device_t dev) search_length = find_fmap_entry("RO_VPD", (void **)vpd_region_ptr); search_address = (unsigned long)(*vpd_region_ptr); #else - void *vpd_file = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "vpd.bin", - CBFS_TYPE_RAW, &search_length); + void *vpd_file = cbfs_boot_map_with_leak("vpd.bin", CBFS_TYPE_RAW, + &search_length); if (vpd_file) { search_address = (unsigned long)vpd_file; } else { diff --git a/src/mainboard/google/falco/romstage.c b/src/mainboard/google/falco/romstage.c index 4e79159..d28a914 100644 --- a/src/mainboard/google/falco/romstage.c +++ b/src/mainboard/google/falco/romstage.c @@ -79,8 +79,8 @@ static void copy_spd(struct pei_data *peid) size_t spd_file_len;
printk(BIOS_DEBUG, "SPD index %d\n", spd_index); - spd_file = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "spd.bin", - CBFS_TYPE_SPD, &spd_file_len); + spd_file = cbfs_boot_map_with_leak("spd.bin", CBFS_TYPE_SPD, + &spd_file_len); if (!spd_file) die("SPD data not found.");
diff --git a/src/mainboard/google/link/romstage.c b/src/mainboard/google/link/romstage.c index 2e7ee52..5872928 100644 --- a/src/mainboard/google/link/romstage.c +++ b/src/mainboard/google/link/romstage.c @@ -95,8 +95,8 @@ static void copy_spd(struct pei_data *peid) int spd_index = get_gpios(gpio_vector);
printk(BIOS_DEBUG, "spd index %d\n", spd_index); - spd_file = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "spd.bin", - CBFS_TYPE_SPD, &spd_file_len); + spd_file = cbfs_boot_map_with_leak("spd.bin", CBFS_TYPE_SPD, + &spd_file_len); if (!spd_file) die("SPD data not found.");
diff --git a/src/mainboard/google/panther/lan.c b/src/mainboard/google/panther/lan.c index 2d7eed0..1b6d314 100644 --- a/src/mainboard/google/panther/lan.c +++ b/src/mainboard/google/panther/lan.c @@ -144,8 +144,8 @@ void lan_init(void) search_length = find_fmap_entry("RO_VPD", (void **)vpd_region_ptr); search_address = (unsigned long)(*vpd_region_ptr); #else - void *vpd_file = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "vpd.bin", - CBFS_TYPE_RAW, &search_length); + void *vpd_file = cbfs_boot_map_with_leak("vpd.bin", CBFS_TYPE_RAW, + &search_length); if (vpd_file) { search_address = (unsigned long)vpd_file; } else { diff --git a/src/mainboard/google/peach_pit/romstage.c b/src/mainboard/google/peach_pit/romstage.c index 04be804..e084b7e 100644 --- a/src/mainboard/google/peach_pit/romstage.c +++ b/src/mainboard/google/peach_pit/romstage.c @@ -21,8 +21,10 @@ #include <stdlib.h>
#include <armv7.h> +#include <boot_device.h> #include <cbfs.h> #include <cbmem.h> +#include <region.h> #include <timestamp.h>
#include <arch/cache.h> @@ -178,29 +180,28 @@ static unsigned long primitive_mem_test(void) /* here is a simple SPI debug test, known to fid trouble */ static void simple_spi_test(void) { - struct cbfs_media default_media, *media; + const struct region_device *boot_dev; int i, amt = 4 * MiB, errors = 0; //u32 *data = (void *)0x40000000; u32 data[1024]; u32 in;
+ boot_device_init(); + boot_dev = boot_device_ro(); amt = sizeof(data); - media = &default_media; - if (init_default_cbfs_media(media) != 0) { + if (boot_dev == NULL) { printk(BIOS_SPEW, "Failed to initialize default media.\n"); return; }
- - media->open(media); - if (media->read(media, data, (size_t) 0, amt) < amt){ + if (rdev_readat(boot_dev, data, 0, amt) < amt) { printk(BIOS_SPEW, "simple_spi_test fails\n"); return; }
for(i = 0; i < amt; i += 4){ - if (media->read(media, &in, (size_t) i, 4) < 1){ + if (rdev_readat(boot_dev, &in, i, 4) < 4) { printk(BIOS_SPEW, "simple_spi_test fails at %d\n", i); return; } @@ -209,7 +210,7 @@ static void simple_spi_test(void) printk(BIOS_SPEW, "BAD at %d(%p):\nRAM %08lx\nSPI %08lx\n", i, &data[i/4], (unsigned long)data[i/4], (unsigned long)in); /* reread it to see which is wrong. */ - if (media->read(media, &in, (size_t) i, 4) < 1){ + if (rdev_readat(boot_dev, &in, i, 4) < 4) { printk(BIOS_SPEW, "simple_spi_test fails at %d\n", i); return; } diff --git a/src/mainboard/google/peppy/romstage.c b/src/mainboard/google/peppy/romstage.c index 27962e1..6f00216 100644 --- a/src/mainboard/google/peppy/romstage.c +++ b/src/mainboard/google/peppy/romstage.c @@ -82,8 +82,8 @@ static void copy_spd(struct pei_data *peid) size_t spd_file_len;
printk(BIOS_DEBUG, "SPD index %d\n", spd_index); - spd_file = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "spd.bin", - CBFS_TYPE_SPD, &spd_file_len); + spd_file = cbfs_boot_map_with_leak("spd.bin", CBFS_TYPE_SPD, + &spd_file_len); if (!spd_file) die("SPD data not found.");
diff --git a/src/mainboard/google/rambi/romstage.c b/src/mainboard/google/rambi/romstage.c index 7c505e7..0cda2f5 100644 --- a/src/mainboard/google/rambi/romstage.c +++ b/src/mainboard/google/rambi/romstage.c @@ -71,9 +71,10 @@ static void *get_spd_pointer(char *spd_file_content, int total_spds, int *dual)
void mainboard_romstage_entry(struct romstage_params *rp) { - struct cbfs_file *spd_file; void *spd_content; int dual_channel = 0; + void *spd_file; + size_t spd_fsize;
struct mrc_params mp = { .mainboard = { @@ -83,12 +84,12 @@ void mainboard_romstage_entry(struct romstage_params *rp) }, };
- spd_file = cbfs_get_file(CBFS_DEFAULT_MEDIA, "spd.bin"); + spd_file = cbfs_boot_map_with_leak("spd.bin", CBFS_TYPE_SPD, + &spd_fsize); if (!spd_file) die("SPD data not found.");
- spd_content = get_spd_pointer(CBFS_SUBHEADER(spd_file), - ntohl(spd_file->len) / SPD_SIZE, + spd_content = get_spd_pointer(spd_file, spd_fsize / SPD_SIZE, &dual_channel); mp.mainboard.dram_data[0] = spd_content; if (dual_channel) diff --git a/src/mainboard/google/samus/spd/spd.c b/src/mainboard/google/samus/spd/spd.c index 00e694e..8ab8ef9 100644 --- a/src/mainboard/google/samus/spd/spd.c +++ b/src/mainboard/google/samus/spd/spd.c @@ -90,8 +90,8 @@ void mainboard_fill_spd_data(struct pei_data *pei_data) }; int spd_gpio[4]; int spd_index; - int spd_file_len; - struct cbfs_file *spd_file; + size_t spd_file_len; + char *spd_file;
/* Proto2B boards use a different GPIO for SPD index bit 3 */ if (google_chromeec_get_board_version() <= SAMUS_EC_BOARD_PROTO2_A) @@ -110,10 +110,9 @@ void mainboard_fill_spd_data(struct pei_data *pei_data) spd_bits[3], spd_gpio[3], spd_bits[2], spd_gpio[2], spd_bits[1], spd_gpio[1], spd_bits[0], spd_gpio[0]);
- spd_file = cbfs_get_file(CBFS_DEFAULT_MEDIA, "spd.bin"); + spd_file = cbfs_boot_map_with_leak("spd.bin", 0xab, &spd_file_len); if (!spd_file) die("SPD data not found."); - spd_file_len = ntohl(spd_file->len);
if (spd_file_len < ((spd_index + 1) * SPD_LEN)) { printk(BIOS_ERR, "SPD index override to 0 - old hardware?\n"); @@ -125,10 +124,8 @@ void mainboard_fill_spd_data(struct pei_data *pei_data)
/* Assume same memory in both channels */ spd_index *= SPD_LEN; - memcpy(pei_data->spd_data[0][0], - ((char*)CBFS_SUBHEADER(spd_file)) + spd_index, SPD_LEN); - memcpy(pei_data->spd_data[1][0], - ((char*)CBFS_SUBHEADER(spd_file)) + spd_index, SPD_LEN); + memcpy(pei_data->spd_data[0][0], spd_file + spd_index, SPD_LEN); + memcpy(pei_data->spd_data[1][0], spd_file + spd_index, SPD_LEN);
/* Make sure a valid SPD was found */ if (pei_data->spd_data[0][0][0] == 0) diff --git a/src/mainboard/google/slippy/romstage.c b/src/mainboard/google/slippy/romstage.c index c242ecd..c89687f 100644 --- a/src/mainboard/google/slippy/romstage.c +++ b/src/mainboard/google/slippy/romstage.c @@ -80,8 +80,8 @@ static void copy_spd(struct pei_data *peid) size_t spd_file_len;
printk(BIOS_DEBUG, "SPD index %d\n", spd_index); - spd_file = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "spd.bin", - CBFS_TYPE_SPD, &spd_file_len); + spd_file = cbfs_boot_map_with_leak("spd.bin", CBFS_TYPE_SPD, + &spd_file_len); if (!spd_file) die("SPD data not found.");
diff --git a/src/mainboard/samsung/lumpy/romstage.c b/src/mainboard/samsung/lumpy/romstage.c index e63a8f9..7e32282 100644 --- a/src/mainboard/samsung/lumpy/romstage.c +++ b/src/mainboard/samsung/lumpy/romstage.c @@ -237,8 +237,8 @@ void main(unsigned long bist) break; }
- spd_data = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "spd.bin", - CBFS_TYPE_SPD, &spd_file_len); + spd_data = cbfs_boot_map_with_leak("spd.bin", CBFS_TYPE_SPD, + &spd_file_len); if (!spd_data) die("SPD data not found."); if (spd_file_len < (spd_index + 1) * 256) diff --git a/src/mainboard/siemens/mc_tcu3/modhwinfo.c b/src/mainboard/siemens/mc_tcu3/modhwinfo.c index 95bb76c..b077868 100644 --- a/src/mainboard/siemens/mc_tcu3/modhwinfo.c +++ b/src/mainboard/siemens/mc_tcu3/modhwinfo.c @@ -31,8 +31,7 @@ u8* get_first_linked_block(char *filename, u8 **file_offset) { u8* block_ptr = NULL;
- block_ptr = (cbfs_get_file_content(CBFS_DEFAULT_MEDIA, filename, - 0x50, NULL)); + block_ptr = cbfs_boot_map_with_leak(filename, 0x50, NULL); if (!block_ptr) return NULL; if (!strncmp((char*)block_ptr, "H1W2M3I4", LEN_MAGIC_NUM)) { @@ -57,8 +56,7 @@ struct hwinfo* get_hwinfo(char *filename) { struct hwinfo* main_hwinfo;
- main_hwinfo = (struct hwinfo*)(cbfs_get_file_content(CBFS_DEFAULT_MEDIA, - filename, 0x50, NULL)); + main_hwinfo = cbfs_boot_map_with_leak(filename, 0x50, NULL); if ((main_hwinfo) && (!strncmp(main_hwinfo->magicNumber, "H1W2M3I4", LEN_MAGIC_NUM)) && (main_hwinfo->length == LEN_MAIN_HWINFO)) diff --git a/src/northbridge/amd/agesa/common/common.c b/src/northbridge/amd/agesa/common/common.c index 29b4c2e..e4f8e9d 100644 --- a/src/northbridge/amd/agesa/common/common.c +++ b/src/northbridge/amd/agesa/common/common.c @@ -38,7 +38,8 @@ AGESA_STATUS common_ReadCbfsSpd (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
char *spd_file;
- spd_file = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "spd.bin", CBFS_TYPE_SPD_BIN, &spd_file_length); + spd_file = cbfs_boot_map_with_leak("spd.bin", CBFS_TYPE_SPD_BIN, + &spd_file_length); if (!spd_file) die("file [spd.bin] not found in CBFS");
diff --git a/src/northbridge/amd/agesa/def_callouts.c b/src/northbridge/amd/agesa/def_callouts.c index 26b1c0d..3f83e9e 100644 --- a/src/northbridge/amd/agesa/def_callouts.c +++ b/src/northbridge/amd/agesa/def_callouts.c @@ -117,8 +117,8 @@ AGESA_STATUS agesa_RunFuncOnAp (UINT32 Func, UINT32 Data, VOID *ConfigPtr) AGESA_STATUS agesa_GfxGetVbiosImage(UINT32 Func, UINT32 FchData, VOID *ConfigPrt) { GFX_VBIOS_IMAGE_INFO *pVbiosImageInfo = (GFX_VBIOS_IMAGE_INFO *)ConfigPrt; - pVbiosImageInfo->ImagePtr = cbfs_get_file_content( - CBFS_DEFAULT_MEDIA, "pci"CONFIG_VGA_BIOS_ID".rom", + pVbiosImageInfo->ImagePtr = cbfs_boot_map_with_leak( + "pci"CONFIG_VGA_BIOS_ID".rom", CBFS_TYPE_OPTIONROM, NULL); /* printk(BIOS_DEBUG, "IMGptr=%x\n", pVbiosImageInfo->ImagePtr); */ return pVbiosImageInfo->ImagePtr == NULL ? AGESA_WARNING : AGESA_SUCCESS; diff --git a/src/northbridge/amd/pi/def_callouts.c b/src/northbridge/amd/pi/def_callouts.c index 2caf183..56a24ac 100644 --- a/src/northbridge/amd/pi/def_callouts.c +++ b/src/northbridge/amd/pi/def_callouts.c @@ -107,8 +107,8 @@ AGESA_STATUS agesa_RunFuncOnAp (UINT32 Func, UINT32 Data, VOID *ConfigPtr) AGESA_STATUS agesa_GfxGetVbiosImage(UINT32 Func, UINT32 FchData, VOID *ConfigPrt) { GFX_VBIOS_IMAGE_INFO *pVbiosImageInfo = (GFX_VBIOS_IMAGE_INFO *)ConfigPrt; - pVbiosImageInfo->ImagePtr = cbfs_get_file_content( - CBFS_DEFAULT_MEDIA, "pci"CONFIG_VGA_BIOS_ID".rom", + pVbiosImageInfo->ImagePtr = cbfs_boot_map_with_leak( + "pci"CONFIG_VGA_BIOS_ID".rom", CBFS_TYPE_OPTIONROM, NULL); printk(BIOS_DEBUG, "agesa_GfxGetVbiosImage: IMGptr=%p\n", pVbiosImageInfo->ImagePtr); return (pVbiosImageInfo->ImagePtr ? AGESA_SUCCESS : AGESA_WARNING); diff --git a/src/northbridge/intel/haswell/mrccache.c b/src/northbridge/intel/haswell/mrccache.c index 8fbac17..d6522a0 100644 --- a/src/northbridge/intel/haswell/mrccache.c +++ b/src/northbridge/intel/haswell/mrccache.c @@ -70,10 +70,9 @@ static u32 get_mrc_cache_region(struct mrc_data_container **mrc_region_ptr) return find_fmap_entry("RW_MRC_CACHE", (void **)mrc_region_ptr); #else size_t region_size; - *mrc_region_ptr = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, - "mrc.cache", - CBFS_TYPE_MRC_CACHE, - ®ion_size); + *mrc_region_ptr = cbfs_boot_map_with_leak("mrc.cache", + CBFS_TYPE_MRC_CACHE, + ®ion_size); return region_size; #endif } diff --git a/src/northbridge/intel/haswell/raminit.c b/src/northbridge/intel/haswell/raminit.c index 6bbb215..4740f73 100644 --- a/src/northbridge/intel/haswell/raminit.c +++ b/src/northbridge/intel/haswell/raminit.c @@ -162,8 +162,8 @@ void sdram_initialize(struct pei_data *pei_data) pei_data->tx_byte = do_putchar;
/* Locate and call UEFI System Agent binary. */ - entry = (unsigned long)cbfs_get_file_content( - CBFS_DEFAULT_MEDIA, "mrc.bin", CBFS_TYPE_MRC, NULL); + entry = (unsigned long)cbfs_boot_map_with_leak("mrc.bin", + CBFS_TYPE_MRC, NULL); if (entry) { int rv; asm volatile ( diff --git a/src/northbridge/intel/i82830/vga.c b/src/northbridge/intel/i82830/vga.c index f846e37..cd07dcb 100644 --- a/src/northbridge/intel/i82830/vga.c +++ b/src/northbridge/intel/i82830/vga.c @@ -31,8 +31,7 @@ static void vga_init(device_t dev) { printk(BIOS_INFO, "Starting Graphics Initialization\n"); size_t mbi_len; - void *mbi = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "mbi.bin", - CBFS_TYPE_MBI, &mbi_len); + void *mbi = cbfs_boot_map_with_leak("mbi.bin", CBFS_TYPE_MBI, &mbi_len);
if (mbi && mbi_len) { /* The GDT or coreboot table is going to live here. But diff --git a/src/northbridge/intel/sandybridge/mrccache.c b/src/northbridge/intel/sandybridge/mrccache.c index 4a69233..6b02c21 100644 --- a/src/northbridge/intel/sandybridge/mrccache.c +++ b/src/northbridge/intel/sandybridge/mrccache.c @@ -70,10 +70,9 @@ static u32 get_mrc_cache_region(struct mrc_data_container **mrc_region_ptr) return find_fmap_entry("RW_MRC_CACHE", (void **)mrc_region_ptr); #else size_t region_size; - *mrc_region_ptr = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, - "mrc.cache", - CBFS_TYPE_MRC_CACHE, - ®ion_size); + *mrc_region_ptr = cbfs_boot_map_with_leak("mrc.cache", + CBFS_TYPE_MRC_CACHE, + ®ion_size); return region_size; #endif
diff --git a/src/northbridge/intel/sandybridge/raminit.c b/src/northbridge/intel/sandybridge/raminit.c index d8c7eef..fde0cfa 100644 --- a/src/northbridge/intel/sandybridge/raminit.c +++ b/src/northbridge/intel/sandybridge/raminit.c @@ -246,8 +246,7 @@ void sdram_initialize(struct pei_data *pei_data) pei_data->tx_byte = do_putchar;
/* Locate and call UEFI System Agent binary. */ - entry = cbfs_get_file_content( - CBFS_DEFAULT_MEDIA, "mrc.bin", CBFS_TYPE_MRC, NULL); + entry = cbfs_boot_map_with_leak("mrc.bin", CBFS_TYPE_MRC, NULL); if (entry) { int rv; rv = entry (pei_data); diff --git a/src/soc/intel/baytrail/romstage/raminit.c b/src/soc/intel/baytrail/romstage/raminit.c index bbee6de..384e31a 100644 --- a/src/soc/intel/baytrail/romstage/raminit.c +++ b/src/soc/intel/baytrail/romstage/raminit.c @@ -148,8 +148,7 @@ void raminit(struct mrc_params *mp, int prev_sleep_state) }
/* Determine if mrc.bin is in the cbfs. */ - if (cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "mrc.bin", CBFS_TYPE_MRC, - NULL) == NULL) { + if (cbfs_boot_map_with_leak("mrc.bin", CBFS_TYPE_MRC, NULL) == NULL) { printk(BIOS_DEBUG, "Couldn't find mrc.bin\n"); return; } diff --git a/src/soc/intel/broadwell/romstage/raminit.c b/src/soc/intel/broadwell/romstage/raminit.c index 6733f1d..5f0390b 100644 --- a/src/soc/intel/broadwell/romstage/raminit.c +++ b/src/soc/intel/broadwell/romstage/raminit.c @@ -86,8 +86,7 @@ void raminit(struct pei_data *pei_data) }
/* Determine if mrc.bin is in the cbfs. */ - entry = (pei_wrapper_entry_t)cbfs_get_file_content( - CBFS_DEFAULT_MEDIA, "mrc.bin", CBFS_TYPE_MRC, NULL); + entry = cbfs_boot_map_with_leak("mrc.bin", CBFS_TYPE_MRC, NULL); if (entry == NULL) { printk(BIOS_DEBUG, "Couldn't find mrc.bin\n"); return; diff --git a/src/soc/nvidia/tegra124/Makefile.inc b/src/soc/nvidia/tegra124/Makefile.inc index d32580e..099502e 100644 --- a/src/soc/nvidia/tegra124/Makefile.inc +++ b/src/soc/nvidia/tegra124/Makefile.inc @@ -1,6 +1,5 @@ bootblock-y += bootblock.c bootblock-y += bootblock_asm.S -bootblock-y += cbfs.c bootblock-y += clock.c bootblock-y += dma.c bootblock-y += i2c.c @@ -21,7 +20,6 @@ bootblock-$(CONFIG_DRIVERS_UART) += uart.c endif
verstage-y += verstage.c -verstage-y += cbfs.c verstage-y += dma.c verstage-y += monotonic_timer.c verstage-y += spi.c @@ -34,7 +32,6 @@ verstage-y += clock.c verstage-y += i2c.c verstage-y += cache.c
-romstage-y += cbfs.c romstage-y += cbmem.c romstage-y += clock.c romstage-y += dma.c @@ -52,7 +49,6 @@ romstage-y += timer.c romstage-y += cache.c romstage-$(CONFIG_DRIVERS_UART) += uart.c
-ramstage-y += cbfs.c ramstage-y += cbmem.c ramstage-y += clock.c ramstage-y += display.c diff --git a/src/soc/nvidia/tegra124/cbfs.c b/src/soc/nvidia/tegra124/cbfs.c deleted file mode 100644 index 4497d6a..0000000 --- a/src/soc/nvidia/tegra124/cbfs.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright 2013 Google Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - -#include <cbfs.h> /* This driver serves as a CBFS media source. */ - -#include "spi.h" - -int init_default_cbfs_media(struct cbfs_media *media) -{ - return initialize_tegra_spi_cbfs_media(media, - (void*)CONFIG_CBFS_CACHE_ADDRESS, - CONFIG_CBFS_CACHE_SIZE); -} diff --git a/src/soc/nvidia/tegra124/spi.c b/src/soc/nvidia/tegra124/spi.c index b88306b..a0b0664 100644 --- a/src/soc/nvidia/tegra124/spi.c +++ b/src/soc/nvidia/tegra124/spi.c @@ -19,8 +19,10 @@ */
#include <assert.h> +#include <boot_device.h> #include <cbfs.h> #include <inttypes.h> +#include <region.h> #include <spi-generic.h> #include <spi_flash.h> #include <stdint.h> @@ -799,22 +801,13 @@ int spi_xfer(struct spi_slave *slave, const void *dout, return ret; }
-/* SPI as CBFS media. */ -struct tegra_spi_media { - struct spi_slave *slave; - struct cbfs_simple_buffer buffer; -}; - -static int tegra_spi_cbfs_open(struct cbfs_media *media) +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs) { - DEBUG_SPI("tegra_spi_cbfs_open\n"); - return 0; -} + struct tegra_spi_channel *channel = to_tegra_spi(bus); + if (!channel) + return NULL;
-static int tegra_spi_cbfs_close(struct cbfs_media *media) -{ - DEBUG_SPI("tegra_spi_cbfs_close\n"); - return 0; + return &channel->slave; }
#define JEDEC_READ 0x03 @@ -822,16 +815,17 @@ static int tegra_spi_cbfs_close(struct cbfs_media *media) #define JEDEC_FAST_READ_DUAL 0x3b #define JEDEC_FAST_READ_DUAL_OUTSIZE 0x05
-static size_t tegra_spi_cbfs_read(struct cbfs_media *media, void *dest, - size_t offset, size_t count) +static struct spi_slave *boot_slave; + +static ssize_t tegra_spi_readat(const struct region_device *rdev, void *dest, + size_t offset, size_t count) { - struct tegra_spi_media *spi = (struct tegra_spi_media *)media->context; u8 spi_read_cmd[JEDEC_FAST_READ_DUAL_OUTSIZE]; unsigned int read_cmd_bytes; int ret = count; struct tegra_spi_channel *channel;
- channel = to_tegra_spi(spi->slave->bus); + channel = to_tegra_spi(boot_slave->bus);
if (channel->dual_mode) { /* @@ -852,9 +846,9 @@ static size_t tegra_spi_cbfs_read(struct cbfs_media *media, void *dest, spi_read_cmd[2] = (offset >> 8) & 0xff; spi_read_cmd[3] = offset & 0xff;
- spi_claim_bus(spi->slave); + spi_claim_bus(boot_slave);
- if (spi_xfer(spi->slave, spi_read_cmd, + if (spi_xfer(boot_slave, spi_read_cmd, read_cmd_bytes, NULL, 0) < 0) { ret = -1; printk(BIOS_ERR, "%s: Failed to transfer %u bytes\n", @@ -865,7 +859,7 @@ static size_t tegra_spi_cbfs_read(struct cbfs_media *media, void *dest, if (channel->dual_mode) { setbits_le32(&channel->regs->command1, SPI_CMD1_BOTH_EN_BIT); } - if (spi_xfer(spi->slave, NULL, 0, dest, count)) { + if (spi_xfer(boot_slave, NULL, 0, dest, count)) { ret = -1; printk(BIOS_ERR, "%s: Failed to transfer %u bytes\n", __func__, count); @@ -875,64 +869,35 @@ static size_t tegra_spi_cbfs_read(struct cbfs_media *media, void *dest,
tegra_spi_cbfs_read_exit: /* de-assert /CS */ - spi_release_bus(spi->slave); - return (ret < 0) ? 0 : ret; + spi_release_bus(boot_slave); + return ret; }
-static void *tegra_spi_cbfs_map(struct cbfs_media *media, size_t offset, - size_t count) -{ - struct tegra_spi_media *spi = (struct tegra_spi_media*)media->context; - void *map; - DEBUG_SPI("tegra_spi_cbfs_map\n"); - map = cbfs_simple_buffer_map(&spi->buffer, media, offset, count); - return map; -} +static const struct region_device_ops tegra_spi_ops = { + .mmap = mmap_helper_rdev_mmap, + .munmap = mmap_helper_rdev_munmap, + .readat = tegra_spi_readat, +}; + +static struct mmap_helper_region_device mdev = + MMAP_HELPER_REGION_INIT(&tegra_spi_ops, 0, CONFIG_ROM_SIZE, + (void *)(uintptr_t)CONFIG_CBFS_CACHE_ADDRESS, + CONFIG_CBFS_CACHE_SIZE);
-static void *tegra_spi_cbfs_unmap(struct cbfs_media *media, - const void *address) +const struct region_device *boot_device_ro(void) { - struct tegra_spi_media *spi = (struct tegra_spi_media*)media->context; - DEBUG_SPI("tegra_spi_cbfs_unmap\n"); - return cbfs_simple_buffer_unmap(&spi->buffer, address); + return &mdev.rdev; }
-int initialize_tegra_spi_cbfs_media(struct cbfs_media *media, - void *buffer_address, - size_t buffer_size) +void boot_device_init(void) { - // TODO Replace static variable to support multiple streams. - static struct tegra_spi_media context; - static struct tegra_spi_channel *channel; - - channel = &tegra_spi_channels[CONFIG_BOOT_MEDIA_SPI_BUS - 1]; - channel->slave.cs = CONFIG_BOOT_MEDIA_SPI_CHIP_SELECT; - - DEBUG_SPI("Initializing CBFS media on SPI\n"); - - context.slave = &channel->slave; - context.buffer.allocated = context.buffer.last_allocate = 0; - context.buffer.buffer = buffer_address; - context.buffer.size = buffer_size; - media->context = (void*)&context; - media->open = tegra_spi_cbfs_open; - media->close = tegra_spi_cbfs_close; - media->read = tegra_spi_cbfs_read; - media->map = tegra_spi_cbfs_map; - media->unmap = tegra_spi_cbfs_unmap; + struct tegra_spi_channel *boot_chan; + + boot_chan = &tegra_spi_channels[CONFIG_BOOT_MEDIA_SPI_BUS - 1]; + boot_chan->slave.cs = CONFIG_BOOT_MEDIA_SPI_CHIP_SELECT;
#if CONFIG_SPI_FLASH_FAST_READ_DUAL_OUTPUT_3B == 1 - channel->dual_mode = 1; + boot_chan->dual_mode = 1; #endif - - return 0; -} - -struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs) -{ - struct tegra_spi_channel *channel = to_tegra_spi(bus); - if (!channel) - return NULL; - - return &channel->slave; + boot_slave = &boot_chan->slave; } diff --git a/src/soc/nvidia/tegra124/spi.h b/src/soc/nvidia/tegra124/spi.h index 11e88fe..13f7dbd 100644 --- a/src/soc/nvidia/tegra124/spi.h +++ b/src/soc/nvidia/tegra124/spi.h @@ -62,11 +62,6 @@ struct tegra_spi_channel { enum spi_xfer_mode xfer_mode; };
-struct cbfs_media; -int initialize_tegra_spi_cbfs_media(struct cbfs_media *media, - void *buffer_address, - size_t buffer_size); - struct tegra_spi_channel *tegra_spi_init(unsigned int bus);
#endif /* __NVIDIA_TEGRA124_SPI_H__ */ diff --git a/src/soc/nvidia/tegra132/Makefile.inc b/src/soc/nvidia/tegra132/Makefile.inc index 10d4d4e..713a67a 100644 --- a/src/soc/nvidia/tegra132/Makefile.inc +++ b/src/soc/nvidia/tegra132/Makefile.inc @@ -1,6 +1,5 @@ bootblock-y += bootblock.c bootblock-y += bootblock_asm.S -bootblock-y += cbfs.c bootblock-y += timer.c bootblock-y += clock.c bootblock-y += spi.c @@ -24,7 +23,6 @@ endif romstage-y += 32bit_reset.S romstage-y += romstage_asm.S romstage-y += addressmap.c -romstage-y += cbfs.c romstage-y += cbmem.c romstage-y += timer.c romstage-y += ccplex.c @@ -49,7 +47,6 @@ romstage-$(CONFIG_DRIVERS_UART) += uart.c
ramstage-y += 32bit_reset.S ramstage-y += addressmap.c -ramstage-y += cbfs.c ramstage-y += cbmem.c ramstage-y += cpu.c ramstage-y += cpu_lib.S diff --git a/src/soc/nvidia/tegra132/cbfs.c b/src/soc/nvidia/tegra132/cbfs.c deleted file mode 100644 index 7b75f7c..0000000 --- a/src/soc/nvidia/tegra132/cbfs.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright 2014 Google Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - - -#include <cbfs.h> /* This driver serves as a CBFS media source. */ - -#include "spi.h" - -int init_default_cbfs_media(struct cbfs_media *media) -{ - return initialize_tegra_spi_cbfs_media(media, - (void*)CONFIG_CBFS_CACHE_ADDRESS, - CONFIG_CBFS_CACHE_SIZE); -} diff --git a/src/soc/nvidia/tegra132/ccplex.c b/src/soc/nvidia/tegra132/ccplex.c index b183e5d..8568992 100644 --- a/src/soc/nvidia/tegra132/ccplex.c +++ b/src/soc/nvidia/tegra132/ccplex.c @@ -75,10 +75,9 @@ static int ccplex_start(void)
int ccplex_load_mts(void) { - struct cbfs_file file; - ssize_t offset; - size_t nread; + ssize_t nread; struct stopwatch sw; + struct cbfsf fh;
/* * MTS location is hard coded to this magic address. The hardware will @@ -86,21 +85,19 @@ int ccplex_load_mts(void) * place in the carveout region. */ void * const mts = (void *)(uintptr_t)MTS_LOAD_ADDRESS; - struct cbfs_media *media = CBFS_DEFAULT_MEDIA;
stopwatch_init(&sw); - offset = cbfs_locate_file(media, &file, MTS_FILE_NAME); - if (offset < 0) { + if (cbfs_boot_locate(&fh, MTS_FILE_NAME, NULL)) { printk(BIOS_DEBUG, "MTS file not found: %s\n", MTS_FILE_NAME); return -1; }
/* Read MTS file into the carveout region. */ - nread = cbfs_read(media, mts, offset, file.len); + nread = cbfs_file_readat(&fh, mts, 0, cbfs_file_size(&fh));
- if (nread != file.len) { + if (nread != cbfs_file_size(&fh)) { printk(BIOS_DEBUG, "MTS bytes read (%zu) != file length(%u)!\n", - nread, file.len); + nread, cbfs_file_size(&fh)); return -1; }
diff --git a/src/soc/nvidia/tegra132/spi.c b/src/soc/nvidia/tegra132/spi.c index 219998c..a910f64 100644 --- a/src/soc/nvidia/tegra132/spi.c +++ b/src/soc/nvidia/tegra132/spi.c @@ -19,8 +19,10 @@ */
#include <assert.h> +#include <boot_device.h> #include <cbfs.h> #include <inttypes.h> +#include <region.h> #include <spi-generic.h> #include <spi_flash.h> #include <stdint.h> @@ -808,22 +810,13 @@ int spi_xfer(struct spi_slave *slave, const void *dout, return ret; }
-/* SPI as CBFS media. */ -struct tegra_spi_media { - struct spi_slave *slave; - struct cbfs_simple_buffer buffer; -}; - -static int tegra_spi_cbfs_open(struct cbfs_media *media) +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs) { - DEBUG_SPI("tegra_spi_cbfs_open\n"); - return 0; -} + struct tegra_spi_channel *channel = to_tegra_spi(bus); + if (!channel) + return NULL;
-static int tegra_spi_cbfs_close(struct cbfs_media *media) -{ - DEBUG_SPI("tegra_spi_cbfs_close\n"); - return 0; + return &channel->slave; }
#define JEDEC_READ 0x03 @@ -831,16 +824,17 @@ static int tegra_spi_cbfs_close(struct cbfs_media *media) #define JEDEC_FAST_READ_DUAL 0x3b #define JEDEC_FAST_READ_DUAL_OUTSIZE 0x05
-static size_t tegra_spi_cbfs_read(struct cbfs_media *media, void *dest, - size_t offset, size_t count) +static struct spi_slave *boot_slave; + +static ssize_t tegra_spi_readat(const struct region_device *rdev, void *dest, + size_t offset, size_t count) { - struct tegra_spi_media *spi = (struct tegra_spi_media *)media->context; u8 spi_read_cmd[JEDEC_FAST_READ_DUAL_OUTSIZE]; unsigned int read_cmd_bytes; int ret = count; struct tegra_spi_channel *channel;
- channel = to_tegra_spi(spi->slave->bus); + channel = to_tegra_spi(boot_slave->bus);
if (channel->dual_mode) { /* @@ -861,9 +855,9 @@ static size_t tegra_spi_cbfs_read(struct cbfs_media *media, void *dest, spi_read_cmd[2] = (offset >> 8) & 0xff; spi_read_cmd[3] = offset & 0xff;
- spi_claim_bus(spi->slave); + spi_claim_bus(boot_slave);
- if (spi_xfer(spi->slave, spi_read_cmd, + if (spi_xfer(boot_slave, spi_read_cmd, read_cmd_bytes, NULL, 0) < 0) { ret = -1; printk(BIOS_ERR, "%s: Failed to transfer %zu bytes\n", @@ -874,7 +868,7 @@ static size_t tegra_spi_cbfs_read(struct cbfs_media *media, void *dest, if (channel->dual_mode) { setbits_le32(&channel->regs->command1, SPI_CMD1_BOTH_EN_BIT); } - if (spi_xfer(spi->slave, NULL, 0, dest, count)) { + if (spi_xfer(boot_slave, NULL, 0, dest, count)) { ret = -1; printk(BIOS_ERR, "%s: Failed to transfer %zu bytes\n", __func__, count); @@ -884,64 +878,35 @@ static size_t tegra_spi_cbfs_read(struct cbfs_media *media, void *dest,
tegra_spi_cbfs_read_exit: /* de-assert /CS */ - spi_release_bus(spi->slave); - return (ret < 0) ? 0 : ret; + spi_release_bus(boot_slave); + return ret; }
-static void *tegra_spi_cbfs_map(struct cbfs_media *media, size_t offset, - size_t count) -{ - struct tegra_spi_media *spi = (struct tegra_spi_media*)media->context; - void *map; - DEBUG_SPI("tegra_spi_cbfs_map\n"); - map = cbfs_simple_buffer_map(&spi->buffer, media, offset, count); - return map; -} +static const struct region_device_ops tegra_spi_ops = { + .mmap = mmap_helper_rdev_mmap, + .munmap = mmap_helper_rdev_munmap, + .readat = tegra_spi_readat, +}; + +static struct mmap_helper_region_device mdev = + MMAP_HELPER_REGION_INIT(&tegra_spi_ops, 0, CONFIG_ROM_SIZE, + (void *)(uintptr_t)CONFIG_CBFS_CACHE_ADDRESS, + CONFIG_CBFS_CACHE_SIZE);
-static void *tegra_spi_cbfs_unmap(struct cbfs_media *media, - const void *address) +const struct region_device *boot_device_ro(void) { - struct tegra_spi_media *spi = (struct tegra_spi_media*)media->context; - DEBUG_SPI("tegra_spi_cbfs_unmap\n"); - return cbfs_simple_buffer_unmap(&spi->buffer, address); + return &mdev.rdev; }
-int initialize_tegra_spi_cbfs_media(struct cbfs_media *media, - void *buffer_address, - size_t buffer_size) +void boot_device_init(void) { - // TODO Replace static variable to support multiple streams. - static struct tegra_spi_media context; - static struct tegra_spi_channel *channel; - - channel = &tegra_spi_channels[CONFIG_BOOT_MEDIA_SPI_BUS - 1]; - channel->slave.cs = CONFIG_BOOT_MEDIA_SPI_CHIP_SELECT; - - DEBUG_SPI("Initializing CBFS media on SPI\n"); - - context.slave = &channel->slave; - context.buffer.allocated = context.buffer.last_allocate = 0; - context.buffer.buffer = buffer_address; - context.buffer.size = buffer_size; - media->context = (void*)&context; - media->open = tegra_spi_cbfs_open; - media->close = tegra_spi_cbfs_close; - media->read = tegra_spi_cbfs_read; - media->map = tegra_spi_cbfs_map; - media->unmap = tegra_spi_cbfs_unmap; + struct tegra_spi_channel *boot_chan; + + boot_chan = &tegra_spi_channels[CONFIG_BOOT_MEDIA_SPI_BUS - 1]; + boot_chan->slave.cs = CONFIG_BOOT_MEDIA_SPI_CHIP_SELECT;
#if CONFIG_SPI_FLASH_FAST_READ_DUAL_OUTPUT_3B == 1 - channel->dual_mode = 1; + boot_chan->dual_mode = 1; #endif - - return 0; -} - -struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs) -{ - struct tegra_spi_channel *channel = to_tegra_spi(bus); - if (!channel) - return NULL; - - return &channel->slave; + boot_slave = &boot_chan->slave; } diff --git a/src/soc/nvidia/tegra132/spi.h b/src/soc/nvidia/tegra132/spi.h index e535059..c744041 100644 --- a/src/soc/nvidia/tegra132/spi.h +++ b/src/soc/nvidia/tegra132/spi.h @@ -63,11 +63,6 @@ struct tegra_spi_channel { enum spi_xfer_mode xfer_mode; };
-struct cbfs_media; -int initialize_tegra_spi_cbfs_media(struct cbfs_media *media, - void *buffer_address, - size_t buffer_size); - struct tegra_spi_channel *tegra_spi_init(unsigned int bus);
#endif /* __NVIDIA_TEGRA132_SPI_H__ */ diff --git a/src/soc/rockchip/rk3288/Makefile.inc b/src/soc/rockchip/rk3288/Makefile.inc index f9aa377..4c06b40 100644 --- a/src/soc/rockchip/rk3288/Makefile.inc +++ b/src/soc/rockchip/rk3288/Makefile.inc @@ -28,7 +28,6 @@ bootblock-y += timer.c bootblock-y += monotonic_timer.c bootblock-y += clock.c bootblock-y += spi.c -bootblock-y += media.c
romstage-y += cbmem.c romstage-y += timer.c @@ -38,7 +37,6 @@ romstage-y += i2c.c romstage-y += clock.c romstage-y += gpio.c romstage-y += spi.c -romstage-y += media.c romstage-y += sdram.c
ramstage-y += soc.c @@ -49,7 +47,6 @@ ramstage-y += i2c.c ramstage-y += clock.c ramstage-y += spi.c ramstage-y += gpio.c -ramstage-y += media.c ramstage-y += rk808.c ramstage-$(CONFIG_DRIVERS_UART) += uart.c
diff --git a/src/soc/rockchip/rk3288/media.c b/src/soc/rockchip/rk3288/media.c deleted file mode 100644 index 1389eb2..0000000 --- a/src/soc/rockchip/rk3288/media.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright 2014 Rockchip Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <cbfs.h> -#include <string.h> -#include <console/console.h> -#include "soc/rockchip/rk3288/spi.h" - -int init_default_cbfs_media(struct cbfs_media *media) -{ -#if defined(__BOOT_BLOCK__) - return initialize_rockchip_spi_cbfs_media(media, - (void *)CONFIG_CBFS_SRAM_CACHE_ADDRESS, - CONFIG_CBFS_SRAM_CACHE_SIZE); -#else - return initialize_rockchip_spi_cbfs_media(media, - (void *)CONFIG_CBFS_DRAM_CACHE_ADDRESS, - CONFIG_CBFS_DRAM_CACHE_SIZE); -#endif -} diff --git a/src/soc/rockchip/rk3288/spi.c b/src/soc/rockchip/rk3288/spi.c index 844d692..7370199 100644 --- a/src/soc/rockchip/rk3288/spi.c +++ b/src/soc/rockchip/rk3288/spi.c @@ -21,6 +21,9 @@ #include <arch/io.h> #include <stdlib.h> #include <assert.h> +#include <boot_device.h> +#include <cbfs.h> +#include <region.h> #include <spi-generic.h> #include <spi_flash.h> #include <delay.h> @@ -254,64 +257,46 @@ static int rockchip_spi_read(struct spi_slave *slave, void *dest, uint32_t len, return len; }
-struct rockchip_spi_media { - struct spi_slave *slave; - struct cbfs_simple_buffer buffer; -}; +static struct spi_slave *boot_slave;
-static int rockchip_spi_cbfs_open(struct cbfs_media *media) +static ssize_t rockchip_spi_readat(const struct region_device *rdev, + void *dest, size_t offset, size_t count) { - return 0; + return rockchip_spi_read(boot_slave, dest, count, offset); }
-static int rockchip_spi_cbfs_close(struct cbfs_media *media) +static void *rockchip_spi_mmap(const struct region_device *rdev, size_t offset, + size_t count) { - return 0; -} - -static size_t rockchip_spi_cbfs_read(struct cbfs_media *media, void *dest, - size_t offset, size_t count) -{ - struct rockchip_spi_media *spi = - (struct rockchip_spi_media *)media->context; + count = ALIGN_UP(count, 4);
- return rockchip_spi_read(spi->slave, dest, count, offset); + return mmap_helper_rdev_mmap(rdev, offset, count); }
-static void *rockchip_spi_cbfs_map(struct cbfs_media *media, size_t offset, - size_t count) -{ - struct rockchip_spi_media *spi = - (struct rockchip_spi_media *)media->context; +static const struct region_device_ops rockchip_spi_ops = { + .mmap = rockchip_spi_mmap, + .munmap = mmap_helper_rdev_munmap, + .readat = rockchip_spi_readat, +};
- count = ALIGN_UP(count, 4); +#if defined(__BOOT_BLOCK__) +#define MAP_CACHE_ADDR (void *)CONFIG_CBFS_SRAM_CACHE_ADDRESS +#define MAP_CACHE_SIZE CONFIG_CBFS_SRAM_CACHE_SIZE +#else +#define MAP_CACHE_ADDR (void *)CONFIG_CBFS_DRAM_CACHE_ADDRESS +#define MAP_CACHE_SIZE CONFIG_CBFS_DRAM_CACHE_SIZE +#endif
- return cbfs_simple_buffer_map(&spi->buffer, media, offset, count); -} +static struct mmap_helper_region_device mdev = + MMAP_HELPER_REGION_INIT(&rockchip_spi_ops, 0, CONFIG_ROM_SIZE, + MAP_CACHE_ADDR, MAP_CACHE_SIZE);
-static void *rockchip_spi_cbfs_unmap(struct cbfs_media *media, - const void *address) +const struct region_device *boot_device_ro(void) { - struct rockchip_spi_media *spi = - (struct rockchip_spi_media *)media->context; - return cbfs_simple_buffer_unmap(&spi->buffer, address); + return &mdev.rdev; }
-int initialize_rockchip_spi_cbfs_media(struct cbfs_media *media, - void *buffer_address, size_t buffer_size) +void boot_device_init(void) { - static struct rockchip_spi_media context; - static struct rockchip_spi_slave *eslave = &rockchip_spi_slaves[2]; - context.slave = &eslave->slave; - context.buffer.allocated = context.buffer.last_allocate = 0; - context.buffer.buffer = buffer_address; - context.buffer.size = buffer_size; - media->context = (void *)&context; - media->open = rockchip_spi_cbfs_open; - media->close = rockchip_spi_cbfs_close; - media->read = rockchip_spi_cbfs_read; - media->map = rockchip_spi_cbfs_map; - media->unmap = rockchip_spi_cbfs_unmap; - - return 0; + boot_slave = &rockchip_spi_slaves[2].slave; } diff --git a/src/soc/rockchip/rk3288/spi.h b/src/soc/rockchip/rk3288/spi.h index c6880c2..462796a 100644 --- a/src/soc/rockchip/rk3288/spi.h +++ b/src/soc/rockchip/rk3288/spi.h @@ -21,7 +21,6 @@ #define __SOC_ROCKCHIP_RK3288_SPI_H__
/* This driver serves as a CBFS media source. */ -#include <cbfs.h> #include <spi-generic.h> #include <stdint.h>
@@ -195,10 +194,6 @@ check_member(rockchip_spi, rxdr, 0x800); #define SPI_CLEAR_INT_RXOI (1 << 2) #define SPI_CLEAR_INT_TXOI (1 << 3)
-/* Serve as CBFS media source */ -int initialize_rockchip_spi_cbfs_media(struct cbfs_media *media, - void *buffer_address, - size_t buffer_size); void rockchip_spi_init(unsigned int bus);
#endif diff --git a/src/soc/samsung/exynos5250/alternate_cbfs.c b/src/soc/samsung/exynos5250/alternate_cbfs.c index 10b33f0..40e2e1c 100644 --- a/src/soc/samsung/exynos5250/alternate_cbfs.c +++ b/src/soc/samsung/exynos5250/alternate_cbfs.c @@ -19,7 +19,9 @@
#include <assert.h> +#include <boot_device.h> #include <cbfs.h> /* This driver serves as a CBFS media source. */ +#include <region.h> #include <stdlib.h> #include <string.h> #include <console/console.h> @@ -44,7 +46,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; @@ -79,7 +81,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__ /* @@ -110,67 +112,44 @@ static int sdmmc_cbfs_open(struct cbfs_media *media) return 0; }
-static int alternate_cbfs_close(struct cbfs_media *media) { return 0; } +static struct mem_region_device alternate_rdev = MEM_REGION_DEV_INIT(NULL, 0);
-static size_t alternate_cbfs_read(struct cbfs_media *media, void *dest, - size_t offset, size_t count) +const struct region_device *boot_device_ro(void) { - ASSERT(offset + count < alternate_cbfs_size); - memcpy(dest, alternate_cbfs_buffer + offset, count); - return count; -} - -static void *alternate_cbfs_map(struct cbfs_media *media, size_t offset, - size_t count) -{ - ASSERT(offset + count < alternate_cbfs_size); - return alternate_cbfs_buffer + offset; -} - -static void *alternate_cbfs_unmap(struct cbfs_media *media, - const void *buffer) { return 0; } - -static int initialize_exynos_sdmmc_cbfs_media(struct cbfs_media *media) -{ - printk(BIOS_DEBUG, "Using Exynos alternate boot mode SDMMC\n"); - - 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; + if (*iram_secondary_base == SECONDARY_BASE_BOOT_USB) + return &alternate_rdev.rdev;
- return 0; + 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; + } }
-static int initialize_exynos_usb_cbfs_media(struct cbfs_media *media) +void boot_device_init(void) { - printk(BIOS_DEBUG, "Using Exynos alternate boot mode USB A-A\n"); - - 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; - - return 0; -} + mem_region_device_init(&alternate_rdev, alternate_cbfs_buffer, + alternate_cbfs_size);
-int init_default_cbfs_media(struct cbfs_media *media) -{ - if (*iram_secondary_base == SECONDARY_BASE_BOOT_USB) - return initialize_exynos_usb_cbfs_media(media); + if (*iram_secondary_base == SECONDARY_BASE_BOOT_USB) { + usb_cbfs_open(); + return; + }
switch (exynos_power->om_stat & OM_STAT_MASK) { case OM_STAT_SDMMC: - return initialize_exynos_sdmmc_cbfs_media(media); + sdmmc_cbfs_open(); + break; case OM_STAT_SPI: - return initialize_exynos_spi_cbfs_media(media, - (void*)CONFIG_CBFS_CACHE_ADDRESS, - CONFIG_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 0; } } diff --git a/src/soc/samsung/exynos5250/spi.c b/src/soc/samsung/exynos5250/spi.c index 33ec698..cb8b096 100644 --- a/src/soc/samsung/exynos5250/spi.c +++ b/src/soc/samsung/exynos5250/spi.c @@ -145,69 +145,47 @@ int exynos_spi_close(struct exynos_spi *regs) }
// SPI as CBFS media. -struct exynos_spi_media { - struct exynos_spi *regs; - struct cbfs_simple_buffer buffer; -}; - -static int exynos_spi_cbfs_open(struct cbfs_media *media) { - struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context; - DEBUG_SPI("exynos_spi_cbfs_open\n"); - return exynos_spi_open(spi->regs); -} +static struct exynos_spi *boot_slave_regs;
-static int exynos_spi_cbfs_close(struct cbfs_media *media) { - struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context; - DEBUG_SPI("exynos_spi_cbfs_close\n"); - return exynos_spi_close(spi->regs); +void exynos_init_spi_boot_device(void) +{ + boot_slave_regs = (void *)EXYNOS5_SPI1_BASE; }
-static size_t exynos_spi_cbfs_read(struct cbfs_media *media, void *dest, - size_t offset, size_t count) { - struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context; +static ssize_t exynos_spi_readat(const struct region_device *rdev, void *dest, + size_t offset, size_t count) +{ int bytes; DEBUG_SPI("exynos_spi_cbfs_read(%u)\n", count); - bytes = exynos_spi_read(spi->regs, dest, count, offset); - // Flush and re-open the device. - exynos_spi_close(spi->regs); - exynos_spi_open(spi->regs); + exynos_spi_open(boot_slave_regs); + bytes = exynos_spi_read(boot_slave_regs, dest, count, offset); + exynos_spi_close(boot_slave_regs); return bytes; }
-static void *exynos_spi_cbfs_map(struct cbfs_media *media, size_t offset, - size_t count) { - struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context; +static void *exynos_spi_map(const struct region_device *rdev, + size_t offset, size_t count) +{ DEBUG_SPI("exynos_spi_cbfs_map\n"); - // See exynos_spi_rx_tx for I/O alignment limitation. + // exynos: spi_rx_tx may work in 4 byte-width-transmission mode and + // requires buffer memory address to be aligned. if (count % 4) count += 4 - (count % 4); - return cbfs_simple_buffer_map(&spi->buffer, media, offset, count); + return mmap_helper_rdev_mmap(rdev, offset, count); }
-static void *exynos_spi_cbfs_unmap(struct cbfs_media *media, - const void *address) { - struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context; - DEBUG_SPI("exynos_spi_cbfs_unmap\n"); - return cbfs_simple_buffer_unmap(&spi->buffer, address); -} +static const struct region_device_ops exynos_spi_ops = { + .mmap = exynos_spi_map, + .munmap = mmap_helper_rdev_munmap, + .readat = exynos_spi_readat, +};
-int initialize_exynos_spi_cbfs_media(struct cbfs_media *media, - void *buffer_address, - size_t buffer_size) { - // TODO Replace static variable to support multiple streams. - static struct exynos_spi_media context; - DEBUG_SPI("initialize_exynos_spi_cbfs_media\n"); - - context.regs = (void*)EXYNOS5_SPI1_BASE; - context.buffer.allocated = context.buffer.last_allocate = 0; - context.buffer.buffer = buffer_address; - context.buffer.size = buffer_size; - media->context = (void*)&context; - media->open = exynos_spi_cbfs_open; - media->close = exynos_spi_cbfs_close; - media->read = exynos_spi_cbfs_read; - media->map = exynos_spi_cbfs_map; - media->unmap = exynos_spi_cbfs_unmap; +static struct mmap_helper_region_device mdev = + MMAP_HELPER_REGION_INIT(&exynos_spi_ops, 0, CONFIG_ROM_SIZE, + (void *)CONFIG_CBFS_CACHE_ADDRESS, + CONFIG_CBFS_CACHE_SIZE);
- return 0; +const struct region_device *exynos_spi_boot_device(void) +{ + return &mdev.rdev; } diff --git a/src/soc/samsung/exynos5250/spi.h b/src/soc/samsung/exynos5250/spi.h index 4301d42..e4d62d2 100644 --- a/src/soc/samsung/exynos5250/spi.h +++ b/src/soc/samsung/exynos5250/spi.h @@ -92,8 +92,6 @@ int exynos_spi_open(struct exynos_spi *regs); int exynos_spi_read(struct exynos_spi *regs, void *dest, u32 len, u32 off); int exynos_spi_close(struct exynos_spi *regs);
-/* Serve as CBFS media source */ -int initialize_exynos_spi_cbfs_media(struct cbfs_media *media, - void *buffer_address, - size_t buffer_size); +void exynos_init_spi_boot_device(void); +const struct region_device *exynos_spi_boot_device(void); #endif diff --git a/src/soc/samsung/exynos5420/alternate_cbfs.c b/src/soc/samsung/exynos5420/alternate_cbfs.c index d19098b..eab6f79 100644 --- a/src/soc/samsung/exynos5420/alternate_cbfs.c +++ b/src/soc/samsung/exynos5420/alternate_cbfs.c @@ -19,7 +19,9 @@
#include <assert.h> +#include <boot_device.h> #include <cbfs.h> /* This driver serves as a CBFS media source. */ +#include <region.h> #include <stdlib.h> #include <string.h> #include <arch/cache.h> @@ -45,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; @@ -83,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__ /* @@ -117,67 +119,44 @@ static int sdmmc_cbfs_open(struct cbfs_media *media) return 0; }
-static int alternate_cbfs_close(struct cbfs_media *media) { return 0; } +static struct mem_region_device alternate_rdev = MEM_REGION_DEV_INIT(NULL, 0);
-static size_t alternate_cbfs_read(struct cbfs_media *media, void *dest, - size_t offset, size_t count) +const struct region_device *boot_device_ro(void) { - ASSERT(offset + count < alternate_cbfs_size); - memcpy(dest, alternate_cbfs_buffer + offset, count); - return count; -} - -static void *alternate_cbfs_map(struct cbfs_media *media, size_t offset, - size_t count) -{ - ASSERT(offset + count < alternate_cbfs_size); - return alternate_cbfs_buffer + offset; -} - -static void *alternate_cbfs_unmap(struct cbfs_media *media, - const void *buffer) { return 0; } - -static int initialize_exynos_sdmmc_cbfs_media(struct cbfs_media *media) -{ - printk(BIOS_DEBUG, "Using Exynos alternate boot mode SDMMC\n"); - - 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; + if (*iram_secondary_base == SECONDARY_BASE_BOOT_USB) + return &alternate_rdev.rdev;
- return 0; + 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; + } }
-static int initialize_exynos_usb_cbfs_media(struct cbfs_media *media) +void boot_device_init(void) { - printk(BIOS_DEBUG, "Using Exynos alternate boot mode USB A-A\n"); - - 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; - - return 0; -} + mem_region_device_init(&alternate_rdev, alternate_cbfs_buffer, + alternate_cbfs_size);
-int init_default_cbfs_media(struct cbfs_media *media) -{ - if (*iram_secondary_base == SECONDARY_BASE_BOOT_USB) - return initialize_exynos_usb_cbfs_media(media); + if (*iram_secondary_base == SECONDARY_BASE_BOOT_USB) { + usb_cbfs_open(); + return; + }
switch (exynos_power->om_stat & OM_STAT_MASK) { case OM_STAT_SDMMC: - return initialize_exynos_sdmmc_cbfs_media(media); + sdmmc_cbfs_open(); + break; case OM_STAT_SPI: - return initialize_exynos_spi_cbfs_media(media, - (void*)CONFIG_CBFS_CACHE_ADDRESS, - CONFIG_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 0; } } diff --git a/src/soc/samsung/exynos5420/spi.c b/src/soc/samsung/exynos5420/spi.c index 36742a7..7f3a136 100644 --- a/src/soc/samsung/exynos5420/spi.c +++ b/src/soc/samsung/exynos5420/spi.c @@ -244,75 +244,43 @@ static int exynos_spi_read(struct spi_slave *slave, void *dest, uint32_t len, }
// SPI as CBFS media. -struct exynos_spi_media { - struct spi_slave *slave; - struct cbfs_simple_buffer buffer; -}; - -static int exynos_spi_cbfs_open(struct cbfs_media *media) -{ - struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context; - DEBUG_SPI("exynos_spi_cbfs_open\n"); - return spi_claim_bus(spi->slave); -} +static struct exynos_spi_slave *boot_slave;
-static int exynos_spi_cbfs_close(struct cbfs_media *media) +void exynos_init_spi_boot_device(void) { - struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context; - DEBUG_SPI("exynos_spi_cbfs_close\n"); - spi_release_bus(spi->slave); - return 0; + boot_slave = &exynos_spi_slaves[1]; }
-static size_t exynos_spi_cbfs_read(struct cbfs_media *media, void *dest, - size_t offset, size_t count) +static ssize_t exynos_spi_readat(const struct region_device *rdev, void *dest, + size_t offset, size_t count) { - struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context; - int bytes; DEBUG_SPI("exynos_spi_cbfs_read(%u)\n", count); - bytes = exynos_spi_read(spi->slave, dest, count, offset); - return bytes; + return exynos_spi_read(&boot_slave->slave, dest, count, offset); }
-static void *exynos_spi_cbfs_map(struct cbfs_media *media, size_t offset, - size_t count) +static void *exynos_spi_map(const struct region_device *rdev, + size_t offset, size_t count) { - struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context; DEBUG_SPI("exynos_spi_cbfs_map\n"); // exynos: spi_rx_tx may work in 4 byte-width-transmission mode and // requires buffer memory address to be aligned. if (count % 4) count += 4 - (count % 4); - return cbfs_simple_buffer_map(&spi->buffer, media, offset, count); + return mmap_helper_rdev_mmap(rdev, offset, count); }
-static void *exynos_spi_cbfs_unmap(struct cbfs_media *media, - const void *address) -{ - struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context; - DEBUG_SPI("exynos_spi_cbfs_unmap\n"); - return cbfs_simple_buffer_unmap(&spi->buffer, address); -} +static const struct region_device_ops exynos_spi_ops = { + .mmap = exynos_spi_map, + .munmap = mmap_helper_rdev_munmap, + .readat = exynos_spi_readat, +};
-int initialize_exynos_spi_cbfs_media(struct cbfs_media *media, - void *buffer_address, - size_t buffer_size) -{ - // TODO Replace static variable to support multiple streams. - static struct exynos_spi_media context; - static struct exynos_spi_slave *eslave = &exynos_spi_slaves[1]; - DEBUG_SPI("initialize_exynos_spi_cbfs_media\n"); - - context.slave = &eslave->slave; - context.buffer.allocated = context.buffer.last_allocate = 0; - context.buffer.buffer = buffer_address; - context.buffer.size = buffer_size; - media->context = (void*)&context; - media->open = exynos_spi_cbfs_open; - media->close = exynos_spi_cbfs_close; - media->read = exynos_spi_cbfs_read; - media->map = exynos_spi_cbfs_map; - media->unmap = exynos_spi_cbfs_unmap; +static struct mmap_helper_region_device mdev = + MMAP_HELPER_REGION_INIT(&exynos_spi_ops, 0, CONFIG_ROM_SIZE, + (void *)CONFIG_CBFS_CACHE_ADDRESS, + CONFIG_CBFS_CACHE_SIZE);
- return 0; +const struct region_device *exynos_spi_boot_device(void) +{ + return &mdev.rdev; } diff --git a/src/soc/samsung/exynos5420/spi.h b/src/soc/samsung/exynos5420/spi.h index 78cca6f..3b03561 100644 --- a/src/soc/samsung/exynos5420/spi.h +++ b/src/soc/samsung/exynos5420/spi.h @@ -91,8 +91,6 @@ check_member(exynos_spi, fb_clk, 0x2c); #define SPI_RX_BYTE_SWAP (1 << 6) #define SPI_RX_HWORD_SWAP (1 << 7)
-/* Serve as CBFS media source */ -int initialize_exynos_spi_cbfs_media(struct cbfs_media *media, - void *buffer_address, - size_t buffer_size); +void exynos_init_spi_boot_device(void); +const struct region_device *exynos_spi_boot_device(void); #endif