Update files

This commit is contained in:
Alex 2022-10-10 23:29:39 +03:00
parent 32b44a50d4
commit 4b6683823f
Signed by untrusted user who does not match committer: enderice2
GPG Key ID: EACC3AD603BAB4DD
39 changed files with 2133 additions and 26 deletions

2
.gitignore vendored
View File

@ -2,4 +2,4 @@
*.map
*.fsys
*.log
files/*.psf
Files/*.psf

View File

@ -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__)

View File

@ -4,7 +4,7 @@
#include <debug.h>
#include "HeapAllocators/Xalloc.hpp"
#include "../lib/liballoc_1_1.h"
#include "../Library/liballoc_1_1.h"
using namespace Memory;

View File

@ -0,0 +1,844 @@
#include <pci.hpp>
#include <memory.hpp>
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<PCIDeviceHeader *> PCI::FindPCIDevice(uint8_t Class, uint8_t Subclass, uint8_t ProgIF)
{
Vector<PCIDeviceHeader *> DeviceFound;
for (auto var : Devices)
if (var->Class == Class && var->Subclass == Subclass && var->ProgIF == ProgIF)
DeviceFound.push_back(var);
return DeviceFound;
}
Vector<PCIDeviceHeader *> PCI::FindPCIDevice(int VendorID, int DeviceID)
{
Vector<PCIDeviceHeader *> 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()
{
}
}

81
Core/Power.cpp Normal file
View File

@ -0,0 +1,81 @@
#include <power.hpp>
#include <memory.hpp>
#include "../kernel.h"
#include <debug.h>
#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

View File

@ -4,6 +4,9 @@
#include <debug.h>
#include <io.h>
volatile bool serialports[8] = {false, false, false, false, false, false, false, false};
Vector<UniversalAsynchronousReceiverTransmitter::Events *> 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<Events *> RegisteredEvents;
UART::UART(SerialPorts Port)
{
#if defined(__amd64__) || defined(__i386__)

View File

@ -2,9 +2,9 @@
#include <lock.hpp>
#include <debug.h>
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");

View File

@ -4,6 +4,7 @@
#include <display.hpp>
#include <symbols.hpp>
#include <memory.hpp>
#include <power.hpp>
#include <string.h>
#include <printf.h>
#include <time.hpp>
@ -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();
}

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,127 @@
#include "acpi.hpp"
#include <debug.h>
#include <io.h>
#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()
{
}
}

View File

@ -0,0 +1,225 @@
#include "acpi.hpp"
#include <time.hpp>
#include <debug.h>
#include <io.h>
// #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()
{
}
}

View File

@ -230,5 +230,5 @@ void init_limine()
strcpy(binfo.Bootloader.Version, BootloaderInfoResponse->version);
// Call kernel entry point
kernel_entry(&binfo);
Entry(&binfo);
}

View File

@ -0,0 +1,64 @@
#include "acpi.hpp"
#include <memory.hpp>
#include <debug.h>
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()
{
}
}

282
arch/amd64/acpi.hpp Normal file
View File

@ -0,0 +1,282 @@
#ifndef __FENNIX_KERNEL_ACPI_H__
#define __FENNIX_KERNEL_ACPI_H__
#include <types.h>
#include <boot/binfo.h>
#include <interrupts.hpp>
#include <vector.hpp>
#include <cpu.hpp>
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<MADTIOApic *> ioapic;
Vector<MADTIso *> iso;
Vector<MADTNmi *> nmi;
Vector<LocalAPIC *> 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__

View File

@ -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.*)
}
}

View File

@ -1,7 +1,7 @@
OUTPUT_FORMAT(elf32-i386)
OUTPUT_ARCH(i386)
ENTRY(kernel_entry)
ENTRY(Entry)
SECTIONS
{

View File

@ -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

156
include/pci.hpp Normal file
View File

@ -0,0 +1,156 @@
#ifndef __FENNIX_KERNEL_PCI_H__
#define __FENNIX_KERNEL_PCI_H__
#include <types.h>
#include <vector.hpp>
#include <debug.h>
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<PCIDeviceHeader *> 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<PCIDeviceHeader *> FindPCIDevice(uint8_t Class, uint8_t Subclass, uint8_t ProgIF);
Vector<PCIDeviceHeader *> FindPCIDevice(int VendorID, int DeviceID);
PCI();
~PCI();
};
}
#endif // !__FENNIX_KERNEL_PCI_H__

24
include/power.hpp Normal file
View File

@ -0,0 +1,24 @@
#ifndef __FENNIX_KERNEL_POWER_H__
#define __FENNIX_KERNEL_POWER_H__
#include <types.h>
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__

View File

@ -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__