]> git.proxmox.com Git - mirror_edk2.git/blob - SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgent/DxeDebugAgentLib.c
Import SourceLevelDebugPkg.
[mirror_edk2.git] / SourceLevelDebugPkg / Library / DebugAgent / DxeDebugAgent / DxeDebugAgentLib.c
1 /** @file
2 Debug Agent library implementition for Dxe Core and Dxr modules.
3
4 Copyright (c) 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 "DxeDebugAgentLib.h"
16
17 DEBUG_AGENT_MAILBOX mMailbox;
18
19 DEBUG_AGENT_MAILBOX *mMailboxPointer;
20
21 IA32_IDT_GATE_DESCRIPTOR mIdtEntryTable[33];
22
23 BOOLEAN mConfigurationTableNeeded = FALSE;
24
25 CONST BOOLEAN MultiProcessorDebugSupport = TRUE;
26
27 /**
28 Constructor allocates the NVS memory to store Mailbox and install configuration table
29 in system table to store its pointer.
30
31 @param[in] ImageHandle The firmware allocated handle for the EFI image.
32 @param[in] SystemTable A pointer to the EFI System Table.
33
34 @retval RETURN_SUCCESS Allocate the global memory space to store guid and function tables.
35 @retval RETURN_OUT_OF_RESOURCES No enough memory to allocated.
36
37 **/
38 RETURN_STATUS
39 EFIAPI
40 DxeDebugAgentLibConstructor (
41 IN EFI_HANDLE ImageHandle,
42 IN EFI_SYSTEM_TABLE *SystemTable
43 )
44 {
45 EFI_STATUS Status;
46 EFI_PHYSICAL_ADDRESS Address;
47
48 if (!mConfigurationTableNeeded) {
49 return RETURN_SUCCESS;
50 }
51
52 Address = 0;
53 Status = gBS->AllocatePages (
54 AllocateAnyPages,
55 EfiACPIMemoryNVS,
56 EFI_SIZE_TO_PAGES (sizeof (DEBUG_AGENT_MAILBOX)),
57 &Address
58 );
59 if (EFI_ERROR (Status)) {
60 return Status;
61 }
62
63 CopyMem (
64 (UINT8 *) (UINTN) Address,
65 (UINT8 *) (UINTN) mMailboxPointer,
66 sizeof (DEBUG_AGENT_MAILBOX)
67 );
68
69 mMailboxPointer = (DEBUG_AGENT_MAILBOX *) (UINTN) Address;
70
71 return gBS->InstallConfigurationTable (&gEfiDebugAgentGuid, (VOID *) mMailboxPointer);
72 }
73
74 /**
75 Get the pointer to Mailbox from the GUIDed HOB.
76
77 @param[in] HobStart The starting HOB pointer to search from.
78
79 @return Pointer to Mailbox.
80
81 **/
82 DEBUG_AGENT_MAILBOX *
83 GetMailboxFromHob (
84 IN VOID *HobStart
85 )
86 {
87 EFI_HOB_GUID_TYPE *GuidHob;
88
89 GuidHob = GetNextGuidHob (&gEfiDebugAgentGuid, HobStart);
90 if (GuidHob == NULL) {
91 return NULL;
92 }
93
94 return (DEBUG_AGENT_MAILBOX *) (GET_GUID_HOB_DATA(GuidHob));
95 }
96
97 /**
98 Get Debug Agent Mailbox pointer.
99
100 @return Mailbox pointer.
101
102 **/
103 DEBUG_AGENT_MAILBOX *
104 GetMailboxPointer (
105 VOID
106 )
107 {
108 return mMailboxPointer;
109 }
110
111 /**
112 Get debug port handle.
113
114 @return Debug port handle.
115
116 **/
117 DEBUG_PORT_HANDLE
118 GetDebugPortHandle (
119 VOID
120 )
121 {
122 return (DEBUG_PORT_HANDLE) (UINTN)(mMailboxPointer->DebugPortHandle);
123 }
124
125
126 /**
127 Initialize debug agent.
128
129 This function is used to set up debug enviroment for DXE phase.
130
131 If this function is called by DXE Core, Context must be the pointer
132 to HOB list which will be used to get GUIDed HOB. It will enable
133 interrupt to support break-in feature.
134 If this function is called by DXE module, Context must be NULL. It
135 will enable interrupt to support break-in feature.
136
137 @param[in] InitFlag Init flag is used to decide initialize process.
138 @param[in] Context Context needed according to InitFlag.
139 @param[in] Function Continue function called by debug agent library; it was
140 optional.
141
142 **/
143 VOID
144 EFIAPI
145 InitializeDebugAgent (
146 IN UINT32 InitFlag,
147 IN VOID *Context, OPTIONAL
148 IN DEBUG_AGENT_CONTINUE Function OPTIONAL
149 )
150 {
151 DEBUG_AGENT_MAILBOX *Mailbox;
152 IA32_DESCRIPTOR Idtr;
153 UINT16 IdtEntryCount;
154 BOOLEAN InterruptStatus;
155
156 if (InitFlag != DEBUG_AGENT_INIT_DXE_CORE &&
157 InitFlag != DEBUG_AGENT_INIT_S3 &&
158 InitFlag != DEBUG_AGENT_INIT_DXE_AP) {
159 return;
160 }
161
162 //
163 // Save and disable original interrupt status
164 //
165 InterruptStatus = SaveAndDisableInterrupts ();
166
167 if (InitFlag == DEBUG_AGENT_INIT_DXE_CORE) {
168 //
169 // Try to get Mailbox from GUIDed HOB.
170 //
171 mConfigurationTableNeeded = TRUE;
172 Mailbox = GetMailboxFromHob (Context);
173
174 } else if (InitFlag == DEBUG_AGENT_INIT_DXE_AP) {
175
176 EnableInterrupts ();
177
178 return;
179
180 } else {
181 //
182 // If it is in S3 path, needn't to install configuration table.
183 //
184 Mailbox = NULL;
185 }
186
187 if (Mailbox != NULL) {
188 //
189 // If Mailbox exists, copy it into one global variable.
190 //
191 CopyMem (&mMailbox, Mailbox, sizeof (DEBUG_AGENT_MAILBOX));
192 mMailbox.DebugPortHandle = 0;
193 } else {
194 //
195 // If Mailbox not exists, used the local Mailbox.
196 //
197 ZeroMem (&mMailbox, sizeof (DEBUG_AGENT_MAILBOX));
198 }
199
200 mMailboxPointer = &mMailbox;
201
202 //
203 // Get original IDT address and size.
204 //
205 AsmReadIdtr ((IA32_DESCRIPTOR *) &Idtr);
206 IdtEntryCount = (UINT16) ((Idtr.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR));
207 if (IdtEntryCount < 33) {
208 Idtr.Limit = (UINT16) (sizeof (IA32_IDT_GATE_DESCRIPTOR) * 33 - 1);
209 Idtr.Base = (UINTN) &mIdtEntryTable;
210 AsmWriteIdtr ((IA32_DESCRIPTOR *) &Idtr);
211 }
212
213 //
214 // Initialize the IDT table entries to support source level debug.
215 //
216 InitializeDebugIdt ();
217
218 //
219 // Initialize debug communication port
220 //
221 mMailboxPointer->DebugPortHandle = (UINT64) (UINTN)DebugPortInitialize (NULL, NULL);
222
223 InitializeSpinLock (&mDebugMpContext.MpContextSpinLock);
224 InitializeSpinLock (&mDebugMpContext.DebugPortSpinLock);
225
226 if (InitFlag == DEBUG_AGENT_INIT_DXE_CORE) {
227 //
228 // Initialize Debug Timer hardware and enable interrupt.
229 //
230 InitializeDebugTimer ();
231 EnableInterrupts ();
232
233 return;
234 } else {
235 //
236 // Disable Debug Timer interrupt in S3 path.
237 //
238 SaveAndSetDebugTimerInterrupt (FALSE);
239
240 //
241 // Restore interrupt state.
242 //
243 SetInterruptState (InterruptStatus);
244 }
245
246 }
247