4 #define EFI_CPU_EFLAGS_IF 0x200
6 THUNK_CONTEXT mThunkContext
;
9 InitializeBiosIntCaller (
10 IN BIOS_VIDEO_DEV
*BiosDev
14 UINT32 RealModeBufferSize
;
15 UINT32 ExtraStackSize
;
16 EFI_PHYSICAL_ADDRESS LegacyRegionBase
;
21 AsmGetThunk16Properties (&RealModeBufferSize
, &ExtraStackSize
);
23 LegacyRegionBase
= 0x100000;
24 Status
= gBS
->AllocatePages (
27 EFI_SIZE_TO_PAGES(RealModeBufferSize
+ ExtraStackSize
+ 200),
30 ASSERT_EFI_ERROR (Status
);
32 mThunkContext
.RealModeBuffer
= (VOID
*)(UINTN
)LegacyRegionBase
;
33 mThunkContext
.RealModeBufferSize
= EFI_PAGES_TO_SIZE (RealModeBufferSize
);
34 mThunkContext
.ThunkAttributes
= 3;
35 AsmPrepareThunk16(&mThunkContext
);
40 InitializeInterruptRedirection (
41 IN BIOS_VIDEO_DEV
*BiosDev
46 Initialize interrupt redirection code and entries, because
47 IDT Vectors 0x68-0x6f must be redirected to IDT Vectors 0x08-0x0f.
48 Or the interrupt will lost when we do thunk.
49 NOTE: We do not reset 8259 vector base, because it will cause pending
60 EFI_PHYSICAL_ADDRESS LegacyRegionBase
;
61 UINTN LegacyRegionLength
;
64 UINT8 ProtectedModeBaseVector
;
65 UINT32 InterruptRedirectionCode
[] = {
66 0x90CF08CD, // INT8; IRET; NOP
67 0x90CF09CD, // INT9; IRET; NOP
68 0x90CF0ACD, // INTA; IRET; NOP
69 0x90CF0BCD, // INTB; IRET; NOP
70 0x90CF0CCD, // INTC; IRET; NOP
71 0x90CF0DCD, // INTD; IRET; NOP
72 0x90CF0ECD, // INTE; IRET; NOP
73 0x90CF0FCD // INTF; IRET; NOP
79 LegacyRegionLength
= sizeof(InterruptRedirectionCode
);
80 LegacyRegionBase
= 0x100000;
81 Status
= gBS
->AllocatePages (
84 EFI_SIZE_TO_PAGES(LegacyRegionLength
),
87 ASSERT_EFI_ERROR (Status
);
90 // Copy code to legacy region
92 CopyMem ((VOID
*)(UINTN
)LegacyRegionBase
, InterruptRedirectionCode
, sizeof (InterruptRedirectionCode
));
95 // Get VectorBase, it should be 0x68
97 Status
= BiosDev
->Legacy8259
->GetVector (BiosDev
->Legacy8259
, Efi8259Irq0
, &ProtectedModeBaseVector
);
98 ASSERT_EFI_ERROR (Status
);
101 // Patch IVT 0x68 ~ 0x6f
103 IdtArray
= (UINT32
*) 0;
104 for (Index
= 0; Index
< 8; Index
++) {
105 IdtArray
[ProtectedModeBaseVector
+ Index
] = ((EFI_SEGMENT (LegacyRegionBase
+ Index
* 4)) << 16) | (EFI_OFFSET (LegacyRegionBase
+ Index
* 4));
114 IN BIOS_VIDEO_DEV
*BiosDev
,
116 IN EFI_IA32_REGISTER_SET
*Regs
121 Thunk to 16-bit real mode and execute a software interrupt with a vector
122 of BiosInt. Regs will contain the 16-bit register context on entry and
126 This - Protocol instance pointer.
127 BiosInt - Processor interrupt vector to invoke
128 Reg - Register contexted passed into (and returned) from thunk to
132 FALSE - Thunk completed, and there were no BIOS errors in the target code.
134 TRUE - There was a BIOS erro in the target code.
140 IA32_REGISTER_SET ThunkRegSet
;
144 Regs
->X
.Flags
.Reserved1
= 1;
145 Regs
->X
.Flags
.Reserved2
= 0;
146 Regs
->X
.Flags
.Reserved3
= 0;
147 Regs
->X
.Flags
.Reserved4
= 0;
148 Regs
->X
.Flags
.IOPL
= 3;
149 Regs
->X
.Flags
.NT
= 0;
150 Regs
->X
.Flags
.IF
= 1;
151 Regs
->X
.Flags
.TF
= 0;
152 Regs
->X
.Flags
.CF
= 0;
154 ZeroMem (&ThunkRegSet
, sizeof (ThunkRegSet
));
155 ThunkRegSet
.E
.EDI
= Regs
->E
.EDI
;
156 ThunkRegSet
.E
.ESI
= Regs
->E
.ESI
;
157 ThunkRegSet
.E
.EBP
= Regs
->E
.EBP
;
158 ThunkRegSet
.E
.EBX
= Regs
->E
.EBX
;
159 ThunkRegSet
.E
.EDX
= Regs
->E
.EDX
;
160 ThunkRegSet
.E
.ECX
= Regs
->E
.ECX
;
161 ThunkRegSet
.E
.EAX
= Regs
->E
.EAX
;
162 ThunkRegSet
.E
.DS
= Regs
->E
.DS
;
163 ThunkRegSet
.E
.ES
= Regs
->E
.ES
;
165 CopyMem (&(ThunkRegSet
.E
.EFLAGS
), &(Regs
->E
.EFlags
), sizeof (UINT32
));
168 // The call to Legacy16 is a critical section to EFI
170 Eflags
= AsmReadEflags ();
171 if ((Eflags
| EFI_CPU_EFLAGS_IF
) != 0) {
172 DisableInterrupts ();
176 // Set Legacy16 state. 0x08, 0x70 is legacy 8259 vector bases.
178 Status
= BiosDev
->Legacy8259
->SetMode (BiosDev
->Legacy8259
, Efi8259LegacyMode
, NULL
, NULL
);
179 ASSERT_EFI_ERROR (Status
);
181 Stack16
= (UINT16
*)((UINT8
*) mThunkContext
.RealModeBuffer
+ mThunkContext
.RealModeBufferSize
- sizeof (UINT16
));
182 Stack16
-= sizeof (ThunkRegSet
.E
.EFLAGS
) / sizeof (UINT16
);
183 CopyMem (Stack16
, &ThunkRegSet
.E
.EFLAGS
, sizeof (ThunkRegSet
.E
.EFLAGS
));
185 ThunkRegSet
.E
.SS
= (UINT16
) (((UINTN
) Stack16
>> 16) << 12);
186 ThunkRegSet
.E
.ESP
= (UINT16
) (UINTN
) Stack16
;
187 ThunkRegSet
.E
.Eip
= (UINT16
)((UINT32
*)NULL
)[BiosInt
];
188 ThunkRegSet
.E
.CS
= (UINT16
)(((UINT32
*)NULL
)[BiosInt
] >> 16);
189 mThunkContext
.RealModeState
= &ThunkRegSet
;
190 AsmThunk16 (&mThunkContext
);
193 // Restore protected mode interrupt state
195 Status
= BiosDev
->Legacy8259
->SetMode (BiosDev
->Legacy8259
, Efi8259ProtectedMode
, NULL
, NULL
);
196 ASSERT_EFI_ERROR (Status
);
199 // End critical section
201 if ((Eflags
| EFI_CPU_EFLAGS_IF
) != 0) {
205 Regs
->E
.EDI
= ThunkRegSet
.E
.EDI
;
206 Regs
->E
.ESI
= ThunkRegSet
.E
.ESI
;
207 Regs
->E
.EBP
= ThunkRegSet
.E
.EBP
;
208 Regs
->E
.EBX
= ThunkRegSet
.E
.EBX
;
209 Regs
->E
.EDX
= ThunkRegSet
.E
.EDX
;
210 Regs
->E
.ECX
= ThunkRegSet
.E
.ECX
;
211 Regs
->E
.EAX
= ThunkRegSet
.E
.EAX
;
212 Regs
->E
.SS
= ThunkRegSet
.E
.SS
;
213 Regs
->E
.CS
= ThunkRegSet
.E
.CS
;
214 Regs
->E
.DS
= ThunkRegSet
.E
.DS
;
215 Regs
->E
.ES
= ThunkRegSet
.E
.ES
;
217 CopyMem (&(Regs
->E
.EFlags
), &(ThunkRegSet
.E
.EFLAGS
), sizeof (UINT32
));
219 Ret
= (BOOLEAN
) (Regs
->E
.EFlags
.CF
== 1);