mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-07-11 15:29:18 +00:00
Updated kernel (tl;dr: improved filesystem, tasking, loading files, etc..)
This commit is contained in:
@ -168,27 +168,35 @@ namespace Driver
|
||||
Driver::Driver()
|
||||
{
|
||||
SmartCriticalSection(DriverInitLock);
|
||||
FileSystem::FILE *DriverDirectory = vfs->Open(Config.DriverDirectory);
|
||||
if (DriverDirectory->Status == FileSystem::FileStatus::OK)
|
||||
foreach (auto driver in DriverDirectory->Node->Children)
|
||||
if (driver->Flags == FileSystem::NodeFlags::FS_FILE)
|
||||
shared_ptr<VirtualFileSystem::File> DriverDirectory = vfs->Open(Config.DriverDirectory);
|
||||
if (DriverDirectory->Status == VirtualFileSystem::FileStatus::OK)
|
||||
{
|
||||
foreach (auto driver in DriverDirectory->node->Children)
|
||||
if (driver->Flags == VirtualFileSystem::NodeFlags::FILE)
|
||||
if (cwk_path_has_extension(driver->Name))
|
||||
{
|
||||
const char *extension;
|
||||
cwk_path_get_extension(driver->Name, &extension, nullptr);
|
||||
if (!strcmp(extension, ".fex") || !strcmp(extension, ".elf"))
|
||||
debug("Driver: %s; Extension: %s", driver->Name, extension);
|
||||
if (strcmp(extension, ".fex") == 0 || strcmp(extension, ".elf") == 0)
|
||||
{
|
||||
uintptr_t ret = this->LoadDriver(driver->Address, driver->Length);
|
||||
char RetString[128];
|
||||
if (ret == DriverCode::OK)
|
||||
strncpy(RetString, "\e058C19OK", 10);
|
||||
else if (ret == DriverCode::NOT_AVAILABLE)
|
||||
else if (ret == DriverCode::NOT_AVAILABLE)
|
||||
strncpy(RetString, "\eFF7900NOT AVAILABLE", 21);
|
||||
else
|
||||
sprintf(RetString, "\eE85230FAILED (%#lx)", ret);
|
||||
KPrint("%s %s", driver->Name, RetString);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
KPrint("\eE85230Failed to open driver directory: %s", Config.DriverDirectory);
|
||||
CPU::Stop();
|
||||
}
|
||||
vfs->Close(DriverDirectory);
|
||||
}
|
||||
|
||||
|
@ -127,7 +127,7 @@ namespace Interrupts
|
||||
if (likely(Frame->InterruptNumber < CPU::x64::IRQ223 && Frame->InterruptNumber > CPU::x64::ISR0))
|
||||
{
|
||||
Handler *handler = (Handler *)RegisteredEvents->Get(Frame->InterruptNumber);
|
||||
if (likely(handler != (Handler *)0xdeadbeef))
|
||||
if (likely(handler != (Handler *)HASHMAP_ERROR))
|
||||
handler->OnInterruptReceived(Frame);
|
||||
else
|
||||
error("IRQ%ld is unhandled on CPU %d.", Frame->InterruptNumber - 32, Core);
|
||||
@ -151,7 +151,7 @@ namespace Interrupts
|
||||
|
||||
Handler::Handler(int InterruptNumber)
|
||||
{
|
||||
if (RegisteredEvents->Get(InterruptNumber) != (uint64_t)0xdeadbeef)
|
||||
if (RegisteredEvents->Get(InterruptNumber) != (uint64_t)HASHMAP_ERROR)
|
||||
{
|
||||
warn("IRQ%d is already registered.", InterruptNumber - 32);
|
||||
return;
|
||||
@ -165,7 +165,7 @@ namespace Interrupts
|
||||
Handler::~Handler()
|
||||
{
|
||||
debug("Unregistering interrupt handler for IRQ%d.", InterruptNumber - 32);
|
||||
if (RegisteredEvents->DeleteNode(InterruptNumber) == 0xdeadbeef)
|
||||
if (RegisteredEvents->DeleteNode(InterruptNumber) == (uint64_t)HASHMAP_ERROR)
|
||||
warn("Node %d not found.", InterruptNumber);
|
||||
}
|
||||
|
||||
|
@ -174,7 +174,7 @@ __no_instrument_function void InitializeMemoryManagement(BootInfo *Info)
|
||||
#endif
|
||||
|
||||
trace("Initializing Physical Memory Manager");
|
||||
KernelAllocator = Physical();
|
||||
// KernelAllocator = Physical(); <- Already called in the constructor
|
||||
KernelAllocator.Init(Info);
|
||||
debug("Memory Info: %lldMB / %lldMB (%lldMB reserved)",
|
||||
TO_MB(KernelAllocator.GetUsedMemory()),
|
||||
@ -338,28 +338,34 @@ void *operator new(size_t Size)
|
||||
{
|
||||
return HeapMalloc(Size);
|
||||
}
|
||||
|
||||
void *operator new[](size_t Size)
|
||||
{
|
||||
return HeapMalloc(Size);
|
||||
}
|
||||
|
||||
void *operator new(unsigned long Size, std::align_val_t Alignment)
|
||||
{
|
||||
fixme("operator new with alignment(%#lx) is not implemented", Alignment);
|
||||
return HeapMalloc(Size);
|
||||
}
|
||||
|
||||
void operator delete(void *Pointer)
|
||||
{
|
||||
HeapFree(Pointer);
|
||||
}
|
||||
|
||||
void operator delete[](void *Pointer)
|
||||
{
|
||||
HeapFree(Pointer);
|
||||
}
|
||||
|
||||
void operator delete(void *Pointer, long unsigned int Size)
|
||||
{
|
||||
HeapFree(Pointer);
|
||||
UNUSED(Size);
|
||||
}
|
||||
|
||||
void operator delete[](void *Pointer, long unsigned int Size)
|
||||
{
|
||||
HeapFree(Pointer);
|
||||
|
@ -1,18 +1,62 @@
|
||||
#include <memory.hpp>
|
||||
#include <debug.h>
|
||||
|
||||
#include "../../kernel.h"
|
||||
|
||||
namespace Memory
|
||||
{
|
||||
ReadFSFunction(MEM_Read)
|
||||
{
|
||||
if (!Size)
|
||||
Size = node->Length;
|
||||
if (Offset > node->Length)
|
||||
return 0;
|
||||
if (Offset + Size > node->Length)
|
||||
Size = node->Length - Offset;
|
||||
memcpy(Buffer, (uint8_t *)(node->Address + Offset), Size);
|
||||
return Size;
|
||||
}
|
||||
|
||||
WriteFSFunction(MEM_Write)
|
||||
{
|
||||
if (!Size)
|
||||
Size = node->Length;
|
||||
if (Offset > node->Length)
|
||||
return 0;
|
||||
if (Offset + Size > node->Length)
|
||||
Size = node->Length - Offset;
|
||||
memcpy((uint8_t *)(node->Address + Offset), Buffer, Size);
|
||||
return Size;
|
||||
}
|
||||
|
||||
VirtualFileSystem::FileSystemOperations mem_op = {
|
||||
.Name = "mem",
|
||||
.Read = MEM_Read,
|
||||
.Write = MEM_Write,
|
||||
};
|
||||
|
||||
uint64_t MemMgr::GetAllocatedMemorySize()
|
||||
{
|
||||
uint64_t Size = 0;
|
||||
foreach (auto var in AllocatedPagesList)
|
||||
Size += var.PageCount;
|
||||
foreach (auto ap in AllocatedPagesList)
|
||||
Size += ap.PageCount;
|
||||
return FROM_PAGES(Size);
|
||||
}
|
||||
|
||||
bool MemMgr::Add(void *Address, size_t Count)
|
||||
{
|
||||
if (Address == nullptr)
|
||||
{
|
||||
error("Address is null!");
|
||||
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)
|
||||
@ -20,8 +64,7 @@ namespace Memory
|
||||
error("Address already exists!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((uintptr_t)Address < (uintptr_t)AllocatedPagesList[i].Address)
|
||||
else if ((uintptr_t)Address < (uintptr_t)AllocatedPagesList[i].Address)
|
||||
{
|
||||
if ((uintptr_t)Address + (Count * PAGE_SIZE) > (uintptr_t)AllocatedPagesList[i].Address)
|
||||
{
|
||||
@ -39,15 +82,47 @@ namespace Memory
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
void *MemMgr::RequestPages(size_t Count, bool User)
|
||||
{
|
||||
void *Address = KernelAllocator.RequestPages(Count);
|
||||
for (size_t i = 0; i < Count; i++)
|
||||
Memory::Virtual(this->PageTable).Remap((void *)((uintptr_t)Address + (i * PAGE_SIZE)), (void *)((uint64_t)Address + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US);
|
||||
{
|
||||
int Flags = Memory::PTFlag::RW;
|
||||
if (User)
|
||||
Flags |= Memory::PTFlag::US;
|
||||
Memory::Virtual(this->PageTable).Remap((void *)((uintptr_t)Address + (i * PAGE_SIZE)), (void *)((uint64_t)Address + (i * PAGE_SIZE)), 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});
|
||||
return Address;
|
||||
}
|
||||
@ -57,39 +132,80 @@ namespace Memory
|
||||
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.
|
||||
/** 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("FreePages: Page count mismatch! (Allocated: %lld, Requested: %lld)", AllocatedPagesList[i].PageCount, Count);
|
||||
error("Page count mismatch! (Allocated: %lld, Requested: %lld)", AllocatedPagesList[i].PageCount, Count);
|
||||
return;
|
||||
}
|
||||
|
||||
KernelAllocator.FreePages(Address, Count);
|
||||
for (size_t i = 0; i < Count; i++)
|
||||
Memory::Virtual(this->PageTable).Remap((void *)((uintptr_t)Address + (i * PAGE_SIZE)), (void *)((uint64_t)Address + (i * PAGE_SIZE)), Memory::PTFlag::RW);
|
||||
// Memory::Virtual(this->PageTable).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;
|
||||
}
|
||||
}
|
||||
|
||||
MemMgr::MemMgr(PageTable4 *PageTable)
|
||||
void MemMgr::DetachAddress(void *Address)
|
||||
{
|
||||
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(PageTable4 *PageTable, VirtualFileSystem::Node *Directory)
|
||||
{
|
||||
if (PageTable)
|
||||
this->PageTable = PageTable;
|
||||
else
|
||||
this->PageTable = (PageTable4 *)CPU::x64::readcr3().raw;
|
||||
debug("MemMgr initialized.");
|
||||
|
||||
this->Directory = Directory;
|
||||
debug("+ %#lx", this);
|
||||
}
|
||||
|
||||
MemMgr::~MemMgr()
|
||||
{
|
||||
foreach (auto var in AllocatedPagesList)
|
||||
foreach (auto ap in AllocatedPagesList)
|
||||
{
|
||||
KernelAllocator.FreePages(var.Address, var.PageCount);
|
||||
for (size_t i = 0; i < var.PageCount; i++)
|
||||
Memory::Virtual(this->PageTable).Remap((void *)((uintptr_t)var.Address + (i * PAGE_SIZE)), (void *)((uintptr_t)var.Address + (i * PAGE_SIZE)), Memory::PTFlag::RW);
|
||||
KernelAllocator.FreePages(ap.Address, ap.PageCount);
|
||||
for (size_t i = 0; i < ap.PageCount; i++)
|
||||
Memory::Virtual(this->PageTable).Remap((void *)((uintptr_t)ap.Address + (i * PAGE_SIZE)), (void *)((uintptr_t)ap.Address + (i * PAGE_SIZE)), Memory::PTFlag::RW);
|
||||
}
|
||||
debug("MemMgr destroyed.");
|
||||
|
||||
if (this->Directory)
|
||||
foreach (auto Child in this->Directory->Children)
|
||||
vfs->Delete(Child, true);
|
||||
|
||||
debug("- %#lx", this);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user