summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJulius Werner <jwerner@chromium.org>2017-06-13 15:53:45 -0700
committerJulius Werner <jwerner@chromium.org>2018-01-19 15:21:12 -0800
commit1c5f5031f38ed77688298d419727a6f0930e0673 (patch)
tree0ce47576b2e24073a1f22ce3d808da2364e3f9c6 /lib
parent890abc33e46349fb01aed443ad7128b82ba34f3d (diff)
coreboot: Add support for CBMEM console
coreboot supports an in-memory console to store firmware logs even when no serial console is available. It is widely supported by coreboot-compatible bootloaders (including SeaBIOS and GRUB) and can be read by the Linux kernel. This patch allows BL31 to add its own log messages to this console. The driver will be registered automatically if coreboot support is compiled in and detects the presence of a console buffer in the coreboot tables. Change-Id: I31254dfa0c2fdeb7454634134b5707b4b4154907 Signed-off-by: Julius Werner <jwerner@chromium.org>
Diffstat (limited to 'lib')
-rw-r--r--lib/coreboot/coreboot.mk4
-rw-r--r--lib/coreboot/coreboot_table.c34
2 files changed, 38 insertions, 0 deletions
diff --git a/lib/coreboot/coreboot.mk b/lib/coreboot/coreboot.mk
index 0cd103f2..bbaa3329 100644
--- a/lib/coreboot/coreboot.mk
+++ b/lib/coreboot/coreboot.mk
@@ -17,4 +17,8 @@ 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
index 76e5d3b7..64f8879e 100644
--- a/lib/coreboot/coreboot_table.c
+++ b/lib/coreboot/coreboot_table.c
@@ -4,10 +4,13 @@
* 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
@@ -26,6 +29,7 @@ typedef struct {
typedef enum {
CB_TAG_SERIAL = 0xf,
+ CB_TAG_CBMEM_CONSOLE = 0x17,
} cb_tag_t;
typedef struct {
@@ -33,6 +37,7 @@ typedef struct {
uint32_t size;
union {
coreboot_serial_t serial;
+ uint64_t uint64;
};
} cb_entry_t;
@@ -53,6 +58,32 @@ static uint32_t read_le32(uint32_t *p)
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)
{
@@ -79,6 +110,9 @@ void coreboot_table_setup(void *base)
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;