summaryrefslogtreecommitdiff
path: root/src/vendorcode/google/chromeos/vboot_wrapper.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vendorcode/google/chromeos/vboot_wrapper.c')
-rw-r--r--src/vendorcode/google/chromeos/vboot_wrapper.c268
1 files changed, 268 insertions, 0 deletions
diff --git a/src/vendorcode/google/chromeos/vboot_wrapper.c b/src/vendorcode/google/chromeos/vboot_wrapper.c
new file mode 100644
index 0000000000..66b7cfb276
--- /dev/null
+++ b/src/vendorcode/google/chromeos/vboot_wrapper.c
@@ -0,0 +1,268 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <console/vtxprintf.h>
+#include <cpu/x86/tsc.h>
+#include <rmodule.h>
+#include <stdlib.h>
+#include <string.h>
+#include "vboot_context.h"
+#include "vboot_handoff.h"
+
+static void vboot_wrapper(struct vboot_context *context);
+
+DEFINE_RMODULE_HEADER(vboot_wrapper_header, vboot_wrapper, RMODULE_TYPE_VBOOT);
+
+/* Keep a global context pointer around for the callbacks to use. */
+static struct vboot_context *gcontext;
+
+/* The FW areas consist of multiple components. At the beginning of
+ * each area is the number of total compoments as well as the size and
+ * offset for each component. One needs to caculate the total size of the
+ * signed firmware region based off of the embedded metadata. */
+#define MAX_NUM_COMPONENTS 20
+
+struct component_entry {
+ uint32_t offset;
+ uint32_t size;
+} __attribute__((packed));
+
+struct components {
+ uint32_t num_components;
+ struct component_entry entries[0];
+} __attribute__((packed));
+
+
+static void parse_component(const struct components *components, int num,
+ struct firmware_component *fw)
+{
+ const char *base;
+
+ if (num >= components->num_components)
+ return;
+
+ /* Offsets are relative to the stat of the book keeping structure. */
+ base = (void *)components;
+
+ fw->address = (uint32_t)&base[components->entries[num].offset];
+ fw->size = (uint32_t)components->entries[num].size;
+}
+
+static void vboot_wrapper(struct vboot_context *context)
+{
+ int i;
+ VbError_t res;
+ const struct components *components;
+
+ gcontext = context;
+
+ VbExDebug("Calling VbInit()\n");
+ res = VbInit(context->cparams, &context->handoff->init_params);
+ VbExDebug("VbInit() returned 0x%08x\n", res);
+
+ if (res != VBERROR_SUCCESS)
+ return;
+
+ VbExDebug("Calling VbSelectFirmware()\n");
+ res = VbSelectFirmware(context->cparams, context->fparams);
+ VbExDebug("VbSelectFirmware() returned 0x%08x\n", res);
+
+ if (res != VBERROR_SUCCESS)
+ return;
+
+ /* Fix up the handoff structure. */
+ context->handoff->selected_firmware =
+ context->fparams->selected_firmware;
+
+ /* Parse out the components for downstream consumption. */
+ if (context->handoff->selected_firmware == VB_SELECT_FIRMWARE_A)
+ components = (void *)context->fw_a;
+ else if (context->handoff->selected_firmware == VB_SELECT_FIRMWARE_B)
+ components = (void *)context->fw_b;
+ else
+ return;
+
+ for (i = 0; i < MAX_PARSED_FW_COMPONENTS; i++) {
+ parse_component(components, i,
+ &context->handoff->components[i]);
+ }
+}
+
+void VbExError(const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ gcontext->log_msg(format, args);
+ va_end(args);
+
+ gcontext->fatal_error();
+}
+
+void VbExDebug(const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ gcontext->log_msg(format, args);
+ va_end(args);
+}
+
+uint64_t VbExGetTimer(void)
+{
+ return rdtscll();
+}
+
+VbError_t VbExNvStorageRead(uint8_t *buf)
+{
+ gcontext->read_vbnv(buf);
+ return VBERROR_SUCCESS;
+}
+
+VbError_t VbExNvStorageWrite(const uint8_t *buf)
+{
+ gcontext->save_vbnv(buf);
+ return VBERROR_SUCCESS;
+}
+
+extern char _heap[];
+extern char _eheap[];
+static char *heap_current;
+static int heap_size;
+
+void *VbExMalloc(size_t size)
+{
+ void *ptr;
+
+ if (heap_current == NULL) {
+ heap_current = &_heap[0];
+ heap_size = &_eheap[0] - &_heap[0];
+ VbExDebug("vboot heap: %p 0x%08x bytes\n",
+ heap_current, heap_size);
+ }
+
+ if (heap_size < size) {
+ VbExError("vboot heap request cannot be fulfilled. "
+ "0x%08x available, 0x%08x requested\n",
+ heap_size, size);
+ }
+
+ ptr = heap_current;
+ heap_size -= size;
+ heap_current += size;
+
+ return ptr;
+}
+
+void VbExFree(void *ptr)
+{
+ /* Leak all memory. */
+}
+
+/* vboot doesn't expose these through the vboot_api.h, but they are needed.
+ * coreboot requires declarations so provide them to avoid compiler errors. */
+int Memcmp(const void *src1, const void *src2, size_t n);
+void *Memcpy(void *dest, const void *src, uint64_t n);
+void *Memset(void *dest, const uint8_t c, uint64_t n);
+
+int Memcmp(const void *src1, const void *src2, size_t n)
+{
+ return memcmp(src1, src2, n);
+}
+
+void *Memcpy(void *dest, const void *src, uint64_t n)
+{
+ return memcpy(dest, src, n);
+}
+
+void *Memset(void *dest, const uint8_t c, uint64_t n)
+{
+ return memset(dest, c, n);
+}
+
+VbError_t VbExHashFirmwareBody(VbCommonParams *cparams, uint32_t firmware_index)
+{
+ uint8_t *data;
+ uint32_t size;
+ uint32_t data_size;
+ struct components *components;
+ uint32_t i;
+
+ switch (firmware_index) {
+ case VB_SELECT_FIRMWARE_A:
+ data = gcontext->fw_a;
+ size = gcontext->fw_a_size;
+ break;
+ case VB_SELECT_FIRMWARE_B:
+ data = gcontext->fw_b;
+ size = gcontext->fw_b_size;
+ break;
+ default:
+ return VBERROR_UNKNOWN;
+ }
+
+ components = (void *)data;
+ data_size = sizeof(struct components);
+
+ if (components->num_components > MAX_NUM_COMPONENTS)
+ return VBERROR_UNKNOWN;
+
+ data_size +=
+ components->num_components * sizeof(struct component_entry);
+
+ for (i = 0; i < components->num_components; i++)
+ data_size += ALIGN(components->entries[i].size, 4);
+
+ if (size < data_size)
+ return VBERROR_UNKNOWN;
+
+ VbUpdateFirmwareBodyHash(cparams, data, data_size);
+
+ return VBERROR_SUCCESS;
+}
+
+VbError_t VbExTpmInit(void)
+{
+ if (gcontext->tis_init())
+ return VBERROR_UNKNOWN;
+ return VbExTpmOpen();
+}
+
+VbError_t VbExTpmClose(void)
+{
+ if (gcontext->tis_close())
+ return VBERROR_UNKNOWN;
+ return VBERROR_SUCCESS;
+}
+
+VbError_t VbExTpmOpen(void)
+{
+ if (gcontext->tis_open())
+ return VBERROR_UNKNOWN;
+ return VBERROR_SUCCESS;
+}
+
+VbError_t VbExTpmSendReceive(const uint8_t *request, uint32_t request_length,
+ uint8_t *response, uint32_t *response_length)
+{
+ if (gcontext->tis_sendrecv(request, request_length,
+ response, response_length))
+ return VBERROR_UNKNOWN;
+ return VBERROR_SUCCESS;
+}
+