summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Universal/DebugSupportDxe/X64/PlDebugSupportX64.c
blob: 943d2c6911b023865fb813216713274c7d0122ab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/** @file
  X64 specific debug support functions

Copyright (c) 2006 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution.  The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php

THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

**/

//
// private header files
//
#include "DebugSupport.h"

/**
  Get Procedure Entry Point from IDT Gate Descriptor.

  @param  IdtGateDecriptor  IDT Gate Descriptor.

  @return Procedure Entry Point located in IDT Gate Descriptor.

**/
UINTN GetProcedureEntryPoint (
  IN IA32_IDT_GATE_DESCRIPTOR  *IdtGateDecriptor
  )
{
  UINTN      ProcedureEntryPoint;
 
  ((UINT16 *) &ProcedureEntryPoint)[0] = (UINT16) IdtGateDecriptor->Bits.OffsetLow;
  ((UINT16 *) &ProcedureEntryPoint)[1] = (UINT16) IdtGateDecriptor->Bits.OffsetHigh;
  ((UINT32 *) &ProcedureEntryPoint)[1] = (UINT32) IdtGateDecriptor->Bits.OffsetUpper;

  return ProcedureEntryPoint;
}

/**
  Allocate pool for a new IDT entry stub.

  Copy the generic stub into the new buffer and fixup the vector number
  and jump target address.

  @param  ExceptionType   This is the exception type that the new stub will be created
                          for.
  @param  Stub            On successful exit, *Stub contains the newly allocated entry stub.

  @retval EFI_SUCCESS     Always.

**/
EFI_STATUS
CreateEntryStub (
  IN EFI_EXCEPTION_TYPE     ExceptionType,
  OUT VOID                  **Stub
  )
{
  UINT8       *StubCopy;

  StubCopy = *Stub;

  //
  // Fixup the stub code for this vector
  //

  // The stub code looks like this:
  //
  //    00000000  6A 00               push    0                       ; push vector number - will be modified before installed
  //    00000002  E9                  db      0e9h                    ; jump rel32
  //    00000003  00000000            dd      0                       ; fixed up to relative address of CommonIdtEntry
  //

  //
  // poke in the exception type so the second push pushes the exception type
  //
  StubCopy[0x1] = (UINT8) ExceptionType;

  //
  // fixup the jump target to point to the common entry
  //
  *(UINT32 *) &StubCopy[0x3] = (UINT32)((UINTN) CommonIdtEntry - (UINTN) &StubCopy[StubSize]);

  return EFI_SUCCESS;
}

/**
  This is the main worker function that manages the state of the interrupt
  handlers.  It both installs and uninstalls interrupt handlers based on the
  value of NewCallback.  If NewCallback is NULL, then uninstall is indicated.
  If NewCallback is non-NULL, then install is indicated.

  @param  NewCallback   If non-NULL, NewCallback specifies the new handler to register.
                        If NULL, specifies that the previously registered handler should
                        be uninstalled.
  @param  ExceptionType Indicates which entry to manage.

  @retval EFI_SUCCESS            Process is ok.
  @retval EFI_INVALID_PARAMETER  Requested uninstalling a handler from a vector that has
                                 no handler registered for it
  @retval EFI_ALREADY_STARTED    Requested install to a vector that already has a handler registered.
  @retval others                 Possible return values are passed through from UnHookEntry and HookEntry.

**/
EFI_STATUS
ManageIdtEntryTable (
  VOID (*NewCallback)(),
  EFI_EXCEPTION_TYPE ExceptionType
  )
{
  EFI_STATUS  Status;

  Status = EFI_SUCCESS;

  if (CompareMem (&IdtEntryTable[ExceptionType].NewDesc, &NullDesc, sizeof (IA32_IDT_GATE_DESCRIPTOR)) != 0) {
    //
    // we've already installed to this vector
    //
    if (NewCallback != NULL) {
      //
      // if the input handler is non-null, error
      //
      Status = EFI_ALREADY_STARTED;
    } else {
      Status = UnhookEntry (ExceptionType);
    }
  } else {
    //
    // no user handler installed on this vector
    //
    if (NewCallback == NULL) {
      //
      // if the input handler is null, error
      //
      Status = EFI_INVALID_PARAMETER;
    } else {
      Status = HookEntry (ExceptionType, NewCallback);
    }
  }
 
  return Status;
}