1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <arch/cbconfig.h>
4 #include <console/console.h>
5 #include <console/uart.h>
6 #include <ip_checksum.h>
7 #include <boot/coreboot_tables.h>
8 #include <boot/tables.h>
9 #include <boot_device.h>
13 #include <device/device.h>
15 #include <fw_config.h>
20 #include <bootsplash.h>
21 #include <spi_flash.h>
22 #include <security/vboot/misc.h>
23 #include <security/vboot/vbnv_layout.h>
26 #if CONFIG(USE_OPTION_TABLE)
27 #include <option_table.h>
30 #if CONFIG(HAVE_ACPI_TABLES)
31 #include <acpi/acpi.h>
33 #include <vendorcode/google/chromeos/chromeos.h>
34 #include <vendorcode/google/chromeos/gnvs.h>
36 #if CONFIG(PLATFORM_USES_FSP2_0)
39 void lb_string_platform_blob_version(struct lb_header
*header
);
42 static struct lb_header
*lb_table_init(unsigned long addr
)
44 struct lb_header
*header
;
46 /* 16 byte align the address */
50 header
= (void *)addr
;
51 header
->signature
[0] = 'L';
52 header
->signature
[1] = 'B';
53 header
->signature
[2] = 'I';
54 header
->signature
[3] = 'O';
55 header
->header_bytes
= sizeof(*header
);
56 header
->header_checksum
= 0;
57 header
->table_bytes
= 0;
58 header
->table_checksum
= 0;
59 header
->table_entries
= 0;
63 static struct lb_record
*lb_first_record(struct lb_header
*header
)
65 struct lb_record
*rec
;
66 rec
= (void *)(((char *)header
) + sizeof(*header
));
70 static struct lb_record
*lb_last_record(struct lb_header
*header
)
72 struct lb_record
*rec
;
73 rec
= (void *)(((char *)header
) + sizeof(*header
)
74 + header
->table_bytes
);
78 struct lb_record
*lb_new_record(struct lb_header
*header
)
80 struct lb_record
*rec
;
81 rec
= lb_last_record(header
);
82 if (header
->table_entries
)
83 header
->table_bytes
+= rec
->size
;
84 rec
= lb_last_record(header
);
85 header
->table_entries
++;
86 rec
->tag
= LB_TAG_UNUSED
;
87 rec
->size
= sizeof(*rec
);
91 static struct lb_memory
*lb_memory(struct lb_header
*header
)
93 struct lb_record
*rec
;
94 struct lb_memory
*mem
;
95 rec
= lb_new_record(header
);
96 mem
= (struct lb_memory
*)rec
;
97 mem
->tag
= LB_TAG_MEMORY
;
98 mem
->size
= sizeof(*mem
);
102 void lb_add_serial(struct lb_serial
*new_serial
, void *data
)
104 struct lb_header
*header
= (struct lb_header
*)data
;
105 struct lb_serial
*serial
;
107 serial
= (struct lb_serial
*)lb_new_record(header
);
108 serial
->tag
= LB_TAG_SERIAL
;
109 serial
->size
= sizeof(*serial
);
110 serial
->type
= new_serial
->type
;
111 serial
->baseaddr
= new_serial
->baseaddr
;
112 serial
->baud
= new_serial
->baud
;
113 serial
->regwidth
= new_serial
->regwidth
;
114 serial
->input_hertz
= new_serial
->input_hertz
;
115 serial
->uart_pci_addr
= new_serial
->uart_pci_addr
;
118 void lb_add_console(uint16_t consoletype
, void *data
)
120 struct lb_header
*header
= (struct lb_header
*)data
;
121 struct lb_console
*console
;
123 console
= (struct lb_console
*)lb_new_record(header
);
124 console
->tag
= LB_TAG_CONSOLE
;
125 console
->size
= sizeof(*console
);
126 console
->type
= consoletype
;
129 static void lb_framebuffer(struct lb_header
*header
)
131 struct lb_framebuffer
*framebuffer
;
132 struct lb_framebuffer fb
= {0};
134 if (!CONFIG(LINEAR_FRAMEBUFFER
) || fill_lb_framebuffer(&fb
))
137 framebuffer
= (struct lb_framebuffer
*)lb_new_record(header
);
138 memcpy(framebuffer
, &fb
, sizeof(*framebuffer
));
139 framebuffer
->tag
= LB_TAG_FRAMEBUFFER
;
140 framebuffer
->size
= sizeof(*framebuffer
);
142 if (CONFIG(BOOTSPLASH
)) {
143 uint8_t *fb_ptr
= (uint8_t *)(uintptr_t)framebuffer
->physical_address
;
144 unsigned int width
= framebuffer
->x_resolution
;
145 unsigned int height
= framebuffer
->y_resolution
;
146 unsigned int depth
= framebuffer
->bits_per_pixel
;
147 set_bootsplash(fb_ptr
, width
, height
, depth
);
151 void lb_add_gpios(struct lb_gpios
*gpios
, const struct lb_gpio
*gpio_table
,
154 size_t table_size
= count
* sizeof(struct lb_gpio
);
156 memcpy(&gpios
->gpios
[gpios
->count
], gpio_table
, table_size
);
157 gpios
->count
+= count
;
158 gpios
->size
+= table_size
;
162 static void lb_gpios(struct lb_header
*header
)
164 struct lb_gpios
*gpios
;
167 gpios
= (struct lb_gpios
*)lb_new_record(header
);
168 gpios
->tag
= LB_TAG_GPIO
;
169 gpios
->size
= sizeof(*gpios
);
171 fill_lb_gpios(gpios
);
173 printk(BIOS_INFO
, "Passing %u GPIOs to payload:\n"
174 " NAME | PORT | POLARITY | VALUE\n",
176 for (g
= &gpios
->gpios
[0]; g
< &gpios
->gpios
[gpios
->count
]; g
++) {
177 printk(BIOS_INFO
, "%16s | ", g
->name
);
179 printk(BIOS_INFO
, " undefined | ");
181 printk(BIOS_INFO
, "%#.8x | ", g
->port
);
182 if (g
->polarity
== ACTIVE_HIGH
)
183 printk(BIOS_INFO
, " high | ");
185 printk(BIOS_INFO
, " low | ");
188 printk(BIOS_INFO
, " low\n");
191 printk(BIOS_INFO
, " high\n");
194 printk(BIOS_INFO
, "undefined\n");
200 static void lb_vbnv(struct lb_header
*header
)
202 #if CONFIG(PC80_SYSTEM)
203 struct lb_range
*vbnv
;
205 vbnv
= (struct lb_range
*)lb_new_record(header
);
206 vbnv
->tag
= LB_TAG_VBNV
;
207 vbnv
->size
= sizeof(*vbnv
);
208 vbnv
->range_start
= CONFIG_VBOOT_VBNV_OFFSET
+ 14;
209 vbnv
->range_size
= VBOOT_VBNV_BLOCK_SIZE
;
212 #endif /* CONFIG_CHROMEOS */
214 __weak
uint32_t board_id(void) { return UNDEFINED_STRAPPING_ID
; }
215 __weak
uint32_t ram_code(void) { return UNDEFINED_STRAPPING_ID
; }
216 __weak
uint32_t sku_id(void) { return UNDEFINED_STRAPPING_ID
; }
217 __weak
uint64_t fw_config_get(void) { return UNDEFINED_FW_CONFIG
; }
219 static void lb_boot_media_params(struct lb_header
*header
)
221 struct lb_boot_media_params
*bmp
;
222 const struct region_device
*boot_dev
;
223 struct region_device cbfs_dev
;
227 if (cbfs_boot_region_device(&cbfs_dev
))
230 boot_dev
= boot_device_ro();
231 if (boot_dev
== NULL
)
234 bmp
= (struct lb_boot_media_params
*)lb_new_record(header
);
235 bmp
->tag
= LB_TAG_BOOT_MEDIA_PARAMS
;
236 bmp
->size
= sizeof(*bmp
);
238 bmp
->cbfs_offset
= region_device_offset(&cbfs_dev
);
239 bmp
->cbfs_size
= region_device_sz(&cbfs_dev
);
240 bmp
->boot_media_size
= region_device_sz(boot_dev
);
242 bmp
->fmap_offset
= get_fmap_flash_offset();
245 static void lb_mmc_info(struct lb_header
*header
)
247 struct lb_mmc_info
*rec
;
250 ms_cbmem
= cbmem_find(CBMEM_ID_MMC_STATUS
);
254 rec
= (struct lb_mmc_info
*)lb_new_record(header
);
256 rec
->tag
= LB_TAG_MMC_INFO
;
257 rec
->size
= sizeof(*rec
);
258 rec
->early_cmd1_status
= *ms_cbmem
;
261 static void add_cbmem_pointers(struct lb_header
*header
)
264 * These CBMEM sections' addresses are included in the coreboot table
265 * with the appropriate tags.
267 const struct section_id
{
271 {CBMEM_ID_TIMESTAMP
, LB_TAG_TIMESTAMPS
},
272 {CBMEM_ID_CONSOLE
, LB_TAG_CBMEM_CONSOLE
},
273 {CBMEM_ID_ACPI_GNVS
, LB_TAG_ACPI_GNVS
},
274 {CBMEM_ID_VPD
, LB_TAG_VPD
},
275 {CBMEM_ID_WIFI_CALIBRATION
, LB_TAG_WIFI_CALIBRATION
},
276 {CBMEM_ID_TCPA_LOG
, LB_TAG_TCPA_LOG
},
277 {CBMEM_ID_FMAP
, LB_TAG_FMAP
},
278 {CBMEM_ID_VBOOT_WORKBUF
, LB_TAG_VBOOT_WORKBUF
},
282 for (i
= 0; i
< ARRAY_SIZE(section_ids
); i
++) {
283 const struct section_id
*sid
= section_ids
+ i
;
284 struct lb_cbmem_ref
*cbmem_ref
;
285 void *cbmem_addr
= cbmem_find(sid
->cbmem_id
);
288 continue; /* This section is not present */
290 cbmem_ref
= (struct lb_cbmem_ref
*)lb_new_record(header
);
292 printk(BIOS_ERR
, "No more room in coreboot table!\n");
295 cbmem_ref
->tag
= sid
->table_tag
;
296 cbmem_ref
->size
= sizeof(*cbmem_ref
);
297 cbmem_ref
->cbmem_addr
= (unsigned long)cbmem_addr
;
301 static struct lb_mainboard
*lb_mainboard(struct lb_header
*header
)
303 struct lb_record
*rec
;
304 struct lb_mainboard
*mainboard
;
305 rec
= lb_new_record(header
);
306 mainboard
= (struct lb_mainboard
*)rec
;
307 mainboard
->tag
= LB_TAG_MAINBOARD
;
309 mainboard
->size
= ALIGN_UP(sizeof(*mainboard
) +
310 strlen(mainboard_vendor
) + 1 +
311 strlen(mainboard_part_number
) + 1, 8);
313 mainboard
->vendor_idx
= 0;
314 mainboard
->part_number_idx
= strlen(mainboard_vendor
) + 1;
316 memcpy(mainboard
->strings
+ mainboard
->vendor_idx
,
317 mainboard_vendor
, strlen(mainboard_vendor
) + 1);
318 memcpy(mainboard
->strings
+ mainboard
->part_number_idx
,
319 mainboard_part_number
, strlen(mainboard_part_number
) + 1);
324 static struct lb_board_config
*lb_board_config(struct lb_header
*header
)
326 struct lb_record
*rec
;
327 struct lb_board_config
*config
;
328 rec
= lb_new_record(header
);
329 config
= (struct lb_board_config
*)rec
;
331 config
->tag
= LB_TAG_BOARD_CONFIG
;
332 config
->size
= sizeof(*config
);
334 config
->board_id
= board_id();
335 config
->ram_code
= ram_code();
336 config
->sku_id
= sku_id();
337 config
->fw_config
= pack_lb64(fw_config_get());
342 #if CONFIG(USE_OPTION_TABLE)
343 static struct cmos_checksum
*lb_cmos_checksum(struct lb_header
*header
)
345 struct lb_record
*rec
;
346 struct cmos_checksum
*cmos_checksum
;
347 rec
= lb_new_record(header
);
348 cmos_checksum
= (struct cmos_checksum
*)rec
;
349 cmos_checksum
->tag
= LB_TAG_OPTION_CHECKSUM
;
351 cmos_checksum
->size
= (sizeof(*cmos_checksum
));
353 cmos_checksum
->range_start
= LB_CKS_RANGE_START
* 8;
354 cmos_checksum
->range_end
= (LB_CKS_RANGE_END
* 8) + 7;
355 cmos_checksum
->location
= LB_CKS_LOC
* 8;
356 cmos_checksum
->type
= CHECKSUM_PCBIOS
;
358 return cmos_checksum
;
362 static void lb_strings(struct lb_header
*header
)
364 static const struct {
368 { LB_TAG_VERSION
, coreboot_version
, },
369 { LB_TAG_EXTRA_VERSION
, coreboot_extra_version
, },
370 { LB_TAG_BUILD
, coreboot_build
, },
371 { LB_TAG_COMPILE_TIME
, coreboot_compile_time
, },
374 for (i
= 0; i
< ARRAY_SIZE(strings
); i
++) {
375 struct lb_string
*rec
;
377 rec
= (struct lb_string
*)lb_new_record(header
);
378 len
= strlen(strings
[i
].string
);
379 rec
->tag
= strings
[i
].tag
;
380 rec
->size
= ALIGN_UP(sizeof(*rec
) + len
+ 1, 8);
381 memcpy(rec
->string
, strings
[i
].string
, len
+1);
386 static void lb_record_version_timestamp(struct lb_header
*header
)
388 struct lb_timestamp
*rec
;
389 rec
= (struct lb_timestamp
*)lb_new_record(header
);
390 rec
->tag
= LB_TAG_VERSION_TIMESTAMP
;
391 rec
->size
= sizeof(*rec
);
392 rec
->timestamp
= coreboot_version_timestamp
;
395 void __weak
lb_board(struct lb_header
*header
) { /* NOOP */ }
398 * It's possible that the system is using a SPI flash as the boot device,
399 * however it is not probing for devices to fill in specifics. In that
400 * case don't provide any information as the correct information is
403 void __weak
lb_spi_flash(struct lb_header
*header
) { /* NOOP */ }
405 static struct lb_forward
*lb_forward(struct lb_header
*header
,
406 struct lb_header
*next_header
)
408 struct lb_record
*rec
;
409 struct lb_forward
*forward
;
410 rec
= lb_new_record(header
);
411 forward
= (struct lb_forward
*)rec
;
412 forward
->tag
= LB_TAG_FORWARD
;
413 forward
->size
= sizeof(*forward
);
414 forward
->forward
= (uint64_t)(unsigned long)next_header
;
418 static unsigned long lb_table_fini(struct lb_header
*head
)
420 struct lb_record
*rec
, *first_rec
;
421 rec
= lb_last_record(head
);
422 if (head
->table_entries
)
423 head
->table_bytes
+= rec
->size
;
425 first_rec
= lb_first_record(head
);
426 head
->table_checksum
= compute_ip_checksum(first_rec
,
428 head
->header_checksum
= 0;
429 head
->header_checksum
= compute_ip_checksum(head
, sizeof(*head
));
431 "Wrote coreboot table at: %p, 0x%x bytes, checksum %x\n",
432 head
, head
->table_bytes
, head
->table_checksum
);
433 return (unsigned long)rec
+ rec
->size
;
436 size_t write_coreboot_forwarding_table(uintptr_t entry
, uintptr_t target
)
438 struct lb_header
*head
;
440 printk(BIOS_DEBUG
, "Writing table forward entry at %p\n",
443 head
= lb_table_init(entry
);
444 lb_forward(head
, (struct lb_header
*)target
);
446 return (uintptr_t)lb_table_fini(head
) - entry
;
449 static uintptr_t write_coreboot_table(uintptr_t rom_table_end
)
451 struct lb_header
*head
;
453 printk(BIOS_DEBUG
, "Writing coreboot table at 0x%08lx\n",
454 (long)rom_table_end
);
456 head
= lb_table_init(rom_table_end
);
458 #if CONFIG(USE_OPTION_TABLE)
460 struct cmos_option_table
*option_table
=
461 cbfs_boot_map_with_leak("cmos_layout.bin",
462 CBFS_COMPONENT_CMOS_LAYOUT
, NULL
);
464 struct lb_record
*rec_dest
= lb_new_record(head
);
465 /* Copy the option config table, it's already a
468 memcpy(rec_dest
, option_table
, option_table
->size
);
469 /* Create CMOS checksum entry in coreboot table */
470 lb_cmos_checksum(head
);
473 "cmos_layout.bin could not be found!\n");
478 /* Serialize resource map into mem table types (LB_MEM_*) */
479 bootmem_write_memory_table(lb_memory(head
));
481 /* Record our motherboard */
484 /* Record the serial ports and consoles */
485 #if CONFIG(CONSOLE_SERIAL)
488 #if CONFIG(CONSOLE_USB)
489 lb_add_console(LB_TAG_CONSOLE_EHCI
, head
);
492 /* Record our various random string information */
494 if (CONFIG(PLATFORM_USES_FSP2_0
))
495 lb_string_platform_blob_version(head
);
496 lb_record_version_timestamp(head
);
497 /* Record our framebuffer */
498 lb_framebuffer(head
);
501 /* Record our GPIO settings (ChromeOS specific) */
504 /* pass along VBNV offsets in CMOS */
508 /* Pass mmc early init status */
511 /* Add SPI flash description if available */
512 if (CONFIG(BOOT_DEVICE_SPI_FLASH
))
515 add_cbmem_pointers(head
);
518 if (CONFIG(SMMSTORE_V2
))
521 /* Add board-specific table entries, if any. */
524 #if CONFIG(CHROMEOS_RAMOOPS)
528 lb_boot_media_params(head
);
530 /* Board configuration information (including straps) */
531 lb_board_config(head
);
533 /* Add architecture records. */
534 lb_arch_add_records(head
);
536 /* Add all cbmem entries into the coreboot tables. */
537 cbmem_add_records_to_cbtable(head
);
539 /* Remember where my valid memory ranges are */
540 return lb_table_fini(head
);
543 void *write_tables(void)
545 uintptr_t cbtable_start
;
546 uintptr_t cbtable_end
;
548 const size_t max_table_size
= COREBOOT_TABLE_SIZE
;
550 cbtable_start
= (uintptr_t)cbmem_add(CBMEM_ID_CBTABLE
, max_table_size
);
552 if (!cbtable_start
) {
553 printk(BIOS_ERR
, "Could not add CBMEM for coreboot table.\n");
557 /* Add architecture specific tables. */
558 arch_write_tables(cbtable_start
);
560 /* Write the coreboot table. */
561 cbtable_end
= write_coreboot_table(cbtable_start
);
562 cbtable_size
= cbtable_end
- cbtable_start
;
564 if (cbtable_size
> max_table_size
) {
565 printk(BIOS_ERR
, "%s: coreboot table didn't fit (%zx/%zx)\n",
566 __func__
, cbtable_size
, max_table_size
);
569 printk(BIOS_DEBUG
, "coreboot table: %zd bytes.\n", cbtable_size
);
571 /* Print CBMEM sections */
573 return (void *)cbtable_start
;