]> git.proxmox.com Git - mirror_edk2.git/blame - DuetPkg/BiosVideoThunkDxe/LegacyBiosThunk.c
Update the copyright notice format
[mirror_edk2.git] / DuetPkg / BiosVideoThunkDxe / LegacyBiosThunk.c
CommitLineData
f1294e4a 1/** @file\r
2 Provide legacy thunk interface for accessing Bios Video Rom.\r
3 \r
b1f700a8
HT
4Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.<BR>\r
5This program and the accompanying materials \r
f1294e4a 6are licensed and made available under the terms and conditions of the BSD License \r
7which accompanies this distribution. The full text of the license may be found at \r
8http://opensource.org/licenses/bsd-license.php \r
9 \r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
12\r
13**/\r
0d92cdc2 14\r
15#include "BiosVideo.h"\r
16\r
17#define EFI_CPU_EFLAGS_IF 0x200\r
18\r
f1294e4a 19/**\r
20 Initialize legacy environment for BIOS INI caller.\r
21 \r
22 @param ThunkContext the instance pointer of THUNK_CONTEXT\r
23**/\r
0d92cdc2 24VOID\r
25InitializeBiosIntCaller (\r
f1294e4a 26 THUNK_CONTEXT *ThunkContext\r
0d92cdc2 27 )\r
28{\r
29 EFI_STATUS Status;\r
30 UINT32 RealModeBufferSize;\r
31 UINT32 ExtraStackSize;\r
32 EFI_PHYSICAL_ADDRESS LegacyRegionBase;\r
6c8e40ca 33 UINT32 LegacyRegionSize;\r
0d92cdc2 34 //\r
35 // Get LegacyRegion\r
36 //\r
37 AsmGetThunk16Properties (&RealModeBufferSize, &ExtraStackSize);\r
6c8e40ca 38 LegacyRegionSize = (((RealModeBufferSize + ExtraStackSize) / EFI_PAGE_SIZE) + 1) * EFI_PAGE_SIZE;\r
0d92cdc2 39 LegacyRegionBase = 0x100000;\r
40 Status = gBS->AllocatePages (\r
41 AllocateMaxAddress,\r
42 EfiACPIMemoryNVS,\r
6c8e40ca 43 EFI_SIZE_TO_PAGES(LegacyRegionSize),\r
0d92cdc2 44 &LegacyRegionBase\r
45 );\r
46 ASSERT_EFI_ERROR (Status);\r
47 \r
f1294e4a 48 ThunkContext->RealModeBuffer = (VOID*)(UINTN)LegacyRegionBase;\r
6c8e40ca 49 ThunkContext->RealModeBufferSize = LegacyRegionSize;\r
50 ThunkContext->ThunkAttributes = THUNK_ATTRIBUTE_BIG_REAL_MODE|THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15;\r
f1294e4a 51 AsmPrepareThunk16(ThunkContext);\r
0d92cdc2 52}\r
53\r
f1294e4a 54/**\r
55 Initialize interrupt redirection code and entries, because\r
56 IDT Vectors 0x68-0x6f must be redirected to IDT Vectors 0x08-0x0f.\r
57 Or the interrupt will lost when we do thunk.\r
58 NOTE: We do not reset 8259 vector base, because it will cause pending\r
59 interrupt lost.\r
60 \r
61 @param Legacy8259 Instance pointer for EFI_LEGACY_8259_PROTOCOL.\r
62 \r
63**/\r
0d92cdc2 64VOID\r
65InitializeInterruptRedirection (\r
f1294e4a 66 IN EFI_LEGACY_8259_PROTOCOL *Legacy8259\r
0d92cdc2 67 )\r
0d92cdc2 68{\r
69 EFI_STATUS Status;\r
70 EFI_PHYSICAL_ADDRESS LegacyRegionBase;\r
71 UINTN LegacyRegionLength;\r
72 UINT32 *IdtArray;\r
73 UINTN Index;\r
74 UINT8 ProtectedModeBaseVector;\r
75 UINT32 InterruptRedirectionCode[] = {\r
76 0x90CF08CD, // INT8; IRET; NOP\r
77 0x90CF09CD, // INT9; IRET; NOP\r
78 0x90CF0ACD, // INTA; IRET; NOP\r
79 0x90CF0BCD, // INTB; IRET; NOP\r
80 0x90CF0CCD, // INTC; IRET; NOP\r
81 0x90CF0DCD, // INTD; IRET; NOP\r
82 0x90CF0ECD, // INTE; IRET; NOP\r
83 0x90CF0FCD // INTF; IRET; NOP\r
84 };\r
85\r
86 //\r
87 // Get LegacyRegion\r
88 //\r
89 LegacyRegionLength = sizeof(InterruptRedirectionCode);\r
90 LegacyRegionBase = 0x100000;\r
91 Status = gBS->AllocatePages (\r
92 AllocateMaxAddress,\r
93 EfiACPIMemoryNVS,\r
94 EFI_SIZE_TO_PAGES(LegacyRegionLength),\r
95 &LegacyRegionBase\r
96 );\r
97 ASSERT_EFI_ERROR (Status);\r
98\r
99 //\r
100 // Copy code to legacy region\r
101 //\r
102 CopyMem ((VOID *)(UINTN)LegacyRegionBase, InterruptRedirectionCode, sizeof (InterruptRedirectionCode));\r
103\r
104 //\r
105 // Get VectorBase, it should be 0x68\r
106 //\r
f1294e4a 107 Status = Legacy8259->GetVector (Legacy8259, Efi8259Irq0, &ProtectedModeBaseVector);\r
0d92cdc2 108 ASSERT_EFI_ERROR (Status);\r
109\r
110 //\r
111 // Patch IVT 0x68 ~ 0x6f\r
112 //\r
113 IdtArray = (UINT32 *) 0;\r
114 for (Index = 0; Index < 8; Index++) {\r
115 IdtArray[ProtectedModeBaseVector + Index] = ((EFI_SEGMENT (LegacyRegionBase + Index * 4)) << 16) | (EFI_OFFSET (LegacyRegionBase + Index * 4));\r
116 }\r
117\r
118 return ;\r
119}\r
120\r
f1294e4a 121/**\r
122 Thunk to 16-bit real mode and execute a software interrupt with a vector \r
123 of BiosInt. Regs will contain the 16-bit register context on entry and \r
124 exit.\r
125 \r
126 @param This Protocol instance pointer.\r
127 @param BiosInt Processor interrupt vector to invoke\r
128 @param Reg Register contexted passed into (and returned) from thunk to 16-bit mode\r
129 \r
130 @retval TRUE Thunk completed, and there were no BIOS errors in the target code.\r
131 See Regs for status.\r
132 @retval FALSE There was a BIOS erro in the target code. \r
133**/\r
0d92cdc2 134BOOLEAN\r
135EFIAPI\r
136LegacyBiosInt86 (\r
137 IN BIOS_VIDEO_DEV *BiosDev,\r
138 IN UINT8 BiosInt,\r
d0c94e59 139 IN IA32_REGISTER_SET *Regs\r
0d92cdc2 140 )\r
0d92cdc2 141{\r
142 UINTN Status;\r
143 UINTN Eflags;\r
144 IA32_REGISTER_SET ThunkRegSet;\r
145 BOOLEAN Ret;\r
146 UINT16 *Stack16;\r
147 \r
0d92cdc2 148 ZeroMem (&ThunkRegSet, sizeof (ThunkRegSet));\r
237bb9d0 149 ThunkRegSet.E.EFLAGS.Bits.Reserved_0 = 1;\r
150 ThunkRegSet.E.EFLAGS.Bits.Reserved_1 = 0;\r
151 ThunkRegSet.E.EFLAGS.Bits.Reserved_2 = 0;\r
152 ThunkRegSet.E.EFLAGS.Bits.Reserved_3 = 0;\r
153 ThunkRegSet.E.EFLAGS.Bits.IOPL = 3;\r
154 ThunkRegSet.E.EFLAGS.Bits.NT = 0;\r
155 ThunkRegSet.E.EFLAGS.Bits.IF = 1;\r
156 ThunkRegSet.E.EFLAGS.Bits.TF = 0;\r
157 ThunkRegSet.E.EFLAGS.Bits.CF = 0;\r
158 \r
0d92cdc2 159 ThunkRegSet.E.EDI = Regs->E.EDI;\r
160 ThunkRegSet.E.ESI = Regs->E.ESI;\r
161 ThunkRegSet.E.EBP = Regs->E.EBP;\r
162 ThunkRegSet.E.EBX = Regs->E.EBX;\r
163 ThunkRegSet.E.EDX = Regs->E.EDX;\r
164 ThunkRegSet.E.ECX = Regs->E.ECX;\r
165 ThunkRegSet.E.EAX = Regs->E.EAX;\r
166 ThunkRegSet.E.DS = Regs->E.DS;\r
167 ThunkRegSet.E.ES = Regs->E.ES;\r
168\r
0d92cdc2 169 //\r
170 // The call to Legacy16 is a critical section to EFI\r
171 //\r
172 Eflags = AsmReadEflags ();\r
173 if ((Eflags | EFI_CPU_EFLAGS_IF) != 0) {\r
174 DisableInterrupts ();\r
175 }\r
176\r
177 //\r
178 // Set Legacy16 state. 0x08, 0x70 is legacy 8259 vector bases.\r
179 //\r
180 Status = BiosDev->Legacy8259->SetMode (BiosDev->Legacy8259, Efi8259LegacyMode, NULL, NULL);\r
181 ASSERT_EFI_ERROR (Status);\r
182 \r
f1294e4a 183 Stack16 = (UINT16 *)((UINT8 *) BiosDev->ThunkContext->RealModeBuffer + BiosDev->ThunkContext->RealModeBufferSize - sizeof (UINT16));\r
0d92cdc2 184\r
185 ThunkRegSet.E.SS = (UINT16) (((UINTN) Stack16 >> 16) << 12);\r
186 ThunkRegSet.E.ESP = (UINT16) (UINTN) Stack16;\r
237bb9d0 187\r
0d92cdc2 188 ThunkRegSet.E.Eip = (UINT16)((UINT32 *)NULL)[BiosInt];\r
189 ThunkRegSet.E.CS = (UINT16)(((UINT32 *)NULL)[BiosInt] >> 16);\r
f1294e4a 190 BiosDev->ThunkContext->RealModeState = &ThunkRegSet;\r
191 AsmThunk16 (BiosDev->ThunkContext);\r
237bb9d0 192 \r
0d92cdc2 193 //\r
194 // Restore protected mode interrupt state\r
195 //\r
196 Status = BiosDev->Legacy8259->SetMode (BiosDev->Legacy8259, Efi8259ProtectedMode, NULL, NULL);\r
197 ASSERT_EFI_ERROR (Status);\r
198\r
199 //\r
200 // End critical section\r
201 //\r
202 if ((Eflags | EFI_CPU_EFLAGS_IF) != 0) {\r
203 EnableInterrupts ();\r
204 }\r
205\r
206 Regs->E.EDI = ThunkRegSet.E.EDI; \r
207 Regs->E.ESI = ThunkRegSet.E.ESI; \r
208 Regs->E.EBP = ThunkRegSet.E.EBP; \r
209 Regs->E.EBX = ThunkRegSet.E.EBX; \r
210 Regs->E.EDX = ThunkRegSet.E.EDX; \r
211 Regs->E.ECX = ThunkRegSet.E.ECX; \r
212 Regs->E.EAX = ThunkRegSet.E.EAX;\r
213 Regs->E.SS = ThunkRegSet.E.SS;\r
214 Regs->E.CS = ThunkRegSet.E.CS; \r
215 Regs->E.DS = ThunkRegSet.E.DS; \r
216 Regs->E.ES = ThunkRegSet.E.ES;\r
217\r
d0c94e59 218 CopyMem (&(Regs->E.EFLAGS), &(ThunkRegSet.E.EFLAGS), sizeof (UINT32));\r
0d92cdc2 219\r
d0c94e59 220 Ret = (BOOLEAN) (Regs->E.EFLAGS.Bits.CF == 1);\r
0d92cdc2 221\r
222 return Ret;\r
223}\r
224\r
225\r