summaryrefslogtreecommitdiff
path: root/payloads/libpayload/libcbfs/cbfs_legacy.c
diff options
context:
space:
mode:
authorJakub Czapiga <jacz@semihalf.com>2021-11-15 08:36:07 +0000
committerFelix Held <felix-coreboot@felixheld.de>2022-01-10 14:30:04 +0000
commit63e54275f684da6f6db8289561726adab5254b39 (patch)
treea01a1b40170f88ef0036585564eb30ac8b57ef48 /payloads/libpayload/libcbfs/cbfs_legacy.c
parent1fa3da4d9b30ad7e63b79b6966794ee179dc6501 (diff)
libpayload: Implement new CBFS access API
This commit adds new CBFS API, which is based on the one available in the main coreboot source tree. Libpayload implementation supports RO/RW file lookups and file contents verification. Change-Id: I00da0658dbac0cddf92ad55611def947932d23c7 Signed-off-by: Jakub Czapiga <jacz@semihalf.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/59497 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Julius Werner <jwerner@chromium.org>
Diffstat (limited to 'payloads/libpayload/libcbfs/cbfs_legacy.c')
-rw-r--r--payloads/libpayload/libcbfs/cbfs_legacy.c223
1 files changed, 223 insertions, 0 deletions
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__ */