]> git.proxmox.com Git - mirror_edk2.git/blame - SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgent/DxeDebugAgentLib.c
Add transit bit check for detecting partial response in iSCSI stack.
[mirror_edk2.git] / SourceLevelDebugPkg / Library / DebugAgent / DxeDebugAgent / DxeDebugAgentLib.c
CommitLineData
18b144ea 1/** @file\r
2 Debug Agent library implementition for Dxe Core and Dxr modules.\r
3\r
b422b62c 4 Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>\r
18b144ea 5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php.\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "DxeDebugAgentLib.h"\r
16\r
17DEBUG_AGENT_MAILBOX mMailbox;\r
b422b62c 18DEBUG_AGENT_MAILBOX *mMailboxPointer = NULL;\r
18b144ea 19IA32_IDT_GATE_DESCRIPTOR mIdtEntryTable[33];\r
b422b62c 20BOOLEAN mDxeCoreFlag = FALSE;\r
21BOOLEAN mMultiProcessorDebugSupport = FALSE;\r
22VOID *mSavedIdtTable = NULL;\r
23UINTN mSaveIdtTableSize = 0;\r
24BOOLEAN mDebugAgentInitialized = FALSE;\r
25BOOLEAN mSkipBreakpoint = FALSE;\r
18b144ea 26\r
27/**\r
b422b62c 28 Check if debug agent support multi-processor.\r
18b144ea 29\r
b422b62c 30 @retval TRUE Multi-processor is supported.\r
31 @retval FALSE Multi-processor is not supported.\r
32\r
33**/\r
34BOOLEAN\r
35MultiProcessorDebugSupport (\r
36 VOID\r
37 )\r
38{\r
39 return mMultiProcessorDebugSupport;\r
40}\r
18b144ea 41\r
b422b62c 42/**\r
43 Internal constructor worker function.\r
44\r
45 It will register one callback function on EFI PCD Protocol.\r
46 It will allocate the NVS memory to store Mailbox and install configuration table\r
47 in system table to store its pointer.\r
18b144ea 48\r
49**/\r
b422b62c 50VOID\r
51InternalConstructorWorker (\r
52 VOID\r
18b144ea 53 )\r
54{\r
55 EFI_STATUS Status;\r
56 EFI_PHYSICAL_ADDRESS Address;\r
b422b62c 57 BOOLEAN DebugTimerInterruptState;\r
93c0bdec 58\r
59 //\r
b422b62c 60 // Install EFI Serial IO protocol on debug port\r
93c0bdec 61 //\r
b422b62c 62 InstallSerialIo ();\r
93c0bdec 63\r
18b144ea 64 Address = 0;\r
65 Status = gBS->AllocatePages (\r
66 AllocateAnyPages,\r
67 EfiACPIMemoryNVS,\r
68 EFI_SIZE_TO_PAGES (sizeof (DEBUG_AGENT_MAILBOX)),\r
69 &Address\r
70 );\r
93c0bdec 71 ASSERT_EFI_ERROR (Status);\r
18b144ea 72\r
b422b62c 73 DebugTimerInterruptState = SaveAndSetDebugTimerInterrupt (FALSE);\r
18b144ea 74 CopyMem (\r
75 (UINT8 *) (UINTN) Address,\r
b422b62c 76 (UINT8 *) (UINTN) GetMailboxPointer (),\r
18b144ea 77 sizeof (DEBUG_AGENT_MAILBOX)\r
78 );\r
b422b62c 79 DebugTimerInterruptState = SaveAndSetDebugTimerInterrupt (DebugTimerInterruptState);\r
18b144ea 80\r
81 mMailboxPointer = (DEBUG_AGENT_MAILBOX *) (UINTN) Address;\r
82\r
93c0bdec 83 Status = gBS->InstallConfigurationTable (&gEfiDebugAgentGuid, (VOID *) mMailboxPointer);\r
84 ASSERT_EFI_ERROR (Status);\r
b422b62c 85}\r
86\r
87/**\r
88 Debug Agent constructor function.\r
89\r
90 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
91 @param[in] SystemTable A pointer to the EFI System Table.\r
92\r
93 @retval RETURN_SUCCESS When this function completed.\r
94\r
95**/\r
96RETURN_STATUS\r
97EFIAPI\r
98DxeDebugAgentLibConstructor (\r
99 IN EFI_HANDLE ImageHandle,\r
100 IN EFI_SYSTEM_TABLE *SystemTable\r
101 )\r
102{\r
103 if (mDxeCoreFlag) {\r
104 //\r
105 // Invoke internal constructor function only when DXE core links this library instance\r
106 //\r
107 InternalConstructorWorker ();\r
108 }\r
109\r
110 return RETURN_SUCCESS;\r
111}\r
112\r
113/**\r
114 Get the pointer to Mailbox from the configuration table.\r
115\r
116 @return Pointer to Mailbox.\r
117\r
118**/\r
119DEBUG_AGENT_MAILBOX *\r
120GetMailboxFromConfigurationTable (\r
121 VOID\r
122 )\r
123{\r
124 EFI_STATUS Status;\r
125 DEBUG_AGENT_MAILBOX *Mailbox;\r
93c0bdec 126 \r
b422b62c 127 Status = EfiGetSystemConfigurationTable (&gEfiDebugAgentGuid, (VOID **) &Mailbox);\r
128 if (Status == EFI_SUCCESS && Mailbox != NULL) {\r
129 VerifyMailboxChecksum (Mailbox);\r
130 return Mailbox;\r
131 } else {\r
132 return NULL;\r
133 }\r
18b144ea 134}\r
135\r
136/**\r
137 Get the pointer to Mailbox from the GUIDed HOB.\r
138\r
139 @param[in] HobStart The starting HOB pointer to search from.\r
140\r
141 @return Pointer to Mailbox.\r
142\r
143**/\r
144DEBUG_AGENT_MAILBOX *\r
145GetMailboxFromHob (\r
146 IN VOID *HobStart\r
147 )\r
148{\r
149 EFI_HOB_GUID_TYPE *GuidHob;\r
b422b62c 150 UINT64 *MailboxLocation;\r
151 DEBUG_AGENT_MAILBOX *Mailbox;\r
18b144ea 152\r
153 GuidHob = GetNextGuidHob (&gEfiDebugAgentGuid, HobStart);\r
154 if (GuidHob == NULL) {\r
155 return NULL;\r
156 }\r
b422b62c 157 MailboxLocation = (UINT64 *) (GET_GUID_HOB_DATA(GuidHob));\r
158 Mailbox = (DEBUG_AGENT_MAILBOX *)(UINTN)(*MailboxLocation);\r
159 VerifyMailboxChecksum (Mailbox);\r
18b144ea 160\r
b422b62c 161 return Mailbox;\r
18b144ea 162}\r
163\r
164/**\r
165 Get Debug Agent Mailbox pointer.\r
166\r
167 @return Mailbox pointer.\r
168\r
169**/\r
170DEBUG_AGENT_MAILBOX *\r
171GetMailboxPointer (\r
172 VOID\r
173 )\r
174{\r
b422b62c 175 AcquireMpSpinLock (&mDebugMpContext.MailboxSpinLock);\r
176 VerifyMailboxChecksum (mMailboxPointer);\r
177 ReleaseMpSpinLock (&mDebugMpContext.MailboxSpinLock);\r
18b144ea 178 return mMailboxPointer;\r
179}\r
180\r
181/**\r
182 Get debug port handle.\r
183\r
184 @return Debug port handle.\r
185\r
186**/\r
187DEBUG_PORT_HANDLE\r
188GetDebugPortHandle (\r
189 VOID\r
190 )\r
191{\r
b422b62c 192 return (DEBUG_PORT_HANDLE) (UINTN)(GetMailboxPointer ()->DebugPortHandle);\r
193}\r
194\r
195/**\r
196 Worker function to setup IDT table and initialize the IDT entries.\r
197\r
198 @param[in] Mailbox Pointer to Mailbox.\r
199\r
200**/\r
201VOID\r
202SetupDebugAgentEnviroment (\r
203 IN DEBUG_AGENT_MAILBOX *Mailbox\r
204 )\r
205{\r
206 IA32_DESCRIPTOR Idtr;\r
207 UINT16 IdtEntryCount;\r
208 UINT64 DebugPortHandle;\r
209\r
210 if (mMultiProcessorDebugSupport) {\r
211 InitializeSpinLock (&mDebugMpContext.MpContextSpinLock);\r
212 InitializeSpinLock (&mDebugMpContext.DebugPortSpinLock);\r
213 InitializeSpinLock (&mDebugMpContext.MailboxSpinLock);\r
214 //\r
215 // Clear Break CPU index value\r
216 //\r
217 mDebugMpContext.BreakAtCpuIndex = (UINT32) -1;\r
218 }\r
219\r
220 //\r
221 // Get original IDT address and size.\r
222 //\r
223 AsmReadIdtr ((IA32_DESCRIPTOR *) &Idtr);\r
224 IdtEntryCount = (UINT16) ((Idtr.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR));\r
225 if (IdtEntryCount < 33) {\r
226 Idtr.Limit = (UINT16) (sizeof (IA32_IDT_GATE_DESCRIPTOR) * 33 - 1);\r
227 Idtr.Base = (UINTN) &mIdtEntryTable;\r
228 ZeroMem (&mIdtEntryTable, Idtr.Limit + 1);\r
229 AsmWriteIdtr ((IA32_DESCRIPTOR *) &Idtr);\r
230 }\r
231\r
232 //\r
233 // Initialize the IDT table entries to support source level debug.\r
234 //\r
235 InitializeDebugIdt ();\r
236\r
237 if (Mailbox != NULL) {\r
238 //\r
239 // If Mailbox exists, copy it into one global variable,\r
240 //\r
241 CopyMem (&mMailbox, Mailbox, sizeof (DEBUG_AGENT_MAILBOX));\r
242 } else {\r
243 ZeroMem (&mMailbox, sizeof (DEBUG_AGENT_MAILBOX));\r
244 } \r
245\r
246 mMailboxPointer = &mMailbox;\r
247 //\r
248 // Initialize debug communication port\r
249 //\r
250 DebugPortHandle = (UINT64) (UINTN)DebugPortInitialize ((VOID *)(UINTN)mMailboxPointer->DebugPortHandle, NULL);\r
251 UpdateMailboxContent (mMailboxPointer, DEBUG_MAILBOX_DEBUG_PORT_HANDLE_INDEX, DebugPortHandle);\r
252\r
253 if (Mailbox == NULL) {\r
254 //\r
255 // Trigger one software interrupt to inform HOST\r
256 //\r
257 TriggerSoftInterrupt (SYSTEM_RESET_SIGNATURE);\r
258 SetDebugFlag (DEBUG_AGENT_FLAG_MEMORY_READY, 1);\r
259 //\r
260 // Memory has been ready\r
261 //\r
262 if (IsHostAttached ()) {\r
263 //\r
264 // Trigger one software interrupt to inform HOST\r
265 //\r
266 TriggerSoftInterrupt (MEMORY_READY_SIGNATURE);\r
267 }\r
268 }\r
18b144ea 269}\r
270\r
b422b62c 271\r
18b144ea 272/**\r
273 Initialize debug agent.\r
274\r
275 This function is used to set up debug enviroment for DXE phase.\r
276\r
277 If this function is called by DXE Core, Context must be the pointer\r
278 to HOB list which will be used to get GUIDed HOB. It will enable\r
279 interrupt to support break-in feature.\r
280 If this function is called by DXE module, Context must be NULL. It\r
281 will enable interrupt to support break-in feature.\r
282\r
283 @param[in] InitFlag Init flag is used to decide initialize process.\r
284 @param[in] Context Context needed according to InitFlag.\r
285 @param[in] Function Continue function called by debug agent library; it was\r
286 optional.\r
287\r
288**/\r
289VOID\r
290EFIAPI\r
291InitializeDebugAgent (\r
292 IN UINT32 InitFlag,\r
293 IN VOID *Context, OPTIONAL\r
294 IN DEBUG_AGENT_CONTINUE Function OPTIONAL\r
295 )\r
296{\r
b422b62c 297 UINT64 *MailboxLocation;\r
18b144ea 298 DEBUG_AGENT_MAILBOX *Mailbox;\r
18b144ea 299 BOOLEAN InterruptStatus;\r
b422b62c 300 VOID *HobList;\r
301 IA32_DESCRIPTOR IdtDescriptor;\r
302 IA32_DESCRIPTOR *Ia32Idtr;\r
303 IA32_IDT_ENTRY *Ia32IdtEntry;\r
18b144ea 304\r
b422b62c 305 if (InitFlag == DEBUG_AGENT_INIT_DXE_AP) {\r
306 //\r
307 // Invoked by AP, enable interrupt to let AP could receive IPI from other processors\r
308 //\r
309 EnableInterrupts ();\r
310 return ;\r
18b144ea 311 }\r
312\r
b422b62c 313 // \r
314 // Disable Debug Timer interrupt\r
315 //\r
316 SaveAndSetDebugTimerInterrupt (FALSE);\r
18b144ea 317 //\r
318 // Save and disable original interrupt status\r
319 //\r
320 InterruptStatus = SaveAndDisableInterrupts ();\r
321\r
b422b62c 322 //\r
323 // Try to get mailbox firstly\r
324 //\r
325 HobList = NULL;\r
326 Mailbox = NULL;\r
327 MailboxLocation = NULL;\r
328\r
329 switch (InitFlag) {\r
330\r
331 case DEBUG_AGENT_INIT_DXE_LOAD:\r
18b144ea 332 //\r
b422b62c 333 // Check if Debug Agent has been initialized before\r
18b144ea 334 //\r
b422b62c 335 if (IsDebugAgentInitialzed ()) {\r
336 DEBUG ((EFI_D_INFO, "Debug Agent: The former agent will be overwritten by the new one!\n"));\r
337 }\r
338\r
339 mMultiProcessorDebugSupport = TRUE;\r
93c0bdec 340 //\r
b422b62c 341 // Save original IDT table\r
342 //\r
343 AsmReadIdtr (&IdtDescriptor);\r
344 mSaveIdtTableSize = IdtDescriptor.Limit + 1;\r
345 mSavedIdtTable = AllocateCopyPool (mSaveIdtTableSize, (VOID *) IdtDescriptor.Base);\r
346 //\r
347 // Initialize Debug Timer hardware\r
348 //\r
349 InitializeDebugTimer ();\r
350 //\r
351 // Check if Debug Agent initialized in DXE phase\r
352 //\r
353 Mailbox = GetMailboxFromConfigurationTable ();\r
354 if (Mailbox == NULL) {\r
355 //\r
356 // Try to get mailbox from GUIDed HOB build in PEI \r
357 //\r
358 HobList = GetHobList ();\r
359 Mailbox = GetMailboxFromHob (HobList);\r
360 }\r
361 //\r
362 // Set up IDT table and prepare for IDT entries\r
363 //\r
364 SetupDebugAgentEnviroment (Mailbox);\r
365 //\r
366 // For DEBUG_AGENT_INIT_S3, needn't to install configuration table and EFI Serial IO protocol\r
367 // For DEBUG_AGENT_INIT_DXE_CORE, InternalConstructorWorker() will invoked in Constructor()\r
368 //\r
369 InternalConstructorWorker ();\r
370 //\r
371 // Enable interrupt to receive Debug Timer interrupt\r
93c0bdec 372 //\r
18b144ea 373 EnableInterrupts ();\r
374\r
b422b62c 375 mDebugAgentInitialized = TRUE;\r
376 FindAndReportModuleImageInfo (SIZE_4KB);\r
377\r
378 *(EFI_STATUS *)Context = EFI_SUCCESS;\r
379\r
380 if (gST->ConOut != NULL) {\r
381 Print (L"Debug Agent: Initialized successfully!\r\n");\r
382 Print (L"If the Debug Port is serial port, please make sure this serial port isn't connected by ISA Serial driver\r\n");\r
383 Print (L"You could do the following steps to disconnect the serial port:\r\n");\r
384 Print (L"1: Shell> drivers\r\n");\r
385 Print (L" ...\r\n");\r
386 Print (L" V VERSION E G G #D #C DRIVER NAME IMAGE NAME\r\n");\r
387 Print (L" == ======== = = = == == =================================== ===================\r\n");\r
388 Print (L" 8F 0000000A B - - 1 14 PCI Bus Driver PciBusDxe\r\n");\r
389 Print (L" 91 00000010 ? - - - - ATA Bus Driver AtaBusDxe\r\n");\r
390 Print (L" ...\r\n");\r
391 Print (L" A7 0000000A B - - 1 1 ISA Serial Driver IsaSerialDxe\r\n");\r
392 Print (L" ...\r\n");\r
393 Print (L"2: Shell> dh -d A7\r\n");\r
394 Print (L" A7: Image(IsaSerialDxe) ImageDevPath (..9FB3-11D4-9A3A-0090273FC14D))DriverBinding ComponentName ComponentName2\r\n");\r
395 Print (L" Driver Name : ISA Serial Driver\r\n");\r
396 Print (L" Image Name : FvFile(93B80003-9FB3-11D4-9A3A-0090273FC14D)\r\n");\r
397 Print (L" Driver Version : 0000000A\r\n");\r
398 Print (L" Driver Type : BUS\r\n");\r
399 Print (L" Configuration : NO\r\n");\r
400 Print (L" Diagnostics : NO\r\n");\r
401 Print (L" Managing :\r\n");\r
402 Print (L" Ctrl[EA] : PciRoot(0x0)/Pci(0x1F,0x0)/Serial(0x0)\r\n");\r
403 Print (L" Child[EB] : PciRoot(0x0)/Pci(0x1F,0x0)/Serial(0x0)/Uart(115200,8,N,1)\r\n");\r
404 Print (L"3: Shell> disconnect EA\r\n");\r
405 Print (L"4: Shell> load -nc DebugAgentDxe.efi\r\n\r\n");\r
406 }\r
407 break;\r
408\r
409 case DEBUG_AGENT_INIT_DXE_UNLOAD:\r
410 if (mDebugAgentInitialized) {\r
411 if (IsHostAttached ()) {\r
412 Print (L"Debug Agent: Host is still connected, please de-attach TARGET firstly!\r\n");\r
413 *(EFI_STATUS *)Context = EFI_ACCESS_DENIED;\r
414 // \r
415 // Enable Debug Timer interrupt again\r
416 //\r
417 SaveAndSetDebugTimerInterrupt (TRUE);\r
418 } else {\r
419 //\r
420 // Restore original IDT table\r
421 //\r
422 AsmReadIdtr (&IdtDescriptor);\r
423 IdtDescriptor.Limit = (UINT16) (mSaveIdtTableSize - 1);\r
424 CopyMem ((VOID *) IdtDescriptor.Base, mSavedIdtTable, mSaveIdtTableSize);\r
425 AsmWriteIdtr (&IdtDescriptor);\r
426 FreePool (mSavedIdtTable);\r
427 mDebugAgentInitialized = FALSE;\r
428 *(EFI_STATUS *)Context = EFI_SUCCESS;\r
429 }\r
430 } else {\r
431 Print (L"Debug Agent: It hasn't been initialized, cannot unload it!\r\n");\r
432 *(EFI_STATUS *)Context = EFI_NOT_STARTED;\r
433 }\r
18b144ea 434\r
18b144ea 435 //\r
b422b62c 436 // Restore interrupt state.\r
18b144ea 437 //\r
b422b62c 438 SetInterruptState (InterruptStatus);\r
439 break;\r
18b144ea 440\r
b422b62c 441 case DEBUG_AGENT_INIT_DXE_CORE:\r
442 mDxeCoreFlag = TRUE;\r
443 mMultiProcessorDebugSupport = TRUE;\r
18b144ea 444 //\r
b422b62c 445 // Initialize Debug Timer hardware\r
18b144ea 446 //\r
b422b62c 447 InitializeDebugTimer ();\r
18b144ea 448 //\r
b422b62c 449 // Try to get mailbox from GUIDed HOB build in PEI \r
18b144ea 450 //\r
b422b62c 451 HobList = Context;\r
452 Mailbox = GetMailboxFromHob (HobList);\r
453 //\r
454 // Set up IDT table and prepare for IDT entries\r
455 //\r
456 SetupDebugAgentEnviroment (Mailbox);\r
457 //\r
458 // Enable interrupt to receive Debug Timer interrupt\r
459 //\r
460 EnableInterrupts ();\r
18b144ea 461\r
b422b62c 462 break;\r
18b144ea 463\r
b422b62c 464 case DEBUG_AGENT_INIT_S3:\r
18b144ea 465\r
b422b62c 466 if (Context != NULL) {\r
467 Ia32Idtr = (IA32_DESCRIPTOR *) Context;\r
468 Ia32IdtEntry = (IA32_IDT_ENTRY *)(Ia32Idtr->Base);\r
469 MailboxLocation = (UINT64 *) (UINTN) (Ia32IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetLow + \r
470 (Ia32IdtEntry[DEBUG_MAILBOX_VECTOR].Bits.OffsetHigh << 16));\r
471 Mailbox = (DEBUG_AGENT_MAILBOX *)(UINTN)(*MailboxLocation);\r
472 VerifyMailboxChecksum (Mailbox);\r
473 }\r
18b144ea 474 //\r
b422b62c 475 // Set up IDT table and prepare for IDT entries\r
18b144ea 476 //\r
b422b62c 477 SetupDebugAgentEnviroment (Mailbox);\r
18b144ea 478 //\r
b422b62c 479 // Disable interrupt\r
18b144ea 480 //\r
b422b62c 481 DisableInterrupts ();\r
482 FindAndReportModuleImageInfo (SIZE_4KB);\r
483 if (GetDebugFlag (DEBUG_AGENT_FLAG_BREAK_BOOT_SCRIPT) == 1) {\r
484 //\r
485 // If Boot Script entry break is set, code will be break at here.\r
486 //\r
487 CpuBreakpoint ();\r
488 }\r
489 break;\r
490\r
491 default:\r
18b144ea 492 //\r
b422b62c 493 // Only DEBUG_AGENT_INIT_PREMEM_SEC and DEBUG_AGENT_INIT_POSTMEM_SEC are allowed for this \r
494 // Debug Agent library instance.\r
18b144ea 495 //\r
b422b62c 496 DEBUG ((EFI_D_ERROR, "Debug Agent: The InitFlag value is not allowed!\n"));\r
497 CpuDeadLoop ();\r
498 break;\r
18b144ea 499 }\r
18b144ea 500}\r