1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <tests/test.h>
5 #include <boot/coreboot_tables.h>
6 #include <boot/tables.h>
9 #include <commonlib/helpers.h>
10 #include <commonlib/region.h>
11 #include <fmap_config.h>
12 #include <fw_config.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 */
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;
39 static struct lb_record
*lb_first_record(struct lb_header
*header
)
41 struct lb_record
*rec
;
42 rec
= (void *)(((char *)header
) + sizeof(*header
));
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), \
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
);
90 static void test_lb_new_record(void **state
)
92 struct lb_header
*header
= *state
;
93 const size_t entries
= 10;
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;
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
= {
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)
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];
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
;
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;
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
)
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
;
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
);
306 *mmc_status
= 0x4433AADD;
311 const struct region_device
*boot_device_ro(void)
313 return &cbfs_boot_dev
.rdev
;
316 uint64_t get_fmap_flash_offset(void)
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
)
335 struct lb_header
*header
;
336 struct lb_record
*record
;
337 int32_t *mmc_status
= cbmem_find(CBMEM_ID_MMC_STATUS
);
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
) {
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
),
362 const struct lb_memory
*memory
= (struct lb_memory
*)record
;
363 const struct lb_memory_range
*range
;
364 const struct resource
*res
;
367 for (int i
= 0; i
< ARRAY_SIZE(mock_bootmem_ranges
); ++i
) {
368 res
= &mock_bootmem_ranges
[i
];
369 range
= &memory
->map
[i
];
372 assert_memory_equal(&value
, &range
->start
,
373 sizeof(lb_uint64_t
));
375 assert_memory_equal(&value
, &range
->size
,
376 sizeof(lb_uint64_t
));
377 assert_int_equal(range
->type
, res
->flags
);
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
),
390 assert_int_equal(ALIGN_UP(sizeof(struct lb_string
)
391 + ARRAY_SIZE(coreboot_version
),
395 case LB_TAG_EXTRA_VERSION
:
396 assert_int_equal(ALIGN_UP(sizeof(struct lb_string
)
397 + ARRAY_SIZE(coreboot_extra_version
),
403 ALIGN_UP(sizeof(struct lb_string
) + ARRAY_SIZE(coreboot_build
),
407 case LB_TAG_COMPILE_TIME
:
408 assert_int_equal(ALIGN_UP(sizeof(struct lb_string
)
409 + ARRAY_SIZE(coreboot_compile_time
),
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
);
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
);
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
);
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
);
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
));
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
);
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
);
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
);
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
);
492 fail_msg("Unexpected tag found in record. Tag ID: 0x%x", record
->tag
);
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
);