]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdePkg/Library/BaseLib/X86Thunk.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdePkg / Library / BaseLib / X86Thunk.c
index 7bcde8389d1a553cf796acad3b774bcc5aaba39a..9940dca8592e9c4d3b728411afa0bc82cc2def6d 100644 (file)
@@ -1,49 +1,19 @@
 /** @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
@@ -53,7 +23,7 @@ extern CONST UINT16                 mTransition;
   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
@@ -62,8 +32,8 @@ extern CONST UINT16                 mTransition;
 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
@@ -90,8 +60,8 @@ InternalAsmThunk16 (
 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
@@ -110,6 +80,9 @@ AsmGetThunk16Properties (
 \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
@@ -119,10 +92,10 @@ AsmGetThunk16Properties (
 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
@@ -139,8 +112,8 @@ AsmPrepareThunk16 (
   // 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
@@ -153,7 +126,7 @@ AsmPrepareThunk16 (
   //\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
@@ -164,20 +137,20 @@ AsmPrepareThunk16 (
     // 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
@@ -185,11 +158,50 @@ AsmPrepareThunk16 (
   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
@@ -198,15 +210,19 @@ AsmPrepareThunk16 (
 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
@@ -225,10 +241,12 @@ AsmThunk16 (
   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
@@ -237,7 +255,7 @@ AsmThunk16 (
 VOID\r
 EFIAPI\r
 AsmPrepareAndThunk16 (\r
-  IN OUT  THUNK_CONTEXT             *ThunkContext\r
+  IN OUT  THUNK_CONTEXT  *ThunkContext\r
   )\r
 {\r
   AsmPrepareThunk16 (ThunkContext);\r