• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
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
4   back to long mode.
5 
6   Copyright (c) 2014 - 2015, 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.
11 
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.
14 
15 **/
16 
17 #include <Uefi.h>
18 #include <Library/BaseLib.h>
19 #include <FspApi.h>
20 
21 #pragma pack(1)
22 typedef union {
23   struct {
24     UINT32  LimitLow    : 16;
25     UINT32  BaseLow     : 16;
26     UINT32  BaseMid     : 8;
27     UINT32  Type        : 4;
28     UINT32  System      : 1;
29     UINT32  Dpl         : 2;
30     UINT32  Present     : 1;
31     UINT32  LimitHigh   : 4;
32     UINT32  Software    : 1;
33     UINT32  Reserved    : 1;
34     UINT32  DefaultSize : 1;
35     UINT32  Granularity : 1;
36     UINT32  BaseHigh    : 8;
37   } Bits;
38   UINT64  Uint64;
39 } IA32_GDT;
40 #pragma pack()
41 
42 GLOBAL_REMOVE_IF_UNREFERENCED IA32_GDT mGdtEntries[] = {
43   {{0,      0,  0,  0,    0,  0,  0,  0,    0,  0, 0,  0,  0}}, /* 0x0:  reserve */
44   {{0xFFFF, 0,  0,  0xB,  1,  0,  1,  0xF,  0,  0, 1,  1,  0}}, /* 0x8:  compatibility mode */
45   {{0xFFFF, 0,  0,  0xB,  1,  0,  1,  0xF,  0,  1, 0,  1,  0}}, /* 0x10: for long mode */
46   {{0xFFFF, 0,  0,  0x3,  1,  0,  1,  0xF,  0,  0, 1,  1,  0}}, /* 0x18: data */
47   {{0,      0,  0,  0,    0,  0,  0,  0,    0,  0, 0,  0,  0}}, /* 0x20: reserve */
48 };
49 
50 //
51 // IA32 Gdt register
52 //
53 GLOBAL_REMOVE_IF_UNREFERENCED IA32_DESCRIPTOR mGdt = {
54   sizeof (mGdtEntries) - 1,
55   (UINTN) mGdtEntries
56   };
57 
58 /**
59   Assembly function to transition from long mode to compatibility mode to execute 32-bit code and then transit back to
60   long mode.
61 
62   @param[in] Function     The 32bit code entry to be executed.
63   @param[in] Param1       The first parameter to pass to 32bit code
64   @param[in] Param2       The second parameter to pass to 32bit code
65   @param[in] InternalGdtr The GDT and GDT descriptor used by this library
66 
67   @return status.
68 **/
69 UINT32
70 AsmExecute32BitCode (
71   IN UINT64           Function,
72   IN UINT64           Param1,
73   IN UINT64           Param2,
74   IN IA32_DESCRIPTOR  *InternalGdtr
75   );
76 
77 /**
78   Wrapper for a thunk  to transition from long mode to compatibility mode to execute 32-bit code and then transit back to
79   long mode.
80 
81   @param[in] Function     The 32bit code entry to be executed.
82   @param[in] Param1       The first parameter to pass to 32bit code.
83 
84   @return EFI_STATUS.
85 **/
86 EFI_STATUS
Execute32BitCode(IN UINT64 Function,IN UINT64 Param1)87 Execute32BitCode (
88   IN UINT64      Function,
89   IN UINT64      Param1
90   )
91 {
92   EFI_STATUS       Status;
93   IA32_DESCRIPTOR  Idtr;
94 
95   //
96   // Idtr might be changed inside of FSP. 32bit FSP only knows the <4G address.
97   // If IDTR.Base is >4G, FSP can not handle. So we need save/restore IDTR here for X64 only.
98   // Interrupt is already disabled here, so it is safety to update IDTR.
99   //
100   AsmReadIdtr (&Idtr);
101   Status = AsmExecute32BitCode (Function, Param1, 0, &mGdt);
102   AsmWriteIdtr (&Idtr);
103 
104   return Status;
105 }
106 
107