Lynx/UEFI/src/Memory/Memory.cpp
2022-10-14 01:48:08 +03:00

147 lines
5.6 KiB
C++

#include "memory.hpp"
#include "liballoc_1_1.h"
extern "C" void printf(const char *format, ...);
extern uint64_t ImageBase, _text, _etext, _data, _edata, _data_size;
using namespace Memory;
Physical KernelAllocator;
PageTable *KernelPageTable = nullptr;
static void *memset(void *s, int c, size_t n)
{
unsigned int i;
for (i = 0; i < n; i++)
((char *)s)[i] = c;
return s;
}
extern "C" void InitializeMemoryManagement(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
{
printf("Initializing Physical Memory Manager\n");
KernelAllocator = Physical();
KernelAllocator.Init(ImageHandle, SystemTable);
printf("Memory Info: %dMB / %dMB (%dMB reserved)",
(KernelAllocator.GetUsedMemory() / 1024 / 1024),
(KernelAllocator.GetTotalMemory() / 1024 / 1024),
(KernelAllocator.GetReservedMemory() / 1024 / 1024));
KernelPageTable = (PageTable *)KernelAllocator.RequestPage();
memset(KernelPageTable, 0, PAGE_SIZE);
Virtual kva = Virtual(KernelPageTable);
printf("Mapping...\n");
uint64_t BootloaderStart = (uint64_t)&ImageBase;
uint64_t BootloaderTextEnd = (uint64_t)&_text;
uint64_t BootloaderDataEnd = (uint64_t)&_data;
uint64_t BootloaderEnd = (uint64_t)&ImageBase + (uint64_t)&_etext + (uint64_t)&_edata;
uint64_t VirtualOffsetNormalVMA = NORMAL_VMA_OFFSET;
uint64_t BaseKernelMapAddress = (uint64_t)0; // TODO: Info->Kernel.PhysicalBase;
EFI_MEMORY_DESCRIPTOR *memDesc = nullptr;
UINTN MapSize, MapKey;
UINTN DescriptorSize;
UINT32 DescriptorVersion;
{
SystemTable->BootServices->GetMemoryMap(&MapSize, memDesc, &MapKey, &DescriptorSize, &DescriptorVersion);
SystemTable->BootServices->AllocatePool(EfiLoaderData, MapSize, (void **)&memDesc);
SystemTable->BootServices->GetMemoryMap(&MapSize, memDesc, &MapKey, &DescriptorSize, &DescriptorVersion);
}
for (uint64_t t = 0; t < MapSize / DescriptorSize; t += PAGE_SIZE)
{
kva.Map((void *)t, (void *)t, PTFlag::RW);
kva.Map((void *)VirtualOffsetNormalVMA, (void *)t, PTFlag::RW);
VirtualOffsetNormalVMA += PAGE_SIZE;
}
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info;
UINTN SizeOfInfo, numModes = 0; //, MaximumSupportedMode = 0;
EFI_STATUS status;
EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
EFI_GUID gopGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
status = uefi_call_wrapper(BS->LocateProtocol, 3, &gopGuid, NULL, (void **)&gop);
if (EFI_ERROR(status))
{
printf("Unable to locate the Graphics Output Protocol.\n");
}
status = uefi_call_wrapper(gop->QueryMode, 4, gop, gop->Mode == NULL ? 0 : gop->Mode->Mode, &SizeOfInfo, &info);
if (status == EFI_NOT_STARTED)
{
printf("The EFI not started!\n");
status = uefi_call_wrapper(gop->SetMode, 2, gop, 0);
}
/* Mapping Framebuffer address */
int itrfb = 0;
while (1)
{
for (uint64_t fb_base = (uint64_t)gop->Mode->FrameBufferBase;
fb_base < ((uint64_t)gop->Mode->FrameBufferBase + ((gop->Mode->Info->PixelsPerScanLine) + PAGE_SIZE));
fb_base += PAGE_SIZE)
kva.Map((void *)fb_base, (void *)fb_base, PTFlag::RW | PTFlag::US);
itrfb++;
}
/* Kernel mapping */
for (uint64_t k = BootloaderStart; k < BootloaderTextEnd; k += PAGE_SIZE)
{
kva.Map((void *)k, (void *)BaseKernelMapAddress, PTFlag::RW);
KernelAllocator.LockPage((void *)BaseKernelMapAddress);
BaseKernelMapAddress += PAGE_SIZE;
}
for (uint64_t k = BootloaderTextEnd; k < BootloaderDataEnd; k += PAGE_SIZE)
{
kva.Map((void *)k, (void *)BaseKernelMapAddress, PTFlag::RW);
KernelAllocator.LockPage((void *)BaseKernelMapAddress);
BaseKernelMapAddress += PAGE_SIZE;
}
for (uint64_t k = BootloaderDataEnd; k < BootloaderEnd; k += PAGE_SIZE)
{
kva.Map((void *)k, (void *)BaseKernelMapAddress, PTFlag::RW);
KernelAllocator.LockPage((void *)BaseKernelMapAddress);
BaseKernelMapAddress += PAGE_SIZE;
}
printf("\nStart: %#llx - Text End: %#llx - End: %#llx\nStart Physical: %#llx - End Physical: %#llx",
BootloaderStart, BootloaderTextEnd, BootloaderEnd, /* Info->Kernel.PhysicalBase */ 0, BaseKernelMapAddress - PAGE_SIZE);
/* BootloaderStart BootloaderTextEnd KernelRoDataEnd BootloaderEnd
Kernel Start & Text Start ------ Text End ------ Kernel Rodata End ------ Kernel Data End & Kernel End
*/
printf("Applying new page table from address %p", KernelPageTable);
__asm__ volatile("mov %0, %%cr3" ::"r"(KernelPageTable));
}
extern "C" void *HeapMalloc(uint64_t Size) { return PREFIX(malloc)(Size); }
extern "C" void *HeapCalloc(uint64_t n, uint64_t Size) { return PREFIX(calloc)(n, Size); }
extern "C" void *HeapRealloc(void *Address, uint64_t Size) { return PREFIX(realloc)(Address, Size); }
extern "C" void HeapFree(void *Address)
{
PREFIX(free)
(Address);
}
void *operator new(uint64_t Size) { return HeapMalloc(Size); }
void *operator new[](uint64_t Size) { 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); }
void operator delete[](void *Pointer, long unsigned int Size) { HeapFree(Pointer); }
EXTERNC int liballoc_lock() {}
EXTERNC int liballoc_unlock() {}
EXTERNC void *liballoc_alloc(size_t Pages) { return KernelAllocator.RequestPages(Pages); }
EXTERNC int liballoc_free(void *Address, size_t Pages)
{
KernelAllocator.FreePages(Address, Pages);
return 0;
}