• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2 
3 Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution.  The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8 
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11 
12 **/
13 
14 #include <Uefi.h>
15 #include "Edb.h"
16 
17 EFI_DEBUGGER_PRIVATE_DATA mDebuggerPrivate = {
18   EFI_DEBUGGER_SIGNATURE,                    // Signature
19   IsaEbc,                                    // Isa
20   (EBC_DEBUGGER_MAJOR_VERSION << 16) |
21     EBC_DEBUGGER_MINOR_VERSION,              // EfiDebuggerRevision
22   (VM_MAJOR_VERSION << 16) |
23     VM_MINOR_VERSION,                        // EbcVmRevision
24   {
25     EFI_DEBUGGER_CONFIGURATION_VERSION,
26     &mDebuggerPrivate,
27   },                                         // DebuggerConfiguration
28   NULL,                                      // DebugImageInfoTableHeader
29   NULL,                                      // Vol
30   NULL,                                      // PciRootBridgeIo
31   mDebuggerCommandSet,                       // DebuggerCommandSet
32   {0},                                       // DebuggerSymbolContext
33   0,                                         // DebuggerBreakpointCount
34   {{0}},                                     // DebuggerBreakpointContext
35   0,                                         // CallStackEntryCount
36   {{0}},                                     // CallStackEntry
37   0,                                         // TraceEntryCount
38   {{0}},                                     // TraceEntry
39   {0},                                       // StepContext
40   {0},                                       // GoTilContext
41   0,                                         // InstructionScope
42   EFI_DEBUG_DEFAULT_INSTRUCTION_NUMBER,      // InstructionNumber
43   EFI_DEBUG_FLAG_EBC_BOE | EFI_DEBUG_FLAG_EBC_BOT, // FeatureFlags
44   0,                                               // StatusFlags
45   FALSE,                                           // EnablePageBreak
46   NULL                                             // BreakEvent
47 };
48 
49 CHAR16 *mExceptionStr[] = {
50   L"EXCEPT_EBC_UNDEFINED",
51   L"EXCEPT_EBC_DIVIDE_ERROR",
52   L"EXCEPT_EBC_DEBUG",
53   L"EXCEPT_EBC_BREAKPOINT",
54   L"EXCEPT_EBC_OVERFLOW",
55   L"EXCEPT_EBC_INVALID_OPCODE",
56   L"EXCEPT_EBC_STACK_FAULT",
57   L"EXCEPT_EBC_ALIGNMENT_CHECK",
58   L"EXCEPT_EBC_INSTRUCTION_ENCODING",
59   L"EXCEPT_EBC_BAD_BREAK",
60   L"EXCEPT_EBC_SINGLE_STEP",
61 };
62 
63 /**
64 
65   Clear all the breakpoint.
66 
67   @param DebuggerPrivate    EBC Debugger private data structure
68   @param NeedRemove         Whether need to remove all the breakpoint
69 
70 **/
71 VOID
EdbClearAllBreakpoint(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN BOOLEAN NeedRemove)72 EdbClearAllBreakpoint (
73   IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
74   IN     BOOLEAN                   NeedRemove
75   )
76 {
77   UINTN    Index;
78 
79   //
80   // Patch all the breakpoint
81   //
82   for (Index = 0; (Index < DebuggerPrivate->DebuggerBreakpointCount) && (Index < EFI_DEBUGGER_BREAKPOINT_MAX); Index++) {
83     if (DebuggerPrivate->DebuggerBreakpointContext[Index].State) {
84       CopyMem (
85         (VOID *)(UINTN)DebuggerPrivate->DebuggerBreakpointContext[Index].BreakpointAddress,
86         &DebuggerPrivate->DebuggerBreakpointContext[Index].OldInstruction,
87         sizeof(UINT16)
88         );
89     }
90   }
91 
92   //
93   // Zero Breakpoint context, if need to remove all breakpoint
94   //
95   if (NeedRemove) {
96     DebuggerPrivate->DebuggerBreakpointCount = 0;
97     ZeroMem (DebuggerPrivate->DebuggerBreakpointContext, sizeof(DebuggerPrivate->DebuggerBreakpointContext));
98   }
99 
100   //
101   // Done
102   //
103   return ;
104 }
105 
106 /**
107 
108   Set all the breakpoint.
109 
110   @param DebuggerPrivate    EBC Debugger private data structure
111 
112 **/
113 VOID
EdbSetAllBreakpoint(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate)114 EdbSetAllBreakpoint (
115   IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate
116   )
117 {
118   UINTN    Index;
119   UINT16   Data16;
120 
121   //
122   // Set all the breakpoint (BREAK(3) : 0x0300)
123   //
124   Data16 = 0x0300;
125   for (Index = 0; (Index < DebuggerPrivate->DebuggerBreakpointCount) && (Index < EFI_DEBUGGER_BREAKPOINT_MAX); Index++) {
126     if (DebuggerPrivate->DebuggerBreakpointContext[Index].State) {
127       CopyMem (
128         (VOID *)(UINTN)DebuggerPrivate->DebuggerBreakpointContext[Index].BreakpointAddress,
129         &Data16,
130         sizeof(UINT16)
131         );
132     }
133   }
134 
135   //
136   // Check if current break is caused by breakpoint set.
137   // If so, we need to patch memory back to let user see the real memory.
138   //
139   if (DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX].BreakpointAddress != 0) {
140     CopyMem (
141       (VOID *)(UINTN)DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX].BreakpointAddress,
142       &DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX].OldInstruction,
143       sizeof(UINT16)
144       );
145     DebuggerPrivate->StatusFlags &= ~EFI_DEBUG_FLAG_EBC_B_BP;
146   }
147 
148   //
149   // Done
150   //
151   return ;
152 }
153 
154 /**
155 
156   Check all the breakpoint, if match, then set status flag, and record current breakpoint.
157   Then clear all breakpoint to let user see a clean memory
158 
159   @param   DebuggerPrivate    EBC Debugger private data structure
160   @param   SystemContext      EBC system context.
161 
162 **/
163 VOID
EdbCheckBreakpoint(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN EFI_SYSTEM_CONTEXT SystemContext)164 EdbCheckBreakpoint (
165   IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
166   IN     EFI_SYSTEM_CONTEXT        SystemContext
167   )
168 {
169   UINT64   Address;
170   UINTN    Index;
171   BOOLEAN  IsHitBreakpoint;
172 
173   //
174   // Roll back IP for breakpoint instruction (BREAK(3) : 0x0300)
175   //
176   Address = SystemContext.SystemContextEbc->Ip - sizeof(UINT16);
177 
178   //
179   // Check if the breakpoint is hit
180   //
181   IsHitBreakpoint = FALSE;
182   for (Index = 0; (Index < DebuggerPrivate->DebuggerBreakpointCount) && (Index < EFI_DEBUGGER_BREAKPOINT_MAX); Index++) {
183     if ((DebuggerPrivate->DebuggerBreakpointContext[Index].BreakpointAddress == Address) &&
184         (DebuggerPrivate->DebuggerBreakpointContext[Index].State)) {
185       IsHitBreakpoint = TRUE;
186       break;
187     }
188   }
189 
190   if (IsHitBreakpoint) {
191     //
192     // If hit, record current breakpoint
193     //
194     DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX] = DebuggerPrivate->DebuggerBreakpointContext[Index];
195     DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX].State = TRUE;
196     //
197     // Update: IP and Instruction (NOTE: Since we not allow set breakpoint to BREAK 3, this update is safe)
198     //
199     SystemContext.SystemContextEbc->Ip = Address;
200     //
201     // Set Flags
202     //
203     DebuggerPrivate->StatusFlags |= EFI_DEBUG_FLAG_EBC_BP;
204   } else {
205     //
206     // If not hit, check whether current IP is in breakpoint list,
207     // because STEP will be triggered before execute the instruction.
208     // We should not patch it in de-init.
209     //
210     Address = SystemContext.SystemContextEbc->Ip;
211 
212     //
213     // Check if the breakpoint is hit
214     //
215     IsHitBreakpoint = FALSE;
216     for (Index = 0; (Index < DebuggerPrivate->DebuggerBreakpointCount) && (Index < EFI_DEBUGGER_BREAKPOINT_MAX); Index++) {
217       if ((DebuggerPrivate->DebuggerBreakpointContext[Index].BreakpointAddress == Address) &&
218           (DebuggerPrivate->DebuggerBreakpointContext[Index].State)) {
219         IsHitBreakpoint = TRUE;
220         break;
221       }
222     }
223 
224     if (IsHitBreakpoint) {
225       //
226       // If hit, record current breakpoint
227       //
228       DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX] = DebuggerPrivate->DebuggerBreakpointContext[Index];
229       DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX].State = TRUE;
230       //
231       // Do not set Breakpoint flag. We record the address here just let it not patch breakpoint address when de-init.
232       //
233     } else {
234       //
235       // Zero current breakpoint
236       //
237       ZeroMem (
238         &DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX],
239         sizeof(DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX])
240         );
241     }
242   }
243 
244   //
245   // Done
246   //
247   return ;
248 }
249 
250 /**
251   clear all the symbol.
252 
253   @param DebuggerPrivate    EBC Debugger private data structure
254 
255 **/
256 VOID
EdbClearSymbol(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate)257 EdbClearSymbol (
258   IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate
259   )
260 {
261   EFI_DEBUGGER_SYMBOL_CONTEXT *DebuggerSymbolContext;
262   EFI_DEBUGGER_SYMBOL_OBJECT  *Object;
263   UINTN                       ObjectIndex;
264   UINTN                       Index;
265 
266   //
267   // Go throuth each object
268   //
269   DebuggerSymbolContext = &DebuggerPrivate->DebuggerSymbolContext;
270   for (ObjectIndex = 0; ObjectIndex < DebuggerSymbolContext->ObjectCount; ObjectIndex++) {
271     Object = &DebuggerSymbolContext->Object[ObjectIndex];
272     //
273     // Go throuth each entry
274     //
275     for (Index = 0; Index < Object->EntryCount; Index++) {
276       ZeroMem (&Object->Entry[Index], sizeof(Object->Entry[Index]));
277     }
278     ZeroMem (Object->Name, sizeof(Object->Name));
279     Object->EntryCount = 0;
280     Object->BaseAddress = 0;
281     Object->StartEntrypointRVA = 0;
282     Object->MainEntrypointRVA = 0;
283     //
284     // Free source buffer
285     //
286     for (Index = 0; Object->SourceBuffer[Index] != NULL; Index++) {
287       gBS->FreePool (Object->SourceBuffer[Index]);
288       Object->SourceBuffer[Index] = NULL;
289     }
290   }
291   DebuggerSymbolContext->ObjectCount = 0;
292 
293   return ;
294 }
295 
296 /**
297 
298   Initialize Debugger private data structure
299 
300   @param DebuggerPrivate   EBC Debugger private data structure
301   @param ExceptionType     Exception type.
302   @param SystemContext     EBC system context.
303   @param Initialized       Whether the DebuggerPrivate data is initialized.
304 
305 **/
306 EFI_STATUS
InitDebuggerPrivateData(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN EFI_EXCEPTION_TYPE ExceptionType,IN EFI_SYSTEM_CONTEXT SystemContext,IN BOOLEAN Initialized)307 InitDebuggerPrivateData (
308   IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
309   IN     EFI_EXCEPTION_TYPE        ExceptionType,
310   IN     EFI_SYSTEM_CONTEXT        SystemContext,
311   IN     BOOLEAN                   Initialized
312   )
313 {
314   //
315   // clear STEP flag in any condition.
316   //
317   if (SystemContext.SystemContextEbc->Flags & ((UINT64) VMFLAGS_STEP)) {
318     SystemContext.SystemContextEbc->Flags &= ~((UINT64) VMFLAGS_STEP);
319   }
320 
321   if (!Initialized) {
322     //
323     // Initialize everything
324     //
325     DebuggerPrivate->InstructionNumber = EFI_DEBUG_DEFAULT_INSTRUCTION_NUMBER;
326 
327     DebuggerPrivate->DebuggerBreakpointCount = 0;
328     ZeroMem (DebuggerPrivate->DebuggerBreakpointContext, sizeof(DebuggerPrivate->DebuggerBreakpointContext));
329 
330 //    DebuggerPrivate->StatusFlags = 0;
331 
332     DebuggerPrivate->DebuggerSymbolContext.DisplaySymbol = TRUE;
333     DebuggerPrivate->DebuggerSymbolContext.DisplayCodeOnly = FALSE;
334     DebuggerPrivate->DebuggerSymbolContext.ObjectCount = 0;
335   } else {
336     //
337     // Already initialized, just check Breakpoint here.
338     //
339     if (ExceptionType == EXCEPT_EBC_BREAKPOINT) {
340       EdbCheckBreakpoint (DebuggerPrivate, SystemContext);
341     }
342 
343     //
344     // Clear all breakpoint
345     //
346     EdbClearAllBreakpoint (DebuggerPrivate, FALSE);
347   }
348 
349   //
350   // Set Scope to currentl IP. (Note: Check Breakpoint may change Ip)
351   //
352   DebuggerPrivate->InstructionScope = SystemContext.SystemContextEbc->Ip;
353 
354   //
355   // Done
356   //
357   return EFI_SUCCESS;
358 }
359 
360 /**
361 
362   De-initialize Debugger private data structure.
363 
364   @param DebuggerPrivate   EBC Debugger private data structure
365   @param ExceptionType     Exception type.
366   @param SystemContext     EBC system context.
367   @param Initialized       Whether the DebuggerPrivate data is initialized.
368 
369 **/
370 EFI_STATUS
DeinitDebuggerPrivateData(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN EFI_EXCEPTION_TYPE ExceptionType,IN EFI_SYSTEM_CONTEXT SystemContext,IN BOOLEAN Initialized)371 DeinitDebuggerPrivateData (
372   IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
373   IN     EFI_EXCEPTION_TYPE        ExceptionType,
374   IN     EFI_SYSTEM_CONTEXT        SystemContext,
375   IN     BOOLEAN                   Initialized
376   )
377 {
378   if (!Initialized) {
379     //
380     // If it does not want initialized state, de-init everything
381     //
382     DebuggerPrivate->FeatureFlags = EFI_DEBUG_FLAG_EBC_BOE | EFI_DEBUG_FLAG_EBC_BOT;
383     DebuggerPrivate->CallStackEntryCount = 0;
384     DebuggerPrivate->TraceEntryCount = 0;
385     ZeroMem (DebuggerPrivate->CallStackEntry, sizeof(DebuggerPrivate->CallStackEntry));
386     ZeroMem (DebuggerPrivate->TraceEntry, sizeof(DebuggerPrivate->TraceEntry));
387 
388     //
389     // Clear all breakpoint
390     //
391     EdbClearAllBreakpoint (DebuggerPrivate, TRUE);
392 
393     //
394     // Clear symbol
395     //
396     EdbClearSymbol (DebuggerPrivate);
397   } else {
398     //
399     // If it wants to keep initialized state, just set breakpoint.
400     //
401     EdbSetAllBreakpoint (DebuggerPrivate);
402   }
403 
404   //
405   // Clear Step context
406   //
407   ZeroMem (&mDebuggerPrivate.StepContext, sizeof(mDebuggerPrivate.StepContext));
408   DebuggerPrivate->StatusFlags = 0;
409 
410   //
411   // Done
412   //
413   return EFI_SUCCESS;
414 }
415 
416 /**
417 
418   Print the reason of current break to EbcDebugger.
419 
420   @param DebuggerPrivate   EBC Debugger private data structure
421   @param ExceptionType     Exception type.
422   @param SystemContext     EBC system context.
423   @param Initialized       Whether the DebuggerPrivate data is initialized.
424 
425 **/
426 VOID
PrintExceptionReason(IN EFI_DEBUGGER_PRIVATE_DATA * DebuggerPrivate,IN EFI_EXCEPTION_TYPE ExceptionType,IN EFI_SYSTEM_CONTEXT SystemContext,IN BOOLEAN Initialized)427 PrintExceptionReason (
428   IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
429   IN     EFI_EXCEPTION_TYPE        ExceptionType,
430   IN     EFI_SYSTEM_CONTEXT        SystemContext,
431   IN     BOOLEAN                   Initialized
432   )
433 {
434   //
435   // Print break status
436   //
437   if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_GT) == EFI_DEBUG_FLAG_EBC_GT) {
438     EDBPrint (L"Break on GoTil\n");
439   } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_BOC) == EFI_DEBUG_FLAG_EBC_BOC) {
440     EDBPrint (L"Break on CALL\n");
441   } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_BOCX) == EFI_DEBUG_FLAG_EBC_BOCX) {
442     EDBPrint (L"Break on CALLEX\n");
443   } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_BOR) == EFI_DEBUG_FLAG_EBC_BOR) {
444     EDBPrint (L"Break on RET\n");
445   } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_BOE) == EFI_DEBUG_FLAG_EBC_BOE) {
446     EDBPrint (L"Break on Entrypoint\n");
447   } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_BOT) == EFI_DEBUG_FLAG_EBC_BOT) {
448     EDBPrint (L"Break on Thunk\n");
449   } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_STEPOVER) == EFI_DEBUG_FLAG_EBC_STEPOVER) {
450     EDBPrint (L"Break on StepOver\n");
451   } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_STEPOUT) == EFI_DEBUG_FLAG_EBC_STEPOUT) {
452     EDBPrint (L"Break on StepOut\n");
453   } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_BP) == EFI_DEBUG_FLAG_EBC_BP) {
454     EDBPrint (L"Break on Breakpoint\n");
455   } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_BOK) == EFI_DEBUG_FLAG_EBC_BOK) {
456     EDBPrint (L"Break on Key\n");
457   } else {
458     EDBPrint (L"Exception Type - %x", (UINTN)ExceptionType);
459     if ((ExceptionType >= EXCEPT_EBC_UNDEFINED) && (ExceptionType <= EXCEPT_EBC_STEP)) {
460       EDBPrint (L" (%s)\n", mExceptionStr[ExceptionType]);
461     } else {
462       EDBPrint (L"\n");
463     }
464   }
465 
466   return ;
467 }
468 
469 /**
470 
471   The default Exception Callback for the VM interpreter.
472   In this function, we report status code, and print debug information
473   about EBC_CONTEXT, then dead loop.
474 
475   @param ExceptionType    Exception type.
476   @param SystemContext    EBC system context.
477 
478 **/
479 VOID
480 EFIAPI
EdbExceptionHandler(IN EFI_EXCEPTION_TYPE ExceptionType,IN OUT EFI_SYSTEM_CONTEXT SystemContext)481 EdbExceptionHandler (
482   IN     EFI_EXCEPTION_TYPE   ExceptionType,
483   IN OUT EFI_SYSTEM_CONTEXT   SystemContext
484   )
485 {
486   CHAR16                  InputBuffer[EFI_DEBUG_INPUS_BUFFER_SIZE];
487   CHAR16                  *CommandArg;
488   EFI_DEBUGGER_COMMAND    DebuggerCommand;
489   EFI_DEBUG_STATUS        DebugStatus;
490   STATIC BOOLEAN          mInitialized;
491 
492   mInitialized = FALSE;
493 
494   DEBUG ((DEBUG_ERROR, "Hello EBC Debugger!\n"));
495 
496   if (!mInitialized) {
497     //
498     // Print version
499     //
500     EDBPrint (
501       L"EBC Interpreter Version - %d.%d\n",
502       (UINTN)VM_MAJOR_VERSION,
503       (UINTN)VM_MINOR_VERSION
504       );
505     EDBPrint (
506       L"EBC Debugger Version - %d.%d\n",
507       (UINTN)EBC_DEBUGGER_MAJOR_VERSION,
508       (UINTN)EBC_DEBUGGER_MINOR_VERSION
509       );
510   }
511   //
512   // Init Private Data
513   //
514   InitDebuggerPrivateData (&mDebuggerPrivate, ExceptionType, SystemContext, mInitialized);
515 
516   //
517   // EDBPrint basic info
518   //
519   PrintExceptionReason (&mDebuggerPrivate, ExceptionType, SystemContext, mInitialized);
520 
521   EdbShowDisasm (&mDebuggerPrivate, SystemContext);
522   // EFI_BREAKPOINT ();
523 
524   if (!mInitialized) {
525     //
526     // Interactive with user
527     //
528     EDBPrint (L"\nPlease enter command now, \'h\' for help.\n");
529     EDBPrint (L"(Using <Command> -b <...> to enable page break.)\n");
530   }
531   mInitialized = TRUE;
532 
533   //
534   // Dispatch each command
535   //
536   while (TRUE) {
537     //
538     // Get user input
539     //
540     Input (L"\n\r" EFI_DEBUG_PROMPT_STRING, InputBuffer, EFI_DEBUG_INPUS_BUFFER_SIZE);
541     EDBPrint (L"\n");
542 
543     //
544     // Get command
545     //
546     DebuggerCommand = MatchDebuggerCommand (InputBuffer, &CommandArg);
547     if (DebuggerCommand == NULL) {
548       EDBPrint (L"ERROR: Command not found!\n");
549       continue;
550     }
551 
552     //
553     // Check PageBreak;
554     //
555     if (CommandArg != NULL) {
556       if (StriCmp (CommandArg, L"-b") == 0) {
557         CommandArg = StrGetNextTokenLine (L" ");
558         mDebuggerPrivate.EnablePageBreak = TRUE;
559       }
560     }
561 
562     //
563     // Dispatch command
564     //
565     DebugStatus = DebuggerCommand (CommandArg, &mDebuggerPrivate, ExceptionType, SystemContext);
566     mDebuggerPrivate.EnablePageBreak = FALSE;
567 
568     //
569     // Check command return status
570     //
571     if (DebugStatus == EFI_DEBUG_RETURN) {
572       mInitialized = FALSE;
573       break;
574     } else if (DebugStatus == EFI_DEBUG_BREAK) {
575       break;
576     } else if (DebugStatus == EFI_DEBUG_CONTINUE) {
577       continue;
578     } else {
579       ASSERT (FALSE);
580     }
581   }
582 
583   //
584   // Deinit Private Data
585   //
586   DeinitDebuggerPrivateData (&mDebuggerPrivate, ExceptionType, SystemContext, mInitialized);
587 
588   DEBUG ((DEBUG_ERROR, "Goodbye EBC Debugger!\n"));
589 
590   return;
591 }
592