Update kernel

This commit is contained in:
Alex
2023-08-06 04:53:14 +03:00
parent 3b65386399
commit 2c51e4432f
181 changed files with 21873 additions and 21475 deletions

View File

@@ -28,7 +28,7 @@ namespace CPU
{
static bool SSEEnabled = false;
char *Vendor()
const char *Vendor()
{
static char Vendor[13] = {0};
if (Vendor[0] != 0)
@@ -52,7 +52,7 @@ namespace CPU
return Vendor;
}
char *Name()
const char *Name()
{
static char Name[49] = {0};
if (Name[0] != 0)
@@ -98,7 +98,7 @@ namespace CPU
return Name;
}
char *Hypervisor()
const char *Hypervisor()
{
static char Hypervisor[13] = {0};
if (Hypervisor[0] != 0)
@@ -255,8 +255,7 @@ namespace CPU
bool SSEEnableAfter = false;
/* Not sure if my code is not working properly or something else is the issue. */
if ((strcmp(Hypervisor(), x86_CPUID_VENDOR_TCG) != 0 &&
strcmp(Hypervisor(), x86_CPUID_VENDOR_VIRTUALBOX) != 0) &&
if ((strcmp(Hypervisor(), x86_CPUID_VENDOR_VIRTUALBOX) != 0) &&
SSESupport)
{
debug("Enabling SSE support...");
@@ -438,16 +437,16 @@ namespace CPU
#endif
}
uintptr_t Counter()
uint64_t Counter()
{
// TODO: Get the counter from the x2APIC or any other timer that is available. (TSC is not available on all CPUs)
uintptr_t Counter;
#if defined(a64)
uint64_t Counter;
#if defined(a86)
uint32_t eax, edx;
asmv("rdtsc"
: "=A"(Counter));
#elif defined(a32)
asmv("rdtsc"
: "=A"(Counter));
: "=a"(eax),
"=d"(edx));
Counter = ((uint64_t)eax) | (((uint64_t)edx) << 32);
#elif defined(aa64)
asmv("mrs %0, cntvct_el0"
: "=r"(Counter));

File diff suppressed because it is too large Load Diff

View File

@@ -52,9 +52,11 @@ namespace CrashHandler
if (cpu)
{
EHPrint("\eE46CEBCPU Data Address: %#lx\n", cpu);
EHPrint("Core Stack: %#lx, Core ID: %ld, Error Code: %ld\n", cpu->Stack, cpu->ID, cpu->ErrorCode);
EHPrint("Core Stack: %#lx, Core ID: %ld, Error Code: %ld\n",
cpu->Stack, cpu->ID, cpu->ErrorCode);
EHPrint("Is Active: %s\n", cpu->IsActive ? "true" : "false");
EHPrint("Current Process: %#lx, Current Thread: %#lx\n", cpu->CurrentProcess, cpu->CurrentThread);
EHPrint("Current Process: %#lx, Current Thread: %#lx\n",
cpu->CurrentProcess.load(), cpu->CurrentThread.load());
EHPrint("Arch Specific Data: %#lx\n", cpu->Data);
EHPrint("Checksum: 0x%X\n", cpu->Checksum);
}
@@ -128,11 +130,11 @@ namespace CrashHandler
#endif
#if defined(a86)
EHPrint("\eA0A0A0DR6: B0:%s B1:%s B2:%s B3:%s BD:%s BS:%s BT:%s\n",
EHPrint("\eA0A0A0DR6: B0:%s B1:%s B2:%s B3:%s\n BD:%s BS:%s BT:%s\n",
data.dr6.B0 ? "True " : "False", data.dr6.B1 ? "True " : "False", data.dr6.B2 ? "True " : "False", data.dr6.B3 ? "True " : "False",
data.dr6.BD ? "True " : "False", data.dr6.BS ? "True " : "False", data.dr6.BT ? "True " : "False");
EHPrint("\eA0F0F0DR7: L0:%s G0:%s L1:%s G1:%s\n L2:%s G2:%s L3:%s G3:%s\n LE:%s GE:%s GD:%s\n R/W0:%s LEN0:%s R/W1:%s LEN1:%s\n R/W2:%s LEN2:%s R/W3:%s LEN3:%s\n",
EHPrint("\eA0F0F0DR7: L0:%s G0:%s L1:%s G1:%s\n L2:%s G2:%s L3:%s G3:%s\n LE:%s GE:%s GD:%s\n R/W0:%s LEN0:%s R/W1:%s LEN1:%s\n R/W2:%s LEN2:%s R/W3:%s LEN3:%s\n",
data.dr7.L0 ? "True " : "False", data.dr7.G0 ? "True " : "False", data.dr7.L1 ? "True " : "False", data.dr7.G1 ? "True " : "False",
data.dr7.L2 ? "True " : "False", data.dr7.G2 ? "True " : "False", data.dr7.L3 ? "True " : "False", data.dr7.G3 ? "True " : "False",
data.dr7.LE ? "True " : "False", data.dr7.GE ? "True " : "False", data.dr7.GD ? "True " : "False", data.dr7.RW0 ? "True " : "False",

View File

@@ -311,7 +311,7 @@ namespace CrashHandler
case CPU::x86::PageFault:
{
EHPrint("Exception: Page Fault\n");
EHPrint("The processor attempted to access a page that is not present.\n");
EHPrint("The processor attempted to access a page that is not present/accessible.\n");
CPU::x64::PageFaultErrorCode params = {.raw = (uint32_t)Frame->ErrorCode};
#if defined(a64)

View File

@@ -41,8 +41,8 @@ namespace CrashHandler
"AAFF00", // Ready
"00AA00", // Running
"FFAA00", // Sleeping
"FFAA00", // Waiting
"FF0088", // Stopped
"FFAA00", // Blocked
"FF0088", // Zombie
"FF0000", // Terminated
};
@@ -51,8 +51,8 @@ namespace CrashHandler
"Ready", // Ready
"Running", // Running
"Sleeping", // Sleeping
"Waiting", // Waiting
"Stopped", // Stopped
"Blocked", // Blocked
"Zombie", // Zombie
"Terminated", // Terminated
};
@@ -62,9 +62,11 @@ namespace CrashHandler
if (data.Thread)
#if defined(a64)
EHPrint("\eFAFAFACrash occurred in thread \eAA0F0F%s\eFAFAFA(%ld) at \e00AAAA%#lx\n", data.Thread->Name, data.Thread->ID, data.Frame->rip);
EHPrint("\eFAFAFACrash occurred in thread \eAA0F0F%s\eFAFAFA(%ld) at \e00AAAA%#lx\n",
data.Thread->Name, data.Thread->ID, data.Frame->rip);
#elif defined(a32)
EHPrint("\eFAFAFACrash occurred in thread \eAA0F0F%s\eFAFAFA(%ld) at \e00AAAA%#lx\n", data.Thread->Name, data.Thread->ID, data.Frame->eip);
EHPrint("\eFAFAFACrash occurred in thread \eAA0F0F%s\eFAFAFA(%ld) at \e00AAAA%#lx\n",
data.Thread->Name, data.Thread->ID, data.Frame->eip);
#elif defined(aa64)
#endif
@@ -72,12 +74,14 @@ namespace CrashHandler
foreach (auto Process in Plist)
{
EHPrint("\e%s-> \eFAFAFA%s\eCCCCCC(%ld) \e00AAAA%s\eFAFAFA PT:\e00AAAA%#lx\n",
StatusColor[Process->Status], Process->Name, Process->ID, StatusString[Process->Status],
StatusColor[Process->Status.load()], Process->Name,
Process->ID, StatusString[Process->Status.load()],
Process->PageTable);
foreach (auto Thread in Process->Threads)
EHPrint("\e%s -> \eFAFAFA%s\eCCCCCC(%ld) \e00AAAA%s\eFAFAFA Stack:\e00AAAA%#lx\n",
StatusColor[Thread->Status], Thread->Name, Thread->ID, StatusString[Thread->Status],
StatusColor[Thread->Status.load()], Thread->Name,
Thread->ID, StatusString[Thread->Status.load()],
Thread->Stack);
}
}

View File

@@ -47,7 +47,7 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
CriticalSection cs;
debug("Interrupts? %s.", cs.IsInterruptsEnabled() ? "Yes" : "No");
fixme("Handling user mode exception");
TaskManager->GetCurrentThread()->Status = Tasking::TaskStatus::Stopped;
thisThread->Status = Tasking::TaskStatus::Zombie;
CPUData *CurCPU = GetCurrentCPU();
{
@@ -354,7 +354,7 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
if (CurCPU->CurrentThread->Stack->Expand(CrashHandler::PageFaultAddress))
{
debug("Stack expanded");
TaskManager->GetCurrentThread()->Status = Tasking::TaskStatus::Ready;
thisThread->Status = Tasking::TaskStatus::Ready;
return;
}
break;
@@ -389,7 +389,7 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
}
}
TaskManager->GetCurrentThread()->Status = Tasking::TaskStatus::Terminated;
thisThread->Status = Tasking::TaskStatus::Terminated;
__sync;
error("End of report.");
CPU::Interrupts(CPU::Enable);

View File

@@ -27,170 +27,170 @@ using namespace UniversalAsynchronousReceiverTransmitter;
static inline NIF void uart_wrapper(char c, void *unused)
{
UART(COM1).Write(c);
UNUSED(unused);
UART(COM1).Write(c);
UNUSED(unused);
}
static inline NIF bool WritePrefix(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, va_list args)
{
const char *DbgLvlString;
switch (Level)
{
case DebugLevelError:
DbgLvlString = "ERROR";
break;
case DebugLevelWarning:
DbgLvlString = "WARN ";
break;
case DebugLevelInfo:
DbgLvlString = "INFO ";
break;
case DebugLevelDebug:
DbgLvlString = "DEBUG";
break;
case DebugLevelTrace:
DbgLvlString = "TRACE";
break;
case DebugLevelFixme:
DbgLvlString = "FIXME";
break;
case DebugLevelStub:
fctprintf(uart_wrapper, nullptr, "STUB | %s>%s() is stub\n", File, Function);
return false;
case DebugLevelFunction:
fctprintf(uart_wrapper, nullptr, "FUNC | %s>%s( ", File, Function);
vfctprintf(uart_wrapper, nullptr, Format, args);
fctprintf(uart_wrapper, nullptr, " )\n");
return false;
case DebugLevelUbsan:
{
DbgLvlString = "UBSAN";
fctprintf(uart_wrapper, nullptr, "%s| ", DbgLvlString);
return true;
}
default:
DbgLvlString = "UNKNW";
break;
}
fctprintf(uart_wrapper, nullptr, "%s| %s>%s:%d: ", DbgLvlString, File, Function, Line);
return true;
const char *DbgLvlString;
switch (Level)
{
case DebugLevelError:
DbgLvlString = "ERROR";
break;
case DebugLevelWarning:
DbgLvlString = "WARN ";
break;
case DebugLevelInfo:
DbgLvlString = "INFO ";
break;
case DebugLevelDebug:
DbgLvlString = "DEBUG";
break;
case DebugLevelTrace:
DbgLvlString = "TRACE";
break;
case DebugLevelFixme:
DbgLvlString = "FIXME";
break;
case DebugLevelStub:
fctprintf(uart_wrapper, nullptr, "STUB | %s>%s() is stub\n", File, Function);
return false;
case DebugLevelFunction:
fctprintf(uart_wrapper, nullptr, "FUNC | %s>%s( ", File, Function);
vfctprintf(uart_wrapper, nullptr, Format, args);
fctprintf(uart_wrapper, nullptr, " )\n");
return false;
case DebugLevelUbsan:
{
DbgLvlString = "UBSAN";
fctprintf(uart_wrapper, nullptr, "%s| ", DbgLvlString);
return true;
}
default:
DbgLvlString = "UNKNW";
break;
}
fctprintf(uart_wrapper, nullptr, "%s| %s>%s:%d: ", DbgLvlString, File, Function, Line);
return true;
}
namespace SysDbg
{
NIF void Write(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
{
va_list args;
va_start(args, Format);
if (!WritePrefix(Level, File, Line, Function, Format, args))
{
va_end(args);
return;
}
vfctprintf(uart_wrapper, nullptr, Format, args);
va_end(args);
}
NIF void Write(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
{
va_list args;
va_start(args, Format);
if (!WritePrefix(Level, File, Line, Function, Format, args))
{
va_end(args);
return;
}
vfctprintf(uart_wrapper, nullptr, Format, args);
va_end(args);
}
NIF void WriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
{
va_list args;
va_start(args, Format);
if (!WritePrefix(Level, File, Line, Function, Format, args))
{
va_end(args);
return;
}
vfctprintf(uart_wrapper, nullptr, Format, args);
va_end(args);
uart_wrapper('\n', nullptr);
}
NIF void WriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
{
va_list args;
va_start(args, Format);
if (!WritePrefix(Level, File, Line, Function, Format, args))
{
va_end(args);
return;
}
vfctprintf(uart_wrapper, nullptr, Format, args);
va_end(args);
uart_wrapper('\n', nullptr);
}
NIF void LockedWrite(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
{
SmartTimeoutLock(DebuggerLock, 1000);
va_list args;
va_start(args, Format);
if (!WritePrefix(Level, File, Line, Function, Format, args))
{
va_end(args);
return;
}
vfctprintf(uart_wrapper, nullptr, Format, args);
va_end(args);
}
NIF void LockedWrite(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
{
SmartTimeoutLock(DebuggerLock, 1000);
va_list args;
va_start(args, Format);
if (!WritePrefix(Level, File, Line, Function, Format, args))
{
va_end(args);
return;
}
vfctprintf(uart_wrapper, nullptr, Format, args);
va_end(args);
}
NIF void LockedWriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
{
SmartTimeoutLock(DebuggerLock, 1000);
va_list args;
va_start(args, Format);
if (!WritePrefix(Level, File, Line, Function, Format, args))
{
va_end(args);
return;
}
vfctprintf(uart_wrapper, nullptr, Format, args);
va_end(args);
uart_wrapper('\n', nullptr);
}
NIF void LockedWriteLine(DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
{
SmartTimeoutLock(DebuggerLock, 1000);
va_list args;
va_start(args, Format);
if (!WritePrefix(Level, File, Line, Function, Format, args))
{
va_end(args);
return;
}
vfctprintf(uart_wrapper, nullptr, Format, args);
va_end(args);
uart_wrapper('\n', nullptr);
}
}
// C compatibility
extern "C" NIF void SysDbgWrite(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
{
va_list args;
va_start(args, Format);
if (!WritePrefix(Level, File, Line, Function, Format, args))
{
va_end(args);
return;
}
vfctprintf(uart_wrapper, nullptr, Format, args);
va_end(args);
va_list args;
va_start(args, Format);
if (!WritePrefix(Level, File, Line, Function, Format, args))
{
va_end(args);
return;
}
vfctprintf(uart_wrapper, nullptr, Format, args);
va_end(args);
}
// C compatibility
extern "C" NIF void SysDbgWriteLine(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
{
va_list args;
va_start(args, Format);
if (!WritePrefix(Level, File, Line, Function, Format, args))
{
va_end(args);
return;
}
vfctprintf(uart_wrapper, nullptr, Format, args);
va_end(args);
uart_wrapper('\n', nullptr);
va_list args;
va_start(args, Format);
if (!WritePrefix(Level, File, Line, Function, Format, args))
{
va_end(args);
return;
}
vfctprintf(uart_wrapper, nullptr, Format, args);
va_end(args);
uart_wrapper('\n', nullptr);
}
// C compatibility
extern "C" NIF void SysDbgLockedWrite(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
{
SmartTimeoutLock(DebuggerLock, 1000);
va_list args;
va_start(args, Format);
if (!WritePrefix(Level, File, Line, Function, Format, args))
{
va_end(args);
return;
}
vfctprintf(uart_wrapper, nullptr, Format, args);
va_end(args);
SmartTimeoutLock(DebuggerLock, 1000);
va_list args;
va_start(args, Format);
if (!WritePrefix(Level, File, Line, Function, Format, args))
{
va_end(args);
return;
}
vfctprintf(uart_wrapper, nullptr, Format, args);
va_end(args);
}
// C compatibility
extern "C" NIF void SysDbgLockedWriteLine(enum DebugLevel Level, const char *File, int Line, const char *Function, const char *Format, ...)
{
SmartTimeoutLock(DebuggerLock, 1000);
va_list args;
va_start(args, Format);
if (!WritePrefix(Level, File, Line, Function, Format, args))
{
va_end(args);
return;
}
vfctprintf(uart_wrapper, nullptr, Format, args);
va_end(args);
uart_wrapper('\n', nullptr);
SmartTimeoutLock(DebuggerLock, 1000);
va_list args;
va_start(args, Format);
if (!WritePrefix(Level, File, Line, Function, Format, args))
{
va_end(args);
return;
}
vfctprintf(uart_wrapper, nullptr, Format, args);
va_end(args);
uart_wrapper('\n', nullptr);
}

View File

@@ -29,7 +29,7 @@ namespace Disk
void Manager::FetchDisks(unsigned long DriverUID)
{
KernelCallback callback{};
callback.Reason = FetchReason;
callback.Reason = QueryReason;
DriverManager->IOCB(DriverUID, &callback);
this->AvailablePorts = callback.DiskCallback.Fetch.Ports;
this->BytesPerSector = callback.DiskCallback.Fetch.BytesPerSector;

View File

@@ -83,29 +83,29 @@ namespace Driver
{
debug("Searching for driver %ld", DUID);
foreach (auto Drv in Drivers)
forItr(Drv, Drivers)
{
if (Drv.DriverUID != DUID)
if (Drv->DriverUID != DUID)
continue;
KernelCallback callback{};
callback.Reason = StopReason;
debug("Stopping & unloading driver %ld [%#lx]", Drv.DriverUID, Drv.Address);
this->IOCB(Drv.DriverUID, &callback);
debug("Stopping & unloading driver %ld [%#lx]", Drv->DriverUID, Drv->Address);
this->IOCB(Drv->DriverUID, &callback);
for (size_t j = 0; j < sizeof(Drv.InterruptHook) / sizeof(Drv.InterruptHook[0]); j++)
for (size_t j = 0; j < sizeof(Drv->InterruptHook) / sizeof(Drv->InterruptHook[0]); j++)
{
if (!Drv.InterruptHook[j])
if (!Drv->InterruptHook[j])
continue;
debug("Interrupt hook %#lx", Drv.InterruptHook[j]);
delete Drv.InterruptHook[j], Drv.InterruptHook[j] = nullptr;
debug("Interrupt hook %#lx", Drv->InterruptHook[j]);
delete Drv->InterruptHook[j], Drv->InterruptHook[j] = nullptr;
}
if (Drv.MemTrk)
delete Drv.MemTrk, Drv.MemTrk = nullptr;
if (Drv->MemTrk)
delete Drv->MemTrk, Drv->MemTrk = nullptr;
Drivers.remove(Drv);
Drivers.erase(Drv);
return true;
}
return false;
@@ -157,7 +157,7 @@ namespace Driver
return DriverCode::OK;
}
DriverCode Driver::LoadDriver(uintptr_t DriverAddress, uintptr_t Size)
DriverCode Driver::LoadDriver(uintptr_t DriverAddress, size_t Size)
{
Fex *DrvHdr = (Fex *)DriverAddress;
if (DrvHdr->Magic[0] != 'F' || DrvHdr->Magic[1] != 'E' || DrvHdr->Magic[2] != 'X' || DrvHdr->Magic[3] != '\0')
@@ -201,22 +201,23 @@ namespace Driver
StartAHCI();
StartVMwareMouse();
StartPS2Mouse();
StartPS2Keyboard();
StartATA();
StartAC97();
StartRTL8139();
StartPCNET();
StartGigabit();
VirtualFileSystem::File DriverDirectory = vfs->Open(Config.DriverDirectory);
if (!DriverDirectory.IsOK())
RefNode *DriverDirectory = vfs->Open(Config.DriverDirectory);
if (!DriverDirectory)
{
KPrint("\eE85230Failed to open driver directory: %s! (Status: %#lx)", Config.DriverDirectory, DriverDirectory.Status);
vfs->Close(DriverDirectory);
KPrint("\eE85230Failed to open %s: %d)",
Config.DriverDirectory, errno);
return;
}
debug("Loading drivers from %s", Config.DriverDirectory);
foreach (auto DrvFile in DriverDirectory.GetChildren())
foreach (auto DrvFile in DriverDirectory->GetNode()->Children)
{
if (DrvFile->Flags != VirtualFileSystem::NodeFlags::FILE)
continue;
@@ -241,7 +242,7 @@ namespace Driver
}
}
}
vfs->Close(DriverDirectory);
delete DriverDirectory;
}
Driver::Driver() {}

View File

@@ -34,6 +34,9 @@ namespace Driver
DriverCode Driver::DriverLoadBindInput(uintptr_t DriverAddress, size_t Size, bool IsBuiltIn)
{
stub;
UNUSED(DriverAddress);
UNUSED(Size);
UNUSED(IsBuiltIn);
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@@ -33,7 +33,7 @@ namespace Driver
{
DriverCode Driver::DriverLoadBindInterrupt(uintptr_t DriverAddress, size_t Size, bool IsBuiltIn)
{
Memory::MemMgr *mem = new Memory::MemMgr(nullptr, TaskManager->GetCurrentProcess()->memDirectory);
Memory::MemMgr *mem = new Memory::MemMgr(nullptr, thisProcess->memDirectory);
BuiltInDriverInfo *bidi = (BuiltInDriverInfo *)DriverAddress;
Fex *fex = nullptr;

View File

@@ -61,7 +61,7 @@ namespace Driver
debug("[%ld] VendorID: %#x; DeviceID: %#x",
devices.size(), PCIDevice->VendorID, PCIDevice->DeviceID);
Memory::MemMgr *mem = new Memory::MemMgr(nullptr, TaskManager->GetCurrentProcess()->memDirectory);
Memory::MemMgr *mem = new Memory::MemMgr(nullptr, thisProcess->memDirectory);
BuiltInDriverInfo *bidi = (BuiltInDriverInfo *)DriverAddress;
Fex *fex = nullptr;

View File

@@ -34,6 +34,9 @@ namespace Driver
DriverCode Driver::DriverLoadBindProcess(uintptr_t DriverAddress, size_t Size, bool IsBuiltIn)
{
stub;
UNUSED(DriverAddress);
UNUSED(Size);
UNUSED(IsBuiltIn);
return DriverCode::NOT_IMPLEMENTED;
}
}

View File

@@ -40,209 +40,213 @@ extern "C" SafeFunction void ExceptionHandler(void *Data) { CrashHandler::Handle
namespace Interrupts
{
struct Event
{
int ID;
void *Data;
};
std::vector<Event> RegisteredEvents;
struct Event
{
int ID;
void *Data;
};
std::vector<Event> RegisteredEvents;
#if defined(a64)
/* APIC::APIC */ void *apic[MAX_CPU];
/* APIC::Timer */ void *apicTimer[MAX_CPU];
/* APIC::APIC */ void *apic[MAX_CPU];
/* APIC::Timer */ void *apicTimer[MAX_CPU];
#elif defined(a32)
/* APIC::APIC */ void *apic[MAX_CPU];
/* APIC::APIC */ void *apic[MAX_CPU];
#elif defined(aa64)
#endif
void *InterruptFrames[INT_FRAMES_MAX];
void *InterruptFrames[INT_FRAMES_MAX];
void Initialize(int Core)
{
void Initialize(int Core)
{
#if defined(a64)
GlobalDescriptorTable::Init(Core);
InterruptDescriptorTable::Init(Core);
CPUData *CoreData = GetCPU(Core);
CoreData->Checksum = CPU_DATA_CHECKSUM;
CPU::x64::wrmsr(CPU::x64::MSR_GS_BASE, (uint64_t)CoreData);
CPU::x64::wrmsr(CPU::x64::MSR_SHADOW_GS_BASE, (uint64_t)CoreData);
CoreData->ID = Core;
CoreData->IsActive = true;
CoreData->Stack = (uintptr_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1)) + STACK_SIZE;
if (CoreData->Checksum != CPU_DATA_CHECKSUM)
{
KPrint("CPU %d checksum mismatch! %x != %x", Core, CoreData->Checksum, CPU_DATA_CHECKSUM);
CPU::Stop();
}
debug("Stack for core %d is %#lx (Address: %#lx)", Core, CoreData->Stack, CoreData->Stack - STACK_SIZE);
InitializeSystemCalls();
GlobalDescriptorTable::Init(Core);
InterruptDescriptorTable::Init(Core);
CPUData *CoreData = GetCPU(Core);
CoreData->Checksum = CPU_DATA_CHECKSUM;
CPU::x64::wrmsr(CPU::x64::MSR_GS_BASE, (uint64_t)CoreData);
CPU::x64::wrmsr(CPU::x64::MSR_SHADOW_GS_BASE, (uint64_t)CoreData);
CoreData->ID = Core;
CoreData->IsActive = true;
CoreData->Stack = (uintptr_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1)) + STACK_SIZE;
if (CoreData->Checksum != CPU_DATA_CHECKSUM)
{
KPrint("CPU %d checksum mismatch! %x != %x",
Core, CoreData->Checksum, CPU_DATA_CHECKSUM);
CPU::Stop();
}
debug("Stack for core %d is %#lx (Address: %#lx)",
Core, CoreData->Stack, CoreData->Stack - STACK_SIZE);
InitializeSystemCalls();
#elif defined(a32)
GlobalDescriptorTable::Init(Core);
InterruptDescriptorTable::Init(Core);
CPUData *CoreData = GetCPU(Core);
CoreData->Checksum = CPU_DATA_CHECKSUM;
CPU::x32::wrmsr(CPU::x32::MSR_GS_BASE, (uint64_t)CoreData);
CPU::x32::wrmsr(CPU::x32::MSR_SHADOW_GS_BASE, (uint64_t)CoreData);
CoreData->ID = Core;
CoreData->IsActive = true;
CoreData->Stack = (uintptr_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1)) + STACK_SIZE;
if (CoreData->Checksum != CPU_DATA_CHECKSUM)
{
KPrint("CPU %d checksum mismatch! %x != %x", Core, CoreData->Checksum, CPU_DATA_CHECKSUM);
CPU::Stop();
}
debug("Stack for core %d is %#lx (Address: %#lx)", Core, CoreData->Stack, CoreData->Stack - STACK_SIZE);
GlobalDescriptorTable::Init(Core);
InterruptDescriptorTable::Init(Core);
CPUData *CoreData = GetCPU(Core);
CoreData->Checksum = CPU_DATA_CHECKSUM;
CPU::x32::wrmsr(CPU::x32::MSR_GS_BASE, (uint64_t)CoreData);
CPU::x32::wrmsr(CPU::x32::MSR_SHADOW_GS_BASE, (uint64_t)CoreData);
CoreData->ID = Core;
CoreData->IsActive = true;
CoreData->Stack = (uintptr_t)KernelAllocator.RequestPages(TO_PAGES(STACK_SIZE + 1)) + STACK_SIZE;
if (CoreData->Checksum != CPU_DATA_CHECKSUM)
{
KPrint("CPU %d checksum mismatch! %x != %x", Core, CoreData->Checksum, CPU_DATA_CHECKSUM);
CPU::Stop();
}
debug("Stack for core %d is %#lx (Address: %#lx)", Core, CoreData->Stack, CoreData->Stack - STACK_SIZE);
#elif defined(aa64)
warn("aarch64 is not supported yet");
warn("aarch64 is not supported yet");
#endif
}
}
void Enable(int Core)
{
void Enable(int Core)
{
#if defined(a64)
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.
apic[Core] = new APIC::APIC(Core);
if (Core == Config.IOAPICInterruptCore) // Redirect IRQs to the specified core.
((APIC::APIC *)apic[Core])->RedirectIRQs(Core);
}
else
{
error("LAPIC not found");
// TODO: PIC
}
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.
apic[Core] = new APIC::APIC(Core);
if (Core == Config.IOAPICInterruptCore) // Redirect IRQs to the specified core.
((APIC::APIC *)apic[Core])->RedirectIRQs(Core);
}
else
{
error("LAPIC not found");
// TODO: PIC
}
#elif defined(a32)
warn("i386 is not supported yet");
warn("i386 is not supported yet");
#elif defined(aa64)
warn("aarch64 is not supported yet");
warn("aarch64 is not supported yet");
#endif
}
}
void InitializeTimer(int Core)
{
// TODO: This function is called by SMP too. Do not initialize timers that doesn't support multiple cores.
void InitializeTimer(int Core)
{
// TODO: This function is called by SMP too. Do not initialize timers that doesn't support multiple cores.
#if defined(a64)
if (apic[Core] != nullptr)
apicTimer[Core] = new APIC::Timer((APIC::APIC *)apic[Core]);
else
{
fixme("apic not found");
}
if (apic[Core] != nullptr)
apicTimer[Core] = new APIC::Timer((APIC::APIC *)apic[Core]);
else
{
fixme("apic not found");
}
#elif defined(a32)
warn("i386 is not supported yet");
warn("i386 is not supported yet");
#elif defined(aa64)
warn("aarch64 is not supported yet");
warn("aarch64 is not supported yet");
#endif
}
}
SafeFunction void RemoveAll()
{
RegisteredEvents.clear();
}
SafeFunction void RemoveAll()
{
RegisteredEvents.clear();
}
extern "C" SafeFunction void MainInterruptHandler(void *Data)
{
extern "C" SafeFunction void MainInterruptHandler(void *Data)
{
#if defined(a64)
CPU::x64::TrapFrame *Frame = (CPU::x64::TrapFrame *)Data;
// debug("IRQ%ld", Frame->InterruptNumber - 32);
CPU::x64::TrapFrame *Frame = (CPU::x64::TrapFrame *)Data;
// debug("IRQ%ld", Frame->InterruptNumber - 32);
memmove(InterruptFrames + 1, InterruptFrames, sizeof(InterruptFrames) - sizeof(InterruptFrames[0]));
InterruptFrames[0] = (void *)Frame->rip;
memmove(InterruptFrames + 1, InterruptFrames, sizeof(InterruptFrames) - sizeof(InterruptFrames[0]));
InterruptFrames[0] = (void *)Frame->rip;
CPUData *CoreData = GetCurrentCPU();
int Core = 0;
if (likely(CoreData != nullptr))
Core = CoreData->ID;
CPUData *CoreData = GetCurrentCPU();
int Core = 0;
if (likely(CoreData != nullptr))
Core = CoreData->ID;
/* If this is false, we have a big problem. */
if (likely(Frame->InterruptNumber < CPU::x86::IRQ223 && Frame->InterruptNumber > CPU::x86::ISR0))
{
/* Halt core interrupt */
if (unlikely(Frame->InterruptNumber == CPU::x86::IRQ29))
CPU::Stop();
/* If this is false, we have a big problem. */
if (likely(Frame->InterruptNumber < CPU::x86::IRQ223 && Frame->InterruptNumber > CPU::x86::ISR0))
{
/* Halt core interrupt */
if (unlikely(Frame->InterruptNumber == CPU::x86::IRQ29))
CPU::Stop();
bool InterruptHandled = false;
foreach (auto ev in RegisteredEvents)
{
bool InterruptHandled = false;
foreach (auto ev in RegisteredEvents)
{
#if defined(a86)
if ((ev.ID + CPU::x86::IRQ0) == static_cast<int>(Frame->InterruptNumber))
if ((ev.ID + CPU::x86::IRQ0) == s_cst(int, Frame->InterruptNumber))
#elif defined(aa64)
if (ev.ID == static_cast<int>(Frame->InterruptNumber))
if (ev.ID == s_cst(int, Frame->InterruptNumber))
#endif
{
((Handler *)ev.Data)->OnInterruptReceived(Frame);
InterruptHandled = true;
}
}
{
Handler *hnd = (Handler *)ev.Data;
hnd->OnInterruptReceived(Frame);
InterruptHandled = true;
}
}
if (!InterruptHandled)
{
error("IRQ%ld is unhandled on CPU %d.", Frame->InterruptNumber - 32, Core);
if (Frame->InterruptNumber == CPU::x86::IRQ1)
{
uint8_t scancode = inb(0x60);
warn("IRQ1 is the keyboard interrupt. Scancode: %#x", scancode);
}
}
if (!InterruptHandled)
{
error("IRQ%ld is unhandled on CPU %d.", Frame->InterruptNumber - 32, Core);
if (Frame->InterruptNumber == CPU::x86::IRQ1)
{
uint8_t scancode = inb(0x60);
warn("IRQ1 is the keyboard interrupt. Scancode: %#x", scancode);
}
}
if (likely(apic[Core]))
{
((APIC::APIC *)Interrupts::apic[Core])->EOI();
// TODO: Handle PIC too
return;
}
// TODO: PIC
}
if (likely(apic[Core]))
{
((APIC::APIC *)Interrupts::apic[Core])->EOI();
// TODO: Handle PIC too
return;
}
// TODO: PIC
}
#elif defined(a32)
void *Frame = Data;
void *Frame = Data;
#elif defined(aa64)
CPU::aarch64::TrapFrame *Frame = (CPU::aarch64::TrapFrame *)Data;
CPU::aarch64::TrapFrame *Frame = (CPU::aarch64::TrapFrame *)Data;
#endif
error("HALT HALT HALT HALT HALT HALT HALT HALT HALT");
CPU::Stop();
}
error("HALT HALT HALT HALT HALT HALT HALT HALT HALT");
CPU::Stop();
}
Handler::Handler(int InterruptNumber)
{
foreach (auto ev in RegisteredEvents)
{
if (ev.ID == InterruptNumber)
{
warn("IRQ%d is already registered.", InterruptNumber);
}
}
Handler::Handler(int InterruptNumber)
{
foreach (auto ev in RegisteredEvents)
{
if (ev.ID == InterruptNumber)
{
warn("IRQ%d is already registered.", InterruptNumber);
}
}
debug("Registering interrupt handler for IRQ%d.", InterruptNumber);
this->InterruptNumber = InterruptNumber;
RegisteredEvents.push_back({InterruptNumber, this});
}
debug("Registering interrupt handler for IRQ%d.", InterruptNumber);
this->InterruptNumber = InterruptNumber;
RegisteredEvents.push_back({InterruptNumber, this});
}
Handler::~Handler()
{
debug("Unregistering interrupt handler for IRQ%d.", this->InterruptNumber);
for (size_t i = 0; i < RegisteredEvents.size(); i++)
{
if (RegisteredEvents[i].ID == this->InterruptNumber)
{
RegisteredEvents.remove(i);
return;
}
}
warn("Event %d not found.", this->InterruptNumber);
}
Handler::~Handler()
{
debug("Unregistering interrupt handler for IRQ%d.", this->InterruptNumber);
forItr(itr, RegisteredEvents)
{
if (itr->ID == this->InterruptNumber)
{
RegisteredEvents.erase(itr);
return;
}
}
warn("Event %d not found.", this->InterruptNumber);
}
#if defined(a64)
void Handler::OnInterruptReceived(CPU::x64::TrapFrame *Frame)
{
trace("Unhandled interrupt IRQ%d", Frame->InterruptNumber - 32);
void Handler::OnInterruptReceived(CPU::x64::TrapFrame *Frame)
{
trace("Unhandled interrupt IRQ%d", Frame->InterruptNumber - 32);
#elif defined(a32)
void Handler::OnInterruptReceived(CPU::x32::TrapFrame *Frame)
{
trace("Unhandled interrupt received");
void Handler::OnInterruptReceived(CPU::x32::TrapFrame *Frame)
{
trace("Unhandled interrupt received");
#elif defined(aa64)
void Handler::OnInterruptReceived(CPU::aarch64::TrapFrame *Frame)
{
trace("Unhandled interrupt received");
void Handler::OnInterruptReceived(CPU::aarch64::TrapFrame *Frame)
{
trace("Unhandled interrupt received");
#endif
}
}
}

View File

@@ -27,52 +27,67 @@
#endif
#ifdef PRINT_BACKTRACE
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wframe-address"
void PrintStacktrace(LockClass::SpinLockData *Lock)
{
if (KernelSymbolTable)
{
struct StackFrame
{
uintptr_t BasePointer;
uintptr_t ReturnAddress;
};
if (KernelSymbolTable)
{
struct StackFrame
{
uintptr_t BasePointer;
uintptr_t ReturnAddress;
};
char DbgAttempt[1024] = "\0";
char DbgHolder[1024] = "\0";
// char DbgAttempt[1024] = "\0";
// char DbgHolder[1024] = "\0";
StackFrame *FrameAttempt = (StackFrame *)Lock->StackPointerAttempt.load();
StackFrame *FrameHolder = (StackFrame *)Lock->StackPointerHolder.load();
std::string DbgAttempt = "\0";
std::string DbgHolder = "\0";
while (Memory::Virtual().Check(FrameAttempt))
{
sprintf(DbgAttempt + strlen(DbgAttempt), "%s<-", KernelSymbolTable->GetSymbolFromAddress(FrameAttempt->ReturnAddress));
FrameAttempt = (StackFrame *)FrameAttempt->BasePointer;
}
StackFrame *FrameAttempt = (StackFrame *)Lock->StackPointerAttempt.load();
StackFrame *FrameHolder = (StackFrame *)Lock->StackPointerHolder.load();
while (Memory::Virtual().Check(FrameHolder))
{
sprintf(DbgHolder + strlen(DbgHolder), "%s<-", KernelSymbolTable->GetSymbolFromAddress(FrameHolder->ReturnAddress));
FrameHolder = (StackFrame *)FrameHolder->BasePointer;
}
while (Memory::Virtual().Check(FrameAttempt))
{
DbgAttempt.concat(KernelSymbolTable->GetSymbolFromAddress(FrameAttempt->ReturnAddress));
DbgAttempt.concat("<-");
FrameAttempt = (StackFrame *)FrameAttempt->BasePointer;
}
debug("Attempt: %s", DbgAttempt.c_str());
debug("Attempt: %s", DbgAttempt);
debug("Holder: %s", DbgHolder);
while (Memory::Virtual().Check(FrameHolder))
{
DbgHolder.concat(KernelSymbolTable->GetSymbolFromAddress(FrameHolder->ReturnAddress));
DbgHolder.concat("<-");
FrameHolder = (StackFrame *)FrameHolder->BasePointer;
}
// debug("\t\t%s<-%s<-%s<-%s<-%s<-%s<-%s<-%s<-%s<-%s",
// KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)),
// KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(1)),
// KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(2)),
// KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(3)),
// KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(4)),
// KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(5)),
// KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(6)),
// KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(7)),
// KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(8)),
// KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(9)));
}
debug("Holder: %s", DbgHolder.c_str());
// debug("\t\t%s<-%s<-%s<-%s<-%s<-%s<-%s<-%s<-%s<-%s",
// KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)),
// KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(1)),
// KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(2)),
// KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(3)),
// KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(4)),
// KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(5)),
// KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(6)),
// KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(7)),
// KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(8)),
// KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(9)));
}
}
#pragma GCC diagnostic pop
#endif
#ifdef DEBUG
#define DEADLOCK_TIMEOUT 0x100000
#define DEADLOCK_TIMEOUT_DEBUGGER 0x1000
#else
#define DEADLOCK_TIMEOUT 0x10000000
#define DEADLOCK_TIMEOUT_DEBUGGER 0x100000
#endif
bool ForceUnlock = false;
@@ -80,161 +95,168 @@ std::atomic_size_t LocksCount = 0;
size_t GetLocksCount() { return LocksCount.load(); }
void LockClass::DeadLock(SpinLockData Lock)
void LockClass::Yield()
{
if (ForceUnlock)
{
warn("Unlocking lock '%s' which it was held by '%s'...", Lock.AttemptingToGet, Lock.CurrentHolder);
this->DeadLocks = 0;
this->Unlock();
return;
}
if (CPU::Interrupts(CPU::Check) &&
TaskManager &&
!TaskManager->IsPanic())
{
TaskManager->Yield();
}
CPUData *CoreData = GetCurrentCPU();
long CCore = 0xdead;
if (CoreData != nullptr)
CCore = CoreData->ID;
CPU::Pause();
}
warn("Potential deadlock in lock '%s' held by '%s'! %ld %s in queue. Interrupts are %s. Core %ld held by %ld. (%ld times happened)",
Lock.AttemptingToGet, Lock.CurrentHolder,
Lock.Count, Lock.Count > 1 ? "locks" : "lock",
CPU::Interrupts(CPU::Check) ? "enabled" : "disabled",
CCore, Lock.Core, this->DeadLocks);
void LockClass::DeadLock(SpinLockData &Lock)
{
if (ForceUnlock)
{
warn("Unlocking lock '%s' which it was held by '%s'...",
Lock.AttemptingToGet, Lock.CurrentHolder);
this->DeadLocks = 0;
this->Unlock();
return;
}
CPUData *CoreData = GetCurrentCPU();
long CCore = 0xdead;
if (CoreData != nullptr)
CCore = CoreData->ID;
warn("Potential deadlock in lock '%s' held by '%s'! %ld %s in queue. Interrupts are %s. Core %ld held by %ld. (%ld times happened)",
Lock.AttemptingToGet, Lock.CurrentHolder,
Lock.Count, Lock.Count > 1 ? "locks" : "lock",
CPU::Interrupts(CPU::Check) ? "enabled" : "disabled",
CCore, Lock.Core, this->DeadLocks);
#ifdef PRINT_BACKTRACE
PrintStacktrace(&Lock);
PrintStacktrace(&Lock);
#endif
// TODO: Print on screen too.
// TODO: Print on screen too.
this->DeadLocks++;
this->DeadLocks++;
if (Config.UnlockDeadLock && this->DeadLocks.load() > 10)
{
warn("Unlocking lock '%s' to prevent deadlock. (this is enabled in the kernel config)", Lock.AttemptingToGet);
this->DeadLocks = 0;
this->Unlock();
}
if (Config.UnlockDeadLock && this->DeadLocks.load() > 10)
{
warn("Unlocking lock '%s' to prevent deadlock. (this is enabled in the kernel config)", Lock.AttemptingToGet);
this->DeadLocks = 0;
this->Unlock();
}
if (TaskManager && !TaskManager->IsPanic())
TaskManager->Schedule();
this->Yield();
}
int LockClass::Lock(const char *FunctionName)
{
LockData.AttemptingToGet = FunctionName;
LockData.StackPointerAttempt = (uintptr_t)__builtin_frame_address(0);
LockData.AttemptingToGet = FunctionName;
LockData.StackPointerAttempt = (uintptr_t)__builtin_frame_address(0);
Retry:
int i = 0;
while (IsLocked.exchange(true, std::memory_order_acquire) && ++i < (DebuggerIsAttached ? 0x100000 : 0x10000000))
{
/* FIXME */
// if (TaskManager && !TaskManager->IsPanic())
// TaskManager->Schedule();
// else
CPU::Pause();
}
int i = 0;
while (IsLocked.exchange(true, std::memory_order_acquire) &&
++i < (DebuggerIsAttached ? DEADLOCK_TIMEOUT_DEBUGGER : DEADLOCK_TIMEOUT))
{
this->Yield();
}
if (i >= (DebuggerIsAttached ? 0x100000 : 0x10000000))
{
DeadLock(LockData);
goto Retry;
}
if (i >= (DebuggerIsAttached ? DEADLOCK_TIMEOUT_DEBUGGER : DEADLOCK_TIMEOUT))
{
DeadLock(LockData);
goto Retry;
}
LockData.Count++;
LockData.CurrentHolder = FunctionName;
LockData.StackPointerHolder = (uintptr_t)__builtin_frame_address(0);
LockData.Count++;
LockData.CurrentHolder = FunctionName;
LockData.StackPointerHolder = (uintptr_t)__builtin_frame_address(0);
CPUData *CoreData = GetCurrentCPU();
if (CoreData != nullptr)
LockData.Core = CoreData->ID;
CPUData *CoreData = GetCurrentCPU();
if (CoreData != nullptr)
LockData.Core = CoreData->ID;
LocksCount++;
LocksCount++;
__sync;
return 0;
__sync;
return 0;
}
int LockClass::Unlock()
{
__sync;
__sync;
IsLocked.store(false, std::memory_order_release);
LockData.Count--;
LocksCount--;
IsLocked.store(false, std::memory_order_release);
LockData.Count--;
LocksCount--;
return 0;
return 0;
}
void LockClass::TimeoutDeadLock(SpinLockData Lock, uint64_t Timeout)
void LockClass::TimeoutDeadLock(SpinLockData &Lock, uint64_t Timeout)
{
CPUData *CoreData = GetCurrentCPU();
long CCore = 0xdead;
CPUData *CoreData = GetCurrentCPU();
long CCore = 0xdead;
if (CoreData != nullptr)
CCore = CoreData->ID;
if (CoreData != nullptr)
CCore = CoreData->ID;
uint64_t Counter = TimeManager->GetCounter();
uint64_t Counter = TimeManager->GetCounter();
warn("Potential deadlock in lock '%s' held by '%s'! %ld %s in queue. Interrupts are %s. Core %ld held by %ld. Timeout in %ld (%ld ticks remaining).",
Lock.AttemptingToGet, Lock.CurrentHolder,
Lock.Count, Lock.Count > 1 ? "locks" : "lock",
CPU::Interrupts(CPU::Check) ? "enabled" : "disabled",
CCore, Lock.Core, Timeout, Timeout - Counter);
warn("Potential deadlock in lock '%s' held by '%s'! %ld %s in queue. Interrupts are %s. Core %ld held by %ld. Timeout in %ld (%ld ticks remaining).",
Lock.AttemptingToGet, Lock.CurrentHolder,
Lock.Count, Lock.Count > 1 ? "locks" : "lock",
CPU::Interrupts(CPU::Check) ? "enabled" : "disabled",
CCore, Lock.Core, Timeout, Timeout - Counter);
#ifdef PRINT_BACKTRACE
PrintStacktrace(&Lock);
PrintStacktrace(&Lock);
#endif
if (Timeout < Counter)
{
warn("Unlocking lock '%s' because of timeout. (%ld < %ld)", Lock.AttemptingToGet, Timeout, Counter);
this->Unlock();
}
if (Timeout < Counter)
{
warn("Unlocking lock '%s' because of timeout. (%ld < %ld)",
Lock.AttemptingToGet, Timeout, Counter);
this->Unlock();
}
if (TaskManager && !TaskManager->IsPanic())
TaskManager->Schedule();
this->Yield();
}
int LockClass::TimeoutLock(const char *FunctionName, uint64_t Timeout)
{
if (!TimeManager)
return Lock(FunctionName);
if (!TimeManager)
return Lock(FunctionName);
LockData.AttemptingToGet = FunctionName;
LockData.StackPointerAttempt = (uintptr_t)__builtin_frame_address(0);
LockData.AttemptingToGet = FunctionName;
LockData.StackPointerAttempt = (uintptr_t)__builtin_frame_address(0);
std::atomic_uint64_t Target = 0;
std::atomic_uint64_t Target = 0;
Retry:
int i = 0;
while (IsLocked.exchange(true, std::memory_order_acquire) && ++i < (DebuggerIsAttached ? 0x100000 : 0x10000000))
{
/* FIXME */
// if (TaskManager && !TaskManager->IsPanic())
// TaskManager->Schedule();
// else
CPU::Pause();
}
int i = 0;
while (IsLocked.exchange(true, std::memory_order_acquire) &&
++i < (DebuggerIsAttached ? DEADLOCK_TIMEOUT_DEBUGGER : DEADLOCK_TIMEOUT))
{
this->Yield();
}
if (i >= (DebuggerIsAttached ? 0x100000 : 0x10000000))
{
if (Target.load() == 0)
Target.store(TimeManager->CalculateTarget(Timeout, Time::Units::Milliseconds));
TimeoutDeadLock(LockData, Target.load());
goto Retry;
}
if (i >= (DebuggerIsAttached ? DEADLOCK_TIMEOUT_DEBUGGER : DEADLOCK_TIMEOUT))
{
if (Target.load() == 0)
Target.store(TimeManager->CalculateTarget(Timeout,
Time::Units::Milliseconds));
TimeoutDeadLock(LockData, Target.load());
goto Retry;
}
LockData.Count++;
LockData.CurrentHolder = FunctionName;
LockData.StackPointerHolder = (uintptr_t)__builtin_frame_address(0);
LockData.Count++;
LockData.CurrentHolder = FunctionName;
LockData.StackPointerHolder = (uintptr_t)__builtin_frame_address(0);
CPUData *CoreData = GetCurrentCPU();
if (CoreData != nullptr)
LockData.Core = CoreData->ID;
CPUData *CoreData = GetCurrentCPU();
if (CoreData != nullptr)
LockData.Core = CoreData->ID;
LocksCount++;
LocksCount++;
__sync;
return 0;
__sync;
return 0;
}

View File

@@ -22,7 +22,7 @@ Xalloc_def;
#define XALLOC_CONCAT(x, y) x##y
#define XStoP(d) (((d) + PAGE_SIZE - 1) / PAGE_SIZE)
#define XPtoS(d) ((d)*PAGE_SIZE)
#define Xalloc_BlockChecksum 0xA110C
#define Xalloc_BlockSanityKey 0xA110C
extern "C" void *Xalloc_REQUEST_PAGES(Xsize_t Pages);
extern "C" void Xalloc_FREE_PAGES(void *Address, Xsize_t Pages);
@@ -55,7 +55,7 @@ namespace Xalloc
public:
void *Address = nullptr;
int Checksum = Xalloc_BlockChecksum;
int Sanity = Xalloc_BlockSanityKey;
Xsize_t Size = 0;
Block *Next = nullptr;
Block *Last = nullptr;
@@ -63,7 +63,7 @@ namespace Xalloc
bool Check()
{
if (this->Checksum != Xalloc_BlockChecksum)
if (this->Sanity != Xalloc_BlockSanityKey)
return false;
return true;
}
@@ -168,8 +168,8 @@ namespace Xalloc
{
if (!CurrentBlock->Check())
{
Xalloc_err("Block %#lx has an invalid checksum! (%#x != %#x)",
(Xuint64_t)CurrentBlock, CurrentBlock->Checksum, Xalloc_BlockChecksum);
Xalloc_err("Block %#lx has an invalid sanity key! (%#x != %#x)",
(Xuint64_t)CurrentBlock, CurrentBlock->Sanity, Xalloc_BlockSanityKey);
while (Xalloc_StopOnFail)
;
}
@@ -210,8 +210,8 @@ namespace Xalloc
{
if (!CurrentBlock->Check())
{
Xalloc_err("Block %#lx has an invalid checksum! (%#x != %#x)",
(Xuint64_t)CurrentBlock, CurrentBlock->Checksum, Xalloc_BlockChecksum);
Xalloc_err("Block %#lx has an invalid sanity key! (%#x != %#x)",
(Xuint64_t)CurrentBlock, CurrentBlock->Sanity, Xalloc_BlockSanityKey);
while (Xalloc_StopOnFail)
;
}

File diff suppressed because it is too large Load Diff

View File

@@ -22,250 +22,266 @@
namespace Memory
{
ReadFSFunction(MEM_Read)
{
if (!Size)
Size = node->Length;
ReadFSFunction(MEM_Read)
{
if (!Size)
Size = node->Length;
if ((size_t)node->Offset > node->Length)
return 0;
if (RefOffset > node->Length)
return 0;
if (node->Offset + Size > node->Length)
Size = node->Length - node->Offset;
if (RefOffset + (off_t)Size > node->Length)
Size = node->Length - RefOffset;
memcpy(Buffer, (uint8_t *)(node->Address + node->Offset), Size);
return Size;
}
memcpy(Buffer, (uint8_t *)(node->Address + RefOffset), Size);
return Size;
}
WriteFSFunction(MEM_Write)
{
if (!Size)
Size = node->Length;
WriteFSFunction(MEM_Write)
{
if (!Size)
Size = node->Length;
if ((size_t)node->Offset > node->Length)
return 0;
if (RefOffset > node->Length)
return 0;
if (node->Offset + Size > node->Length)
Size = node->Length - node->Offset;
if (RefOffset + (off_t)Size > node->Length)
Size = node->Length - RefOffset;
memcpy((uint8_t *)(node->Address + node->Offset), Buffer, Size);
return Size;
}
memcpy((uint8_t *)(node->Address + RefOffset), Buffer, Size);
return Size;
}
VirtualFileSystem::FileSystemOperations mem_op = {
.Name = "mem",
.Read = MEM_Read,
.Write = MEM_Write,
};
VirtualFileSystem::FileSystemOperations mem_op = {
.Name = "mem",
.Read = MEM_Read,
.Write = MEM_Write,
};
uint64_t MemMgr::GetAllocatedMemorySize()
{
SmartLock(MgrLock);
uint64_t Size = 0;
foreach (auto ap in AllocatedPagesList)
Size += ap.PageCount;
return FROM_PAGES(Size);
}
uint64_t MemMgr::GetAllocatedMemorySize()
{
SmartLock(MgrLock);
uint64_t Size = 0;
foreach (auto ap in AllocatedPagesList)
Size += ap.PageCount;
return FROM_PAGES(Size);
}
bool MemMgr::Add(void *Address, size_t Count)
{
SmartLock(MgrLock);
if (Address == nullptr)
{
error("Address is null!");
return false;
}
bool MemMgr::Add(void *Address, size_t Count)
{
SmartLock(MgrLock);
if (Address == nullptr)
{
error("Address is null!");
return false;
}
if (Count == 0)
{
error("Count is 0!");
return false;
}
if (Count == 0)
{
error("Count is 0!");
return false;
}
for (size_t i = 0; i < AllocatedPagesList.size(); i++)
{
if (AllocatedPagesList[i].Address == Address)
{
error("Address already exists!");
return false;
}
else if ((uintptr_t)Address < (uintptr_t)AllocatedPagesList[i].Address)
{
if ((uintptr_t)Address + (Count * PAGE_SIZE) > (uintptr_t)AllocatedPagesList[i].Address)
{
error("Address intersects with an allocated page!");
return false;
}
}
else
{
if ((uintptr_t)AllocatedPagesList[i].Address + (AllocatedPagesList[i].PageCount * PAGE_SIZE) > (uintptr_t)Address)
{
error("Address intersects with an allocated page!");
return false;
}
}
}
for (size_t i = 0; i < AllocatedPagesList.size(); i++)
{
if (AllocatedPagesList[i].Address == Address)
{
error("Address already exists!");
return false;
}
else if ((uintptr_t)Address < (uintptr_t)AllocatedPagesList[i].Address)
{
if ((uintptr_t)Address + (Count * PAGE_SIZE) > (uintptr_t)AllocatedPagesList[i].Address)
{
error("Address intersects with an allocated page!");
return false;
}
}
else
{
if ((uintptr_t)AllocatedPagesList[i].Address + (AllocatedPagesList[i].PageCount * PAGE_SIZE) > (uintptr_t)Address)
{
error("Address intersects with an allocated page!");
return false;
}
}
}
if (this->Directory)
{
char FileName[64];
sprintf(FileName, "%lx-%ld", (uintptr_t)Address, Count);
VirtualFileSystem::Node *n = vfs->Create(FileName, VirtualFileSystem::NodeFlags::FILE, this->Directory);
if (n)
{
n->Address = (uintptr_t)Address;
n->Length = Count * PAGE_SIZE;
n->Operator = &mem_op;
}
}
AllocatedPagesList.push_back({Address, Count});
return true;
}
void *MemMgr::RequestPages(size_t Count, bool User)
{
SmartLock(MgrLock);
void *Address = KernelAllocator.RequestPages(Count);
for (size_t i = 0; i < Count; i++)
{
int Flags = Memory::PTFlag::RW;
if (User)
Flags |= Memory::PTFlag::US;
void *AddressToMap = (void *)((uintptr_t)Address + (i * PAGE_SIZE));
Memory::Virtual vmm = Memory::Virtual(this->Table);
vmm.Remap(AddressToMap, AddressToMap, Flags);
}
if (this->Directory)
{
char FileName[64];
sprintf(FileName, "%lx-%ld", (uintptr_t)Address, Count);
VirtualFileSystem::Node *n = vfs->Create(FileName, VirtualFileSystem::NodeFlags::FILE, this->Directory);
if (n) // If null, error or file already exists
{
n->Address = (uintptr_t)Address;
n->Length = Count * PAGE_SIZE;
n->Operator = &mem_op;
}
}
AllocatedPagesList.push_back({Address, Count});
/* For security reasons, we clear the allocated page
if it's a user page. */
if (User)
memset(Address, 0, Count * PAGE_SIZE);
return Address;
}
void MemMgr::FreePages(void *Address, size_t Count)
{
SmartLock(MgrLock);
for (size_t i = 0; i < AllocatedPagesList.size(); i++)
{
if (AllocatedPagesList[i].Address == Address)
{
/** TODO: Advanced checks. Allow if the page count is less than the requested one.
* This will allow the user to free only a part of the allocated pages.
*
* But this will be in a separate function because we need to specify if we
* want to free from the start or from the end and return the new address.
*/
if (AllocatedPagesList[i].PageCount != Count)
{
error("Page count mismatch! (Allocated: %lld, Requested: %lld)", AllocatedPagesList[i].PageCount, Count);
return;
}
KernelAllocator.FreePages(Address, Count);
Memory::Virtual vmm = Memory::Virtual(this->Table);
for (size_t i = 0; i < Count; i++)
{
void *AddressToMap = (void *)((uintptr_t)Address + (i * PAGE_SIZE));
vmm.Remap(AddressToMap, AddressToMap, Memory::PTFlag::RW);
// vmm.Unmap((void *)((uintptr_t)Address + (i * PAGE_SIZE)));
}
if (this->Directory)
{
char FileName[64];
sprintf(FileName, "%lx-%ld", (uintptr_t)Address, Count);
VirtualFileSystem::FileStatus s = vfs->Delete(FileName, false, this->Directory);
if (s != VirtualFileSystem::FileStatus::OK)
error("Failed to delete file %s", FileName);
}
AllocatedPagesList.remove(i);
return;
}
}
}
void MemMgr::DetachAddress(void *Address)
{
SmartLock(MgrLock);
for (size_t i = 0; i < AllocatedPagesList.size(); i++)
{
if (AllocatedPagesList[i].Address == Address)
{
if (this->Directory)
{
char FileName[64];
sprintf(FileName, "%lx-%ld", (uintptr_t)Address, AllocatedPagesList[i].PageCount);
VirtualFileSystem::FileStatus s = vfs->Delete(FileName, false, this->Directory);
if (s != VirtualFileSystem::FileStatus::OK)
error("Failed to delete file %s", FileName);
}
AllocatedPagesList.remove(i);
return;
}
}
}
MemMgr::MemMgr(PageTable *Table, VirtualFileSystem::Node *Directory)
{
SmartLock(MgrLock);
if (Table)
this->Table = Table;
else
{
#if defined(a64)
this->Table = (PageTable *)CPU::x64::readcr3().raw;
if (this->Directory)
{
char FileName[64];
#if defined(a64) || defined(aa64)
sprintf(FileName, "%lx-%ld", (uintptr_t)Address, Count);
#elif defined(a32)
this->Table = (PageTable *)CPU::x32::readcr3().raw;
sprintf(FileName, "%x-%ld", (uintptr_t)Address, Count);
#endif
}
VirtualFileSystem::Node *n = vfs->Create(FileName, VirtualFileSystem::NodeFlags::FILE, this->Directory);
if (n)
{
n->Address = (uintptr_t)Address;
n->Length = Count * PAGE_SIZE;
n->Operator = &mem_op;
}
}
this->Directory = Directory;
debug("+ %#lx", this);
}
AllocatedPagesList.push_back({Address, Count});
return true;
}
MemMgr::~MemMgr()
{
SmartLock(MgrLock);
foreach (auto ap in AllocatedPagesList)
{
KernelAllocator.FreePages(ap.Address, ap.PageCount);
Memory::Virtual vmm = Memory::Virtual(this->Table);
for (size_t i = 0; i < ap.PageCount; i++)
vmm.Remap((void *)((uintptr_t)ap.Address + (i * PAGE_SIZE)),
(void *)((uintptr_t)ap.Address + (i * PAGE_SIZE)),
Memory::PTFlag::RW);
}
void *MemMgr::RequestPages(size_t Count, bool User)
{
SmartLock(MgrLock);
void *Address = KernelAllocator.RequestPages(Count);
for (size_t i = 0; i < Count; i++)
{
int Flags = Memory::PTFlag::RW;
if (User)
Flags |= Memory::PTFlag::US;
if (this->Directory)
{
foreach (auto Child in this->Directory->Children)
vfs->Delete(Child, true);
}
void *AddressToMap = (void *)((uintptr_t)Address + (i * PAGE_SIZE));
debug("- %#lx", this);
}
Memory::Virtual vmm = Memory::Virtual(this->Table);
vmm.Remap(AddressToMap, AddressToMap, Flags);
}
if (this->Directory)
{
char FileName[64];
#if defined(a64) || defined(aa64)
sprintf(FileName, "%lx-%ld", (uintptr_t)Address, Count);
#elif defined(a32)
sprintf(FileName, "%x-%ld", (uintptr_t)Address, Count);
#endif
VirtualFileSystem::Node *n = vfs->Create(FileName, VirtualFileSystem::NodeFlags::FILE, this->Directory);
if (n) // If null, error or file already exists
{
n->Address = (uintptr_t)Address;
n->Length = Count * PAGE_SIZE;
n->Operator = &mem_op;
}
}
AllocatedPagesList.push_back({Address, Count});
/* For security reasons, we clear the allocated page
if it's a user page. */
if (User)
memset(Address, 0, Count * PAGE_SIZE);
return Address;
}
void MemMgr::FreePages(void *Address, size_t Count)
{
SmartLock(MgrLock);
forItr(itr, AllocatedPagesList)
{
if (itr->Address == Address)
{
/** TODO: Advanced checks. Allow if the page count is less than the requested one.
* This will allow the user to free only a part of the allocated pages.
*
* But this will be in a separate function because we need to specify if we
* want to free from the start or from the end and return the new address.
*/
if (itr->PageCount != Count)
{
error("Page count mismatch! (Allocated: %lld, Requested: %lld)", itr->PageCount, Count);
return;
}
KernelAllocator.FreePages(Address, Count);
Memory::Virtual vmm = Memory::Virtual(this->Table);
for (size_t i = 0; i < Count; i++)
{
void *AddressToMap = (void *)((uintptr_t)Address + (i * PAGE_SIZE));
vmm.Remap(AddressToMap, AddressToMap, Memory::PTFlag::RW);
// vmm.Unmap((void *)((uintptr_t)Address + (i * PAGE_SIZE)));
}
if (this->Directory)
{
char FileName[64];
#if defined(a64) || defined(aa64)
sprintf(FileName, "%lx-%ld", (uintptr_t)Address, Count);
#elif defined(a32)
sprintf(FileName, "%x-%ld", (uintptr_t)Address, Count);
#endif
if (!vfs->Delete(FileName, false, this->Directory))
error("Failed to delete file %s", FileName);
}
AllocatedPagesList.erase(itr);
return;
}
}
}
void MemMgr::DetachAddress(void *Address)
{
SmartLock(MgrLock);
forItr(itr, AllocatedPagesList)
{
if (itr->Address == Address)
{
if (this->Directory)
{
char FileName[64];
#if defined(a64) || defined(aa64)
sprintf(FileName, "%lx-%ld", (uintptr_t)Address, itr->PageCount);
#elif defined(a32)
sprintf(FileName, "%x-%ld", (uintptr_t)Address, itr->PageCount);
#endif
if (!vfs->Delete(FileName, false, this->Directory))
error("Failed to delete file %s", FileName);
}
AllocatedPagesList.erase(itr);
return;
}
}
}
MemMgr::MemMgr(PageTable *Table, VirtualFileSystem::Node *Directory)
{
SmartLock(MgrLock);
if (Table)
this->Table = Table;
else
{
#if defined(a64)
this->Table = (PageTable *)CPU::x64::readcr3().raw;
#elif defined(a32)
this->Table = (PageTable *)CPU::x32::readcr3().raw;
#endif
}
this->Directory = Directory;
debug("+ %#lx %s", this,
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "");
}
MemMgr::~MemMgr()
{
SmartLock(MgrLock);
foreach (auto ap in AllocatedPagesList)
{
KernelAllocator.FreePages(ap.Address, ap.PageCount);
Memory::Virtual vmm = Memory::Virtual(this->Table);
for (size_t i = 0; i < ap.PageCount; i++)
vmm.Remap((void *)((uintptr_t)ap.Address + (i * PAGE_SIZE)),
(void *)((uintptr_t)ap.Address + (i * PAGE_SIZE)),
Memory::PTFlag::RW);
}
if (this->Directory)
{
foreach (auto Child in this->Directory->Children)
vfs->Delete(Child, true);
}
debug("- %#lx %s", this,
KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "");
}
}

View File

@@ -26,467 +26,477 @@
namespace Memory
{
uint64_t Physical::GetTotalMemory()
{
SmartLock(this->MemoryLock);
return this->TotalMemory;
}
uint64_t Physical::GetTotalMemory()
{
return this->TotalMemory.load();
}
uint64_t Physical::GetFreeMemory()
{
SmartLock(this->MemoryLock);
return this->FreeMemory;
}
uint64_t Physical::GetFreeMemory()
{
return this->FreeMemory.load();
}
uint64_t Physical::GetReservedMemory()
{
SmartLock(this->MemoryLock);
return this->ReservedMemory;
}
uint64_t Physical::GetReservedMemory()
{
return this->ReservedMemory.load();
}
uint64_t Physical::GetUsedMemory()
{
SmartLock(this->MemoryLock);
return this->UsedMemory;
}
uint64_t Physical::GetUsedMemory()
{
return this->UsedMemory.load();
}
bool Physical::SwapPage(void *Address)
{
fixme("%p", Address);
return false;
}
bool Physical::SwapPage(void *Address)
{
fixme("%p", Address);
return false;
}
bool Physical::SwapPages(void *Address, size_t PageCount)
{
for (size_t i = 0; i < PageCount; i++)
{
if (!this->SwapPage((void *)((uintptr_t)Address + (i * PAGE_SIZE))))
return false;
}
return false;
}
bool Physical::SwapPages(void *Address, size_t PageCount)
{
for (size_t i = 0; i < PageCount; i++)
{
if (!this->SwapPage((void *)((uintptr_t)Address + (i * PAGE_SIZE))))
return false;
}
return false;
}
bool Physical::UnswapPage(void *Address)
{
fixme("%p", Address);
return false;
}
bool Physical::UnswapPage(void *Address)
{
fixme("%p", Address);
return false;
}
bool Physical::UnswapPages(void *Address, size_t PageCount)
{
for (size_t i = 0; i < PageCount; i++)
{
if (!this->UnswapPage((void *)((uintptr_t)Address + (i * PAGE_SIZE))))
return false;
}
return false;
}
bool Physical::UnswapPages(void *Address, size_t PageCount)
{
for (size_t i = 0; i < PageCount; i++)
{
if (!this->UnswapPage((void *)((uintptr_t)Address + (i * PAGE_SIZE))))
return false;
}
return false;
}
void *Physical::RequestPage()
{
SmartLock(this->MemoryLock);
void *Physical::RequestPage()
{
SmartLock(this->MemoryLock);
for (; PageBitmapIndex < PageBitmap.Size * 8; PageBitmapIndex++)
{
if (PageBitmap[PageBitmapIndex] == true)
continue;
for (; PageBitmapIndex < PageBitmap.Size * 8; PageBitmapIndex++)
{
if (PageBitmap[PageBitmapIndex] == true)
continue;
this->LockPage((void *)(PageBitmapIndex * PAGE_SIZE));
this->LockPage((void *)(PageBitmapIndex * PAGE_SIZE));
#ifdef DEBUG
if (EnableExternalMemoryTracer)
{
char LockTmpStr[64];
strcpy_unsafe(LockTmpStr, __FUNCTION__);
strcat_unsafe(LockTmpStr, "_memTrk");
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
sprintf(mExtTrkLog, "RequestPage( )=%p~%p\n\r",
(void *)(PageBitmapIndex * PAGE_SIZE), __builtin_return_address(0));
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
{
if (mExtTrkLog[i] == '\r')
break;
mTrkUART.Write(mExtTrkLog[i]);
}
mExtTrkLock.Unlock();
}
if (EnableExternalMemoryTracer)
{
char LockTmpStr[64];
strcpy_unsafe(LockTmpStr, __FUNCTION__);
strcat_unsafe(LockTmpStr, "_memTrk");
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
sprintf(mExtTrkLog, "RequestPage( )=%p~%p\n\r",
(void *)(PageBitmapIndex * PAGE_SIZE), __builtin_return_address(0));
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
{
if (mExtTrkLog[i] == '\r')
break;
mTrkUART.Write(mExtTrkLog[i]);
}
mExtTrkLock.Unlock();
}
#endif
return (void *)(PageBitmapIndex * PAGE_SIZE);
}
return (void *)(PageBitmapIndex * PAGE_SIZE);
}
if (this->SwapPage((void *)(PageBitmapIndex * PAGE_SIZE)))
{
this->LockPage((void *)(PageBitmapIndex * PAGE_SIZE));
return (void *)(PageBitmapIndex * PAGE_SIZE);
}
if (this->SwapPage((void *)(PageBitmapIndex * PAGE_SIZE)))
{
this->LockPage((void *)(PageBitmapIndex * PAGE_SIZE));
return (void *)(PageBitmapIndex * PAGE_SIZE);
}
if (TaskManager && !TaskManager->IsPanic())
{
error("Out of memory! Killing current process...");
TaskManager->KillProcess(TaskManager->GetCurrentProcess(), Tasking::KILL_OOM);
TaskManager->Schedule();
}
if (TaskManager && !TaskManager->IsPanic())
{
error("Out of memory! Killing current process...");
TaskManager->KillProcess(thisProcess, Tasking::KILL_OOM);
TaskManager->Yield();
}
error("Out of memory! (Free: %ldMB; Used: %ldMB; Reserved: %ldMB)", TO_MB(FreeMemory), TO_MB(UsedMemory), TO_MB(ReservedMemory));
CPU::Stop();
__builtin_unreachable();
}
error("Out of memory! (Free: %ld MiB; Used: %ld MiB; Reserved: %ld MiB)",
TO_MiB(FreeMemory), TO_MiB(UsedMemory), TO_MiB(ReservedMemory));
KPrint("Out of memory! (Free: %ld MiB; Used: %ld MiB; Reserved: %ld MiB)",
TO_MiB(FreeMemory), TO_MiB(UsedMemory), TO_MiB(ReservedMemory));
CPU::Stop();
__builtin_unreachable();
}
void *Physical::RequestPages(size_t Count)
{
SmartLock(this->MemoryLock);
void *Physical::RequestPages(size_t Count)
{
SmartLock(this->MemoryLock);
for (; PageBitmapIndex < PageBitmap.Size * 8; PageBitmapIndex++)
{
if (PageBitmap[PageBitmapIndex] == true)
continue;
for (; PageBitmapIndex < PageBitmap.Size * 8; PageBitmapIndex++)
{
if (PageBitmap[PageBitmapIndex] == true)
continue;
for (uint64_t Index = PageBitmapIndex; Index < PageBitmap.Size * 8; Index++)
{
if (PageBitmap[Index] == true)
continue;
for (uint64_t Index = PageBitmapIndex; Index < PageBitmap.Size * 8; Index++)
{
if (PageBitmap[Index] == true)
continue;
for (size_t i = 0; i < Count; i++)
{
if (PageBitmap[Index + i] == true)
goto NextPage;
}
for (size_t i = 0; i < Count; i++)
{
if (PageBitmap[Index + i] == true)
goto NextPage;
}
this->LockPages((void *)(Index * PAGE_SIZE), Count);
this->LockPages((void *)(Index * PAGE_SIZE), Count);
#ifdef DEBUG
if (EnableExternalMemoryTracer)
{
char LockTmpStr[64];
strcpy_unsafe(LockTmpStr, __FUNCTION__);
strcat_unsafe(LockTmpStr, "_memTrk");
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
sprintf(mExtTrkLog, "RequestPages( %ld )=%p~%p\n\r",
Count,
(void *)(Index * PAGE_SIZE), __builtin_return_address(0));
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
{
if (mExtTrkLog[i] == '\r')
break;
mTrkUART.Write(mExtTrkLog[i]);
}
mExtTrkLock.Unlock();
}
if (EnableExternalMemoryTracer)
{
char LockTmpStr[64];
strcpy_unsafe(LockTmpStr, __FUNCTION__);
strcat_unsafe(LockTmpStr, "_memTrk");
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
sprintf(mExtTrkLog, "RequestPages( %ld )=%p~%p\n\r",
Count,
(void *)(Index * PAGE_SIZE), __builtin_return_address(0));
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
{
if (mExtTrkLog[i] == '\r')
break;
mTrkUART.Write(mExtTrkLog[i]);
}
mExtTrkLock.Unlock();
}
#endif
return (void *)(Index * PAGE_SIZE);
return (void *)(Index * PAGE_SIZE);
NextPage:
Index += Count;
continue;
}
}
NextPage:
Index += Count;
continue;
}
}
if (this->SwapPages((void *)(PageBitmapIndex * PAGE_SIZE), Count))
{
this->LockPages((void *)(PageBitmapIndex * PAGE_SIZE), Count);
return (void *)(PageBitmapIndex * PAGE_SIZE);
}
if (this->SwapPages((void *)(PageBitmapIndex * PAGE_SIZE), Count))
{
this->LockPages((void *)(PageBitmapIndex * PAGE_SIZE), Count);
return (void *)(PageBitmapIndex * PAGE_SIZE);
}
if (TaskManager && !TaskManager->IsPanic())
{
error("Out of memory! Killing current process...");
TaskManager->KillProcess(TaskManager->GetCurrentProcess(), Tasking::KILL_OOM);
TaskManager->Schedule();
}
if (TaskManager && !TaskManager->IsPanic())
{
error("Out of memory! Killing current process...");
TaskManager->KillProcess(thisProcess, Tasking::KILL_OOM);
TaskManager->Yield();
}
error("Out of memory! (Free: %ldMB; Used: %ldMB; Reserved: %ldMB)", TO_MB(FreeMemory), TO_MB(UsedMemory), TO_MB(ReservedMemory));
CPU::Halt(true);
__builtin_unreachable();
}
error("Out of memory! (Free: %ld MiB; Used: %ld MiB; Reserved: %ld MiB)",
TO_MiB(FreeMemory), TO_MiB(UsedMemory), TO_MiB(ReservedMemory));
KPrint("Out of memory! (Free: %ld MiB; Used: %ld MiB; Reserved: %ld MiB)",
TO_MiB(FreeMemory), TO_MiB(UsedMemory), TO_MiB(ReservedMemory));
CPU::Halt(true);
__builtin_unreachable();
}
void Physical::FreePage(void *Address)
{
SmartLock(this->MemoryLock);
void Physical::FreePage(void *Address)
{
SmartLock(this->MemoryLock);
if (unlikely(Address == nullptr))
{
warn("Null pointer passed to FreePage.");
return;
}
if (unlikely(Address == nullptr))
{
warn("Null pointer passed to FreePage.");
return;
}
size_t Index = (size_t)Address / PAGE_SIZE;
size_t Index = (size_t)Address / PAGE_SIZE;
if (unlikely(PageBitmap[Index] == false))
{
warn("Tried to free an already free page. (%p)", Address);
return;
}
if (unlikely(PageBitmap[Index] == false))
{
warn("Tried to free an already free page. (%p)",
Address);
return;
}
if (PageBitmap.Set(Index, false))
{
FreeMemory += PAGE_SIZE;
UsedMemory -= PAGE_SIZE;
if (PageBitmapIndex > Index)
PageBitmapIndex = Index;
}
if (PageBitmap.Set(Index, false))
{
FreeMemory += PAGE_SIZE;
UsedMemory -= PAGE_SIZE;
if (PageBitmapIndex > Index)
PageBitmapIndex = Index;
}
#ifdef DEBUG
if (EnableExternalMemoryTracer)
{
char LockTmpStr[64];
strcpy_unsafe(LockTmpStr, __FUNCTION__);
strcat_unsafe(LockTmpStr, "_memTrk");
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
sprintf(mExtTrkLog, "FreePage( %p )~%p\n\r",
Address,
__builtin_return_address(0));
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
{
if (mExtTrkLog[i] == '\r')
break;
mTrkUART.Write(mExtTrkLog[i]);
}
mExtTrkLock.Unlock();
}
if (EnableExternalMemoryTracer)
{
char LockTmpStr[64];
strcpy_unsafe(LockTmpStr, __FUNCTION__);
strcat_unsafe(LockTmpStr, "_memTrk");
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
sprintf(mExtTrkLog, "FreePage( %p )~%p\n\r",
Address,
__builtin_return_address(0));
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
{
if (mExtTrkLog[i] == '\r')
break;
mTrkUART.Write(mExtTrkLog[i]);
}
mExtTrkLock.Unlock();
}
#endif
}
}
void Physical::FreePages(void *Address, size_t Count)
{
if (unlikely(Address == nullptr || Count == 0))
{
warn("%s%s%s passed to FreePages.", Address == nullptr ? "Null pointer " : "", Address == nullptr && Count == 0 ? "and " : "", Count == 0 ? "Zero count" : "");
return;
}
void Physical::FreePages(void *Address, size_t Count)
{
if (unlikely(Address == nullptr || Count == 0))
{
warn("%s%s%s passed to FreePages.", Address == nullptr ? "Null pointer " : "", Address == nullptr && Count == 0 ? "and " : "", Count == 0 ? "Zero count" : "");
return;
}
#ifdef DEBUG
if (EnableExternalMemoryTracer)
{
char LockTmpStr[64];
strcpy_unsafe(LockTmpStr, __FUNCTION__);
strcat_unsafe(LockTmpStr, "_memTrk");
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
sprintf(mExtTrkLog, "!FreePages( %p %ld )~%p\n\r",
Address, Count,
__builtin_return_address(0));
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
{
if (mExtTrkLog[i] == '\r')
break;
mTrkUART.Write(mExtTrkLog[i]);
}
mExtTrkLock.Unlock();
}
if (EnableExternalMemoryTracer)
{
char LockTmpStr[64];
strcpy_unsafe(LockTmpStr, __FUNCTION__);
strcat_unsafe(LockTmpStr, "_memTrk");
mExtTrkLock.TimeoutLock(LockTmpStr, 10000);
sprintf(mExtTrkLog, "!FreePages( %p %ld )~%p\n\r",
Address, Count,
__builtin_return_address(0));
UniversalAsynchronousReceiverTransmitter::UART mTrkUART = UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM3);
for (short i = 0; i < MEM_TRK_MAX_SIZE; i++)
{
if (mExtTrkLog[i] == '\r')
break;
mTrkUART.Write(mExtTrkLog[i]);
}
mExtTrkLock.Unlock();
}
#endif
for (size_t t = 0; t < Count; t++)
this->FreePage((void *)((uintptr_t)Address + (t * PAGE_SIZE)));
}
for (size_t t = 0; t < Count; t++)
this->FreePage((void *)((uintptr_t)Address + (t * PAGE_SIZE)));
}
void Physical::LockPage(void *Address)
{
if (unlikely(Address == nullptr))
warn("Trying to lock null address.");
void Physical::LockPage(void *Address)
{
if (unlikely(Address == nullptr))
warn("Trying to lock null address.");
uintptr_t Index = (uintptr_t)Address / PAGE_SIZE;
uintptr_t Index = (uintptr_t)Address / PAGE_SIZE;
if (unlikely(PageBitmap[Index] == true))
return;
if (unlikely(PageBitmap[Index] == true))
return;
if (PageBitmap.Set(Index, true))
{
FreeMemory -= PAGE_SIZE;
UsedMemory += PAGE_SIZE;
}
}
if (PageBitmap.Set(Index, true))
{
FreeMemory -= PAGE_SIZE;
UsedMemory += PAGE_SIZE;
}
}
void Physical::LockPages(void *Address, size_t PageCount)
{
if (unlikely(Address == nullptr || PageCount == 0))
warn("Trying to lock %s%s.", Address ? "null address" : "", PageCount ? "0 pages" : "");
void Physical::LockPages(void *Address, size_t PageCount)
{
if (unlikely(Address == nullptr || PageCount == 0))
warn("Trying to lock %s%s.",
Address ? "null address" : "",
PageCount ? "0 pages" : "");
for (size_t i = 0; i < PageCount; i++)
this->LockPage((void *)((uintptr_t)Address + (i * PAGE_SIZE)));
}
for (size_t i = 0; i < PageCount; i++)
this->LockPage((void *)((uintptr_t)Address + (i * PAGE_SIZE)));
}
void Physical::ReservePage(void *Address)
{
if (unlikely(Address == nullptr))
warn("Trying to reserve null address.");
void Physical::ReservePage(void *Address)
{
if (unlikely(Address == nullptr))
warn("Trying to reserve null address.");
uintptr_t Index = (Address == NULL) ? 0 : (uintptr_t)Address / PAGE_SIZE;
uintptr_t Index = (Address == NULL) ? 0 : (uintptr_t)Address / PAGE_SIZE;
if (unlikely(PageBitmap[Index] == true))
return;
if (unlikely(PageBitmap[Index] == true))
return;
if (PageBitmap.Set(Index, true))
{
FreeMemory -= PAGE_SIZE;
ReservedMemory += PAGE_SIZE;
}
}
if (PageBitmap.Set(Index, true))
{
FreeMemory -= PAGE_SIZE;
ReservedMemory += PAGE_SIZE;
}
}
void Physical::ReservePages(void *Address, size_t PageCount)
{
if (unlikely(Address == nullptr || PageCount == 0))
warn("Trying to reserve %s%s.", Address ? "null address" : "", PageCount ? "0 pages" : "");
void Physical::ReservePages(void *Address, size_t PageCount)
{
if (unlikely(Address == nullptr || PageCount == 0))
warn("Trying to reserve %s%s.",
Address ? "null address" : "",
PageCount ? "0 pages" : "");
for (size_t t = 0; t < PageCount; t++)
{
uintptr_t Index = ((uintptr_t)Address + (t * PAGE_SIZE)) / PAGE_SIZE;
for (size_t t = 0; t < PageCount; t++)
{
uintptr_t Index = ((uintptr_t)Address + (t * PAGE_SIZE)) / PAGE_SIZE;
if (unlikely(PageBitmap[Index] == true))
return;
if (unlikely(PageBitmap[Index] == true))
return;
if (PageBitmap.Set(Index, true))
{
FreeMemory -= PAGE_SIZE;
ReservedMemory += PAGE_SIZE;
}
}
}
if (PageBitmap.Set(Index, true))
{
FreeMemory -= PAGE_SIZE;
ReservedMemory += PAGE_SIZE;
}
}
}
void Physical::UnreservePage(void *Address)
{
if (unlikely(Address == nullptr))
warn("Trying to unreserve null address.");
void Physical::UnreservePage(void *Address)
{
if (unlikely(Address == nullptr))
warn("Trying to unreserve null address.");
uintptr_t Index = (Address == NULL) ? 0 : (uintptr_t)Address / PAGE_SIZE;
uintptr_t Index = (Address == NULL) ? 0 : (uintptr_t)Address / PAGE_SIZE;
if (unlikely(PageBitmap[Index] == false))
return;
if (unlikely(PageBitmap[Index] == false))
return;
if (PageBitmap.Set(Index, false))
{
FreeMemory += PAGE_SIZE;
ReservedMemory -= PAGE_SIZE;
if (PageBitmapIndex > Index)
PageBitmapIndex = Index;
}
}
if (PageBitmap.Set(Index, false))
{
FreeMemory += PAGE_SIZE;
ReservedMemory -= PAGE_SIZE;
if (PageBitmapIndex > Index)
PageBitmapIndex = Index;
}
}
void Physical::UnreservePages(void *Address, size_t PageCount)
{
if (unlikely(Address == nullptr || PageCount == 0))
warn("Trying to unreserve %s%s.", Address ? "null address" : "", PageCount ? "0 pages" : "");
void Physical::UnreservePages(void *Address, size_t PageCount)
{
if (unlikely(Address == nullptr || PageCount == 0))
warn("Trying to unreserve %s%s.",
Address ? "null address" : "",
PageCount ? "0 pages" : "");
for (size_t t = 0; t < PageCount; t++)
{
uintptr_t Index = ((uintptr_t)Address + (t * PAGE_SIZE)) / PAGE_SIZE;
for (size_t t = 0; t < PageCount; t++)
{
uintptr_t Index = ((uintptr_t)Address + (t * PAGE_SIZE)) / PAGE_SIZE;
if (unlikely(PageBitmap[Index] == false))
return;
if (unlikely(PageBitmap[Index] == false))
return;
if (PageBitmap.Set(Index, false))
{
FreeMemory += PAGE_SIZE;
ReservedMemory -= PAGE_SIZE;
if (PageBitmapIndex > Index)
PageBitmapIndex = Index;
}
}
}
if (PageBitmap.Set(Index, false))
{
FreeMemory += PAGE_SIZE;
ReservedMemory -= PAGE_SIZE;
if (PageBitmapIndex > Index)
PageBitmapIndex = Index;
}
}
}
void Physical::Init()
{
SmartLock(this->MemoryLock);
void Physical::Init()
{
SmartLock(this->MemoryLock);
uint64_t MemorySize = bInfo.Memory.Size;
debug("Memory size: %lld bytes (%ld pages)", MemorySize, TO_PAGES(MemorySize));
TotalMemory = MemorySize;
FreeMemory = MemorySize;
uint64_t MemorySize = bInfo.Memory.Size;
debug("Memory size: %lld bytes (%ld pages)",
MemorySize, TO_PAGES(MemorySize));
TotalMemory = MemorySize;
FreeMemory = MemorySize;
size_t BitmapSize = (size_t)(MemorySize / PAGE_SIZE) / 8 + 1;
uintptr_t BitmapAddress = 0x0;
size_t BitmapAddressSize = 0;
size_t BitmapSize = (size_t)(MemorySize / PAGE_SIZE) / 8 + 1;
uintptr_t BitmapAddress = 0x0;
size_t BitmapAddressSize = 0;
uintptr_t KernelStart = (uintptr_t)bInfo.Kernel.PhysicalBase;
uintptr_t KernelEnd = (uintptr_t)bInfo.Kernel.PhysicalBase + bInfo.Kernel.Size;
uintptr_t KernelStart = (uintptr_t)bInfo.Kernel.PhysicalBase;
uintptr_t KernelEnd = (uintptr_t)bInfo.Kernel.PhysicalBase + bInfo.Kernel.Size;
for (uint64_t i = 0; i < bInfo.Memory.Entries; i++)
{
if (bInfo.Memory.Entry[i].Type == Usable)
{
uintptr_t RegionAddress = (uintptr_t)bInfo.Memory.Entry[i].BaseAddress;
uintptr_t RegionSize = bInfo.Memory.Entry[i].Length;
for (uint64_t i = 0; i < bInfo.Memory.Entries; i++)
{
if (bInfo.Memory.Entry[i].Type == Usable)
{
uintptr_t RegionAddress = (uintptr_t)bInfo.Memory.Entry[i].BaseAddress;
uintptr_t RegionSize = bInfo.Memory.Entry[i].Length;
/* We don't want to use 0 as a memory address. */
if (RegionAddress == 0x0)
continue;
/* We don't want to use the first 1MB of memory. */
if (RegionAddress <= 0xFFFFF)
continue;
if ((BitmapSize + 0x100) > RegionSize)
{
debug("Region %p-%p (%dMB) is too small for bitmap.",
(void *)RegionAddress,
(void *)(RegionAddress + RegionSize),
TO_MB(RegionSize));
continue;
}
if ((BitmapSize + 0x100) > RegionSize)
{
debug("Region %p-%p (%d MiB) is too small for bitmap.",
(void *)RegionAddress,
(void *)(RegionAddress + RegionSize),
TO_MiB(RegionSize));
continue;
}
BitmapAddress = RegionAddress;
BitmapAddressSize = RegionSize;
BitmapAddress = RegionAddress;
BitmapAddressSize = RegionSize;
if (RegionAddress >= KernelStart && KernelEnd <= (RegionAddress + RegionSize))
{
BitmapAddress = KernelEnd;
BitmapAddressSize = RegionSize - (KernelEnd - RegionAddress);
}
if (RegionAddress >= KernelStart && KernelEnd <= (RegionAddress + RegionSize))
{
BitmapAddress = KernelEnd;
BitmapAddressSize = RegionSize - (KernelEnd - RegionAddress);
}
if ((BitmapSize + 0x100) > BitmapAddressSize)
{
debug("Region %p-%p (%dMB) is too small for bitmap.",
(void *)RegionAddress,
(void *)(RegionAddress + BitmapAddressSize),
TO_MB(BitmapAddressSize));
continue;
}
if ((BitmapSize + 0x100) > BitmapAddressSize)
{
debug("Region %p-%p (%d MiB) is too small for bitmap.",
(void *)RegionAddress,
(void *)(RegionAddress + BitmapAddressSize),
TO_MiB(BitmapAddressSize));
continue;
}
for (size_t i = 0; i < MAX_MODULES; i++)
{
uintptr_t ModuleStart = (uintptr_t)bInfo.Modules[i].Address;
uintptr_t ModuleEnd = (uintptr_t)bInfo.Modules[i].Address + bInfo.Modules[i].Size;
for (size_t i = 0; i < MAX_MODULES; i++)
{
uintptr_t ModuleStart = (uintptr_t)bInfo.Modules[i].Address;
uintptr_t ModuleEnd = (uintptr_t)bInfo.Modules[i].Address + bInfo.Modules[i].Size;
if (ModuleStart == 0x0)
break;
if (ModuleStart == 0x0)
break;
if (RegionAddress >= ModuleStart && ModuleEnd <= (RegionAddress + RegionSize))
{
BitmapAddress = ModuleEnd;
BitmapAddressSize = RegionSize - (ModuleEnd - RegionAddress);
}
}
if (RegionAddress >= ModuleStart && ModuleEnd <= (RegionAddress + RegionSize))
{
BitmapAddress = ModuleEnd;
BitmapAddressSize = RegionSize - (ModuleEnd - RegionAddress);
}
}
if ((BitmapSize + 0x100) > BitmapAddressSize)
{
debug("Region %p-%p (%dMB) is too small for bitmap.",
(void *)BitmapAddress,
(void *)(BitmapAddress + BitmapAddressSize),
TO_MB(BitmapAddressSize));
continue;
}
if ((BitmapSize + 0x100) > BitmapAddressSize)
{
debug("Region %p-%p (%d MiB) is too small for bitmap.",
(void *)BitmapAddress,
(void *)(BitmapAddress + BitmapAddressSize),
TO_MiB(BitmapAddressSize));
continue;
}
debug("Found free memory for bitmap: %p (%dMB)",
(void *)BitmapAddress,
TO_MB(BitmapAddressSize));
break;
}
}
debug("Found free memory for bitmap: %p (%d MiB)",
(void *)BitmapAddress,
TO_MiB(BitmapAddressSize));
break;
}
}
if (BitmapAddress == 0x0)
{
error("No free memory found!");
CPU::Stop();
}
if (BitmapAddress == 0x0)
{
error("No free memory found!");
CPU::Stop();
}
/* TODO: Read swap config and make the configure the bitmap size correctly */
debug("Initializing Bitmap at %p-%p (%d Bytes)",
BitmapAddress,
(void *)(BitmapAddress + BitmapSize),
BitmapSize);
/* TODO: Read swap config and make the configure the bitmap size correctly */
debug("Initializing Bitmap at %p-%p (%d Bytes)",
BitmapAddress,
(void *)(BitmapAddress + BitmapSize),
BitmapSize);
PageBitmap.Size = BitmapSize;
PageBitmap.Buffer = (uint8_t *)BitmapAddress;
for (size_t i = 0; i < BitmapSize; i++)
*(uint8_t *)(PageBitmap.Buffer + i) = 0;
PageBitmap.Size = BitmapSize;
PageBitmap.Buffer = (uint8_t *)BitmapAddress;
for (size_t i = 0; i < BitmapSize; i++)
*(uint8_t *)(PageBitmap.Buffer + i) = 0;
ReserveEssentials();
}
ReserveEssentials();
}
Physical::Physical() {}
Physical::~Physical() {}
Physical::Physical() {}
Physical::~Physical() {}
}

View File

@@ -18,6 +18,7 @@
#include <memory.hpp>
#include <debug.h>
#include <elf.h>
#ifdef DEBUG
#include <uart.hpp>
#endif
@@ -44,7 +45,13 @@ namespace Memory
for (uint64_t i = 0; i < bInfo.Memory.Entries; i++)
{
if (bInfo.Memory.Entry[i].Type == Usable)
this->UnreservePages(bInfo.Memory.Entry[i].BaseAddress, TO_PAGES(bInfo.Memory.Entry[i].Length));
{
if (uintptr_t(bInfo.Memory.Entry[i].BaseAddress) <= 0xFFFFF)
continue;
this->UnreservePages(bInfo.Memory.Entry[i].BaseAddress,
TO_PAGES(bInfo.Memory.Entry[i].Length));
}
}
debug("Reserving 0x0-0xFFFFF range...");
@@ -57,18 +64,72 @@ namespace Memory
*/
this->ReservePages((void *)0x0, TO_PAGES(0xFFFFF));
debug("Reserving bitmap region %#lx-%#lx...", PageBitmap.Buffer, (void *)((uintptr_t)PageBitmap.Buffer + PageBitmap.Size));
debug("Reserving bitmap region %#lx-%#lx...",
PageBitmap.Buffer,
(void *)((uintptr_t)PageBitmap.Buffer + PageBitmap.Size));
this->ReservePages(PageBitmap.Buffer, TO_PAGES(PageBitmap.Size));
debug("Reserving kernel physical region %#lx-%#lx...", bInfo.Kernel.PhysicalBase, (void *)((uintptr_t)bInfo.Kernel.PhysicalBase + bInfo.Kernel.Size));
debug("Reserving kernel physical region %#lx-%#lx...",
bInfo.Kernel.PhysicalBase,
(void *)((uintptr_t)bInfo.Kernel.PhysicalBase + bInfo.Kernel.Size));
this->ReservePages(bInfo.Kernel.PhysicalBase, TO_PAGES(bInfo.Kernel.Size));
debug("Reserving kernel file and symbols...");
if (bInfo.Kernel.FileBase)
this->ReservePages(bInfo.Kernel.FileBase, TO_PAGES(bInfo.Kernel.Size));
if (bInfo.Kernel.Symbols.Num && bInfo.Kernel.Symbols.EntSize && bInfo.Kernel.Symbols.Shndx)
this->ReservePages((void *)bInfo.Kernel.Symbols.Sections, TO_PAGES(bInfo.Kernel.Symbols.Num * bInfo.Kernel.Symbols.EntSize));
if (bInfo.Kernel.Symbols.Num &&
bInfo.Kernel.Symbols.EntSize &&
bInfo.Kernel.Symbols.Shndx)
{
char *sections = reinterpret_cast<char *>(bInfo.Kernel.Symbols.Sections);
uint8_t *StringAddress = nullptr;
Elf_Sym *Symbols = nullptr;
#if defined(a64) || defined(aa64)
Elf64_Xword SymbolSize = 0;
Elf64_Xword StringSize = 0;
#elif defined(a32)
Elf32_Word SymbolSize = 0;
Elf32_Word StringSize = 0;
#endif
for (size_t i = 0; i < bInfo.Kernel.Symbols.Num; ++i)
{
Elf_Shdr *sym = (Elf_Shdr *)&sections[bInfo.Kernel.Symbols.EntSize * i];
Elf_Shdr *str = (Elf_Shdr *)&sections[bInfo.Kernel.Symbols.EntSize *
sym->sh_link];
if (sym->sh_type == SHT_SYMTAB &&
str->sh_type == SHT_STRTAB)
{
Symbols = (Elf_Sym *)sym->sh_addr;
StringAddress = (uint8_t *)str->sh_addr;
SymbolSize = (int)sym->sh_size;
StringSize = (int)str->sh_size;
debug("Symbol table found, %d entries",
SymbolSize / sym->sh_entsize);
break;
}
}
if (Symbols)
{
debug("Reserving symbol table region %#lx-%#lx...",
Symbols, (void *)((uintptr_t)Symbols + SymbolSize));
this->ReservePages(Symbols, TO_PAGES(SymbolSize));
}
if (StringAddress)
{
debug("Reserving string table region %#lx-%#lx...",
StringAddress, (void *)((uintptr_t)StringAddress + StringSize));
this->ReservePages(StringAddress, TO_PAGES(StringSize));
}
}
debug("Reserving kernel modules...");
@@ -78,13 +139,17 @@ namespace Memory
continue;
debug("Reserving module %s (%#lx-%#lx)...", bInfo.Modules[i].CommandLine,
bInfo.Modules[i].Address, (void *)((uintptr_t)bInfo.Modules[i].Address + bInfo.Modules[i].Size));
bInfo.Modules[i].Address,
(void *)((uintptr_t)bInfo.Modules[i].Address + bInfo.Modules[i].Size));
this->ReservePages((void *)bInfo.Modules[i].Address, TO_PAGES(bInfo.Modules[i].Size));
this->ReservePages((void *)bInfo.Modules[i].Address,
TO_PAGES(bInfo.Modules[i].Size));
}
#if defined(a86)
debug("Reserving RSDT region %#lx-%#lx...", bInfo.RSDP, (void *)((uintptr_t)bInfo.RSDP + sizeof(BootInfo::RSDPInfo)));
debug("Reserving RSDT region %#lx-%#lx...", bInfo.RSDP,
(void *)((uintptr_t)bInfo.RSDP + sizeof(BootInfo::RSDPInfo)));
this->ReservePages(bInfo.RSDP, TO_PAGES(sizeof(BootInfo::RSDPInfo)));
ACPI::ACPI::ACPIHeader *ACPIPtr = nullptr;
@@ -115,23 +180,27 @@ namespace Memory
}
#endif
size_t TableSize = ((ACPIPtr->Length - sizeof(ACPI::ACPI::ACPIHeader)) / (XSDT ? 8 : 4));
size_t TableSize = ((ACPIPtr->Length - sizeof(ACPI::ACPI::ACPIHeader)) /
(XSDT ? 8 : 4));
debug("Reserving %d ACPI tables...", TableSize);
for (size_t t = 0; t < TableSize; t++)
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
// TODO: Should I be concerned about unaligned memory access?
ACPI::ACPI::ACPIHeader *SDTHdr = nullptr;
if (XSDT)
SDTHdr = (ACPI::ACPI::ACPIHeader *)(*(uint64_t *)((uint64_t)ACPIPtr + sizeof(ACPI::ACPI::ACPIHeader) + (t * 8)));
SDTHdr =
(ACPI::ACPI::ACPIHeader *)(*(uint64_t *)((uint64_t)ACPIPtr +
sizeof(ACPI::ACPI::ACPIHeader) +
(t * 8)));
else
SDTHdr = (ACPI::ACPI::ACPIHeader *)(*(uint32_t *)((uint64_t)ACPIPtr + sizeof(ACPI::ACPI::ACPIHeader) + (t * 4)));
SDTHdr =
(ACPI::ACPI::ACPIHeader *)(*(uint32_t *)((uint64_t)ACPIPtr +
sizeof(ACPI::ACPI::ACPIHeader) +
(t * 4)));
#pragma GCC diagnostic pop
this->ReservePages(SDTHdr, TO_PAGES(SDTHdr->Length));
}

15
Core/Memory/SmartHeap.cpp Normal file
View File

@@ -0,0 +1,15 @@
#include <memory.hpp>
namespace Memory
{
SmartHeap::SmartHeap(size_t Size)
{
this->Object = kmalloc(Size);
this->ObjectSize = Size;
}
SmartHeap::~SmartHeap()
{
kfree(this->Object);
}
}

View File

@@ -29,111 +29,102 @@
namespace Power
{
void Power::Reboot()
{
if (((ACPI::ACPI *)this->acpi)->FADT)
if (((ACPI::DSDT *)this->dsdt)->ACPIShutdownSupported)
((ACPI::DSDT *)this->dsdt)->Reboot();
void Power::Reboot()
{
if (((ACPI::ACPI *)this->acpi)->FADT)
if (((ACPI::DSDT *)this->dsdt)->ACPIShutdownSupported)
((ACPI::DSDT *)this->dsdt)->Reboot();
uint8_t val = 0x02;
while (val & 0x02)
val = inb(0x64);
outb(0x64, 0xFE);
uint8_t val = 0x02;
while (val & 0x02)
val = inb(0x64);
outb(0x64, 0xFE);
warn("Executing the second attempt to reboot...");
warn("Executing the second attempt to reboot...");
// second attempt to reboot
// https://wiki.osdev.org/Reboot
uint8_t temp;
asmv("cli");
do
{
temp = inb(0x64);
if (((temp) & (1 << (0))) != 0)
inb(0x60);
} while (((temp) & (1 << (1))) != 0);
outb(0x64, 0xFE);
// https://wiki.osdev.org/Reboot
/* Second attempt to reboot */
asmv("cli");
uint8_t temp;
do
{
temp = inb(0x64);
if (((temp) & (1 << (0))) != 0)
inb(0x60);
} while (((temp) & (1 << (1))) != 0);
outb(0x64, 0xFE);
CPU::Stop();
}
CPU::Stop();
}
void Power::Shutdown()
{
if (((ACPI::ACPI *)this->acpi)->FADT)
if (((ACPI::DSDT *)this->dsdt)->ACPIShutdownSupported)
((ACPI::DSDT *)this->dsdt)->Shutdown();
void Power::Shutdown()
{
if (((ACPI::ACPI *)this->acpi)->FADT)
if (((ACPI::DSDT *)this->dsdt)->ACPIShutdownSupported)
((ACPI::DSDT *)this->dsdt)->Shutdown();
/* TODO: If no ACPI, display "It is now safe to turn off your computer" */
outl(0xB004, 0x2000); // for qemu
outl(0x604, 0x2000); // if qemu not working, bochs and older versions of qemu
outl(0x4004, 0x3400); // virtual box
CPU::Stop();
}
/* FIXME: Detect emulators and use their shutdown methods */
#ifdef DEBUG
outl(0xB004, 0x2000); // for qemu
outl(0x604, 0x2000); // if qemu not working, bochs and older versions of qemu
outl(0x4004, 0x3400); // virtual box
#endif
CPU::Stop();
}
void Power::InitDSDT()
{
if (((ACPI::ACPI *)this->acpi)->FADT)
this->dsdt = new ACPI::DSDT((ACPI::ACPI *)acpi);
}
void Power::InitDSDT()
{
if (((ACPI::ACPI *)this->acpi)->FADT)
this->dsdt = new ACPI::DSDT((ACPI::ACPI *)acpi);
}
Power::Power()
{
this->acpi = new ACPI::ACPI;
this->madt = new ACPI::MADT(((ACPI::ACPI *)acpi)->MADT);
trace("Power manager initialized");
}
Power::~Power()
{
debug("Destructor called");
}
Power::Power()
{
this->acpi = new ACPI::ACPI;
this->madt = new ACPI::MADT(((ACPI::ACPI *)acpi)->MADT);
trace("Power manager initialized");
}
}
#elif defined(a32)
namespace Power
{
void Power::Reboot()
{
warn("Reboot not implemented for i386");
}
void Power::Reboot()
{
warn("Reboot not implemented for i386");
}
void Power::Shutdown()
{
warn("Shutdown not implemented for i386");
}
void Power::Shutdown()
{
warn("Shutdown not implemented for i386");
}
Power::Power()
{
error("Power not implemented for i386");
}
Power::~Power()
{
}
Power::Power()
{
error("Power not implemented for i386");
}
}
#elif defined(aa64)
namespace Power
{
void Power::Reboot()
{
warn("Reboot not implemented for aarch64");
}
void Power::Reboot()
{
warn("Reboot not implemented for aarch64");
}
void Power::Shutdown()
{
warn("Shutdown not implemented for aarch64");
}
void Power::Shutdown()
{
warn("Shutdown not implemented for aarch64");
}
Power::Power()
{
error("Power not implemented for aarch64");
}
Power::~Power()
{
}
Power::Power()
{
error("Power not implemented for aarch64");
}
}
#endif

View File

@@ -25,220 +25,228 @@
namespace SymbolResolver
{
const NIF char *Symbols::GetSymbolFromAddress(uintptr_t Address)
{
Symbols::SymbolTable Result{0, (char *)"<unknown>"};
for (int64_t i = 0; i < this->TotalEntries; i++)
if (this->SymTable[i].Address <= Address && this->SymTable[i].Address > Result.Address)
Result = this->SymTable[i];
return Result.FunctionName;
}
const NIF char *Symbols::GetSymbolFromAddress(uintptr_t Address)
{
SymbolTable Result{};
foreach (auto tbl in this->SymTable)
{
if (tbl.Address <= Address &&
tbl.Address > Result.Address)
Result = tbl;
}
// debug("Address: %#lx, Function: %s",
// Address, Result.FunctionName);
return Result.FunctionName;
}
void Symbols::AddSymbol(uintptr_t Address, const char *Name)
{
if (this->TotalEntries >= 0x10000)
{
error("Symbol table is full");
return;
}
void Symbols::AddSymbol(uintptr_t Address, const char *Name)
{
SymbolTable tbl{};
tbl.Address = Address;
tbl.FunctionName = (char *)Name;
this->SymTable.push_back(tbl);
this->SymbolTableExists = true;
}
this->SymTable[this->TotalEntries].Address = Address;
strcpy(this->SymTable[this->TotalEntries].FunctionName, Name);
this->TotalEntries++;
}
__no_sanitize("alignment") void Symbols::AddBySymbolInfo(uint64_t Num, uint64_t EntSize, uint64_t Shndx, uintptr_t Sections)
{
__no_sanitize("alignment") void Symbols::AddSymbolInfoFromGRUB(uint64_t Num,
uint64_t EntSize,
__unused uint64_t Shndx,
uintptr_t Sections)
{
#ifdef a32
fixme("Function not working on 32-bit");
return;
fixme("Function not working on 32-bit");
return;
#endif
if (this->TotalEntries >= 0x10000)
{
error("Symbol table is full");
return;
}
char *sections = reinterpret_cast<char *>(Sections);
Elf_Sym *Symbols = nullptr;
uint8_t *StringAddress = nullptr;
#if defined(a64) || defined(aa64)
Elf64_Shdr *ElfSections = (Elf64_Shdr *)(Sections);
Elf64_Sym *ElfSymbols = nullptr;
Elf64_Xword SymbolSize = 0;
// Elf64_Xword StringSize = 0;
#elif defined(a32)
Elf32_Shdr *ElfSections = (Elf32_Shdr *)(Sections);
Elf32_Sym *ElfSymbols = nullptr;
Elf32_Word SymbolSize = 0;
// Elf32_Word StringSize = 0;
#endif
char *strtab = nullptr;
int64_t TotalEntries = 0;
for (size_t i = 0; i < Num; ++i)
{
Elf_Shdr *sym = (Elf_Shdr *)&sections[EntSize * i];
Elf_Shdr *str = (Elf_Shdr *)&sections[EntSize * sym->sh_link];
if (sym->sh_type == SHT_SYMTAB &&
str->sh_type == SHT_STRTAB)
{
Symbols = (Elf_Sym *)sym->sh_addr;
StringAddress = (uint8_t *)str->sh_addr;
SymbolSize = (int)sym->sh_size;
// StringSize = (int)str->sh_size;
// TotalEntries = Section.sh_size / sizeof(Elf64_Sym)
TotalEntries = sym->sh_size / sym->sh_entsize;
debug("Symbol table found, %d entries",
SymbolSize / sym->sh_entsize);
UNUSED(SymbolSize);
break;
}
}
if (Symbols != nullptr && StringAddress != nullptr)
{
int64_t Index, MinimumIndex;
for (int64_t i = 0; i < TotalEntries - 1; i++)
{
MinimumIndex = i;
for (Index = i + 1; Index < TotalEntries; Index++)
if (Symbols[Index].st_value < Symbols[MinimumIndex].st_value)
MinimumIndex = Index;
Elf_Sym tmp = Symbols[MinimumIndex];
Symbols[MinimumIndex] = Symbols[i];
Symbols[i] = tmp;
}
while (Symbols[0].st_value == 0)
{
if (TotalEntries <= 0)
break;
Symbols++;
TotalEntries--;
}
if (TotalEntries <= 0)
{
error("Symbol table is empty");
return;
}
debug("Symbol table loaded, %d entries (%ld KiB)",
TotalEntries, TO_KiB(TotalEntries * sizeof(SymbolTable)));
Elf_Sym *sym = nullptr;
const char *name = nullptr;
for (int64_t i = 0, g = TotalEntries; i < g; i++)
{
sym = &Symbols[i];
name = (const char *)&StringAddress[Symbols[i].st_name];
if (strlen(name) == 0)
continue;
SymbolTable tbl{};
tbl.Address = sym->st_value;
tbl.FunctionName = (char *)name;
this->SymTable.push_back(tbl);
this->SymbolTableExists = true;
// debug("Symbol %d: %#lx %s(%#lx)",
// i, tbl.Address,
// tbl.FunctionName,
// name);
}
}
}
void Symbols::AppendSymbols(uintptr_t ImageAddress, uintptr_t BaseAddress)
{
/* FIXME: Get only the required headers instead of the whole file */
if (ImageAddress == 0 || Memory::Virtual().Check((void *)ImageAddress) == false)
{
error("Invalid image address %#lx", ImageAddress);
return;
}
debug("Solving symbols for address: %#llx", ImageAddress);
for (uint64_t i = 0; i < Num; i++)
switch (ElfSections[i].sh_type)
{
case SHT_SYMTAB:
#if defined(a64) || defined(aa64)
ElfSymbols = (Elf64_Sym *)(Sections + ElfSections[i].sh_offset);
this->TotalEntries = ElfSections[i].sh_size / sizeof(Elf64_Sym);
Elf64_Ehdr *Header = (Elf64_Ehdr *)ImageAddress;
#elif defined(a32)
ElfSymbols = (Elf32_Sym *)(Sections + ElfSections[i].sh_offset);
this->TotalEntries = ElfSections[i].sh_size / sizeof(Elf32_Sym);
Elf32_Ehdr *Header = (Elf32_Ehdr *)ImageAddress;
#endif
if (this->TotalEntries >= 0x10000)
this->TotalEntries = 0x10000 - 1;
if (Header->e_ident[0] != 0x7F &&
Header->e_ident[1] != 'E' &&
Header->e_ident[2] != 'L' &&
Header->e_ident[3] != 'F')
{
error("Invalid ELF header");
return;
}
debug("Symbol table found, %d entries", this->TotalEntries);
break;
case SHT_STRTAB:
if (Shndx == i)
{
debug("String table found, %d entries", ElfSections[i].sh_size);
}
else
{
strtab = (char *)(Sections + ElfSections[i].sh_offset);
debug("String table found, %d entries", ElfSections[i].sh_size);
}
break;
default:
break;
}
Elf_Shdr *ElfSections = (Elf_Shdr *)(ImageAddress + Header->e_shoff);
Elf_Sym *ElfSymbols = nullptr;
char *strtab = nullptr;
int64_t TotalEntries = 0;
if (ElfSymbols != nullptr && strtab != nullptr)
{
int64_t Index, MinimumIndex;
for (int64_t i = 0; i < this->TotalEntries - 1; i++)
{
MinimumIndex = i;
for (Index = i + 1; Index < this->TotalEntries; Index++)
if (ElfSymbols[Index].st_value < ElfSymbols[MinimumIndex].st_value)
MinimumIndex = Index;
#if defined(a64) || defined(aa64)
Elf64_Sym tmp = ElfSymbols[MinimumIndex];
#elif defined(a32)
Elf32_Sym tmp = ElfSymbols[MinimumIndex];
#endif
ElfSymbols[MinimumIndex] = ElfSymbols[i];
ElfSymbols[i] = tmp;
}
for (uint16_t i = 0; i < Header->e_shnum; i++)
{
switch (ElfSections[i].sh_type)
{
case SHT_SYMTAB:
ElfSymbols = (Elf_Sym *)(ImageAddress + ElfSections[i].sh_offset);
TotalEntries = ElfSections[i].sh_size / sizeof(Elf_Sym);
debug("Symbol table found, %d entries", TotalEntries);
break;
case SHT_STRTAB:
if (Header->e_shstrndx == i)
{
debug("String table found, %d entries", ElfSections[i].sh_size);
}
else
{
strtab = (char *)(ImageAddress + ElfSections[i].sh_offset);
debug("String table found, %d entries", ElfSections[i].sh_size);
}
break;
default:
break;
}
}
while (ElfSymbols[0].st_value == 0)
{
if (this->TotalEntries <= 0)
break;
ElfSymbols++;
this->TotalEntries--;
}
if (ElfSymbols != nullptr && strtab != nullptr)
{
int64_t Index, MinimumIndex;
for (int64_t i = 0; i < TotalEntries - 1; i++)
{
MinimumIndex = i;
for (Index = i + 1; Index < TotalEntries; Index++)
if (ElfSymbols[Index].st_value < ElfSymbols[MinimumIndex].st_value)
MinimumIndex = Index;
Elf_Sym tmp = ElfSymbols[MinimumIndex];
ElfSymbols[MinimumIndex] = ElfSymbols[i];
ElfSymbols[i] = tmp;
}
if (this->TotalEntries <= 0)
{
error("Symbol table is empty");
return;
}
while (ElfSymbols[0].st_value == 0)
{
ElfSymbols++;
TotalEntries--;
}
trace("Symbol table loaded, %d entries (%ldKB)", this->TotalEntries, TO_KB(this->TotalEntries * sizeof(SymbolTable)));
for (int64_t i = 0, g = this->TotalEntries; i < g; i++)
{
this->SymTable[i].Address = ElfSymbols[i].st_value;
this->SymTable[i].FunctionName = &strtab[ElfSymbols[i].st_name];
trace("Symbol table loaded, %d entries (%ld KiB)",
TotalEntries, TO_KiB(TotalEntries * sizeof(SymbolTable)));
// debug("Symbol %d: %#llx %s", i, this->SymTable[i].Address, this->SymTable[i].FunctionName);
}
}
}
/* TODO: maybe a checker for duplicated addresses? */
Elf_Sym *sym = nullptr;
const char *name = nullptr;
for (int64_t i = 0, g = TotalEntries; i < g; i++)
{
sym = &ElfSymbols[i];
name = &strtab[ElfSymbols[i].st_name];
SymbolTable tbl{};
tbl.Address = sym->st_value + BaseAddress;
tbl.FunctionName = (char *)name;
this->SymTable.push_back(tbl);
this->SymbolTableExists = true;
Symbols::Symbols(uintptr_t ImageAddress)
{
if (ImageAddress == 0 || Memory::Virtual().Check((void *)ImageAddress) == false)
{
error("Invalid image address %#lx", ImageAddress);
return;
}
// debug("Symbol %d: %#llx %s", i,
// this->SymTable[i].Address,
// this->SymTable[i].FunctionName);
}
}
}
this->Image = (void *)ImageAddress;
debug("Solving symbols for address: %#llx", ImageAddress);
#if defined(a64) || defined(aa64)
Elf64_Ehdr *Header = (Elf64_Ehdr *)ImageAddress;
#elif defined(a32)
Elf32_Ehdr *Header = (Elf32_Ehdr *)ImageAddress;
#endif
if (Header->e_ident[0] != 0x7F &&
Header->e_ident[1] != 'E' &&
Header->e_ident[2] != 'L' &&
Header->e_ident[3] != 'F')
{
error("Invalid ELF header");
return;
}
#if defined(a64) || defined(aa64)
Elf64_Shdr *ElfSections = (Elf64_Shdr *)(ImageAddress + Header->e_shoff);
Elf64_Sym *ElfSymbols = nullptr;
#elif defined(a32)
Elf32_Shdr *ElfSections = (Elf32_Shdr *)(ImageAddress + Header->e_shoff);
Elf32_Sym *ElfSymbols = nullptr;
#endif
char *strtab = nullptr;
Symbols::Symbols(uintptr_t ImageAddress)
{
this->Image = (void *)ImageAddress;
this->AppendSymbols(ImageAddress);
}
for (uint16_t i = 0; i < Header->e_shnum; i++)
switch (ElfSections[i].sh_type)
{
case SHT_SYMTAB:
#if defined(a64) || defined(aa64)
ElfSymbols = (Elf64_Sym *)(ImageAddress + ElfSections[i].sh_offset);
this->TotalEntries = ElfSections[i].sh_size / sizeof(Elf64_Sym);
#elif defined(a32)
ElfSymbols = (Elf32_Sym *)(ImageAddress + ElfSections[i].sh_offset);
this->TotalEntries = ElfSections[i].sh_size / sizeof(Elf32_Sym);
#endif
if (this->TotalEntries >= 0x10000)
this->TotalEntries = 0x10000 - 1;
debug("Symbol table found, %d entries", this->TotalEntries);
break;
case SHT_STRTAB:
if (Header->e_shstrndx == i)
{
debug("String table found, %d entries", ElfSections[i].sh_size);
}
else
{
strtab = (char *)(ImageAddress + ElfSections[i].sh_offset);
debug("String table found, %d entries", ElfSections[i].sh_size);
}
break;
default:
break;
}
if (ElfSymbols != nullptr && strtab != nullptr)
{
int64_t Index, MinimumIndex;
for (int64_t i = 0; i < this->TotalEntries - 1; i++)
{
MinimumIndex = i;
for (Index = i + 1; Index < this->TotalEntries; Index++)
if (ElfSymbols[Index].st_value < ElfSymbols[MinimumIndex].st_value)
MinimumIndex = Index;
#if defined(a64) || defined(aa64)
Elf64_Sym tmp = ElfSymbols[MinimumIndex];
#elif defined(a32)
Elf32_Sym tmp = ElfSymbols[MinimumIndex];
#endif
ElfSymbols[MinimumIndex] = ElfSymbols[i];
ElfSymbols[i] = tmp;
}
while (ElfSymbols[0].st_value == 0)
{
ElfSymbols++;
this->TotalEntries--;
}
trace("Symbol table loaded, %d entries (%ldKB)", this->TotalEntries, TO_KB(this->TotalEntries * sizeof(SymbolTable)));
for (int64_t i = 0, g = this->TotalEntries; i < g; i++)
{
this->SymTable[i].Address = ElfSymbols[i].st_value;
this->SymTable[i].FunctionName = &strtab[ElfSymbols[i].st_name];
// debug("Symbol %d: %#llx %s", i, this->SymTable[i].Address, this->SymTable[i].FunctionName);
}
}
}
Symbols::~Symbols() {}
Symbols::~Symbols() {}
}

View File

@@ -32,52 +32,52 @@
namespace Time
{
bool HighPrecisionEventTimer::Sleep(size_t Duration, Units Unit)
{
bool HighPrecisionEventTimer::Sleep(size_t Duration, Units Unit)
{
#if defined(a64)
size_t Target = mminq(&((HPET *)hpet)->MainCounterValue) + (Duration * ConvertUnit(Unit)) / clk;
uint64_t Target = mminq(&((HPET *)hpet)->MainCounterValue) + (Duration * ConvertUnit(Unit)) / clk;
while (mminq(&((HPET *)hpet)->MainCounterValue) < Target)
CPU::Pause();
CPU::Pause();
return true;
#elif defined(a32)
size_t Target = mminl(&((HPET *)hpet)->MainCounterValue) + (Duration * ConvertUnit(Unit)) / clk;
uint64_t Target = mminl(&((HPET *)hpet)->MainCounterValue) + (Duration * ConvertUnit(Unit)) / clk;
while (mminl(&((HPET *)hpet)->MainCounterValue) < Target)
CPU::Pause();
CPU::Pause();
return true;
#endif
return false;
}
}
size_t HighPrecisionEventTimer::GetCounter()
{
uint64_t HighPrecisionEventTimer::GetCounter()
{
#if defined(a64)
return mminq(&((HPET *)hpet)->MainCounterValue);
#elif defined(a32)
return mminl(&((HPET *)hpet)->MainCounterValue);
#endif
}
}
size_t HighPrecisionEventTimer::CalculateTarget(size_t Target, Units Unit)
{
uint64_t HighPrecisionEventTimer::CalculateTarget(uint64_t Target, Units Unit)
{
#if defined(a64)
return mminq(&((HPET *)hpet)->MainCounterValue) + (Target * ConvertUnit(Unit)) / clk;
#elif defined(a32)
return mminl(&((HPET *)hpet)->MainCounterValue) + (Target * ConvertUnit(Unit)) / clk;
#endif
}
}
size_t HighPrecisionEventTimer::GetNanosecondsSinceClassCreation()
{
uint64_t HighPrecisionEventTimer::GetNanosecondsSinceClassCreation()
{
#if defined(a86)
size_t Subtraction = this->GetCounter() - this->ClassCreationTime;
uint64_t Subtraction = this->GetCounter() - this->ClassCreationTime;
if (Subtraction <= 0 || this->clk <= 0)
return 0;
return Subtraction / (this->clk / ConvertUnit(Units::Nanoseconds));
return 0;
return uint64_t(Subtraction / (this->clk / ConvertUnit(Units::Nanoseconds)));
#endif
}
}
HighPrecisionEventTimer::HighPrecisionEventTimer(void *hpet)
{
HighPrecisionEventTimer::HighPrecisionEventTimer(void *hpet)
{
#if defined(a86)
ACPI::ACPI::HPETHeader *HPET_HDR = (ACPI::ACPI::HPETHeader *)hpet;
Memory::Virtual().Remap((void *)HPET_HDR->Address.Address,
@@ -86,6 +86,7 @@ return false;
this->hpet = (HPET *)HPET_HDR->Address.Address;
trace("%s timer is at address %016p", HPET_HDR->Header.OEMID, (void *)HPET_HDR->Address.Address);
clk = s_cst(uint32_t, (uint64_t)this->hpet->GeneralCapabilities >> 32);
debug("HPET clock is %u Hz", clk);
#ifdef a64
mmoutq(&this->hpet->GeneralConfiguration, 0);
mmoutq(&this->hpet->MainCounterValue, 0);
@@ -97,9 +98,9 @@ return false;
#endif
ClassCreationTime = this->GetCounter();
#endif
}
}
HighPrecisionEventTimer::~HighPrecisionEventTimer()
{
}
HighPrecisionEventTimer::~HighPrecisionEventTimer()
{
}
}

View File

@@ -34,31 +34,31 @@ namespace Time
bool TimeStampCounter::Sleep(size_t Duration, Units Unit)
{
#if defined(a86)
size_t Target = this->GetCounter() + (Duration * ConvertUnit(Unit)) / this->clk;
uint64_t Target = this->GetCounter() + (Duration * ConvertUnit(Unit)) / this->clk;
while (this->GetCounter() < Target)
CPU::Pause();
return true;
#endif
}
size_t TimeStampCounter::GetCounter()
uint64_t TimeStampCounter::GetCounter()
{
#if defined(a86)
return CPU::Counter();
#endif
}
size_t TimeStampCounter::CalculateTarget(size_t Target, Units Unit)
uint64_t TimeStampCounter::CalculateTarget(uint64_t Target, Units Unit)
{
#if defined(a86)
return this->GetCounter() + (Target * ConvertUnit(Unit)) / this->clk;
return uint64_t((this->GetCounter() + (Target * ConvertUnit(Unit))) / this->clk);
#endif
}
size_t TimeStampCounter::GetNanosecondsSinceClassCreation()
uint64_t TimeStampCounter::GetNanosecondsSinceClassCreation()
{
#if defined(a86)
return (this->GetCounter() - this->ClassCreationTime) / this->clk;
return uint64_t((this->GetCounter() - this->ClassCreationTime) / this->clk);
#endif
}

View File

@@ -61,90 +61,90 @@ namespace Time
}
}
size_t time::GetCounter()
uint64_t time::GetCounter()
{
switch (ActiveTimer)
{
case NONE:
error("No timer is active");
return false;
return 0;
case RTC:
fixme("RTC sleep not implemented");
return false;
return 0;
case PIT:
fixme("PIT sleep not implemented");
return false;
return 0;
case HPET:
return this->hpet->GetCounter();
case ACPI:
fixme("ACPI sleep not implemented");
return false;
return 0;
case APIC:
fixme("APIC sleep not implemented");
return false;
return 0;
case TSC:
return this->tsc->GetCounter();
default:
error("Unknown timer");
return false;
return 0;
}
}
size_t time::CalculateTarget(size_t Target, Units Unit)
uint64_t time::CalculateTarget(uint64_t Target, Units Unit)
{
switch (ActiveTimer)
{
case NONE:
error("No timer is active");
return false;
return 0;
case RTC:
fixme("RTC sleep not implemented");
return false;
return 0;
case PIT:
fixme("PIT sleep not implemented");
return false;
return 0;
case HPET:
return this->hpet->CalculateTarget(Target, Unit);
case ACPI:
fixme("ACPI sleep not implemented");
return false;
return 0;
case APIC:
fixme("APIC sleep not implemented");
return false;
return 0;
case TSC:
return this->tsc->CalculateTarget(Target, Unit);
default:
error("Unknown timer");
return false;
return 0;
}
}
size_t time::GetNanosecondsSinceClassCreation()
uint64_t time::GetNanosecondsSinceClassCreation()
{
switch (ActiveTimer)
{
case NONE:
error("No timer is active");
return false;
return 0;
case RTC:
fixme("RTC sleep not implemented");
return false;
return 0;
case PIT:
fixme("PIT sleep not implemented");
return false;
return 0;
case HPET:
return this->hpet->GetNanosecondsSinceClassCreation();
case ACPI:
fixme("ACPI sleep not implemented");
return false;
return 0;
case APIC:
fixme("APIC sleep not implemented");
return false;
return 0;
case TSC:
return this->tsc->GetNanosecondsSinceClassCreation();
default:
error("Unknown timer");
return false;
return 0;
}
}

View File

@@ -20,6 +20,8 @@
#include <convert.h>
#include <debug.h>
#ifdef DEBUG
// TODO: implement:
/*
__ubsan_handle_type_mismatch_v1_abort
@@ -47,320 +49,320 @@ __ubsan_handle_pointer_overflow_abort
__ubsan_handle_cfi_check_fail
*/
extern void __asan_report_load1(void *unknown)
void __asan_report_load1(void *unknown)
{
ubsan("load1");
UNUSED(unknown);
}
extern void __asan_report_load2(void *unknown)
void __asan_report_load2(void *unknown)
{
ubsan("load2");
UNUSED(unknown);
}
extern void __asan_report_load4(void *unknown)
void __asan_report_load4(void *unknown)
{
ubsan("load4");
UNUSED(unknown);
}
extern void __asan_report_load8(void *unknown)
void __asan_report_load8(void *unknown)
{
ubsan("load8");
UNUSED(unknown);
}
extern void __asan_report_load16(void *unknown)
void __asan_report_load16(void *unknown)
{
ubsan("load16");
UNUSED(unknown);
}
extern void __asan_report_load_n(void *unknown, uintptr_t size)
void __asan_report_load_n(void *unknown, uintptr_t size)
{
ubsan("loadn");
UNUSED(unknown);
UNUSED(size);
}
extern void __asan_report_store1(void *unknown)
void __asan_report_store1(void *unknown)
{
ubsan("store1");
UNUSED(unknown);
}
extern void __asan_report_store2(void *unknown)
void __asan_report_store2(void *unknown)
{
ubsan("store2");
UNUSED(unknown);
}
extern void __asan_report_store4(void *unknown)
void __asan_report_store4(void *unknown)
{
ubsan("store4");
UNUSED(unknown);
}
extern void __asan_report_store8(void *unknown)
void __asan_report_store8(void *unknown)
{
ubsan("store8");
UNUSED(unknown);
}
extern void __asan_report_store16(void *unknown)
void __asan_report_store16(void *unknown)
{
ubsan("store16");
UNUSED(unknown);
}
extern void __asan_report_store_n(void *unknown, uintptr_t size)
void __asan_report_store_n(void *unknown, uintptr_t size)
{
ubsan("storen");
UNUSED(unknown);
UNUSED(size);
}
extern void __asan_report_load1_noabort(void *unknown)
void __asan_report_load1_noabort(void *unknown)
{
ubsan("load1");
UNUSED(unknown);
}
extern void __asan_report_load2_noabort(void *unknown)
void __asan_report_load2_noabort(void *unknown)
{
ubsan("load2");
UNUSED(unknown);
}
extern void __asan_report_load4_noabort(void *unknown)
void __asan_report_load4_noabort(void *unknown)
{
ubsan("load4");
UNUSED(unknown);
}
extern void __asan_report_load8_noabort(void *unknown)
void __asan_report_load8_noabort(void *unknown)
{
ubsan("load8");
UNUSED(unknown);
}
extern void __asan_report_load16_noabort(void *unknown)
void __asan_report_load16_noabort(void *unknown)
{
ubsan("load16");
UNUSED(unknown);
}
extern void __asan_report_load_n_noabort(void *unknown, uintptr_t size)
void __asan_report_load_n_noabort(void *unknown, uintptr_t size)
{
ubsan("loadn");
UNUSED(unknown);
UNUSED(size);
}
extern void __asan_report_store1_noabort(void *unknown)
void __asan_report_store1_noabort(void *unknown)
{
ubsan("store1");
UNUSED(unknown);
}
extern void __asan_report_store2_noabort(void *unknown)
void __asan_report_store2_noabort(void *unknown)
{
ubsan("store2");
UNUSED(unknown);
}
extern void __asan_report_store4_noabort(void *unknown)
void __asan_report_store4_noabort(void *unknown)
{
ubsan("store4");
UNUSED(unknown);
}
extern void __asan_report_store8_noabort(void *unknown)
void __asan_report_store8_noabort(void *unknown)
{
ubsan("store8");
UNUSED(unknown);
}
extern void __asan_report_store16_noabort(void *unknown)
void __asan_report_store16_noabort(void *unknown)
{
ubsan("store16");
UNUSED(unknown);
}
extern void __asan_report_store_n_noabort(void *unknown, uintptr_t size)
void __asan_report_store_n_noabort(void *unknown, uintptr_t size)
{
ubsan("storen");
UNUSED(unknown);
UNUSED(size);
}
extern void __asan_stack_malloc_0(uintptr_t size)
void __asan_stack_malloc_0(uintptr_t size)
{
ubsan("stack malloc 0");
UNUSED(size);
}
extern void __asan_stack_malloc_1(uintptr_t size)
void __asan_stack_malloc_1(uintptr_t size)
{
ubsan("stack malloc 1");
UNUSED(size);
}
extern void __asan_stack_malloc_2(uintptr_t size)
void __asan_stack_malloc_2(uintptr_t size)
{
ubsan("stack malloc 2");
UNUSED(size);
}
extern void __asan_stack_malloc_3(uintptr_t size)
void __asan_stack_malloc_3(uintptr_t size)
{
ubsan("stack malloc 3");
UNUSED(size);
}
extern void __asan_stack_malloc_4(uintptr_t size)
void __asan_stack_malloc_4(uintptr_t size)
{
ubsan("stack malloc 4");
UNUSED(size);
}
extern void __asan_stack_malloc_5(uintptr_t size)
void __asan_stack_malloc_5(uintptr_t size)
{
ubsan("stack malloc 5");
UNUSED(size);
}
extern void __asan_stack_malloc_6(uintptr_t size)
void __asan_stack_malloc_6(uintptr_t size)
{
ubsan("stack malloc 6");
UNUSED(size);
}
extern void __asan_stack_malloc_7(uintptr_t size)
void __asan_stack_malloc_7(uintptr_t size)
{
ubsan("stack malloc 7");
UNUSED(size);
}
extern void __asan_stack_malloc_8(uintptr_t size)
void __asan_stack_malloc_8(uintptr_t size)
{
ubsan("stack malloc 8");
UNUSED(size);
}
extern void __asan_stack_malloc_9(uintptr_t size)
void __asan_stack_malloc_9(uintptr_t size)
{
ubsan("stack malloc 9");
UNUSED(size);
}
extern void __asan_stack_free_0(void *ptr, uintptr_t size)
void __asan_stack_free_0(void *ptr, uintptr_t size)
{
ubsan("stack free 0");
UNUSED(ptr);
UNUSED(size);
}
extern void __asan_stack_free_1(void *ptr, uintptr_t size)
void __asan_stack_free_1(void *ptr, uintptr_t size)
{
ubsan("stack free 1");
UNUSED(ptr);
UNUSED(size);
}
extern void __asan_stack_free_2(void *ptr, uintptr_t size)
void __asan_stack_free_2(void *ptr, uintptr_t size)
{
ubsan("stack free 2");
UNUSED(ptr);
UNUSED(size);
}
extern void __asan_stack_free_3(void *ptr, uintptr_t size)
void __asan_stack_free_3(void *ptr, uintptr_t size)
{
ubsan("stack free 3");
UNUSED(ptr);
UNUSED(size);
}
extern void __asan_stack_free_4(void *ptr, uintptr_t size)
void __asan_stack_free_4(void *ptr, uintptr_t size)
{
ubsan("stack free 4");
UNUSED(ptr);
UNUSED(size);
}
extern void __asan_stack_free_5(void *ptr, uintptr_t size)
void __asan_stack_free_5(void *ptr, uintptr_t size)
{
ubsan("stack free 5");
UNUSED(ptr);
UNUSED(size);
}
extern void __asan_stack_free_6(void *ptr, uintptr_t size)
void __asan_stack_free_6(void *ptr, uintptr_t size)
{
ubsan("stack free 6");
UNUSED(ptr);
UNUSED(size);
}
extern void __asan_stack_free_7(void *ptr, uintptr_t size)
void __asan_stack_free_7(void *ptr, uintptr_t size)
{
ubsan("stack free 7");
UNUSED(ptr);
UNUSED(size);
}
extern void __asan_stack_free_8(void *ptr, uintptr_t size)
void __asan_stack_free_8(void *ptr, uintptr_t size)
{
ubsan("stack free 8");
UNUSED(ptr);
UNUSED(size);
}
extern void __asan_stack_free_9(void *ptr, uintptr_t size)
void __asan_stack_free_9(void *ptr, uintptr_t size)
{
ubsan("stack free 9");
UNUSED(ptr);
UNUSED(size);
}
extern void __asan_poison_stack_memory(void *addr, uintptr_t size)
void __asan_poison_stack_memory(void *addr, uintptr_t size)
{
ubsan("poison stack memory");
UNUSED(addr);
UNUSED(size);
}
extern void __asan_unpoison_stack_memory(void *addr, uintptr_t size)
void __asan_unpoison_stack_memory(void *addr, uintptr_t size)
{
ubsan("unpoison stack memory");
UNUSED(addr);
UNUSED(size);
}
extern void __asan_before_dynamic_init(const char *module_name)
void __asan_before_dynamic_init(const char *module_name)
{
ubsan("before dynamic init");
UNUSED(module_name);
}
extern void __asan_after_dynamic_init(void) { ubsan("after dynamic init"); }
void __asan_after_dynamic_init(void) { ubsan("after dynamic init"); }
extern void __asan_register_globals(void *unknown, size_t size)
void __asan_register_globals(void *unknown, size_t size)
{
ubsan("register_globals");
UNUSED(unknown);
UNUSED(size);
}
extern void __asan_unregister_globals(void) { ubsan("unregister_globals"); }
void __asan_unregister_globals(void) { ubsan("unregister_globals"); }
extern void __asan_init(void) { ubsan("init"); }
extern void __asan_version_mismatch_check_v8(void) { ubsan("version_mismatch_check_v8"); }
extern void __asan_option_detect_stack_use_after_return(void) { ubsan("stack use after return"); }
void __asan_init(void) { ubsan("init"); }
void __asan_version_mismatch_check_v8(void) { ubsan("version_mismatch_check_v8"); }
void __asan_option_detect_stack_use_after_return(void) { ubsan("stack use after return"); }
extern __noreturn void __asan_handle_no_return(void)
__noreturn void __asan_handle_no_return(void)
{
ubsan("no_return");
while (1)
@@ -511,3 +513,5 @@ void __ubsan_handle_dynamic_type_cache_miss(struct dynamic_type_cache_miss_data
ubsan("Dynamic type cache miss.");
UNUSED(ptr);
}
#endif

View File

@@ -26,18 +26,18 @@ std::vector<UniversalAsynchronousReceiverTransmitter::Events *> RegisteredEvents
#if defined(a86)
NIF __always_inline inline uint8_t NoProfiler_inportb(uint16_t Port)
{
uint8_t Result;
asm("in %%dx, %%al"
: "=a"(Result)
: "d"(Port));
return Result;
uint8_t Result;
asm("in %%dx, %%al"
: "=a"(Result)
: "d"(Port));
return Result;
}
NIF __always_inline inline void NoProfiler_outportb(uint16_t Port, uint8_t Data)
{
asmv("out %%al, %%dx"
:
: "a"(Data), "d"(Port));
asmv("out %%al, %%dx"
:
: "a"(Data), "d"(Port));
}
#endif
@@ -52,123 +52,125 @@ namespace UniversalAsynchronousReceiverTransmitter
#define SERIAL_RATE_38400_HI 0x00
#define SERIAL_BUFFER_EMPTY 0x20
/* TODO: Serial Port implementation needs reword. https://wiki.osdev.org/Serial_Ports */
/* TODO: Serial Port implementation needs reword. https://wiki.osdev.org/Serial_Ports */
SafeFunction NIF UART::UART(SerialPorts Port)
{
SafeFunction NIF UART::UART(SerialPorts Port)
{
#if defined(a86)
if (Port == COMNULL)
return;
if (Port == COMNULL)
return;
this->Port = Port;
int PortNumber = 0;
this->Port = Port;
int PortNumber = 0;
switch (Port)
{
case COM1:
PortNumber = 0;
break;
case COM2:
PortNumber = 1;
break;
case COM3:
PortNumber = 2;
break;
case COM4:
PortNumber = 3;
break;
case COM5:
PortNumber = 4;
break;
case COM6:
PortNumber = 5;
break;
case COM7:
PortNumber = 6;
break;
case COM8:
PortNumber = 7;
break;
default:
return;
}
switch (Port)
{
case COM1:
PortNumber = 0;
break;
case COM2:
PortNumber = 1;
break;
case COM3:
PortNumber = 2;
break;
case COM4:
PortNumber = 3;
break;
case COM5:
PortNumber = 4;
break;
case COM6:
PortNumber = 5;
break;
case COM7:
PortNumber = 6;
break;
case COM8:
PortNumber = 7;
break;
default:
return;
}
if (serialports[PortNumber])
return;
if (serialports[PortNumber])
return;
// Initialize the serial port
NoProfiler_outportb(s_cst(uint16_t, Port + 1), 0x00); // Disable all interrupts
NoProfiler_outportb(s_cst(uint16_t, Port + 3), SERIAL_ENABLE_DLAB); // Enable DLAB (set baud rate divisor)
NoProfiler_outportb(s_cst(uint16_t, Port + 0), SERIAL_RATE_115200_LO); // Set divisor to 1 (lo byte) 115200 baud
NoProfiler_outportb(s_cst(uint16_t, Port + 1), SERIAL_RATE_115200_HI); // (hi byte)
NoProfiler_outportb(s_cst(uint16_t, Port + 3), 0x03); // 8 bits, no parity, one stop bit
NoProfiler_outportb(s_cst(uint16_t, Port + 2), 0xC7); // Enable FIFO, clear them, with 14-byte threshold
NoProfiler_outportb(s_cst(uint16_t, Port + 4), 0x0B); // IRQs enabled, RTS/DSR set
// Initialize the serial port
NoProfiler_outportb(s_cst(uint16_t, Port + 1), 0x00); // Disable all interrupts
NoProfiler_outportb(s_cst(uint16_t, Port + 3), SERIAL_ENABLE_DLAB); // Enable DLAB (set baud rate divisor)
NoProfiler_outportb(s_cst(uint16_t, Port + 0), SERIAL_RATE_115200_LO); // Set divisor to 1 (lo byte) 115200 baud
NoProfiler_outportb(s_cst(uint16_t, Port + 1), SERIAL_RATE_115200_HI); // (hi byte)
NoProfiler_outportb(s_cst(uint16_t, Port + 3), 0x03); // 8 bits, no parity, one stop bit
NoProfiler_outportb(s_cst(uint16_t, Port + 2), 0xC7); // Enable FIFO, clear them, with 14-byte threshold
NoProfiler_outportb(s_cst(uint16_t, Port + 4), 0x0B); // IRQs enabled, RTS/DSR set
/* FIXME https://wiki.osdev.org/Serial_Ports */
// NoProfiler_outportb(s_cst(uint16_t, Port + 0), 0x1E);
// NoProfiler_outportb(s_cst(uint16_t, Port + 0), 0xAE);
// Check if the serial port is faulty.
// if (NoProfiler_inportb(s_cst(uint16_t, Port + 0)) != 0xAE)
// {
// static int once = 0;
// if (!once++)
// warn("Serial port %#llx is faulty.", Port);
// // serialports[Port] = false; // ignore for now
// // return;
// }
/* FIXME https://wiki.osdev.org/Serial_Ports */
// NoProfiler_outportb(s_cst(uint16_t, Port + 0), 0x1E);
// NoProfiler_outportb(s_cst(uint16_t, Port + 0), 0xAE);
// Check if the serial port is faulty.
// if (NoProfiler_inportb(s_cst(uint16_t, Port + 0)) != 0xAE)
// {
// static int once = 0;
// if (!once++)
// warn("Serial port %#llx is faulty.", Port);
// // serialports[Port] = false; // ignore for now
// // return;
// }
// Set to normal operation mode.
NoProfiler_outportb(s_cst(uint16_t, Port + 4), 0x0F);
serialports[PortNumber] = true;
// Set to normal operation mode.
NoProfiler_outportb(s_cst(uint16_t, Port + 4), 0x0F);
serialports[PortNumber] = true;
#endif
}
}
SafeFunction NIF UART::~UART() {}
SafeFunction NIF UART::~UART() {}
SafeFunction NIF void UART::Write(uint8_t Char)
{
SafeFunction NIF void UART::Write(uint8_t Char)
{
#if defined(a86)
while ((NoProfiler_inportb(s_cst(uint16_t, Port + 5)) & SERIAL_BUFFER_EMPTY) == 0)
;
NoProfiler_outportb(Port, Char);
while ((NoProfiler_inportb(s_cst(uint16_t, Port + 5)) & SERIAL_BUFFER_EMPTY) == 0)
;
NoProfiler_outportb(Port, Char);
#endif
foreach (auto e in RegisteredEvents)
if (e->GetRegisteredPort() == Port || e->GetRegisteredPort() == COMNULL)
e->OnSent(Char);
}
foreach (auto e in RegisteredEvents)
if (e->GetRegisteredPort() == Port || e->GetRegisteredPort() == COMNULL)
e->OnSent(Char);
}
SafeFunction NIF uint8_t UART::Read()
{
SafeFunction NIF uint8_t UART::Read()
{
#if defined(a86)
while ((NoProfiler_inportb(s_cst(uint16_t, Port + 5)) & 1) == 0)
;
return NoProfiler_inportb(Port);
while ((NoProfiler_inportb(s_cst(uint16_t, Port + 5)) & 1) == 0)
;
return NoProfiler_inportb(Port);
#endif
foreach (auto e in RegisteredEvents)
{
if (e->GetRegisteredPort() == Port || e->GetRegisteredPort() == COMNULL)
{
foreach (auto e in RegisteredEvents)
{
if (e->GetRegisteredPort() == Port || e->GetRegisteredPort() == COMNULL)
{
#if defined(a86)
e->OnReceived(NoProfiler_inportb(Port));
e->OnReceived(NoProfiler_inportb(Port));
#endif
}
}
}
}
}
}
SafeFunction NIF Events::Events(SerialPorts Port)
{
this->Port = Port;
RegisteredEvents.push_back(this);
}
SafeFunction NIF Events::Events(SerialPorts Port)
{
this->Port = Port;
RegisteredEvents.push_back(this);
}
SafeFunction NIF Events::~Events()
{
for (size_t i = 0; i < RegisteredEvents.size(); i++)
if (RegisteredEvents[i] == this)
{
RegisteredEvents.remove(i);
return;
}
}
SafeFunction NIF Events::~Events()
{
forItr(itr, RegisteredEvents)
{
if (*itr == this)
{
RegisteredEvents.erase(itr);
return;
}
}
}
}

View File

@@ -28,418 +28,419 @@ NewLock(PrintLock);
namespace Video
{
Font *Display::GetCurrentFont() { return CurrentFont; }
void Display::SetCurrentFont(Font *Font) { CurrentFont = Font; }
uint16_t Display::GetBitsPerPixel() { return this->framebuffer.BitsPerPixel; }
size_t Display::GetPitch() { return this->framebuffer.Pitch; }
Font *Display::GetCurrentFont() { return CurrentFont; }
void Display::SetCurrentFont(Font *Font) { CurrentFont = Font; }
uint16_t Display::GetBitsPerPixel() { return this->framebuffer.BitsPerPixel; }
size_t Display::GetPitch() { return this->framebuffer.Pitch; }
void Display::CreateBuffer(uint32_t Width, uint32_t Height, int Index)
{
if (Width == 0 || Height == 0)
{
Width = this->framebuffer.Width;
Height = this->framebuffer.Height;
debug("Buffer %d created with default size (%d, %d)", Index, Width, Height);
}
void Display::CreateBuffer(uint32_t Width, uint32_t Height, int Index)
{
if (Width == 0 || Height == 0)
{
Width = this->framebuffer.Width;
Height = this->framebuffer.Height;
debug("Buffer %d created with default size (%d, %d)", Index, Width, Height);
}
if (this->Buffers[Index].Checksum == 0xBBFFE515A117E)
{
warn("Buffer %d already exists, skipping creation", Index);
return;
}
if (this->Buffers[Index].Checksum == 0xBBFFE515A117E)
{
warn("Buffer %d already exists, skipping creation", Index);
return;
}
size_t Size = this->framebuffer.Pitch * Height;
size_t Size = this->framebuffer.Pitch * Height;
this->Buffers[Index].Buffer = KernelAllocator.RequestPages(TO_PAGES(Size + 1));
memset(this->Buffers[Index].Buffer, 0, Size);
this->Buffers[Index].Buffer = KernelAllocator.RequestPages(TO_PAGES(Size + 1));
memset(this->Buffers[Index].Buffer, 0, Size);
this->Buffers[Index].Width = Width;
this->Buffers[Index].Height = Height;
this->Buffers[Index].Size = Size;
this->Buffers[Index].Color = 0xFFFFFF;
this->Buffers[Index].CursorX = 0;
this->Buffers[Index].CursorY = 0;
this->Buffers[Index].Brightness = 100;
this->Buffers[Index].Checksum = 0xBBFFE515A117E;
debug("Buffer %d created", Index);
}
this->Buffers[Index].Width = Width;
this->Buffers[Index].Height = Height;
this->Buffers[Index].Size = Size;
this->Buffers[Index].Color = 0xFFFFFF;
this->Buffers[Index].CursorX = 0;
this->Buffers[Index].CursorY = 0;
this->Buffers[Index].Brightness = 100;
this->Buffers[Index].Checksum = 0xBBFFE515A117E;
debug("Buffer %d created", Index);
}
void Display::SetBuffer(int Index)
{
if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E))
{
debug("Invalid buffer %d", Index);
return;
}
void Display::SetBuffer(int Index)
{
if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E))
{
debug("Invalid buffer %d", Index);
return;
}
if (this->Buffers[Index].Brightness != 100)
this->SetBrightness(this->Buffers[Index].Brightness, Index);
if (this->Buffers[Index].Brightness != 100)
this->SetBrightness(this->Buffers[Index].Brightness, Index);
if (this->Buffers[Index].Brightness == 0) /* Just clear the buffer */
memset(this->Buffers[Index].Buffer, 0, this->Buffers[Index].Size);
if (this->Buffers[Index].Brightness == 0) /* Just clear the buffer */
memset(this->Buffers[Index].Buffer, 0, this->Buffers[Index].Size);
memcpy(this->framebuffer.BaseAddress, this->Buffers[Index].Buffer, this->Buffers[Index].Size);
}
memcpy(this->framebuffer.BaseAddress, this->Buffers[Index].Buffer, this->Buffers[Index].Size);
}
ScreenBuffer *Display::GetBuffer(int Index) { return &this->Buffers[Index]; }
ScreenBuffer *Display::GetBuffer(int Index) { return &this->Buffers[Index]; }
void Display::ClearBuffer(int Index)
{
if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E))
{
debug("Invalid buffer %d", Index);
return;
}
void Display::ClearBuffer(int Index)
{
if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E))
{
debug("Invalid buffer %d", Index);
return;
}
memset(this->Buffers[Index].Buffer, 0, this->Buffers[Index].Size);
}
memset(this->Buffers[Index].Buffer, 0, this->Buffers[Index].Size);
}
void Display::DeleteBuffer(int Index)
{
if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E))
{
debug("Invalid buffer %d", Index);
return;
}
void Display::DeleteBuffer(int Index)
{
if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E))
{
debug("Invalid buffer %d", Index);
return;
}
KernelAllocator.FreePages(this->Buffers[Index].Buffer, TO_PAGES(this->Buffers[Index].Size + 1));
this->Buffers[Index].Buffer = nullptr;
this->Buffers[Index].Checksum = 0;
debug("Buffer %d deleted", Index);
}
KernelAllocator.FreePages(this->Buffers[Index].Buffer, TO_PAGES(this->Buffers[Index].Size + 1));
this->Buffers[Index].Buffer = nullptr;
this->Buffers[Index].Checksum = 0;
debug("Buffer %d deleted", Index);
}
void Display::SetBrightness(int Value, int Index)
{
if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E))
{
debug("Invalid buffer %d", Index);
return;
}
void Display::SetBrightness(int Value, int Index)
{
if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E))
{
debug("Invalid buffer %d", Index);
return;
}
if (Value > 100)
Value = 100;
else if (Value < 0)
Value = 0;
if (Value > 100)
Value = 100;
else if (Value < 0)
Value = 0;
uint32_t *pixel = (uint32_t *)this->Buffers[Index].Buffer;
uint32_t *pixel = (uint32_t *)this->Buffers[Index].Buffer;
for (uint32_t y = 0; y < this->Buffers[Index].Height; y++)
{
for (uint32_t x = 0; x < this->Buffers[Index].Width; x++)
{
uint32_t color = pixel[y * this->Buffers[Index].Width + x];
for (uint32_t y = 0; y < this->Buffers[Index].Height; y++)
{
for (uint32_t x = 0; x < this->Buffers[Index].Width; x++)
{
uint32_t color = pixel[y * this->Buffers[Index].Width + x];
uint8_t r = color & 0xff;
uint8_t g = (color >> 8) & 0xff;
uint8_t b = (color >> 16) & 0xff;
uint8_t r = color & 0xff;
uint8_t g = (color >> 8) & 0xff;
uint8_t b = (color >> 16) & 0xff;
r = s_cst(uint8_t, (r * Value) / 100);
g = s_cst(uint8_t, (g * Value) / 100);
b = s_cst(uint8_t, (b * Value) / 100);
r = s_cst(uint8_t, (r * Value) / 100);
g = s_cst(uint8_t, (g * Value) / 100);
b = s_cst(uint8_t, (b * Value) / 100);
pixel[y * this->Buffers[Index].Width + x] = (b << 16) | (g << 8) | r;
}
}
this->Buffers[Index].Brightness = s_cst(char, Value);
}
pixel[y * this->Buffers[Index].Width + x] = (b << 16) | (g << 8) | r;
}
}
this->Buffers[Index].Brightness = s_cst(char, Value);
}
void Display::SetBufferCursor(int Index, uint32_t X, uint32_t Y)
{
if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E))
{
debug("Invalid buffer %d", Index);
return;
}
void Display::SetBufferCursor(int Index, uint32_t X, uint32_t Y)
{
if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E))
{
debug("Invalid buffer %d", Index);
return;
}
this->Buffers[Index].CursorX = X;
this->Buffers[Index].CursorY = Y;
}
this->Buffers[Index].CursorX = X;
this->Buffers[Index].CursorY = Y;
}
void Display::GetBufferCursor(int Index, uint32_t *X, uint32_t *Y)
{
if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E))
{
debug("Invalid buffer %d", Index);
return;
}
void Display::GetBufferCursor(int Index, uint32_t *X, uint32_t *Y)
{
if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E))
{
debug("Invalid buffer %d", Index);
return;
}
*X = this->Buffers[Index].CursorX;
*Y = this->Buffers[Index].CursorY;
}
*X = this->Buffers[Index].CursorX;
*Y = this->Buffers[Index].CursorY;
}
void Display::SetPixel(uint32_t X, uint32_t Y, uint32_t Color, int Index)
{
if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E))
{
debug("Invalid buffer %d", Index);
return;
}
void Display::SetPixel(uint32_t X, uint32_t Y, uint32_t Color, int Index)
{
if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E))
{
debug("Invalid buffer %d", Index);
return;
}
if (unlikely(X >= this->Buffers[Index].Width))
X = this->Buffers[Index].Width - 1;
if (unlikely(X >= this->Buffers[Index].Width))
X = this->Buffers[Index].Width - 1;
if (unlikely(Y >= this->Buffers[Index].Height))
Y = this->Buffers[Index].Height - 1;
if (unlikely(Y >= this->Buffers[Index].Height))
Y = this->Buffers[Index].Height - 1;
uint32_t *Pixel = (uint32_t *)((uintptr_t)this->Buffers[Index].Buffer + (Y * this->Buffers[Index].Width + X) * (this->framebuffer.BitsPerPixel / 8));
*Pixel = Color;
}
uint32_t *Pixel = (uint32_t *)((uintptr_t)this->Buffers[Index].Buffer + (Y * this->Buffers[Index].Width + X) * (this->framebuffer.BitsPerPixel / 8));
*Pixel = Color;
}
uint32_t Display::GetPixel(uint32_t X, uint32_t Y, int Index)
{
if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E))
return 0;
uint32_t Display::GetPixel(uint32_t X, uint32_t Y, int Index)
{
if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E))
return 0;
if (unlikely(X >= this->Buffers[Index].Width || Y >= this->Buffers[Index].Height))
return 0;
if (unlikely(X >= this->Buffers[Index].Width || Y >= this->Buffers[Index].Height))
return 0;
uint32_t *Pixel = (uint32_t *)((uintptr_t)this->Buffers[Index].Buffer + (Y * this->Buffers[Index].Width + X) * (this->framebuffer.BitsPerPixel / 8));
return *Pixel;
}
uint32_t *Pixel = (uint32_t *)((uintptr_t)this->Buffers[Index].Buffer + (Y * this->Buffers[Index].Width + X) * (this->framebuffer.BitsPerPixel / 8));
return *Pixel;
}
void Display::Scroll(int Index, int Lines)
{
if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E))
{
debug("Invalid buffer %d", Index);
return;
}
void Display::Scroll(int Index, int Lines)
{
if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E))
{
debug("Invalid buffer %d", Index);
return;
}
if (this->Buffers[Index].DoNotScroll)
return;
if (this->Buffers[Index].DoNotScroll)
return;
if (Lines == 0)
return;
if (Lines == 0)
return;
if (Lines > 0)
{
uint32_t LineSize = this->Buffers[Index].Width * (this->framebuffer.BitsPerPixel / 8);
uint32_t BytesToMove = LineSize * Lines * this->CurrentFont->GetInfo().Height;
size_t BytesToClear = this->Buffers[Index].Size - BytesToMove;
memmove(this->Buffers[Index].Buffer, (uint8_t *)this->Buffers[Index].Buffer + BytesToMove, BytesToClear);
memset((uint8_t *)this->Buffers[Index].Buffer + BytesToClear, 0, BytesToMove);
}
}
if (Lines > 0)
{
uint32_t LineSize = this->Buffers[Index].Width * (this->framebuffer.BitsPerPixel / 8);
uint32_t BytesToMove = LineSize * Lines * this->CurrentFont->GetInfo().Height;
size_t BytesToClear = this->Buffers[Index].Size - BytesToMove;
memmove(this->Buffers[Index].Buffer, (uint8_t *)this->Buffers[Index].Buffer + BytesToMove, BytesToClear);
memset((uint8_t *)this->Buffers[Index].Buffer + BytesToClear, 0, BytesToMove);
}
}
void Display::SetDoNotScroll(bool Value, int Index)
{
if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E))
{
debug("Invalid buffer %d", Index);
return;
}
void Display::SetDoNotScroll(bool Value, int Index)
{
if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E))
{
debug("Invalid buffer %d", Index);
return;
}
this->Buffers[Index].DoNotScroll = Value;
}
this->Buffers[Index].DoNotScroll = Value;
}
#if defined(a32)
__no_sanitize("undefined")
__no_sanitize("undefined")
#endif
char Display::Print(char Char, int Index, bool WriteToUART)
{
if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E))
return 0;
char Display::Print(char Char, int Index, bool WriteToUART)
{
if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E))
return 0;
// SmartLock(PrintLock);
// SmartLock(PrintLock);
if (this->ColorIteration)
{
// RRGGBB
if (Char >= '0' && Char <= '9')
this->Buffers[Index].Color = (this->Buffers[Index].Color << 4) | (Char - '0');
else if (Char >= 'a' && Char <= 'f')
this->Buffers[Index].Color = (this->Buffers[Index].Color << 4) | (Char - 'a' + 10);
else if (Char >= 'A' && Char <= 'F')
this->Buffers[Index].Color = (this->Buffers[Index].Color << 4) | (Char - 'A' + 10);
else
this->Buffers[Index].Color = 0xFFFFFF;
if (WriteToUART)
UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write(Char);
this->ColorPickerIteration++;
if (this->ColorPickerIteration == 6)
{
this->ColorPickerIteration = 0;
if (WriteToUART)
UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write(']');
this->ColorIteration = false;
}
return Char;
}
if (this->ColorIteration)
{
// RRGGBB
if (Char >= '0' && Char <= '9')
this->Buffers[Index].Color = (this->Buffers[Index].Color << 4) | (Char - '0');
else if (Char >= 'a' && Char <= 'f')
this->Buffers[Index].Color = (this->Buffers[Index].Color << 4) | (Char - 'a' + 10);
else if (Char >= 'A' && Char <= 'F')
this->Buffers[Index].Color = (this->Buffers[Index].Color << 4) | (Char - 'A' + 10);
else
this->Buffers[Index].Color = 0xFFFFFF;
if (WriteToUART)
UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write(Char);
this->ColorPickerIteration++;
if (this->ColorPickerIteration == 6)
{
this->ColorPickerIteration = 0;
if (WriteToUART)
UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write(']');
this->ColorIteration = false;
}
return Char;
}
if (WriteToUART)
UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write(Char);
if (WriteToUART)
UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write(Char);
switch (Char)
{
case '\e':
{
if (WriteToUART)
UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write('[');
this->ColorIteration = true;
return Char;
}
case '\b':
{
switch (this->CurrentFont->GetInfo().Type)
{
case FontType::PCScreenFont1:
{
fixme("PCScreenFont1");
break;
}
case FontType::PCScreenFont2:
{
uint32_t fonthdrWidth = this->CurrentFont->GetInfo().PSF2Font->Header->width;
uint32_t fonthdrHeight = this->CurrentFont->GetInfo().PSF2Font->Header->height;
switch (Char)
{
case '\e':
{
if (WriteToUART)
UniversalAsynchronousReceiverTransmitter::UART(UniversalAsynchronousReceiverTransmitter::COM1).Write('[');
this->ColorIteration = true;
return Char;
}
case '\b':
{
switch (this->CurrentFont->GetInfo().Type)
{
case FontType::PCScreenFont1:
{
fixme("PCScreenFont1");
break;
}
case FontType::PCScreenFont2:
{
uint32_t fonthdrWidth = this->CurrentFont->GetInfo().PSF2Font->Header->width;
uint32_t fonthdrHeight = this->CurrentFont->GetInfo().PSF2Font->Header->height;
for (unsigned long Y = this->Buffers[Index].CursorY; Y < this->Buffers[Index].CursorY + fonthdrHeight; Y++)
for (unsigned long X = this->Buffers[Index].CursorX - fonthdrWidth; X < this->Buffers[Index].CursorX; X++)
*(uint32_t *)((uintptr_t)this->Buffers[Index].Buffer +
(Y * this->Buffers[Index].Width + X) * (this->framebuffer.BitsPerPixel / 8)) = 0;
break;
}
default:
warn("Unsupported font type");
break;
}
for (unsigned long Y = this->Buffers[Index].CursorY; Y < this->Buffers[Index].CursorY + fonthdrHeight; Y++)
for (unsigned long X = this->Buffers[Index].CursorX - fonthdrWidth; X < this->Buffers[Index].CursorX; X++)
*(uint32_t *)((uintptr_t)this->Buffers[Index].Buffer +
(Y * this->Buffers[Index].Width + X) * (this->framebuffer.BitsPerPixel / 8)) = 0;
break;
}
default:
warn("Unsupported font type");
break;
}
if (this->Buffers[Index].CursorX > 0)
this->Buffers[Index].CursorX -= this->GetCurrentFont()->GetInfo().Width;
if (this->Buffers[Index].CursorX > 0)
this->Buffers[Index].CursorX -= this->GetCurrentFont()->GetInfo().Width;
return Char;
}
case '\t':
{
this->Buffers[Index].CursorX = (this->Buffers[Index].CursorX + 8) & ~(8 - 1);
return Char;
}
case '\r':
{
this->Buffers[Index].CursorX = 0;
return Char;
}
case '\n':
{
this->Buffers[Index].CursorX = 0;
this->Buffers[Index].CursorY += this->GetCurrentFont()->GetInfo().Height;
return Char;
}
default:
break;
}
return Char;
}
case '\t':
{
this->Buffers[Index].CursorX = (this->Buffers[Index].CursorX + 8) & ~(8 - 1);
return Char;
}
case '\r':
{
this->Buffers[Index].CursorX = 0;
return Char;
}
case '\n':
{
this->Buffers[Index].CursorX = 0;
this->Buffers[Index].CursorY += this->GetCurrentFont()->GetInfo().Height;
return Char;
}
default:
break;
}
uint32_t FontHeight = this->GetCurrentFont()->GetInfo().Height;
uint32_t FontHeight = this->GetCurrentFont()->GetInfo().Height;
if (this->Buffers[Index].CursorX + this->GetCurrentFont()->GetInfo().Width >= this->Buffers[Index].Width)
{
this->Buffers[Index].CursorX = 0;
this->Buffers[Index].CursorY += FontHeight;
}
if (this->Buffers[Index].CursorX + this->GetCurrentFont()->GetInfo().Width >= this->Buffers[Index].Width)
{
this->Buffers[Index].CursorX = 0;
this->Buffers[Index].CursorY += FontHeight;
}
if (this->Buffers[Index].CursorY + FontHeight >= this->Buffers[Index].Height)
{
if (!this->Buffers[Index].DoNotScroll)
{
this->Buffers[Index].CursorY -= FontHeight;
this->Scroll(Index, 1);
}
}
if (this->Buffers[Index].CursorY + FontHeight >= this->Buffers[Index].Height)
{
if (!this->Buffers[Index].DoNotScroll)
{
this->Buffers[Index].CursorY -= FontHeight;
this->Scroll(Index, 1);
}
}
switch (this->CurrentFont->GetInfo().Type)
{
case FontType::PCScreenFont1:
{
uint32_t *PixelPtr = (uint32_t *)this->Buffers[Index].Buffer;
char *FontPtr = (char *)this->CurrentFont->GetInfo().PSF1Font->GlyphBuffer + (Char * this->CurrentFont->GetInfo().PSF1Font->Header->charsize);
for (uint64_t Y = this->Buffers[Index].CursorY; Y < this->Buffers[Index].CursorY + 16; Y++)
{
for (uint64_t X = this->Buffers[Index].CursorX; X < this->Buffers[Index].CursorX + 8; X++)
if ((*FontPtr & (0b10000000 >> (X - this->Buffers[Index].CursorX))) > 0)
*(unsigned int *)(PixelPtr + X + (Y * this->Buffers[Index].Width)) = this->Buffers[Index].Color;
FontPtr++;
}
this->Buffers[Index].CursorX += 8;
switch (this->CurrentFont->GetInfo().Type)
{
case FontType::PCScreenFont1:
{
uint32_t *PixelPtr = (uint32_t *)this->Buffers[Index].Buffer;
char *FontPtr = (char *)this->CurrentFont->GetInfo().PSF1Font->GlyphBuffer + (Char * this->CurrentFont->GetInfo().PSF1Font->Header->charsize);
for (uint64_t Y = this->Buffers[Index].CursorY; Y < this->Buffers[Index].CursorY + 16; Y++)
{
for (uint64_t X = this->Buffers[Index].CursorX; X < this->Buffers[Index].CursorX + 8; X++)
if ((*FontPtr & (0b10000000 >> (X - this->Buffers[Index].CursorX))) > 0)
*(unsigned int *)(PixelPtr + X + (Y * this->Buffers[Index].Width)) = this->Buffers[Index].Color;
FontPtr++;
}
this->Buffers[Index].CursorX += 8;
break;
}
case FontType::PCScreenFont2:
{
// if (this->CurrentFont->PSF2Font->GlyphBuffer == (uint16_t *)0x01) // HAS UNICODE TABLE
// Char = this->CurrentFont->PSF2Font->GlyphBuffer[Char];
int BytesPerLine = (this->CurrentFont->GetInfo().PSF2Font->Header->width + 7) / 8;
char *FontAddress = (char *)this->CurrentFont->GetInfo().StartAddress;
uint32_t FontHeaderSize = this->CurrentFont->GetInfo().PSF2Font->Header->headersize;
uint32_t FontCharSize = this->CurrentFont->GetInfo().PSF2Font->Header->charsize;
uint32_t FontLength = this->CurrentFont->GetInfo().PSF2Font->Header->length;
char *FontPtr = FontAddress + FontHeaderSize + (Char > 0 && (uint32_t)Char < FontLength ? Char : 0) * FontCharSize;
break;
}
case FontType::PCScreenFont2:
{
// if (this->CurrentFont->PSF2Font->GlyphBuffer == (uint16_t *)0x01) // HAS UNICODE TABLE
// Char = this->CurrentFont->PSF2Font->GlyphBuffer[Char];
int BytesPerLine = (this->CurrentFont->GetInfo().PSF2Font->Header->width + 7) / 8;
char *FontAddress = (char *)this->CurrentFont->GetInfo().StartAddress;
uint32_t FontHeaderSize = this->CurrentFont->GetInfo().PSF2Font->Header->headersize;
uint32_t FontCharSize = this->CurrentFont->GetInfo().PSF2Font->Header->charsize;
uint32_t FontLength = this->CurrentFont->GetInfo().PSF2Font->Header->length;
char *FontPtr = FontAddress + FontHeaderSize + (Char > 0 && (uint32_t)Char < FontLength ? Char : 0) * FontCharSize;
uint32_t FontHdrWidth = this->CurrentFont->GetInfo().PSF2Font->Header->width;
uint32_t FontHdrHeight = this->CurrentFont->GetInfo().PSF2Font->Header->height;
uint32_t FontHdrWidth = this->CurrentFont->GetInfo().PSF2Font->Header->width;
uint32_t FontHdrHeight = this->CurrentFont->GetInfo().PSF2Font->Header->height;
for (size_t Y = this->Buffers[Index].CursorY; Y < this->Buffers[Index].CursorY + FontHdrHeight; Y++)
{
for (size_t X = this->Buffers[Index].CursorX; X < this->Buffers[Index].CursorX + FontHdrWidth; X++)
{
if ((*FontPtr & (0b10000000 >> (X - this->Buffers[Index].CursorX))) > 0)
{
void *FramebufferAddress = (void *)((uintptr_t)this->Buffers[Index].Buffer +
(Y * this->Buffers[Index].Width + X) *
(this->framebuffer.BitsPerPixel / 8));
*(uint32_t *)FramebufferAddress = this->Buffers[Index].Color;
}
}
FontPtr += BytesPerLine;
}
this->Buffers[Index].CursorX += FontHdrWidth;
break;
}
default:
warn("Unsupported font type");
break;
}
return Char;
}
for (size_t Y = this->Buffers[Index].CursorY; Y < this->Buffers[Index].CursorY + FontHdrHeight; Y++)
{
for (size_t X = this->Buffers[Index].CursorX; X < this->Buffers[Index].CursorX + FontHdrWidth; X++)
{
if ((*FontPtr & (0b10000000 >> (X - this->Buffers[Index].CursorX))) > 0)
{
void *FramebufferAddress = (void *)((uintptr_t)this->Buffers[Index].Buffer +
(Y * this->Buffers[Index].Width + X) *
(this->framebuffer.BitsPerPixel / 8));
*(uint32_t *)FramebufferAddress = this->Buffers[Index].Color;
}
}
FontPtr += BytesPerLine;
}
this->Buffers[Index].CursorX += FontHdrWidth;
break;
}
default:
warn("Unsupported font type");
break;
}
return Char;
}
void Display::DrawString(const char *String, uint32_t X, uint32_t Y, int Index, bool WriteToUART)
{
if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E))
{
debug("Invalid buffer %d", Index);
return;
}
void Display::DrawString(const char *String, uint32_t X, uint32_t Y, int Index, bool WriteToUART)
{
if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E))
{
debug("Invalid buffer %d", Index);
return;
}
this->Buffers[Index].CursorX = X;
this->Buffers[Index].CursorY = Y;
this->Buffers[Index].CursorX = X;
this->Buffers[Index].CursorY = Y;
for (int i = 0; String[i] != '\0'; i++)
this->Print(String[i], Index, WriteToUART);
}
for (int i = 0; String[i] != '\0'; i++)
this->Print(String[i], Index, WriteToUART);
}
Display::Display(BootInfo::FramebufferInfo Info, bool LoadDefaultFont)
{
this->framebuffer = Info;
if (LoadDefaultFont)
{
this->CurrentFont = new Font(&_binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_start, &_binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_end, FontType::PCScreenFont2);
Display::Display(BootInfo::FramebufferInfo Info, bool LoadDefaultFont)
{
this->framebuffer = Info;
if (LoadDefaultFont)
{
this->CurrentFont = new Font(&_binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_start, &_binary_Files_tamsyn_font_1_11_Tamsyn7x14r_psf_end, FontType::PCScreenFont2);
#ifdef DEBUG
FontInfo Info = this->CurrentFont->GetInfo();
debug("Font loaded: %dx%d %s",
Info.Width, Info.Height, Info.Type == FontType::PCScreenFont1 ? "PSF1" : "PSF2");
FontInfo Info = this->CurrentFont->GetInfo();
debug("Font loaded: %dx%d %s",
Info.Width, Info.Height,
Info.Type == FontType::PCScreenFont1 ? "PSF1" : "PSF2");
#endif
}
this->CreateBuffer(Info.Width, Info.Height, 0);
}
}
this->CreateBuffer(Info.Width, Info.Height, 0);
}
Display::~Display()
{
debug("Destructor called");
this->ClearBuffer(0);
this->SetBuffer(0);
Display::~Display()
{
debug("Destructor called");
this->ClearBuffer(0);
this->SetBuffer(0);
for (int i = 0; i < s_cst(int, sizeof(this->Buffers) / sizeof(this->Buffers[0])); i++)
{
if (this->Buffers[i].Checksum == 0xBBFFE515A117E)
this->DeleteBuffer(i);
}
}
for (int i = 0; i < s_cst(int, sizeof(this->Buffers) / sizeof(this->Buffers[0])); i++)
{
if (this->Buffers[i].Checksum == 0xBBFFE515A117E)
this->DeleteBuffer(i);
}
}
}

View File

@@ -36,9 +36,11 @@ namespace Video
PSF2_HEADER *font2 = (PSF2_HEADER *)KernelAllocator.RequestPages(TO_PAGES(FontDataLength + 1));
memcpy((void *)font2, Start, FontDataLength);
Memory::Virtual().Map((void *)font2, (void *)font2, FontDataLength, Memory::PTFlag::RW);
Memory::Virtual().Map((void *)font2, (void *)font2,
FontDataLength, Memory::PTFlag::RW);
if (font2->magic[0] != PSF2_MAGIC0 || font2->magic[1] != PSF2_MAGIC1 || font2->magic[2] != PSF2_MAGIC2 || font2->magic[3] != PSF2_MAGIC3)
if (font2->magic[0] != PSF2_MAGIC0 || font2->magic[1] != PSF2_MAGIC1 ||
font2->magic[2] != PSF2_MAGIC2 || font2->magic[3] != PSF2_MAGIC3)
{
error("Font2 magic mismatch.");
KernelAllocator.FreePages((void *)font2, TO_PAGES(FontDataLength + 1));
@@ -46,7 +48,8 @@ namespace Video
}
this->Info.PSF2Font->Header = font2;
this->Info.PSF2Font->GlyphBuffer = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(Start) + sizeof(PSF2_HEADER));
this->Info.PSF2Font->GlyphBuffer =
r_cst(void *, r_cst(uintptr_t, Start) + sizeof(PSF2_HEADER));
this->Info.Width = font2->width;
this->Info.Height = font2->height;
}
@@ -59,7 +62,8 @@ namespace Video
uint32_t glyphBufferSize = font1->charsize * 256;
if (font1->mode == 1) // 512 glyph mode
glyphBufferSize = font1->charsize * 512;
void *glyphBuffer = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(Start) + sizeof(PSF1_HEADER));
void *glyphBuffer =
r_cst(void *, r_cst(uintptr_t, Start) + sizeof(PSF1_HEADER));
this->Info.PSF1Font->Header = font1;
this->Info.PSF1Font->GlyphBuffer = glyphBuffer;
UNUSED(glyphBufferSize); // TODO: Use this in the future?