From 3429c77ab09b69eef4ed752c2d641ed724e72110 Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Fri, 9 Jun 2017 15:17:15 -0700 Subject: [PATCH] Add platform-independent coreboot support library This patch adds the foundation for a platform-independent coreboot support library that can be shared by all platforms that boot BL31 from coreboot (acting as BL2). It adds code to parse the "coreboot table", a data structure that coreboot uses to communicate different kinds of information to later-stage firmware and certain OS drivers. As a first small use case for this information, allow platforms to access the serial console configuration used by coreboot, removing the need to hardcode base address and divisors and allowing Trusted Firmware to benefit from coreboot's user configuration (e.g. which UART to pick and which baud rate to use). Change-Id: I2bfb39cd2609ce6640b844ab68df6c9ae3f28e9e Signed-off-by: Julius Werner --- include/lib/coreboot.h | 24 ++++++++++ lib/coreboot/coreboot.mk | 20 ++++++++ lib/coreboot/coreboot_table.c | 89 +++++++++++++++++++++++++++++++++++ make_helpers/defaults.mk | 4 ++ 4 files changed, 137 insertions(+) create mode 100644 include/lib/coreboot.h create mode 100644 lib/coreboot/coreboot.mk create mode 100644 lib/coreboot/coreboot_table.c diff --git a/include/lib/coreboot.h b/include/lib/coreboot.h new file mode 100644 index 000000000..4b1f200a2 --- /dev/null +++ b/include/lib/coreboot.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __COREBOOT_H__ +#define __COREBOOT_H__ + +#include + +typedef struct { + uint32_t type; /* always 2 (memory-mapped) on ARM */ + uint32_t baseaddr; + uint32_t baud; + uint32_t regwidth; /* in bytes, i.e. usually 4 */ + uint32_t input_hertz; + uint32_t uart_pci_addr; /* unused on current ARM systems */ +} coreboot_serial_t; +extern coreboot_serial_t coreboot_serial; + +void coreboot_table_setup(void *base); + +#endif /* __COREBOOT_H__ */ diff --git a/lib/coreboot/coreboot.mk b/lib/coreboot/coreboot.mk new file mode 100644 index 000000000..0cd103f27 --- /dev/null +++ b/lib/coreboot/coreboot.mk @@ -0,0 +1,20 @@ +# +# 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) + +endif # COREBOOT diff --git a/lib/coreboot/coreboot_table.c b/lib/coreboot/coreboot_table.c new file mode 100644 index 000000000..76e5d3b70 --- /dev/null +++ b/lib/coreboot/coreboot_table.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +/* + * Structures describing coreboot's in-memory descriptor tables. See + * /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_t; + +typedef struct { + uint32_t tag; + uint32_t size; + union { + coreboot_serial_t serial; + }; +} 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; +} + +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; + default: + /* There are many tags TF doesn't need to care about. */ + break; + } + + ptr += read_le32(&entry->size); + } +} diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk index 2eb922f89..eb1bb0aea 100644 --- a/make_helpers/defaults.mk +++ b/make_helpers/defaults.mk @@ -31,6 +31,10 @@ BASE_COMMIT := origin/master # The platform Makefile is free to override this value. COLD_BOOT_SINGLE_CPU := 0 +# Flag to compile in coreboot support code. Exclude by default. The coreboot +# Makefile system will set this when compiling TF as part of a coreboot image. +COREBOOT := 0 + # For Chain of Trust CREATE_KEYS := 1