2 Execute 32-bit code in Long Mode
3 Provide a thunk function to transition from long mode to compatibility mode to execute 32-bit code and then transit
6 Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "ScriptSave.h"
31 UINT32 DefaultSize
: 1;
32 UINT32 Granularity
: 1;
39 /// Byte packed structure for an IA-32 Interrupt Gate Descriptor.
43 UINT32 OffsetLow
:16; ///< Offset bits 15..0.
44 UINT32 Selector
:16; ///< Selector.
45 UINT32 Reserved_0
:8; ///< Reserved.
46 UINT32 GateType
:8; ///< Gate Type. See #defines above.
47 UINT32 OffsetHigh
:16; ///< Offset bits 31..16.
53 #define COMPATIBILITY_MODE_SELECTOR 8
56 // Global Descriptor Table (GDT)
58 GLOBAL_REMOVE_IF_UNREFERENCED IA32_GDT mGdtEntries
[] = {
59 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 0x0: reserve */
60 {{0xFFFF, 0, 0, 0xB, 1, 0, 1, 0xF, 0, 0, 1, 1, 0}}, /* 0x8: compatibility mode */
61 {{0xFFFF, 0, 0, 0xB, 1, 0, 1, 0xF, 0, 1, 0, 1, 0}}, /* 0x10: for long mode */
62 {{0xFFFF, 0, 0, 0x3, 1, 0, 1, 0xF, 0, 0, 1, 1, 0}}, /* 0x18: data */
63 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 0x20: reserve */
69 GLOBAL_REMOVE_IF_UNREFERENCED IA32_DESCRIPTOR mGdt
= {
70 sizeof (mGdtEntries
) - 1,
74 Assembly function to transition from long mode to compatibility mode to execute 32-bit code and then transit back to
76 @param Function The 32bit code entry to be executed.
77 @param Param1 The first parameter to pass to 32bit code
78 @param Param2 The second parameter to pass to 32bit code
79 @param InternalGdtr The GDT and GDT descriptor used by this library
81 @retval EFI_SUCCESS Execute 32bit code successfully.
82 @retval other Something wrong when execute the 32bit code
89 IN IA32_DESCRIPTOR
*InternalGdtr
93 Wrapper for a thunk to transition from long mode to compatibility mode to execute 32-bit code and then transit back to
96 @param Function The 32bit code entry to be executed.
97 @param Param1 The first parameter to pass to 32bit code
98 @param Param2 The second parameter to pass to 32bit code
99 @retval EFI_SUCCESS Execute 32bit code successfully.
100 @retval other Something wrong when execute the 32bit code
111 IA32_DESCRIPTOR
*Ia32Idtr
;
112 IA32_DESCRIPTOR X64Idtr
;
113 UINTN Ia32IdtEntryCount
;
115 IA32_IDT_ENTRY
*Ia32IdtEntry
;
118 // Save x64 IDT Descriptor
120 AsmReadIdtr ((IA32_DESCRIPTOR
*) &X64Idtr
);
123 // Get the IA32 IDT Descriptor saved in 16 bytes in front of X64 IDT table.
125 Ia32Idtr
= (IA32_DESCRIPTOR
*) (UINTN
) (X64Idtr
.Base
- 16);
126 Ia32IdtEntryCount
= (Ia32Idtr
->Limit
+ 1) / sizeof (IA32_IDT_ENTRY
);
128 Ia32IdtEntry
= (IA32_IDT_ENTRY
*)(Ia32Idtr
->Base
);
129 for (Index
= 0; Index
< Ia32IdtEntryCount
; Index
++ ) {
131 // Use the new Code Selector value
133 Ia32IdtEntry
[Index
].Bits
.Selector
= COMPATIBILITY_MODE_SELECTOR
;
137 // Setup IA32 IDT table for 32-bit framework Boot Script code
139 AsmWriteIdtr (Ia32Idtr
);
141 ASSERT (Function
!= 0);
143 Status
= AsmExecute32BitCode (
151 // Restore X64 IDT table
153 AsmWriteIdtr ((IA32_DESCRIPTOR
*) &X64Idtr
);