Dear coreboot admins,
currently I am not able to sign into Gerrit using my Google Mail
account.
Not found
The page you requested was not found, or you do not have permission to view this page.
Do you have similar problems?
Thanks,
Paul
Hung-Te Lin (hungte(a)chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2191
-gerrit
commit 0c99cf50e9b9882cc57d3af70067b54ff854c02f
Author: Hung-Te Lin <hungte(a)chromium.org>
Date: Fri Jan 25 12:42:40 2013 +0800
libpayload: New CBFS to support multiple firmware media source.
Upgrade CBFS in libpayload to use new media-based implementation from coreboot
( http://review.coreboot.org/#/c/2182/ ).
Old CBFS functions (cbfs_find, cbfs_find_file, get_cbfs_header) are still
supported, although the recommended way is to use new CBFS API.
To migrate your existing x86 payload source:
- Change cbfs_find to cbfs_get_file
- Change cbfs_find_file to cbfs_get_file_content
- Prefix every CBFS call with a CBFS_DEFAULT_MEDIA argument.
Ex, char *jpeg_data = cbfs_find_file("splash.jpg", CBFS_TYPE_BOOTSPLASH);
=> char *jpeg_data = cbfs_get_file_content(
CBFS_DEFAULT_MEDIA, "splash.jpg", CBFS_TYPE_BOOTSPLASH);
The legacy setup_cbfs_from_{ram,flash} is also supported, although the better
equivalent is to make a new media instance:
struct cbfs_media ram_media;
init_cbfs_ram_media(&ram_media, start, size);
char *data = cbfs_get_file_content(&ram_media, "myfile", my_type);
Verified by being successfully linked with filo.
Change-Id: If797bc7e3ba975d7e3be905c59424f7a93b8ce11
Signed-off-by: Hung-Te Lin <hungte(a)chromium.org>
---
payloads/libpayload/arch/x86/Makefile.inc | 2 +
payloads/libpayload/arch/x86/rom_media.c | 111 ++++++++++++++
payloads/libpayload/include/cbfs.h | 102 +++++++++++--
payloads/libpayload/include/cbfs_core.h | 74 +++++++---
payloads/libpayload/include/stdint.h | 1 +
payloads/libpayload/libcbfs/Makefile.inc | 1 +
payloads/libpayload/libcbfs/cbfs.c | 232 ++++++++++++++++++++++++------
payloads/libpayload/libcbfs/cbfs_core.c | 198 ++++++++++++++-----------
payloads/libpayload/libcbfs/ram_media.c | 114 +++++++++++++++
9 files changed, 676 insertions(+), 159 deletions(-)
diff --git a/payloads/libpayload/arch/x86/Makefile.inc b/payloads/libpayload/arch/x86/Makefile.inc
index 8f68b07..0977eb1 100644
--- a/payloads/libpayload/arch/x86/Makefile.inc
+++ b/payloads/libpayload/arch/x86/Makefile.inc
@@ -33,5 +33,7 @@ libc-y += timer.c coreboot.c util.S
libc-y += exec.S virtual.c
libc-y += string.c
+libcbfs-$(CONFIG_CBFS) += rom_media.c
+
# Multiboot support is configurable
libc-$(CONFIG_MULTIBOOT) += multiboot.c
diff --git a/payloads/libpayload/arch/x86/rom_media.c b/payloads/libpayload/arch/x86/rom_media.c
new file mode 100644
index 0000000..e9fa94c
--- /dev/null
+++ b/payloads/libpayload/arch/x86/rom_media.c
@@ -0,0 +1,111 @@
+/*
+ * This file is part of the libpayload project.
+ *
+ * Copyright (C) 2013 The Chromium OS Authors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#define LIBPAYLOAD
+
+#include <cbfs.h>
+#include <string.h>
+
+#ifdef LIBPAYLOAD
+# define printk(x...)
+# define init_default_cbfs_media libpayload_init_default_cbfs_media
+ extern int libpayload_init_default_cbfs_media(struct cbfs_media *media);
+#else
+# include <console/console.h>
+#endif
+
+// Implementation of memory-mapped ROM media source on X86.
+
+static int x86_rom_open(struct cbfs_media *media) {
+ return 0;
+}
+
+static void *x86_rom_map(struct cbfs_media *media, size_t offset, size_t count) {
+ void *ptr;
+ // Some address (ex, pointer to master header) may be given in memory
+ // mapped location. To workaround that, we handle >0xf0000000 as real
+ // memory pointer.
+
+ if ((uint32_t)offset > (uint32_t)0xf0000000)
+ ptr = (void*)offset;
+ else
+ ptr = (void*)(0 - (uint32_t)media->context + offset);
+ return ptr;
+}
+
+static void *x86_rom_unmap(struct cbfs_media *media, const void *address) {
+ return NULL;
+}
+
+static size_t x86_rom_read(struct cbfs_media *media, void *dest, size_t offset,
+ size_t count) {
+ void *ptr = x86_rom_map(media, offset, count);
+ memcpy(dest, ptr, count);
+ x86_rom_unmap(media, ptr);
+ return count;
+}
+
+static int x86_rom_close(struct cbfs_media *media) {
+ return 0;
+}
+
+int init_x86rom_cbfs_media(struct cbfs_media *media);
+int init_x86rom_cbfs_media(struct cbfs_media *media) {
+ // On X86, we always keep a reference of pointer to CBFS header in
+ // 0xfffffffc, and the pointer is still a memory-mapped address.
+ // Since the CBFS core always use ROM offset, we need to figure out
+ // header->romsize even before media is initialized.
+ struct cbfs_header *header = (struct cbfs_header*)
+ *(uint32_t*)(0xfffffffc);
+ if (CBFS_HEADER_MAGIC != ntohl(header->magic)) {
+#if defined(CONFIG_ROM_SIZE)
+ printk(BIOS_ERR, "Invalid CBFS master header at %p\n", header);
+ media->context = (void*)CONFIG_ROM_SIZE;
+#else
+ return -1;
+#endif
+ } else {
+ uint32_t romsize = ntohl(header->romsize);
+ media->context = (void*)romsize;
+#if defined(CONFIG_ROM_SIZE)
+ if (CONFIG_ROM_SIZE != romsize)
+ printk(BIOS_INFO, "Warning: rom size unmatch (%d/%d)\n",
+ CONFIG_ROM_SIZE, romsize);
+#endif
+ }
+ media->open = x86_rom_open;
+ media->close = x86_rom_close;
+ media->map = x86_rom_map;
+ media->unmap = x86_rom_unmap;
+ media->read = x86_rom_read;
+ return 0;
+}
+
+int init_default_cbfs_media(struct cbfs_media *media) {
+ return init_x86rom_cbfs_media(media);
+}
diff --git a/payloads/libpayload/include/cbfs.h b/payloads/libpayload/include/cbfs.h
index cf0584e..cf17252 100644
--- a/payloads/libpayload/include/cbfs.h
+++ b/payloads/libpayload/include/cbfs.h
@@ -1,16 +1,92 @@
-#include <arch/types.h>
+/*
+ * This file is part of the libpayload project.
+ *
+ * Copyright (C) 2008 Jordan Crouse <jordan(a)cosmicpenguin.net>
+ * Copyright (C) 2013 The Chromium OS Authors. All rights reserved.
+ *
+ * This file is dual-licensed. You can choose between:
+ * - The GNU GPL, version 2, as published by the Free Software Foundation
+ * - The revised BSD license (without advertising clause)
+ *
+ * ---------------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ * ---------------------------------------------------------------------------
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ---------------------------------------------------------------------------
+ */
+
+#ifndef _CBFS_H_
+#define _CBFS_H_
+
+#include <cbfs_core.h>
+
+/* legacy APIs */
+const struct cbfs_header *get_cbfs_header(void);
+struct cbfs_file *cbfs_find(const char *name);
+void *cbfs_find_file(const char *name, int type);
+
+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);
-/* FIXME: workaround for coreboot/libpayload Kconfig differences */
-#ifndef CONFIG_ARCH_ARMV7
-#define CONFIG_ARCH_ARMV7 0
-#endif
-#ifndef CONFIG_ARCH_POWERPC
-#define CONFIG_ARCH_POWERPC 0
-#endif
-#ifndef CONFIG_ARCH_X86
-#define CONFIG_ARCH_X86 0
#endif
-#include "cbfs_core.h"
-void setup_cbfs_from_ram(void* start, uint32_t size);
-void setup_cbfs_from_flash(void);
diff --git a/payloads/libpayload/include/cbfs_core.h b/payloads/libpayload/include/cbfs_core.h
index a3c54b1..395eef3 100644
--- a/payloads/libpayload/include/cbfs_core.h
+++ b/payloads/libpayload/include/cbfs_core.h
@@ -1,8 +1,9 @@
/*
- * This file is part of the coreboot project.
+ * This file is part of the libpayload project.
*
* Copyright (C) 2008 Jordan Crouse <jordan(a)cosmicpenguin.net>
* Copyright (C) 2012 Google, Inc.
+ * Copyright (C) 2013 The Chromium OS Authors. All rights reserved.
*
* This file is dual-licensed. You can choose between:
* - The GNU GPL, version 2, as published by the Free Software Foundation
@@ -50,6 +51,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 +79,18 @@
#define CBFS_COMPONENT_CMOS_DEFAULT 0xaa
#define CBFS_COMPONENT_CMOS_LAYOUT 0x01aa
-
-/** this is the master cbfs header - it need to be
- located somewhere in the bootblock. Where it
- actually lives is up to coreboot. On x86, a
- pointer to this header will live at 0xFFFFFFFC,
- so we can easily find it. */
-
#define CBFS_HEADER_MAGIC 0x4F524243
-#if CONFIG_ARCH_X86
-#define CBFS_HEADPTR_ADDR 0xFFFFFFFC
-#elif CONFIG_ARCH_ARMV7
-/* FIXME: This could also be 0xFFFF0000 with HIVECS enabled */
-#define CBFS_HEADPTR_ADDR 0x0000000C
-#endif
#define CBFS_HEADER_VERSION1 0x31313131
#define CBFS_HEADER_VERSION2 0x31313132
#define CBFS_HEADER_VERSION CBFS_HEADER_VERSION2
+#define CBFS_HEADER_INVALID_ADDRESS ((void*)(0xffffffff))
+
+/** this is the master cbfs header - it need to be located somewhere available
+ to bootblock (to load romstage). Where it actually lives is up to coreboot.
+ On x86, a pointer to this header will live at 0xFFFFFFFC.
+ For other platforms, you need to define CONFIG_CBFS_HEADER_ROM_OFFSET */
+
struct cbfs_header {
uint32_t magic;
uint32_t version;
@@ -181,16 +180,49 @@ struct cbfs_optionrom {
#define CBFS_NAME(_c) (((char *) (_c)) + sizeof(struct cbfs_file))
#define CBFS_SUBHEADER(_p) ( (void *) ((((uint8_t *) (_p)) + ntohl((_p)->offset))) )
-/* returns pointer to file inside CBFS or NULL */
-struct cbfs_file *cbfs_find(const char *name);
+#define CBFS_MEDIA_INVALID_MAP_ADDRESS ((void*)(0xffffffff))
+#define CBFS_DEFAULT_MEDIA ((void*)(0x0))
+
+/* 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/payloads/libpayload/include/stdint.h b/payloads/libpayload/include/stdint.h
index 8e5083e..dd7439d 100644
--- a/payloads/libpayload/include/stdint.h
+++ b/payloads/libpayload/include/stdint.h
@@ -32,4 +32,5 @@
#include <arch/types.h>
typedef unsigned long uintptr_t;
+typedef long intptr_t;
#endif
diff --git a/payloads/libpayload/libcbfs/Makefile.inc b/payloads/libpayload/libcbfs/Makefile.inc
index 50f4821..0d3e1ec 100644
--- a/payloads/libpayload/libcbfs/Makefile.inc
+++ b/payloads/libpayload/libcbfs/Makefile.inc
@@ -28,4 +28,5 @@
##
libcbfs-$(CONFIG_CBFS) += cbfs.c
+libcbfs-$(CONFIG_CBFS) += ram_media.c
diff --git a/payloads/libpayload/libcbfs/cbfs.c b/payloads/libpayload/libcbfs/cbfs.c
index 026b73c..90d035e 100644
--- a/payloads/libpayload/libcbfs/cbfs.c
+++ b/payloads/libpayload/libcbfs/cbfs.c
@@ -2,6 +2,7 @@
* This file is part of the libpayload project.
*
* Copyright (C) 2011 secunet Security Networks AG
+ * Copyright (C) 2013 The Chromium OS Authors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,80 +27,221 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
+#define LIBPAYLOAD
+
+#ifdef LIBPAYLOAD
+# include <libpayload-config.h>
+# ifdef CONFIG_LZMA
+# include <lzma.h>
+# define CBFS_CORE_WITH_LZMA
+# endif
+# define CBFS_MINI_BUILD
+#elif defined(__SMM__)
+# define CBFS_MINI_BUILD
+#else
+# define CBFS_CORE_WITH_LZMA
+# include <lib.h>
+#endif
-#include <endian.h>
-#include <stdio.h>
-#include <string.h>
#include <cbfs.h>
+#include <string.h>
-#ifdef CONFIG_LZMA
-#define CBFS_CORE_WITH_LZMA
-#include <lzma.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
-#define ERROR(x...) printf(x)
-#define LOG(x...)
-
-static uint32_t host_virt_to_phys(void *addr);
-static void *host_phys_to_virt(uint32_t addr);
+#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
-uint32_t romstart(void);
-uint32_t romend(void);
+#include "cbfs_core.c"
-#include <arch/virtual.h>
-static uint32_t host_virt_to_phys(void *addr)
+#ifndef __SMM__
+static inline int tohex4(unsigned int c)
{
- return virt_to_phys(addr);
+ return (c <= 9) ? (c + '0') : (c - 10 + 'a');
}
-static void *host_phys_to_virt(uint32_t addr)
+static void tohex16(unsigned int val, char* dest)
{
- return phys_to_virt(addr);
+ dest[0] = tohex4(val>>12);
+ dest[1] = tohex4((val>>8) & 0xf);
+ dest[2] = tohex4((val>>4) & 0xf);
+ dest[3] = tohex4(val & 0xf);
}
-#undef virt_to_phys
-#undef phys_to_virt
-uint32_t (*virt_to_phys)(void *) = host_virt_to_phys;
-void* (*phys_to_virt)(uint32_t) = host_phys_to_virt;
+void *cbfs_load_optionrom(struct cbfs_media *media, uint16_t vendor,
+ uint16_t device, void *dest)
+{
+ char name[17] = "pciXXXX,XXXX.rom";
+ struct cbfs_optionrom *orom;
+ uint8_t *src;
+ tohex16(vendor, name+3);
+ tohex16(device, name+8);
-uint32_t _romstart = 0xffffffff;
-uint32_t _romend = 0;
+ orom = (struct cbfs_optionrom *)
+ cbfs_get_file_content(media, name, CBFS_TYPE_OPTIONROM);
-uint32_t romstart(void)
-{
- return _romstart;
+ if (orom == NULL)
+ return NULL;
+
+ /* They might have specified a dest address. If so, we can decompress.
+ * If not, there's not much hope of decompressing or relocating the rom.
+ * in the common case, the expansion rom is uncompressed, we
+ * pass 0 in for the dest, and all we have to do is find the rom and
+ * return a pointer to it.
+ */
+
+ /* BUG: the cbfstool is (not yet) including a cbfs_optionrom header */
+ src = (uint8_t*)orom; // + sizeof(struct cbfs_optionrom);
+
+ if (! dest)
+ return src;
+
+ if (cbfs_decompress(ntohl(orom->compression),
+ src,
+ dest,
+ ntohl(orom->len)))
+ return NULL;
+
+ return dest;
}
-uint32_t romend(void)
+void * cbfs_load_stage(struct cbfs_media *media, const char *name)
{
- return _romend;
+ struct cbfs_stage *stage = (struct cbfs_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. */
+ uint32_t entry;
+
+ if (stage == NULL)
+ return (void *) -1;
+
+ LOG("loading stage %s @ 0x%x (%d bytes), entry @ 0x%llx\n",
+ name,
+ (uint32_t) stage->load, stage->memlen,
+ stage->entry);
+ memset((void *) (uint32_t) stage->load, 0, stage->memlen);
+
+ if (cbfs_decompress(stage->compression,
+ ((unsigned char *) stage) +
+ sizeof(struct cbfs_stage),
+ (void *) (uint32_t) stage->load,
+ stage->len))
+ return (void *) -1;
+
+ DEBUG("stage loaded.\n");
+
+ entry = stage->entry;
+ // entry = ntohll(stage->entry);
+
+ return (void *) entry;
}
-#include "cbfs_core.c"
+int cbfs_execute_stage(struct cbfs_media *media, const char *name)
+{
+ struct cbfs_stage *stage = (struct cbfs_stage *)
+ cbfs_get_file_content(media, name, CBFS_TYPE_STAGE);
-static uint32_t ram_cbfs_offset;
+ if (stage == NULL)
+ return 1;
-static uint32_t ram_virt_to_phys(void *addr)
-{
- return (uint32_t)addr - ram_cbfs_offset;
+ if (ntohl(stage->compression) != CBFS_COMPRESS_NONE) {
+ LOG("Unable to run %s: Compressed file"
+ "Not supported for in-place execution\n", name);
+ return 1;
+ }
+
+ /* FIXME: This isn't right */
+ LOG("run @ %p\n", (void *) ntohl((uint32_t) stage->entry));
+ return run_address((void *)(uintptr_t)ntohll(stage->entry));
}
-static void *ram_phys_to_virt(uint32_t addr)
+void *cbfs_load_payload(struct cbfs_media *media, const char *name)
{
- return (void*)addr + ram_cbfs_offset;
+ return (struct cbfs_payload *)cbfs_get_file_content(
+ media, name, CBFS_TYPE_PAYLOAD);
}
-void setup_cbfs_from_ram(void* start, uint32_t size)
-{
- /* assumes rollover */
- ram_cbfs_offset = (uint32_t)start + size;
- virt_to_phys = ram_virt_to_phys;
- phys_to_virt = ram_phys_to_virt;
+struct cbfs_file *cbfs_find(const char *name) {
+ return cbfs_get_file(CBFS_DEFAULT_MEDIA, name);
+}
+
+void *cbfs_find_file(const char *name, int type) {
+ return cbfs_get_file_content(CBFS_DEFAULT_MEDIA, name, type);
+}
+
+const struct cbfs_header *get_cbfs_header(void) {
+ return cbfs_get_header(CBFS_DEFAULT_MEDIA);
}
-void setup_cbfs_from_flash(void)
+/* 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;
+}
+
+/**
+ * run_address is passed the address of a function taking no parameters and
+ * jumps to it, returning the result.
+ * @param f the address to call as a function.
+ * @return value returned by the function.
+ */
+
+int run_address(void *f)
{
- virt_to_phys = host_virt_to_phys;
- phys_to_virt = host_phys_to_virt;
+ int (*v) (void);
+ v = f;
+ return v();
}
+
+#endif
diff --git a/payloads/libpayload/libcbfs/cbfs_core.c b/payloads/libpayload/libcbfs/cbfs_core.c
index 4bf755b..3a95def 100644
--- a/payloads/libpayload/libcbfs/cbfs_core.c
+++ b/payloads/libpayload/libcbfs/cbfs_core.c
@@ -2,6 +2,7 @@
* This file is part of the libpayload project.
*
* Copyright (C) 2011 secunet Security Networks AG
+ * Copyright (C) 2013 The Chromium OS Authors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -27,119 +28,153 @@
* 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)
*
* LOG(x...)
- * print a debug message x (in printf format)
+ * print a 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.
+ * DEBUG(x...)
+ * print a debug message x (in printf format)
*
- * 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 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("Searching 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;
- }
- LOG("Check %s\n", CBFS_NAME(file));
- if (strcmp(CBFS_NAME(file), name) == 0) {
- 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);
@@ -147,7 +182,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;
}
@@ -168,7 +204,9 @@ int cbfs_decompress(int algo, void *src, void *dst, int len)
return -1;
#endif
default:
- ERROR("tried to decompress %d bytes with algorithm #%x, but that algorithm id is unsupported.\n", len, algo);
+ ERROR("tried to decompress %d bytes with algorithm #%x,"
+ "but that algorithm id is unsupported.\n", len,
+ algo);
return -1;
}
}
diff --git a/payloads/libpayload/libcbfs/ram_media.c b/payloads/libpayload/libcbfs/ram_media.c
new file mode 100644
index 0000000..1043e01
--- /dev/null
+++ b/payloads/libpayload/libcbfs/ram_media.c
@@ -0,0 +1,114 @@
+/*
+ * This file is part of the libpayload project.
+ *
+ * Copyright (C) 2013 The Chromium OS Authors. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <cbfs.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+// Implementation of a media source based on given memory buffer.
+struct ram_media {
+ char *start;
+ size_t size;
+};
+
+static int ram_open(struct cbfs_media *media) {
+ return 0;
+}
+
+static void *ram_map(struct cbfs_media *media, size_t offset, size_t count) {
+ struct ram_media *m = (struct ram_media*)media->context;
+ if (offset + count >= m->size) {
+ printf("ERROR: ram_map: request out of range (0x%x+0x%x)\n",
+ offset, count);
+ return NULL;
+ }
+ return (void*)(m->start + offset);
+}
+
+static void *ram_unmap(struct cbfs_media *media, const void *address) {
+ return NULL;
+}
+
+static size_t ram_read(struct cbfs_media *media, void *dest, size_t offset,
+ size_t count) {
+ void *ptr = ram_map(media, offset, count);
+ memcpy(dest, ptr, count);
+ ram_unmap(media, ptr);
+ return count;
+}
+
+static int ram_close(struct cbfs_media *media) {
+ return 0;
+}
+
+int init_cbfs_ram_media(struct cbfs_media *media, void *start, size_t size);
+int init_cbfs_ram_media(struct cbfs_media *media, void *start, size_t size) {
+ // TODO Find a way to release unused media. Maybe adding media->destroy.
+ struct ram_media *m = (struct ram_media*)malloc(sizeof(*m));
+ m->start = start;
+ m->size = size;
+ media->context = (void*)m;
+ media->open = ram_open;
+ media->close = ram_close;
+ media->map = ram_map;
+ media->unmap = ram_unmap;
+ media->read = ram_read;
+ return 0;
+}
+
+// Legacy setup_cbfs_from_*.
+static int is_default_cbfs_media_initialized;
+static struct cbfs_media default_cbfs_media;
+
+int setup_cbfs_from_ram(void *start, uint32_t size);
+int setup_cbfs_from_ram(void *start, uint32_t size) {
+ int result = init_cbfs_ram_media(&default_cbfs_media, start, size);
+ if (result == 0)
+ is_default_cbfs_media_initialized = 1;
+ return result;
+}
+
+extern int libpayload_init_default_cbfs_media(struct cbfs_media *media);
+int setup_cbfs_from_flash(void);
+int setup_cbfs_from_flash(void) {
+ int result = libpayload_init_default_cbfs_media(&default_cbfs_media);
+ if (result == 0)
+ is_default_cbfs_media_initialized = 1;
+ return result;
+}
+
+int init_default_cbfs_media(struct cbfs_media *media) {
+ int result = 0;
+ if (is_default_cbfs_media_initialized != 1) {
+ result = setup_cbfs_from_flash();
+ }
+ if (result == 0)
+ memcpy(media, &default_cbfs_media, sizeof(*media));
+ return result;
+}
Zheng Bao (zheng.bao(a)amd.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2247
-gerrit
commit f01fa0d49438e208d254979819c980290ce8d1e0
Author: zbao <fishbaozi(a)gmail.com>
Date: Thu Jan 31 14:35:59 2013 +0800
crossgcc: Save the script itself when cross build is over.
In case that the new toolchains don't work well, we can trace back
and reproduce the old tools by checking the xgcc folder. It is useful
when my team member need to get my old toolchains on his different
host machine.
Change-Id: I54e4bc6afcfbbf622165af6eae27bbb6efc2e8cc
Signed-off-by: Zheng Bao <zheng.bao(a)amd.com>
Signed-off-by: zbao <fishbaozi(a)gmail.com>
---
util/crossgcc/buildgcc | 2 ++
1 file changed, 2 insertions(+)
diff --git a/util/crossgcc/buildgcc b/util/crossgcc/buildgcc
index c69e7cd..834f060 100755
--- a/util/crossgcc/buildgcc
+++ b/util/crossgcc/buildgcc
@@ -595,6 +595,8 @@ test -r $IASL_DIR/generate/unix/.failed && printf "${RED}failed${NC}\n" || \
test -r $IASL_DIR/generate/unix/.failed && exit 1
fi
+cp `pwd`/$0 $DESTDIR$TARGETDIR/
+
if [ $SAVETEMPS -eq 0 ]; then
printf "Cleaning up... "
rm -rf ${GMP_DIR} build-gmp
Hung-Te Lin (hungte(a)chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2246
-gerrit
commit 99484ee7b406b00fb266e88dc17b2852e4ab0c7e
Author: Hung-Te Lin <hungte(a)chromium.org>
Date: Thu Jan 31 12:14:46 2013 +0800
lib: Prevent unaligned memory access in LZMA decode library.
LZMA decode library used to retrieve output size by:
outSize = *(UInt32 *)(src + LZMA_PROPERTIES_SIZE);
'src' is aligned but LZMA_PROPERTIES_SIZE may refer to an unaligned address like
src+5, and using that as integer pointer may fail on platforms like ARM.
To fix this, use memcpy to copy into aligned variable outSize.
Change-Id: If678e735cb270c3e5e29f36f1fad318096bf7d59
Signed-off-by: Hung-Te Lin <hungte(a)chromium.org>
---
src/lib/lzma.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/lib/lzma.c b/src/lib/lzma.c
index f0b88c1..a2d91d1 100644
--- a/src/lib/lzma.c
+++ b/src/lib/lzma.c
@@ -31,7 +31,8 @@ unsigned long ulzma(unsigned char * src, unsigned char * dst)
unsigned char scratchpad[15980];
memcpy(properties, src, LZMA_PROPERTIES_SIZE);
- outSize = *(UInt32 *)(src + LZMA_PROPERTIES_SIZE);
+ /* Do memcpy to prevent unaligned memory access. */
+ memcpy(&outSize, src + LZMA_PROPERTIES_SIZE, sizeof(outSize));
if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) {
printk(BIOS_WARNING, "lzma: Incorrect stream properties.\n");
return 0;
yeah, these are terrible names. Those pointers are going away soon anyway.
ron
On Wed, Jan 30, 2013 at 5:11 PM, Bernhard Urban <lewurm(a)gmail.com> wrote:
> I can't log into gerrit at the moment, so I reply here.
>
> On Thu, Jan 31, 2013 at 1:08 AM, Ronald G. Minnich <gerrit(a)coreboot.org> wrote:
>> + /* wow, did it work? */
>> + int i;
>> + u32 *c = (void *)0x40000000;
>
> what is at 0x40000000? what is "c"?
> Please use a define or a more descriptive name for the pointer.
>
>
> Thanks,
> Bernhard
>
> --
> coreboot mailing list: coreboot(a)coreboot.org
> http://www.coreboot.org/mailman/listinfo/coreboot
Ronald G. Minnich (rminnich(a)gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2245
-gerrit
commit 811c662cef85e57d950d092b039965cb3ce8a8a9
Author: Ronald G. Minnich <rminnich(a)gmail.com>
Date: Wed Jan 30 15:55:36 2013 -0800
Google/snow: romstage that turns on memory and loads a ram stage with cbfs
This is a first cut at a romstage. It sets up memory, although that
needs some work; and finds and loads a ram stage, though that fails
in the decompress step.
But it's quite a bit more than we had. Note that to use this you MUST
disable CONFIG_COMPRESS_RAMSTAGE. Still an issue there. Also, it does no
good to call the ramstage; nothing ever comes out :-(
Romstage calls bootblock_exit to ensure we call ramstage in ARM mode.
Change-Id: I02a0eb48828500bf83c3c57d4bacb396e58bf9a5
Signed-off-by: Ronald G. Minnich <rminnich(a)gmail.com>
---
src/arch/armv7/Makefile.inc | 1 +
src/mainboard/google/snow/romstage.c | 97 ++++++++++++++++++++++++++++++------
2 files changed, 84 insertions(+), 14 deletions(-)
diff --git a/src/arch/armv7/Makefile.inc b/src/arch/armv7/Makefile.inc
index ba734a6..5f5305d 100644
--- a/src/arch/armv7/Makefile.inc
+++ b/src/arch/armv7/Makefile.inc
@@ -330,3 +330,4 @@ $(objgenerated)/crt0.s: $(objgenerated)/crt0.romstage.S $(obj)/config.h $(obj)/b
@printf " CC $(subst $(obj)/,,$(@))\n"
$(CC) -MMD -x assembler-with-cpp -E -I$(src)/include -I$(src)/arch/armv7/include -I$(obj) -include $(obj)/config.h -include $(obj)/build.h -I. -I$(src) $< -o $@
+romstage-y += bootblock_exit.c
diff --git a/src/mainboard/google/snow/romstage.c b/src/mainboard/google/snow/romstage.c
index 3f3f3ec..f1592ae 100644
--- a/src/mainboard/google/snow/romstage.c
+++ b/src/mainboard/google/snow/romstage.c
@@ -20,26 +20,20 @@
#include <types.h>
#include <system.h>
#include <cache.h>
+#include <cbfs.h>
-#if 0
-#include <arch/io.h>
-
-/* FIXME: make i2c.h use standard types */
-#define uchar unsigned char
-#define uint unsigned int
-#include <device/i2c.h>
-
-#include <cpu/samsung/s5p-common/s3c24x0_i2c.h>
-#include "cpu/samsung/exynos5250/dmc.h"
-#include <cpu/samsung/exynos5250/power.h>
+#include <cpu/samsung/exynos5250/setup.h>
+#include <cpu/samsung/exynos5250/dmc.h>
#include <cpu/samsung/exynos5250/clock_init.h>
-#include <cpu/samsung/exynos5-common/uart.h>
-#endif
+
#include <console/console.h>
+#include <arch/bootblock_exit.h>
void main(void);
+
void main(void)
{
+ struct cbfs_media cbfs;
// volatile unsigned long *pshold = (unsigned long *)0x1004330c;
// i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
// power_init();
@@ -47,7 +41,82 @@ void main(void)
// exynos_pinmux_config(PERIPH_ID_UART3, PINMUX_FLAG_NONE);
console_init();
printk(BIOS_INFO, "hello from romstage\n");
+ /* u-boot tends to parameterize lots of things, and you end up
+ * calling things that decode things. In the case of this
+ * part, on this board, we only care about DDR3. Since we
+ * know what kind of memory we have, and that kind of stuff is
+ * just another path for obscure errors, just call the ddr3
+ * init. Rule: Keep it simple.
+ */
+ extern struct mem_timings mem_timings[];
+ struct mem_timings *mem = mem_timings;
+ int ret;
+
+ // mem = clock_get_mem_timings();
+ printk(BIOS_SPEW, "clock_get_mem_timings returns %08lx\n",
+ (unsigned long)mem);
+ printk(BIOS_SPEW, "man: 0x%x type: 0x%x, div: 0x%x, mhz: 0x%x\n",
+ mem->mem_manuf,
+ mem->mem_type,
+ mem->mpll_mdiv,
+ mem->frequency_mhz);
+ /* the 0x1f is the interleaving size. It's kind of hard to see
+ * where and how this might vary. It might want to be a config
+ * variable, but making it a config variable might actually be
+ * dangerous.
+ */
+ ret = ddr3_mem_ctrl_init(mem, 0x1f);
+ if (ret) {
+ printk(BIOS_ERR, "Memory controller init failed, err: %x\n",
+ ret);
+ while(1);
+ }
+
+ printk(BIOS_INFO, "ddr3_init done\n");
+ /* wow, did it work? */
+ int i;
+ u32 *c = (void *)0x40000000;
// *pshold &= ~0x100; /* shut down */
- mmu_setup(CONFIG_SYS_SDRAM_BASE, CONFIG_DRAM_SIZE_MB * 1024);
+// mmu_setup(CONFIG_SYS_SDRAM_BASE, CONFIG_DRAM_SIZE_MB * 1024);
+// printk(BIOS_INFO, "mmu_setup done\n");
+ for(i = 0; i < 16384; i++)
+ c[i] = i+32768;
+ for(i = 0; i < 16384; i++)
+ if (c[i] != i+32768)
+ printk(BIOS_SPEW, "BADc[%02x]: %02x,", i, c[i]);
+ for(i = 0; i < 1048576; i++)
+ c[i] = 0;
+ ret = init_default_cbfs_media(&cbfs);
+ if (ret){
+ printk(BIOS_ERR, "init_default_cbfs_media returned %d: HALT\n",
+ ret);
+ while (1);
+ }
+// void *start;
+
+ struct cbfs_stage *stage = (struct cbfs_stage *)
+ cbfs_get_file_content(&cbfs, "fallback/coreboot_ram",
+ CBFS_TYPE_STAGE);
+ printk(BIOS_ERR, "Stage: %p\n", stage);
+ printk(BIOS_ERR, "loading stage %s @ 0x%x (0x%x bytes),entry @ 0x%p\n",
+ "ram stage",
+ (uint32_t) stage->load, stage->memlen,
+ (void *)(u32)stage->entry);
+ /* for reference and testing ... we should be able to remove soon */
+#if 0
+// c = (void *)(u32)(stage->load + stage->len);
+ c = (void *)(u32)(stage->load);
+ printk(BIOS_ERR, "memzero 0x%x words starting at %p\n",
+ (stage->memlen /*- stage->len*/)/4, c);
+ for(i = 0; i < (stage->memlen /*- stage->len*/)/4; i++){
+ printk(BIOS_INFO, "%p, ", &c[i]);
+ c[i] = 0;
+ }
+#endif
+ void *entry = cbfs_load_stage(&cbfs, "fallback/coreboot_ram");
+ printk(BIOS_INFO, "entry is %p\n", entry);
+
+ printk(BIOS_ERR, "DONE\n");
+ bootblock_exit((u32)entry);
}
Ronald G. Minnich (rminnich(a)gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2245
-gerrit
commit c3f4e05181484c3ce66ac857c13c13ca2c1ee1bb
Author: Ronald G. Minnich <rminnich(a)gmail.com>
Date: Wed Jan 30 15:55:36 2013 -0800
Google/snow: romstage that turns on memory and loads a ram stage with cbfs
This is a first cut at a romstage. It sets up memory, although that
needs some work; and finds and loads a ram stage, though that fails
in the decompress step.
But it's quite a bit more than we had.
Change-Id: I02a0eb48828500bf83c3c57d4bacb396e58bf9a5
Signed-off-by: Ronald G. Minnich <rminnich(a)gmail.com>
---
src/mainboard/google/snow/romstage.c | 98 ++++++++++++++++++++++++++++++------
1 file changed, 83 insertions(+), 15 deletions(-)
diff --git a/src/mainboard/google/snow/romstage.c b/src/mainboard/google/snow/romstage.c
index 3f3f3ec..0026eb9 100644
--- a/src/mainboard/google/snow/romstage.c
+++ b/src/mainboard/google/snow/romstage.c
@@ -20,26 +20,19 @@
#include <types.h>
#include <system.h>
#include <cache.h>
+#include <cbfs.h>
-#if 0
-#include <arch/io.h>
-
-/* FIXME: make i2c.h use standard types */
-#define uchar unsigned char
-#define uint unsigned int
-#include <device/i2c.h>
-
-#include <cpu/samsung/s5p-common/s3c24x0_i2c.h>
-#include "cpu/samsung/exynos5250/dmc.h"
-#include <cpu/samsung/exynos5250/power.h>
+#include <cpu/samsung/exynos5250/setup.h>
+#include <cpu/samsung/exynos5250/dmc.h>
#include <cpu/samsung/exynos5250/clock_init.h>
-#include <cpu/samsung/exynos5-common/uart.h>
-#endif
+
#include <console/console.h>
void main(void);
+
void main(void)
{
+ struct cbfs_media cbfs;
// volatile unsigned long *pshold = (unsigned long *)0x1004330c;
// i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
// power_init();
@@ -47,7 +40,82 @@ void main(void)
// exynos_pinmux_config(PERIPH_ID_UART3, PINMUX_FLAG_NONE);
console_init();
printk(BIOS_INFO, "hello from romstage\n");
-
+ /* u-boot tends to parameterize lots of things, and you end up
+ * calling things that decode things. In the case of this
+ * part, on this board, we only care about DDR3. Since we
+ * know what kind of memory we have, and that kind of stuff is
+ * just another path for obscure errors, just call the ddr3
+ * init. Rule: Keep it simple.
+ */
+ extern struct mem_timings mem_timings[];
+ struct mem_timings *mem = mem_timings;
+ int ret;
+
+ // mem = clock_get_mem_timings();
+ printk(BIOS_SPEW, "clock_get_mem_timings returns %08lx\n",
+ (unsigned long)mem);
+ printk(BIOS_SPEW, "man: 0x%x type: 0x%x, div: 0x%x, mhz: 0x%x\n",
+ mem->mem_manuf,
+ mem->mem_type,
+ mem->mpll_mdiv,
+ mem->frequency_mhz);
+ /* the 0x1f is the interleaving size. It's kind of hard to see
+ * where and how this might vary. It might want to be a config
+ * variable, but making it a config variable might actually be
+ * dangerous.
+ */
+ ret = ddr3_mem_ctrl_init(mem, 0x1f);
+ if (ret) {
+ printk(BIOS_ERR, "Memory controller init failed, err: %x\n",
+ ret);
+ while(1);
+ }
+
+ printk(BIOS_INFO, "ddr3_init done\n");
+ /* wow, did it work? */
+ int i;
+ u32 *c = (void *)0x40000000;
+
// *pshold &= ~0x100; /* shut down */
- mmu_setup(CONFIG_SYS_SDRAM_BASE, CONFIG_DRAM_SIZE_MB * 1024);
+// mmu_setup(CONFIG_SYS_SDRAM_BASE, CONFIG_DRAM_SIZE_MB * 1024);
+// printk(BIOS_INFO, "mmu_setup done\n");
+ for(i = 0; i < 16384; i++)
+ c[i] = i+32768;
+ for(i = 0; i < 16384; i++)
+ if (c[i] != i+32768)
+ printk(BIOS_SPEW, "BADc[%02x]: %02x,", i, c[i]);
+ for(i = 0; i < 1048576; i++)
+ c[i] = 0;
+ ret = init_default_cbfs_media(&cbfs);
+ if (ret){
+ printk(BIOS_ERR, "init_default_cbfs_media returned %d: HALT\n",
+ ret);
+ while (1);
+ }
+// void *start;
+
+ struct cbfs_stage *stage = (struct cbfs_stage *)
+ cbfs_get_file_content(&cbfs, "fallback/coreboot_ram",
+ CBFS_TYPE_STAGE);
+ printk(BIOS_ERR, "Stage: %p\n", stage);
+ printk(BIOS_ERR, "loading stage %s @ 0x%x (0x%x bytes),entry @ 0x%p\n",
+ "ram stage",
+ (uint32_t) stage->load, stage->memlen,
+ (void *)(u32)stage->entry);
+ /* for reference and testing ... we should be able to remove soon */
+#if 0
+// c = (void *)(u32)(stage->load + stage->len);
+ c = (void *)(u32)(stage->load);
+ printk(BIOS_ERR, "memzero 0x%x words starting at %p\n",
+ (stage->memlen /*- stage->len*/)/4, c);
+ for(i = 0; i < (stage->memlen /*- stage->len*/)/4; i++){
+ printk(BIOS_INFO, "%p, ", &c[i]);
+ c[i] = 0;
+ }
+#endif
+ void *entry = cbfs_load_stage(&cbfs, "fallback/coreboot_ram");
+ printk(BIOS_INFO, "entry is %p\n", entry);
+
+ printk(BIOS_ERR, "DONE\nHALT\n");
+ while (1);
}
Ronald G. Minnich (rminnich(a)gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2245
-gerrit
commit e3fd92a494e60c0cbce2de0d618763e9b48cd7a7
Author: Ronald G. Minnich <rminnich(a)gmail.com>
Date: Wed Jan 30 15:55:36 2013 -0800
Google/snow: romstage that turns on memory and loads a ram stage with cbfs
This is a first cut at a romstage. It sets up memory, although that
needs some work; and finds and loads a ram stage, though that fails
in the decompress step.
But it's quite a bit more than we had. Note that to use this you MUST
disable CONFIG_COMPRESS_RAMSTAGE. Still an issue there. Also, it does no
good to call the ramstage; nothing ever comes out :-(
Change-Id: I02a0eb48828500bf83c3c57d4bacb396e58bf9a5
Signed-off-by: Ronald G. Minnich <rminnich(a)gmail.com>
---
src/mainboard/google/snow/romstage.c | 97 ++++++++++++++++++++++++++++++------
1 file changed, 83 insertions(+), 14 deletions(-)
diff --git a/src/mainboard/google/snow/romstage.c b/src/mainboard/google/snow/romstage.c
index 3f3f3ec..f1592ae 100644
--- a/src/mainboard/google/snow/romstage.c
+++ b/src/mainboard/google/snow/romstage.c
@@ -20,26 +20,20 @@
#include <types.h>
#include <system.h>
#include <cache.h>
+#include <cbfs.h>
-#if 0
-#include <arch/io.h>
-
-/* FIXME: make i2c.h use standard types */
-#define uchar unsigned char
-#define uint unsigned int
-#include <device/i2c.h>
-
-#include <cpu/samsung/s5p-common/s3c24x0_i2c.h>
-#include "cpu/samsung/exynos5250/dmc.h"
-#include <cpu/samsung/exynos5250/power.h>
+#include <cpu/samsung/exynos5250/setup.h>
+#include <cpu/samsung/exynos5250/dmc.h>
#include <cpu/samsung/exynos5250/clock_init.h>
-#include <cpu/samsung/exynos5-common/uart.h>
-#endif
+
#include <console/console.h>
+#include <arch/bootblock_exit.h>
void main(void);
+
void main(void)
{
+ struct cbfs_media cbfs;
// volatile unsigned long *pshold = (unsigned long *)0x1004330c;
// i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
// power_init();
@@ -47,7 +41,82 @@ void main(void)
// exynos_pinmux_config(PERIPH_ID_UART3, PINMUX_FLAG_NONE);
console_init();
printk(BIOS_INFO, "hello from romstage\n");
+ /* u-boot tends to parameterize lots of things, and you end up
+ * calling things that decode things. In the case of this
+ * part, on this board, we only care about DDR3. Since we
+ * know what kind of memory we have, and that kind of stuff is
+ * just another path for obscure errors, just call the ddr3
+ * init. Rule: Keep it simple.
+ */
+ extern struct mem_timings mem_timings[];
+ struct mem_timings *mem = mem_timings;
+ int ret;
+
+ // mem = clock_get_mem_timings();
+ printk(BIOS_SPEW, "clock_get_mem_timings returns %08lx\n",
+ (unsigned long)mem);
+ printk(BIOS_SPEW, "man: 0x%x type: 0x%x, div: 0x%x, mhz: 0x%x\n",
+ mem->mem_manuf,
+ mem->mem_type,
+ mem->mpll_mdiv,
+ mem->frequency_mhz);
+ /* the 0x1f is the interleaving size. It's kind of hard to see
+ * where and how this might vary. It might want to be a config
+ * variable, but making it a config variable might actually be
+ * dangerous.
+ */
+ ret = ddr3_mem_ctrl_init(mem, 0x1f);
+ if (ret) {
+ printk(BIOS_ERR, "Memory controller init failed, err: %x\n",
+ ret);
+ while(1);
+ }
+
+ printk(BIOS_INFO, "ddr3_init done\n");
+ /* wow, did it work? */
+ int i;
+ u32 *c = (void *)0x40000000;
// *pshold &= ~0x100; /* shut down */
- mmu_setup(CONFIG_SYS_SDRAM_BASE, CONFIG_DRAM_SIZE_MB * 1024);
+// mmu_setup(CONFIG_SYS_SDRAM_BASE, CONFIG_DRAM_SIZE_MB * 1024);
+// printk(BIOS_INFO, "mmu_setup done\n");
+ for(i = 0; i < 16384; i++)
+ c[i] = i+32768;
+ for(i = 0; i < 16384; i++)
+ if (c[i] != i+32768)
+ printk(BIOS_SPEW, "BADc[%02x]: %02x,", i, c[i]);
+ for(i = 0; i < 1048576; i++)
+ c[i] = 0;
+ ret = init_default_cbfs_media(&cbfs);
+ if (ret){
+ printk(BIOS_ERR, "init_default_cbfs_media returned %d: HALT\n",
+ ret);
+ while (1);
+ }
+// void *start;
+
+ struct cbfs_stage *stage = (struct cbfs_stage *)
+ cbfs_get_file_content(&cbfs, "fallback/coreboot_ram",
+ CBFS_TYPE_STAGE);
+ printk(BIOS_ERR, "Stage: %p\n", stage);
+ printk(BIOS_ERR, "loading stage %s @ 0x%x (0x%x bytes),entry @ 0x%p\n",
+ "ram stage",
+ (uint32_t) stage->load, stage->memlen,
+ (void *)(u32)stage->entry);
+ /* for reference and testing ... we should be able to remove soon */
+#if 0
+// c = (void *)(u32)(stage->load + stage->len);
+ c = (void *)(u32)(stage->load);
+ printk(BIOS_ERR, "memzero 0x%x words starting at %p\n",
+ (stage->memlen /*- stage->len*/)/4, c);
+ for(i = 0; i < (stage->memlen /*- stage->len*/)/4; i++){
+ printk(BIOS_INFO, "%p, ", &c[i]);
+ c[i] = 0;
+ }
+#endif
+ void *entry = cbfs_load_stage(&cbfs, "fallback/coreboot_ram");
+ printk(BIOS_INFO, "entry is %p\n", entry);
+
+ printk(BIOS_ERR, "DONE\n");
+ bootblock_exit((u32)entry);
}
Ronald G. Minnich (rminnich(a)gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2235
-gerrit
commit 1d4d6040ec2814aec9d8550f96e0cba189f08b50
Author: Ronald G. Minnich <rminnich(a)gmail.com>
Date: Wed Jan 30 14:29:34 2013 -0800
Improve how our printk calls do_div by using constants.
The do_div code has a nice optimization in it when it is called with
constants. The current highly generalized use of it defeats those
optimizations and causes trouble on ARM, resulting in a complex and
buggy code path.
Since we only need to print in bases 8, 10, and 16, do a minor
restructuring of the code so that we call do_div with constants.
If you need base 2, print in base 16 and do it in your head. :-)
This fixes an ongoing problem with ARM, will not harm X86, and will
help PPC should we ever want to support it again.
Plus, I don't have to ever try to understand the div64 assembly and where
it's going wrong :-)
Change-Id: I6a480011916eb0834e05c5bb10909d83330fe797
Signed-off-by: Ronald G. Minnich <rminnich(a)gmail.com>
---
src/console/vtxprintf.c | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/src/console/vtxprintf.c b/src/console/vtxprintf.c
index 28c5a60..9de2584 100644
--- a/src/console/vtxprintf.c
+++ b/src/console/vtxprintf.c
@@ -69,8 +69,22 @@ static int number(void (*tx_byte)(unsigned char byte),
i = 0;
if (num == 0)
tmp[i++]='0';
- else while (num != 0)
- tmp[i++] = digits[do_div(num,base)];
+ else while (num != 0){
+ /* there are some nice optimizations in the
+ * Macros-From-Hell that form the div64 code
+ * *IF* you call it with a constant.
+ * We're firmware, we only do bases
+ * 8, 10, and 16. Let's be smart.
+ * This greatly helps ARM, reduces the
+ * code footprint at compile time, and does not hurt x86.
+ */
+ if (base == 10)
+ tmp[i++] = digits[do_div(num,10)];
+ else if (base == 8)
+ tmp[i++] = digits[do_div(num,8)];
+ else /* sorry, you're out of choices */
+ tmp[i++] = digits[do_div(num,16)];
+ }
if (i > precision)
precision = i;
size -= precision;
the following patch was just integrated into master:
commit bc3abbbaf05123f87cee143845868bf6b95fdd3e
Author: Ronald G. Minnich <rminnich(a)gmail.com>
Date: Wed Jan 30 15:05:19 2013 -0600
armv7: don't hang on divide by zero
People make mistakes. Hanging the box is not a good reason to kill the firmware,
esp. since this is probably happening in a printk.
The only issue with the recursive call to printk is that we may
deadlock if we have locked something. But we can at least try.
Hanging is certainly not what we want ...
Change-Id: Ib3bc87bc395ae89e115cf6d042f4167856422ca1
Signed-off-by: Ronald G. Minnich <rminnich(a)gmail.com>
Reviewed-on: http://review.coreboot.org/2233
Tested-by: build bot (Jenkins)
Reviewed-by: Peter Stuge <peter(a)stuge.se>
Build-Tested: build bot (Jenkins) at Wed Jan 30 22:34:57 2013, giving +1
Reviewed-By: Peter Stuge <peter(a)stuge.se> at Wed Jan 30 22:36:25 2013, giving +2
See http://review.coreboot.org/2233 for details.
-gerrit