xref: /rk3399_ARM-atf/lib/coreboot/coreboot_table.c (revision 3429c77ab09b69eef4ed752c2d641ed724e72110)
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