summaryrefslogtreecommitdiff
path: root/payloads/libpayload/libcbfs
diff options
context:
space:
mode:
Diffstat (limited to 'payloads/libpayload/libcbfs')
-rw-r--r--payloads/libpayload/libcbfs/Kconfig31
-rw-r--r--payloads/libpayload/libcbfs/Makefile.inc6
-rw-r--r--payloads/libpayload/libcbfs/cbfs.c363
-rw-r--r--payloads/libpayload/libcbfs/cbfs_core.c1
-rw-r--r--payloads/libpayload/libcbfs/cbfs_legacy.c223
5 files changed, 419 insertions, 205 deletions
diff --git a/payloads/libpayload/libcbfs/Kconfig b/payloads/libpayload/libcbfs/Kconfig
new file mode 100644
index 0000000000..634d77f3e5
--- /dev/null
+++ b/payloads/libpayload/libcbfs/Kconfig
@@ -0,0 +1,31 @@
+## SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later
+
+config CBFS
+ bool "CBFS support"
+ default y
+ help
+ CBFS is the archive format of coreboot
+
+if CBFS
+
+config DEBUG_CBFS
+ bool "Output verbose CBFS debug messages"
+ default n
+ help
+ This option enables additional CBFS related debug messages.
+
+config ENABLE_CBFS_FALLBACK
+ bool "Fallback to RO (COREBOOT) region"
+ default n
+ help
+ When this option is enabled, the CBFS code will look for a file in the
+ RO (COREBOOT) region, if it isn't available in the active RW region.
+ This option makes sense only if CONFIG_VBOOT was enabled in the coreboot.
+
+config CBFS_VERIFICATION
+ bool "Enable CBFS verification"
+ depends on VBOOT
+ help
+ This option enables hash verification of CBFS files in RO (COREBOOT) and RW regions.
+
+endif
diff --git a/payloads/libpayload/libcbfs/Makefile.inc b/payloads/libpayload/libcbfs/Makefile.inc
index 85ef485822..53e6f7fa43 100644
--- a/payloads/libpayload/libcbfs/Makefile.inc
+++ b/payloads/libpayload/libcbfs/Makefile.inc
@@ -28,3 +28,9 @@
libcbfs-$(CONFIG_LP_CBFS) += cbfs.c
libcbfs-$(CONFIG_LP_CBFS) += ram_media.c
+libcbfs-$(CONFIG_LP_CBFS) += cbfs_legacy.c
+
+ifeq ($(CONFIG_LP_CBFS),y)
+libcbfs-srcs += $(coreboottop)/src/commonlib/bsd/cbfs_private.c
+libcbfs-srcs += $(coreboottop)/src/commonlib/bsd/cbfs_mcache.c
+endif
diff --git a/payloads/libpayload/libcbfs/cbfs.c b/payloads/libpayload/libcbfs/cbfs.c
index d24b528ded..530f9e292d 100644
--- a/payloads/libpayload/libcbfs/cbfs.c
+++ b/payloads/libpayload/libcbfs/cbfs.c
@@ -1,243 +1,198 @@
-/*
- *
- * Copyright (C) 2011 secunet Security Networks AG
- * Copyright (C) 2013 Google, Inc.
- *
- * 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
-
-#ifdef LIBPAYLOAD
-# include <libpayload-config.h>
-# if CONFIG(LP_LZMA)
-# include <lzma.h>
-# define CBFS_CORE_WITH_LZMA
-# endif
-# if CONFIG(LP_LZ4)
-# include <lz4.h>
-# define CBFS_CORE_WITH_LZ4
-# endif
-# define CBFS_MINI_BUILD
-#elif defined(__SMM__)
-# define CBFS_MINI_BUILD
-#else
-# define CBFS_CORE_WITH_LZMA
-# define CBFS_CORE_WITH_LZ4
-# include <lib.h>
-#endif
+/* SPDX-License-Identifier: BSD-3-Clause */
+#include <libpayload-config.h>
+#include <arch/virtual.h>
+#include <assert.h>
#include <cbfs.h>
+#include <commonlib/bsd/cbfs_private.h>
+#include <commonlib/bsd/fmap_serialized.h>
+#include <libpayload.h>
+#include <lz4.h>
+#include <lzma.h>
#include <string.h>
+#include <sysinfo.h>
-#ifdef LIBPAYLOAD
-# include <stdio.h>
-# define DEBUG(x...)
-# define LOG(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_LP_DEBUG_CBFS
-# define DEBUG(x...) printk(BIOS_SPEW, "CBFS: " x)
-# else
-# define DEBUG(x...)
-# endif
-#endif
-
-#include "cbfs_core.c"
-
-#ifndef __SMM__
-static inline int tohex4(unsigned int c)
-{
- return (c <= 9) ? (c + '0') : (c - 10 + 'a');
-}
-static void tohex16(unsigned int val, char* dest)
+static const struct cbfs_boot_device *cbfs_get_boot_device(bool force_ro)
{
- dest[0] = tohex4(val>>12);
- dest[1] = tohex4((val>>8) & 0xf);
- dest[2] = tohex4((val>>4) & 0xf);
- dest[3] = tohex4(val & 0xf);
-}
+ static struct cbfs_boot_device ro;
+ static struct cbfs_boot_device rw;
+
+ if (!force_ro) {
+ if (!rw.dev.size) {
+ rw.dev.offset = lib_sysinfo.cbfs_offset;
+ rw.dev.size = lib_sysinfo.cbfs_size;
+ rw.mcache = phys_to_virt(lib_sysinfo.cbfs_rw_mcache_offset);
+ rw.mcache_size = lib_sysinfo.cbfs_rw_mcache_size;
+ }
+ return &rw;
+ }
-void *cbfs_load_optionrom(struct cbfs_media *media, uint16_t vendor,
- uint16_t device)
-{
- char name[17] = "pciXXXX,XXXX.rom";
+ if (ro.dev.size)
+ return &ro;
- tohex16(vendor, name+3);
- tohex16(device, name+8);
+ if (fmap_locate_area("COREBOOT", &ro.dev.offset, &ro.dev.size))
+ return NULL;
+
+ ro.mcache = phys_to_virt(lib_sysinfo.cbfs_ro_mcache_offset);
+ ro.mcache_size = lib_sysinfo.cbfs_ro_mcache_size;
- return cbfs_get_file_content(media, name, CBFS_TYPE_OPTIONROM, NULL);
+ return &ro;
}
-void * cbfs_load_stage(struct cbfs_media *media, const char *name)
+ssize_t _cbfs_boot_lookup(const char *name, bool force_ro, union cbfs_mdata *mdata)
{
- struct cbfs_stage *stage = (struct cbfs_stage *)
- cbfs_get_file_content(media, name, CBFS_TYPE_STAGE, NULL);
- /* this is a mess. There is no ntohll. */
- /* for now, assume compatible byte order until we solve this. */
- uintptr_t entry;
- uint32_t final_size;
-
- if (stage == NULL)
- return (void *) -1;
-
- LOG("loading stage %s @ %p (%d bytes), entry @ 0x%llx\n",
- name,
- (void*)(uintptr_t) stage->load, stage->memlen,
- stage->entry);
-
- final_size = cbfs_decompress(stage->compression,
- ((unsigned char *) stage) +
- sizeof(struct cbfs_stage),
- stage->len,
- (void *) (uintptr_t) stage->load,
- stage->memlen);
- if (!final_size) {
- entry = -1;
- goto out;
+ const struct cbfs_boot_device *cbd = cbfs_get_boot_device(force_ro);
+ if (!cbd)
+ return CB_ERR;
+
+ size_t data_offset;
+ cb_err_t err = CB_CBFS_CACHE_FULL;
+ if (cbd->mcache_size)
+ err = cbfs_mcache_lookup(cbd->mcache, cbd->mcache_size, name, mdata,
+ &data_offset);
+
+ if (err == CB_CBFS_CACHE_FULL)
+ err = cbfs_lookup(&cbd->dev, name, mdata, &data_offset, NULL);
+
+ /* Fallback to RO if possible. */
+ if (CONFIG(LP_ENABLE_CBFS_FALLBACK) && !force_ro && err == CB_CBFS_NOT_FOUND) {
+ LOG("Fall back to RO region for '%s'\n", name);
+ return _cbfs_boot_lookup(name, true, mdata);
}
- memset((void *)((uintptr_t)stage->load + final_size), 0,
- stage->memlen - final_size);
-
- DEBUG("stage loaded.\n");
-
- entry = stage->entry;
- // entry = ntohll(stage->entry);
+ if (err) {
+ if (err == CB_CBFS_NOT_FOUND)
+ LOG("'%s' not found.\n", name);
+ else
+ ERROR("Error %d when looking up '%s'\n", err, name);
+ return err;
+ }
-out:
- free(stage);
- return (void *) entry;
+ return cbd->dev.offset + data_offset;
}
-int cbfs_execute_stage(struct cbfs_media *media, const char *name)
+void cbfs_unmap(void *mapping)
{
- struct cbfs_stage *stage = (struct cbfs_stage *)
- cbfs_get_file_content(media, name, CBFS_TYPE_STAGE, NULL);
+ free(mapping);
+}
- if (stage == NULL)
- return 1;
+static bool cbfs_file_hash_mismatch(const void *buffer, size_t size,
+ const union cbfs_mdata *mdata)
+{
+ if (!CONFIG(LP_CBFS_VERIFICATION))
+ return false;
- if (ntohl(stage->compression) != CBFS_COMPRESS_NONE) {
- LOG("Unable to run %s: Compressed file"
- "Not supported for in-place execution\n", name);
- free(stage);
- return 1;
+ const struct vb2_hash *hash = cbfs_file_hash(mdata);
+ if (!hash) {
+ ERROR("'%s' does not have a file hash!\n", mdata->h.filename);
+ return true;
+ }
+ if (vb2_hash_verify(buffer, size, hash) != VB2_SUCCESS) {
+ ERROR("'%s' file hash mismatch!\n", mdata->h.filename);
+ return true;
}
- LOG("run @ %p\n", (void *) (uintptr_t)ntohll(stage->entry));
- int result = run_address((void *)(uintptr_t)ntohll(stage->entry));
- free(stage);
- return result;
+ return false;
}
-void *cbfs_load_payload(struct cbfs_media *media, const char *name)
+static size_t cbfs_load_and_decompress(size_t offset, size_t in_size, void *buffer,
+ size_t buffer_size, uint32_t compression,
+ const union cbfs_mdata *mdata)
{
- return (struct cbfs_payload *)cbfs_get_file_content(
- media, name, CBFS_TYPE_SELF, NULL);
-}
+ void *load = buffer;
+ size_t out_size = 0;
+
+ DEBUG("Decompressing %zu bytes from '%s' to %p with algo %d\n", in_size,
+ mdata->h.filename, buffer, compression);
+
+ if (compression != CBFS_COMPRESS_NONE) {
+ load = malloc(in_size);
+ if (!load) {
+ ERROR("'%s' buffer allocation failed\n", mdata->h.filename);
+ return 0;
+ }
+ }
-struct cbfs_file *cbfs_find(const char *name) {
- struct cbfs_handle *handle = cbfs_get_handle(CBFS_DEFAULT_MEDIA, name);
- struct cbfs_media *m = &handle->media;
- void *ret;
+ if (boot_device_read(load, offset, in_size) != in_size) {
+ ERROR("'%s' failed to read contents of file\n", mdata->h.filename);
+ goto out;
+ }
- if (!handle)
- return NULL;
+ if (cbfs_file_hash_mismatch(buffer, in_size, mdata))
+ goto out;
- ret = m->map(m, handle->media_offset,
- handle->content_offset + handle->content_size);
- if (ret == CBFS_MEDIA_INVALID_MAP_ADDRESS) {
- free(handle);
- return NULL;
+ switch (compression) {
+ case CBFS_COMPRESS_NONE:
+ out_size = in_size;
+ break;
+ case CBFS_COMPRESS_LZ4:
+ if (!CONFIG(LP_LZ4))
+ goto out;
+ out_size = ulz4fn(load, in_size, buffer, buffer_size);
+ break;
+ case CBFS_COMPRESS_LZMA:
+ if (!CONFIG(LP_LZMA))
+ goto out;
+ out_size = ulzman(load, in_size, buffer, buffer_size);
+ break;
+ default:
+ ERROR("'%s' decompression algo %d not supported\n", mdata->h.filename,
+ compression);
}
-
- free(handle);
- return ret;
+out:
+ if (load != buffer)
+ free(load);
+ return out_size;
}
-void *cbfs_find_file(const char *name, int type) {
- return cbfs_get_file_content(CBFS_DEFAULT_MEDIA, name, type, NULL);
-}
+void *_cbfs_load(const char *name, void *buf, size_t *size_inout, bool force_ro)
+{
+ ssize_t offset;
+ size_t out_size;
+ union cbfs_mdata mdata;
+ bool malloced = false;
-const struct cbfs_header *get_cbfs_header(void) {
- return cbfs_get_header(CBFS_DEFAULT_MEDIA);
-}
+ DEBUG("%s(name='%s', buf=%p, force_ro=%s)\n", __func__, name, buf,
+ force_ro ? "true" : "false");
-/* 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=%zu, count=%zu): "
- "allocated=%zu, size=%zu, last_allocate=%zu\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;
+ offset = _cbfs_boot_lookup(name, force_ro, &mdata);
+ if (offset < 0)
+ return NULL;
+
+ uint32_t compression = CBFS_COMPRESS_NONE;
+ const struct cbfs_file_attr_compression *cattr =
+ cbfs_find_attr(&mdata, CBFS_FILE_ATTR_TAG_COMPRESSION, sizeof(*cattr));
+ if (cattr) {
+ compression = be32toh(cattr->compression);
+ out_size = be32toh(cattr->decompressed_size);
+ } else {
+ out_size = be32toh(mdata.h.len);
}
- 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=%p): "
- "allocated=%zu, size=%zu, last_allocate=%zu\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;
+ if (buf) {
+ if (!size_inout || *size_inout < out_size) {
+ ERROR("'%s' buffer too small", mdata.h.filename);
+ return NULL;
+ }
+ } else {
+ buf = malloc(out_size);
+ if (!buf) {
+ ERROR("'%s' allocation failure", mdata.h.filename);
+ return NULL;
+ }
+ malloced = true;
}
- 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.
- */
+ if (cbfs_load_and_decompress(offset, be32toh(mdata.h.len), buf, out_size, compression,
+ &mdata)
+ != out_size) {
+ if (malloced)
+ free(buf);
+ return NULL;
+ }
+ if (size_inout)
+ *size_inout = out_size;
-int run_address(void *f)
-{
- int (*v) (void);
- v = f;
- return v();
+ return buf;
}
-
-#endif
diff --git a/payloads/libpayload/libcbfs/cbfs_core.c b/payloads/libpayload/libcbfs/cbfs_core.c
index 82c2846054..bc513682c9 100644
--- a/payloads/libpayload/libcbfs/cbfs_core.c
+++ b/payloads/libpayload/libcbfs/cbfs_core.c
@@ -242,7 +242,6 @@ void *cbfs_get_contents(struct cbfs_handle *handle, size_t *size, size_t limit)
cbfs_get_attr(handle, CBFS_FILE_ATTR_TAG_COMPRESSION);
if (comp) {
algo = ntohl(comp->compression);
- DEBUG("File '%s' is compressed (alg=%d)\n", name, algo);
*size = ntohl(comp->decompressed_size);
/* TODO: Implement partial decompression with |limit| */
}
diff --git a/payloads/libpayload/libcbfs/cbfs_legacy.c b/payloads/libpayload/libcbfs/cbfs_legacy.c
new file mode 100644
index 0000000000..8249196d9a
--- /dev/null
+++ b/payloads/libpayload/libcbfs/cbfs_legacy.c
@@ -0,0 +1,223 @@
+/*
+ *
+ * Copyright (C) 2011 secunet Security Networks AG
+ * Copyright (C) 2013 Google, Inc.
+ *
+ * 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 <libpayload-config.h>
+#if CONFIG(LP_LZMA)
+# include <lzma.h>
+# define CB_CBFS_CORE_WITH_LZMA
+#endif
+#if CONFIG(LP_LZ4)
+# include <lz4.h>
+# define CB_CBFS_CORE_WITH_LZ4
+#endif
+
+#include <cbfs_legacy.h>
+#include <stdio.h>
+
+#define DEBUG(x...)
+#define LOG(x...)
+#define ERROR(x...) printf(x)
+
+#ifndef __SMM__
+
+#include "cbfs_core.c"
+
+static inline int tohex4(unsigned int c)
+{
+ 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);
+}
+
+void *cbfs_load_optionrom(struct cbfs_media *media, uint16_t vendor,
+ uint16_t device)
+{
+ char name[17] = "pciXXXX,XXXX.rom";
+
+ tohex16(vendor, name+3);
+ tohex16(device, name+8);
+
+ return cbfs_get_file_content(media, name, CBFS_TYPE_OPTIONROM, NULL);
+}
+
+void *cbfs_load_stage(struct cbfs_media *media, const char *name)
+{
+ struct cbfs_stage *stage = (struct cbfs_stage *)
+ cbfs_get_file_content(media, name, CBFS_TYPE_STAGE, NULL);
+ /* this is a mess. There is no ntohll. */
+ /* for now, assume compatible byte order until we solve this. */
+ uintptr_t entry;
+ uint32_t final_size;
+
+ if (stage == NULL)
+ return (void *) -1;
+
+ LOG("loading stage %s @ %p (%d bytes), entry @ 0x%llx\n", name,
+ (void *)(uintptr_t)stage->load, stage->memlen, stage->entry);
+
+ final_size = cbfs_decompress(stage->compression,
+ ((unsigned char *) stage) +
+ sizeof(struct cbfs_stage),
+ stage->len,
+ (void *) (uintptr_t) stage->load,
+ stage->memlen);
+ if (!final_size) {
+ entry = -1;
+ goto out;
+ }
+
+ memset((void *)((uintptr_t)stage->load + final_size), 0,
+ stage->memlen - final_size);
+
+ DEBUG("stage loaded.\n");
+
+ entry = stage->entry;
+ // entry = ntohll(stage->entry);
+
+out:
+ free(stage);
+ return (void *) entry;
+}
+
+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, NULL);
+
+ if (stage == NULL)
+ return 1;
+
+ if (ntohl(stage->compression) != CBFS_COMPRESS_NONE) {
+ LOG("Unable to run %s: Compressed file"
+ "Not supported for in-place execution\n", name);
+ free(stage);
+ return 1;
+ }
+
+ LOG("run @ %p\n", (void *) (uintptr_t)ntohll(stage->entry));
+ int result = run_address((void *)(uintptr_t)ntohll(stage->entry));
+ free(stage);
+ return result;
+}
+
+void *cbfs_load_payload(struct cbfs_media *media, const char *name)
+{
+ return (struct cbfs_payload *)cbfs_get_file_content(
+ media, name, CBFS_TYPE_SELF, NULL);
+}
+
+struct cbfs_file *cbfs_find(const char *name)
+{
+ struct cbfs_handle *handle = cbfs_get_handle(CBFS_DEFAULT_MEDIA, name);
+ struct cbfs_media *m = &handle->media;
+ void *ret;
+
+ if (!handle)
+ return NULL;
+
+ ret = m->map(m, handle->media_offset,
+ handle->content_offset + handle->content_size);
+ if (ret == CBFS_MEDIA_INVALID_MAP_ADDRESS) {
+ free(handle);
+ return NULL;
+ }
+
+ free(handle);
+ return ret;
+}
+
+void *cbfs_find_file(const char *name, int type)
+{
+ return cbfs_get_file_content(CBFS_DEFAULT_MEDIA, name, type, NULL);
+}
+
+const struct cbfs_header *get_cbfs_header(void)
+{
+ return cbfs_get_header(CBFS_DEFAULT_MEDIA);
+}
+
+/* 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=%zu, count=%zu): "
+ "allocated=%zu, size=%zu, last_allocate=%zu\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=%p): "
+ "allocated=%zu, size=%zu, last_allocate=%zu\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)
+{
+ int (*v)(void);
+ v = f;
+ return v();
+}
+
+#endif /* __SMM__ */