a new allocator that doesn't yet fix msi
This commit is contained in:
1 parent
79906b4c2c
commit
23d7ff90f7
12 files changed
+134
-81
No files matched your search
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"CurrentProjectSetting": "No Configurations"
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"ExpandedNodes": [
|
||||
""
|
||||
],
|
||||
"PreviewInSolutionExplorer": false
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"Version": 1,
|
||||
"WorkspaceRootPath": "C:\\Users\\Administrator\\Documents\\binkx86\\",
|
||||
"Documents": [],
|
||||
"DocumentGroupContainers": [
|
||||
{
|
||||
"Orientation": 0,
|
||||
"VerticalTabListWidth": 256,
|
||||
"DocumentGroups": [
|
||||
{
|
||||
"DockedWidth": 200,
|
||||
"SelectedChildIndex": -1,
|
||||
"Children": [
|
||||
{
|
||||
"$type": "Bookmark",
|
||||
"Name": "ST:0:0:{1c4feeaa-4718-4aa9-859d-94ce25d182ba}"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
+7
-5
@@ -165,6 +165,8 @@ typedef DWORD LCTYPE;
|
||||
#pragma endregion
|
||||
|
||||
extern int stricmp(const char *s1, const char *s2);
|
||||
extern void* Malloc(size_t size);
|
||||
extern void Free(void* ptr);
|
||||
|
||||
// --- Memory ---
|
||||
HANDLE HeapCreate(DWORD, SIZE_T, SIZE_T) {
|
||||
@@ -179,24 +181,24 @@ BOOL HeapDestroy(HANDLE) {
|
||||
|
||||
LPVOID HeapAlloc(HANDLE, DWORD, SIZE_T size) {
|
||||
PRINT(L"Called: HeapAlloc with size: %ull\n", size);
|
||||
return AllocatePool(size);
|
||||
return Malloc(size);
|
||||
}
|
||||
|
||||
BOOL HeapFree(HANDLE, DWORD, LPVOID ptr) {
|
||||
PRINT(L"Called: HeapFree with ptr: %p\n", ptr);
|
||||
if (ptr)
|
||||
FreePool(ptr);
|
||||
Free(ptr);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
LPVOID HeapReAlloc(HANDLE, DWORD, LPVOID ptr, SIZE_T size) {
|
||||
PRINT(L"Called: HeapReAlloc with size: %ull and ptr: %p\n", size, ptr);
|
||||
if (!ptr) return AllocatePool(size);
|
||||
LPVOID newPtr = AllocatePool(size);
|
||||
if (!ptr) return Malloc(size);
|
||||
LPVOID newPtr = Malloc(size);
|
||||
if (!newPtr) return nullptr;
|
||||
// No original size info; can't fully emulate, user must handle
|
||||
CopyMem(newPtr, ptr, size);
|
||||
FreePool(ptr);
|
||||
Free(ptr);
|
||||
return newPtr;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#include <efi.h>
|
||||
#include <efilib.h>
|
||||
#include <x86_64\pe.h>
|
||||
#define malloc AllocatePool
|
||||
#define free FreePool
|
||||
#include <immintrin.h>
|
||||
#include <compiler_defines.h>
|
||||
#include "bink.h"
|
||||
@@ -78,63 +76,127 @@ EFI_GRAPHICS_OUTPUT_PROTOCOL* gop;
|
||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL* framebuffer;
|
||||
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION* mode_info;
|
||||
|
||||
#define SIMD_ALIGNMENT_BYTES 32
|
||||
#define ALIGN_MASK (~(SIMD_ALIGNMENT_BYTES - 1))
|
||||
#define ALIGN_CAST(ptr) ((UINTN)(ptr))
|
||||
struct BlockHeader {
|
||||
uint32_t magic;
|
||||
size_t size;
|
||||
bool free;
|
||||
BlockHeader* next;
|
||||
};
|
||||
|
||||
void* Malloc(size_t size) {
|
||||
PRINT(L"Malloc called with size: %u\n", size);
|
||||
constexpr uint32_t MAGIC_ALLOCATED = 0xCAFEBABE;
|
||||
constexpr uint32_t MAGIC_FREED = 0xDEADBEEF;
|
||||
|
||||
VOID *OriginalPtr;
|
||||
VOID **AlignedPtrLoc;
|
||||
UINTN TotalSize;
|
||||
UINTN Addr;
|
||||
static void* g_memoryPool = 0;
|
||||
static size_t g_poolSize = 0;
|
||||
static struct BlockHeader* g_freeList = 0;
|
||||
|
||||
// Calculate total size:
|
||||
// 1. User requested size
|
||||
// 2. Maximum space for alignment padding (SIMD_ALIGNMENT_BYTES - 1)
|
||||
// 3. Space to store the original pointer for freeing (sizeof(VOID*))
|
||||
TotalSize = size + SIMD_ALIGNMENT_BYTES - 1 + sizeof(VOID*);
|
||||
#define AVX_ALIGN 32
|
||||
#define ALIGN_UP(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
|
||||
|
||||
// 1. Allocate a larger block of memory using the UEFI Pool service.
|
||||
if (EFI_ERROR(gBS->AllocatePool(EfiLoaderData, TotalSize, &OriginalPtr))) {
|
||||
return NULL; // Allocation failed
|
||||
void InitAllocatorFromBuffer(void* buffer, size_t size) {
|
||||
PRINT(L"Initializing custom allocator with buffer %p of size %ull\n", buffer, size);
|
||||
if (!buffer || size <= sizeof(struct BlockHeader)) {
|
||||
Print(L"Invalid buffer or size for allocator initialization\n");
|
||||
gBS->Stall(5 * 1000000); // 5 seconds
|
||||
gRT->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL);
|
||||
}
|
||||
|
||||
// 2. Calculate the aligned address.
|
||||
// Start the alignment calculation *after* the space reserved for the original pointer.
|
||||
Addr = ALIGN_CAST(OriginalPtr) + sizeof(VOID*);
|
||||
g_memoryPool = buffer;
|
||||
g_poolSize = size;
|
||||
|
||||
// Align the address up to the nearest SIMD_ALIGNMENT_BYTES multiple:
|
||||
// (Addr + Alignment - 1) & ~(Alignment - 1)
|
||||
Addr = (Addr + SIMD_ALIGNMENT_BYTES - 1) & ALIGN_MASK;
|
||||
g_freeList = (struct BlockHeader*)buffer;
|
||||
g_freeList->magic = MAGIC_ALLOCATED;
|
||||
g_freeList->size = size - sizeof(struct BlockHeader);
|
||||
g_freeList->free = true;
|
||||
g_freeList->next = 0;
|
||||
}
|
||||
|
||||
// 3. Store the original pointer (OriginalPtr) immediately before the aligned address (Addr).
|
||||
// The location is 8 bytes (sizeof(VOID*)) behind the start of the aligned block.
|
||||
AlignedPtrLoc = (VOID**)(Addr - sizeof(VOID*));
|
||||
*AlignedPtrLoc = OriginalPtr;
|
||||
static bool IsPointerInPool(void* ptr) {
|
||||
return ptr >= g_memoryPool &&
|
||||
ptr < (void*)((uint8_t*)g_memoryPool + g_poolSize);
|
||||
}
|
||||
|
||||
// 4. Return the aligned address to the caller.
|
||||
return (VOID*)Addr;
|
||||
void* Malloc(size_t size) {
|
||||
PRINT(L"Allocating memory of size %ull\n", size);
|
||||
size = ALIGN_UP(size, AVX_ALIGN); // ensure AVX alignment
|
||||
struct BlockHeader* best = 0;
|
||||
struct BlockHeader* bestPrev = 0;
|
||||
struct BlockHeader* prev = 0;
|
||||
struct BlockHeader* current = g_freeList;
|
||||
|
||||
while (current) {
|
||||
if (current->free && current->size >= size) {
|
||||
if (!best || current->size < best->size) {
|
||||
best = current;
|
||||
bestPrev = prev;
|
||||
}
|
||||
}
|
||||
prev = current;
|
||||
current = current->next;
|
||||
}
|
||||
|
||||
if (!best) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uintptr_t payloadAddr = (uintptr_t)(best + 1);
|
||||
uintptr_t alignedAddr = ALIGN_UP(payloadAddr, AVX_ALIGN);
|
||||
size_t padding = alignedAddr - payloadAddr;
|
||||
|
||||
size_t totalNeeded = size + padding;
|
||||
if (best->size < totalNeeded) {
|
||||
return 0; // not enough space
|
||||
}
|
||||
|
||||
size_t remaining = best->size - totalNeeded;
|
||||
|
||||
if (remaining > sizeof(struct BlockHeader)) {
|
||||
struct BlockHeader* newBlock = (struct BlockHeader*)((uint8_t*)(best + 1) + totalNeeded);
|
||||
newBlock->magic = MAGIC_ALLOCATED;
|
||||
newBlock->size = remaining - sizeof(struct BlockHeader);
|
||||
newBlock->free = true;
|
||||
newBlock->next = best->next;
|
||||
best->next = newBlock;
|
||||
}
|
||||
|
||||
best->magic = MAGIC_ALLOCATED;
|
||||
best->free = false;
|
||||
best->size = totalNeeded;
|
||||
|
||||
return (void*)alignedAddr;
|
||||
}
|
||||
|
||||
void Free(void* ptr) {
|
||||
PRINT(L"Free called with ptr: %p\n", ptr);
|
||||
PRINT(L"Freeing memory at %p\n", ptr);
|
||||
if (!ptr || !IsPointerInPool(ptr)) return;
|
||||
|
||||
VOID **OriginalPtrLoc;
|
||||
VOID *OriginalPtr;
|
||||
struct BlockHeader* block = (struct BlockHeader*)((uint8_t*)ptr - sizeof(struct BlockHeader));
|
||||
|
||||
if (ptr == NULL) {
|
||||
return;
|
||||
while (block->magic != MAGIC_ALLOCATED && (uint8_t*)block > (uint8_t*)g_memoryPool) {
|
||||
block = (struct BlockHeader*)((uint8_t*)block - 1); // backtrack if pointer was aligned forward
|
||||
}
|
||||
|
||||
// 1. Calculate the address where the original pointer is stored.
|
||||
// It is located sizeof(VOID*) bytes immediately before the AlignedPtr.
|
||||
OriginalPtrLoc = (VOID**)(ALIGN_CAST(ptr) - sizeof(VOID*));
|
||||
OriginalPtr = *OriginalPtrLoc;
|
||||
if (!IsPointerInPool(block) || block->magic != MAGIC_ALLOCATED) {
|
||||
Print(L"Invalid pointer passed to Free: %p\n", ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. Use the UEFI Boot Service to free the original, unaligned block.
|
||||
gBS->FreePool(OriginalPtr);
|
||||
block->magic = MAGIC_FREED;
|
||||
block->free = true;
|
||||
|
||||
// Coalesce
|
||||
struct BlockHeader* current = g_freeList;
|
||||
while (current) {
|
||||
if (current->free) {
|
||||
struct BlockHeader* next = current->next;
|
||||
while (next && next->free) {
|
||||
current->size += sizeof(struct BlockHeader) + next->size;
|
||||
current->next = next->next;
|
||||
next = next->next;
|
||||
}
|
||||
}
|
||||
current = current->next;
|
||||
}
|
||||
}
|
||||
|
||||
EFI_STATUS InitializeGop() {
|
||||
@@ -584,7 +646,7 @@ bool LoadBinkDLL(EFI_FILE_HANDLE volume) {
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
void Blit1280x720_AVX2_NT(
|
||||
void Blit_AVX2_NT(
|
||||
EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop,
|
||||
uint32_t *src,
|
||||
UINTN src_width, UINTN src_height
|
||||
@@ -677,6 +739,27 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) {
|
||||
SystemTable->BootServices->SetWatchdogTimer(0, 0, 0, NULL);
|
||||
Print(L"Hello, World!\n");
|
||||
|
||||
VOID* HeapMemory = NULL;
|
||||
UINTN AllocationSize = 512 * 1024 * 1024; // 512 MB
|
||||
UINTN Pages = AllocationSize / 4096; // UEFI page size is 4KB
|
||||
|
||||
EFI_STATUS Status = gBS->AllocatePages(
|
||||
AllocateAnyPages,
|
||||
EfiLoaderData,
|
||||
Pages,
|
||||
(EFI_PHYSICAL_ADDRESS*)&HeapMemory
|
||||
);
|
||||
|
||||
if (EFI_ERROR(Status)) {
|
||||
Print(L"Failed to allocate memory pool pages: %r\n", Status);
|
||||
gBS->Stall(5 * 1000 * 1000);
|
||||
gST->RuntimeServices->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL);
|
||||
return Status;
|
||||
}
|
||||
|
||||
InitAllocatorFromBuffer(HeapMemory, AllocationSize);
|
||||
Print(L"Custom allocator initialized\n");
|
||||
|
||||
InitializeGop();
|
||||
Print(L"GOP initialized\n");
|
||||
|
||||
@@ -779,7 +862,7 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) {
|
||||
|
||||
pBinkNextFrame(bink);
|
||||
|
||||
Blit1280x720_AVX2_NT(gop, framebuffer, width, height);
|
||||
Blit_AVX2_NT(gop, framebuffer, width, height);
|
||||
|
||||
Print(L"\rframe %d done", bink->FrameNum);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user