From da46a782197819d81c21d16e7af4c83a73824d6f Mon Sep 17 00:00:00 2001 From: antifallobst Date: Tue, 25 Apr 2023 17:13:09 +0200 Subject: [PATCH] feature (PCI): implemented basic PCI enumerating --- .gitignore | 1 - inc/drivers/acpi/acpi.h | 2 -- inc/drivers/acpi/mcfg.h | 23 +++++++++++++ inc/drivers/pci.h | 43 ++++++++++++++++++++++++- run.sh | 9 +++--- src/boot/kmain.c | 3 ++ src/drivers/acpi/acpi.c | 20 ++++++++---- src/drivers/pci.c | 71 ++++++++++++++++++++++++++++++++++++++++- src/mm/page_map.c | 1 + 9 files changed, 157 insertions(+), 16 deletions(-) create mode 100644 inc/drivers/acpi/mcfg.h diff --git a/.gitignore b/.gitignore index dd6d270..66293d8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ build cmake-build-debug noxos.log -*.img # For test disk images diff --git a/inc/drivers/acpi/acpi.h b/inc/drivers/acpi/acpi.h index 5b1153d..6a0042c 100644 --- a/inc/drivers/acpi/acpi.h +++ b/inc/drivers/acpi/acpi.h @@ -26,8 +26,6 @@ typedef struct { uint64_t address; } __attribute__((packed)) acpi_gas_T; -extern acpi_sdt_header_T *g_mcfg_table; - void acpi_init (boot_info_T* boot_info); acpi_sdt_header_T* acpi_find_table (acpi_sdt_header_T* xsdt, string_t table_id); diff --git a/inc/drivers/acpi/mcfg.h b/inc/drivers/acpi/mcfg.h new file mode 100644 index 0000000..1345145 --- /dev/null +++ b/inc/drivers/acpi/mcfg.h @@ -0,0 +1,23 @@ +// This file is part of noxos and licensed under the MIT open source license + +#ifndef NOXOS_MCFG_H +#define NOXOS_MCFG_H + +#include "drivers/acpi/acpi.h" + +typedef struct { + acpi_sdt_header_T header; + uint64_t reserved; +} __attribute__((packed)) acpi_mcfg_T; + +typedef struct { + uint64_t base; + uint16_t pci_segment_group; + uint8_t pci_start_bus; + uint8_t pci_end_bus; + uint32_t reserved; +} __attribute__((packed)) acpi_mcfg_device_config_T; + +extern acpi_mcfg_T* g_acpi_table_mcfg; + +#endif //NOXOS_MCFG_H diff --git a/inc/drivers/pci.h b/inc/drivers/pci.h index 8a4cf0b..df5309a 100644 --- a/inc/drivers/pci.h +++ b/inc/drivers/pci.h @@ -1,7 +1,48 @@ +// This file is part of noxos and licensed under the MIT open source license #ifndef NOXOS_PCI_H #define NOXOS_PCI_H +#include "utils/stdtypes.h" +#include "utils/string.h" +typedef struct { + uint16_t vendor_id; + uint16_t device_id; + uint16_t command_reg; + uint16_t status_reg; + uint8_t revision_id; + uint8_t progif; // Programming Interface Byte + uint8_t subclass; + uint8_t main_class; + uint8_t cache_line_size; + uint8_t latency_timer; + uint8_t header_type; + uint8_t bist; // Built-in Self-Test +} __attribute__((packed)) pci_device_header_T; -#endif +typedef struct { + pci_device_header_T header; + uint32_t bar0; + uint32_t bar1; + uint32_t bar2; + uint32_t bar3; + uint32_t bar4; + uint32_t bar5; + uint32_t cardbus_cis_pointer; + uint16_t subsystem_vendor_id; + uint16_t subsystem_id; + uint32_t expansion_rom_base_address; + uint8_t capabilities; + uint8_t reserved[7]; + uint8_t interrupt_line; + uint8_t interrupt_pin; + uint8_t min_grant; + uint8_t max_latency; +} __attribute__((packed)) pci_header_0_T; + +void pci_init (); +string_t pci_get_vendor_string (uint16_t vendor_id); +string_t pci_get_device_string (uint16_t device_id); + +#endif // NOXOS_PCI_H diff --git a/run.sh b/run.sh index ddb989f..b0d135f 100755 --- a/run.sh +++ b/run.sh @@ -1,11 +1,10 @@ #!/bin/bash # This file is part of noxos and licensed under the MIT open source license -EMUFLAGS="-no-reboot -m 256M -cdrom build/noxos.iso -chardev stdio,id=log,logfile=noxos.log -serial chardev:log -drive id=disk,file=test_disk.img,if=none \ --device ahci,id=disk \ --device ide-hd,drive=disk - -" +EMUFLAGS="-no-reboot -machine q35 -cpu qemu64 -m 256M \ + -drive file=build/noxos.iso,id=disk \ + -drive file=fat:rw:ramdisk \ + -chardev stdio,id=log,logfile=noxos.log -serial chardev:log" emulate_bios() { echo "<=====| Emulating |=====>" diff --git a/src/boot/kmain.c b/src/boot/kmain.c index 9799a00..c1b8af7 100644 --- a/src/boot/kmain.c +++ b/src/boot/kmain.c @@ -13,6 +13,7 @@ #include "drivers/graphics/renderer.h" #include "drivers/fs/vfs.h" #include "drivers/acpi/acpi.h" +#include "drivers/pci.h" //#include "drivers/ps2/keyboard.h" #include "proc/scheduler.h" @@ -43,6 +44,8 @@ void kernel_init(boot_info_T* boot_info) { acpi_init(boot_info); + pci_init(); + // ps2_keyboard_init(); scheduler_init(boot_info); diff --git a/src/drivers/acpi/acpi.c b/src/drivers/acpi/acpi.c index ca7eaa8..d7401ff 100644 --- a/src/drivers/acpi/acpi.c +++ b/src/drivers/acpi/acpi.c @@ -3,12 +3,13 @@ #include "drivers/acpi/acpi.h" #include "drivers/acpi/rsdp.h" #include "drivers/acpi/fadt.h" +#include "drivers/acpi/mcfg.h" #include "utils/logger.h" #include "utils/memory.h" #include "utils/panic.h" -acpi_sdt_header_T *g_mcfg_table; -acpi_fadt_T *g_acpi_table_fadt; +acpi_fadt_T* g_acpi_table_fadt; +acpi_mcfg_T* g_acpi_table_mcfg; void acpi_init(boot_info_T* boot_info) { log(LOG_INFO, "Initializing ACPI - RSDP: 0x%x", boot_info->rsdp); @@ -27,12 +28,21 @@ void acpi_init(boot_info_T* boot_info) { if (!rsdp_descriptor_v2_verify(boot_info->rsdp)) { log(LOG_WARNING, " RSDP header verification failed"); } - g_acpi_table_fadt = (acpi_fadt_T*)acpi_find_table((acpi_sdt_header_T*)((rsdp_descriptor_v2_T*)boot_info->rsdp)->xsdt_address, "FACP"); + acpi_sdt_header_T* xsdt = ((rsdp_descriptor_v2_T*)boot_info->rsdp)->xsdt_address; + + g_acpi_table_fadt = (acpi_fadt_T*)acpi_find_table(xsdt, "FACP"); if (g_acpi_table_fadt == NULL) { panic(NULL, " FADT table not found"); } log(LOG_INFO, " found FADT at address 0x%x", g_acpi_table_fadt); + + g_acpi_table_mcfg = (acpi_mcfg_T*)acpi_find_table(xsdt, "MCFG"); + if (g_acpi_table_mcfg == NULL) { + panic(NULL, " MCFG table not found"); + } + log(LOG_INFO, " found MCFG at address 0x%x", g_acpi_table_mcfg); + break; } default: { @@ -40,8 +50,6 @@ void acpi_init(boot_info_T* boot_info) { break; } } - - g_mcfg_table = acpi_find_table((acpi_sdt_header_T*)((rsdp_descriptor_v2_T*)boot_info->rsdp)->xsdt_address, "MCFG"); } acpi_sdt_header_T* acpi_find_table(acpi_sdt_header_T* xsdt, string_t table_id) { @@ -54,6 +62,6 @@ acpi_sdt_header_T* acpi_find_table(acpi_sdt_header_T* xsdt, string_t table_id) { if (!memory_compare(sdt->signature, (void*)table_id, 4)) continue; return sdt; } - log(LOG_WARNING, " table '%.4' not found (no matching xsdt entry)"); + log(LOG_WARNING, " table '%.4s' not found (no matching xsdt entry)", table_id); return NULL; } \ No newline at end of file diff --git a/src/drivers/pci.c b/src/drivers/pci.c index c6de129..e22c666 100644 --- a/src/drivers/pci.c +++ b/src/drivers/pci.c @@ -1,3 +1,72 @@ -#include +// This file is part of noxos and licensed under the MIT open source license +#include "drivers/pci.h" +#include "drivers/acpi/acpi.h" +#include "drivers/acpi/mcfg.h" +#include "mm/page_map.h" +#include "utils/logger.h" +string_t pci_get_vendor_string(uint16_t vendor_id) { + switch (vendor_id) { + case 0x1234: return "QEMU"; + case 0x8086: return "Intel"; + default: return "Unknown"; + } +} + +string_t pci_get_device_string(uint16_t device_id) { + switch (device_id) { + case 0x1111: return "Bochs Graphics Adaptor"; + case 0x29C0: return "Express DRAM Controller"; + default: return "Unknown"; + } +} + +void pci_enumerate_function(void* device_address, uint8_t function) { + void* function_address = (void*)((uint64_t)device_address + (function << 12)); + page_map_map_memory(g_kernel_page_map, function_address, function_address, PM_FLAG_READ_WRITE); + + pci_device_header_T* device_header = (pci_device_header_T*)function_address; + if (device_header->device_id == 0 || device_header->device_id == 0xFFFF) return; + log(LOG_DEBUG, " Vendor ID: 0x%xw - %s", device_header->vendor_id, pci_get_vendor_string(device_header->vendor_id)); + log(LOG_DEBUG, " Device ID: 0x%xw - %s", device_header->device_id, pci_get_device_string(device_header->device_id)); + + log(LOG_DEBUG, " Found device CLASS[0x%xb] SUBCLASS[0x%xb] PROGIF[0x%xb]", device_header->main_class, device_header->subclass, device_header->progif); +} + +void pci_enumerate_device(void* bus_address, uint8_t device) { + void* device_address = (void*)((uint64_t)bus_address + (device << 15)); + page_map_map_memory(g_kernel_page_map, device_address, device_address, PM_FLAG_READ_WRITE); + + pci_device_header_T* device_header = (pci_device_header_T*)device_address; + if (device_header->device_id == 0 || device_header->device_id == 0xFFFF) return; + + for (uint8_t function = 0; function < 8; function++) { + pci_enumerate_function(device_address, function); + } +} + +void pci_enumerate_bus(void* base, uint8_t bus) { + void* bus_address = (void*)((uint64_t)base + (bus << 20)); + page_map_map_memory(g_kernel_page_map, bus_address, bus_address, PM_FLAG_READ_WRITE); + + pci_device_header_T* device_header = (pci_device_header_T*)bus_address; + if (device_header->device_id == 0 || device_header->device_id == 0xFFFF) return; + + for (uint8_t device = 0; device < 32; device++) { + pci_enumerate_device(bus_address, device); + } +} + +void pci_init() { + uint32_t num_configs = (g_acpi_table_mcfg->header.length - sizeof(acpi_mcfg_T)) / sizeof(acpi_mcfg_device_config_T); + acpi_mcfg_device_config_T* configs = (acpi_mcfg_device_config_T*)(&g_acpi_table_mcfg[1]); + + for (uint32_t i = 0; i < num_configs; i++) { + acpi_mcfg_device_config_T* config = &configs[i]; + + for (uint8_t bus = config->pci_start_bus; bus < config->pci_end_bus; bus++) { + pci_enumerate_bus((void*)config->base, bus); + } + } +} \ No newline at end of file diff --git a/src/mm/page_map.c b/src/mm/page_map.c index 03650c9..74929b0 100644 --- a/src/mm/page_map.c +++ b/src/mm/page_map.c @@ -57,6 +57,7 @@ void page_map_map_memory(page_map_T* page_map, void* virtual_address, void* phys page_map_T* page_table = page_map_request_entry(page_directory, page_table_index); uint64_t* page = &page_table->entries[page_index]; + *page = 0; page_map_entry_set_address(page, (void*)((uint64_t)physical_address >> 12)); page_map_entry_set_flags(page, PM_FLAG_PRESENT | flags); }