]> git.proxmox.com Git - mirror_edk2.git/blob - DuetPkg/CpuDxe/Cpu.c
Patch to remove STATIC modifier. This is on longer recommended by EFI Framework codin...
[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 VOID
323 DumpExceptionDataDebugOut (
324 IN EFI_EXCEPTION_TYPE InterruptType,
325 IN EFI_SYSTEM_CONTEXT SystemContext
326 )
327 {
328 UINT32 ErrorCodeFlag;
329
330 ErrorCodeFlag = 0x00027d00;
331
332 #ifdef EFI32
333 DEBUG ((
334 EFI_D_ERROR,
335 "!!!! IA32 Exception Type - %08x !!!!\n",
336 InterruptType
337 ));
338 DEBUG ((
339 EFI_D_ERROR,
340 "EIP - %08x, CS - %08x, EFLAGS - %08x\n",
341 SystemContext.SystemContextIa32->Eip,
342 SystemContext.SystemContextIa32->Cs,
343 SystemContext.SystemContextIa32->Eflags
344 ));
345 if (ErrorCodeFlag & (1 << InterruptType)) {
346 DEBUG ((
347 EFI_D_ERROR,
348 "ExceptionData - %08x\n",
349 SystemContext.SystemContextIa32->ExceptionData
350 ));
351 }
352 DEBUG ((
353 EFI_D_ERROR,
354 "EAX - %08x, ECX - %08x, EDX - %08x, EBX - %08x\n",
355 SystemContext.SystemContextIa32->Eax,
356 SystemContext.SystemContextIa32->Ecx,
357 SystemContext.SystemContextIa32->Edx,
358 SystemContext.SystemContextIa32->Ebx
359 ));
360 DEBUG ((
361 EFI_D_ERROR,
362 "ESP - %08x, EBP - %08x, ESI - %08x, EDI - %08x\n",
363 SystemContext.SystemContextIa32->Esp,
364 SystemContext.SystemContextIa32->Ebp,
365 SystemContext.SystemContextIa32->Esi,
366 SystemContext.SystemContextIa32->Edi
367 ));
368 DEBUG ((
369 EFI_D_ERROR,
370 "DS - %08x, ES - %08x, FS - %08x, GS - %08x, SS - %08x\n",
371 SystemContext.SystemContextIa32->Ds,
372 SystemContext.SystemContextIa32->Es,
373 SystemContext.SystemContextIa32->Fs,
374 SystemContext.SystemContextIa32->Gs,
375 SystemContext.SystemContextIa32->Ss
376 ));
377 DEBUG ((
378 EFI_D_ERROR,
379 "GDTR - %08x %08x, IDTR - %08x %08x\n",
380 SystemContext.SystemContextIa32->Gdtr[0],
381 SystemContext.SystemContextIa32->Gdtr[1],
382 SystemContext.SystemContextIa32->Idtr[0],
383 SystemContext.SystemContextIa32->Idtr[1]
384 ));
385 DEBUG ((
386 EFI_D_ERROR,
387 "LDTR - %08x, TR - %08x\n",
388 SystemContext.SystemContextIa32->Ldtr,
389 SystemContext.SystemContextIa32->Tr
390 ));
391 DEBUG ((
392 EFI_D_ERROR,
393 "CR0 - %08x, CR2 - %08x, CR3 - %08x, CR4 - %08x\n",
394 SystemContext.SystemContextIa32->Cr0,
395 SystemContext.SystemContextIa32->Cr2,
396 SystemContext.SystemContextIa32->Cr3,
397 SystemContext.SystemContextIa32->Cr4
398 ));
399 DEBUG ((
400 EFI_D_ERROR,
401 "DR0 - %08x, DR1 - %08x, DR2 - %08x, DR3 - %08x\n",
402 SystemContext.SystemContextIa32->Dr0,
403 SystemContext.SystemContextIa32->Dr1,
404 SystemContext.SystemContextIa32->Dr2,
405 SystemContext.SystemContextIa32->Dr3
406 ));
407 DEBUG ((
408 EFI_D_ERROR,
409 "DR6 - %08x, DR7 - %08x\n",
410 SystemContext.SystemContextIa32->Dr6,
411 SystemContext.SystemContextIa32->Dr7
412 ));
413 #else
414 DEBUG ((
415 EFI_D_ERROR,
416 "!!!! X64 Exception Type - %016lx !!!!\n",
417 (UINT64)InterruptType
418 ));
419 DEBUG ((
420 EFI_D_ERROR,
421 "RIP - %016lx, CS - %016lx, RFLAGS - %016lx\n",
422 SystemContext.SystemContextX64->Rip,
423 SystemContext.SystemContextX64->Cs,
424 SystemContext.SystemContextX64->Rflags
425 ));
426 if (ErrorCodeFlag & (1 << InterruptType)) {
427 DEBUG ((
428 EFI_D_ERROR,
429 "ExceptionData - %016lx\n",
430 SystemContext.SystemContextX64->ExceptionData
431 ));
432 }
433 DEBUG ((
434 EFI_D_ERROR,
435 "RAX - %016lx, RCX - %016lx, RDX - %016lx\n",
436 SystemContext.SystemContextX64->Rax,
437 SystemContext.SystemContextX64->Rcx,
438 SystemContext.SystemContextX64->Rdx
439 ));
440 DEBUG ((
441 EFI_D_ERROR,
442 "RBX - %016lx, RSP - %016lx, RBP - %016lx\n",
443 SystemContext.SystemContextX64->Rbx,
444 SystemContext.SystemContextX64->Rsp,
445 SystemContext.SystemContextX64->Rbp
446 ));
447 DEBUG ((
448 EFI_D_ERROR,
449 "RSI - %016lx, RDI - %016lx\n",
450 SystemContext.SystemContextX64->Rsi,
451 SystemContext.SystemContextX64->Rdi
452 ));
453 DEBUG ((
454 EFI_D_ERROR,
455 "R8 - %016lx, R9 - %016lx, R10 - %016lx\n",
456 SystemContext.SystemContextX64->R8,
457 SystemContext.SystemContextX64->R9,
458 SystemContext.SystemContextX64->R10
459 ));
460 DEBUG ((
461 EFI_D_ERROR,
462 "R11 - %016lx, R12 - %016lx, R13 - %016lx\n",
463 SystemContext.SystemContextX64->R11,
464 SystemContext.SystemContextX64->R12,
465 SystemContext.SystemContextX64->R13
466 ));
467 DEBUG ((
468 EFI_D_ERROR,
469 "R14 - %016lx, R15 - %016lx\n",
470 SystemContext.SystemContextX64->R14,
471 SystemContext.SystemContextX64->R15
472 ));
473 DEBUG ((
474 EFI_D_ERROR,
475 "DS - %016lx, ES - %016lx, FS - %016lx\n",
476 SystemContext.SystemContextX64->Ds,
477 SystemContext.SystemContextX64->Es,
478 SystemContext.SystemContextX64->Fs
479 ));
480 DEBUG ((
481 EFI_D_ERROR,
482 "GS - %016lx, SS - %016lx\n",
483 SystemContext.SystemContextX64->Gs,
484 SystemContext.SystemContextX64->Ss
485 ));
486 DEBUG ((
487 EFI_D_ERROR,
488 "GDTR - %016lx %016lx, LDTR - %016lx\n",
489 SystemContext.SystemContextX64->Gdtr[0],
490 SystemContext.SystemContextX64->Gdtr[1],
491 SystemContext.SystemContextX64->Ldtr
492 ));
493 DEBUG ((
494 EFI_D_ERROR,
495 "IDTR - %016lx %016lx, TR - %016lx\n",
496 SystemContext.SystemContextX64->Idtr[0],
497 SystemContext.SystemContextX64->Idtr[1],
498 SystemContext.SystemContextX64->Tr
499 ));
500 DEBUG ((
501 EFI_D_ERROR,
502 "CR0 - %016lx, CR2 - %016lx, CR3 - %016lx\n",
503 SystemContext.SystemContextX64->Cr0,
504 SystemContext.SystemContextX64->Cr2,
505 SystemContext.SystemContextX64->Cr3
506 ));
507 DEBUG ((
508 EFI_D_ERROR,
509 "CR4 - %016lx, CR8 - %016lx\n",
510 SystemContext.SystemContextX64->Cr4,
511 SystemContext.SystemContextX64->Cr8
512 ));
513 DEBUG ((
514 EFI_D_ERROR,
515 "DR0 - %016lx, DR1 - %016lx, DR2 - %016lx\n",
516 SystemContext.SystemContextX64->Dr0,
517 SystemContext.SystemContextX64->Dr1,
518 SystemContext.SystemContextX64->Dr2
519 ));
520 DEBUG ((
521 EFI_D_ERROR,
522 "DR3 - %016lx, DR6 - %016lx, DR7 - %016lx\n",
523 SystemContext.SystemContextX64->Dr3,
524 SystemContext.SystemContextX64->Dr6,
525 SystemContext.SystemContextX64->Dr7
526 ));
527 #endif
528 return ;
529 }
530 #endif
531
532 UINTN
533 SPrint (
534 IN OUT CHAR16 *Buffer,
535 IN CONST CHAR16 *Format,
536 ...
537 )
538 {
539 VA_LIST Marker;
540 UINTN Index;
541 UINTN Flags;
542 UINTN Width;
543 UINT64 Value;
544
545 VA_START (Marker, Format);
546
547 //
548 // Process the format string. Stop if Buffer is over run.
549 //
550
551 for (Index = 0; *Format != 0; Format++) {
552 if (*Format != L'%') {
553 Buffer[Index++] = *Format;
554 } else {
555
556 //
557 // Now it's time to parse what follows after %
558 // Support: % [ 0 width ] [ l ] x
559 // width - fill 0, to ensure the width of x will be "width"
560 // l - UINT64 instead of UINT32
561 //
562 Width = 0;
563 Flags = 0;
564 Format ++;
565
566 if (*Format == L'0') {
567 Flags |= PREFIX_ZERO;
568 do {
569 Width += Width * 10 + (*Format - L'0');
570 Format ++;
571 } while (*Format >= L'1' && *Format <= L'9');
572 }
573
574 if (*Format == L'l') {
575 Flags |= LONG_TYPE;
576 Format ++;
577 }
578
579
580 switch (*Format) {
581 case 'X':
582 Flags |= PREFIX_ZERO;
583 Width = sizeof (UINT64) * 2;
584 //
585 // break skiped on purpose
586 //
587 case 'x':
588 if ((Flags & LONG_TYPE) == LONG_TYPE) {
589 Value = VA_ARG (Marker, UINT64);
590 } else {
591 Value = VA_ARG (Marker, UINTN);
592 }
593
594 UnicodeValueToString (Buffer+Index, Flags, Value, Width);
595
596 for ( ; Buffer[Index] != L'\0'; Index ++) {
597 }
598
599 break;
600
601 default:
602 //
603 // if the type is unknown print it to the screen
604 //
605 Buffer[Index++] = *Format;
606 }
607 }
608 }
609 Buffer[Index++] = '\0';
610
611 VA_END (Marker);
612 return Index;
613 }
614
615 VOID
616 DumpExceptionDataVgaOut (
617 IN EFI_EXCEPTION_TYPE InterruptType,
618 IN EFI_SYSTEM_CONTEXT SystemContext
619 )
620 {
621 UINTN COLUMN_MAX;
622 UINTN ROW_MAX;
623 UINT32 ErrorCodeFlag;
624 CHAR16 *VideoBufferBase;
625 CHAR16 *VideoBuffer;
626 UINTN Index;
627
628 COLUMN_MAX = 80;
629 ROW_MAX = 25;
630 ErrorCodeFlag = 0x00027d00;
631 VideoBufferBase = (CHAR16 *) (UINTN) 0xb8000;
632 VideoBuffer = (CHAR16 *) (UINTN) 0xb8000;
633
634 #ifdef EFI32
635 SPrint (
636 VideoBuffer,
637 L"!!!! IA32 Exception Type - %08x !!!!",
638 InterruptType
639 );
640 VideoBuffer += COLUMN_MAX;
641 SPrint (
642 VideoBuffer,
643 L"EIP - %08x, CS - %08x, EFLAGS - %08x",
644 SystemContext.SystemContextIa32->Eip,
645 SystemContext.SystemContextIa32->Cs,
646 SystemContext.SystemContextIa32->Eflags
647 );
648 VideoBuffer += COLUMN_MAX;
649 if (ErrorCodeFlag & (1 << InterruptType)) {
650 SPrint (
651 VideoBuffer,
652 L"ExceptionData - %08x",
653 SystemContext.SystemContextIa32->ExceptionData
654 );
655 VideoBuffer += COLUMN_MAX;
656 }
657 SPrint (
658 VideoBuffer,
659 L"EAX - %08x, ECX - %08x, EDX - %08x, EBX - %08x",
660 SystemContext.SystemContextIa32->Eax,
661 SystemContext.SystemContextIa32->Ecx,
662 SystemContext.SystemContextIa32->Edx,
663 SystemContext.SystemContextIa32->Ebx
664 );
665 VideoBuffer += COLUMN_MAX;
666
667 SPrint (
668 VideoBuffer,
669 L"ESP - %08x, EBP - %08x, ESI - %08x, EDI - %08x",
670 SystemContext.SystemContextIa32->Esp,
671 SystemContext.SystemContextIa32->Ebp,
672 SystemContext.SystemContextIa32->Esi,
673 SystemContext.SystemContextIa32->Edi
674 );
675 VideoBuffer += COLUMN_MAX;
676
677 SPrint (
678 VideoBuffer,
679 L"DS - %08x, ES - %08x, FS - %08x, GS - %08x, SS - %08x",
680 SystemContext.SystemContextIa32->Ds,
681 SystemContext.SystemContextIa32->Es,
682 SystemContext.SystemContextIa32->Fs,
683 SystemContext.SystemContextIa32->Gs,
684 SystemContext.SystemContextIa32->Ss
685 );
686 VideoBuffer += COLUMN_MAX;
687
688 SPrint (
689 VideoBuffer,
690 L"GDTR - %08x %08x, IDTR - %08x %08x",
691 SystemContext.SystemContextIa32->Gdtr[0],
692 SystemContext.SystemContextIa32->Gdtr[1],
693 SystemContext.SystemContextIa32->Idtr[0],
694 SystemContext.SystemContextIa32->Idtr[1]
695 );
696 VideoBuffer += COLUMN_MAX;
697
698 SPrint (
699 VideoBuffer,
700 L"LDTR - %08x, TR - %08x",
701 SystemContext.SystemContextIa32->Ldtr,
702 SystemContext.SystemContextIa32->Tr
703 );
704 VideoBuffer += COLUMN_MAX;
705
706 SPrint (
707 VideoBuffer,
708 L"CR0 - %08x, CR2 - %08x, CR3 - %08x, CR4 - %08x",
709 SystemContext.SystemContextIa32->Cr0,
710 SystemContext.SystemContextIa32->Cr2,
711 SystemContext.SystemContextIa32->Cr3,
712 SystemContext.SystemContextIa32->Cr4
713 );
714 VideoBuffer += COLUMN_MAX;
715
716 SPrint (
717 VideoBuffer,
718 L"DR0 - %08x, DR1 - %08x, DR2 - %08x, DR3 - %08x",
719 SystemContext.SystemContextIa32->Dr0,
720 SystemContext.SystemContextIa32->Dr1,
721 SystemContext.SystemContextIa32->Dr2,
722 SystemContext.SystemContextIa32->Dr3
723 );
724 VideoBuffer += COLUMN_MAX;
725
726 SPrint (
727 VideoBuffer,
728 L"DR6 - %08x, DR7 - %08x",
729 SystemContext.SystemContextIa32->Dr6,
730 SystemContext.SystemContextIa32->Dr7
731 );
732 VideoBuffer += COLUMN_MAX;
733 #else
734 SPrint (
735 VideoBuffer,
736 L"!!!! X64 Exception Type - %016lx !!!!",
737 (UINT64)InterruptType
738 );
739 VideoBuffer += COLUMN_MAX;
740
741 SPrint (
742 VideoBuffer,
743 L"RIP - %016lx, CS - %016lx, RFLAGS - %016lx",
744 SystemContext.SystemContextX64->Rip,
745 SystemContext.SystemContextX64->Cs,
746 SystemContext.SystemContextX64->Rflags
747 );
748 VideoBuffer += COLUMN_MAX;
749
750 if (ErrorCodeFlag & (1 << InterruptType)) {
751 SPrint (
752 VideoBuffer,
753 L"ExceptionData - %016lx",
754 SystemContext.SystemContextX64->ExceptionData
755 );
756 VideoBuffer += COLUMN_MAX;
757 }
758
759 SPrint (
760 VideoBuffer,
761 L"RAX - %016lx, RCX - %016lx, RDX - %016lx",
762 SystemContext.SystemContextX64->Rax,
763 SystemContext.SystemContextX64->Rcx,
764 SystemContext.SystemContextX64->Rdx
765 );
766 VideoBuffer += COLUMN_MAX;
767
768 SPrint (
769 VideoBuffer,
770 L"RBX - %016lx, RSP - %016lx, RBP - %016lx",
771 SystemContext.SystemContextX64->Rbx,
772 SystemContext.SystemContextX64->Rsp,
773 SystemContext.SystemContextX64->Rbp
774 );
775 VideoBuffer += COLUMN_MAX;
776
777 SPrint (
778 VideoBuffer,
779 L"RSI - %016lx, RDI - %016lx",
780 SystemContext.SystemContextX64->Rsi,
781 SystemContext.SystemContextX64->Rdi
782 );
783 VideoBuffer += COLUMN_MAX;
784
785 SPrint (
786 VideoBuffer,
787 L"R8 - %016lx, R9 - %016lx, R10 - %016lx",
788 SystemContext.SystemContextX64->R8,
789 SystemContext.SystemContextX64->R9,
790 SystemContext.SystemContextX64->R10
791 );
792 VideoBuffer += COLUMN_MAX;
793
794 SPrint (
795 VideoBuffer,
796 L"R11 - %016lx, R12 - %016lx, R13 - %016lx",
797 SystemContext.SystemContextX64->R11,
798 SystemContext.SystemContextX64->R12,
799 SystemContext.SystemContextX64->R13
800 );
801 VideoBuffer += COLUMN_MAX;
802
803 SPrint (
804 VideoBuffer,
805 L"R14 - %016lx, R15 - %016lx",
806 SystemContext.SystemContextX64->R14,
807 SystemContext.SystemContextX64->R15
808 );
809 VideoBuffer += COLUMN_MAX;
810
811 SPrint (
812 VideoBuffer,
813 L"DS - %016lx, ES - %016lx, FS - %016lx",
814 SystemContext.SystemContextX64->Ds,
815 SystemContext.SystemContextX64->Es,
816 SystemContext.SystemContextX64->Fs
817 );
818 VideoBuffer += COLUMN_MAX;
819
820 SPrint (
821 VideoBuffer,
822 L"GS - %016lx, SS - %016lx",
823 SystemContext.SystemContextX64->Gs,
824 SystemContext.SystemContextX64->Ss
825 );
826 VideoBuffer += COLUMN_MAX;
827
828 SPrint (
829 VideoBuffer,
830 L"GDTR - %016lx %016lx, LDTR - %016lx",
831 SystemContext.SystemContextX64->Gdtr[0],
832 SystemContext.SystemContextX64->Gdtr[1],
833 SystemContext.SystemContextX64->Ldtr
834 );
835 VideoBuffer += COLUMN_MAX;
836
837 SPrint (
838 VideoBuffer,
839 L"IDTR - %016lx %016lx, TR - %016lx",
840 SystemContext.SystemContextX64->Idtr[0],
841 SystemContext.SystemContextX64->Idtr[1],
842 SystemContext.SystemContextX64->Tr
843 );
844 VideoBuffer += COLUMN_MAX;
845
846 SPrint (
847 VideoBuffer,
848 L"CR0 - %016lx, CR2 - %016lx, CR3 - %016lx",
849 SystemContext.SystemContextX64->Cr0,
850 SystemContext.SystemContextX64->Cr2,
851 SystemContext.SystemContextX64->Cr3
852 );
853 VideoBuffer += COLUMN_MAX;
854
855 SPrint (
856 VideoBuffer,
857 L"CR4 - %016lx, CR8 - %016lx",
858 SystemContext.SystemContextX64->Cr4,
859 SystemContext.SystemContextX64->Cr8
860 );
861 VideoBuffer += COLUMN_MAX;
862
863 SPrint (
864 VideoBuffer,
865 L"DR0 - %016lx, DR1 - %016lx, DR2 - %016lx",
866 SystemContext.SystemContextX64->Dr0,
867 SystemContext.SystemContextX64->Dr1,
868 SystemContext.SystemContextX64->Dr2
869 );
870 VideoBuffer += COLUMN_MAX;
871
872 SPrint (
873 VideoBuffer,
874 L"DR3 - %016lx, DR6 - %016lx, DR7 - %016lx",
875 SystemContext.SystemContextX64->Dr3,
876 SystemContext.SystemContextX64->Dr6,
877 SystemContext.SystemContextX64->Dr7
878 );
879 VideoBuffer += COLUMN_MAX;
880 #endif
881
882 for (Index = 0; Index < COLUMN_MAX * ROW_MAX; Index ++) {
883 if (Index > (UINTN)(VideoBuffer - VideoBufferBase)) {
884 VideoBufferBase[Index] = 0x0c20;
885 } else {
886 VideoBufferBase[Index] |= 0x0c00;
887 }
888 }
889
890 return ;
891 }
892
893 #if CPU_EXCEPTION_VGA_SWITCH
894 UINT16
895 SwitchVideoMode (
896 UINT16 NewVideoMode
897 )
898 /*++
899 Description
900 Switch Video Mode from current mode to new mode, and return the old mode.
901 Use Thuink
902
903 Arguments
904 NewVideoMode - new video mode want to set
905
906 Return
907 UINT16 - (UINT16) -1 indicates failure
908 Other value indicates the old mode, which can be used for restore later
909
910 --*/
911 {
912 EFI_STATUS Status;
913 EFI_LEGACY_BIOS_THUNK_PROTOCOL *LegacyBios;
914 EFI_IA32_REGISTER_SET Regs;
915 UINT16 OriginalVideoMode = (UINT16) -1;
916
917 //
918 // See if the Legacy BIOS Protocol is available
919 //
920 Status = gBS->LocateProtocol (&gEfiLegacyBiosThunkProtocolGuid, NULL, (VOID **) &LegacyBios);
921 if (EFI_ERROR (Status)) {
922 return OriginalVideoMode;
923 }
924
925 //
926 // VESA SuperVGA BIOS - GET CURRENT VIDEO MODE
927 // AX = 4F03h
928 // Return:AL = 4Fh if function supported
929 // AH = status 00h successful
930 // BX = video mode (see #0082,#0083)
931 //
932 gBS->SetMem (&Regs, sizeof (Regs), 0);
933 Regs.X.AX = 0x4F03;
934 LegacyBios->Int86 (LegacyBios, 0x10, &Regs);
935 if (Regs.X.AX == 0x004F) {
936 OriginalVideoMode = Regs.X.BX;
937 } else {
938 //
939 // VIDEO - GET CURRENT VIDEO MODE
940 // AH = 0Fh
941 // Return:AH = number of character columns
942 // AL = display mode (see #0009 at AH=00h)
943 // BH = active page (see AH=05h)
944 //
945 gBS->SetMem (&Regs, sizeof (Regs), 0);
946 Regs.H.AH = 0x0F;
947 LegacyBios->Int86 (LegacyBios, 0x10, &Regs);
948 OriginalVideoMode = Regs.H.AL;
949 }
950
951 //
952 // Set new video mode
953 //
954 if (NewVideoMode < 0x100) {
955 //
956 // Set the 80x25 Text VGA Mode: Assume successful always
957 //
958 // VIDEO - SET VIDEO MODE
959 // AH = 00h
960 // AL = desired video mode (see #0009)
961 // Return:AL = video mode flag (Phoenix, AMI BIOS)
962 // 20h mode > 7
963 // 30h modes 0-5 and 7
964 // 3Fh mode 6
965 // AL = CRT controller mode byte (Phoenix 386 BIOS v1.10)
966 //
967 gBS->SetMem (&Regs, sizeof (Regs), 0);
968 Regs.H.AH = 0x00;
969 Regs.H.AL = (UINT8) NewVideoMode;
970 LegacyBios->Int86 (LegacyBios, 0x10, &Regs);
971
972 //
973 // VIDEO - TEXT-MODE CHARGEN - LOAD ROM 8x16 CHARACTER SET (VGA)
974 // AX = 1114h
975 // BL = block to load
976 // Return:Nothing
977 //
978 gBS->SetMem (&Regs, sizeof (Regs), 0);
979 Regs.H.AH = 0x11;
980 Regs.H.AL = 0x14;
981 Regs.H.BL = 0;
982 LegacyBios->Int86 (LegacyBios, 0x10, &Regs);
983 } else {
984 //
985 // VESA SuperVGA BIOS - SET SuperVGA VIDEO MODE
986 // AX = 4F02h
987 // BX = mode (see #0082,#0083)
988 // bit 15 set means don't clear video memory
989 // bit 14 set means enable linear framebuffer mode (VBE v2.0+)
990 // Return:AL = 4Fh if function supported
991 // AH = status
992 // 00h successful
993 // 01h failed
994 //
995 gBS->SetMem (&Regs, sizeof (Regs), 0);
996 Regs.X.AX = 0x4F02;
997 Regs.X.BX = NewVideoMode;
998 LegacyBios->Int86 (LegacyBios, 0x10, &Regs);
999 if (Regs.X.AX != 0x004F) {
1000 DEBUG ((EFI_D_ERROR, "SORRY: Cannot set to video mode: 0x%04X!\n", NewVideoMode));
1001 return (UINT16) -1;
1002 }
1003 }
1004
1005 return OriginalVideoMode;
1006 }
1007 #endif
1008
1009 VOID
1010 ExceptionHandler (
1011 IN EFI_EXCEPTION_TYPE InterruptType,
1012 IN EFI_SYSTEM_CONTEXT SystemContext
1013 )
1014 {
1015 #if CPU_EXCEPTION_VGA_SWITCH
1016 UINT16 VideoMode;
1017 #endif
1018
1019 #if CPU_EXCEPTION_DEBUG_OUTPUT
1020 DumpExceptionDataDebugOut (InterruptType, SystemContext);
1021 #endif
1022
1023 #if CPU_EXCEPTION_VGA_SWITCH
1024 //
1025 // Switch to text mode for RED-SCREEN output
1026 //
1027 VideoMode = SwitchVideoMode (0x83);
1028 if (VideoMode == (UINT16) -1) {
1029 DEBUG ((EFI_D_ERROR, "Video Mode Unknown!\n"));
1030 }
1031 #endif
1032
1033 DumpExceptionDataVgaOut (InterruptType, SystemContext);
1034
1035 //
1036 // Use this macro to hang so that the compiler does not optimize out
1037 // the following RET instructions. This allows us to return if we
1038 // have a debugger attached.
1039 //
1040 CpuDeadLoop ();
1041
1042 #if CPU_EXCEPTION_VGA_SWITCH
1043 //
1044 // Switch back to the old video mode
1045 //
1046 if (VideoMode != (UINT16)-1) {
1047 SwitchVideoMode (VideoMode);
1048 }
1049 #endif
1050
1051 return ;
1052 }
1053
1054 VOID
1055 TimerHandler (
1056 IN EFI_EXCEPTION_TYPE InterruptType,
1057 IN EFI_SYSTEM_CONTEXT SystemContext
1058 )
1059 {
1060 if (mTimerHandler != NULL) {
1061 mTimerHandler (InterruptType, SystemContext);
1062 }
1063 }
1064
1065 EFI_STATUS
1066 EFIAPI
1067 InitializeCpu (
1068 IN EFI_HANDLE ImageHandle,
1069 IN EFI_SYSTEM_TABLE *SystemTable
1070 )
1071 /*++
1072
1073 Routine Description:
1074 Initialize the state information for the CPU Architectural Protocol
1075
1076 Arguments:
1077 ImageHandle of the loaded driver
1078 Pointer to the System Table
1079
1080 Returns:
1081 EFI_SUCCESS - thread can be successfully created
1082 EFI_OUT_OF_RESOURCES - cannot allocate protocol data structure
1083 EFI_DEVICE_ERROR - cannot create the thread
1084
1085 --*/
1086 {
1087 EFI_STATUS Status;
1088 EFI_8259_IRQ Irq;
1089 UINT32 InterruptVector;
1090
1091 //
1092 // Find the Legacy8259 protocol.
1093 //
1094 Status = gBS->LocateProtocol (&gEfiLegacy8259ProtocolGuid, NULL, (VOID **) &gLegacy8259);
1095 ASSERT_EFI_ERROR (Status);
1096
1097 //
1098 // Get the interrupt vector number corresponding to IRQ0 from the 8259 driver
1099 //
1100 Status = gLegacy8259->GetVector (gLegacy8259, Efi8259Irq0, (UINT8 *) &mTimerVector);
1101 ASSERT_EFI_ERROR (Status);
1102
1103 //
1104 // Reload GDT, IDT
1105 //
1106 InitDescriptor ();
1107
1108 //
1109 // Install Exception Handler (0x00 ~ 0x1F)
1110 //
1111 for (InterruptVector = 0; InterruptVector < 0x20; InterruptVector++) {
1112 InstallInterruptHandler (
1113 InterruptVector,
1114 (VOID (*)(VOID))(UINTN)((UINTN)SystemExceptionHandler + mExceptionCodeSize * InterruptVector)
1115 );
1116 }
1117
1118 //
1119 // Install Timer Handler
1120 //
1121 InstallInterruptHandler (mTimerVector, SystemTimerHandler);
1122
1123 //
1124 // BUGBUG: We add all other interrupt vector
1125 //
1126 for (Irq = Efi8259Irq1; Irq <= Efi8259Irq15; Irq++) {
1127 InterruptVector = 0;
1128 Status = gLegacy8259->GetVector (gLegacy8259, Irq, (UINT8 *) &InterruptVector);
1129 ASSERT_EFI_ERROR (Status);
1130 InstallInterruptHandler (InterruptVector, SystemTimerHandler);
1131 }
1132
1133 //
1134 // Install CPU Architectural Protocol and the thunk protocol
1135 //
1136 mHandle = NULL;
1137 Status = gBS->InstallMultipleProtocolInterfaces (
1138 &mHandle,
1139 &gEfiCpuArchProtocolGuid,
1140 &mCpu,
1141 NULL
1142 );
1143 ASSERT_EFI_ERROR (Status);
1144
1145 return EFI_SUCCESS;
1146 }
1147