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