]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - DuetPkg/BiosVideoThunkDxe/LegacyBiosThunk.c
Update the copyright notice format
[mirror_edk2.git] / DuetPkg / BiosVideoThunkDxe / LegacyBiosThunk.c
... / ...
CommitLineData
1/** @file\r
2 Provide legacy thunk interface for accessing Bios Video Rom.\r
3 \r
4Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.<BR>\r
5This program and the accompanying materials \r
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
14\r
15#include "BiosVideo.h"\r
16\r
17#define EFI_CPU_EFLAGS_IF 0x200\r
18\r
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
24VOID\r
25InitializeBiosIntCaller (\r
26 THUNK_CONTEXT *ThunkContext\r
27 )\r
28{\r
29 EFI_STATUS Status;\r
30 UINT32 RealModeBufferSize;\r
31 UINT32 ExtraStackSize;\r
32 EFI_PHYSICAL_ADDRESS LegacyRegionBase;\r
33 UINT32 LegacyRegionSize;\r
34 //\r
35 // Get LegacyRegion\r
36 //\r
37 AsmGetThunk16Properties (&RealModeBufferSize, &ExtraStackSize);\r
38 LegacyRegionSize = (((RealModeBufferSize + ExtraStackSize) / EFI_PAGE_SIZE) + 1) * EFI_PAGE_SIZE;\r
39 LegacyRegionBase = 0x100000;\r
40 Status = gBS->AllocatePages (\r
41 AllocateMaxAddress,\r
42 EfiACPIMemoryNVS,\r
43 EFI_SIZE_TO_PAGES(LegacyRegionSize),\r
44 &LegacyRegionBase\r
45 );\r
46 ASSERT_EFI_ERROR (Status);\r
47 \r
48 ThunkContext->RealModeBuffer = (VOID*)(UINTN)LegacyRegionBase;\r
49 ThunkContext->RealModeBufferSize = LegacyRegionSize;\r
50 ThunkContext->ThunkAttributes = THUNK_ATTRIBUTE_BIG_REAL_MODE|THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15;\r
51 AsmPrepareThunk16(ThunkContext);\r
52}\r
53\r
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
64VOID\r
65InitializeInterruptRedirection (\r
66 IN EFI_LEGACY_8259_PROTOCOL *Legacy8259\r
67 )\r
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
107 Status = Legacy8259->GetVector (Legacy8259, Efi8259Irq0, &ProtectedModeBaseVector);\r
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
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
134BOOLEAN\r
135EFIAPI\r
136LegacyBiosInt86 (\r
137 IN BIOS_VIDEO_DEV *BiosDev,\r
138 IN UINT8 BiosInt,\r
139 IN IA32_REGISTER_SET *Regs\r
140 )\r
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
148 ZeroMem (&ThunkRegSet, sizeof (ThunkRegSet));\r
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
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
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
183 Stack16 = (UINT16 *)((UINT8 *) BiosDev->ThunkContext->RealModeBuffer + BiosDev->ThunkContext->RealModeBufferSize - sizeof (UINT16));\r
184\r
185 ThunkRegSet.E.SS = (UINT16) (((UINTN) Stack16 >> 16) << 12);\r
186 ThunkRegSet.E.ESP = (UINT16) (UINTN) Stack16;\r
187\r
188 ThunkRegSet.E.Eip = (UINT16)((UINT32 *)NULL)[BiosInt];\r
189 ThunkRegSet.E.CS = (UINT16)(((UINT32 *)NULL)[BiosInt] >> 16);\r
190 BiosDev->ThunkContext->RealModeState = &ThunkRegSet;\r
191 AsmThunk16 (BiosDev->ThunkContext);\r
192 \r
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
218 CopyMem (&(Regs->E.EFLAGS), &(ThunkRegSet.E.EFLAGS), sizeof (UINT32));\r
219\r
220 Ret = (BOOLEAN) (Regs->E.EFLAGS.Bits.CF == 1);\r
221\r
222 return Ret;\r
223}\r
224\r
225\r