diff --git a/.vs/ProjectSettings.json b/.vs/ProjectSettings.json deleted file mode 100644 index b11371a..0000000 --- a/.vs/ProjectSettings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "CurrentProjectSetting": "No Configurations" -} \ No newline at end of file diff --git a/.vs/VSWorkspaceState.json b/.vs/VSWorkspaceState.json deleted file mode 100644 index 9568b22..0000000 --- a/.vs/VSWorkspaceState.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "ExpandedNodes": [ - "" - ], - "PreviewInSolutionExplorer": false -} \ No newline at end of file diff --git a/.vs/binkx86/CopilotIndices/17.14.1091.29919/SemanticSymbols.db b/.vs/binkx86/CopilotIndices/17.14.1091.29919/SemanticSymbols.db deleted file mode 100644 index 330f6d0..0000000 Binary files a/.vs/binkx86/CopilotIndices/17.14.1091.29919/SemanticSymbols.db and /dev/null differ diff --git a/.vs/binkx86/FileContentIndex/6451e624-7538-4cf0-b10b-7f9fd5b494e2.vsidx b/.vs/binkx86/FileContentIndex/6451e624-7538-4cf0-b10b-7f9fd5b494e2.vsidx deleted file mode 100644 index a9bc7fa..0000000 Binary files a/.vs/binkx86/FileContentIndex/6451e624-7538-4cf0-b10b-7f9fd5b494e2.vsidx and /dev/null differ diff --git a/.vs/binkx86/v17/.wsuo b/.vs/binkx86/v17/.wsuo deleted file mode 100644 index 0912c4a..0000000 Binary files a/.vs/binkx86/v17/.wsuo and /dev/null differ diff --git a/.vs/binkx86/v17/Browse.VC.db b/.vs/binkx86/v17/Browse.VC.db deleted file mode 100644 index 64381ae..0000000 Binary files a/.vs/binkx86/v17/Browse.VC.db and /dev/null differ diff --git a/.vs/binkx86/v17/DocumentLayout.json b/.vs/binkx86/v17/DocumentLayout.json deleted file mode 100644 index 74a3ed6..0000000 --- a/.vs/binkx86/v17/DocumentLayout.json +++ /dev/null @@ -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}" - } - ] - } - ] - } - ] -} \ No newline at end of file diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite deleted file mode 100644 index e19a856..0000000 Binary files a/.vs/slnx.sqlite and /dev/null differ diff --git a/OVMF/OVMF_VARS_4M.fd b/OVMF/OVMF_VARS_4M.fd index fcca96c..aed955f 100644 Binary files a/OVMF/OVMF_VARS_4M.fd and b/OVMF/OVMF_VARS_4M.fd differ diff --git a/fatroot/EFI/Boot/BootX64.efi b/fatroot/EFI/Boot/BootX64.efi index 5b62a74..818832e 100644 Binary files a/fatroot/EFI/Boot/BootX64.efi and b/fatroot/EFI/Boot/BootX64.efi differ diff --git a/kernel32.cpp b/kernel32.cpp index 1a420d2..5b16e97 100644 --- a/kernel32.cpp +++ b/kernel32.cpp @@ -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; } diff --git a/main.cpp b/main.cpp index 7a3f1ab..e941ed2 100644 --- a/main.cpp +++ b/main.cpp @@ -1,8 +1,6 @@ #include #include #include -#define malloc AllocatePool -#define free FreePool #include #include #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); }