Fix 32-bit compilation

This commit is contained in:
Alex 2023-08-23 16:59:21 +03:00
parent 8898791257
commit bef0897442
Signed by untrusted user who does not match committer: enderice2
GPG Key ID: EACC3AD603BAB4DD
58 changed files with 4419 additions and 3418 deletions

View File

@ -1,7 +1,7 @@
/* Based on this tutorial: /* Based on this tutorial:
https://github.com/s-matyukevich/raspberry-pi-os */ https://github.com/s-matyukevich/raspberry-pi-os */
.section ".text.boot" .section ".text.boot", "a"
.extern _bss_start .extern _bss_start
.extern _bss_end .extern _bss_end

View File

@ -24,135 +24,135 @@
namespace ACPI namespace ACPI
{ {
__no_sanitize("alignment") void *ACPI::FindTable(ACPI::ACPIHeader *ACPIHeader, char *Signature) __no_sanitize("alignment") void *ACPI::FindTable(ACPI::ACPIHeader *ACPIHeader, char *Signature)
{ {
for (uint64_t t = 0; t < ((ACPIHeader->Length - sizeof(ACPI::ACPIHeader)) / (XSDTSupported ? 8 : 4)); t++) for (uint64_t t = 0; t < ((ACPIHeader->Length - sizeof(ACPI::ACPIHeader)) / (XSDTSupported ? 8 : 4)); t++)
{ {
#pragma GCC diagnostic push #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" #pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
// TODO: Should I be concerned about unaligned memory access? // TODO: Should I be concerned about unaligned memory access?
ACPI::ACPIHeader *SDTHdr = nullptr; ACPI::ACPIHeader *SDTHdr = nullptr;
if (XSDTSupported) if (XSDTSupported)
SDTHdr = (ACPI::ACPIHeader *)(*(uint64_t *)((uint64_t)ACPIHeader + sizeof(ACPI::ACPIHeader) + (t * 8))); SDTHdr = (ACPI::ACPIHeader *)(*(uint64_t *)((uint64_t)ACPIHeader + sizeof(ACPI::ACPIHeader) + (t * 8)));
else else
SDTHdr = (ACPI::ACPIHeader *)(*(uint32_t *)((uint64_t)ACPIHeader + sizeof(ACPI::ACPIHeader) + (t * 4))); SDTHdr = (ACPI::ACPIHeader *)(*(uint32_t *)((uint64_t)ACPIHeader + sizeof(ACPI::ACPIHeader) + (t * 4)));
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
if (SDTHdr->Signature[i] != Signature[i]) if (SDTHdr->Signature[i] != Signature[i])
break; break;
if (i == 3) if (i == 3)
{ {
trace("%s found at address %p", Signature, (uintptr_t)SDTHdr); trace("%s found at address %p", Signature, (uintptr_t)SDTHdr);
return SDTHdr; return SDTHdr;
} }
} }
} }
// warn("%s not found!", Signature); // warn("%s not found!", Signature);
return nullptr; return nullptr;
} }
void ACPI::SearchTables(ACPIHeader *Header) void ACPI::SearchTables(ACPIHeader *Header)
{ {
if (!Header) if (!Header)
return; return;
HPET = (HPETHeader *)FindTable(Header, (char *)"HPET"); HPET = (HPETHeader *)FindTable(Header, (char *)"HPET");
FADT = (FADTHeader *)FindTable(Header, (char *)"FACP"); FADT = (FADTHeader *)FindTable(Header, (char *)"FACP");
MCFG = (MCFGHeader *)FindTable(Header, (char *)"MCFG"); MCFG = (MCFGHeader *)FindTable(Header, (char *)"MCFG");
BGRT = (BGRTHeader *)FindTable(Header, (char *)"BGRT"); BGRT = (BGRTHeader *)FindTable(Header, (char *)"BGRT");
SRAT = (SRATHeader *)FindTable(Header, (char *)"SRAT"); SRAT = (SRATHeader *)FindTable(Header, (char *)"SRAT");
TPM2 = (TPM2Header *)FindTable(Header, (char *)"TPM2"); TPM2 = (TPM2Header *)FindTable(Header, (char *)"TPM2");
TCPA = (TCPAHeader *)FindTable(Header, (char *)"TCPA"); TCPA = (TCPAHeader *)FindTable(Header, (char *)"TCPA");
WAET = (WAETHeader *)FindTable(Header, (char *)"WAET"); WAET = (WAETHeader *)FindTable(Header, (char *)"WAET");
MADT = (MADTHeader *)FindTable(Header, (char *)"APIC"); MADT = (MADTHeader *)FindTable(Header, (char *)"APIC");
HEST = (HESTHeader *)FindTable(Header, (char *)"HEST"); HEST = (HESTHeader *)FindTable(Header, (char *)"HEST");
FindTable(Header, (char *)"BERT"); FindTable(Header, (char *)"BERT");
FindTable(Header, (char *)"CPEP"); FindTable(Header, (char *)"CPEP");
FindTable(Header, (char *)"DSDT"); FindTable(Header, (char *)"DSDT");
FindTable(Header, (char *)"ECDT"); FindTable(Header, (char *)"ECDT");
FindTable(Header, (char *)"EINJ"); FindTable(Header, (char *)"EINJ");
FindTable(Header, (char *)"ERST"); FindTable(Header, (char *)"ERST");
FindTable(Header, (char *)"FACS"); FindTable(Header, (char *)"FACS");
FindTable(Header, (char *)"MSCT"); FindTable(Header, (char *)"MSCT");
FindTable(Header, (char *)"MPST"); FindTable(Header, (char *)"MPST");
FindTable(Header, (char *)"OEMx"); FindTable(Header, (char *)"OEMx");
FindTable(Header, (char *)"PMTT"); FindTable(Header, (char *)"PMTT");
FindTable(Header, (char *)"PSDT"); FindTable(Header, (char *)"PSDT");
FindTable(Header, (char *)"RASF"); FindTable(Header, (char *)"RASF");
FindTable(Header, (char *)"RSDT"); FindTable(Header, (char *)"RSDT");
FindTable(Header, (char *)"SBST"); FindTable(Header, (char *)"SBST");
FindTable(Header, (char *)"SLIT"); FindTable(Header, (char *)"SLIT");
FindTable(Header, (char *)"SSDT"); FindTable(Header, (char *)"SSDT");
FindTable(Header, (char *)"XSDT"); FindTable(Header, (char *)"XSDT");
FindTable(Header, (char *)"DRTM"); FindTable(Header, (char *)"DRTM");
FindTable(Header, (char *)"FPDT"); FindTable(Header, (char *)"FPDT");
FindTable(Header, (char *)"GTDT"); FindTable(Header, (char *)"GTDT");
FindTable(Header, (char *)"PCCT"); FindTable(Header, (char *)"PCCT");
FindTable(Header, (char *)"S3PT"); FindTable(Header, (char *)"S3PT");
FindTable(Header, (char *)"MATR"); FindTable(Header, (char *)"MATR");
FindTable(Header, (char *)"MSDM"); FindTable(Header, (char *)"MSDM");
FindTable(Header, (char *)"WPBT"); FindTable(Header, (char *)"WPBT");
FindTable(Header, (char *)"OSDT"); FindTable(Header, (char *)"OSDT");
FindTable(Header, (char *)"RSDP"); FindTable(Header, (char *)"RSDP");
FindTable(Header, (char *)"NFIT"); FindTable(Header, (char *)"NFIT");
FindTable(Header, (char *)"ASF!"); FindTable(Header, (char *)"ASF!");
FindTable(Header, (char *)"BOOT"); FindTable(Header, (char *)"BOOT");
FindTable(Header, (char *)"CSRT"); FindTable(Header, (char *)"CSRT");
FindTable(Header, (char *)"DBG2"); FindTable(Header, (char *)"DBG2");
FindTable(Header, (char *)"DBGP"); FindTable(Header, (char *)"DBGP");
FindTable(Header, (char *)"DMAR"); FindTable(Header, (char *)"DMAR");
FindTable(Header, (char *)"IBFT"); FindTable(Header, (char *)"IBFT");
FindTable(Header, (char *)"IORT"); FindTable(Header, (char *)"IORT");
FindTable(Header, (char *)"IVRS"); FindTable(Header, (char *)"IVRS");
FindTable(Header, (char *)"LPIT"); FindTable(Header, (char *)"LPIT");
FindTable(Header, (char *)"MCHI"); FindTable(Header, (char *)"MCHI");
FindTable(Header, (char *)"MTMR"); FindTable(Header, (char *)"MTMR");
FindTable(Header, (char *)"SLIC"); FindTable(Header, (char *)"SLIC");
FindTable(Header, (char *)"SPCR"); FindTable(Header, (char *)"SPCR");
FindTable(Header, (char *)"SPMI"); FindTable(Header, (char *)"SPMI");
FindTable(Header, (char *)"UEFI"); FindTable(Header, (char *)"UEFI");
FindTable(Header, (char *)"VRTC"); FindTable(Header, (char *)"VRTC");
FindTable(Header, (char *)"WDAT"); FindTable(Header, (char *)"WDAT");
FindTable(Header, (char *)"WDDT"); FindTable(Header, (char *)"WDDT");
FindTable(Header, (char *)"WDRT"); FindTable(Header, (char *)"WDRT");
FindTable(Header, (char *)"ATKG"); FindTable(Header, (char *)"ATKG");
FindTable(Header, (char *)"GSCI"); FindTable(Header, (char *)"GSCI");
FindTable(Header, (char *)"IEIT"); FindTable(Header, (char *)"IEIT");
FindTable(Header, (char *)"HMAT"); FindTable(Header, (char *)"HMAT");
FindTable(Header, (char *)"CEDT"); FindTable(Header, (char *)"CEDT");
FindTable(Header, (char *)"AEST"); FindTable(Header, (char *)"AEST");
} }
ACPI::ACPI() ACPI::ACPI()
{ {
trace("Initializing ACPI"); trace("Initializing ACPI");
if (bInfo.RSDP->Revision >= 2 && bInfo.RSDP->XSDTAddress) if (bInfo.RSDP->Revision >= 2 && bInfo.RSDP->XSDTAddress)
{ {
debug("XSDT supported"); debug("XSDT supported");
XSDTSupported = true; XSDTSupported = true;
XSDT = (ACPIHeader *)(bInfo.RSDP->XSDTAddress); XSDT = (ACPIHeader *)(bInfo.RSDP->XSDTAddress);
} }
else else
{ {
debug("RSDT supported"); debug("RSDT supported");
XSDT = (ACPIHeader *)(uintptr_t)bInfo.RSDP->RSDTAddress; XSDT = (ACPIHeader *)(uintptr_t)bInfo.RSDP->RSDTAddress;
} }
this->SearchTables(XSDT); this->SearchTables(XSDT);
if (FADT) if (FADT)
{ {
outb(s_cst(uint16_t, FADT->SMI_CommandPort), FADT->AcpiEnable); outb(s_cst(uint16_t, FADT->SMI_CommandPort), FADT->AcpiEnable);
while (!(inw(s_cst(uint16_t, FADT->PM1aControlBlock)) & 1)) while (!(inw(s_cst(uint16_t, FADT->PM1aControlBlock)) & 1))
; ;
} }
} }
ACPI::~ACPI() ACPI::~ACPI()
{ {
} }
} }

View File

@ -26,292 +26,292 @@
void InitLimine(); void InitLimine();
static volatile struct limine_entry_point_request EntryPointRequest = { static volatile struct limine_entry_point_request EntryPointRequest = {
.id = LIMINE_ENTRY_POINT_REQUEST, .id = LIMINE_ENTRY_POINT_REQUEST,
.revision = 0, .revision = 0,
.response = NULL, .response = NULL,
.entry = InitLimine}; .entry = InitLimine};
static volatile struct limine_bootloader_info_request BootloaderInfoRequest = { static volatile struct limine_bootloader_info_request BootloaderInfoRequest = {
.id = LIMINE_BOOTLOADER_INFO_REQUEST, .id = LIMINE_BOOTLOADER_INFO_REQUEST,
.revision = 0}; .revision = 0};
static volatile struct limine_framebuffer_request FramebufferRequest = { static volatile struct limine_framebuffer_request FramebufferRequest = {
.id = LIMINE_FRAMEBUFFER_REQUEST, .id = LIMINE_FRAMEBUFFER_REQUEST,
.revision = 0}; .revision = 0};
static volatile struct limine_memmap_request MemmapRequest = { static volatile struct limine_memmap_request MemmapRequest = {
.id = LIMINE_MEMMAP_REQUEST, .id = LIMINE_MEMMAP_REQUEST,
.revision = 0}; .revision = 0};
static volatile struct limine_kernel_address_request KernelAddressRequest = { static volatile struct limine_kernel_address_request KernelAddressRequest = {
.id = LIMINE_KERNEL_ADDRESS_REQUEST, .id = LIMINE_KERNEL_ADDRESS_REQUEST,
.revision = 0}; .revision = 0};
static volatile struct limine_rsdp_request RsdpRequest = { static volatile struct limine_rsdp_request RsdpRequest = {
.id = LIMINE_RSDP_REQUEST, .id = LIMINE_RSDP_REQUEST,
.revision = 0}; .revision = 0};
static volatile struct limine_kernel_file_request KernelFileRequest = { static volatile struct limine_kernel_file_request KernelFileRequest = {
.id = LIMINE_KERNEL_FILE_REQUEST, .id = LIMINE_KERNEL_FILE_REQUEST,
.revision = 0}; .revision = 0};
static volatile struct limine_module_request ModuleRequest = { static volatile struct limine_module_request ModuleRequest = {
.id = LIMINE_MODULE_REQUEST, .id = LIMINE_MODULE_REQUEST,
.revision = 0}; .revision = 0};
static volatile struct limine_smbios_request SmbiosRequest = { static volatile struct limine_smbios_request SmbiosRequest = {
.id = LIMINE_SMBIOS_REQUEST, .id = LIMINE_SMBIOS_REQUEST,
.revision = 0}; .revision = 0};
void *TempStackPtr = NULL; void *TempStackPtr = NULL;
__naked __used __no_stack_protector void InitLimine() __naked __used __no_stack_protector void InitLimine()
{ {
asmv("mov %%rsp, %0" asmv("mov %%rsp, %0"
: "=r"(TempStackPtr)); : "=r"(TempStackPtr));
asmv("mov %0, %%rsp" asmv("mov %0, %%rsp"
: :
: "r"((uintptr_t)TempStackPtr - 0xFFFF800000000000)); : "r"((uintptr_t)TempStackPtr - 0xFFFF800000000000));
asmv("mov $0, %rax\n" asmv("mov $0, %rax\n"
"mov $0, %rbx\n" "mov $0, %rbx\n"
"mov $0, %rcx\n" "mov $0, %rcx\n"
"mov $0, %rdx\n" "mov $0, %rdx\n"
"mov $0, %rsi\n" "mov $0, %rsi\n"
"mov $0, %rdi\n" "mov $0, %rdi\n"
"mov $0, %rbp\n" "mov $0, %rbp\n"
"mov $0, %r8\n" "mov $0, %r8\n"
"mov $0, %r9\n" "mov $0, %r9\n"
"mov $0, %r10\n" "mov $0, %r10\n"
"mov $0, %r11\n" "mov $0, %r11\n"
"mov $0, %r12\n" "mov $0, %r12\n"
"mov $0, %r13\n" "mov $0, %r13\n"
"mov $0, %r14\n" "mov $0, %r14\n"
"mov $0, %r15"); "mov $0, %r15");
asmv("jmp InitLimineAfterStack"); asmv("jmp InitLimineAfterStack");
} }
SafeFunction NIF void InitLimineAfterStack() SafeFunction NIF void InitLimineAfterStack()
{ {
struct BootInfo binfo = {}; struct BootInfo binfo = {};
struct limine_bootloader_info_response *BootloaderInfoResponse = BootloaderInfoRequest.response; struct limine_bootloader_info_response *BootloaderInfoResponse = BootloaderInfoRequest.response;
info("Bootloader: %s %s", BootloaderInfoResponse->name, BootloaderInfoResponse->version); info("Bootloader: %s %s", BootloaderInfoResponse->name, BootloaderInfoResponse->version);
struct limine_framebuffer_response *FrameBufferResponse = FramebufferRequest.response; struct limine_framebuffer_response *FrameBufferResponse = FramebufferRequest.response;
struct limine_memmap_response *MemmapResponse = MemmapRequest.response; struct limine_memmap_response *MemmapResponse = MemmapRequest.response;
struct limine_kernel_address_response *KernelAddressResponse = KernelAddressRequest.response; struct limine_kernel_address_response *KernelAddressResponse = KernelAddressRequest.response;
struct limine_rsdp_response *RsdpResponse = RsdpRequest.response; struct limine_rsdp_response *RsdpResponse = RsdpRequest.response;
struct limine_kernel_file_response *KernelFileResponse = KernelFileRequest.response; struct limine_kernel_file_response *KernelFileResponse = KernelFileRequest.response;
struct limine_module_response *ModuleResponse = ModuleRequest.response; struct limine_module_response *ModuleResponse = ModuleRequest.response;
struct limine_smbios_response *SmbiosResponse = SmbiosRequest.response; struct limine_smbios_response *SmbiosResponse = SmbiosRequest.response;
if (FrameBufferResponse == NULL || FrameBufferResponse->framebuffer_count < 1) if (FrameBufferResponse == NULL || FrameBufferResponse->framebuffer_count < 1)
{ {
error("No framebuffer available [%#lx;%ld]", FrameBufferResponse, error("No framebuffer available [%#lx;%ld]", FrameBufferResponse,
(FrameBufferResponse == NULL) ? 0 : FrameBufferResponse->framebuffer_count); (FrameBufferResponse == NULL) ? 0 : FrameBufferResponse->framebuffer_count);
inf_loop asmv("hlt"); inf_loop asmv("hlt");
} }
if (MemmapResponse == NULL || MemmapResponse->entry_count < 1) if (MemmapResponse == NULL || MemmapResponse->entry_count < 1)
{ {
error("No memory map available [%#lx;%ld]", MemmapResponse, error("No memory map available [%#lx;%ld]", MemmapResponse,
(MemmapResponse == NULL) ? 0 : MemmapResponse->entry_count); (MemmapResponse == NULL) ? 0 : MemmapResponse->entry_count);
inf_loop asmv("hlt"); inf_loop asmv("hlt");
} }
if (KernelAddressResponse == NULL) if (KernelAddressResponse == NULL)
{ {
error("No kernel address available [%#lx]", KernelAddressResponse); error("No kernel address available [%#lx]", KernelAddressResponse);
inf_loop asmv("hlt"); inf_loop asmv("hlt");
} }
if (RsdpResponse == NULL || RsdpResponse->address == 0) if (RsdpResponse == NULL || RsdpResponse->address == 0)
{ {
error("No RSDP address available [%#lx;%#lx]", RsdpResponse, error("No RSDP address available [%#lx;%#lx]", RsdpResponse,
(RsdpResponse == NULL) ? 0 : RsdpResponse->address); (RsdpResponse == NULL) ? 0 : RsdpResponse->address);
inf_loop asmv("hlt"); inf_loop asmv("hlt");
} }
if (KernelFileResponse == NULL || KernelFileResponse->kernel_file == NULL) if (KernelFileResponse == NULL || KernelFileResponse->kernel_file == NULL)
{ {
error("No kernel file available [%#lx;%#lx]", KernelFileResponse, error("No kernel file available [%#lx;%#lx]", KernelFileResponse,
(KernelFileResponse == NULL) ? 0 : KernelFileResponse->kernel_file); (KernelFileResponse == NULL) ? 0 : KernelFileResponse->kernel_file);
inf_loop asmv("hlt"); inf_loop asmv("hlt");
} }
/* Actual parsing starts here */ /* Actual parsing starts here */
for (uint64_t i = 0; i < FrameBufferResponse->framebuffer_count; i++) for (uint64_t i = 0; i < FrameBufferResponse->framebuffer_count; i++)
{ {
struct limine_framebuffer *framebuffer = FrameBufferResponse->framebuffers[i]; struct limine_framebuffer *framebuffer = FrameBufferResponse->framebuffers[i];
switch (framebuffer->memory_model) switch (framebuffer->memory_model)
{ {
case LIMINE_FRAMEBUFFER_RGB: case LIMINE_FRAMEBUFFER_RGB:
binfo.Framebuffer[i].Type = RGB; binfo.Framebuffer[i].Type = RGB;
break; break;
default: default:
{ {
error("Unsupported framebuffer memory model %d", framebuffer->memory_model); error("Unsupported framebuffer memory model %d", framebuffer->memory_model);
inf_loop asmv("hlt"); inf_loop asmv("hlt");
} }
} }
binfo.Framebuffer[i].BaseAddress = (void *)((uintptr_t)framebuffer->address - 0xFFFF800000000000); binfo.Framebuffer[i].BaseAddress = (void *)((uintptr_t)framebuffer->address - 0xFFFF800000000000);
binfo.Framebuffer[i].Width = (uint32_t)framebuffer->width; binfo.Framebuffer[i].Width = (uint32_t)framebuffer->width;
binfo.Framebuffer[i].Height = (uint32_t)framebuffer->height; binfo.Framebuffer[i].Height = (uint32_t)framebuffer->height;
binfo.Framebuffer[i].Pitch = (uint32_t)framebuffer->pitch; binfo.Framebuffer[i].Pitch = (uint32_t)framebuffer->pitch;
binfo.Framebuffer[i].BitsPerPixel = framebuffer->bpp; binfo.Framebuffer[i].BitsPerPixel = framebuffer->bpp;
binfo.Framebuffer[i].RedMaskSize = framebuffer->red_mask_size; binfo.Framebuffer[i].RedMaskSize = framebuffer->red_mask_size;
binfo.Framebuffer[i].RedMaskShift = framebuffer->red_mask_shift; binfo.Framebuffer[i].RedMaskShift = framebuffer->red_mask_shift;
binfo.Framebuffer[i].GreenMaskSize = framebuffer->green_mask_size; binfo.Framebuffer[i].GreenMaskSize = framebuffer->green_mask_size;
binfo.Framebuffer[i].GreenMaskShift = framebuffer->green_mask_shift; binfo.Framebuffer[i].GreenMaskShift = framebuffer->green_mask_shift;
binfo.Framebuffer[i].BlueMaskSize = framebuffer->blue_mask_size; binfo.Framebuffer[i].BlueMaskSize = framebuffer->blue_mask_size;
binfo.Framebuffer[i].BlueMaskShift = framebuffer->blue_mask_shift; binfo.Framebuffer[i].BlueMaskShift = framebuffer->blue_mask_shift;
binfo.Framebuffer[i].ExtendedDisplayIdentificationData = framebuffer->edid; binfo.Framebuffer[i].ExtendedDisplayIdentificationData = framebuffer->edid;
binfo.Framebuffer[i].EDIDSize = framebuffer->edid_size; binfo.Framebuffer[i].EDIDSize = framebuffer->edid_size;
debug("Framebuffer %d: %dx%d %d bpp", i, debug("Framebuffer %d: %dx%d %d bpp", i,
binfo.Framebuffer[i].Width, binfo.Framebuffer[i].Width,
binfo.Framebuffer[i].Height, binfo.Framebuffer[i].Height,
binfo.Framebuffer[i].BitsPerPixel); binfo.Framebuffer[i].BitsPerPixel);
debug("More info:\nAddress: %#lx\nPitch: %ld\nType: %d\nRedMaskSize: %d\nRedMaskShift: %d\nGreenMaskSize: %d\nGreenMaskShift: %d\nBlueMaskSize: %d\nBlueMaskShift: %d\nEDID: %#lx\nEDIDSize: %d", debug("More info:\nAddress: %#lx\nPitch: %ld\nType: %d\nRedMaskSize: %d\nRedMaskShift: %d\nGreenMaskSize: %d\nGreenMaskShift: %d\nBlueMaskSize: %d\nBlueMaskShift: %d\nEDID: %#lx\nEDIDSize: %d",
binfo.Framebuffer[i].BaseAddress, binfo.Framebuffer[i].BaseAddress,
binfo.Framebuffer[i].Pitch, binfo.Framebuffer[i].Pitch,
binfo.Framebuffer[i].Type, binfo.Framebuffer[i].Type,
binfo.Framebuffer[i].RedMaskSize, binfo.Framebuffer[i].RedMaskSize,
binfo.Framebuffer[i].RedMaskShift, binfo.Framebuffer[i].RedMaskShift,
binfo.Framebuffer[i].GreenMaskSize, binfo.Framebuffer[i].GreenMaskSize,
binfo.Framebuffer[i].GreenMaskShift, binfo.Framebuffer[i].GreenMaskShift,
binfo.Framebuffer[i].BlueMaskSize, binfo.Framebuffer[i].BlueMaskSize,
binfo.Framebuffer[i].BlueMaskShift, binfo.Framebuffer[i].BlueMaskShift,
binfo.Framebuffer[i].ExtendedDisplayIdentificationData, binfo.Framebuffer[i].ExtendedDisplayIdentificationData,
binfo.Framebuffer[i].EDIDSize); binfo.Framebuffer[i].EDIDSize);
} }
binfo.Memory.Entries = MemmapResponse->entry_count; binfo.Memory.Entries = MemmapResponse->entry_count;
for (uint64_t i = 0; i < MemmapResponse->entry_count; i++) for (uint64_t i = 0; i < MemmapResponse->entry_count; i++)
{ {
if (MemmapResponse->entry_count > MAX_MEMORY_ENTRIES) if (MemmapResponse->entry_count > MAX_MEMORY_ENTRIES)
{ {
warn("Too many memory entries, skipping the rest..."); warn("Too many memory entries, skipping the rest...");
break; break;
} }
struct limine_memmap_entry *entry = MemmapResponse->entries[i]; struct limine_memmap_entry *entry = MemmapResponse->entries[i];
if (!entry) if (!entry)
{ {
warn("Null memory entry %ld (%#lx), skipping...", i, entry); warn("Null memory entry %ld (%#lx), skipping...", i, entry);
continue; continue;
} }
binfo.Memory.Size += entry->length; binfo.Memory.Size += entry->length;
switch (entry->type) switch (entry->type)
{ {
case LIMINE_MEMMAP_USABLE: case LIMINE_MEMMAP_USABLE:
binfo.Memory.Entry[i].BaseAddress = (void *)entry->base; binfo.Memory.Entry[i].BaseAddress = (void *)entry->base;
binfo.Memory.Entry[i].Length = entry->length; binfo.Memory.Entry[i].Length = entry->length;
binfo.Memory.Entry[i].Type = Usable; binfo.Memory.Entry[i].Type = Usable;
break; break;
case LIMINE_MEMMAP_RESERVED: case LIMINE_MEMMAP_RESERVED:
binfo.Memory.Entry[i].BaseAddress = (void *)entry->base; binfo.Memory.Entry[i].BaseAddress = (void *)entry->base;
binfo.Memory.Entry[i].Length = entry->length; binfo.Memory.Entry[i].Length = entry->length;
binfo.Memory.Entry[i].Type = Reserved; binfo.Memory.Entry[i].Type = Reserved;
break; break;
case LIMINE_MEMMAP_ACPI_RECLAIMABLE: case LIMINE_MEMMAP_ACPI_RECLAIMABLE:
binfo.Memory.Entry[i].BaseAddress = (void *)entry->base; binfo.Memory.Entry[i].BaseAddress = (void *)entry->base;
binfo.Memory.Entry[i].Length = entry->length; binfo.Memory.Entry[i].Length = entry->length;
binfo.Memory.Entry[i].Type = ACPIReclaimable; binfo.Memory.Entry[i].Type = ACPIReclaimable;
break; break;
case LIMINE_MEMMAP_ACPI_NVS: case LIMINE_MEMMAP_ACPI_NVS:
binfo.Memory.Entry[i].BaseAddress = (void *)entry->base; binfo.Memory.Entry[i].BaseAddress = (void *)entry->base;
binfo.Memory.Entry[i].Length = entry->length; binfo.Memory.Entry[i].Length = entry->length;
binfo.Memory.Entry[i].Type = ACPINVS; binfo.Memory.Entry[i].Type = ACPINVS;
break; break;
case LIMINE_MEMMAP_BAD_MEMORY: case LIMINE_MEMMAP_BAD_MEMORY:
binfo.Memory.Entry[i].BaseAddress = (void *)entry->base; binfo.Memory.Entry[i].BaseAddress = (void *)entry->base;
binfo.Memory.Entry[i].Length = entry->length; binfo.Memory.Entry[i].Length = entry->length;
binfo.Memory.Entry[i].Type = BadMemory; binfo.Memory.Entry[i].Type = BadMemory;
break; break;
case LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE: case LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE:
binfo.Memory.Entry[i].BaseAddress = (void *)entry->base; binfo.Memory.Entry[i].BaseAddress = (void *)entry->base;
binfo.Memory.Entry[i].Length = entry->length; binfo.Memory.Entry[i].Length = entry->length;
binfo.Memory.Entry[i].Type = BootloaderReclaimable; binfo.Memory.Entry[i].Type = BootloaderReclaimable;
break; break;
case LIMINE_MEMMAP_KERNEL_AND_MODULES: case LIMINE_MEMMAP_KERNEL_AND_MODULES:
binfo.Memory.Entry[i].BaseAddress = (void *)entry->base; binfo.Memory.Entry[i].BaseAddress = (void *)entry->base;
binfo.Memory.Entry[i].Length = entry->length; binfo.Memory.Entry[i].Length = entry->length;
binfo.Memory.Entry[i].Type = KernelAndModules; binfo.Memory.Entry[i].Type = KernelAndModules;
break; break;
case LIMINE_MEMMAP_FRAMEBUFFER: case LIMINE_MEMMAP_FRAMEBUFFER:
binfo.Memory.Entry[i].BaseAddress = (void *)entry->base; binfo.Memory.Entry[i].BaseAddress = (void *)entry->base;
binfo.Memory.Entry[i].Length = entry->length; binfo.Memory.Entry[i].Length = entry->length;
binfo.Memory.Entry[i].Type = Framebuffer; binfo.Memory.Entry[i].Type = Framebuffer;
break; break;
default: default:
binfo.Memory.Entry[i].BaseAddress = (void *)entry->base; binfo.Memory.Entry[i].BaseAddress = (void *)entry->base;
binfo.Memory.Entry[i].Length = entry->length; binfo.Memory.Entry[i].Length = entry->length;
binfo.Memory.Entry[i].Type = Unknown; binfo.Memory.Entry[i].Type = Unknown;
break; break;
} }
} }
if (ModuleResponse != NULL && ModuleResponse->module_count > 0) if (ModuleResponse != NULL && ModuleResponse->module_count > 0)
{ {
for (uint64_t i = 0; i < ModuleResponse->module_count; i++) for (uint64_t i = 0; i < ModuleResponse->module_count; i++)
{ {
if (i > MAX_MODULES) if (i > MAX_MODULES)
{ {
warn("Too many modules, skipping the rest..."); warn("Too many modules, skipping the rest...");
break; break;
} }
binfo.Modules[i].Address = (void *)((uint64_t)ModuleResponse->modules[i]->address - 0xFFFF800000000000); binfo.Modules[i].Address = (void *)((uint64_t)ModuleResponse->modules[i]->address - 0xFFFF800000000000);
binfo.Modules[i].Size = ModuleResponse->modules[i]->size; binfo.Modules[i].Size = ModuleResponse->modules[i]->size;
strncpy(binfo.Modules[i].Path, strncpy(binfo.Modules[i].Path,
ModuleResponse->modules[i]->path, ModuleResponse->modules[i]->path,
strlen(ModuleResponse->modules[i]->path) + 1); strlen(ModuleResponse->modules[i]->path) + 1);
strncpy(binfo.Modules[i].CommandLine, strncpy(binfo.Modules[i].CommandLine,
ModuleResponse->modules[i]->cmdline, ModuleResponse->modules[i]->cmdline,
strlen(ModuleResponse->modules[i]->cmdline) + 1); strlen(ModuleResponse->modules[i]->cmdline) + 1);
debug("Module %d:\nAddress: %#lx\nPath: \"%s\"\nCommand Line: \"%s\"\nSize: %ld", debug("Module %d:\nAddress: %#lx\nPath: \"%s\"\nCommand Line: \"%s\"\nSize: %ld",
i, i,
binfo.Modules[i].Address, binfo.Modules[i].Address,
binfo.Modules[i].Path, binfo.Modules[i].Path,
binfo.Modules[i].CommandLine, binfo.Modules[i].CommandLine,
binfo.Modules[i].Size); binfo.Modules[i].Size);
} }
} }
binfo.RSDP = (struct RSDPInfo *)((uintptr_t)RsdpResponse->address - 0xFFFF800000000000); binfo.RSDP = (struct RSDPInfo *)((uintptr_t)RsdpResponse->address - 0xFFFF800000000000);
debug("RSDP: %#lx [Signature: \"%.8s\"] [OEM: \"%.6s\"]", debug("RSDP: %#lx [Signature: \"%.8s\"] [OEM: \"%.6s\"]",
binfo.RSDP, binfo.RSDP->Signature, binfo.RSDP->OEMID); binfo.RSDP, binfo.RSDP->Signature, binfo.RSDP->OEMID);
if (SmbiosResponse->entry_64 != NULL) if (SmbiosResponse->entry_64 != NULL)
binfo.SMBIOSPtr = (void *)((uintptr_t)SmbiosResponse->entry_64 - 0xFFFF800000000000); binfo.SMBIOSPtr = (void *)((uintptr_t)SmbiosResponse->entry_64 - 0xFFFF800000000000);
else if (SmbiosResponse->entry_32 != NULL) else if (SmbiosResponse->entry_32 != NULL)
binfo.SMBIOSPtr = (void *)((uintptr_t)SmbiosResponse->entry_32 - 0xFFFF800000000000); binfo.SMBIOSPtr = (void *)((uintptr_t)SmbiosResponse->entry_32 - 0xFFFF800000000000);
else else
binfo.SMBIOSPtr = NULL; binfo.SMBIOSPtr = NULL;
debug("SMBIOS: %#lx %#lx (binfo: %#lx)", debug("SMBIOS: %#lx %#lx (binfo: %#lx)",
SmbiosResponse->entry_32, SmbiosResponse->entry_32,
SmbiosResponse->entry_64, SmbiosResponse->entry_64,
binfo.SMBIOSPtr); binfo.SMBIOSPtr);
binfo.Kernel.PhysicalBase = (void *)KernelAddressResponse->physical_base; binfo.Kernel.PhysicalBase = (void *)KernelAddressResponse->physical_base;
binfo.Kernel.VirtualBase = (void *)KernelAddressResponse->virtual_base; binfo.Kernel.VirtualBase = (void *)KernelAddressResponse->virtual_base;
binfo.Kernel.FileBase = (void *)((uintptr_t)KernelFileResponse->kernel_file->address - 0xFFFF800000000000); binfo.Kernel.FileBase = (void *)((uintptr_t)KernelFileResponse->kernel_file->address - 0xFFFF800000000000);
binfo.Kernel.Size = KernelFileResponse->kernel_file->size; binfo.Kernel.Size = KernelFileResponse->kernel_file->size;
strncpy(binfo.Kernel.CommandLine, strncpy(binfo.Kernel.CommandLine,
KernelFileResponse->kernel_file->cmdline, KernelFileResponse->kernel_file->cmdline,
strlen(KernelFileResponse->kernel_file->cmdline) + 1); strlen(KernelFileResponse->kernel_file->cmdline) + 1);
debug("Kernel physical address: %#lx", binfo.Kernel.PhysicalBase); debug("Kernel physical address: %#lx", binfo.Kernel.PhysicalBase);
debug("Kernel virtual address: %#lx", binfo.Kernel.VirtualBase); debug("Kernel virtual address: %#lx", binfo.Kernel.VirtualBase);
strncpy(binfo.Bootloader.Name, strncpy(binfo.Bootloader.Name,
BootloaderInfoResponse->name, BootloaderInfoResponse->name,
strlen(BootloaderInfoResponse->name) + 1); strlen(BootloaderInfoResponse->name) + 1);
strncpy(binfo.Bootloader.Version, strncpy(binfo.Bootloader.Version,
BootloaderInfoResponse->version, BootloaderInfoResponse->version,
strlen(BootloaderInfoResponse->version) + 1); strlen(BootloaderInfoResponse->version) + 1);
Entry(&binfo); Entry(&binfo);
} }

View File

@ -18,7 +18,7 @@
.intel_syntax noprefix .intel_syntax noprefix
.code32 .code32
.section .multiboot .section .multiboot, "a"
.align 4 .align 4
MULTIBOOT_HEADER: MULTIBOOT_HEADER:

View File

@ -16,7 +16,7 @@
*/ */
.code32 .code32
.section .bootstrap.text .section .bootstrap.text, "a"
.global Multiboot1_start .global Multiboot1_start
Multiboot1_start: Multiboot1_start:

View File

@ -18,7 +18,7 @@
.intel_syntax noprefix .intel_syntax noprefix
.code32 .code32
.section .bootstrap.text .section .bootstrap.text, "a"
.global DetectCPUID .global DetectCPUID
DetectCPUID: DetectCPUID:

View File

@ -16,7 +16,7 @@
*/ */
.code32 .code32
.section .bootstrap.text .section .bootstrap.text, "a"
.align 32 .align 32
.global gdtr .global gdtr

View File

@ -16,7 +16,7 @@
*/ */
.code64 .code64
.section .bootstrap.data .section .bootstrap.data, "a"
/* Access bits */ /* Access bits */
A = 0x1 A = 0x1

View File

@ -19,7 +19,7 @@
.extern Multiboot2_start .extern Multiboot2_start
/* https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html */ /* https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html */
.section .multiboot2 .section .multiboot2, "a"
.align 0x1000 .align 0x1000
MULTIBOOT2_HEADER_START: MULTIBOOT2_HEADER_START:
.long 0xE85250D6 .long 0xE85250D6

View File

@ -19,140 +19,140 @@
union __attribute__((packed)) PageTableEntry union __attribute__((packed)) PageTableEntry
{ {
struct struct
{ {
bool Present : 1; // 0 bool Present : 1; // 0
bool ReadWrite : 1; // 1 bool ReadWrite : 1; // 1
bool UserSupervisor : 1; // 2 bool UserSupervisor : 1; // 2
bool WriteThrough : 1; // 3 bool WriteThrough : 1; // 3
bool CacheDisable : 1; // 4 bool CacheDisable : 1; // 4
bool Accessed : 1; // 5 bool Accessed : 1; // 5
bool Dirty : 1; // 6 bool Dirty : 1; // 6
bool PageAttributeTable : 1; // 7 bool PageAttributeTable : 1; // 7
bool Global : 1; // 8 bool Global : 1; // 8
uint8_t Available0 : 3; // 9-11 uint8_t Available0 : 3; // 9-11
uint64_t Address : 40; // 12-51 uint64_t Address : 40; // 12-51
uint32_t Available1 : 7; // 52-58 uint32_t Available1 : 7; // 52-58
uint8_t ProtectionKey : 4; // 59-62 uint8_t ProtectionKey : 4; // 59-62
bool ExecuteDisable : 1; // 63 bool ExecuteDisable : 1; // 63
}; };
uint64_t raw; uint64_t raw;
__always_inline inline SafeFunction NIF void SetAddress(uintptr_t _Address) __always_inline inline SafeFunction NIF void SetAddress(uintptr_t _Address)
{ {
_Address &= 0x000000FFFFFFFFFF; _Address &= 0x000000FFFFFFFFFF;
this->raw &= 0xFFF0000000000FFF; this->raw &= 0xFFF0000000000FFF;
this->raw |= (_Address << 12); this->raw |= (_Address << 12);
} }
__always_inline inline SafeFunction NIF uintptr_t GetAddress() { return (this->raw & 0x000FFFFFFFFFF000) >> 12; } __always_inline inline SafeFunction NIF uintptr_t GetAddress() { return (this->raw & 0x000FFFFFFFFFF000) >> 12; }
}; };
struct __attribute__((packed)) PageTableEntryPtr struct __attribute__((packed)) PageTableEntryPtr
{ {
PageTableEntry Entries[512]; PageTableEntry Entries[512];
}; };
union __attribute__((packed)) PageDirectoryEntry union __attribute__((packed)) PageDirectoryEntry
{ {
struct struct
{ {
bool Present : 1; // 0 bool Present : 1; // 0
bool ReadWrite : 1; // 1 bool ReadWrite : 1; // 1
bool UserSupervisor : 1; // 2 bool UserSupervisor : 1; // 2
bool WriteThrough : 1; // 3 bool WriteThrough : 1; // 3
bool CacheDisable : 1; // 4 bool CacheDisable : 1; // 4
bool Accessed : 1; // 5 bool Accessed : 1; // 5
bool Available0 : 1; // 6 bool Available0 : 1; // 6
bool PageSize : 1; // 7 bool PageSize : 1; // 7
uint8_t Available1 : 4; // 8-11 uint8_t Available1 : 4; // 8-11
uint64_t Address : 40; // 12-51 uint64_t Address : 40; // 12-51
uint32_t Available2 : 11; // 52-62 uint32_t Available2 : 11; // 52-62
bool ExecuteDisable : 1; // 63 bool ExecuteDisable : 1; // 63
}; };
uint64_t raw; uint64_t raw;
__always_inline inline SafeFunction NIF void SetAddress(uintptr_t _Address) __always_inline inline SafeFunction NIF void SetAddress(uintptr_t _Address)
{ {
_Address &= 0x000000FFFFFFFFFF; _Address &= 0x000000FFFFFFFFFF;
this->raw &= 0xFFF0000000000FFF; this->raw &= 0xFFF0000000000FFF;
this->raw |= (_Address << 12); this->raw |= (_Address << 12);
} }
__always_inline inline SafeFunction NIF uintptr_t GetAddress() { return (this->raw & 0x000FFFFFFFFFF000) >> 12; } __always_inline inline SafeFunction NIF uintptr_t GetAddress() { return (this->raw & 0x000FFFFFFFFFF000) >> 12; }
}; };
struct __attribute__((packed)) PageDirectoryEntryPtr struct __attribute__((packed)) PageDirectoryEntryPtr
{ {
PageDirectoryEntry Entries[512]; PageDirectoryEntry Entries[512];
}; };
union __attribute__((packed)) PageDirectoryPointerTableEntry union __attribute__((packed)) PageDirectoryPointerTableEntry
{ {
struct struct
{ {
bool Present : 1; // 0 bool Present : 1; // 0
bool ReadWrite : 1; // 1 bool ReadWrite : 1; // 1
bool UserSupervisor : 1; // 2 bool UserSupervisor : 1; // 2
bool WriteThrough : 1; // 3 bool WriteThrough : 1; // 3
bool CacheDisable : 1; // 4 bool CacheDisable : 1; // 4
bool Accessed : 1; // 5 bool Accessed : 1; // 5
bool Available0 : 1; // 6 bool Available0 : 1; // 6
bool PageSize : 1; // 7 bool PageSize : 1; // 7
uint8_t Available1 : 4; // 8-11 uint8_t Available1 : 4; // 8-11
uint64_t Address : 40; // 12-51 uint64_t Address : 40; // 12-51
uint32_t Available2 : 11; // 52-62 uint32_t Available2 : 11; // 52-62
bool ExecuteDisable : 1; // 63 bool ExecuteDisable : 1; // 63
}; };
uint64_t raw; uint64_t raw;
__always_inline inline SafeFunction NIF void SetAddress(uintptr_t _Address) __always_inline inline SafeFunction NIF void SetAddress(uintptr_t _Address)
{ {
_Address &= 0x000000FFFFFFFFFF; _Address &= 0x000000FFFFFFFFFF;
this->raw &= 0xFFF0000000000FFF; this->raw &= 0xFFF0000000000FFF;
this->raw |= (_Address << 12); this->raw |= (_Address << 12);
} }
__always_inline inline SafeFunction NIF uintptr_t GetAddress() { return (this->raw & 0x000FFFFFFFFFF000) >> 12; } __always_inline inline SafeFunction NIF uintptr_t GetAddress() { return (this->raw & 0x000FFFFFFFFFF000) >> 12; }
}; };
struct __attribute__((packed)) PageDirectoryPointerTableEntryPtr struct __attribute__((packed)) PageDirectoryPointerTableEntryPtr
{ {
PageDirectoryPointerTableEntry Entries[512]; PageDirectoryPointerTableEntry Entries[512];
}; };
union __attribute__((packed)) PageMapLevel4 union __attribute__((packed)) PageMapLevel4
{ {
struct struct
{ {
bool Present : 1; // 0 bool Present : 1; // 0
bool ReadWrite : 1; // 1 bool ReadWrite : 1; // 1
bool UserSupervisor : 1; // 2 bool UserSupervisor : 1; // 2
bool WriteThrough : 1; // 3 bool WriteThrough : 1; // 3
bool CacheDisable : 1; // 4 bool CacheDisable : 1; // 4
bool Accessed : 1; // 5 bool Accessed : 1; // 5
bool Available0 : 1; // 6 bool Available0 : 1; // 6
bool Reserved0 : 1; // 7 bool Reserved0 : 1; // 7
uint8_t Available1 : 4; // 8-11 uint8_t Available1 : 4; // 8-11
uint64_t Address : 40; // 12-51 uint64_t Address : 40; // 12-51
uint32_t Available2 : 11; // 52-62 uint32_t Available2 : 11; // 52-62
bool ExecuteDisable : 1; // 63 bool ExecuteDisable : 1; // 63
}; };
uint64_t raw; uint64_t raw;
__always_inline inline SafeFunction NIF void SetAddress(uintptr_t _Address) __always_inline inline SafeFunction NIF void SetAddress(uintptr_t _Address)
{ {
_Address &= 0x000000FFFFFFFFFF; _Address &= 0x000000FFFFFFFFFF;
this->raw &= 0xFFF0000000000FFF; this->raw &= 0xFFF0000000000FFF;
this->raw |= (_Address << 12); this->raw |= (_Address << 12);
} }
__always_inline inline SafeFunction NIF uintptr_t GetAddress() { return (this->raw & 0x000FFFFFFFFFF000) >> 12; } __always_inline inline SafeFunction NIF uintptr_t GetAddress() { return (this->raw & 0x000FFFFFFFFFF000) >> 12; }
}; };
struct PageTable4 struct PageTable4
{ {
PageMapLevel4 Entries[512]; PageMapLevel4 Entries[512];
} __attribute__((aligned(0x1000))); } __attribute__((aligned(0x1000)));
extern "C" char BootPageTable[]; extern "C" char BootPageTable[];
@ -163,139 +163,139 @@ __attribute__((section(".bootstrap.data"))) static size_t BPT_Allocated = 0x4000
__always_inline inline SafeFunction NIF void *RequestPage() __always_inline inline SafeFunction NIF void *RequestPage()
{ {
void *Page = (void *)(BootPageTable + BPT_Allocated); void *Page = (void *)(BootPageTable + BPT_Allocated);
BPT_Allocated += 0x1000; BPT_Allocated += 0x1000;
if (BPT_Allocated >= 0x10000) /* The length of BootPageTable */ if (BPT_Allocated >= 0x10000) /* The length of BootPageTable */
{ {
while (true) while (true)
; ;
} }
return Page; return Page;
} }
class PageMapIndexer class PageMapIndexer
{ {
public: public:
uintptr_t PMLIndex = 0; uintptr_t PMLIndex = 0;
uintptr_t PDPTEIndex = 0; uintptr_t PDPTEIndex = 0;
uintptr_t PDEIndex = 0; uintptr_t PDEIndex = 0;
uintptr_t PTEIndex = 0; uintptr_t PTEIndex = 0;
__always_inline inline SafeFunction NIF PageMapIndexer(uintptr_t VirtualAddress) __always_inline inline SafeFunction NIF PageMapIndexer(uintptr_t VirtualAddress)
{ {
uintptr_t Address = VirtualAddress; uintptr_t Address = VirtualAddress;
Address >>= 12; Address >>= 12;
this->PTEIndex = Address & 0x1FF; this->PTEIndex = Address & 0x1FF;
Address >>= 9; Address >>= 9;
this->PDEIndex = Address & 0x1FF; this->PDEIndex = Address & 0x1FF;
Address >>= 9; Address >>= 9;
this->PDPTEIndex = Address & 0x1FF; this->PDPTEIndex = Address & 0x1FF;
Address >>= 9; Address >>= 9;
this->PMLIndex = Address & 0x1FF; this->PMLIndex = Address & 0x1FF;
} }
}; };
__attribute__((section(".bootstrap.text"))) SafeFunction NIF void MB2_64_Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags) __attribute__((section(".bootstrap.text"))) SafeFunction NIF void MB2_64_Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags)
{ {
PageMapIndexer Index = PageMapIndexer((uintptr_t)VirtualAddress); PageMapIndexer Index = PageMapIndexer((uintptr_t)VirtualAddress);
// Clear any flags that are not 1 << 0 (Present) - 1 << 5 (Accessed) because rest are for page table entries only // Clear any flags that are not 1 << 0 (Present) - 1 << 5 (Accessed) because rest are for page table entries only
uint64_t DirectoryFlags = Flags & 0x3F; uint64_t DirectoryFlags = Flags & 0x3F;
PageMapLevel4 PML4 = BPTable->Entries[Index.PMLIndex]; PageMapLevel4 PML4 = BPTable->Entries[Index.PMLIndex];
PageDirectoryPointerTableEntryPtr *PDPTEPtr = nullptr; PageDirectoryPointerTableEntryPtr *PDPTEPtr = nullptr;
if (!PML4.Present) if (!PML4.Present)
{ {
PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)RequestPage(); PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)RequestPage();
if (PDPTEPtr == nullptr) if (PDPTEPtr == nullptr)
return; return;
{ {
void *ptr = PDPTEPtr; void *ptr = PDPTEPtr;
uint8_t value = 0; uint8_t value = 0;
size_t num = 0x1000; size_t num = 0x1000;
uint8_t *p = (uint8_t *)ptr; uint8_t *p = (uint8_t *)ptr;
for (size_t i = 0; i < num; i++) for (size_t i = 0; i < num; i++)
p[i] = value; p[i] = value;
} }
PML4.Present = true; PML4.Present = true;
PML4.SetAddress((uintptr_t)PDPTEPtr >> 12); PML4.SetAddress((uintptr_t)PDPTEPtr >> 12);
} }
else else
PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4.GetAddress() << 12); PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4.GetAddress() << 12);
PML4.raw |= DirectoryFlags; PML4.raw |= DirectoryFlags;
BPTable->Entries[Index.PMLIndex] = PML4; BPTable->Entries[Index.PMLIndex] = PML4;
PageDirectoryPointerTableEntry PDPTE = PDPTEPtr->Entries[Index.PDPTEIndex]; PageDirectoryPointerTableEntry PDPTE = PDPTEPtr->Entries[Index.PDPTEIndex];
PageDirectoryEntryPtr *PDEPtr = nullptr; PageDirectoryEntryPtr *PDEPtr = nullptr;
if (!PDPTE.Present) if (!PDPTE.Present)
{ {
PDEPtr = (PageDirectoryEntryPtr *)RequestPage(); PDEPtr = (PageDirectoryEntryPtr *)RequestPage();
if (PDEPtr == nullptr) if (PDEPtr == nullptr)
return; return;
{ {
void *ptr = PDEPtr; void *ptr = PDEPtr;
uint8_t value = 0; uint8_t value = 0;
size_t num = 0x1000; size_t num = 0x1000;
uint8_t *p = (uint8_t *)ptr; uint8_t *p = (uint8_t *)ptr;
for (size_t i = 0; i < num; i++) for (size_t i = 0; i < num; i++)
p[i] = value; p[i] = value;
} }
PDPTE.Present = true; PDPTE.Present = true;
PDPTE.SetAddress((uintptr_t)PDEPtr >> 12); PDPTE.SetAddress((uintptr_t)PDEPtr >> 12);
} }
else else
PDEPtr = (PageDirectoryEntryPtr *)((uintptr_t)PDPTE.GetAddress() << 12); PDEPtr = (PageDirectoryEntryPtr *)((uintptr_t)PDPTE.GetAddress() << 12);
PDPTE.raw |= DirectoryFlags; PDPTE.raw |= DirectoryFlags;
PDPTEPtr->Entries[Index.PDPTEIndex] = PDPTE; PDPTEPtr->Entries[Index.PDPTEIndex] = PDPTE;
PageDirectoryEntry PDE = PDEPtr->Entries[Index.PDEIndex]; PageDirectoryEntry PDE = PDEPtr->Entries[Index.PDEIndex];
PageTableEntryPtr *PTEPtr = nullptr; PageTableEntryPtr *PTEPtr = nullptr;
if (!PDE.Present) if (!PDE.Present)
{ {
PTEPtr = (PageTableEntryPtr *)RequestPage(); PTEPtr = (PageTableEntryPtr *)RequestPage();
if (PTEPtr == nullptr) if (PTEPtr == nullptr)
return; return;
{ {
void *ptr = PTEPtr; void *ptr = PTEPtr;
uint8_t value = 0; uint8_t value = 0;
size_t num = 0x1000; size_t num = 0x1000;
uint8_t *p = (uint8_t *)ptr; uint8_t *p = (uint8_t *)ptr;
for (size_t i = 0; i < num; i++) for (size_t i = 0; i < num; i++)
p[i] = value; p[i] = value;
} }
PDE.Present = true; PDE.Present = true;
PDE.SetAddress((uintptr_t)PTEPtr >> 12); PDE.SetAddress((uintptr_t)PTEPtr >> 12);
} }
else else
PTEPtr = (PageTableEntryPtr *)((uintptr_t)PDE.GetAddress() << 12); PTEPtr = (PageTableEntryPtr *)((uintptr_t)PDE.GetAddress() << 12);
PDE.raw |= DirectoryFlags; PDE.raw |= DirectoryFlags;
PDEPtr->Entries[Index.PDEIndex] = PDE; PDEPtr->Entries[Index.PDEIndex] = PDE;
PageTableEntry PTE = PTEPtr->Entries[Index.PTEIndex]; PageTableEntry PTE = PTEPtr->Entries[Index.PTEIndex];
PTE.Present = true; PTE.Present = true;
PTE.raw |= Flags; PTE.raw |= Flags;
PTE.SetAddress((uintptr_t)PhysicalAddress >> 12); PTE.SetAddress((uintptr_t)PhysicalAddress >> 12);
PTEPtr->Entries[Index.PTEIndex] = PTE; PTEPtr->Entries[Index.PTEIndex] = PTE;
asmv("invlpg (%0)" asmv("invlpg (%0)"
: :
: "r"(VirtualAddress) : "r"(VirtualAddress)
: "memory"); : "memory");
} }
EXTERNC __attribute__((section(".bootstrap.text"))) SafeFunction NIF __attribute__((section(".bootstrap.text"))) void UpdatePageTable64() EXTERNC __attribute__((section(".bootstrap.text"))) SafeFunction NIF __attribute__((section(".bootstrap.text"))) void UpdatePageTable64()
{ {
BPTable = (PageTable4 *)BootPageTable; BPTable = (PageTable4 *)BootPageTable;
uintptr_t KernelStart = (uintptr_t)&_kernel_start; uintptr_t KernelStart = (uintptr_t)&_kernel_start;
uintptr_t KernelEnd = (uintptr_t)&_kernel_end; uintptr_t KernelEnd = (uintptr_t)&_kernel_end;
uintptr_t PhysicalStart = KernelStart - 0xFFFFFFFF80000000; uintptr_t PhysicalStart = KernelStart - 0xFFFFFFFF80000000;
for (uintptr_t i = KernelStart; i < KernelEnd; i += 0x1000) for (uintptr_t i = KernelStart; i < KernelEnd; i += 0x1000)
{ {
MB2_64_Map((void *)i, (void *)PhysicalStart, 0x3); MB2_64_Map((void *)i, (void *)PhysicalStart, 0x3);
PhysicalStart += 0x1000; PhysicalStart += 0x1000;
} }
asmv("mov %%cr3, %%rax\n" asmv("mov %%cr3, %%rax\n"
"mov %%rax, %%cr3\n" "mov %%rax, %%cr3\n"
: :
: :
: "rax"); : "rax");
} }

View File

@ -18,13 +18,13 @@
PAGE_TABLE_SIZE = 0x4 PAGE_TABLE_SIZE = 0x4
.code32 .code32
.section .bootstrap.data .section .bootstrap.data, "a"
.align 0x1000 .align 0x1000
.global BootPageTable .global BootPageTable
BootPageTable: BootPageTable:
.space 0x10000 /* 0x4000 bytes will be used in UpdatePageTable */ .space 0x10000 /* 0x4000 bytes will be used in UpdatePageTable */
.section .bootstrap.text .section .bootstrap.text, "a"
.global UpdatePageTable .global UpdatePageTable
UpdatePageTable: UpdatePageTable:
mov $(BootPageTable + 0x0000), %edi /* First PML4E */ mov $(BootPageTable + 0x0000), %edi /* First PML4E */

View File

@ -30,14 +30,14 @@ KERNEL_STACK_SIZE = 0x4000 /* 16KB */
.extern GDT64.Code .extern GDT64.Code
.extern GDT64.Data .extern GDT64.Data
.section .bootstrap.data .section .bootstrap.data, "a"
MB_HeaderMagic: MB_HeaderMagic:
.quad 0 .quad 0
MB_HeaderInfo: MB_HeaderInfo:
.quad 0 .quad 0
.section .bootstrap.text .section .bootstrap.text, "a"
.global Multiboot2_start .global Multiboot2_start
Multiboot2_start: Multiboot2_start:
@ -113,7 +113,7 @@ HigherHalfStart:
hlt hlt
jmp .Hang jmp .Hang
.section .bootstrap.bss .section .bootstrap.bss, "a"
.align 16 .align 16
KernelStack: KernelStack:
.space KERNEL_STACK_SIZE .space KERNEL_STACK_SIZE

View File

@ -21,7 +21,7 @@
.extern Multiboot2_start .extern Multiboot2_start
.code32 .code32
.section .bootstrap.text .section .bootstrap.text, "a"
.global _start .global _start
_start: _start:

View File

@ -36,10 +36,10 @@
namespace ACPI namespace ACPI
{ {
__always_inline inline bool IsCanonical(uint64_t Address) __always_inline inline bool IsCanonical(uint64_t Address)
{ {
return ((Address <= 0x00007FFFFFFFFFFF) || ((Address >= 0xFFFF800000000000) && (Address <= 0xFFFFFFFFFFFFFFFF))); return ((Address <= 0x00007FFFFFFFFFFF) || ((Address >= 0xFFFF800000000000) && (Address <= 0xFFFFFFFFFFFFFFFF)));
} }
#define ACPI_ENABLED 0x0001 #define ACPI_ENABLED 0x0001
#define ACPI_SLEEP 0x2000 #define ACPI_SLEEP 0x2000
@ -48,208 +48,208 @@ namespace ACPI
#define ACPI_GAS_IO 1 #define ACPI_GAS_IO 1
#define ACPI_GAS_PCI 2 #define ACPI_GAS_PCI 2
void DSDT::OnInterruptReceived(CPU::x64::TrapFrame *Frame) void DSDT::OnInterruptReceived(CPU::x64::TrapFrame *Frame)
{ {
debug("SCI Handle Triggered"); debug("SCI Handle Triggered");
uint16_t Event = 0; uint16_t Event = 0;
{ {
uint16_t a = 0, b = 0; uint16_t a = 0, b = 0;
if (acpi->FADT->PM1aEventBlock) if (acpi->FADT->PM1aEventBlock)
{ {
a = inw(s_cst(uint16_t, acpi->FADT->PM1aEventBlock)); a = inw(s_cst(uint16_t, acpi->FADT->PM1aEventBlock));
outw(s_cst(uint16_t, acpi->FADT->PM1aEventBlock), a); outw(s_cst(uint16_t, acpi->FADT->PM1aEventBlock), a);
} }
if (acpi->FADT->PM1bEventBlock) if (acpi->FADT->PM1bEventBlock)
{ {
b = inw(s_cst(uint16_t, acpi->FADT->PM1bEventBlock)); b = inw(s_cst(uint16_t, acpi->FADT->PM1bEventBlock));
outw(s_cst(uint16_t, acpi->FADT->PM1bEventBlock), b); outw(s_cst(uint16_t, acpi->FADT->PM1bEventBlock), b);
} }
Event = a | b; Event = a | b;
} }
debug("SCI Event: %#lx", Event); debug("SCI Event: %#lx", Event);
if (Event & ACPI_BUSMASTER) if (Event & ACPI_BUSMASTER)
{ {
fixme("ACPI Busmaster"); fixme("ACPI Busmaster");
} }
else if (Event & ACPI_GLOBAL) else if (Event & ACPI_GLOBAL)
{ {
fixme("ACPI Global"); fixme("ACPI Global");
} }
else if (Event & ACPI_POWER_BUTTON) else if (Event & ACPI_POWER_BUTTON)
{ {
if (TaskManager && !TaskManager->IsPanic()) if (TaskManager && !TaskManager->IsPanic())
{ {
TaskManager->CreateThread(TaskManager->CreateProcess(nullptr, TaskManager->CreateThread(TaskManager->CreateProcess(nullptr,
"Shutdown", "Shutdown",
Tasking::TaskExecutionMode::Kernel), Tasking::TaskExecutionMode::Kernel),
Tasking::IP(KST_Shutdown)); Tasking::IP(KST_Shutdown));
} }
else else
KernelShutdownThread(false); KernelShutdownThread(false);
} }
else if (Event & ACPI_SLEEP_BUTTON) else if (Event & ACPI_SLEEP_BUTTON)
{ {
fixme("ACPI Sleep Button"); fixme("ACPI Sleep Button");
} }
else if (Event & ACPI_RTC_ALARM) else if (Event & ACPI_RTC_ALARM)
{ {
fixme("ACPI RTC Alarm"); fixme("ACPI RTC Alarm");
} }
else if (Event & ACPI_PCIE_WAKE) else if (Event & ACPI_PCIE_WAKE)
{ {
fixme("ACPI PCIe Wake"); fixme("ACPI PCIe Wake");
} }
else if (Event & ACPI_WAKE) else if (Event & ACPI_WAKE)
{ {
fixme("ACPI Wake"); fixme("ACPI Wake");
} }
else if (Event & ACPI_TIMER) else if (Event & ACPI_TIMER)
{ {
fixme("ACPI Timer"); fixme("ACPI Timer");
} }
else else
{ {
error("ACPI unknown event %#lx on CPU %d", Event, GetCurrentCPU()->ID); error("ACPI unknown event %#lx on CPU %d", Event, GetCurrentCPU()->ID);
CPU::Stop(); CPU::Stop();
} }
UNUSED(Frame); UNUSED(Frame);
} }
void DSDT::Shutdown() void DSDT::Shutdown()
{ {
trace("Shutting down..."); trace("Shutting down...");
if (SCI_EN == 1) if (SCI_EN == 1)
{ {
outw(s_cst(uint16_t, acpi->FADT->PM1aControlBlock), outw(s_cst(uint16_t, acpi->FADT->PM1aControlBlock),
s_cst(uint16_t, s_cst(uint16_t,
(inw(s_cst(uint16_t, (inw(s_cst(uint16_t,
acpi->FADT->PM1aControlBlock)) & acpi->FADT->PM1aControlBlock)) &
0xE3FF) | 0xE3FF) |
((SLP_TYPa << 10) | ACPI_SLEEP))); ((SLP_TYPa << 10) | ACPI_SLEEP)));
if (acpi->FADT->PM1bControlBlock) if (acpi->FADT->PM1bControlBlock)
outw(s_cst(uint16_t, acpi->FADT->PM1bControlBlock), outw(s_cst(uint16_t, acpi->FADT->PM1bControlBlock),
s_cst(uint16_t, s_cst(uint16_t,
(inw( (inw(
s_cst(uint16_t, acpi->FADT->PM1bControlBlock)) & s_cst(uint16_t, acpi->FADT->PM1bControlBlock)) &
0xE3FF) | 0xE3FF) |
((SLP_TYPb << 10) | ACPI_SLEEP))); ((SLP_TYPb << 10) | ACPI_SLEEP)));
outw(s_cst(uint16_t, PM1a_CNT), SLP_TYPa | SLP_EN); outw(s_cst(uint16_t, PM1a_CNT), SLP_TYPa | SLP_EN);
if (PM1b_CNT) if (PM1b_CNT)
outw(s_cst(uint16_t, PM1b_CNT), SLP_TYPb | SLP_EN); outw(s_cst(uint16_t, PM1b_CNT), SLP_TYPb | SLP_EN);
} }
} }
void DSDT::Reboot() void DSDT::Reboot()
{ {
trace("Rebooting..."); trace("Rebooting...");
switch (acpi->FADT->ResetReg.AddressSpace) switch (acpi->FADT->ResetReg.AddressSpace)
{ {
case ACPI_GAS_MMIO: case ACPI_GAS_MMIO:
{ {
*(uint8_t *)(acpi->FADT->ResetReg.Address) = acpi->FADT->ResetValue; *(uint8_t *)(acpi->FADT->ResetReg.Address) = acpi->FADT->ResetValue;
break; break;
} }
case ACPI_GAS_IO: case ACPI_GAS_IO:
{ {
outb(s_cst(uint16_t, acpi->FADT->ResetReg.Address), acpi->FADT->ResetValue); outb(s_cst(uint16_t, acpi->FADT->ResetReg.Address), acpi->FADT->ResetValue);
break; break;
} }
case ACPI_GAS_PCI: case ACPI_GAS_PCI:
{ {
fixme("ACPI_GAS_PCI not supported."); fixme("ACPI_GAS_PCI not supported.");
/* /*
seg - 0 seg - 0
bus - 0 bus - 0
dev - (FADT->ResetReg.Address >> 32) & 0xFFFF dev - (FADT->ResetReg.Address >> 32) & 0xFFFF
function - (FADT->ResetReg.Address >> 16) & 0xFFFF function - (FADT->ResetReg.Address >> 16) & 0xFFFF
offset - FADT->ResetReg.Address & 0xFFFF offset - FADT->ResetReg.Address & 0xFFFF
value - FADT->ResetValue value - FADT->ResetValue
*/ */
break; break;
} }
default: default:
{ {
error("Unknown reset register address space: %d", acpi->FADT->ResetReg.AddressSpace); error("Unknown reset register address space: %d", acpi->FADT->ResetReg.AddressSpace);
break; break;
} }
} }
} }
DSDT::DSDT(ACPI *acpi) : Interrupts::Handler(acpi->FADT->SCI_Interrupt) DSDT::DSDT(ACPI *acpi) : Interrupts::Handler(acpi->FADT->SCI_Interrupt)
{ {
this->acpi = acpi; this->acpi = acpi;
uint64_t Address = ((IsCanonical(acpi->FADT->X_Dsdt) && acpi->XSDTSupported) ? acpi->FADT->X_Dsdt : acpi->FADT->Dsdt); uint64_t Address = ((IsCanonical(acpi->FADT->X_Dsdt) && acpi->XSDTSupported) ? acpi->FADT->X_Dsdt : acpi->FADT->Dsdt);
uint8_t *S5Address = (uint8_t *)(Address) + 36; uint8_t *S5Address = (uint8_t *)(Address) + 36;
ACPI::ACPI::ACPIHeader *Header = (ACPI::ACPI::ACPIHeader *)Address; ACPI::ACPI::ACPIHeader *Header = (ACPI::ACPI::ACPIHeader *)Address;
size_t Length = Header->Length; size_t Length = Header->Length;
while (Length-- > 0) while (Length-- > 0)
{ {
if (!memcmp(S5Address, "_S5_", 4)) if (!memcmp(S5Address, "_S5_", 4))
break; break;
S5Address++; S5Address++;
} }
if (Length <= 0) if (Length <= 0)
{ {
warn("_S5 not present in ACPI"); warn("_S5 not present in ACPI");
return; return;
} }
if ((*(S5Address - 1) == 0x08 || (*(S5Address - 2) == 0x08 && *(S5Address - 1) == '\\')) && *(S5Address + 4) == 0x12) if ((*(S5Address - 1) == 0x08 || (*(S5Address - 2) == 0x08 && *(S5Address - 1) == '\\')) && *(S5Address + 4) == 0x12)
{ {
S5Address += 5; S5Address += 5;
S5Address += ((*S5Address & 0xC0) >> 6) + 2; S5Address += ((*S5Address & 0xC0) >> 6) + 2;
if (*S5Address == 0x0A) if (*S5Address == 0x0A)
S5Address++; S5Address++;
SLP_TYPa = s_cst(uint16_t, *(S5Address) << 10); SLP_TYPa = s_cst(uint16_t, *(S5Address) << 10);
S5Address++; S5Address++;
if (*S5Address == 0x0A) if (*S5Address == 0x0A)
S5Address++; S5Address++;
SLP_TYPb = s_cst(uint16_t, *(S5Address) << 10); SLP_TYPb = s_cst(uint16_t, *(S5Address) << 10);
SMI_CMD = acpi->FADT->SMI_CommandPort; SMI_CMD = acpi->FADT->SMI_CommandPort;
ACPI_ENABLE = acpi->FADT->AcpiEnable; ACPI_ENABLE = acpi->FADT->AcpiEnable;
ACPI_DISABLE = acpi->FADT->AcpiDisable; ACPI_DISABLE = acpi->FADT->AcpiDisable;
PM1a_CNT = acpi->FADT->PM1aControlBlock; PM1a_CNT = acpi->FADT->PM1aControlBlock;
PM1b_CNT = acpi->FADT->PM1bControlBlock; PM1b_CNT = acpi->FADT->PM1bControlBlock;
PM1_CNT_LEN = acpi->FADT->PM1ControlLength; PM1_CNT_LEN = acpi->FADT->PM1ControlLength;
SLP_EN = 1 << 13; SLP_EN = 1 << 13;
SCI_EN = 1; SCI_EN = 1;
trace("ACPI Shutdown is supported"); trace("ACPI Shutdown is supported");
ACPIShutdownSupported = true; ACPIShutdownSupported = true;
uint16_t value = ACPI_POWER_BUTTON | ACPI_SLEEP_BUTTON | ACPI_WAKE; uint16_t value = ACPI_POWER_BUTTON | ACPI_SLEEP_BUTTON | ACPI_WAKE;
{ {
uint16_t a = s_cst(uint16_t, acpi->FADT->PM1aEventBlock + (acpi->FADT->PM1EventLength / 2)); uint16_t a = s_cst(uint16_t, acpi->FADT->PM1aEventBlock + (acpi->FADT->PM1EventLength / 2));
uint16_t b = s_cst(uint16_t, acpi->FADT->PM1bEventBlock + (acpi->FADT->PM1EventLength / 2)); uint16_t b = s_cst(uint16_t, acpi->FADT->PM1bEventBlock + (acpi->FADT->PM1EventLength / 2));
debug("SCI Event: %#llx [a:%#x b:%#x]", value, a, b); debug("SCI Event: %#llx [a:%#x b:%#x]", value, a, b);
if (acpi->FADT->PM1aEventBlock) if (acpi->FADT->PM1aEventBlock)
outw(a, value); outw(a, value);
if (acpi->FADT->PM1bEventBlock) if (acpi->FADT->PM1bEventBlock)
outw(b, value); outw(b, value);
} }
{ {
uint16_t a = 0, b = 0; uint16_t a = 0, b = 0;
if (acpi->FADT->PM1aEventBlock) if (acpi->FADT->PM1aEventBlock)
{ {
a = inw(s_cst(uint16_t, acpi->FADT->PM1aEventBlock)); a = inw(s_cst(uint16_t, acpi->FADT->PM1aEventBlock));
outw(s_cst(uint16_t, acpi->FADT->PM1aEventBlock), a); outw(s_cst(uint16_t, acpi->FADT->PM1aEventBlock), a);
} }
if (acpi->FADT->PM1bEventBlock) if (acpi->FADT->PM1bEventBlock)
{ {
b = inw(s_cst(uint16_t, acpi->FADT->PM1bEventBlock)); b = inw(s_cst(uint16_t, acpi->FADT->PM1bEventBlock));
outw(s_cst(uint16_t, acpi->FADT->PM1bEventBlock), b); outw(s_cst(uint16_t, acpi->FADT->PM1bEventBlock), b);
} }
} }
((APIC::APIC *)Interrupts::apic[0])->RedirectIRQ(0, acpi->FADT->SCI_Interrupt, 1); ((APIC::APIC *)Interrupts::apic[0])->RedirectIRQ(0, acpi->FADT->SCI_Interrupt, 1);
return; return;
} }
warn("Failed to parse _S5 in ACPI"); warn("Failed to parse _S5 in ACPI");
SCI_EN = 0; SCI_EN = 0;
} }
DSDT::~DSDT() DSDT::~DSDT()
{ {
} }
} }

View File

@ -24,68 +24,68 @@
namespace ACPI namespace ACPI
{ {
MADT::MADT(ACPI::MADTHeader *madt) MADT::MADT(ACPI::MADTHeader *madt)
{ {
trace("Initializing MADT"); trace("Initializing MADT");
CPUCores = 0; CPUCores = 0;
LAPICAddress = (LAPIC *)(uintptr_t)madt->LocalControllerAddress; LAPICAddress = (LAPIC *)(uintptr_t)madt->LocalControllerAddress;
for (uint8_t *ptr = (uint8_t *)(madt->Entries); for (uint8_t *ptr = (uint8_t *)(madt->Entries);
(uintptr_t)(ptr) < (uintptr_t)(madt) + madt->Header.Length; (uintptr_t)(ptr) < (uintptr_t)(madt) + madt->Header.Length;
ptr += *(ptr + 1)) ptr += *(ptr + 1))
{ {
switch (*(ptr)) switch (*(ptr))
{ {
case 0: case 0:
{ {
if (ptr[4] & 1) if (ptr[4] & 1)
{ {
lapic.push_back((LocalAPIC *)ptr); lapic.push_back((LocalAPIC *)ptr);
KPrint("Local APIC \e8888FF%d\eCCCCCC (APIC \e8888FF%d\eCCCCCC) found.", lapic.back()->ACPIProcessorId, lapic.back()->APICId); KPrint("Local APIC \e8888FF%d\eCCCCCC (APIC \e8888FF%d\eCCCCCC) found.", lapic.back()->ACPIProcessorId, lapic.back()->APICId);
CPUCores++; CPUCores++;
} }
break; break;
} }
case 1: case 1:
{ {
ioapic.push_back((MADTIOApic *)ptr); ioapic.push_back((MADTIOApic *)ptr);
KPrint("I/O APIC \e8888FF%d\eCCCCCC (Address \e8888FF%#lx\eCCCCCC) found.", ioapic.back()->APICID, ioapic.back()->Address); KPrint("I/O APIC \e8888FF%d\eCCCCCC (Address \e8888FF%#lx\eCCCCCC) found.", ioapic.back()->APICID, ioapic.back()->Address);
Memory::Virtual(KernelPageTable).Map((void *)(uintptr_t)ioapic.back()->Address, (void *)(uintptr_t)ioapic.back()->Address, Memory::PTFlag::RW | Memory::PTFlag::PCD); // Make sure that the address is mapped. Memory::Virtual(KernelPageTable).Map((void *)(uintptr_t)ioapic.back()->Address, (void *)(uintptr_t)ioapic.back()->Address, Memory::PTFlag::RW | Memory::PTFlag::PCD); // Make sure that the address is mapped.
break; break;
} }
case 2: case 2:
{ {
iso.push_back((MADTIso *)ptr); iso.push_back((MADTIso *)ptr);
KPrint("ISO (IRQ:\e8888FF%#lx\eCCCCCC, BUS:\e8888FF%#lx\eCCCCCC, GSI:\e8888FF%#lx\eCCCCCC, %s\eCCCCCC/%s\eCCCCCC) found.", KPrint("ISO (IRQ:\e8888FF%#lx\eCCCCCC, BUS:\e8888FF%#lx\eCCCCCC, GSI:\e8888FF%#lx\eCCCCCC, %s\eCCCCCC/%s\eCCCCCC) found.",
iso.back()->IRQSource, iso.back()->BuSSource, iso.back()->GSI, iso.back()->IRQSource, iso.back()->BuSSource, iso.back()->GSI,
iso.back()->Flags & 0x00000004 ? "\e1770FFActive High" : "\e475EFFActive Low", iso.back()->Flags & 0x00000004 ? "\e1770FFActive High" : "\e475EFFActive Low",
iso.back()->Flags & 0x00000100 ? "\e00962DEdge Triggered" : "\e008F58Level Triggered"); iso.back()->Flags & 0x00000100 ? "\e00962DEdge Triggered" : "\e008F58Level Triggered");
break; break;
} }
case 4: case 4:
{ {
nmi.push_back((MADTNmi *)ptr); nmi.push_back((MADTNmi *)ptr);
KPrint("NMI \e8888FF%#lx\eCCCCCC (lint:\e8888FF%#lx\eCCCCCC) found.", nmi.back()->processor, nmi.back()->lint); KPrint("NMI \e8888FF%#lx\eCCCCCC (lint:\e8888FF%#lx\eCCCCCC) found.", nmi.back()->processor, nmi.back()->lint);
break; break;
} }
case 5: case 5:
{ {
LAPICAddress = (LAPIC *)ptr; LAPICAddress = (LAPIC *)ptr;
KPrint("APIC found at \e8888FF%#lx\eCCCCCC", LAPICAddress); KPrint("APIC found at \e8888FF%#lx\eCCCCCC", LAPICAddress);
break; break;
} }
default: default:
{ {
KPrint("Unknown MADT entry \e8888FF%#lx\eCCCCCC", *(ptr)); KPrint("Unknown MADT entry \e8888FF%#lx\eCCCCCC", *(ptr));
break; break;
} }
} }
Memory::Virtual(KernelPageTable).Map((void *)LAPICAddress, (void *)LAPICAddress, Memory::PTFlag::RW | Memory::PTFlag::PCD); // I should map more than one page? Memory::Virtual(KernelPageTable).Map((void *)LAPICAddress, (void *)LAPICAddress, Memory::PTFlag::RW | Memory::PTFlag::PCD); // I should map more than one page?
} }
CPUCores--; // We start at 0 (BSP) and end at 11 (APs), so we have 12 cores. CPUCores--; // We start at 0 (BSP) and end at 11 (APs), so we have 12 cores.
KPrint("Total CPU cores: %d", CPUCores + 1); KPrint("Total CPU cores: %d", CPUCores + 1);
} }
MADT::~MADT() MADT::~MADT()
{ {
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -24,7 +24,7 @@ TRAMPOLINE_IDT = 0x590
TRAMPOLINE_CORE = 0x600 TRAMPOLINE_CORE = 0x600
TRAMPOLINE_START = 0x2000 TRAMPOLINE_START = 0x2000
.section .text .section .text, "a"
/* ========== 16-bit ========== */ /* ========== 16-bit ========== */

View File

@ -25,330 +25,330 @@
namespace APIC namespace APIC
{ {
enum APICRegisters enum APICRegisters
{ {
// source from: https://github.com/pdoane/osdev/blob/master/intr/local_apic.c // source from: https://github.com/pdoane/osdev/blob/master/intr/local_apic.c
APIC_ID = 0x20, // Local APIC ID APIC_ID = 0x20, // Local APIC ID
APIC_VER = 0x30, // Local APIC Version APIC_VER = 0x30, // Local APIC Version
APIC_TPR = 0x80, // Task Priority APIC_TPR = 0x80, // Task Priority
APIC_APR = 0x90, // Arbitration Priority APIC_APR = 0x90, // Arbitration Priority
APIC_PPR = 0xA0, // Processor Priority APIC_PPR = 0xA0, // Processor Priority
APIC_EOI = 0xB0, // EOI APIC_EOI = 0xB0, // EOI
APIC_RRD = 0xC0, // Remote Read APIC_RRD = 0xC0, // Remote Read
APIC_LDR = 0xD0, // Logical Destination APIC_LDR = 0xD0, // Logical Destination
APIC_DFR = 0xE0, // Destination Format APIC_DFR = 0xE0, // Destination Format
APIC_SVR = 0xF0, // Spurious Interrupt Vector APIC_SVR = 0xF0, // Spurious Interrupt Vector
APIC_ISR = 0x100, // In-Service (8 registers) APIC_ISR = 0x100, // In-Service (8 registers)
APIC_TMR = 0x180, // Trigger Mode (8 registers) APIC_TMR = 0x180, // Trigger Mode (8 registers)
APIC_IRR = 0x200, // Interrupt Request (8 registers) APIC_IRR = 0x200, // Interrupt Request (8 registers)
APIC_ESR = 0x280, // Error Status APIC_ESR = 0x280, // Error Status
APIC_ICRLO = 0x300, // Interrupt Command APIC_ICRLO = 0x300, // Interrupt Command
APIC_ICRHI = 0x310, // Interrupt Command [63:32] APIC_ICRHI = 0x310, // Interrupt Command [63:32]
APIC_TIMER = 0x320, // LVT Timer APIC_TIMER = 0x320, // LVT Timer
APIC_THERMAL = 0x330, // LVT Thermal Sensor APIC_THERMAL = 0x330, // LVT Thermal Sensor
APIC_PERF = 0x340, // LVT Performance Counter APIC_PERF = 0x340, // LVT Performance Counter
APIC_LINT0 = 0x350, // LVT LINT0 APIC_LINT0 = 0x350, // LVT LINT0
APIC_LINT1 = 0x360, // LVT LINT1 APIC_LINT1 = 0x360, // LVT LINT1
APIC_ERROR = 0x370, // LVT Error APIC_ERROR = 0x370, // LVT Error
APIC_TICR = 0x380, // Initial Count (for Timer) APIC_TICR = 0x380, // Initial Count (for Timer)
APIC_TCCR = 0x390, // Current Count (for Timer) APIC_TCCR = 0x390, // Current Count (for Timer)
APIC_TDCR = 0x3E0, // Divide Configuration (for Timer) APIC_TDCR = 0x3E0, // Divide Configuration (for Timer)
}; };
enum IOAPICRegisters enum IOAPICRegisters
{ {
GetIOAPICVersion = 0x1 GetIOAPICVersion = 0x1
}; };
enum IOAPICFlags enum IOAPICFlags
{ {
ActiveHighLow = 2, ActiveHighLow = 2,
EdgeLevel = 8 EdgeLevel = 8
}; };
enum APICDeliveryMode enum APICDeliveryMode
{ {
Fixed = 0b000, Fixed = 0b000,
LowestPriority = 0b001, /* Reserved */ LowestPriority = 0b001, /* Reserved */
SMI = 0b010, SMI = 0b010,
APIC_DELIVERY_MODE_RESERVED0 = 0b011, /* Reserved */ APIC_DELIVERY_MODE_RESERVED0 = 0b011, /* Reserved */
NMI = 0b100, NMI = 0b100,
INIT = 0b101, INIT = 0b101,
Startup = 0b110, Startup = 0b110,
ExtINT = 0b111 /* Reserved */ ExtINT = 0b111 /* Reserved */
}; };
enum APICDestinationMode enum APICDestinationMode
{ {
Physical = 0b0, Physical = 0b0,
Logical = 0b1 Logical = 0b1
}; };
enum APICDeliveryStatus enum APICDeliveryStatus
{ {
Idle = 0b0, Idle = 0b0,
SendPending = 0b1 SendPending = 0b1
}; };
enum APICLevel enum APICLevel
{ {
DeAssert = 0b0, DeAssert = 0b0,
Assert = 0b1 Assert = 0b1
}; };
enum APICTriggerMode enum APICTriggerMode
{ {
Edge = 0b0, Edge = 0b0,
Level = 0b1 Level = 0b1
}; };
enum APICDestinationShorthand enum APICDestinationShorthand
{ {
NoShorthand = 0b00, NoShorthand = 0b00,
Self = 0b01, Self = 0b01,
AllIncludingSelf = 0b10, AllIncludingSelf = 0b10,
AllExcludingSelf = 0b11 AllExcludingSelf = 0b11
}; };
enum LVTTimerDivide enum LVTTimerDivide
{ {
DivideBy2 = 0b000, DivideBy2 = 0b000,
DivideBy4 = 0b001, DivideBy4 = 0b001,
DivideBy8 = 0b010, DivideBy8 = 0b010,
DivideBy16 = 0b011, DivideBy16 = 0b011,
DivideBy32 = 0b100, DivideBy32 = 0b100,
DivideBy64 = 0b101, DivideBy64 = 0b101,
DivideBy128 = 0b110, DivideBy128 = 0b110,
DivideBy1 = 0b111 DivideBy1 = 0b111
}; };
enum LVTTimerMask enum LVTTimerMask
{ {
Unmasked = 0b0, Unmasked = 0b0,
Masked = 0b1 Masked = 0b1
}; };
enum LVTTimerMode enum LVTTimerMode
{ {
OneShot = 0b00, OneShot = 0b00,
Periodic = 0b01, Periodic = 0b01,
TSCDeadline = 0b10 TSCDeadline = 0b10
}; };
typedef union typedef union
{ {
struct struct
{ {
/** @brief Interrupt Vector */ /** @brief Interrupt Vector */
uint64_t Vector : 8; uint64_t Vector : 8;
/** @brief Reserved */ /** @brief Reserved */
uint64_t Reserved0 : 4; uint64_t Reserved0 : 4;
/** /**
* @brief Delivery Status * @brief Delivery Status
* *
* 0: Idle * 0: Idle
* 1: Send Pending * 1: Send Pending
*/ */
uint64_t DeliveryStatus : 1; uint64_t DeliveryStatus : 1;
/** @brief Reserved */ /** @brief Reserved */
uint64_t Reserved1 : 3; uint64_t Reserved1 : 3;
/** /**
* @brief Mask * @brief Mask
* *
* 0: Not masked * 0: Not masked
* 1: Masked * 1: Masked
*/ */
uint64_t Mask : 1; uint64_t Mask : 1;
/** @brief Timer Mode /** @brief Timer Mode
* *
* 0: One-shot * 0: One-shot
* 1: Periodic * 1: Periodic
* 2: TSC-Deadline * 2: TSC-Deadline
*/ */
uint64_t TimerMode : 1; uint64_t TimerMode : 1;
/** @brief Reserved */ /** @brief Reserved */
uint64_t Reserved2 : 14; uint64_t Reserved2 : 14;
}; };
uint64_t raw; uint64_t raw;
} __packed LVTTimer; } __packed LVTTimer;
typedef union typedef union
{ {
struct struct
{ {
/** @brief Spurious Vector */ /** @brief Spurious Vector */
uint64_t Vector : 8; uint64_t Vector : 8;
/** @brief Enable or disable APIC software */ /** @brief Enable or disable APIC software */
uint64_t Software : 1; uint64_t Software : 1;
/** @brief Focus Processor Checking */ /** @brief Focus Processor Checking */
uint64_t FocusProcessorChecking : 1; uint64_t FocusProcessorChecking : 1;
/** @brief Reserved */ /** @brief Reserved */
uint64_t Reserved : 2; uint64_t Reserved : 2;
/** @brief Disable EOI Broadcast */ /** @brief Disable EOI Broadcast */
uint64_t DisableEOIBroadcast : 1; uint64_t DisableEOIBroadcast : 1;
/** @brief Reserved */ /** @brief Reserved */
uint64_t Reserved1 : 19; uint64_t Reserved1 : 19;
}; };
uint64_t raw; uint64_t raw;
} __packed Spurious; } __packed Spurious;
typedef union typedef union
{ {
struct struct
{ {
/** @brief Interrupt Vector */ /** @brief Interrupt Vector */
uint64_t Vector : 8; uint64_t Vector : 8;
/** @brief Delivery Mode */ /** @brief Delivery Mode */
uint64_t DeliveryMode : 3; uint64_t DeliveryMode : 3;
/** @brief Destination Mode /** @brief Destination Mode
* *
* 0: Physical * 0: Physical
* 1: Logical * 1: Logical
*/ */
uint64_t DestinationMode : 1; uint64_t DestinationMode : 1;
/** @brief Delivery Status /** @brief Delivery Status
* *
* @note Reserved when in x2APIC mode * @note Reserved when in x2APIC mode
*/ */
uint64_t DeliveryStatus : 1; uint64_t DeliveryStatus : 1;
/** @brief Reserved */ /** @brief Reserved */
uint64_t Reserved0 : 1; uint64_t Reserved0 : 1;
/** @brief Level /** @brief Level
* *
* 0: Deassert * 0: Deassert
* 1: Assert * 1: Assert
*/ */
uint64_t Level : 1; uint64_t Level : 1;
/** @brief Trigger Mode /** @brief Trigger Mode
* *
* 0: Edge * 0: Edge
* 1: Level * 1: Level
*/ */
uint64_t TriggerMode : 1; uint64_t TriggerMode : 1;
/** @brief Reserved */ /** @brief Reserved */
uint64_t Reserved1 : 2; uint64_t Reserved1 : 2;
/** @brief Destination Shorthand /** @brief Destination Shorthand
* *
* 0: No shorthand * 0: No shorthand
* 1: Self * 1: Self
* 2: All including self * 2: All including self
* 3: All excluding self * 3: All excluding self
*/ */
uint64_t DestinationShorthand : 2; uint64_t DestinationShorthand : 2;
/** @brief Reserved */ /** @brief Reserved */
uint64_t Reserved2 : 12; uint64_t Reserved2 : 12;
}; };
uint64_t raw; uint64_t raw;
} __packed InterruptCommandRegisterLow; } __packed InterruptCommandRegisterLow;
typedef union typedef union
{ {
struct struct
{ {
/** @brief Reserved */ /** @brief Reserved */
uint64_t Reserved0 : 24; uint64_t Reserved0 : 24;
/** @brief Destination */ /** @brief Destination */
uint64_t Destination : 8; uint64_t Destination : 8;
}; };
uint64_t raw; uint64_t raw;
} __packed InterruptCommandRegisterHigh; } __packed InterruptCommandRegisterHigh;
typedef union typedef union
{ {
struct struct
{ {
/** @brief Interrupt Vector */ /** @brief Interrupt Vector */
uint64_t Vector : 8; uint64_t Vector : 8;
/** @brief Delivery Mode */ /** @brief Delivery Mode */
uint64_t DeliveryMode : 3; uint64_t DeliveryMode : 3;
/** @brief Destination Mode /** @brief Destination Mode
* *
* 0: Physical * 0: Physical
* 1: Logical * 1: Logical
*/ */
uint64_t DestinationMode : 1; uint64_t DestinationMode : 1;
/** @brief Delivery Status */ /** @brief Delivery Status */
uint64_t DeliveryStatus : 1; uint64_t DeliveryStatus : 1;
/** @brief Interrupt Input Pin Polarity /** @brief Interrupt Input Pin Polarity
* *
* 0: Active High * 0: Active High
* 1: Active Low * 1: Active Low
*/ */
uint64_t Polarity : 1; uint64_t Polarity : 1;
/** @brief Remote IRR */ /** @brief Remote IRR */
uint64_t RemoteIRR : 1; uint64_t RemoteIRR : 1;
/** @brief Trigger Mode /** @brief Trigger Mode
* *
* 0: Edge * 0: Edge
* 1: Level * 1: Level
*/ */
uint64_t TriggerMode : 1; uint64_t TriggerMode : 1;
/** @brief Mask */ /** @brief Mask */
uint64_t Mask : 1; uint64_t Mask : 1;
/** @brief Reserved */ /** @brief Reserved */
uint64_t Reserved0 : 15; uint64_t Reserved0 : 15;
/** @brief Reserved */ /** @brief Reserved */
uint64_t Reserved1 : 24; uint64_t Reserved1 : 24;
/** @brief Destination */ /** @brief Destination */
uint64_t DestinationID : 8; uint64_t DestinationID : 8;
}; };
struct struct
{ {
uint64_t Low; uint64_t Low;
uint64_t High; uint64_t High;
} split; } split;
uint64_t raw; uint64_t raw;
} __packed IOAPICRedirectEntry; } __packed IOAPICRedirectEntry;
typedef union typedef union
{ {
struct struct
{ {
uint64_t Version : 8; uint64_t Version : 8;
uint64_t Reserved : 8; uint64_t Reserved : 8;
uint64_t MaximumRedirectionEntry : 8; uint64_t MaximumRedirectionEntry : 8;
uint64_t Reserved2 : 8; uint64_t Reserved2 : 8;
}; };
uint64_t raw; uint64_t raw;
} __packed IOAPICVersion; } __packed IOAPICVersion;
class APIC class APIC
{ {
private: private:
bool x2APICSupported = false; bool x2APICSupported = false;
uint64_t APICBaseAddress = 0; uint64_t APICBaseAddress = 0;
public: public:
uint32_t Read(uint32_t Register); uint32_t Read(uint32_t Register);
void Write(uint32_t Register, uint32_t Value); void Write(uint32_t Register, uint32_t Value);
void IOWrite(uint64_t Base, uint32_t Register, uint32_t Value); void IOWrite(uint64_t Base, uint32_t Register, uint32_t Value);
uint32_t IORead(uint64_t Base, uint32_t Register); uint32_t IORead(uint64_t Base, uint32_t Register);
void EOI(); void EOI();
void RedirectIRQs(int CPU = 0); void RedirectIRQs(int CPU = 0);
void WaitForIPI(); void WaitForIPI();
void IPI(int CPU, InterruptCommandRegisterLow icr); void IPI(int CPU, InterruptCommandRegisterLow icr);
void SendInitIPI(int CPU); void SendInitIPI(int CPU);
void SendStartupIPI(int CPU, uint64_t StartupAddress); void SendStartupIPI(int CPU, uint64_t StartupAddress);
uint32_t IOGetMaxRedirect(uint32_t APICID); uint32_t IOGetMaxRedirect(uint32_t APICID);
void RawRedirectIRQ(uint16_t Vector, uint32_t GSI, uint16_t Flags, int CPU, int Status); void RawRedirectIRQ(uint16_t Vector, uint32_t GSI, uint16_t Flags, int CPU, int Status);
void RedirectIRQ(int CPU, uint16_t IRQ, int Status); void RedirectIRQ(int CPU, uint16_t IRQ, int Status);
APIC(int Core); APIC(int Core);
~APIC(); ~APIC();
}; };
class Timer : public Interrupts::Handler class Timer : public Interrupts::Handler
{ {
private: private:
APIC *lapic; APIC *lapic;
uint64_t Ticks = 0; uint64_t Ticks = 0;
void OnInterruptReceived(CPU::x64::TrapFrame *Frame); void OnInterruptReceived(CPU::x64::TrapFrame *Frame);
public: public:
uint64_t GetTicks() { return Ticks; } uint64_t GetTicks() { return Ticks; }
void OneShot(uint32_t Vector, uint64_t Miliseconds); void OneShot(uint32_t Vector, uint64_t Miliseconds);
Timer(APIC *apic); Timer(APIC *apic);
~Timer(); ~Timer();
}; };
} }
#endif // !__FENNIX_KERNEL_APIC_H__ #endif // !__FENNIX_KERNEL_APIC_H__

View File

@ -22,63 +22,63 @@
namespace InterruptDescriptorTable namespace InterruptDescriptorTable
{ {
typedef enum _InterruptGateType typedef enum _InterruptGateType
{ {
TASK = 0b101, TASK = 0b101,
INT_16BIT = 0b110, INT_16BIT = 0b110,
TRAP_16BIT = 0b111, TRAP_16BIT = 0b111,
INT_32BIT = 0b1110, INT_32BIT = 0b1110,
TRAP_32BIT = 0b1111, TRAP_32BIT = 0b1111,
} InterruptGateType; } InterruptGateType;
typedef enum _InterruptRingType typedef enum _InterruptRingType
{ {
RING0 = 0b0, RING0 = 0b0,
RING1 = 0b1, RING1 = 0b1,
RING2 = 0b10, RING2 = 0b10,
RING3 = 0b11, RING3 = 0b11,
} InterruptRingType; } InterruptRingType;
typedef enum _InterruptStackTableType typedef enum _InterruptStackTableType
{ {
IST0 = 0b0, IST0 = 0b0,
IST1 = 0b1, IST1 = 0b1,
IST2 = 0b10, IST2 = 0b10,
IST3 = 0b11, IST3 = 0b11,
IST4 = 0b100, IST4 = 0b100,
IST5 = 0b101, IST5 = 0b101,
IST6 = 0b110, IST6 = 0b110,
} InterruptStackTableType; } InterruptStackTableType;
typedef struct _InterruptDescriptorTableEntry typedef struct _InterruptDescriptorTableEntry
{ {
uint64_t BaseLow : 16; uint64_t BaseLow : 16;
uint64_t SegmentSelector : 16; uint64_t SegmentSelector : 16;
uint64_t InterruptStackTable : 3; uint64_t InterruptStackTable : 3;
uint64_t Reserved1 : 5; uint64_t Reserved1 : 5;
uint64_t Flags : 4; uint64_t Flags : 4;
uint64_t Reserved2 : 1; uint64_t Reserved2 : 1;
uint64_t Ring : 2; uint64_t Ring : 2;
uint64_t Present : 1; uint64_t Present : 1;
uint64_t BaseHigh : 48; uint64_t BaseHigh : 48;
uint64_t Reserved3 : 32; uint64_t Reserved3 : 32;
} __packed InterruptDescriptorTableEntry; } __packed InterruptDescriptorTableEntry;
typedef struct _InterruptDescriptorTableDescriptor typedef struct _InterruptDescriptorTableDescriptor
{ {
uint16_t Length; uint16_t Length;
InterruptDescriptorTableEntry *Entries; InterruptDescriptorTableEntry *Entries;
} __packed InterruptDescriptorTableDescriptor; } __packed InterruptDescriptorTableDescriptor;
void SetEntry(uint8_t Index, void SetEntry(uint8_t Index,
void (*Base)(), void (*Base)(),
InterruptStackTableType InterruptStackTable, InterruptStackTableType InterruptStackTable,
InterruptGateType Gate, InterruptGateType Gate,
InterruptRingType Ring, InterruptRingType Ring,
bool Present, bool Present,
uint16_t SegmentSelector); uint16_t SegmentSelector);
void Init(int Core); void Init(int Core);
} }
#endif // !__FENNIX_KERNEL_IDT_H__ #endif // !__FENNIX_KERNEL_IDT_H__

View File

@ -0,0 +1,158 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "acpi.hpp"
#include <debug.h>
#include <io.h>
#include "../../kernel.h"
namespace ACPI
{
__no_sanitize("alignment") void *ACPI::FindTable(ACPI::ACPIHeader *ACPIHeader, char *Signature)
{
for (uint64_t t = 0; t < ((ACPIHeader->Length - sizeof(ACPI::ACPIHeader)) / (XSDTSupported ? 8 : 4)); t++)
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
// TODO: 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)));
#pragma GCC diagnostic pop
for (int i = 0; i < 4; i++)
{
if (SDTHdr->Signature[i] != Signature[i])
break;
if (i == 3)
{
trace("%s found at address %p", Signature, (uintptr_t)SDTHdr);
return SDTHdr;
}
}
}
// warn("%s not found!", Signature);
return nullptr;
}
void ACPI::SearchTables(ACPIHeader *Header)
{
if (!Header)
return;
HPET = (HPETHeader *)FindTable(Header, (char *)"HPET");
FADT = (FADTHeader *)FindTable(Header, (char *)"FACP");
MCFG = (MCFGHeader *)FindTable(Header, (char *)"MCFG");
BGRT = (BGRTHeader *)FindTable(Header, (char *)"BGRT");
SRAT = (SRATHeader *)FindTable(Header, (char *)"SRAT");
TPM2 = (TPM2Header *)FindTable(Header, (char *)"TPM2");
TCPA = (TCPAHeader *)FindTable(Header, (char *)"TCPA");
WAET = (WAETHeader *)FindTable(Header, (char *)"WAET");
MADT = (MADTHeader *)FindTable(Header, (char *)"APIC");
HEST = (HESTHeader *)FindTable(Header, (char *)"HEST");
FindTable(Header, (char *)"BERT");
FindTable(Header, (char *)"CPEP");
FindTable(Header, (char *)"DSDT");
FindTable(Header, (char *)"ECDT");
FindTable(Header, (char *)"EINJ");
FindTable(Header, (char *)"ERST");
FindTable(Header, (char *)"FACS");
FindTable(Header, (char *)"MSCT");
FindTable(Header, (char *)"MPST");
FindTable(Header, (char *)"OEMx");
FindTable(Header, (char *)"PMTT");
FindTable(Header, (char *)"PSDT");
FindTable(Header, (char *)"RASF");
FindTable(Header, (char *)"RSDT");
FindTable(Header, (char *)"SBST");
FindTable(Header, (char *)"SLIT");
FindTable(Header, (char *)"SSDT");
FindTable(Header, (char *)"XSDT");
FindTable(Header, (char *)"DRTM");
FindTable(Header, (char *)"FPDT");
FindTable(Header, (char *)"GTDT");
FindTable(Header, (char *)"PCCT");
FindTable(Header, (char *)"S3PT");
FindTable(Header, (char *)"MATR");
FindTable(Header, (char *)"MSDM");
FindTable(Header, (char *)"WPBT");
FindTable(Header, (char *)"OSDT");
FindTable(Header, (char *)"RSDP");
FindTable(Header, (char *)"NFIT");
FindTable(Header, (char *)"ASF!");
FindTable(Header, (char *)"BOOT");
FindTable(Header, (char *)"CSRT");
FindTable(Header, (char *)"DBG2");
FindTable(Header, (char *)"DBGP");
FindTable(Header, (char *)"DMAR");
FindTable(Header, (char *)"IBFT");
FindTable(Header, (char *)"IORT");
FindTable(Header, (char *)"IVRS");
FindTable(Header, (char *)"LPIT");
FindTable(Header, (char *)"MCHI");
FindTable(Header, (char *)"MTMR");
FindTable(Header, (char *)"SLIC");
FindTable(Header, (char *)"SPCR");
FindTable(Header, (char *)"SPMI");
FindTable(Header, (char *)"UEFI");
FindTable(Header, (char *)"VRTC");
FindTable(Header, (char *)"WDAT");
FindTable(Header, (char *)"WDDT");
FindTable(Header, (char *)"WDRT");
FindTable(Header, (char *)"ATKG");
FindTable(Header, (char *)"GSCI");
FindTable(Header, (char *)"IEIT");
FindTable(Header, (char *)"HMAT");
FindTable(Header, (char *)"CEDT");
FindTable(Header, (char *)"AEST");
}
ACPI::ACPI()
{
trace("Initializing ACPI");
if (bInfo.RSDP->Revision >= 2 && bInfo.RSDP->XSDTAddress)
{
debug("XSDT supported");
XSDTSupported = true;
XSDT = (ACPIHeader *)(bInfo.RSDP->XSDTAddress);
}
else
{
debug("RSDT supported");
XSDT = (ACPIHeader *)(uintptr_t)bInfo.RSDP->RSDTAddress;
}
this->SearchTables(XSDT);
if (FADT)
{
outb(s_cst(uint16_t, FADT->SMI_CommandPort), FADT->AcpiEnable);
while (!(inw(s_cst(uint16_t, FADT->PM1aControlBlock)) & 1))
;
}
}
ACPI::~ACPI()
{
}
}

View File

@ -18,7 +18,7 @@
.intel_syntax noprefix .intel_syntax noprefix
.code32 .code32
.section .multiboot .section .multiboot, "a"
.align 4 .align 4
MULTIBOOT_HEADER: MULTIBOOT_HEADER:

View File

@ -16,7 +16,7 @@
*/ */
.code32 .code32
.section .bootstrap.text .section .bootstrap.text, "a"
.global Multiboot1_start .global Multiboot1_start
Multiboot1_start: Multiboot1_start:

View File

@ -18,7 +18,7 @@
.intel_syntax noprefix .intel_syntax noprefix
.code32 .code32
.section .bootstrap.text .section .bootstrap.text, "a"
.global DetectCPUID .global DetectCPUID
DetectCPUID: DetectCPUID:

View File

@ -18,7 +18,7 @@
.intel_syntax noprefix .intel_syntax noprefix
.code32 .code32
.section .bootstrap.text .section .bootstrap.text, "a"
.align 32 .align 32
.global gdtr .global gdtr

View File

@ -21,7 +21,7 @@
.extern Multiboot2_start .extern Multiboot2_start
/* https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html */ /* https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html */
.section .multiboot2 .section .multiboot2, "a"
.align 0x1000 .align 0x1000
MULTIBOOT2_HEADER_START: MULTIBOOT2_HEADER_START:
.long 0xE85250D6 .long 0xE85250D6

View File

@ -25,291 +25,291 @@
EXTERNC void multiboot_main(uintptr_t Magic, uintptr_t Info) EXTERNC void multiboot_main(uintptr_t Magic, uintptr_t Info)
{ {
if (Info == NULL || Magic == NULL) if (Info == NULL || Magic == NULL)
{ {
if (Magic == NULL) if (Magic == NULL)
error("Multiboot magic is NULL"); error("Multiboot magic is NULL");
if (Info == NULL) if (Info == NULL)
error("Multiboot info is NULL"); error("Multiboot info is NULL");
CPU::Stop(); CPU::Stop();
} }
else if (Magic != MULTIBOOT2_BOOTLOADER_MAGIC) else if (Magic != MULTIBOOT2_BOOTLOADER_MAGIC)
{ {
error("Multiboot magic is invalid (%#x != %#x)", Magic, MULTIBOOT2_BOOTLOADER_MAGIC); error("Multiboot magic is invalid (%#x != %#x)", Magic, MULTIBOOT2_BOOTLOADER_MAGIC);
CPU::Stop(); CPU::Stop();
} }
BootInfo mb2binfo{}; BootInfo mb2binfo{};
{ {
uint64_t div = 1193180 / 1000; uint64_t div = 1193180 / 1000;
outb(0x43, 0xB6); outb(0x43, 0xB6);
outb(0x42, (uint8_t)div); outb(0x42, (uint8_t)div);
outb(0x42, (uint8_t)(div >> 8)); outb(0x42, (uint8_t)(div >> 8));
uint8_t tmp = inb(0x61); uint8_t tmp = inb(0x61);
if (tmp != (tmp | 3)) if (tmp != (tmp | 3))
outb(0x61, tmp | 3); outb(0x61, tmp | 3);
int pos = 0; int pos = 0;
auto InfoAddress = Info; auto InfoAddress = Info;
for (auto Tag = (struct multiboot_tag *)((uint8_t *)InfoAddress + 8); for (auto Tag = (struct multiboot_tag *)((uint8_t *)InfoAddress + 8);
; ;
Tag = (struct multiboot_tag *)((multiboot_uint8_t *)Tag + ((Tag->size + 7) & ~7))) Tag = (struct multiboot_tag *)((multiboot_uint8_t *)Tag + ((Tag->size + 7) & ~7)))
{ {
if (Tag->type == MULTIBOOT_TAG_TYPE_END) if (Tag->type == MULTIBOOT_TAG_TYPE_END)
{ {
debug("End of multiboot2 tags"); debug("End of multiboot2 tags");
break; break;
} }
switch (Tag->type) switch (Tag->type)
{ {
case MULTIBOOT_TAG_TYPE_CMDLINE: case MULTIBOOT_TAG_TYPE_CMDLINE:
{ {
strncpy(mb2binfo.Kernel.CommandLine, strncpy(mb2binfo.Kernel.CommandLine,
((multiboot_tag_string *)Tag)->string, ((multiboot_tag_string *)Tag)->string,
strlen(((multiboot_tag_string *)Tag)->string)); strlen(((multiboot_tag_string *)Tag)->string));
debug("Kernel command line: %s", mb2binfo.Kernel.CommandLine); debug("Kernel command line: %s", mb2binfo.Kernel.CommandLine);
break; break;
} }
case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME: case MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME:
{ {
strncpy(mb2binfo.Bootloader.Name, strncpy(mb2binfo.Bootloader.Name,
((multiboot_tag_string *)Tag)->string, ((multiboot_tag_string *)Tag)->string,
strlen(((multiboot_tag_string *)Tag)->string)); strlen(((multiboot_tag_string *)Tag)->string));
debug("Bootloader name: %s", mb2binfo.Bootloader.Name); debug("Bootloader name: %s", mb2binfo.Bootloader.Name);
break; break;
} }
case MULTIBOOT_TAG_TYPE_MODULE: case MULTIBOOT_TAG_TYPE_MODULE:
{ {
multiboot_tag_module *module = (multiboot_tag_module *)Tag; multiboot_tag_module *module = (multiboot_tag_module *)Tag;
static int module_count = 0; static int module_count = 0;
mb2binfo.Modules[module_count].Address = (void *)(uint64_t)module->mod_start; mb2binfo.Modules[module_count].Address = (void *)(uint64_t)module->mod_start;
mb2binfo.Modules[module_count].Size = module->mod_end - module->mod_start; mb2binfo.Modules[module_count].Size = module->mod_end - module->mod_start;
strncpy(mb2binfo.Modules[module_count].Path, "(null)", 6); strncpy(mb2binfo.Modules[module_count].Path, "(null)", 6);
strncpy(mb2binfo.Modules[module_count].CommandLine, module->cmdline, strncpy(mb2binfo.Modules[module_count].CommandLine, module->cmdline,
strlen(module->cmdline)); strlen(module->cmdline));
debug("Module: %s", mb2binfo.Modules[module_count].Path); debug("Module: %s", mb2binfo.Modules[module_count].Path);
module_count++; module_count++;
break; break;
} }
case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO: case MULTIBOOT_TAG_TYPE_BASIC_MEMINFO:
{ {
multiboot_tag_basic_meminfo *meminfo = (multiboot_tag_basic_meminfo *)Tag; multiboot_tag_basic_meminfo *meminfo = (multiboot_tag_basic_meminfo *)Tag;
fixme("basic_meminfo->[mem_lower: %#x, mem_upper: %#x]", fixme("basic_meminfo->[mem_lower: %#x, mem_upper: %#x]",
meminfo->mem_lower, meminfo->mem_upper); meminfo->mem_lower, meminfo->mem_upper);
break; break;
} }
case MULTIBOOT_TAG_TYPE_BOOTDEV: case MULTIBOOT_TAG_TYPE_BOOTDEV:
{ {
multiboot_tag_bootdev *bootdev = (multiboot_tag_bootdev *)Tag; multiboot_tag_bootdev *bootdev = (multiboot_tag_bootdev *)Tag;
fixme("bootdev->[biosdev: %#x, slice: %#x, part: %#x]", fixme("bootdev->[biosdev: %#x, slice: %#x, part: %#x]",
bootdev->biosdev, bootdev->slice, bootdev->part); bootdev->biosdev, bootdev->slice, bootdev->part);
break; break;
} }
case MULTIBOOT_TAG_TYPE_MMAP: case MULTIBOOT_TAG_TYPE_MMAP:
{ {
multiboot_tag_mmap *mmap = (multiboot_tag_mmap *)Tag; multiboot_tag_mmap *mmap = (multiboot_tag_mmap *)Tag;
size_t EntryCount = mmap->size / sizeof(multiboot_mmap_entry); size_t EntryCount = mmap->size / sizeof(multiboot_mmap_entry);
mb2binfo.Memory.Entries = EntryCount; mb2binfo.Memory.Entries = EntryCount;
for (uint32_t i = 0; i < EntryCount; i++) for (uint32_t i = 0; i < EntryCount; i++)
{ {
if (i > MAX_MEMORY_ENTRIES) if (i > MAX_MEMORY_ENTRIES)
{ {
warn("Too many memory entries, skipping the rest..."); warn("Too many memory entries, skipping the rest...");
break; break;
} }
multiboot_mmap_entry entry = mmap->entries[i]; multiboot_mmap_entry entry = mmap->entries[i];
mb2binfo.Memory.Size += (size_t)entry.len; mb2binfo.Memory.Size += (size_t)entry.len;
switch (entry.type) switch (entry.type)
{ {
case MULTIBOOT_MEMORY_AVAILABLE: case MULTIBOOT_MEMORY_AVAILABLE:
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
mb2binfo.Memory.Entry[i].Length = (size_t)entry.len; mb2binfo.Memory.Entry[i].Length = (size_t)entry.len;
mb2binfo.Memory.Entry[i].Type = Usable; mb2binfo.Memory.Entry[i].Type = Usable;
break; break;
case MULTIBOOT_MEMORY_RESERVED: case MULTIBOOT_MEMORY_RESERVED:
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
mb2binfo.Memory.Entry[i].Length = (size_t)entry.len; mb2binfo.Memory.Entry[i].Length = (size_t)entry.len;
mb2binfo.Memory.Entry[i].Type = Reserved; mb2binfo.Memory.Entry[i].Type = Reserved;
break; break;
case MULTIBOOT_MEMORY_ACPI_RECLAIMABLE: case MULTIBOOT_MEMORY_ACPI_RECLAIMABLE:
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
mb2binfo.Memory.Entry[i].Length = (size_t)entry.len; mb2binfo.Memory.Entry[i].Length = (size_t)entry.len;
mb2binfo.Memory.Entry[i].Type = ACPIReclaimable; mb2binfo.Memory.Entry[i].Type = ACPIReclaimable;
break; break;
case MULTIBOOT_MEMORY_NVS: case MULTIBOOT_MEMORY_NVS:
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
mb2binfo.Memory.Entry[i].Length = (size_t)entry.len; mb2binfo.Memory.Entry[i].Length = (size_t)entry.len;
mb2binfo.Memory.Entry[i].Type = ACPINVS; mb2binfo.Memory.Entry[i].Type = ACPINVS;
break; break;
case MULTIBOOT_MEMORY_BADRAM: case MULTIBOOT_MEMORY_BADRAM:
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
mb2binfo.Memory.Entry[i].Length = (size_t)entry.len; mb2binfo.Memory.Entry[i].Length = (size_t)entry.len;
mb2binfo.Memory.Entry[i].Type = BadMemory; mb2binfo.Memory.Entry[i].Type = BadMemory;
break; break;
default: default:
mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr; mb2binfo.Memory.Entry[i].BaseAddress = (void *)entry.addr;
mb2binfo.Memory.Entry[i].Length = (size_t)entry.len; mb2binfo.Memory.Entry[i].Length = (size_t)entry.len;
mb2binfo.Memory.Entry[i].Type = Unknown; mb2binfo.Memory.Entry[i].Type = Unknown;
break; break;
} }
debug("Memory entry: [BaseAddress: %#x, Length: %#x, Type: %d]", debug("Memory entry: [BaseAddress: %#x, Length: %#x, Type: %d]",
mb2binfo.Memory.Entry[i].BaseAddress, mb2binfo.Memory.Entry[i].BaseAddress,
mb2binfo.Memory.Entry[i].Length, mb2binfo.Memory.Entry[i].Length,
mb2binfo.Memory.Entry[i].Type); mb2binfo.Memory.Entry[i].Type);
} }
break; break;
} }
case MULTIBOOT_TAG_TYPE_VBE: case MULTIBOOT_TAG_TYPE_VBE:
{ {
multiboot_tag_vbe *vbe = (multiboot_tag_vbe *)Tag; multiboot_tag_vbe *vbe = (multiboot_tag_vbe *)Tag;
fixme("vbe->[vbe_mode: %#x, vbe_interface_seg: %#x, vbe_interface_off: %#x, vbe_interface_len: %#x]", fixme("vbe->[vbe_mode: %#x, vbe_interface_seg: %#x, vbe_interface_off: %#x, vbe_interface_len: %#x]",
vbe->vbe_mode, vbe->vbe_interface_seg, vbe->vbe_interface_off, vbe->vbe_interface_len); vbe->vbe_mode, vbe->vbe_interface_seg, vbe->vbe_interface_off, vbe->vbe_interface_len);
break; break;
} }
case MULTIBOOT_TAG_TYPE_FRAMEBUFFER: case MULTIBOOT_TAG_TYPE_FRAMEBUFFER:
{ {
multiboot_tag_framebuffer *fb = (multiboot_tag_framebuffer *)Tag; multiboot_tag_framebuffer *fb = (multiboot_tag_framebuffer *)Tag;
static int fb_count = 0; static int fb_count = 0;
mb2binfo.Framebuffer[fb_count].BaseAddress = (void *)fb->common.framebuffer_addr; mb2binfo.Framebuffer[fb_count].BaseAddress = (void *)fb->common.framebuffer_addr;
mb2binfo.Framebuffer[fb_count].Width = fb->common.framebuffer_width; mb2binfo.Framebuffer[fb_count].Width = fb->common.framebuffer_width;
mb2binfo.Framebuffer[fb_count].Height = fb->common.framebuffer_height; mb2binfo.Framebuffer[fb_count].Height = fb->common.framebuffer_height;
mb2binfo.Framebuffer[fb_count].Pitch = fb->common.framebuffer_pitch; mb2binfo.Framebuffer[fb_count].Pitch = fb->common.framebuffer_pitch;
mb2binfo.Framebuffer[fb_count].BitsPerPixel = fb->common.framebuffer_bpp; mb2binfo.Framebuffer[fb_count].BitsPerPixel = fb->common.framebuffer_bpp;
switch (fb->common.framebuffer_type) switch (fb->common.framebuffer_type)
{ {
case MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED: case MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED:
{ {
mb2binfo.Framebuffer[fb_count].Type = Indexed; mb2binfo.Framebuffer[fb_count].Type = Indexed;
break; break;
} }
case MULTIBOOT_FRAMEBUFFER_TYPE_RGB: case MULTIBOOT_FRAMEBUFFER_TYPE_RGB:
{ {
mb2binfo.Framebuffer[fb_count].Type = RGB; mb2binfo.Framebuffer[fb_count].Type = RGB;
mb2binfo.Framebuffer[fb_count].RedMaskSize = fb->framebuffer_red_mask_size; mb2binfo.Framebuffer[fb_count].RedMaskSize = fb->framebuffer_red_mask_size;
mb2binfo.Framebuffer[fb_count].RedMaskShift = fb->framebuffer_red_field_position; mb2binfo.Framebuffer[fb_count].RedMaskShift = fb->framebuffer_red_field_position;
mb2binfo.Framebuffer[fb_count].GreenMaskSize = fb->framebuffer_green_mask_size; mb2binfo.Framebuffer[fb_count].GreenMaskSize = fb->framebuffer_green_mask_size;
mb2binfo.Framebuffer[fb_count].GreenMaskShift = fb->framebuffer_green_field_position; mb2binfo.Framebuffer[fb_count].GreenMaskShift = fb->framebuffer_green_field_position;
mb2binfo.Framebuffer[fb_count].BlueMaskSize = fb->framebuffer_blue_mask_size; mb2binfo.Framebuffer[fb_count].BlueMaskSize = fb->framebuffer_blue_mask_size;
mb2binfo.Framebuffer[fb_count].BlueMaskShift = fb->framebuffer_blue_field_position; mb2binfo.Framebuffer[fb_count].BlueMaskShift = fb->framebuffer_blue_field_position;
break; break;
} }
case MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT: case MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT:
{ {
mb2binfo.Framebuffer[fb_count].Type = EGA; mb2binfo.Framebuffer[fb_count].Type = EGA;
break; break;
} }
default: default:
{ {
mb2binfo.Framebuffer[fb_count].Type = Unknown_Framebuffer_Type; mb2binfo.Framebuffer[fb_count].Type = Unknown_Framebuffer_Type;
break; break;
} }
} }
debug("Framebuffer %d: %dx%d %d bpp", fb_count, fb->common.framebuffer_width, fb->common.framebuffer_height, fb->common.framebuffer_bpp); debug("Framebuffer %d: %dx%d %d bpp", fb_count, fb->common.framebuffer_width, fb->common.framebuffer_height, fb->common.framebuffer_bpp);
debug("More info:\nAddress: %p\nPitch: %lld\nMemoryModel: %d\nRedMaskSize: %d\nRedMaskShift: %d\nGreenMaskSize: %d\nGreenMaskShift: %d\nBlueMaskSize: %d\nBlueMaskShift: %d", debug("More info:\nAddress: %p\nPitch: %lld\nMemoryModel: %d\nRedMaskSize: %d\nRedMaskShift: %d\nGreenMaskSize: %d\nGreenMaskShift: %d\nBlueMaskSize: %d\nBlueMaskShift: %d",
fb->common.framebuffer_addr, fb->common.framebuffer_pitch, fb->common.framebuffer_type, fb->common.framebuffer_addr, fb->common.framebuffer_pitch, fb->common.framebuffer_type,
fb->framebuffer_red_mask_size, fb->framebuffer_red_field_position, fb->framebuffer_green_mask_size, fb->framebuffer_red_mask_size, fb->framebuffer_red_field_position, fb->framebuffer_green_mask_size,
fb->framebuffer_green_field_position, fb->framebuffer_blue_mask_size, fb->framebuffer_blue_field_position); fb->framebuffer_green_field_position, fb->framebuffer_blue_mask_size, fb->framebuffer_blue_field_position);
fb_count++; fb_count++;
break; break;
} }
case MULTIBOOT_TAG_TYPE_ELF_SECTIONS: case MULTIBOOT_TAG_TYPE_ELF_SECTIONS:
{ {
multiboot_tag_elf_sections *elf = (multiboot_tag_elf_sections *)Tag; multiboot_tag_elf_sections *elf = (multiboot_tag_elf_sections *)Tag;
mb2binfo.Kernel.Symbols.Num = elf->num; mb2binfo.Kernel.Symbols.Num = elf->num;
mb2binfo.Kernel.Symbols.EntSize = elf->entsize; mb2binfo.Kernel.Symbols.EntSize = elf->entsize;
mb2binfo.Kernel.Symbols.Shndx = elf->shndx; mb2binfo.Kernel.Symbols.Shndx = elf->shndx;
mb2binfo.Kernel.Symbols.Sections = (uintptr_t)&elf->sections; mb2binfo.Kernel.Symbols.Sections = (uintptr_t)&elf->sections;
break; break;
} }
case MULTIBOOT_TAG_TYPE_APM: case MULTIBOOT_TAG_TYPE_APM:
{ {
multiboot_tag_apm *apm = (multiboot_tag_apm *)Tag; multiboot_tag_apm *apm = (multiboot_tag_apm *)Tag;
fixme("apm->[version: %d, cseg: %d, offset: %d, cseg_16: %d, dseg: %d, flags: %d, cseg_len: %d, cseg_16_len: %d, dseg_len: %d]", fixme("apm->[version: %d, cseg: %d, offset: %d, cseg_16: %d, dseg: %d, flags: %d, cseg_len: %d, cseg_16_len: %d, dseg_len: %d]",
apm->version, apm->cseg, apm->offset, apm->cseg_16, apm->dseg, apm->flags, apm->cseg_len, apm->cseg_16_len, apm->dseg_len); apm->version, apm->cseg, apm->offset, apm->cseg_16, apm->dseg, apm->flags, apm->cseg_len, apm->cseg_16_len, apm->dseg_len);
break; break;
} }
case MULTIBOOT_TAG_TYPE_EFI32: case MULTIBOOT_TAG_TYPE_EFI32:
{ {
multiboot_tag_efi32 *efi32 = (multiboot_tag_efi32 *)Tag; multiboot_tag_efi32 *efi32 = (multiboot_tag_efi32 *)Tag;
fixme("efi32->[pointer: %p, size: %d]", efi32->pointer, efi32->size); fixme("efi32->[pointer: %p, size: %d]", efi32->pointer, efi32->size);
break; break;
} }
case MULTIBOOT_TAG_TYPE_EFI64: case MULTIBOOT_TAG_TYPE_EFI64:
{ {
multiboot_tag_efi64 *efi64 = (multiboot_tag_efi64 *)Tag; multiboot_tag_efi64 *efi64 = (multiboot_tag_efi64 *)Tag;
fixme("efi64->[pointer: %p, size: %d]", efi64->pointer, efi64->size); fixme("efi64->[pointer: %p, size: %d]", efi64->pointer, efi64->size);
break; break;
} }
case MULTIBOOT_TAG_TYPE_SMBIOS: case MULTIBOOT_TAG_TYPE_SMBIOS:
{ {
multiboot_tag_smbios *smbios = (multiboot_tag_smbios *)Tag; multiboot_tag_smbios *smbios = (multiboot_tag_smbios *)Tag;
fixme("smbios->[major: %d, minor: %d]", smbios->major, smbios->minor); fixme("smbios->[major: %d, minor: %d]", smbios->major, smbios->minor);
break; break;
} }
case MULTIBOOT_TAG_TYPE_ACPI_OLD: case MULTIBOOT_TAG_TYPE_ACPI_OLD:
{ {
mb2binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_old_acpi *)Tag)->rsdp; mb2binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_old_acpi *)Tag)->rsdp;
debug("OLD ACPI RSDP: %p", mb2binfo.RSDP); debug("OLD ACPI RSDP: %p", mb2binfo.RSDP);
break; break;
} }
case MULTIBOOT_TAG_TYPE_ACPI_NEW: case MULTIBOOT_TAG_TYPE_ACPI_NEW:
{ {
mb2binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_new_acpi *)Tag)->rsdp; mb2binfo.RSDP = (BootInfo::RSDPInfo *)((multiboot_tag_new_acpi *)Tag)->rsdp;
debug("NEW ACPI RSDP: %p", mb2binfo.RSDP); debug("NEW ACPI RSDP: %p", mb2binfo.RSDP);
break; break;
} }
case MULTIBOOT_TAG_TYPE_NETWORK: case MULTIBOOT_TAG_TYPE_NETWORK:
{ {
multiboot_tag_network *net = (multiboot_tag_network *)Tag; multiboot_tag_network *net = (multiboot_tag_network *)Tag;
fixme("network->[dhcpack: %p]", net->dhcpack); fixme("network->[dhcpack: %p]", net->dhcpack);
break; break;
} }
case MULTIBOOT_TAG_TYPE_EFI_MMAP: case MULTIBOOT_TAG_TYPE_EFI_MMAP:
{ {
multiboot_tag_efi_mmap *efi_mmap = (multiboot_tag_efi_mmap *)Tag; multiboot_tag_efi_mmap *efi_mmap = (multiboot_tag_efi_mmap *)Tag;
fixme("efi_mmap->[descr_size: %d, descr_vers: %d, efi_mmap: %p]", fixme("efi_mmap->[descr_size: %d, descr_vers: %d, efi_mmap: %p]",
efi_mmap->descr_size, efi_mmap->descr_vers, efi_mmap->efi_mmap); efi_mmap->descr_size, efi_mmap->descr_vers, efi_mmap->efi_mmap);
break; break;
} }
case MULTIBOOT_TAG_TYPE_EFI_BS: case MULTIBOOT_TAG_TYPE_EFI_BS:
{ {
fixme("efi_bs->[%p] (unknown structure)", Tag); fixme("efi_bs->[%p] (unknown structure)", Tag);
break; break;
} }
case MULTIBOOT_TAG_TYPE_EFI32_IH: case MULTIBOOT_TAG_TYPE_EFI32_IH:
{ {
multiboot_tag_efi32_ih *efi32_ih = (multiboot_tag_efi32_ih *)Tag; multiboot_tag_efi32_ih *efi32_ih = (multiboot_tag_efi32_ih *)Tag;
fixme("efi32_ih->[pointer: %p]", efi32_ih->pointer); fixme("efi32_ih->[pointer: %p]", efi32_ih->pointer);
break; break;
} }
case MULTIBOOT_TAG_TYPE_EFI64_IH: case MULTIBOOT_TAG_TYPE_EFI64_IH:
{ {
multiboot_tag_efi64_ih *efi64_ih = (multiboot_tag_efi64_ih *)Tag; multiboot_tag_efi64_ih *efi64_ih = (multiboot_tag_efi64_ih *)Tag;
fixme("efi64_ih->[pointer: %p]", efi64_ih->pointer); fixme("efi64_ih->[pointer: %p]", efi64_ih->pointer);
break; break;
} }
case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR: case MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR:
{ {
multiboot_tag_load_base_addr *load_base_addr = (multiboot_tag_load_base_addr *)Tag; multiboot_tag_load_base_addr *load_base_addr = (multiboot_tag_load_base_addr *)Tag;
mb2binfo.Kernel.PhysicalBase = (void *)(uint64_t)load_base_addr->load_base_addr; mb2binfo.Kernel.PhysicalBase = (void *)(uint64_t)load_base_addr->load_base_addr;
mb2binfo.Kernel.VirtualBase = (void *)(uint64_t)(load_base_addr->load_base_addr + 0xFFFFFFFF80000000); mb2binfo.Kernel.VirtualBase = (void *)(uint64_t)(load_base_addr->load_base_addr + 0xFFFFFFFF80000000);
mb2binfo.Kernel.Size = (size_t)(((uint64_t)&_kernel_end - (uint64_t)&_kernel_start) + ((uint64_t)&_bootstrap_end - (uint64_t)&_bootstrap_start)); mb2binfo.Kernel.Size = (size_t)(((uint64_t)&_kernel_end - (uint64_t)&_kernel_start) + ((uint64_t)&_bootstrap_end - (uint64_t)&_bootstrap_start));
debug("Kernel base: %p (physical) %p (virtual)", mb2binfo.Kernel.PhysicalBase, mb2binfo.Kernel.VirtualBase); debug("Kernel base: %p (physical) %p (virtual)", mb2binfo.Kernel.PhysicalBase, mb2binfo.Kernel.VirtualBase);
break; break;
} }
default: default:
{ {
error("Unknown multiboot2 tag type: %d", Tag->type); error("Unknown multiboot2 tag type: %d", Tag->type);
break; break;
} }
} }
} }
tmp = inb(0x61) & 0xFC; tmp = inb(0x61) & 0xFC;
outb(0x61, tmp); outb(0x61, tmp);
} }
Entry(&mb2binfo); Entry(&mb2binfo);
} }

View File

@ -19,7 +19,7 @@
KERNEL_VIRTUAL_BASE = 0xC0000000 /* 3GB */ KERNEL_VIRTUAL_BASE = 0xC0000000 /* 3GB */
KERNEL_PAGE_NUMBER = 768 /* KERNEL_VIRTUAL_BASE >> 22 */ KERNEL_PAGE_NUMBER = 768 /* KERNEL_VIRTUAL_BASE >> 22 */
.section .bootstrap.data .section .bootstrap.data, "a"
.align 0x1000 .align 0x1000
.global BootPageTable .global BootPageTable
BootPageTable: BootPageTable:

View File

@ -24,14 +24,14 @@ KERNEL_STACK_SIZE = 0x4000 /* 16KB */
.extern LoadGDT32 .extern LoadGDT32
.extern BootPageTable .extern BootPageTable
.section .bootstrap.data .section .bootstrap.data, "a"
MB_HeaderMagic: MB_HeaderMagic:
.quad 0 .quad 0
MB_HeaderInfo: MB_HeaderInfo:
.quad 0 .quad 0
.section .bootstrap.text .section .bootstrap.text, "a"
.global Multiboot2_start .global Multiboot2_start
Multiboot2_start: Multiboot2_start:
@ -73,7 +73,7 @@ Multiboot2_start:
hlt hlt
jmp .Hang jmp .Hang
.section .bootstrap.bss .section .bootstrap.bss, "a"
.align 16 .align 16
KernelStack: KernelStack:
.space KERNEL_STACK_SIZE .space KERNEL_STACK_SIZE

View File

@ -21,7 +21,7 @@
.extern Multiboot2_start .extern Multiboot2_start
.code32 .code32
.section .bootstrap.text .section .bootstrap.text, "a"
.global _start .global _start
_start: _start:

View File

@ -0,0 +1,255 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "acpi.hpp"
#include <time.hpp>
#include <debug.h>
#include <smp.hpp>
#include <io.h>
#include "cpu/apic.hpp"
#include "../../kernel.h"
#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
{
__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::OnInterruptReceived(CPU::x32::TrapFrame *Frame)
{
debug("SCI Handle Triggered");
uint16_t Event = 0;
{
uint16_t a = 0, b = 0;
if (acpi->FADT->PM1aEventBlock)
{
a = inw(s_cst(uint16_t, acpi->FADT->PM1aEventBlock));
outw(s_cst(uint16_t, acpi->FADT->PM1aEventBlock), a);
}
if (acpi->FADT->PM1bEventBlock)
{
b = inw(s_cst(uint16_t, acpi->FADT->PM1bEventBlock));
outw(s_cst(uint16_t, acpi->FADT->PM1bEventBlock), b);
}
Event = a | b;
}
debug("SCI Event: %#lx", Event);
if (Event & ACPI_BUSMASTER)
{
fixme("ACPI Busmaster");
}
else if (Event & ACPI_GLOBAL)
{
fixme("ACPI Global");
}
else if (Event & ACPI_POWER_BUTTON)
{
if (TaskManager && !TaskManager->IsPanic())
{
TaskManager->CreateThread(TaskManager->CreateProcess(nullptr,
"Shutdown",
Tasking::TaskExecutionMode::Kernel),
Tasking::IP(KST_Shutdown));
}
else
KernelShutdownThread(false);
}
else if (Event & ACPI_SLEEP_BUTTON)
{
fixme("ACPI Sleep Button");
}
else if (Event & ACPI_RTC_ALARM)
{
fixme("ACPI RTC Alarm");
}
else if (Event & ACPI_PCIE_WAKE)
{
fixme("ACPI PCIe Wake");
}
else if (Event & ACPI_WAKE)
{
fixme("ACPI Wake");
}
else if (Event & ACPI_TIMER)
{
fixme("ACPI Timer");
}
else
{
error("ACPI unknown event %#lx on CPU %d", Event, GetCurrentCPU()->ID);
CPU::Stop();
}
UNUSED(Frame);
}
void DSDT::Shutdown()
{
trace("Shutting down...");
if (SCI_EN == 1)
{
outw(s_cst(uint16_t, acpi->FADT->PM1aControlBlock),
s_cst(uint16_t,
(inw(s_cst(uint16_t,
acpi->FADT->PM1aControlBlock)) &
0xE3FF) |
((SLP_TYPa << 10) | ACPI_SLEEP)));
if (acpi->FADT->PM1bControlBlock)
outw(s_cst(uint16_t, acpi->FADT->PM1bControlBlock),
s_cst(uint16_t,
(inw(
s_cst(uint16_t, acpi->FADT->PM1bControlBlock)) &
0xE3FF) |
((SLP_TYPb << 10) | ACPI_SLEEP)));
outw(s_cst(uint16_t, PM1a_CNT), SLP_TYPa | SLP_EN);
if (PM1b_CNT)
outw(s_cst(uint16_t, PM1b_CNT), SLP_TYPb | SLP_EN);
}
}
void DSDT::Reboot()
{
trace("Rebooting...");
switch (acpi->FADT->ResetReg.AddressSpace)
{
case ACPI_GAS_MMIO:
{
*(uint8_t *)(acpi->FADT->ResetReg.Address) = acpi->FADT->ResetValue;
break;
}
case ACPI_GAS_IO:
{
outb(s_cst(uint16_t, 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;
}
default:
{
error("Unknown reset register address space: %d", acpi->FADT->ResetReg.AddressSpace);
break;
}
}
}
DSDT::DSDT(ACPI *acpi) : Interrupts::Handler(acpi->FADT->SCI_Interrupt)
{
this->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;
size_t Length = Header->Length;
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 = s_cst(uint16_t, *(S5Address) << 10);
S5Address++;
if (*S5Address == 0x0A)
S5Address++;
SLP_TYPb = s_cst(uint16_t, *(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;
uint16_t value = ACPI_POWER_BUTTON | ACPI_SLEEP_BUTTON | ACPI_WAKE;
{
uint16_t a = s_cst(uint16_t, acpi->FADT->PM1aEventBlock + (acpi->FADT->PM1EventLength / 2));
uint16_t b = s_cst(uint16_t, acpi->FADT->PM1bEventBlock + (acpi->FADT->PM1EventLength / 2));
debug("SCI Event: %#lx [a:%#x b:%#x]", value, a, b);
if (acpi->FADT->PM1aEventBlock)
outw(a, value);
if (acpi->FADT->PM1bEventBlock)
outw(b, value);
}
{
uint16_t a = 0, b = 0;
if (acpi->FADT->PM1aEventBlock)
{
a = inw(s_cst(uint16_t, acpi->FADT->PM1aEventBlock));
outw(s_cst(uint16_t, acpi->FADT->PM1aEventBlock), a);
}
if (acpi->FADT->PM1bEventBlock)
{
b = inw(s_cst(uint16_t, acpi->FADT->PM1bEventBlock));
outw(s_cst(uint16_t, acpi->FADT->PM1bEventBlock), b);
}
}
((APIC::APIC *)Interrupts::apic[0])->RedirectIRQ(0, acpi->FADT->SCI_Interrupt, 1);
return;
}
warn("Failed to parse _S5 in ACPI");
SCI_EN = 0;
}
DSDT::~DSDT()
{
}
}

View File

@ -76,7 +76,7 @@ namespace Memory
{ {
// 0x1000 aligned // 0x1000 aligned
uintptr_t Address = (uintptr_t)VirtualAddress; uintptr_t Address = (uintptr_t)VirtualAddress;
Address &= 0xFFFFFFFFFFFFF000; Address &= 0xFFFFF000;
PageMapIndexer Index = PageMapIndexer(Address); PageMapIndexer Index = PageMapIndexer(Address);
@ -101,7 +101,7 @@ namespace Memory
PageDirectoryEntry *Virtual::GetPDE(void *VirtualAddress, MapType Type) PageDirectoryEntry *Virtual::GetPDE(void *VirtualAddress, MapType Type)
{ {
uintptr_t Address = (uintptr_t)VirtualAddress; uintptr_t Address = (uintptr_t)VirtualAddress;
Address &= 0xFFFFFFFFFFFFF000; Address &= 0xFFFFF000;
PageMapIndexer Index = PageMapIndexer(Address); PageMapIndexer Index = PageMapIndexer(Address);
PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex]; PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex];
@ -113,7 +113,7 @@ namespace Memory
PageTableEntry *Virtual::GetPTE(void *VirtualAddress, MapType Type) PageTableEntry *Virtual::GetPTE(void *VirtualAddress, MapType Type)
{ {
uintptr_t Address = (uintptr_t)VirtualAddress; uintptr_t Address = (uintptr_t)VirtualAddress;
Address &= 0xFFFFFFFFFFFFF000; Address &= 0xFFFFF000;
PageMapIndexer Index = PageMapIndexer(Address); PageMapIndexer Index = PageMapIndexer(Address);
PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex]; PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex];

View File

@ -0,0 +1,91 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "acpi.hpp"
#include <memory.hpp>
#include <debug.h>
#include "../../kernel.h"
namespace ACPI
{
MADT::MADT(ACPI::MADTHeader *madt)
{
trace("Initializing MADT");
CPUCores = 0;
LAPICAddress = (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);
KPrint("Local APIC \e8888FF%d\eCCCCCC (APIC \e8888FF%d\eCCCCCC) found.", lapic.back()->ACPIProcessorId, lapic.back()->APICId);
CPUCores++;
}
break;
}
case 1:
{
ioapic.push_back((MADTIOApic *)ptr);
KPrint("I/O APIC \e8888FF%d\eCCCCCC (Address \e8888FF%#lx\eCCCCCC) found.", ioapic.back()->APICID, ioapic.back()->Address);
Memory::Virtual(KernelPageTable).Map((void *)(uintptr_t)ioapic.back()->Address, (void *)(uintptr_t)ioapic.back()->Address, Memory::PTFlag::RW | Memory::PTFlag::PCD); // Make sure that the address is mapped.
break;
}
case 2:
{
iso.push_back((MADTIso *)ptr);
KPrint("ISO (IRQ:\e8888FF%#lx\eCCCCCC, BUS:\e8888FF%#lx\eCCCCCC, GSI:\e8888FF%#lx\eCCCCCC, %s\eCCCCCC/%s\eCCCCCC) found.",
iso.back()->IRQSource, iso.back()->BuSSource, iso.back()->GSI,
iso.back()->Flags & 0x00000004 ? "\e1770FFActive High" : "\e475EFFActive Low",
iso.back()->Flags & 0x00000100 ? "\e00962DEdge Triggered" : "\e008F58Level Triggered");
break;
}
case 4:
{
nmi.push_back((MADTNmi *)ptr);
KPrint("NMI \e8888FF%#lx\eCCCCCC (lint:\e8888FF%#lx\eCCCCCC) found.", nmi.back()->processor, nmi.back()->lint);
break;
}
case 5:
{
LAPICAddress = (LAPIC *)ptr;
KPrint("APIC found at \e8888FF%#lx\eCCCCCC", LAPICAddress);
break;
}
default:
{
KPrint("Unknown MADT entry \e8888FF%#lx\eCCCCCC", *(ptr));
break;
}
}
Memory::Virtual(KernelPageTable).Map((void *)LAPICAddress, (void *)LAPICAddress, Memory::PTFlag::RW | Memory::PTFlag::PCD); // I should map more than one page?
}
CPUCores--; // We start at 0 (BSP) and end at 11 (APs), so we have 12 cores.
KPrint("Total CPU cores: %d", CPUCores + 1);
}
MADT::~MADT()
{
}
}

View File

@ -0,0 +1,411 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#include "apic.hpp"
#include <memory.hpp>
#include <uart.hpp>
#include <lock.hpp>
#include <cpu.hpp>
#include <smp.hpp>
#include <io.h>
#include "../../../kernel.h"
#include "../acpi.hpp"
NewLock(APICLock);
using namespace CPU::x32;
using namespace CPU::x86;
/*
In constructor APIC::APIC::APIC(int):
warning: left shift count >= width of type
| APICBaseAddress = BaseStruct.ApicBaseLo << 12u | BaseStruct.ApicBaseHi << 32u;
| ~~~~~~~~~~~~~~~~~~~~~~^~~~~~
*/
#pragma GCC diagnostic ignored "-Wshift-count-overflow"
namespace APIC
{
// headache
// https://www.amd.com/system/files/TechDocs/24593.pdf
// https://www.naic.edu/~phil/software/intel/318148.pdf
uint32_t APIC::Read(uint32_t Register)
{
#ifdef DEBUG
if (Register != APIC_ICRLO &&
Register != APIC_ICRHI &&
Register != APIC_ID)
debug("APIC::Read(%#lx) [x2=%d]", Register, x2APICSupported ? 1 : 0);
#endif
if (x2APICSupported)
{
if (Register != APIC_ICRHI)
return s_cst(uint32_t, rdmsr((Register >> 4) + 0x800));
else
return s_cst(uint32_t, rdmsr(0x30 + 0x800));
}
else
{
CPU::MemBar::Barrier();
uint32_t ret = *((volatile uint32_t *)((uintptr_t)APICBaseAddress + Register));
CPU::MemBar::Barrier();
return ret;
}
}
void APIC::Write(uint32_t Register, uint32_t Value)
{
#ifdef DEBUG
if (Register != APIC_EOI &&
Register != APIC_TDCR &&
Register != APIC_TIMER &&
Register != APIC_TICR &&
Register != APIC_ICRLO &&
Register != APIC_ICRHI)
debug("APIC::Write(%#lx, %#lx) [x2=%d]", Register, Value, x2APICSupported ? 1 : 0);
#endif
if (x2APICSupported)
{
if (Register != APIC_ICRHI)
wrmsr((Register >> 4) + 0x800, Value);
else
wrmsr(MSR_X2APIC_ICR, Value);
}
else
{
CPU::MemBar::Barrier();
*((volatile uint32_t *)(((uintptr_t)APICBaseAddress) + Register)) = Value;
CPU::MemBar::Barrier();
}
}
void APIC::IOWrite(uint64_t Base, uint32_t Register, uint32_t Value)
{
debug("APIC::IOWrite(%#lx, %#lx, %#lx)", Base, Register, Value);
CPU::MemBar::Barrier();
*((volatile uint32_t *)(((uintptr_t)Base))) = Register;
CPU::MemBar::Barrier();
*((volatile uint32_t *)(((uintptr_t)Base + 16))) = Value;
CPU::MemBar::Barrier();
}
uint32_t APIC::IORead(uint64_t Base, uint32_t Register)
{
debug("APIC::IORead(%#lx, %#lx)", Base, Register);
CPU::MemBar::Barrier();
*((volatile uint32_t *)(((uintptr_t)Base))) = Register;
CPU::MemBar::Barrier();
uint32_t ret = *((volatile uint32_t *)(((uintptr_t)Base + 16)));
CPU::MemBar::Barrier();
return ret;
}
void APIC::EOI() { this->Write(APIC_EOI, 0); }
void APIC::WaitForIPI()
{
InterruptCommandRegisterLow icr = {.raw = 0};
do
{
icr.raw = this->Read(APIC_ICRLO);
CPU::Pause();
} while (icr.DeliveryStatus != Idle);
}
void APIC::IPI(uint8_t CPU, InterruptCommandRegisterLow icr)
{
SmartCriticalSection(APICLock);
if (x2APICSupported)
{
wrmsr(MSR_X2APIC_ICR, s_cst(uint32_t, icr.raw));
this->WaitForIPI();
}
else
{
this->Write(APIC_ICRHI, (CPU << 24));
this->Write(APIC_ICRLO, s_cst(uint32_t, icr.raw));
this->WaitForIPI();
}
}
void APIC::SendInitIPI(uint8_t CPU)
{
SmartCriticalSection(APICLock);
if (x2APICSupported)
{
InterruptCommandRegisterLow icr = {.raw = 0};
icr.DeliveryMode = INIT;
icr.Level = Assert;
wrmsr(MSR_X2APIC_ICR, s_cst(uint32_t, icr.raw));
this->WaitForIPI();
}
else
{
InterruptCommandRegisterLow icr = {.raw = 0};
icr.DeliveryMode = INIT;
icr.Level = Assert;
this->Write(APIC_ICRHI, (CPU << 24));
this->Write(APIC_ICRLO, s_cst(uint32_t, icr.raw));
this->WaitForIPI();
}
}
void APIC::SendStartupIPI(uint8_t CPU, uint64_t StartupAddress)
{
SmartCriticalSection(APICLock);
if (x2APICSupported)
{
InterruptCommandRegisterLow icr = {.raw = 0};
icr.Vector = s_cst(uint8_t, StartupAddress >> 12);
icr.DeliveryMode = Startup;
icr.Level = Assert;
wrmsr(MSR_X2APIC_ICR, s_cst(uint32_t, icr.raw));
this->WaitForIPI();
}
else
{
InterruptCommandRegisterLow icr = {.raw = 0};
icr.Vector = s_cst(uint8_t, StartupAddress >> 12);
icr.DeliveryMode = Startup;
icr.Level = Assert;
this->Write(APIC_ICRHI, (CPU << 24));
this->Write(APIC_ICRLO, s_cst(uint32_t, icr.raw));
this->WaitForIPI();
}
}
uint32_t APIC::IOGetMaxRedirect(uint32_t APICID)
{
uint32_t TableAddress = (this->IORead((((ACPI::MADT *)PowerManager->GetMADT())->ioapic[APICID]->Address), GetIOAPICVersion));
return ((IOAPICVersion *)&TableAddress)->MaximumRedirectionEntry;
}
void APIC::RawRedirectIRQ(uint16_t Vector, uint32_t GSI, uint16_t Flags, int CPU, int Status)
{
uint64_t Value = Vector;
int64_t IOAPICTarget = -1;
for (uint64_t i = 0; ((ACPI::MADT *)PowerManager->GetMADT())->ioapic[std::size_t(i)] != 0; i++)
if (((ACPI::MADT *)PowerManager->GetMADT())->ioapic[std::size_t(i)]->GSIBase <= GSI)
if (((ACPI::MADT *)PowerManager->GetMADT())->ioapic[std::size_t(i)]->GSIBase + IOGetMaxRedirect(s_cst(uint32_t, i)) > GSI)
{
IOAPICTarget = i;
break;
}
if (IOAPICTarget == -1)
{
error("No ISO table found for I/O APIC");
return;
}
// TODO: IOAPICRedirectEntry Entry = {.raw = 0};
if (Flags & ActiveHighLow)
Value |= (1 << 13);
if (Flags & EdgeLevel)
Value |= (1 << 15);
if (!Status)
Value |= (1 << 16);
Value |= (((uintptr_t)CPU) << 56);
uint32_t IORegister = (GSI - ((ACPI::MADT *)PowerManager->GetMADT())->ioapic[std::size_t(IOAPICTarget)]->GSIBase) * 2 + 16;
this->IOWrite(((ACPI::MADT *)PowerManager->GetMADT())->ioapic[std::size_t(IOAPICTarget)]->Address,
IORegister, (uint32_t)Value);
this->IOWrite(((ACPI::MADT *)PowerManager->GetMADT())->ioapic[std::size_t(IOAPICTarget)]->Address,
IORegister + 1, (uint32_t)(Value >> 32));
}
void APIC::RedirectIRQ(int CPU, uint16_t IRQ, int Status)
{
for (uint64_t i = 0; i < ((ACPI::MADT *)PowerManager->GetMADT())->iso.size(); i++)
if (((ACPI::MADT *)PowerManager->GetMADT())->iso[std::size_t(i)]->IRQSource == IRQ)
{
debug("[ISO %d] Mapping to source IRQ%#d GSI:%#lx on CPU %d",
i, ((ACPI::MADT *)PowerManager->GetMADT())->iso[std::size_t(i)]->IRQSource,
((ACPI::MADT *)PowerManager->GetMADT())->iso[std::size_t(i)]->GSI,
CPU);
this->RawRedirectIRQ(((ACPI::MADT *)PowerManager->GetMADT())->iso[std::size_t(i)]->IRQSource + 0x20,
((ACPI::MADT *)PowerManager->GetMADT())->iso[std::size_t(i)]->GSI,
((ACPI::MADT *)PowerManager->GetMADT())->iso[std::size_t(i)]->Flags,
CPU, Status);
return;
}
debug("Mapping IRQ%d on CPU %d", IRQ, CPU);
this->RawRedirectIRQ(IRQ + 0x20, IRQ, 0, CPU, Status);
}
void APIC::RedirectIRQs(int CPU)
{
SmartCriticalSection(APICLock);
debug("Redirecting IRQs...");
for (uint8_t i = 0; i < 16; i++)
this->RedirectIRQ(CPU, i, 1);
debug("Redirecting IRQs completed.");
}
APIC::APIC(int Core)
{
SmartCriticalSection(APICLock);
APIC_BASE BaseStruct = {.raw = rdmsr(MSR_APIC_BASE)};
uint64_t BaseLow = BaseStruct.ApicBaseLo;
uint64_t BaseHigh = BaseStruct.ApicBaseHi;
this->APICBaseAddress = BaseLow << 12u | BaseHigh << 32u;
trace("APIC Address: %#lx", this->APICBaseAddress);
Memory::Virtual().Map((void *)this->APICBaseAddress, (void *)this->APICBaseAddress, Memory::PTFlag::RW | Memory::PTFlag::PCD);
bool x2APICSupported = false;
if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0)
{
CPU::x86::AMD::CPUID0x00000001 cpuid;
cpuid.Get();
if (cpuid.ECX.x2APIC)
{
// x2APICSupported = cpuid.ECX.x2APIC;
fixme("x2APIC is supported");
}
}
else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
{
CPU::x86::Intel::CPUID0x00000001 cpuid;
cpuid.Get();
if (cpuid.ECX.x2APIC)
{
// x2APICSupported = cpuid.ECX.x2APIC;
fixme("x2APIC is supported");
}
}
if (x2APICSupported)
{
this->x2APICSupported = true;
wrmsr(MSR_APIC_BASE, (rdmsr(MSR_APIC_BASE) | (1 << 11)) & ~(1 << 10));
BaseStruct.EN = 1;
wrmsr(MSR_APIC_BASE, BaseStruct.raw);
}
else
{
BaseStruct.EN = 1;
wrmsr(MSR_APIC_BASE, BaseStruct.raw);
}
this->Write(APIC_TPR, 0x0);
// this->Write(APIC_SVR, this->Read(APIC_SVR) | 0x100); // 0x1FF or 0x100 ? on https://wiki.osdev.org/APIC is 0x100
if (!this->x2APICSupported)
{
this->Write(APIC_DFR, 0xF0000000);
this->Write(APIC_LDR, this->Read(APIC_ID));
}
ACPI::MADT *madt = (ACPI::MADT *)PowerManager->GetMADT();
for (size_t i = 0; i < madt->nmi.size(); i++)
{
if (madt->nmi[std::size_t(i)]->processor != 0xFF && Core != madt->nmi[std::size_t(i)]->processor)
return;
uint32_t nmi = 0x402;
if (madt->nmi[std::size_t(i)]->flags & 2)
nmi |= 1 << 13;
if (madt->nmi[std::size_t(i)]->flags & 8)
nmi |= 1 << 15;
if (madt->nmi[std::size_t(i)]->lint == 0)
this->Write(APIC_LINT0, nmi);
else if (madt->nmi[std::size_t(i)]->lint == 1)
this->Write(APIC_LINT1, nmi);
}
// Setup the spurrious interrupt vector
Spurious Spurious = {.raw = this->Read(APIC_SVR)};
Spurious.Vector = IRQ223; // TODO: Should I map the IRQ to something?
Spurious.Software = 1;
this->Write(APIC_SVR, s_cst(uint32_t, Spurious.raw));
static int once = 0;
if (!once++)
{
// Disable PIT
outb(0x43, 0x28);
outb(0x40, 0x0);
// Disable PIC
outb(0x21, 0xFF);
outb(0xA1, 0xFF);
}
}
APIC::~APIC() {}
void Timer::OnInterruptReceived(TrapFrame *Frame) { UNUSED(Frame); }
void Timer::OneShot(uint32_t Vector, uint64_t Miliseconds)
{
SmartCriticalSection(APICLock);
LVTTimer timer = {.raw = 0};
timer.Vector = s_cst(uint8_t, Vector);
timer.TimerMode = 0;
if (strcmp(CPU::Hypervisor(), x86_CPUID_VENDOR_TCG) != 0)
this->lapic->Write(APIC_TDCR, DivideBy128);
else
this->lapic->Write(APIC_TDCR, DivideBy16);
this->lapic->Write(APIC_TICR, s_cst(uint32_t, Ticks * Miliseconds));
this->lapic->Write(APIC_TIMER, s_cst(uint32_t, timer.raw));
}
Timer::Timer(APIC *apic) : Interrupts::Handler(0) /* IRQ0 */
{
SmartCriticalSection(APICLock);
this->lapic = apic;
LVTTimerDivide Divider = DivideBy16;
trace("Initializing APIC timer on CPU %d", GetCurrentCPU()->ID);
this->lapic->Write(APIC_TDCR, Divider);
this->lapic->Write(APIC_TICR, 0xFFFFFFFF);
TimeManager->Sleep(1, Time::Units::Milliseconds);
// Mask the timer
this->lapic->Write(APIC_TIMER, 0x10000 /* LVTTimer.Mask flag */);
Ticks = 0xFFFFFFFF - this->lapic->Read(APIC_TCCR);
// Config for IRQ0 timer
LVTTimer timer = {.raw = 0};
timer.Vector = IRQ0;
timer.Mask = Unmasked;
timer.TimerMode = LVTTimerMode::OneShot;
// Initialize APIC timer
this->lapic->Write(APIC_TDCR, Divider);
this->lapic->Write(APIC_TICR, s_cst(uint32_t, Ticks));
this->lapic->Write(APIC_TIMER, s_cst(uint32_t, timer.raw));
trace("%d APIC Timer %d ticks in.", GetCurrentCPU()->ID, Ticks);
KPrint("APIC Timer: \e8888FF%ld\eCCCCCC ticks.", Ticks);
}
Timer::~Timer()
{
}
}

View File

@ -228,7 +228,14 @@ namespace GlobalDescriptorTable
gdt[Core].Entries->TaskStateSegment.BaseLow = Base & 0xFFFF; gdt[Core].Entries->TaskStateSegment.BaseLow = Base & 0xFFFF;
gdt[Core].Entries->TaskStateSegment.BaseMiddle = uint8_t((Base >> 16) & 0xFF); gdt[Core].Entries->TaskStateSegment.BaseMiddle = uint8_t((Base >> 16) & 0xFF);
gdt[Core].Entries->TaskStateSegment.BaseHigh = uint8_t((Base >> 24) & 0xFF); gdt[Core].Entries->TaskStateSegment.BaseHigh = uint8_t((Base >> 24) & 0xFF);
#pragma diagnostic push
#pragma GCC diagnostic ignored "-Wshift-count-overflow"
gdt[Core].Entries->TaskStateSegment.BaseUpper = s_cst(uint32_t, (Base >> 32) & 0xFFFFFFFF); gdt[Core].Entries->TaskStateSegment.BaseUpper = s_cst(uint32_t, (Base >> 32) & 0xFFFFFFFF);
#pragma diagnostic pop
gdt[Core].Entries->TaskStateSegment.Access = {.A = 1, .RW = 0, .DC = 0, .E = 1, .S = 0, .DPL = 0, .P = 1}; gdt[Core].Entries->TaskStateSegment.Access = {.A = 1, .RW = 0, .DC = 0, .E = 1, .S = 0, .DPL = 0, .P = 1};
gdt[Core].Entries->TaskStateSegment.Granularity = (0 << 4) | ((Limit >> 16) & 0xF); gdt[Core].Entries->TaskStateSegment.Granularity = (0 << 4) | ((Limit >> 16) & 0xF);

File diff suppressed because it is too large Load Diff

View File

@ -23,17 +23,27 @@
#include <cpu.hpp> #include <cpu.hpp>
#include <atomic> #include <atomic>
#include <smp.hpp>
#include <memory.hpp>
#include <ints.hpp>
#include <assert.h>
#include <cpu.hpp>
#include <atomic>
#include "../../../kernel.h" #include "../../../kernel.h"
#include "../acpi.hpp"
#include "apic.hpp"
enum SMPTrampolineAddress enum SMPTrampolineAddress
{ {
PAGE_TABLE = 0x500, PAGE_TABLE = 0x500,
START_ADDR = 0x520, START_ADDR = 0x520,
STACK = 0x570, STACK = 0x570,
GDT = 0x580, GDT = 0x580,
IDT = 0x590, IDT = 0x590,
CORE = 0x600, CORE = 0x600,
TRAMPOLINE_START = 0x2000 TRAMPOLINE_START = 0x2000
}; };
std::atomic_bool CPUEnabled = false; std::atomic_bool CPUEnabled = false;
@ -45,22 +55,33 @@ SafeFunction CPUData *GetCPU(long id) { return &CPUs[id]; }
SafeFunction CPUData *GetCurrentCPU() SafeFunction CPUData *GetCurrentCPU()
{ {
uint64_t ret = 0; uint64_t ret = 0;
if (!(&CPUs[ret])->IsActive) if (!(&CPUs[ret])->IsActive)
{ {
// error("CPU %d is not active!", ret); FIXME // error("CPU %d is not active!", ret); FIXME
return &CPUs[0]; return &CPUs[0];
} }
assert((&CPUs[ret])->Checksum == CPU_DATA_CHECKSUM); assert((&CPUs[ret])->Checksum == CPU_DATA_CHECKSUM);
return &CPUs[ret]; return &CPUs[ret];
} }
namespace SMP namespace SMP
{ {
int CPUCores = 0; int CPUCores = 0;
void Initialize(void *madt) void Initialize(void *_madt)
{ {
fixme("SMP::Initialize() is not implemented!"); ACPI::MADT *madt = (ACPI::MADT *)_madt;
}
int Cores = madt->CPUCores + 1;
if (Config.Cores > madt->CPUCores + 1)
KPrint("More cores requested than available. Using %d cores", madt->CPUCores + 1);
else if (Config.Cores != 0)
Cores = Config.Cores;
CPUCores = Cores;
fixme("SMP::Initialize() is not implemented!");
}
} }

View File

@ -25,330 +25,330 @@
namespace APIC namespace APIC
{ {
enum APICRegisters enum APICRegisters
{ {
// source from: https://github.com/pdoane/osdev/blob/master/intr/local_apic.c // source from: https://github.com/pdoane/osdev/blob/master/intr/local_apic.c
APIC_ID = 0x20, // Local APIC ID APIC_ID = 0x20, // Local APIC ID
APIC_VER = 0x30, // Local APIC Version APIC_VER = 0x30, // Local APIC Version
APIC_TPR = 0x80, // Task Priority APIC_TPR = 0x80, // Task Priority
APIC_APR = 0x90, // Arbitration Priority APIC_APR = 0x90, // Arbitration Priority
APIC_PPR = 0xA0, // Processor Priority APIC_PPR = 0xA0, // Processor Priority
APIC_EOI = 0xB0, // EOI APIC_EOI = 0xB0, // EOI
APIC_RRD = 0xC0, // Remote Read APIC_RRD = 0xC0, // Remote Read
APIC_LDR = 0xD0, // Logical Destination APIC_LDR = 0xD0, // Logical Destination
APIC_DFR = 0xE0, // Destination Format APIC_DFR = 0xE0, // Destination Format
APIC_SVR = 0xF0, // Spurious Interrupt Vector APIC_SVR = 0xF0, // Spurious Interrupt Vector
APIC_ISR = 0x100, // In-Service (8 registers) APIC_ISR = 0x100, // In-Service (8 registers)
APIC_TMR = 0x180, // Trigger Mode (8 registers) APIC_TMR = 0x180, // Trigger Mode (8 registers)
APIC_IRR = 0x200, // Interrupt Request (8 registers) APIC_IRR = 0x200, // Interrupt Request (8 registers)
APIC_ESR = 0x280, // Error Status APIC_ESR = 0x280, // Error Status
APIC_ICRLO = 0x300, // Interrupt Command APIC_ICRLO = 0x300, // Interrupt Command
APIC_ICRHI = 0x310, // Interrupt Command [63:32] APIC_ICRHI = 0x310, // Interrupt Command [63:32]
APIC_TIMER = 0x320, // LVT Timer APIC_TIMER = 0x320, // LVT Timer
APIC_THERMAL = 0x330, // LVT Thermal Sensor APIC_THERMAL = 0x330, // LVT Thermal Sensor
APIC_PERF = 0x340, // LVT Performance Counter APIC_PERF = 0x340, // LVT Performance Counter
APIC_LINT0 = 0x350, // LVT LINT0 APIC_LINT0 = 0x350, // LVT LINT0
APIC_LINT1 = 0x360, // LVT LINT1 APIC_LINT1 = 0x360, // LVT LINT1
APIC_ERROR = 0x370, // LVT Error APIC_ERROR = 0x370, // LVT Error
APIC_TICR = 0x380, // Initial Count (for Timer) APIC_TICR = 0x380, // Initial Count (for Timer)
APIC_TCCR = 0x390, // Current Count (for Timer) APIC_TCCR = 0x390, // Current Count (for Timer)
APIC_TDCR = 0x3E0, // Divide Configuration (for Timer) APIC_TDCR = 0x3E0, // Divide Configuration (for Timer)
}; };
enum IOAPICRegisters enum IOAPICRegisters
{ {
GetIOAPICVersion = 0x1 GetIOAPICVersion = 0x1
}; };
enum IOAPICFlags enum IOAPICFlags
{ {
ActiveHighLow = 2, ActiveHighLow = 2,
EdgeLevel = 8 EdgeLevel = 8
}; };
enum APICDeliveryMode enum APICDeliveryMode
{ {
Fixed = 0b000, Fixed = 0b000,
LowestPriority = 0b001, /* Reserved */ LowestPriority = 0b001, /* Reserved */
SMI = 0b010, SMI = 0b010,
APIC_DELIVERY_MODE_RESERVED0 = 0b011, /* Reserved */ APIC_DELIVERY_MODE_RESERVED0 = 0b011, /* Reserved */
NMI = 0b100, NMI = 0b100,
INIT = 0b101, INIT = 0b101,
Startup = 0b110, Startup = 0b110,
ExtINT = 0b111 /* Reserved */ ExtINT = 0b111 /* Reserved */
}; };
enum APICDestinationMode enum APICDestinationMode
{ {
Physical = 0b0, Physical = 0b0,
Logical = 0b1 Logical = 0b1
}; };
enum APICDeliveryStatus enum APICDeliveryStatus
{ {
Idle = 0b0, Idle = 0b0,
SendPending = 0b1 SendPending = 0b1
}; };
enum APICLevel enum APICLevel
{ {
DeAssert = 0b0, DeAssert = 0b0,
Assert = 0b1 Assert = 0b1
}; };
enum APICTriggerMode enum APICTriggerMode
{ {
Edge = 0b0, Edge = 0b0,
Level = 0b1 Level = 0b1
}; };
enum APICDestinationShorthand enum APICDestinationShorthand
{ {
NoShorthand = 0b00, NoShorthand = 0b00,
Self = 0b01, Self = 0b01,
AllIncludingSelf = 0b10, AllIncludingSelf = 0b10,
AllExcludingSelf = 0b11 AllExcludingSelf = 0b11
}; };
enum LVTTimerDivide enum LVTTimerDivide
{ {
DivideBy2 = 0b000, DivideBy2 = 0b000,
DivideBy4 = 0b001, DivideBy4 = 0b001,
DivideBy8 = 0b010, DivideBy8 = 0b010,
DivideBy16 = 0b011, DivideBy16 = 0b011,
DivideBy32 = 0b100, DivideBy32 = 0b100,
DivideBy64 = 0b101, DivideBy64 = 0b101,
DivideBy128 = 0b110, DivideBy128 = 0b110,
DivideBy1 = 0b111 DivideBy1 = 0b111
}; };
enum LVTTimerMask enum LVTTimerMask
{ {
Unmasked = 0b0, Unmasked = 0b0,
Masked = 0b1 Masked = 0b1
}; };
enum LVTTimerMode enum LVTTimerMode
{ {
OneShot = 0b00, OneShot = 0b00,
Periodic = 0b01, Periodic = 0b01,
TSCDeadline = 0b10 TSCDeadline = 0b10
}; };
typedef union typedef union
{ {
struct struct
{ {
/** @brief Interrupt Vector */ /** @brief Interrupt Vector */
uint64_t Vector : 8; uint64_t Vector : 8;
/** @brief Reserved */ /** @brief Reserved */
uint64_t Reserved0 : 4; uint64_t Reserved0 : 4;
/** /**
* @brief Delivery Status * @brief Delivery Status
* *
* 0: Idle * 0: Idle
* 1: Send Pending * 1: Send Pending
*/ */
uint64_t DeliveryStatus : 1; uint64_t DeliveryStatus : 1;
/** @brief Reserved */ /** @brief Reserved */
uint64_t Reserved1 : 3; uint64_t Reserved1 : 3;
/** /**
* @brief Mask * @brief Mask
* *
* 0: Not masked * 0: Not masked
* 1: Masked * 1: Masked
*/ */
uint64_t Mask : 1; uint64_t Mask : 1;
/** @brief Timer Mode /** @brief Timer Mode
* *
* 0: One-shot * 0: One-shot
* 1: Periodic * 1: Periodic
* 2: TSC-Deadline * 2: TSC-Deadline
*/ */
uint64_t TimerMode : 1; uint64_t TimerMode : 1;
/** @brief Reserved */ /** @brief Reserved */
uint64_t Reserved2 : 14; uint64_t Reserved2 : 14;
}; };
uint64_t raw; uint64_t raw;
} __packed LVTTimer; } __packed LVTTimer;
typedef union typedef union
{ {
struct struct
{ {
/** @brief Spurious Vector */ /** @brief Spurious Vector */
uint64_t Vector : 8; uint64_t Vector : 8;
/** @brief Enable or disable APIC software */ /** @brief Enable or disable APIC software */
uint64_t Software : 1; uint64_t Software : 1;
/** @brief Focus Processor Checking */ /** @brief Focus Processor Checking */
uint64_t FocusProcessorChecking : 1; uint64_t FocusProcessorChecking : 1;
/** @brief Reserved */ /** @brief Reserved */
uint64_t Reserved : 2; uint64_t Reserved : 2;
/** @brief Disable EOI Broadcast */ /** @brief Disable EOI Broadcast */
uint64_t DisableEOIBroadcast : 1; uint64_t DisableEOIBroadcast : 1;
/** @brief Reserved */ /** @brief Reserved */
uint64_t Reserved1 : 19; uint64_t Reserved1 : 19;
}; };
uint64_t raw; uint64_t raw;
} __packed Spurious; } __packed Spurious;
typedef union typedef union
{ {
struct struct
{ {
/** @brief Interrupt Vector */ /** @brief Interrupt Vector */
uint64_t Vector : 8; uint64_t Vector : 8;
/** @brief Delivery Mode */ /** @brief Delivery Mode */
uint64_t DeliveryMode : 3; uint64_t DeliveryMode : 3;
/** @brief Destination Mode /** @brief Destination Mode
* *
* 0: Physical * 0: Physical
* 1: Logical * 1: Logical
*/ */
uint64_t DestinationMode : 1; uint64_t DestinationMode : 1;
/** @brief Delivery Status /** @brief Delivery Status
* *
* @note Reserved when in x2APIC mode * @note Reserved when in x2APIC mode
*/ */
uint64_t DeliveryStatus : 1; uint64_t DeliveryStatus : 1;
/** @brief Reserved */ /** @brief Reserved */
uint64_t Reserved0 : 1; uint64_t Reserved0 : 1;
/** @brief Level /** @brief Level
* *
* 0: Deassert * 0: Deassert
* 1: Assert * 1: Assert
*/ */
uint64_t Level : 1; uint64_t Level : 1;
/** @brief Trigger Mode /** @brief Trigger Mode
* *
* 0: Edge * 0: Edge
* 1: Level * 1: Level
*/ */
uint64_t TriggerMode : 1; uint64_t TriggerMode : 1;
/** @brief Reserved */ /** @brief Reserved */
uint64_t Reserved1 : 2; uint64_t Reserved1 : 2;
/** @brief Destination Shorthand /** @brief Destination Shorthand
* *
* 0: No shorthand * 0: No shorthand
* 1: Self * 1: Self
* 2: All including self * 2: All including self
* 3: All excluding self * 3: All excluding self
*/ */
uint64_t DestinationShorthand : 2; uint64_t DestinationShorthand : 2;
/** @brief Reserved */ /** @brief Reserved */
uint64_t Reserved2 : 12; uint64_t Reserved2 : 12;
}; };
uint64_t raw; uint64_t raw;
} __packed InterruptCommandRegisterLow; } __packed InterruptCommandRegisterLow;
typedef union typedef union
{ {
struct struct
{ {
/** @brief Reserved */ /** @brief Reserved */
uint64_t Reserved0 : 24; uint64_t Reserved0 : 24;
/** @brief Destination */ /** @brief Destination */
uint64_t Destination : 8; uint64_t Destination : 8;
}; };
uint64_t raw; uint64_t raw;
} __packed InterruptCommandRegisterHigh; } __packed InterruptCommandRegisterHigh;
typedef union typedef union
{ {
struct struct
{ {
/** @brief Interrupt Vector */ /** @brief Interrupt Vector */
uint64_t Vector : 8; uint64_t Vector : 8;
/** @brief Delivery Mode */ /** @brief Delivery Mode */
uint64_t DeliveryMode : 3; uint64_t DeliveryMode : 3;
/** @brief Destination Mode /** @brief Destination Mode
* *
* 0: Physical * 0: Physical
* 1: Logical * 1: Logical
*/ */
uint64_t DestinationMode : 1; uint64_t DestinationMode : 1;
/** @brief Delivery Status */ /** @brief Delivery Status */
uint64_t DeliveryStatus : 1; uint64_t DeliveryStatus : 1;
/** @brief Interrupt Input Pin Polarity /** @brief Interrupt Input Pin Polarity
* *
* 0: Active High * 0: Active High
* 1: Active Low * 1: Active Low
*/ */
uint64_t Polarity : 1; uint64_t Polarity : 1;
/** @brief Remote IRR */ /** @brief Remote IRR */
uint64_t RemoteIRR : 1; uint64_t RemoteIRR : 1;
/** @brief Trigger Mode /** @brief Trigger Mode
* *
* 0: Edge * 0: Edge
* 1: Level * 1: Level
*/ */
uint64_t TriggerMode : 1; uint64_t TriggerMode : 1;
/** @brief Mask */ /** @brief Mask */
uint64_t Mask : 1; uint64_t Mask : 1;
/** @brief Reserved */ /** @brief Reserved */
uint64_t Reserved0 : 15; uint64_t Reserved0 : 15;
/** @brief Reserved */ /** @brief Reserved */
uint64_t Reserved1 : 24; uint64_t Reserved1 : 24;
/** @brief Destination */ /** @brief Destination */
uint64_t DestinationID : 8; uint64_t DestinationID : 8;
}; };
struct struct
{ {
uint64_t Low; uint64_t Low;
uint64_t High; uint64_t High;
} split; } split;
uint64_t raw; uint64_t raw;
} __packed IOAPICRedirectEntry; } __packed IOAPICRedirectEntry;
typedef union typedef union
{ {
struct struct
{ {
uint64_t Version : 8; uint64_t Version : 8;
uint64_t Reserved : 8; uint64_t Reserved : 8;
uint64_t MaximumRedirectionEntry : 8; uint64_t MaximumRedirectionEntry : 8;
uint64_t Reserved2 : 8; uint64_t Reserved2 : 8;
}; };
uint64_t raw; uint64_t raw;
} __packed IOAPICVersion; } __packed IOAPICVersion;
class APIC class APIC
{ {
private: private:
bool x2APICSupported = false; bool x2APICSupported = false;
uint64_t APICBaseAddress = 0; uint64_t APICBaseAddress = 0;
public: public:
uint32_t Read(uint32_t Register); uint32_t Read(uint32_t Register);
void Write(uint32_t Register, uint32_t Value); void Write(uint32_t Register, uint32_t Value);
void IOWrite(uint64_t Base, uint32_t Register, uint32_t Value); void IOWrite(uint64_t Base, uint32_t Register, uint32_t Value);
uint32_t IORead(uint64_t Base, uint32_t Register); uint32_t IORead(uint64_t Base, uint32_t Register);
void EOI(); void EOI();
void RedirectIRQs(int CPU = 0); void RedirectIRQs(int CPU = 0);
void WaitForIPI(); void WaitForIPI();
void IPI(uint8_t CPU, InterruptCommandRegisterLow icr); void IPI(uint8_t CPU, InterruptCommandRegisterLow icr);
void SendInitIPI(uint8_t CPU); void SendInitIPI(uint8_t CPU);
void SendStartupIPI(uint8_t CPU, uint64_t StartupAddress); void SendStartupIPI(uint8_t CPU, uint64_t StartupAddress);
uint32_t IOGetMaxRedirect(uint32_t APICID); uint32_t IOGetMaxRedirect(uint32_t APICID);
void RawRedirectIRQ(uint8_t Vector, uint32_t GSI, uint16_t Flags, int CPU, int Status); void RawRedirectIRQ(uint16_t Vector, uint32_t GSI, uint16_t Flags, int CPU, int Status);
void RedirectIRQ(int CPU, uint16_t IRQ, int Status); void RedirectIRQ(int CPU, uint16_t IRQ, int Status);
APIC(int Core); APIC(int Core);
~APIC(); ~APIC();
}; };
class Timer : public Interrupts::Handler class Timer : public Interrupts::Handler
{ {
private: private:
APIC *lapic; APIC *lapic;
uint64_t Ticks = 0; uint64_t Ticks = 0;
void OnInterruptReceived(CPU::x32::TrapFrame *Frame); void OnInterruptReceived(CPU::x32::TrapFrame *Frame);
public: public:
uint64_t GetTicks() { return Ticks; } uint64_t GetTicks() { return Ticks; }
void OneShot(uint32_t Vector, uint64_t Miliseconds); void OneShot(uint32_t Vector, uint64_t Miliseconds);
Timer(APIC *apic); Timer(APIC *apic);
~Timer(); ~Timer();
}; };
} }
#endif // !__FENNIX_KERNEL_APIC_H__ #endif // !__FENNIX_KERNEL_APIC_H__

View File

@ -22,49 +22,49 @@
namespace InterruptDescriptorTable namespace InterruptDescriptorTable
{ {
typedef enum _InterruptGateType typedef enum _InterruptGateType
{ {
TASK = 0b101, TASK = 0b101,
INT_16BIT = 0b110, INT_16BIT = 0b110,
TRAP_16BIT = 0b111, TRAP_16BIT = 0b111,
INT_32BIT = 0b1110, INT_32BIT = 0b1110,
TRAP_32BIT = 0b1111, TRAP_32BIT = 0b1111,
} InterruptGateType; } InterruptGateType;
typedef enum _InterruptRingType typedef enum _InterruptRingType
{ {
RING0 = 0b0, RING0 = 0b0,
RING1 = 0b1, RING1 = 0b1,
RING2 = 0b10, RING2 = 0b10,
RING3 = 0b11, RING3 = 0b11,
} InterruptRingType; } InterruptRingType;
typedef struct _InterruptDescriptorTableEntry typedef struct _InterruptDescriptorTableEntry
{ {
uint32_t LowOffset : 16; uint32_t LowOffset : 16;
uint32_t SegmentSelector : 16; uint32_t SegmentSelector : 16;
uint32_t Reserved0 : 5; uint32_t Reserved0 : 5;
uint32_t Flags : 4; uint32_t Flags : 4;
uint32_t Reserved1 : 1; uint32_t Reserved1 : 1;
uint32_t Ring : 2; uint32_t Ring : 2;
uint32_t Present : 1; uint32_t Present : 1;
uint32_t HighOffset : 16; uint32_t HighOffset : 16;
} __packed InterruptDescriptorTableEntry; } __packed InterruptDescriptorTableEntry;
typedef struct _InterruptDescriptorTableDescriptor typedef struct _InterruptDescriptorTableDescriptor
{ {
uint16_t Length; uint16_t Length;
InterruptDescriptorTableEntry *Entries; InterruptDescriptorTableEntry *Entries;
} __packed InterruptDescriptorTableDescriptor; } __packed InterruptDescriptorTableDescriptor;
void SetEntry(uint8_t Index, void SetEntry(uint8_t Index,
void (*Base)(), void (*Base)(),
InterruptGateType Gate, InterruptGateType Gate,
InterruptRingType Ring, InterruptRingType Ring,
bool Present, bool Present,
uint16_t SegmentSelector); uint16_t SegmentSelector);
void Init(int Core); void Init(int Core);
} }
#endif // !__FENNIX_KERNEL_IDT_H__ #endif // !__FENNIX_KERNEL_IDT_H__

View File

@ -35,74 +35,92 @@
NewLock(DriverDisplayPrintLock); NewLock(DriverDisplayPrintLock);
void DriverDebugPrint(char *String, unsigned long DriverUID) { trace("[%ld] %s", DriverUID, String); } void DriverDebugPrint(char *String, __UINT64_TYPE__ DriverUID)
{
trace("[%ld] %s", DriverUID, String);
}
void DriverDisplayPrint(char *String) void DriverDisplayPrint(char *String)
{ {
SmartLock(DriverDisplayPrintLock); SmartLock(DriverDisplayPrintLock);
for (unsigned long i = 0; i < strlen(String); i++) for (__UINT64_TYPE__ i = 0; i < strlen(String); i++)
Display->Print(String[i], 0, true); Display->Print(String[i], 0, true);
} }
void *RequestPage(unsigned long Size) void *RequestPage(__UINT64_TYPE__ Size)
{ {
void *ret = KernelAllocator.RequestPages(Size + 1); void *ret = KernelAllocator.RequestPages(size_t(Size + 1));
drvdbg("Allocated %ld pages (%#lx-%#lx)", Size, (unsigned long)ret, (unsigned long)ret + FROM_PAGES(Size)); drvdbg("Allocated %ld pages (%#lx-%#lx)",
Size, (__UINT64_TYPE__)ret,
(__UINT64_TYPE__)ret + FROM_PAGES(Size));
return ret; return ret;
} }
void FreePage(void *Page, unsigned long Size) void FreePage(void *Page, __UINT64_TYPE__ Size)
{ {
drvdbg("Freeing %ld pages (%#lx-%#lx)", Size, (unsigned long)Page, (unsigned long)Page + FROM_PAGES(Size)); drvdbg("Freeing %ld pages (%#lx-%#lx)",
KernelAllocator.FreePages(Page, Size + 1); Size, (__UINT64_TYPE__)Page,
(__UINT64_TYPE__)Page + FROM_PAGES(Size));
KernelAllocator.FreePages(Page, size_t(Size + 1));
} }
void MapMemory(void *VirtualAddress, void *PhysicalAddress, unsigned long Flags) void MapMemory(void *VirtualAddress, void *PhysicalAddress, __UINT64_TYPE__ Flags)
{ {
SmartLock(DriverDisplayPrintLock); SmartLock(DriverDisplayPrintLock);
drvdbg("Mapping %#lx to %#lx with flags %#lx...", (unsigned long)VirtualAddress, (unsigned long)PhysicalAddress, Flags); drvdbg("Mapping %#lx to %#lx with flags %#lx...",
(__UINT64_TYPE__)VirtualAddress,
(__UINT64_TYPE__)PhysicalAddress, Flags);
Memory::Virtual(KernelPageTable).Map(VirtualAddress, PhysicalAddress, Flags); Memory::Virtual(KernelPageTable).Map(VirtualAddress, PhysicalAddress, Flags);
} }
void UnmapMemory(void *VirtualAddress) void UnmapMemory(void *VirtualAddress)
{ {
SmartLock(DriverDisplayPrintLock); SmartLock(DriverDisplayPrintLock);
drvdbg("Unmapping %#lx...", (unsigned long)VirtualAddress); drvdbg("Unmapping %#lx...",
(__UINT64_TYPE__)VirtualAddress);
Memory::Virtual(KernelPageTable).Unmap(VirtualAddress); Memory::Virtual(KernelPageTable).Unmap(VirtualAddress);
} }
void *Drivermemcpy(void *Destination, void *Source, unsigned long Size) void *Drivermemcpy(void *Destination, void *Source, __UINT64_TYPE__ Size)
{ {
SmartLock(DriverDisplayPrintLock); SmartLock(DriverDisplayPrintLock);
drvdbg("Copying %ld bytes from %#lx-%#lx to %#lx-%#lx...", Size, drvdbg("Copying %ld bytes from %#lx-%#lx to %#lx-%#lx...", Size,
(unsigned long)Source, (unsigned long)Source + Size, (__UINT64_TYPE__)Source, (__UINT64_TYPE__)Source + Size,
(unsigned long)Destination, (unsigned long)Destination + Size); (__UINT64_TYPE__)Destination, (__UINT64_TYPE__)Destination + Size);
return memcpy(Destination, Source, Size); return memcpy(Destination, Source, size_t(Size));
} }
void *Drivermemset(void *Destination, int Value, unsigned long Size) void *Drivermemset(void *Destination, int Value, __UINT64_TYPE__ Size)
{ {
SmartLock(DriverDisplayPrintLock); SmartLock(DriverDisplayPrintLock);
drvdbg("Setting value %#x at %#lx-%#lx (%ld bytes)...", Value, drvdbg("Setting value %#x at %#lx-%#lx (%ld bytes)...", Value,
(unsigned long)Destination, (unsigned long)Destination + Size, (__UINT64_TYPE__)Destination,
Size); (__UINT64_TYPE__)Destination + Size, Size);
return memset(Destination, Value, Size); return memset(Destination, Value, size_t(Size));
} }
void DriverNetSend(unsigned int DriverID, unsigned char *Data, unsigned short Size) void DriverNetSend(__UINT32_TYPE__ DriverID,
__UINT8_TYPE__ *Data,
__UINT16_TYPE__ Size)
{ {
// This is useless I guess... // This is useless I guess...
if (NIManager) if (NIManager)
NIManager->DrvSend(DriverID, Data, Size); NIManager->DrvSend(DriverID, Data, Size);
} }
void DriverNetReceive(unsigned int DriverID, unsigned char *Data, unsigned short Size) void DriverNetReceive(__UINT32_TYPE__ DriverID,
__UINT8_TYPE__ *Data,
__UINT16_TYPE__ Size)
{ {
if (NIManager) if (NIManager)
NIManager->DrvReceive(DriverID, Data, Size); NIManager->DrvReceive(DriverID, Data, Size);
} }
void DriverAHCIDiskRead(unsigned int DriverID, unsigned long Sector, unsigned char *Data, unsigned int SectorCount, unsigned char Port) void DriverAHCIDiskRead(__UINT32_TYPE__ DriverID,
__UINT64_TYPE__ Sector,
__UINT8_TYPE__ *Data,
__UINT32_TYPE__ SectorCount,
__UINT8_TYPE__ Port)
{ {
DumpData("DriverDiskRead", Data, SectorCount * 512); DumpData("DriverDiskRead", Data, SectorCount * 512);
UNUSED(DriverID); UNUSED(DriverID);
@ -110,41 +128,50 @@ void DriverAHCIDiskRead(unsigned int DriverID, unsigned long Sector, unsigned ch
UNUSED(Port); UNUSED(Port);
} }
void DriverAHCIDiskWrite(unsigned int DriverID, unsigned long Sector, unsigned char *Data, unsigned int SectorCount, unsigned char Port) void DriverAHCIDiskWrite(__UINT32_TYPE__ DriverID,
__UINT64_TYPE__ Sector,
__UINT8_TYPE__ *Data,
__UINT32_TYPE__ SectorCount,
__UINT8_TYPE__ Port)
{ {
DumpData("DriverDiskWrite", Data, SectorCount * 512); DumpData("DriverDiskWrite",
Data, SectorCount * 512);
UNUSED(DriverID); UNUSED(DriverID);
UNUSED(Sector); UNUSED(Sector);
UNUSED(Port); UNUSED(Port);
} }
char *DriverPCIGetDeviceName(unsigned int VendorID, unsigned int DeviceID) char *DriverPCIGetDeviceName(__UINT32_TYPE__ VendorID,
__UINT32_TYPE__ DeviceID)
{ {
UNUSED(VendorID); UNUSED(VendorID);
UNUSED(DeviceID); UNUSED(DeviceID);
return (char *)"Unknown"; return (char *)"Unknown";
} }
unsigned int DriverGetWidth() __UINT32_TYPE__ DriverGetWidth()
{ {
/* TODO: We won't rely only on display buffers, what about graphics drivers and changing resolutions? */ /* TODO: We won't rely only on display buffers,
what about graphics drivers and changing resolutions? */
return Display->GetBuffer(0)->Width; return Display->GetBuffer(0)->Width;
} }
unsigned int DriverGetHeight() __UINT32_TYPE__ DriverGetHeight()
{ {
/* TODO: We won't rely only on display buffers, what about graphics drivers and changing resolutions? */ /* TODO: We won't rely only on display buffers,
what about graphics drivers and changing resolutions? */
return Display->GetBuffer(0)->Height; return Display->GetBuffer(0)->Height;
} }
void DriverSleep(unsigned long Milliseconds) void DriverSleep(__UINT64_TYPE__ Milliseconds)
{ {
SmartLock(DriverDisplayPrintLock); SmartLock(DriverDisplayPrintLock);
drvdbg("Sleeping for %ld milliseconds...", Milliseconds); drvdbg("Sleeping for %ld milliseconds...", Milliseconds);
if (TaskManager) if (TaskManager)
TaskManager->Sleep(Milliseconds); TaskManager->Sleep(Milliseconds);
else else
TimeManager->Sleep(Milliseconds, Time::Units::Milliseconds); TimeManager->Sleep(size_t(Milliseconds),
Time::Units::Milliseconds);
} }
int Driversprintf(char *Buffer, const char *Format, ...) int Driversprintf(char *Buffer, const char *Format, ...)

View File

@ -30,6 +30,8 @@
#elif defined(a32) #elif defined(a32)
#include "../Architecture/i386/cpu/gdt.hpp" #include "../Architecture/i386/cpu/gdt.hpp"
#include "../Architecture/i386/cpu/idt.hpp" #include "../Architecture/i386/cpu/idt.hpp"
#include "../Architecture/i386/acpi.hpp"
#include "../Architecture/i386/cpu/apic.hpp"
#elif defined(aa64) #elif defined(aa64)
#endif #endif
@ -47,11 +49,9 @@ namespace Interrupts
}; };
std::vector<Event> RegisteredEvents; std::vector<Event> RegisteredEvents;
#if defined(a64) #if defined(a86)
/* APIC::APIC */ void *apic[MAX_CPU]; /* APIC::APIC */ void *apic[MAX_CPU];
/* APIC::Timer */ void *apicTimer[MAX_CPU]; /* APIC::Timer */ void *apicTimer[MAX_CPU];
#elif defined(a32)
/* APIC::APIC */ void *apic[MAX_CPU];
#elif defined(aa64) #elif defined(aa64)
#endif #endif
void *InterruptFrames[INT_FRAMES_MAX]; void *InterruptFrames[INT_FRAMES_MAX];
@ -89,10 +89,12 @@ namespace Interrupts
CoreData->Stack = (uintptr_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1)) + STACK_SIZE; CoreData->Stack = (uintptr_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1)) + STACK_SIZE;
if (CoreData->Checksum != CPU_DATA_CHECKSUM) if (CoreData->Checksum != CPU_DATA_CHECKSUM)
{ {
KPrint("CPU %d checksum mismatch! %x != %x", Core, CoreData->Checksum, CPU_DATA_CHECKSUM); KPrint("CPU %d checksum mismatch! %x != %x",
Core, CoreData->Checksum, CPU_DATA_CHECKSUM);
CPU::Stop(); CPU::Stop();
} }
debug("Stack for core %d is %#lx (Address: %#lx)", Core, CoreData->Stack, CoreData->Stack - STACK_SIZE); debug("Stack for core %d is %#lx (Address: %#lx)",
Core, CoreData->Stack, CoreData->Stack - STACK_SIZE);
#elif defined(aa64) #elif defined(aa64)
warn("aarch64 is not supported yet"); warn("aarch64 is not supported yet");
#endif #endif
@ -100,7 +102,7 @@ namespace Interrupts
void Enable(int Core) void Enable(int Core)
{ {
#if defined(a64) #if defined(a86)
if (((ACPI::MADT *)PowerManager->GetMADT())->LAPICAddress != nullptr) if (((ACPI::MADT *)PowerManager->GetMADT())->LAPICAddress != nullptr)
{ {
// TODO: This function is called by SMP too. Do not initialize timers that doesn't support multiple cores. // TODO: This function is called by SMP too. Do not initialize timers that doesn't support multiple cores.
@ -113,8 +115,6 @@ namespace Interrupts
error("LAPIC not found"); error("LAPIC not found");
// TODO: PIC // TODO: PIC
} }
#elif defined(a32)
warn("i386 is not supported yet");
#elif defined(aa64) #elif defined(aa64)
warn("aarch64 is not supported yet"); warn("aarch64 is not supported yet");
#endif #endif
@ -123,15 +123,13 @@ namespace Interrupts
void InitializeTimer(int Core) void InitializeTimer(int Core)
{ {
// TODO: This function is called by SMP too. Do not initialize timers that doesn't support multiple cores. // TODO: This function is called by SMP too. Do not initialize timers that doesn't support multiple cores.
#if defined(a64) #if defined(a86)
if (apic[Core] != nullptr) if (apic[Core] != nullptr)
apicTimer[Core] = new APIC::Timer((APIC::APIC *)apic[Core]); apicTimer[Core] = new APIC::Timer((APIC::APIC *)apic[Core]);
else else
{ {
fixme("apic not found"); fixme("apic not found");
} }
#elif defined(a32)
warn("i386 is not supported yet");
#elif defined(aa64) #elif defined(aa64)
warn("aarch64 is not supported yet"); warn("aarch64 is not supported yet");
#endif #endif

View File

@ -21,6 +21,7 @@
#if defined(a64) #if defined(a64)
#include "../Architecture/amd64/acpi.hpp" #include "../Architecture/amd64/acpi.hpp"
#elif defined(a32) #elif defined(a32)
#include "../Architecture/i386/acpi.hpp"
#elif defined(aa64) #elif defined(aa64)
#endif #endif
@ -883,10 +884,10 @@ namespace PCI
} }
} }
void PCI::EnumerateFunction(uintptr_t DeviceAddress, uintptr_t Function) void PCI::EnumerateFunction(uint64_t DeviceAddress, uintptr_t Function)
{ {
uintptr_t Offset = Function << 12; uintptr_t Offset = Function << 12;
uintptr_t FunctionAddress = DeviceAddress + Offset; uint64_t FunctionAddress = DeviceAddress + Offset;
Memory::Virtual(KernelPageTable).Map((void *)FunctionAddress, (void *)FunctionAddress, Memory::PTFlag::RW); Memory::Virtual(KernelPageTable).Map((void *)FunctionAddress, (void *)FunctionAddress, Memory::PTFlag::RW);
PCIDeviceHeader *PCIDeviceHdr = (PCIDeviceHeader *)FunctionAddress; PCIDeviceHeader *PCIDeviceHdr = (PCIDeviceHeader *)FunctionAddress;
if (PCIDeviceHdr->DeviceID == 0) if (PCIDeviceHdr->DeviceID == 0)
@ -899,10 +900,10 @@ namespace PCI
#endif #endif
} }
void PCI::EnumerateDevice(uintptr_t BusAddress, uintptr_t Device) void PCI::EnumerateDevice(uint64_t BusAddress, uintptr_t Device)
{ {
uintptr_t Offset = Device << 15; uintptr_t Offset = Device << 15;
uintptr_t DeviceAddress = BusAddress + Offset; uint64_t DeviceAddress = BusAddress + Offset;
Memory::Virtual(KernelPageTable).Map((void *)DeviceAddress, (void *)DeviceAddress, Memory::PTFlag::RW); Memory::Virtual(KernelPageTable).Map((void *)DeviceAddress, (void *)DeviceAddress, Memory::PTFlag::RW);
PCIDeviceHeader *PCIDeviceHdr = (PCIDeviceHeader *)DeviceAddress; PCIDeviceHeader *PCIDeviceHdr = (PCIDeviceHeader *)DeviceAddress;
if (PCIDeviceHdr->DeviceID == 0) if (PCIDeviceHdr->DeviceID == 0)
@ -913,10 +914,10 @@ namespace PCI
EnumerateFunction(DeviceAddress, Function); EnumerateFunction(DeviceAddress, Function);
} }
void PCI::EnumerateBus(uintptr_t BaseAddress, uintptr_t Bus) void PCI::EnumerateBus(uint64_t BaseAddress, uintptr_t Bus)
{ {
uintptr_t Offset = Bus << 20; uintptr_t Offset = Bus << 20;
uintptr_t BusAddress = BaseAddress + Offset; uint64_t BusAddress = BaseAddress + Offset;
Memory::Virtual(KernelPageTable).Map((void *)BusAddress, (void *)BusAddress, Memory::PTFlag::RW); Memory::Virtual(KernelPageTable).Map((void *)BusAddress, (void *)BusAddress, Memory::PTFlag::RW);
PCIDeviceHeader *PCIDeviceHdr = (PCIDeviceHeader *)BusAddress; PCIDeviceHeader *PCIDeviceHdr = (PCIDeviceHeader *)BusAddress;
if (Bus != 0) // TODO: VirtualBox workaround (UNTESTED ON REAL HARDWARE!) if (Bus != 0) // TODO: VirtualBox workaround (UNTESTED ON REAL HARDWARE!)
@ -955,20 +956,18 @@ namespace PCI
PCI::PCI() PCI::PCI()
{ {
#if defined(a64) #if defined(a86)
int Entries = s_cst(int, ((((ACPI::ACPI *)PowerManager->GetACPI())->MCFG->Header.Length) - sizeof(ACPI::ACPI::MCFGHeader)) / sizeof(DeviceConfig)); int Entries = s_cst(int, ((((ACPI::ACPI *)PowerManager->GetACPI())->MCFG->Header.Length) - sizeof(ACPI::ACPI::MCFGHeader)) / sizeof(DeviceConfig));
Memory::Virtual vmm = Memory::Virtual(KernelPageTable); Memory::Virtual vmm = Memory::Virtual(KernelPageTable);
for (int t = 0; t < Entries; t++) for (int t = 0; t < Entries; t++)
{ {
DeviceConfig *NewDeviceConfig = (DeviceConfig *)((uintptr_t)((ACPI::ACPI *)PowerManager->GetACPI())->MCFG + sizeof(ACPI::ACPI::MCFGHeader) + (sizeof(DeviceConfig) * t)); DeviceConfig *NewDeviceConfig = (DeviceConfig *)((uintptr_t)((ACPI::ACPI *)PowerManager->GetACPI())->MCFG + sizeof(ACPI::ACPI::MCFGHeader) + (sizeof(DeviceConfig) * t));
vmm.Map((void *)NewDeviceConfig->BaseAddress, (void *)NewDeviceConfig->BaseAddress, Memory::PTFlag::RW); vmm.Map((void *)NewDeviceConfig->BaseAddress, (void *)NewDeviceConfig->BaseAddress, Memory::PTFlag::RW);
debug("PCI Entry %d Address:%#llx BUS:%#llx-%#llx", t, NewDeviceConfig->BaseAddress, debug("PCI Entry %d Address:%p BUS:%#x-%#x", t, NewDeviceConfig->BaseAddress,
NewDeviceConfig->StartBus, NewDeviceConfig->EndBus); NewDeviceConfig->StartBus, NewDeviceConfig->EndBus);
for (uintptr_t Bus = NewDeviceConfig->StartBus; Bus < NewDeviceConfig->EndBus; Bus++) for (uintptr_t Bus = NewDeviceConfig->StartBus; Bus < NewDeviceConfig->EndBus; Bus++)
EnumerateBus(NewDeviceConfig->BaseAddress, Bus); EnumerateBus(NewDeviceConfig->BaseAddress, Bus);
} }
#elif defined(a32)
error("PCI not implemented on i386");
#elif defined(aa64) #elif defined(aa64)
error("PCI not implemented on aarch64"); error("PCI not implemented on aarch64");
#endif #endif

View File

@ -19,13 +19,16 @@
#include <memory.hpp> #include <memory.hpp>
#include <debug.h> #include <debug.h>
#include <io.h>
#include "../kernel.h" #include "../kernel.h"
#if defined(a64) #if defined(a64)
#include <io.h>
#include "../Architecture/amd64/acpi.hpp" #include "../Architecture/amd64/acpi.hpp"
#elif defined(a32)
#include "../Architecture/i386/acpi.hpp"
#elif defined(aa64)
#endif
namespace Power namespace Power
{ {
@ -86,45 +89,3 @@ namespace Power
trace("Power manager initialized"); trace("Power manager initialized");
} }
} }
#elif defined(a32)
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");
}
}
#elif defined(aa64)
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");
}
}
#endif

View File

@ -53,10 +53,6 @@ namespace SymbolResolver
__unused uint64_t Shndx, __unused uint64_t Shndx,
uintptr_t Sections) uintptr_t Sections)
{ {
#ifdef a32
fixme("Function not working on 32-bit");
return;
#endif
char *sections = reinterpret_cast<char *>(Sections); char *sections = reinterpret_cast<char *>(Sections);
Elf_Sym *Symbols = nullptr; Elf_Sym *Symbols = nullptr;

160
DAPI.hpp
View File

@ -84,32 +84,32 @@ struct KernelAPI
struct KAPIInfo struct KAPIInfo
{ {
unsigned long Offset; __UINT64_TYPE__ Offset;
unsigned int DriverUID; __UINT32_TYPE__ DriverUID;
char KernelDebug; char KernelDebug;
} Info; } Info;
struct KAPIMemory struct KAPIMemory
{ {
unsigned long PageSize; __UINT64_TYPE__ PageSize;
void *(*RequestPage)(unsigned long Size); void *(*RequestPage)(__UINT64_TYPE__ Size);
void (*FreePage)(void *Page, unsigned long Size); void (*FreePage)(void *Page, __UINT64_TYPE__ Size);
void (*Map)(void *VirtualAddress, void *PhysicalAddress, unsigned long Flags); void (*Map)(void *VirtualAddress, void *PhysicalAddress, __UINT64_TYPE__ Flags);
void (*Unmap)(void *VirtualAddress); void (*Unmap)(void *VirtualAddress);
} Memory; } Memory;
struct KAPIPCI struct KAPIPCI
{ {
char *(*GetDeviceName)(unsigned int VendorID, unsigned int DeviceID); char *(*GetDeviceName)(__UINT32_TYPE__ VendorID, __UINT32_TYPE__ DeviceID);
} PCI; } PCI;
struct KAPIUtilities struct KAPIUtilities
{ {
void (*DebugPrint)(char *String, unsigned long DriverUID); void (*DebugPrint)(char *String, __UINT64_TYPE__ DriverUID);
void (*DisplayPrint)(char *Value); void (*DisplayPrint)(char *Value);
void *(*memcpy)(void *Destination, void *Source, unsigned long Size); void *(*memcpy)(void *Destination, void *Source, __UINT64_TYPE__ Size);
void *(*memset)(void *Destination, int Value, unsigned long Size); void *(*memset)(void *Destination, int Value, __UINT64_TYPE__ Size);
void (*Sleep)(unsigned long Milliseconds); void (*Sleep)(__UINT64_TYPE__ Milliseconds);
int (*sprintf)(char *Buffer, const char *Format, ...); int (*sprintf)(char *Buffer, const char *Format, ...);
} Util; } Util;
@ -118,8 +118,8 @@ struct KernelAPI
/** Connects to the network manager */ /** Connects to the network manager */
struct struct
{ {
void (*SendPacket)(unsigned int DriverID, unsigned char *Data, unsigned short Size); void (*SendPacket)(__UINT32_TYPE__ DriverID, __UINT8_TYPE__ *Data, __UINT16_TYPE__ Size);
void (*ReceivePacket)(unsigned int DriverID, unsigned char *Data, unsigned short Size); void (*ReceivePacket)(__UINT32_TYPE__ DriverID, __UINT8_TYPE__ *Data, __UINT16_TYPE__ Size);
} Network; } Network;
/** Connects to the disk manager */ /** Connects to the disk manager */
@ -127,16 +127,16 @@ struct KernelAPI
{ {
struct struct
{ {
void (*ReadSector)(unsigned int DriverID, unsigned long Sector, unsigned char *Data, unsigned int SectorCount, unsigned char Port); void (*ReadSector)(__UINT32_TYPE__ DriverID, __UINT64_TYPE__ Sector, __UINT8_TYPE__ *Data, __UINT32_TYPE__ SectorCount, __UINT8_TYPE__ Port);
void (*WriteSector)(unsigned int DriverID, unsigned long Sector, unsigned char *Data, unsigned int SectorCount, unsigned char Port); void (*WriteSector)(__UINT32_TYPE__ DriverID, __UINT64_TYPE__ Sector, __UINT8_TYPE__ *Data, __UINT32_TYPE__ SectorCount, __UINT8_TYPE__ Port);
} AHCI; } AHCI;
} Disk; } Disk;
} Command; } Command;
struct KAPIDisplay struct KAPIDisplay
{ {
unsigned int (*GetWidth)(void); __UINT32_TYPE__ (*GetWidth)(void);
unsigned int (*GetHeight)(void); __UINT32_TYPE__ (*GetHeight)(void);
/* TODO: Add more */ /* TODO: Add more */
} Display; } Display;
} __attribute__((packed)); } __attribute__((packed));
@ -230,21 +230,21 @@ union KernelCallback
{ {
CallbackReason Reason; CallbackReason Reason;
void *RawPtr; void *RawPtr;
unsigned long RawData; __UINT64_TYPE__ RawData;
/** When the kernel wants to send a packet. */ /** When the kernel wants to send a packet. */
struct struct
{ {
struct struct
{ {
unsigned char *Data; __UINT8_TYPE__ *Data;
unsigned long Length; __UINT64_TYPE__ Length;
} Send; } Send;
struct struct
{ {
char Name[128]; char Name[128];
unsigned long MAC; __UINT64_TYPE__ MAC;
} Fetch; } Fetch;
} NetworkCallback; } NetworkCallback;
@ -253,16 +253,16 @@ union KernelCallback
{ {
struct struct
{ {
unsigned long Sector; __UINT64_TYPE__ Sector;
unsigned long SectorCount; __UINT64_TYPE__ SectorCount;
unsigned char Port; __UINT8_TYPE__ Port;
unsigned char *Buffer; __UINT8_TYPE__ *Buffer;
bool Write; bool Write;
} RW; } RW;
struct struct
{ {
unsigned char Ports; __UINT8_TYPE__ Ports;
int BytesPerSector; int BytesPerSector;
} Fetch; } Fetch;
} DiskCallback; } DiskCallback;
@ -272,9 +272,9 @@ union KernelCallback
{ {
struct struct
{ {
unsigned long X; __UINT64_TYPE__ X;
unsigned long Y; __UINT64_TYPE__ Y;
unsigned long Z; __UINT64_TYPE__ Z;
struct struct
{ {
bool Left; bool Left;
@ -287,10 +287,10 @@ union KernelCallback
{ {
/** /**
* The key. * The key.
* *
* @note This is a scancode, not a character. * @note This is a scancode, not a character.
*/ */
unsigned char Key; __UINT8_TYPE__ Key;
} Keyboard; } Keyboard;
} InputCallback; } InputCallback;
@ -308,7 +308,7 @@ union KernelCallback
* *
* 0 - 100 * 0 - 100
*/ */
unsigned char Volume; __UINT8_TYPE__ Volume;
/** /**
* Adjust the encoding. * Adjust the encoding.
@ -349,7 +349,7 @@ union KernelCallback
* *
* ... - More * ... - More
*/ */
unsigned short Encoding; __UINT16_TYPE__ Encoding;
/** /**
* Adjust the sample rate. * Adjust the sample rate.
@ -364,7 +364,7 @@ union KernelCallback
* 7 - 88200 Hz * 7 - 88200 Hz
* 8 - 96000 Hz * 8 - 96000 Hz
*/ */
unsigned char SampleRate; __UINT8_TYPE__ SampleRate;
/** /**
* Adjust the channels. * Adjust the channels.
@ -372,30 +372,30 @@ union KernelCallback
* 0 - Mono * 0 - Mono
* 1 - Stereo * 1 - Stereo
*/ */
unsigned char Channels; __UINT8_TYPE__ Channels;
} Adjust; } Adjust;
struct struct
{ {
unsigned char *Data; __UINT8_TYPE__ *Data;
unsigned long Length; __UINT64_TYPE__ Length;
} Send; } Send;
struct struct
{ {
unsigned char Volume; __UINT8_TYPE__ Volume;
unsigned short Encoding; __UINT16_TYPE__ Encoding;
unsigned char SampleRate; __UINT8_TYPE__ SampleRate;
unsigned char Channels; __UINT8_TYPE__ Channels;
} Fetch; } Fetch;
} AudioCallback; } AudioCallback;
struct struct
{ {
unsigned char Vector; __UINT8_TYPE__ Vector;
} InterruptInfo; } InterruptInfo;
}; };
unsigned long raw; __UINT64_TYPE__ raw;
} __attribute__((packed)); } __attribute__((packed));
union CPURegisters union CPURegisters
@ -403,51 +403,51 @@ union CPURegisters
struct struct
{ {
#if defined(__x86_64__) || defined(__amd64__) #if defined(__x86_64__) || defined(__amd64__)
unsigned long r15; __UINT64_TYPE__ r15;
unsigned long r14; __UINT64_TYPE__ r14;
unsigned long r13; __UINT64_TYPE__ r13;
unsigned long r12; __UINT64_TYPE__ r12;
unsigned long r11; __UINT64_TYPE__ r11;
unsigned long r10; __UINT64_TYPE__ r10;
unsigned long r9; __UINT64_TYPE__ r9;
unsigned long r8; __UINT64_TYPE__ r8;
unsigned long rbp; __UINT64_TYPE__ rbp;
unsigned long rdi; __UINT64_TYPE__ rdi;
unsigned long rsi; __UINT64_TYPE__ rsi;
unsigned long rdx; __UINT64_TYPE__ rdx;
unsigned long rcx; __UINT64_TYPE__ rcx;
unsigned long rbx; __UINT64_TYPE__ rbx;
unsigned long rax; __UINT64_TYPE__ rax;
unsigned long InterruptNumber; __UINT64_TYPE__ InterruptNumber;
unsigned long ErrorCode; __UINT64_TYPE__ ErrorCode;
unsigned long rip; __UINT64_TYPE__ rip;
unsigned long cs; __UINT64_TYPE__ cs;
unsigned long rflags; __UINT64_TYPE__ rflags;
unsigned long rsp; __UINT64_TYPE__ rsp;
unsigned long ss; __UINT64_TYPE__ ss;
#elif defined(__i386__) #elif defined(__i386__)
unsigned int ebp; __UINT32_TYPE__ ebp;
unsigned int edi; __UINT32_TYPE__ edi;
unsigned int esi; __UINT32_TYPE__ esi;
unsigned int edx; __UINT32_TYPE__ edx;
unsigned int ecx; __UINT32_TYPE__ ecx;
unsigned int ebx; __UINT32_TYPE__ ebx;
unsigned int eax; __UINT32_TYPE__ eax;
unsigned int InterruptNumber; __UINT32_TYPE__ InterruptNumber;
unsigned int ErrorCode; __UINT32_TYPE__ ErrorCode;
unsigned int eip; __UINT32_TYPE__ eip;
unsigned int cs; __UINT32_TYPE__ cs;
unsigned int eflags; __UINT32_TYPE__ eflags;
unsigned int esp; __UINT32_TYPE__ esp;
unsigned int ss; __UINT32_TYPE__ ss;
#else #else
#warning "Unsupported architecture" #warning "Unsupported architecture"
#endif #endif
}; };
unsigned long raw; __UINT64_TYPE__ raw;
} __attribute__((packed)); } __attribute__((packed));
#endif // !__FENNIX_DRIVER_API_H__ #endif // !__FENNIX_DRIVER_API_H__

View File

@ -47,6 +47,7 @@ namespace Execute
uint64_t EntryPoint, uint64_t EntryPoint,
uint64_t BaseAddress) uint64_t BaseAddress)
{ {
#if defined(a64)
char *aux_platform = (char *)mm->RequestPages(1, true); /* TODO: 4KiB is too much for this */ char *aux_platform = (char *)mm->RequestPages(1, true); /* TODO: 4KiB is too much for this */
strcpy(aux_platform, "x86_64"); strcpy(aux_platform, "x86_64");
@ -79,9 +80,10 @@ namespace Execute
Elfauxv.push_back({.archaux = {.a_type = AT_PHDR, .a_un = {.a_val = (uint64_t)phdr_array}}}); Elfauxv.push_back({.archaux = {.a_type = AT_PHDR, .a_un = {.a_val = (uint64_t)phdr_array}}});
// AT_CLKTCK 17 // AT_CLKTCK 17
Elfauxv.push_back({.archaux = {.a_type = AT_PAGESZ, .a_un = {.a_val = (uint64_t)PAGE_SIZE}}}); Elfauxv.push_back({.archaux = {.a_type = AT_PAGESZ, .a_un = {.a_val = (uint64_t)PAGE_SIZE}}});
// AT_HWCAP 16 // AT_HWCAP 16
// AT_MINSIGSTKSZ 51 // AT_MINSIGSTKSZ 51
// AT_SYSINFO_EHDR 33 // AT_SYSINFO_EHDR 33
#endif
} }
void ELFObject::LoadExec_x86_32(int fd, PCB *TargetProcess) void ELFObject::LoadExec_x86_32(int fd, PCB *TargetProcess)
@ -93,6 +95,7 @@ namespace Execute
void ELFObject::LoadExec_x86_64(int fd, PCB *TargetProcess) void ELFObject::LoadExec_x86_64(int fd, PCB *TargetProcess)
{ {
#if defined(a64)
std::string InterpreterPath; std::string InterpreterPath;
std::vector<Elf64_Phdr> PhdrINTERP = ELFGetSymbolType_x86_64(fd, PT_INTERP); std::vector<Elf64_Phdr> PhdrINTERP = ELFGetSymbolType_x86_64(fd, PT_INTERP);
foreach (auto Interp in PhdrINTERP) foreach (auto Interp in PhdrINTERP)
@ -121,19 +124,7 @@ namespace Execute
if (LoadInterpreter(ifd, TargetProcess)) if (LoadInterpreter(ifd, TargetProcess))
{ {
/* ba deci de aici trb sa fac /* FIXME: specify argv[1] as the location for the interpreter */
sa se incarce interperter-ul
argv[1] ar trb sa fie locatia pt intrep */
// modific argv-ul
// TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME
// TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME
// TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME
// TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME
// TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME
// TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME
// TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME
debug("Interpreter loaded successfully"); debug("Interpreter loaded successfully");
fclose(ifd); fclose(ifd);
@ -231,6 +222,7 @@ namespace Execute
this->ip = EntryPoint; this->ip = EntryPoint;
this->IsElfValid = true; this->IsElfValid = true;
#endif
} }
void ELFObject::LoadDyn_x86_32(int fd, PCB *TargetProcess) void ELFObject::LoadDyn_x86_32(int fd, PCB *TargetProcess)
@ -242,6 +234,7 @@ namespace Execute
void ELFObject::LoadDyn_x86_64(int fd, PCB *TargetProcess) void ELFObject::LoadDyn_x86_64(int fd, PCB *TargetProcess)
{ {
#if defined(a64)
std::string InterpreterPath; std::string InterpreterPath;
std::vector<Elf64_Phdr> PhdrINTERP = ELFGetSymbolType_x86_64(fd, PT_INTERP); std::vector<Elf64_Phdr> PhdrINTERP = ELFGetSymbolType_x86_64(fd, PT_INTERP);
foreach (auto Interp in PhdrINTERP) foreach (auto Interp in PhdrINTERP)
@ -270,18 +263,7 @@ namespace Execute
if (LoadInterpreter(ifd, TargetProcess)) if (LoadInterpreter(ifd, TargetProcess))
{ {
/* ba deci de aici trb sa fac /* FIXME: specify argv[1] as the location for the interpreter */
sa se incarce interperter-ul
argv[1] ar trb sa fie locatia pt intrep */
// modific argv-ul
// TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME
// TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME
// TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME
// TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME
// TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME
// TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME
// TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME TODO FIXME
debug("Interpreter loaded successfully"); debug("Interpreter loaded successfully");
fclose(ifd); fclose(ifd);
@ -619,6 +601,7 @@ namespace Execute
this->ip = EntryPoint; this->ip = EntryPoint;
this->IsElfValid = true; this->IsElfValid = true;
#endif
} }
bool ELFObject::LoadInterpreter(int fd, PCB *TargetProcess) bool ELFObject::LoadInterpreter(int fd, PCB *TargetProcess)

View File

@ -95,6 +95,7 @@ namespace Execute
Elf64_Sym ELFLookupSymbol(int fd, const char *Name) Elf64_Sym ELFLookupSymbol(int fd, const char *Name)
{ {
#if defined(a64)
off_t OldOffset = lseek(fd, 0, SEEK_CUR); off_t OldOffset = lseek(fd, 0, SEEK_CUR);
Elf64_Ehdr Header; Elf64_Ehdr Header;
@ -152,6 +153,7 @@ namespace Execute
} }
error("Symbol not found."); error("Symbol not found.");
lseek(fd, OldOffset, SEEK_SET); lseek(fd, OldOffset, SEEK_SET);
#endif
return {}; return {};
} }
@ -198,6 +200,8 @@ namespace Execute
Elf64_Shdr *Target = GetELFSection(Header, Symbol->st_shndx); Elf64_Shdr *Target = GetELFSection(Header, Symbol->st_shndx);
return (uintptr_t)Header + Symbol->st_value + Target->sh_offset; return (uintptr_t)Header + Symbol->st_value + Target->sh_offset;
} }
#elif defined(a32)
return 0xdead;
#endif #endif
} }
} }

View File

@ -252,9 +252,16 @@ EXTERNC void KPrint(const char *Format, ...)
uint64_t Nanoseconds = TimeManager->GetNanosecondsSinceClassCreation(); uint64_t Nanoseconds = TimeManager->GetNanosecondsSinceClassCreation();
if (Nanoseconds != 0) if (Nanoseconds != 0)
{ {
#if defined(a64)
printf("\eCCCCCC[\e00AEFF%lu.%07lu\eCCCCCC] ", printf("\eCCCCCC[\e00AEFF%lu.%07lu\eCCCCCC] ",
Nanoseconds / 10000000, Nanoseconds / 10000000, Nanoseconds % 10000000);
Nanoseconds % 10000000); #elif defined(a32)
printf("\eCCCCCC[\e00AEFF%llu.%07llu\eCCCCCC] ",
Nanoseconds / 10000000, Nanoseconds % 10000000);
#elif defined(aa64)
printf("\eCCCCCC[\e00AEFF%lu.%07lu\eCCCCCC] ",
Nanoseconds / 10000000, Nanoseconds % 10000000);
#endif
} }
} }
@ -324,10 +331,8 @@ EXTERNC NIF void Main()
KPrint("Enabling Interrupts on Bootstrap Processor"); KPrint("Enabling Interrupts on Bootstrap Processor");
Interrupts::Enable(0); Interrupts::Enable(0);
#if defined(a64) #if defined(a86)
PowerManager->InitDSDT(); PowerManager->InitDSDT();
#elif defined(a32)
// FIXME: Add ACPI support for i386
#elif defined(aa64) #elif defined(aa64)
#endif #endif

View File

@ -30,17 +30,31 @@ void cmd_top(const char *)
printf("\e9400A1PID \e9CA100Name \e00A15BState \eCCCCCCPriority Memory Usage CPU Usage\n"); printf("\e9400A1PID \e9CA100Name \e00A15BState \eCCCCCCPriority Memory Usage CPU Usage\n");
foreach (auto Proc in TaskManager->GetProcessList()) foreach (auto Proc in TaskManager->GetProcessList())
{ {
#if defined(a64)
printf("\e9400A1%-4d \e9CA100%-20s \e00A15B%s \eCCCCCC%d %ld %ld\n", printf("\e9400A1%-4d \e9CA100%-20s \e00A15B%s \eCCCCCC%d %ld %ld\n",
Proc->ID, Proc->Name, Proc->Status == Running ? "Running" : "Stopped", Proc->ID, Proc->Name, Proc->Status == Running ? "Running" : "Stopped",
Proc->Info.Priority, Proc->Memory->GetAllocatedMemorySize(), Proc->Info.Priority, Proc->Memory->GetAllocatedMemorySize(),
Proc->Info.UserTime + Proc->Info.KernelTime); Proc->Info.UserTime + Proc->Info.KernelTime);
#elif defined(a32)
printf("\e9400A1%-4d \e9CA100%-20s \e00A15B%s \eCCCCCC%d %lld %lld\n",
Proc->ID, Proc->Name, Proc->Status == Running ? "Running" : "Stopped",
Proc->Info.Priority, Proc->Memory->GetAllocatedMemorySize(),
Proc->Info.UserTime + Proc->Info.KernelTime);
#endif
foreach (auto Thrd in Proc->Threads) foreach (auto Thrd in Proc->Threads)
{ {
#if defined(a64)
printf(" \eA80011%-4d \e9CA100%-20s \e00A15B%s \eCCCCCC%d %ld %ld\n", printf(" \eA80011%-4d \e9CA100%-20s \e00A15B%s \eCCCCCC%d %ld %ld\n",
Thrd->ID, Thrd->Name, Thrd->Status == Running ? "Running" : "Stopped", Thrd->ID, Thrd->Name, Thrd->Status == Running ? "Running" : "Stopped",
Thrd->Info.Priority, Thrd->Memory->GetAllocatedMemorySize(), Thrd->Info.Priority, Thrd->Memory->GetAllocatedMemorySize(),
Thrd->Info.UserTime + Thrd->Info.KernelTime); Thrd->Info.UserTime + Thrd->Info.KernelTime);
#elif defined(a32)
printf(" \eA80011%-4d \e9CA100%-20s \e00A15B%s \eCCCCCC%d %lld %lld\n",
Thrd->ID, Thrd->Name, Thrd->Status == Running ? "Running" : "Stopped",
Thrd->Info.Priority, Thrd->Memory->GetAllocatedMemorySize(),
Thrd->Info.UserTime + Thrd->Info.KernelTime);
#endif
} }
} }
} }

View File

@ -27,12 +27,12 @@ void cmd_uptime(const char *)
{ {
if (TimeManager) if (TimeManager)
{ {
size_t Nanoseconds = uint64_t Nanoseconds =
TimeManager->GetNanosecondsSinceClassCreation(); TimeManager->GetNanosecondsSinceClassCreation();
size_t Seconds = Nanoseconds / 10000000; uint64_t Seconds = Nanoseconds / 10000000;
size_t Minutes = Seconds / 60; uint64_t Minutes = Seconds / 60;
size_t Hours = Minutes / 60; uint64_t Hours = Minutes / 60;
size_t Days = Hours / 24; uint64_t Days = Hours / 24;
debug("Nanoseconds: %ld", Nanoseconds); debug("Nanoseconds: %ld", Nanoseconds);
@ -40,9 +40,15 @@ void cmd_uptime(const char *)
Minutes %= 60; Minutes %= 60;
Hours %= 24; Hours %= 24;
#if defined(a64)
printf("%ld days, %ld hours, %ld minutes, %ld %s\n", printf("%ld days, %ld hours, %ld minutes, %ld %s\n",
Days, Hours, Minutes, Seconds, Days, Hours, Minutes, Seconds,
Seconds == 1 ? "second" : "seconds"); Seconds == 1 ? "second" : "seconds");
#elif defined(a32)
printf("%lld days, %lld hours, %lld minutes, %lld %s\n",
Days, Hours, Minutes, Seconds,
Seconds == 1 ? "second" : "seconds");
#endif
} }
else else
{ {

View File

@ -170,8 +170,14 @@ void TaskMgr()
continue; continue;
int Status = Proc->Status.load(); int Status = Proc->Status.load();
uint64_t ProcessCpuUsage = GetUsage(OldSystemTime, &Proc->Info); uint64_t ProcessCpuUsage = GetUsage(OldSystemTime, &Proc->Info);
#if defined(a64)
printf("\e%s-> \eAABBCC%s \e00AAAA%s %ld%% (KT: %ld UT: %ld)\n", printf("\e%s-> \eAABBCC%s \e00AAAA%s %ld%% (KT: %ld UT: %ld)\n",
Statuses[Status], Proc->Name, StatusesSign[Status], ProcessCpuUsage, Proc->Info.KernelTime, Proc->Info.UserTime); Statuses[Status], Proc->Name, StatusesSign[Status], ProcessCpuUsage, Proc->Info.KernelTime, Proc->Info.UserTime);
#elif defined(a32)
printf("\e%s-> \eAABBCC%s \e00AAAA%s %lld%% (KT: %lld UT: %lld)\n",
Statuses[Status], Proc->Name, StatusesSign[Status], ProcessCpuUsage, Proc->Info.KernelTime, Proc->Info.UserTime);
#elif defined(aa64)
#endif
foreach (auto Thd in Proc->Threads) foreach (auto Thd in Proc->Threads)
{ {
@ -185,7 +191,7 @@ void TaskMgr()
Thd->Info.UserTime, Thd->Registers.rip, Thd->Info.UserTime, Thd->Registers.rip,
Thd->Parent->ELFSymbolTable ? Thd->Parent->ELFSymbolTable->GetSymbolFromAddress(Thd->Registers.rip) : "unknown"); Thd->Parent->ELFSymbolTable ? Thd->Parent->ELFSymbolTable->GetSymbolFromAddress(Thd->Registers.rip) : "unknown");
#elif defined(a32) #elif defined(a32)
printf(" \e%s-> \eAABBCC%s \e00AAAA%s %lld%% (KT: %lld UT: %lld, IP: \e24FF2B%#lx \eEDFF24%s\e00AAAA)\n\eAABBCC", printf(" \e%s-> \eAABBCC%s \e00AAAA%s %lld%% (KT: %lld UT: %lld, IP: \e24FF2B%#x \eEDFF24%s\e00AAAA)\n\eAABBCC",
Statuses[Status], Thd->Name, StatusesSign[Status], ThreadCpuUsage, Thd->Info.KernelTime, Statuses[Status], Thd->Name, StatusesSign[Status], ThreadCpuUsage, Thd->Info.KernelTime,
Thd->Info.UserTime, Thd->Registers.eip, Thd->Info.UserTime, Thd->Registers.eip,
Thd->Parent->ELFSymbolTable ? Thd->Parent->ELFSymbolTable->GetSymbolFromAddress(Thd->Registers.eip) : "unknown"); Thd->Parent->ELFSymbolTable ? Thd->Parent->ELFSymbolTable->GetSymbolFromAddress(Thd->Registers.eip) : "unknown");
@ -196,12 +202,14 @@ void TaskMgr()
OldSystemTime = TimeManager->GetCounter(); OldSystemTime = TimeManager->GetCounter();
#if defined(a64) #if defined(a64)
register uintptr_t CurrentStackAddress asm("rsp"); register uintptr_t CurrentStackAddress asm("rsp");
printf("Sanity: %d, Stack: %#lx", sanity++, CurrentStackAddress);
#elif defined(a32) #elif defined(a32)
register uintptr_t CurrentStackAddress asm("esp"); register uintptr_t CurrentStackAddress asm("esp");
printf("Sanity: %d, Stack: %#x", sanity++, CurrentStackAddress);
#elif defined(aa64) #elif defined(aa64)
register uintptr_t CurrentStackAddress asm("sp"); register uintptr_t CurrentStackAddress asm("sp");
#endif
printf("Sanity: %d, Stack: %#lx", sanity++, CurrentStackAddress); printf("Sanity: %d, Stack: %#lx", sanity++, CurrentStackAddress);
#endif
if (sanity > 1000) if (sanity > 1000)
sanity = 0; sanity = 0;
Display->SetBufferCursor(0, tmpX, tmpY); Display->SetBufferCursor(0, tmpX, tmpY);

View File

@ -72,7 +72,7 @@ namespace AdvancedHostControllerInterface
this->AHCIPortType = Type; this->AHCIPortType = Type;
this->HBAPortPtr = PortPtr; this->HBAPortPtr = PortPtr;
this->Buffer = static_cast<uint8_t *>(KAPI.Memory.RequestPage(1)); this->Buffer = static_cast<uint8_t *>(KAPI.Memory.RequestPage(1));
memset(this->Buffer, 0, KAPI.Memory.PageSize); memset(this->Buffer, 0, size_t(KAPI.Memory.PageSize));
this->PortNumber = PortNumber; this->PortNumber = PortNumber;
} }

View File

@ -283,7 +283,8 @@ namespace AudioCodec97
do do
{ {
size_t Wrote = (KAPI.Memory.PageSize > Length) ? Length : KAPI.Memory.PageSize; size_t Wrote = (KAPI.Memory.PageSize > Length) ? size_t(Length)
: size_t(KAPI.Memory.PageSize);
if (Wrote == 0) if (Wrote == 0)
break; break;

View File

@ -113,9 +113,14 @@ namespace Gigabit
RX[i]->Status = 0; RX[i]->Status = 0;
} }
#pragma diagnostic push
#pragma GCC diagnostic ignored "-Wshift-count-overflow"
WriteCMD(REG::TXDESCLO, (uint32_t)(Ptr >> 32)); WriteCMD(REG::TXDESCLO, (uint32_t)(Ptr >> 32));
WriteCMD(REG::TXDESCHI, (uint32_t)(Ptr & 0xFFFFFFFF)); WriteCMD(REG::TXDESCHI, (uint32_t)(Ptr & 0xFFFFFFFF));
#pragma diagnostic pop
WriteCMD(REG::RXDESCLO, (uint32_t)Ptr); WriteCMD(REG::RXDESCLO, (uint32_t)Ptr);
WriteCMD(REG::RXDESCHI, 0); WriteCMD(REG::RXDESCHI, 0);

View File

@ -31,6 +31,7 @@
#include "../Architecture/amd64/cpu/gdt.hpp" #include "../Architecture/amd64/cpu/gdt.hpp"
#elif defined(a32) #elif defined(a32)
#include "../Architecture/i386/cpu/apic.hpp" #include "../Architecture/i386/cpu/apic.hpp"
#include "../Architecture/i386/cpu/gdt.hpp"
#elif defined(aa64) #elif defined(aa64)
#endif #endif
@ -218,9 +219,9 @@ namespace Tasking
foreach (AuxiliaryVector var in auxv_array) foreach (AuxiliaryVector var in auxv_array)
{ {
// Subtract the size of the auxillary vector // Subtract the size of the auxillary vector
Stack64 -= sizeof(Elf64_auxv_t) / sizeof(uintptr_t); Stack64 -= sizeof(Elf_auxv_t) / sizeof(uintptr_t);
// Store the auxillary vector // Store the auxillary vector
POKE(Elf64_auxv_t, Stack64) = var.archaux; POKE(Elf_auxv_t, Stack64) = var.archaux;
// TODO: Store strings to the stack // TODO: Store strings to the stack
} }
@ -263,7 +264,14 @@ namespace Tasking
debug("SubtractStack: %#lx", SubtractStack); debug("SubtractStack: %#lx", SubtractStack);
// Set the stack pointer to the new stack // Set the stack pointer to the new stack
this->Registers.rsp = ((uintptr_t)this->Stack->GetStackTop() - SubtractStack); uintptr_t StackPointerReg = ((uintptr_t)this->Stack->GetStackTop() - SubtractStack);
#if defined(a64)
this->Registers.rsp = StackPointerReg;
#elif defined(a32)
this->Registers.esp = StackPointerReg;
#elif defined(aa64)
this->Registers.sp = StackPointerReg;
#endif
if (ArgvSize > 0) if (ArgvSize > 0)
delete[] ArgvStrings; delete[] ArgvStrings;
@ -274,10 +282,22 @@ namespace Tasking
DumpData("Stack Data", (void *)((uintptr_t)this->Stack->GetStackPhysicalTop() - (uintptr_t)SubtractStack), SubtractStack); DumpData("Stack Data", (void *)((uintptr_t)this->Stack->GetStackPhysicalTop() - (uintptr_t)SubtractStack), SubtractStack);
#endif #endif
#if defined(a64)
this->Registers.rdi = (uintptr_t)ArgvSize; // argc this->Registers.rdi = (uintptr_t)ArgvSize; // argc
this->Registers.rsi = (uintptr_t)(this->Registers.rsp + 8); // argv this->Registers.rsi = (uintptr_t)(this->Registers.rsp + 8); // argv
this->Registers.rcx = (uintptr_t)EnvpSize; // envc this->Registers.rcx = (uintptr_t)EnvpSize; // envc
this->Registers.rdx = (uintptr_t)(this->Registers.rsp + 8 + (8 * ArgvSize) + 8); // envp this->Registers.rdx = (uintptr_t)(this->Registers.rsp + 8 + (8 * ArgvSize) + 8); // envp
#elif defined(a32)
this->Registers.eax = (uintptr_t)ArgvSize; // argc
this->Registers.ebx = (uintptr_t)(this->Registers.esp + 4); // argv
this->Registers.ecx = (uintptr_t)EnvpSize; // envc
this->Registers.edx = (uintptr_t)(this->Registers.esp + 4 + (4 * ArgvSize) + 4); // envp
#elif defined(aa64)
this->Registers.x0 = (uintptr_t)ArgvSize; // argc
this->Registers.x1 = (uintptr_t)(this->Registers.sp + 8); // argv
this->Registers.x2 = (uintptr_t)EnvpSize; // envc
this->Registers.x3 = (uintptr_t)(this->Registers.sp + 8 + (8 * ArgvSize) + 8); // envp
#endif
} }
void TCB::SetupUserStack_x86_32(const char **argv, void TCB::SetupUserStack_x86_32(const char **argv,

View File

@ -77,15 +77,17 @@ typedef struct
} a_un; } a_un;
} Elf64_auxv_t; } Elf64_auxv_t;
#if defined(a64)
typedef Elf64_auxv_t Elf_auxv_t;
#elif defined(a32)
typedef Elf64_auxv_t Elf_auxv_t;
#elif defined(aa64)
typedef Elf64_auxv_t Elf_auxv_t;
#endif
typedef struct typedef struct
{ {
#if defined(a64) Elf_auxv_t archaux;
Elf64_auxv_t archaux;
#elif defined(a32)
Elf32_auxv_t archaux;
#elif defined(aa64)
Elf64_auxv_t archaux;
#endif
} AuxiliaryVector; } AuxiliaryVector;
#endif // !__FENNIX_KERNEL_ABI_H__ #endif // !__FENNIX_KERNEL_ABI_H__

View File

@ -210,6 +210,35 @@ namespace CPU
namespace x32 namespace x32
{ {
/**
* @brief MSR_APIC_BASE structure
* @see MSR_APIC_BASE
*/
typedef union
{
struct
{
/** @brief Reserved */
uint32_t Reserved0 : 8;
/**
* @brief BSP Flag
* @details If the BSP flag is set to 1, the processor is the bootstrap processor.
*/
uint32_t BSP : 1;
/** @brief Reserved */
uint32_t Reserved1 : 1;
/** @brief Enable x2APIC mode */
uint32_t EXTD : 1;
/** @brief APIC Global Enable */
uint32_t EN : 1;
/** @brief APIC Base Low Address */
uint32_t ApicBaseLo : 20;
/** @brief APIC Base High Address */
uint32_t ApicBaseHi : 32;
};
uint64_t raw;
} __packed APIC_BASE;
typedef union typedef union
{ {
struct struct

View File

@ -213,7 +213,7 @@ namespace PCI
struct DeviceConfig struct DeviceConfig
{ {
uintptr_t BaseAddress; uint64_t BaseAddress;
uint16_t PCISegGroup; uint16_t PCISegGroup;
uint8_t StartBus; uint8_t StartBus;
uint8_t EndBus; uint8_t EndBus;
@ -228,9 +228,9 @@ namespace PCI
public: public:
std::vector<PCIDeviceHeader *> &GetDevices() { return Devices; } std::vector<PCIDeviceHeader *> &GetDevices() { return Devices; }
void MapPCIAddresses(PCIDeviceHeader *PCIDevice, Memory::PageTable *Table = nullptr); void MapPCIAddresses(PCIDeviceHeader *PCIDevice, Memory::PageTable *Table = nullptr);
void EnumerateFunction(uintptr_t DeviceAddress, uintptr_t Function); void EnumerateFunction(uint64_t DeviceAddress, uintptr_t Function);
void EnumerateDevice(uintptr_t BusAddress, uintptr_t Device); void EnumerateDevice(uint64_t BusAddress, uintptr_t Device);
void EnumerateBus(uintptr_t BaseAddress, uintptr_t Bus); void EnumerateBus(uint64_t BaseAddress, uintptr_t Bus);
std::vector<PCIDeviceHeader *> FindPCIDevice(uint8_t Class, uint8_t Subclass, uint8_t ProgIF); std::vector<PCIDeviceHeader *> FindPCIDevice(uint8_t Class, uint8_t Subclass, uint8_t ProgIF);
std::vector<PCIDeviceHeader *> FindPCIDevice(int VendorID, int DeviceID); std::vector<PCIDeviceHeader *> FindPCIDevice(int VendorID, int DeviceID);

View File

@ -52,15 +52,15 @@ namespace Time
private: private:
struct HPET struct HPET
{ {
uintptr_t GeneralCapabilities; uint64_t GeneralCapabilities;
uintptr_t Reserved0; uint64_t Reserved0;
uintptr_t GeneralConfiguration; uint64_t GeneralConfiguration;
uintptr_t Reserved1; uint64_t Reserved1;
uintptr_t GeneralIntStatus; uint64_t GeneralIntStatus;
uintptr_t Reserved2; uint64_t Reserved2;
uintptr_t Reserved3[24]; uint64_t Reserved3[24];
uintptr_t MainCounterValue; uint64_t MainCounterValue;
uintptr_t Reserved4; uint64_t Reserved4;
}; };
uint32_t clk = 0; uint32_t clk = 0;