1 /* 2 * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <coreboot.h> 8 #include <debug.h> 9 #include <mmio.h> 10 #include <string.h> 11 12 /* 13 * Structures describing coreboot's in-memory descriptor tables. See 14 * <coreboot>/src/commonlib/include/commonlib/coreboot_tables.h for 15 * canonical implementation. 16 */ 17 18 typedef struct { 19 char signature[4]; 20 uint32_t header_bytes; 21 uint32_t header_checksum; 22 uint32_t table_bytes; 23 uint32_t table_checksum; 24 uint32_t table_entries; 25 } cb_header_t; 26 27 typedef enum { 28 CB_TAG_SERIAL = 0xf, 29 } cb_tag_t; 30 31 typedef struct { 32 uint32_t tag; 33 uint32_t size; 34 union { 35 coreboot_serial_t serial; 36 }; 37 } cb_entry_t; 38 39 coreboot_serial_t coreboot_serial; 40 41 /* 42 * The coreboot table is parsed before the MMU is enabled (i.e. with strongly 43 * ordered memory), so we cannot make unaligned accesses. The table entries 44 * immediately follow one another without padding, so nothing after the header 45 * is guaranteed to be naturally aligned. Therefore, we need to define safety 46 * functions that can read unaligned integers. 47 */ 48 static uint32_t read_le32(uint32_t *p) 49 { 50 uintptr_t addr = (uintptr_t)p; 51 return mmio_read_8(addr) | 52 mmio_read_8(addr + 1) << 8 | 53 mmio_read_8(addr + 2) << 16 | 54 mmio_read_8(addr + 3) << 24; 55 } 56 57 void coreboot_table_setup(void *base) 58 { 59 cb_header_t *header = base; 60 void *ptr; 61 int i; 62 63 if (strncmp(header->signature, "LBIO", 4)) { 64 ERROR("coreboot table signature corrupt!\n"); 65 return; 66 } 67 68 ptr = base + header->header_bytes; 69 for (i = 0; i < header->table_entries; i++) { 70 cb_entry_t *entry = ptr; 71 72 if (ptr - base >= header->header_bytes + header->table_bytes) { 73 ERROR("coreboot table exceeds its bounds!\n"); 74 break; 75 } 76 77 switch (read_le32(&entry->tag)) { 78 case CB_TAG_SERIAL: 79 memcpy(&coreboot_serial, &entry->serial, 80 sizeof(coreboot_serial)); 81 break; 82 default: 83 /* There are many tags TF doesn't need to care about. */ 84 break; 85 } 86 87 ptr += read_le32(&entry->size); 88 } 89 } 90