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