[BOOTLIB]: Begin adding support for transferring to newly loaded i386 image.
authorAlex Ionescu <aionescu@gmail.com>
Sat, 4 Feb 2017 21:59:52 +0000 (21:59 +0000)
committerAlex Ionescu <aionescu@gmail.com>
Sat, 4 Feb 2017 21:59:52 +0000 (21:59 +0000)
svn path=/trunk/; revision=73687

reactos/boot/environ/CMakeLists.txt
reactos/boot/environ/include/bl.h
reactos/boot/environ/lib/arch/i386/transfer.s [new file with mode: 0644]
reactos/boot/environ/lib/misc/image.c

index 2a049a1..5a63aff 100644 (file)
@@ -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
index dc00685..d7dd2df 100644 (file)
@@ -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 (file)
index 0000000..e3547bd
--- /dev/null
@@ -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 <asm.inc>
+#include <ks386.inc>
+
+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
index 55d9bd8..d8dec2f 100644 (file)
@@ -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;
 }