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
|
#pragma endregion
|
||||||
|
|
||||||
extern int stricmp(const char *s1, const char *s2);
|
extern int stricmp(const char *s1, const char *s2);
|
||||||
|
extern void* Malloc(size_t size);
|
||||||
|
extern void Free(void* ptr);
|
||||||
|
|
||||||
// --- Memory ---
|
// --- Memory ---
|
||||||
HANDLE HeapCreate(DWORD, SIZE_T, SIZE_T) {
|
HANDLE HeapCreate(DWORD, SIZE_T, SIZE_T) {
|
||||||
@@ -179,24 +181,24 @@ BOOL HeapDestroy(HANDLE) {
|
|||||||
|
|
||||||
LPVOID HeapAlloc(HANDLE, DWORD, SIZE_T size) {
|
LPVOID HeapAlloc(HANDLE, DWORD, SIZE_T size) {
|
||||||
PRINT(L"Called: HeapAlloc with size: %ull\n", size);
|
PRINT(L"Called: HeapAlloc with size: %ull\n", size);
|
||||||
return AllocatePool(size);
|
return Malloc(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL HeapFree(HANDLE, DWORD, LPVOID ptr) {
|
BOOL HeapFree(HANDLE, DWORD, LPVOID ptr) {
|
||||||
PRINT(L"Called: HeapFree with ptr: %p\n", ptr);
|
PRINT(L"Called: HeapFree with ptr: %p\n", ptr);
|
||||||
if (ptr)
|
if (ptr)
|
||||||
FreePool(ptr);
|
Free(ptr);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
LPVOID HeapReAlloc(HANDLE, DWORD, LPVOID ptr, SIZE_T size) {
|
LPVOID HeapReAlloc(HANDLE, DWORD, LPVOID ptr, SIZE_T size) {
|
||||||
PRINT(L"Called: HeapReAlloc with size: %ull and ptr: %p\n", size, ptr);
|
PRINT(L"Called: HeapReAlloc with size: %ull and ptr: %p\n", size, ptr);
|
||||||
if (!ptr) return AllocatePool(size);
|
if (!ptr) return Malloc(size);
|
||||||
LPVOID newPtr = AllocatePool(size);
|
LPVOID newPtr = Malloc(size);
|
||||||
if (!newPtr) return nullptr;
|
if (!newPtr) return nullptr;
|
||||||
// No original size info; can't fully emulate, user must handle
|
// No original size info; can't fully emulate, user must handle
|
||||||
CopyMem(newPtr, ptr, size);
|
CopyMem(newPtr, ptr, size);
|
||||||
FreePool(ptr);
|
Free(ptr);
|
||||||
return newPtr;
|
return newPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
#include <efi.h>
|
#include <efi.h>
|
||||||
#include <efilib.h>
|
#include <efilib.h>
|
||||||
#include <x86_64\pe.h>
|
#include <x86_64\pe.h>
|
||||||
#define malloc AllocatePool
|
|
||||||
#define free FreePool
|
|
||||||
#include <immintrin.h>
|
#include <immintrin.h>
|
||||||
#include <compiler_defines.h>
|
#include <compiler_defines.h>
|
||||||
#include "bink.h"
|
#include "bink.h"
|
||||||
@@ -78,63 +76,127 @@ EFI_GRAPHICS_OUTPUT_PROTOCOL* gop;
|
|||||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL* framebuffer;
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL* framebuffer;
|
||||||
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION* mode_info;
|
EFI_GRAPHICS_OUTPUT_MODE_INFORMATION* mode_info;
|
||||||
|
|
||||||
#define SIMD_ALIGNMENT_BYTES 32
|
struct BlockHeader {
|
||||||
#define ALIGN_MASK (~(SIMD_ALIGNMENT_BYTES - 1))
|
uint32_t magic;
|
||||||
#define ALIGN_CAST(ptr) ((UINTN)(ptr))
|
size_t size;
|
||||||
|
bool free;
|
||||||
|
BlockHeader* next;
|
||||||
|
};
|
||||||
|
|
||||||
void* Malloc(size_t size) {
|
constexpr uint32_t MAGIC_ALLOCATED = 0xCAFEBABE;
|
||||||
PRINT(L"Malloc called with size: %u\n", size);
|
constexpr uint32_t MAGIC_FREED = 0xDEADBEEF;
|
||||||
|
|
||||||
VOID *OriginalPtr;
|
static void* g_memoryPool = 0;
|
||||||
VOID **AlignedPtrLoc;
|
static size_t g_poolSize = 0;
|
||||||
UINTN TotalSize;
|
static struct BlockHeader* g_freeList = 0;
|
||||||
UINTN Addr;
|
|
||||||
|
|
||||||
// Calculate total size:
|
#define AVX_ALIGN 32
|
||||||
// 1. User requested size
|
#define ALIGN_UP(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
|
||||||
// 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*);
|
|
||||||
|
|
||||||
// 1. Allocate a larger block of memory using the UEFI Pool service.
|
void InitAllocatorFromBuffer(void* buffer, size_t size) {
|
||||||
if (EFI_ERROR(gBS->AllocatePool(EfiLoaderData, TotalSize, &OriginalPtr))) {
|
PRINT(L"Initializing custom allocator with buffer %p of size %ull\n", buffer, size);
|
||||||
return NULL; // Allocation failed
|
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.
|
g_memoryPool = buffer;
|
||||||
// Start the alignment calculation *after* the space reserved for the original pointer.
|
g_poolSize = size;
|
||||||
Addr = ALIGN_CAST(OriginalPtr) + sizeof(VOID*);
|
|
||||||
|
|
||||||
// Align the address up to the nearest SIMD_ALIGNMENT_BYTES multiple:
|
g_freeList = (struct BlockHeader*)buffer;
|
||||||
// (Addr + Alignment - 1) & ~(Alignment - 1)
|
g_freeList->magic = MAGIC_ALLOCATED;
|
||||||
Addr = (Addr + SIMD_ALIGNMENT_BYTES - 1) & ALIGN_MASK;
|
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).
|
static bool IsPointerInPool(void* ptr) {
|
||||||
// The location is 8 bytes (sizeof(VOID*)) behind the start of the aligned block.
|
return ptr >= g_memoryPool &&
|
||||||
AlignedPtrLoc = (VOID**)(Addr - sizeof(VOID*));
|
ptr < (void*)((uint8_t*)g_memoryPool + g_poolSize);
|
||||||
*AlignedPtrLoc = OriginalPtr;
|
}
|
||||||
|
|
||||||
// 4. Return the aligned address to the caller.
|
void* Malloc(size_t size) {
|
||||||
return (VOID*)Addr;
|
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) {
|
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;
|
struct BlockHeader* block = (struct BlockHeader*)((uint8_t*)ptr - sizeof(struct BlockHeader));
|
||||||
VOID *OriginalPtr;
|
|
||||||
|
|
||||||
if (ptr == NULL) {
|
while (block->magic != MAGIC_ALLOCATED && (uint8_t*)block > (uint8_t*)g_memoryPool) {
|
||||||
return;
|
block = (struct BlockHeader*)((uint8_t*)block - 1); // backtrack if pointer was aligned forward
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. Calculate the address where the original pointer is stored.
|
if (!IsPointerInPool(block) || block->magic != MAGIC_ALLOCATED) {
|
||||||
// It is located sizeof(VOID*) bytes immediately before the AlignedPtr.
|
Print(L"Invalid pointer passed to Free: %p\n", ptr);
|
||||||
OriginalPtrLoc = (VOID**)(ALIGN_CAST(ptr) - sizeof(VOID*));
|
return;
|
||||||
OriginalPtr = *OriginalPtrLoc;
|
}
|
||||||
|
|
||||||
// 2. Use the UEFI Boot Service to free the original, unaligned block.
|
block->magic = MAGIC_FREED;
|
||||||
gBS->FreePool(OriginalPtr);
|
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() {
|
EFI_STATUS InitializeGop() {
|
||||||
@@ -584,7 +646,7 @@ bool LoadBinkDLL(EFI_FILE_HANDLE volume) {
|
|||||||
}
|
}
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
void Blit1280x720_AVX2_NT(
|
void Blit_AVX2_NT(
|
||||||
EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop,
|
EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop,
|
||||||
uint32_t *src,
|
uint32_t *src,
|
||||||
UINTN src_width, UINTN src_height
|
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);
|
SystemTable->BootServices->SetWatchdogTimer(0, 0, 0, NULL);
|
||||||
Print(L"Hello, World!\n");
|
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();
|
InitializeGop();
|
||||||
Print(L"GOP initialized\n");
|
Print(L"GOP initialized\n");
|
||||||
|
|
||||||
@@ -779,7 +862,7 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) {
|
|||||||
|
|
||||||
pBinkNextFrame(bink);
|
pBinkNextFrame(bink);
|
||||||
|
|
||||||
Blit1280x720_AVX2_NT(gop, framebuffer, width, height);
|
Blit_AVX2_NT(gop, framebuffer, width, height);
|
||||||
|
|
||||||
Print(L"\rframe %d done", bink->FrameNum);
|
Print(L"\rframe %d done", bink->FrameNum);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user