]> git.proxmox.com Git - mirror_edk2.git/blame - DuetPkg/CpuDxe/Cpu.c
DuetPkg: Add DXE APRIORI for 8259 driver
[mirror_edk2.git] / DuetPkg / CpuDxe / Cpu.c
CommitLineData
c69dd9df 1/*++\r
2\r
b1f700a8
HT
3Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>\r
4This program and the accompanying materials \r
c69dd9df 5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13 Cpu.c\r
14\r
15Abstract:\r
16\r
17--*/\r
18\r
19#include "CpuDxe.h"\r
20\r
21//\r
22// Global Variables\r
23//\r
24\r
25BOOLEAN mInterruptState = FALSE;\r
26extern UINT32 mExceptionCodeSize;\r
27UINTN mTimerVector = 0;\r
28volatile EFI_CPU_INTERRUPT_HANDLER mTimerHandler = NULL;\r
29EFI_LEGACY_8259_PROTOCOL *gLegacy8259 = NULL;\r
23833b2c 30THUNK_CONTEXT mThunkContext;\r
31#define EFI_CPU_EFLAGS_IF 0x200\r
c69dd9df 32\r
23833b2c 33VOID\r
34InitializeBiosIntCaller (\r
35 VOID\r
36 );\r
37 \r
38BOOLEAN\r
39EFIAPI\r
40LegacyBiosInt86 (\r
41 IN UINT8 BiosInt,\r
42 IN EFI_IA32_REGISTER_SET *Regs\r
43 );\r
44 \r
c69dd9df 45//\r
46// The Cpu Architectural Protocol that this Driver produces\r
47//\r
48EFI_HANDLE mHandle = NULL;\r
49EFI_CPU_ARCH_PROTOCOL mCpu = {\r
50 CpuFlushCpuDataCache,\r
51 CpuEnableInterrupt,\r
52 CpuDisableInterrupt,\r
53 CpuGetInterruptState,\r
54 CpuInit,\r
55 CpuRegisterInterruptHandler,\r
56 CpuGetTimerValue,\r
57 CpuSetMemoryAttributes,\r
58 1, // NumberOfTimers\r
59 4, // DmaBufferAlignment\r
60};\r
61\r
62EFI_STATUS\r
63EFIAPI\r
64CpuFlushCpuDataCache (\r
65 IN EFI_CPU_ARCH_PROTOCOL *This,\r
66 IN EFI_PHYSICAL_ADDRESS Start,\r
67 IN UINT64 Length,\r
68 IN EFI_CPU_FLUSH_TYPE FlushType\r
69 )\r
70/*++\r
71\r
72Routine Description:\r
73 Flush CPU data cache. If the instruction cache is fully coherent\r
74 with all DMA operations then function can just return EFI_SUCCESS.\r
75\r
76Arguments:\r
77 This - Protocol instance structure\r
78 Start - Physical address to start flushing from.\r
79 Length - Number of bytes to flush. Round up to chipset \r
80 granularity.\r
81 FlushType - Specifies the type of flush operation to perform.\r
82\r
83Returns: \r
84\r
85 EFI_SUCCESS - If cache was flushed\r
86 EFI_UNSUPPORTED - If flush type is not supported.\r
87 EFI_DEVICE_ERROR - If requested range could not be flushed.\r
88\r
89--*/\r
90{\r
91 if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) {\r
92 AsmWbinvd ();\r
93 return EFI_SUCCESS;\r
94 } else if (FlushType == EfiCpuFlushTypeInvalidate) {\r
95 AsmInvd ();\r
96 return EFI_SUCCESS;\r
97 } else {\r
98 return EFI_UNSUPPORTED;\r
99 }\r
100}\r
101\r
102\r
103EFI_STATUS\r
104EFIAPI\r
105CpuEnableInterrupt (\r
106 IN EFI_CPU_ARCH_PROTOCOL *This\r
107 )\r
108/*++\r
109\r
110Routine Description:\r
111 Enables CPU interrupts.\r
112\r
113Arguments:\r
114 This - Protocol instance structure\r
115\r
116Returns: \r
117 EFI_SUCCESS - If interrupts were enabled in the CPU\r
118 EFI_DEVICE_ERROR - If interrupts could not be enabled on the CPU.\r
119\r
120--*/\r
121{\r
122 EnableInterrupts (); \r
123\r
124 mInterruptState = TRUE;\r
125 return EFI_SUCCESS;\r
126}\r
127\r
128\r
129EFI_STATUS\r
130EFIAPI\r
131CpuDisableInterrupt (\r
132 IN EFI_CPU_ARCH_PROTOCOL *This\r
133 )\r
134/*++\r
135\r
136Routine Description:\r
137 Disables CPU interrupts.\r
138\r
139Arguments:\r
140 This - Protocol instance structure\r
141\r
142Returns: \r
143 EFI_SUCCESS - If interrupts were disabled in the CPU.\r
144 EFI_DEVICE_ERROR - If interrupts could not be disabled on the CPU.\r
145\r
146--*/\r
147{\r
148 DisableInterrupts ();\r
149 \r
150 mInterruptState = FALSE;\r
151 return EFI_SUCCESS;\r
152}\r
153\r
154\r
155EFI_STATUS\r
156EFIAPI\r
157CpuGetInterruptState (\r
158 IN EFI_CPU_ARCH_PROTOCOL *This,\r
159 OUT BOOLEAN *State\r
160 )\r
161/*++\r
162\r
163Routine Description:\r
164 Return the state of interrupts.\r
165\r
166Arguments:\r
167 This - Protocol instance structure\r
168 State - Pointer to the CPU's current interrupt state\r
169\r
170Returns: \r
171 EFI_SUCCESS - If interrupts were disabled in the CPU.\r
172 EFI_INVALID_PARAMETER - State is NULL.\r
173 \r
174--*/\r
175{\r
176 if (State == NULL) {\r
177 return EFI_INVALID_PARAMETER;\r
178 }\r
179\r
180 *State = mInterruptState;\r
181 return EFI_SUCCESS;\r
182}\r
183\r
184\r
185EFI_STATUS\r
186EFIAPI\r
187CpuInit (\r
188 IN EFI_CPU_ARCH_PROTOCOL *This,\r
189 IN EFI_CPU_INIT_TYPE InitType\r
190 )\r
191\r
192/*++\r
193\r
194Routine Description:\r
195 Generates an INIT to the CPU\r
196\r
197Arguments:\r
198 This - Protocol instance structure\r
199 InitType - Type of CPU INIT to perform\r
200\r
201Returns: \r
202 EFI_SUCCESS - If CPU INIT occurred. This value should never be\r
203 seen.\r
204 EFI_DEVICE_ERROR - If CPU INIT failed.\r
205 EFI_NOT_SUPPORTED - Requested type of CPU INIT not supported.\r
206\r
207--*/\r
208{\r
209 return EFI_UNSUPPORTED;\r
210}\r
211\r
212\r
213EFI_STATUS\r
214EFIAPI\r
215CpuRegisterInterruptHandler (\r
216 IN EFI_CPU_ARCH_PROTOCOL *This,\r
217 IN EFI_EXCEPTION_TYPE InterruptType,\r
218 IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler\r
219 )\r
220/*++\r
221\r
222Routine Description:\r
223 Registers a function to be called from the CPU interrupt handler.\r
224\r
225Arguments:\r
226 This - Protocol instance structure\r
227 InterruptType - Defines which interrupt to hook. IA-32 valid range\r
228 is 0x00 through 0xFF\r
229 InterruptHandler - A pointer to a function of type \r
230 EFI_CPU_INTERRUPT_HANDLER that is called when a\r
231 processor interrupt occurs. A null pointer\r
232 is an error condition.\r
233\r
234Returns: \r
235 EFI_SUCCESS - If handler installed or uninstalled.\r
236 EFI_ALREADY_STARTED - InterruptHandler is not NULL, and a handler for \r
237 InterruptType was previously installed\r
238 EFI_INVALID_PARAMETER - InterruptHandler is NULL, and a handler for \r
239 InterruptType was not previously installed.\r
240 EFI_UNSUPPORTED - The interrupt specified by InterruptType is not\r
241 supported.\r
242\r
243--*/\r
244{\r
245 if ((InterruptType < 0) || (InterruptType >= INTERRUPT_VECTOR_NUMBER)) {\r
246 return EFI_UNSUPPORTED;\r
247 }\r
248 if ((UINTN)(UINT32)InterruptType != mTimerVector) {\r
249 return EFI_UNSUPPORTED;\r
250 }\r
251 if ((mTimerHandler == NULL) && (InterruptHandler == NULL)) {\r
252 return EFI_INVALID_PARAMETER;\r
253 } else if ((mTimerHandler != NULL) && (InterruptHandler != NULL)) {\r
254 return EFI_ALREADY_STARTED;\r
255 }\r
256 mTimerHandler = InterruptHandler;\r
257 return EFI_SUCCESS;\r
258}\r
259\r
260EFI_STATUS\r
261EFIAPI\r
262CpuGetTimerValue (\r
263 IN EFI_CPU_ARCH_PROTOCOL *This,\r
264 IN UINT32 TimerIndex,\r
265 OUT UINT64 *TimerValue,\r
266 OUT UINT64 *TimerPeriod OPTIONAL\r
267 )\r
268/*++\r
269\r
270Routine Description:\r
271 Returns a timer value from one of the CPU's internal timers. There is no\r
272 inherent time interval between ticks but is a function of the CPU \r
273 frequency.\r
274\r
275Arguments:\r
276 This - Protocol instance structure\r
277 TimerIndex - Specifies which CPU timer ie requested\r
278 TimerValue - Pointer to the returned timer value\r
279 TimerPeriod - \r
280\r
281Returns: \r
282 EFI_SUCCESS - If the CPU timer count was returned.\r
283 EFI_UNSUPPORTED - If the CPU does not have any readable timers\r
284 EFI_DEVICE_ERROR - If an error occurred reading the timer.\r
285 EFI_INVALID_PARAMETER - TimerIndex is not valid\r
286\r
287--*/\r
288{ \r
289 if (TimerValue == NULL) {\r
290 return EFI_INVALID_PARAMETER;\r
291 }\r
292 \r
293 if (TimerIndex == 0) {\r
294 *TimerValue = AsmReadTsc ();\r
295 if (TimerPeriod != NULL) {\r
296 //\r
297 // BugBug: Hard coded. Don't know how to do this generically\r
298 //\r
299 *TimerPeriod = 1000000000;\r
300 }\r
301 return EFI_SUCCESS;\r
302 }\r
303 return EFI_INVALID_PARAMETER;\r
304}\r
305\r
306EFI_STATUS\r
307EFIAPI\r
308CpuSetMemoryAttributes (\r
309 IN EFI_CPU_ARCH_PROTOCOL *This,\r
310 IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
311 IN UINT64 Length,\r
312 IN UINT64 Attributes\r
313 )\r
314/*++\r
315\r
316Routine Description:\r
317 Set memory cacheability attributes for given range of memeory\r
318\r
319Arguments:\r
320 This - Protocol instance structure\r
321 BaseAddress - Specifies the start address of the memory range\r
322 Length - Specifies the length of the memory range\r
323 Attributes - The memory cacheability for the memory range\r
324\r
325Returns: \r
326 EFI_SUCCESS - If the cacheability of that memory range is set successfully\r
327 EFI_UNSUPPORTED - If the desired operation cannot be done\r
328 EFI_INVALID_PARAMETER - The input parameter is not correct, such as Length = 0\r
329\r
330--*/\r
331{\r
332 return EFI_UNSUPPORTED;\r
333}\r
334\r
335#if CPU_EXCEPTION_DEBUG_OUTPUT\r
c69dd9df 336VOID\r
337DumpExceptionDataDebugOut (\r
338 IN EFI_EXCEPTION_TYPE InterruptType,\r
339 IN EFI_SYSTEM_CONTEXT SystemContext\r
340 )\r
341{\r
342 UINT32 ErrorCodeFlag;\r
343\r
344 ErrorCodeFlag = 0x00027d00;\r
345\r
72be1c7a 346#ifdef MDE_CPU_IA32\r
c69dd9df 347 DEBUG ((\r
348 EFI_D_ERROR,\r
349 "!!!! IA32 Exception Type - %08x !!!!\n",\r
350 InterruptType\r
351 ));\r
352 DEBUG ((\r
353 EFI_D_ERROR,\r
354 "EIP - %08x, CS - %08x, EFLAGS - %08x\n",\r
355 SystemContext.SystemContextIa32->Eip,\r
356 SystemContext.SystemContextIa32->Cs,\r
357 SystemContext.SystemContextIa32->Eflags\r
358 ));\r
359 if (ErrorCodeFlag & (1 << InterruptType)) {\r
360 DEBUG ((\r
361 EFI_D_ERROR,\r
362 "ExceptionData - %08x\n",\r
363 SystemContext.SystemContextIa32->ExceptionData\r
364 ));\r
365 }\r
366 DEBUG ((\r
367 EFI_D_ERROR,\r
368 "EAX - %08x, ECX - %08x, EDX - %08x, EBX - %08x\n",\r
369 SystemContext.SystemContextIa32->Eax,\r
370 SystemContext.SystemContextIa32->Ecx,\r
371 SystemContext.SystemContextIa32->Edx,\r
372 SystemContext.SystemContextIa32->Ebx\r
373 ));\r
374 DEBUG ((\r
375 EFI_D_ERROR,\r
376 "ESP - %08x, EBP - %08x, ESI - %08x, EDI - %08x\n",\r
377 SystemContext.SystemContextIa32->Esp,\r
378 SystemContext.SystemContextIa32->Ebp,\r
379 SystemContext.SystemContextIa32->Esi,\r
380 SystemContext.SystemContextIa32->Edi\r
381 ));\r
382 DEBUG ((\r
383 EFI_D_ERROR,\r
384 "DS - %08x, ES - %08x, FS - %08x, GS - %08x, SS - %08x\n",\r
385 SystemContext.SystemContextIa32->Ds,\r
386 SystemContext.SystemContextIa32->Es,\r
387 SystemContext.SystemContextIa32->Fs,\r
388 SystemContext.SystemContextIa32->Gs,\r
389 SystemContext.SystemContextIa32->Ss\r
390 ));\r
391 DEBUG ((\r
392 EFI_D_ERROR,\r
393 "GDTR - %08x %08x, IDTR - %08x %08x\n",\r
394 SystemContext.SystemContextIa32->Gdtr[0],\r
395 SystemContext.SystemContextIa32->Gdtr[1],\r
396 SystemContext.SystemContextIa32->Idtr[0],\r
397 SystemContext.SystemContextIa32->Idtr[1]\r
398 ));\r
399 DEBUG ((\r
400 EFI_D_ERROR,\r
401 "LDTR - %08x, TR - %08x\n",\r
402 SystemContext.SystemContextIa32->Ldtr,\r
403 SystemContext.SystemContextIa32->Tr\r
404 ));\r
405 DEBUG ((\r
406 EFI_D_ERROR,\r
407 "CR0 - %08x, CR2 - %08x, CR3 - %08x, CR4 - %08x\n",\r
408 SystemContext.SystemContextIa32->Cr0,\r
409 SystemContext.SystemContextIa32->Cr2,\r
410 SystemContext.SystemContextIa32->Cr3,\r
411 SystemContext.SystemContextIa32->Cr4\r
412 ));\r
413 DEBUG ((\r
414 EFI_D_ERROR,\r
415 "DR0 - %08x, DR1 - %08x, DR2 - %08x, DR3 - %08x\n",\r
416 SystemContext.SystemContextIa32->Dr0,\r
417 SystemContext.SystemContextIa32->Dr1,\r
418 SystemContext.SystemContextIa32->Dr2,\r
419 SystemContext.SystemContextIa32->Dr3\r
420 ));\r
421 DEBUG ((\r
422 EFI_D_ERROR,\r
423 "DR6 - %08x, DR7 - %08x\n",\r
424 SystemContext.SystemContextIa32->Dr6,\r
425 SystemContext.SystemContextIa32->Dr7\r
426 ));\r
427#else\r
428 DEBUG ((\r
429 EFI_D_ERROR,\r
430 "!!!! X64 Exception Type - %016lx !!!!\n",\r
431 (UINT64)InterruptType\r
432 ));\r
433 DEBUG ((\r
434 EFI_D_ERROR,\r
435 "RIP - %016lx, CS - %016lx, RFLAGS - %016lx\n",\r
436 SystemContext.SystemContextX64->Rip,\r
437 SystemContext.SystemContextX64->Cs,\r
438 SystemContext.SystemContextX64->Rflags\r
439 ));\r
440 if (ErrorCodeFlag & (1 << InterruptType)) {\r
441 DEBUG ((\r
442 EFI_D_ERROR,\r
443 "ExceptionData - %016lx\n",\r
444 SystemContext.SystemContextX64->ExceptionData\r
445 ));\r
446 }\r
447 DEBUG ((\r
448 EFI_D_ERROR,\r
449 "RAX - %016lx, RCX - %016lx, RDX - %016lx\n",\r
450 SystemContext.SystemContextX64->Rax,\r
451 SystemContext.SystemContextX64->Rcx,\r
452 SystemContext.SystemContextX64->Rdx\r
453 ));\r
454 DEBUG ((\r
455 EFI_D_ERROR,\r
456 "RBX - %016lx, RSP - %016lx, RBP - %016lx\n",\r
457 SystemContext.SystemContextX64->Rbx,\r
458 SystemContext.SystemContextX64->Rsp,\r
459 SystemContext.SystemContextX64->Rbp\r
460 ));\r
461 DEBUG ((\r
462 EFI_D_ERROR,\r
463 "RSI - %016lx, RDI - %016lx\n",\r
464 SystemContext.SystemContextX64->Rsi,\r
465 SystemContext.SystemContextX64->Rdi\r
466 ));\r
467 DEBUG ((\r
468 EFI_D_ERROR,\r
469 "R8 - %016lx, R9 - %016lx, R10 - %016lx\n",\r
470 SystemContext.SystemContextX64->R8,\r
471 SystemContext.SystemContextX64->R9,\r
472 SystemContext.SystemContextX64->R10\r
473 ));\r
474 DEBUG ((\r
475 EFI_D_ERROR,\r
476 "R11 - %016lx, R12 - %016lx, R13 - %016lx\n",\r
477 SystemContext.SystemContextX64->R11,\r
478 SystemContext.SystemContextX64->R12,\r
479 SystemContext.SystemContextX64->R13\r
480 ));\r
481 DEBUG ((\r
482 EFI_D_ERROR,\r
483 "R14 - %016lx, R15 - %016lx\n",\r
484 SystemContext.SystemContextX64->R14,\r
485 SystemContext.SystemContextX64->R15\r
486 ));\r
487 DEBUG ((\r
488 EFI_D_ERROR,\r
489 "DS - %016lx, ES - %016lx, FS - %016lx\n",\r
490 SystemContext.SystemContextX64->Ds,\r
491 SystemContext.SystemContextX64->Es,\r
492 SystemContext.SystemContextX64->Fs\r
493 ));\r
494 DEBUG ((\r
495 EFI_D_ERROR,\r
496 "GS - %016lx, SS - %016lx\n",\r
497 SystemContext.SystemContextX64->Gs,\r
498 SystemContext.SystemContextX64->Ss\r
499 ));\r
500 DEBUG ((\r
501 EFI_D_ERROR,\r
502 "GDTR - %016lx %016lx, LDTR - %016lx\n",\r
503 SystemContext.SystemContextX64->Gdtr[0],\r
504 SystemContext.SystemContextX64->Gdtr[1],\r
505 SystemContext.SystemContextX64->Ldtr\r
506 ));\r
507 DEBUG ((\r
508 EFI_D_ERROR,\r
509 "IDTR - %016lx %016lx, TR - %016lx\n",\r
510 SystemContext.SystemContextX64->Idtr[0],\r
511 SystemContext.SystemContextX64->Idtr[1],\r
512 SystemContext.SystemContextX64->Tr\r
513 ));\r
514 DEBUG ((\r
515 EFI_D_ERROR,\r
516 "CR0 - %016lx, CR2 - %016lx, CR3 - %016lx\n",\r
517 SystemContext.SystemContextX64->Cr0,\r
518 SystemContext.SystemContextX64->Cr2,\r
519 SystemContext.SystemContextX64->Cr3\r
520 ));\r
521 DEBUG ((\r
522 EFI_D_ERROR,\r
523 "CR4 - %016lx, CR8 - %016lx\n",\r
524 SystemContext.SystemContextX64->Cr4,\r
525 SystemContext.SystemContextX64->Cr8\r
526 ));\r
527 DEBUG ((\r
528 EFI_D_ERROR,\r
529 "DR0 - %016lx, DR1 - %016lx, DR2 - %016lx\n",\r
530 SystemContext.SystemContextX64->Dr0,\r
531 SystemContext.SystemContextX64->Dr1,\r
532 SystemContext.SystemContextX64->Dr2\r
533 ));\r
534 DEBUG ((\r
535 EFI_D_ERROR,\r
536 "DR3 - %016lx, DR6 - %016lx, DR7 - %016lx\n",\r
537 SystemContext.SystemContextX64->Dr3,\r
538 SystemContext.SystemContextX64->Dr6,\r
539 SystemContext.SystemContextX64->Dr7\r
540 ));\r
541#endif\r
542 return ;\r
543}\r
544#endif\r
545\r
c69dd9df 546\r
c69dd9df 547VOID\r
548DumpExceptionDataVgaOut (\r
549 IN EFI_EXCEPTION_TYPE InterruptType,\r
550 IN EFI_SYSTEM_CONTEXT SystemContext\r
551 )\r
552{\r
553 UINTN COLUMN_MAX;\r
554 UINTN ROW_MAX;\r
555 UINT32 ErrorCodeFlag;\r
556 CHAR16 *VideoBufferBase;\r
557 CHAR16 *VideoBuffer;\r
558 UINTN Index;\r
559\r
560 COLUMN_MAX = 80;\r
561 ROW_MAX = 25;\r
562 ErrorCodeFlag = 0x00027d00;\r
563 VideoBufferBase = (CHAR16 *) (UINTN) 0xb8000;\r
564 VideoBuffer = (CHAR16 *) (UINTN) 0xb8000;\r
565\r
72be1c7a 566#ifdef MDE_CPU_IA32\r
f05b1c14 567 UnicodeSPrintAsciiFormat (\r
568 VideoBuffer,\r
569 COLUMN_MAX * sizeof (CHAR16),\r
570 "!!!! IA32 Exception Type - %08x !!!!",\r
c69dd9df 571 InterruptType\r
572 );\r
573 VideoBuffer += COLUMN_MAX;\r
f05b1c14 574 UnicodeSPrintAsciiFormat (\r
575 VideoBuffer,\r
576 COLUMN_MAX * sizeof (CHAR16),\r
577 "EIP - %08x, CS - %08x, EFLAGS - %08x",\r
c69dd9df 578 SystemContext.SystemContextIa32->Eip,\r
579 SystemContext.SystemContextIa32->Cs,\r
580 SystemContext.SystemContextIa32->Eflags\r
581 );\r
582 VideoBuffer += COLUMN_MAX;\r
583 if (ErrorCodeFlag & (1 << InterruptType)) {\r
f05b1c14 584 UnicodeSPrintAsciiFormat (\r
c69dd9df 585 VideoBuffer,\r
f05b1c14 586 COLUMN_MAX * sizeof (CHAR16),\r
587 "ExceptionData - %08x",\r
c69dd9df 588 SystemContext.SystemContextIa32->ExceptionData\r
589 );\r
590 VideoBuffer += COLUMN_MAX;\r
591 }\r
f05b1c14 592 UnicodeSPrintAsciiFormat (\r
c69dd9df 593 VideoBuffer,\r
f05b1c14 594 COLUMN_MAX * sizeof (CHAR16),\r
595 "EAX - %08x, ECX - %08x, EDX - %08x, EBX - %08x",\r
c69dd9df 596 SystemContext.SystemContextIa32->Eax,\r
597 SystemContext.SystemContextIa32->Ecx,\r
598 SystemContext.SystemContextIa32->Edx,\r
599 SystemContext.SystemContextIa32->Ebx\r
600 );\r
601 VideoBuffer += COLUMN_MAX;\r
602\r
f05b1c14 603 UnicodeSPrintAsciiFormat (\r
c69dd9df 604 VideoBuffer,\r
f05b1c14 605 COLUMN_MAX * sizeof (CHAR16),\r
606 "ESP - %08x, EBP - %08x, ESI - %08x, EDI - %08x",\r
c69dd9df 607 SystemContext.SystemContextIa32->Esp,\r
608 SystemContext.SystemContextIa32->Ebp,\r
609 SystemContext.SystemContextIa32->Esi,\r
610 SystemContext.SystemContextIa32->Edi\r
611 );\r
612 VideoBuffer += COLUMN_MAX;\r
613\r
f05b1c14 614 UnicodeSPrintAsciiFormat (\r
c69dd9df 615 VideoBuffer,\r
f05b1c14 616 COLUMN_MAX * sizeof (CHAR16),\r
617 "DS - %08x, ES - %08x, FS - %08x, GS - %08x, SS - %08x",\r
c69dd9df 618 SystemContext.SystemContextIa32->Ds,\r
619 SystemContext.SystemContextIa32->Es,\r
620 SystemContext.SystemContextIa32->Fs,\r
621 SystemContext.SystemContextIa32->Gs,\r
622 SystemContext.SystemContextIa32->Ss\r
623 );\r
624 VideoBuffer += COLUMN_MAX;\r
625\r
f05b1c14 626 UnicodeSPrintAsciiFormat (\r
c69dd9df 627 VideoBuffer,\r
f05b1c14 628 COLUMN_MAX * sizeof (CHAR16),\r
629 "GDTR - %08x %08x, IDTR - %08x %08x",\r
c69dd9df 630 SystemContext.SystemContextIa32->Gdtr[0],\r
631 SystemContext.SystemContextIa32->Gdtr[1],\r
632 SystemContext.SystemContextIa32->Idtr[0],\r
633 SystemContext.SystemContextIa32->Idtr[1]\r
634 );\r
635 VideoBuffer += COLUMN_MAX;\r
636\r
f05b1c14 637 UnicodeSPrintAsciiFormat (\r
c69dd9df 638 VideoBuffer,\r
f05b1c14 639 COLUMN_MAX * sizeof (CHAR16),\r
640 "LDTR - %08x, TR - %08x",\r
c69dd9df 641 SystemContext.SystemContextIa32->Ldtr,\r
642 SystemContext.SystemContextIa32->Tr\r
643 );\r
644 VideoBuffer += COLUMN_MAX;\r
645\r
f05b1c14 646 UnicodeSPrintAsciiFormat (\r
c69dd9df 647 VideoBuffer,\r
f05b1c14 648 COLUMN_MAX * sizeof (CHAR16),\r
649 "CR0 - %08x, CR2 - %08x, CR3 - %08x, CR4 - %08x",\r
c69dd9df 650 SystemContext.SystemContextIa32->Cr0,\r
651 SystemContext.SystemContextIa32->Cr2,\r
652 SystemContext.SystemContextIa32->Cr3,\r
653 SystemContext.SystemContextIa32->Cr4\r
654 );\r
655 VideoBuffer += COLUMN_MAX;\r
656\r
f05b1c14 657 UnicodeSPrintAsciiFormat (\r
c69dd9df 658 VideoBuffer,\r
f05b1c14 659 COLUMN_MAX * sizeof (CHAR16),\r
660 "DR0 - %08x, DR1 - %08x, DR2 - %08x, DR3 - %08x",\r
c69dd9df 661 SystemContext.SystemContextIa32->Dr0,\r
662 SystemContext.SystemContextIa32->Dr1,\r
663 SystemContext.SystemContextIa32->Dr2,\r
664 SystemContext.SystemContextIa32->Dr3\r
665 );\r
666 VideoBuffer += COLUMN_MAX;\r
667\r
f05b1c14 668 UnicodeSPrintAsciiFormat (\r
c69dd9df 669 VideoBuffer,\r
f05b1c14 670 COLUMN_MAX * sizeof (CHAR16),\r
671 "DR6 - %08x, DR7 - %08x",\r
c69dd9df 672 SystemContext.SystemContextIa32->Dr6,\r
673 SystemContext.SystemContextIa32->Dr7\r
674 );\r
675 VideoBuffer += COLUMN_MAX;\r
676#else\r
f05b1c14 677 UnicodeSPrintAsciiFormat (\r
c69dd9df 678 VideoBuffer,\r
f05b1c14 679 COLUMN_MAX * sizeof (CHAR16),\r
680 "!!!! X64 Exception Type - %016lx !!!!",\r
c69dd9df 681 (UINT64)InterruptType\r
682 );\r
683 VideoBuffer += COLUMN_MAX;\r
684\r
f05b1c14 685 UnicodeSPrintAsciiFormat (\r
c69dd9df 686 VideoBuffer,\r
f05b1c14 687 COLUMN_MAX * sizeof (CHAR16),\r
688 "RIP - %016lx, CS - %016lx, RFLAGS - %016lx",\r
c69dd9df 689 SystemContext.SystemContextX64->Rip,\r
690 SystemContext.SystemContextX64->Cs,\r
691 SystemContext.SystemContextX64->Rflags\r
692 );\r
693 VideoBuffer += COLUMN_MAX;\r
694\r
695 if (ErrorCodeFlag & (1 << InterruptType)) {\r
f05b1c14 696 UnicodeSPrintAsciiFormat (\r
c69dd9df 697 VideoBuffer,\r
f05b1c14 698 COLUMN_MAX * sizeof (CHAR16),\r
699 "ExceptionData - %016lx",\r
c69dd9df 700 SystemContext.SystemContextX64->ExceptionData\r
701 );\r
702 VideoBuffer += COLUMN_MAX;\r
703 }\r
704\r
f05b1c14 705 UnicodeSPrintAsciiFormat (\r
c69dd9df 706 VideoBuffer,\r
f05b1c14 707 COLUMN_MAX * sizeof (CHAR16),\r
708 "RAX - %016lx, RCX - %016lx, RDX - %016lx",\r
c69dd9df 709 SystemContext.SystemContextX64->Rax,\r
710 SystemContext.SystemContextX64->Rcx,\r
711 SystemContext.SystemContextX64->Rdx\r
712 );\r
713 VideoBuffer += COLUMN_MAX;\r
714\r
f05b1c14 715 UnicodeSPrintAsciiFormat (\r
c69dd9df 716 VideoBuffer,\r
f05b1c14 717 COLUMN_MAX * sizeof (CHAR16),\r
718 "RBX - %016lx, RSP - %016lx, RBP - %016lx",\r
c69dd9df 719 SystemContext.SystemContextX64->Rbx,\r
720 SystemContext.SystemContextX64->Rsp,\r
721 SystemContext.SystemContextX64->Rbp\r
722 );\r
723 VideoBuffer += COLUMN_MAX;\r
724\r
f05b1c14 725 UnicodeSPrintAsciiFormat (\r
c69dd9df 726 VideoBuffer,\r
f05b1c14 727 COLUMN_MAX * sizeof (CHAR16),\r
728 "RSI - %016lx, RDI - %016lx",\r
c69dd9df 729 SystemContext.SystemContextX64->Rsi,\r
730 SystemContext.SystemContextX64->Rdi\r
731 );\r
732 VideoBuffer += COLUMN_MAX;\r
733\r
f05b1c14 734 UnicodeSPrintAsciiFormat (\r
c69dd9df 735 VideoBuffer,\r
f05b1c14 736 COLUMN_MAX * sizeof (CHAR16),\r
737 "R8 - %016lx, R9 - %016lx, R10 - %016lx",\r
c69dd9df 738 SystemContext.SystemContextX64->R8,\r
739 SystemContext.SystemContextX64->R9,\r
740 SystemContext.SystemContextX64->R10\r
741 );\r
742 VideoBuffer += COLUMN_MAX;\r
743\r
f05b1c14 744 UnicodeSPrintAsciiFormat (\r
c69dd9df 745 VideoBuffer,\r
f05b1c14 746 COLUMN_MAX * sizeof (CHAR16),\r
747 "R11 - %016lx, R12 - %016lx, R13 - %016lx",\r
c69dd9df 748 SystemContext.SystemContextX64->R11,\r
749 SystemContext.SystemContextX64->R12,\r
750 SystemContext.SystemContextX64->R13\r
751 );\r
752 VideoBuffer += COLUMN_MAX;\r
753\r
f05b1c14 754 UnicodeSPrintAsciiFormat (\r
c69dd9df 755 VideoBuffer,\r
f05b1c14 756 COLUMN_MAX * sizeof (CHAR16),\r
757 "R14 - %016lx, R15 - %016lx",\r
c69dd9df 758 SystemContext.SystemContextX64->R14,\r
759 SystemContext.SystemContextX64->R15\r
760 );\r
761 VideoBuffer += COLUMN_MAX;\r
762\r
f05b1c14 763 UnicodeSPrintAsciiFormat (\r
c69dd9df 764 VideoBuffer,\r
f05b1c14 765 COLUMN_MAX * sizeof (CHAR16),\r
766 "DS - %016lx, ES - %016lx, FS - %016lx",\r
c69dd9df 767 SystemContext.SystemContextX64->Ds,\r
768 SystemContext.SystemContextX64->Es,\r
769 SystemContext.SystemContextX64->Fs\r
770 );\r
771 VideoBuffer += COLUMN_MAX;\r
772\r
f05b1c14 773 UnicodeSPrintAsciiFormat (\r
c69dd9df 774 VideoBuffer,\r
f05b1c14 775 COLUMN_MAX * sizeof (CHAR16),\r
776 "GS - %016lx, SS - %016lx",\r
c69dd9df 777 SystemContext.SystemContextX64->Gs,\r
778 SystemContext.SystemContextX64->Ss\r
779 );\r
780 VideoBuffer += COLUMN_MAX;\r
781\r
f05b1c14 782 UnicodeSPrintAsciiFormat (\r
c69dd9df 783 VideoBuffer,\r
f05b1c14 784 COLUMN_MAX * sizeof (CHAR16),\r
785 "GDTR - %016lx %016lx, LDTR - %016lx",\r
c69dd9df 786 SystemContext.SystemContextX64->Gdtr[0],\r
787 SystemContext.SystemContextX64->Gdtr[1],\r
788 SystemContext.SystemContextX64->Ldtr\r
789 );\r
790 VideoBuffer += COLUMN_MAX;\r
791\r
f05b1c14 792 UnicodeSPrintAsciiFormat (\r
c69dd9df 793 VideoBuffer,\r
f05b1c14 794 COLUMN_MAX * sizeof (CHAR16),\r
795 "IDTR - %016lx %016lx, TR - %016lx",\r
c69dd9df 796 SystemContext.SystemContextX64->Idtr[0],\r
797 SystemContext.SystemContextX64->Idtr[1],\r
798 SystemContext.SystemContextX64->Tr\r
799 );\r
800 VideoBuffer += COLUMN_MAX;\r
801\r
f05b1c14 802 UnicodeSPrintAsciiFormat (\r
c69dd9df 803 VideoBuffer,\r
f05b1c14 804 COLUMN_MAX * sizeof (CHAR16),\r
805 "CR0 - %016lx, CR2 - %016lx, CR3 - %016lx",\r
c69dd9df 806 SystemContext.SystemContextX64->Cr0,\r
807 SystemContext.SystemContextX64->Cr2,\r
808 SystemContext.SystemContextX64->Cr3\r
809 );\r
810 VideoBuffer += COLUMN_MAX;\r
811\r
f05b1c14 812 UnicodeSPrintAsciiFormat (\r
c69dd9df 813 VideoBuffer,\r
f05b1c14 814 COLUMN_MAX * sizeof (CHAR16),\r
815 "CR4 - %016lx, CR8 - %016lx",\r
c69dd9df 816 SystemContext.SystemContextX64->Cr4,\r
817 SystemContext.SystemContextX64->Cr8\r
818 );\r
819 VideoBuffer += COLUMN_MAX;\r
820\r
f05b1c14 821 UnicodeSPrintAsciiFormat (\r
c69dd9df 822 VideoBuffer,\r
f05b1c14 823 COLUMN_MAX * sizeof (CHAR16),\r
824 "DR0 - %016lx, DR1 - %016lx, DR2 - %016lx",\r
c69dd9df 825 SystemContext.SystemContextX64->Dr0,\r
826 SystemContext.SystemContextX64->Dr1,\r
827 SystemContext.SystemContextX64->Dr2\r
828 );\r
829 VideoBuffer += COLUMN_MAX;\r
830\r
f05b1c14 831 UnicodeSPrintAsciiFormat (\r
c69dd9df 832 VideoBuffer,\r
f05b1c14 833 COLUMN_MAX * sizeof (CHAR16),\r
834 "DR3 - %016lx, DR6 - %016lx, DR7 - %016lx",\r
c69dd9df 835 SystemContext.SystemContextX64->Dr3,\r
836 SystemContext.SystemContextX64->Dr6,\r
837 SystemContext.SystemContextX64->Dr7\r
838 );\r
839 VideoBuffer += COLUMN_MAX;\r
840#endif\r
841\r
842 for (Index = 0; Index < COLUMN_MAX * ROW_MAX; Index ++) {\r
843 if (Index > (UINTN)(VideoBuffer - VideoBufferBase)) {\r
844 VideoBufferBase[Index] = 0x0c20;\r
845 } else {\r
846 VideoBufferBase[Index] |= 0x0c00;\r
847 }\r
848 }\r
849\r
850 return ;\r
851}\r
852\r
853#if CPU_EXCEPTION_VGA_SWITCH\r
c69dd9df 854UINT16\r
855SwitchVideoMode (\r
856 UINT16 NewVideoMode\r
857 )\r
858/*++\r
859Description\r
860 Switch Video Mode from current mode to new mode, and return the old mode.\r
861 Use Thuink\r
862\r
863Arguments\r
864 NewVideoMode - new video mode want to set\r
865\r
866Return\r
867 UINT16 - (UINT16) -1 indicates failure\r
868 Other value indicates the old mode, which can be used for restore later\r
869 \r
870--*/\r
871{\r
872 EFI_STATUS Status;\r
873 EFI_LEGACY_BIOS_THUNK_PROTOCOL *LegacyBios;\r
874 EFI_IA32_REGISTER_SET Regs;\r
875 UINT16 OriginalVideoMode = (UINT16) -1;\r
876 \r
c69dd9df 877\r
878 //\r
879 // VESA SuperVGA BIOS - GET CURRENT VIDEO MODE\r
880 // AX = 4F03h\r
881 // Return:AL = 4Fh if function supported\r
882 // AH = status 00h successful\r
883 // BX = video mode (see #0082,#0083)\r
884 //\r
885 gBS->SetMem (&Regs, sizeof (Regs), 0);\r
886 Regs.X.AX = 0x4F03;\r
23833b2c 887 LegacyBiosInt86 (0x10, &Regs);\r
c69dd9df 888 if (Regs.X.AX == 0x004F) {\r
889 OriginalVideoMode = Regs.X.BX;\r
890 } else {\r
891 //\r
892 // VIDEO - GET CURRENT VIDEO MODE\r
893 // AH = 0Fh\r
894 // Return:AH = number of character columns\r
895 // AL = display mode (see #0009 at AH=00h)\r
896 // BH = active page (see AH=05h)\r
897 //\r
898 gBS->SetMem (&Regs, sizeof (Regs), 0);\r
899 Regs.H.AH = 0x0F;\r
23833b2c 900 LegacyBiosInt86 (0x10, &Regs);\r
c69dd9df 901 OriginalVideoMode = Regs.H.AL;\r
902 }\r
903\r
904 //\r
905 // Set new video mode\r
906 //\r
907 if (NewVideoMode < 0x100) {\r
908 //\r
909 // Set the 80x25 Text VGA Mode: Assume successful always\r
910 //\r
911 // VIDEO - SET VIDEO MODE\r
912 // AH = 00h\r
913 // AL = desired video mode (see #0009)\r
914 // Return:AL = video mode flag (Phoenix, AMI BIOS)\r
915 // 20h mode > 7\r
916 // 30h modes 0-5 and 7\r
917 // 3Fh mode 6\r
918 // AL = CRT controller mode byte (Phoenix 386 BIOS v1.10)\r
919 //\r
920 gBS->SetMem (&Regs, sizeof (Regs), 0);\r
921 Regs.H.AH = 0x00;\r
922 Regs.H.AL = (UINT8) NewVideoMode;\r
23833b2c 923 LegacyBiosInt86 (0x10, &Regs);\r
c69dd9df 924\r
925 //\r
926 // VIDEO - TEXT-MODE CHARGEN - LOAD ROM 8x16 CHARACTER SET (VGA)\r
927 // AX = 1114h\r
928 // BL = block to load\r
929 // Return:Nothing\r
930 //\r
931 gBS->SetMem (&Regs, sizeof (Regs), 0);\r
932 Regs.H.AH = 0x11;\r
933 Regs.H.AL = 0x14;\r
934 Regs.H.BL = 0;\r
23833b2c 935 LegacyBiosInt86 (0x10, &Regs);\r
c69dd9df 936 } else {\r
937 //\r
938 // VESA SuperVGA BIOS - SET SuperVGA VIDEO MODE\r
939 // AX = 4F02h\r
940 // BX = mode (see #0082,#0083)\r
941 // bit 15 set means don't clear video memory\r
942 // bit 14 set means enable linear framebuffer mode (VBE v2.0+)\r
943 // Return:AL = 4Fh if function supported\r
944 // AH = status\r
945 // 00h successful\r
946 // 01h failed\r
947 //\r
948 gBS->SetMem (&Regs, sizeof (Regs), 0);\r
949 Regs.X.AX = 0x4F02;\r
950 Regs.X.BX = NewVideoMode;\r
23833b2c 951 LegacyBiosInt86 (0x10, &Regs);\r
c69dd9df 952 if (Regs.X.AX != 0x004F) {\r
953 DEBUG ((EFI_D_ERROR, "SORRY: Cannot set to video mode: 0x%04X!\n", NewVideoMode));\r
954 return (UINT16) -1;\r
955 }\r
956 }\r
957\r
958 return OriginalVideoMode;\r
959}\r
960#endif\r
961\r
962VOID\r
963ExceptionHandler (\r
964 IN EFI_EXCEPTION_TYPE InterruptType,\r
965 IN EFI_SYSTEM_CONTEXT SystemContext\r
966 )\r
967{\r
968#if CPU_EXCEPTION_VGA_SWITCH\r
969 UINT16 VideoMode;\r
970#endif\r
971\r
972#if CPU_EXCEPTION_DEBUG_OUTPUT\r
973 DumpExceptionDataDebugOut (InterruptType, SystemContext);\r
974#endif\r
975\r
976#if CPU_EXCEPTION_VGA_SWITCH\r
977 //\r
978 // Switch to text mode for RED-SCREEN output\r
979 //\r
980 VideoMode = SwitchVideoMode (0x83);\r
981 if (VideoMode == (UINT16) -1) {\r
982 DEBUG ((EFI_D_ERROR, "Video Mode Unknown!\n"));\r
983 }\r
984#endif\r
985\r
986 DumpExceptionDataVgaOut (InterruptType, SystemContext);\r
987\r
988 //\r
989 // Use this macro to hang so that the compiler does not optimize out\r
990 // the following RET instructions. This allows us to return if we\r
991 // have a debugger attached.\r
992 //\r
993 CpuDeadLoop ();\r
994\r
995#if CPU_EXCEPTION_VGA_SWITCH\r
996 //\r
997 // Switch back to the old video mode\r
998 //\r
999 if (VideoMode != (UINT16)-1) {\r
1000 SwitchVideoMode (VideoMode);\r
1001 }\r
1002#endif\r
1003\r
1004 return ;\r
1005}\r
1006\r
1007VOID\r
1008TimerHandler (\r
1009 IN EFI_EXCEPTION_TYPE InterruptType,\r
1010 IN EFI_SYSTEM_CONTEXT SystemContext\r
1011 )\r
1012{\r
1013 if (mTimerHandler != NULL) {\r
1014 mTimerHandler (InterruptType, SystemContext);\r
1015 }\r
1016}\r
1017\r
1018EFI_STATUS\r
1019EFIAPI\r
1020InitializeCpu (\r
1021 IN EFI_HANDLE ImageHandle,\r
1022 IN EFI_SYSTEM_TABLE *SystemTable\r
1023 )\r
1024/*++\r
1025\r
1026Routine Description:\r
1027 Initialize the state information for the CPU Architectural Protocol\r
1028\r
1029Arguments:\r
1030 ImageHandle of the loaded driver\r
1031 Pointer to the System Table\r
1032\r
1033Returns:\r
1034 EFI_SUCCESS - thread can be successfully created\r
1035 EFI_OUT_OF_RESOURCES - cannot allocate protocol data structure\r
1036 EFI_DEVICE_ERROR - cannot create the thread\r
1037\r
1038--*/\r
1039{\r
1040 EFI_STATUS Status;\r
1041 EFI_8259_IRQ Irq;\r
1042 UINT32 InterruptVector;\r
1043\r
1044 //\r
1045 // Find the Legacy8259 protocol.\r
1046 //\r
1047 Status = gBS->LocateProtocol (&gEfiLegacy8259ProtocolGuid, NULL, (VOID **) &gLegacy8259);\r
1048 ASSERT_EFI_ERROR (Status);\r
1049\r
1050 //\r
1051 // Get the interrupt vector number corresponding to IRQ0 from the 8259 driver\r
1052 //\r
1053 Status = gLegacy8259->GetVector (gLegacy8259, Efi8259Irq0, (UINT8 *) &mTimerVector);\r
1054 ASSERT_EFI_ERROR (Status);\r
1055\r
1056 //\r
1057 // Reload GDT, IDT\r
1058 //\r
1059 InitDescriptor ();\r
1060\r
1061 //\r
1062 // Install Exception Handler (0x00 ~ 0x1F)\r
1063 //\r
1064 for (InterruptVector = 0; InterruptVector < 0x20; InterruptVector++) {\r
1065 InstallInterruptHandler (\r
1066 InterruptVector,\r
1067 (VOID (*)(VOID))(UINTN)((UINTN)SystemExceptionHandler + mExceptionCodeSize * InterruptVector)\r
1068 );\r
1069 }\r
1070\r
1071 //\r
1072 // Install Timer Handler\r
1073 //\r
1074 InstallInterruptHandler (mTimerVector, SystemTimerHandler);\r
1075\r
1076 //\r
1077 // BUGBUG: We add all other interrupt vector\r
1078 //\r
1079 for (Irq = Efi8259Irq1; Irq <= Efi8259Irq15; Irq++) {\r
1080 InterruptVector = 0;\r
1081 Status = gLegacy8259->GetVector (gLegacy8259, Irq, (UINT8 *) &InterruptVector);\r
1082 ASSERT_EFI_ERROR (Status);\r
1083 InstallInterruptHandler (InterruptVector, SystemTimerHandler);\r
1084 }\r
1085\r
23833b2c 1086 InitializeBiosIntCaller();\r
1087 \r
c69dd9df 1088 //\r
1089 // Install CPU Architectural Protocol and the thunk protocol\r
1090 //\r
1091 mHandle = NULL;\r
1092 Status = gBS->InstallMultipleProtocolInterfaces (\r
1093 &mHandle,\r
1094 &gEfiCpuArchProtocolGuid,\r
1095 &mCpu,\r
1096 NULL\r
1097 );\r
1098 ASSERT_EFI_ERROR (Status);\r
1099\r
1100 return EFI_SUCCESS;\r
1101}\r
1102\r
23833b2c 1103VOID\r
1104InitializeBiosIntCaller (\r
1105 VOID\r
1106 )\r
1107{\r
1108 EFI_STATUS Status;\r
1109 UINT32 RealModeBufferSize;\r
1110 UINT32 ExtraStackSize;\r
1111 EFI_PHYSICAL_ADDRESS LegacyRegionBase;\r
1112 \r
1113 //\r
1114 // Get LegacyRegion\r
1115 //\r
1116 AsmGetThunk16Properties (&RealModeBufferSize, &ExtraStackSize);\r
1117\r
1118 LegacyRegionBase = 0x100000;\r
1119 Status = gBS->AllocatePages (\r
1120 AllocateMaxAddress,\r
1121 EfiACPIMemoryNVS,\r
1122 EFI_SIZE_TO_PAGES(RealModeBufferSize + ExtraStackSize + 200),\r
1123 &LegacyRegionBase\r
1124 );\r
1125 ASSERT_EFI_ERROR (Status);\r
1126 \r
1127 mThunkContext.RealModeBuffer = (VOID*)(UINTN)LegacyRegionBase;\r
1128 mThunkContext.RealModeBufferSize = EFI_PAGES_TO_SIZE (RealModeBufferSize);\r
1129 mThunkContext.ThunkAttributes = 3;\r
1130 AsmPrepareThunk16(&mThunkContext);\r
1131 \r
1132}\r
1133\r
1134BOOLEAN\r
1135EFIAPI\r
1136LegacyBiosInt86 (\r
1137 IN UINT8 BiosInt,\r
1138 IN EFI_IA32_REGISTER_SET *Regs\r
1139 )\r
1140{\r
1141 UINTN Status;\r
1142 UINTN Eflags;\r
1143 IA32_REGISTER_SET ThunkRegSet;\r
1144 BOOLEAN Ret;\r
1145 UINT16 *Stack16;\r
1146 \r
1147 Regs->X.Flags.Reserved1 = 1;\r
1148 Regs->X.Flags.Reserved2 = 0;\r
1149 Regs->X.Flags.Reserved3 = 0;\r
1150 Regs->X.Flags.Reserved4 = 0;\r
1151 Regs->X.Flags.IOPL = 3;\r
1152 Regs->X.Flags.NT = 0;\r
1153 Regs->X.Flags.IF = 1;\r
1154 Regs->X.Flags.TF = 0;\r
1155 Regs->X.Flags.CF = 0;\r
1156\r
1157 ZeroMem (&ThunkRegSet, sizeof (ThunkRegSet));\r
1158 ThunkRegSet.E.EDI = Regs->E.EDI;\r
1159 ThunkRegSet.E.ESI = Regs->E.ESI;\r
1160 ThunkRegSet.E.EBP = Regs->E.EBP;\r
1161 ThunkRegSet.E.EBX = Regs->E.EBX;\r
1162 ThunkRegSet.E.EDX = Regs->E.EDX;\r
1163 ThunkRegSet.E.ECX = Regs->E.ECX;\r
1164 ThunkRegSet.E.EAX = Regs->E.EAX;\r
1165 ThunkRegSet.E.DS = Regs->E.DS;\r
1166 ThunkRegSet.E.ES = Regs->E.ES;\r
1167\r
1168 CopyMem (&(ThunkRegSet.E.EFLAGS), &(Regs->E.EFlags), sizeof (UINT32));\r
1169 \r
1170 //\r
1171 // The call to Legacy16 is a critical section to EFI\r
1172 //\r
1173 Eflags = AsmReadEflags ();\r
1174 if ((Eflags | EFI_CPU_EFLAGS_IF) != 0) {\r
1175 DisableInterrupts ();\r
1176 }\r
1177\r
1178 //\r
1179 // Set Legacy16 state. 0x08, 0x70 is legacy 8259 vector bases.\r
1180 //\r
1181 Status = gLegacy8259->SetMode (gLegacy8259, Efi8259LegacyMode, NULL, NULL);\r
1182 ASSERT_EFI_ERROR (Status);\r
1183 \r
1184 Stack16 = (UINT16 *)((UINT8 *) mThunkContext.RealModeBuffer + mThunkContext.RealModeBufferSize - sizeof (UINT16));\r
1185 Stack16 -= sizeof (ThunkRegSet.E.EFLAGS) / sizeof (UINT16);\r
1186 CopyMem (Stack16, &ThunkRegSet.E.EFLAGS, sizeof (ThunkRegSet.E.EFLAGS));\r
1187\r
1188 ThunkRegSet.E.SS = (UINT16) (((UINTN) Stack16 >> 16) << 12);\r
1189 ThunkRegSet.E.ESP = (UINT16) (UINTN) Stack16;\r
1190 ThunkRegSet.E.Eip = (UINT16)((UINT32 *)NULL)[BiosInt];\r
1191 ThunkRegSet.E.CS = (UINT16)(((UINT32 *)NULL)[BiosInt] >> 16);\r
1192 mThunkContext.RealModeState = &ThunkRegSet;\r
1193 AsmThunk16 (&mThunkContext);\r
1194\r
1195 //\r
1196 // Restore protected mode interrupt state\r
1197 //\r
1198 Status = gLegacy8259->SetMode (gLegacy8259, Efi8259ProtectedMode, NULL, NULL);\r
1199 ASSERT_EFI_ERROR (Status);\r
1200\r
1201 //\r
1202 // End critical section\r
1203 //\r
1204 if ((Eflags | EFI_CPU_EFLAGS_IF) != 0) {\r
1205 EnableInterrupts ();\r
1206 }\r
1207\r
1208 Regs->E.EDI = ThunkRegSet.E.EDI; \r
1209 Regs->E.ESI = ThunkRegSet.E.ESI; \r
1210 Regs->E.EBP = ThunkRegSet.E.EBP; \r
1211 Regs->E.EBX = ThunkRegSet.E.EBX; \r
1212 Regs->E.EDX = ThunkRegSet.E.EDX; \r
1213 Regs->E.ECX = ThunkRegSet.E.ECX; \r
1214 Regs->E.EAX = ThunkRegSet.E.EAX;\r
1215 Regs->E.SS = ThunkRegSet.E.SS;\r
1216 Regs->E.CS = ThunkRegSet.E.CS; \r
1217 Regs->E.DS = ThunkRegSet.E.DS; \r
1218 Regs->E.ES = ThunkRegSet.E.ES;\r
1219\r
1220 CopyMem (&(Regs->E.EFlags), &(ThunkRegSet.E.EFLAGS), sizeof (UINT32));\r
1221\r
1222 Ret = (BOOLEAN) (Regs->E.EFlags.CF == 1);\r
1223\r
1224 return Ret;\r
1225}\r