/** @file\r
Real Mode Thunk Functions for IA32 and x64.\r
\r
- Copyright (c) 2006, Intel Corporation<BR>\r
- All rights reserved. This program and the accompanying materials\r
- are licensed and made available under the terms and conditions of the BSD License\r
- which accompanies this distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
-\r
#include "BaseLibInternals.h"\r
\r
-\r
-//\r
-// Byte packed structure for a segment descriptor in a GDT/LDT\r
-//\r
-typedef union {\r
- struct {\r
- UINT32 LimitLow:16;\r
- UINT32 BaseLow:16;\r
- UINT32 BaseMid:8;\r
- UINT32 Type:4;\r
- UINT32 S:1;\r
- UINT32 DPL:2;\r
- UINT32 P:1;\r
- UINT32 LimitHigh:4;\r
- UINT32 AVL:1;\r
- UINT32 L:1;\r
- UINT32 DB:1;\r
- UINT32 G:1;\r
- UINT32 BaseHigh:8;\r
- } Bits;\r
- UINT64 Uint64;\r
-} IA32_SEGMENT_DESCRIPTOR;\r
-\r
-extern CONST UINT8 m16Start;\r
-extern CONST UINT16 m16Size;\r
-extern CONST UINT16 mThunk16Attr;\r
-extern CONST UINT16 m16Gdt;\r
-extern CONST UINT16 m16GdtrBase;\r
-extern CONST UINT16 mTransition;\r
+extern CONST UINT8 m16Start;\r
+extern CONST UINT16 m16Size;\r
+extern CONST UINT16 mThunk16Attr;\r
+extern CONST UINT16 m16Gdt;\r
+extern CONST UINT16 m16GdtrBase;\r
+extern CONST UINT16 mTransition;\r
\r
/**\r
Invokes 16-bit code in big real mode and returns the updated register set.\r
on the real mode stack and the starting address of the save area is returned.\r
\r
@param RegisterSet Values of registers before invocation of 16-bit code.\r
- @param Transition Pointer to the transition code under 1MB.\r
+ @param Transition The pointer to the transition code under 1MB.\r
\r
@return The pointer to a IA32_REGISTER_SET structure containing the updated\r
register values.\r
IA32_REGISTER_SET *\r
EFIAPI\r
InternalAsmThunk16 (\r
- IN IA32_REGISTER_SET *RegisterSet,\r
- IN OUT VOID *Transition\r
+ IN IA32_REGISTER_SET *RegisterSet,\r
+ IN OUT VOID *Transition\r
);\r
\r
/**\r
VOID\r
EFIAPI\r
AsmGetThunk16Properties (\r
- OUT UINT32 *RealModeBufferSize,\r
- OUT UINT32 *ExtraStackSize\r
+ OUT UINT32 *RealModeBufferSize,\r
+ OUT UINT32 *ExtraStackSize\r
)\r
{\r
ASSERT (RealModeBufferSize != NULL);\r
\r
Prepares all structures and code required to use AsmThunk16().\r
\r
+ This interface is limited to be used in either physical mode or virtual modes with paging enabled where the\r
+ virtual to physical mappings for ThunkContext.RealModeBuffer is mapped 1:1.\r
+\r
If ThunkContext is NULL, then ASSERT().\r
\r
@param ThunkContext A pointer to the context structure that describes the\r
VOID\r
EFIAPI\r
AsmPrepareThunk16 (\r
- OUT THUNK_CONTEXT *ThunkContext\r
+ IN OUT THUNK_CONTEXT *ThunkContext\r
)\r
{\r
- IA32_SEGMENT_DESCRIPTOR *RealModeGdt;\r
+ IA32_SEGMENT_DESCRIPTOR *RealModeGdt;\r
\r
ASSERT (ThunkContext != NULL);\r
ASSERT ((UINTN)ThunkContext->RealModeBuffer < 0x100000);\r
// RealModeGdt[2]: Data Segment\r
// RealModeGdt[3]: Call Gate\r
//\r
- RealModeGdt = (IA32_SEGMENT_DESCRIPTOR*)(\r
- (UINTN)ThunkContext->RealModeBuffer + m16Gdt);\r
+ RealModeGdt = (IA32_SEGMENT_DESCRIPTOR *)(\r
+ (UINTN)ThunkContext->RealModeBuffer + m16Gdt);\r
\r
//\r
// Update Code & Data Segment Descriptor\r
//\r
// Update transition code entry point offset\r
//\r
- *(UINT32*)((UINTN)ThunkContext->RealModeBuffer + mTransition) +=\r
+ *(UINT32 *)((UINTN)ThunkContext->RealModeBuffer + mTransition) +=\r
(UINT32)(UINTN)ThunkContext->RealModeBuffer & 0xf;\r
\r
//\r
// Set segment limits to 64KB\r
//\r
RealModeGdt[1].Bits.LimitHigh = 0;\r
- RealModeGdt[1].Bits.G = 0;\r
+ RealModeGdt[1].Bits.G = 0;\r
RealModeGdt[2].Bits.LimitHigh = 0;\r
- RealModeGdt[2].Bits.G = 0;\r
+ RealModeGdt[2].Bits.G = 0;\r
}\r
\r
//\r
// Update GDTBASE for this thunk context\r
//\r
- *(VOID**)((UINTN)ThunkContext->RealModeBuffer + m16GdtrBase) = RealModeGdt;\r
+ *(VOID **)((UINTN)ThunkContext->RealModeBuffer + m16GdtrBase) = RealModeGdt;\r
\r
//\r
// Update Thunk Attributes\r
//\r
- *(UINT32*)((UINTN)ThunkContext->RealModeBuffer + mThunk16Attr) =\r
+ *(UINT32 *)((UINTN)ThunkContext->RealModeBuffer + mThunk16Attr) =\r
ThunkContext->ThunkAttributes;\r
}\r
\r
Transfers control to a 16-bit real mode entry point and returns the results.\r
\r
Transfers control to a 16-bit real mode entry point and returns the results.\r
- AsmPrepareThunk16() must be called with ThunkContext before this function is\r
- used. This function must be called with interrupts disabled.\r
+ AsmPrepareThunk16() must be called with ThunkContext before this function is used.\r
+ This function must be called with interrupts disabled.\r
+\r
+ The register state from the RealModeState field of ThunkContext is restored just prior\r
+ to calling the 16-bit real mode entry point. This includes the EFLAGS field of RealModeState,\r
+ which is used to set the interrupt state when a 16-bit real mode entry point is called.\r
+ Control is transferred to the 16-bit real mode entry point specified by the CS and Eip fields of RealModeState.\r
+ The stack is initialized to the SS and ESP fields of RealModeState. Any parameters passed to\r
+ the 16-bit real mode code must be populated by the caller at SS:ESP prior to calling this function.\r
+ The 16-bit real mode entry point is invoked with a 16-bit CALL FAR instruction,\r
+ so when accessing stack contents, the 16-bit real mode code must account for the 16-bit segment\r
+ and 16-bit offset of the return address that were pushed onto the stack. The 16-bit real mode entry\r
+ point must exit with a RETF instruction. The register state is captured into RealModeState immediately\r
+ after the RETF instruction is executed.\r
+\r
+ If EFLAGS specifies interrupts enabled, or any of the 16-bit real mode code enables interrupts,\r
+ or any of the 16-bit real mode code makes a SW interrupt, then the caller is responsible for making sure\r
+ the IDT at address 0 is initialized to handle any HW or SW interrupts that may occur while in 16-bit real mode.\r
+\r
+ If EFLAGS specifies interrupts enabled, or any of the 16-bit real mode code enables interrupts,\r
+ then the caller is responsible for making sure the 8259 PIC is in a state compatible with 16-bit real mode.\r
+ This includes the base vectors, the interrupt masks, and the edge/level trigger mode.\r
+\r
+ If THUNK_ATTRIBUTE_BIG_REAL_MODE is set in the ThunkAttributes field of ThunkContext, then the user code\r
+ is invoked in big real mode. Otherwise, the user code is invoked in 16-bit real mode with 64KB segment limits.\r
+\r
+ If neither THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 nor THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL are set in\r
+ ThunkAttributes, then it is assumed that the user code did not enable the A20 mask, and no attempt is made to\r
+ disable the A20 mask.\r
+\r
+ If THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 is set and THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL is clear in\r
+ ThunkAttributes, then attempt to use the INT 15 service to disable the A20 mask. If this INT 15 call fails,\r
+ then attempt to disable the A20 mask by directly accessing the 8042 keyboard controller I/O ports.\r
+\r
+ If THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 is clear and THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL is set in\r
+ ThunkAttributes, then attempt to disable the A20 mask by directly accessing the 8042 keyboard controller I/O ports.\r
\r
If ThunkContext is NULL, then ASSERT().\r
If AsmPrepareThunk16() was not previously called with ThunkContext, then ASSERT().\r
+ If both THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 and THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL are set in\r
+ ThunkAttributes, then ASSERT().\r
+\r
+ This interface is limited to be used in either physical mode or virtual modes with paging enabled where the\r
+ virtual to physical mappings for ThunkContext.RealModeBuffer is mapped 1:1.\r
\r
@param ThunkContext A pointer to the context structure that describes the\r
16-bit real mode code to call.\r
VOID\r
EFIAPI\r
AsmThunk16 (\r
- IN OUT THUNK_CONTEXT *ThunkContext\r
+ IN OUT THUNK_CONTEXT *ThunkContext\r
)\r
{\r
- IA32_REGISTER_SET *UpdatedRegs;\r
+ IA32_REGISTER_SET *UpdatedRegs;\r
\r
ASSERT (ThunkContext != NULL);\r
ASSERT ((UINTN)ThunkContext->RealModeBuffer < 0x100000);\r
ASSERT (ThunkContext->RealModeBufferSize >= m16Size);\r
ASSERT ((UINTN)ThunkContext->RealModeBuffer + m16Size <= 0x100000);\r
+ ASSERT (\r
+ ((ThunkContext->ThunkAttributes & (THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 | THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL)) != \\r
+ (THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 | THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL))\r
+ );\r
\r
UpdatedRegs = InternalAsmThunk16 (\r
ThunkContext->RealModeState,\r
caller only need to perform a single 16-bit real mode thunk, then this\r
service should be used. If the caller intends to make more than one 16-bit\r
real mode thunk, then it is more efficient if AsmPrepareThunk16() is called\r
- once and AsmThunk16() can be called for each 16-bit real mode thunk. This\r
- function must be called with interrupts disabled.\r
+ once and AsmThunk16() can be called for each 16-bit real mode thunk.\r
\r
- If ThunkContext is NULL, then ASSERT().\r
+ This interface is limited to be used in either physical mode or virtual modes with paging enabled where the\r
+ virtual to physical mappings for ThunkContext.RealModeBuffer is mapped 1:1.\r
+\r
+ See AsmPrepareThunk16() and AsmThunk16() for the detailed description and ASSERT() conditions.\r
\r
@param ThunkContext A pointer to the context structure that describes the\r
16-bit real mode code to call.\r
VOID\r
EFIAPI\r
AsmPrepareAndThunk16 (\r
- IN OUT THUNK_CONTEXT *ThunkContext\r
+ IN OUT THUNK_CONTEXT *ThunkContext\r
)\r
{\r
AsmPrepareThunk16 (ThunkContext);\r