1 /** @file 2 IA32 specific functions to support Debug Support protocol. 3 4 Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.<BR> 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 **/ 14 15 #include "PlDebugSupport.h" 16 17 IA32_IDT_GATE_DESCRIPTOR NullDesc = {{0}}; 18 19 /** 20 Get Interrupt Handle from IDT Gate Descriptor. 21 22 @param IdtGateDescriptor IDT Gate Descriptor. 23 24 @return Interrupt Handle stored in IDT Gate Descriptor. 25 26 **/ 27 UINTN 28 GetInterruptHandleFromIdt ( 29 IN IA32_IDT_GATE_DESCRIPTOR *IdtGateDescriptor 30 ) 31 { 32 UINTN InterruptHandle; 33 34 // 35 // InterruptHandle 0-15 : OffsetLow 36 // InterruptHandle 16-31 : OffsetHigh 37 // 38 ((UINT16 *) &InterruptHandle)[0] = (UINT16) IdtGateDescriptor->Bits.OffsetLow; 39 ((UINT16 *) &InterruptHandle)[1] = (UINT16) IdtGateDescriptor->Bits.OffsetHigh; 40 41 return InterruptHandle; 42 } 43 44 /** 45 Allocate pool for a new IDT entry stub. 46 47 Copy the generic stub into the new buffer and fixup the vector number 48 and jump target address. 49 50 @param ExceptionType This is the exception type that the new stub will be created 51 for. 52 @param Stub On successful exit, *Stub contains the newly allocated entry stub. 53 54 **/ 55 VOID 56 CreateEntryStub ( 57 IN EFI_EXCEPTION_TYPE ExceptionType, 58 OUT VOID **Stub 59 ) 60 { 61 UINT8 *StubCopy; 62 63 StubCopy = *Stub; 64 65 // 66 // Fixup the stub code for this vector 67 // 68 69 // The stub code looks like this: 70 // 71 // 00000000 89 25 00000004 R mov AppEsp, esp ; save stack top 72 // 00000006 BC 00008014 R mov esp, offset DbgStkBot ; switch to debugger stack 73 // 0000000B 6A 00 push 0 ; push vector number - will be modified before installed 74 // 0000000D E9 db 0e9h ; jump rel32 75 // 0000000E 00000000 dd 0 ; fixed up to relative address of CommonIdtEntry 76 // 77 78 // 79 // poke in the exception type so the second push pushes the exception type 80 // 81 StubCopy[0x0c] = (UINT8) ExceptionType; 82 83 // 84 // fixup the jump target to point to the common entry 85 // 86 *(UINT32 *) &StubCopy[0x0e] = (UINT32) CommonIdtEntry - (UINT32) &StubCopy[StubSize]; 87 88 return ; 89 } 90 91 /** 92 This is the main worker function that manages the state of the interrupt 93 handlers. It both installs and uninstalls interrupt handlers based on the 94 value of NewCallback. If NewCallback is NULL, then uninstall is indicated. 95 If NewCallback is non-NULL, then install is indicated. 96 97 @param NewCallback If non-NULL, NewCallback specifies the new handler to register. 98 If NULL, specifies that the previously registered handler should 99 be uninstalled. 100 @param ExceptionType Indicates which entry to manage. 101 102 @retval EFI_SUCCESS Installing or Uninstalling operation is ok. 103 @retval EFI_INVALID_PARAMETER Requested uninstalling a handler from a vector that has 104 no handler registered for it 105 @retval EFI_ALREADY_STARTED Requested install to a vector that already has a handler registered. 106 107 **/ 108 EFI_STATUS 109 ManageIdtEntryTable ( 110 CALLBACK_FUNC NewCallback, 111 EFI_EXCEPTION_TYPE ExceptionType 112 ) 113 { 114 EFI_STATUS Status; 115 116 Status = EFI_SUCCESS; 117 118 if (CompareMem (&IdtEntryTable[ExceptionType].NewDesc, &NullDesc, sizeof (IA32_IDT_GATE_DESCRIPTOR)) != 0) { 119 // 120 // we've already installed to this vector 121 // 122 if (NewCallback != NULL) { 123 // 124 // if the input handler is non-null, error 125 // 126 Status = EFI_ALREADY_STARTED; 127 } else { 128 UnhookEntry (ExceptionType); 129 } 130 } else { 131 // 132 // no user handler installed on this vector 133 // 134 if (NewCallback == NULL) { 135 // 136 // if the input handler is null, error 137 // 138 Status = EFI_INVALID_PARAMETER; 139 } else { 140 HookEntry (ExceptionType, NewCallback); 141 } 142 } 143 144 return Status; 145 } 146