diff --git a/.gitignore b/.gitignore index c0edcf1..9852334 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,4 @@ *.map *.fsys *.log -files/*.psf +Files/*.psf diff --git a/arch/CPU.cpp b/Core/CPU.cpp similarity index 94% rename from arch/CPU.cpp rename to Core/CPU.cpp index 2c540aa..64ea63b 100644 --- a/arch/CPU.cpp +++ b/Core/CPU.cpp @@ -78,6 +78,20 @@ namespace CPU #endif } + void Stop() + { + while (1) + { +#if defined(__amd64__) || defined(__i386__) + asmv("cli"); + asmv("hlt"); +#elif defined(__aarch64__) + asmv("msr daifset, #2"); + asmv("wfe"); +#endif + } + } + void Halt() { #if defined(__amd64__) || defined(__i386__) diff --git a/core/Debugger.cpp b/Core/Debugger.cpp similarity index 100% rename from core/Debugger.cpp rename to Core/Debugger.cpp diff --git a/core/Interrupts/IntManager.cpp b/Core/Interrupts/IntManager.cpp similarity index 100% rename from core/Interrupts/IntManager.cpp rename to Core/Interrupts/IntManager.cpp diff --git a/core/Memory/HeapAllocators/Xalloc.cpp b/Core/Memory/HeapAllocators/Xalloc.cpp similarity index 100% rename from core/Memory/HeapAllocators/Xalloc.cpp rename to Core/Memory/HeapAllocators/Xalloc.cpp diff --git a/core/Memory/HeapAllocators/Xalloc.hpp b/Core/Memory/HeapAllocators/Xalloc.hpp similarity index 100% rename from core/Memory/HeapAllocators/Xalloc.hpp rename to Core/Memory/HeapAllocators/Xalloc.hpp diff --git a/core/Memory/Memory.cpp b/Core/Memory/Memory.cpp similarity index 99% rename from core/Memory/Memory.cpp rename to Core/Memory/Memory.cpp index 7003e45..74cc6f1 100644 --- a/core/Memory/Memory.cpp +++ b/Core/Memory/Memory.cpp @@ -4,7 +4,7 @@ #include #include "HeapAllocators/Xalloc.hpp" -#include "../lib/liballoc_1_1.h" +#include "../Library/liballoc_1_1.h" using namespace Memory; diff --git a/core/Memory/PhysicalMemoryManager.cpp b/Core/Memory/PhysicalMemoryManager.cpp similarity index 100% rename from core/Memory/PhysicalMemoryManager.cpp rename to Core/Memory/PhysicalMemoryManager.cpp diff --git a/core/Memory/VirtualMemoryManager.cpp b/Core/Memory/VirtualMemoryManager.cpp similarity index 100% rename from core/Memory/VirtualMemoryManager.cpp rename to Core/Memory/VirtualMemoryManager.cpp diff --git a/Core/PeripheralComponentInterconnect.cpp b/Core/PeripheralComponentInterconnect.cpp new file mode 100644 index 0000000..ea432aa --- /dev/null +++ b/Core/PeripheralComponentInterconnect.cpp @@ -0,0 +1,844 @@ +#include + +#include + +namespace PCI +{ + namespace Descriptors + { + char HexToStringOutput8[128]; + const char *u8ToHexString(uint8_t Value) + { + uint8_t *ValuePtr = &Value; + uint8_t *Ptr; + uint8_t Temp; + uint8_t Size = 1 * 2 - 1; + for (uint8_t i = 0; i < Size; i++) + { + Ptr = ((uint8_t *)ValuePtr + i); + Temp = ((*Ptr & 0xF0) >> 4); + HexToStringOutput8[Size - (i * 2 + 1)] = Temp + (Temp > 9 ? 55 : '0'); + Temp = ((*Ptr & 0x0F)); + HexToStringOutput8[Size - (i * 2)] = Temp + (Temp > 9 ? 55 : '0'); + } + HexToStringOutput8[Size + 1] = 0; + return HexToStringOutput8; + } + + char HexToStringOutput32[128]; + const char *u32ToHexString(uint32_t Value) + { + uint32_t *ValuePtr = &Value; + uint8_t *Ptr; + uint8_t Temp; + uint8_t Size = 4 * 2 - 1; + for (uint8_t i = 0; i < Size; i++) + { + Ptr = ((uint8_t *)ValuePtr + i); + Temp = ((*Ptr & 0xF0) >> 4); + HexToStringOutput32[Size - (i * 2 + 1)] = Temp + (Temp > 9 ? 55 : '0'); + Temp = ((*Ptr & 0x0F)); + HexToStringOutput32[Size - (i * 2)] = Temp + (Temp > 9 ? 55 : '0'); + } + HexToStringOutput32[Size + 1] = 0; + return HexToStringOutput32; + } + + const char *MassStorageControllerSubclassName(uint8_t SubclassCode) + { + switch (SubclassCode) + { + case 0x00: + return "SCSI Bus Controller"; + case 0x01: + return "IDE Controller"; + case 0x02: + return "Floppy Disk Controller"; + case 0x03: + return "IPI Bus Controller"; + case 0x04: + return "RAID Controller"; + case 0x05: + return "ATA Controller"; + case 0x06: + return "Serial ATA"; + case 0x07: + return "Serial Attached SCSI Controller"; + case 0x08: + return "Non-Volatile Memory Controller"; + case 0x80: + return "Mass Storage Controller"; + default: + break; + } + fixme("Unknown mass storage controller %02x", SubclassCode); + return u8ToHexString(SubclassCode); + } + + const char *NetworkControllerSubclassName(uint8_t SubclassCode) + { + switch (SubclassCode) + { + case 0x00: + return "Ethernet Controller"; + case 0x01: + return "Token Ring Controller"; + case 0x02: + return "FDDI Controller"; + case 0x03: + return "ATM Controller"; + case 0x04: + return "ISDN Controller"; + case 0x05: + return "WorldFip Controller"; + case 0x06: + return "PICMG HyperCard Controller"; + case 0x07: + return "Infiniband Controller"; + case 0x08: + return "Fabric Controller"; + case 0x80: + return "Network Controller"; + default: + break; + } + fixme("Unknown network controller %02x", SubclassCode); + return u8ToHexString(SubclassCode); + } + + const char *DisplayControllerSubclassName(uint8_t SubclassCode) + { + switch (SubclassCode) + { + case 0x00: + return "VGA Compatible Controller"; + case 0x01: + return "XGA Controller"; + case 0x02: + return "3D Controller"; + case 0x80: + return "Display Controller"; + default: + break; + } + fixme("Unknown display controller %02x", SubclassCode); + return u8ToHexString(SubclassCode); + } + + const char *CommunicationControllerSubclassName(uint8_t SubclassCode) + { + switch (SubclassCode) + { + case 0x00: + return "Serial Controller"; + case 0x01: + return "Parallel Controller"; + case 0x02: + return "Multi-Serial Controller"; + case 0x03: + return "IEEE-1284 Controller"; + case 0x04: + return "ATM Controller"; + case 0x05: + return "Object Storage Controller"; + case 0x80: + return "Communication controller"; + default: + break; + } + fixme("Unknown communication controller %02x", SubclassCode); + return u8ToHexString(SubclassCode); + } + + const char *BaseSystemPeripheralSubclassName(uint8_t SubclassCode) + { + // not sure if it's right + switch (SubclassCode) + { + case 0x00: + return "Unclassified"; + case 0x01: + return "Keyboard"; + case 0x02: + return "Pointing Device"; + case 0x03: + return "Mouse"; + case 0x04: + return "Scanner"; + case 0x05: + return "Gameport"; + case 0x80: + return "Unclassified"; + default: + break; + } + fixme("Unknown base system peripheral %02x", SubclassCode); + return u8ToHexString(SubclassCode); + } + + const char *SerialBusControllerSubclassName(uint8_t SubclassCode) + { + switch (SubclassCode) + { + case 0x00: + return "FireWire (IEEE 1394) Controller"; + case 0x01: + return "ACCESS Bus Controller"; + case 0x02: + return "SSA Controller"; + case 0x03: + return "USB Controller"; + case 0x04: + return "Fibre Channel Controller"; + case 0x05: + return "SMBus Controller"; + case 0x06: + return "Infiniband Controller"; + case 0x07: + return "IPMI Interface Controller"; + case 0x08: + return "SERCOS Interface (IEC 61491) Controller"; + case 0x09: + return "CANbus Controller"; + case 0x80: + return "Serial Bus Controller"; + default: + break; + } + fixme("Unknown serial bus controller %02x", SubclassCode); + return u8ToHexString(SubclassCode); + } + + const char *BridgeDeviceSubclassName(uint8_t SubclassCode) + { + switch (SubclassCode) + { + case 0x00: + return "Host Bridge"; + case 0x01: + return "ISA Bridge"; + case 0x02: + return "EISA Bridge"; + case 0x03: + return "MCA Bridge"; + case 0x04: + return "PCI-to-PCI Bridge"; + case 0x05: + return "PCMCIA Bridge"; + case 0x06: + return "NuBus Bridge"; + case 0x07: + return "CardBus Bridge"; + case 0x08: + return "RACEway Bridge"; + case 0x09: + return "PCI-to-PCI Bridge"; + case 0x0A: + return "InfiniBand-to-PCI Host Bridge"; + case 0x80: + return "Bridge Device"; + default: + break; + } + fixme("Unknown bridge device %02x", SubclassCode); + return u8ToHexString(SubclassCode); + } + + const char *WirelessControllerSubclassName(uint8_t SubclassCode) + { + switch (SubclassCode) + { + case 0x11: + return "Bluetooth"; + case 0x20: + return "802.1a controller"; + case 0x21: + return "802.1b controller"; + case 0x80: + return "Wireless controller"; + default: + break; + } + fixme("Unknown wireless controller %02x", SubclassCode); + return u8ToHexString(SubclassCode); + } + + const char *GetVendorName(uint32_t VendorID) + { + switch (VendorID) + { + case 0x1000: + return "Symbios Logic"; + case 0x1B36: + case 0x1AF4: + return "Red Hat, Inc."; + case 0x10EC: + return "Realtek Semiconductor Co., Ltd."; + case 0x80EE: + return "VirtualBox"; + case 0x1274: + return "Ensoniq"; + case 0x1234: + return "QEMU"; + case 0x15AD: + return "VMware"; + case 0x8086: + return "Intel Corporation"; + case 0x1022: + return "Advanced Micro Devices, Inc."; + case 0x10DE: + return "NVIDIA Corporation"; + case 0x1AE0: + return "Google, Inc."; + case 0x1a58: + return "Razer USA Ltd."; + case 0x1414: + return "Microsoft Corporation"; + default: + break; + } + fixme("Unknown vendor %04x", VendorID); + return u32ToHexString(VendorID); + } + + const char *GetDeviceName(uint32_t VendorID, uint32_t DeviceID) + { + switch (VendorID) + { + case SymbiosLogic: + { + switch (DeviceID) + { + case 0x30: + return "53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI"; + case 0x1000: + return "63C815"; + default: + break; + } + break; + } + case RedHat: + { + switch (DeviceID) + { + case 0x1000: + case 0x1041: + return "Virtio network device"; + case 0x1001: + case 0x1042: + return "Virtio block device"; + case 0x1002: + case 0x1045: + return "Virtio memory balloon"; + case 0x1003: + case 0x1043: + return "Virtio console"; + case 0x1004: + case 0x1048: + return "Virtio SCSI"; + case 0x1005: + case 0x1044: + return "Virtio RNG"; + case 0x1009: + case 0x1049: + case 0x105a: + return "Virtio filesystem"; + case 0x1050: + return "Virtio GPU"; + case 0x1052: + return "Virtio input"; + case 0x1053: + return "Virtio socket"; + case 1110: + return "Inter-VM shared memory"; + case 0x1af41100: + return "QEMU Virtual Machine"; + default: + break; + } + break; + } + case REDHat2: + { + switch (DeviceID) + { + case 0x0001: + return "QEMU PCI-PCI bridge"; + case 0x0002: + return "QEMU PCI 16550A Adapter"; + case 0x0003: + return "QEMU PCI Dual-port 16550A Adapter"; + case 0x0004: + return "QEMU PCI Quad-port 16550A Adapter"; + case 0x0005: + return "QEMU PCI Test Device"; + case 0x0006: + return "PCI Rocker Ethernet switch device"; + case 0x0007: + return "PCI SD Card Host Controller Interface"; + case 0x0008: + return "QEMU PCIe Host bridge"; + case 0x0009: + return "QEMU PCI Expander bridge"; + case 0x000A: + return "PCI-PCI bridge (multiseat)"; + case 0x000B: + return "QEMU PCIe Expander bridge"; + case 0x000C: + return "QEMU PCIe Root port"; + case 0x000D: + return "QEMU XHCI Host Controller"; + case 0x0010: + return "QEMU NVM Express Controller"; + case 0x0100: + return "QXL paravirtual graphic card"; + case 0x1AF41100: + return "QEMU Virtual Machine"; + default: + break; + } + break; + } + case Realtek: + { + switch (DeviceID) + { + case 0x8029: + return "RTL-8029(AS)"; + case 0x8139: + return "RTL-8139/8139C/8139C+ Ethernet Controller"; + default: + break; + } + break; + } + case VirtualBox: + { + switch (DeviceID) + { + case 0xCAFE: + return "VirtualBox Guest Service"; + case 0xBEEF: + return "VirtualBox Graphics Adapter"; + case 0x0021: + return "USB Tablet"; + case 0x0022: + return "Multitouch tablet"; + case 0x4E56: + return "NVM Express"; + default: + break; + } + break; + } + case Ensoniq: + { + switch (DeviceID) + { + case 0x5000: + return "ES1370 [AudioPCI]"; + default: + break; + } + break; + } + case QEMU: + { + switch (DeviceID) + { + case 0x1111: + return "QEMU Display"; + default: + break; + } + break; + } + case VMware: + { + switch (DeviceID) + { + case 0x0740: + return "Virtual Machine Communication Interface"; + case 0x0405: + return "SVGA II Adapter"; + case 0x0790: + return "PCI bridge"; + case 0x07A0: + return "PCI Express Root Port"; + case 0x0774: + return "USB1.1 UHCI Controller"; + case 0x0770: + return "USB2 EHCI Controller"; + case 0x0779: + return "USB3 xHCI 1.0 Controller"; + case 0x07F0: + return "NVM Express"; + default: + break; + } + break; + } + case IntelCorporation: + { + switch (DeviceID) + { + case 0x1229: + return "82557/8/9/0/1 Ethernet Pro 100"; + case 0x1209: + return "8255xER/82551IT Fast Ethernet Controller"; + case 0x100E: + return "82540EM Gigabit Ethernet Controller"; + case 0x7190: + return "440BX/ZX/DX - 82443BX/ZX/DX Host bridge"; + case 0x7191: + return "440BX/ZX/DX - 82443BX/ZX/DX AGP bridge"; + case 0x7110: + return "82371AB/EB/MB PIIX4 ISA"; + case 0x7111: + return "82371AB/EB/MB PIIX4 IDE"; + case 0x7113: + return "82371AB/EB/MB PIIX4 ACPI"; + case 0x1e31: + return "7 Series/C210 Series Chipset Family USB xHCI Host Controller"; + case 0x100F: + return "82545EM Gigabit Ethernet Controller (Copper)"; + case 0x1371: + return "ES1371/ES1373 / Creative Labs CT2518"; + case 0x27b9: + return "82801GBM (ICH7-M) LPC Interface Bridge"; + case 0x07E0: + return "SATA AHCI controller"; + case 0x293E: + return "82801I (ICH9 Family) HD Audio Controller"; + case 0x2935: + return "82801I (ICH9 Family) USB UHCI Controller #2"; + case 0x2936: + return "82801I (ICH9 Family) USB UHCI Controller #3"; + case 0x293A: + return "82801I (ICH9 Family) USB2 EHCI Controller #1"; + case 0x2934: + return "82801I (ICH9 Family) USB UHCI Controller #1"; + case 0x2668: + return "82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller"; + case 0x2415: + return "82801AA AC'97 Audio Controller"; + case 0x10D3: + return "82574L Gigabit Network Connection"; + case 0x29C0: + return "82G33/G31/P35/P31 Express DRAM Controller"; + case 0x2918: + return "82801IB (ICH9) LPC Interface Controller"; + case 0x2829: + return "82801HM/HEM (ICH8M/ICH8M-E) SATA Controller [AHCI mode]"; + case 0x2922: + return "82801IR/IO/IH (ICH9R/DO/DH) 6 port SATA Controller [AHCI mode]"; + case 0x2930: + return "82801I (ICH9 Family) SMBus Controller"; + default: + break; + } + break; + } + case AdvancedMicroDevices: + { + switch (DeviceID) + { + case 0x2000: + return "79C970 [PCnet32 LANCE]"; + default: + break; + } + break; + } + } + fixme("Unknown device %04x:%04x", VendorID, DeviceID); + return u32ToHexString(DeviceID); + } + + const char *GetSubclassName(uint8_t ClassCode, uint8_t SubclassCode) + { + switch (ClassCode) + { + case 0x00: + return "Unclassified"; + case 0x01: + return MassStorageControllerSubclassName(SubclassCode); + case 0x02: + return NetworkControllerSubclassName(SubclassCode); + case 0x03: + return DisplayControllerSubclassName(SubclassCode); + case 0x04: + return "Multimedia controller"; + case 0x05: + return "Memory Controller"; + case 0x06: + return BridgeDeviceSubclassName(SubclassCode); + case 0x07: + return CommunicationControllerSubclassName(SubclassCode); + case 0x08: + return BaseSystemPeripheralSubclassName(SubclassCode); + case 0x09: + return "Input device controller"; + case 0x0A: + return "Docking station"; + case 0x0B: + return "Processor"; + case 0x0C: + return SerialBusControllerSubclassName(SubclassCode); + case 0x0D: + return WirelessControllerSubclassName(SubclassCode); + case 0x0E: + return "Intelligent controller"; + case 0x0F: + return "Satellite communication controller"; + case 0x10: + return "Encryption controller"; + case 0x11: + return "Signal processing accelerators"; + case 0x12: + return "Processing accelerators"; + case 0x13: + return "Non-Essential Instrumentation"; + case 0x40: + return "Coprocessor"; + default: + break; + } + fixme("Unknown subclass name %02x:%02x", ClassCode, SubclassCode); + return u8ToHexString(SubclassCode); + } + + const char *GetProgIFName(uint8_t ClassCode, uint8_t SubclassCode, uint8_t ProgIF) + { + switch (ClassCode) + { + case 0x01: + { + switch (SubclassCode) + { + case 0x06: + { + switch (ProgIF) + { + case 0: + return "Vendor Specific SATA Controller"; + case 1: + return "AHCI SATA Controller"; + case 2: + return "Serial Storage Bus SATA Controller"; + default: + return "SATA controller"; + } + break; + } + case 0x08: + { + switch (ProgIF) + { + case 0x01: + return "NVMHCI Controller"; + case 0x02: + return "NVM Express Controller"; + default: + return "Non-Volatile Memory Controller"; + } + break; + } + } + break; + } + case 0x03: + { + switch (SubclassCode) + { + case 0x00: + switch (ProgIF) + { + case 0x00: + return "VGA Controller"; + case 0x01: + return "8514-Compatible Controller"; + default: + return "VGA Compatible Controller"; + } + break; + } + break; + } + case 0x07: + { + switch (SubclassCode) + { + case 0x00: + { + switch (ProgIF) + { + case 0x00: + return "Serial controller <8250>"; + case 0x01: + return "Serial controller <16450>"; + case 0x02: + return "Serial controller <16550>"; + case 0x03: + return "Serial controller <16650>"; + case 0x04: + return "Serial controller <16750>"; + case 0x05: + return "Serial controller <16850>"; + case 0x06: + return "Serial controller <16950"; + default: + return "Serial controller"; + } + break; + } + default: + break; + } + break; + } + case 0x0C: + { + switch (SubclassCode) + { + case 0x00: + switch (ProgIF) + { + case 0x00: + return "Generic FireWire (IEEE 1394) Controller"; + case 0x10: + return "OHCI FireWire (IEEE 1394) Controller"; + default: + break; + } + case 0x03: + switch (ProgIF) + { + case 0x00: + return "UHCI (USB1) Controller"; + case 0x10: + return "OHCI (USB1) Controller"; + case 0x20: + return "EHCI (USB2) Controller"; + case 0x30: + return "XHCI (USB3) Controller"; + case 0x80: + return "Unspecified"; + case 0xFE: + return "USB Device"; + default: + break; + } + default: + break; + } + break; + } + } + // not really a fixme + // fixme("Unknown prog IF name %02x:%02x:%02x", ClassCode, SubclassCode, ProgIF); + return u8ToHexString(ProgIF); + } + } + +#ifdef DEBUG + void e(PCIDeviceHeader *hdr) + { + debug("%s / %s / %s / %s / %s", + Descriptors::GetVendorName(hdr->VendorID), + Descriptors::GetDeviceName(hdr->VendorID, hdr->DeviceID), + Descriptors::DeviceClasses[hdr->Class], + Descriptors::GetSubclassName(hdr->Class, hdr->Subclass), + Descriptors::GetProgIFName(hdr->Class, hdr->Subclass, hdr->ProgIF)); + } +#endif + + void PCI::EnumerateFunction(uint64_t DeviceAddress, uint64_t Function) + { + uint64_t Offset = Function << 12; + uint64_t FunctionAddress = DeviceAddress + Offset; + Memory::Virtual().Map((void *)FunctionAddress, (void *)FunctionAddress, Memory::PTFlag::RW); + PCIDeviceHeader *PCIDeviceHdr = (PCIDeviceHeader *)FunctionAddress; + if (PCIDeviceHdr->DeviceID == 0) + return; + if (PCIDeviceHdr->DeviceID == 0xFFFF) + return; + Devices.push_back(PCIDeviceHdr); +#ifdef DEBUG + e(PCIDeviceHdr); +#endif + } + + void PCI::EnumerateDevice(uint64_t BusAddress, uint64_t Device) + { + uint64_t Offset = Device << 15; + uint64_t DeviceAddress = BusAddress + Offset; + Memory::Virtual().Map((void *)DeviceAddress, (void *)DeviceAddress, Memory::PTFlag::RW); + PCIDeviceHeader *PCIDeviceHdr = (PCIDeviceHeader *)DeviceAddress; + if (PCIDeviceHdr->DeviceID == 0) + return; + if (PCIDeviceHdr->DeviceID == 0xFFFF) + return; + for (uint64_t Function = 0; Function < 8; Function++) + EnumerateFunction(DeviceAddress, Function); + } + + void PCI::EnumerateBus(uint64_t BaseAddress, uint64_t Bus) + { + uint64_t Offset = Bus << 20; + uint64_t BusAddress = BaseAddress + Offset; + Memory::Virtual().Map((void *)BusAddress, (void *)BusAddress, Memory::PTFlag::RW); + PCIDeviceHeader *PCIDeviceHdr = (PCIDeviceHeader *)BusAddress; + if (Bus != 0) // TODO: VirtualBox workaround (UNTESTED ON REAL HARDWARE!) + { + if (PCIDeviceHdr->DeviceID == 0) + return; + if (PCIDeviceHdr->DeviceID == 0xFFFF) + return; + } + trace("PCI Bus DeviceID:%#llx VendorID:%#llx BIST:%#llx Cache:%#llx Class:%#llx Cmd:%#llx HdrType:%#llx LatencyTimer:%#llx ProgIF:%#llx RevID:%#llx Status:%#llx SubClass:%#llx ", + PCIDeviceHdr->DeviceID, PCIDeviceHdr->VendorID, PCIDeviceHdr->BIST, + PCIDeviceHdr->CacheLineSize, PCIDeviceHdr->Class, PCIDeviceHdr->Command, + PCIDeviceHdr->HeaderType, PCIDeviceHdr->LatencyTimer, PCIDeviceHdr->ProgIF, + PCIDeviceHdr->RevisionID, PCIDeviceHdr->Status, PCIDeviceHdr->Subclass); + for (uint64_t Device = 0; Device < 32; Device++) + EnumerateDevice(BusAddress, Device); + } + + Vector PCI::FindPCIDevice(uint8_t Class, uint8_t Subclass, uint8_t ProgIF) + { + Vector DeviceFound; + for (auto var : Devices) + if (var->Class == Class && var->Subclass == Subclass && var->ProgIF == ProgIF) + DeviceFound.push_back(var); + return DeviceFound; + } + + Vector PCI::FindPCIDevice(int VendorID, int DeviceID) + { + Vector DeviceFound; + for (auto var : Devices) + if (var->VendorID == VendorID && var->DeviceID == DeviceID) + DeviceFound.push_back(var); + return DeviceFound; + } + + PCI::PCI() + { + // int Entries = ((MCFG->Header.Length) - sizeof(ACPI::ACPI::MCFGHeader)) / sizeof(DeviceConfig); + // for (int t = 0; t < Entries; t++) + // { + // DeviceConfig *NewDeviceConfig = (DeviceConfig *)((uint64_t)MCFG + sizeof(ACPI::ACPI::MCFGHeader) + (sizeof(DeviceConfig) * t)); + // Memory::Virtual().Map((void *)NewDeviceConfig->BaseAddress, (void *)NewDeviceConfig->BaseAddress, Memory::PTFlag::RW); + // trace("PCI Entry %d Address:%#llx BUS:%#llx-%#llx", t, NewDeviceConfig->BaseAddress, + // NewDeviceConfig->StartBus, NewDeviceConfig->EndBus); + // for (uint64_t Bus = NewDeviceConfig->StartBus; Bus < NewDeviceConfig->EndBus; Bus++) + // EnumerateBus(NewDeviceConfig->BaseAddress, Bus); + // } + } + + PCI::~PCI() + { + } +} diff --git a/Core/Power.cpp b/Core/Power.cpp new file mode 100644 index 0000000..6204cb5 --- /dev/null +++ b/Core/Power.cpp @@ -0,0 +1,81 @@ +#include + +#include +#include "../kernel.h" +#include + +#if defined(__amd64__) +#include "../arch/amd64/acpi.hpp" + +namespace Power +{ + void Power::Reboot() + { + } + + void Power::Shutdown() + { + } + + Power::Power() + { + this->acpi = new ACPI::ACPI(bInfo); + this->dsdt = new ACPI::DSDT((ACPI::ACPI *)acpi); + this->madt = new ACPI::MADT(((ACPI::ACPI *)acpi)->MADT); + trace("Power manager initialized"); + } + + Power::~Power() + { + } +} + +#elif defined(__i386__) + +namespace Power +{ + void Power::Reboot() + { + warn("Reboot not implemented for i386"); + } + + void Power::Shutdown() + { + warn("Shutdown not implemented for i386"); + } + + Power::Power() + { + error("Power not implemented for i386"); + } + + Power::~Power() + { + } +} + +#elif defined(__aarch64__) + +namespace Power +{ + void Power::Reboot() + { + warn("Reboot not implemented for aarch64"); + } + + void Power::Shutdown() + { + warn("Shutdown not implemented for aarch64"); + } + + Power::Power() + { + error("Power not implemented for aarch64"); + } + + Power::~Power() + { + } +} + +#endif \ No newline at end of file diff --git a/core/README.md b/Core/README.md similarity index 100% rename from core/README.md rename to Core/README.md diff --git a/core/StackGuard.c b/Core/StackGuard.c similarity index 100% rename from core/StackGuard.c rename to Core/StackGuard.c diff --git a/core/Symbols.cpp b/Core/Symbols.cpp similarity index 100% rename from core/Symbols.cpp rename to Core/Symbols.cpp diff --git a/arch/Time.cpp b/Core/Time.cpp similarity index 100% rename from arch/Time.cpp rename to Core/Time.cpp diff --git a/arch/UniversalAsynchronousReceiverTransmitter.cpp b/Core/UniversalAsynchronousReceiverTransmitter.cpp similarity index 94% rename from arch/UniversalAsynchronousReceiverTransmitter.cpp rename to Core/UniversalAsynchronousReceiverTransmitter.cpp index 7a239c1..e8618bb 100644 --- a/arch/UniversalAsynchronousReceiverTransmitter.cpp +++ b/Core/UniversalAsynchronousReceiverTransmitter.cpp @@ -4,6 +4,9 @@ #include #include +volatile bool serialports[8] = {false, false, false, false, false, false, false, false}; +Vector RegisteredEvents; + namespace UniversalAsynchronousReceiverTransmitter { #define SERIAL_ENABLE_DLAB 0x80 @@ -11,10 +14,6 @@ namespace UniversalAsynchronousReceiverTransmitter #define SERIAL_RATE_38400_HI 0x00 #define SERIAL_BUFFER_EMPTY 0x20 - volatile bool serialports[8] = {false, false, false, false, false, false, false, false}; - - Vector RegisteredEvents; - UART::UART(SerialPorts Port) { #if defined(__amd64__) || defined(__i386__) diff --git a/core/Video/Display.cpp b/Core/Video/Display.cpp similarity index 93% rename from core/Video/Display.cpp rename to Core/Video/Display.cpp index 3ba6bb0..34e465f 100644 --- a/core/Video/Display.cpp +++ b/Core/Video/Display.cpp @@ -2,9 +2,9 @@ #include #include -extern uint64_t _binary_files_ter_powerline_v12n_psf_start; -extern uint64_t _binary_files_ter_powerline_v12n_psf_end; -extern uint64_t _binary_files_ter_powerline_v12n_psf_size; +extern uint64_t _binary_Files_ter_powerline_v12n_psf_start; +extern uint64_t _binary_Files_ter_powerline_v12n_psf_end; +extern uint64_t _binary_Files_ter_powerline_v12n_psf_size; NEWLOCK(PrintLock); @@ -105,7 +105,7 @@ namespace Video this->framebuffer = Info; if (LoadDefaultFont) { - this->CurrentFont = new Font(&_binary_files_ter_powerline_v12n_psf_start, &_binary_files_ter_powerline_v12n_psf_end, FontType::PCScreenFont2); + this->CurrentFont = new Font(&_binary_Files_ter_powerline_v12n_psf_start, &_binary_Files_ter_powerline_v12n_psf_end, FontType::PCScreenFont2); FontInfo Info = this->CurrentFont->GetInfo(); debug("Font loaded: %dx%d %s", Info.Width, Info.Height, Info.Type == FontType::PCScreenFont1 ? "PSF1" : "PSF2"); diff --git a/core/Video/Font.cpp b/Core/Video/Font.cpp similarity index 100% rename from core/Video/Font.cpp rename to Core/Video/Font.cpp diff --git a/Kernel.cpp b/Kernel.cpp index 67ed447..17e978e 100644 --- a/Kernel.cpp +++ b/Kernel.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -12,6 +13,7 @@ BootInfo *bInfo = nullptr; Video::Display *Display = nullptr; SymbolResolver::Symbols *KernelSymbolTable = nullptr; +Power::Power *PowerManager = nullptr; // For the Display class. Printing on first buffer. extern "C" void putchar(char c) { Display->Print(c, 0); } @@ -33,14 +35,14 @@ void KPrint(const char *format, ...) Display->SetBuffer(0); } -EXTERNC void kernel_aarch64_entry(uint64_t dtb_ptr32, uint64_t x1, uint64_t x2, uint64_t x3) +EXTERNC void aarch64Entry(uint64_t dtb_ptr32, uint64_t x1, uint64_t x2, uint64_t x3) { trace("Hello, World!"); while (1) CPU::Halt(); } -EXTERNC void kernel_entry(BootInfo *Info) +EXTERNC void Entry(BootInfo *Info) { trace("Hello, World!"); InitializeMemoryManagement(Info); @@ -54,6 +56,8 @@ EXTERNC void kernel_entry(BootInfo *Info) Interrupts::Initialize(); KPrint("Loading kernel symbols"); KernelSymbolTable = new SymbolResolver::Symbols((uint64_t)Info->Kernel.FileBase); + KPrint("Initializing Power Manager"); + PowerManager = new Power::Power; while (1) CPU::Halt(); } diff --git a/lib/Bitmap.cpp b/Library/Bitmap.cpp similarity index 100% rename from lib/Bitmap.cpp rename to Library/Bitmap.cpp diff --git a/lib/String.c b/Library/String.c similarity index 100% rename from lib/String.c rename to Library/String.c diff --git a/lib/cxxabi.cpp b/Library/cxxabi.cpp similarity index 100% rename from lib/cxxabi.cpp rename to Library/cxxabi.cpp diff --git a/lib/liballoc_1_1.c b/Library/liballoc_1_1.c similarity index 100% rename from lib/liballoc_1_1.c rename to Library/liballoc_1_1.c diff --git a/lib/liballoc_1_1.h b/Library/liballoc_1_1.h similarity index 100% rename from lib/liballoc_1_1.h rename to Library/liballoc_1_1.h diff --git a/lib/liballocimpl.cpp b/Library/liballocimpl.cpp similarity index 100% rename from lib/liballocimpl.cpp rename to Library/liballocimpl.cpp diff --git a/lib/printf.c b/Library/printf.c similarity index 100% rename from lib/printf.c rename to Library/printf.c diff --git a/Makefile b/Makefile index 57ab994..d7798a7 100644 --- a/Makefile +++ b/Makefile @@ -100,9 +100,9 @@ default: $(error Please specify a target) prepare: - rm -f ./files/ter-powerline-v12n.psf - wget https://raw.githubusercontent.com/powerline/fonts/master/Terminus/PSF/ter-powerline-v12n.psf.gz -P files - gzip -d files/ter-powerline-v12n.psf.gz + rm -f ./Files/ter-powerline-v12n.psf + wget https://raw.githubusercontent.com/powerline/fonts/master/Terminus/PSF/ter-powerline-v12n.psf.gz -P Files + gzip -d Files/ter-powerline-v12n.psf.gz build: $(KERNEL_FILENAME) $(OBJDUMP) -D -d $(KERNEL_FILENAME) > kernel_dump.map diff --git a/arch/aarch64/boot.S b/arch/aarch64/boot.S index ece3d73..5d524b2 100644 --- a/arch/aarch64/boot.S +++ b/arch/aarch64/boot.S @@ -11,7 +11,7 @@ _start: str xzr, [x5], #8 sub w6, w6, #1 cbnz w6, 1b -2: bl kernel_aarch64_entry +2: bl aarch64Entry Halt: wfe b Halt diff --git a/arch/amd64/AdvancedConfigurationandPowerInterface.cpp b/arch/amd64/AdvancedConfigurationandPowerInterface.cpp new file mode 100644 index 0000000..3205334 --- /dev/null +++ b/arch/amd64/AdvancedConfigurationandPowerInterface.cpp @@ -0,0 +1,127 @@ +#include "acpi.hpp" + +#include +#include + +#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" + +namespace ACPI +{ + void *ACPI::FindTable(ACPI::ACPIHeader *ACPIHeader, char *Signature) + { + for (uint64_t t = 0; t < ((ACPIHeader->Length - sizeof(ACPI::ACPIHeader)) / (XSDTSupported ? 8 : 4)); t++) + { + // Should I be concerned about unaligned memory access? + ACPI::ACPIHeader *SDTHdr = nullptr; + if (XSDTSupported) + SDTHdr = (ACPI::ACPIHeader *)(*(uint64_t *)((uint64_t)ACPIHeader + sizeof(ACPI::ACPIHeader) + (t * 8))); + else + SDTHdr = (ACPI::ACPIHeader *)(*(uint32_t *)((uint64_t)ACPIHeader + sizeof(ACPI::ACPIHeader) + (t * 4))); + + for (uint64_t i = 0; i < 4; i++) + { + if (SDTHdr->Signature[i] != Signature[i]) + break; + if (i == 3) + { + trace("%s found!", Signature); + return SDTHdr; + } + } + } + // warn("%s not found!", Signature); + return 0; + } + + void ACPI::SearchTables(ACPIHeader *Header) + { + if (!Header) + return; + + HPET = (HPETHeader *)FindTable(XSDT, (char *)"HPET"); + FADT = (FADTHeader *)FindTable(XSDT, (char *)"FACP"); + MCFG = (MCFGHeader *)FindTable(XSDT, (char *)"MCFG"); + BGRT = (BGRTHeader *)FindTable(XSDT, (char *)"BGRT"); + SRAT = (SRATHeader *)FindTable(XSDT, (char *)"SRAT"); + TPM2 = (TPM2Header *)FindTable(XSDT, (char *)"TPM2"); + TCPA = (TCPAHeader *)FindTable(XSDT, (char *)"TCPA"); + WAET = (WAETHeader *)FindTable(XSDT, (char *)"WAET"); + MADT = (MADTHeader *)FindTable(XSDT, (char *)"APIC"); + HEST = (HESTHeader *)FindTable(XSDT, (char *)"HEST"); + FindTable(XSDT, (char *)"BERT"); + FindTable(XSDT, (char *)"CPEP"); + FindTable(XSDT, (char *)"DSDT"); + FindTable(XSDT, (char *)"ECDT"); + FindTable(XSDT, (char *)"EINJ"); + FindTable(XSDT, (char *)"ERST"); + FindTable(XSDT, (char *)"FACS"); + FindTable(XSDT, (char *)"MSCT"); + FindTable(XSDT, (char *)"MPST"); + FindTable(XSDT, (char *)"OEMx"); + FindTable(XSDT, (char *)"PMTT"); + FindTable(XSDT, (char *)"PSDT"); + FindTable(XSDT, (char *)"RASF"); + FindTable(XSDT, (char *)"RSDT"); + FindTable(XSDT, (char *)"SBST"); + FindTable(XSDT, (char *)"SLIT"); + FindTable(XSDT, (char *)"SSDT"); + FindTable(XSDT, (char *)"XSDT"); + FindTable(XSDT, (char *)"DRTM"); + FindTable(XSDT, (char *)"FPDT"); + FindTable(XSDT, (char *)"GTDT"); + FindTable(XSDT, (char *)"PCCT"); + FindTable(XSDT, (char *)"S3PT"); + FindTable(XSDT, (char *)"MATR"); + FindTable(XSDT, (char *)"MSDM"); + FindTable(XSDT, (char *)"WPBT"); + FindTable(XSDT, (char *)"OSDT"); + FindTable(XSDT, (char *)"RSDP"); + FindTable(XSDT, (char *)"NFIT"); + FindTable(XSDT, (char *)"ASF!"); + FindTable(XSDT, (char *)"BOOT"); + FindTable(XSDT, (char *)"CSRT"); + FindTable(XSDT, (char *)"DBG2"); + FindTable(XSDT, (char *)"DBGP"); + FindTable(XSDT, (char *)"DMAR"); + FindTable(XSDT, (char *)"IBFT"); + FindTable(XSDT, (char *)"IORT"); + FindTable(XSDT, (char *)"IVRS"); + FindTable(XSDT, (char *)"LPIT"); + FindTable(XSDT, (char *)"MCHI"); + FindTable(XSDT, (char *)"MTMR"); + FindTable(XSDT, (char *)"SLIC"); + FindTable(XSDT, (char *)"SPCR"); + FindTable(XSDT, (char *)"SPMI"); + FindTable(XSDT, (char *)"UEFI"); + FindTable(XSDT, (char *)"VRTC"); + FindTable(XSDT, (char *)"WDAT"); + FindTable(XSDT, (char *)"WDDT"); + FindTable(XSDT, (char *)"WDRT"); + } + + ACPI::ACPI(BootInfo *Info) + { + trace("Initializing ACPI"); + if (Info->RSDP->Revision >= 2 && Info->RSDP->XSDTAddress) + { + debug("XSDT supported"); + XSDTSupported = true; + XSDT = (ACPIHeader *)(Info->RSDP->XSDTAddress); + } + else + { + debug("RSDT supported"); + XSDT = (ACPIHeader *)(uintptr_t)Info->RSDP->RSDTAddress; + } + + this->SearchTables(XSDT); + + outb(FADT->SMI_CommandPort, FADT->AcpiEnable); + while (!(inw(FADT->PM1aControlBlock) & 1)) + ; + } + + ACPI::~ACPI() + { + } +} diff --git a/arch/amd64/DifferentiatedSystemDescriptionTable.cpp b/arch/amd64/DifferentiatedSystemDescriptionTable.cpp new file mode 100644 index 0000000..1a2735a --- /dev/null +++ b/arch/amd64/DifferentiatedSystemDescriptionTable.cpp @@ -0,0 +1,225 @@ +#include "acpi.hpp" + +#include +#include +#include + +// #include "../timer.h" +// #include "apic.hpp" +// #include "smp.hpp" + +#define ACPI_TIMER 0x0001 +#define ACPI_BUSMASTER 0x0010 +#define ACPI_GLOBAL 0x0020 +#define ACPI_POWER_BUTTON 0x0100 +#define ACPI_SLEEP_BUTTON 0x0200 +#define ACPI_RTC_ALARM 0x0400 +#define ACPI_PCIE_WAKE 0x4000 +#define ACPI_WAKE 0x8000 + +namespace ACPI +{ + __attribute__((always_inline)) inline bool IsCanonical(uint64_t Address) + { + return ((Address <= 0x00007FFFFFFFFFFF) || ((Address >= 0xFFFF800000000000) && (Address <= 0xFFFFFFFFFFFFFFFF))); + } + +#define ACPI_ENABLED 0x0001 +#define ACPI_SLEEP 0x2000 + +#define ACPI_GAS_MMIO 0 +#define ACPI_GAS_IO 1 +#define ACPI_GAS_PCI 2 + + void DSDT::SCIHandler(CPU::x64::TrapFrame *regs) + { + debug("SCI Handle Triggered"); + uint16_t event = this->GetSCIevent(); + debug("SCI Event: %#llx", event); + if (event & ACPI_TIMER) + event &= ~ACPI_TIMER; // Remove the ACPI timer flag. + switch (event) + { + case ACPI_POWER_BUTTON: + { + this->Shutdown(); + Time tm = ReadClock(); + while (tm.Second == ReadClock().Second) + ; + outw(0xB004, 0x2000); + outw(0x604, 0x2000); + outw(0x4004, 0x3400); + CPU::Stop(); + break; + } + default: + { + warn("unknown event 0x%04p", event); + return; + } + } + UNUSED(regs); + } + + void DSDT::Shutdown() + { + trace("Shutting down..."); + if (!ACPIShutdownSupported) + { + outl(0xB004, 0x2000); // for qemu + outl(0x604, 0x2000); // if qemu not working, bochs and older versions of qemu + outl(0x4004, 0x3400); // virtual box + } + else if (SCI_EN == 1) + { + outw(acpi->FADT->PM1aControlBlock, (inw(acpi->FADT->PM1aControlBlock) & 0xE3FF) | ((SLP_TYPa << 10) | ACPI_SLEEP)); + if (acpi->FADT->PM1bControlBlock) + outw(acpi->FADT->PM1bControlBlock, (inw(acpi->FADT->PM1bControlBlock) & 0xE3FF) | ((SLP_TYPb << 10) | ACPI_SLEEP)); + outw(PM1a_CNT, SLP_TYPa | SLP_EN); + if (PM1b_CNT) + outw(PM1b_CNT, SLP_TYPb | SLP_EN); + } + CPU::Stop(); + } + + void DSDT::Reboot() + { + trace("Rebooting..."); + if (!ACPIShutdownSupported) + { + uint8_t val = 0x02; + while (val & 0x02) + val = inb(0x64); + outb(0x64, 0xFE); + + warn("Executing the second attempt to reboot..."); + + // second attempt to reboot + // https://wiki.osdev.org/Reboot + uint8_t temp; + asm volatile("cli"); + do + { + temp = inb(0x64); + if (((temp) & (1 << (0))) != 0) + inb(0x60); + } while (((temp) & (1 << (1))) != 0); + outb(0x64, 0xFE); + + CPU::Stop(); + } + switch (acpi->FADT->ResetReg.AddressSpace) + { + case ACPI_GAS_MMIO: + *(uint8_t *)(acpi->FADT->ResetReg.Address) = acpi->FADT->ResetValue; + break; + case ACPI_GAS_IO: + outb(acpi->FADT->ResetReg.Address, acpi->FADT->ResetValue); + break; + case ACPI_GAS_PCI: + fixme("ACPI_GAS_PCI not supported."); + /* + seg - 0 + bus - 0 + dev - (FADT->ResetReg.Address >> 32) & 0xFFFF + function - (FADT->ResetReg.Address >> 16) & 0xFFFF + offset - FADT->ResetReg.Address & 0xFFFF + value - FADT->ResetValue + */ + break; + } + CPU::Stop(); + } + + uint16_t DSDT::GetSCIevent() + { + uint16_t a = 0, b = 0; + if (acpi->FADT->PM1aEventBlock) + { + a = inw(acpi->FADT->PM1aEventBlock); + outw(acpi->FADT->PM1aEventBlock, a); + } + if (acpi->FADT->PM1bEventBlock) + { + b = inw(acpi->FADT->PM1bEventBlock); + outw(acpi->FADT->PM1bEventBlock, b); + } + return a | b; + } + + void DSDT::SetSCIevent(uint16_t value) + { + uint16_t a = acpi->FADT->PM1aEventBlock + (acpi->FADT->PM1EventLength / 2); + uint16_t b = acpi->FADT->PM1bEventBlock + (acpi->FADT->PM1EventLength / 2); + if (acpi->FADT->PM1aEventBlock) + outw(a, value); + if (acpi->FADT->PM1bEventBlock) + outw(b, value); + } + + void DSDT::RegisterSCIEvents() + { + this->SetSCIevent(ACPI_POWER_BUTTON | ACPI_SLEEP_BUTTON | ACPI_WAKE); + GetSCIevent(); + } + + void DSDT::InitSCI() + { + // this should be done for all CPUs + if (ACPIShutdownSupported) + { + debug("Registering SCI Handler to vector IRQ%d", acpi->FADT->SCI_Interrupt); + this->RegisterSCIEvents(); + // RegisterInterrupt(this->SCIHandler, acpi->FADT->SCI_Interrupt + CPU::x64::IRQ0, true, true); + } + } + + DSDT::DSDT(ACPI *acpi) + { + uint64_t Address = ((IsCanonical(acpi->FADT->X_Dsdt) && acpi->XSDTSupported) ? acpi->FADT->X_Dsdt : acpi->FADT->Dsdt); + uint8_t *S5Address = (uint8_t *)(Address) + 36; + ACPI::ACPI::ACPIHeader *Header = (ACPI::ACPI::ACPIHeader *)Address; + uint64_t Length = Header->Length; + Address *= 2; + while (Length-- > 0) + { + if (!memcmp(S5Address, "_S5_", 4)) + break; + S5Address++; + } + if (Length <= 0) + { + warn("_S5 not present in ACPI"); + return; + } + if ((*(S5Address - 1) == 0x08 || (*(S5Address - 2) == 0x08 && *(S5Address - 1) == '\\')) && *(S5Address + 4) == 0x12) + { + S5Address += 5; + S5Address += ((*S5Address & 0xC0) >> 6) + 2; + if (*S5Address == 0x0A) + S5Address++; + SLP_TYPa = *(S5Address) << 10; + S5Address++; + if (*S5Address == 0x0A) + S5Address++; + SLP_TYPb = *(S5Address) << 10; + SMI_CMD = acpi->FADT->SMI_CommandPort; + ACPI_ENABLE = acpi->FADT->AcpiEnable; + ACPI_DISABLE = acpi->FADT->AcpiDisable; + PM1a_CNT = acpi->FADT->PM1aControlBlock; + PM1b_CNT = acpi->FADT->PM1bControlBlock; + PM1_CNT_LEN = acpi->FADT->PM1ControlLength; + SLP_EN = 1 << 13; + SCI_EN = 1; + trace("ACPI Shutdown is supported"); + ACPIShutdownSupported = true; + return; + } + warn("Failed to parse _S5 in ACPI"); + SCI_EN = 0; + } + + DSDT::~DSDT() + { + } +} diff --git a/arch/amd64/Limine.c b/arch/amd64/Limine.c index f36d43e..22412f0 100644 --- a/arch/amd64/Limine.c +++ b/arch/amd64/Limine.c @@ -230,5 +230,5 @@ void init_limine() strcpy(binfo.Bootloader.Version, BootloaderInfoResponse->version); // Call kernel entry point - kernel_entry(&binfo); + Entry(&binfo); } diff --git a/arch/amd64/MultipleAPICDescriptionTable.cpp b/arch/amd64/MultipleAPICDescriptionTable.cpp new file mode 100644 index 0000000..d170380 --- /dev/null +++ b/arch/amd64/MultipleAPICDescriptionTable.cpp @@ -0,0 +1,64 @@ +#include "acpi.hpp" + +#include +#include + +namespace ACPI +{ + MADT::MADT(ACPI::MADTHeader *madt) + { + LAPICAddr = (LAPIC *)(uintptr_t)madt->LocalControllerAddress; + for (uint8_t *ptr = (uint8_t *)(madt->Entries); + (uintptr_t)(ptr) < (uintptr_t)(madt) + madt->Header.Length; + ptr += *(ptr + 1)) + { + switch (*(ptr)) + { + case 0: + { + if (ptr[4] & 1) + { + lapic.push_back((LocalAPIC *)ptr); + trace("Local APIC %#llx (APIC %#llx) found.", lapic.back()->ACPIProcessorId, lapic.back()->APICId); + CPUCores++; + } + break; + } + case 1: + { + ioapic.push_back((MADTIOApic *)ptr); + trace("I/O APIC %#llx (Address %#llx) found.", ioapic.back()->APICID, ioapic.back()->addr); + Memory::Virtual().Map((void *)(uintptr_t)ioapic.back()->addr, (void *)(uintptr_t)ioapic.back()->addr, Memory::PTFlag::RW | Memory::PTFlag::PCD); // Make sure that the address is mapped. + break; + } + case 2: + { + iso.push_back((MADTIso *)ptr); + trace("ISO (IRQ:%#llx, BUS:%#llx, GSI:%#llx, %s/%s) found.", + iso.back()->IRQSource, iso.back()->BuSSource, iso.back()->GSI, + iso.back()->Flags & 0x00000004 ? "Active High" : "Active Low", + iso.back()->Flags & 0x00000100 ? "Edge Triggered" : "Level Triggered"); + break; + } + case 4: + { + nmi.push_back((MADTNmi *)ptr); + trace("NMI %#llx (lint:%#llx) found.", nmi.back()->processor, nmi.back()->lint); + break; + } + case 5: + { + LAPICAddr = (LAPIC *)ptr; + trace("APIC found at %#llx", LAPICAddr); + break; + } + } + Memory::Virtual().Map((void *)LAPICAddr, (void *)LAPICAddr, Memory::PTFlag::RW | Memory::PTFlag::PCD); // I should map more than one page? + } + trace("Total CPU cores: %d", CPUCores); + } + + MADT::~MADT() + { + } +} diff --git a/arch/amd64/acpi.hpp b/arch/amd64/acpi.hpp new file mode 100644 index 0000000..fcb604d --- /dev/null +++ b/arch/amd64/acpi.hpp @@ -0,0 +1,282 @@ +#ifndef __FENNIX_KERNEL_ACPI_H__ +#define __FENNIX_KERNEL_ACPI_H__ + +#include + +#include +#include +#include +#include + +namespace ACPI +{ + class ACPI + { + public: + struct ACPIHeader + { + unsigned char Signature[4]; + uint32_t Length; + uint8_t Revision; + uint8_t Checksum; + uint8_t OEMID[6]; + uint8_t OEMTableID[8]; + uint32_t OEMRevision; + uint32_t CreatorID; + uint32_t CreatorRevision; + } __attribute__((packed)); + + struct GenericAddressStructure + { + uint8_t AddressSpace; + uint8_t BitWidth; + uint8_t BitOffset; + uint8_t AccessSize; + uint64_t Address; + } __attribute__((packed)); + + struct MCFGHeader + { + struct ACPIHeader Header; + uint64_t Reserved; + } __attribute__((packed)); + + struct HPETHeader + { + ACPIHeader header; + uint8_t hardware_rev_id; + uint8_t comparator_count : 5; + uint8_t counter_size : 1; + uint8_t reserved : 1; + uint8_t legacy_replacement : 1; + uint16_t pci_vendor_id; + struct GenericAddressStructure address; + uint8_t hpet_number; + uint16_t minimum_tick; + uint8_t page_protection; + } __attribute__((packed)); + + struct FADTHeader + { + ACPIHeader header; + uint32_t FirmwareCtrl; + uint32_t Dsdt; + uint8_t Reserved; + uint8_t PreferredPowerManagementProfile; + uint16_t SCI_Interrupt; + uint32_t SMI_CommandPort; + uint8_t AcpiEnable; + uint8_t AcpiDisable; + uint8_t S4BIOS_REQ; + uint8_t PSTATE_Control; + uint32_t PM1aEventBlock; + uint32_t PM1bEventBlock; + uint32_t PM1aControlBlock; + uint32_t PM1bControlBlock; + uint32_t PM2ControlBlock; + uint32_t PMTimerBlock; + uint32_t GPE0Block; + uint32_t GPE1Block; + uint8_t PM1EventLength; + uint8_t PM1ControlLength; + uint8_t PM2ControlLength; + uint8_t PMTimerLength; + uint8_t GPE0Length; + uint8_t GPE1Length; + uint8_t GPE1Base; + uint8_t CStateControl; + uint16_t WorstC2Latency; + uint16_t WorstC3Latency; + uint16_t FlushSize; + uint16_t FlushStride; + uint8_t DutyOffset; + uint8_t DutyWidth; + uint8_t DayAlarm; + uint8_t MonthAlarm; + uint8_t Century; + uint16_t BootArchitectureFlags; + uint8_t Reserved2; + uint32_t Flags; + struct GenericAddressStructure ResetReg; + uint8_t ResetValue; + uint8_t Reserved3[3]; + uint64_t X_FirmwareControl; + uint64_t X_Dsdt; + struct GenericAddressStructure X_PM1aEventBlock; + struct GenericAddressStructure X_PM1bEventBlock; + struct GenericAddressStructure X_PM1aControlBlock; + struct GenericAddressStructure X_PM1bControlBlock; + struct GenericAddressStructure X_PM2ControlBlock; + struct GenericAddressStructure X_PMTimerBlock; + struct GenericAddressStructure X_GPE0Block; + struct GenericAddressStructure X_GPE1Block; + } __attribute__((packed)); + + struct BGRTHeader + { + ACPIHeader Header; + uint16_t Version; + uint8_t Status; + uint8_t ImageType; + uint64_t ImageAddress; + uint32_t ImageOffsetX; + uint32_t ImageOffsetY; + }; + + struct SRATHeader + { + ACPIHeader Header; + uint32_t TableRevision; // Must be value 1 + uint64_t Reserved; // Reserved, must be zero + }; + + struct TPM2Header + { + ACPIHeader Header; + uint32_t Flags; + uint64_t ControlAddress; + uint32_t StartMethod; + }; + + struct TCPAHeader + { + ACPIHeader Header; + uint16_t Reserved; + uint32_t MaxLogLength; + uint64_t LogAddress; + }; + + struct WAETHeader + { + ACPIHeader Header; + uint32_t Flags; + }; + + struct HESTHeader + { + ACPIHeader Header; + uint32_t ErrorSourceCount; + }; + + struct MADTHeader + { + ACPIHeader Header; + uint32_t LocalControllerAddress; + uint32_t Flags; + char Entries[]; + } __attribute__((packed)); + + ACPIHeader *XSDT = nullptr; + MCFGHeader *MCFG = nullptr; + HPETHeader *HPET = nullptr; + FADTHeader *FADT = nullptr; + BGRTHeader *BGRT = nullptr; + SRATHeader *SRAT = nullptr; + TPM2Header *TPM2 = nullptr; + TCPAHeader *TCPA = nullptr; + WAETHeader *WAET = nullptr; + MADTHeader *MADT = nullptr; + HESTHeader *HEST = nullptr; + bool XSDTSupported = false; + + void *FindTable(ACPIHeader *ACPIHeader, char *Signature); + void SearchTables(ACPIHeader *Header); + ACPI(BootInfo *Info); + ~ACPI(); + }; + + class MADT + { + public: + struct APICHeader + { + uint8_t Type; + uint8_t Length; + } __attribute__((packed)); + + struct MADTIOApic + { + struct APICHeader Header; + uint8_t APICID; + uint8_t reserved; + uint32_t addr; + uint32_t gsib; + } __attribute__((packed)); + + struct MADTIso + { + struct APICHeader Header; + uint8_t BuSSource; + uint8_t IRQSource; + uint32_t GSI; + uint16_t Flags; + } __attribute__((packed)); + + struct MADTNmi + { + struct APICHeader Header; + uint8_t processor; + uint16_t flags; + uint8_t lint; + } __attribute__((packed)); + + struct LocalAPIC + { + struct APICHeader Header; + uint8_t ACPIProcessorId; + uint8_t APICId; + uint32_t Flags; + } __attribute__((packed)); + + struct LAPIC + { + uint8_t id; + uintptr_t PhysicalAddress; + void *VirtualAddress; + }; + + Vector ioapic; + Vector iso; + Vector nmi; + Vector lapic; + struct LAPIC *LAPICAddr; + uint8_t CPUCores; + + MADT(ACPI::MADTHeader *madt); + ~MADT(); + }; + + class DSDT + { + private: + uint32_t SMI_CMD = 0; + uint8_t ACPI_ENABLE = 0; + uint8_t ACPI_DISABLE = 0; + uint32_t PM1a_CNT = 0; + uint32_t PM1b_CNT = 0; + uint16_t SLP_TYPa = 0; + uint16_t SLP_TYPb = 0; + uint16_t SLP_EN = 0; + uint16_t SCI_EN = 0; + uint8_t PM1_CNT_LEN = 0; + + ACPI *acpi; + + public: + bool ACPIShutdownSupported = false; + + void SCIHandler(CPU::x64::TrapFrame *regs); + void RegisterSCIEvents(); + void SetSCIevent(uint16_t value); + uint16_t GetSCIevent(); + + void Reboot(); + void Shutdown(); + + void InitSCI(); + DSDT(ACPI *acpi); + ~DSDT(); + }; +} + +#endif // !__FENNIX_KERNEL_ACPI_H__ diff --git a/arch/amd64/linker.ld b/arch/amd64/linker.ld index f56690c..07992d3 100644 --- a/arch/amd64/linker.ld +++ b/arch/amd64/linker.ld @@ -1,7 +1,7 @@ OUTPUT_FORMAT(elf64-x86-64) OUTPUT_ARCH(i386:x86-64) -ENTRY(kernel_entry) +ENTRY(Entry) SECTIONS { @@ -36,10 +36,4 @@ SECTIONS } . += CONSTANT(MAXPAGESIZE); _kernel_end = ALIGN(CONSTANT(MAXPAGESIZE)); - - /DISCARD/ : - { - *(.eh_frame) - *(.note .note.*) - } } diff --git a/arch/i686/linker.ld b/arch/i686/linker.ld index ab00c84..7d2fb0a 100644 --- a/arch/i686/linker.ld +++ b/arch/i686/linker.ld @@ -1,7 +1,7 @@ OUTPUT_FORMAT(elf32-i386) OUTPUT_ARCH(i386) -ENTRY(kernel_entry) +ENTRY(Entry) SECTIONS { diff --git a/include/cpu.hpp b/include/cpu.hpp index c6dc2ee..26860b6 100644 --- a/include/cpu.hpp +++ b/include/cpu.hpp @@ -53,6 +53,11 @@ namespace CPU */ void Pause(); + /** + * @brief Stop the CPU (infinite loop) + */ + void Stop(); + /** * @brief Halt the CPU */ @@ -127,6 +132,294 @@ namespace CPU namespace x64 { + typedef enum + { + DivideByZero = 0x0, + Debug = 0x1, + NonMaskableInterrupt = 0x2, + Breakpoint = 0x3, + Overflow = 0x4, + BoundRange = 0x5, + InvalidOpcode = 0x6, + DeviceNotAvailable = 0x7, + DoubleFault = 0x8, + CoprocessorSegmentOverrun = 0x9, + InvalidTSS = 0xa, + SegmentNotPresent = 0xb, + StackSegmentFault = 0xc, + GeneralProtectionFault = 0xd, + PageFault = 0xe, + x87FloatingPoint = 0x10, + AlignmentCheck = 0x11, + MachineCheck = 0x12, + SIMDFloatingPoint = 0x13, + Virtualization = 0x14, + Security = 0x1e + } ISRExceptions; + + typedef enum + { + ISR0 = 0x0, // Divide-by-zero Error + ISR1 = 0x1, // Debug + ISR2 = 0x2, // Non-maskable Interrupt + ISR3 = 0x3, // Breakpoint + ISR4 = 0x4, // Overflow + ISR5 = 0x5, // Bound Range Exceeded + ISR6 = 0x6, // Invalid Opcode + ISR7 = 0x7, // Device Not Available + ISR8 = 0x8, // Double Fault + ISR9 = 0x9, // Coprocessor Segment Overrun + ISR10 = 0xa, // Invalid TSS + ISR11 = 0xb, // Segment Not P + ISR12 = 0xc, // Stack-Segment Fault + ISR13 = 0xd, // General Protection Fault + ISR14 = 0xe, // Page Fault + ISR15 = 0xf, // Reserved + ISR16 = 0x10, // x87 Floating-Point Exception + ISR17 = 0x11, // Alignment Check + ISR18 = 0x12, // Machine Check + ISR19 = 0x13, // SIMD Floating-Point Exception + ISR20 = 0x14, // Virtualization Exception + ISR21 = 0x15, // Reserved + ISR22 = 0x16, // Reserved + ISR23 = 0x17, // Reserved + ISR24 = 0x18, // Reserved + ISR25 = 0x19, // Reserved + ISR26 = 0x1a, // Reserved + ISR27 = 0x1b, // Reserved + ISR28 = 0x1c, // Reserved + ISR29 = 0x1d, // Reserved + ISR30 = 0x1e, // Security Exception + ISR31 = 0x1f, // Reserved + + IRQ0 = 0x20, // Programmable Interrupt Timer Interrupt + IRQ1 = 0x21, // Keyboard Interrupt + IRQ2 = 0x22, // Cascade (used internally by the two PICs. never raised) + IRQ3 = 0x23, // COM2 (if enabled) + IRQ4 = 0x24, // COM1 (if enabled) + IRQ5 = 0x25, // LPT2 (if enabled) + IRQ6 = 0x26, // Floppy Disk + IRQ7 = 0x27, // LPT1 / Unreliable "spurious" interrupt (usually) + IRQ8 = 0x28, // CMOS real-time clock (if enabled) + IRQ9 = 0x29, // Free for peripherals / legacy SCSI / NIC + IRQ10 = 0x2a, // Free for peripherals / SCSI / NIC + IRQ11 = 0x2b, // Free for peripherals / SCSI / NIC + IRQ12 = 0x2c, // PS2 Mouse + IRQ13 = 0x2d, // FPU / Coprocessor / Inter-processor + IRQ14 = 0x2e, // Primary ATA Hard Disk + IRQ15 = 0x2f, // Secondary ATA Hard Disk + + IRQ16 = 0x30, // Reserved for multitasking + IRQ17 = 0x31, // Reserved for monotasking + + IRQ18 = 0x32, + IRQ19 = 0x33, + IRQ20 = 0x34, + IRQ21 = 0x35, + IRQ22 = 0x36, + IRQ23 = 0x37, + IRQ24 = 0x38, + IRQ25 = 0x39, + IRQ26 = 0x3a, + IRQ27 = 0x3b, + IRQ28 = 0x3c, + IRQ29 = 0x3d, + IRQ30 = 0x3e, + IRQ31 = 0x3f, + IRQ32 = 0x40, + IRQ33 = 0x41, + IRQ34 = 0x42, + IRQ35 = 0x43, + IRQ36 = 0x44, + IRQ37 = 0x45, + IRQ38 = 0x46, + IRQ39 = 0x47, + IRQ40 = 0x48, + IRQ41 = 0x49, + IRQ42 = 0x4a, + IRQ43 = 0x4b, + IRQ44 = 0x4c, + IRQ45 = 0x4d, + IRQ46 = 0x4e, + IRQ47 = 0x4f, + IRQ48 = 0x50, + IRQ49 = 0x51, + IRQ50 = 0x52, + IRQ51 = 0x53, + IRQ52 = 0x54, + IRQ53 = 0x55, + IRQ54 = 0x56, + IRQ55 = 0x57, + IRQ56 = 0x58, + IRQ57 = 0x59, + IRQ58 = 0x5a, + IRQ59 = 0x5b, + IRQ60 = 0x5c, + IRQ61 = 0x5d, + IRQ62 = 0x5e, + IRQ63 = 0x5f, + IRQ64 = 0x60, + IRQ65 = 0x61, + IRQ66 = 0x62, + IRQ67 = 0x63, + IRQ68 = 0x64, + IRQ69 = 0x65, + IRQ70 = 0x66, + IRQ71 = 0x67, + IRQ72 = 0x68, + IRQ73 = 0x69, + IRQ74 = 0x6a, + IRQ75 = 0x6b, + IRQ76 = 0x6c, + IRQ77 = 0x6d, + IRQ78 = 0x6e, + IRQ79 = 0x6f, + IRQ80 = 0x70, + IRQ81 = 0x71, + IRQ82 = 0x72, + IRQ83 = 0x73, + IRQ84 = 0x74, + IRQ85 = 0x75, + IRQ86 = 0x76, + IRQ87 = 0x77, + IRQ88 = 0x78, + IRQ89 = 0x79, + IRQ90 = 0x7a, + IRQ91 = 0x7b, + IRQ92 = 0x7c, + IRQ93 = 0x7d, + IRQ94 = 0x7e, + IRQ95 = 0x7f, + IRQ96 = 0x80, + IRQ97 = 0x81, + IRQ98 = 0x82, + IRQ99 = 0x83, + IRQ100 = 0x84, + IRQ101 = 0x85, + IRQ102 = 0x86, + IRQ103 = 0x87, + IRQ104 = 0x88, + IRQ105 = 0x89, + IRQ106 = 0x8a, + IRQ107 = 0x8b, + IRQ108 = 0x8c, + IRQ109 = 0x8d, + IRQ110 = 0x8e, + IRQ111 = 0x8f, + IRQ112 = 0x90, + IRQ113 = 0x91, + IRQ114 = 0x92, + IRQ115 = 0x93, + IRQ116 = 0x94, + IRQ117 = 0x95, + IRQ118 = 0x96, + IRQ119 = 0x97, + IRQ120 = 0x98, + IRQ121 = 0x99, + IRQ122 = 0x9a, + IRQ123 = 0x9b, + IRQ124 = 0x9c, + IRQ125 = 0x9d, + IRQ126 = 0x9e, + IRQ127 = 0x9f, + IRQ128 = 0xa0, + IRQ129 = 0xa1, + IRQ130 = 0xa2, + IRQ131 = 0xa3, + IRQ132 = 0xa4, + IRQ133 = 0xa5, + IRQ134 = 0xa6, + IRQ135 = 0xa7, + IRQ136 = 0xa8, + IRQ137 = 0xa9, + IRQ138 = 0xaa, + IRQ139 = 0xab, + IRQ140 = 0xac, + IRQ141 = 0xad, + IRQ142 = 0xae, + IRQ143 = 0xaf, + IRQ144 = 0xb0, + IRQ145 = 0xb1, + IRQ146 = 0xb2, + IRQ147 = 0xb3, + IRQ148 = 0xb4, + IRQ149 = 0xb5, + IRQ150 = 0xb6, + IRQ151 = 0xb7, + IRQ152 = 0xb8, + IRQ153 = 0xb9, + IRQ154 = 0xba, + IRQ155 = 0xbb, + IRQ156 = 0xbc, + IRQ157 = 0xbd, + IRQ158 = 0xbe, + IRQ159 = 0xbf, + IRQ160 = 0xc0, + IRQ161 = 0xc1, + IRQ162 = 0xc2, + IRQ163 = 0xc3, + IRQ164 = 0xc4, + IRQ165 = 0xc5, + IRQ166 = 0xc6, + IRQ167 = 0xc7, + IRQ168 = 0xc8, + IRQ169 = 0xc9, + IRQ170 = 0xca, + IRQ171 = 0xcb, + IRQ172 = 0xcc, + IRQ173 = 0xcd, + IRQ174 = 0xce, + IRQ175 = 0xcf, + IRQ176 = 0xd0, + IRQ177 = 0xd1, + IRQ178 = 0xd2, + IRQ179 = 0xd3, + IRQ180 = 0xd4, + IRQ181 = 0xd5, + IRQ182 = 0xd6, + IRQ183 = 0xd7, + IRQ184 = 0xd8, + IRQ185 = 0xd9, + IRQ186 = 0xda, + IRQ187 = 0xdb, + IRQ188 = 0xdc, + IRQ189 = 0xdd, + IRQ190 = 0xde, + IRQ191 = 0xdf, + IRQ192 = 0xe0, + IRQ193 = 0xe1, + IRQ194 = 0xe2, + IRQ195 = 0xe3, + IRQ196 = 0xe4, + IRQ197 = 0xe5, + IRQ198 = 0xe6, + IRQ199 = 0xe7, + IRQ200 = 0xe8, + IRQ201 = 0xe9, + IRQ202 = 0xea, + IRQ203 = 0xeb, + IRQ204 = 0xec, + IRQ205 = 0xed, + IRQ206 = 0xee, + IRQ207 = 0xef, + IRQ208 = 0xf0, + IRQ209 = 0xf1, + IRQ210 = 0xf2, + IRQ211 = 0xf3, + IRQ212 = 0xf4, + IRQ213 = 0xf5, + IRQ214 = 0xf6, + IRQ215 = 0xf7, + IRQ216 = 0xf8, + IRQ217 = 0xf9, + IRQ218 = 0xfa, + IRQ219 = 0xfb, + IRQ220 = 0xfc, + IRQ221 = 0xfd, + IRQ222 = 0xfe, + IRQ223 = 0xff, + } Interrupts; + typedef union { struct diff --git a/include/pci.hpp b/include/pci.hpp new file mode 100644 index 0000000..a808457 --- /dev/null +++ b/include/pci.hpp @@ -0,0 +1,156 @@ +#ifndef __FENNIX_KERNEL_PCI_H__ +#define __FENNIX_KERNEL_PCI_H__ + +#include + +#include +#include + +namespace PCI +{ + namespace Descriptors + { + enum PCIVendors + { + SymbiosLogic = 0x1000, + RedHat = 0x1AF4, + REDHat2 = 0x1B36, + Realtek = 0x10EC, + VirtualBox = 0x80EE, + Ensoniq = 0x1274, + QEMU = 0x1234, + VMware = 0x15AD, + IntelCorporation = 0x8086, + AdvancedMicroDevices = 0x1022, + NVIDIACorporation = 0x10DE + }; + + const char *const DeviceClasses[]{ + "Unclassified", + "Mass Storage Controller", + "Network Controller", + "Display Controller", + "Multimedia Controller", + "Memory Controller", + "Bridge Device", + "Simple Communication Controller", + "Base System Peripheral", + "Input Device Controller", + "Docking Station", + "Processor", + "Serial Bus Controller", + "Wireless Controller", + "Intelligent Controller", + "Satellite Communication Controller", + "Encryption Controller", + "Signal Processing Controller", + "Processing Accelerator", + "Non Essential Instrumentation"}; + + const char *MassStorageControllerSubclassName(uint8_t SubclassCode); + const char *NetworkControllerSubclassName(uint8_t SubclassCode); + const char *DisplayControllerSubclassName(uint8_t SubclassCode); + const char *CommunicationControllerSubclassName(uint8_t SubclassCode); + const char *BaseSystemPeripheralSubclassName(uint8_t SubclassCode); + const char *SerialBusControllerSubclassName(uint8_t SubclassCode); + const char *BridgeDeviceSubclassName(uint8_t SubclassCode); + const char *WirelessControllerSubclassName(uint8_t SubclassCode); + const char *GetVendorName(uint32_t VendorID); + const char *GetDeviceName(uint32_t VendorID, uint32_t DeviceID); + const char *GetSubclassName(uint8_t ClassCode, uint8_t SubclassCode); + const char *GetProgIFName(uint8_t ClassCode, uint8_t SubclassCode, uint8_t ProgIF); + } + + /* https://sites.uclouvain.be/SystInfo/usr/include/linux/pci_regs.h.html */ + enum PCICommands + { + /** @brief Enable response in I/O space */ + PCI_COMMAND_IO = 0x1, + /** @brief Enable response in Memory space */ + PCI_COMMAND_MEMORY = 0x2, + /** @brief Enable bus mastering */ + PCI_COMMAND_MASTER = 0x4, + /** @brief Enable response to special cycles */ + PCI_COMMAND_SPECIAL = 0x8, + /** @brief Use memory write and invalidate */ + PCI_COMMAND_INVALIDATE = 0x10, + /** @brief Enable palette snooping */ + PCI_COMMAND_VGA_PALETTE = 0x20, + /** @brief Enable parity checking */ + PCI_COMMAND_PARITY = 0x40, + /** @brief Enable address/data stepping */ + PCI_COMMAND_WAIT = 0x80, + /** @brief Enable SERR */ + PCI_COMMAND_SERR = 0x100, + /** @brief Enable back-to-back writes */ + PCI_COMMAND_FAST_BACK = 0x200, + /** @brief INTx Emulation Disable */ + PCI_COMMAND_INTX_DISABLE = 0x400 + }; + + struct PCIDeviceHeader + { + uint16_t VendorID; + uint16_t DeviceID; + uint16_t Command; + uint16_t Status; + uint8_t RevisionID; + uint8_t ProgIF; + uint8_t Subclass; + uint8_t Class; + uint8_t CacheLineSize; + uint8_t LatencyTimer; + uint8_t HeaderType; + uint8_t BIST; + }; + + struct PCIHeader0 + { + PCIDeviceHeader Header; + uint32_t BAR0; + uint32_t BAR1; + uint32_t BAR2; + uint32_t BAR3; + uint32_t BAR4; + uint32_t BAR5; + uint32_t CardbusCISPtr; + uint16_t SubsystemVendorID; + uint16_t SubsystemID; + uint32_t ExpansionROMBaseAddr; + uint8_t CapabilitiesPtr; + uint8_t Rsv0; + uint16_t Rsv1; + uint32_t Rsv2; + uint8_t InterruptLine; + uint8_t InterruptPin; + uint8_t MinGrant; + uint8_t MaxLatency; + }; + + struct DeviceConfig + { + uint64_t BaseAddress; + uint16_t PCISegGroup; + uint8_t StartBus; + uint8_t EndBus; + uint32_t Reserved; + } __attribute__((packed)); + + class PCI + { + private: + Vector Devices; + + public: + void EnumerateFunction(uint64_t DeviceAddress, uint64_t Function); + void EnumerateDevice(uint64_t BusAddress, uint64_t Device); + void EnumerateBus(uint64_t BaseAddress, uint64_t Bus); + Vector FindPCIDevice(uint8_t Class, uint8_t Subclass, uint8_t ProgIF); + Vector FindPCIDevice(int VendorID, int DeviceID); + + PCI(); + ~PCI(); + }; +} + +#endif // !__FENNIX_KERNEL_PCI_H__ diff --git a/include/power.hpp b/include/power.hpp new file mode 100644 index 0000000..3db9fd6 --- /dev/null +++ b/include/power.hpp @@ -0,0 +1,24 @@ +#ifndef __FENNIX_KERNEL_POWER_H__ +#define __FENNIX_KERNEL_POWER_H__ + +#include + +namespace Power +{ + class Power + { + private: + // specific for 64 and 32 bit + void *acpi; + void *dsdt; + void *madt; + + public: + void Reboot(); + void Shutdown(); + Power(); + ~Power(); + }; +} + +#endif // !__FENNIX_KERNEL_POWER_H__ diff --git a/kernel.h b/kernel.h index d875dbe..55a47b2 100644 --- a/kernel.h +++ b/kernel.h @@ -6,6 +6,6 @@ extern struct BootInfo *bInfo; -EXTERNC void kernel_entry(struct BootInfo *Info); +EXTERNC void Entry(struct BootInfo *Info); #endif // !__FENNIX_KERNEL_KERNEL_H__