diff --git a/tools/unit-tests/Makefile b/tools/unit-tests/Makefile index 9d3644602..83c771be2 100644 --- a/tools/unit-tests/Makefile +++ b/tools/unit-tests/Makefile @@ -39,6 +39,9 @@ unit-aes256: ../../include/target.h unit-extflash.c unit-chacha20: ../../include/target.h unit-extflash.c gcc -o $@ $^ $(CFLAGS) $(LDFLAGS) +unit-pci: unit-pci.c ../../src/pci.c + gcc -o $@ $< $(CFLAGS) $(LDFLAGS) + %.o:%.c gcc -c -o $@ $^ $(CFLAGS) diff --git a/tools/unit-tests/unit-pci.c b/tools/unit-tests/unit-pci.c new file mode 100644 index 000000000..b48065655 --- /dev/null +++ b/tools/unit-tests/unit-pci.c @@ -0,0 +1,178 @@ +#include +#include +#include +#include +#include + +#define MOCKED_BASE (2*1024*1024*1024ULL) +#define MOCKED_LEN (1024*1024*1024ULL) +#define PCI_USE_ECAM +#define PCI_ECAM_BASE MOCKED_BASE + +#include +#include + +struct type1_pci_header { + uint16_t vendor_id; + uint16_t device_id; + uint16_t command; + uint16_t status; + uint8_t revision_id; + uint8_t prog_if; + uint8_t subclass; + uint8_t class_code; + uint8_t cache_line_size; + uint8_t latency_timer; + uint8_t header_type; + uint8_t bist; + uint32_t base_address_0; + uint32_t base_address_1; + uint8_t primary_bus_number; + uint8_t secondary_bus_number; + uint8_t subordinate_bus_number; + uint8_t secondary_latency_timer; + uint16_t io_base; + uint16_t io_limit; + uint16_t secondary_status; + uint16_t memory_base; + uint16_t memory_limit; + uint16_t prefetchable_memory_base; + uint16_t prefetchable_memory_limit; + uint32_t prefetchable_base_upper; + uint32_t prefetchable_limit_upper; + uint16_t io_base_upper; + uint16_t io_limit_upper; + uint8_t capability_pointer; + uint8_t reserved_0[3]; + uint32_t expansion_rom_base_address; + uint8_t interrupt_line; + uint8_t interrupt_pin; + uint16_t bridge_control; +}; + +struct type1_pci_header type1_pci_header_mock = { + .vendor_id = 0xdead, + .device_id = 0xddee, + .status = 0x8000, + .command = 0x0010, + .class_code = 0x06, + .subclass = 0x04, + .prog_if = 0x80, + .revision_id = 0x03, + .bist = 0x00, + .header_type = 0x01, + .latency_timer = 0x40, + .cache_line_size = 0x08, + .base_address_0 = 0x12345678, + .base_address_1 = 0x9abcdef0, + .secondary_latency_timer = 0xee, + .subordinate_bus_number = 0xdd, + .secondary_bus_number = 0xbb, + .primary_bus_number = 0xaa, + .secondary_status = 0x0000, + .io_limit = 0xffff, + .io_base = 0x0000, + .memory_limit = 0xffff, + .memory_base = 0x0000, + .prefetchable_memory_limit = 0xffff, + .prefetchable_memory_base = 0x0000, + .prefetchable_base_upper = 0x00000000, + .prefetchable_limit_upper = 0x00000000, + .io_limit_upper = 0x0000, + .io_base_upper = 0x0000, + .reserved_0 = {0x00, 0x00}, + .capability_pointer = 0x00, + .expansion_rom_base_address = 0x13579bdf, + .bridge_control = 0x0000, + .interrupt_pin = 0x01, + .interrupt_line = 0x0a +}; + +void mmio_write32(uintptr_t address, uint32_t value) +{ + uint32_t *p = (uint32_t*)address; + *p = value; +} + +uint32_t mmio_read32(uintptr_t address) +{ + return *((uint32_t*)(address)); +} + +void panic() +{ + ck_abort_msg("panic!"); +} + +START_TEST (test_pci_config_write) +{ + struct type1_pci_header *hdr_mem; + uint16_t reg16; + uint8_t reg8; + + hdr_mem = + (struct type1_pci_header *)mmap((uint8_t *)MOCKED_BASE, MOCKED_LEN, + PROT_WRITE | PROT_READ, + MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0); + + ck_assert_ptr_eq(hdr_mem, (uint8_t*)MOCKED_BASE); + + memcpy(hdr_mem, &type1_pci_header_mock, sizeof(type1_pci_header_mock)); + reg16 = pci_config_read16(0, 0, 0, PCI_VENDOR_ID_OFFSET); + ck_assert_uint_eq(reg16, hdr_mem->vendor_id); + reg16 = pci_config_read16(0, 0, 0, PCI_DEVICE_ID_OFFSET); + ck_assert_uint_eq(reg16, hdr_mem->device_id); + reg16 = 0xdead; + pci_config_write16(0, 0, 0, PCI_VENDOR_ID_OFFSET, reg16); + ck_assert_uint_eq(reg16, hdr_mem->vendor_id); + reg16 = 0xbeef; + pci_config_write16(0, 0, 0, PCI_DEVICE_ID_OFFSET, reg16); + ck_assert_uint_eq(reg16, hdr_mem->device_id); + reg8 = pci_config_read8(0, 0, 0, PCI_PRIMARY_BUS); + ck_assert_uint_eq(reg8, hdr_mem->primary_bus_number); + reg8 = pci_config_read8(0, 0, 0, PCI_SECONDARY_BUS); + ck_assert_uint_eq(reg8, hdr_mem->secondary_bus_number); + reg8 = 0xbe; + pci_config_write8(0, 0, 0, PCI_PRIMARY_BUS, reg8); + ck_assert_uint_eq(reg8, hdr_mem->primary_bus_number); + reg8 = 0xca; + pci_config_write8(0, 0, 0, PCI_SECONDARY_BUS, reg8); + ck_assert_uint_eq(reg8, hdr_mem->secondary_bus_number); + pci_config_write32(0, 0, 0, PCI_PRIMARY_BUS, 0xaabbccdd); + ck_assert_uint_eq(0xaabbccdd, *((uint32_t*)&(hdr_mem->primary_bus_number))); + reg8 = pci_config_read8(0, 0, 0, PCI_SECONDARY_BUS); + ck_assert_uint_eq(reg8, hdr_mem->secondary_bus_number); + reg8 = 0xbe; + pci_config_write8(0, 0, 0, PCI_PRIMARY_BUS, reg8); + ck_assert_uint_eq(reg8, hdr_mem->primary_bus_number); + + munmap(hdr_mem, MOCKED_LEN); +} +END_TEST + +Suite *wolfboot_suite(void) +{ + + /* Suite initialization */ + Suite *s = suite_create("wolfboot-pci"); + + /* Test cases */ + TCase *pci_config = tcase_create("pci-config-write"); + + tcase_add_test(pci_config, test_pci_config_write); + tcase_set_timeout(pci_config, 60*5); + suite_add_tcase(s, pci_config); + + return s; +} + +int main(void) +{ + int fails; + Suite *s = wolfboot_suite(); + SRunner *sr = srunner_create(s); + srunner_run_all(sr, CK_NORMAL); + fails = srunner_ntests_failed(sr); + srunner_free(sr); + return fails; +}