diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..57e345a --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.vs/ +*.efi +*.obj +qemu.log diff --git a/.vscode/settings.json b/.vscode/settings.json index 432dc97..47f8d30 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,5 +4,11 @@ "chrono": "cpp", "system_error": "cpp", "xlocale": "cpp" + }, + "files.exclude": { + "**/*.rpyc": true, + "**/*.rpa": true, + "**/*.rpymc": true, + "**/cache/": true } } \ No newline at end of file diff --git a/OVMF/OVMF_VARS_4M.fd b/OVMF/OVMF_VARS_4M.fd index 0d40440..fcca96c 100644 Binary files a/OVMF/OVMF_VARS_4M.fd and b/OVMF/OVMF_VARS_4M.fd differ diff --git a/build.bat b/build.bat index 8ae8484..0d18ae5 100644 --- a/build.bat +++ b/build.bat @@ -5,5 +5,5 @@ cl user32.cpp /c /Brepro /GS- /GR- /Oi /EHs-c- /nologo /Zc:threadSafeInit- /I in cl ole32.cpp /c /Brepro /GS- /GR- /Oi /EHs-c- /nologo /Zc:threadSafeInit- /I include || pause && exit /b cl kernel32.cpp /Brepro /c /GS- /GR- /Oi /EHs-c- /nologo /Zc:threadSafeInit- /I include || pause && exit /b cl winmm.cpp /c /Brepro /GS- /GR- /Oi /EHs-c- /nologo /Zc:threadSafeInit- /I include || pause && exit /b -link helpers.obj main.obj user32.obj ole32.obj kernel32.obj winmm.obj /Brepro /STACK:16777216 /NODEFAULTLIB /ENTRY:efi_main /NOLOGO /SUBSYSTEM:EFI_APPLICATION /OUT:BootX64.efi efilib.lib /MACHINE:X64 || pause && exit /b +link helpers.obj main.obj user32.obj ole32.obj kernel32.obj winmm.obj /Brepro /STACK:0x400000,0x100000 /NODEFAULTLIB /ENTRY:efi_main /NOLOGO /SUBSYSTEM:EFI_APPLICATION /OUT:BootX64.efi efilib.lib /MACHINE:X64 || pause && exit /b copy /B /Y BootX64.efi fatroot\EFI\Boot\ diff --git a/fatroot/EFI/Boot/BootX64.efi b/fatroot/EFI/Boot/BootX64.efi index 3f45672..5b62a74 100644 Binary files a/fatroot/EFI/Boot/BootX64.efi and b/fatroot/EFI/Boot/BootX64.efi differ diff --git a/fatroot/video2.bk2 b/fatroot/video2.bk2 new file mode 100644 index 0000000..39217ac Binary files /dev/null and b/fatroot/video2.bk2 differ diff --git a/kernel32.cpp b/kernel32.cpp index 002c494..1a420d2 100644 --- a/kernel32.cpp +++ b/kernel32.cpp @@ -164,10 +164,12 @@ typedef DWORD LCID; typedef DWORD LCTYPE; #pragma endregion +extern int stricmp(const char *s1, const char *s2); + // --- Memory --- HANDLE HeapCreate(DWORD, SIZE_T, SIZE_T) { PRINT(L"Called: HeapCreate\n"); - return nullptr; + return reinterpret_cast(1); } BOOL HeapDestroy(HANDLE) { @@ -272,13 +274,122 @@ HMODULE GetModuleHandleA(LPCSTR name) { return reinterpret_cast(1); } +void SleepConditionVariableCS(void*, void*, unsigned) { + PRINT(L"Called: SleepConditionVariableCS\n"); +} + +BOOL TryEnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection) { + PRINT(L"Called: TryEnterCriticalSection\n"); + return TRUE; +} + +BOOL GetLogicalProcessorInformation(void*, void*) { + PRINT(L"Called: GetLogicalProcessorInformation\n"); + return FALSE; +} + +void InitializeConditionVariable(void* cond) { + PRINT(L"Called: InitializeConditionVariable\n"); + // No-op stub +} + +int timeBeginPeriod(UINT period) { + PRINT(L"Called: timeBeginPeriod\n"); + return 0; +} + +int timeEndPeriod(UINT period) { + PRINT(L"Called: timeEndPeriod\n"); + return 0; +} + +void WakeConditionVariable(void* cond) { + PRINT(L"Called: WakeConditionVariable\n"); + // No-op stub +} + +void WakeAllConditionVariable(void* cond) { + PRINT(L"Called: WakeAllConditionVariable\n"); + // No-op stub +} + +BOOL InitializeCriticalSectionAndSpinCount(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount) { + PRINT(L"Called: InitializeCriticalSectionAndSpinCount\n"); + return TRUE; +} + +int waveOutOpen() { PRINT(L"Called: waveOutOpen\n"); return 0; } +int waveOutPause() { PRINT(L"Called: waveOutPause\n"); return 0; } +int waveOutPrepareHeader() { PRINT(L"Called: waveOutPrepareHeader\n"); return 0; } +int waveOutUnprepareHeader() { PRINT(L"Called: waveOutUnprepareHeader\n"); return 0; } +int waveOutWrite() { PRINT(L"Called: waveOutWrite\n"); return 0; } +int waveOutReset() { PRINT(L"Called: waveOutReset\n"); return 0; } +int waveOutClose() { PRINT(L"Called: waveOutClose\n"); return 0; } +int waveOutRestart() { PRINT(L"Called: waveOutRestart\n"); return 0; } +int waveOutSetVolume() { PRINT(L"Called: waveOutSetVolume\n"); return 0; } + FARPROC GetProcAddress(HMODULE, LPCSTR func) { - PRINT(L"Called: GetProcAddress with string: %a\n", func); + PRINT(L"Called: GetProcAddress with func: %a\n", func); + if (stricmp(func, "waveOutOpen") == 0) { + return reinterpret_cast(waveOutOpen); + } + else if (stricmp(func, "waveOutPause") == 0) { + return reinterpret_cast(waveOutPause); + } + else if (stricmp(func, "waveOutPrepareHeader") == 0) { + return reinterpret_cast(waveOutPrepareHeader); + } + else if (stricmp(func, "waveOutUnprepareHeader") == 0) { + return reinterpret_cast(waveOutUnprepareHeader); + } + else if (stricmp(func, "waveOutWrite") == 0) { + return reinterpret_cast(waveOutWrite); + } + else if (stricmp(func, "waveOutReset") == 0) { + return reinterpret_cast(waveOutReset); + } + else if (stricmp(func, "waveOutClose") == 0) { + return reinterpret_cast(waveOutClose); + } + else if (stricmp(func, "waveOutRestart") == 0) { + return reinterpret_cast(waveOutRestart); + } + else if (stricmp(func, "waveOutSetVolume") == 0) { + return reinterpret_cast(waveOutSetVolume); + } + else if (stricmp(func, "SleepConditionVariableCS") == 0) { + return reinterpret_cast(SleepConditionVariableCS); + } + else if (stricmp(func, "TryEnterCriticalSection") == 0) { + return reinterpret_cast(TryEnterCriticalSection); + } + else if (stricmp(func, "GetLogicalProcessorInformation") == 0) { + return reinterpret_cast(GetLogicalProcessorInformation); + } + else if (stricmp(func, "InitializeConditionVariable") == 0) { + return reinterpret_cast(InitializeConditionVariable); + } + else if (stricmp(func, "timeBeginPeriod") == 0) { + return reinterpret_cast(timeBeginPeriod); + } + else if (stricmp(func, "timeEndPeriod") == 0) { + return reinterpret_cast(timeEndPeriod); + } + else if (stricmp(func, "WakeConditionVariable") == 0) { + return reinterpret_cast(WakeConditionVariable); + } + else if (stricmp(func, "InitializeCriticalSectionAndSpinCount") == 0) { + return reinterpret_cast(InitializeCriticalSectionAndSpinCount); + } + else if (stricmp(func, "WakeAllConditionVariable") == 0) { + return reinterpret_cast(WakeAllConditionVariable); + } + PRINT(L"Unknown function requested!\n"); return nullptr; } -HMODULE LoadLibraryA(LPCSTR) { - PRINT(L"Called: LoadLibraryA\n"); +HMODULE LoadLibraryA(LPCSTR name) { + PRINT(L"Called: LoadLibraryA with name: %a\n", name); return reinterpret_cast(1); } @@ -293,11 +404,6 @@ void ExitProcess(UINT uExitCode) { while(1); // halt } -BOOL InitializeCriticalSectionAndSpinCount(LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount) { - PRINT(L"Called: InitializeCriticalSectionAndSpinCount\n"); - return TRUE; -} - DWORD GetSystemDirectoryA(LPSTR lpBuffer, DWORD uSize) { PRINT(L"Called: GetSystemDirectoryA\n"); if (lpBuffer && uSize > 0) { @@ -704,8 +810,6 @@ int MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int return convertedCount; } -extern int stricmp(const char *s1, const char *s2); - void* ResolveKernel32(const char* functionName) { if (stricmp(functionName, "HeapCreate") == 0) { return HeapCreate; diff --git a/main.cpp b/main.cpp index cdc0f01..7a3f1ab 100644 --- a/main.cpp +++ b/main.cpp @@ -78,6 +78,65 @@ 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)) + +void* Malloc(size_t size) { + PRINT(L"Malloc called with size: %u\n", size); + + VOID *OriginalPtr; + VOID **AlignedPtrLoc; + UINTN TotalSize; + UINTN Addr; + + // 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*); + + // 1. Allocate a larger block of memory using the UEFI Pool service. + if (EFI_ERROR(gBS->AllocatePool(EfiLoaderData, TotalSize, &OriginalPtr))) { + return NULL; // Allocation failed + } + + // 2. Calculate the aligned address. + // Start the alignment calculation *after* the space reserved for the original pointer. + Addr = ALIGN_CAST(OriginalPtr) + sizeof(VOID*); + + // Align the address up to the nearest SIMD_ALIGNMENT_BYTES multiple: + // (Addr + Alignment - 1) & ~(Alignment - 1) + Addr = (Addr + SIMD_ALIGNMENT_BYTES - 1) & ALIGN_MASK; + + // 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; + + // 4. Return the aligned address to the caller. + return (VOID*)Addr; +} + +void Free(void* ptr) { + PRINT(L"Free called with ptr: %p\n", ptr); + + VOID **OriginalPtrLoc; + VOID *OriginalPtr; + + if (ptr == NULL) { + return; + } + + // 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; + + // 2. Use the UEFI Boot Service to free the original, unaligned block. + gBS->FreePool(OriginalPtr); +} + EFI_STATUS InitializeGop() { EFI_STATUS Status; @@ -135,7 +194,7 @@ void* LoadFile(EFI_FILE_HANDLE volume, const wchar_t* filename) { return NULL; } - VOID* file_buffer = AllocatePool(file_size); + VOID* file_buffer = Malloc(file_size); if (!file_buffer) { return NULL; } SetMem(file_buffer, file_size, 0); @@ -148,13 +207,13 @@ void* LoadFile(EFI_FILE_HANDLE volume, const wchar_t* filename) { if (EFI_ERROR(file_loading_status)) { Print(L"Failed to read file: %r\n", file_loading_status); // Free the allocated memory if the read fails - FreePool(file_buffer); + Free(file_buffer); return NULL; } if (read_size != file_size) { Print(L"Read size mismatch: expected %llu, got %llu\n", file_size, read_size); - FreePool(file_buffer); + Free(file_buffer); return NULL; } @@ -339,7 +398,7 @@ void* LoadPeImage(void* buffer) { // Allocate memory for the full image uint64_t imageSize = pe->OptionalHeader.SizeOfImage; - uint64_t imageBase = (uint64_t)AllocatePool(imageSize); + uint64_t imageBase = (uint64_t)Malloc(imageSize); if (!imageBase) { Print(L"Failed to allocate image memory\n"); return NULL; @@ -453,7 +512,7 @@ bool LoadBinkDLL(EFI_FILE_HANDLE volume) { } void* binkBase = LoadPeImage(binkFileBuffer); - FreePool(binkFileBuffer); // Free the file buffer, as LoadPeImage copied it. + Free(binkFileBuffer); // Free the file buffer, as LoadPeImage copied it. if (!binkBase) { return false; } @@ -613,31 +672,6 @@ EFI_STATUS SetMaxResolution(EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop) { extern "C" void enable_avx2(); -void* Malloc(size_t size) { - PRINT(L"Malloc called with size: %u\n", size); - - void* addr = AllocatePool(size); - if (!addr) { - PRINT(L"Allocation failed!\n"); - return NULL; - } - - ZeroMem(addr, size); - - return addr; -} - -void Free(void* ptr) { - PRINT(L"Free called with ptr: %p\n", ptr); - - if (!ptr) { - PRINT(L"Pointer is NULL, nothing to free!\n"); - return; - } - - FreePool(ptr); -} - EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) { InitializeLib(ImageHandle, SystemTable); SystemTable->BootServices->SetWatchdogTimer(0, 0, 0, NULL); @@ -662,11 +696,9 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) { Print(L"Bink function pointers initialized (propably)!\n"); - pBinkSetSoundSystem(0, 0); // no sound + //pBinkSetSoundSystem(pBinkOpenWaveOut, 0); pBinkSetMemory((BINKMEMALLOC)Malloc, (BINKMEMFREE)Free); // debug allocators pBinkSetIO(0); // no io - //pBinkSetTimerRead() // r.i.p. my version of the sdk - // UPDATE: spoofed in kernel32.cpp Print(L"BinkSet* called\n"); @@ -675,19 +707,19 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) { Print(L"Video file loaded into memory\n"); HBINK bink = NULL; - bink = pBinkOpen((const char*)video_file, BINKFROMMEMORY); + bink = pBinkOpen((const char*)video_file, BINKFROMMEMORY | BINKNOSKIP | BINKNOTHREADEDIO); Print(L"Opened Bink!\n"); int width = bink->Width, height = bink->Height; Print(L"Width: %d, Height: %d\n", width, height); // Allocate framebuffer - uint32_t* framebuffer = (uint32_t*)AllocatePool(width * height * sizeof(uint32_t)); + uint32_t* framebuffer = (uint32_t*)Malloc(width * height * sizeof(uint32_t)); if (!framebuffer) { Print(L"Failed to allocate framebuffer!\n"); gBS->Stall(5 * 1000 * 1000); pBinkClose(bink); - FreePool(video_file); + Free(video_file); return 1; } @@ -699,7 +731,7 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) { while (true) { // Check if the video is done if (bink->FrameNum >= bink->Frames) { - Print(L"Video playback finished!\n"); + Print(L"\nVideo playback finished!\n"); break; // exit the loop if the video is done } @@ -716,22 +748,18 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) { continue; // skip this frame } - // int code = pBinkDoFrame(bink); - // if (code != 0) { - // Print(L"BinkDoFrame failed!\n"); - // pBinkClose(bink); - // FreePool(video_file); - // gBS->Stall(5 * 1000 * 1000); - // gST->RuntimeServices->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL); - // return 1; - // } - pBinkDoFrame(bink); - // no error handling? that's right! - // because it uses SEH internally and i don't have the will power to tackle that - // no SEH handling = #GP on throw, #GP on throw = no error handling, no error handling = no video + int code = pBinkDoFrame(bink); + if (code != 0) { + Print(L"BinkDoFrame failed!\n"); + pBinkClose(bink); + Free(video_file); + gBS->Stall(5 * 1000 * 1000); + gST->RuntimeServices->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL); + return 1; + } // Copy frame to our buffer - int code = pBinkCopyToBuffer( + code = pBinkCopyToBuffer( bink, framebuffer, width * 4, @@ -743,7 +771,7 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) { if (code != 0 && code != 1) { Print(L"BinkCopyToBuffer failed!\n"); pBinkClose(bink); - FreePool(video_file); + Free(video_file); gBS->Stall(5 * 1000 * 1000); gST->RuntimeServices->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL); return 1; @@ -756,14 +784,14 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) { Print(L"\rframe %d done", bink->FrameNum); } - Print(L"\nSkipped frames: %u\n", skipped_frames); + Print(L"Skipped frames: %u\n", skipped_frames); pBinkClose(bink); - FreePool(video_file); - FreePool(framebuffer); + Free(video_file); + Free(framebuffer); - Print(L"Exiting\n"); + Print(L"Exiting...\n"); gBS->Stall(5 * 1000 * 1000); gST->RuntimeServices->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL);