]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/BaseLib/X86Thunk.c
MdePkg: Apply uncrustify changes
[mirror_edk2.git] / MdePkg / Library / BaseLib / X86Thunk.c
CommitLineData
e1f414b6 1/** @file\r
030cd1a2 2 Real Mode Thunk Functions for IA32 and x64.\r
e1f414b6 3\r
9095d37b 4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
9344f092 5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
e1f414b6 6\r
e1f414b6 7**/\r
8\r
47fc17d8 9#include "BaseLibInternals.h"\r
f734a10a 10\r
2f88bd3a
MK
11extern CONST UINT8 m16Start;\r
12extern CONST UINT16 m16Size;\r
13extern CONST UINT16 mThunk16Attr;\r
14extern CONST UINT16 m16Gdt;\r
15extern CONST UINT16 m16GdtrBase;\r
16extern CONST UINT16 mTransition;\r
e1f414b6 17\r
18/**\r
19 Invokes 16-bit code in big real mode and returns the updated register set.\r
20\r
21 This function transfers control to the 16-bit code specified by CS:EIP using\r
22 the stack specified by SS:ESP in RegisterSet. The updated registers are saved\r
23 on the real mode stack and the starting address of the save area is returned.\r
24\r
25 @param RegisterSet Values of registers before invocation of 16-bit code.\r
127010dd 26 @param Transition The pointer to the transition code under 1MB.\r
e1f414b6 27\r
28 @return The pointer to a IA32_REGISTER_SET structure containing the updated\r
29 register values.\r
30\r
31**/\r
32IA32_REGISTER_SET *\r
33EFIAPI\r
34InternalAsmThunk16 (\r
2f88bd3a
MK
35 IN IA32_REGISTER_SET *RegisterSet,\r
36 IN OUT VOID *Transition\r
e1f414b6 37 );\r
38\r
39/**\r
40 Retrieves the properties for 16-bit thunk functions.\r
41\r
42 Computes the size of the buffer and stack below 1MB required to use the\r
43 AsmPrepareThunk16(), AsmThunk16() and AsmPrepareAndThunk16() functions. This\r
44 buffer size is returned in RealModeBufferSize, and the stack size is returned\r
45 in ExtraStackSize. If parameters are passed to the 16-bit real mode code,\r
46 then the actual minimum stack size is ExtraStackSize plus the maximum number\r
47 of bytes that need to be passed to the 16-bit real mode code.\r
48\r
49 If RealModeBufferSize is NULL, then ASSERT().\r
50 If ExtraStackSize is NULL, then ASSERT().\r
51\r
52 @param RealModeBufferSize A pointer to the size of the buffer below 1MB\r
53 required to use the 16-bit thunk functions.\r
54 @param ExtraStackSize A pointer to the extra size of stack below 1MB\r
55 that the 16-bit thunk functions require for\r
56 temporary storage in the transition to and from\r
57 16-bit real mode.\r
58\r
59**/\r
60VOID\r
61EFIAPI\r
62AsmGetThunk16Properties (\r
2f88bd3a
MK
63 OUT UINT32 *RealModeBufferSize,\r
64 OUT UINT32 *ExtraStackSize\r
e1f414b6 65 )\r
66{\r
67 ASSERT (RealModeBufferSize != NULL);\r
68 ASSERT (ExtraStackSize != NULL);\r
69\r
70 *RealModeBufferSize = m16Size;\r
71\r
72 //\r
73 // Extra 4 bytes for return address, and another 4 bytes for mode transition\r
74 //\r
75 *ExtraStackSize = sizeof (IA32_DWORD_REGS) + 8;\r
76}\r
77\r
78/**\r
79 Prepares all structures a code required to use AsmThunk16().\r
80\r
81 Prepares all structures and code required to use AsmThunk16().\r
9095d37b 82\r
8243b089 83 This interface is limited to be used in either physical mode or virtual modes with paging enabled where the\r
84 virtual to physical mappings for ThunkContext.RealModeBuffer is mapped 1:1.\r
e1f414b6 85\r
86 If ThunkContext is NULL, then ASSERT().\r
87\r
88 @param ThunkContext A pointer to the context structure that describes the\r
89 16-bit real mode code to call.\r
90\r
91**/\r
92VOID\r
93EFIAPI\r
94AsmPrepareThunk16 (\r
2f88bd3a 95 IN OUT THUNK_CONTEXT *ThunkContext\r
e1f414b6 96 )\r
97{\r
2f88bd3a 98 IA32_SEGMENT_DESCRIPTOR *RealModeGdt;\r
e1f414b6 99\r
100 ASSERT (ThunkContext != NULL);\r
101 ASSERT ((UINTN)ThunkContext->RealModeBuffer < 0x100000);\r
102 ASSERT (ThunkContext->RealModeBufferSize >= m16Size);\r
103 ASSERT ((UINTN)ThunkContext->RealModeBuffer + m16Size <= 0x100000);\r
104\r
105 CopyMem (ThunkContext->RealModeBuffer, &m16Start, m16Size);\r
106\r
107 //\r
108 // Point RealModeGdt to the GDT to be used in transition\r
109 //\r
110 // RealModeGdt[0]: Reserved as NULL descriptor\r
111 // RealModeGdt[1]: Code Segment\r
112 // RealModeGdt[2]: Data Segment\r
113 // RealModeGdt[3]: Call Gate\r
114 //\r
2f88bd3a
MK
115 RealModeGdt = (IA32_SEGMENT_DESCRIPTOR *)(\r
116 (UINTN)ThunkContext->RealModeBuffer + m16Gdt);\r
e1f414b6 117\r
118 //\r
119 // Update Code & Data Segment Descriptor\r
120 //\r
121 RealModeGdt[1].Bits.BaseLow =\r
122 (UINT32)(UINTN)ThunkContext->RealModeBuffer & ~0xf;\r
123 RealModeGdt[1].Bits.BaseMid =\r
124 (UINT32)(UINTN)ThunkContext->RealModeBuffer >> 16;\r
125\r
126 //\r
127 // Update transition code entry point offset\r
128 //\r
2f88bd3a 129 *(UINT32 *)((UINTN)ThunkContext->RealModeBuffer + mTransition) +=\r
e1f414b6 130 (UINT32)(UINTN)ThunkContext->RealModeBuffer & 0xf;\r
131\r
132 //\r
133 // Update Segment Limits for both Code and Data Segment Descriptors\r
134 //\r
135 if ((ThunkContext->ThunkAttributes & THUNK_ATTRIBUTE_BIG_REAL_MODE) == 0) {\r
136 //\r
137 // Set segment limits to 64KB\r
138 //\r
139 RealModeGdt[1].Bits.LimitHigh = 0;\r
2f88bd3a 140 RealModeGdt[1].Bits.G = 0;\r
e1f414b6 141 RealModeGdt[2].Bits.LimitHigh = 0;\r
2f88bd3a 142 RealModeGdt[2].Bits.G = 0;\r
e1f414b6 143 }\r
144\r
145 //\r
146 // Update GDTBASE for this thunk context\r
147 //\r
2f88bd3a 148 *(VOID **)((UINTN)ThunkContext->RealModeBuffer + m16GdtrBase) = RealModeGdt;\r
e1f414b6 149\r
150 //\r
151 // Update Thunk Attributes\r
152 //\r
2f88bd3a 153 *(UINT32 *)((UINTN)ThunkContext->RealModeBuffer + mThunk16Attr) =\r
e1f414b6 154 ThunkContext->ThunkAttributes;\r
155}\r
156\r
157/**\r
158 Transfers control to a 16-bit real mode entry point and returns the results.\r
159\r
160 Transfers control to a 16-bit real mode entry point and returns the results.\r
2fc60b70 161 AsmPrepareThunk16() must be called with ThunkContext before this function is used.\r
162 This function must be called with interrupts disabled.\r
163\r
9095d37b
LG
164 The register state from the RealModeState field of ThunkContext is restored just prior\r
165 to calling the 16-bit real mode entry point. This includes the EFLAGS field of RealModeState,\r
2fc60b70 166 which is used to set the interrupt state when a 16-bit real mode entry point is called.\r
167 Control is transferred to the 16-bit real mode entry point specified by the CS and Eip fields of RealModeState.\r
9095d37b
LG
168 The stack is initialized to the SS and ESP fields of RealModeState. Any parameters passed to\r
169 the 16-bit real mode code must be populated by the caller at SS:ESP prior to calling this function.\r
2fc60b70 170 The 16-bit real mode entry point is invoked with a 16-bit CALL FAR instruction,\r
9095d37b
LG
171 so when accessing stack contents, the 16-bit real mode code must account for the 16-bit segment\r
172 and 16-bit offset of the return address that were pushed onto the stack. The 16-bit real mode entry\r
173 point must exit with a RETF instruction. The register state is captured into RealModeState immediately\r
2fc60b70 174 after the RETF instruction is executed.\r
9095d37b
LG
175\r
176 If EFLAGS specifies interrupts enabled, or any of the 16-bit real mode code enables interrupts,\r
177 or any of the 16-bit real mode code makes a SW interrupt, then the caller is responsible for making sure\r
178 the IDT at address 0 is initialized to handle any HW or SW interrupts that may occur while in 16-bit real mode.\r
179\r
180 If EFLAGS specifies interrupts enabled, or any of the 16-bit real mode code enables interrupts,\r
181 then the caller is responsible for making sure the 8259 PIC is in a state compatible with 16-bit real mode.\r
2fc60b70 182 This includes the base vectors, the interrupt masks, and the edge/level trigger mode.\r
9095d37b
LG
183\r
184 If THUNK_ATTRIBUTE_BIG_REAL_MODE is set in the ThunkAttributes field of ThunkContext, then the user code\r
2fc60b70 185 is invoked in big real mode. Otherwise, the user code is invoked in 16-bit real mode with 64KB segment limits.\r
9095d37b
LG
186\r
187 If neither THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 nor THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL are set in\r
188 ThunkAttributes, then it is assumed that the user code did not enable the A20 mask, and no attempt is made to\r
2fc60b70 189 disable the A20 mask.\r
9095d37b
LG
190\r
191 If THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 is set and THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL is clear in\r
192 ThunkAttributes, then attempt to use the INT 15 service to disable the A20 mask. If this INT 15 call fails,\r
2fc60b70 193 then attempt to disable the A20 mask by directly accessing the 8042 keyboard controller I/O ports.\r
9095d37b
LG
194\r
195 If THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 is clear and THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL is set in\r
2fc60b70 196 ThunkAttributes, then attempt to disable the A20 mask by directly accessing the 8042 keyboard controller I/O ports.\r
9095d37b 197\r
e1f414b6 198 If ThunkContext is NULL, then ASSERT().\r
199 If AsmPrepareThunk16() was not previously called with ThunkContext, then ASSERT().\r
9095d37b 200 If both THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 and THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL are set in\r
2fc60b70 201 ThunkAttributes, then ASSERT().\r
e1f414b6 202\r
8243b089 203 This interface is limited to be used in either physical mode or virtual modes with paging enabled where the\r
204 virtual to physical mappings for ThunkContext.RealModeBuffer is mapped 1:1.\r
9095d37b 205\r
e1f414b6 206 @param ThunkContext A pointer to the context structure that describes the\r
207 16-bit real mode code to call.\r
208\r
209**/\r
210VOID\r
211EFIAPI\r
212AsmThunk16 (\r
2f88bd3a 213 IN OUT THUNK_CONTEXT *ThunkContext\r
e1f414b6 214 )\r
215{\r
2f88bd3a 216 IA32_REGISTER_SET *UpdatedRegs;\r
e1f414b6 217\r
218 ASSERT (ThunkContext != NULL);\r
219 ASSERT ((UINTN)ThunkContext->RealModeBuffer < 0x100000);\r
220 ASSERT (ThunkContext->RealModeBufferSize >= m16Size);\r
221 ASSERT ((UINTN)ThunkContext->RealModeBuffer + m16Size <= 0x100000);\r
2f88bd3a
MK
222 ASSERT (\r
223 ((ThunkContext->ThunkAttributes & (THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 | THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL)) != \\r
224 (THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 | THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL))\r
225 );\r
9095d37b 226\r
e1f414b6 227 UpdatedRegs = InternalAsmThunk16 (\r
228 ThunkContext->RealModeState,\r
229 ThunkContext->RealModeBuffer\r
230 );\r
231\r
232 CopyMem (ThunkContext->RealModeState, UpdatedRegs, sizeof (*UpdatedRegs));\r
233}\r
234\r
235/**\r
236 Prepares all structures and code for a 16-bit real mode thunk, transfers\r
237 control to a 16-bit real mode entry point, and returns the results.\r
238\r
239 Prepares all structures and code for a 16-bit real mode thunk, transfers\r
240 control to a 16-bit real mode entry point, and returns the results. If the\r
241 caller only need to perform a single 16-bit real mode thunk, then this\r
242 service should be used. If the caller intends to make more than one 16-bit\r
243 real mode thunk, then it is more efficient if AsmPrepareThunk16() is called\r
2fc60b70 244 once and AsmThunk16() can be called for each 16-bit real mode thunk.\r
e1f414b6 245\r
8243b089 246 This interface is limited to be used in either physical mode or virtual modes with paging enabled where the\r
247 virtual to physical mappings for ThunkContext.RealModeBuffer is mapped 1:1.\r
9095d37b 248\r
2fc60b70 249 See AsmPrepareThunk16() and AsmThunk16() for the detailed description and ASSERT() conditions.\r
e1f414b6 250\r
251 @param ThunkContext A pointer to the context structure that describes the\r
252 16-bit real mode code to call.\r
253\r
254**/\r
255VOID\r
256EFIAPI\r
257AsmPrepareAndThunk16 (\r
2f88bd3a 258 IN OUT THUNK_CONTEXT *ThunkContext\r
e1f414b6 259 )\r
260{\r
261 AsmPrepareThunk16 (ThunkContext);\r
262 AsmThunk16 (ThunkContext);\r
263}\r