1 /*
2 * Copyright (c) 2026 Abdelkader Boudih <freebsd@seuros.com>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7 /*
8 * coreboot(4) driver for FreeBSD
9 *
10 * Structures and constants derived from the coreboot table specification.
11 */
12
13 #ifndef _DEV_COREBOOT_COREBOOT_H_
14 #define _DEV_COREBOOT_COREBOOT_H_
15
16 #include <sys/types.h>
17 #include <sys/conf.h>
18 #include <sys/sysctl.h>
19 #include <sys/bus.h>
20
21 #include <dev/coreboot/corebootio.h>
22
23 #define CB_HEADER_SIGNATURE "LBIO"
24 #define CB_HEADER_SIG_LEN 4
25
26 /*
27 * Memory scan range for coreboot table discovery.
28 * Low memory (0x0–0x1000) contains a forward pointer to the real table.
29 */
30 #define CB_SCAN_LOW_START 0x00000000
31 #define CB_SCAN_LOW_END 0x00001000
32 #define CB_SCAN_LOW_STEP 16
33
34 /*
35 * Defensive limits for parsing untrusted firmware-provided lengths.
36 */
37 #define CB_TABLE_ALIGN 4
38 #define CB_MAX_HEADER_BYTES 4096
39 #define CB_MAX_TABLE_BYTES (1024 * 1024)
40 #define CB_MAX_TABLE_MAP_BYTES (CB_MAX_HEADER_BYTES + CB_MAX_TABLE_BYTES)
41 #define CB_MAX_CONSOLE_BYTES (1024 * 1024)
42
43 /*
44 * Coreboot table record tags - only tags we actually parse.
45 * Full enum preserved for forward compatibility (unknown tags are skipped).
46 */
47 enum cb_tag {
48 CB_TAG_UNUSED = 0x0000,
49 CB_TAG_MAINBOARD = 0x0003,
50 CB_TAG_VERSION = 0x0004,
51 CB_TAG_EXTRA_VERSION = 0x0005,
52 CB_TAG_BUILD = 0x0006,
53 CB_TAG_COMPILE_TIME = 0x0007,
54 CB_TAG_COMPILER = 0x000b,
55 CB_TAG_SERIAL = 0x000f,
56 CB_TAG_CONSOLE = 0x0010,
57 CB_TAG_FORWARD = 0x0011,
58 CB_TAG_FRAMEBUFFER = 0x0012,
59 CB_TAG_GPIO = 0x0013,
60 CB_TAG_TIMESTAMPS = 0x0016,
61 CB_TAG_CBMEM_CONSOLE = 0x0017,
62 CB_TAG_ACPI_GNVS = 0x0024,
63 CB_TAG_VERSION_TIMESTAMP = 0x0026,
64 CB_TAG_WIFI_CALIBRATION = 0x0027,
65 CB_TAG_SPI_FLASH = 0x0029,
66 CB_TAG_SERIALNO = 0x002a,
67 CB_TAG_VPD = 0x002c,
68 CB_TAG_BOOT_MEDIA_PARAMS = 0x0030,
69 CB_TAG_CBMEM_ENTRY = 0x0031,
70 CB_TAG_TSC_INFO = 0x0032,
71 CB_TAG_MAC_ADDRS = 0x0033,
72 CB_TAG_VBOOT_WORKBUF = 0x0034,
73 CB_TAG_MMC_INFO = 0x0035,
74 CB_TAG_TPM_CB_LOG = 0x0036,
75 CB_TAG_FMAP = 0x0037,
76 CB_TAG_PLATFORM_BLOB_VERSION = 0x0038,
77 CB_TAG_SMMSTOREV2 = 0x0039,
78 CB_TAG_TPM_PPI_HANDOFF = 0x003a,
79 CB_TAG_BOARD_CONFIG = 0x0040,
80 CB_TAG_ACPI_CNVS = 0x0041,
81 CB_TAG_TYPE_C_INFO = 0x0042,
82 CB_TAG_ACPI_RSDP = 0x0043,
83 CB_TAG_PCIE = 0x0044,
84 CB_TAG_ROOT_BRIDGE_INFO = 0x0048,
85 };
86
87 /*
88 * Coreboot table header - located at a physical address found by scanning
89 * low memory for the "LBIO" signature.
90 */
91 struct cb_header {
92 uint8_t signature[CB_HEADER_SIG_LEN];
93 uint32_t header_bytes;
94 uint32_t header_checksum;
95 uint32_t table_bytes;
96 uint32_t table_checksum;
97 uint32_t table_entries;
98 } __packed;
99
100 /*
101 * Generic record header - every table entry starts with this.
102 */
103 struct cb_record {
104 uint32_t tag;
105 uint32_t size;
106 } __packed;
107
108 /*
109 * CB_TAG_FORWARD - pointer to the real table in high memory.
110 */
111 struct cb_forward {
112 uint32_t tag;
113 uint32_t size;
114 uint64_t forward;
115 } __packed;
116
117 /*
118 * CB_TAG_MAINBOARD - board vendor and part number.
119 * Strings are packed after the struct, indexed by vendor_idx and part_idx.
120 */
121 struct cb_mainboard {
122 uint32_t tag;
123 uint32_t size;
124 uint8_t vendor_idx;
125 uint8_t part_idx;
126 uint8_t strings[];
127 } __packed;
128
129 /*
130 * Variable-length string record - used by VERSION, BUILD, COMPILE_*, etc.
131 */
132 struct cb_string {
133 uint32_t tag;
134 uint32_t size;
135 uint8_t string[];
136 } __packed;
137
138 /*
139 * CB_TAG_SERIAL - serial port configuration.
140 */
141 struct cb_serial {
142 uint32_t tag;
143 uint32_t size;
144 uint32_t type;
145 uint32_t baseaddr;
146 uint32_t baud;
147 uint32_t regwidth;
148 uint32_t input_hertz;
149 } __packed;
150
151 /*
152 * CB_TAG_CBMEM_CONSOLE - pointer to firmware console ring buffer.
153 */
154 struct cb_cbmem_ref {
155 uint32_t tag;
156 uint32_t size;
157 uint64_t cbmem_addr;
158 } __packed;
159
160 /*
161 * CB_TAG_CBMEM_ENTRY - one per CBMEM region.
162 */
163 struct cb_cbmem_entry {
164 uint32_t tag;
165 uint32_t size;
166 uint64_t address;
167 uint32_t entry_size;
168 uint32_t id;
169 } __packed;
170
171 /*
172 * CB_TAG_TSC_INFO - TSC frequency.
173 */
174 struct cb_tsc_info {
175 uint32_t tag;
176 uint32_t size;
177 uint32_t freq_khz;
178 } __packed;
179
180 /*
181 * CB_TAG_VERSION_TIMESTAMP - build version timestamp.
182 * timestamp is Unix time in seconds (seconds since 1970-01-01 UTC).
183 */
184 struct cb_version_timestamp {
185 uint32_t tag;
186 uint32_t size;
187 uint32_t timestamp;
188 } __packed;
189
190 /*
191 * CB_TAG_BOARD_CONFIG - board identification and firmware config.
192 */
193 struct cb_board_config {
194 uint32_t tag;
195 uint32_t size;
196 uint64_t fw_config;
197 uint32_t board_id;
198 uint32_t ram_code;
199 uint32_t sku_id;
200 } __packed;
201
202 /*
203 * CB_TAG_BOOT_MEDIA_PARAMS - offsets and sizes on boot media.
204 */
205 struct cb_boot_media_params {
206 uint32_t tag;
207 uint32_t size;
208 uint64_t fmap_offset;
209 uint64_t cbfs_offset;
210 uint64_t cbfs_size;
211 uint64_t boot_media_size;
212 } __packed;
213
214 /*
215 * CB_TAG_MMC_INFO - early eMMC/MMC status.
216 */
217 struct cb_mmc_info {
218 uint32_t tag;
219 uint32_t size;
220 int32_t early_cmd1_status;
221 } __packed;
222
223 /*
224 * CB_TAG_PCIE - PCIe controller base address.
225 */
226 struct cb_pcie {
227 uint32_t tag;
228 uint32_t size;
229 uint64_t ctrl_base;
230 } __packed;
231
232 /*
233 * CB_TAG_MAC_ADDRS - factory-provisioned MAC addresses.
234 */
235 struct cb_mac_address {
236 uint8_t mac_addr[6];
237 uint8_t pad[2];
238 } __packed;
239
240 struct cb_macs {
241 uint32_t tag;
242 uint32_t size;
243 uint32_t count;
244 struct cb_mac_address entries[];
245 } __packed;
246
247 /*
248 * CB_TAG_SPI_FLASH - SPI flash chip parameters.
249 */
250 struct cb_flash_mmap_window {
251 uint32_t flash_base;
252 uint32_t host_base;
253 uint32_t size;
254 } __packed;
255
256 struct cb_spi_flash {
257 uint32_t tag;
258 uint32_t size;
259 uint32_t flash_size;
260 uint32_t sector_size;
261 uint8_t erase_cmd;
262 uint8_t flags;
263 uint16_t reserved;
264 uint32_t mmap_count;
265 struct cb_flash_mmap_window mmap_table[];
266 } __packed;
267
268 /*
269 * CB_TAG_CONSOLE - firmware console type.
270 */
271 struct cb_console {
272 uint32_t tag;
273 uint32_t size;
274 uint16_t type;
275 uint8_t pad[2];
276 } __packed;
277
278 #define CB_CONSOLE_SERIAL8250 0
279 #define CB_CONSOLE_VGA 1 /* obsolete */
280 #define CB_CONSOLE_EHCI 5
281 #define CB_CONSOLE_SERIAL8250MEM 6
282
283 /*
284 * CB_TAG_FRAMEBUFFER - linear framebuffer info.
285 * The orientation, flags, and pad fields were added later.
286 * Minimum record size is up to reserved_mask_size (29 bytes).
287 */
288 #define CB_FRAMEBUFFER_MIN_SIZE 29
289 struct cb_framebuffer {
290 uint32_t tag;
291 uint32_t size;
292 uint64_t physical_address;
293 uint32_t x_resolution;
294 uint32_t y_resolution;
295 uint32_t bytes_per_line;
296 uint8_t bits_per_pixel;
297 uint8_t red_mask_pos;
298 uint8_t red_mask_size;
299 uint8_t green_mask_pos;
300 uint8_t green_mask_size;
301 uint8_t blue_mask_pos;
302 uint8_t blue_mask_size;
303 uint8_t reserved_mask_pos;
304 uint8_t reserved_mask_size;
305 uint8_t orientation;
306 uint8_t flags;
307 uint8_t pad;
308 } __packed;
309
310 /*
311 * CB_TAG_GPIO - GPIO pin states.
312 */
313 struct cb_gpio {
314 uint32_t port;
315 uint32_t polarity;
316 uint32_t value;
317 uint8_t name[16];
318 } __packed;
319
320 struct cb_gpios {
321 uint32_t tag;
322 uint32_t size;
323 uint32_t count;
324 struct cb_gpio entries[];
325 } __packed;
326
327 /*
328 * CB_TAG_TPM_PPI_HANDOFF - TPM Physical Presence Interface handoff.
329 */
330 struct cb_tpm_ppi {
331 uint32_t tag;
332 uint32_t size;
333 uint32_t ppi_address;
334 uint8_t tpm_version; /* 1=TPM1.2, 2=TPM2.0 */
335 uint8_t ppi_version; /* BCD encoded */
336 uint8_t pad[2];
337 } __packed;
338
339 /*
340 * CB_TAG_SMMSTOREV2 - SMM-based variable store configuration.
341 *
342 * The mmap_addr field was added after the initial implementation.
343 * Older coreboot emits a shorter record (32 bytes) without it.
344 * Consumers must check rec->size to detect whether mmap_addr is present.
345 */
346 #define CB_SMMSTOREV2_BASE_SIZE 32 /* size without mmap_addr */
347 struct cb_smmstorev2 {
348 uint32_t tag;
349 uint32_t size;
350 uint32_t num_blocks;
351 uint32_t block_size;
352 uint32_t mmap_addr_lo; /* deprecated 32-bit address */
353 uint32_t com_buffer;
354 uint32_t com_buffer_size;
355 uint8_t apm_cmd;
356 uint8_t unused[3];
357 /* Fields below only present if size > CB_SMMSTOREV2_BASE_SIZE */
358 uint64_t mmap_addr; /* 64-bit address (preferred) */
359 } __packed;
360
361 /*
362 * CB_TAG_ACPI_RSDP - ACPI Root System Description Pointer address.
363 */
364 struct cb_acpi_rsdp {
365 uint32_t tag;
366 uint32_t size;
367 uint64_t rsdp_pointer;
368 } __packed;
369
370 /*
371 * CBMEM console ring buffer (in-memory structure at cbmem_addr).
372 * Bit 31 of cursor indicates overflow (ring has wrapped).
373 */
374 struct cbmem_console {
375 uint32_t size;
376 uint32_t cursor;
377 uint8_t body[];
378 } __packed;
379
380 #define CBMEM_CONSOLE_CURSOR_MASK ((1 << 28) - 1)
381 #define CBMEM_CONSOLE_OVERFLOW (1 << 31)
382
383 #define CB_MAX_MAC_ADDRS 8
384 #define CB_MAX_GPIOS 32
385
386 /*
387 * Driver softc
388 */
389 struct coreboot_softc {
390 device_t dev;
391
392 vm_paddr_t table_paddr;
393 vm_size_t table_size;
394 void *table_vaddr;
395
396 char version[64];
397 char build[64];
398 char compile_time[64];
399 char compiler[128];
400 char extra_version[64];
401 char platform_blob_version[64];
402 char serialno[64];
403 uint32_t version_timestamp;
404 int has_version_timestamp;
405
406 char mb_vendor[64];
407 char mb_part[64];
408
409 uint32_t serial_baseaddr;
410 uint32_t serial_baud;
411 uint32_t serial_regwidth;
412 int has_serial;
413
414 uint32_t tsc_freq_khz;
415 int has_tsc_info;
416
417 uint64_t pcie_ctrl_base;
418 int has_pcie;
419
420 uint64_t fmap_offset;
421 uint64_t cbfs_offset;
422 uint64_t cbfs_size;
423 uint64_t boot_media_size;
424 int has_boot_media;
425
426 int32_t mmc_early_cmd1_status;
427 int has_mmc_info;
428
429 vm_paddr_t console_paddr;
430 vm_size_t console_size;
431 uint32_t console_data_size;
432 struct cbmem_console *console_vaddr;
433 int has_console;
434 struct cdev *console_cdev;
435
436 uint32_t cbmem_count;
437 struct cbmem_entry_info cbmem_entries[CB_MAX_CBMEM_ENTRIES];
438 struct cdev *cbmem_cdev;
439
440 uint64_t fw_config;
441 uint32_t board_id;
442 uint32_t ram_code;
443 uint32_t sku_id;
444 int has_board_config;
445
446 uint32_t mac_count;
447 struct cb_mac_address macs[CB_MAX_MAC_ADDRS];
448 char mac_strs[CB_MAX_MAC_ADDRS][18];
449
450 uint64_t acpi_rsdp;
451 int has_acpi_rsdp;
452
453 uint32_t spi_flash_size;
454 uint32_t spi_sector_size;
455 uint8_t spi_erase_cmd;
456 uint8_t spi_flags;
457 int has_spi_flash;
458
459 uint16_t console_type;
460 int has_console_type;
461
462 uint64_t fb_addr;
463 uint32_t fb_x_res;
464 uint32_t fb_y_res;
465 uint32_t fb_stride;
466 uint8_t fb_bpp;
467 int has_framebuffer;
468
469 uint32_t gpio_count;
470 struct cb_gpio gpios[CB_MAX_GPIOS];
471
472 uint32_t tpm_ppi_addr;
473 uint8_t tpm_version;
474 int has_tpm;
475
476 vm_paddr_t tpm_log_paddr;
477 int has_tpm_log;
478
479 vm_paddr_t acpi_gnvs_paddr;
480 int has_acpi_gnvs;
481 vm_paddr_t acpi_cnvs_paddr;
482 int has_acpi_cnvs;
483 vm_paddr_t vpd_paddr;
484 int has_vpd;
485 vm_paddr_t wifi_cal_paddr;
486 int has_wifi_cal;
487 vm_paddr_t fmap_paddr;
488 int has_fmap;
489 vm_paddr_t vboot_workbuf_paddr;
490 int has_vboot_workbuf;
491 vm_paddr_t type_c_info_paddr;
492 int has_type_c_info;
493 vm_paddr_t root_bridge_info_paddr;
494 int has_root_bridge_info;
495
496 uint32_t smmstore_num_blocks;
497 uint32_t smmstore_block_size;
498 uint64_t smmstore_mmap_addr;
499 uint32_t smmstore_com_buffer;
500 uint8_t smmstore_apm_cmd;
501 int has_smmstore;
502
503 vm_paddr_t timestamps_paddr;
504 int has_timestamps;
505
506 struct sysctl_ctx_list sysctl_ctx;
507 struct sysctl_oid *sysctl_tree;
508 };
509
510 /*
511 * Generic ID-to-name linear search.
512 * The table must be terminated by an entry with name == NULL.
513 * Returns fallback if no match is found.
514 */
515 struct cb_id_name {
516 uint32_t id;
517 const char *name;
518 };
519
520 static __inline const char *
cb_id_lookup(const struct cb_id_name * tbl,uint32_t id,const char * fallback)521 cb_id_lookup(const struct cb_id_name *tbl, uint32_t id, const char *fallback)
522 {
523 int i;
524
525 for (i = 0; tbl[i].name != NULL; i++) {
526 if (tbl[i].id == id)
527 return (tbl[i].name);
528 }
529 return (fallback);
530 }
531
532 /*
533 * CBMEM ID to human-readable name lookup.
534 */
535 static __inline const char *
cbmem_id_to_name(uint32_t id)536 cbmem_id_to_name(uint32_t id)
537 {
538 static const struct cb_id_name names[] = {
539 { CBMEM_ID_ACPI, "ACPI" },
540 { CBMEM_ID_ACPI_GNVS, "ACPI GNVS" },
541 { CBMEM_ID_AFTER_CAR, "AFTER CAR" },
542 { CBMEM_ID_CBTABLE, "COREBOOT" },
543 { CBMEM_ID_CBTABLE_FWD, "COREBOOT FWD" },
544 { CBMEM_ID_CBFS_RO_MCACHE, "RO MCACHE" },
545 { CBMEM_ID_CBFS_RW_MCACHE, "RW MCACHE" },
546 { CBMEM_ID_CONSOLE, "CONSOLE" },
547 { CBMEM_ID_ELOG, "ELOG" },
548 { CBMEM_ID_FMAP, "FMAP" },
549 { CBMEM_ID_FREESPACE, "FREE SPACE" },
550 { CBMEM_ID_FSP_RESERVED_MEMORY, "FSP MEMORY" },
551 { CBMEM_ID_FSP_RUNTIME, "FSP RUNTIME" },
552 { CBMEM_ID_FSPM_VERSION, "FSPM VERSION" },
553 { CBMEM_ID_IGD_OPREGION, "IGD OPREGION" },
554 { CBMEM_ID_IMD_ROOT, "IMD ROOT" },
555 { CBMEM_ID_IMD_SMALL, "IMD SMALL" },
556 { CBMEM_ID_MEMINFO, "MEM INFO" },
557 { CBMEM_ID_MPTABLE, "SMP TABLE" },
558 { CBMEM_ID_MRCDATA, "MRC DATA" },
559 { CBMEM_ID_PIRQ, "IRQ TABLE" },
560 { CBMEM_ID_POWER_STATE, "POWER STATE" },
561 { CBMEM_ID_RAM_OOPS, "RAMOOPS" },
562 { CBMEM_ID_RAMSTAGE, "RAMSTAGE" },
563 { CBMEM_ID_REFCODE, "REFCODE" },
564 { CBMEM_ID_RESUME, "ACPI RESUME" },
565 { CBMEM_ID_ROMSTAGE_INFO, "ROMSTAGE" },
566 { CBMEM_ID_ROMSTAGE_RAM_STACK, "ROMSTG STACK" },
567 { CBMEM_ID_ROOT, "CBMEM ROOT" },
568 { CBMEM_ID_SMBIOS, "SMBIOS" },
569 { CBMEM_ID_SMM_COMBUFFER, "SMM COMBUF" },
570 { CBMEM_ID_SMM_SAVE_SPACE, "SMM BACKUP" },
571 { CBMEM_ID_TIMESTAMP, "TIMESTAMP" },
572 { CBMEM_ID_VBOOT_WORKBUF, "VBOOT WORK" },
573 { CBMEM_ID_VPD, "VPD" },
574 { 0, NULL }
575 };
576
577 return (cb_id_lookup(names, id, "UNKNOWN"));
578 }
579
580 /*
581 * IP-style 16-bit checksum (RFC 1071) over 16-bit words.
582 * When computed over data including its checksum field, result is 0.
583 */
584 static __inline uint16_t
cb_checksum(const void * ptr,size_t len)585 cb_checksum(const void *ptr, size_t len)
586 {
587 const uint8_t *p = (const uint8_t *)ptr;
588 uint32_t sum = 0;
589 size_t i;
590
591 for (i = 0; i + 1 < len; i += 2)
592 sum += (uint32_t)p[i] | ((uint32_t)p[i + 1] << 8);
593
594 if (i < len)
595 sum += p[i];
596
597 while (sum >> 16)
598 sum = (sum & 0xffff) + (sum >> 16);
599
600 return ((uint16_t)~sum);
601 }
602
603 /*
604 * Destroy a character device and clear the pointer.
605 * Safe to call with a NULL cdev pointer.
606 */
607 static __inline void
coreboot_cdev_destroy(struct cdev ** cdevp)608 coreboot_cdev_destroy(struct cdev **cdevp)
609 {
610
611 if (*cdevp != NULL) {
612 destroy_dev(*cdevp);
613 *cdevp = NULL;
614 }
615 }
616
617 /* Functions exported from coreboot.c */
618 struct coreboot_softc *coreboot_get_softc(void);
619
620 /* Functions exported from coreboot_console.c */
621 int coreboot_console_create(struct coreboot_softc *sc);
622 void coreboot_console_destroy(struct coreboot_softc *sc);
623
624 /* Functions exported from coreboot_cbmem.c */
625 int coreboot_cbmem_create(struct coreboot_softc *sc);
626 void coreboot_cbmem_destroy(struct coreboot_softc *sc);
627
628 /* Functions exported from coreboot_timestamps.c */
629 int coreboot_timestamps_register(struct coreboot_softc *sc,
630 struct sysctl_oid *parent);
631
632 #endif /* _DEV_COREBOOT_COREBOOT_H_ */
633