Home | History | Annotate | Download | only in Ia32
      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