Compare commits
3 Commits
633f6b925e
...
debd7ef91a
Author | SHA1 | Date | |
---|---|---|---|
debd7ef91a | |||
f74809718a | |||
e4500c27e3 |
|
@ -21,6 +21,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
|
#include <x86intrin.h>
|
||||||
|
|
||||||
#include <efibind.h>
|
#include <efibind.h>
|
||||||
#include <efitypes.h>
|
#include <efitypes.h>
|
||||||
|
@ -626,7 +627,7 @@ void PrepareSystem(FILELOADER_PARAMS* FLOP);
|
||||||
|
|
||||||
/* System Utilities */
|
/* System Utilities */
|
||||||
size_t ClockTick(void);
|
size_t ClockTick(void);
|
||||||
void Halt(void);
|
void panic(void);
|
||||||
void PrepareAVX(void);
|
void PrepareAVX(void);
|
||||||
void AVXStub(void);
|
void AVXStub(void);
|
||||||
void PrepareMaskableInterrupts(void);
|
void PrepareMaskableInterrupts(void);
|
||||||
|
@ -730,6 +731,13 @@ void timer_install();
|
||||||
|
|
||||||
/* ==================== Memory ==================== */
|
/* ==================== Memory ==================== */
|
||||||
|
|
||||||
|
// Standard GCC reqs
|
||||||
|
void* memmove (void* dest, const void* src, size_t len);
|
||||||
|
void memset(void* src, int chr, size_t n);
|
||||||
|
void memcpy(void* dest, void* src, size_t n);
|
||||||
|
int memcmp (const void* str1, const void* str2, size_t count);
|
||||||
|
|
||||||
|
|
||||||
uint8_t VerifyZero(size_t Length, size_t Start);
|
uint8_t VerifyZero(size_t Length, size_t Start);
|
||||||
|
|
||||||
size_t FetchMemoryLimit(void);
|
size_t FetchMemoryLimit(void);
|
||||||
|
@ -755,9 +763,10 @@ EFI_PHYSICAL_ADDRESS AllocatePagetable(size_t PagetableSize);
|
||||||
/* AVX */
|
/* AVX */
|
||||||
void* memmoveAVX(void* Dest, void* Source, size_t Length);
|
void* memmoveAVX(void* Dest, void* Source, size_t Length);
|
||||||
void* memcpyAVX(void* Dest, void* Source, size_t Length);
|
void* memcpyAVX(void* Dest, void* Source, size_t Length);
|
||||||
void* memsetAVX(void* Dest, void* Source, size_t Length);
|
void* memsetAVX(void* Dest, const uint8_t Source, size_t Length);
|
||||||
void* memsetAVX_By4Bytes(void* Dest, void* Source, size_t Length);
|
void* memsetAVX_By4Bytes(void* Dest, const uint32_t Source, size_t Length);
|
||||||
uint8_t memcmpAVX(const void* String1, const void* String2, size_t Length);
|
uint8_t memcmpAVX(const void* String1, const void* String2, size_t Length);
|
||||||
|
#define CACHESIZE 3*1024*1024
|
||||||
|
|
||||||
|
|
||||||
/* Physical Addresses */
|
/* Physical Addresses */
|
||||||
|
|
726
kernel/memory.c
726
kernel/memory.c
|
@ -7,8 +7,734 @@
|
||||||
/* Bear with me.
|
/* Bear with me.
|
||||||
* The plan for this file is to contain all of the memory management, as you can probably tell.
|
* The plan for this file is to contain all of the memory management, as you can probably tell.
|
||||||
* That means alloc, free, move, set, and AVX of all the above.
|
* That means alloc, free, move, set, and AVX of all the above.
|
||||||
|
*
|
||||||
|
* Also, this system will be paged. That means virtual address management.
|
||||||
* That means a lot of work, and a lot of commenting.
|
* That means a lot of work, and a lot of commenting.
|
||||||
*
|
*
|
||||||
* TODO: The above.
|
* TODO: The above.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <kernel.h>
|
||||||
|
|
||||||
|
// malloc. Allocates relative to the nearest alignment value.
|
||||||
|
|
||||||
|
__attribute__((malloc)) void* kalloc(size_t Bytes) {
|
||||||
|
if(Bytes <= 16) {
|
||||||
|
return kalloc_16(Bytes);
|
||||||
|
} else if(Bytes <= 32) {
|
||||||
|
return kalloc_32(Bytes);
|
||||||
|
} else if(Bytes < 4096) {
|
||||||
|
return kalloc_64(Bytes);
|
||||||
|
} else {
|
||||||
|
return kalloc_pages(EFI_SIZE_TO_PAGES(Bytes));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Alignment allocation
|
||||||
|
|
||||||
|
__attribute__((malloc)) void* kalloc_16(size_t Bytes) {
|
||||||
|
EFI_PHYSICAL_ADDRESS Buffer = AllocateFreeAddress_By16Bytes(Bytes, Buffer);
|
||||||
|
return (void*)Buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((malloc)) void* kalloc_32(size_t Bytes) {
|
||||||
|
EFI_PHYSICAL_ADDRESS Buffer = AllocateFreeAddress_By32Bytes(Bytes, Buffer);
|
||||||
|
return (void*)Buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((malloc)) void* kalloc_64(size_t Bytes) {
|
||||||
|
EFI_PHYSICAL_ADDRESS Buffer = AllocateFreeAddress_By64Bytes(Bytes, Buffer);
|
||||||
|
return (void*)Buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((malloc)) void* kalloc_pages(size_t Pages) {
|
||||||
|
EFI_PHYSICAL_ADDRESS Buffer = AllocateFreeAddress_ByPage(Pages, Buffer);
|
||||||
|
return (void*)Buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t VerifyZero(size_t Length, size_t Base) {
|
||||||
|
for(size_t i = 0; i < Length; i++) {
|
||||||
|
if ( *(uint8_t* )(Base + i) != 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the byte after the last mapped byte of memory.
|
||||||
|
// AKA, tells you exactly how much RAM is installed.
|
||||||
|
|
||||||
|
size_t FetchMemoryLimit() {
|
||||||
|
EFI_MEMORY_DESCRIPTOR* Piece;
|
||||||
|
size_t CurrentAddress = 0, MaxAddress = 0;
|
||||||
|
|
||||||
|
for(Piece = Memory_Info.MemoryMap;
|
||||||
|
Piece < (EFI_MEMORY_DESCRIPTOR*)((uint8_t*) Memory_Info.MemoryMap + Memory_Info.MemoryMapSize);
|
||||||
|
Piece = (EFI_MEMORY_DESCRIPTOR*)((uint8_t* )Piece + Memory_Info.MemoryMapDescriptorSize)) {
|
||||||
|
|
||||||
|
CurrentAddress = Piece->PhysicalStart + EFI_PAGES_TO_SIZE(Piece->NumberOfPages);
|
||||||
|
if(CurrentAddress > MaxAddress) {
|
||||||
|
MaxAddress = CurrentAddress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return MaxAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculates how much RAM is visible to the kernel (EG. Not taken by GPU or UEFI)
|
||||||
|
size_t FetchVisibleMemory() {
|
||||||
|
EFI_MEMORY_DESCRIPTOR* Piece;
|
||||||
|
size_t Total = 0;
|
||||||
|
|
||||||
|
for(Piece = Memory_Info.MemoryMap;
|
||||||
|
Piece < (EFI_MEMORY_DESCRIPTOR*)((uint8_t*) Memory_Info.MemoryMap + Memory_Info.MemoryMapSize);
|
||||||
|
Piece = (EFI_MEMORY_DESCRIPTOR*)((uint8_t* )Piece + Memory_Info.MemoryMapDescriptorSize)) {
|
||||||
|
if( (Piece->Type != EfiMemoryMappedIO) &&
|
||||||
|
(Piece->Type != EfiMemoryMappedIOPortSpace) &&
|
||||||
|
(Piece->Type != EfiPalCode) &&
|
||||||
|
(Piece->Type != EfiPersistentMemory) &&
|
||||||
|
(Piece->Type != EfiMaxMemoryType)) {
|
||||||
|
|
||||||
|
Total += EFI_PAGES_TO_SIZE(Piece->NumberOfPages);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Total;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calulcate the total EfiConventionalMemory
|
||||||
|
size_t FetchAvailableMemory() {
|
||||||
|
EFI_MEMORY_DESCRIPTOR* Piece;
|
||||||
|
size_t Total = 0;
|
||||||
|
|
||||||
|
for(Piece = Memory_Info.MemoryMap;
|
||||||
|
Piece < (EFI_MEMORY_DESCRIPTOR*)((uint8_t*) Memory_Info.MemoryMap + Memory_Info.MemoryMapSize);
|
||||||
|
Piece = (EFI_MEMORY_DESCRIPTOR*)((uint8_t* )Piece + Memory_Info.MemoryMapDescriptorSize)) {
|
||||||
|
if(Piece->Type == EfiConventionalMemory) {
|
||||||
|
Total += EFI_PAGES_TO_SIZE(Piece->NumberOfPages);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Total;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculates the total EfiPersistentMemory
|
||||||
|
size_t FetchAvailablePMemory() {
|
||||||
|
EFI_MEMORY_DESCRIPTOR* Piece;
|
||||||
|
size_t Total;
|
||||||
|
|
||||||
|
for(Piece = Memory_Info.MemoryMap;
|
||||||
|
Piece < (EFI_MEMORY_DESCRIPTOR*)((uint8_t*) Memory_Info.MemoryMap + Memory_Info.MemoryMapSize);
|
||||||
|
Piece = (EFI_MEMORY_DESCRIPTOR*)((uint8_t* )Piece + Memory_Info.MemoryMapDescriptorSize)) {
|
||||||
|
if(Piece->Type == EfiPersistentMemory) {
|
||||||
|
Total += EFI_PAGES_TO_SIZE(Piece->NumberOfPages);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Total;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t FetchInstalledMemory() {
|
||||||
|
size_t Total = FetchVisibleMemory();
|
||||||
|
Total += (63 << 20); // DDR3 min is 64MB
|
||||||
|
|
||||||
|
return (Total & ~((64 << 20) - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// From Syncboot/memory.c
|
||||||
|
static const char Memory_Segments[16][27] = {
|
||||||
|
"EfiReservedMemoryType ",
|
||||||
|
"EfiLoaderCode ",
|
||||||
|
"EfiLoaderData ",
|
||||||
|
"EfiBootServicesCode ",
|
||||||
|
"EfiBootServicesData ",
|
||||||
|
"EfiRuntimeServicesCode ",
|
||||||
|
"EfiRuntimeServicesData ",
|
||||||
|
"EfiConventionalMemory ",
|
||||||
|
"EfiUnusableMemory ",
|
||||||
|
"EfiACPIReclaimMemory ",
|
||||||
|
"EfiACPIMemoryNVS ",
|
||||||
|
"EfiMemoryMappedIO ",
|
||||||
|
"EfiMemoryMappedIOPortSpace",
|
||||||
|
"EfiPalCode ",
|
||||||
|
"EfiPersistentMemory ",
|
||||||
|
"EfiMaxMemoryType ",
|
||||||
|
"malloc ", // EfiMaxMemoryType + 1
|
||||||
|
"vmalloc ", // EfiMaxMemoryType + 2
|
||||||
|
"MemMap ", // EfiMaxMemoryType + 3
|
||||||
|
"PageTables " // EfiMaxMemoryType + 4
|
||||||
|
};
|
||||||
|
|
||||||
|
void PrintMemoryMap() {
|
||||||
|
EFI_MEMORY_DESCRIPTOR* Piece;
|
||||||
|
|
||||||
|
uint16_t line = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
printf(L"MemMapSize: %qx, MemMapDescriptorSize: %1u, MemMapDescriptorVersion: %u\r\n", Memory_Info.MemoryMapSize, Memory_Info.MemoryMapDescriptorSize, Memory_Info.MemoryMapDescriptorVersion);
|
||||||
|
|
||||||
|
for (Piece = Memory_Info.MemoryMap;
|
||||||
|
Piece < (EFI_MEMORY_DESCRIPTOR*)((uint8_t*)Memory_Info.MemoryMap + Memory_Info.MemoryMapSize);
|
||||||
|
Piece = (EFI_MEMORY_DESCRIPTOR*)((UINT8*)Piece + Memory_Info.MemoryMapDescriptorSize)) {
|
||||||
|
|
||||||
|
if (line % 20 == 0) {
|
||||||
|
printf(L"# Memory Type Phys Addr Start Num Of Pages Attr\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(L"%2hu: %s 0x%016qx 0x%qx 0x%qx\r\n", line, Memory_Segments[Piece->Type], Piece->PhysicalStart, Piece->NumberOfPages, Piece->Attribute);
|
||||||
|
line++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_MEMORY_DESCRIPTOR* SetIdentityMap(EFI_RUNTIME_SERVICES* RT) {
|
||||||
|
EFI_MEMORY_DESCRIPTOR* Piece;
|
||||||
|
|
||||||
|
for (Piece = Memory_Info.MemoryMap;
|
||||||
|
Piece < (EFI_MEMORY_DESCRIPTOR*)((uint8_t*)Memory_Info.MemoryMap + Memory_Info.MemoryMapSize);
|
||||||
|
Piece = (EFI_MEMORY_DESCRIPTOR*)((UINT8*)Piece + Memory_Info.MemoryMapDescriptorSize)) {
|
||||||
|
Piece->VirtualStart = Piece->PhysicalStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(EFI_ERROR(RT->SetVirtualAddressMap(Memory_Info.MemoryMapSize, Memory_Info.MemoryMapDescriptorSize, Memory_Info.MemoryMapDescriptorVersion, Memory_Info.MemoryMap))) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Memory_Info.MemoryMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This installs the memory map into itself.
|
||||||
|
// Sounds crazy, but it works.
|
||||||
|
void InstallMemoryMap() {
|
||||||
|
EFI_MEMORY_DESCRIPTOR* Piece;
|
||||||
|
size_t Pages = EFI_SIZE_TO_PAGES(Memory_Info.MemoryMapSize + Memory_Info.MemoryMapDescriptorSize);
|
||||||
|
|
||||||
|
EFI_PHYSICAL_ADDRESS NewMapBase = FindFreeAddress(Pages, 0);
|
||||||
|
|
||||||
|
if(NewMapBase == ~0ULL) {
|
||||||
|
printf("Can't move memory map to embiggen it. Ergo, kalloc is not available.\r\n");
|
||||||
|
} else {
|
||||||
|
// Start moving.
|
||||||
|
EFI_MEMORY_DESCRIPTOR* NewMap = (EFI_MEMORY_DESCRIPTOR* )NewMapBase;
|
||||||
|
// Clear out the space for the new map.
|
||||||
|
memsetAVX(NewMap, 0, Pages << EFI_PAGE_SHIFT);
|
||||||
|
// Move the old map to where the new one is.
|
||||||
|
memmoveAVX(NewMap, Memory_Info.MemoryMap, Memory_Info.MemoryMapSize);
|
||||||
|
// Remove the old map.
|
||||||
|
memsetAVX(Memory_Info.MemoryMap, 0, Memory_Info.MemoryMapSize);
|
||||||
|
// Set the global map to the new one.
|
||||||
|
Memory_Info.MemoryMap = NewMap;
|
||||||
|
|
||||||
|
// Start expanding.
|
||||||
|
|
||||||
|
// First, find the PhysicalStart place.
|
||||||
|
for (Piece = Memory_Info.MemoryMap;
|
||||||
|
Piece < (EFI_MEMORY_DESCRIPTOR*)((uint8_t*)Memory_Info.MemoryMap + Memory_Info.MemoryMapSize);
|
||||||
|
Piece = (EFI_MEMORY_DESCRIPTOR*)((UINT8*)Piece + Memory_Info.MemoryMapDescriptorSize)) {
|
||||||
|
|
||||||
|
if(Piece->PhysicalStart == NewMapBase) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if((uint8_t*) Piece == ((uint8_t*)Memory_Info.MemoryMap + Memory_Info.MemoryMapSize)) {
|
||||||
|
printf("Memory Map not found.\r\n");
|
||||||
|
} else {
|
||||||
|
// Piece now contains PhysicalStart
|
||||||
|
// Mark the new area as containing the memory map.
|
||||||
|
if(Piece->NumberOfPages == Pages) {
|
||||||
|
Piece->Type = EfiMaxMemoryType + 3; // Memory Map
|
||||||
|
} else {
|
||||||
|
// We need to tell the memory map that there's now a section *in* the memory map *for* the memory map.
|
||||||
|
// so, temporarily store the current Piece.
|
||||||
|
EFI_MEMORY_DESCRIPTOR NewDescriptor;
|
||||||
|
NewDescriptor.Type = EfiMaxMemoryType + 3;
|
||||||
|
NewDescriptor.Pad = Piece->Pad;
|
||||||
|
NewDescriptor.PhysicalStart = Piece->PhysicalStart;
|
||||||
|
NewDescriptor.VirtualStart = Piece->VirtualStart;
|
||||||
|
NewDescriptor.NumberOfPages = Pages;
|
||||||
|
NewDescriptor.Attribute = Piece->Attribute;
|
||||||
|
|
||||||
|
// Shrink the descriptor; ew've added things.
|
||||||
|
Piece->PhysicalStart += (Pages << EFI_PAGE_SHIFT);
|
||||||
|
Piece->VirtualStart += (Pages << EFI_PAGE_SHIFT);
|
||||||
|
Piece->NumberOfPages -= Pages;
|
||||||
|
// Move things about
|
||||||
|
memmoveAVX((uint8_t*)Piece + Memory_Info.MemoryMapDescriptorSize, Piece, ((uint8_t*)Memory_Info.MemoryMap + Memory_Info.MemoryMapSize) - (uint8_t*)Piece);
|
||||||
|
// And move the old piece back
|
||||||
|
Piece->Type = NewDescriptor.Type;
|
||||||
|
Piece->Pad = NewDescriptor.Pad;
|
||||||
|
Piece->PhysicalStart = NewDescriptor.PhysicalStart;
|
||||||
|
Piece->VirtualStart = NewDescriptor.VirtualStart;
|
||||||
|
Piece->NumberOfPages = NewDescriptor.NumberOfPages;
|
||||||
|
Piece->Attribute = NewDescriptor.Attribute;
|
||||||
|
|
||||||
|
// We added a descriptor, so tell the map that it's now bigger.
|
||||||
|
Memory_Info.MemoryMapSize += Memory_Info.MemoryMapDescriptorSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_PHYSICAL_ADDRESS AllocatePagetable(size_t PageTableSize) {
|
||||||
|
EFI_MEMORY_DESCRIPTOR* Piece;
|
||||||
|
size_t Pages = EFI_SIZE_TO_PAGES(PageTableSize);
|
||||||
|
|
||||||
|
EFI_PHYSICAL_ADDRESS PagetableAddress = FindFreeAddress(Pages, 0);
|
||||||
|
|
||||||
|
if(PagetableAddress == ~0ULL) {
|
||||||
|
printf("Not enough space for page tables.\r\n");
|
||||||
|
panic();
|
||||||
|
} else {
|
||||||
|
memsetAVX((void*)PagetableAddress, 0, Pages << EFI_PAGE_SHIFT);
|
||||||
|
for (Piece = Memory_Info.MemoryMap;
|
||||||
|
Piece < (EFI_MEMORY_DESCRIPTOR*)((uint8_t*)Memory_Info.MemoryMap + Memory_Info.MemoryMapSize);
|
||||||
|
Piece = (EFI_MEMORY_DESCRIPTOR*)((UINT8*)Piece + Memory_Info.MemoryMapDescriptorSize)) {
|
||||||
|
if(Piece->PhysicalStart == PagetableAddress) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if((uint8_t* )Piece == ((uint8_t* )Memory_Info.MemoryMap + Memory_Info.MemoryMapSize)) {
|
||||||
|
printf("Pagetable space not found.\r\n");
|
||||||
|
panic();
|
||||||
|
} else {
|
||||||
|
if(Piece->NumberOfPages == Pages) {
|
||||||
|
Piece->Type = EfiMaxMemoryType + 4; // Pagetables
|
||||||
|
} else {
|
||||||
|
// We need to tell the memory map that there's now a section *in* the memory map *for* the memory map.
|
||||||
|
// so, temporarily store the current Piece.
|
||||||
|
EFI_MEMORY_DESCRIPTOR NewDescriptor;
|
||||||
|
NewDescriptor.Type = EfiMaxMemoryType + 4;
|
||||||
|
NewDescriptor.Pad = Piece->Pad;
|
||||||
|
NewDescriptor.PhysicalStart = Piece->PhysicalStart;
|
||||||
|
NewDescriptor.VirtualStart = Piece->VirtualStart;
|
||||||
|
NewDescriptor.NumberOfPages = Pages;
|
||||||
|
NewDescriptor.Attribute = Piece->Attribute;
|
||||||
|
|
||||||
|
// Shrink the descriptor; ew've added things.
|
||||||
|
Piece->PhysicalStart += (Pages << EFI_PAGE_SHIFT);
|
||||||
|
Piece->VirtualStart += (Pages << EFI_PAGE_SHIFT);
|
||||||
|
Piece->NumberOfPages -= Pages;
|
||||||
|
// Move things about
|
||||||
|
memmoveAVX((uint8_t*)Piece + Memory_Info.MemoryMapDescriptorSize, Piece, ((uint8_t*)Memory_Info.MemoryMap + Memory_Info.MemoryMapSize) - (uint8_t*)Piece);
|
||||||
|
// And move the old piece back
|
||||||
|
Piece->Type = NewDescriptor.Type;
|
||||||
|
Piece->Pad = NewDescriptor.Pad;
|
||||||
|
Piece->PhysicalStart = NewDescriptor.PhysicalStart;
|
||||||
|
Piece->VirtualStart = NewDescriptor.VirtualStart;
|
||||||
|
Piece->NumberOfPages = NewDescriptor.NumberOfPages;
|
||||||
|
Piece->Attribute = NewDescriptor.Attribute;
|
||||||
|
|
||||||
|
// We added a descriptor, so tell the map that it's now bigger.
|
||||||
|
Memory_Info.MemoryMapSize += Memory_Info.MemoryMapDescriptorSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return PagetableAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_PHYSICAL_ADDRESS FindFreeAddress(size_t pages, EFI_PHYSICAL_ADDRESS OldAddress) {
|
||||||
|
|
||||||
|
EFI_MEMORY_DESCRIPTOR* Piece;
|
||||||
|
|
||||||
|
for (Piece = Memory_Info.MemoryMap;
|
||||||
|
Piece < (EFI_MEMORY_DESCRIPTOR*)((uint8_t*)Memory_Info.MemoryMap + Memory_Info.MemoryMapSize);
|
||||||
|
Piece = (EFI_MEMORY_DESCRIPTOR*)((uint8_t*)Piece + Memory_Info.MemoryMapDescriptorSize)) {
|
||||||
|
if ((Piece->Type == EfiConventionalMemory) && (Piece->NumberOfPages >= pages) && (Piece->PhysicalStart > OldAddress))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Piece >= (EFI_MEMORY_DESCRIPTOR*)((uint8_t*)Memory_Info.MemoryMap + Memory_Info.MemoryMapSize)) {
|
||||||
|
printf("Out of available memory!\r\n");
|
||||||
|
return ~0ULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Piece->PhysicalStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_PHYSICAL_ADDRESS FindFreeAddress_ByPage(size_t pages, EFI_PHYSICAL_ADDRESS OldAddress) {
|
||||||
|
EFI_MEMORY_DESCRIPTOR* Piece;
|
||||||
|
EFI_PHYSICAL_ADDRESS PhysicalEnd;
|
||||||
|
EFI_PHYSICAL_ADDRESS DiscoveredAddress;
|
||||||
|
|
||||||
|
for (Piece = Memory_Info.MemoryMap;
|
||||||
|
Piece < (EFI_MEMORY_DESCRIPTOR*)((uint8_t*)Memory_Info.MemoryMap + Memory_Info.MemoryMapSize);
|
||||||
|
Piece = (EFI_MEMORY_DESCRIPTOR*)((uint8_t*)Piece + Memory_Info.MemoryMapDescriptorSize)) {
|
||||||
|
|
||||||
|
if ((Piece->Type == EfiConventionalMemory) && (Piece->NumberOfPages >= pages)) {
|
||||||
|
PhysicalEnd = Piece->PhysicalStart + (Piece->NumberOfPages << EFI_PAGE_SHIFT) - EFI_PAGE_MASK; // Get the end of this range, and use it to set a bound on the range (define a max returnable address).
|
||||||
|
if ((OldAddress >= Piece->PhysicalStart) && ((OldAddress + (pages << EFI_PAGE_SHIFT)) < PhysicalEnd)) {
|
||||||
|
DiscoveredAddress = OldAddress + EFI_PAGE_SIZE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (Piece->PhysicalStart > OldAddress) {
|
||||||
|
DiscoveredAddress = Piece->PhysicalStart;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Piece >= (EFI_MEMORY_DESCRIPTOR*)((uint8_t*)Memory_Info.MemoryMap + Memory_Info.MemoryMapSize)) {
|
||||||
|
printf(L"No more free addresses by page...\r\n");
|
||||||
|
return ~0ULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DiscoveredAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_PHYSICAL_ADDRESS AllocateFreeAddress_By16Bytes(size_t Bytes, EFI_PHYSICAL_ADDRESS OldAddress) {
|
||||||
|
EFI_MEMORY_DESCRIPTOR* Piece;
|
||||||
|
EFI_PHYSICAL_ADDRESS PhysicalEnd;
|
||||||
|
EFI_PHYSICAL_ADDRESS DiscoveredAddress;
|
||||||
|
size_t X16Bytes = Bytes >> 4;
|
||||||
|
if(Bytes & 0xF) {
|
||||||
|
X16Bytes++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(Piece = Memory_Info.MemoryMap;
|
||||||
|
Piece < (EFI_MEMORY_DESCRIPTOR*)((uint8_t*)Memory_Info.MemoryMap + Memory_Info.MemoryMapSize);
|
||||||
|
Piece = (EFI_MEMORY_DESCRIPTOR*)((uint8_t*)Piece + Memory_Info.MemoryMapDescriptorSize)) {
|
||||||
|
|
||||||
|
if((Piece->Type == EfiConventionalMemory) && ((Piece->NumberOfPages << EFI_PAGE_SHIFT) >= X16Bytes)) {
|
||||||
|
// Found a range big enough.
|
||||||
|
// Get the end of this range for bounds checking
|
||||||
|
PhysicalEnd = Piece->PhysicalStart + (Piece->NumberOfPages << EFI_PAGE_SHIFT) - 1;
|
||||||
|
|
||||||
|
if((OldAddress >= Piece->PhysicalStart) && ((OldAddress + (X16Bytes << 4)) < PhysicalEnd)) { // Bounds check on OldAddress
|
||||||
|
// OldAddress + offset is [still] in-bounds, so return the next available x-byte aligned address in the range.
|
||||||
|
DiscoveredAddress = OldAddress + X16Bytes; // Left shift num_x_bytes by 1 or 2 to check every 0x10 or 0x100 sets of bytes (must also modify the above PhysicalEnd bound check)
|
||||||
|
break;
|
||||||
|
// If we would run over PhysicalEnd, we need to go to the next EfiConventionalMemory range
|
||||||
|
}
|
||||||
|
else if(Piece->PhysicalStart > OldAddress) { // Turns out the nearest compatible PhysicalStart is > OldAddress. Use that, then.
|
||||||
|
DiscoveredAddress = Piece->PhysicalStart;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop ended without a DiscoveredAddress
|
||||||
|
if(Piece >= (EFI_MEMORY_DESCRIPTOR*)((uint8_t*)Memory_Info.MemoryMap + Memory_Info.MemoryMapSize))
|
||||||
|
{
|
||||||
|
// Return address -1, which will cause AllocatePages to fail
|
||||||
|
printf("No more free physical addresses by 16 bytes...\r\n");
|
||||||
|
return ~0ULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DiscoveredAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
EFI_PHYSICAL_ADDRESS AllocateFreeAddress_By32Bytes(size_t Bytes, EFI_PHYSICAL_ADDRESS OldAddress) {
|
||||||
|
EFI_MEMORY_DESCRIPTOR* Piece;
|
||||||
|
EFI_PHYSICAL_ADDRESS PhysicalEnd;
|
||||||
|
EFI_PHYSICAL_ADDRESS DiscoveredAddress;
|
||||||
|
size_t X32Bytes = Bytes >> 5;
|
||||||
|
if(Bytes & 0x1F) {
|
||||||
|
X32Bytes++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(Piece = Memory_Info.MemoryMap;
|
||||||
|
Piece < (EFI_MEMORY_DESCRIPTOR*)((uint8_t*)Memory_Info.MemoryMap + Memory_Info.MemoryMapSize);
|
||||||
|
Piece = (EFI_MEMORY_DESCRIPTOR*)((uint8_t*)Piece + Memory_Info.MemoryMapDescriptorSize)) {
|
||||||
|
|
||||||
|
if((Piece->Type == EfiConventionalMemory) && ((Piece->NumberOfPages << EFI_PAGE_SHIFT) >= X32Bytes)) {
|
||||||
|
// Found a range big enough.
|
||||||
|
// Get the end of this range for bounds checking
|
||||||
|
PhysicalEnd = Piece->PhysicalStart + (Piece->NumberOfPages << EFI_PAGE_SHIFT) - 1;
|
||||||
|
|
||||||
|
if((OldAddress >= Piece->PhysicalStart) && ((OldAddress + (X32Bytes << 5)) < PhysicalEnd)) { // Bounds check on OldAddress
|
||||||
|
// OldAddress + offset is [still] in-bounds, so return the next available x-byte aligned address in the range.
|
||||||
|
DiscoveredAddress = OldAddress + X32Bytes; // Left shift num_x_bytes by 1 or 2 to check every 0x10 or 0x100 sets of bytes (must also modify the above PhysicalEnd bound check)
|
||||||
|
break;
|
||||||
|
// If we would run over PhysicalEnd, we need to go to the next EfiConventionalMemory range
|
||||||
|
}
|
||||||
|
else if(Piece->PhysicalStart > OldAddress) { // Turns out the nearest compatible PhysicalStart is > OldAddress. Use that, then.
|
||||||
|
DiscoveredAddress = Piece->PhysicalStart;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop ended without a DiscoveredAddress
|
||||||
|
if(Piece >= (EFI_MEMORY_DESCRIPTOR*)((uint8_t*)Memory_Info.MemoryMap + Memory_Info.MemoryMapSize))
|
||||||
|
{
|
||||||
|
// Return address -1, which will cause AllocatePages to fail
|
||||||
|
printf("No more free physical addresses by 32 bytes...\r\n");
|
||||||
|
return ~0ULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DiscoveredAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EFI_PHYSICAL_ADDRESS AllocateFreeAddress_By64Bytes(size_t Bytes, EFI_PHYSICAL_ADDRESS OldAddress) {
|
||||||
|
EFI_MEMORY_DESCRIPTOR* Piece;
|
||||||
|
EFI_PHYSICAL_ADDRESS PhysicalEnd;
|
||||||
|
EFI_PHYSICAL_ADDRESS DiscoveredAddress;
|
||||||
|
size_t X64Bytes = Bytes >> 6;
|
||||||
|
if(Bytes & 0x3F) {
|
||||||
|
X64Bytes++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(Piece = Memory_Info.MemoryMap;
|
||||||
|
Piece < (EFI_MEMORY_DESCRIPTOR*)((uint8_t*)Memory_Info.MemoryMap + Memory_Info.MemoryMapSize);
|
||||||
|
Piece = (EFI_MEMORY_DESCRIPTOR*)((uint8_t*)Piece + Memory_Info.MemoryMapDescriptorSize)) {
|
||||||
|
|
||||||
|
if((Piece->Type == EfiConventionalMemory) && ((Piece->NumberOfPages << EFI_PAGE_SHIFT) >= X64Bytes)) {
|
||||||
|
// Found a range big enough.
|
||||||
|
// Get the end of this range for bounds checking
|
||||||
|
PhysicalEnd = Piece->PhysicalStart + (Piece->NumberOfPages << EFI_PAGE_SHIFT) - 1;
|
||||||
|
|
||||||
|
if((OldAddress >= Piece->PhysicalStart) && ((OldAddress + (X64Bytes << 6)) < PhysicalEnd)) { // Bounds check on OldAddress
|
||||||
|
// OldAddress + offset is [still] in-bounds, so return the next available x-byte aligned address in the range.
|
||||||
|
DiscoveredAddress = OldAddress + X64Bytes; // Left shift num_x_bytes by 1 or 2 to check every 0x10 or 0x100 sets of bytes (must also modify the above PhysicalEnd bound check)
|
||||||
|
break;
|
||||||
|
// If we would run over PhysicalEnd, we need to go to the next EfiConventionalMemory range
|
||||||
|
}
|
||||||
|
else if(Piece->PhysicalStart > OldAddress) { // Turns out the nearest compatible PhysicalStart is > OldAddress. Use that, then.
|
||||||
|
DiscoveredAddress = Piece->PhysicalStart;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop ended without a DiscoveredAddress
|
||||||
|
if(Piece >= (EFI_MEMORY_DESCRIPTOR*)((uint8_t*)Memory_Info.MemoryMap + Memory_Info.MemoryMapSize))
|
||||||
|
{
|
||||||
|
// Return address -1, which will cause AllocatePages to fail
|
||||||
|
printf("No more free physical addresses by 16 bytes...\r\n");
|
||||||
|
return ~0ULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DiscoveredAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
// per the UEFI Specification (2.7A), EfiBootServicesCode and EfiBootServicesData should be free.
|
||||||
|
// This function is safe, meaning that calling it more than once doesn't change anything.
|
||||||
|
|
||||||
|
void ReclaimEfiBootServicesMemory() {
|
||||||
|
EFI_MEMORY_DESCRIPTOR* Piece;
|
||||||
|
|
||||||
|
for (Piece = Memory_Info.MemoryMap;
|
||||||
|
Piece < (EFI_MEMORY_DESCRIPTOR*)((uint8_t*)Memory_Info.MemoryMap + Memory_Info.MemoryMapSize);
|
||||||
|
Piece = (EFI_MEMORY_DESCRIPTOR*)((UINT8*)Piece + Memory_Info.MemoryMapDescriptorSize)) {
|
||||||
|
if((Piece->Type == EfiBootServicesCode) || (Piece->Type == EfiBootServicesData)) {
|
||||||
|
Piece->Type = EfiConventionalMemory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MergeFragmentedMemory();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function does the above, but for EfiLoaderData (Syncboot data)
|
||||||
|
// This is not recommended, as this stored the FILELOADER_PARAMS.
|
||||||
|
// Before calling this, make a copy.
|
||||||
|
|
||||||
|
void ReclaimEfiLoaderCodeMemory() {
|
||||||
|
EFI_MEMORY_DESCRIPTOR* Piece;
|
||||||
|
|
||||||
|
for (Piece = Memory_Info.MemoryMap;
|
||||||
|
Piece < (EFI_MEMORY_DESCRIPTOR*)((uint8_t*)Memory_Info.MemoryMap + Memory_Info.MemoryMapSize);
|
||||||
|
Piece = (EFI_MEMORY_DESCRIPTOR*)((UINT8*)Piece + Memory_Info.MemoryMapDescriptorSize)) {
|
||||||
|
if(Piece->Type == EfiLoaderData) {
|
||||||
|
Piece->Type = EfiConventionalMemory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MergeFragmentedMemory();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Cleans up the memory map, merging adjacent EfiConventionalMemory entries.
|
||||||
|
void MergeFragmentedMemory() {
|
||||||
|
|
||||||
|
EFI_MEMORY_DESCRIPTOR* Piece;
|
||||||
|
EFI_MEMORY_DESCRIPTOR* Piece2;
|
||||||
|
EFI_PHYSICAL_ADDRESS PhysicalEnd;
|
||||||
|
size_t Pages = 1;
|
||||||
|
|
||||||
|
|
||||||
|
for (Piece = Memory_Info.MemoryMap;
|
||||||
|
Piece < (EFI_MEMORY_DESCRIPTOR*)((uint8_t*)Memory_Info.MemoryMap + Memory_Info.MemoryMapSize);
|
||||||
|
Piece = (EFI_MEMORY_DESCRIPTOR*)((UINT8*)Piece + Memory_Info.MemoryMapDescriptorSize)) {
|
||||||
|
if(Piece->Type == EfiConventionalMemory) {
|
||||||
|
|
||||||
|
PhysicalEnd = Piece->PhysicalStart + (Piece->NumberOfPages << EFI_PAGE_SHIFT);
|
||||||
|
|
||||||
|
|
||||||
|
for (Piece2 = Memory_Info.MemoryMap;
|
||||||
|
Piece2 < (EFI_MEMORY_DESCRIPTOR*)((uint8_t*)Memory_Info.MemoryMap + Memory_Info.MemoryMapSize);
|
||||||
|
Piece2 = (EFI_MEMORY_DESCRIPTOR*)((UINT8*)Piece2 + Memory_Info.MemoryMapDescriptorSize)) {
|
||||||
|
|
||||||
|
if((Piece2->Type == EfiConventionalMemory) && (PhysicalEnd == Piece2->PhysicalStart)) { // If this segment is adjacent to the last one (Piece)
|
||||||
|
Piece->NumberOfPages += Piece2->NumberOfPages;
|
||||||
|
|
||||||
|
memsetAVX(Piece2, 0, Memory_Info.MemoryMapDescriptorSize);
|
||||||
|
// Move the memory down a page
|
||||||
|
memmoveAVX(Piece2, (uint8_t* )Piece2 + Memory_Info.MemoryMapDescriptorSize, ((uint8_t* )Memory_Info.MemoryMap + Memory_Info.MemoryMapSize) - ((uint8_t* )Piece2 + Memory_Info.MemoryMapDescriptorSize));
|
||||||
|
|
||||||
|
Memory_Info.MemoryMapSize -= Memory_Info.MemoryMapDescriptorSize;
|
||||||
|
|
||||||
|
memsetAVX((uint8_t* )Memory_Info.MemoryMap + Memory_Info.MemoryMapSize, 0, Memory_Info.MemoryMapDescriptorSize);
|
||||||
|
|
||||||
|
Piece2 = (EFI_MEMORY_DESCRIPTOR* )((uint8_t* )Piece2 - Memory_Info.MemoryMapDescriptorSize);
|
||||||
|
|
||||||
|
PhysicalEnd = Piece->PhysicalStart + (Piece->NumberOfPages << EFI_PAGE_SHIFT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if(Piece->Type == EfiMaxMemoryType + 3 ) {
|
||||||
|
Pages = Piece->NumberOfPages;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Pages2 = (Memory_Info.MemoryMapSize + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
|
||||||
|
|
||||||
|
if(Pages2 < Pages) {
|
||||||
|
|
||||||
|
for (Piece = Memory_Info.MemoryMap;
|
||||||
|
Piece < (EFI_MEMORY_DESCRIPTOR*)((uint8_t*)Memory_Info.MemoryMap + Memory_Info.MemoryMapSize);
|
||||||
|
Piece = (EFI_MEMORY_DESCRIPTOR*)((UINT8*)Piece + Memory_Info.MemoryMapDescriptorSize)) {
|
||||||
|
|
||||||
|
if((Piece->Type == EfiMaxMemoryType + 3)) {
|
||||||
|
if( ((EFI_MEMORY_DESCRIPTOR* )((uint8_t* )Piece + Memory_Info.MemoryMapDescriptorSize))->Type == EfiConventionalMemory ) {
|
||||||
|
size_t FreePages = Pages - Pages2;
|
||||||
|
|
||||||
|
Piece->NumberOfPages = Pages2;
|
||||||
|
|
||||||
|
((EFI_MEMORY_DESCRIPTOR* )((uint8_t* )Piece + Memory_Info.MemoryMapDescriptorSize))->NumberOfPages += FreePages;
|
||||||
|
((EFI_MEMORY_DESCRIPTOR* )((uint8_t* )Piece + Memory_Info.MemoryMapDescriptorSize))->PhysicalStart -= (FreePages << EFI_PAGE_SHIFT);
|
||||||
|
((EFI_MEMORY_DESCRIPTOR* )((uint8_t* )Piece + Memory_Info.MemoryMapDescriptorSize))->VirtualStart -= (FreePages << EFI_PAGE_SHIFT);
|
||||||
|
} else if ((Memory_Info.MemoryMapSize + Memory_Info.MemoryMapDescriptorSize) <= (Pages2 << EFI_PAGE_SHIFT)) {
|
||||||
|
|
||||||
|
EFI_MEMORY_DESCRIPTOR NewDescriptor;
|
||||||
|
NewDescriptor.Type = Piece->Type;
|
||||||
|
NewDescriptor.Pad = Piece->Pad;
|
||||||
|
NewDescriptor.PhysicalStart = Piece->PhysicalStart;
|
||||||
|
NewDescriptor.VirtualStart = Piece->VirtualStart;
|
||||||
|
NewDescriptor.NumberOfPages = Pages2;
|
||||||
|
NewDescriptor.Attribute = Piece->Attribute;
|
||||||
|
|
||||||
|
Piece->Type = EfiConventionalMemory;
|
||||||
|
|
||||||
|
// Shrink the descriptor; ew've added things.
|
||||||
|
Piece->PhysicalStart += (Pages2 << EFI_PAGE_SHIFT);
|
||||||
|
Piece->VirtualStart += (Pages2 << EFI_PAGE_SHIFT);
|
||||||
|
Piece->NumberOfPages = Pages - Pages2;
|
||||||
|
// Move things about
|
||||||
|
memmoveAVX((uint8_t*)Piece + Memory_Info.MemoryMapDescriptorSize, Piece, ((uint8_t*)Memory_Info.MemoryMap + Memory_Info.MemoryMapSize) - (uint8_t*)Piece);
|
||||||
|
// And move the old piece back
|
||||||
|
Piece->Type = NewDescriptor.Type;
|
||||||
|
Piece->Pad = NewDescriptor.Pad;
|
||||||
|
Piece->PhysicalStart = NewDescriptor.PhysicalStart;
|
||||||
|
Piece->VirtualStart = NewDescriptor.VirtualStart;
|
||||||
|
Piece->NumberOfPages = NewDescriptor.NumberOfPages;
|
||||||
|
Piece->Attribute = NewDescriptor.Attribute;
|
||||||
|
|
||||||
|
// We added a descriptor, so tell the map that it's now bigger.
|
||||||
|
Memory_Info.MemoryMapSize += Memory_Info.MemoryMapDescriptorSize;
|
||||||
|
} else {
|
||||||
|
size_t PagesPerDescriptor = (Memory_Info.MemoryMapDescriptorSize + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT;
|
||||||
|
|
||||||
|
if((Pages2 + PagesPerDescriptor) < Pages) {
|
||||||
|
size_t FreePages = Pages - Pages2 - PagesPerDescriptor;
|
||||||
|
|
||||||
|
EFI_MEMORY_DESCRIPTOR NewDescriptor;
|
||||||
|
NewDescriptor.Type = Piece->Type;
|
||||||
|
NewDescriptor.Pad = Piece->Pad;
|
||||||
|
NewDescriptor.PhysicalStart = Piece->PhysicalStart;
|
||||||
|
NewDescriptor.VirtualStart = Piece->VirtualStart;
|
||||||
|
NewDescriptor.NumberOfPages = Pages2 + PagesPerDescriptor;
|
||||||
|
NewDescriptor.Attribute = Piece->Attribute;
|
||||||
|
|
||||||
|
Piece->Type = EfiConventionalMemory;
|
||||||
|
|
||||||
|
// Shrink the descriptor; ew've added things.
|
||||||
|
Piece->PhysicalStart += ((Pages2 + PagesPerDescriptor) << EFI_PAGE_SHIFT);
|
||||||
|
Piece->VirtualStart += ((Pages2 + PagesPerDescriptor) << EFI_PAGE_SHIFT);
|
||||||
|
Piece->NumberOfPages = FreePages;
|
||||||
|
// Move things about
|
||||||
|
memmoveAVX((uint8_t*)Piece + Memory_Info.MemoryMapDescriptorSize, Piece, ((uint8_t*)Memory_Info.MemoryMap + Memory_Info.MemoryMapSize) - (uint8_t*)Piece);
|
||||||
|
// And move the old piece back
|
||||||
|
Piece->Type = NewDescriptor.Type;
|
||||||
|
Piece->Pad = NewDescriptor.Pad;
|
||||||
|
Piece->PhysicalStart = NewDescriptor.PhysicalStart;
|
||||||
|
Piece->VirtualStart = NewDescriptor.VirtualStart;
|
||||||
|
Piece->NumberOfPages = NewDescriptor.NumberOfPages;
|
||||||
|
Piece->Attribute = NewDescriptor.Attribute;
|
||||||
|
|
||||||
|
// We added a descriptor, so tell the map that it's now bigger.
|
||||||
|
Memory_Info.MemoryMapSize += Memory_Info.MemoryMapDescriptorSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_PHYSICAL_ADDRESS PurgeAllMemory() {
|
||||||
|
EFI_MEMORY_DESCRIPTOR* Piece;
|
||||||
|
EFI_PHYSICAL_ADDRESS Exit = 0;
|
||||||
|
|
||||||
|
|
||||||
|
for (Piece = Memory_Info.MemoryMap;
|
||||||
|
Piece < (EFI_MEMORY_DESCRIPTOR*)((uint8_t*)Memory_Info.MemoryMap + Memory_Info.MemoryMapSize);
|
||||||
|
Piece = (EFI_MEMORY_DESCRIPTOR*)((UINT8*)Piece + Memory_Info.MemoryMapDescriptorSize)) {
|
||||||
|
|
||||||
|
if(Piece->Type == EfiConventionalMemory) {
|
||||||
|
memsetAVX( (void* )Piece->PhysicalStart, 0, EFI_PAGES_TO_SIZE(Piece->NumberOfPages));
|
||||||
|
Exit = VerifyZero(EFI_PAGES_TO_SIZE(Piece->NumberOfPages), Piece->PhysicalStart);
|
||||||
|
if(Exit) {
|
||||||
|
printf("Unable to clear memory. First populated address is %#qx. Memory Descriptor starts at %#qx.\r\n", Exit, Piece->PhysicalStart);
|
||||||
|
} else {
|
||||||
|
printf("Zeroed memory.\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_PHYSICAL_ADDRESS AllocateFreeAddress_ByPage(size_t Pages, EFI_PHYSICAL_ADDRESS SearchStart) {
|
||||||
|
EFI_MEMORY_DESCRIPTOR* Piece;
|
||||||
|
EFI_PHYSICAL_ADDRESS End, Address;
|
||||||
|
|
||||||
|
for (Piece = Memory_Info.MemoryMap;
|
||||||
|
Piece < (EFI_MEMORY_DESCRIPTOR*)((uint8_t*)Memory_Info.MemoryMap + Memory_Info.MemoryMapSize);
|
||||||
|
Piece = (EFI_MEMORY_DESCRIPTOR*)((UINT8*)Piece + Memory_Info.MemoryMapDescriptorSize)) {
|
||||||
|
if((Piece->Type == EfiConventionalMemory) && (Piece->NumberOfPages >= Pages)) {
|
||||||
|
End = Piece->PhysicalStart + (Piece->NumberOfPages << EFI_PAGE_SHIFT) - 1;
|
||||||
|
|
||||||
|
if((SearchStart >= Piece->PhysicalStart) && ((SearchStart + (Pages << EFI_PAGE_SHIFT)) << End)) {
|
||||||
|
Address = SearchStart + EFI_PAGE_SIZE;
|
||||||
|
break;
|
||||||
|
} else if(Piece->PhysicalStart > SearchStart) {
|
||||||
|
Address = Piece->PhysicalStart;
|
||||||
|
|
||||||
|
if(Piece->NumberOfPages - Pages == 0) {
|
||||||
|
Piece->Type = EfiMaxMemoryType + 1;
|
||||||
|
}
|
||||||
|
// TODO: Allocate a new page
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Piece >= (EFI_MEMORY_DESCRIPTOR* )((uint8_t* )Memory_Info.MemoryMap + Memory_Info.MemoryMapSize)) {
|
||||||
|
printf("Out of pages!\r\n");
|
||||||
|
return ~0ULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Address;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Here we go.
|
||||||
|
// This is going to be a mess.
|
||||||
|
// This abuses AVX (SSE3) to do simultaneous memory operations.
|
||||||
|
// I expect this to be useful in graphics - we can move up to 16 pixels with one - one! CPU cycle.
|
||||||
|
|
|
@ -39,8 +39,29 @@ void memcpy(void* dest, void* src, size_t n) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* memmove (void *dest, const void *src, size_t len) {
|
||||||
|
const char *s = (char *)src;
|
||||||
|
char *d = (char *)dest;
|
||||||
|
|
||||||
|
const char *nexts = s + len;
|
||||||
|
char *nextd = d + len;
|
||||||
|
|
||||||
|
if (d < s) {
|
||||||
|
while (d != nextd) {
|
||||||
|
*d++ = *s++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
while (nextd != d) {
|
||||||
|
*--nextd = *--nexts;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Memory Set. Required by GCC>
|
Memory Set. Required by GCC.
|
||||||
* @param src: The data to be overwritten.
|
* @param src: The data to be overwritten.
|
||||||
* @param chr: The byte to overwrite the source with.
|
* @param chr: The byte to overwrite the source with.
|
||||||
* @param n: How many bytes to overwrite.
|
* @param n: How many bytes to overwrite.
|
||||||
|
@ -52,6 +73,19 @@ void memset(void* src, int chr, size_t n) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int memcmp (const void *str1, const void *str2, size_t count) {
|
||||||
|
const unsigned char *s1 = (unsigned char *)str1;
|
||||||
|
const unsigned char *s2 = (unsigned char *)str2;
|
||||||
|
|
||||||
|
while (count-- > 0) {
|
||||||
|
if (*s1++ != *s2++) {
|
||||||
|
return s1[-1] < s2[-1] ? -1 : 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Turns an integer into a C-str.
|
Turns an integer into a C-str.
|
||||||
* @note Inefficient and unsafe.
|
* @note Inefficient and unsafe.
|
||||||
|
@ -165,7 +199,7 @@ void empty_string(char* string) {
|
||||||
|
|
||||||
* @param cause: A string, telling the basic reason for the crash.
|
* @param cause: A string, telling the basic reason for the crash.
|
||||||
*/
|
*/
|
||||||
void panic(char* cause) {
|
void panic() {
|
||||||
printf("Kernel Halted.");
|
printf("Kernel Halted.");
|
||||||
|
|
||||||
for(;;);
|
for(;;);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user