soc/amd/sabrina,vc/amd/fsp/sabrina: Add UART support for Sabrina
[coreboot.git] / tests / lib / coreboot_table-test.c
blob2bf1f61da024fd8fb156d45444393c5c3d862e4e
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <tests/test.h>
4 #include <boardid.h>
5 #include <boot/coreboot_tables.h>
6 #include <boot/tables.h>
7 #include <cbfs.h>
8 #include <cbmem.h>
9 #include <commonlib/helpers.h>
10 #include <commonlib/region.h>
11 #include <fmap_config.h>
12 #include <fw_config.h>
13 #include <stdbool.h>
14 #include <version.h>
17 /* Copy of lb_table_init() implementation for testing purposes */
18 static struct lb_header *lb_table_init(unsigned long addr)
20 struct lb_header *header;
22 /* 16 byte align the address */
23 addr += 15;
24 addr &= ~15;
26 header = (void *)addr;
27 header->signature[0] = 'L';
28 header->signature[1] = 'B';
29 header->signature[2] = 'I';
30 header->signature[3] = 'O';
31 header->header_bytes = sizeof(*header);
32 header->header_checksum = 0;
33 header->table_bytes = 0;
34 header->table_checksum = 0;
35 header->table_entries = 0;
36 return header;
39 static struct lb_record *lb_first_record(struct lb_header *header)
41 struct lb_record *rec;
42 rec = (void *)(((char *)header) + sizeof(*header));
43 return rec;
46 #define LB_RECORD_FOR_EACH(record_ptr, index, header) \
47 for (index = 0, record_ptr = lb_first_record(header); index < header->table_entries; \
48 record_ptr = (struct lb_record *)((uintptr_t)record_ptr + record_ptr->size), \
49 index++)
51 static void test_lb_add_gpios(void **state)
53 struct lb_gpio gpios[] = {
54 {-1, ACTIVE_HIGH, 1, "lid"},
55 {-1, ACTIVE_HIGH, 0, "power"},
56 {-1, ACTIVE_HIGH, 1, "oprom"},
57 {-1, ACTIVE_HIGH, 0, "EC in RW"},
59 const size_t gpios_buf_size = sizeof(struct lb_gpios) + sizeof(struct lb_gpio) * 32;
60 uint8_t gpios_buf[gpios_buf_size];
61 struct lb_gpios *gpios_table = (struct lb_gpios *)gpios_buf;
62 gpios_table->count = 0;
63 gpios_table->size = 0;
64 gpios_table->tag = LB_TAG_GPIO;
66 /* Add GPIOs an check if they have been added to the table.
67 GPIOs are added in the same order to the end of the table. */
68 lb_add_gpios(gpios_table, gpios, ARRAY_SIZE(gpios));
69 assert_int_equal(ARRAY_SIZE(gpios), gpios_table->count);
70 assert_int_equal(sizeof(gpios), gpios_table->size);
71 assert_memory_equal(&gpios_table->gpios[0], gpios, sizeof(gpios));
73 /* Add subset of gpios and check if they have been added correctly. */
74 lb_add_gpios(gpios_table, &gpios[1], 2);
75 assert_int_equal(ARRAY_SIZE(gpios) + 2, gpios_table->count);
76 assert_int_equal(sizeof(gpios) + 2 * sizeof(gpios[0]), gpios_table->size);
77 assert_memory_equal(&gpios_table->gpios[0], gpios, sizeof(gpios));
78 assert_memory_equal(&gpios_table->gpios[ARRAY_SIZE(gpios)], &gpios[1],
79 2 * sizeof(gpios[0]));
82 uint8_t tables_buffer[sizeof(struct lb_header) + 10 * KiB];
83 static int setup_test_header(void **state)
85 *state = lb_table_init((uintptr_t)tables_buffer);
87 return 0;
90 static void test_lb_new_record(void **state)
92 struct lb_header *header = *state;
93 const size_t entries = 10;
94 int i;
95 size_t entries_offset;
96 size_t accumulated_size = 0;
97 struct lb_record *curr;
100 assert_int_equal(0, header->table_entries);
101 assert_int_equal(0, header->table_bytes);
103 lb_new_record(header);
104 assert_int_equal(1, header->table_entries);
105 assert_int_equal(0, header->table_bytes);
107 /* Create few entries with varying sizes (but at least of sizeof(struct lb_record))
108 Accumulate and check size of table after each lb_new_record() call. */
109 entries_offset = header->table_entries;
110 accumulated_size = sizeof(struct lb_record);
111 for (i = 0; i < entries; ++i) {
112 curr = lb_new_record(header);
113 curr->size = sizeof(struct lb_record) + ((i + 2) * 7) % 32;
115 assert_int_equal(entries_offset + (i + 1), header->table_entries);
116 assert_int_equal(accumulated_size, header->table_bytes);
117 accumulated_size += curr->size;
121 static void test_lb_add_serial(void **state)
123 struct lb_header *header = *state;
124 struct lb_serial serial;
126 serial.type = LB_SERIAL_TYPE_MEMORY_MAPPED;
127 serial.baseaddr = 0xFEDC6000;
128 serial.baud = 115200;
129 serial.regwidth = 1;
130 serial.input_hertz = 115200 * 16;
131 serial.uart_pci_addr = 0x0;
132 lb_add_serial(&serial, header);
134 assert_int_equal(1, header->table_entries);
135 /* Table bytes and checksum should be zero, because it is updated with size of previous
136 record or when table is closed. No previous record is present. */
137 assert_int_equal(0, header->table_bytes);
138 assert_int_equal(0, header->table_checksum);
141 static void test_lb_add_console(void **state)
143 struct lb_header *header = *state;
145 lb_add_console(LB_TAG_CONSOLE_SERIAL8250MEM, header);
146 assert_int_equal(1, header->table_entries);
147 /* Table bytes and checksum should be zero, because it is updated with size of previous
148 record or when table is closed. No previous record is present. */
149 assert_int_equal(0, header->table_bytes);
150 assert_int_equal(0, header->table_checksum);
153 static void test_multiple_entries(void **state)
155 struct lb_header *header = *state;
157 /* Add two entries */
158 lb_add_console(LB_TAG_CONSOLE_SERIAL8250, header);
159 lb_add_console(LB_TAG_CONSOLE_SERIAL8250MEM, header);
161 assert_int_equal(2, header->table_entries);
162 assert_int_equal(sizeof(struct lb_console), header->table_bytes);
165 static void test_write_coreboot_forwarding_table(void **state)
167 struct lb_header *header = *state;
168 uint8_t forwarding_table_buffer[sizeof(struct lb_header)
169 + 2 * sizeof(struct lb_forward)];
170 struct lb_header *forward_header =
171 (struct lb_header *)ALIGN_UP((uintptr_t)forwarding_table_buffer, 16);
172 size_t forwarding_table_size = write_coreboot_forwarding_table(
173 (uintptr_t)forwarding_table_buffer, (uintptr_t)header);
174 size_t expected_forwarding_table_size =
175 ALIGN_UP((uintptr_t)forwarding_table_buffer, 16) + sizeof(struct lb_header)
176 + sizeof(struct lb_forward) - (uintptr_t)forwarding_table_buffer;
177 assert_int_equal(expected_forwarding_table_size, forwarding_table_size);
179 assert_int_equal(1, forward_header->table_entries);
180 assert_int_equal(sizeof(struct lb_forward), forward_header->table_bytes);
181 assert_ptr_equal(header,
182 ((struct lb_forward *)lb_first_record(forward_header))->forward);
185 /* Mocks for write_tables() */
186 const char mainboard_vendor[] = CONFIG_MAINBOARD_VENDOR;
187 const char mainboard_part_number[] = CONFIG_MAINBOARD_PART_NUMBER;
189 const char coreboot_version[] = "4.13";
190 const char coreboot_extra_version[] = "abcdef";
191 const char coreboot_build[] = "Coreboot build info";
192 const unsigned int coreboot_version_timestamp = 1617191902U;
193 const unsigned int coreboot_major_revision = 4;
194 const unsigned int coreboot_minor_revision = 13;
196 const char coreboot_compile_time[] = "13:58:22";
197 const char coreboot_dmi_date[] = "03/31/2021";
199 const struct bcd_date coreboot_build_date = {
200 .century = 0x20,
201 .year = 0x20,
202 .month = 0x03,
203 .day = 0x31,
204 .weekday = 0x2,
207 const unsigned int asl_revision = 0x20200925;
209 void arch_write_tables(uintptr_t coreboot_table)
213 static const uintptr_t ebda_base = 0xf0000;
214 uintptr_t get_coreboot_rsdp(void)
216 return ebda_base;
219 struct resource mock_bootmem_ranges[] = {
220 {.base = 0x1000, .size = 0x2000, .flags = LB_MEM_RAM},
221 {.base = 0x0000, .size = 0x4000, .flags = LB_MEM_RAM},
224 void bootmem_write_memory_table(struct lb_memory *mem)
226 struct lb_memory_range *lb_r = &mem->map[0];
227 int i;
229 /* Insert entries for testing */
230 for (i = 0; i < ARRAY_SIZE(mock_bootmem_ranges); ++i) {
231 struct resource *res = &mock_bootmem_ranges[i];
232 lb_r->start = res->base;
233 lb_r->size = res->size;
234 lb_r->type = res->flags;
235 lb_r++;
236 mem->size += sizeof(struct lb_memory_range);
240 void uart_fill_lb(void *data)
242 struct lb_serial serial;
243 serial.type = LB_SERIAL_TYPE_MEMORY_MAPPED;
244 serial.baseaddr = 0xFEDC6000;
245 serial.baud = 115200;
246 serial.regwidth = 1;
247 serial.input_hertz = 115200 * 16;
248 serial.uart_pci_addr = 0x0;
249 lb_add_serial(&serial, data);
251 lb_add_console(LB_TAG_CONSOLE_SERIAL8250MEM, data);
254 struct cbfs_boot_device cbfs_boot_dev = {
255 .rdev = REGION_DEV_INIT(NULL, 0, 0x1000),
256 .mcache = (void *)0x1000,
257 .mcache_size = 0x1000,
260 const struct cbfs_boot_device *cbfs_get_boot_device(bool force_ro)
262 return &cbfs_boot_dev;
265 void cbmem_run_init_hooks(int is_recovery)
269 extern uintptr_t _cbmem_top_ptr;
270 void *cbmem_top_chipset(void)
272 return (void *)_cbmem_top_ptr;
275 #define CBMEM_SIZE (64 * KiB)
277 static int teardown_write_tables_test(void **state)
279 free(*state);
280 _cbmem_top_ptr = 0;
281 return 0;
284 static int setup_write_tables_test(void **state)
286 /* Allocate more data to have space for alignment */
287 void *top_ptr = malloc(CBMEM_SIZE + DYN_CBMEM_ALIGN_SIZE);
288 int32_t *mmc_status = NULL;
290 if (!top_ptr)
291 return -1;
293 *state = top_ptr;
295 _cbmem_top_ptr = ALIGN_UP((uintptr_t)top_ptr + CBMEM_SIZE, DYN_CBMEM_ALIGN_SIZE);
297 cbmem_initialize_empty();
299 mmc_status = cbmem_add(CBMEM_ID_MMC_STATUS, sizeof(int32_t));
301 if (mmc_status == NULL) {
302 teardown_write_tables_test(state);
303 return -1;
306 *mmc_status = 0x4433AADD;
308 return 0;
311 const struct region_device *boot_device_ro(void)
313 return &cbfs_boot_dev.rdev;
316 uint64_t get_fmap_flash_offset(void)
318 return FMAP_OFFSET;
321 uint32_t freq_khz = 5000 * 1000;
322 void lb_arch_add_records(struct lb_header *header)
324 struct lb_tsc_info *tsc_info;
326 tsc_info = (void *)lb_new_record(header);
327 tsc_info->tag = LB_TAG_TSC_INFO;
328 tsc_info->size = sizeof(*tsc_info);
329 tsc_info->freq_khz = freq_khz;
332 static void test_write_tables(void **state)
334 void *cbtable_start;
335 struct lb_header *header;
336 struct lb_record *record;
337 int32_t *mmc_status = cbmem_find(CBMEM_ID_MMC_STATUS);
338 size_t i = 0;
340 /* Expect function to store cbtable entry in cbmem */
341 cbtable_start = write_tables();
342 assert_ptr_equal(cbtable_start, cbmem_find(CBMEM_ID_CBTABLE));
344 /* Expect correct lb_header at cbtable_start address */
345 header = (struct lb_header *)cbtable_start;
346 assert_non_null(header);
347 assert_memory_equal("LBIO", header, 4);
348 assert_int_equal(sizeof(*header), header->header_bytes);
349 /* At least one entry should be present. */
350 assert_int_not_equal(0, header->table_entries);
352 LB_RECORD_FOR_EACH(record, i, header)
354 switch (record->tag) {
355 case LB_TAG_MEMORY:
356 /* Should be the same as in bootmem_write_memory_table() */
357 assert_int_equal(sizeof(struct lb_memory)
358 + ARRAY_SIZE(mock_bootmem_ranges)
359 * sizeof(struct lb_memory_range),
360 record->size);
362 const struct lb_memory *memory = (struct lb_memory *)record;
363 const struct lb_memory_range *range;
364 const struct resource *res;
365 lb_uint64_t value;
367 for (int i = 0; i < ARRAY_SIZE(mock_bootmem_ranges); ++i) {
368 res = &mock_bootmem_ranges[i];
369 range = &memory->map[i];
371 value = res->base;
372 assert_memory_equal(&value, &range->start,
373 sizeof(lb_uint64_t));
374 value = res->size;
375 assert_memory_equal(&value, &range->size,
376 sizeof(lb_uint64_t));
377 assert_int_equal(range->type, res->flags);
379 break;
380 case LB_TAG_MAINBOARD:
381 /* Mainboard record contains its header followed
382 by two null-terminated strings */
383 assert_int_equal(ALIGN_UP(sizeof(struct lb_mainboard)
384 + ARRAY_SIZE(mainboard_vendor)
385 + ARRAY_SIZE(mainboard_part_number),
387 record->size);
388 break;
389 case LB_TAG_VERSION:
390 assert_int_equal(ALIGN_UP(sizeof(struct lb_string)
391 + ARRAY_SIZE(coreboot_version),
393 record->size);
394 break;
395 case LB_TAG_EXTRA_VERSION:
396 assert_int_equal(ALIGN_UP(sizeof(struct lb_string)
397 + ARRAY_SIZE(coreboot_extra_version),
399 record->size);
400 break;
401 case LB_TAG_BUILD:
402 assert_int_equal(
403 ALIGN_UP(sizeof(struct lb_string) + ARRAY_SIZE(coreboot_build),
405 record->size);
406 break;
407 case LB_TAG_COMPILE_TIME:
408 assert_int_equal(ALIGN_UP(sizeof(struct lb_string)
409 + ARRAY_SIZE(coreboot_compile_time),
411 record->size);
412 break;
413 case LB_TAG_SERIAL:
414 assert_int_equal(sizeof(struct lb_serial), record->size);
416 /* This struct have the same values as created in uart_fill_lb() */
417 const struct lb_serial *serial = (struct lb_serial *)record;
418 assert_int_equal(LB_SERIAL_TYPE_MEMORY_MAPPED, serial->type);
419 assert_int_equal(0xFEDC6000, serial->baseaddr);
420 assert_int_equal(115200, serial->baud);
421 assert_int_equal(1, serial->regwidth);
422 assert_int_equal(115200 * 16, serial->input_hertz);
423 assert_int_equal(0x0, serial->uart_pci_addr);
424 break;
425 case LB_TAG_CONSOLE:
426 assert_int_equal(sizeof(struct lb_console), record->size);
428 /* This struct have the same values as created in uart_fill_lb() */
429 const struct lb_console *console = (struct lb_console *)record;
430 assert_int_equal(LB_TAG_CONSOLE_SERIAL8250MEM, console->type);
431 break;
432 case LB_TAG_VERSION_TIMESTAMP:
433 assert_int_equal(sizeof(struct lb_timestamp), record->size);
435 const struct lb_timestamp *timestamp = (struct lb_timestamp *)record;
436 assert_int_equal(coreboot_version_timestamp, timestamp->timestamp);
437 break;
438 case LB_TAG_BOOT_MEDIA_PARAMS:
439 assert_int_equal(sizeof(struct lb_boot_media_params), record->size);
441 const struct lb_boot_media_params *bmp =
442 (struct lb_boot_media_params *)record;
443 const struct cbfs_boot_device *cbd = cbfs_get_boot_device(false);
444 const struct region_device *boot_dev = boot_device_ro();
445 assert_int_equal(region_device_offset(&cbd->rdev), bmp->cbfs_offset);
446 assert_int_equal(region_device_sz(&cbd->rdev), bmp->cbfs_size);
447 assert_int_equal(region_device_sz(boot_dev), bmp->boot_media_size);
448 assert_int_equal(get_fmap_flash_offset(), bmp->fmap_offset);
450 break;
451 case LB_TAG_CBMEM_ENTRY:
452 assert_int_equal(sizeof(struct lb_cbmem_entry), record->size);
454 const struct lb_cbmem_entry *cbmem_entry =
455 (struct lb_cbmem_entry *)record;
456 const LargestIntegralType expected_tags[] = {CBMEM_ID_CBTABLE,
457 CBMEM_ID_MMC_STATUS};
458 assert_in_set(cbmem_entry->id, expected_tags,
459 ARRAY_SIZE(expected_tags));
460 break;
461 case LB_TAG_TSC_INFO:
462 assert_int_equal(sizeof(struct lb_tsc_info), record->size);
464 const struct lb_tsc_info *tsc_info = (struct lb_tsc_info *)record;
465 assert_int_equal(freq_khz, tsc_info->freq_khz);
466 break;
467 case LB_TAG_MMC_INFO:
468 assert_int_equal(sizeof(struct lb_mmc_info), record->size);
470 const struct lb_mmc_info *mmc_info = (struct lb_mmc_info *)record;
471 assert_int_equal(*mmc_status, mmc_info->early_cmd1_status);
472 break;
473 case LB_TAG_BOARD_CONFIG:
474 assert_int_equal(sizeof(struct lb_board_config), record->size);
476 const struct lb_board_config *board_config =
477 (struct lb_board_config *)record;
478 const lb_uint64_t expected_fw_version = fw_config_get();
479 assert_memory_equal(&expected_fw_version, &board_config->fw_config,
480 sizeof(lb_uint64_t));
481 assert_int_equal(board_id(), board_config->board_id);
482 assert_int_equal(ram_code(), board_config->ram_code);
483 assert_int_equal(sku_id(), board_config->sku_id);
484 break;
485 case LB_TAG_ACPI_RSDP:
486 assert_int_equal(sizeof(struct lb_acpi_rsdp), record->size);
488 const struct lb_acpi_rsdp *acpi_rsdp = (struct lb_acpi_rsdp *)record;
489 assert_int_equal(ebda_base, acpi_rsdp->rsdp_pointer);
490 break;
491 default:
492 fail_msg("Unexpected tag found in record. Tag ID: 0x%x", record->tag);
497 int main(void)
499 const struct CMUnitTest tests[] = {
500 cmocka_unit_test(test_lb_add_gpios),
501 cmocka_unit_test_setup(test_lb_new_record, setup_test_header),
502 cmocka_unit_test_setup(test_lb_add_serial, setup_test_header),
503 cmocka_unit_test_setup(test_lb_add_console, setup_test_header),
504 cmocka_unit_test_setup(test_multiple_entries, setup_test_header),
505 cmocka_unit_test_setup(test_write_coreboot_forwarding_table, setup_test_header),
506 cmocka_unit_test_setup_teardown(test_write_tables, setup_write_tables_test,
507 teardown_write_tables_test),
510 return cb_run_group_tests(tests, NULL, NULL);