Hung-Te Lin (hungte@chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2182
-gerrit
commit 68638823cf222e4ab748f1a512678d369812d796 Author: Hung-Te Lin hungte@chromium.org Date: Tue Jan 22 18:57:56 2013 +0800
Extend CBFS to support arbitrary ROM source media.
Summary: 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 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 (or 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 ARM (loaded romstage properly for Google/Snow). - Verified to work on x86/qemu.
Change-Id: Iac911ded25a6f2feffbf3101a81364625bb07746 Signed-off-by: Hung-Te Lin hungte@chromium.org --- src/arch/armv7/boot/coreboot_table.c | 4 +- src/arch/armv7/bootblock_simple.c | 4 +- src/arch/armv7/include/arch/cbfs.h | 101 +++---- 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 | 95 +++++++ src/cpu/intel/microcode/microcode.c | 5 +- src/cpu/samsung/exynos5-common/Makefile.inc | 4 +- src/cpu/samsung/exynos5-common/spi.c | 233 +++++++++++++++++ src/cpu/samsung/exynos5-common/spi.h | 13 + src/cpu/samsung/exynos5-common/spl_boot.c | 291 --------------------- src/cpu/samsung/exynos5250/Kconfig | 8 + 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 | 36 ++- src/include/cbfs_core.h | 71 +++-- src/include/endian.h | 28 ++ src/lib/cbfs.c | 130 ++++++--- src/lib/cbfs_core.c | 197 ++++++++------ src/lib/hardwaremain.c | 5 +- src/lib/selfboot.c | 9 - src/mainboard/google/snow/bootblock.c | 253 +----------------- 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 +- 31 files changed, 763 insertions(+), 786 deletions(-)
diff --git a/src/arch/armv7/boot/coreboot_table.c b/src/arch/armv7/boot/coreboot_table.c index 86a004d..b2d88aa 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 af76d4c..d97075e 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 f060643..e34a0d2 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 <string.h> -#include <types.h> #include <cbfs_core.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) -{ - 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"); +void *memset(void *dest, int c, size_t n) { + char *d = (char*)dest; + while (n-- > 0) + *d++ = c; + return dest; +} + +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; +}
- 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; - } +unsigned long ulzma(unsigned char *src, unsigned char *dest) { + // TODO remove this. + return -1; } -#endif + +#endif // __INCLUDE_ARCH_CBFS__ diff --git a/src/arch/x86/boot/coreboot_table.c b/src/arch/x86/boot/coreboot_table.c index 8dccd77..04fba47 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 72e70ba..f65ced2 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 2186072..f4dc8b8 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 1f87e7a..a023141 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 0000000..09a3b3a --- /dev/null +++ b/src/arch/x86/lib/rom_media.c @@ -0,0 +1,95 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2013 Google Inc + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; version 2 of + * the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include <cbfs.h> +#include <string.h> + +#ifdef LIBPAYLOAD +# define printk(x...) +#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_default_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; +} diff --git a/src/cpu/intel/microcode/microcode.c b/src/cpu/intel/microcode/microcode.c index 15d6513..713a6df 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 cad6cb3..d919347 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 0000000..ce64b5f --- /dev/null +++ b/src/cpu/samsung/exynos5-common/spi.c @@ -0,0 +1,233 @@ +/* + * Copyright (C) 2011 Samsung Electronics + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 + */ + +/* FIXME(dhendrix): pulled in a lot of extra crap such as partition and string + libs*/ +#include <assert.h> +#include <common.h> +#include <stdlib.h> +#include <string.h> + +#include <console/console.h> +#include <console/loglevel.h> + +#include <config.h> +#include <spi.h> + +#include <cpu/samsung/exynos5250/gpio.h> +#include <cpu/samsung/exynos5250/clk.h> +#include <cpu/samsung/exynos5250/cpu.h> +#include <cpu/samsung/exynos5250/periph.h> +#include <cpu/samsung/exynos5250/pinmux.h> + +#include <cpu/samsung/exynos5-common/cpu.h> +#include <cpu/samsung/exynos5-common/exynos5-common.h> +#include <cpu/samsung/exynos5-common/spi.h> + +#include <system.h> +#include <arch/io.h> +#include <lib.h> + +#define OM_STAT (0x1f << 1) +#define EXYNOS_BASE_SPI1 ((void *)0x12d30000) + +static void exynos_spi_rx_tx(struct exynos_spi *regs, int todo, + void *dinp, void const *doutp, int i) +{ + int rx_lvl, tx_lvl; + uint *rxp = (uint *)(dinp + (i * (32 * 1024))); + uint out_bytes, in_bytes; + + out_bytes = in_bytes = todo; + setbits_le32(®s->ch_cfg, SPI_CH_RST); + clrbits_le32(®s->ch_cfg, SPI_CH_RST); + writel(((todo * 8) / 32) | SPI_PACKET_CNT_EN, ®s->pkt_cnt); + + while (in_bytes) { + uint32_t spi_sts; + int temp; + + spi_sts = readl(®s->spi_sts); + rx_lvl = ((spi_sts >> 15) & 0x7f); + tx_lvl = ((spi_sts >> 6) & 0x7f); + while (tx_lvl < 32 && out_bytes) { + temp = 0xffffffff; + writel(temp, ®s->tx_data); + out_bytes -= 4; + tx_lvl += 4; + } + while (rx_lvl >= 4 && in_bytes) { + temp = readl(®s->rx_data); + if (rxp) + *rxp++ = temp; + in_bytes -= 4; + rx_lvl -= 4; + } + } +} + +int exynos_spi_open(struct exynos_spi *regs) +{ + clock_set_rate(PERIPH_ID_SPI1, 50000000); /* set spi clock to 50Mhz */ + /* set the spi1 GPIO */ +// exynos_pinmux_config(PERIPH_ID_SPI1, PINMUX_FLAG_NONE); + gpio_cfg_pin(GPIO_A24, 0x2); + gpio_cfg_pin(GPIO_A25, 0x2); + gpio_cfg_pin(GPIO_A26, 0x2); + gpio_cfg_pin(GPIO_A27, 0x2); + + /* set pktcnt and enable it */ + writel(4 | SPI_PACKET_CNT_EN, ®s->pkt_cnt); + /* set FB_CLK_SEL */ + writel(SPI_FB_DELAY_180, ®s->fb_clk); + /* set CH_WIDTH and BUS_WIDTH as word */ + setbits_le32(®s->mode_cfg, + SPI_MODE_CH_WIDTH_WORD | SPI_MODE_BUS_WIDTH_WORD); + clrbits_le32(®s->ch_cfg, SPI_CH_CPOL_L); /* CPOL: active high */ + + /* clear rx and tx channel if set priveously */ + clrbits_le32(®s->ch_cfg, SPI_RX_CH_ON | SPI_TX_CH_ON); + + setbits_le32(®s->swap_cfg, + SPI_RX_SWAP_EN | SPI_RX_BYTE_SWAP | SPI_RX_HWORD_SWAP); + + /* do a soft reset */ + setbits_le32(®s->ch_cfg, SPI_CH_RST); + clrbits_le32(®s->ch_cfg, SPI_CH_RST); + + /* now set rx and tx channel ON */ + setbits_le32(®s->ch_cfg, SPI_RX_CH_ON | SPI_TX_CH_ON | SPI_CH_HS_EN); + clrbits_le32(®s->cs_reg, SPI_SLAVE_SIG_INACT); /* CS low */ + return 0; +} + +int exynos_spi_read(struct exynos_spi *regs, void *dest, u32 len, u32 off) +{ + int upto, todo; + int i; + /* Send read instruction (0x3h) followed by a 24 bit addr */ + writel((SF_READ_DATA_CMD << 24) | off, ®s->tx_data); + + /* waiting for TX done */ + while (!(readl(®s->spi_sts) & SPI_ST_TX_DONE)); + + for (upto = 0, i = 0; upto < len; upto += todo, i++) { + todo = MIN(len - upto, (1 << 15)); + exynos_spi_rx_tx(regs, todo, dest, (void *)(off), i); + } + + setbits_le32(®s->cs_reg, SPI_SLAVE_SIG_INACT);/* make the CS high */ + + /* + * Let put controller mode to BYTE as + * SPI driver does not support WORD mode yet + */ + clrbits_le32(®s->mode_cfg, + SPI_MODE_CH_WIDTH_WORD | SPI_MODE_BUS_WIDTH_WORD); + writel(0, ®s->swap_cfg); + + return len; +} + +int exynos_spi_close(struct exynos_spi *regs) +{ + /* + * Flush spi tx, rx fifos and reset the SPI controller + * and clear rx/tx channel + */ + clrsetbits_le32(®s->ch_cfg, SPI_CH_HS_EN, SPI_CH_RST); + clrbits_le32(®s->ch_cfg, SPI_CH_RST); + clrbits_le32(®s->ch_cfg, SPI_TX_CH_ON | SPI_RX_CH_ON); + return 0; +} + +// SPI as CBFS media. +struct exynos_spi_media { + struct exynos_spi *regs; + struct cbfs_simple_buffer buffer; +}; + +static int exynos_spi_cbfs_open(struct cbfs_media *media) { + struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context; + printk(BIOS_SPEW, "SPI: exynos_spi_cbfs_open\n"); + return exynos_spi_open(spi->regs); +} + +static int exynos_spi_cbfs_close(struct cbfs_media *media) { + struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context; + printk(BIOS_SPEW, "SPI: exynos_spi_cbfs_close\n"); + return exynos_spi_close(spi->regs); +} + +static size_t exynos_spi_cbfs_read(struct cbfs_media *media, void *dest, + size_t offset, size_t count) { + struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context; + int bytes; + printk(BIOS_SPEW, "SPI: exynos_spi_cbfs_read\n"); + bytes = exynos_spi_read(spi->regs, dest, count, offset); + // Flush and re-open the device. + exynos_spi_close(spi->regs); + exynos_spi_open(spi->regs); + return bytes; +} + +static void *exynos_spi_cbfs_map(struct cbfs_media *media, size_t offset, + size_t count) { + struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context; + printk(BIOS_SPEW, "SPI: exynos_spi_cbfs_map\n"); + return cbfs_simple_buffer_map(&spi->buffer, media, offset, count); +} + +static void *exynos_spi_cbfs_unmap(struct cbfs_media *media, + const void *address) { + struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context; + printk(BIOS_SPEW, "SPI: exynos_spi_cbfs_unmap\n"); + return cbfs_simple_buffer_unmap(&spi->buffer, address); +} + +int initialize_exynos_spi_cbfs_media(struct cbfs_media *media, + void *buffer_address, + size_t buffer_size) { + // TODO Replace static variable to support multiple streams. + static struct exynos_spi_media context; + printk(BIOS_SPEW, "SPI: initialize_exynos_spi_cbfs_media\n"); + + context.regs = EXYNOS_BASE_SPI1; + context.buffer.allocated = context.buffer.last_allocate = 0; + context.buffer.buffer = buffer_address; + context.buffer.size = buffer_size; + media->context = (void*)&context; + media->open = exynos_spi_cbfs_open; + media->close = exynos_spi_cbfs_close; + media->read = exynos_spi_cbfs_read; + media->map = exynos_spi_cbfs_map; + media->unmap = exynos_spi_cbfs_unmap; + + return 0; +} + +int init_default_cbfs_media(struct cbfs_media *media) { + // TODO make 0x17000 (size of cache) a Kconfig variable, or calculate by + // top of IRAM. + return initialize_exynos_spi_cbfs_media( + media, (void*)CONFIG_CBFS_CACHE_ADDRESS, 0x17000); +} diff --git a/src/cpu/samsung/exynos5-common/spi.h b/src/cpu/samsung/exynos5-common/spi.h index 3f36759..e021888 100644 --- a/src/cpu/samsung/exynos5-common/spi.h +++ b/src/cpu/samsung/exynos5-common/spi.h @@ -22,6 +22,9 @@
#ifndef __ASSEMBLER__
+// This driver serves as a CBFS media source. +#include <cbfs.h> + /* SPI peripheral register map; padded to 64KB */ struct exynos_spi { unsigned int ch_cfg; /* 0x00 */ @@ -85,5 +88,15 @@ struct exynos_spi { #define SPI_RX_BYTE_SWAP (1 << 6) #define SPI_RX_HWORD_SWAP (1 << 7)
+/* API */ +int exynos_spi_open(struct exynos_spi *regs); +int exynos_spi_read(struct exynos_spi *regs, void *dest, u32 len, u32 off); +int exynos_spi_close(struct exynos_spi *regs); + +/* Serve as CBFS Media */ +int initialize_exynos_spi_cbfs_media(struct cbfs_media *media, + void *buffer_address, + size_t buffer_size); + #endif /* __ASSEMBLER__ */ #endif diff --git a/src/cpu/samsung/exynos5-common/spl_boot.c b/src/cpu/samsung/exynos5-common/spl_boot.c index ecff871..1e264e3 100644 --- a/src/cpu/samsung/exynos5-common/spl_boot.c +++ b/src/cpu/samsung/exynos5-common/spl_boot.c @@ -55,9 +55,6 @@
#include <arch/io.h>
-/* FIXME(dhendrix): clean out u-boot global data stuff */ -//DECLARE_GLOBAL_DATA_PTR; - #define OM_STAT (0x1f << 1)
/** @@ -102,117 +99,6 @@ static int config_branch_prediction(int set_cr_z) return cr & CR_Z; }
-#if 0 -static void spi_rx_tx(struct exynos_spi *regs, int todo, - void *dinp, void const *doutp, int i) -{ - uint *rxp = (uint *)(dinp + (i * (32 * 1024))); - int rx_lvl, tx_lvl; - uint out_bytes, in_bytes; - - out_bytes = in_bytes = todo; - setbits_le32(®s->ch_cfg, SPI_CH_RST); - clrbits_le32(®s->ch_cfg, SPI_CH_RST); - writel(((todo * 8) / 32) | SPI_PACKET_CNT_EN, ®s->pkt_cnt); - - while (in_bytes) { - uint32_t spi_sts; - int temp; - - spi_sts = readl(®s->spi_sts); - rx_lvl = ((spi_sts >> 15) & 0x7f); - tx_lvl = ((spi_sts >> 6) & 0x7f); - while (tx_lvl < 32 && out_bytes) { - temp = 0xffffffff; - writel(temp, ®s->tx_data); - out_bytes -= 4; - tx_lvl += 4; - } - while (rx_lvl >= 4 && in_bytes) { - temp = readl(®s->rx_data); - if (rxp) - *rxp++ = temp; - in_bytes -= 4; - rx_lvl -= 4; - } - } -} -#endif - -/* FIXME(dhendrix): feels like exynos_spi_copy should go somewhere else... */ -#if 0 -/** - * Copy uboot from spi flash to RAM - * - * @parma uboot_size size of u-boot to copy - */ -static void exynos_spi_copy(unsigned int uboot_size) -{ - int upto, todo; - int i; -// struct exynos_spi *regs = (struct exynos_spi *)samsung_get_base_spi1(); - struct exynos_spi *regs = (struct exynos_spi *)0x12d30000; - - clock_set_rate(PERIPH_ID_SPI1, 50000000); /* set spi clock to 50Mhz */ - /* set the spi1 GPIO */ - exynos_pinmux_config(PERIPH_ID_SPI1, PINMUX_FLAG_NONE); - - /* set pktcnt and enable it */ - writel(4 | SPI_PACKET_CNT_EN, ®s->pkt_cnt); - /* set FB_CLK_SEL */ - writel(SPI_FB_DELAY_180, ®s->fb_clk); - /* set CH_WIDTH and BUS_WIDTH as word */ - setbits_le32(®s->mode_cfg, SPI_MODE_CH_WIDTH_WORD | - SPI_MODE_BUS_WIDTH_WORD); - clrbits_le32(®s->ch_cfg, SPI_CH_CPOL_L); /* CPOL: active high */ - - /* clear rx and tx channel if set priveously */ - clrbits_le32(®s->ch_cfg, SPI_RX_CH_ON | SPI_TX_CH_ON); - - setbits_le32(®s->swap_cfg, SPI_RX_SWAP_EN | - SPI_RX_BYTE_SWAP | - SPI_RX_HWORD_SWAP); - - /* do a soft reset */ - setbits_le32(®s->ch_cfg, SPI_CH_RST); - clrbits_le32(®s->ch_cfg, SPI_CH_RST); - - /* now set rx and tx channel ON */ - setbits_le32(®s->ch_cfg, SPI_RX_CH_ON | SPI_TX_CH_ON | SPI_CH_HS_EN); - clrbits_le32(®s->cs_reg, SPI_SLAVE_SIG_INACT); /* CS low */ - - /* Send read instruction (0x3h) followed by a 24 bit addr */ - writel((SF_READ_DATA_CMD << 24) | SPI_FLASH_UBOOT_POS, ®s->tx_data); - - /* waiting for TX done */ - while (!(readl(®s->spi_sts) & SPI_ST_TX_DONE)); - - for (upto = 0, i = 0; upto < uboot_size; upto += todo, i++) { - todo = MIN(uboot_size - upto, (1 << 15)); - spi_rx_tx(regs, todo, (void *)(CONFIG_SYS_TEXT_BASE), - (void *)(SPI_FLASH_UBOOT_POS), i); - } - - setbits_le32(®s->cs_reg, SPI_SLAVE_SIG_INACT);/* make the CS high */ - - /* - * Let put controller mode to BYTE as - * SPI driver does not support WORD mode yet - */ - clrbits_le32(®s->mode_cfg, SPI_MODE_CH_WIDTH_WORD | - SPI_MODE_BUS_WIDTH_WORD); - writel(0, ®s->swap_cfg); - - /* - * Flush spi tx, rx fifos and reset the SPI controller - * and clear rx/tx channel - */ - clrsetbits_le32(®s->ch_cfg, SPI_CH_HS_EN, SPI_CH_RST); - clrbits_le32(®s->ch_cfg, SPI_CH_RST); - clrbits_le32(®s->ch_cfg, SPI_TX_CH_ON | SPI_RX_CH_ON); -} -#endif - /* Copy U-Boot image to RAM */ static void copy_uboot_to_ram(void) { @@ -272,34 +158,6 @@ static void copy_uboot_to_ram(void) debug("U-Boot copied\n"); }
-#if 0 -/** - * Set up the U-Boot global_data pointer - * - * This sets the address of the global data, and sets up basic values. - * - * @param gdp Value to give to gd - */ -static void setup_global_data(gd_t *gdp) -{ - gd = gdp; - memzero((void *)gd, sizeof(gd_t)); - gd->flags |= GD_FLG_RELOC; - gd->baudrate = CONFIG_BAUDRATE; - gd->have_console = 1; -} -#endif - -#if 0 -/* Tell the loaded U-Boot that it was loaded from SPL */ -static void exynos5_set_spl_marker(void) -{ - uint32_t *marker = (uint32_t *)CONFIG_SPL_MARKER; - - *marker = EXYNOS5_SPL_MARKER; -} -#endif - /* Board-specific call to see if wakeup is allowed. */ static int __def_board_wakeup_permitted(void) { @@ -308,152 +166,3 @@ static int __def_board_wakeup_permitted(void) int board_wakeup_permitted(void) __attribute__((weak, alias("__def_board_wakeup_permitted")));
-void board_init_f(void) -{ - /* - * The gd struct is only needed for serial initialization. Since this - * function is called in SPL u-boot. We store the gd struct in the - * stack instead of the default memory region which may not be - * initialized. - */ -// __attribute__((aligned(8))) gd_t local_gd; -// __attribute__((noreturn)) void (*uboot)(void); - -// exynos5_set_spl_marker(); -// setup_global_data(&local_gd); - - /* - * Init subsystems, and resume if required. For a normal boot this - * will set up the UART and display a message. - */ - if (lowlevel_init_subsystems()) { - if (!board_wakeup_permitted()) - power_reset(); - power_exit_wakeup(); - } - -// printk(BIOS_INFO, "\n\nU-Boot SPL, board rev %u\n", board_get_revision()); - - copy_uboot_to_ram(); - /* Jump to U-Boot image */ -// uboot = (void *)CONFIG_SYS_TEXT_BASE; -// uboot(); - /* Never returns Here */ -// printk(BIOS_ERR, "%s: u-boot jump failed", __func__); - printk(BIOS_INFO, "%s: we should not be here...", __func__); - hlt(); -} - -/* Place Holders */ -void board_init_r(gd_t *id, ulong dest_addr) -{ - /* Function attribute is no-return */ - /* This Function never executes */ - while (1) - ; -} - -//void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3) {} - -#if 0 -/* - * The following functions are required when linking console library to SPL. - * - * Enabling UART in SPL u-boot requires console library. But some - * functions we needed in the console library depends on a bunch - * of library in libgeneric, like lib/ctype.o, lib/div64.o, lib/string.o, - * and lib/vsprintf.o. Adding them makes the SPL u-boot too large and not - * fit into the expected size. - * - * So we mock these functions in SPL, i.e. vsprintf(), panic(), etc., - * in order to cut its dependency. - */ -int vsprintf(char *buf, const char *fmt, va_list args) -{ - char *str = buf, *s; - ulong u; - - /* - * We won't implement all full functions of vsprintf(). - * We only implement %s and %u, and ignore others and directly use - * the original format string as its result. - */ - - while (*fmt) { - if (*fmt != '%') { - *str++ = *fmt++; - continue; - } - fmt++; - switch (*fmt) { - case '%': - *str++ = *fmt++; - break; - case 's': - fmt++; - s = va_arg(args, char *); - while (*s) - *str++ = *s++; - break; - case 'u': - fmt++; - u = va_arg(args, ulong); - s = simple_itoa(u); - while (*s) - *str++ = *s++; - break; - default: - /* Print the original string for unsupported formats */ - *str++ = '%'; - *str++ = *fmt++; - } - } - *str = '\0'; - return str - buf; -} -#endif - -#if 0 -void panic(const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - vprintf(fmt, args); - putc('\n'); - va_end(args); -#if defined(CONFIG_PANIC_HANG) - hang(); -#else - udelay(100000); /* allow messages to go out */ - do_reset(NULL, 0, 0, NULL); -#endif - while (1) - ; -} -#endif - -#if 0 -void __assert_fail(const char *assertion, const char *file, unsigned line, - const char *function) -{ - /* This will not return */ - panic("%s:%u: %s: Assertion `%s' failed.", file, line, function, - assertion); -} -#endif - -#if 0 -char *simple_itoa(ulong i) -{ - /* 21 digits plus null terminator, good for 64-bit or smaller ints */ - static char local[22] __attribute__((section(".data"))); - char *p = &local[21]; - - *p-- = '\0'; - do { - *p-- = '0' + i % 10; - i /= 10; - } while (i > 0); - return p + 1; -} -#endif diff --git a/src/cpu/samsung/exynos5250/Kconfig b/src/cpu/samsung/exynos5250/Kconfig index f5beddc..2c417cb 100644 --- a/src/cpu/samsung/exynos5250/Kconfig +++ b/src/cpu/samsung/exynos5250/Kconfig @@ -48,6 +48,14 @@ config ROMSTAGE_SIZE hex default 0x10000
+config CBFS_HEADER_ROM_OFFSET + hex "offset of master CBFS header in ROM" + default 0x2040 + +config CBFS_CACHE_ADDRESS + hex "memory address to put CBFS cache data" + default 0x02060000 + # 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 8f7ee22..d5757f8 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 697d869..07eff0d 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 9dbe07c..5952dae 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 fe67515..bb0d760 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 d8d1778..5ffa9d7 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 b33e932..f8b4304 100644 --- a/src/include/cbfs.h +++ b/src/include/cbfs.h @@ -49,14 +49,38 @@ #ifndef _CBFS_H_ #define _CBFS_H_
-#include "cbfs_core.h" -#include <boot/coreboot_tables.h> +#include <cbfs_core.h>
-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 a3c54b1..cfa8a82 100644 --- a/src/include/cbfs_core.h +++ b/src/include/cbfs_core.h @@ -50,6 +50,10 @@ #ifndef _CBFS_CORE_H_ #define _CBFS_CORE_H_
+#include <endian.h> +#include <stddef.h> +#include <stdint.h> + /** 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 +78,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 +179,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)) + +/* Media for CBFS to load files. */ +struct cbfs_media { + + /* implementation dependent context, to hold resource references */ + void *context;
-/* returns pointer to file data inside CBFS */ -void *cbfs_get_file(const char *name); + /* opens media and returns 0 on success, -1 on failure */ + int (*open)(struct cbfs_media *media);
-/* returns pointer to file data inside CBFS after if type is correct */ -void *cbfs_find_file(const char *name, int type); + /* 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 0000000..7ce26b8 --- /dev/null +++ b/src/include/endian.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2012 The Chromium OS Authors. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 diff --git a/src/lib/cbfs.c b/src/lib/cbfs.c index 98672d4..a9911f4 100644 --- a/src/lib/cbfs.c +++ b/src/lib/cbfs.c @@ -17,57 +17,68 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA */
-#include <types.h> -#include <string.h> -#include <console/console.h> +#ifdef LIBPAYLOAD +#include <libpayload-config.h> +#endif + #include <cbfs.h> -#include <lib.h> -#include <arch/byteorder.h> +#include <string.h>
-// 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 <stdio.h> +# define DEBUG(x...) +# define LOG(x...) printf(x) +# define ERROR(x...) printf(x) #else -#define DEBUG(x...) +# 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 -// 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 +88,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 +105,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 +137,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 +152,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 +213,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 15cb68e..2c9fcc8 100644 --- a/src/lib/cbfs_core.c +++ b/src/lib/cbfs_core.c @@ -27,14 +27,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 +46,138 @@ * 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 <cbfs_core.h> +#include <cbfs.h> +#include <string.h>
+#ifdef CBFS_CORE_WITH_LZMA +extern unsigned long ulzma(unsigned char *src, unsigned char *dst); +#endif
-/* 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; - - /* 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; + const struct cbfs_header *header; + struct cbfs_media default_media; + + if (media == CBFS_DEFAULT_MEDIA) { + media = &default_media; + if (init_default_cbfs_media(media) != 0) { + ERROR("Failed to 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; - - 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); + 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; + + if (media == CBFS_DEFAULT_MEDIA) { + media = &default_media; + if (init_default_cbfs_media(media) != 0) { + ERROR("Failed to initializee default media.\n"); return NULL; } } - return NULL; -} - -void *cbfs_get_file(const char *name) -{ - struct cbfs_file *file = cbfs_find(name);
- if (file == NULL) { - ERROR("Could not find file '%s'.\n", name); + if (CBFS_HEADER_INVALID_ADDRESS == (header = cbfs_get_header(media))) return NULL; - }
- return (void*)CBFS_SUBHEADER(file); + // 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_find_file(const char *name, int type) +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); @@ -151,7 +185,8 @@ 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; }
@@ -172,7 +207,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 eed243a..85c05f5 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 c5fb62a..56124da 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 d5ee0a3..e9fc13e 100644 --- a/src/mainboard/google/snow/bootblock.c +++ b/src/mainboard/google/snow/bootblock.c @@ -17,11 +17,10 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
-#define uchar unsigned char -#define uint unsigned int - #include <stdlib.h> #include <types.h> +#include <assert.h> +#include <arch/armv7/include/common.h> #include <arch/io.h> #include "cpu/samsung/exynos5250/clk.h" #include "cpu/samsung/exynos5250/cpu.h" @@ -34,6 +33,7 @@ #include "cpu/samsung/s5p-common/s3c24x0_i2c.h" #include "cpu/samsung/exynos5-common/spi.h" #include "cpu/samsung/exynos5-common/uart.h" +#include "cbfs_core.h"
#include <device/i2c.h> #include <drivers/maxim/max77686/max77686.h> @@ -42,87 +42,9 @@
#define EXYNOS5_CLOCK_BASE 0x10010000
-/* 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) -{ - unsigned int *rxp = (unsigned int *)(dinp + (i * (32 * 1024))); - int rx_lvl, tx_lvl; - unsigned int out_bytes, in_bytes; - - out_bytes = in_bytes = todo; - setbits_le32(®s->ch_cfg, SPI_CH_RST); - clrbits_le32(®s->ch_cfg, SPI_CH_RST); - writel(((todo * 8) / 32) | SPI_PACKET_CNT_EN, ®s->pkt_cnt); - - while (in_bytes) { - uint32_t spi_sts; - int temp; - - spi_sts = readl(®s->spi_sts); - rx_lvl = ((spi_sts >> 15) & 0x7f); - tx_lvl = ((spi_sts >> 6) & 0x7f); - while (tx_lvl < 32 && out_bytes) { - temp = 0xffffffff; - writel(temp, ®s->tx_data); - out_bytes -= 4; - tx_lvl += 4; - } - while (rx_lvl >= 4 && in_bytes) { - temp = readl(®s->rx_data); - if (rxp) - *rxp++ = temp; - in_bytes -= 4; - rx_lvl -= 4; - } - } -} +// TODO Move this to Makefile.inc once we support adding bootblock stage files. +#include "cpu/samsung/exynos5-common/spi.c"
-#if 0 -void clock_ll_set_pre_ratio(enum periph_id periph_id, unsigned divisor) -{ - struct exynos5_clock *clk = - (struct exynos5_clock *)samsung_get_base_clock(); - unsigned shift; - unsigned mask = 0xff; - u32 *reg; - - /* - * For now we only handle a very small subset of peipherals here. - * Others will need to (and do) mangle the clock registers - * themselves, At some point it is hoped that this function can work - * from a table or calculated register offset / mask. For now this - * is at least better than spreading clock control code around - * U-Boot. - */ - switch (periph_id) { - case PERIPH_ID_SPI0: - reg = &clk->div_peric1; - shift = 8; - break; - case PERIPH_ID_SPI1: - reg = &clk->div_peric1; - shift = 24; - break; - case PERIPH_ID_SPI2: - reg = &clk->div_peric2; - shift = 8; - break; - case PERIPH_ID_SPI3: - reg = &clk->sclk_div_isp; - shift = 4; - break; - case PERIPH_ID_SPI4: - reg = &clk->sclk_div_isp; - shift = 16; - break; - default: - debug("%s: Unsupported peripheral ID %d\n", __func__, - periph_id); - return; - } -} -#endif void clock_ll_set_pre_ratio(enum periph_id periph_id, unsigned divisor) { struct exynos5_clock *clk = @@ -136,43 +58,6 @@ void clock_ll_set_pre_ratio(enum periph_id periph_id, unsigned divisor) clrsetbits_le32(reg, mask << shift, (divisor & mask) << shift); }
-#if 0 -void clock_ll_set_ratio(enum periph_id periph_id, unsigned divisor) -{ - struct exynos5_clock *clk = - (struct exynos5_clock *)samsung_get_base_clock(); - unsigned shift; - unsigned mask = 0xff; - u32 *reg; - - switch (periph_id) { - case PERIPH_ID_SPI0: - reg = &clk->div_peric1; - shift = 0; - break; - case PERIPH_ID_SPI1: - reg = &clk->div_peric1; - shift = 16; - break; - case PERIPH_ID_SPI2: - reg = &clk->div_peric2; - shift = 0; - break; - case PERIPH_ID_SPI3: - reg = &clk->sclk_div_isp; - shift = 0; - break; - case PERIPH_ID_SPI4: - reg = &clk->sclk_div_isp; - shift = 12; - break; - default: - debug("%s: Unsupported peripheral ID %d\n", __func__, - periph_id); - return; - } -} -#endif void clock_ll_set_ratio(enum periph_id periph_id, unsigned divisor) { struct exynos5_clock *clk = @@ -249,44 +134,6 @@ static int clock_calc_best_scalar(unsigned int main_scaler_bits, return best_main_scalar; }
-#if 0 -int clock_set_rate(enum periph_id periph_id, unsigned int rate) -{ - int main; - unsigned int fine; - - switch (periph_id) { - case PERIPH_ID_SPI0: - case PERIPH_ID_SPI1: - case PERIPH_ID_SPI2: - case PERIPH_ID_SPI3: - case PERIPH_ID_SPI4: - main = clock_calc_best_scalar(4, 8, 400000000, rate, &fine); - if (main < 0) { - debug("%s: Cannot set clock rate for periph %d", - __func__, periph_id); - return -1; - } - clock_ll_set_ratio(periph_id, main - 1); - clock_ll_set_pre_ratio(periph_id, fine - 1); - break; - default: - debug("%s: Unsupported peripheral ID %d\n", __func__, - periph_id); - return -1; - } - main = clock_calc_best_scalar(4, 8, 400000000, rate, &fine); - if (main < 0) { - debug("%s: Cannot set clock rate for periph %d", - __func__, periph_id); - return -1; - } - clock_ll_set_ratio(PERIPH_ID_SPI1, main - 1); - clock_ll_set_pre_ratio(PERIPH_ID_SPI1, fine - 1); - - return 0; -} -#endif int clock_set_rate(enum periph_id periph_id, unsigned int rate) { int main; @@ -358,77 +205,6 @@ void gpio_cfg_pin(int gpio, int cfg) writel(value, &bank->con); }
-//static void exynos_spi_copy(unsigned int uboot_size) -static void copy_romstage(uint32_t spi_addr, uint32_t sram_addr, unsigned int len) -{ - int upto, todo; - int i; -// struct exynos_spi *regs = (struct exynos_spi *)samsung_get_base_spi1(); - struct exynos_spi *regs = (struct exynos_spi *)0x12d30000; - - clock_set_rate(PERIPH_ID_SPI1, 50000000); /* set spi clock to 50Mhz */ - /* set the spi1 GPIO */ -// exynos_pinmux_config(PERIPH_ID_SPI1, PINMUX_FLAG_NONE); - gpio_cfg_pin(GPIO_A24, 0x2); - gpio_cfg_pin(GPIO_A25, 0x2); - gpio_cfg_pin(GPIO_A26, 0x2); - gpio_cfg_pin(GPIO_A27, 0x2); - - /* set pktcnt and enable it */ - writel(4 | SPI_PACKET_CNT_EN, ®s->pkt_cnt); - /* set FB_CLK_SEL */ - writel(SPI_FB_DELAY_180, ®s->fb_clk); - /* set CH_WIDTH and BUS_WIDTH as word */ - setbits_le32(®s->mode_cfg, SPI_MODE_CH_WIDTH_WORD | - SPI_MODE_BUS_WIDTH_WORD); - clrbits_le32(®s->ch_cfg, SPI_CH_CPOL_L); /* CPOL: active high */ - - /* clear rx and tx channel if set priveously */ - clrbits_le32(®s->ch_cfg, SPI_RX_CH_ON | SPI_TX_CH_ON); - - setbits_le32(®s->swap_cfg, SPI_RX_SWAP_EN | - SPI_RX_BYTE_SWAP | - SPI_RX_HWORD_SWAP); - - /* do a soft reset */ - setbits_le32(®s->ch_cfg, SPI_CH_RST); - clrbits_le32(®s->ch_cfg, SPI_CH_RST); - - /* now set rx and tx channel ON */ - setbits_le32(®s->ch_cfg, SPI_RX_CH_ON | SPI_TX_CH_ON | SPI_CH_HS_EN); - clrbits_le32(®s->cs_reg, SPI_SLAVE_SIG_INACT); /* CS low */ - - /* Send read instruction (0x3h) followed by a 24 bit addr */ - writel((SF_READ_DATA_CMD << 24) | spi_addr, ®s->tx_data); - - /* waiting for TX done */ - while (!(readl(®s->spi_sts) & SPI_ST_TX_DONE)); - - for (upto = 0, i = 0; upto < len; upto += todo, i++) { - todo = MIN(len - upto, (1 << 15)); - spi_rx_tx(regs, todo, (void *)(sram_addr), - (void *)(spi_addr), i); - } - - setbits_le32(®s->cs_reg, SPI_SLAVE_SIG_INACT);/* make the CS high */ - - /* - * Let put controller mode to BYTE as - * SPI driver does not support WORD mode yet - */ - clrbits_le32(®s->mode_cfg, SPI_MODE_CH_WIDTH_WORD | - SPI_MODE_BUS_WIDTH_WORD); - writel(0, ®s->swap_cfg); - - /* - * Flush spi tx, rx fifos and reset the SPI controller - * and clear rx/tx channel - */ - clrsetbits_le32(®s->ch_cfg, SPI_CH_HS_EN, SPI_CH_RST); - clrbits_le32(®s->ch_cfg, SPI_CH_RST); - clrbits_le32(®s->ch_cfg, SPI_TX_CH_ON | SPI_RX_CH_ON); -} - /* Pull mode */ #define EXYNOS_GPIO_PULL_NONE 0x0 #define EXYNOS_GPIO_PULL_DOWN 0x1 @@ -850,21 +626,15 @@ void do_barriers(void) ); }
-void sdelay(unsigned long loops); -void sdelay(unsigned long loops) -{ - __asm__ volatile ("1:\n" "subs %0, %1, #1\n" - "bne 1b":"=r" (loops):"0"(loops)); -} - /* is this right? meh, it seems to work well enough... */ void my_udelay(unsigned int n); void my_udelay(unsigned int n) { - sdelay(n * 1000); + n *= 1000; + __asm__ volatile ("1:\n" "subs %0, %1, #1\n" + "bne 1b":"=r" (n):"0"(n)); }
- void i2c_init(int speed, int slaveadd) { struct s3c24x0_i2c_bus *i2c = &i2c0; @@ -2141,13 +1911,6 @@ void bootblock_mainboard_init(void) do_serial(); printk(BIOS_INFO, "%s: UART initialized\n", __func__);
- /* Copy romstage data from SPI ROM to SRAM */ - printk(BIOS_INFO, "Copying romstage:\n" - "\tSPI offset: 0x%06x\n" - "\tiRAM offset: 0x%08x\n" - "\tSize: 0x%x\n", - 0, CONFIG_SPI_IMAGE_HACK, CONFIG_ROMSTAGE_SIZE); - copy_romstage(0x0, CONFIG_SPI_IMAGE_HACK, CONFIG_ROMSTAGE_SIZE); #if 0 /* FIXME: dump SRAM content for sanity checking */ uint32_t u; diff --git a/src/mainboard/samsung/lumpy/romstage.c b/src/mainboard/samsung/lumpy/romstage.c index 5600cf6..9bc193b 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 7c3b0ac..8c5605c 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 1ec7f87..40e7d9d 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 b5a1c23..f25aaa1 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 (