summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authordavidcunado-arm <david.cunado@arm.com>2018-01-24 14:31:53 +0000
committerGitHub <noreply@github.com>2018-01-24 14:31:53 +0000
commit040f1e6987ab78ce459a96137a92cb985c16a136 (patch)
tree4ac8cf8073f03180de5b04373302518727a03490 /lib
parentd2184052ec9f7055e666885d2e9f1c563bdd8d93 (diff)
parent1c5f5031f38ed77688298d419727a6f0930e0673 (diff)
Merge pull request #1193 from jwerner-chromium/JW_coreboot
New console API and coreboot support [v4]
Diffstat (limited to 'lib')
-rw-r--r--lib/coreboot/coreboot.mk24
-rw-r--r--lib/coreboot/coreboot_table.c123
2 files changed, 147 insertions, 0 deletions
diff --git a/lib/coreboot/coreboot.mk b/lib/coreboot/coreboot.mk
new file mode 100644
index 00000000..bbaa3329
--- /dev/null
+++ b/lib/coreboot/coreboot.mk
@@ -0,0 +1,24 @@
+#
+# Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+COREBOOT := 0
+$(eval $(call assert_boolean,COREBOOT))
+$(eval $(call add_define,COREBOOT))
+
+ifeq (${COREBOOT},1)
+
+ifneq (${ARCH},aarch64)
+$(error "coreboot only supports Trusted Firmware on AArch64.")
+endif
+
+BL31_SOURCES += $(addprefix lib/coreboot/, \
+ coreboot_table.c)
+
+BL31_SOURCES += drivers/coreboot/cbmem_console/${ARCH}/cbmem_console.S
+
+INCLUDES += -Iinclude/drivers/coreboot
+
+endif # COREBOOT
diff --git a/lib/coreboot/coreboot_table.c b/lib/coreboot/coreboot_table.c
new file mode 100644
index 00000000..64f8879e
--- /dev/null
+++ b/lib/coreboot/coreboot_table.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <cbmem_console.h>
+#include <coreboot.h>
+#include <debug.h>
+#include <mmio.h>
+#include <string.h>
+#include <xlat_tables_v2.h>
+
+/*
+ * Structures describing coreboot's in-memory descriptor tables. See
+ * <coreboot>/src/commonlib/include/commonlib/coreboot_tables.h for
+ * canonical implementation.
+ */
+
+typedef struct {
+ char signature[4];
+ uint32_t header_bytes;
+ uint32_t header_checksum;
+ uint32_t table_bytes;
+ uint32_t table_checksum;
+ uint32_t table_entries;
+} cb_header_t;
+
+typedef enum {
+ CB_TAG_SERIAL = 0xf,
+ CB_TAG_CBMEM_CONSOLE = 0x17,
+} cb_tag_t;
+
+typedef struct {
+ uint32_t tag;
+ uint32_t size;
+ union {
+ coreboot_serial_t serial;
+ uint64_t uint64;
+ };
+} cb_entry_t;
+
+coreboot_serial_t coreboot_serial;
+
+/*
+ * The coreboot table is parsed before the MMU is enabled (i.e. with strongly
+ * ordered memory), so we cannot make unaligned accesses. The table entries
+ * immediately follow one another without padding, so nothing after the header
+ * is guaranteed to be naturally aligned. Therefore, we need to define safety
+ * functions that can read unaligned integers.
+ */
+static uint32_t read_le32(uint32_t *p)
+{
+ uintptr_t addr = (uintptr_t)p;
+ return mmio_read_8(addr) |
+ mmio_read_8(addr + 1) << 8 |
+ mmio_read_8(addr + 2) << 16 |
+ mmio_read_8(addr + 3) << 24;
+}
+static uint64_t read_le64(uint64_t *p)
+{
+ return read_le32((void *)p) | (uint64_t)read_le32((void *)p + 4) << 32;
+}
+
+static void expand_and_mmap(uintptr_t baseaddr, size_t size)
+{
+ uintptr_t pageaddr = round_down(baseaddr, PAGE_SIZE);
+ size_t expanded = round_up(baseaddr - pageaddr + size, PAGE_SIZE);
+ mmap_add_region(pageaddr, pageaddr, expanded,
+ MT_MEMORY | MT_RW | MT_NS | MT_EXECUTE_NEVER);
+}
+
+static void setup_cbmem_console(uintptr_t baseaddr)
+{
+ static console_cbmc_t console;
+ assert(!console.base); /* should only have one CBMEM console */
+
+ /* CBMEM console structure stores its size in first header field. */
+ uint32_t size = *(uint32_t *)baseaddr;
+ expand_and_mmap(baseaddr, size);
+ console_cbmc_register(baseaddr, &console);
+ console_set_scope(&console.console, CONSOLE_FLAG_BOOT |
+ CONSOLE_FLAG_RUNTIME |
+ CONSOLE_FLAG_CRASH);
+}
+
+void coreboot_table_setup(void *base)
+{
+ cb_header_t *header = base;
+ void *ptr;
+ int i;
+
+ if (strncmp(header->signature, "LBIO", 4)) {
+ ERROR("coreboot table signature corrupt!\n");
+ return;
+ }
+
+ ptr = base + header->header_bytes;
+ for (i = 0; i < header->table_entries; i++) {
+ cb_entry_t *entry = ptr;
+
+ if (ptr - base >= header->header_bytes + header->table_bytes) {
+ ERROR("coreboot table exceeds its bounds!\n");
+ break;
+ }
+
+ switch (read_le32(&entry->tag)) {
+ case CB_TAG_SERIAL:
+ memcpy(&coreboot_serial, &entry->serial,
+ sizeof(coreboot_serial));
+ break;
+ case CB_TAG_CBMEM_CONSOLE:
+ setup_cbmem_console(read_le64(&entry->uint64));
+ break;
+ default:
+ /* There are many tags TF doesn't need to care about. */
+ break;
+ }
+
+ ptr += read_le32(&entry->size);
+ }
+}