diff options
Diffstat (limited to 'lib/coreboot/coreboot_table.c')
-rw-r--r-- | lib/coreboot/coreboot_table.c | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/lib/coreboot/coreboot_table.c b/lib/coreboot/coreboot_table.c new file mode 100644 index 00000000..76e5d3b7 --- /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 <coreboot.h> +#include <debug.h> +#include <mmio.h> +#include <string.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_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); + } +} |