]> git.proxmox.com Git - mirror_edk2.git/blob - DuetPkg/CpuDxe/Cpu.c
Add thunk code for CpuDxe driver.
[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 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 EFI32
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 UINTN
547 SPrint (
548 IN OUT CHAR16 *Buffer,
549 IN CONST CHAR16 *Format,
550 ...
551 )
552 {
553 VA_LIST Marker;
554 UINTN Index;
555 UINTN Flags;
556 UINTN Width;
557 UINT64 Value;
558
559 VA_START (Marker, Format);
560
561 //
562 // Process the format string. Stop if Buffer is over run.
563 //
564
565 for (Index = 0; *Format != 0; Format++) {
566 if (*Format != L'%') {
567 Buffer[Index++] = *Format;
568 } else {
569
570 //
571 // Now it's time to parse what follows after %
572 // Support: % [ 0 width ] [ l ] x
573 // width - fill 0, to ensure the width of x will be "width"
574 // l - UINT64 instead of UINT32
575 //
576 Width = 0;
577 Flags = 0;
578 Format ++;
579
580 if (*Format == L'0') {
581 Flags |= PREFIX_ZERO;
582 do {
583 Width += Width * 10 + (*Format - L'0');
584 Format ++;
585 } while (*Format >= L'1' && *Format <= L'9');
586 }
587
588 if (*Format == L'l') {
589 Flags |= LONG_TYPE;
590 Format ++;
591 }
592
593
594 switch (*Format) {
595 case 'X':
596 Flags |= PREFIX_ZERO;
597 Width = sizeof (UINT64) * 2;
598 //
599 // break skiped on purpose
600 //
601 case 'x':
602 if ((Flags & LONG_TYPE) == LONG_TYPE) {
603 Value = VA_ARG (Marker, UINT64);
604 } else {
605 Value = VA_ARG (Marker, UINTN);
606 }
607
608 UnicodeValueToString (Buffer+Index, Flags, Value, Width);
609
610 for ( ; Buffer[Index] != L'\0'; Index ++) {
611 }
612
613 break;
614
615 default:
616 //
617 // if the type is unknown print it to the screen
618 //
619 Buffer[Index++] = *Format;
620 }
621 }
622 }
623 Buffer[Index++] = '\0';
624
625 VA_END (Marker);
626 return Index;
627 }
628
629 VOID
630 DumpExceptionDataVgaOut (
631 IN EFI_EXCEPTION_TYPE InterruptType,
632 IN EFI_SYSTEM_CONTEXT SystemContext
633 )
634 {
635 UINTN COLUMN_MAX;
636 UINTN ROW_MAX;
637 UINT32 ErrorCodeFlag;
638 CHAR16 *VideoBufferBase;
639 CHAR16 *VideoBuffer;
640 UINTN Index;
641
642 COLUMN_MAX = 80;
643 ROW_MAX = 25;
644 ErrorCodeFlag = 0x00027d00;
645 VideoBufferBase = (CHAR16 *) (UINTN) 0xb8000;
646 VideoBuffer = (CHAR16 *) (UINTN) 0xb8000;
647
648 #ifdef EFI32
649 SPrint (
650 VideoBuffer,
651 L"!!!! IA32 Exception Type - %08x !!!!",
652 InterruptType
653 );
654 VideoBuffer += COLUMN_MAX;
655 SPrint (
656 VideoBuffer,
657 L"EIP - %08x, CS - %08x, EFLAGS - %08x",
658 SystemContext.SystemContextIa32->Eip,
659 SystemContext.SystemContextIa32->Cs,
660 SystemContext.SystemContextIa32->Eflags
661 );
662 VideoBuffer += COLUMN_MAX;
663 if (ErrorCodeFlag & (1 << InterruptType)) {
664 SPrint (
665 VideoBuffer,
666 L"ExceptionData - %08x",
667 SystemContext.SystemContextIa32->ExceptionData
668 );
669 VideoBuffer += COLUMN_MAX;
670 }
671 SPrint (
672 VideoBuffer,
673 L"EAX - %08x, ECX - %08x, EDX - %08x, EBX - %08x",
674 SystemContext.SystemContextIa32->Eax,
675 SystemContext.SystemContextIa32->Ecx,
676 SystemContext.SystemContextIa32->Edx,
677 SystemContext.SystemContextIa32->Ebx
678 );
679 VideoBuffer += COLUMN_MAX;
680
681 SPrint (
682 VideoBuffer,
683 L"ESP - %08x, EBP - %08x, ESI - %08x, EDI - %08x",
684 SystemContext.SystemContextIa32->Esp,
685 SystemContext.SystemContextIa32->Ebp,
686 SystemContext.SystemContextIa32->Esi,
687 SystemContext.SystemContextIa32->Edi
688 );
689 VideoBuffer += COLUMN_MAX;
690
691 SPrint (
692 VideoBuffer,
693 L"DS - %08x, ES - %08x, FS - %08x, GS - %08x, SS - %08x",
694 SystemContext.SystemContextIa32->Ds,
695 SystemContext.SystemContextIa32->Es,
696 SystemContext.SystemContextIa32->Fs,
697 SystemContext.SystemContextIa32->Gs,
698 SystemContext.SystemContextIa32->Ss
699 );
700 VideoBuffer += COLUMN_MAX;
701
702 SPrint (
703 VideoBuffer,
704 L"GDTR - %08x %08x, IDTR - %08x %08x",
705 SystemContext.SystemContextIa32->Gdtr[0],
706 SystemContext.SystemContextIa32->Gdtr[1],
707 SystemContext.SystemContextIa32->Idtr[0],
708 SystemContext.SystemContextIa32->Idtr[1]
709 );
710 VideoBuffer += COLUMN_MAX;
711
712 SPrint (
713 VideoBuffer,
714 L"LDTR - %08x, TR - %08x",
715 SystemContext.SystemContextIa32->Ldtr,
716 SystemContext.SystemContextIa32->Tr
717 );
718 VideoBuffer += COLUMN_MAX;
719
720 SPrint (
721 VideoBuffer,
722 L"CR0 - %08x, CR2 - %08x, CR3 - %08x, CR4 - %08x",
723 SystemContext.SystemContextIa32->Cr0,
724 SystemContext.SystemContextIa32->Cr2,
725 SystemContext.SystemContextIa32->Cr3,
726 SystemContext.SystemContextIa32->Cr4
727 );
728 VideoBuffer += COLUMN_MAX;
729
730 SPrint (
731 VideoBuffer,
732 L"DR0 - %08x, DR1 - %08x, DR2 - %08x, DR3 - %08x",
733 SystemContext.SystemContextIa32->Dr0,
734 SystemContext.SystemContextIa32->Dr1,
735 SystemContext.SystemContextIa32->Dr2,
736 SystemContext.SystemContextIa32->Dr3
737 );
738 VideoBuffer += COLUMN_MAX;
739
740 SPrint (
741 VideoBuffer,
742 L"DR6 - %08x, DR7 - %08x",
743 SystemContext.SystemContextIa32->Dr6,
744 SystemContext.SystemContextIa32->Dr7
745 );
746 VideoBuffer += COLUMN_MAX;
747 #else
748 SPrint (
749 VideoBuffer,
750 L"!!!! X64 Exception Type - %016lx !!!!",
751 (UINT64)InterruptType
752 );
753 VideoBuffer += COLUMN_MAX;
754
755 SPrint (
756 VideoBuffer,
757 L"RIP - %016lx, CS - %016lx, RFLAGS - %016lx",
758 SystemContext.SystemContextX64->Rip,
759 SystemContext.SystemContextX64->Cs,
760 SystemContext.SystemContextX64->Rflags
761 );
762 VideoBuffer += COLUMN_MAX;
763
764 if (ErrorCodeFlag & (1 << InterruptType)) {
765 SPrint (
766 VideoBuffer,
767 L"ExceptionData - %016lx",
768 SystemContext.SystemContextX64->ExceptionData
769 );
770 VideoBuffer += COLUMN_MAX;
771 }
772
773 SPrint (
774 VideoBuffer,
775 L"RAX - %016lx, RCX - %016lx, RDX - %016lx",
776 SystemContext.SystemContextX64->Rax,
777 SystemContext.SystemContextX64->Rcx,
778 SystemContext.SystemContextX64->Rdx
779 );
780 VideoBuffer += COLUMN_MAX;
781
782 SPrint (
783 VideoBuffer,
784 L"RBX - %016lx, RSP - %016lx, RBP - %016lx",
785 SystemContext.SystemContextX64->Rbx,
786 SystemContext.SystemContextX64->Rsp,
787 SystemContext.SystemContextX64->Rbp
788 );
789 VideoBuffer += COLUMN_MAX;
790
791 SPrint (
792 VideoBuffer,
793 L"RSI - %016lx, RDI - %016lx",
794 SystemContext.SystemContextX64->Rsi,
795 SystemContext.SystemContextX64->Rdi
796 );
797 VideoBuffer += COLUMN_MAX;
798
799 SPrint (
800 VideoBuffer,
801 L"R8 - %016lx, R9 - %016lx, R10 - %016lx",
802 SystemContext.SystemContextX64->R8,
803 SystemContext.SystemContextX64->R9,
804 SystemContext.SystemContextX64->R10
805 );
806 VideoBuffer += COLUMN_MAX;
807
808 SPrint (
809 VideoBuffer,
810 L"R11 - %016lx, R12 - %016lx, R13 - %016lx",
811 SystemContext.SystemContextX64->R11,
812 SystemContext.SystemContextX64->R12,
813 SystemContext.SystemContextX64->R13
814 );
815 VideoBuffer += COLUMN_MAX;
816
817 SPrint (
818 VideoBuffer,
819 L"R14 - %016lx, R15 - %016lx",
820 SystemContext.SystemContextX64->R14,
821 SystemContext.SystemContextX64->R15
822 );
823 VideoBuffer += COLUMN_MAX;
824
825 SPrint (
826 VideoBuffer,
827 L"DS - %016lx, ES - %016lx, FS - %016lx",
828 SystemContext.SystemContextX64->Ds,
829 SystemContext.SystemContextX64->Es,
830 SystemContext.SystemContextX64->Fs
831 );
832 VideoBuffer += COLUMN_MAX;
833
834 SPrint (
835 VideoBuffer,
836 L"GS - %016lx, SS - %016lx",
837 SystemContext.SystemContextX64->Gs,
838 SystemContext.SystemContextX64->Ss
839 );
840 VideoBuffer += COLUMN_MAX;
841
842 SPrint (
843 VideoBuffer,
844 L"GDTR - %016lx %016lx, LDTR - %016lx",
845 SystemContext.SystemContextX64->Gdtr[0],
846 SystemContext.SystemContextX64->Gdtr[1],
847 SystemContext.SystemContextX64->Ldtr
848 );
849 VideoBuffer += COLUMN_MAX;
850
851 SPrint (
852 VideoBuffer,
853 L"IDTR - %016lx %016lx, TR - %016lx",
854 SystemContext.SystemContextX64->Idtr[0],
855 SystemContext.SystemContextX64->Idtr[1],
856 SystemContext.SystemContextX64->Tr
857 );
858 VideoBuffer += COLUMN_MAX;
859
860 SPrint (
861 VideoBuffer,
862 L"CR0 - %016lx, CR2 - %016lx, CR3 - %016lx",
863 SystemContext.SystemContextX64->Cr0,
864 SystemContext.SystemContextX64->Cr2,
865 SystemContext.SystemContextX64->Cr3
866 );
867 VideoBuffer += COLUMN_MAX;
868
869 SPrint (
870 VideoBuffer,
871 L"CR4 - %016lx, CR8 - %016lx",
872 SystemContext.SystemContextX64->Cr4,
873 SystemContext.SystemContextX64->Cr8
874 );
875 VideoBuffer += COLUMN_MAX;
876
877 SPrint (
878 VideoBuffer,
879 L"DR0 - %016lx, DR1 - %016lx, DR2 - %016lx",
880 SystemContext.SystemContextX64->Dr0,
881 SystemContext.SystemContextX64->Dr1,
882 SystemContext.SystemContextX64->Dr2
883 );
884 VideoBuffer += COLUMN_MAX;
885
886 SPrint (
887 VideoBuffer,
888 L"DR3 - %016lx, DR6 - %016lx, DR7 - %016lx",
889 SystemContext.SystemContextX64->Dr3,
890 SystemContext.SystemContextX64->Dr6,
891 SystemContext.SystemContextX64->Dr7
892 );
893 VideoBuffer += COLUMN_MAX;
894 #endif
895
896 for (Index = 0; Index < COLUMN_MAX * ROW_MAX; Index ++) {
897 if (Index > (UINTN)(VideoBuffer - VideoBufferBase)) {
898 VideoBufferBase[Index] = 0x0c20;
899 } else {
900 VideoBufferBase[Index] |= 0x0c00;
901 }
902 }
903
904 return ;
905 }
906
907 #if CPU_EXCEPTION_VGA_SWITCH
908 UINT16
909 SwitchVideoMode (
910 UINT16 NewVideoMode
911 )
912 /*++
913 Description
914 Switch Video Mode from current mode to new mode, and return the old mode.
915 Use Thuink
916
917 Arguments
918 NewVideoMode - new video mode want to set
919
920 Return
921 UINT16 - (UINT16) -1 indicates failure
922 Other value indicates the old mode, which can be used for restore later
923
924 --*/
925 {
926 EFI_STATUS Status;
927 EFI_LEGACY_BIOS_THUNK_PROTOCOL *LegacyBios;
928 EFI_IA32_REGISTER_SET Regs;
929 UINT16 OriginalVideoMode = (UINT16) -1;
930
931
932 //
933 // VESA SuperVGA BIOS - GET CURRENT VIDEO MODE
934 // AX = 4F03h
935 // Return:AL = 4Fh if function supported
936 // AH = status 00h successful
937 // BX = video mode (see #0082,#0083)
938 //
939 gBS->SetMem (&Regs, sizeof (Regs), 0);
940 Regs.X.AX = 0x4F03;
941 LegacyBiosInt86 (0x10, &Regs);
942 if (Regs.X.AX == 0x004F) {
943 OriginalVideoMode = Regs.X.BX;
944 } else {
945 //
946 // VIDEO - GET CURRENT VIDEO MODE
947 // AH = 0Fh
948 // Return:AH = number of character columns
949 // AL = display mode (see #0009 at AH=00h)
950 // BH = active page (see AH=05h)
951 //
952 gBS->SetMem (&Regs, sizeof (Regs), 0);
953 Regs.H.AH = 0x0F;
954 LegacyBiosInt86 (0x10, &Regs);
955 OriginalVideoMode = Regs.H.AL;
956 }
957
958 //
959 // Set new video mode
960 //
961 if (NewVideoMode < 0x100) {
962 //
963 // Set the 80x25 Text VGA Mode: Assume successful always
964 //
965 // VIDEO - SET VIDEO MODE
966 // AH = 00h
967 // AL = desired video mode (see #0009)
968 // Return:AL = video mode flag (Phoenix, AMI BIOS)
969 // 20h mode > 7
970 // 30h modes 0-5 and 7
971 // 3Fh mode 6
972 // AL = CRT controller mode byte (Phoenix 386 BIOS v1.10)
973 //
974 gBS->SetMem (&Regs, sizeof (Regs), 0);
975 Regs.H.AH = 0x00;
976 Regs.H.AL = (UINT8) NewVideoMode;
977 LegacyBiosInt86 (0x10, &Regs);
978
979 //
980 // VIDEO - TEXT-MODE CHARGEN - LOAD ROM 8x16 CHARACTER SET (VGA)
981 // AX = 1114h
982 // BL = block to load
983 // Return:Nothing
984 //
985 gBS->SetMem (&Regs, sizeof (Regs), 0);
986 Regs.H.AH = 0x11;
987 Regs.H.AL = 0x14;
988 Regs.H.BL = 0;
989 LegacyBiosInt86 (0x10, &Regs);
990 } else {
991 //
992 // VESA SuperVGA BIOS - SET SuperVGA VIDEO MODE
993 // AX = 4F02h
994 // BX = mode (see #0082,#0083)
995 // bit 15 set means don't clear video memory
996 // bit 14 set means enable linear framebuffer mode (VBE v2.0+)
997 // Return:AL = 4Fh if function supported
998 // AH = status
999 // 00h successful
1000 // 01h failed
1001 //
1002 gBS->SetMem (&Regs, sizeof (Regs), 0);
1003 Regs.X.AX = 0x4F02;
1004 Regs.X.BX = NewVideoMode;
1005 LegacyBiosInt86 (0x10, &Regs);
1006 if (Regs.X.AX != 0x004F) {
1007 DEBUG ((EFI_D_ERROR, "SORRY: Cannot set to video mode: 0x%04X!\n", NewVideoMode));
1008 return (UINT16) -1;
1009 }
1010 }
1011
1012 return OriginalVideoMode;
1013 }
1014 #endif
1015
1016 VOID
1017 ExceptionHandler (
1018 IN EFI_EXCEPTION_TYPE InterruptType,
1019 IN EFI_SYSTEM_CONTEXT SystemContext
1020 )
1021 {
1022 #if CPU_EXCEPTION_VGA_SWITCH
1023 UINT16 VideoMode;
1024 #endif
1025
1026 #if CPU_EXCEPTION_DEBUG_OUTPUT
1027 DumpExceptionDataDebugOut (InterruptType, SystemContext);
1028 #endif
1029
1030 #if CPU_EXCEPTION_VGA_SWITCH
1031 //
1032 // Switch to text mode for RED-SCREEN output
1033 //
1034 VideoMode = SwitchVideoMode (0x83);
1035 if (VideoMode == (UINT16) -1) {
1036 DEBUG ((EFI_D_ERROR, "Video Mode Unknown!\n"));
1037 }
1038 #endif
1039
1040 DumpExceptionDataVgaOut (InterruptType, SystemContext);
1041
1042 //
1043 // Use this macro to hang so that the compiler does not optimize out
1044 // the following RET instructions. This allows us to return if we
1045 // have a debugger attached.
1046 //
1047 CpuDeadLoop ();
1048
1049 #if CPU_EXCEPTION_VGA_SWITCH
1050 //
1051 // Switch back to the old video mode
1052 //
1053 if (VideoMode != (UINT16)-1) {
1054 SwitchVideoMode (VideoMode);
1055 }
1056 #endif
1057
1058 return ;
1059 }
1060
1061 VOID
1062 TimerHandler (
1063 IN EFI_EXCEPTION_TYPE InterruptType,
1064 IN EFI_SYSTEM_CONTEXT SystemContext
1065 )
1066 {
1067 if (mTimerHandler != NULL) {
1068 mTimerHandler (InterruptType, SystemContext);
1069 }
1070 }
1071
1072 EFI_STATUS
1073 EFIAPI
1074 InitializeCpu (
1075 IN EFI_HANDLE ImageHandle,
1076 IN EFI_SYSTEM_TABLE *SystemTable
1077 )
1078 /*++
1079
1080 Routine Description:
1081 Initialize the state information for the CPU Architectural Protocol
1082
1083 Arguments:
1084 ImageHandle of the loaded driver
1085 Pointer to the System Table
1086
1087 Returns:
1088 EFI_SUCCESS - thread can be successfully created
1089 EFI_OUT_OF_RESOURCES - cannot allocate protocol data structure
1090 EFI_DEVICE_ERROR - cannot create the thread
1091
1092 --*/
1093 {
1094 EFI_STATUS Status;
1095 EFI_8259_IRQ Irq;
1096 UINT32 InterruptVector;
1097
1098 //
1099 // Find the Legacy8259 protocol.
1100 //
1101 Status = gBS->LocateProtocol (&gEfiLegacy8259ProtocolGuid, NULL, (VOID **) &gLegacy8259);
1102 ASSERT_EFI_ERROR (Status);
1103
1104 //
1105 // Get the interrupt vector number corresponding to IRQ0 from the 8259 driver
1106 //
1107 Status = gLegacy8259->GetVector (gLegacy8259, Efi8259Irq0, (UINT8 *) &mTimerVector);
1108 ASSERT_EFI_ERROR (Status);
1109
1110 //
1111 // Reload GDT, IDT
1112 //
1113 InitDescriptor ();
1114
1115 //
1116 // Install Exception Handler (0x00 ~ 0x1F)
1117 //
1118 for (InterruptVector = 0; InterruptVector < 0x20; InterruptVector++) {
1119 InstallInterruptHandler (
1120 InterruptVector,
1121 (VOID (*)(VOID))(UINTN)((UINTN)SystemExceptionHandler + mExceptionCodeSize * InterruptVector)
1122 );
1123 }
1124
1125 //
1126 // Install Timer Handler
1127 //
1128 InstallInterruptHandler (mTimerVector, SystemTimerHandler);
1129
1130 //
1131 // BUGBUG: We add all other interrupt vector
1132 //
1133 for (Irq = Efi8259Irq1; Irq <= Efi8259Irq15; Irq++) {
1134 InterruptVector = 0;
1135 Status = gLegacy8259->GetVector (gLegacy8259, Irq, (UINT8 *) &InterruptVector);
1136 ASSERT_EFI_ERROR (Status);
1137 InstallInterruptHandler (InterruptVector, SystemTimerHandler);
1138 }
1139
1140 InitializeBiosIntCaller();
1141
1142 //
1143 // Install CPU Architectural Protocol and the thunk protocol
1144 //
1145 mHandle = NULL;
1146 Status = gBS->InstallMultipleProtocolInterfaces (
1147 &mHandle,
1148 &gEfiCpuArchProtocolGuid,
1149 &mCpu,
1150 NULL
1151 );
1152 ASSERT_EFI_ERROR (Status);
1153
1154 return EFI_SUCCESS;
1155 }
1156
1157 VOID
1158 InitializeBiosIntCaller (
1159 VOID
1160 )
1161 {
1162 EFI_STATUS Status;
1163 UINT32 RealModeBufferSize;
1164 UINT32 ExtraStackSize;
1165 EFI_PHYSICAL_ADDRESS LegacyRegionBase;
1166
1167 //
1168 // Get LegacyRegion
1169 //
1170 AsmGetThunk16Properties (&RealModeBufferSize, &ExtraStackSize);
1171
1172 LegacyRegionBase = 0x100000;
1173 Status = gBS->AllocatePages (
1174 AllocateMaxAddress,
1175 EfiACPIMemoryNVS,
1176 EFI_SIZE_TO_PAGES(RealModeBufferSize + ExtraStackSize + 200),
1177 &LegacyRegionBase
1178 );
1179 ASSERT_EFI_ERROR (Status);
1180
1181 mThunkContext.RealModeBuffer = (VOID*)(UINTN)LegacyRegionBase;
1182 mThunkContext.RealModeBufferSize = EFI_PAGES_TO_SIZE (RealModeBufferSize);
1183 mThunkContext.ThunkAttributes = 3;
1184 AsmPrepareThunk16(&mThunkContext);
1185
1186 }
1187
1188 BOOLEAN
1189 EFIAPI
1190 LegacyBiosInt86 (
1191 IN UINT8 BiosInt,
1192 IN EFI_IA32_REGISTER_SET *Regs
1193 )
1194 {
1195 UINTN Status;
1196 UINTN Eflags;
1197 IA32_REGISTER_SET ThunkRegSet;
1198 BOOLEAN Ret;
1199 UINT16 *Stack16;
1200
1201 Regs->X.Flags.Reserved1 = 1;
1202 Regs->X.Flags.Reserved2 = 0;
1203 Regs->X.Flags.Reserved3 = 0;
1204 Regs->X.Flags.Reserved4 = 0;
1205 Regs->X.Flags.IOPL = 3;
1206 Regs->X.Flags.NT = 0;
1207 Regs->X.Flags.IF = 1;
1208 Regs->X.Flags.TF = 0;
1209 Regs->X.Flags.CF = 0;
1210
1211 ZeroMem (&ThunkRegSet, sizeof (ThunkRegSet));
1212 ThunkRegSet.E.EDI = Regs->E.EDI;
1213 ThunkRegSet.E.ESI = Regs->E.ESI;
1214 ThunkRegSet.E.EBP = Regs->E.EBP;
1215 ThunkRegSet.E.EBX = Regs->E.EBX;
1216 ThunkRegSet.E.EDX = Regs->E.EDX;
1217 ThunkRegSet.E.ECX = Regs->E.ECX;
1218 ThunkRegSet.E.EAX = Regs->E.EAX;
1219 ThunkRegSet.E.DS = Regs->E.DS;
1220 ThunkRegSet.E.ES = Regs->E.ES;
1221
1222 CopyMem (&(ThunkRegSet.E.EFLAGS), &(Regs->E.EFlags), sizeof (UINT32));
1223
1224 //
1225 // The call to Legacy16 is a critical section to EFI
1226 //
1227 Eflags = AsmReadEflags ();
1228 if ((Eflags | EFI_CPU_EFLAGS_IF) != 0) {
1229 DisableInterrupts ();
1230 }
1231
1232 //
1233 // Set Legacy16 state. 0x08, 0x70 is legacy 8259 vector bases.
1234 //
1235 Status = gLegacy8259->SetMode (gLegacy8259, Efi8259LegacyMode, NULL, NULL);
1236 ASSERT_EFI_ERROR (Status);
1237
1238 Stack16 = (UINT16 *)((UINT8 *) mThunkContext.RealModeBuffer + mThunkContext.RealModeBufferSize - sizeof (UINT16));
1239 Stack16 -= sizeof (ThunkRegSet.E.EFLAGS) / sizeof (UINT16);
1240 CopyMem (Stack16, &ThunkRegSet.E.EFLAGS, sizeof (ThunkRegSet.E.EFLAGS));
1241
1242 ThunkRegSet.E.SS = (UINT16) (((UINTN) Stack16 >> 16) << 12);
1243 ThunkRegSet.E.ESP = (UINT16) (UINTN) Stack16;
1244 ThunkRegSet.E.Eip = (UINT16)((UINT32 *)NULL)[BiosInt];
1245 ThunkRegSet.E.CS = (UINT16)(((UINT32 *)NULL)[BiosInt] >> 16);
1246 mThunkContext.RealModeState = &ThunkRegSet;
1247 AsmThunk16 (&mThunkContext);
1248
1249 //
1250 // Restore protected mode interrupt state
1251 //
1252 Status = gLegacy8259->SetMode (gLegacy8259, Efi8259ProtectedMode, NULL, NULL);
1253 ASSERT_EFI_ERROR (Status);
1254
1255 //
1256 // End critical section
1257 //
1258 if ((Eflags | EFI_CPU_EFLAGS_IF) != 0) {
1259 EnableInterrupts ();
1260 }
1261
1262 Regs->E.EDI = ThunkRegSet.E.EDI;
1263 Regs->E.ESI = ThunkRegSet.E.ESI;
1264 Regs->E.EBP = ThunkRegSet.E.EBP;
1265 Regs->E.EBX = ThunkRegSet.E.EBX;
1266 Regs->E.EDX = ThunkRegSet.E.EDX;
1267 Regs->E.ECX = ThunkRegSet.E.ECX;
1268 Regs->E.EAX = ThunkRegSet.E.EAX;
1269 Regs->E.SS = ThunkRegSet.E.SS;
1270 Regs->E.CS = ThunkRegSet.E.CS;
1271 Regs->E.DS = ThunkRegSet.E.DS;
1272 Regs->E.ES = ThunkRegSet.E.ES;
1273
1274 CopyMem (&(Regs->E.EFlags), &(ThunkRegSet.E.EFLAGS), sizeof (UINT32));
1275
1276 Ret = (BOOLEAN) (Regs->E.EFlags.CF == 1);
1277
1278 return Ret;
1279 }