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 <hungte@chromium.org>
Reviewed-on: http://review.coreboot.org/2182
Tested-by: build bot (Jenkins)
Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
This commit is contained in:
Hung-Te Lin 2013-01-22 18:57:56 +08:00 committed by Ronald G. Minnich
parent 5fc64dca45
commit 6fe0cab205
29 changed files with 546 additions and 259 deletions

View File

@ -640,7 +640,9 @@ unsigned long write_coreboot_table(
#if CONFIG_USE_OPTION_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) { if (option_table) {
struct lb_record *rec_dest = lb_new_record(head); struct lb_record *rec_dest = lb_new_record(head);
/* Copy the option config table, it's already a lb_record... */ /* Copy the option config table, it's already a lb_record... */

View File

@ -45,7 +45,9 @@ void main(unsigned long bist)
} }
printk(BIOS_INFO, "bootblock main(): loading romstage\n"); 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"); printk(BIOS_INFO, "bootblock main(): jumping to romstage\n");
if (romstage_entry) bootblock_exit(romstage_entry); if (romstage_entry) bootblock_exit(romstage_entry);
hlt(); hlt();

View File

@ -20,82 +20,41 @@
#ifndef __INCLUDE_ARCH_CBFS__ #ifndef __INCLUDE_ARCH_CBFS__
#define __INCLUDE_ARCH_CBFS__ #define __INCLUDE_ARCH_CBFS__
#include <string.h>
#include <types.h>
#include <cbfs_core.h> #include <cbfs_core.h>
#include <arch/byteorder.h> #include <arch/byteorder.h>
#include <arch/cbfs.h>
// 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) // mem* and ulzma are now workarounds for bootblock compilation.
{ void *memcpy(void *dest, const void *src, size_t n) {
return strcmp(file->magic, CBFS_FILE_MAGIC) ? 0 : 1; char *d = (char *)dest;
const char *s = (const char*)src;
while (n-- > 0)
*d++ = *s++;
return dest;
} }
static unsigned long loadstage(const char* target) void *memset(void *dest, int c, size_t n) {
{ char *d = (char*)dest;
unsigned long offset, align; while (n-- > 0)
struct cbfs_header *header = (struct cbfs_header *)(CONFIG_BOOTBLOCK_BASE + 0x40); *d++ = c;
/* FIXME: magic offsets */ return dest;
// 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;
}
} }
#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__

View File

@ -638,7 +638,9 @@ unsigned long write_coreboot_table(
#if CONFIG_USE_OPTION_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) { if (option_table) {
struct lb_record *rec_dest = lb_new_record(head); struct lb_record *rec_dest = lb_new_record(head);
/* Copy the option config table, it's already a lb_record... */ /* Copy the option config table, it's already a lb_record... */

View File

@ -120,7 +120,6 @@ static int smbios_processor_name(char *start)
static int smbios_write_type0(unsigned long *current, int handle) static int smbios_write_type0(unsigned long *current, int handle)
{ {
struct cbfs_header *hdr;
struct smbios_type0 *t = (struct smbios_type0 *)*current; struct smbios_type0 *t = (struct smbios_type0 *)*current;
int len = sizeof(struct smbios_type0); 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); vboot_data->vbt10 = (u32)t->eos + (version_offset - 1);
#endif #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->system_bios_major_release = 4;
t->bios_characteristics = t->bios_characteristics =
BIOS_CHARACTERISTICS_PCI_SUPPORTED | BIOS_CHARACTERISTICS_PCI_SUPPORTED |

View File

@ -8,13 +8,16 @@ ramstage-$(CONFIG_IOAPIC) += ioapic.c
ramstage-y += memset.c ramstage-y += memset.c
ramstage-y += memcpy.c ramstage-y += memcpy.c
ramstage-y += ebda.c ramstage-y += ebda.c
ramstage-y += rom_media.c
romstage-y += romstage_console.c romstage-y += romstage_console.c
romstage-y += cbfs_and_run.c romstage-y += cbfs_and_run.c
romstage-y += memset.c romstage-y += memset.c
romstage-y += memcpy.c romstage-y += memcpy.c
romstage-y += rom_media.c
smm-y += memset.c smm-y += memset.c
smm-y += memcpy.c smm-y += memcpy.c
smm-y += rom_media.c
$(obj)/arch/x86/lib/console.ramstage.o :: $(obj)/build.h $(obj)/arch/x86/lib/console.ramstage.o :: $(obj)/build.h

View File

@ -28,7 +28,7 @@ static void cbfs_and_run_core(const char *filename, unsigned ebp)
timestamp_add_now(TS_START_COPYRAM); timestamp_add_now(TS_START_COPYRAM);
print_debug("Loading image.\n"); print_debug("Loading image.\n");
dst = cbfs_load_stage(filename); dst = cbfs_load_stage(CBFS_DEFAULT_MEDIA, filename);
if ((void *)dst == (void *) -1) if ((void *)dst == (void *) -1)
die("FATAL: Essential component is missing.\n"); die("FATAL: Essential component is missing.\n");

View File

@ -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 <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);
}

View File

@ -166,8 +166,9 @@ void intel_update_microcode_from_cbfs(void)
#ifdef __PRE_RAM__ #ifdef __PRE_RAM__
microcode_blob = walkcbfs((char *) MICROCODE_CBFS_FILE); microcode_blob = walkcbfs((char *) MICROCODE_CBFS_FILE);
#else #else
microcode_blob = cbfs_find_file(MICROCODE_CBFS_FILE, microcode_blob = cbfs_get_file_content(CBFS_DEFAULT_MEDIA,
CBFS_TYPE_MICROCODE); MICROCODE_CBFS_FILE,
CBFS_TYPE_MICROCODE);
#endif #endif
intel_update_microcode(microcode_blob); intel_update_microcode(microcode_blob);
} }

View File

@ -1,2 +1,2 @@
#romstage-y += soc.c romstage-y += spi.c
romstage-y += spl_boot.c ramstage-y += spi.c

View File

@ -0,0 +1,7 @@
#include <cbfs.h>
/* TODO provide a real SPI driver here for firmware media. */
int init_default_cbfs_media(struct cbfs_media *media) {
return -1;
}

View File

@ -48,6 +48,22 @@ config ROMSTAGE_SIZE
hex hex
default 0x10000 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 # FIXME: This is for copying SPI content into SRAM temporarily and
# will be removed when we have the SPI streaming driver implemented. # will be removed when we have the SPI streaming driver implemented.
config SPI_IMAGE_HACK config SPI_IMAGE_HACK

View File

@ -105,7 +105,7 @@ unsigned int nano_update_ucode(void)
const struct cbfs_file *cbfs_ucode; const struct cbfs_file *cbfs_ucode;
u32 fms = cpuid_eax(0x1); 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 ? */ /* Oops, did you forget to include the microcode ? */
if(cbfs_ucode == NULL) { if(cbfs_ucode == NULL) {
printk(BIOS_ALERT, "WARNING: No microcode file found in CBFS. " printk(BIOS_ALERT, "WARNING: No microcode file found in CBFS. "

View File

@ -248,8 +248,9 @@ void vbe_set_graphics(void)
#if CONFIG_BOOTSPLASH #if CONFIG_BOOTSPLASH
struct jpeg_decdata *decdata; struct jpeg_decdata *decdata;
decdata = malloc(sizeof(*decdata)); decdata = malloc(sizeof(*decdata));
unsigned char *jpeg = cbfs_find_file("bootsplash.jpg", unsigned char *jpeg = cbfs_get_file_content(CBFS_DEFAULT_MEDIA,
CBFS_TYPE_BOOTSPLASH); "bootsplash.jpg",
CBFS_TYPE_BOOTSPLASH);
if (!jpeg) { if (!jpeg) {
printk(BIOS_DEBUG, "VBE: No bootsplash found.\n"); printk(BIOS_DEBUG, "VBE: No bootsplash found.\n");
return; return;
@ -366,7 +367,8 @@ void do_vsmbios(void)
printk(BIOS_SPEW, "VSA: Real mode stub @%p: %d bytes\n", REALMODE_BASE, printk(BIOS_SPEW, "VSA: Real mode stub @%p: %d bytes\n", REALMODE_BASE,
(u32)&__realmode_code_size); (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"); printk(BIOS_ERR, "Failed to load VSA.\n");
return; return;
} }

View File

@ -725,7 +725,9 @@ void vbe_set_graphics(void)
* cares. */ * cares. */
// int imagesize = 1024*768*2; // 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) { if (!jpeg) {
DEBUG_PRINTF_VBE("Could not find bootsplash.jpg\n"); DEBUG_PRINTF_VBE("Could not find bootsplash.jpg\n");
return; return;

View File

@ -35,7 +35,8 @@ struct rom_header *pci_rom_probe(struct device *dev)
struct pci_data *rom_data; struct pci_data *rom_data;
/* If it's in FLASH, then don't check device for ROM. */ /* 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 vendev = (dev->vendor << 16) | dev->device;
u32 mapped_vendev = vendev; u32 mapped_vendev = vendev;
@ -45,8 +46,10 @@ struct rom_header *pci_rom_probe(struct device *dev)
if (!rom_header) { if (!rom_header) {
if (vendev != mapped_vendev) { if (vendev != mapped_vendev) {
rom_header = cbfs_load_optionrom(mapped_vendev >> 16, rom_header = cbfs_load_optionrom(
mapped_vendev & 0xffff , NULL); CBFS_DEFAULT_MEDIA,
mapped_vendev >> 16,
mapped_vendev & 0xffff, NULL);
} }
} }

View File

@ -190,7 +190,8 @@ int get_option(void *dest, const char *name)
namelen = strnlen(name, CMOS_MAX_NAME_LENGTH); namelen = strnlen(name, CMOS_MAX_NAME_LENGTH);
/* find the requested entry record */ /* 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) { if (!ct) {
printk(BIOS_ERR, "RTC: cmos_layout.bin could not be found. " printk(BIOS_ERR, "RTC: cmos_layout.bin could not be found. "
"Options are disabled\n"); "Options are disabled\n");
@ -268,7 +269,8 @@ int set_option(const char *name, void *value)
namelen = strnlen(name, CMOS_MAX_NAME_LENGTH); namelen = strnlen(name, CMOS_MAX_NAME_LENGTH);
/* find the requested entry record */ /* 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) { if (!ct) {
printk(BIOS_ERR, "cmos_layout.bin could not be found. Options are disabled\n"); printk(BIOS_ERR, "cmos_layout.bin could not be found. Options are disabled\n");
return(-2); return(-2);

View File

@ -2,6 +2,7 @@
* This file is part of the coreboot project. * This file is part of the coreboot project.
* *
* Copyright (C) 2008 Jordan Crouse <jordan@cosmicpenguin.net> * Copyright (C) 2008 Jordan Crouse <jordan@cosmicpenguin.net>
* Copyright (C) 2013 The Chromium OS Authors. All rights reserved.
* *
* This file is dual-licensed. You can choose between: * This file is dual-licensed. You can choose between:
* - The GNU GPL, version 2, as published by the Free Software Foundation * - The GNU GPL, version 2, as published by the Free Software Foundation
@ -49,14 +50,38 @@
#ifndef _CBFS_H_ #ifndef _CBFS_H_
#define _CBFS_H_ #define _CBFS_H_
#include "cbfs_core.h" #include <cbfs_core.h>
#include <boot/coreboot_tables.h>
void *cbfs_load_payload(struct lb_memory *lb_mem, const char *name); int cbfs_execute_stage(struct cbfs_media *media, const char *name);
void *cbfs_load_stage(const char *name); void *cbfs_load_optionrom(struct cbfs_media *media, uint16_t vendor,
int cbfs_execute_stage(const char *name); uint16_t device, void * dest);
void *cbfs_load_optionrom(u16 vendor, u16 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); int run_address(void *f);
/* Defined in src/lib/selfboot.c */
struct lb_memory;
int selfboot(struct lb_memory *mem, struct cbfs_payload *payload); 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 #endif

View File

@ -3,6 +3,7 @@
* *
* Copyright (C) 2008 Jordan Crouse <jordan@cosmicpenguin.net> * Copyright (C) 2008 Jordan Crouse <jordan@cosmicpenguin.net>
* Copyright (C) 2012 Google, Inc. * Copyright (C) 2012 Google, Inc.
* Copyright (C) 2013 The Chromium OS Authors. All rights reserved.
* *
* This file is dual-licensed. You can choose between: * This file is dual-licensed. You can choose between:
* - The GNU GPL, version 2, as published by the Free Software Foundation * - The GNU GPL, version 2, as published by the Free Software Foundation
@ -50,6 +51,10 @@
#ifndef _CBFS_CORE_H_ #ifndef _CBFS_CORE_H_
#define _CBFS_CORE_H_ #define _CBFS_CORE_H_
#include <endian.h>
#include <stddef.h>
#include <stdint.h>
/** These are standard values for the known compression /** These are standard values for the known compression
alogrithms that coreboot knows about for stages and alogrithms that coreboot knows about for stages and
payloads. Of course, other CBFS users can use whatever payloads. Of course, other CBFS users can use whatever
@ -74,24 +79,18 @@
#define CBFS_COMPONENT_CMOS_DEFAULT 0xaa #define CBFS_COMPONENT_CMOS_DEFAULT 0xaa
#define CBFS_COMPONENT_CMOS_LAYOUT 0x01aa #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 #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_VERSION1 0x31313131
#define CBFS_HEADER_VERSION2 0x31313132 #define CBFS_HEADER_VERSION2 0x31313132
#define CBFS_HEADER_VERSION CBFS_HEADER_VERSION2 #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 { struct cbfs_header {
uint32_t magic; uint32_t magic;
uint32_t version; uint32_t version;
@ -181,16 +180,49 @@ struct cbfs_optionrom {
#define CBFS_NAME(_c) (((char *) (_c)) + sizeof(struct cbfs_file)) #define CBFS_NAME(_c) (((char *) (_c)) + sizeof(struct cbfs_file))
#define CBFS_SUBHEADER(_p) ( (void *) ((((uint8_t *) (_p)) + ntohl((_p)->offset))) ) #define CBFS_SUBHEADER(_p) ( (void *) ((((uint8_t *) (_p)) + ntohl((_p)->offset))) )
/* returns pointer to file inside CBFS or NULL */ #define CBFS_MEDIA_INVALID_MAP_ADDRESS ((void*)(0xffffffff))
struct cbfs_file *cbfs_find(const char *name); #define CBFS_DEFAULT_MEDIA ((void*)(0x0))
/* returns pointer to file data inside CBFS */ /* Media for CBFS to load files. */
void *cbfs_get_file(const char *name); struct cbfs_media {
/* returns pointer to file data inside CBFS after if type is correct */ /* implementation dependent context, to hold resource references */
void *cbfs_find_file(const char *name, int type); 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 */ /* returns 0 on success, -1 on failure */
int cbfs_decompress(int algo, void *src, void *dst, int len); 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 #endif

25
src/include/endian.h Normal file
View File

@ -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 <arch/byteorder.h>
#endif

View File

@ -2,6 +2,7 @@
* This file is part of the coreboot project. * This file is part of the coreboot project.
* *
* Copyright (C) 2008, Jordan Crouse <jordan@cosmicpenguin.net> * 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 * 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 * 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 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
*/ */
#include <types.h> #ifdef LIBPAYLOAD
#include <string.h> # include <libpayload-config.h>
#include <console/console.h> # ifdef CONFIG_LZMA
#include <cbfs.h> # include <lzma.h>
#include <lib.h> # define CBFS_CORE_WITH_LZMA
#include <arch/byteorder.h> # endif
# define CBFS_MINI_BUILD
// use CBFS core #elif defined(__SMM__)
#ifndef __SMM__ # define CBFS_MINI_BUILD
#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)
#else #else
#define DEBUG(x...) # define CBFS_CORE_WITH_LZMA
# include <lib.h>
#endif
#include <cbfs.h>
#include <string.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
// FIXME: romstart/romend are fine on x86, but not on ARM
#define romstart() 0xffffffff
#define romend() 0
#include "cbfs_core.c" #include "cbfs_core.c"
#ifndef __SMM__ #ifndef __SMM__
static inline int tohex4(unsigned int c) 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) static void tohex16(unsigned int val, char* dest)
{ {
dest[0]=tohex4(val>>12); dest[0] = tohex4(val>>12);
dest[1]=tohex4((val>>8) & 0xf); dest[1] = tohex4((val>>8) & 0xf);
dest[2]=tohex4((val>>4) & 0xf); dest[2] = tohex4((val>>4) & 0xf);
dest[3]=tohex4(val & 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; struct cbfs_optionrom *orom;
u8 *src; uint8_t *src;
tohex16(vendor, name+3); tohex16(vendor, name+3);
tohex16(device, name+8); tohex16(device, name+8);
orom = (struct cbfs_optionrom *) orom = (struct cbfs_optionrom *)
cbfs_find_file(name, CBFS_TYPE_OPTIONROM); cbfs_get_file_content(media, name, CBFS_TYPE_OPTIONROM);
if (orom == NULL) if (orom == NULL)
return 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 * 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 * pass 0 in for the dest, and all we have to do is find the rom and
* return a pointer to it. * return a pointer to it.
*/ */
/* BUG: the cbfstool is (not yet) including a cbfs_optionrom header */ /* 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) if (! dest)
return src; return src;
@ -94,27 +112,27 @@ void *cbfs_load_optionrom(u16 vendor, u16 device, void * dest)
return 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 *) 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. */ /* this is a mess. There is no ntohll. */
/* for now, assume compatible byte order until we solve this. */ /* for now, assume compatible byte order until we solve this. */
u32 entry; uint32_t entry;
if (stage == NULL) if (stage == NULL)
return (void *) -1; return (void *) -1;
LOG("loading stage %s @ 0x%x (%d bytes), entry @ 0x%llx\n", LOG("loading stage %s @ 0x%x (%d bytes), entry @ 0x%llx\n",
name, name,
(u32) stage->load, stage->memlen, (uint32_t) stage->load, stage->memlen,
stage->entry); stage->entry);
memset((void *) (u32) stage->load, 0, stage->memlen); memset((void *) (uint32_t) stage->load, 0, stage->memlen);
if (cbfs_decompress(stage->compression, if (cbfs_decompress(stage->compression,
((unsigned char *) stage) + ((unsigned char *) stage) +
sizeof(struct cbfs_stage), sizeof(struct cbfs_stage),
(void *) (u32) stage->load, (void *) (uint32_t) stage->load,
stage->len)) stage->len))
return (void *) -1; return (void *) -1;
@ -126,10 +144,10 @@ void * cbfs_load_stage(const char *name)
return (void *) entry; 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 *) 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) if (stage == NULL)
return 1; return 1;
@ -141,8 +159,52 @@ int cbfs_execute_stage(const char *name)
} }
/* FIXME: This isn't right */ /* FIXME: This isn't right */
LOG("run @ %p\n", (void *) ntohl((u32) stage->entry)); LOG("run @ %p\n", (void *) ntohl((uint32_t) stage->entry));
return run_address((void *) (intptr_t)ntohll(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; v = f;
return v(); return v();
} }
#endif #endif

View File

@ -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) 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 * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
@ -27,14 +28,15 @@
* SUCH DAMAGE. * 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) * CBFS_CORE_WITH_LZMA (must be #define)
* if defined, ulzma() must exist for decompression of data streams * if defined, ulzma() must exist for decompression of data streams
* *
* phys_to_virt(x), virt_to_phys(x) * CBFS_HEADER_ROM_ADDRESS
* translate physical addresses to virtual and vice versa * ROM address (offset) of CBFS header. Underlying CBFS media may interpret
* can be idempotent if no mapping is necessary. * it in other way so we call this "address".
* *
* ERROR(x...) * ERROR(x...)
* print an error message x (in printf format) * print an error message x (in printf format)
@ -45,105 +47,134 @@
* DEBUG(x...) * DEBUG(x...)
* print a debug message x (in printf format) * 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 <cbfs_core.h> #include <cbfs.h>
#include <string.h>
/* returns a pointer to CBFS master header, or CBFS_HEADER_INVALID_ADDRESS
/* returns pointer to master header or 0xffffffff if not found */ * on failure */
struct cbfs_header *get_cbfs_header(void) 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 (media == CBFS_DEFAULT_MEDIA) {
if (romstart() == 0xffffffff) { media = &default_media;
header = (struct cbfs_header*)phys_to_virt(*(uint32_t*)phys_to_virt(romend() + CBFS_HEADPTR_ADDR)); if (init_default_cbfs_media(media) != 0) {
} else { ERROR("Failed to initializee default media.\n");
// FIXME: where's the master header on ARM (our current bottom-aligned platform)? return NULL;
header = 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)) { 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) { if (header->magic == 0xffffffff) {
ERROR("Maybe ROM is not mapped properly?\n"); ERROR("Maybe ROM is not mapped properly?\n");
} }
return (void*)0xffffffff; return CBFS_HEADER_INVALID_ADDRESS;
} }
return header; 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*/ /* 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(); const char *file_name;
if (header == (void*)0xffffffff) return NULL; 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); if (media == CBFS_DEFAULT_MEDIA) {
media = &default_media;
void *data, *dataend, *origdata; if (init_default_cbfs_media(media) != 0) {
/* find first entry */ ERROR("Failed to initializee default media.\n");
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);
return NULL; 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; 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); struct cbfs_file *file = cbfs_get_file(media, 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);
if (file == NULL) { if (file == NULL) {
ERROR("Could not find file '%s'.\n", name); 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) { 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 NULL;
} }
return (void*)CBFS_SUBHEADER(file); return (void *)CBFS_SUBHEADER(file);
} }
int cbfs_decompress(int algo, void *src, void *dst, int len) 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; return -1;
#endif #endif
default: 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; return -1;
} }
} }

View File

@ -59,6 +59,7 @@ void hardwaremain(int boot_complete);
void hardwaremain(int boot_complete) void hardwaremain(int boot_complete)
{ {
struct lb_memory *lb_mem; struct lb_memory *lb_mem;
void *payload;
timestamp_stash(TS_START_RAMSTAGE); timestamp_stash(TS_START_RAMSTAGE);
post_code(POST_ENTRY_RAMSTAGE); post_code(POST_ENTRY_RAMSTAGE);
@ -141,8 +142,8 @@ void hardwaremain(int boot_complete)
timestamp_add_now(TS_LOAD_PAYLOAD); timestamp_add_now(TS_LOAD_PAYLOAD);
void *payload; payload = cbfs_load_payload(CBFS_DEFAULT_MEDIA,
payload = cbfs_load_payload(lb_mem, CONFIG_CBFS_PREFIX "/payload"); CONFIG_CBFS_PREFIX "/payload");
if (! payload) if (! payload)
die("Could not find a payload\n"); die("Could not find a payload\n");

View File

@ -536,12 +536,3 @@ out:
return 0; 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;
}

View File

@ -39,9 +39,13 @@
#include <drivers/maxim/max77686/max77686.h> #include <drivers/maxim/max77686/max77686.h>
#include <console/console.h> #include <console/console.h>
#include <cbfs.h>
#define EXYNOS5_CLOCK_BASE 0x10010000 #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? */ /* FIXME(dhendrix): Can we move this SPI stuff elsewhere? */
static void spi_rx_tx(struct exynos_spi *regs, int todo, static void spi_rx_tx(struct exynos_spi *regs, int todo,
void *dinp, void const *doutp, int i) void *dinp, void const *doutp, int i)

View File

@ -301,7 +301,7 @@ void main(unsigned long bist)
break; break;
} }
spd_file = cbfs_find("spd.bin"); spd_file = cbfs_get_file(CBFS_DEFAULT_MEDIA, "spd.bin");
if (!spd_file) if (!spd_file)
die("SPD data not found."); die("SPD data not found.");
if (spd_file->len < (spd_index + 1) * 256) if (spd_file->len < (spd_index + 1) * 256)

View File

@ -398,7 +398,9 @@ AGESA_STATUS fam15tn_DefaultRet (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
AGESA_STATUS fam15tn_HookGfxGetVbiosImage(UINT32 Func, UINT32 FchData, VOID *ConfigPrt) AGESA_STATUS fam15tn_HookGfxGetVbiosImage(UINT32 Func, UINT32 FchData, VOID *ConfigPrt)
{ {
GFX_VBIOS_IMAGE_INFO *pVbiosImageInfo = (GFX_VBIOS_IMAGE_INFO *)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); */ /* printk(BIOS_DEBUG, "IMGptr=%x\n", pVbiosImageInfo->ImagePtr); */
return pVbiosImageInfo->ImagePtr == NULL ? AGESA_WARNING : AGESA_SUCCESS; return pVbiosImageInfo->ImagePtr == NULL ? AGESA_WARNING : AGESA_SUCCESS;
} }

View File

@ -32,7 +32,7 @@
static void vga_init(device_t dev) static void vga_init(device_t dev)
{ {
printk(BIOS_INFO, "Starting Graphics Initialization\n"); 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; void *mbi = NULL;
unsigned int mbi_len = 0; unsigned int mbi_len = 0;

View File

@ -252,7 +252,9 @@ void sdram_initialize(struct pei_data *pei_data)
pei_data->tx_byte = console_tx_byte; pei_data->tx_byte = console_tx_byte;
/* Locate and call UEFI System Agent binary. */ /* 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) { if (entry) {
int rv; int rv;
asm volatile ( asm volatile (