/ payloads / coreinfo / coreboot_module.c
coreboot_module.c
  1  /* SPDX-License-Identifier: GPL-2.0-only */
  2  
  3  #include "coreinfo.h"
  4  #include <coreboot_tables.h>
  5  
  6  #if CONFIG(MODULE_COREBOOT)
  7  
  8  #define MAX_MEMORY_COUNT 5
  9  
 10  static struct {
 11  	int mem_count;
 12  	int mem_actual;
 13  
 14  	struct cb_memory_range range[MAX_MEMORY_COUNT];
 15  
 16  	char vendor[32];
 17  	char part[32];
 18  
 19  	char strings[10][64];
 20  
 21  	struct cb_serial serial;
 22  	struct cb_console console;
 23  } cb_info;
 24  
 25  static int tables_good = 0;
 26  
 27  static int coreboot_module_redraw(WINDOW *win)
 28  {
 29  	int row = 2;
 30  	int i;
 31  
 32  	print_module_title(win, "coreboot Tables");
 33  
 34  	if (tables_good) {
 35  		mvwprintw(win, row++, 1, "No coreboot tables were found");
 36  		return 0;
 37  	}
 38  
 39  	mvwprintw(win, row++, 1, "Vendor: %s", cb_info.vendor);
 40  	mvwprintw(win, row++, 1, "Part: %s", cb_info.part);
 41  
 42  	mvwprintw(win, row++, 1, "Version: %s%s",
 43  		  cb_info.strings[CB_TAG_VERSION - 0x4],
 44  		  cb_info.strings[CB_TAG_EXTRA_VERSION - 0x4]);
 45  
 46  	mvwprintw(win, row++, 1, "Built: %s (%s@%s.%s)",
 47  		  cb_info.strings[CB_TAG_BUILD - 0x4],
 48  		  cb_info.strings[CB_TAG_COMPILE_BY - 0x04],
 49  		  cb_info.strings[CB_TAG_COMPILE_HOST - 0x04],
 50  		  cb_info.strings[CB_TAG_COMPILE_DOMAIN - 0x04]);
 51  
 52  	if (cb_info.serial.tag != 0x0) {
 53  		mvwprintw(win, row++, 1, "Serial Port I/O base: 0x%x",
 54  			  cb_info.serial.baseaddr);
 55  	}
 56  
 57  	if (cb_info.console.tag != 0x0) {
 58  		mvwprintw(win, row++, 1, "Default Output Console: ");
 59  
 60  		switch (cb_info.console.type) {
 61  		case CB_TAG_CONSOLE_SERIAL8250:
 62  			wprintw(win, "Serial Port");
 63  			break;
 64  		case CB_TAG_CONSOLE_VGA:
 65  			wprintw(win, "VGA");
 66  			break;
 67  		case CB_TAG_CONSOLE_BTEXT:
 68  			wprintw(win, "BTEXT");
 69  			break;
 70  		case CB_TAG_CONSOLE_LOGBUF:
 71  			wprintw(win, "Log Buffer");
 72  			break;
 73  		case CB_TAG_CONSOLE_SROM:
 74  			wprintw(win, "Serial ROM");
 75  			break;
 76  		case CB_TAG_CONSOLE_EHCI:
 77  			wprintw(win, "USB Debug");
 78  			break;
 79  		}
 80  	}
 81  
 82  	row++;
 83  	mvwprintw(win, row++, 1, "-- Memory Map --");
 84  
 85  	for (i = 0; i < cb_info.mem_count; i++) {
 86  		switch (cb_info.range[i].type) {
 87  		case CB_MEM_RAM:
 88  			mvwprintw(win, row++, 3, "     RAM: ");
 89  			break;
 90  		case CB_MEM_RESERVED:
 91  			mvwprintw(win, row++, 3, "Reserved: ");
 92  			break;
 93  		case CB_MEM_TABLE:
 94  			mvwprintw(win, row++, 3, "   Table: ");
 95  		}
 96  
 97  		wprintw(win, "%16.16llx - %16.16llx", cb_info.range[i].start,
 98  			cb_info.range[i].start + cb_info.range[i].size - 1);
 99  	}
100  
101  	return 0;
102  }
103  
104  static void parse_memory(unsigned char *ptr)
105  {
106  	struct cb_memory *mem = (struct cb_memory *)ptr;
107  	int max = (MEM_RANGE_COUNT(mem) > MAX_MEMORY_COUNT)
108  	    ? MAX_MEMORY_COUNT : MEM_RANGE_COUNT(mem);
109  	int i;
110  
111  	for (i = 0; i < max; i++) {
112  		struct cb_memory_range *range =
113  		    (struct cb_memory_range *)MEM_RANGE_PTR(mem, i);
114  
115  		memcpy(&cb_info.range[i], range, sizeof(*range));
116  	}
117  
118  	cb_info.mem_count = max;
119  	cb_info.mem_actual = MEM_RANGE_COUNT(mem);
120  }
121  
122  static void parse_mainboard(unsigned char *ptr)
123  {
124  	struct cb_mainboard *mb = (struct cb_mainboard *)ptr;
125  
126  	strncpy(cb_info.vendor, cb_mb_vendor_string(mb), sizeof(cb_info.vendor) - 1);
127  	strncpy(cb_info.part, cb_mb_part_string(mb), sizeof(cb_info.part) - 1);
128  }
129  
130  static void parse_strings(unsigned char *ptr)
131  {
132  	struct cb_string *string = (struct cb_string *)ptr;
133  	int index = string->tag - CB_TAG_VERSION;
134  
135  	strncpy(cb_info.strings[index], (const char *)string->string, 63);
136  	cb_info.strings[index][63] = 0;
137  }
138  
139  static void parse_serial(unsigned char *ptr)
140  {
141  	memcpy(&cb_info.serial, (struct cb_serial *)ptr,
142  	       sizeof(struct cb_serial));
143  }
144  
145  static void parse_console(unsigned char *ptr)
146  {
147  	memcpy(&cb_info.console, (struct cb_console *)ptr,
148  	       sizeof(struct cb_console));
149  }
150  
151  static int parse_header(void *addr, int len)
152  {
153  	struct cb_header *header;
154  	unsigned char *ptr = (unsigned char *)addr;
155  	int i;
156  
157  	for (i = 0; i < len; i += 16, ptr += 16) {
158  		header = (struct cb_header *)ptr;
159  
160  		if (!strncmp((const char *)header->signature, "LBIO", 4))
161  			break;
162  	}
163  
164  	/* We walked the entire space and didn't find anything. */
165  	if (i >= len)
166  		return -1;
167  
168  	if (!header->table_bytes)
169  		return 0;
170  
171  	/* FIXME: Check the checksum. */
172  
173  	if (cb_checksum(header, sizeof(*header)))
174  		return -1;
175  
176  	if (cb_checksum((ptr + sizeof(*header)), header->table_bytes)
177  	    != header->table_checksum)
178  		return -1;
179  
180  	/* Now, walk the tables. */
181  	ptr += header->header_bytes;
182  
183  	for (u32 j = 0; j < header->table_entries; j++) {
184  		struct cb_record *rec = (struct cb_record *)ptr;
185  
186  		switch (rec->tag) {
187  		case CB_TAG_FORWARD:
188  			return parse_header((void *)(unsigned long)((struct cb_forward *)rec)->forward, 1);
189  		case CB_TAG_MEMORY:
190  			parse_memory(ptr);
191  			break;
192  		case CB_TAG_MAINBOARD:
193  			parse_mainboard(ptr);
194  			break;
195  		case CB_TAG_VERSION:
196  		case CB_TAG_EXTRA_VERSION:
197  		case CB_TAG_BUILD:
198  		case CB_TAG_COMPILE_TIME:
199  		case CB_TAG_COMPILE_BY:
200  		case CB_TAG_COMPILE_HOST:
201  		case CB_TAG_COMPILE_DOMAIN:
202  		case CB_TAG_COMPILER:
203  		case CB_TAG_LINKER:
204  		case CB_TAG_ASSEMBLER:
205  			parse_strings(ptr);
206  			break;
207  		case CB_TAG_SERIAL:
208  			parse_serial(ptr);
209  			break;
210  		case CB_TAG_CONSOLE:
211  			parse_console(ptr);
212  			break;
213  		default:
214  			break;
215  		}
216  
217  		ptr += rec->size;
218  	}
219  
220  	return 1;
221  }
222  
223  static int coreboot_module_init(void)
224  {
225  	int ret = parse_header((void *)0x00000, 0x1000);
226  
227  	if (ret != 1)
228  		ret = parse_header((void *)0xf0000, 0x1000);
229  
230  	/* Return error if we couldn't find it at either address. */
231  	tables_good = (ret == 1) ? 0 : -1;
232  	return tables_good;
233  }
234  
235  struct coreinfo_module coreboot_module = {
236  	.name = "coreboot",
237  	.init = coreboot_module_init,
238  	.redraw = coreboot_module_redraw,
239  };
240  
241  #else
242  
243  struct coreinfo_module coreboot_module = {
244  };
245  
246  #endif