From 6fe0cab205e131525efbfce4f59da344b1e76598 Mon Sep 17 00:00:00 2001 From: Hung-Te Lin Date: Tue, 22 Jan 2013 18:57:56 +0800 Subject: [PATCH] Extend CBFS to support arbitrary ROM source media. Summary: Isolate CBFS underlying I/O to board/arch-specific implementations as "media stream", to allow loading and booting romstage on non-x86. CBFS functions now all take a new "media source" parameter; use CBFS_DEFAULT_MEDIA if you simply want to load from main firmware. API Changes: cbfs_find => cbfs_get_file. cbfs_find_file => cbfs_get_file_content. cbfs_get_file => cbfs_get_file_content with correct type. CBFS used to work only on memory-mapped ROM (all x86). For platforms like ARM, the ROM may come from USB, UART, or SPI -- any serial devices and not available for memory mapping. To support these devices (and allowing CBFS to read from multiple source at the same time), CBFS operations are now virtual-ized into "cbfs_media". To simplify porting existing code, every media source must support both "reading into pre-allocated memory (read)" and "read and return an allocated buffer (map)". For devices without native memory-mapped ROM, "cbfs_simple_buffer*" provides simple memory mapping simulation. Every CBFS function now takes a cbfs_media* as parameter. CBFS_DEFAULT_MEDIA is defined for CBFS functions to automatically initialize a per-board default media (CBFS will internally calls init_default_cbfs_media). Also revised CBFS function names relying on memory mapped backend (ex, "cbfs_find" => actually loads files). Now we only have two getters: struct cbfs_file *entry = cbfs_get_file(media, name); void *data = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, name, type); Test results: - Verified to work on x86/qemu. - Compiles on ARM, and follow up commit will provide working SPI driver. Change-Id: Iac911ded25a6f2feffbf3101a81364625bb07746 Signed-off-by: Hung-Te Lin Reviewed-on: http://review.coreboot.org/2182 Tested-by: build bot (Jenkins) Reviewed-by: Ronald G. Minnich --- src/arch/armv7/boot/coreboot_table.c | 4 +- src/arch/armv7/bootblock_simple.c | 4 +- src/arch/armv7/include/arch/cbfs.h | 103 +++------ src/arch/x86/boot/coreboot_table.c | 4 +- src/arch/x86/boot/smbios.c | 12 +- src/arch/x86/lib/Makefile.inc | 3 + src/arch/x86/lib/cbfs_and_run.c | 2 +- src/arch/x86/lib/rom_media.c | 101 +++++++++ src/cpu/intel/microcode/microcode.c | 5 +- src/cpu/samsung/exynos5-common/Makefile.inc | 4 +- src/cpu/samsung/exynos5-common/spi.c | 7 + src/cpu/samsung/exynos5250/Kconfig | 16 ++ src/cpu/via/nano/update_ucode.c | 2 +- src/device/oprom/realmode/x86.c | 8 +- src/device/oprom/yabel/vbe.c | 4 +- src/device/pci_rom.c | 9 +- src/drivers/pc80/mc146818rtc.c | 6 +- src/include/cbfs.h | 37 +++- src/include/cbfs_core.h | 72 +++++-- src/include/endian.h | 25 +++ src/lib/cbfs.c | 147 +++++++++---- src/lib/cbfs_core.c | 200 ++++++++++-------- src/lib/hardwaremain.c | 5 +- src/lib/selfboot.c | 9 - src/mainboard/google/snow/bootblock.c | 4 + src/mainboard/samsung/lumpy/romstage.c | 2 +- .../amd/agesa/family15tn/fam15tn_callouts.c | 4 +- src/northbridge/intel/i82830/vga.c | 2 +- src/northbridge/intel/sandybridge/raminit.c | 4 +- 29 files changed, 546 insertions(+), 259 deletions(-) create mode 100644 src/arch/x86/lib/rom_media.c create mode 100644 src/cpu/samsung/exynos5-common/spi.c create mode 100644 src/include/endian.h diff --git a/src/arch/armv7/boot/coreboot_table.c b/src/arch/armv7/boot/coreboot_table.c index 86a004d887..b2d88aa776 100644 --- a/src/arch/armv7/boot/coreboot_table.c +++ b/src/arch/armv7/boot/coreboot_table.c @@ -640,7 +640,9 @@ unsigned long write_coreboot_table( #if CONFIG_USE_OPTION_TABLE { - struct cmos_option_table *option_table = cbfs_find_file("cmos_layout.bin", 0x1aa); + struct cmos_option_table *option_table = cbfs_get_file_content( + CBFS_DEFAULT_MEDIA, "cmos_layout.bin", + CBFS_COMPONENT_CMOS_LAYOUT); if (option_table) { struct lb_record *rec_dest = lb_new_record(head); /* Copy the option config table, it's already a lb_record... */ diff --git a/src/arch/armv7/bootblock_simple.c b/src/arch/armv7/bootblock_simple.c index af76d4c973..d97075e2f8 100644 --- a/src/arch/armv7/bootblock_simple.c +++ b/src/arch/armv7/bootblock_simple.c @@ -45,7 +45,9 @@ void main(unsigned long bist) } printk(BIOS_INFO, "bootblock main(): loading romstage\n"); - romstage_entry = loadstage(target1); + romstage_entry = (unsigned long)cbfs_load_stage( + CBFS_DEFAULT_MEDIA, target1); + printk(BIOS_INFO, "bootblock main(): jumping to romstage\n"); if (romstage_entry) bootblock_exit(romstage_entry); hlt(); diff --git a/src/arch/armv7/include/arch/cbfs.h b/src/arch/armv7/include/arch/cbfs.h index f060643936..e34a0d2b27 100644 --- a/src/arch/armv7/include/arch/cbfs.h +++ b/src/arch/armv7/include/arch/cbfs.h @@ -20,82 +20,41 @@ #ifndef __INCLUDE_ARCH_CBFS__ #define __INCLUDE_ARCH_CBFS__ -#include -#include #include #include -#include +// TODO FIXME This file is only for providing CBFS function in bootblock. +// Should be removed once bootblock can link lib/* files. +#include "lib/cbfs.c" -static int cbfs_check_magic(struct cbfs_file *file) -{ - return strcmp(file->magic, CBFS_FILE_MAGIC) ? 0 : 1; +// mem* and ulzma are now workarounds for bootblock compilation. +void *memcpy(void *dest, const void *src, size_t n) { + char *d = (char *)dest; + const char *s = (const char*)src; + while (n-- > 0) + *d++ = *s++; + return dest; } -static unsigned long loadstage(const char* target) -{ - unsigned long offset, align; - struct cbfs_header *header = (struct cbfs_header *)(CONFIG_BOOTBLOCK_BASE + 0x40); - /* FIXME: magic offsets */ - // if (ntohl(header->magic) != CBFS_HEADER_MAGIC) - // printk(BIOS_ERR, "ERROR: No valid CBFS header found!\n"); - - offset = ntohl(header->offset); - align = ntohl(header->align); - printk(BIOS_INFO, "cbfs header (0x%p)\n", header); - printk(BIOS_INFO, "\tmagic: 0x%08x\n", ntohl(header->magic)); - printk(BIOS_INFO, "\tversion: 0x%08x\n", ntohl(header->version)); - printk(BIOS_INFO, "\tromsize: 0x%08x\n", ntohl(header->romsize)); - printk(BIOS_INFO, "\tbootblocksize: 0x%08x\n", ntohl(header->bootblocksize)); - printk(BIOS_INFO, "\talign: 0x%08x\n", ntohl(header->align)); - printk(BIOS_INFO, "\toffset: 0x%08x\n", ntohl(header->offset)); - while(1) { - struct cbfs_file *file; - struct cbfs_stage *stage; - /* FIXME: SPI image hack */ - file = (struct cbfs_file *)(offset + CONFIG_SPI_IMAGE_HACK); - if (!cbfs_check_magic(file)) { - printk(BIOS_INFO, "magic is wrong, file: %p\n", file); - return 0; - } - if (!strcmp(CBFS_NAME(file), target)) { - uint32_t load, entry; - printk(BIOS_INFO, "CBFS name matched, offset: %p\n", file); - printk(BIOS_INFO, "\tmagic: %02x%02x%02x%02x%02x%02x%02x%02x\n", - file->magic[0], file->magic[1], file->magic[2], file->magic[3], - file->magic[4], file->magic[5], file->magic[6], file->magic[7]); - printk(BIOS_INFO, "\tlen: 0x%08x\n", ntohl(file->len)); - printk(BIOS_INFO, "\ttype: 0x%08x\n", ntohl(file->type)); - printk(BIOS_INFO, "\tchecksum: 0x%08x\n", ntohl(file->checksum)); - printk(BIOS_INFO, "\toffset: 0x%08x\n", ntohl(file->offset)); - /* exploit the fact that this is all word-aligned. */ - stage = CBFS_SUBHEADER(file); - load = stage->load; - entry = stage->entry; - int i; - u32 *to = (void *)load; - u32 *from = (void *)((u8 *)stage+sizeof(*stage)); - /* we could do memmove/memset here. But the math gets messy. - * far easier just to do what we want. - */ - printk(BIOS_INFO, "entry: 0x%08x, load: 0x%08x, " - "len: 0x%08x, memlen: 0x%08x\n", entry, - load, stage->len, stage->memlen); - for(i = 0; i < stage->len; i += 4) - *to++ = *from++; - for(; i < stage->memlen; i += 4) - *to++ = 0; - return entry; - } - int flen = ntohl(file->len); - int foffset = ntohl(file->offset); - unsigned long oldoffset = offset; - offset = ALIGN(offset + foffset + flen, align); - printk(BIOS_INFO, "offset: 0x%08lx\n", offset); - if (offset <= oldoffset) - return 0; - if (offset > CONFIG_ROMSTAGE_SIZE) - return 0; - } +void *memset(void *dest, int c, size_t n) { + char *d = (char*)dest; + while (n-- > 0) + *d++ = c; + return dest; } -#endif + +int memcmp(const void *ptr1, const void *ptr2, size_t n) { + const char *s1 = (const char*)ptr1, *s2 = (const char*)ptr2; + int c; + while (n-- > 0) + if ((c = *s1++ - *s2++)) + return c; + return 0; +} + +unsigned long ulzma(unsigned char *src, unsigned char *dest) { + // TODO remove this. + return -1; +} + +#endif // __INCLUDE_ARCH_CBFS__ diff --git a/src/arch/x86/boot/coreboot_table.c b/src/arch/x86/boot/coreboot_table.c index 8dccd77287..04fba47b3f 100644 --- a/src/arch/x86/boot/coreboot_table.c +++ b/src/arch/x86/boot/coreboot_table.c @@ -638,7 +638,9 @@ unsigned long write_coreboot_table( #if CONFIG_USE_OPTION_TABLE { - struct cmos_option_table *option_table = cbfs_find_file("cmos_layout.bin", 0x1aa); + struct cmos_option_table *option_table = cbfs_get_file_content( + CBFS_DEFAULT_MEDIA, "cmos_layout.bin", + CBFS_COMPONENT_CMOS_LAYOUT); if (option_table) { struct lb_record *rec_dest = lb_new_record(head); /* Copy the option config table, it's already a lb_record... */ diff --git a/src/arch/x86/boot/smbios.c b/src/arch/x86/boot/smbios.c index 72e70bacea..f65ced2746 100644 --- a/src/arch/x86/boot/smbios.c +++ b/src/arch/x86/boot/smbios.c @@ -120,7 +120,6 @@ static int smbios_processor_name(char *start) static int smbios_write_type0(unsigned long *current, int handle) { - struct cbfs_header *hdr; struct smbios_type0 *t = (struct smbios_type0 *)*current; int len = sizeof(struct smbios_type0); @@ -143,8 +142,15 @@ static int smbios_write_type0(unsigned long *current, int handle) vboot_data->vbt10 = (u32)t->eos + (version_offset - 1); #endif - if ((hdr = get_cbfs_header()) != (struct cbfs_header *)0xffffffff) - t->bios_rom_size = (ntohl(hdr->romsize) / 65535) - 1; + { + const struct cbfs_header *header; + u32 romsize = CONFIG_ROM_SIZE; + header = cbfs_get_header(CBFS_DEFAULT_MEDIA); + if (header != CBFS_HEADER_INVALID_ADDRESS) + romsize = ntohl(header->romsize); + t->bios_rom_size = (romsize / 65535) - 1; + } + t->system_bios_major_release = 4; t->bios_characteristics = BIOS_CHARACTERISTICS_PCI_SUPPORTED | diff --git a/src/arch/x86/lib/Makefile.inc b/src/arch/x86/lib/Makefile.inc index 2186072ab4..f4dc8b8426 100644 --- a/src/arch/x86/lib/Makefile.inc +++ b/src/arch/x86/lib/Makefile.inc @@ -8,13 +8,16 @@ ramstage-$(CONFIG_IOAPIC) += ioapic.c ramstage-y += memset.c ramstage-y += memcpy.c ramstage-y += ebda.c +ramstage-y += rom_media.c romstage-y += romstage_console.c romstage-y += cbfs_and_run.c romstage-y += memset.c romstage-y += memcpy.c +romstage-y += rom_media.c smm-y += memset.c smm-y += memcpy.c +smm-y += rom_media.c $(obj)/arch/x86/lib/console.ramstage.o :: $(obj)/build.h diff --git a/src/arch/x86/lib/cbfs_and_run.c b/src/arch/x86/lib/cbfs_and_run.c index 1f87e7ab62..a023141650 100644 --- a/src/arch/x86/lib/cbfs_and_run.c +++ b/src/arch/x86/lib/cbfs_and_run.c @@ -28,7 +28,7 @@ static void cbfs_and_run_core(const char *filename, unsigned ebp) timestamp_add_now(TS_START_COPYRAM); print_debug("Loading image.\n"); - dst = cbfs_load_stage(filename); + dst = cbfs_load_stage(CBFS_DEFAULT_MEDIA, filename); if ((void *)dst == (void *) -1) die("FATAL: Essential component is missing.\n"); diff --git a/src/arch/x86/lib/rom_media.c b/src/arch/x86/lib/rom_media.c new file mode 100644 index 0000000000..ed2122cb4e --- /dev/null +++ b/src/arch/x86/lib/rom_media.c @@ -0,0 +1,101 @@ +/* + * 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 +#include + +#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 +#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/intel/microcode/microcode.c b/src/cpu/intel/microcode/microcode.c index 15d6513b33..713a6df19b 100644 --- a/src/cpu/intel/microcode/microcode.c +++ b/src/cpu/intel/microcode/microcode.c @@ -166,8 +166,9 @@ void intel_update_microcode_from_cbfs(void) #ifdef __PRE_RAM__ microcode_blob = walkcbfs((char *) MICROCODE_CBFS_FILE); #else - microcode_blob = cbfs_find_file(MICROCODE_CBFS_FILE, - CBFS_TYPE_MICROCODE); + microcode_blob = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, + MICROCODE_CBFS_FILE, + CBFS_TYPE_MICROCODE); #endif intel_update_microcode(microcode_blob); } diff --git a/src/cpu/samsung/exynos5-common/Makefile.inc b/src/cpu/samsung/exynos5-common/Makefile.inc index cad6cb3de7..d919347836 100644 --- a/src/cpu/samsung/exynos5-common/Makefile.inc +++ b/src/cpu/samsung/exynos5-common/Makefile.inc @@ -1,2 +1,2 @@ -#romstage-y += soc.c -romstage-y += spl_boot.c +romstage-y += spi.c +ramstage-y += spi.c diff --git a/src/cpu/samsung/exynos5-common/spi.c b/src/cpu/samsung/exynos5-common/spi.c new file mode 100644 index 0000000000..e13eadf3fe --- /dev/null +++ b/src/cpu/samsung/exynos5-common/spi.c @@ -0,0 +1,7 @@ +#include + +/* TODO provide a real SPI driver here for firmware media. */ + +int init_default_cbfs_media(struct cbfs_media *media) { + return -1; +} diff --git a/src/cpu/samsung/exynos5250/Kconfig b/src/cpu/samsung/exynos5250/Kconfig index f5beddcdb4..41a1446ef2 100644 --- a/src/cpu/samsung/exynos5250/Kconfig +++ b/src/cpu/samsung/exynos5250/Kconfig @@ -48,6 +48,22 @@ config ROMSTAGE_SIZE hex default 0x10000 +# TODO Change this to some better address not overlapping bootblock when +# cbfstool supports creating header in arbitrary location. +config CBFS_HEADER_ROM_OFFSET + hex "offset of master CBFS header in ROM" + default 0x2040 + +# TODO We may probably move this to board-specific implementation files instead +# of KConfig values. +config CBFS_CACHE_ADDRESS + hex "memory address to put CBFS cache data" + default 0x02060000 + +config CBFS_CACHE_SIZE + hex "size of CBFS cache data" + default 0x000017000 + # FIXME: This is for copying SPI content into SRAM temporarily and # will be removed when we have the SPI streaming driver implemented. config SPI_IMAGE_HACK diff --git a/src/cpu/via/nano/update_ucode.c b/src/cpu/via/nano/update_ucode.c index 8f7ee224a4..d5757f87a7 100644 --- a/src/cpu/via/nano/update_ucode.c +++ b/src/cpu/via/nano/update_ucode.c @@ -105,7 +105,7 @@ unsigned int nano_update_ucode(void) const struct cbfs_file *cbfs_ucode; u32 fms = cpuid_eax(0x1); - cbfs_ucode = cbfs_find("cpu_microcode_blob.bin"); + cbfs_ucode = cbfs_get_file(CBFS_DEFAULT_MEDIA, "cpu_microcode_blob.bin"); /* Oops, did you forget to include the microcode ? */ if(cbfs_ucode == NULL) { printk(BIOS_ALERT, "WARNING: No microcode file found in CBFS. " diff --git a/src/device/oprom/realmode/x86.c b/src/device/oprom/realmode/x86.c index 697d869821..07eff0ddee 100644 --- a/src/device/oprom/realmode/x86.c +++ b/src/device/oprom/realmode/x86.c @@ -248,8 +248,9 @@ void vbe_set_graphics(void) #if CONFIG_BOOTSPLASH struct jpeg_decdata *decdata; decdata = malloc(sizeof(*decdata)); - unsigned char *jpeg = cbfs_find_file("bootsplash.jpg", - CBFS_TYPE_BOOTSPLASH); + unsigned char *jpeg = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, + "bootsplash.jpg", + CBFS_TYPE_BOOTSPLASH); if (!jpeg) { printk(BIOS_DEBUG, "VBE: No bootsplash found.\n"); return; @@ -366,7 +367,8 @@ void do_vsmbios(void) printk(BIOS_SPEW, "VSA: Real mode stub @%p: %d bytes\n", REALMODE_BASE, (u32)&__realmode_code_size); - if ((unsigned int)cbfs_load_stage("vsa") != VSA2_ENTRY_POINT) { + if ((unsigned int)cbfs_load_stage(CBFS_DEFAULT_MEDIA, "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 9dbe07cdd5..5952dae568 100644 --- a/src/device/oprom/yabel/vbe.c +++ b/src/device/oprom/yabel/vbe.c @@ -725,7 +725,9 @@ void vbe_set_graphics(void) * cares. */ // int imagesize = 1024*768*2; - unsigned char *jpeg = cbfs_find_file("bootsplash.jpg", CBFS_TYPE_BOOTSPLASH); + unsigned char *jpeg = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, + "bootsplash.jpg", + CBFS_TYPE_BOOTSPLASH); 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 fe67515936..bb0d76066e 100644 --- a/src/device/pci_rom.c +++ b/src/device/pci_rom.c @@ -35,7 +35,8 @@ 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(dev->vendor, dev->device, NULL); + rom_header = cbfs_load_optionrom(CBFS_DEFAULT_MEDIA, dev->vendor, + dev->device, NULL); u32 vendev = (dev->vendor << 16) | dev->device; u32 mapped_vendev = vendev; @@ -45,8 +46,10 @@ struct rom_header *pci_rom_probe(struct device *dev) if (!rom_header) { if (vendev != mapped_vendev) { - rom_header = cbfs_load_optionrom(mapped_vendev >> 16, - mapped_vendev & 0xffff , NULL); + rom_header = cbfs_load_optionrom( + CBFS_DEFAULT_MEDIA, + mapped_vendev >> 16, + mapped_vendev & 0xffff, NULL); } } diff --git a/src/drivers/pc80/mc146818rtc.c b/src/drivers/pc80/mc146818rtc.c index d8d1778b5c..5ffa9d7fc4 100644 --- a/src/drivers/pc80/mc146818rtc.c +++ b/src/drivers/pc80/mc146818rtc.c @@ -190,7 +190,8 @@ int get_option(void *dest, const char *name) namelen = strnlen(name, CMOS_MAX_NAME_LENGTH); /* find the requested entry record */ - ct=cbfs_find_file("cmos_layout.bin", CBFS_COMPONENT_CMOS_LAYOUT); + ct = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "cmos_layout.bin", + CBFS_COMPONENT_CMOS_LAYOUT); if (!ct) { printk(BIOS_ERR, "RTC: cmos_layout.bin could not be found. " "Options are disabled\n"); @@ -268,7 +269,8 @@ int set_option(const char *name, void *value) namelen = strnlen(name, CMOS_MAX_NAME_LENGTH); /* find the requested entry record */ - ct=cbfs_find_file("cmos_layout.bin", CBFS_COMPONENT_CMOS_LAYOUT); + ct = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "cmos_layout.bin", + CBFS_COMPONENT_CMOS_LAYOUT); if (!ct) { printk(BIOS_ERR, "cmos_layout.bin could not be found. Options are disabled\n"); return(-2); diff --git a/src/include/cbfs.h b/src/include/cbfs.h index b33e9327a8..9bfe2ceb96 100644 --- a/src/include/cbfs.h +++ b/src/include/cbfs.h @@ -2,6 +2,7 @@ * This file is part of the coreboot project. * * Copyright (C) 2008 Jordan Crouse + * 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 @@ -49,14 +50,38 @@ #ifndef _CBFS_H_ #define _CBFS_H_ -#include "cbfs_core.h" -#include +#include -void *cbfs_load_payload(struct lb_memory *lb_mem, const char *name); -void *cbfs_load_stage(const char *name); -int cbfs_execute_stage(const char *name); -void *cbfs_load_optionrom(u16 vendor, u16 device, void * dest); +int cbfs_execute_stage(struct cbfs_media *media, const char *name); +void *cbfs_load_optionrom(struct cbfs_media *media, uint16_t vendor, + uint16_t device, void * dest); +void *cbfs_load_payload(struct cbfs_media *media, const char *name); +void *cbfs_load_stage(struct cbfs_media *media, const char *name); + +/* 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); + +// Utility functions int run_address(void *f); + +/* Defined in src/lib/selfboot.c */ +struct lb_memory; int selfboot(struct lb_memory *mem, struct cbfs_payload *payload); + +/* Defined in individual arch / board implementation. */ +int init_default_cbfs_media(struct cbfs_media *media); + #endif diff --git a/src/include/cbfs_core.h b/src/include/cbfs_core.h index a3c54b18f7..20636e244a 100644 --- a/src/include/cbfs_core.h +++ b/src/include/cbfs_core.h @@ -3,6 +3,7 @@ * * Copyright (C) 2008 Jordan Crouse * 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 @@ -50,6 +51,10 @@ #ifndef _CBFS_CORE_H_ #define _CBFS_CORE_H_ +#include +#include +#include + /** These are standard values for the known compression alogrithms that coreboot knows about for stages and payloads. Of course, other CBFS users can use whatever @@ -74,24 +79,18 @@ #define CBFS_COMPONENT_CMOS_DEFAULT 0xaa #define CBFS_COMPONENT_CMOS_LAYOUT 0x01aa - -/** this is the master cbfs header - it need to be - located somewhere in the bootblock. Where it - actually lives is up to coreboot. On x86, a - pointer to this header will live at 0xFFFFFFFC, - so we can easily find it. */ - #define CBFS_HEADER_MAGIC 0x4F524243 -#if CONFIG_ARCH_X86 -#define CBFS_HEADPTR_ADDR 0xFFFFFFFC -#elif CONFIG_ARCH_ARMV7 -/* FIXME: This could also be 0xFFFF0000 with HIVECS enabled */ -#define CBFS_HEADPTR_ADDR 0x0000000C -#endif #define CBFS_HEADER_VERSION1 0x31313131 #define CBFS_HEADER_VERSION2 0x31313132 #define CBFS_HEADER_VERSION CBFS_HEADER_VERSION2 +#define CBFS_HEADER_INVALID_ADDRESS ((void*)(0xffffffff)) + +/** this is the master cbfs header - it need to be located somewhere available + to bootblock (to load romstage). Where it actually lives is up to coreboot. + On x86, a pointer to this header will live at 0xFFFFFFFC. + For other platforms, you need to define CONFIG_CBFS_HEADER_ROM_OFFSET */ + struct cbfs_header { uint32_t magic; uint32_t version; @@ -181,16 +180,49 @@ struct cbfs_optionrom { #define CBFS_NAME(_c) (((char *) (_c)) + sizeof(struct cbfs_file)) #define CBFS_SUBHEADER(_p) ( (void *) ((((uint8_t *) (_p)) + ntohl((_p)->offset))) ) -/* returns pointer to file inside CBFS or NULL */ -struct cbfs_file *cbfs_find(const char *name); +#define CBFS_MEDIA_INVALID_MAP_ADDRESS ((void*)(0xffffffff)) +#define CBFS_DEFAULT_MEDIA ((void*)(0x0)) -/* returns pointer to file data inside CBFS */ -void *cbfs_get_file(const char *name); +/* Media for CBFS to load files. */ +struct cbfs_media { -/* returns pointer to file data inside CBFS after if type is correct */ -void *cbfs_find_file(const char *name, int type); + /* 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); +}; + +/* 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); /* returns 0 on success, -1 on failure */ int cbfs_decompress(int algo, void *src, void *dst, int len); -struct cbfs_header *get_cbfs_header(void); + +/* 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 diff --git a/src/include/endian.h b/src/include/endian.h new file mode 100644 index 0000000000..b511a491a8 --- /dev/null +++ b/src/include/endian.h @@ -0,0 +1,25 @@ +/* + * 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; either version 2 of + * the License, or (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _ENDIAN_H_ +#define _ENDIAN_H_ + +#include + +#endif diff --git a/src/lib/cbfs.c b/src/lib/cbfs.c index 98672d4ae6..3e44582f4d 100644 --- a/src/lib/cbfs.c +++ b/src/lib/cbfs.c @@ -2,6 +2,7 @@ * This file is part of the coreboot project. * * Copyright (C) 2008, Jordan Crouse + * 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 @@ -17,57 +18,74 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA */ -#include -#include -#include -#include -#include -#include - -// use CBFS core -#ifndef __SMM__ -#define CBFS_CORE_WITH_LZMA -#endif -#define phys_to_virt(x) (void*)(x) -#define virt_to_phys(x) (uint32_t)(x) -#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) +#ifdef LIBPAYLOAD +# include +# ifdef CONFIG_LZMA +# include +# define CBFS_CORE_WITH_LZMA +# endif +# define CBFS_MINI_BUILD +#elif defined(__SMM__) +# define CBFS_MINI_BUILD #else -#define DEBUG(x...) +# define CBFS_CORE_WITH_LZMA +# include +#endif + +#include +#include + +#ifdef LIBPAYLOAD +# include +# define DEBUG(x...) +# define LOG(x...) printf(x) +# define ERROR(x...) printf(x) +#else +# include +# 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 -// FIXME: romstart/romend are fine on x86, but not on ARM -#define romstart() 0xffffffff -#define romend() 0 #include "cbfs_core.c" #ifndef __SMM__ static inline int tohex4(unsigned int c) { - return (c<=9)?(c+'0'):(c-10+'a'); + 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); + 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(u16 vendor, u16 device, void * dest) +void *cbfs_load_optionrom(struct cbfs_media *media, uint16_t vendor, + uint16_t device, void *dest) { - char name[17]="pciXXXX,XXXX.rom"; + char name[17] = "pciXXXX,XXXX.rom"; struct cbfs_optionrom *orom; - u8 *src; + uint8_t *src; tohex16(vendor, name+3); tohex16(device, name+8); orom = (struct cbfs_optionrom *) - cbfs_find_file(name, CBFS_TYPE_OPTIONROM); + cbfs_get_file_content(media, name, CBFS_TYPE_OPTIONROM); if (orom == NULL) return NULL; @@ -77,10 +95,10 @@ void *cbfs_load_optionrom(u16 vendor, u16 device, void * dest) * 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 = ((unsigned char *) orom); // + sizeof(struct cbfs_optionrom); + src = (uint8_t *)orom; // + sizeof(struct cbfs_optionrom); if (! dest) return src; @@ -94,27 +112,27 @@ void *cbfs_load_optionrom(u16 vendor, u16 device, void * dest) return dest; } -void * cbfs_load_stage(const char *name) +void * cbfs_load_stage(struct cbfs_media *media, const char *name) { struct cbfs_stage *stage = (struct cbfs_stage *) - cbfs_find_file(name, CBFS_TYPE_STAGE); + cbfs_get_file_content(media, name, CBFS_TYPE_STAGE); /* this is a mess. There is no ntohll. */ /* for now, assume compatible byte order until we solve this. */ - u32 entry; + uint32_t entry; if (stage == NULL) return (void *) -1; LOG("loading stage %s @ 0x%x (%d bytes), entry @ 0x%llx\n", name, - (u32) stage->load, stage->memlen, + (uint32_t) stage->load, stage->memlen, stage->entry); - memset((void *) (u32) stage->load, 0, stage->memlen); + memset((void *) (uint32_t) stage->load, 0, stage->memlen); if (cbfs_decompress(stage->compression, ((unsigned char *) stage) + sizeof(struct cbfs_stage), - (void *) (u32) stage->load, + (void *) (uint32_t) stage->load, stage->len)) return (void *) -1; @@ -126,10 +144,10 @@ void * cbfs_load_stage(const char *name) return (void *) entry; } -int cbfs_execute_stage(const char *name) +int cbfs_execute_stage(struct cbfs_media *media, const char *name) { struct cbfs_stage *stage = (struct cbfs_stage *) - cbfs_find_file(name, CBFS_TYPE_STAGE); + cbfs_get_file_content(media, name, CBFS_TYPE_STAGE); if (stage == NULL) return 1; @@ -141,8 +159,52 @@ int cbfs_execute_stage(const char *name) } /* FIXME: This isn't right */ - LOG("run @ %p\n", (void *) ntohl((u32) stage->entry)); - return run_address((void *) (intptr_t)ntohll(stage->entry)); + LOG("run @ %p\n", (void *) ntohl((uint32_t) stage->entry)); + return run_address((void *)(uintptr_t)ntohll(stage->entry)); +} + +void *cbfs_load_payload(struct cbfs_media *media, const char *name) +{ + return (struct cbfs_payload *)cbfs_get_file_content( + media, name, CBFS_TYPE_PAYLOAD); +} + +/* 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=%d, count=%d): " + "allocated=%d, size=%d, last_allocate=%d\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=%d, size=%d, last_allocate=%d\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; } /** @@ -158,4 +220,5 @@ int run_address(void *f) v = f; return v(); } + #endif diff --git a/src/lib/cbfs_core.c b/src/lib/cbfs_core.c index 15cb68e9bc..6e4f4890c4 100644 --- a/src/lib/cbfs_core.c +++ b/src/lib/cbfs_core.c @@ -1,7 +1,8 @@ /* - * This file is part of the libpayload project. + * 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 @@ -27,14 +28,15 @@ * SUCH DAMAGE. */ -/* The CBFS core requires a couple of #defines or functions to adapt it to the target environment: +/* 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 * - * phys_to_virt(x), virt_to_phys(x) - * translate physical addresses to virtual and vice versa - * can be idempotent if no mapping is necessary. + * 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) @@ -45,105 +47,134 @@ * DEBUG(x...) * print a debug message x (in printf format) * - * romstart() - * returns the start address of the ROM image, or 0xffffffff if ROM is - * top-aligned. This is a physical address. - * - * romend() - * returns the highest address of the ROM image + 1, for use if - * romstart() == 0xffffffff. This is a physical address. */ -#include +#include +#include - -/* returns pointer to master header or 0xffffffff if not found */ -struct cbfs_header *get_cbfs_header(void) +/* 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) { - struct cbfs_header *header; + const struct cbfs_header *header; + struct cbfs_media default_media; - /* find header */ - if (romstart() == 0xffffffff) { - header = (struct cbfs_header*)phys_to_virt(*(uint32_t*)phys_to_virt(romend() + CBFS_HEADPTR_ADDR)); - } else { - // FIXME: where's the master header on ARM (our current bottom-aligned platform)? - header = NULL; + if (media == CBFS_DEFAULT_MEDIA) { + media = &default_media; + if (init_default_cbfs_media(media) != 0) { + ERROR("Failed to initializee default media.\n"); + return NULL; + } } + + 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 %p: %x vs %x.\n", header, 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 (void*)0xffffffff; + return CBFS_HEADER_INVALID_ADDRESS; } return header; } -// by must be power-of-two -#define CBFS_ALIGN(val, by) (typeof(val))((uint32_t)(val + by - 1) & (uint32_t)~(by - 1)) -#define CBFS_ALIGN_UP(val, by) CBFS_ALIGN(val + 1, by) - /* public API starts here*/ -struct cbfs_file *cbfs_find(const char *name) +struct cbfs_file *cbfs_get_file(struct cbfs_media *media, const char *name) { - struct cbfs_header *header = get_cbfs_header(); - if (header == (void*)0xffffffff) return NULL; + const char *file_name; + uint32_t offset, align, romsize, name_len; + const struct cbfs_header *header; + struct cbfs_file file, *file_ptr; + struct cbfs_media default_media; - LOG("Looking for '%s'\n", name); - - void *data, *dataend, *origdata; - /* find first entry */ - if (romstart() == 0xffffffff) { - data = (void*)phys_to_virt(romend()) - ntohl(header->romsize) + ntohl(header->offset); - dataend = (void*)phys_to_virt(romend()); - } else { - data = (void*)phys_to_virt(romstart()) + ntohl(header->offset); - dataend = (void*)phys_to_virt(romstart()) + ntohl(header->romsize); - } - dataend -= ntohl(header->bootblocksize); - - int align = ntohl(header->align); - - origdata = data; - while ((data < (dataend - 1)) && (data >= origdata)) { - struct cbfs_file *file = data; - if (memcmp(CBFS_FILE_MAGIC, file->magic, strlen(CBFS_FILE_MAGIC)) != 0) { - // no file header found. corruption? - // proceed in aligned steps to resynchronize - LOG("ERROR: No file header found at %p, attempting to recover by searching for header\n", data); - data = phys_to_virt(CBFS_ALIGN_UP(virt_to_phys(data), align)); - continue; - } - DEBUG("Check '%s'\n", CBFS_NAME(file)); - if (strcmp(CBFS_NAME(file), name) == 0) { - LOG("found.\n"); - return file; - } - void *olddata = data; - data = phys_to_virt(CBFS_ALIGN(virt_to_phys(data) + ntohl(file->len) + ntohl(file->offset), align)); - if (olddata > data) { - LOG("Something is wrong here. File chain moved from %p to %p\n", olddata, data); + if (media == CBFS_DEFAULT_MEDIA) { + media = &default_media; + if (init_default_cbfs_media(media) != 0) { + ERROR("Failed to initializee default media.\n"); return NULL; } } + + if (CBFS_HEADER_INVALID_ADDRESS == (header = cbfs_get_header(media))) + return NULL; + + // Logical offset (for source media) of first file. + offset = ntohl(header->offset); + align = ntohl(header->align); + romsize = ntohl(header->romsize); + + // TODO header->romsize seems broken now on ARM. Remove this when it's + // fixed. +#if defined(CONFIG_ARCH_ARMV7) && CONFIG_ARCH_ARMV7 + romsize = CONFIG_ROM_SIZE; +#endif + DEBUG("offset: 0x%x, align: %d, romsize: %d\n", offset, align, romsize); + + LOG("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); + ERROR("ERROR: No file header found at 0x%xx - " + "try next aligned address: 0x%x.\n", offset, + offset + new_align); + offset += new_align; + continue; + } + name_len = ntohl(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) { + int file_offset = ntohl(file.offset), + file_len = ntohl(file.len); + LOG("Found file (offset=0x%x, len=%d).\n", + offset + file_offset, file_len); + media->unmap(media, file_name); + file_ptr = media->map(media, offset, + file_offset + file_len); + media->close(media); + return file_ptr; + } else { + LOG(" (unmatched file @0x%x: %s)\n", offset, file_name); + media->unmap(media, file_name); + } + + // Move to next file. + offset += ntohl(file.len) + ntohl(file.offset); + if (offset % align) + offset += align - (offset % align); + } + media->close(media); + ERROR("ERROR: Not found.\n"); return NULL; } -void *cbfs_get_file(const char *name) +void *cbfs_get_file_content(struct cbfs_media *media, const char *name, int type) { - struct cbfs_file *file = cbfs_find(name); - - if (file == NULL) { - ERROR("Could not find file '%s'.\n", name); - return NULL; - } - - return (void*)CBFS_SUBHEADER(file); -} - -void *cbfs_find_file(const char *name, int type) -{ - struct cbfs_file *file = cbfs_find(name); + struct cbfs_file *file = cbfs_get_file(media, name); if (file == NULL) { ERROR("Could not find file '%s'.\n", name); @@ -151,11 +182,12 @@ void *cbfs_find_file(const char *name, int type) } if (ntohl(file->type) != type) { - ERROR("File '%s' is of type %x, but we requested %x.\n", name, ntohl(file->type), type); + ERROR("File '%s' is of type %x, but we requested %x.\n", name, + ntohl(file->type), type); return NULL; } - return (void*)CBFS_SUBHEADER(file); + return (void *)CBFS_SUBHEADER(file); } int cbfs_decompress(int algo, void *src, void *dst, int len) @@ -172,7 +204,9 @@ int cbfs_decompress(int algo, void *src, void *dst, int len) return -1; #endif default: - ERROR("tried to decompress %d bytes with algorithm #%x, but that algorithm id is unsupported.\n", len, algo); + ERROR("tried to decompress %d bytes with algorithm #%x," + "but that algorithm id is unsupported.\n", len, + algo); return -1; } } diff --git a/src/lib/hardwaremain.c b/src/lib/hardwaremain.c index eed243ad75..85c05f5093 100644 --- a/src/lib/hardwaremain.c +++ b/src/lib/hardwaremain.c @@ -59,6 +59,7 @@ void hardwaremain(int boot_complete); void hardwaremain(int boot_complete) { struct lb_memory *lb_mem; + void *payload; timestamp_stash(TS_START_RAMSTAGE); post_code(POST_ENTRY_RAMSTAGE); @@ -141,8 +142,8 @@ void hardwaremain(int boot_complete) timestamp_add_now(TS_LOAD_PAYLOAD); - void *payload; - payload = cbfs_load_payload(lb_mem, CONFIG_CBFS_PREFIX "/payload"); + payload = cbfs_load_payload(CBFS_DEFAULT_MEDIA, + CONFIG_CBFS_PREFIX "/payload"); if (! payload) die("Could not find a payload\n"); diff --git a/src/lib/selfboot.c b/src/lib/selfboot.c index c5fb62adca..56124da317 100644 --- a/src/lib/selfboot.c +++ b/src/lib/selfboot.c @@ -536,12 +536,3 @@ out: return 0; } -void *cbfs_load_payload(struct lb_memory *lb_mem, const char *name) -{ - struct cbfs_payload *payload; - - payload = (struct cbfs_payload *)cbfs_find_file(name, CBFS_TYPE_PAYLOAD); - - return payload; -} - diff --git a/src/mainboard/google/snow/bootblock.c b/src/mainboard/google/snow/bootblock.c index d5ee0a378a..5b3efa025c 100644 --- a/src/mainboard/google/snow/bootblock.c +++ b/src/mainboard/google/snow/bootblock.c @@ -39,9 +39,13 @@ #include #include +#include #define EXYNOS5_CLOCK_BASE 0x10010000 +/* TODO Move to Makefile.inc once we support adding bootblock stage files. */ +#include "cpu/samsung/exynos5-common/spi.c" + /* FIXME(dhendrix): Can we move this SPI stuff elsewhere? */ static void spi_rx_tx(struct exynos_spi *regs, int todo, void *dinp, void const *doutp, int i) diff --git a/src/mainboard/samsung/lumpy/romstage.c b/src/mainboard/samsung/lumpy/romstage.c index 5600cf616d..9bc193bb56 100644 --- a/src/mainboard/samsung/lumpy/romstage.c +++ b/src/mainboard/samsung/lumpy/romstage.c @@ -301,7 +301,7 @@ void main(unsigned long bist) break; } - spd_file = cbfs_find("spd.bin"); + spd_file = cbfs_get_file(CBFS_DEFAULT_MEDIA, "spd.bin"); if (!spd_file) die("SPD data not found."); if (spd_file->len < (spd_index + 1) * 256) diff --git a/src/northbridge/amd/agesa/family15tn/fam15tn_callouts.c b/src/northbridge/amd/agesa/family15tn/fam15tn_callouts.c index 7c3b0ac9cf..8c5605c041 100644 --- a/src/northbridge/amd/agesa/family15tn/fam15tn_callouts.c +++ b/src/northbridge/amd/agesa/family15tn/fam15tn_callouts.c @@ -398,7 +398,9 @@ AGESA_STATUS fam15tn_DefaultRet (UINT32 Func, UINT32 Data, VOID *ConfigPtr) AGESA_STATUS fam15tn_HookGfxGetVbiosImage(UINT32 Func, UINT32 FchData, VOID *ConfigPrt) { GFX_VBIOS_IMAGE_INFO *pVbiosImageInfo = (GFX_VBIOS_IMAGE_INFO *)ConfigPrt; - pVbiosImageInfo->ImagePtr = cbfs_find_file("pci"CONFIG_VGA_BIOS_ID".rom", CBFS_TYPE_OPTIONROM); + pVbiosImageInfo->ImagePtr = cbfs_get_file_content( + CBFS_DEFAULT_MEDIA, "pci"CONFIG_VGA_BIOS_ID".rom", + CBFS_TYPE_OPTIONROM); /* printk(BIOS_DEBUG, "IMGptr=%x\n", pVbiosImageInfo->ImagePtr); */ return pVbiosImageInfo->ImagePtr == NULL ? AGESA_WARNING : AGESA_SUCCESS; } diff --git a/src/northbridge/intel/i82830/vga.c b/src/northbridge/intel/i82830/vga.c index 1ec7f87b6b..40e7d9d9d2 100644 --- a/src/northbridge/intel/i82830/vga.c +++ b/src/northbridge/intel/i82830/vga.c @@ -32,7 +32,7 @@ static void vga_init(device_t dev) { printk(BIOS_INFO, "Starting Graphics Initialization\n"); - struct cbfs_file *file = cbfs_find("mbi.bin"); + struct cbfs_file *file = cbfs_get_file(CBFS_DEFAULT_MEDIA, "mbi.bin"); void *mbi = NULL; unsigned int mbi_len = 0; diff --git a/src/northbridge/intel/sandybridge/raminit.c b/src/northbridge/intel/sandybridge/raminit.c index b5a1c23f94..f25aaa1195 100644 --- a/src/northbridge/intel/sandybridge/raminit.c +++ b/src/northbridge/intel/sandybridge/raminit.c @@ -252,7 +252,9 @@ void sdram_initialize(struct pei_data *pei_data) pei_data->tx_byte = console_tx_byte; /* Locate and call UEFI System Agent binary. */ - entry = (unsigned long)cbfs_find_file("mrc.bin", 0xab); + /* TODO make MRC blob (0xab?) defined in cbfs_core.h. */ + entry = (unsigned long)cbfs_get_file_content( + CBFS_DEFAULT_MEDIA, "mrc.bin", 0xab); if (entry) { int rv; asm volatile (