From 28dad177a0344a150f262652b24fae3b357a2eaf Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Sat, 4 Feb 2017 21:59:52 +0000 Subject: [PATCH] [BOOTLIB]: Begin adding support for transferring to newly loaded i386 image. svn path=/trunk/; revision=73687 --- reactos/boot/environ/CMakeLists.txt | 2 +- reactos/boot/environ/include/bl.h | 13 +++ reactos/boot/environ/lib/arch/i386/transfer.s | 81 ++++++++++++++ reactos/boot/environ/lib/misc/image.c | 100 +++++++++++++++++- 4 files changed, 192 insertions(+), 4 deletions(-) create mode 100644 reactos/boot/environ/lib/arch/i386/transfer.s diff --git a/reactos/boot/environ/CMakeLists.txt b/reactos/boot/environ/CMakeLists.txt index 2a049a179bb..5a63aff7bab 100644 --- a/reactos/boot/environ/CMakeLists.txt +++ b/reactos/boot/environ/CMakeLists.txt @@ -45,7 +45,7 @@ list(APPEND BOOTLIB_SOURCE if(ARCH STREQUAL "i386") list(APPEND BOOTLIB_ASM_SOURCE - #lib/arch/i386/foo.asm + lib/arch/i386/transfer.s ) list(APPEND BOOTLIB_SOURCE lib/arch/i386/arch.c diff --git a/reactos/boot/environ/include/bl.h b/reactos/boot/environ/include/bl.h index dc00685ca09..d7dd2df86ee 100644 --- a/reactos/boot/environ/include/bl.h +++ b/reactos/boot/environ/include/bl.h @@ -283,6 +283,7 @@ typedef enum _BL_MEMORY_TYPE BlLoaderPageDirectory = 0xD0000006, BlLoaderReferencePage = 0xD0000007, BlLoaderRamDisk = 0xD0000008, + BlLoaderArchData = 0xD0000009, BlLoaderData = 0xD000000A, BlLoaderRegistry = 0xD000000B, BlLoaderBlockMemory = 0xD000000C, @@ -1180,6 +1181,13 @@ typedef struct _BL_IMAGE_APPLICATION_ENTRY ULONG ImageSize; } BL_IMAGE_APPLICATION_ENTRY, *PBL_IMAGE_APPLICATION_ENTRY; +typedef struct _BL_IMAGE_PARAMETERS +{ + PVOID Buffer; + ULONG ActualSize; + ULONG BufferSize; +} BL_IMAGE_PARAMETERS, *PBL_IMAGE_PARAMETERS; + typedef struct _BL_DEFERRED_FONT_FILE { LIST_ENTRY ListEntry; @@ -1937,6 +1945,11 @@ BlpArchSwitchContext ( _In_ BL_ARCH_MODE NewMode ); +VOID +Archx86TransferTo32BitApplicationAsm ( + VOID + ); + /* MEMORY DESCRIPTOR ROUTINES ************************************************/ VOID diff --git a/reactos/boot/environ/lib/arch/i386/transfer.s b/reactos/boot/environ/lib/arch/i386/transfer.s new file mode 100644 index 00000000000..e3547bde888 --- /dev/null +++ b/reactos/boot/environ/lib/arch/i386/transfer.s @@ -0,0 +1,81 @@ +/* + * COPYRIGHT: See COPYING.ARM in the top level directory + * PROJECT: ReactOS UEFI Boot Library + * FILE: boot/environ/lib/arch/transfer.asm + * PURPOSE: Boot Library i386 Transfer Functions + * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org) + */ + +/* INCLUDES ******************************************************************/ + +#include +#include + +EXTERN _GdtRegister:DWORD +EXTERN _IdtRegister:DWORD +EXTERN _BootAppGdtRegister:DWORD +EXTERN _BootAppIdtRegister:DWORD +EXTERN _BootApp32Stack:DWORD +EXTERN _BootApp32EntryRoutine:DWORD +EXTERN _BootApp32Parameters:DWORD + +/* FUNCTIONS ****************************************************************/ +.code + +PUBLIC _Archx86TransferTo32BitApplicationAsm +_Archx86TransferTo32BitApplicationAsm: + + /* Save non-volatile registers */ + push ebp + push esi + push edi + push ebx + + /* Save data segments */ + push es + push ds + + /* Save the old stack */ + mov ebx, esp + + /* Save current GDT/IDT, then load new one */ + sgdt fword ptr _GdtRegister + sidt fword ptr _IdtRegister + lgdt fword ptr _BootAppGdtRegister + lidt fword ptr _BootAppIdtRegister + + /* Load the new stack */ + xor ebp, ebp + mov esp, _BootApp32Stack + + /* Push old stack onto new stack */ + push ebx + + /* Call the entry routine, passing the parameters */ + mov eax, _BootApp32Parameters + push eax + mov eax, _BootApp32EntryRoutine + call eax + + /* Retore old stack */ + pop ebx + mov esp, ebx + + /* Restore old GDT/IDT */ + lgdt fword ptr _GdtRegister + lidt fword ptr _IdtRegister + + /* Retore old segments */ + pop ds + pop es + + /* Retore non-volatiles */ + pop ebx + pop edi + pop esi + pop ebp + + /* All done */ + retn + +END diff --git a/reactos/boot/environ/lib/misc/image.c b/reactos/boot/environ/lib/misc/image.c index 55d9bd858df..d8dec2f557e 100644 --- a/reactos/boot/environ/lib/misc/image.c +++ b/reactos/boot/environ/lib/misc/image.c @@ -17,6 +17,14 @@ ULONG IapAllocatedTableEntries; ULONG IapTableEntries; PVOID* IapImageTable; +KDESCRIPTOR GdtRegister; +KDESCRIPTOR IdtRegister; +KDESCRIPTOR BootAppGdtRegister; +KDESCRIPTOR BootAppIdtRegister; +PVOID BootApp32EntryRoutine; +PVOID BootApp32Parameters; +PVOID BootApp32Stack; + /* FUNCTIONS *****************************************************************/ NTSTATUS @@ -1596,6 +1604,17 @@ BlpPdParseReturnArguments ( return STATUS_NOT_IMPLEMENTED; } +NTSTATUS +ImgpInitializeBootApplicationParameters ( + _In_ PBL_IMAGE_PARAMETERS ImageParameters, + _In_ PBL_APPLICATION_ENTRY AppEntry, + _In_ PVOID ImageBase, + _In_ ULONG ImageSize + ) +{ + return STATUS_SUCCESS; +} + NTSTATUS ImgArchEfiStartBootApplication ( _In_ PBL_APPLICATION_ENTRY AppEntry, @@ -1604,9 +1623,84 @@ ImgArchEfiStartBootApplication ( _In_ PBL_RETURN_ARGUMENTS ReturnArguments ) { - /* Not yet implemented. This is the last step! */ - EfiPrintf(L"EFI APPLICATION START!!!\r\n"); - EfiStall(100000000); + KDESCRIPTOR Gdt, Idt; + ULONG BootSizeNeeded; + NTSTATUS Status; + PVOID BootData; + PIMAGE_NT_HEADERS NtHeaders; + PVOID NewStack, NewGdt, NewIdt; + BL_IMAGE_PARAMETERS Parameters; + + /* Read the current IDT and GDT */ + _sgdt(&Gdt.Limit); + __sidt(&Idt.Limit); + + /* Allocate space for the IDT, GDT, and 24 pages of stack */ + BootSizeNeeded = (ULONG)PAGE_ALIGN(Idt.Limit + Gdt.Limit + 1 + 25 * PAGE_SIZE); + Status = MmPapAllocatePagesInRange(&BootData, + BlLoaderArchData, + BootSizeNeeded >> PAGE_SHIFT, + 0, + 0, + NULL, + 0); + if (!NT_SUCCESS(Status)) + { + goto Quickie; + } + + RtlZeroMemory(BootData, BootSizeNeeded); + + NewStack = (PVOID)((ULONG_PTR)BootData + (24 * PAGE_SIZE) - 8); + NewGdt = (PVOID)((ULONG_PTR)BootData + (24 * PAGE_SIZE)); + NewIdt = (PVOID)((ULONG_PTR)BootData + (24 * PAGE_SIZE) + Gdt.Limit + 1); + + RtlCopyMemory(NewGdt, (PVOID)Gdt.Base, Gdt.Limit + 1); + RtlCopyMemory(NewIdt, (PVOID)Idt.Base, Idt.Limit + 1); + + RtlImageNtHeaderEx(0, ImageBase, ImageSize, &NtHeaders); + + RtlZeroMemory(&Parameters, sizeof(Parameters)); + + Status = ImgpInitializeBootApplicationParameters(&Parameters, + AppEntry, + ImageBase, + ImageSize); + if (NT_SUCCESS(Status)) + { + BootAppGdtRegister = Gdt; + BootAppIdtRegister = Idt; + + BootApp32EntryRoutine = (PVOID)((ULONG_PTR)ImageBase + + NtHeaders->OptionalHeader. + AddressOfEntryPoint); + BootApp32Parameters = Parameters.Buffer; + BootApp32Stack = NewStack; + +#if BL_KD_SUPPORT + BlBdStop(); +#endif + /* Not yet implemented. This is the last step! */ + EfiPrintf(L"EFI APPLICATION START!!!\r\n"); + EfiStall(100000000); + + /* Make it so */ + Archx86TransferTo32BitApplicationAsm(); + + /* Not yet implemented. This is the last step! */ + EfiPrintf(L"EFI APPLICATION RETURNED!!!\r\n"); + EfiStall(100000000); +#if BL_KD_SUPPORT + BlBdStart(); +#endif + } + +Quickie: + if (BootData) + { + //MmPapFreePages(bootData, TRUE); + } + return STATUS_NOT_IMPLEMENTED; }