summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile6
-rw-r--r--README1
-rw-r--r--common/Makefile1
-rw-r--r--common/cmd_cbfs.c118
-rw-r--r--fs/Makefile1
-rw-r--r--fs/cbfs/Makefile44
-rw-r--r--fs/cbfs/cbfs.c296
-rw-r--r--include/cbfs.h61
8 files changed, 525 insertions, 3 deletions
diff --git a/Makefile b/Makefile
index 74c48d1d16..6cb7ce85a6 100644
--- a/Makefile
+++ b/Makefile
@@ -234,9 +234,9 @@ ifeq ($(CONFIG_OF_EMBED),y)
LIBS += dts/libdts.o
endif
LIBS += arch/$(ARCH)/lib/lib$(ARCH).o
-LIBS += fs/cramfs/libcramfs.o fs/fat/libfat.o fs/fdos/libfdos.o fs/jffs2/libjffs2.o \
- fs/reiserfs/libreiserfs.o fs/ext2/libext2fs.o fs/yaffs2/libyaffs2.o \
- fs/ubifs/libubifs.o
+LIBS += fs/cramfs/libcramfs.o fs/fat/libfat.o fs/fdos/libfdos.o \
+ fs/jffs2/libjffs2.o fs/reiserfs/libreiserfs.o fs/ext2/libext2fs.o \
+ fs/yaffs2/libyaffs2.o fs/ubifs/libubifs.o fs/cbfs/libcbfs.o
LIBS += net/libnet.o
LIBS += disk/libdisk.o
LIBS += drivers/bios_emulator/libatibiosemu.o
diff --git a/README b/README
index 3468db04cb..9cef0b2604 100644
--- a/README
+++ b/README
@@ -653,6 +653,7 @@ The following options need to be configured:
CONFIG_CMD_BSP * Board specific commands
CONFIG_CMD_BOOTD bootd
CONFIG_CMD_CACHE * icache, dcache
+ CONFIG_CMD_CBFS * Support for coreboot's CBFS
CONFIG_CMD_CONSOLE coninfo
CONFIG_CMD_CRC32 * crc32
CONFIG_CMD_DATE * support for RTC, date/time...
diff --git a/common/Makefile b/common/Makefile
index 02bea72adf..5beec0067e 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -95,6 +95,7 @@ COBJS-$(CONFIG_ENV_IS_IN_EEPROM) += cmd_eeprom.o
COBJS-$(CONFIG_CMD_EEPROM) += cmd_eeprom.o
COBJS-$(CONFIG_CMD_ELF) += cmd_elf.o
COBJS-$(CONFIG_SYS_HUSH_PARSER) += cmd_exit.o
+COBJS-$(CONFIG_CMD_CBFS) += cmd_cbfs.o
COBJS-$(CONFIG_CMD_EXT2) += cmd_ext2.o
COBJS-$(CONFIG_CMD_FAT) += cmd_fat.o
COBJS-$(CONFIG_CMD_FDC)$(CONFIG_CMD_FDOS) += cmd_fdc.o
diff --git a/common/cmd_cbfs.c b/common/cmd_cbfs.c
new file mode 100644
index 0000000000..8fce99e155
--- /dev/null
+++ b/common/cmd_cbfs.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ *
+ * 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
+ */
+
+/*
+ * CBFS commands
+ */
+#include <common.h>
+#include <command.h>
+#include <cbfs.h>
+
+int do_cbfs_init(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+ uintptr_t end_of_rom = 0xffffffff;
+ char *ep;
+
+ if (argc > 2) {
+ printf("usage: cbfsls [end of rom]>\n");
+ return 0;
+ }
+ if (argc == 2) {
+ end_of_rom = (int)simple_strtoul(argv[1], &ep, 16);
+ if (*ep) {
+ puts("\n** Invalid end of ROM **\n");
+ return 1;
+ }
+ }
+ return file_cbfs_init(end_of_rom);
+}
+
+U_BOOT_CMD(
+ cbfsinit, 2, 0, do_cbfs_init,
+ "initialize the cbfs driver",
+ "[end of rom]\n"
+ " - Initialize the cbfs driver. The optional 'end of rom'\n"
+ " parameter specifies where the end of the ROM is that the\n"
+ " CBFS is in. It defaults to 0xFFFFFFFF\n"
+);
+
+int do_cbfs_fsload (cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+ long size;
+ unsigned long offset;
+ unsigned long count;
+ char buf[12];
+
+ if (argc < 3) {
+ printf("usage: cbfsload <addr> <filename> [bytes]\n");
+ return 1;
+ }
+
+ /* parse offset and count */
+ offset = simple_strtoul(argv[1], NULL, 16);
+ if (argc == 4)
+ count = simple_strtoul(argv[3], NULL, 16);
+ else
+ count = 0;
+
+ size = file_cbfs_read(argv[2], (void *)offset, count);
+ if (size < 0) {
+ printf("\n** Unable to read \"%s\" from cbfs **\n", argv[2]);
+ return 1;
+ }
+
+ printf("\n%ld bytes read\n", size);
+
+ sprintf(buf, "%lX", size);
+ setenv("filesize", buf);
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ cbfsload, 4, 0, do_cbfs_fsload,
+ "load binary file from a cbfs filesystem",
+ "<addr> <filename> [bytes]\n"
+ " - load binary file 'filename' from the cbfs to address 'addr'\n"
+);
+
+int do_cbfs_ls (cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+ return file_cbfs_ls();
+}
+
+U_BOOT_CMD(
+ cbfsls, 1, 1, do_cbfs_ls,
+ "list files",
+ " - list the files in the cbfs\n"
+);
+
+int do_cbfs_fsinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+ return file_cbfs_fsinfo();
+}
+
+U_BOOT_CMD(
+ cbfsinfo, 1, 1, do_cbfs_fsinfo,
+ "print information about filesystem",
+ " - print information about the cbfs filesystem\n"
+);
diff --git a/fs/Makefile b/fs/Makefile
index 22aad126bc..ca2146407f 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -23,6 +23,7 @@
#
subdirs-$(CONFIG_CMD_CRAMFS) := cramfs
+subdirs-$(CONFIG_CMD_CBFS) += cbfs
subdirs-$(CONFIG_CMD_EXT2) += ext2
subdirs-$(CONFIG_CMD_FAT) += fat
subdirs-$(CONFIG_CMD_FDOS) += fdos
diff --git a/fs/cbfs/Makefile b/fs/cbfs/Makefile
new file mode 100644
index 0000000000..864fdf9f87
--- /dev/null
+++ b/fs/cbfs/Makefile
@@ -0,0 +1,44 @@
+#
+# 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
+#
+
+include $(TOPDIR)/config.mk
+
+LIB = $(obj)libcbfs.o
+
+AOBJS =
+COBJS-$(CONFIG_CMD_CBFS) := cbfs.o
+
+SRCS := $(AOBJS:.o=.S) $(COBJS-y:.o=.c)
+OBJS := $(addprefix $(obj),$(AOBJS) $(COBJS-y))
+
+all: $(LIB) $(AOBJS)
+
+$(LIB): $(obj).depend $(OBJS)
+ $(call cmd_link_o_target, $(OBJS))
+
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/fs/cbfs/cbfs.c b/fs/cbfs/cbfs.c
new file mode 100644
index 0000000000..d1b03c7e1a
--- /dev/null
+++ b/fs/cbfs/cbfs.c
@@ -0,0 +1,296 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <config.h>
+#include <cbfs.h>
+#include <malloc.h>
+#include <asm/byteorder.h>
+
+#define CBFS_TYPE_STAGE 0x10
+#define CBFS_TYPE_PAYLOAD 0x20
+#define CBFS_TYPE_OPTIONROM 0x30
+#define CBFS_TYPE_BOOTSPLASH 0x40
+#define CBFS_TYPE_RAW 0x50
+#define CBFS_TYPE_VSA 0x51
+#define CBFS_TYPE_MBI 0x52
+#define CBFS_TYPE_MICROCODE 0x53
+#define CBFS_COMPONENT_CMOS_DEFAULT 0xaa
+#define CBFS_COMPONENT_CMOS_LAYOUT 0x01aa
+
+typedef struct CbfsHeader {
+ u32 magic;
+ u32 version;
+ u32 romSize;
+ u32 bootBlockSize;
+ u32 align;
+ u32 offset;
+ u32 pad[2];
+} __attribute__((packed)) CbfsHeader;
+
+typedef struct CbfsFileHeader {
+ u8 magic[8];
+ u32 len;
+ u32 type;
+ u32 checksum;
+ u32 offset;
+} __attribute__((packed)) CbfsFileHeader;
+
+typedef struct CbfsCacheNode {
+ CbfsFileHeader header;
+ struct CbfsCacheNode *next;
+ void *data;
+ char *name;
+} __attribute__((packed)) CbfsCacheNode;
+
+
+static const u32 goodMagic = 0x4f524243;
+static const u8 goodFileMagic[] = "LARCHIVE";
+
+
+static int initialized;
+static struct CbfsHeader header;
+static CbfsCacheNode *fileCache;
+
+static void swap_header(CbfsHeader *dest, CbfsHeader *src)
+{
+ dest->magic = be32_to_cpu(src->magic);
+ dest->version = be32_to_cpu(src->version);
+ dest->romSize = be32_to_cpu(src->romSize);
+ dest->bootBlockSize = be32_to_cpu(src->bootBlockSize);
+ dest->align = be32_to_cpu(src->align);
+ dest->offset = be32_to_cpu(src->offset);
+}
+
+static void swap_file_header(CbfsFileHeader *dest, CbfsFileHeader *src)
+{
+ memcpy(&dest->magic, &src->magic, sizeof(dest->magic));
+ dest->len = be32_to_cpu(src->len);
+ dest->type = be32_to_cpu(src->type);
+ dest->checksum = be32_to_cpu(src->checksum);
+ dest->offset = be32_to_cpu(src->offset);
+}
+
+static int init_check(void)
+{
+ if (!initialized) {
+ printf("CBFS not initialized.\n");
+ return 1;
+ }
+ return 0;
+}
+
+static int file_cbfs_fill_cache(u8 *start, u32 size, u32 align)
+{
+ CbfsCacheNode *cacheNode;
+ CbfsCacheNode *newNode;
+ CbfsCacheNode **cacheTail = &fileCache;
+
+ /* Clear out old information. */
+ cacheNode = fileCache;
+ while (cacheNode) {
+ CbfsCacheNode *oldNode = cacheNode;
+ cacheNode = cacheNode->next;
+ free(oldNode->name);
+ free(oldNode);
+ }
+ fileCache = NULL;
+
+ while (size >= align) {
+ CbfsFileHeader *fileHeader = (CbfsFileHeader *)start;
+ u32 nameLen;
+ u32 step;
+
+ /* Check if there's a file here. */
+ if (memcmp(goodFileMagic, &(fileHeader->magic),
+ sizeof(fileHeader->magic))) {
+ size -= align;
+ start += align;
+ continue;
+ }
+
+ newNode = (CbfsCacheNode *)malloc(sizeof(CbfsCacheNode));
+ swap_file_header(&newNode->header, fileHeader);
+ if (newNode->header.offset < sizeof(CbfsFileHeader) ||
+ newNode->header.offset > newNode->header.len) {
+ printf("Bad file in CBFS.\n");
+ return 1;
+ }
+ newNode->next = NULL;
+ newNode->data = start + newNode->header.offset;
+ nameLen = newNode->header.offset - sizeof(CbfsFileHeader);
+ /* Add a byte for a NULL terminator. */
+ newNode->name = (char *)malloc(nameLen + 1);
+ strncpy(newNode->name,
+ ((char *)fileHeader) + sizeof(CbfsFileHeader),
+ nameLen);
+ newNode->name[nameLen] = 0;
+ *cacheTail = newNode;
+ cacheTail = &newNode->next;
+
+ step = newNode->header.len;
+ if (step % align)
+ step = step + align - step % align;
+
+ size -= step;
+ start += step;
+ }
+ return 0;
+}
+
+int file_cbfs_init(uintptr_t endOfRom)
+{
+ CbfsHeader *headerInRom;
+ u8 *startOfRom;
+ initialized = 0;
+
+ headerInRom = (CbfsHeader *)(uintptr_t)*(u32 *)(endOfRom - 3);
+ swap_header(&header, headerInRom);
+
+ if (header.magic != goodMagic || header.offset >
+ header.romSize - header.bootBlockSize) {
+ printf("Bad CBFS header.\n");
+ return 1;
+ }
+
+ startOfRom = (u8 *)(endOfRom + 1 - header.romSize);
+
+ if (file_cbfs_fill_cache(startOfRom + header.offset,
+ header.romSize, header.align)) {
+ return 1;
+ }
+
+ initialized = 1;
+ return 0;
+}
+
+long file_cbfs_read(const char *filename, void *buffer, unsigned long maxsize)
+{
+ struct CbfsCacheNode *cacheNode = fileCache;
+ u32 size;
+
+ if (init_check())
+ return 1;
+
+ while (cacheNode) {
+ if (!strcmp(filename, cacheNode->name))
+ break;
+ cacheNode = cacheNode->next;
+ }
+ if (!cacheNode) {
+ printf("File %s not found.\n", filename);
+ return -1;
+ }
+
+ printf("reading %s\n", filename);
+
+ size = cacheNode->header.len;
+ if (maxsize && size > maxsize)
+ size = maxsize;
+
+ memcpy(buffer, cacheNode->data, size);
+
+ return size;
+}
+
+int file_cbfs_ls(void)
+{
+ struct CbfsCacheNode *cacheNode = fileCache;
+ int files = 0;
+
+ if (init_check())
+ return 1;
+
+ printf(" size type name\n");
+ printf("------------------------------------------\n");
+ while (cacheNode) {
+ char *typeName = NULL;
+ printf(" %8d", cacheNode->header.len);
+
+ switch (cacheNode->header.type) {
+ case CBFS_TYPE_STAGE:
+ typeName = "stage";
+ break;
+ case CBFS_TYPE_PAYLOAD:
+ typeName = "payload";
+ break;
+ case CBFS_TYPE_OPTIONROM:
+ typeName = "option rom";
+ break;
+ case CBFS_TYPE_BOOTSPLASH:
+ typeName = "boot splash";
+ break;
+ case CBFS_TYPE_RAW:
+ typeName = "raw";
+ break;
+ case CBFS_TYPE_VSA:
+ typeName = "vsa";
+ break;
+ case CBFS_TYPE_MBI:
+ typeName = "mbi";
+ break;
+ case CBFS_TYPE_MICROCODE:
+ typeName = "microcode";
+ break;
+ case CBFS_COMPONENT_CMOS_DEFAULT:
+ typeName = "cmos default";
+ break;
+ case CBFS_COMPONENT_CMOS_LAYOUT:
+ typeName = "cmos layout";
+ break;
+ case -1UL:
+ typeName = "null";
+ break;
+ }
+ if (typeName)
+ printf(" %16s", typeName);
+ else
+ printf(" %16d", cacheNode->header.type);
+
+ if (cacheNode->name[0])
+ printf(" %s\n", cacheNode->name);
+ else
+ printf(" %s\n", "(empty)");
+ cacheNode = cacheNode->next;
+ files++;
+ }
+
+ printf("\n%d file(s)\n\n", files);
+ return 0;
+}
+
+int file_cbfs_fsinfo(void)
+{
+ if (init_check())
+ return 1;
+
+ printf("\n");
+ printf("CBFS version: %#x\n", header.version);
+ printf("ROM size: %#x\n", header.romSize);
+ printf("Boot block size: %#x\n", header.bootBlockSize);
+ printf("CBFS size: %#x\n",
+ header.romSize - header.bootBlockSize - header.offset);
+ printf("Alignment: %d\n", header.align);
+ printf("Offset: %#x\n", header.offset);
+ printf("\n");
+ return 0;
+}
diff --git a/include/cbfs.h b/include/cbfs.h
new file mode 100644
index 0000000000..7a4d0c6550
--- /dev/null
+++ b/include/cbfs.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ *
+ * 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 __CBFS_H
+#define __CBFS_H
+
+/*
+ * Initialize the CBFS driver and load metadata into RAM.
+ *
+ * @param end_of_rom Points to the end of the ROM the CBFS should be read
+ * from.
+ *
+ * @return Zero on success, non-zero on failure
+ */
+int file_cbfs_init(uintptr_t end_of_rom);
+
+/*
+ * Read a file from CBFS into RAM
+ *
+ * @param filename The name of the file to read.
+ * @param buffer Where to read it into memory.
+ *
+ * @return If positive or zero, the number of characters read. If negative, an
+ * error occurred.
+ */
+long file_cbfs_read(const char *filename, void *buffer, unsigned long maxsize);
+
+/*
+ * List the files names, types, and sizes in the current CBFS.
+ *
+ * @return Zero on success, non-zero on failure.
+ */
+int file_cbfs_ls(void);
+
+/*
+ * Print information from the CBFS header.
+ *
+ * @return Zero on success, non-zero on failure.
+ */
+int file_cbfs_fsinfo(void);
+
+#endif /* __CBFS_H */