]> git.proxmox.com Git - mirror_edk2.git/blame - EdkCompatibilityPkg/Compatibility/BootScriptSaveOnS3SaveStateThunk/X64/DispatchExecute.c
1. Updated S3Resume2Pei to save IA32 IDT table setup in protected mode.
[mirror_edk2.git] / EdkCompatibilityPkg / Compatibility / BootScriptSaveOnS3SaveStateThunk / X64 / DispatchExecute.c
CommitLineData
d766b228
JY
1/** @file\r
2 Execute 32-bit code in Long Mode\r
3 Provide a thunk function to transition from long mode to compatibility mode to execute 32-bit code and then transit\r
4 back to long mode.\r
5 \r
e47459e6 6 Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>\r
d766b228
JY
7 This program and the accompanying materials\r
8 are licensed and made available under the terms and conditions of the BSD License\r
9 which accompanies this distribution. The full text of the license may be found at\r
10 http://opensource.org/licenses/bsd-license.php\r
11\r
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
16#include "ScriptSave.h"\r
17\r
18#pragma pack(1)\r
19typedef union {\r
20 struct {\r
21 UINT32 LimitLow : 16;\r
22 UINT32 BaseLow : 16;\r
23 UINT32 BaseMid : 8;\r
24 UINT32 Type : 4;\r
25 UINT32 System : 1;\r
26 UINT32 Dpl : 2;\r
27 UINT32 Present : 1;\r
28 UINT32 LimitHigh : 4;\r
29 UINT32 Software : 1;\r
30 UINT32 Reserved : 1;\r
31 UINT32 DefaultSize : 1;\r
32 UINT32 Granularity : 1;\r
33 UINT32 BaseHigh : 8;\r
34 } Bits;\r
35 UINT64 Uint64;\r
36} IA32_GDT;\r
e47459e6 37\r
38///\r
39/// Byte packed structure for an IA-32 Interrupt Gate Descriptor.\r
40///\r
41typedef union {\r
42 struct {\r
43 UINT32 OffsetLow:16; ///< Offset bits 15..0.\r
44 UINT32 Selector:16; ///< Selector.\r
45 UINT32 Reserved_0:8; ///< Reserved.\r
46 UINT32 GateType:8; ///< Gate Type. See #defines above.\r
47 UINT32 OffsetHigh:16; ///< Offset bits 31..16.\r
48 } Bits;\r
49 UINT64 Uint64;\r
50} IA32_IDT_ENTRY;\r
d766b228
JY
51#pragma pack()\r
52\r
e47459e6 53#define COMPATIBILITY_MODE_SELECTOR 8\r
54\r
d766b228
JY
55//\r
56// Global Descriptor Table (GDT)\r
57//\r
58GLOBAL_REMOVE_IF_UNREFERENCED IA32_GDT mGdtEntries[] = {\r
59 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 0x0: reserve */\r
60 {{0xFFFF, 0, 0, 0xB, 1, 0, 1, 0xF, 0, 0, 1, 1, 0}}, /* 0x8: compatibility mode */\r
61 {{0xFFFF, 0, 0, 0xB, 1, 0, 1, 0xF, 0, 1, 0, 1, 0}}, /* 0x10: for long mode */\r
62 {{0xFFFF, 0, 0, 0x3, 1, 0, 1, 0xF, 0, 0, 1, 1, 0}}, /* 0x18: data */\r
63 {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, /* 0x20: reserve */\r
64};\r
65\r
66//\r
67// IA32 Gdt register\r
68//\r
69GLOBAL_REMOVE_IF_UNREFERENCED IA32_DESCRIPTOR mGdt = {\r
70 sizeof (mGdtEntries) - 1,\r
71 (UINTN) mGdtEntries\r
72 };\r
73/**\r
74 Assembly function to transition from long mode to compatibility mode to execute 32-bit code and then transit back to\r
75 long mode.\r
76 @param Function The 32bit code entry to be executed.\r
77 @param Param1 The first parameter to pass to 32bit code\r
78 @param Param2 The second parameter to pass to 32bit code\r
79 @param InternalGdtr The GDT and GDT descriptor used by this library\r
80 \r
81 @retval EFI_SUCCESS Execute 32bit code successfully.\r
82 @retval other Something wrong when execute the 32bit code \r
83**/\r
84EFI_STATUS\r
85AsmExecute32BitCode (\r
86 IN UINT64 Function,\r
87 IN UINT64 Param1,\r
88 IN UINT64 Param2,\r
89 IN IA32_DESCRIPTOR *InternalGdtr\r
90 );\r
91 \r
92/**\r
93 Wrapper for a thunk to transition from long mode to compatibility mode to execute 32-bit code and then transit back to\r
94 long mode.\r
95 \r
96 @param Function The 32bit code entry to be executed.\r
97 @param Param1 The first parameter to pass to 32bit code\r
98 @param Param2 The second parameter to pass to 32bit code\r
99 @retval EFI_SUCCESS Execute 32bit code successfully.\r
100 @retval other Something wrong when execute the 32bit code \r
101 \r
102**/ \r
103EFI_STATUS\r
104Execute32BitCode (\r
105 IN UINT64 Function,\r
106 IN UINT64 Param1,\r
107 IN UINT64 Param2\r
108 )\r
109{\r
110 EFI_STATUS Status;\r
e47459e6 111 IA32_DESCRIPTOR *Ia32Idtr;\r
112 IA32_DESCRIPTOR X64Idtr;\r
113 UINTN Ia32IdtEntryCount;\r
114 UINTN Index;\r
115 IA32_IDT_ENTRY *Ia32IdtEntry;\r
116\r
117 //\r
118 // Save x64 IDT Descriptor\r
119 //\r
120 AsmReadIdtr ((IA32_DESCRIPTOR *) &X64Idtr);\r
121\r
122 //\r
123 // Get the IA32 IDT Descriptor saved in 16 bytes in front of X64 IDT table.\r
124 //\r
125 Ia32Idtr = (IA32_DESCRIPTOR *) (UINTN) (X64Idtr.Base - 16);\r
126 Ia32IdtEntryCount = (Ia32Idtr->Limit + 1) / sizeof (IA32_IDT_ENTRY);\r
127\r
128 Ia32IdtEntry = (IA32_IDT_ENTRY *)(Ia32Idtr->Base);\r
129 for (Index = 0; Index < Ia32IdtEntryCount; Index ++ ) {\r
130 //\r
131 // Use the new Code Selector value\r
132 //\r
133 Ia32IdtEntry[Index].Bits.Selector = COMPATIBILITY_MODE_SELECTOR;\r
134 }\r
135\r
136 //\r
137 // Setup IA32 IDT table for 32-bit framework Boot Script code\r
138 //\r
139 AsmWriteIdtr (Ia32Idtr);\r
140\r
d766b228
JY
141 ASSERT (Function != 0);\r
142 \r
143 Status = AsmExecute32BitCode (\r
144 Function,\r
145 Param1,\r
146 Param2,\r
147 &mGdt\r
148 );\r
e47459e6 149\r
150 //\r
151 // Restore X64 IDT table\r
152 //\r
153 AsmWriteIdtr ((IA32_DESCRIPTOR *) &X64Idtr);\r
154\r
d766b228
JY
155 return Status;\r
156}\r
157\r