public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Pete Batard <pete@akeo.ie>
To: edk2-devel@lists.01.org
Subject: [PATCH (RESEND) v2 2/3] MdeModulePkg/EbcDxe: add EBC Debugger
Date: Mon, 14 Nov 2016 13:14:17 +0000	[thread overview]
Message-ID: <20161114131418.11876-3-pete@akeo.ie> (raw)
In-Reply-To: <20161114131418.11876-1-pete@akeo.ie>

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Pete Batard <pete@akeo.ie>
---
 MdeModulePkg/MdeModulePkg.dsc                      |    3 +-
 MdeModulePkg/Universal/EbcDxe/EbcDebugger.inf      |  120 +
 MdeModulePkg/Universal/EbcDxe/EbcDebugger.uni      |   24 +
 MdeModulePkg/Universal/EbcDxe/EbcDebugger/Edb.c    |  659 +++++
 MdeModulePkg/Universal/EbcDxe/EbcDebugger/Edb.h    |   62 +
 .../Universal/EbcDxe/EbcDebugger/EdbCmdBranch.c    |  336 +++
 .../Universal/EbcDxe/EbcDebugger/EdbCmdBreak.c     |  327 +++
 .../EbcDxe/EbcDebugger/EdbCmdBreakpoint.c          |  614 +++++
 .../Universal/EbcDxe/EbcDebugger/EdbCmdExtIo.c     |  219 ++
 .../Universal/EbcDxe/EbcDebugger/EdbCmdExtPci.c    |  186 ++
 .../Universal/EbcDxe/EbcDebugger/EdbCmdGo.c        |   93 +
 .../Universal/EbcDxe/EbcDebugger/EdbCmdHelp.c      |   86 +
 .../Universal/EbcDxe/EbcDebugger/EdbCmdMemory.c    |  683 +++++
 .../Universal/EbcDxe/EbcDebugger/EdbCmdQuit.c      |   50 +
 .../Universal/EbcDxe/EbcDebugger/EdbCmdRegister.c  |  136 +
 .../Universal/EbcDxe/EbcDebugger/EdbCmdScope.c     |  123 +
 .../Universal/EbcDxe/EbcDebugger/EdbCmdStep.c      |  198 ++
 .../Universal/EbcDxe/EbcDebugger/EdbCmdSymbol.c    |  952 +++++++
 .../Universal/EbcDxe/EbcDebugger/EdbCommand.c      |  680 +++++
 .../Universal/EbcDxe/EbcDebugger/EdbCommand.h      |  106 +
 .../Universal/EbcDxe/EbcDebugger/EdbCommon.h       |  246 ++
 .../Universal/EbcDxe/EbcDebugger/EdbDisasm.c       | 1907 ++++++++++++++
 .../Universal/EbcDxe/EbcDebugger/EdbDisasm.h       |   42 +
 .../EbcDxe/EbcDebugger/EdbDisasmSupport.c          | 1461 +++++++++++
 .../EbcDxe/EbcDebugger/EdbDisasmSupport.h          |  241 ++
 .../Universal/EbcDxe/EbcDebugger/EdbHook.c         | 1003 ++++++++
 .../Universal/EbcDxe/EbcDebugger/EdbHook.h         |   27 +
 .../Universal/EbcDxe/EbcDebugger/EdbSupport.h      |  240 ++
 .../Universal/EbcDxe/EbcDebugger/EdbSupportFile.c  |  415 +++
 .../EbcDxe/EbcDebugger/EdbSupportString.c          |  991 ++++++++
 .../Universal/EbcDxe/EbcDebugger/EdbSupportUI.c    |  708 ++++++
 .../Universal/EbcDxe/EbcDebugger/EdbSymbol.c       | 2669 ++++++++++++++++++++
 .../Universal/EbcDxe/EbcDebugger/EdbSymbol.h       |  128 +
 MdeModulePkg/Universal/EbcDxe/EbcDebuggerExtra.uni |   17 +
 34 files changed, 15751 insertions(+), 1 deletion(-)
 create mode 100644 MdeModulePkg/Universal/EbcDxe/EbcDebugger.inf
 create mode 100644 MdeModulePkg/Universal/EbcDxe/EbcDebugger.uni
 create mode 100644 MdeModulePkg/Universal/EbcDxe/EbcDebugger/Edb.c
 create mode 100644 MdeModulePkg/Universal/EbcDxe/EbcDebugger/Edb.h
 create mode 100644 MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdBranch.c
 create mode 100644 MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdBreak.c
 create mode 100644 MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdBreakpoint.c
 create mode 100644 MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdExtIo.c
 create mode 100644 MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdExtPci.c
 create mode 100644 MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdGo.c
 create mode 100644 MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdHelp.c
 create mode 100644 MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdMemory.c
 create mode 100644 MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdQuit.c
 create mode 100644 MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdRegister.c
 create mode 100644 MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdScope.c
 create mode 100644 MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdStep.c
 create mode 100644 MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdSymbol.c
 create mode 100644 MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCommand.c
 create mode 100644 MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCommand.h
 create mode 100644 MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCommon.h
 create mode 100644 MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbDisasm.c
 create mode 100644 MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbDisasm.h
 create mode 100644 MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbDisasmSupport.c
 create mode 100644 MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbDisasmSupport.h
 create mode 100644 MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbHook.c
 create mode 100644 MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbHook.h
 create mode 100644 MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSupport.h
 create mode 100644 MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSupportFile.c
 create mode 100644 MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSupportString.c
 create mode 100644 MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSupportUI.c
 create mode 100644 MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSymbol.c
 create mode 100644 MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSymbol.h
 create mode 100644 MdeModulePkg/Universal/EbcDxe/EbcDebuggerExtra.uni

diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc
index ea75c8598404..369c8365100c 100644
--- a/MdeModulePkg/MdeModulePkg.dsc
+++ b/MdeModulePkg/MdeModulePkg.dsc
@@ -427,10 +427,11 @@
   MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.inf
   MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
 
-[Components.IA32, Components.X64, Components.IPF]  
+[Components.IA32, Components.X64, Components.IPF, Components.AARCH64]
   MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.inf
   MdeModulePkg/Universal/DebugSupportDxe/DebugSupportDxe.inf
   MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
+  MdeModulePkg/Universal/EbcDxe/EbcDebugger.inf
 
 [Components.IA32, Components.X64, Components.Ebc]
   MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf {
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger.inf b/MdeModulePkg/Universal/EbcDxe/EbcDebugger.inf
new file mode 100644
index 000000000000..d2db23dd158f
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger.inf
@@ -0,0 +1,120 @@
+## @file
+#  EFI Byte Code (EBC) Debugger.
+#
+#  Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
+#
+#  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.
+#
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = EbcDebugger
+  MODULE_UNI_FILE                = EbcDebugger.uni
+  FILE_GUID                      = 8296AF37-D183-4416-B3B6-19D2A80AD4A8
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = InitializeEbcDriver
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF AARCH64
+#
+
+[Sources]
+  EbcDebuggerHook.h
+  EbcInt.c
+  EbcInt.h
+  EbcExecute.c
+  EbcExecute.h
+  EbcDebugger/Edb.c
+  EbcDebugger/Edb.h
+  EbcDebugger/EdbCommon.h
+  EbcDebugger/EdbCmdBranch.c
+  EbcDebugger/EdbCmdBreak.c
+  EbcDebugger/EdbCmdBreakpoint.c
+  EbcDebugger/EdbCmdGo.c
+  EbcDebugger/EdbCmdHelp.c
+  EbcDebugger/EdbCmdMemory.c
+  EbcDebugger/EdbCmdRegister.c
+  EbcDebugger/EdbCmdQuit.c
+  EbcDebugger/EdbCmdScope.c
+  EbcDebugger/EdbCmdStep.c
+  EbcDebugger/EdbCmdSymbol.c
+  EbcDebugger/EdbCmdExtIo.c
+  EbcDebugger/EdbCmdExtPci.c
+  EbcDebugger/EdbCommand.c
+  EbcDebugger/EdbCommand.h
+  EbcDebugger/EdbDisasm.c
+  EbcDebugger/EdbDisasm.h
+  EbcDebugger/EdbDisasmSupport.c
+  EbcDebugger/EdbDisasmSupport.h
+  EbcDebugger/EdbSymbol.c
+  EbcDebugger/EdbSymbol.h
+  EbcDebugger/EdbHook.c
+  EbcDebugger/EdbHook.h
+  EbcDebugger/EdbSupport.h
+  EbcDebugger/EdbSupportUI.c
+  EbcDebugger/EdbSupportString.c
+  EbcDebugger/EdbSupportFile.c
+
+[Sources.Ia32]
+  Ia32/EbcSupport.c
+  Ia32/EbcLowLevel.nasm
+  Ia32/EbcLowLevel.S
+  Ia32/EbcLowLevel.asm
+
+[Sources.X64]
+  X64/EbcSupport.c
+  X64/EbcLowLevel.nasm
+  X64/EbcLowLevel.S
+  X64/EbcLowLevel.asm
+
+[Sources.IPF]
+  Ipf/EbcSupport.h
+  Ipf/EbcSupport.c
+  Ipf/EbcLowLevel.s
+
+[Sources.AARCH64]
+  AArch64/EbcSupport.c
+  AArch64/EbcLowLevel.S
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+  UefiDriverEntryPoint
+  UefiLib
+  UefiBootServicesTableLib
+  MemoryAllocationLib
+  BaseMemoryLib
+  DebugLib
+  BaseLib
+
+[Protocols]
+  gEfiDebugSupportProtocolGuid                  ## PRODUCES
+  gEfiEbcProtocolGuid                           ## PRODUCES
+  gEfiEbcVmTestProtocolGuid                     ## SOMETIMES_PRODUCES
+  gEfiEbcSimpleDebuggerProtocolGuid             ## SOMETIMES_CONSUMES
+  gEfiPciRootBridgeIoProtocolGuid               ## SOMETIMES_CONSUMES
+  gEfiSimpleFileSystemProtocolGuid              ## SOMETIMES_CONSUMES
+
+[Guids]
+  gEfiFileInfoGuid                              ## SOMETIMES_CONSUMES ## GUID
+  gEfiFileSystemInfoGuid                        ## SOMETIMES_CONSUMES ## GUID
+  gEfiFileSystemVolumeLabelInfoIdGuid           ## SOMETIMES_CONSUMES ## GUID
+  gEfiDebugImageInfoTableGuid                   ## SOMETIMES_CONSUMES ## GUID
+
+[Depex]
+  TRUE
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  EbcDebuggerExtra.uni
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger.uni b/MdeModulePkg/Universal/EbcDxe/EbcDebugger.uni
new file mode 100644
index 000000000000..155a9e3e5820
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger.uni
@@ -0,0 +1,24 @@
+// /** @file
+// EFI Byte Code (EBC) Debugger.
+//
+// This application can display statistical information about variable usage for SMM variable
+// driver and non-SMM variable driver.
+// Note that if Variable Dxe/Smm driver doesn't enable the feature by setting PcdVariableCollectStatistics
+// as TRUE, the application will not display variable statistical information.
+//
+// Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
+//
+// 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.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "EFI Byte Code (EBC) Debugger application"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "This application enables the debugging of EBC runtimes."
+
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger/Edb.c b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/Edb.c
new file mode 100644
index 000000000000..7c6f54600904
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/Edb.c
@@ -0,0 +1,659 @@
+/*++
+
+Copyright (c) 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.
+
+Module Name:
+
+  Ebc.c
+
+Abstract:
+
+--*/
+
+#include <Uefi.h>
+#include "Edb.h"
+
+EFI_DEBUGGER_PRIVATE_DATA mDebuggerPrivate = {
+  EFI_DEBUGGER_SIGNATURE,                    // Signature
+  IsaEbc,                                    // Isa
+  (EBC_DEBUGGER_MAJOR_VERSION << 16) |
+    EBC_DEBUGGER_MINOR_VERSION,              // EfiDebuggerRevision
+  (VM_MAJOR_VERSION << 16) |
+    VM_MINOR_VERSION,                        // EbcVmRevision
+  NULL,                                      // DebugImageInfoTableHeader
+  NULL,                                      // Vol
+  NULL,                                      // PciRootBridgeIo
+  mDebuggerCommandSet,                       // DebuggerCommandSet
+  {0},                                       // DebuggerSymbolContext
+  0,                                         // DebuggerBreakpointCount
+  {{0}},                                     // DebuggerBreakpointContext
+  0,                                         // CallStackEntryCount
+  {{0}},                                     // CallStackEntry
+  0,                                         // TraceEntryCount
+  {{0}},                                     // TraceEntry
+  {0},                                       // StepContext
+  {0},                                       // GoTilContext
+  0,                                         // InstructionScope
+  EFI_DEBUG_DEFAULT_INSTRUCTION_NUMBER,      // InstructionNumber
+  EFI_DEBUG_FLAG_EBC_BOE | EFI_DEBUG_FLAG_EBC_BOT, // FeatureFlags
+  0,                                               // StatusFlags
+  FALSE,                                           // EnablePageBreak
+  NULL                                             // BreakEvent
+};
+
+CHAR16 *mExceptionStr[] = {
+  L"EXCEPT_EBC_UNDEFINED",
+  L"EXCEPT_EBC_DIVIDE_ERROR",
+  L"EXCEPT_EBC_DEBUG",
+  L"EXCEPT_EBC_BREAKPOINT",
+  L"EXCEPT_EBC_OVERFLOW",
+  L"EXCEPT_EBC_INVALID_OPCODE",
+  L"EXCEPT_EBC_STACK_FAULT",
+  L"EXCEPT_EBC_ALIGNMENT_CHECK",
+  L"EXCEPT_EBC_INSTRUCTION_ENCODING",
+  L"EXCEPT_EBC_BAD_BREAK",
+  L"EXCEPT_EBC_SINGLE_STEP",
+};
+
+VOID
+EdbClearAllBreakpoint (
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     BOOLEAN                   NeedRemove
+  )
+/*++
+
+Routine Description:
+
+  Clear all the breakpoint
+
+Arguments:
+
+  DebuggerPrivate - EBC Debugger private data structure
+  NeedRemove      - Whether need to remove all the breakpoint
+
+Returns:
+
+  None
+
+--*/
+{
+  UINTN    Index;
+
+  //
+  // Patch all the breakpoint
+  //
+  for (Index = 0; (Index < DebuggerPrivate->DebuggerBreakpointCount) && (Index < EFI_DEBUGGER_BREAKPOINT_MAX); Index++) {
+    if (DebuggerPrivate->DebuggerBreakpointContext[Index].State) {
+      CopyMem (
+        (VOID *)(UINTN)DebuggerPrivate->DebuggerBreakpointContext[Index].BreakpointAddress,
+        &DebuggerPrivate->DebuggerBreakpointContext[Index].OldInstruction,
+        sizeof(UINT16)
+        );
+    }
+  }
+
+  //
+  // Zero Breakpoint context, if need to remove all breakpoint
+  //
+  if (NeedRemove) {
+    DebuggerPrivate->DebuggerBreakpointCount = 0;
+    ZeroMem (DebuggerPrivate->DebuggerBreakpointContext, sizeof(DebuggerPrivate->DebuggerBreakpointContext));
+  }
+
+  //
+  // Done
+  //
+  return ;
+}
+
+VOID
+EdbSetAllBreakpoint (
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate
+  )
+/*++
+
+Routine Description:
+
+  Set all the breakpoint
+
+Arguments:
+
+  DebuggerPrivate - EBC Debugger private data structure
+
+Returns:
+
+  None
+
+--*/
+{
+  UINTN    Index;
+  UINT16   Data16;
+
+  //
+  // Set all the breakpoint (BREAK(3) : 0x0300)
+  //
+  Data16 = 0x0300;
+  for (Index = 0; (Index < DebuggerPrivate->DebuggerBreakpointCount) && (Index < EFI_DEBUGGER_BREAKPOINT_MAX); Index++) {
+    if (DebuggerPrivate->DebuggerBreakpointContext[Index].State) {
+      CopyMem (
+        (VOID *)(UINTN)DebuggerPrivate->DebuggerBreakpointContext[Index].BreakpointAddress,
+        &Data16,
+        sizeof(UINT16)
+        );
+    }
+  }
+
+  //
+  // Check if current break is caused by breakpoint set.
+  // If so, we need to patch memory back to let user see the real memory.
+  //
+  if (DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX].BreakpointAddress != 0) {
+    CopyMem (
+      (VOID *)(UINTN)DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX].BreakpointAddress,
+      &DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX].OldInstruction,
+      sizeof(UINT16)
+      );
+    DebuggerPrivate->StatusFlags &= ~EFI_DEBUG_FLAG_EBC_B_BP;
+  }
+
+  //
+  // Done
+  //
+  return ;
+}
+
+VOID
+EdbCheckBreakpoint (
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  Check all the breakpoint, if match, then set status flag, and record current breakpoint.
+  Then clear all breakpoint to let user see a clean memory
+
+Arguments:
+
+  DebuggerPrivate - EBC Debugger private data structure
+  SystemContext   - EBC system context.
+
+Returns:
+
+  None
+
+--*/
+{
+  UINT64   Address;
+  UINTN    Index;
+  UINT16   OldInstruction;
+  BOOLEAN  IsHitBreakpoint;
+
+  //
+  // Roll back IP for breakpoint instruction (BREAK(3) : 0x0300)
+  //
+  Address = SystemContext.SystemContextEbc->Ip - sizeof(UINT16);
+
+  //
+  // Check if the breakpoint is hit
+  //
+  IsHitBreakpoint = FALSE;
+  for (Index = 0; (Index < DebuggerPrivate->DebuggerBreakpointCount) && (Index < EFI_DEBUGGER_BREAKPOINT_MAX); Index++) {
+    if ((DebuggerPrivate->DebuggerBreakpointContext[Index].BreakpointAddress == Address) &&
+        (DebuggerPrivate->DebuggerBreakpointContext[Index].State)) {
+      OldInstruction = (UINT16)DebuggerPrivate->DebuggerBreakpointContext[Index].OldInstruction;
+      IsHitBreakpoint = TRUE;
+      break;
+    }
+  }
+
+  if (IsHitBreakpoint) {
+    //
+    // If hit, record current breakpoint
+    //
+    DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX] = DebuggerPrivate->DebuggerBreakpointContext[Index];
+    DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX].State = TRUE;
+    //
+    // Update: IP and Instruction (NOTE: Since we not allow set breakpoint to BREAK 3, this update is safe)
+    //
+    SystemContext.SystemContextEbc->Ip = Address;
+    //
+    // Set Flags
+    //
+    DebuggerPrivate->StatusFlags |= EFI_DEBUG_FLAG_EBC_BP;
+  } else {
+    //
+    // If not hit, check whether current IP is in breakpoint list,
+    // because STEP will be triggered before execute the instruction.
+    // We should not patch it in de-init.
+    //
+    Address = SystemContext.SystemContextEbc->Ip;
+
+    //
+    // Check if the breakpoint is hit
+    //
+    IsHitBreakpoint = FALSE;
+    for (Index = 0; (Index < DebuggerPrivate->DebuggerBreakpointCount) && (Index < EFI_DEBUGGER_BREAKPOINT_MAX); Index++) {
+      if ((DebuggerPrivate->DebuggerBreakpointContext[Index].BreakpointAddress == Address) &&
+          (DebuggerPrivate->DebuggerBreakpointContext[Index].State)) {
+        OldInstruction = (UINT16)DebuggerPrivate->DebuggerBreakpointContext[Index].OldInstruction;
+        IsHitBreakpoint = TRUE;
+        break;
+      }
+    }
+
+    if (IsHitBreakpoint) {
+      //
+      // If hit, record current breakpoint
+      //
+      DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX] = DebuggerPrivate->DebuggerBreakpointContext[Index];
+      DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX].State = TRUE;
+      //
+      // Do not set Breakpoint flag. We record the address here just let it not patch breakpoint address when de-init.
+      //
+    } else {
+      //
+      // Zero current breakpoint
+      //
+      ZeroMem (
+        &DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX],
+        sizeof(DebuggerPrivate->DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX])
+        );
+    }
+  }
+
+  //
+  // Done
+  //
+  return ;
+}
+
+VOID
+EdbClearSymbol (
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate
+  )
+/*++
+
+Routine Description:
+
+  clear all the symbol
+
+Arguments:
+
+  DebuggerPrivate - EBC Debugger private data structure
+
+Returns:
+
+  None
+
+--*/
+{
+  EFI_DEBUGGER_SYMBOL_CONTEXT *DebuggerSymbolContext;
+  EFI_DEBUGGER_SYMBOL_OBJECT  *Object;
+  UINTN                       ObjectIndex;
+  UINTN                       Index;
+
+  //
+  // Go throuth each object
+  //
+  DebuggerSymbolContext = &DebuggerPrivate->DebuggerSymbolContext;
+  for (ObjectIndex = 0; ObjectIndex < DebuggerSymbolContext->ObjectCount; ObjectIndex++) {
+    Object = &DebuggerSymbolContext->Object[ObjectIndex];
+    //
+    // Go throuth each entry
+    //
+    for (Index = 0; Index < Object->EntryCount; Index++) {
+      ZeroMem (&Object->Entry[Index], sizeof(Object->Entry[Index]));
+    }
+    ZeroMem (Object->Name, sizeof(Object->Name));
+    Object->EntryCount = 0;
+    Object->BaseAddress = 0;
+    Object->StartEntrypointRVA = 0;
+    Object->MainEntrypointRVA = 0;
+    //
+    // Free source buffer
+    //
+    for (Index = 0; Object->SourceBuffer[Index] != NULL; Index++) {
+      gBS->FreePool (Object->SourceBuffer[Index]);
+      Object->SourceBuffer[Index] = NULL;
+    }
+  }
+  DebuggerSymbolContext->ObjectCount = 0;
+
+  return ;
+}
+
+EFI_STATUS
+InitDebuggerPrivateData (
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN     EFI_SYSTEM_CONTEXT        SystemContext,
+  IN     BOOLEAN                   Initialized
+  )
+/*++
+
+Routine Description:
+
+  Initialize Debugger private data structure
+
+Arguments:
+
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+  Initialized     - Whether the DebuggerPrivate data is initialized.
+
+Returns:
+
+  None
+
+--*/
+{
+  //
+  // clear STEP flag in any condition.
+  //
+  if (SystemContext.SystemContextEbc->Flags & VMFLAGS_STEP) {
+    SystemContext.SystemContextEbc->Flags &= ~VMFLAGS_STEP;
+  }
+
+  if (!Initialized) {
+    //
+    // Initialize everything
+    //
+    DebuggerPrivate->InstructionNumber = EFI_DEBUG_DEFAULT_INSTRUCTION_NUMBER;
+
+    DebuggerPrivate->DebuggerBreakpointCount = 0;
+    ZeroMem (DebuggerPrivate->DebuggerBreakpointContext, sizeof(DebuggerPrivate->DebuggerBreakpointContext));
+
+//    DebuggerPrivate->StatusFlags = 0;
+
+    DebuggerPrivate->DebuggerSymbolContext.DisplaySymbol = TRUE;
+    DebuggerPrivate->DebuggerSymbolContext.DisplayCodeOnly = FALSE;
+    DebuggerPrivate->DebuggerSymbolContext.ObjectCount = 0;
+  } else {
+    //
+    // Already initialized, just check Breakpoint here.
+    //
+    if (ExceptionType == EXCEPT_EBC_BREAKPOINT) {
+      EdbCheckBreakpoint (DebuggerPrivate, SystemContext);
+    }
+
+    //
+    // Clear all breakpoint
+    //
+    EdbClearAllBreakpoint (DebuggerPrivate, FALSE);
+  }
+
+  //
+  // Set Scope to currentl IP. (Note: Check Breakpoint may change Ip)
+  //
+  DebuggerPrivate->InstructionScope = SystemContext.SystemContextEbc->Ip;
+
+  //
+  // Done
+  //
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+DeinitDebuggerPrivateData (
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN     EFI_SYSTEM_CONTEXT        SystemContext,
+  IN     BOOLEAN                   Initialized
+  )
+/*++
+
+Routine Description:
+
+  De-initialize Debugger private data structure
+
+Arguments:
+
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+  Initialized     - Whether the DebuggerPrivate data is initialized.
+
+Returns:
+
+  None
+
+--*/
+{
+  if (!Initialized) {
+    //
+    // If it does not want initialized state, de-init everything
+    //
+    DebuggerPrivate->FeatureFlags = EFI_DEBUG_FLAG_EBC_BOE | EFI_DEBUG_FLAG_EBC_BOT;
+    DebuggerPrivate->CallStackEntryCount = 0;
+    DebuggerPrivate->TraceEntryCount = 0;
+    ZeroMem (DebuggerPrivate->CallStackEntry, sizeof(DebuggerPrivate->CallStackEntry));
+    ZeroMem (DebuggerPrivate->TraceEntry, sizeof(DebuggerPrivate->TraceEntry));
+
+    //
+    // Clear all breakpoint
+    //
+    EdbClearAllBreakpoint (DebuggerPrivate, TRUE);
+
+    //
+    // Clear symbol
+    //
+    EdbClearSymbol (DebuggerPrivate);
+  } else {
+    //
+    // If it wants to keep initialized state, just set breakpoint.
+    //
+    EdbSetAllBreakpoint (DebuggerPrivate);
+  }
+
+  //
+  // Clear Step context
+  //
+  ZeroMem (&mDebuggerPrivate.StepContext, sizeof(mDebuggerPrivate.StepContext));
+  DebuggerPrivate->StatusFlags = 0;
+
+  //
+  // Done
+  //
+  return EFI_SUCCESS;
+}
+
+VOID
+PrintExceptionReason (
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN     EFI_SYSTEM_CONTEXT        SystemContext,
+  IN     BOOLEAN                   Initialized
+  )
+/*++
+
+Routine Description:
+
+  Print the reason of current break to EbcDebugger.
+
+Arguments:
+
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+  Initialized     - Whether the DebuggerPrivate data is initialized.
+
+Returns:
+
+  None
+
+--*/
+{
+  //
+  // Print break status
+  //
+  if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_GT) == EFI_DEBUG_FLAG_EBC_GT) {
+    EDBPrint (L"Break on GoTil\n");
+  } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_BOC) == EFI_DEBUG_FLAG_EBC_BOC) {
+    EDBPrint (L"Break on CALL\n");
+  } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_BOCX) == EFI_DEBUG_FLAG_EBC_BOCX) {
+    EDBPrint (L"Break on CALLEX\n");
+  } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_BOR) == EFI_DEBUG_FLAG_EBC_BOR) {
+    EDBPrint (L"Break on RET\n");
+  } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_BOE) == EFI_DEBUG_FLAG_EBC_BOE) {
+    EDBPrint (L"Break on Entrypoint\n");
+  } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_BOT) == EFI_DEBUG_FLAG_EBC_BOT) {
+    EDBPrint (L"Break on Thunk\n");
+  } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_STEPOVER) == EFI_DEBUG_FLAG_EBC_STEPOVER) {
+    EDBPrint (L"Break on StepOver\n");
+  } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_STEPOUT) == EFI_DEBUG_FLAG_EBC_STEPOUT) {
+    EDBPrint (L"Break on StepOut\n");
+  } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_BP) == EFI_DEBUG_FLAG_EBC_BP) {
+    EDBPrint (L"Break on Breakpoint\n");
+  } else if ((DebuggerPrivate->StatusFlags & EFI_DEBUG_FLAG_EBC_BOK) == EFI_DEBUG_FLAG_EBC_BOK) {
+    EDBPrint (L"Break on Key\n");
+  } else {
+    EDBPrint (L"Exception Type - %x", (UINTN)ExceptionType);
+    if ((ExceptionType >= EXCEPT_EBC_UNDEFINED) && (ExceptionType <= EXCEPT_EBC_STEP)) {
+      EDBPrint (L" (%s)\n", mExceptionStr[ExceptionType]);
+    } else {
+      EDBPrint (L"\n");
+    }
+  }
+
+  return ;
+}
+
+VOID
+EFIAPI
+EdbExceptionHandler (
+  IN     EFI_EXCEPTION_TYPE   ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT   SystemContext
+  )
+/*++
+
+Routine Description:
+
+  The default Exception Callback for the VM interpreter.
+  In this function, we report status code, and print debug information
+  about EBC_CONTEXT, then dead loop.
+
+Arguments:
+
+  InterruptType - Interrupt type.
+  SystemContext - EBC system context.
+
+Returns:
+
+  None
+
+--*/
+{
+  CHAR16                  InputBuffer[EFI_DEBUG_INPUS_BUFFER_SIZE];
+  CHAR16                  *CommandArg;
+  EFI_DEBUGGER_COMMAND    DebuggerCommand;
+  EFI_DEBUG_STATUS        DebugStatus;
+  STATIC BOOLEAN          mInitialized = FALSE;
+
+  DEBUG ((EFI_D_ERROR, "Hello EBC Debugger!\n"));
+
+  if (!mInitialized) {
+    //
+    // Print version
+    //
+    EDBPrint (
+      L"EBC Interpreter Version - %d.%d\n",
+      (UINTN)VM_MAJOR_VERSION,
+      (UINTN)VM_MINOR_VERSION
+      );
+    EDBPrint (
+      L"EBC Debugger Version - %d.%d\n",
+      (UINTN)EBC_DEBUGGER_MAJOR_VERSION,
+      (UINTN)EBC_DEBUGGER_MINOR_VERSION
+      );
+  }
+  //
+  // Init Private Data
+  //
+  InitDebuggerPrivateData (&mDebuggerPrivate, ExceptionType, SystemContext, mInitialized);
+
+  //
+  // EDBPrint basic info
+  //
+  PrintExceptionReason (&mDebuggerPrivate, ExceptionType, SystemContext, mInitialized);
+
+  EdbShowDisasm (&mDebuggerPrivate, SystemContext);
+  // EFI_BREAKPOINT ();
+
+  if (!mInitialized) {
+    //
+    // Interactive with user
+    //
+    EDBPrint (L"\nPlease enter command now, \'h\' for help.\n");
+    EDBPrint (L"(Using <Command> -b <...> to enable page break.)\n");
+  }
+  mInitialized = TRUE;
+
+  //
+  // Dispatch each command
+  //
+  while (TRUE) {
+    //
+    // Get user input
+    //
+    Input (L"\n\r" EFI_DEBUG_PROMPT_STRING, InputBuffer, EFI_DEBUG_INPUS_BUFFER_SIZE);
+    EDBPrint (L"\n");
+
+    //
+    // Get command
+    //
+    DebuggerCommand = MatchDebuggerCommand (InputBuffer, &CommandArg);
+    if (DebuggerCommand == NULL) {
+      EDBPrint (L"ERROR: Command not found!\n");
+      continue;
+    }
+
+    //
+    // Check PageBreak;
+    //
+    if (CommandArg != NULL) {
+      if (StriCmp (CommandArg, L"-b") == 0) {
+        CommandArg = StrGetNextTokenLine (L" ");
+        mDebuggerPrivate.EnablePageBreak = TRUE;
+      }
+    }
+
+    //
+    // Dispatch command
+    //
+    DebugStatus = DebuggerCommand (CommandArg, &mDebuggerPrivate, ExceptionType, SystemContext);
+    mDebuggerPrivate.EnablePageBreak = FALSE;
+
+    //
+    // Check command return status
+    //
+    if (DebugStatus == EFI_DEBUG_RETURN) {
+      mInitialized = FALSE;
+      break;
+    } else if (DebugStatus == EFI_DEBUG_BREAK) {
+      break;
+    } else if (DebugStatus == EFI_DEBUG_CONTINUE) {
+      continue;
+    } else {
+      ASSERT (FALSE);
+    }
+  }
+
+  //
+  // Deinit Private Data
+  //
+  DeinitDebuggerPrivateData (&mDebuggerPrivate, ExceptionType, SystemContext, mInitialized);
+
+  DEBUG ((EFI_D_ERROR, "Goodbye EBC Debugger!\n"));
+
+  return;
+}
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger/Edb.h b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/Edb.h
new file mode 100644
index 000000000000..cdddb0469226
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/Edb.h
@@ -0,0 +1,62 @@
+/*++
+
+Copyright (c) 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.
+
+Module Name:
+
+  Edb.h
+
+Abstract:
+
+
+--*/
+
+#ifndef _EFI_EDB_H_
+#define _EFI_EDB_H_
+
+#include <Uefi.h>
+#include "EdbCommon.h"
+
+#include "EbcInt.h"
+#include "EbcExecute.h"
+
+#define EBC_DEBUGGER_MAJOR_VERSION   1
+#define EBC_DEBUGGER_MINOR_VERSION   0
+
+#define EFI_DEBUG_RETURN    1
+#define EFI_DEBUG_BREAK     2
+#define EFI_DEBUG_CONTINUE  3
+
+//
+// Function
+//
+EFI_STATUS
+EfiDebuggerEntrypoint (
+  IN EFI_HANDLE                     ImageHandle,
+  IN EFI_SYSTEM_TABLE               *SystemTable
+  );
+
+VOID
+EFIAPI
+EdbExceptionHandler (
+  IN     EFI_EXCEPTION_TYPE   ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT   SystemContext
+  );
+
+extern EFI_DEBUGGER_PRIVATE_DATA mDebuggerPrivate;
+
+#include "EdbSupport.h"
+#include "EdbCommand.h"
+#include "EdbDisasm.h"
+#include "EdbDisasmSupport.h"
+#include "EdbSymbol.h"
+#include "EdbHook.h"
+
+#endif
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdBranch.c b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdBranch.c
new file mode 100644
index 000000000000..d049f302dd50
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdBranch.c
@@ -0,0 +1,336 @@
+/*++
+
+Copyright (c) 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.
+
+Module Name:
+
+  EdbCmdBranch.c
+
+Abstract:
+
+
+--*/
+
+#include "Edb.h"
+
+CHAR16 *mBranchTypeStr[] = {
+  L"(CALL)",
+  L"(CALLEX)",
+  L"(RET)",
+  L"(JMP)",
+  L"(JMP8)",
+};
+
+CHAR16 *
+EdbBranchTypeToStr (
+  IN EFI_DEBUGGER_BRANCH_TYPE  Type
+  )
+/*++
+
+Routine Description:
+
+  Comvert Branch Type to string
+
+Arguments:
+
+  Type            - Branch Type
+
+Returns:
+
+  String
+
+--*/
+{
+  if (Type < 0 || Type >= EfiDebuggerBranchTypeEbcMax) {
+    return L"(Unknown Type)";
+  }
+
+  return mBranchTypeStr [Type];
+}
+
+EFI_DEBUG_STATUS
+DebuggerCallStack (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - CallStack
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  INTN                           Index;
+  UINTN                          SubIndex;
+  CHAR8                          *FuncName;
+  EFI_DEBUGGER_CALLSTACK_CONTEXT *CallStackEntry;
+  BOOLEAN                        ShowParameter;
+  UINTN                          ParameterNumber;
+
+  ShowParameter = FALSE;
+  ParameterNumber = EFI_DEBUGGER_CALL_DEFAULT_PARAMETER;
+
+  //
+  // Check argument
+  //
+  if (CommandArg != NULL) {
+    if (StriCmp (CommandArg, L"c") == 0) {
+      //
+      // Clear Call-Stack
+      //
+      DebuggerPrivate->CallStackEntryCount = 0;
+      ZeroMem (DebuggerPrivate->CallStackEntry, sizeof(DebuggerPrivate->CallStackEntry));
+      EDBPrint (L"Call-Stack is cleared\n");
+      return EFI_DEBUG_CONTINUE;
+    } else if (StriCmp (CommandArg, L"p") == 0) {
+      //
+      // Print Call-Stack with parameter
+      //
+      ShowParameter = TRUE;
+      CommandArg = StrGetNextTokenLine (L" ");
+      if (CommandArg != NULL) {
+        //
+        // Try to get the parameter number
+        //
+        ParameterNumber = Atoi (CommandArg);
+        if (ParameterNumber > 16) {
+          EDBPrint (L"Call-Stack argument Invalid\n");
+          return EFI_DEBUG_CONTINUE;
+        }
+      }
+    } else {
+      EDBPrint (L"Call-Stack argument Invalid\n");
+      return EFI_DEBUG_CONTINUE;
+    }
+  }
+
+  //
+  // Check CallStack Entry Count
+  //
+  if (DebuggerPrivate->CallStackEntryCount == 0) {
+    EDBPrint (L"No Call-Stack\n");
+    return EFI_DEBUG_CONTINUE;
+  } else if (DebuggerPrivate->CallStackEntryCount > EFI_DEBUGGER_CALLSTACK_MAX) {
+    EDBPrint (L"Call-Stack Crash, re-initialize!\n");
+    DebuggerPrivate->CallStackEntryCount = 0;
+    return EFI_DEBUG_CONTINUE;
+  }
+
+  //
+  // Go through each CallStack entry and print
+  //
+  EDBPrint (L"Call-Stack (TOP):\n");
+  EDBPrint (L"         Caller             Callee        Name\n");
+  EDBPrint (L"  ================== ================== ========\n");
+//EDBPrint (L"  0x00000000FFFFFFFF 0xFFFFFFFF00000000 EfiMain\n");
+  for (Index = (INTN)(DebuggerPrivate->CallStackEntryCount - 1); Index >= 0; Index--) {
+    //
+    // Get CallStack and print
+    //
+    CallStackEntry = &DebuggerPrivate->CallStackEntry[Index];
+    EDBPrint (
+      L"  0x%016lx 0x%016lx",
+      CallStackEntry->SourceAddress,
+      CallStackEntry->DestAddress
+      );
+    FuncName = FindSymbolStr ((UINTN)CallStackEntry->DestAddress);
+    if (FuncName != NULL) {
+      EDBPrint (L" %a()", FuncName);
+    }
+    EDBPrint (L"\n");
+
+    if (ShowParameter) {
+      //
+      // Print parameter
+      //
+      if (sizeof(UINTN) == sizeof(UINT64)) {
+        EDBPrint (
+          L"    Parameter Address (0x%016lx) (\n",
+          CallStackEntry->ParameterAddr
+          );
+        if (ParameterNumber == 0) {
+          EDBPrint (L"        )\n");
+          continue;
+        }
+        //
+        // Print each parameter
+        //
+        for (SubIndex = 0; SubIndex < ParameterNumber - 1; SubIndex++) {
+          if (SubIndex % 2 == 0) {
+            EDBPrint (L"        ");
+          }
+          EDBPrint (
+            L"0x%016lx, ",
+            CallStackEntry->Parameter[SubIndex]
+            );
+          if (SubIndex % 2 == 1) {
+            EDBPrint (L"\n");
+          }
+        }
+        if (SubIndex % 2 == 0) {
+          EDBPrint (L"        ");
+        }
+        EDBPrint (
+          L"0x%016lx\n",
+          CallStackEntry->Parameter[SubIndex]
+          );
+        EDBPrint (L"        )\n");
+        //
+        // break only for parameter
+        //
+        if ((((DebuggerPrivate->CallStackEntryCount - Index) % (16 / ParameterNumber)) == 0) &&
+            (Index != 0)) {
+          if (SetPageBreak ()) {
+            break;
+          }
+        }
+      } else {
+        EDBPrint (
+          L"    Parameter Address (0x%08x) (\n",
+          CallStackEntry->ParameterAddr
+          );
+        if (ParameterNumber == 0) {
+          EDBPrint (L"        )\n");
+          continue;
+        }
+        //
+        // Print each parameter
+        //
+        for (SubIndex = 0; SubIndex < ParameterNumber - 1; SubIndex++) {
+          if (SubIndex % 4 == 0) {
+            EDBPrint (L"        ");
+          }
+          EDBPrint (
+            L"0x%08x, ",
+            CallStackEntry->Parameter[SubIndex]
+            );
+          if (SubIndex % 4 == 3) {
+            EDBPrint (L"\n");
+          }
+        }
+        if (SubIndex % 4 == 0) {
+          EDBPrint (L"        ");
+        }
+        EDBPrint (
+          L"0x%08x\n",
+          CallStackEntry->Parameter[SubIndex]
+          );
+        EDBPrint (L"        )\n");
+        //
+        // break only for parameter
+        //
+        if ((((DebuggerPrivate->CallStackEntryCount - Index) % (32 / ParameterNumber)) == 0) &&
+            (Index != 0)) {
+          if (SetPageBreak ()) {
+            break;
+          }
+        }
+      }
+    }
+  }
+
+  //
+  // Done
+  //
+  return EFI_DEBUG_CONTINUE;
+}
+
+EFI_DEBUG_STATUS
+DebuggerInstructionBranch (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - InstructionBranch
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  UINTN  Index;
+
+  //
+  // Check argument
+  //
+  if (CommandArg != NULL) {
+    if (StriCmp (CommandArg, L"c") == 0) {
+      //
+      // Clear Trace
+      //
+      DebuggerPrivate->TraceEntryCount = 0;
+      ZeroMem (DebuggerPrivate->TraceEntry, sizeof(DebuggerPrivate->TraceEntry));
+      EDBPrint (L"Instruction Trace is cleared\n");
+    } else {
+      EDBPrint (L"Trace argument Invalid\n");
+    }
+    return EFI_DEBUG_CONTINUE;
+  }
+
+  //
+  // Check Trace Entry Count
+  //
+  if (DebuggerPrivate->TraceEntryCount == 0) {
+    EDBPrint (L"No Instruction Trace\n");
+    return EFI_DEBUG_CONTINUE;
+  } else if (DebuggerPrivate->TraceEntryCount > EFI_DEBUGGER_TRACE_MAX) {
+    EDBPrint (L"Instruction Trace Crash, re-initialize!\n");
+    DebuggerPrivate->TraceEntryCount = 0;
+    return EFI_DEBUG_CONTINUE;
+  }
+
+  //
+  // Go through each Trace entry and print
+  //
+  EDBPrint (L"Instruction Trace (->Latest):\n");
+  EDBPrint (L"    Source Addr        Destination Addr   Type\n");
+  EDBPrint (L"  ================== ================== ========\n");
+//EDBPrint (L"  0x00000000FFFFFFFF 0xFFFFFFFF00000000  (CALLEX)\n");
+  for (Index = 0; Index < DebuggerPrivate->TraceEntryCount; Index++) {
+    EDBPrint (
+      L"  0x%016lx 0x%016lx  %s\n",
+      DebuggerPrivate->TraceEntry[Index].SourceAddress,
+      DebuggerPrivate->TraceEntry[Index].DestAddress,
+      EdbBranchTypeToStr (DebuggerPrivate->TraceEntry[Index].Type)
+      );
+  }
+
+  //
+  // Done
+  //
+  return EFI_DEBUG_CONTINUE;
+}
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdBreak.c b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdBreak.c
new file mode 100644
index 000000000000..937f965f3ae2
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdBreak.c
@@ -0,0 +1,327 @@
+/*++
+
+Copyright (c) 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.
+
+Module Name:
+
+  EdbCmdBreak.c
+
+Abstract:
+
+
+--*/
+
+#include "Edb.h"
+
+EFI_DEBUG_STATUS
+DebuggerBreakOnCALL (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - BreakOnCALL
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  //
+  // Check argument
+  //
+  if (CommandArg == NULL) {
+    if ((DebuggerPrivate->FeatureFlags & EFI_DEBUG_FLAG_EBC_BOC) == EFI_DEBUG_FLAG_EBC_BOC) {
+      EDBPrint (L"BOC on\n");
+    } else {
+      EDBPrint (L"BOC off\n");
+    }
+  } else if (StriCmp (CommandArg, L"on") == 0) {
+    DebuggerPrivate->FeatureFlags |= EFI_DEBUG_FLAG_EBC_BOC;
+    EDBPrint (L"BOC on\n");
+  } else if (StriCmp (CommandArg, L"off") == 0) {
+    DebuggerPrivate->FeatureFlags &= ~EFI_DEBUG_FLAG_EBC_B_BOC;
+    EDBPrint (L"BOC off\n");
+  } else {
+    EDBPrint (L"BOC - argument error\n");
+  }
+
+  //
+  // Done
+  //
+  return EFI_DEBUG_CONTINUE;
+}
+
+EFI_DEBUG_STATUS
+DebuggerBreakOnCALLEX (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - BreakOnCALLEX
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  //
+  // Check argument
+  //
+  if (CommandArg == NULL) {
+    if ((DebuggerPrivate->FeatureFlags & EFI_DEBUG_FLAG_EBC_BOCX) == EFI_DEBUG_FLAG_EBC_BOCX) {
+      EDBPrint (L"BOCX on\n");
+    } else {
+      EDBPrint (L"BOCX off\n");
+    }
+  } else if (StriCmp (CommandArg, L"on") == 0) {
+    DebuggerPrivate->FeatureFlags |= EFI_DEBUG_FLAG_EBC_BOCX;
+    EDBPrint (L"BOCX on\n");
+  } else if (StriCmp (CommandArg, L"off") == 0) {
+    DebuggerPrivate->FeatureFlags &= ~EFI_DEBUG_FLAG_EBC_B_BOCX;
+    EDBPrint (L"BOCX off\n");
+  } else {
+    EDBPrint (L"BOCX - argument error\n");
+  }
+
+  //
+  // Done
+  //
+  return EFI_DEBUG_CONTINUE;
+}
+
+EFI_DEBUG_STATUS
+DebuggerBreakOnRET (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - BreakOnRET
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  //
+  // Check argument
+  //
+  if (CommandArg == NULL) {
+    if ((DebuggerPrivate->FeatureFlags & EFI_DEBUG_FLAG_EBC_BOR) == EFI_DEBUG_FLAG_EBC_BOR) {
+      EDBPrint (L"BOR on\n");
+    } else {
+      EDBPrint (L"BOR off\n");
+    }
+  } else if (StriCmp (CommandArg, L"on") == 0) {
+    DebuggerPrivate->FeatureFlags |= EFI_DEBUG_FLAG_EBC_BOR;
+    EDBPrint (L"BOR on\n");
+  } else if (StriCmp (CommandArg, L"off") == 0) {
+    DebuggerPrivate->FeatureFlags &= ~EFI_DEBUG_FLAG_EBC_B_BOR;
+    EDBPrint (L"BOR off\n");
+  } else {
+    EDBPrint (L"BOR - argument error\n");
+  }
+
+  //
+  // Done
+  //
+  return EFI_DEBUG_CONTINUE;
+}
+
+EFI_DEBUG_STATUS
+DebuggerBreakOnEntrypoint (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - BreakOnEntrypoint
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  //
+  // Check argument
+  //
+  if (CommandArg == NULL) {
+    if ((DebuggerPrivate->FeatureFlags & EFI_DEBUG_FLAG_EBC_BOE) == EFI_DEBUG_FLAG_EBC_BOE) {
+      EDBPrint (L"BOE on\n");
+    } else {
+      EDBPrint (L"BOE off\n");
+    }
+  } else if (StriCmp (CommandArg, L"on") == 0) {
+    DebuggerPrivate->FeatureFlags |= EFI_DEBUG_FLAG_EBC_BOE;
+    EDBPrint (L"BOE on\n");
+  } else if (StriCmp (CommandArg, L"off") == 0) {
+    DebuggerPrivate->FeatureFlags &= ~EFI_DEBUG_FLAG_EBC_B_BOE;
+    EDBPrint (L"BOE off\n");
+  } else {
+    EDBPrint (L"BOE - argument error\n");
+  }
+
+  //
+  // Done
+  //
+  return EFI_DEBUG_CONTINUE;
+}
+
+EFI_DEBUG_STATUS
+DebuggerBreakOnThunk (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - BreakOnThunk
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  //
+  // Check argument
+  //
+  if (CommandArg == NULL) {
+    if ((DebuggerPrivate->FeatureFlags & EFI_DEBUG_FLAG_EBC_BOT) == EFI_DEBUG_FLAG_EBC_BOT) {
+      EDBPrint (L"BOT on\n");
+    } else {
+      EDBPrint (L"BOT off\n");
+    }
+  } else if (StriCmp (CommandArg, L"on") == 0) {
+    DebuggerPrivate->FeatureFlags |= EFI_DEBUG_FLAG_EBC_BOT;
+    EDBPrint (L"BOT on\n");
+  } else if (StriCmp (CommandArg, L"off") == 0) {
+    DebuggerPrivate->FeatureFlags &= ~EFI_DEBUG_FLAG_EBC_B_BOT;
+    EDBPrint (L"BOT off\n");
+  } else {
+    EDBPrint (L"BOT - argument error\n");
+  }
+
+  //
+  // Done
+  //
+  return EFI_DEBUG_CONTINUE;
+}
+
+EFI_DEBUG_STATUS
+DebuggerBreakOnKey (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - BreakOnKey
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  //
+  // Check argument
+  //
+  if (CommandArg == NULL) {
+    if ((DebuggerPrivate->FeatureFlags & EFI_DEBUG_FLAG_EBC_BOK) == EFI_DEBUG_FLAG_EBC_BOK) {
+      EDBPrint (L"BOK on\n");
+    } else {
+      EDBPrint (L"BOK off\n");
+    }
+  } else if (StriCmp (CommandArg, L"on") == 0) {
+    DebuggerPrivate->FeatureFlags |= EFI_DEBUG_FLAG_EBC_BOK;
+    EDBPrint (L"BOK on\n");
+  } else if (StriCmp (CommandArg, L"off") == 0) {
+    DebuggerPrivate->FeatureFlags &= ~EFI_DEBUG_FLAG_EBC_B_BOK;
+    EDBPrint (L"BOK off\n");
+  } else {
+    EDBPrint (L"BOK - argument error\n");
+  }
+
+  //
+  // Done
+  //
+  return EFI_DEBUG_CONTINUE;
+}
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdBreakpoint.c b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdBreakpoint.c
new file mode 100644
index 000000000000..8f849a86955e
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdBreakpoint.c
@@ -0,0 +1,614 @@
+/*++
+
+Copyright (c) 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.
+
+Module Name:
+
+  EdbCmdBreakpoint.c
+
+Abstract:
+
+
+--*/
+
+#include "Edb.h"
+
+BOOLEAN
+IsEBCBREAK3 (
+  IN UINTN            Address
+  )
+/*++
+
+Routine Description:
+
+  Check whether current IP is EBC BREAK3 instruction
+
+Arguments:
+
+  Address   - EBC IP address.
+
+Returns:
+
+  TRUE  - Current IP is EBC BREAK3 instruction
+  FALSE - Current IP is not EBC BREAK3 instruction
+
+--*/
+{
+  if (GET_OPCODE(Address) != OPCODE_BREAK) {
+    return FALSE;
+  }
+
+  if (GET_OPERANDS (Address) != 3) {
+    return FALSE;
+  } else {
+    return TRUE;
+  }
+}
+
+BOOLEAN
+DebuggerBreakpointIsDuplicated (
+  IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN UINTN                     Address
+  )
+/*++
+
+Routine Description:
+
+  Check whether the Address is already set in breakpoint
+
+Arguments:
+
+  DebuggerPrivate - EBC Debugger private data structure
+  Address         - Breakpoint Address
+
+Returns:
+
+  TRUE          - breakpoint is found
+  FALSE         - breakpoint is not found
+
+--*/
+{
+  UINTN  Index;
+
+  //
+  // Go through each breakpoint context
+  //
+  for (Index = 0; Index < DebuggerPrivate->DebuggerBreakpointCount; Index++) {
+    if (DebuggerPrivate->DebuggerBreakpointContext[Index].BreakpointAddress == Address) {
+      //
+      // Found it
+      //
+      return TRUE;
+    }
+  }
+
+  //
+  // Not found
+  //
+  return FALSE;
+}
+
+EFI_STATUS
+DebuggerBreakpointAdd (
+  IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN UINTN                     Address
+  )
+/*++
+
+Routine Description:
+
+  Add this breakpoint
+
+Arguments:
+
+  DebuggerPrivate - EBC Debugger private data structure
+  Address         - Breakpoint Address
+
+Returns:
+
+  EFI_SUCCESS          - breakpoint added successfully
+  EFI_ALREADY_STARTED  - breakpoint is already added
+  EFI_OUT_OF_RESOURCES - all the breakpoint entries are used
+
+--*/
+{
+  //
+  // Check duplicated breakpoint
+  //
+  if (DebuggerBreakpointIsDuplicated (DebuggerPrivate, Address)) {
+    EDBPrint (L"Breakpoint duplicated!\n");
+    return EFI_ALREADY_STARTED;
+  }
+
+  //
+  // Check whether the address is a breakpoint 3 instruction
+  //
+  if (IsEBCBREAK3 (Address)) {
+    EDBPrint (L"Breakpoint can not be set on BREAK 3 instruction!\n");
+    return EFI_ALREADY_STARTED;
+  }
+
+  if (DebuggerPrivate->DebuggerBreakpointCount >= EFI_DEBUGGER_BREAKPOINT_MAX) {
+    EDBPrint (L"Breakpoint out of resource!\n");
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Set the breakpoint
+  //
+  DebuggerPrivate->DebuggerBreakpointContext[DebuggerPrivate->DebuggerBreakpointCount].BreakpointAddress = Address;
+  DebuggerPrivate->DebuggerBreakpointContext[DebuggerPrivate->DebuggerBreakpointCount].State = TRUE;
+  DebuggerPrivate->DebuggerBreakpointContext[DebuggerPrivate->DebuggerBreakpointCount].OldInstruction = 0;
+  CopyMem (
+    &DebuggerPrivate->DebuggerBreakpointContext[DebuggerPrivate->DebuggerBreakpointCount].OldInstruction,
+    (VOID *)Address,
+    sizeof(UINT16)
+    );
+
+  DebuggerPrivate->DebuggerBreakpointCount ++;
+
+  //
+  // Done
+  //
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+DebuggerBreakpointDel (
+  IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN UINTN                     Index
+  )
+/*++
+
+Routine Description:
+
+  Delete this breakpoint
+
+Arguments:
+
+  DebuggerPrivate - EBC Debugger private data structure
+  Index           - Breakpoint Index
+
+Returns:
+
+  EFI_SUCCESS   - breakpoint deleted successfully
+  EFI_NOT_FOUND - breakpoint not found
+
+--*/
+{
+  UINTN    BpIndex;
+
+  if ((Index >= EFI_DEBUGGER_BREAKPOINT_MAX) ||
+      (Index >= DebuggerPrivate->DebuggerBreakpointCount)) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Delete this breakpoint
+  //
+  for (BpIndex = Index; BpIndex < DebuggerPrivate->DebuggerBreakpointCount - 1; BpIndex++) {
+    DebuggerPrivate->DebuggerBreakpointContext[BpIndex] = DebuggerPrivate->DebuggerBreakpointContext[BpIndex + 1];
+  }
+  ZeroMem (
+    &DebuggerPrivate->DebuggerBreakpointContext[BpIndex],
+    sizeof(DebuggerPrivate->DebuggerBreakpointContext[BpIndex])
+    );
+
+  DebuggerPrivate->DebuggerBreakpointCount --;
+
+  //
+  // Done
+  //
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+DebuggerBreakpointDis (
+  IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN UINTN                     Index
+  )
+/*++
+
+Routine Description:
+
+  Disable this breakpoint
+
+Arguments:
+
+  DebuggerPrivate - EBC Debugger private data structure
+  Index           - Breakpoint Index
+
+Returns:
+
+  EFI_SUCCESS   - breakpoint disabled successfully
+  EFI_NOT_FOUND - breakpoint not found
+
+--*/
+{
+  if ((Index >= EFI_DEBUGGER_BREAKPOINT_MAX) ||
+      (Index >= DebuggerPrivate->DebuggerBreakpointCount)) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Disable this breakpoint
+  //
+  DebuggerPrivate->DebuggerBreakpointContext[Index].State = FALSE;
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+DebuggerBreakpointEn (
+  IN EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN UINTN                     Index
+  )
+/*++
+
+Routine Description:
+
+  Enable this breakpoint
+
+Arguments:
+
+  DebuggerPrivate - EBC Debugger private data structure
+  Index           - Breakpoint Index
+
+Returns:
+
+  EFI_SUCCESS   - breakpoint enabled successfully
+  EFI_NOT_FOUND - breakpoint not found
+
+--*/
+{
+  if ((Index >= EFI_DEBUGGER_BREAKPOINT_MAX) ||
+      (Index >= DebuggerPrivate->DebuggerBreakpointCount)) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Enable this breakpoint
+  //
+  DebuggerPrivate->DebuggerBreakpointContext[Index].State = TRUE;
+
+  return EFI_SUCCESS;
+}
+
+EFI_DEBUG_STATUS
+DebuggerBreakpointList (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - BreakpointList
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  UINTN Index;
+
+  //
+  // Check breakpoint cound
+  //
+  if (DebuggerPrivate->DebuggerBreakpointCount == 0) {
+    EDBPrint (L"No Breakpoint\n");
+    return EFI_DEBUG_CONTINUE;
+  } else if (DebuggerPrivate->DebuggerBreakpointCount > EFI_DEBUGGER_BREAKPOINT_MAX) {
+    EDBPrint (L"Breakpoint too many!\n");
+    DebuggerPrivate->DebuggerBreakpointCount = 0;
+    return EFI_DEBUG_CONTINUE;
+  }
+
+  //
+  // Go through each breakpoint
+  //
+  EDBPrint (L"Breakpoint :\n");
+  EDBPrint (L" Index   Address            Status\n");
+  EDBPrint (L"======= ================== ========\n");
+//EDBPrint (L"   1    0xFFFFFFFF00000000    *\n");
+//EDBPrint (L"  12    0x00000000FFFFFFFF\n");
+  for (Index = 0; Index < DebuggerPrivate->DebuggerBreakpointCount; Index++) {
+    //
+    // Print the breakpoint
+    //
+    EDBPrint (L"  %2d    0x%016lx", Index, DebuggerPrivate->DebuggerBreakpointContext[Index].BreakpointAddress);
+    if (DebuggerPrivate->DebuggerBreakpointContext[Index].State) {
+      EDBPrint (L"    *\n");
+    } else {
+      EDBPrint (L"\n");
+    }
+  }
+
+  //
+  // Done
+  //
+  return EFI_DEBUG_CONTINUE;
+}
+
+EFI_DEBUG_STATUS
+DebuggerBreakpointSet (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - BreakpointSet
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  UINTN      Address;
+  EFI_STATUS Status;
+
+  if (CommandArg == NULL) {
+    EDBPrint (L"BreakpointSet Argument error!\n");
+    return EFI_DEBUG_CONTINUE;
+  }
+
+  //
+  // Get breakpoint address
+  //
+  Status = Symboltoi (CommandArg, &Address);
+  if (EFI_ERROR (Status)) {
+    if (Status == EFI_NOT_FOUND) {
+      Address = Xtoi(CommandArg);
+    } else {
+      //
+      // Something wrong, let Symboltoi print error info.
+      //
+      EDBPrint (L"Command Argument error!\n");
+      return EFI_DEBUG_CONTINUE;
+    }
+  }
+
+  //
+  // Add breakpoint
+  //
+  Status = DebuggerBreakpointAdd (DebuggerPrivate, Address);
+  if (EFI_ERROR(Status)) {
+    EDBPrint (L"BreakpointSet error!\n");
+  }
+
+  //
+  // Done
+  //
+  return EFI_DEBUG_CONTINUE;
+}
+
+EFI_DEBUG_STATUS
+DebuggerBreakpointClear (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - BreakpointClear
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  UINTN      Index;
+  EFI_STATUS Status;
+  UINTN      Address;
+  UINT16     OldInstruction;
+
+  if (CommandArg == NULL) {
+    EDBPrint (L"BreakpointClear Argument error!\n");
+    return EFI_DEBUG_CONTINUE;
+  }
+
+  if (StriCmp (CommandArg, L"*") == 0) {
+    //
+    // delete all breakpoint
+    //
+    DebuggerPrivate->DebuggerBreakpointCount = 0;
+    ZeroMem (DebuggerPrivate->DebuggerBreakpointContext, sizeof(DebuggerPrivate->DebuggerBreakpointContext));
+    EDBPrint (L"All the Breakpoint is cleared\n");
+    return EFI_DEBUG_CONTINUE;
+  }
+
+  //
+  // Get breakpoint index
+  //
+  Index = Atoi(CommandArg);
+
+  if ((Index >= EFI_DEBUGGER_BREAKPOINT_MAX) ||
+      (Index >= DebuggerPrivate->DebuggerBreakpointCount)) {
+    EDBPrint (L"BreakpointClear error!\n");
+    return EFI_DEBUG_CONTINUE;
+  } else {
+    Address = (UINTN)DebuggerPrivate->DebuggerBreakpointContext[Index].BreakpointAddress;
+    OldInstruction = (UINT16)DebuggerPrivate->DebuggerBreakpointContext[Index].OldInstruction;
+  }
+
+  //
+  // Delete breakpoint
+  //
+  Status = DebuggerBreakpointDel (DebuggerPrivate, Index);
+  if (EFI_ERROR(Status)) {
+    EDBPrint (L"BreakpointClear error!\n");
+  }
+
+  //
+  // Done
+  //
+  return EFI_DEBUG_CONTINUE;
+}
+
+EFI_DEBUG_STATUS
+DebuggerBreakpointDisable (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - BreakpointDisable
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  UINTN      Index;
+  EFI_STATUS Status;
+
+  if (CommandArg == NULL) {
+    EDBPrint (L"BreakpointDisable Argument error!\n");
+    return EFI_DEBUG_CONTINUE;
+  }
+
+  if (StriCmp (CommandArg, L"*") == 0) {
+    //
+    // disable all breakpoint
+    //
+    for (Index = 0; Index < DebuggerPrivate->DebuggerBreakpointCount; Index++) {
+      Status = DebuggerBreakpointDis (DebuggerPrivate, Index);
+    }
+    EDBPrint (L"All the Breakpoint is disabled\n");
+    return EFI_DEBUG_CONTINUE;
+  }
+
+  //
+  // Get breakpoint index
+  //
+  Index = Atoi(CommandArg);
+
+  //
+  // Disable breakpoint
+  //
+  Status = DebuggerBreakpointDis (DebuggerPrivate, Index);
+  if (EFI_ERROR(Status)) {
+    EDBPrint (L"BreakpointDisable error!\n");
+  }
+
+  //
+  // Done
+  //
+  return EFI_DEBUG_CONTINUE;
+}
+
+EFI_DEBUG_STATUS
+DebuggerBreakpointEnable (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - BreakpointEnable
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  UINTN      Index;
+  EFI_STATUS Status;
+
+  if (CommandArg == NULL) {
+    EDBPrint (L"BreakpointEnable Argument error!\n");
+    return EFI_DEBUG_CONTINUE;
+  }
+
+  if (StriCmp (CommandArg, L"*") == 0) {
+    //
+    // enable all breakpoint
+    //
+    for (Index = 0; Index < DebuggerPrivate->DebuggerBreakpointCount; Index++) {
+      Status = DebuggerBreakpointEn (DebuggerPrivate, Index);
+    }
+    EDBPrint (L"All the Breakpoint is enabled\n");
+    return EFI_DEBUG_CONTINUE;
+  }
+
+  //
+  // Get breakpoint index
+  //
+  Index = Atoi(CommandArg);
+
+  //
+  // Enable breakpoint
+  //
+  Status = DebuggerBreakpointEn (DebuggerPrivate, Index);
+  if (EFI_ERROR(Status)) {
+    EDBPrint (L"BreakpointEnable error!\n");
+  }
+
+  //
+  // Done
+  //
+  return EFI_DEBUG_CONTINUE;
+}
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdExtIo.c b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdExtIo.c
new file mode 100644
index 000000000000..a21c8f903a86
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdExtIo.c
@@ -0,0 +1,219 @@
+/*++
+
+Copyright (c) 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.
+
+Module Name:
+
+  EdbCmdExtIo.c
+
+Abstract:
+
+
+--*/
+
+#include "Edb.h"
+
+EFI_DEBUG_STATUS
+DebuggerExtIoIB (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - IB
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  EDBPrint (L"Unsupported\n");
+  //
+  // TBD
+  //
+  return EFI_DEBUG_CONTINUE;
+}
+
+EFI_DEBUG_STATUS
+DebuggerExtIoIW (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - IW
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  EDBPrint (L"Unsupported\n");
+  //
+  // TBD
+  //
+  return EFI_DEBUG_CONTINUE;
+}
+
+EFI_DEBUG_STATUS
+DebuggerExtIoID (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - ID
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  EDBPrint (L"Unsupported\n");
+  //
+  // TBD
+  //
+  return EFI_DEBUG_CONTINUE;
+}
+
+EFI_DEBUG_STATUS
+DebuggerExtIoOB (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - OB
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  EDBPrint (L"Unsupported\n");
+  //
+  // TBD
+  //
+  return EFI_DEBUG_CONTINUE;
+}
+
+EFI_DEBUG_STATUS
+DebuggerExtIoOW (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - OW
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  EDBPrint (L"Unsupported\n");
+  //
+  // TBD
+  //
+  return EFI_DEBUG_CONTINUE;
+}
+
+EFI_DEBUG_STATUS
+DebuggerExtIoOD (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - OD
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  EDBPrint (L"Unsupported\n");
+  //
+  // TBD
+  //
+  return EFI_DEBUG_CONTINUE;
+}
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdExtPci.c b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdExtPci.c
new file mode 100644
index 000000000000..6a297987ff9b
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdExtPci.c
@@ -0,0 +1,186 @@
+/*++
+
+Copyright (c) 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.
+
+Module Name:
+
+  EdbCmdExtPci.c
+
+Abstract:
+
+
+--*/
+
+#include "Edb.h"
+
+EFI_DEBUG_STATUS
+DebuggerExtPciPCIL (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - PCIL
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  EDBPrint (L"Unsupported\n");
+  //
+  // TBD
+  //
+  return EFI_DEBUG_CONTINUE;
+}
+
+EFI_DEBUG_STATUS
+DebuggerExtPciPCID (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - PCID
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  EDBPrint (L"Unsupported\n");
+  //
+  // TBD
+  //
+  return EFI_DEBUG_CONTINUE;
+}
+
+EFI_DEBUG_STATUS
+DebuggerExtPciCFGB (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - CFGB
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  EDBPrint (L"Unsupported\n");
+  //
+  // TBD
+  //
+  return EFI_DEBUG_CONTINUE;
+}
+
+EFI_DEBUG_STATUS
+DebuggerExtPciCFGW (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - CFGW
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  EDBPrint (L"Unsupported\n");
+  //
+  // TBD
+  //
+  return EFI_DEBUG_CONTINUE;
+}
+
+EFI_DEBUG_STATUS
+DebuggerExtPciCFGD (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - CFGD
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  EDBPrint (L"Unsupported\n");
+  //
+  // TBD
+  //
+  return EFI_DEBUG_CONTINUE;
+}
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdGo.c b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdGo.c
new file mode 100644
index 000000000000..78ab2a17c34e
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdGo.c
@@ -0,0 +1,93 @@
+/*++
+
+Copyright (c) 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.
+
+Module Name:
+
+  EdbCmdGo.c
+
+Abstract:
+
+
+--*/
+
+#include "Edb.h"
+
+EFI_DEBUG_STATUS
+DebuggerGo (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - Go
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_BREAK    - formal return value
+  EFI_DEBUG_CONTINUE - something wrong
+
+--*/
+{
+  UINTN        Address;
+  CHAR16       *CommandStr;
+  EFI_STATUS   Status;
+
+  //
+  // Check argument
+  //
+  if (CommandArg != NULL) {
+    if (StriCmp (CommandArg, L"til") == 0) {
+      CommandStr = StrGetNextTokenLine (L" ");
+      if (CommandStr != NULL) {
+        //
+        // Enable GoTil break now
+        // set BreakAddress, and set feature flag.
+        //
+        Status = Symboltoi (CommandStr, &Address);
+        if (EFI_ERROR (Status)) {
+          if (Status == EFI_NOT_FOUND) {
+            Address = Xtoi(CommandStr);
+          } else {
+            //
+            // Something wrong, let Symboltoi print error info.
+            //
+            EDBPrint (L"Command Argument error!\n");
+            return EFI_DEBUG_CONTINUE;
+          }
+        }
+        DebuggerPrivate->GoTilContext.BreakAddress = Address;
+        DebuggerPrivate->FeatureFlags |= EFI_DEBUG_FLAG_EBC_GT;
+      } else {
+        EDBPrint (L"Command Argument error!\n");
+        return EFI_DEBUG_CONTINUE;
+      }
+    } else {
+      EDBPrint (L"Command Argument error!\n");
+      return EFI_DEBUG_CONTINUE;
+    }
+  }
+
+  //
+  // Done
+  //
+  return EFI_DEBUG_BREAK;
+}
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdHelp.c b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdHelp.c
new file mode 100644
index 000000000000..037a08f27a68
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdHelp.c
@@ -0,0 +1,86 @@
+/*++
+
+Copyright (c) 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.
+
+Module Name:
+
+  EdbCmdHelp.c
+
+Abstract:
+
+
+--*/
+
+#include "Edb.h"
+
+EFI_DEBUG_STATUS
+DebuggerHelp (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - Help
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  UINTN Index;
+
+  //
+  // if no argument, print all the command title
+  //
+  if (CommandArg == NULL) {
+    for (Index = 0; DebuggerPrivate->DebuggerCommandSet[Index].CommandName != NULL; Index++) {
+      EDBPrint (DebuggerPrivate->DebuggerCommandSet[Index].ClassName);
+      if (StrCmp (DebuggerPrivate->DebuggerCommandSet[Index].CommandTitle, L"") != 0) {
+        EDBPrint (L"  ");
+        EDBPrint (DebuggerPrivate->DebuggerCommandSet[Index].CommandTitle);
+      }
+    }
+    return EFI_DEBUG_CONTINUE;
+  }
+
+  //
+  // If there is argument, the argument should be command name.
+  // Find the command and print the detail information.
+  //
+  for (Index = 0; DebuggerPrivate->DebuggerCommandSet[Index].CommandName != NULL; Index++) {
+    if (StriCmp (CommandArg, DebuggerPrivate->DebuggerCommandSet[Index].CommandName) == 0) {
+      EDBPrint (DebuggerPrivate->DebuggerCommandSet[Index].CommandHelp);
+      EDBPrint (DebuggerPrivate->DebuggerCommandSet[Index].CommandSyntax);
+      return EFI_DEBUG_CONTINUE;
+    }
+  }
+
+  //
+  // Command not found.
+  //
+  EDBPrint (L"No help info for this command\n");
+
+  //
+  // Done
+  //
+  return EFI_DEBUG_CONTINUE;
+}
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdMemory.c b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdMemory.c
new file mode 100644
index 000000000000..8858e40fb5fa
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdMemory.c
@@ -0,0 +1,683 @@
+/*++
+
+Copyright (c) 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.
+
+Module Name:
+
+  EdbCmdMemory.c
+
+Abstract:
+
+
+--*/
+
+#include "Edb.h"
+
+UINTN
+EdbDisplayMemoryUnit (
+  IN UINTN           Address,
+  IN EDB_DATA_WIDTH  Width
+  )
+/*++
+
+Routine Description:
+
+  Display memory unit
+
+Arguments:
+
+  Address         - Memory Address
+  Width           - Memory Width
+
+Returns:
+
+  Length of the memory unit
+
+--*/
+{
+  UINT8  Data8;
+  UINT16 Data16;
+  UINT32 Data32;
+  UINT64 Data64;
+
+  //
+  // Print accroding to width
+  //
+  switch (Width) {
+  case EdbWidthUint8:
+    CopyMem (&Data8, (VOID *)Address, sizeof(UINT8));
+    EDBPrint (L"%02x ", Data8);
+    return sizeof(UINT8);
+  case EdbWidthUint16:
+    CopyMem (&Data16, (VOID *)Address, sizeof(UINT16));
+    EDBPrint (L"%04x ", Data16);
+    return sizeof(UINT16);
+  case EdbWidthUint32:
+    CopyMem (&Data32, (VOID *)Address, sizeof(UINT32));
+    EDBPrint (L"%08x ", Data32);
+    return sizeof(UINT32);
+  case EdbWidthUint64:
+    CopyMem (&Data64, (VOID *)Address, sizeof(UINT64));
+    EDBPrint (L"%016lx ", Data64);
+    return sizeof(UINT64);
+  default:
+    ASSERT (FALSE);
+    break;
+  }
+
+  //
+  // something wrong
+  //
+  return 0;
+}
+
+VOID
+EdbDisplayMemory (
+  IN UINTN          Address,
+  IN UINTN          Count,
+  IN EDB_DATA_WIDTH Width
+  )
+/*++
+
+Routine Description:
+
+  Display memory
+
+Arguments:
+
+  Address         - Memory Address
+  Count           - Memory Count
+  Width           - Memory Width
+
+Returns:
+
+  None
+
+--*/
+{
+  UINTN  LineNumber;
+  UINTN  ByteNumber;
+  UINTN  LineIndex;
+  UINTN  ByteIndex;
+  UINTN  NumberInLine;
+
+  if (Count == 0) {
+    return ;
+  }
+
+  //
+  // Get line number and byte number
+  //
+  switch (Width) {
+  case EdbWidthUint8:
+    NumberInLine = 16;
+    break;
+  case EdbWidthUint16:
+    NumberInLine = 8;
+    break;
+  case EdbWidthUint32:
+    NumberInLine = 4;
+    break;
+  case EdbWidthUint64:
+    NumberInLine = 2;
+    break;
+  default:
+    return;
+  }
+
+  LineNumber = Count / NumberInLine;
+  ByteNumber = Count % NumberInLine;
+  if (ByteNumber == 0) {
+    LineNumber -= 1;
+    ByteNumber  = NumberInLine;
+  }
+
+  //
+  // Print each line
+  //
+  for (LineIndex = 0; LineIndex < LineNumber; LineIndex++) {
+
+    //
+    // Break check
+    //
+    if (((LineIndex % EFI_DEBUGGER_LINE_NUMBER_IN_PAGE) == 0) &&
+        (LineIndex != 0)) {
+      if (SetPageBreak ()) {
+        break;
+      }
+    }
+
+    EDBPrint (EDB_PRINT_ADDRESS_FORMAT, (UINTN)Address);
+    for (ByteIndex = 0; ByteIndex < NumberInLine; ByteIndex++) {
+      Address += EdbDisplayMemoryUnit (Address, Width);
+    }
+    EDBPrint (L"\n");
+  }
+
+  //
+  // Break check
+  //
+  if (((LineIndex % EFI_DEBUGGER_LINE_NUMBER_IN_PAGE) == 0) &&
+      (LineIndex != 0)) {
+    if (SetPageBreak ()) {
+      return;
+    }
+  }
+
+  //
+  // Print last line
+  //
+  EDBPrint (EDB_PRINT_ADDRESS_FORMAT, (UINTN)Address);
+  for (ByteIndex = 0; ByteIndex < ByteNumber; ByteIndex++) {
+    Address += EdbDisplayMemoryUnit (Address, Width);
+  }
+
+  return ;
+}
+
+VOID
+EdbEnterMemory (
+  IN UINTN          Address,
+  IN VOID           *Value,
+  IN EDB_DATA_WIDTH Width
+  )
+/*++
+
+Routine Description:
+
+  Entry memory
+
+Arguments:
+
+  Address         - Memory Address
+  Value           - Memory Value
+  Width           - Memory Width
+
+Returns:
+
+  None
+
+--*/
+{
+  switch (Width) {
+  case EdbWidthUint8:
+    CopyMem ((VOID *)Address, Value, sizeof(UINT8));
+    break;
+  case EdbWidthUint16:
+    CopyMem ((VOID *)Address, Value, sizeof(UINT16));
+    break;
+  case EdbWidthUint32:
+    CopyMem ((VOID *)Address, Value, sizeof(UINT32));
+    break;
+  case EdbWidthUint64:
+    CopyMem ((VOID *)Address, Value, sizeof(UINT64));
+    break;
+  default:
+    break;
+  }
+
+  return ;
+}
+
+EFI_STATUS
+EdbGetMemoryAddressCount (
+  IN CHAR16    *CommandArg,
+  IN UINTN     *Address,
+  IN UINTN     *Count
+  )
+/*++
+
+Routine Description:
+
+  Get memory address and count
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  Address         - Memory Address
+  Count           - Memory Count
+
+Returns:
+
+  EFI_SUCCESS           - memory address and count are got
+  EFI_INVALID_PARAMETER - something wrong
+
+--*/
+{
+  CHAR16       *CommandStr;
+  UINTN        MemAddress;
+  EFI_STATUS   Status;
+
+  //
+  // Get Address
+  //
+  CommandStr = CommandArg;
+  if (CommandStr == NULL) {
+    EDBPrint (L"Memory: Address error!\n");
+    return EFI_INVALID_PARAMETER;
+  }
+  Status = Symboltoi (CommandStr, &MemAddress);
+  if (EFI_ERROR (Status)) {
+    if (Status == EFI_NOT_FOUND) {
+      MemAddress = Xtoi(CommandStr);
+    } else {
+      //
+      // Something wrong, let Symboltoi print error info.
+      //
+      EDBPrint (L"Command Argument error!\n");
+      return EFI_INVALID_PARAMETER;
+    }
+  }
+  *Address = MemAddress;
+
+  //
+  // Get Count
+  //
+  CommandStr = StrGetNextTokenLine (L" ");
+  if (CommandStr == NULL) {
+    *Count = 1;
+  } else {
+    *Count = Xtoi(CommandStr);
+  }
+
+  //
+  // Done
+  //
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EdbGetMemoryAddressValue (
+  IN CHAR16    *CommandArg,
+  IN UINTN     *Address,
+  IN UINT64    *Value
+  )
+/*++
+
+Routine Description:
+
+  Get memory address and value
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  Address         - Memory Address
+  Value           - Memory Value
+
+Returns:
+
+  EFI_SUCCESS           - memory address and value are got
+  EFI_INVALID_PARAMETER - something wrong
+
+--*/
+{
+  CHAR16       *CommandStr;
+  UINTN        MemAddress;
+  EFI_STATUS   Status;
+
+  //
+  // Get Address
+  //
+  CommandStr = CommandArg;
+  if (CommandStr == NULL) {
+    EDBPrint (L"Memory: Address error!\n");
+    return EFI_INVALID_PARAMETER;
+  }
+  Status = Symboltoi (CommandStr, &MemAddress);
+  if (EFI_ERROR (Status)) {
+    if (Status == EFI_NOT_FOUND) {
+      MemAddress = Xtoi(CommandStr);
+    } else {
+      //
+      // Something wrong, let Symboltoi print error info.
+      //
+      EDBPrint (L"Command Argument error!\n");
+      return EFI_INVALID_PARAMETER;
+    }
+  }
+  *Address = MemAddress;
+
+  //
+  // Get Value
+  //
+  CommandStr = StrGetNextTokenLine (L" ");
+  if (CommandStr == NULL) {
+    EDBPrint (L"Memory: Value error!\n");
+    return EFI_INVALID_PARAMETER;
+  }
+  *Value = LXtoi(CommandStr);
+
+  //
+  // Done
+  //
+  return EFI_SUCCESS;
+}
+
+EFI_DEBUG_STATUS
+DebuggerMemoryDisplay (
+  IN     CHAR16                    *CommandArg,
+  IN     EDB_DATA_WIDTH            Width
+  )
+/*++
+
+Routine Description:
+
+  Display memory
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  Width           - Memory Width
+
+Returns:
+
+  EFI_DEBUG_RETURN   - formal return value
+
+--*/
+{
+  EFI_STATUS Status;
+  UINTN      Address;
+  UINTN      Count;
+
+  //
+  // Get memory address and count
+  //
+  Status = EdbGetMemoryAddressCount (CommandArg, &Address, &Count);
+  if (EFI_ERROR(Status)) {
+    return EFI_DEBUG_CONTINUE;
+  }
+
+  //
+  // Display memory
+  //
+  EdbDisplayMemory (Address, Count, Width);
+
+  //
+  // Done
+  //
+  return EFI_DEBUG_CONTINUE;
+}
+
+EFI_DEBUG_STATUS
+DebuggerMemoryEnter (
+  IN     CHAR16                    *CommandArg,
+  IN     EDB_DATA_WIDTH            Width
+  )
+/*++
+
+Routine Description:
+
+  Enter memory
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  Width           - Memory Width
+
+Returns:
+
+  EFI_DEBUG_RETURN   - formal return value
+
+--*/
+{
+  EFI_STATUS Status;
+  UINTN      Address;
+  UINT64     Value;
+
+  //
+  // Get memory address and value
+  //
+  Status = EdbGetMemoryAddressValue (CommandArg, &Address, &Value);
+  if (EFI_ERROR(Status)) {
+    return EFI_DEBUG_CONTINUE;
+  }
+
+  //
+  // Enter memory
+  //
+  EdbEnterMemory (Address, &Value, Width);
+
+  //
+  // Done
+  //
+  return EFI_DEBUG_CONTINUE;
+}
+
+EFI_DEBUG_STATUS
+DebuggerMemoryDB (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - DB
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_RETURN   - formal return value
+
+--*/
+{
+  return DebuggerMemoryDisplay (CommandArg, EdbWidthUint8);
+}
+
+EFI_DEBUG_STATUS
+DebuggerMemoryDW (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - DW
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_RETURN   - formal return value
+
+--*/
+{
+  return DebuggerMemoryDisplay (CommandArg, EdbWidthUint16);
+}
+
+EFI_DEBUG_STATUS
+DebuggerMemoryDD (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - DD
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_RETURN   - formal return value
+
+--*/
+{
+  return DebuggerMemoryDisplay (CommandArg, EdbWidthUint32);
+}
+
+EFI_DEBUG_STATUS
+DebuggerMemoryDQ (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - DQ
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_RETURN   - formal return value
+
+--*/
+{
+  return DebuggerMemoryDisplay (CommandArg, EdbWidthUint64);
+}
+
+EFI_DEBUG_STATUS
+DebuggerMemoryEB (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - EB
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_RETURN   - formal return value
+
+--*/
+{
+  return DebuggerMemoryEnter (CommandArg, EdbWidthUint8);
+}
+
+EFI_DEBUG_STATUS
+DebuggerMemoryEW (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - EW
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_RETURN   - formal return value
+
+--*/
+{
+  return DebuggerMemoryEnter (CommandArg, EdbWidthUint16);
+}
+
+EFI_DEBUG_STATUS
+DebuggerMemoryED (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - ED
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_RETURN   - formal return value
+
+--*/
+{
+  return DebuggerMemoryEnter (CommandArg, EdbWidthUint32);
+}
+
+EFI_DEBUG_STATUS
+DebuggerMemoryEQ (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - EQ
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_RETURN   - formal return value
+
+--*/
+{
+  return DebuggerMemoryEnter (CommandArg, EdbWidthUint64);
+}
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdQuit.c b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdQuit.c
new file mode 100644
index 000000000000..a53c675bb2cb
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdQuit.c
@@ -0,0 +1,50 @@
+/*++
+
+Copyright (c) 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.
+
+Module Name:
+
+  EdbCmdQuit.c
+
+Abstract:
+
+
+--*/
+
+#include "Edb.h"
+
+EFI_DEBUG_STATUS
+DebuggerQuit (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - Quit
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_RETURN   - formal return value
+
+--*/
+{
+  return EFI_DEBUG_RETURN;
+}
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdRegister.c b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdRegister.c
new file mode 100644
index 000000000000..480163c9b846
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdRegister.c
@@ -0,0 +1,136 @@
+/*++
+
+Copyright (c) 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.
+
+Module Name:
+
+  EdbCmdRegister.c
+
+Abstract:
+
+
+--*/
+
+#include "Edb.h"
+
+EFI_DEBUG_STATUS
+DebuggerRegister (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - Register
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  CHAR16  *RegName;
+  CHAR16  *RegValStr;
+  UINT64  RegVal;
+
+  //
+  // Check Argument, NULL means print all register
+  //
+  if (CommandArg == 0) {
+    EDBPrint (
+      L"  R0 - 0x%016lx, R1 - 0x%016lx\n",
+      SystemContext.SystemContextEbc->R0,
+      SystemContext.SystemContextEbc->R1
+      );
+    EDBPrint (
+      L"  R2 - 0x%016lx, R3 - 0x%016lx\n",
+      SystemContext.SystemContextEbc->R2,
+      SystemContext.SystemContextEbc->R3
+      );
+    EDBPrint (
+      L"  R4 - 0x%016lx, R5 - 0x%016lx\n",
+      SystemContext.SystemContextEbc->R4,
+      SystemContext.SystemContextEbc->R5
+      );
+    EDBPrint (
+      L"  R6 - 0x%016lx, R7 - 0x%016lx\n",
+      SystemContext.SystemContextEbc->R6,
+      SystemContext.SystemContextEbc->R7
+      );
+    EDBPrint (
+      L"  Flags - 0x%016lx, ControlFlags - 0x%016lx\n",
+      SystemContext.SystemContextEbc->Flags,
+      SystemContext.SystemContextEbc->ControlFlags
+      );
+    EDBPrint (
+      L"  Ip - 0x%016lx\n",
+      SystemContext.SystemContextEbc->Ip
+      );
+    return EFI_DEBUG_CONTINUE;
+  }
+
+  //
+  // Get register name
+  //
+  RegName = CommandArg;
+  //
+  // Get register value
+  //
+  RegValStr = StrGetNextTokenLine (L" ");
+  if (RegValStr == NULL) {
+    EDBPrint (L"Invalid Register Value\n");
+    return EFI_DEBUG_CONTINUE;
+  }
+  RegVal = LXtoi (RegValStr);
+
+  //
+  // Assign register value
+  //
+  if (StriCmp (RegName, L"R0") == 0) {
+    SystemContext.SystemContextEbc->R0 = RegVal;
+  } else if (StriCmp (RegName, L"R1") == 0) {
+    SystemContext.SystemContextEbc->R1 = RegVal;
+  } else if (StriCmp (RegName, L"R2") == 0) {
+    SystemContext.SystemContextEbc->R2 = RegVal;
+  } else if (StriCmp (RegName, L"R3") == 0) {
+    SystemContext.SystemContextEbc->R3 = RegVal;
+  } else if (StriCmp (RegName, L"R4") == 0) {
+    SystemContext.SystemContextEbc->R4 = RegVal;
+  } else if (StriCmp (RegName, L"R5") == 0) {
+    SystemContext.SystemContextEbc->R5 = RegVal;
+  } else if (StriCmp (RegName, L"R6") == 0) {
+    SystemContext.SystemContextEbc->R6 = RegVal;
+  } else if (StriCmp (RegName, L"R7") == 0) {
+    SystemContext.SystemContextEbc->R7 = RegVal;
+  } else if (StriCmp (RegName, L"Flags") == 0) {
+    SystemContext.SystemContextEbc->Flags = RegVal;
+  } else if (StriCmp (RegName, L"ControlFlags") == 0) {
+    SystemContext.SystemContextEbc->ControlFlags = RegVal;
+  } else if (StriCmp (RegName, L"Ip") == 0) {
+    SystemContext.SystemContextEbc->Ip = RegVal;
+  } else {
+    EDBPrint (L"Invalid Register - %s\n", RegName);
+  }
+
+  //
+  // Done
+  //
+  return EFI_DEBUG_CONTINUE;
+}
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdScope.c b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdScope.c
new file mode 100644
index 000000000000..6f29e0b1bbd0
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdScope.c
@@ -0,0 +1,123 @@
+/*++
+
+Copyright (c) 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.
+
+Module Name:
+
+  EdbCmdScope.c
+
+Abstract:
+
+
+--*/
+
+#include "Edb.h"
+
+EFI_DEBUG_STATUS
+DebuggerScope (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - Scope
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  EFI_STATUS   Status;
+  UINTN        Address;
+
+  if (CommandArg == NULL) {
+    EDBPrint (L"Scope: invalid Address\n");
+    return EFI_DEBUG_CONTINUE;
+  }
+
+  //
+  // Load new scope
+  //
+  Status = Symboltoi (CommandArg, &Address);
+  if (EFI_ERROR (Status)) {
+    if (Status == EFI_NOT_FOUND) {
+      Address = Xtoi(CommandArg);
+    } else {
+      //
+      // Something wrong, let Symboltoi print error info.
+      //
+      EDBPrint (L"Command Argument error!\n");
+      return EFI_DEBUG_CONTINUE;
+    }
+  }
+  DebuggerPrivate->InstructionScope = Address;
+  EDBPrint (L"Scope: 0x%x\n", DebuggerPrivate->InstructionScope);
+  EdbShowDisasm (DebuggerPrivate, SystemContext);
+
+  //
+  // Done
+  //
+  return EFI_DEBUG_CONTINUE;
+}
+
+EFI_DEBUG_STATUS
+DebuggerList (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - List
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  if (CommandArg == NULL) {
+    EdbShowDisasm (DebuggerPrivate, SystemContext);
+  } else {
+    //
+    // Load new list number
+    //
+    DebuggerPrivate->InstructionNumber = Atoi(CommandArg);
+    EDBPrint (L"List Number: %d\n", DebuggerPrivate->InstructionNumber);
+    EdbShowDisasm (DebuggerPrivate, SystemContext);
+  }
+
+  //
+  // Done
+  //
+  return EFI_DEBUG_CONTINUE;
+}
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdStep.c b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdStep.c
new file mode 100644
index 000000000000..f5d461218750
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdStep.c
@@ -0,0 +1,198 @@
+/*++
+
+Copyright (c) 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.
+
+Module Name:
+
+  EdbCmdStep.c
+
+Abstract:
+
+
+--*/
+
+#include "Edb.h"
+
+BOOLEAN
+IsEBCCALL (
+  IN UINTN            Address
+  )
+/*++
+
+Routine Description:
+
+  Check whether current IP is EBC CALL instruction (NOTE: CALLEX is exclusive)
+
+Arguments:
+
+  Address   - EBC IP address.
+
+Returns:
+
+  TRUE  - Current IP is EBC CALL instruction
+  FALSE - Current IP is not EBC CALL instruction
+
+--*/
+{
+  if (GET_OPCODE(Address) != OPCODE_CALL) {
+    return FALSE;
+  }
+
+  if (GET_OPERANDS (Address) & OPERAND_M_NATIVE_CALL) {
+    return FALSE;
+  } else {
+    return TRUE;
+  }
+}
+
+BOOLEAN
+IsEBCRET (
+  IN UINTN            Address
+  )
+/*++
+
+Routine Description:
+
+  Check whether current IP is EBC RET instruction
+
+Arguments:
+
+  Address   - EBC IP address.
+
+Returns:
+
+  TRUE  - Current IP is EBC RET instruction
+  FALSE - Current IP is not EBC RET instruction
+
+--*/
+{
+  if (GET_OPCODE(Address) != OPCODE_RET) {
+    return FALSE;
+  }
+
+  if (GET_OPERANDS (Address) != 0) {
+    return FALSE;
+  } else {
+    return TRUE;
+  }
+}
+
+EFI_DEBUG_STATUS
+DebuggerStepInto (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - StepInto
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  SystemContext.SystemContextEbc->Flags |= VMFLAGS_STEP;
+
+  return EFI_DEBUG_BREAK;
+}
+
+EFI_DEBUG_STATUS
+DebuggerStepOver (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - StepOver
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  if (IsEBCCALL((UINTN)SystemContext.SystemContextEbc->Ip)) {
+    //
+    // Check CALL (NOTE: CALLEX is exclusive)
+    //
+    DebuggerPrivate->FeatureFlags |= EFI_DEBUG_FLAG_EBC_STEPOVER;
+  } else {
+    //
+    // Other instruction including CALLEX
+    //
+    SystemContext.SystemContextEbc->Flags |= VMFLAGS_STEP;
+  }
+
+  return EFI_DEBUG_BREAK;
+}
+
+EFI_DEBUG_STATUS
+DebuggerStepOut (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - StepOut
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  if (IsEBCRET((UINTN)SystemContext.SystemContextEbc->Ip)) {
+    //
+    // Check RET
+    //
+    SystemContext.SystemContextEbc->Flags |= VMFLAGS_STEP;
+  } else {
+    //
+    // Other instruction
+    //
+    DebuggerPrivate->FeatureFlags |= EFI_DEBUG_FLAG_EBC_STEPOUT;
+  }
+
+  return EFI_DEBUG_BREAK;
+}
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdSymbol.c b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdSymbol.c
new file mode 100644
index 000000000000..d9dc99cd9a27
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCmdSymbol.c
@@ -0,0 +1,952 @@
+/*++
+
+Copyright (c) 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.
+
+Module Name:
+
+  EdbCmdSymbol.c
+
+Abstract:
+
+
+--*/
+
+#include "Edb.h"
+
+CHAR16 *
+GetFileNameFromFullPath (
+  IN CHAR16   *FullPath
+  )
+/*++
+
+Routine Description:
+
+  Get file name from full path
+
+Arguments:
+
+  FullPath        - full file path
+
+Returns:
+
+  file name
+
+--*/
+{
+  CHAR16   *FileName;
+  CHAR16   *TempFileName;
+
+  FileName = FullPath;
+  TempFileName = StrGetNewTokenLine (FullPath, L"\\");
+
+  while (TempFileName != NULL) {
+    FileName = TempFileName;
+    TempFileName = StrGetNextTokenLine (L"\\");
+    PatchForStrTokenBefore (TempFileName, L'\\');
+  }
+
+  return FileName;
+}
+
+CHAR16 *
+GetDirNameFromFullPath (
+  IN CHAR16   *FullPath
+  )
+/*++
+
+Routine Description:
+
+  Get dir name from full path
+
+Arguments:
+
+  FullPath        - full file path
+
+Returns:
+
+  dir name
+
+--*/
+{
+  CHAR16   *FileName;
+
+  FileName = GetFileNameFromFullPath (FullPath);
+  if (FileName != FullPath) {
+    *(FileName - 1) = 0;
+    return FullPath;
+  }
+
+  return L"";
+}
+
+CHAR16 *
+ConstructFullPath (
+  IN CHAR16   *DirPath,
+  IN CHAR16   *FilePath,
+  IN UINTN    Size
+  )
+/*++
+
+Routine Description:
+
+  Construct full path accroding to dir and file path
+
+Arguments:
+
+  DirPath         - dir path
+  FilePath        - file path
+  Size            - dir max size
+
+Returns:
+
+  Full file name
+
+--*/
+{
+  UINTN DirPathSize;
+
+  DirPathSize = StrLen(DirPath);
+  *(DirPath + DirPathSize) = L'\\';
+  StrnCatS (DirPath, DirPathSize + Size + 1, FilePath, Size);
+
+  *(DirPath + DirPathSize + Size + 1) = 0;
+
+  return DirPath;
+}
+
+CHAR16 *mSymbolTypeStr[] = {
+  L"( F)",
+  L"(SF)",
+  L"(GV)",
+  L"(SV)",
+};
+
+CHAR16 *
+EdbSymbolTypeToStr (
+  IN EFI_DEBUGGER_SYMBOL_TYPE  Type
+  )
+/*++
+
+Routine Description:
+
+  Comvert Symbol Type to string
+
+Arguments:
+
+  Type            - Symbol Type
+
+Returns:
+
+  String
+
+--*/
+{
+  if (Type < 0 || Type >= EfiDebuggerSymbolTypeMax) {
+    return L"(?)";
+  }
+
+  return mSymbolTypeStr [Type];
+}
+
+EFI_DEBUG_STATUS
+DebuggerDisplaySymbolAccrodingToAddress (
+  IN     UINTN                      Address,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate
+  )
+/*++
+
+Routine Description:
+
+  Find the symbol accroding to address and display symbol
+
+Arguments:
+
+  Address         - SymbolAddress
+  DebuggerPrivate - EBC Debugger private data structure
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  EFI_DEBUGGER_SYMBOL_OBJECT *Object;
+  EFI_DEBUGGER_SYMBOL_ENTRY  *Entry;
+  UINTN                      CandidateAddress;
+
+  //
+  // Find the nearest symbol address
+  //
+  CandidateAddress = EbdFindSymbolAddress (Address, EdbMatchSymbolTypeNearestAddress, &Object, &Entry);
+  if (CandidateAddress == 0) {
+    EDBPrint (L"Symbole at Address not found!\n");
+    return EFI_DEBUG_CONTINUE;
+  } else if (Address != CandidateAddress) {
+    EDBPrint (L"Symbole at Address not found, print nearest one!\n");
+  }
+
+  //
+  // Display symbol
+  //
+  EDBPrint (L"Symbol File Name: %s\n", Object->Name);
+  if (sizeof(UINTN) == sizeof(UINT64)) {
+    EDBPrint (L"        Address      Type  Symbol\n");
+    EDBPrint (L"  ================== ==== ========\n");
+//  EDBPrint (L"  0xFFFFFFFF00000000 ( F) TestMain\n");
+    EDBPrint (
+      L"  0x%016lx %s %a\n",
+      (UINT64)Entry->RVA + Object->BaseAddress,
+      EdbSymbolTypeToStr (Entry->Type),
+      Entry->Name
+      );
+  } else {
+    EDBPrint (L"   Address   Type  Symbol\n");
+    EDBPrint (L"  ========== ==== ========\n");
+//  EDBPrint (L"  0xFFFF0000 ( F) TestMain\n");
+    EDBPrint (
+      L"  0x%08x %s %a\n",
+      Entry->RVA + Object->BaseAddress,
+      EdbSymbolTypeToStr (Entry->Type),
+      Entry->Name
+      );
+  }
+
+  //
+  // Done
+  //
+  return EFI_DEBUG_CONTINUE;
+}
+
+EFI_DEBUG_STATUS
+DebuggerDisplaySymbolAccrodingToName (
+  IN     CHAR16                     *SymbolFileName,
+  IN     CHAR16                     *SymbolName,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate
+  )
+/*++
+
+Routine Description:
+
+  Find the symbol accroding to name and display symbol
+
+Arguments:
+
+  SymbolFileName  - The Symbol File Name, NULL means for all
+  SymbolName      - The Symbol Name, NULL means for all
+  DebuggerPrivate - EBC Debugger private data structure
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  UINTN                      Index;
+  UINTN                      SubIndex;
+  EFI_DEBUGGER_SYMBOL_OBJECT *Object;
+  EFI_DEBUGGER_SYMBOL_ENTRY  *Entry;
+
+  if (DebuggerPrivate->DebuggerSymbolContext.ObjectCount == 0) {
+    EDBPrint (L"No Symbol File!\n");
+    return EFI_DEBUG_CONTINUE;
+  }
+
+  //
+  // Go throuth each symbol file
+  //
+  Object = DebuggerPrivate->DebuggerSymbolContext.Object;
+  for (Index = 0; Index < DebuggerPrivate->DebuggerSymbolContext.ObjectCount; Index++, Object++) {
+    if ((SymbolFileName != NULL) &&
+        (StriCmp (SymbolFileName, Object->Name) != 0)) {
+      continue;
+    }
+
+    //
+    // Break each symbol file
+    //
+    if (Index != 0) {
+      if (SetPageBreak ()) {
+        break;
+      }
+    }
+
+    EDBPrint (L"Symbol File Name: %s\n", Object->Name);
+    if (Object->EntryCount == 0) {
+      EDBPrint (L"No Symbol!\n");
+      continue;
+    }
+    Entry = Object->Entry;
+    if (sizeof(UINTN) == sizeof(UINT64)) {
+      EDBPrint (L"        Address      Type  Symbol\n");
+      EDBPrint (L"  ================== ==== ========\n");
+//    EDBPrint (L"  0xFFFFFFFF00000000 ( F) TestMain (EbcTest.obj)\n");
+    } else {
+      EDBPrint (L"   Address   Type  Symbol\n");
+      EDBPrint (L"  ========== ==== ========\n");
+//    EDBPrint (L"  0xFFFF0000 ( F) TestMain (EbcTest.obj)\n");
+    }
+
+    //
+    // Go through each symbol name
+    //
+    for (SubIndex = 0; SubIndex < Object->EntryCount; SubIndex++, Entry++) {
+      if ((SymbolName != NULL) &&
+          (StrCmpUnicodeAndAscii (SymbolName, Entry->Name) != 0)) {
+        continue;
+      }
+
+      //
+      // Break symbol
+      //
+      if (((SubIndex % EFI_DEBUGGER_LINE_NUMBER_IN_PAGE) == 0) &&
+          (SubIndex != 0)) {
+        if (SetPageBreak ()) {
+          break;
+        }
+      }
+
+      if (sizeof(UINTN) == sizeof(UINT64)) {
+        EDBPrint (
+          L"  0x%016lx %s %a (%a)\n",
+          (UINT64)Entry->RVA + Object->BaseAddress,
+          EdbSymbolTypeToStr (Entry->Type),
+          Entry->Name,
+          Entry->ObjName
+          );
+      } else {
+        EDBPrint (
+          L"  0x%08x %s %a (%a)\n",
+          Entry->RVA + Object->BaseAddress,
+          EdbSymbolTypeToStr (Entry->Type),
+          Entry->Name,
+          Entry->ObjName
+          );
+      }
+    }
+  }
+
+  //
+  // Done
+  //
+  return EFI_DEBUG_CONTINUE;
+}
+
+EFI_DEBUG_STATUS
+DebuggerListSymbol (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - ListSymbol
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  CHAR16                     *SymbolFileName;
+  CHAR16                     *SymbolName;
+  CHAR16                     *CommandStr;
+  UINTN                      Address;
+
+  SymbolFileName = NULL;
+  SymbolName = NULL;
+  CommandStr = CommandArg;
+
+  //
+  // display symbol according to address
+  //
+  if (CommandStr != NULL) {
+    if ((StriCmp (CommandStr, L"F") != 0) &&
+        (StriCmp (CommandStr, L"S") != 0)) {
+      Address = Xtoi (CommandStr);
+      return DebuggerDisplaySymbolAccrodingToAddress (Address, DebuggerPrivate);
+    }
+  }
+
+  //
+  // Get SymbolFileName
+  //
+  if (CommandStr != NULL) {
+    if (StriCmp (CommandStr, L"F") == 0) {
+      CommandStr = StrGetNextTokenLine (L" ");
+      if (CommandStr == NULL) {
+        EDBPrint (L"Symbol File Name missing!\n");
+        return EFI_DEBUG_CONTINUE;
+      } else {
+        SymbolFileName = CommandStr;
+        CommandStr = StrGetNextTokenLine (L" ");
+      }
+    }
+  }
+  //
+  // Get SymbolName
+  //
+  if (CommandStr != NULL) {
+    if (StriCmp (CommandStr, L"S") == 0) {
+      CommandStr = StrGetNextTokenLine (L" ");
+      if (CommandStr == NULL) {
+        EDBPrint (L"Symbol Name missing!\n");
+        return EFI_DEBUG_CONTINUE;
+      } else {
+        SymbolName = CommandStr;
+        CommandStr = StrGetNextTokenLine (L" ");
+      }
+    }
+  }
+  if (CommandStr != NULL) {
+    EDBPrint (L"Argument error!\n");
+    return EFI_DEBUG_CONTINUE;
+  }
+
+  //
+  // display symbol according to name
+  //
+  return DebuggerDisplaySymbolAccrodingToName (SymbolFileName, SymbolName, DebuggerPrivate);
+}
+
+EFI_DEBUG_STATUS
+DebuggerLoadSymbol (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - LoadSymbol
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  UINTN      BufferSize;
+  VOID       *Buffer;
+  EFI_STATUS Status;
+  CHAR16     *FileName;
+  CHAR16     *CommandArg2;
+  BOOLEAN    IsLoadCode;
+  CHAR16     *DirName;
+  CHAR16     CodFile[EFI_DEBUGGER_SYMBOL_NAME_MAX];
+  CHAR16     *CodFileName;
+  UINTN      Index;
+
+  //
+  // Check the argument
+  //
+  if (CommandArg == NULL) {
+    EDBPrint (L"SymbolFile not found!\n");
+    return EFI_DEBUG_CONTINUE;
+  }
+  IsLoadCode = FALSE;
+  CommandArg2 = StrGetNextTokenLine (L" ");
+  if (CommandArg2 != NULL) {
+    if (StriCmp (CommandArg2, L"a") == 0) {
+      IsLoadCode = TRUE;
+    } else {
+      EDBPrint (L"Argument error!\n");
+      return EFI_DEBUG_CONTINUE;
+    }
+  }
+
+  if (StrLen (CommandArg) <= 4) {
+    EDBPrint (L"SymbolFile name error!\n");
+    return EFI_DEBUG_CONTINUE;
+  }
+  if (StriCmp (CommandArg + (StrLen (CommandArg) - 4), L".map") != 0) {
+    EDBPrint (L"SymbolFile name error!\n");
+    return EFI_DEBUG_CONTINUE;
+  }
+
+  //
+  // Read MAP file to memory
+  //
+  Status = ReadFileToBuffer (DebuggerPrivate, CommandArg, &BufferSize, &Buffer, TRUE);
+  if (EFI_ERROR(Status)) {
+    EDBPrint (L"SymbolFile read error!\n");
+    return EFI_DEBUG_CONTINUE;
+  }
+
+  FileName = GetFileNameFromFullPath (CommandArg);
+  //
+  // Load Symbol
+  //
+  Status = EdbLoadSymbol (DebuggerPrivate, FileName, BufferSize, Buffer);
+  if (EFI_ERROR(Status)) {
+    EDBPrint (L"LoadSymbol error!\n");
+    gBS->FreePool (Buffer);
+    return EFI_DEBUG_CONTINUE;
+  }
+  gBS->FreePool (Buffer);
+
+  //
+  // Patch Symbol for RVA
+  //
+  Status = EdbPatchSymbolRVA (DebuggerPrivate, FileName, EdbEbcImageRvaSearchTypeLast);
+  if (EFI_ERROR(Status)) {
+    EDBPrint (L"PatchSymbol RVA  - %r! Using the RVA in symbol file.\n", Status);
+  } else {
+    DEBUG ((EFI_D_ERROR, "PatchSymbol RVA successfully!\n"));
+  }
+
+  if (!IsLoadCode) {
+    return EFI_DEBUG_CONTINUE;
+  }
+
+  //
+  // load each cod file
+  //
+  DirName = GetDirNameFromFullPath (CommandArg);
+  ZeroMem (CodFile, sizeof(CodFile));
+  if (StrCmp (DirName, L"") != 0) {
+    StrCpyS (CodFile, sizeof(CodFile), DirName);
+  } else {
+    DirName = L"\\";
+  }
+
+  //
+  // Go throuth each file under this dir
+  //
+  Index = 0;
+  CodFileName = GetFileNameUnderDir (DebuggerPrivate, DirName, L".cod", &Index);
+  while (CodFileName != NULL) {
+    ZeroMem (CodFile, sizeof(CodFile));
+    if (StrCmp (DirName, L"\\") != 0) {
+      StrCpyS (CodFile, sizeof(CodFile), DirName);
+    }
+
+    //
+    // read cod file to memory
+    //
+    Status = ReadFileToBuffer (DebuggerPrivate, ConstructFullPath (CodFile, CodFileName, EFI_DEBUGGER_SYMBOL_NAME_MAX - StrLen (CodFile) - 2), &BufferSize, &Buffer, FALSE);
+    if (EFI_ERROR(Status)) {
+      EDBPrint (L"CodeFile read error!\n");
+      CodFileName = GetFileNameUnderDir (DebuggerPrivate, DirName, L".cod", &Index);
+      continue;
+    }
+
+    //
+    // Load Code
+    //
+    Status = EdbLoadCode (DebuggerPrivate, FileName, CodFileName, BufferSize, Buffer);
+    if (EFI_ERROR (Status)) {
+      EDBPrint (L"LoadCode error!\n");
+      gBS->FreePool (Buffer);
+      CodFileName = GetFileNameUnderDir (DebuggerPrivate, DirName, L".cod", &Index);
+      continue;
+    }
+
+    //
+    // Record the buffer
+    //
+    Status = EdbAddCodeBuffer (DebuggerPrivate, FileName, CodFileName, BufferSize, Buffer);
+    if (EFI_ERROR (Status)) {
+      EDBPrint (L"AddCodeBuffer error!\n");
+      gBS->FreePool (Buffer);
+      CodFileName = GetFileNameUnderDir (DebuggerPrivate, DirName, L".cod", &Index);
+      continue;
+    }
+
+    //
+    // Get next file
+    //
+    CodFileName = GetFileNameUnderDir (DebuggerPrivate, DirName, L".cod", &Index);
+  }
+
+  //
+  // Done
+  //
+  return EFI_DEBUG_CONTINUE;
+}
+
+EFI_DEBUG_STATUS
+DebuggerUnloadSymbol (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - UnloadSymbol
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  EFI_STATUS Status;
+  CHAR16     *FileName;
+  CHAR16     *DirName;
+  CHAR16     CodFile[EFI_DEBUGGER_SYMBOL_NAME_MAX];
+  CHAR16     *CodFileName;
+  UINTN      Index;
+  VOID       *BufferPtr;
+
+  //
+  // Check the argument
+  //
+  if (CommandArg == NULL) {
+    EDBPrint (L"SymbolFile not found!\n");
+    return EFI_DEBUG_CONTINUE;
+  }
+
+  FileName = GetFileNameFromFullPath (CommandArg);
+
+  //
+  // Unload Code
+  //
+  DirName = GetDirNameFromFullPath (CommandArg);
+  ZeroMem (CodFile, sizeof(CodFile));
+  if (StrCmp (DirName, L"") != 0) {
+    StrCpyS (CodFile, sizeof(CodFile), DirName);
+  } else {
+    DirName = L"\\";
+  }
+
+  //
+  // Go through each file under this dir
+  //
+  Index = 0;
+  CodFileName = GetFileNameUnderDir (DebuggerPrivate, DirName, L".cod", &Index);
+  while (CodFileName != NULL) {
+    ZeroMem (CodFile, sizeof(CodFile));
+    if (StrCmp (DirName, L"\\") != 0) {
+      StrCpyS (CodFile, sizeof(CodFile), DirName);
+    }
+
+    //
+    // Unload Code
+    //
+    Status = EdbUnloadCode (DebuggerPrivate, FileName, CodFileName, &BufferPtr);
+    if (EFI_ERROR (Status)) {
+      EDBPrint (L"UnloadCode error!\n");
+      CodFileName = GetFileNameUnderDir (DebuggerPrivate, DirName, L".cod", &Index);
+      continue;
+    }
+
+    //
+    // Delete the code buffer
+    //
+    Status = EdbDeleteCodeBuffer (DebuggerPrivate, FileName, CodFileName, BufferPtr);
+    if (EFI_ERROR (Status)) {
+      EDBPrint (L"DeleteCodeBuffer error!\n");
+      CodFileName = GetFileNameUnderDir (DebuggerPrivate, DirName, L".cod", &Index);
+      continue;
+    }
+
+    //
+    // Get next file
+    //
+    CodFileName = GetFileNameUnderDir (DebuggerPrivate, DirName, L".cod", &Index);
+  }
+
+  //
+  // Unload Symbol
+  //
+  Status = EdbUnloadSymbol (DebuggerPrivate, FileName);
+  if (EFI_ERROR(Status)) {
+    EDBPrint (L"UnloadSymbol error!\n");
+  }
+
+  //
+  // Done
+  //
+  return EFI_DEBUG_CONTINUE;
+}
+
+EFI_DEBUG_STATUS
+DebuggerDisplaySymbol (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - DisplaySymbol
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  if (CommandArg == NULL) {
+    DebuggerPrivate->DebuggerSymbolContext.DisplaySymbol = !DebuggerPrivate->DebuggerSymbolContext.DisplaySymbol;
+    EdbShowDisasm (DebuggerPrivate, SystemContext);
+  } else if (StriCmp (CommandArg, L"on") == 0) {
+    DebuggerPrivate->DebuggerSymbolContext.DisplaySymbol = TRUE;
+    EdbShowDisasm (DebuggerPrivate, SystemContext);
+  } else if (StriCmp (CommandArg, L"off") == 0) {
+    DebuggerPrivate->DebuggerSymbolContext.DisplaySymbol = FALSE;
+    EdbShowDisasm (DebuggerPrivate, SystemContext);
+  } else {
+    EDBPrint (L"DisplaySymbol - argument error\n");
+  }
+
+  return EFI_DEBUG_CONTINUE;
+}
+
+EFI_DEBUG_STATUS
+DebuggerLoadCode (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - LoadCode
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  UINTN      BufferSize;
+  VOID       *Buffer;
+  EFI_STATUS Status;
+  CHAR16     *CommandArg2;
+  CHAR16     *FileName;
+  CHAR16     *MapFileName;
+
+  //
+  // Check the argument
+  //
+  if (CommandArg == NULL) {
+    EDBPrint (L"CodeFile not found!\n");
+    return EFI_DEBUG_CONTINUE;
+  }
+  CommandArg2 = StrGetNextTokenLine (L" ");
+  if (CommandArg2 == NULL) {
+    EDBPrint (L"SymbolFile not found!\n");
+    return EFI_DEBUG_CONTINUE;
+  }
+
+  if (StrLen (CommandArg) <= 4) {
+    EDBPrint (L"CodeFile name error!\n");
+    return EFI_DEBUG_CONTINUE;
+  }
+  if (StriCmp (CommandArg + (StrLen (CommandArg) - 4), L".cod") != 0) {
+    EDBPrint (L"CodeFile name error!\n");
+    return EFI_DEBUG_CONTINUE;
+  }
+  if (StrLen (CommandArg2) <= 4) {
+    EDBPrint (L"SymbolFile name error!\n");
+    return EFI_DEBUG_CONTINUE;
+  }
+  if (StriCmp (CommandArg2 + (StrLen (CommandArg2) - 4), L".map") != 0) {
+    EDBPrint (L"SymbolFile name error!\n");
+    return EFI_DEBUG_CONTINUE;
+  }
+
+  //
+  // read cod file to memory
+  //
+  Status = ReadFileToBuffer (DebuggerPrivate, CommandArg, &BufferSize, &Buffer, TRUE);
+  if (EFI_ERROR(Status)) {
+    EDBPrint (L"CodeFile read error!\n");
+    return EFI_DEBUG_CONTINUE;
+  }
+
+  FileName = GetFileNameFromFullPath (CommandArg);
+  MapFileName = GetFileNameFromFullPath (CommandArg2);
+  //
+  // Load Code
+  //
+  Status = EdbLoadCode (DebuggerPrivate, MapFileName, FileName, BufferSize, Buffer);
+  if (EFI_ERROR (Status)) {
+    EDBPrint (L"LoadCode error!\n");
+    gBS->FreePool (Buffer);
+    return EFI_DEBUG_CONTINUE;
+  }
+
+  //
+  // Record the buffer
+  //
+  Status = EdbAddCodeBuffer (DebuggerPrivate, MapFileName, FileName, BufferSize, Buffer);
+  if (EFI_ERROR (Status)) {
+    EDBPrint (L"AddCodeBuffer error!\n");
+    gBS->FreePool (Buffer);
+    return EFI_DEBUG_CONTINUE;
+  }
+
+  //
+  // Done
+  //
+  return EFI_DEBUG_CONTINUE;
+}
+
+EFI_DEBUG_STATUS
+DebuggerUnloadCode (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - UnloadCode
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  CHAR16     *CommandArg2;
+  CHAR16     *FileName;
+  CHAR16     *MapFileName;
+  EFI_STATUS Status;
+  VOID       *BufferPtr;
+
+  //
+  // Check the argument
+  //
+  if (CommandArg == NULL) {
+    EDBPrint (L"CodeFile not found!\n");
+    return EFI_DEBUG_CONTINUE;
+  }
+  CommandArg2 = StrGetNextTokenLine (L" ");
+  if (CommandArg2 == NULL) {
+    EDBPrint (L"SymbolFile not found!\n");
+    return EFI_DEBUG_CONTINUE;
+  }
+
+  FileName = GetFileNameFromFullPath (CommandArg);
+  MapFileName = GetFileNameFromFullPath (CommandArg2);
+
+  //
+  // Unload Code
+  //
+  Status = EdbUnloadCode (DebuggerPrivate, MapFileName, FileName, &BufferPtr);
+  if (EFI_ERROR (Status)) {
+    EDBPrint (L"UnloadCode error!\n");
+    return EFI_DEBUG_CONTINUE;
+  }
+
+  //
+  // Delete Code buffer
+  //
+  Status = EdbDeleteCodeBuffer (DebuggerPrivate, MapFileName, FileName, BufferPtr);
+  if (EFI_ERROR (Status)) {
+    EDBPrint (L"DeleteCodeBuffer error!\n");
+  }
+
+  //
+  // Done
+  //
+  return EFI_DEBUG_CONTINUE;
+}
+
+EFI_DEBUG_STATUS
+DebuggerDisplayCode (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  DebuggerCommand - DisplayCode
+
+Arguments:
+
+  CommandArg      - The argument for this command
+  DebuggerPrivate - EBC Debugger private data structure
+  InterruptType   - Interrupt type.
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_DEBUG_CONTINUE - formal return value
+
+--*/
+{
+  if (CommandArg == NULL) {
+    DebuggerPrivate->DebuggerSymbolContext.DisplayCodeOnly = !DebuggerPrivate->DebuggerSymbolContext.DisplayCodeOnly;
+    EdbShowDisasm (DebuggerPrivate, SystemContext);
+  } else if (StriCmp (CommandArg, L"on") == 0) {
+    DebuggerPrivate->DebuggerSymbolContext.DisplayCodeOnly = TRUE;
+    EdbShowDisasm (DebuggerPrivate, SystemContext);
+  } else if (StriCmp (CommandArg, L"off") == 0) {
+    DebuggerPrivate->DebuggerSymbolContext.DisplayCodeOnly = FALSE;
+    EdbShowDisasm (DebuggerPrivate, SystemContext);
+  } else {
+    EDBPrint (L"DisplayCode - argument error\n");
+  }
+
+  return EFI_DEBUG_CONTINUE;
+}
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCommand.c b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCommand.c
new file mode 100644
index 000000000000..5421cb5bc2f9
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCommand.c
@@ -0,0 +1,680 @@
+/*++
+
+Copyright (c) 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.
+
+Module Name:
+
+  EdbCommand.c
+
+Abstract:
+
+
+--*/
+
+#include "Edb.h"
+
+//
+// Debugger Command Table
+//
+EFI_DEBUGGER_COMMAND_SET  mDebuggerCommandSet[] = {
+  //
+  // Execution
+  //
+  {
+    L"G",
+    L"G/[F5]             - continue to run the program\n",
+    L"The go command is used to cause the debugger to not interrupt execution of the EBC image. The debugger will only break execution of the interpreter if an exception is encountered (including an EBC breakpoint).\n\n",
+    L"G [til <Address|Symbol>]\n"
+    L"  (No Argument) - It means continue run the program.\n"
+    L"  til           - It means continuing run the program till IP is the Address.\n"
+    L"  <Address>     - The hexical address user want to break at.\n"
+    L"  <Symbol>      - The symbol name for target address user want to break at. It has following format [MapFileName:]SymbolName\n",
+    L"Execution:\n",
+    {SCAN_F5, CHAR_NULL},
+    DebuggerGo
+  },
+  {
+    L"T",
+    L"T/[F8]             - step into\n",
+    L"The step into command will cause the EBC debugger to step a single instruction. If the instruction is a call to internal code (CALL), then the debugger will break at the new function CALL.\n\n",
+    L"T\n"
+    L"  (No Argument)\n",
+    L"",
+    {SCAN_F8, CHAR_NULL},
+    DebuggerStepInto
+  },
+  {
+    L"P",
+    L"P/[F10]            - step over\n",
+    L"The step over command will cause the EBC debugger to step a single instruction. If the instruction is a call to internal code (CALL), then the external call will be made and the debugger will break at the instruction following the CALL.\n\n",
+    L"P\n"
+    L"  (No Argument)\n",
+    L"",
+    {SCAN_F10, CHAR_NULL},
+    DebuggerStepOver
+  },
+  {
+    L"O",
+    L"O/[F11]            - step out\n",
+    L"The step out command causes the EBC debugger to step out function calls. The function will be executed, but the debugger will stop after the called function returns.\n\n",
+    L"O\n"
+    L"  (No Argument)\n",
+    L"",
+    {SCAN_F11, CHAR_NULL},
+    DebuggerStepOut
+  },
+  {
+    L"Q",
+    L"Q                  - reset the debugger to default value and go\n",
+    L"The quit command will reset the debugger to default value and go.\n\n",
+    L"Q\n"
+    L"  (No Argument)\n",
+    L"",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerQuit
+  },
+  //
+  // Break
+  //
+  {
+    L"BOC",
+    L"BO[C|CX|R|E|T|K]   - break on CALL/CALLEX/RET/Entrypoint/Native Thunk/Key\n",
+    L"Enabling break-on-call will cause the debugger to halt execution and display the debugger prompt prior to executing any EBC CALL (to EBC) instructions.\n\n",
+    L"BOC [on|off]\n"
+    L"  (No Argument) - show current state\n"
+    L"  on            - enable break-on-call\n"
+    L"  off           - disable break-on-call\n",
+    L"Break:\n",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerBreakOnCALL
+  },
+  {
+    L"BOCX",
+    L"",
+    L"Enabling break-on-callex will cause the debugger to halt execution and display the debugger prompt prior to executing EBC CALLEX (thunk out) instructions.\n\n",
+    L"BOCX [on|off]\n"
+    L"  (No Argument) - show current state\n"
+    L"  on            - enable break-on-callex\n"
+    L"  off           - disable break-on-callex\n",
+    L"",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerBreakOnCALLEX
+  },
+  {
+    L"BOR",
+    L"",
+    L"Enabling break-on-return will cause the debugger to halt execution and display the debugger prompt prior to executing EBC RET instructions.\n\n",
+    L"BOR [on|off]\n"
+    L"  (No Argument) - show current state\n"
+    L"  on            - enable break-on-return\n"
+    L"  off           - disable break-on-return\n",
+    L"",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerBreakOnRET
+  },
+  {
+    L"BOE",
+    L"",
+    L"Enabling break-on-entrypoint will cause the debugger to halt execution and display the debugger prompt prior to start a driver entry point. (Default is on)\n\n",
+    L"BOE [on|off]\n"
+    L"  (No Argument) - show current state\n"
+    L"  on            - enable break-on-entrypoint\n"
+    L"  off           - disable break-on-entrypoint\n",
+    L"",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerBreakOnEntrypoint
+  },
+  {
+    L"BOT",
+    L"",
+    L"Enabling break-on-thunk will cause the debugger to halt execution and display the debugger prompt prior to start native call EBC thunk. (Default is on)\n\n",
+    L"BOT [on|off]\n"
+    L"  (No Argument) - show current state\n"
+    L"  on            - enable break-on-thunk\n"
+    L"  off           - disable break-on-thunk\n",
+    L"",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerBreakOnThunk
+  },
+  {
+    L"BOK",
+    L"",
+    L"Enabling break-on-key will cause the debugger to halt execution and display the debugger prompt after press any key.\n\n",
+    L"BOK [on|off]\n"
+    L"  (No Argument) - show current state\n"
+    L"  on            - enable break-on-key\n"
+    L"  off           - disable break-on-key\n",
+    L"",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerBreakOnKey
+  },
+  {
+    L"BL",
+    L"B[L|P|C|D|E]       - breakpoint list/set/clear/disable/enable\n",
+    L"List Breakpoint\n\n",
+    L"BL\n"
+    L"  (No Argument) - show the state for current breakpoint\n",
+    L"",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerBreakpointList
+  },
+  {
+    L"BP",
+    L"",
+    L"Set Breakpoint\n\n",
+    L"BP <Address|Symbol>\n"
+    L"  <Address> - Hexical breakpoint address\n"
+    L"  <Symbol>  - Symbol name for breakpoint address. It has following format [MapFileName:]SymbolName.\n",
+    L"",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerBreakpointSet
+  },
+  {
+    L"BC",
+    L"",
+    L"Clear Breakpoint\n\n",
+    L"BC <Index>|*\n"
+    L"  <Index>   - Decimal breakpoint index, which can be got from BL command\n"
+    L"  *         - For all the breakpoint\n",
+    L"",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerBreakpointClear
+  },
+  {
+    L"BD",
+    L"",
+    L"Disable Breakpoint\n\n",
+    L"BD <Index>|*\n"
+    L"  <Index>   - Decimal breakpoint index, which can be got from BL command\n"
+    L"  *         - For all the breakpoint\n",
+    L"",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerBreakpointDisable
+  },
+  {
+    L"BE",
+    L"",
+    L"Enable Breakpoint\n\n",
+    L"BE <Index>|*\n"
+    L"  <Index>   - Decimal breakpoint index, which can be got from BL command\n"
+    L"  *         - For all the breakpoint\n",
+    L"",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerBreakpointEnable
+  },
+  //
+  // Information
+  //
+  {
+    L"K",
+    L"K                  - show/clear call-stack\n",
+    L"The call-stack command will show or clear the current call-stack.\n\n",
+    L"K [p [<ParameterNum>]|c]\n"
+    L"  (No Argument) - Show current call-stack\n"
+    L"  p             - Show current call-stack with parameters\n"
+    L"  ParameterNum  - Decimal call-stack parameters number, 8 by default, 16 as max\n"
+    L"  c             - Clear current call-stack\n",
+    L"Information:\n",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerCallStack
+  },
+  {
+    L"TRACE",
+    L"TRACE              - show/clear trace instruction branch\n",
+    L"The trace command will show or clear the latest instruction branch.\n\n",
+    L"TRACE [c]\n"
+    L"  (No Argument) - Show current instrcution branch\n"
+    L"  c             - Clear current instruction branch\n",
+    L"",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerInstructionBranch
+  },
+  {
+    L"R",
+    L"R/[F2]             - display/modify register\n",
+    L"The register command is used to display or modify the contents of EBC VM registers. (R0~R7, Flags, IP)\n\n",
+    L"R [<Register> <Value>]\n"
+    L"  (No Argument) - Display all registers\n"
+    L"  <Register>    - EBC VM register name (R0~R7, Flags, ControlFlags, and IP\n"
+    L"  <Value>       - The Hexical value of register\n",
+    L"",
+    {SCAN_F2, CHAR_NULL},
+    DebuggerRegister
+  },
+  {
+    L"L",
+    L"L/[F4]             - show/load instruction assembly count\n",
+    L"The list assembly command will disassemble instructions starting with the current EBC VM instruction pointer. (by default 5 instructions)\n\n",
+    L"L [<Count>]\n"
+    L"  (No Argument) - List current assembly code\n"
+    L"  Count         - The decimal instruction assembly count\n",
+    L"",
+    {SCAN_F4, CHAR_NULL},
+    DebuggerList
+  },
+  {
+    L"SCOPE",
+    L"SCOPE              - load scope address\n",
+    L"The scope command will disassemble instructions starting with the Scope. (by default current EBC VM IP)\n\n",
+    L"SCOPE <Address|Symbol>\n"
+    L"  <Address> - The Hexical address where user wants to see the assembly code\n"
+    L"  <Symbol>  - Symbol name for scope address. It has following format [MapFileName:]SymbolName.\n",
+    L"",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerScope
+  },
+  {
+    L"DB",
+    L"[D|E][B|W|D|Q]     - display/modify memory\n",
+    L"Display BYTES Memory\n\n",
+    L"DB <Address|Symbol> [<Count>]\n"
+    L"  <Address> - The hexical memory address\n"
+    L"  <Symbol>  - Symbol name for memory address. It has following format [MapFileName:]SymbolName.\n"
+    L"  <Count>   - The hexical memory count (not set means 1)\n",
+    L"",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerMemoryDB
+  },
+  {
+    L"DW",
+    L"",
+    L"Display WORDS Memory\n\n",
+    L"DW <Address|Symbol> [<Count>]\n"
+    L"  <Address> - The hexical memory address\n"
+    L"  <Symbol>  - Symbol name for memory address. It has following format [MapFileName:]SymbolName.\n"
+    L"  <Count>   - The hexical memory count (not set means 1)\n",
+    L"",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerMemoryDW
+  },
+  {
+    L"DD",
+    L"",
+    L"Display DWORDS Memory\n\n",
+    L"DD <Address|Symbol> [<Count>]\n"
+    L"  <Address> - The hexical memory address\n"
+    L"  <Symbol>  - Symbol name for memory address. It has following format [MapFileName:]SymbolName.\n"
+    L"  <Count>   - The hexical memory count (not set means 1)\n",
+    L"",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerMemoryDD
+  },
+  {
+    L"DQ",
+    L"",
+    L"Display QWORDS Memory\n\n",
+    L"DQ <Address|Symbol> [<Count>]\n"
+    L"  <Address> - The hexical memory address\n"
+    L"  <Symbol>  - Symbol name for memory address. It has following format [MapFileName:]SymbolName.\n"
+    L"  <Count>   - The hexical memory count (not set means 1)\n",
+    L"",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerMemoryDQ
+  },
+  {
+    L"EB",
+    L"",
+    L"Enter BYTES Memory\n\n",
+    L"EB <Address|Symbol> <Value>\n"
+    L"  <Address> - The hexical memory address\n"
+    L"  <Symbol>  - Symbol name for memory address. It has following format [MapFileName:]SymbolName.\n"
+    L"  <Value>   - The hexical memory value\n",
+    L"",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerMemoryEB
+  },
+  {
+    L"EW",
+    L"",
+    L"Enter WORDS Memory\n\n",
+    L"EW <Address|Symbol> <Value>\n"
+    L"  <Address> - The hexical memory address\n"
+    L"  <Symbol>  - Symbol name for memory address. It has following format [MapFileName:]SymbolName.\n"
+    L"  <Value>   - The hexical memory value\n",
+    L"",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerMemoryEW
+  },
+  {
+    L"ED",
+    L"",
+    L"Enter DWORDS Memory\n\n",
+    L"ED <Address|Symbol> <Value>\n"
+    L"  <Address> - The hexical memory address\n"
+    L"  <Symbol>  - Symbol name for memory address. It has following format [MapFileName:]SymbolName.\n"
+    L"  <Value>   - The hexical memory value\n",
+    L"",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerMemoryED
+  },
+  {
+    L"EQ",
+    L"",
+    L"Enter QWORDS Memory\n\n",
+    L"EQ <Address|Symbol> <Value>\n"
+    L"  <Address> - The hexical memory address\n"
+    L"  <Symbol>  - Symbol name for memory address. It has following format [MapFileName:]SymbolName.\n"
+    L"  <Value>   - The hexical memory value\n",
+    L"",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerMemoryEQ
+  },
+  //
+  // Symbol
+  //
+  {
+    L"LN",
+    L"LN                 - list the symbol\n",
+    L"The show symbol command will list all the current symbol. It can list the symbol in one symbol file, or list the same symbol in all the files. It can also list the symbol according to nearest address.\n\n",
+    L"LN [[F <SymbolFile>] [S <Symbol>]] | <Address>\n"
+    L"  (No Argument)  - List all the symbol\n"
+    L"  F <SymbolFile> - List the symbol in this symbol file only\n"
+    L"  S <Symbol>     - List this symbol only\n"
+    L"  <Address>      - The hexical memory address, which user want to find the symbol for.\n",
+    L"Symbol:\n",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerListSymbol
+  },
+  {
+    L"LOADSYMBOL",
+    L"[UN]LOADSYMBOL     - load/unload the symbol file\n",
+    L"The load symbol command will load the ebc map file. Then it parses the function name and global variable, and the print real name when do the disassembly. (Symbol file name should be XXX.MAP)\n\n",
+    L"LOADSYMBOL <SymbolFile> [a]\n"
+    L"  SymbolFile - The EBC symbol file (Its name should be XXX.MAP)\n"
+    L"  a          - Automatically load code files in the same dir\n",
+    L"",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerLoadSymbol
+  },
+  {
+    L"UNLOADSYMBOL",
+    L"",
+    L"The unload symbol command will unload the ebc map and cod file. After that the name will not be print.\n\n",
+    L"UNLOADSYMBOL <SymbolFile>\n"
+    L"  SymbolFile - The EBC symbol file (Its name should be XXX.MAP)\n",
+    L"",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerUnloadSymbol
+  },
+  {
+    L"LOADCODE",
+    L"[UN]LOADCODE       - load/unload the code file\n",
+    L"The load code command will load the ebc cod file. Then it parses the cod file, and the print source code when do the disassembly. (Code file name should be XXX.COD)\n\n",
+    L"LOADCODE <CodeFile> <SymbolFile>\n"
+    L"  CodeFile   - The EBC code file (Its name should be XXX.COD)\n"
+    L"  SymbolFile - The EBC symbol file (Its name should be XXX.MAP)\n",
+    L"",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerLoadCode
+  },
+  {
+    L"UNLOADCODE",
+    L"",
+    L"The unload code command will unload the ebc cod file. After that the source code will not be print.\n\n",
+    L"UNLOADCODE <CodeFile> <SymbolFile>\n"
+    L"  CodeFile   - The EBC code file (Its name should be XXX.COD)\n"
+    L"  SymbolFile - The EBC symbol file (Its name should be XXX.MAP)\n",
+    L"",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerUnloadCode
+  },
+  {
+    L"DISPLAYSYMBOL",
+    L"DISPLAYSYMBOL/[F3] - disable/enable the symbol output\n",
+    L"",
+    L"The display symbol command will configure the symbol show or not-show when disassembly.\n\n"
+    L"DISPLAYSYMBOL [on|off]\n"
+    L"  (No Argument) - swtich symbol output state to another one\n"
+    L"  on            - enable symbol output\n"
+    L"  off           - disable symbol output\n",
+    L"",
+    {SCAN_F3, CHAR_NULL},
+    DebuggerDisplaySymbol
+  },
+  {
+    L"DISPLAYCODE",
+    L"DISPLAYCODE/[F6]   - disable/enable the source code only output\n",
+    L"",
+    L"The display code command will configure the source code only show or misc source code with assembly.\n\n"
+    L"DISPLAYCODE [on|off]\n"
+    L"  (No Argument) - swtich source only output state to another one\n"
+    L"  on            - enable source only output\n"
+    L"  off           - disable source only output\n",
+    L"",
+    {SCAN_F6, CHAR_NULL},
+    DebuggerDisplayCode
+  },
+  //
+  // Other
+  //
+  {
+    L"H",
+    L"",
+    L"The help command will print help information for each command\n\n",
+    L"H [<Command>]\n",
+    L"",
+    {SCAN_F1, CHAR_NULL},
+    DebuggerHelp
+  },
+/*
+  //
+  // Extended
+  //
+  {
+    L"!IB",
+    L"![I|O][B|W|D]      - display/modify IO\n",
+    L"",
+    L"!IB <Address>\n",
+    L"Extended:\n",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerExtIoIB
+  },
+  {
+    L"!IW",
+    L"",
+    L"",
+    L"!IW <Address>\n",
+    L"",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerExtIoIW
+  },
+  {
+    L"!ID",
+    L"",
+    L"",
+    L"!ID <Address>\n",
+    L"",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerExtIoID
+  },
+  {
+    L"!OB",
+    L"",
+    L"",
+    L"!OB <Address> <Value>\n",
+    L"",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerExtIoOB
+  },
+  {
+    L"!OW",
+    L"",
+    L"",
+    L"!OW <Address> <Value>\n",
+    L"",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerExtIoOW
+  },
+  {
+    L"!OD",
+    L"",
+    L"",
+    L"!OD <Address> <Value>\n",
+    L"",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerExtIoOD
+  },
+  {
+    L"!PCIL",
+    L"!PCIL              - list PCI device, with BAR\n",
+    L"",
+    L"!PCIL [B]\n",
+    L"",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerExtPciPCIL
+  },
+  {
+    L"!PCID",
+    L"!PCID              - show PCI space\n",
+    L"",
+    L"!PCID Bus Device Function [H|B|E]\n",
+    L"",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerExtPciPCID
+  },
+  {
+    L"!CFGB",
+    L"!CFG[B|W|D]        - show/modify PCI space",
+    L"",
+    L"!CFGB <Address> [<Value>]\n",
+    L"",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerExtPciCFGB
+  },
+  {
+    L"!CFGW",
+    L"",
+    L"",
+    L"!CFGW <Address> [<Value>]\n",
+    L"",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerExtPciCFGW
+  },
+  {
+    L"!CFGD",
+    L"",
+    L"",
+    L"!CFGD <Address> [<Value>]\n",
+    L"",
+    {SCAN_NULL, CHAR_NULL},
+    DebuggerExtPciCFGD
+  },
+*/
+  {
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    {SCAN_NULL, CHAR_NULL},
+    NULL
+  },
+};
+
+EFI_DEBUGGER_COMMAND
+MatchDebuggerCommand (
+  IN CHAR16    *CommandName,
+  IN CHAR16    **CommandArg
+  )
+/*++
+
+Routine Description:
+
+  Find the command according to name
+
+Arguments:
+
+  CommandName   - Command Name
+  CommandArg    - Command Argument
+
+Returns:
+
+  Not NULL        - The DebuggerCommand is found successfully
+  NULL            - not found
+
+--*/
+{
+  UINTN  Index;
+  CHAR16 *Temp;
+
+  //
+  // Get Command Name
+  //
+  Temp = StrGetNewTokenLine (CommandName, L" ");
+  CommandName = Temp;
+  //
+  // Get Command Argument
+  //
+  Temp = StrGetNextTokenLine (L" ");
+  *CommandArg = Temp;
+
+  if (CommandName == NULL) {
+    return NULL;
+  }
+
+  //
+  // Go through each command, check the CommandName
+  //
+  for (Index = 0; mDebuggerCommandSet[Index].CommandName != NULL; Index++) {
+    if (StriCmp (CommandName, mDebuggerCommandSet[Index].CommandName) == 0) {
+      //
+      // Found
+      //
+      return mDebuggerCommandSet[Index].CommandFunc;
+    }
+  }
+
+  //
+  // Not found
+  //
+  return NULL;
+}
+
+CHAR16 *
+GetCommandNameByKey (
+  IN EFI_INPUT_KEY CommandKey
+  )
+/*++
+
+Routine Description:
+
+  Find the command name according to the function key
+
+Arguments:
+
+  CommandKey    - Command Function Key
+
+Returns:
+
+  Not NULL        - The DebuggerName is found successfully
+  NULL            - not found
+
+--*/
+{
+  UINTN  Index;
+
+  //
+  // Go through each command, check the CommandKey
+  //
+  for (Index = 0; mDebuggerCommandSet[Index].CommandName != NULL; Index++) {
+    if ((mDebuggerCommandSet[Index].CommandKey.UnicodeChar == CommandKey.UnicodeChar) &&
+        (mDebuggerCommandSet[Index].CommandKey.ScanCode    == CommandKey.ScanCode)) {
+      //
+      // Found
+      //
+      return mDebuggerCommandSet[Index].CommandName;
+    }
+  }
+
+  //
+  // Not found
+  //
+  return NULL;
+}
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCommand.h b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCommand.h
new file mode 100644
index 000000000000..ca2a56fba93f
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCommand.h
@@ -0,0 +1,106 @@
+/*++
+
+Copyright (c) 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.
+
+Module Name:
+
+  EdbCommand.h
+
+Abstract:
+
+
+--*/
+
+#ifndef _EFI_EDB_COMMAND_H_
+#define _EFI_EDB_COMMAND_H_
+
+typedef enum {
+  EdbWidthUint8,
+  EdbWidthUint16,
+  EdbWidthUint32,
+  EdbWidthUint64,
+  EdbWidthMax
+} EDB_DATA_WIDTH;
+
+EFI_DEBUGGER_COMMAND
+MatchDebuggerCommand (
+  IN CHAR16    *CommandName,
+  IN CHAR16    **CommandArg
+  );
+
+CHAR16 *
+GetCommandNameByKey (
+  IN EFI_INPUT_KEY CommandKey
+  );
+
+//
+// Definition for Command Table
+//
+#define EDB_COMMAND_DEFINE(func) \
+EFI_DEBUG_STATUS \
+func ( \
+  IN     CHAR16                    *CommandArg, \
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate, \
+  IN     EFI_EXCEPTION_TYPE        ExceptionType, \
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext \
+  )
+
+EDB_COMMAND_DEFINE (DebuggerCallStack);
+EDB_COMMAND_DEFINE (DebuggerInstructionBranch);
+EDB_COMMAND_DEFINE (DebuggerBreakOnCALL);
+EDB_COMMAND_DEFINE (DebuggerBreakOnCALLEX);
+EDB_COMMAND_DEFINE (DebuggerBreakOnRET);
+EDB_COMMAND_DEFINE (DebuggerBreakOnEntrypoint);
+EDB_COMMAND_DEFINE (DebuggerBreakOnThunk);
+EDB_COMMAND_DEFINE (DebuggerBreakOnKey);
+EDB_COMMAND_DEFINE (DebuggerBreakpointList);
+EDB_COMMAND_DEFINE (DebuggerBreakpointSet);
+EDB_COMMAND_DEFINE (DebuggerBreakpointClear);
+EDB_COMMAND_DEFINE (DebuggerBreakpointDisable);
+EDB_COMMAND_DEFINE (DebuggerBreakpointEnable);
+EDB_COMMAND_DEFINE (DebuggerGo);
+EDB_COMMAND_DEFINE (DebuggerHelp);
+EDB_COMMAND_DEFINE (DebuggerMemoryDB);
+EDB_COMMAND_DEFINE (DebuggerMemoryDW);
+EDB_COMMAND_DEFINE (DebuggerMemoryDD);
+EDB_COMMAND_DEFINE (DebuggerMemoryDQ);
+EDB_COMMAND_DEFINE (DebuggerMemoryEB);
+EDB_COMMAND_DEFINE (DebuggerMemoryEW);
+EDB_COMMAND_DEFINE (DebuggerMemoryED);
+EDB_COMMAND_DEFINE (DebuggerMemoryEQ);
+EDB_COMMAND_DEFINE (DebuggerQuit);
+EDB_COMMAND_DEFINE (DebuggerRegister);
+EDB_COMMAND_DEFINE (DebuggerScope);
+EDB_COMMAND_DEFINE (DebuggerList);
+EDB_COMMAND_DEFINE (DebuggerStepInto);
+EDB_COMMAND_DEFINE (DebuggerStepOver);
+EDB_COMMAND_DEFINE (DebuggerStepOut);
+EDB_COMMAND_DEFINE (DebuggerListSymbol);
+EDB_COMMAND_DEFINE (DebuggerLoadSymbol);
+EDB_COMMAND_DEFINE (DebuggerUnloadSymbol);
+EDB_COMMAND_DEFINE (DebuggerDisplaySymbol);
+EDB_COMMAND_DEFINE (DebuggerLoadCode);
+EDB_COMMAND_DEFINE (DebuggerUnloadCode);
+EDB_COMMAND_DEFINE (DebuggerDisplayCode);
+EDB_COMMAND_DEFINE (DebuggerExtIoIB);
+EDB_COMMAND_DEFINE (DebuggerExtIoIW);
+EDB_COMMAND_DEFINE (DebuggerExtIoID);
+EDB_COMMAND_DEFINE (DebuggerExtIoOB);
+EDB_COMMAND_DEFINE (DebuggerExtIoOW);
+EDB_COMMAND_DEFINE (DebuggerExtIoOD);
+EDB_COMMAND_DEFINE (DebuggerExtPciPCIL);
+EDB_COMMAND_DEFINE (DebuggerExtPciPCID);
+EDB_COMMAND_DEFINE (DebuggerExtPciCFGB);
+EDB_COMMAND_DEFINE (DebuggerExtPciCFGW);
+EDB_COMMAND_DEFINE (DebuggerExtPciCFGD);
+
+extern EFI_DEBUGGER_COMMAND_SET  mDebuggerCommandSet[];
+
+#endif
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCommon.h b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCommon.h
new file mode 100644
index 000000000000..84d5be89be40
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCommon.h
@@ -0,0 +1,246 @@
+/*++
+
+Copyright (c) 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.
+
+Module Name:
+
+  EdbCommon.h
+
+Abstract:
+
+
+--*/
+
+#ifndef _EFI_EDB_COMMON_H_
+#define _EFI_EDB_COMMON_H_
+
+#include <Uefi.h>
+#include <Library/UefiLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/DebugSupport.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <Guid/FileInfo.h>
+#include <Guid/FileSystemInfo.h>
+#include <Guid/FileSystemVolumeLabelInfo.h>
+#include <Guid/DebugImageInfoTable.h>
+
+typedef UINTN EFI_DEBUG_STATUS;
+
+typedef struct _EFI_DEBUGGER_PRIVATE_DATA EFI_DEBUGGER_PRIVATE_DATA;
+
+//
+// Definition for Debugger Command
+//
+typedef
+EFI_DEBUG_STATUS
+(* EFI_DEBUGGER_COMMAND) (
+  IN     CHAR16                    *CommandArg,
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_EXCEPTION_TYPE        ExceptionType,
+  IN OUT EFI_SYSTEM_CONTEXT        SystemContext
+);
+
+typedef struct {
+  CHAR16                *CommandName;
+  CHAR16                *CommandTitle;
+  CHAR16                *CommandHelp;
+  CHAR16                *CommandSyntax;
+  CHAR16                *ClassName;
+  EFI_INPUT_KEY         CommandKey;
+  EFI_DEBUGGER_COMMAND  CommandFunc;
+} EFI_DEBUGGER_COMMAND_SET;
+
+//
+// Definition for Debugger Symbol
+//
+#define EFI_DEBUGGER_SYMBOL_NAME_MAX     256
+#define EFI_DEBUGGER_SYMBOL_ENTRY_MAX    512
+#define EFI_DEBUGGER_SYMBOL_OBJECT_MAX   32
+
+//
+// We have following SYMBOL data structure:
+//
+// SYMBOL_CONTEXT -> SYMBOL_OBJECT -> SYMBOL_ENTRY (FuncXXX, 0xXXX)
+//                                    SYMBOL_ENTRY (VarYYY,  0xYYY)
+//                                    SYMBOL_ENTRY
+//
+//                   SYMBOL_OBJECT -> SYMBOL_ENTRY
+//                                    SYMBOL_ENTRY
+//
+//                   SYMBOL_OBJECT -> SYMBOL_ENTRY
+//                                    SYMBOL_ENTRY
+//
+
+typedef enum {
+  EfiDebuggerSymbolFunction,
+  EfiDebuggerSymbolStaticFunction,
+  EfiDebuggerSymbolGlobalVariable,
+  EfiDebuggerSymbolStaticVariable,
+  EfiDebuggerSymbolTypeMax,
+} EFI_DEBUGGER_SYMBOL_TYPE;
+
+typedef struct {
+  CHAR8                      Name[EFI_DEBUGGER_SYMBOL_NAME_MAX];
+  UINTN                      RVA;
+  EFI_DEBUGGER_SYMBOL_TYPE   Type;
+  CHAR8                      ObjName[EFI_DEBUGGER_SYMBOL_NAME_MAX];
+  CHAR8                      *CodBuffer;
+  UINTN                      CodBufferSize;
+  UINTN                      FuncOffsetBase;
+  CHAR8                      *SourceBuffer;
+} EFI_DEBUGGER_SYMBOL_ENTRY;
+
+typedef struct {
+  CHAR16                     Name[EFI_DEBUGGER_SYMBOL_NAME_MAX];
+  UINTN                      EntryCount;
+  UINTN                      MaxEntryCount;
+  UINTN                      BaseAddress;
+  UINTN                      StartEntrypointRVA;
+  UINTN                      MainEntrypointRVA;
+  EFI_DEBUGGER_SYMBOL_ENTRY  *Entry;
+  VOID                       **SourceBuffer;
+} EFI_DEBUGGER_SYMBOL_OBJECT;
+
+typedef struct {
+  UINTN                       ObjectCount;
+  UINTN                       MaxObjectCount;
+  EFI_DEBUGGER_SYMBOL_OBJECT  *Object;
+  BOOLEAN                     DisplaySymbol;
+  BOOLEAN                     DisplayCodeOnly;
+} EFI_DEBUGGER_SYMBOL_CONTEXT;
+
+//
+// Definition for Debugger Breakpoint
+//
+#define EFI_DEBUGGER_BREAKPOINT_MAX    0x10
+
+typedef struct {
+  EFI_PHYSICAL_ADDRESS      BreakpointAddress;
+  UINT64                    OldInstruction;    // UINT64 is enough for an instruction
+  BOOLEAN                   State;
+} EFI_DEBUGGER_BREAKPOINT_CONTEXT;
+
+//
+// Definition for Debugger Call-Stack
+//
+#define EFI_DEBUGGER_CALLSTACK_MAX     0x10
+
+typedef enum {
+  EfiDebuggerBranchTypeEbcCall,
+  EfiDebuggerBranchTypeEbcCallEx,
+  EfiDebuggerBranchTypeEbcRet,
+  EfiDebuggerBranchTypeEbcJmp,
+  EfiDebuggerBranchTypeEbcJmp8,
+  EfiDebuggerBranchTypeEbcMax,
+} EFI_DEBUGGER_BRANCH_TYPE;
+
+#define EFI_DEBUGGER_CALL_MAX_PARAMETER      0x16
+#define EFI_DEBUGGER_CALL_DEFAULT_PARAMETER  0x8
+
+typedef struct {
+  EFI_PHYSICAL_ADDRESS      SourceAddress;
+  EFI_PHYSICAL_ADDRESS      DestAddress;
+  //
+  // We save all parameter here, because code may update the parameter as local variable.
+  //
+  UINTN                     ParameterAddr;
+  UINTN                     Parameter[EFI_DEBUGGER_CALL_MAX_PARAMETER];
+  EFI_DEBUGGER_BRANCH_TYPE  Type;
+} EFI_DEBUGGER_CALLSTACK_CONTEXT;
+
+//
+// Definition for Debugger Trace
+//
+#define EFI_DEBUGGER_TRACE_MAX         0x10
+
+typedef struct {
+  EFI_PHYSICAL_ADDRESS      SourceAddress;
+  EFI_PHYSICAL_ADDRESS      DestAddress;
+  EFI_DEBUGGER_BRANCH_TYPE  Type;
+} EFI_DEBUGGER_TRACE_CONTEXT;
+
+//
+// Definition for Debugger Step
+//
+typedef struct {
+  EFI_PHYSICAL_ADDRESS      BreakAddress;
+  EFI_PHYSICAL_ADDRESS      FramePointer;
+} EFI_DEBUGGER_STEP_CONTEXT;
+
+//
+// Definition for Debugger GoTil
+//
+typedef struct {
+  EFI_PHYSICAL_ADDRESS      BreakAddress;
+} EFI_DEBUGGER_GOTIL_CONTEXT;
+
+//
+// Definition for Debugger private data structure
+//
+#define EFI_DEBUGGER_SIGNATURE         SIGNATURE_32 ('e', 'd', 'b', '!')
+
+#define EFI_DEBUG_DEFAULT_INSTRUCTION_NUMBER  5
+
+#define EFI_DEBUG_BREAK_TIMER_INTERVAL        10000000   // 1 second
+
+#define EFI_DEBUG_FLAG_EBC            0x80000000
+#define EFI_DEBUG_FLAG_EBC_B_BOC      0x1
+#define EFI_DEBUG_FLAG_EBC_B_BOCX     0x2
+#define EFI_DEBUG_FLAG_EBC_B_BOR      0x4
+#define EFI_DEBUG_FLAG_EBC_B_BOE      0x8
+#define EFI_DEBUG_FLAG_EBC_B_BOT      0x10
+#define EFI_DEBUG_FLAG_EBC_B_STEPOVER 0x20
+#define EFI_DEBUG_FLAG_EBC_B_STEPOUT  0x40
+#define EFI_DEBUG_FLAG_EBC_B_BP       0x80
+#define EFI_DEBUG_FLAG_EBC_B_GT       0x100
+#define EFI_DEBUG_FLAG_EBC_B_BOK      0x200
+#define EFI_DEBUG_FLAG_EBC_BOC        (EFI_DEBUG_FLAG_EBC | EFI_DEBUG_FLAG_EBC_B_BOC)
+#define EFI_DEBUG_FLAG_EBC_BOCX       (EFI_DEBUG_FLAG_EBC | EFI_DEBUG_FLAG_EBC_B_BOCX)
+#define EFI_DEBUG_FLAG_EBC_BOR        (EFI_DEBUG_FLAG_EBC | EFI_DEBUG_FLAG_EBC_B_BOR)
+#define EFI_DEBUG_FLAG_EBC_BOE        (EFI_DEBUG_FLAG_EBC | EFI_DEBUG_FLAG_EBC_B_BOE)
+#define EFI_DEBUG_FLAG_EBC_BOT        (EFI_DEBUG_FLAG_EBC | EFI_DEBUG_FLAG_EBC_B_BOT)
+#define EFI_DEBUG_FLAG_EBC_STEPOVER   (EFI_DEBUG_FLAG_EBC | EFI_DEBUG_FLAG_EBC_B_STEPOVER)
+#define EFI_DEBUG_FLAG_EBC_STEPOUT    (EFI_DEBUG_FLAG_EBC | EFI_DEBUG_FLAG_EBC_B_STEPOUT)
+#define EFI_DEBUG_FLAG_EBC_BP         (EFI_DEBUG_FLAG_EBC | EFI_DEBUG_FLAG_EBC_B_BP)
+#define EFI_DEBUG_FLAG_EBC_GT         (EFI_DEBUG_FLAG_EBC | EFI_DEBUG_FLAG_EBC_B_GT)
+#define EFI_DEBUG_FLAG_EBC_BOK        (EFI_DEBUG_FLAG_EBC | EFI_DEBUG_FLAG_EBC_B_BOK)
+
+//
+// Debugger private data structure
+//
+typedef struct _EFI_DEBUGGER_PRIVATE_DATA {
+  UINT32                                      Signature;
+  EFI_INSTRUCTION_SET_ARCHITECTURE            Isa;
+  UINT32                                      EfiDebuggerRevision;
+  UINT32                                      EbcVmRevision;
+  EFI_DEBUG_IMAGE_INFO_TABLE_HEADER           *DebugImageInfoTableHeader;
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL             *Vol;
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL             *PciRootBridgeIo;
+  EFI_DEBUGGER_COMMAND_SET                    *DebuggerCommandSet;
+  EFI_DEBUGGER_SYMBOL_CONTEXT                 DebuggerSymbolContext;
+  UINTN                                       DebuggerBreakpointCount;
+  EFI_DEBUGGER_BREAKPOINT_CONTEXT             DebuggerBreakpointContext[EFI_DEBUGGER_BREAKPOINT_MAX + 1];
+  UINTN                                       CallStackEntryCount;
+  EFI_DEBUGGER_CALLSTACK_CONTEXT              CallStackEntry[EFI_DEBUGGER_CALLSTACK_MAX + 1];
+  UINTN                                       TraceEntryCount;
+  EFI_DEBUGGER_TRACE_CONTEXT                  TraceEntry[EFI_DEBUGGER_TRACE_MAX + 1];
+  EFI_DEBUGGER_STEP_CONTEXT                   StepContext;
+  EFI_DEBUGGER_GOTIL_CONTEXT                  GoTilContext;
+  EFI_PHYSICAL_ADDRESS                        InstructionScope;
+  UINTN                                       InstructionNumber;
+  UINT32                                      FeatureFlags;
+  UINT32                                      StatusFlags;
+  BOOLEAN                                     EnablePageBreak;
+  EFI_EVENT                                   BreakEvent;
+} EFI_DEBUGGER_PRIVATE_DATA;
+
+#endif
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbDisasm.c b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbDisasm.c
new file mode 100644
index 000000000000..1cbb29ce0bad
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbDisasm.c
@@ -0,0 +1,1907 @@
+/*++
+
+Copyright (c) 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.
+
+Module Name:
+
+  EdbDisasm.c
+
+Abstract:
+
+
+--*/
+
+#include "Edb.h"
+
+//
+// Debugger Disasm definition
+//
+#define EDB_DISASM_DEFINE(func) \
+UINTN \
+func ( \
+  IN     EFI_PHYSICAL_ADDRESS      InstructionAddress, \
+  IN     EFI_SYSTEM_CONTEXT        SystemContext, \
+  OUT    CHAR16                    **DisasmString \
+  )
+
+EDB_DISASM_DEFINE (EdbDisasmBREAK);
+EDB_DISASM_DEFINE (EdbDisasmJMP);
+EDB_DISASM_DEFINE (EdbDisasmJMP8);
+EDB_DISASM_DEFINE (EdbDisasmCALL);
+EDB_DISASM_DEFINE (EdbDisasmRET);
+EDB_DISASM_DEFINE (EdbDisasmCMP);
+EDB_DISASM_DEFINE (EdbDisasmUnsignedDataManip);
+EDB_DISASM_DEFINE (EdbDisasmSignedDataManip);
+EDB_DISASM_DEFINE (EdbDisasmMOVxx);
+EDB_DISASM_DEFINE (EdbDisasmMOVsnw);
+EDB_DISASM_DEFINE (EdbDisasmMOVsnd);
+EDB_DISASM_DEFINE (EdbDisasmLOADSP);
+EDB_DISASM_DEFINE (EdbDisasmSTORESP);
+EDB_DISASM_DEFINE (EdbDisasmPUSH);
+EDB_DISASM_DEFINE (EdbDisasmPOP);
+EDB_DISASM_DEFINE (EdbDisasmCMPI);
+EDB_DISASM_DEFINE (EdbDisasmPUSHn);
+EDB_DISASM_DEFINE (EdbDisasmPOPn);
+EDB_DISASM_DEFINE (EdbDisasmMOVI);
+EDB_DISASM_DEFINE (EdbDisasmMOVIn);
+EDB_DISASM_DEFINE (EdbDisasmMOVREL);
+
+//
+// Debugger Disasm Table
+//
+EDB_DISASM_INSTRUCTION mEdbDisasmInstructionTable[] = {
+  EdbDisasmBREAK,             // opcode 0x00 BREAK
+  EdbDisasmJMP,               // opcode 0x01 JMP
+  EdbDisasmJMP8,              // opcode 0x02 JMP8
+  EdbDisasmCALL,              // opcode 0x03 CALL
+  EdbDisasmRET,               // opcode 0x04 RET
+  EdbDisasmCMP,               // opcode 0x05 CMPEQ
+  EdbDisasmCMP,               // opcode 0x06 CMPLTE
+  EdbDisasmCMP,               // opcode 0x07 CMPGTE
+  EdbDisasmCMP,               // opcode 0x08 CMPULTE
+  EdbDisasmCMP,               // opcode 0x09 CMPUGTE
+  EdbDisasmUnsignedDataManip, // opcode 0x0A NOT
+  EdbDisasmSignedDataManip,   // opcode 0x0B NEG
+  EdbDisasmSignedDataManip,   // opcode 0x0C ADD
+  EdbDisasmSignedDataManip,   // opcode 0x0D SUB
+  EdbDisasmSignedDataManip,   // opcode 0x0E MUL
+  EdbDisasmUnsignedDataManip, // opcode 0x0F MULU
+  EdbDisasmSignedDataManip,   // opcode 0x10 DIV
+  EdbDisasmUnsignedDataManip, // opcode 0x11 DIVU
+  EdbDisasmSignedDataManip,   // opcode 0x12 MOD
+  EdbDisasmUnsignedDataManip, // opcode 0x13 MODU
+  EdbDisasmUnsignedDataManip, // opcode 0x14 AND
+  EdbDisasmUnsignedDataManip, // opcode 0x15 OR
+  EdbDisasmUnsignedDataManip, // opcode 0x16 XOR
+  EdbDisasmUnsignedDataManip, // opcode 0x17 SHL
+  EdbDisasmUnsignedDataManip, // opcode 0x18 SHR
+  EdbDisasmSignedDataManip,   // opcode 0x19 ASHR
+  EdbDisasmUnsignedDataManip, // opcode 0x1A EXTNDB
+  EdbDisasmUnsignedDataManip, // opcode 0x1B EXTNDW
+  EdbDisasmUnsignedDataManip, // opcode 0x1C EXTNDD
+  EdbDisasmMOVxx,             // opcode 0x1D MOVBW
+  EdbDisasmMOVxx,             // opcode 0x1E MOVWW
+  EdbDisasmMOVxx,             // opcode 0x1F MOVDW
+  EdbDisasmMOVxx,             // opcode 0x20 MOVQW
+  EdbDisasmMOVxx,             // opcode 0x21 MOVBD
+  EdbDisasmMOVxx,             // opcode 0x22 MOVWD
+  EdbDisasmMOVxx,             // opcode 0x23 MOVDD
+  EdbDisasmMOVxx,             // opcode 0x24 MOVQD
+  EdbDisasmMOVsnw,            // opcode 0x25 MOVSNW
+  EdbDisasmMOVsnd,            // opcode 0x26 MOVSND
+  NULL,                       // opcode 0x27
+  EdbDisasmMOVxx,             // opcode 0x28 MOVQQ
+  EdbDisasmLOADSP,            // opcode 0x29 LOADSP
+  EdbDisasmSTORESP,           // opcode 0x2A STORESP
+  EdbDisasmPUSH,              // opcode 0x2B PUSH
+  EdbDisasmPOP,               // opcode 0x2C POP
+  EdbDisasmCMPI,              // opcode 0x2D CMPIEQ
+  EdbDisasmCMPI,              // opcode 0x2E CMPILTE
+  EdbDisasmCMPI,              // opcode 0x2F CMPIGTE
+  EdbDisasmCMPI,              // opcode 0x30 CMPIULTE
+  EdbDisasmCMPI,              // opcode 0x31 CMPIUGTE
+  EdbDisasmMOVxx,             // opcode 0x32 MOVNW
+  EdbDisasmMOVxx,             // opcode 0x33 MOVND
+  NULL,                       // opcode 0x34
+  EdbDisasmPUSHn,             // opcode 0x35 PUSHN
+  EdbDisasmPOPn,              // opcode 0x36 POPN
+  EdbDisasmMOVI,              // opcode 0x37 MOVI
+  EdbDisasmMOVIn,             // opcode 0x38 MOVIN
+  EdbDisasmMOVREL,            // opcode 0x39 MOVREL
+};
+
+UINTN
+EdbDisasmBREAK (
+  IN     EFI_PHYSICAL_ADDRESS      InstructionAddress,
+  IN     EFI_SYSTEM_CONTEXT        SystemContext,
+  OUT    CHAR16                    **DisasmString
+  )
+/*++
+
+Routine Description:
+
+  Disasm instruction - BREAK
+
+Arguments:
+
+  InstructionAddress - The instruction address
+  SystemContext      - EBC system context.
+  DisasmString       - The instruction string
+
+Returns:
+
+  Instruction length
+
+--*/
+{
+  ASSERT (GET_OPCODE(InstructionAddress) == OPCODE_BREAK);
+
+  if (*(UINT8 *)(UINTN)(InstructionAddress + 1) > 6) {
+    return 0;
+  }
+
+  //
+  // Construct Disasm String
+  //
+  if (DisasmString != NULL) {
+    *DisasmString = EdbPreInstructionString ();
+
+    EdbPrintInstructionName (L"BREAK");
+    EdbPrintDatan (*(UINT8 *)(UINTN)(InstructionAddress + 1));
+
+    EdbPostInstructionString ();
+  }
+
+  return 2;
+}
+
+extern CONST UINT8                    mJMPLen[];
+
+UINTN
+EdbDisasmJMP (
+  IN     EFI_PHYSICAL_ADDRESS      InstructionAddress,
+  IN     EFI_SYSTEM_CONTEXT        SystemContext,
+  OUT    CHAR16                    **DisasmString
+  )
+/*++
+
+Routine Description:
+
+  Disasm instruction - JMP
+
+Arguments:
+
+  InstructionAddress - The instruction address
+  SystemContext      - EBC system context.
+  DisasmString       - The instruction string
+
+Returns:
+
+  Instruction length
+
+--*/
+{
+  UINT8   Modifiers;
+  UINT8   Operands;
+  UINTN   Size;
+  UINT32  Data32;
+  UINT64  Data64;
+
+  ASSERT (GET_OPCODE(InstructionAddress) == OPCODE_JMP);
+
+  Modifiers  = GET_MODIFIERS (InstructionAddress);
+  Operands   = GET_OPERANDS (InstructionAddress);
+  Size = (UINTN)mJMPLen[(Modifiers >> 6) & 0x03];
+
+  //
+  // Construct Disasm String
+  //
+  if (DisasmString != NULL) {
+    *DisasmString = EdbPreInstructionString ();
+
+    EdbPrintInstructionName (L"JMP");
+//    if (Modifiers & OPCODE_M_IMMDATA64) {
+//      EdbPrintInstructionName (L"64");
+//    } else {
+//      EdbPrintInstructionName (L"32");
+//    }
+    if (Modifiers & CONDITION_M_CONDITIONAL) {
+      if (Modifiers & JMP_M_CS) {
+        EdbPrintInstructionName (L"cs");
+      } else {
+        EdbPrintInstructionName (L"cc");
+      }
+    }
+
+    InstructionAddress += 2;
+    if (Modifiers & OPCODE_M_IMMDATA64) {
+      CopyMem (&Data64, (VOID *)(UINTN)(InstructionAddress), sizeof(UINT64));
+      if (Modifiers & OPCODE_M_IMMDATA) {
+        EdbPrintData64 (Data64);
+      } else {
+        return 0;
+      }
+    } else {
+      CopyMem (&Data32, (VOID *)(UINTN)(InstructionAddress), sizeof(UINT32));
+      EdbPrintRegister1 (Operands);
+
+      if ((Operands & OPERAND_M_INDIRECT1) == 0) {
+        if ((Modifiers & OPCODE_M_IMMDATA) == 0) {
+          Data32 = 0;
+        }
+        EdbPrintImmDatan (Data32);
+      } else {
+        EdbPrintRawIndexData32 (Data32);
+      }
+    }
+
+    EdbPostInstructionString ();
+  }
+
+  return Size;
+}
+
+UINTN
+EdbDisasmJMP8 (
+  IN     EFI_PHYSICAL_ADDRESS      InstructionAddress,
+  IN     EFI_SYSTEM_CONTEXT        SystemContext,
+  OUT    CHAR16                    **DisasmString
+  )
+/*++
+
+Routine Description:
+
+  Disasm instruction - JMP8
+
+Arguments:
+
+  InstructionAddress - The instruction address
+  SystemContext      - EBC system context.
+  DisasmString       - The instruction string
+
+Returns:
+
+  Instruction length
+
+--*/
+{
+  UINT8   Modifiers;
+
+  ASSERT (GET_OPCODE(InstructionAddress) == OPCODE_JMP8);
+  Modifiers  = GET_MODIFIERS (InstructionAddress);
+
+  //
+  // Construct Disasm String
+  //
+  if (DisasmString != NULL) {
+    *DisasmString = EdbPreInstructionString ();
+
+    EdbPrintInstructionName (L"JMP8");
+    if (Modifiers & CONDITION_M_CONDITIONAL) {
+      if (Modifiers & JMP_M_CS) {
+        EdbPrintInstructionName (L"cs");
+      } else {
+        EdbPrintInstructionName (L"cc");
+      }
+    }
+
+    EdbPrintData8 (*(UINT8 *)(UINTN)(InstructionAddress + 1));
+
+    EdbPostInstructionString ();
+  }
+
+  return 2;
+}
+
+UINTN
+EdbDisasmCALL (
+  IN     EFI_PHYSICAL_ADDRESS      InstructionAddress,
+  IN     EFI_SYSTEM_CONTEXT        SystemContext,
+  OUT    CHAR16                    **DisasmString
+  )
+/*++
+
+Routine Description:
+
+  Disasm instruction - CALL
+
+Arguments:
+
+  InstructionAddress - The instruction address
+  SystemContext      - EBC system context.
+  DisasmString       - The instruction string
+
+Returns:
+
+  Instruction length
+
+--*/
+{
+  UINT8   Modifiers;
+  UINT8   Operands;
+  UINTN   Size;
+  UINT32  Data32;
+  UINT64  Data64;
+  UINT64  Ip;
+  UINTN   Result;
+  EFI_PHYSICAL_ADDRESS      SavedInstructionAddress;
+
+  ASSERT (GET_OPCODE(InstructionAddress) == OPCODE_CALL);
+  SavedInstructionAddress = InstructionAddress;
+
+  Modifiers  = GET_MODIFIERS (InstructionAddress);
+  Operands   = GET_OPERANDS (InstructionAddress);
+  Size = (UINTN)mJMPLen[(Modifiers >> 6) & 0x03];
+
+  //
+  // Construct Disasm String
+  //
+  if (DisasmString != NULL) {
+    *DisasmString = EdbPreInstructionString ();
+
+    EdbPrintInstructionName (L"CALL");
+//    if (Modifiers & OPCODE_M_IMMDATA64) {
+//      EdbPrintInstructionName (L"64");
+//    } else {
+//      EdbPrintInstructionName (L"32");
+//    }
+    if (Operands & OPERAND_M_NATIVE_CALL) {
+      EdbPrintInstructionName (L"EX");
+    }
+//    if ((Operands & OPERAND_M_RELATIVE_ADDR) == 0) {
+//      EdbPrintInstructionName (L"a");
+//    }
+
+    InstructionAddress += 2;
+    if (Modifiers & OPCODE_M_IMMDATA64) {
+      CopyMem (&Data64, (VOID *)(UINTN)(InstructionAddress), sizeof(UINT64));
+      Ip = Data64;
+      if (Modifiers & OPCODE_M_IMMDATA) {
+        Result = EdbFindAndPrintSymbol ((UINTN)Ip);
+        if (Result == 0) {
+          EdbPrintData64 (Data64);
+        }
+      } else {
+        return 0;
+      }
+    } else {
+      if (Modifiers & OPCODE_M_IMMDATA) {
+        CopyMem (&Data32, (VOID *)(UINTN)(InstructionAddress), sizeof(UINT32));
+      } else {
+        Data32 = 0;
+      }
+
+      if ((Operands & OPERAND_M_OP1) == 0) {
+        Ip = (UINT64)Data32;
+      } else {
+        Ip = GetRegisterValue (SystemContext, (Operands & OPERAND_M_OP1));
+      }
+
+      if ((Operands & OPERAND_M_INDIRECT1) == 0) {
+        if (Operands & OPERAND_M_RELATIVE_ADDR) {
+          Result = EdbFindAndPrintSymbol ((UINTN)(SavedInstructionAddress + Ip + Size));
+        } else {
+          Result = EdbFindAndPrintSymbol ((UINTN)Ip);
+        }
+        if (Result == 0) {
+          EdbPrintRegister1 (Operands);
+          if (Modifiers & OPCODE_M_IMMDATA) {
+            EdbPrintImmData32 (Data32);
+          }
+        }
+      } else {
+        EdbPrintRegister1 (Operands);
+        if (Modifiers & OPCODE_M_IMMDATA) {
+          EdbPrintRawIndexData32 (Data32);
+        }
+      }
+    }
+
+    EdbPostInstructionString ();
+  }
+
+  return Size;
+}
+
+UINTN
+EdbDisasmRET (
+  IN     EFI_PHYSICAL_ADDRESS      InstructionAddress,
+  IN     EFI_SYSTEM_CONTEXT        SystemContext,
+  OUT    CHAR16                    **DisasmString
+  )
+/*++
+
+Routine Description:
+
+  Disasm instruction - RET
+
+Arguments:
+
+  InstructionAddress - The instruction address
+  SystemContext      - EBC system context.
+  DisasmString       - The instruction string
+
+Returns:
+
+  Instruction length
+
+--*/
+{
+  ASSERT (GET_OPCODE(InstructionAddress) == OPCODE_RET);
+
+  if (*(UINT8 *)(UINTN)(InstructionAddress + 1) != 0) {
+    return 0;
+  }
+
+  //
+  // Construct Disasm String
+  //
+  if (DisasmString != NULL) {
+    *DisasmString = EdbPreInstructionString ();
+
+    EdbPrintInstructionName (L"RET");
+
+    EdbPostInstructionString ();
+  }
+
+  return 2;
+}
+
+UINTN
+EdbDisasmCMP (
+  IN     EFI_PHYSICAL_ADDRESS      InstructionAddress,
+  IN     EFI_SYSTEM_CONTEXT        SystemContext,
+  OUT    CHAR16                    **DisasmString
+  )
+/*++
+
+Routine Description:
+
+  Disasm instruction - CMP
+
+Arguments:
+
+  InstructionAddress - The instruction address
+  SystemContext      - EBC system context.
+  DisasmString       - The instruction string
+
+Returns:
+
+  Instruction length
+
+--*/
+{
+  UINT8  Opcode;
+  UINT8  Modifiers;
+  UINT8  Operands;
+  UINT16 Data16;
+  UINTN  Size;
+
+  ASSERT (
+    (GET_OPCODE(InstructionAddress) == OPCODE_CMPEQ)   ||
+    (GET_OPCODE(InstructionAddress) == OPCODE_CMPLTE)  ||
+    (GET_OPCODE(InstructionAddress) == OPCODE_CMPGTE)  ||
+    (GET_OPCODE(InstructionAddress) == OPCODE_CMPULTE) ||
+    (GET_OPCODE(InstructionAddress) == OPCODE_CMPUGTE)
+    );
+
+  Opcode     = GET_OPCODE (InstructionAddress);
+  Modifiers  = GET_MODIFIERS (InstructionAddress);
+  Operands   = GET_OPERANDS (InstructionAddress);
+  if (Modifiers & OPCODE_M_IMMDATA) {
+    Size = 4;
+  } else {
+    Size = 2;
+  }
+
+  //
+  // Construct Disasm String
+  //
+  if (DisasmString != NULL) {
+    *DisasmString = EdbPreInstructionString ();
+
+    EdbPrintInstructionName (L"CMP");
+//    if (Modifiers & OPCODE_M_64BIT) {
+//      EdbPrintInstructionName (L"64");
+//    } else {
+//      EdbPrintInstructionName (L"32");
+//    }
+    switch (Opcode) {
+    case OPCODE_CMPEQ:
+      EdbPrintInstructionName (L"eq");
+      break;
+    case OPCODE_CMPLTE:
+      EdbPrintInstructionName (L"lte");
+      break;
+    case OPCODE_CMPGTE:
+      EdbPrintInstructionName (L"gte");
+      break;
+    case OPCODE_CMPULTE:
+      EdbPrintInstructionName (L"ulte");
+      break;
+    case OPCODE_CMPUGTE:
+      EdbPrintInstructionName (L"ugte");
+      break;
+    }
+
+    EdbPrintRegister1 (Operands);
+    InstructionAddress += 2;
+
+    EdbPrintComma ();
+    EdbPrintRegister2 (Operands);
+
+    if (Modifiers & OPCODE_M_IMMDATA) {
+      CopyMem (&Data16, (VOID *)(UINTN)(InstructionAddress), sizeof(UINT16));
+      if (Operands & OPERAND_M_INDIRECT2) {
+        EdbPrintRawIndexData16 (Data16);
+      } else {
+        EdbPrintImmDatan (Data16);
+      }
+    }
+
+    EdbPostInstructionString ();
+  }
+
+  return Size;
+}
+
+UINTN
+EdbDisasmUnsignedDataManip (
+  IN     EFI_PHYSICAL_ADDRESS      InstructionAddress,
+  IN     EFI_SYSTEM_CONTEXT        SystemContext,
+  OUT    CHAR16                    **DisasmString
+  )
+/*++
+
+Routine Description:
+
+  Disasm instruction - Unsigned Data Manipulate
+
+Arguments:
+
+  InstructionAddress - The instruction address
+  SystemContext      - EBC system context.
+  DisasmString       - The instruction string
+
+Returns:
+
+  Instruction length
+
+--*/
+{
+  UINT8  Modifiers;
+  UINT8  Opcode;
+  UINT8  Operands;
+  UINTN  Size;
+  UINT16 Data16;
+
+  ASSERT (
+    (GET_OPCODE(InstructionAddress) == OPCODE_NOT)    ||
+    (GET_OPCODE(InstructionAddress) == OPCODE_MULU)   ||
+    (GET_OPCODE(InstructionAddress) == OPCODE_DIVU)   ||
+    (GET_OPCODE(InstructionAddress) == OPCODE_MODU)   ||
+    (GET_OPCODE(InstructionAddress) == OPCODE_AND)    ||
+    (GET_OPCODE(InstructionAddress) == OPCODE_OR)     ||
+    (GET_OPCODE(InstructionAddress) == OPCODE_XOR)    ||
+    (GET_OPCODE(InstructionAddress) == OPCODE_SHL)    ||
+    (GET_OPCODE(InstructionAddress) == OPCODE_SHR)    ||
+    (GET_OPCODE(InstructionAddress) == OPCODE_EXTNDB) ||
+    (GET_OPCODE(InstructionAddress) == OPCODE_EXTNDW) ||
+    (GET_OPCODE(InstructionAddress) == OPCODE_EXTNDD)
+    );
+
+  Opcode     = GET_OPCODE (InstructionAddress);
+  Operands   = GET_OPERANDS (InstructionAddress);
+  Modifiers  = GET_MODIFIERS (InstructionAddress);
+  if (Modifiers & DATAMANIP_M_IMMDATA) {
+    Size = 4;
+  } else {
+    Size = 2;
+  }
+
+  //
+  // Construct Disasm String
+  //
+  if (DisasmString != NULL) {
+    *DisasmString = EdbPreInstructionString ();
+
+    switch (Opcode) {
+    case OPCODE_NOT:
+      EdbPrintInstructionName (L"NOT");
+      break;
+    case OPCODE_MULU:
+      EdbPrintInstructionName (L"MULU");
+      break;
+    case OPCODE_DIVU:
+      EdbPrintInstructionName (L"DIVU");
+      break;
+    case OPCODE_MODU:
+      EdbPrintInstructionName (L"MODU");
+      break;
+    case OPCODE_AND:
+      EdbPrintInstructionName (L"AND");
+      break;
+    case OPCODE_OR:
+      EdbPrintInstructionName (L"OR");
+      break;
+    case OPCODE_XOR:
+      EdbPrintInstructionName (L"XOR");
+      break;
+    case OPCODE_SHL:
+      EdbPrintInstructionName (L"SHL");
+      break;
+    case OPCODE_SHR:
+      EdbPrintInstructionName (L"SHR");
+      break;
+    case OPCODE_EXTNDB:
+      EdbPrintInstructionName (L"EXTNDB");
+      break;
+    case OPCODE_EXTNDW:
+      EdbPrintInstructionName (L"EXTNDW");
+      break;
+    case OPCODE_EXTNDD:
+      EdbPrintInstructionName (L"EXTNDD");
+      break;
+    }
+//    if (Modifiers & DATAMANIP_M_64) {
+//      EdbPrintInstructionName (L"64");
+//    } else {
+//      EdbPrintInstructionName (L"32");
+//    }
+
+    EdbPrintRegister1 (Operands);
+    EdbPrintComma ();
+    EdbPrintRegister2 (Operands);
+
+    InstructionAddress += 2;
+    if (Modifiers & DATAMANIP_M_IMMDATA) {
+      CopyMem (&Data16, (VOID *)(UINTN)(InstructionAddress), sizeof(UINT16));
+      if (Operands & OPERAND_M_INDIRECT2) {
+        EdbPrintRawIndexData16 (Data16);
+      } else {
+        EdbPrintImmDatan (Data16);
+      }
+    }
+
+    EdbPostInstructionString ();
+  }
+
+  return Size;
+}
+
+UINTN
+EdbDisasmSignedDataManip (
+  IN     EFI_PHYSICAL_ADDRESS      InstructionAddress,
+  IN     EFI_SYSTEM_CONTEXT        SystemContext,
+  OUT    CHAR16                    **DisasmString
+  )
+/*++
+
+Routine Description:
+
+  Disasm instruction - Signed Data Manipulate
+
+Arguments:
+
+  InstructionAddress - The instruction address
+  SystemContext      - EBC system context.
+  DisasmString       - The instruction string
+
+Returns:
+
+  Instruction length
+
+--*/
+{
+  UINT8  Modifiers;
+  UINT8  Opcode;
+  UINT8  Operands;
+  UINTN  Size;
+  UINT16 Data16;
+
+  ASSERT (
+    (GET_OPCODE(InstructionAddress) == OPCODE_NEG)   ||
+    (GET_OPCODE(InstructionAddress) == OPCODE_ADD)   ||
+    (GET_OPCODE(InstructionAddress) == OPCODE_SUB)   ||
+    (GET_OPCODE(InstructionAddress) == OPCODE_MUL)   ||
+    (GET_OPCODE(InstructionAddress) == OPCODE_DIV)   ||
+    (GET_OPCODE(InstructionAddress) == OPCODE_MOD)   ||
+    (GET_OPCODE(InstructionAddress) == OPCODE_ASHR)
+    );
+
+  Opcode     = GET_OPCODE (InstructionAddress);
+  Operands   = GET_OPERANDS (InstructionAddress);
+  Modifiers  = GET_MODIFIERS (InstructionAddress);
+  if (Modifiers & DATAMANIP_M_IMMDATA) {
+    Size = 4;
+  } else {
+    Size = 2;
+  }
+
+  //
+  // Construct Disasm String
+  //
+  if (DisasmString != NULL) {
+    *DisasmString = EdbPreInstructionString ();
+
+    switch (Opcode) {
+    case OPCODE_NEG:
+      EdbPrintInstructionName (L"NEG");
+      break;
+    case OPCODE_ADD:
+      EdbPrintInstructionName (L"ADD");
+      break;
+    case OPCODE_SUB:
+      EdbPrintInstructionName (L"SUB");
+      break;
+    case OPCODE_MUL:
+      EdbPrintInstructionName (L"MUL");
+      break;
+    case OPCODE_DIV:
+      EdbPrintInstructionName (L"DIV");
+      break;
+    case OPCODE_MOD:
+      EdbPrintInstructionName (L"MOD");
+      break;
+    case OPCODE_ASHR:
+      EdbPrintInstructionName (L"ASHR");
+      break;
+    }
+//    if (Modifiers & DATAMANIP_M_64) {
+//      EdbPrintInstructionName (L"64");
+//    } else {
+//      EdbPrintInstructionName (L"32");
+//    }
+
+    EdbPrintRegister1 (Operands);
+    EdbPrintComma ();
+    EdbPrintRegister2 (Operands);
+
+    InstructionAddress += 2;
+    if (Modifiers & DATAMANIP_M_IMMDATA) {
+      CopyMem (&Data16, (VOID *)(UINTN)(InstructionAddress), sizeof(UINT16));
+      if (Operands & OPERAND_M_INDIRECT2) {
+        EdbPrintRawIndexData16 (Data16);
+      } else {
+        EdbPrintImmDatan (Data16);
+      }
+    }
+
+    EdbPostInstructionString ();
+  }
+
+  return Size;
+}
+
+UINTN
+EdbDisasmMOVxx (
+  IN     EFI_PHYSICAL_ADDRESS      InstructionAddress,
+  IN     EFI_SYSTEM_CONTEXT        SystemContext,
+  OUT    CHAR16                    **DisasmString
+  )
+/*++
+
+Routine Description:
+
+  Disasm instruction - MOVxx
+
+Arguments:
+
+  InstructionAddress - The instruction address
+  SystemContext      - EBC system context.
+  DisasmString       - The instruction string
+
+Returns:
+
+  Instruction length
+
+--*/
+{
+  UINT8   Modifiers;
+  UINT8   Opcode;
+  UINT8   Operands;
+  UINTN   Size;
+  UINT16  Data16;
+  UINT32  Data32;
+  UINT64  Data64;
+
+  ASSERT (
+    (GET_OPCODE(InstructionAddress) == OPCODE_MOVBW)   ||
+    (GET_OPCODE(InstructionAddress) == OPCODE_MOVWW)   ||
+    (GET_OPCODE(InstructionAddress) == OPCODE_MOVDW)   ||
+    (GET_OPCODE(InstructionAddress) == OPCODE_MOVQW)   ||
+    (GET_OPCODE(InstructionAddress) == OPCODE_MOVBD)   ||
+    (GET_OPCODE(InstructionAddress) == OPCODE_MOVWD)   ||
+    (GET_OPCODE(InstructionAddress) == OPCODE_MOVDD)   ||
+    (GET_OPCODE(InstructionAddress) == OPCODE_MOVQD)   ||
+    (GET_OPCODE(InstructionAddress) == OPCODE_MOVQQ)   ||
+    (GET_OPCODE(InstructionAddress) == OPCODE_MOVNW)   ||
+    (GET_OPCODE(InstructionAddress) == OPCODE_MOVND)
+    );
+
+  Opcode     = GET_OPCODE (InstructionAddress);
+  Modifiers  = GET_MODIFIERS (InstructionAddress);
+  Operands   = GET_OPERANDS (InstructionAddress);
+  Size = 2;
+  if (Modifiers & (OPCODE_M_IMMED_OP1 | OPCODE_M_IMMED_OP2)) {
+    if ((Opcode <= OPCODE_MOVQW) || (Opcode == OPCODE_MOVNW)) {
+      if (Modifiers & OPCODE_M_IMMED_OP1) {
+        Size += 2;
+      }
+      if (Modifiers & OPCODE_M_IMMED_OP2) {
+        Size += 2;
+      }
+    } else if ((Opcode <= OPCODE_MOVQD) || (Opcode == OPCODE_MOVND)) {
+      if (Modifiers & OPCODE_M_IMMED_OP1) {
+        Size += 4;
+      }
+      if (Modifiers & OPCODE_M_IMMED_OP2) {
+        Size += 4;
+      }
+    } else if (Opcode == OPCODE_MOVQQ) {
+      if (Modifiers & OPCODE_M_IMMED_OP1) {
+        Size += 8;
+      }
+      if (Modifiers & OPCODE_M_IMMED_OP2) {
+        Size += 8;
+      }
+    }
+  }
+
+  //
+  // Construct Disasm String
+  //
+  if (DisasmString != NULL) {
+    *DisasmString = EdbPreInstructionString ();
+
+    EdbPrintInstructionName (L"MOV");
+    switch (Opcode) {
+    case OPCODE_MOVBW:
+      EdbPrintInstructionName (L"bw");
+      break;
+    case OPCODE_MOVWW:
+      EdbPrintInstructionName (L"ww");
+      break;
+    case OPCODE_MOVDW:
+      EdbPrintInstructionName (L"dw");
+      break;
+    case OPCODE_MOVQW:
+      EdbPrintInstructionName (L"qw");
+      break;
+    case OPCODE_MOVBD:
+      EdbPrintInstructionName (L"bd");
+      break;
+    case OPCODE_MOVWD:
+      EdbPrintInstructionName (L"wd");
+      break;
+    case OPCODE_MOVDD:
+      EdbPrintInstructionName (L"dd");
+      break;
+    case OPCODE_MOVQD:
+      EdbPrintInstructionName (L"qd");
+      break;
+    case OPCODE_MOVQQ:
+      EdbPrintInstructionName (L"qq");
+      break;
+    case OPCODE_MOVNW:
+      EdbPrintInstructionName (L"nw");
+      break;
+    case OPCODE_MOVND:
+      EdbPrintInstructionName (L"nd");
+      break;
+    }
+
+    EdbPrintRegister1 (Operands);
+
+    InstructionAddress += 2;
+    if (Modifiers & OPCODE_M_IMMED_OP1) {
+      if ((Opcode <= OPCODE_MOVQW) || (Opcode == OPCODE_MOVNW)) {
+        CopyMem (&Data16, (VOID *)(UINTN)(InstructionAddress), sizeof(UINT16));
+        InstructionAddress += 2;
+        EdbPrintRawIndexData16 (Data16);
+      } else if ((Opcode <= OPCODE_MOVQD) || (Opcode == OPCODE_MOVND)) {
+        CopyMem (&Data32, (VOID *)(UINTN)(InstructionAddress), sizeof(UINT32));
+        InstructionAddress += 4;
+        EdbPrintRawIndexData32 (Data32);
+      } else if (Opcode == OPCODE_MOVQQ) {
+        CopyMem (&Data64, (VOID *)(UINTN)(InstructionAddress), sizeof(UINT64));
+        InstructionAddress += 8;
+        EdbPrintRawIndexData64 (Data64);
+      }
+    }
+
+    EdbPrintComma ();
+    EdbPrintRegister2 (Operands);
+
+    if (Modifiers & OPCODE_M_IMMED_OP2) {
+      if ((Opcode <= OPCODE_MOVQW) || (Opcode == OPCODE_MOVNW)) {
+        CopyMem (&Data16, (VOID *)(UINTN)(InstructionAddress), sizeof(UINT16));
+        EdbPrintRawIndexData16 (Data16);
+      } else if ((Opcode <= OPCODE_MOVQD) || (Opcode == OPCODE_MOVND)) {
+        CopyMem (&Data32, (VOID *)(UINTN)(InstructionAddress), sizeof(UINT32));
+        EdbPrintRawIndexData32 (Data32);
+      } else if (Opcode == OPCODE_MOVQQ) {
+        CopyMem (&Data64, (VOID *)(UINTN)(InstructionAddress), sizeof(UINT64));
+        EdbPrintRawIndexData64 (Data64);
+      }
+    }
+
+    EdbPostInstructionString ();
+  }
+
+  return Size;
+}
+
+UINTN
+EdbDisasmMOVsnw (
+  IN     EFI_PHYSICAL_ADDRESS      InstructionAddress,
+  IN     EFI_SYSTEM_CONTEXT        SystemContext,
+  OUT    CHAR16                    **DisasmString
+  )
+/*++
+
+Routine Description:
+
+  Disasm instruction - MOVsnw
+
+Arguments:
+
+  InstructionAddress - The instruction address
+  SystemContext      - EBC system context.
+  DisasmString       - The instruction string
+
+Returns:
+
+  Instruction length
+
+--*/
+{
+  UINT8  Modifiers;
+  UINT8  Operands;
+  UINTN  Size;
+  UINT16 Data16;
+
+  ASSERT (GET_OPCODE(InstructionAddress) == OPCODE_MOVSNW);
+
+  Modifiers  = GET_MODIFIERS (InstructionAddress);
+  Operands   = GET_OPERANDS (InstructionAddress);
+  Size = 2;
+  if (Modifiers & OPCODE_M_IMMED_OP1) {
+    Size += 2;
+  }
+  if (Modifiers & OPCODE_M_IMMED_OP2) {
+    Size += 2;
+  }
+
+  //
+  // Construct Disasm String
+  //
+  if (DisasmString != NULL) {
+    *DisasmString = EdbPreInstructionString ();
+
+    EdbPrintInstructionName (L"MOVsnw");
+
+    EdbPrintRegister1 (Operands);
+
+    InstructionAddress += 2;
+    if (Modifiers & OPCODE_M_IMMED_OP1) {
+      CopyMem (&Data16, (VOID *)(UINTN)(InstructionAddress), sizeof(UINT16));
+      InstructionAddress += 2;
+      EdbPrintRawIndexData16 (Data16);
+    }
+
+    EdbPrintComma ();
+    EdbPrintRegister2 (Operands);
+
+    if (Modifiers & OPCODE_M_IMMED_OP2) {
+      CopyMem (&Data16, (VOID *)(UINTN)(InstructionAddress), sizeof(UINT16));
+      if (Operands & OPERAND_M_INDIRECT2) {
+        EdbPrintRawIndexData16 (Data16);
+      } else {
+        EdbPrintImmDatan (Data16);
+      }
+    }
+
+    EdbPostInstructionString ();
+  }
+
+  return Size;
+}
+
+UINTN
+EdbDisasmMOVsnd (
+  IN     EFI_PHYSICAL_ADDRESS      InstructionAddress,
+  IN     EFI_SYSTEM_CONTEXT        SystemContext,
+  OUT    CHAR16                    **DisasmString
+  )
+/*++
+
+Routine Description:
+
+  Disasm instruction - MOVsnd
+
+Arguments:
+
+  InstructionAddress - The instruction address
+  SystemContext      - EBC system context.
+  DisasmString       - The instruction string
+
+Returns:
+
+  Instruction length
+
+--*/
+{
+  UINT8  Modifiers;
+  UINT8  Operands;
+  UINTN  Size;
+  UINT32 Data32;
+
+  ASSERT (GET_OPCODE(InstructionAddress) == OPCODE_MOVSND);
+
+  Modifiers  = GET_MODIFIERS (InstructionAddress);
+  Operands   = GET_OPERANDS (InstructionAddress);
+  Size = 2;
+  if (Modifiers & OPCODE_M_IMMED_OP1) {
+    Size += 4;
+  }
+  if (Modifiers & OPCODE_M_IMMED_OP2) {
+    Size += 4;
+  }
+
+  //
+  // Construct Disasm String
+  //
+  if (DisasmString != NULL) {
+    *DisasmString = EdbPreInstructionString ();
+
+    EdbPrintInstructionName (L"MOVsnd");
+
+    EdbPrintRegister1 (Operands);
+
+    InstructionAddress += 2;
+    if (Modifiers & OPCODE_M_IMMED_OP1) {
+      CopyMem (&Data32, (VOID *)(UINTN)(InstructionAddress), sizeof(UINT32));
+      InstructionAddress += 4;
+      EdbPrintRawIndexData32 (Data32);
+    }
+
+    EdbPrintComma ();
+    EdbPrintRegister2 (Operands);
+
+    if (Modifiers & OPCODE_M_IMMED_OP2) {
+      CopyMem (&Data32, (VOID *)(UINTN)(InstructionAddress), sizeof(UINT32));
+      if (Operands & OPERAND_M_INDIRECT2) {
+        EdbPrintRawIndexData32 (Data32);
+      } else {
+        EdbPrintImmDatan (Data32);
+      }
+    }
+
+    EdbPostInstructionString ();
+  }
+
+  return Size;
+}
+
+UINTN
+EdbDisasmLOADSP (
+  IN     EFI_PHYSICAL_ADDRESS      InstructionAddress,
+  IN     EFI_SYSTEM_CONTEXT        SystemContext,
+  OUT    CHAR16                    **DisasmString
+  )
+/*++
+
+Routine Description:
+
+  Disasm instruction - LOADSP
+
+Arguments:
+
+  InstructionAddress - The instruction address
+  SystemContext      - EBC system context.
+  DisasmString       - The instruction string
+
+Returns:
+
+  Instruction length
+
+--*/
+{
+  UINT8  Operands;
+
+  ASSERT (GET_OPCODE(InstructionAddress) == OPCODE_LOADSP);
+
+  Operands   = GET_OPERANDS (InstructionAddress);
+
+  //
+  // Construct Disasm String
+  //
+  if (DisasmString != NULL) {
+    *DisasmString = EdbPreInstructionString ();
+
+    EdbPrintInstructionName (L"LOADSP");
+
+    EdbPrintDedicatedRegister1 (Operands);
+
+    EdbPrintRegister2 (Operands);
+
+    EdbPostInstructionString ();
+  }
+
+  return 2;
+}
+
+UINTN
+EdbDisasmSTORESP (
+  IN     EFI_PHYSICAL_ADDRESS      InstructionAddress,
+  IN     EFI_SYSTEM_CONTEXT        SystemContext,
+  OUT    CHAR16                    **DisasmString
+  )
+/*++
+
+Routine Description:
+
+  Disasm instruction - STORESP
+
+Arguments:
+
+  InstructionAddress - The instruction address
+  SystemContext      - EBC system context.
+  DisasmString       - The instruction string
+
+Returns:
+
+  Instruction length
+
+--*/
+{
+  UINT8  Operands;
+
+  ASSERT (GET_OPCODE(InstructionAddress) == OPCODE_STORESP);
+
+  Operands   = GET_OPERANDS (InstructionAddress);
+
+  //
+  // Construct Disasm String
+  //
+  if (DisasmString != NULL) {
+    *DisasmString = EdbPreInstructionString ();
+
+    EdbPrintInstructionName (L"STORESP");
+
+    EdbPrintRegister1 (Operands);
+
+    EdbPrintDedicatedRegister2 (Operands);
+
+    EdbPostInstructionString ();
+  }
+
+  return 2;
+}
+
+UINTN
+EdbDisasmPUSH (
+  IN     EFI_PHYSICAL_ADDRESS      InstructionAddress,
+  IN     EFI_SYSTEM_CONTEXT        SystemContext,
+  OUT    CHAR16                    **DisasmString
+  )
+/*++
+
+Routine Description:
+
+  Disasm instruction - PUSH
+
+Arguments:
+
+  InstructionAddress - The instruction address
+  SystemContext      - EBC system context.
+  DisasmString       - The instruction string
+
+Returns:
+
+  Instruction length
+
+--*/
+{
+  UINT8  Modifiers;
+  UINT8  Operands;
+  UINTN  Size;
+  UINT16 Data16;
+
+  ASSERT (GET_OPCODE(InstructionAddress) == OPCODE_PUSH);
+
+  Operands   = GET_OPERANDS (InstructionAddress);
+  Modifiers  = GET_MODIFIERS (InstructionAddress);
+  if (Modifiers & PUSHPOP_M_IMMDATA) {
+    Size = 4;
+  } else {
+    Size = 2;
+  }
+
+  //
+  // Construct Disasm String
+  //
+  if (DisasmString != NULL) {
+    *DisasmString = EdbPreInstructionString ();
+
+    EdbPrintInstructionName (L"PUSH");
+//    if (Modifiers & PUSHPOP_M_64) {
+//      EdbPrintInstructionName (L"64");
+//    } else {
+//      EdbPrintInstructionName (L"32");
+//    }
+
+    EdbPrintRegister1 (Operands);
+
+    InstructionAddress += 2;
+    if (Modifiers & PUSHPOP_M_IMMDATA) {
+      CopyMem (&Data16, (VOID *)(UINTN)(InstructionAddress), sizeof(UINT16));
+      if (Operands & OPERAND_M_INDIRECT1) {
+        EdbPrintRawIndexData16 (Data16);
+      } else {
+        EdbPrintImmDatan (Data16);
+      }
+    }
+
+    EdbPostInstructionString ();
+  }
+
+  return Size;
+}
+
+UINTN
+EdbDisasmPOP (
+  IN     EFI_PHYSICAL_ADDRESS      InstructionAddress,
+  IN     EFI_SYSTEM_CONTEXT        SystemContext,
+  OUT    CHAR16                    **DisasmString
+  )
+/*++
+
+Routine Description:
+
+  Disasm instruction - POP
+
+Arguments:
+
+  InstructionAddress - The instruction address
+  SystemContext      - EBC system context.
+  DisasmString       - The instruction string
+
+Returns:
+
+  Instruction length
+
+--*/
+{
+  UINT8  Modifiers;
+  UINT8  Operands;
+  UINTN  Size;
+  UINT16 Data16;
+
+  ASSERT (GET_OPCODE(InstructionAddress) == OPCODE_POP);
+
+  Operands   = GET_OPERANDS (InstructionAddress);
+  Modifiers  = GET_MODIFIERS (InstructionAddress);
+  if (Modifiers & PUSHPOP_M_IMMDATA) {
+    Size = 4;
+  } else {
+    Size = 2;
+  }
+
+  //
+  // Construct Disasm String
+  //
+  if (DisasmString != NULL) {
+    *DisasmString = EdbPreInstructionString ();
+
+    EdbPrintInstructionName (L"POP");
+//    if (Modifiers & PUSHPOP_M_64) {
+//      EdbPrintInstructionName (L"64");
+//    } else {
+//      EdbPrintInstructionName (L"32");
+//    }
+
+    EdbPrintRegister1 (Operands);
+
+    InstructionAddress += 2;
+    if (Modifiers & PUSHPOP_M_IMMDATA) {
+      CopyMem (&Data16, (VOID *)(UINTN)(InstructionAddress), sizeof(UINT16));
+      if (Operands & OPERAND_M_INDIRECT1) {
+        EdbPrintRawIndexData16 (Data16);
+      } else {
+        EdbPrintImmDatan (Data16);
+      }
+    }
+
+    EdbPostInstructionString ();
+  }
+
+  return Size;
+}
+
+UINTN
+EdbDisasmCMPI (
+  IN     EFI_PHYSICAL_ADDRESS      InstructionAddress,
+  IN     EFI_SYSTEM_CONTEXT        SystemContext,
+  OUT    CHAR16                    **DisasmString
+  )
+/*++
+
+Routine Description:
+
+  Disasm instruction - CMPI
+
+Arguments:
+
+  InstructionAddress - The instruction address
+  SystemContext      - EBC system context.
+  DisasmString       - The instruction string
+
+Returns:
+
+  Instruction length
+
+--*/
+{
+  UINT8  Modifiers;
+  UINT8  Opcode;
+  UINT8  Operands;
+  UINT16 Data16;
+  UINT32 Data32;
+  UINTN  Size;
+
+  ASSERT (
+    (GET_OPCODE(InstructionAddress) == OPCODE_CMPIEQ)   ||
+    (GET_OPCODE(InstructionAddress) == OPCODE_CMPILTE)  ||
+    (GET_OPCODE(InstructionAddress) == OPCODE_CMPIGTE)  ||
+    (GET_OPCODE(InstructionAddress) == OPCODE_CMPIULTE) ||
+    (GET_OPCODE(InstructionAddress) == OPCODE_CMPIUGTE)
+    );
+
+  Modifiers  = GET_MODIFIERS (InstructionAddress);
+  Opcode     = GET_OPCODE (InstructionAddress);
+  Operands   = GET_OPERANDS (InstructionAddress);
+
+  if ((Operands & 0xE0) != 0) {
+    return 0;
+  }
+
+  Size = 2;
+  if (Operands & OPERAND_M_CMPI_INDEX) {
+    Size += 2;
+  }
+  if (Modifiers & OPCODE_M_CMPI32_DATA) {
+    Size += 4;
+  } else {
+    Size += 2;
+  }
+
+  //
+  // Construct Disasm String
+  //
+  if (DisasmString != NULL) {
+    *DisasmString = EdbPreInstructionString ();
+
+    EdbPrintInstructionName (L"CMPI");
+//    if (Modifiers & OPCODE_M_CMPI64) {
+//      EdbPrintInstructionName (L"64");
+//    } else {
+//      EdbPrintInstructionName (L"32");
+//    }
+    if (Modifiers & OPCODE_M_CMPI32_DATA) {
+      EdbPrintInstructionName (L"d");
+    } else {
+      EdbPrintInstructionName (L"w");
+    }
+    switch (Opcode) {
+    case OPCODE_CMPIEQ:
+      EdbPrintInstructionName (L"eq");
+      break;
+    case OPCODE_CMPILTE:
+      EdbPrintInstructionName (L"lte");
+      break;
+    case OPCODE_CMPIGTE:
+      EdbPrintInstructionName (L"gte");
+      break;
+    case OPCODE_CMPIULTE:
+      EdbPrintInstructionName (L"ulte");
+      break;
+    case OPCODE_CMPIUGTE:
+      EdbPrintInstructionName (L"ugte");
+      break;
+    }
+
+    EdbPrintRegister1 (Operands);
+
+    InstructionAddress += 2;
+    if (Operands & OPERAND_M_CMPI_INDEX) {
+      CopyMem (&Data16, (VOID *)(UINTN)(InstructionAddress), sizeof(UINT16));
+      InstructionAddress += 2;
+      EdbPrintRawIndexData16 (Data16);
+    }
+
+    EdbPrintComma ();
+
+    if (Modifiers & OPCODE_M_CMPI32_DATA) {
+      CopyMem (&Data32, (VOID *)(UINTN)(InstructionAddress), sizeof(UINT32));
+      EdbPrintDatan (Data32);
+    } else {
+      CopyMem (&Data16, (VOID *)(UINTN)(InstructionAddress), sizeof(UINT16));
+      EdbPrintDatan (Data16);
+    }
+
+    EdbPostInstructionString ();
+  }
+
+  return Size;
+}
+
+UINTN
+EdbDisasmPUSHn (
+  IN     EFI_PHYSICAL_ADDRESS      InstructionAddress,
+  IN     EFI_SYSTEM_CONTEXT        SystemContext,
+  OUT    CHAR16                    **DisasmString
+  )
+/*++
+
+Routine Description:
+
+  Disasm instruction - PUSHn
+
+Arguments:
+
+  InstructionAddress - The instruction address
+  SystemContext      - EBC system context.
+  DisasmString       - The instruction string
+
+Returns:
+
+  Instruction length
+
+--*/
+{
+  UINT8  Modifiers;
+  UINT8  Operands;
+  UINTN  Size;
+  UINT16 Data16;
+
+  ASSERT (GET_OPCODE(InstructionAddress) == OPCODE_PUSHN);
+
+  Operands   = GET_OPERANDS (InstructionAddress);
+  Modifiers  = GET_MODIFIERS (InstructionAddress);
+  if (Modifiers & PUSHPOP_M_IMMDATA) {
+    Size = 4;
+  } else {
+    Size = 2;
+  }
+
+  //
+  // Construct Disasm String
+  //
+  if (DisasmString != NULL) {
+    *DisasmString = EdbPreInstructionString ();
+
+    EdbPrintInstructionName (L"PUSHn");
+
+    EdbPrintRegister1 (Operands);
+
+    InstructionAddress += 2;
+    if (Modifiers & PUSHPOP_M_IMMDATA) {
+      CopyMem (&Data16, (VOID *)(UINTN)(InstructionAddress), sizeof(UINT16));
+      if (Operands & OPERAND_M_INDIRECT1) {
+        EdbPrintRawIndexData16 (Data16);
+      } else {
+        EdbPrintImmDatan (Data16);
+      }
+    }
+
+    EdbPostInstructionString ();
+  }
+
+  return Size;
+}
+
+UINTN
+EdbDisasmPOPn (
+  IN     EFI_PHYSICAL_ADDRESS      InstructionAddress,
+  IN     EFI_SYSTEM_CONTEXT        SystemContext,
+  OUT    CHAR16                    **DisasmString
+  )
+/*++
+
+Routine Description:
+
+  Disasm instruction - POPn
+
+Arguments:
+
+  InstructionAddress - The instruction address
+  SystemContext      - EBC system context.
+  DisasmString       - The instruction string
+
+Returns:
+
+  Instruction length
+
+--*/
+{
+  UINT8  Modifiers;
+  UINT8  Operands;
+  UINTN  Size;
+  UINT16 Data16;
+
+  ASSERT (GET_OPCODE(InstructionAddress) == OPCODE_POPN);
+
+  Operands   = GET_OPERANDS (InstructionAddress);
+  Modifiers  = GET_MODIFIERS (InstructionAddress);
+  if (Modifiers & PUSHPOP_M_IMMDATA) {
+    Size = 4;
+  } else {
+    Size = 2;
+  }
+
+  //
+  // Construct Disasm String
+  //
+  if (DisasmString != NULL) {
+    *DisasmString = EdbPreInstructionString ();
+
+    EdbPrintInstructionName (L"POPn");
+
+    EdbPrintRegister1 (Operands);
+
+    InstructionAddress += 2;
+    if (Modifiers & PUSHPOP_M_IMMDATA) {
+      CopyMem (&Data16, (VOID *)(UINTN)(InstructionAddress), sizeof(UINT16));
+      if (Operands & OPERAND_M_INDIRECT1) {
+        EdbPrintRawIndexData16 (Data16);
+      } else {
+        EdbPrintImmDatan (Data16);
+      }
+    }
+
+    EdbPostInstructionString ();
+  }
+
+  return Size;
+}
+
+UINTN
+EdbDisasmMOVI (
+  IN     EFI_PHYSICAL_ADDRESS      InstructionAddress,
+  IN     EFI_SYSTEM_CONTEXT        SystemContext,
+  OUT    CHAR16                    **DisasmString
+  )
+/*++
+
+Routine Description:
+
+  Disasm instruction - MOVI
+
+Arguments:
+
+  InstructionAddress - The instruction address
+  SystemContext      - EBC system context.
+  DisasmString       - The instruction string
+
+Returns:
+
+  Instruction length
+
+--*/
+{
+  UINT8  Modifiers;
+  UINT8  Operands;
+  UINTN  Size;
+  UINT16 Data16;
+  UINT32 Data32;
+  UINT64 Data64;
+
+  ASSERT (GET_OPCODE(InstructionAddress) == OPCODE_MOVI);
+
+  Modifiers  = GET_MODIFIERS (InstructionAddress);
+  Operands   = GET_OPERANDS (InstructionAddress);
+
+  if (Operands & MOVI_M_IMMDATA) {
+    Size    = 4;
+  } else {
+    Size    = 2;
+  }
+  if ((Modifiers & MOVI_M_DATAWIDTH) == MOVI_DATAWIDTH16) {
+    Size += 2;
+  } else if ((Modifiers & MOVI_M_DATAWIDTH) == MOVI_DATAWIDTH32) {
+    Size += 4;
+  } else if ((Modifiers & MOVI_M_DATAWIDTH) == MOVI_DATAWIDTH64) {
+    Size += 8;
+  }
+
+  //
+  // Construct Disasm String
+  //
+  if (DisasmString != NULL) {
+    *DisasmString = EdbPreInstructionString ();
+
+    EdbPrintInstructionName (L"MOVI");
+    switch (Operands & MOVI_M_MOVEWIDTH) {
+    case MOVI_MOVEWIDTH8:
+      EdbPrintInstructionName (L"b");
+      break;
+    case MOVI_MOVEWIDTH16:
+      EdbPrintInstructionName (L"w");
+      break;
+    case MOVI_MOVEWIDTH32:
+      EdbPrintInstructionName (L"d");
+      break;
+    case MOVI_MOVEWIDTH64:
+      EdbPrintInstructionName (L"q");
+      break;
+    }
+    switch (Modifiers & MOVI_M_DATAWIDTH) {
+    case MOVI_DATAWIDTH16:
+      EdbPrintInstructionName (L"w");
+      break;
+    case MOVI_DATAWIDTH32:
+      EdbPrintInstructionName (L"d");
+      break;
+    case MOVI_DATAWIDTH64:
+      EdbPrintInstructionName (L"q");
+      break;
+    }
+
+    EdbPrintRegister1 (Operands);
+
+    InstructionAddress += 2;
+    if (Operands & MOVI_M_IMMDATA) {
+      CopyMem (&Data16, (VOID *)(UINTN)(InstructionAddress), sizeof(UINT16));
+      InstructionAddress += 2;
+      EdbPrintRawIndexData16 (Data16);
+    }
+
+    EdbPrintComma ();
+
+    switch (Modifiers & MOVI_M_DATAWIDTH) {
+    case MOVI_DATAWIDTH16:
+      CopyMem (&Data16, (VOID *)(UINTN)(InstructionAddress), sizeof(UINT16));
+      EdbPrintDatan (Data16);
+      break;
+    case MOVI_DATAWIDTH32:
+      CopyMem (&Data32, (VOID *)(UINTN)(InstructionAddress), sizeof(UINT32));
+      EdbPrintDatan (Data32);
+      break;
+    case MOVI_DATAWIDTH64:
+      CopyMem (&Data64, (VOID *)(UINTN)(InstructionAddress), sizeof(UINT64));
+      EdbPrintData64n (Data64);
+      break;
+    }
+
+    EdbPostInstructionString ();
+  }
+
+  return Size;
+}
+
+UINTN
+EdbDisasmMOVIn (
+  IN     EFI_PHYSICAL_ADDRESS      InstructionAddress,
+  IN     EFI_SYSTEM_CONTEXT        SystemContext,
+  OUT    CHAR16                    **DisasmString
+  )
+/*++
+
+Routine Description:
+
+  Disasm instruction - MOVIn
+
+Arguments:
+
+  InstructionAddress - The instruction address
+  SystemContext      - EBC system context.
+  DisasmString       - The instruction string
+
+Returns:
+
+  Instruction length
+
+--*/
+{
+  UINT8  Modifiers;
+  UINT8  Operands;
+  UINTN  Size;
+  UINT16 Data16;
+  UINT32 Data32;
+  UINT64 Data64;
+
+  ASSERT (GET_OPCODE(InstructionAddress) == OPCODE_MOVIN);
+
+  Modifiers  = GET_MODIFIERS (InstructionAddress);
+  Operands   = GET_OPERANDS (InstructionAddress);
+
+  if (Operands & MOVI_M_IMMDATA) {
+    Size    = 4;
+  } else {
+    Size    = 2;
+  }
+  if ((Modifiers & MOVI_M_DATAWIDTH) == MOVI_DATAWIDTH16) {
+    Size += 2;
+  } else if ((Modifiers & MOVI_M_DATAWIDTH) == MOVI_DATAWIDTH32) {
+    Size += 4;
+  } else if ((Modifiers & MOVI_M_DATAWIDTH) == MOVI_DATAWIDTH64) {
+    Size += 8;
+  }
+
+  //
+  // Construct Disasm String
+  //
+  if (DisasmString != NULL) {
+    *DisasmString = EdbPreInstructionString ();
+
+    EdbPrintInstructionName (L"MOVIn");
+    switch (Modifiers & MOVI_M_DATAWIDTH) {
+    case MOVI_DATAWIDTH16:
+      EdbPrintInstructionName (L"w");
+      break;
+    case MOVI_DATAWIDTH32:
+      EdbPrintInstructionName (L"d");
+      break;
+    case MOVI_DATAWIDTH64:
+      EdbPrintInstructionName (L"q");
+      break;
+    }
+
+    EdbPrintRegister1 (Operands);
+
+    InstructionAddress += 2;
+    if (Operands & MOVI_M_IMMDATA) {
+      CopyMem (&Data16, (VOID *)(UINTN)(InstructionAddress), sizeof(UINT16));
+      InstructionAddress += 2;
+      EdbPrintRawIndexData16 (Data16);
+    }
+
+    EdbPrintComma ();
+
+    switch (Modifiers & MOVI_M_DATAWIDTH) {
+    case MOVI_DATAWIDTH16:
+      CopyMem (&Data16, (VOID *)(UINTN)(InstructionAddress), sizeof(UINT16));
+      EdbPrintRawIndexData16 (Data16);
+      break;
+    case MOVI_DATAWIDTH32:
+      CopyMem (&Data32, (VOID *)(UINTN)(InstructionAddress), sizeof(UINT32));
+      EdbPrintRawIndexData32 (Data32);
+      break;
+    case MOVI_DATAWIDTH64:
+      CopyMem (&Data64, (VOID *)(UINTN)(InstructionAddress), sizeof(UINT64));
+      EdbPrintRawIndexData64 (Data64);
+      break;
+    }
+
+    EdbPostInstructionString ();
+  }
+
+  return Size;
+}
+
+UINTN
+EdbDisasmMOVREL (
+  IN     EFI_PHYSICAL_ADDRESS      InstructionAddress,
+  IN     EFI_SYSTEM_CONTEXT        SystemContext,
+  OUT    CHAR16                    **DisasmString
+  )
+/*++
+
+Routine Description:
+
+  Disasm instruction - MOVREL
+
+Arguments:
+
+  InstructionAddress - The instruction address
+  SystemContext      - EBC system context.
+  DisasmString       - The instruction string
+
+Returns:
+
+  Instruction length
+
+--*/
+{
+  UINT8   Modifiers;
+  UINT8   Operands;
+  UINTN   Size;
+  UINT16  Data16;
+  UINT32  Data32;
+  UINT64  Data64;
+  UINTN   Result;
+  EFI_PHYSICAL_ADDRESS      SavedInstructionAddress;
+
+  ASSERT (GET_OPCODE(InstructionAddress) == OPCODE_MOVREL);
+  SavedInstructionAddress = InstructionAddress;
+
+  Modifiers  = GET_MODIFIERS (InstructionAddress);
+  Operands   = GET_OPERANDS (InstructionAddress);
+
+  if (Operands & MOVI_M_IMMDATA) {
+    Size    = 4;
+  } else {
+    Size    = 2;
+  }
+  if ((Modifiers & MOVI_M_DATAWIDTH) == MOVI_DATAWIDTH16) {
+    Size += 2;
+  } else if ((Modifiers & MOVI_M_DATAWIDTH) == MOVI_DATAWIDTH32) {
+    Size += 4;
+  } else if ((Modifiers & MOVI_M_DATAWIDTH) == MOVI_DATAWIDTH64) {
+    Size += 8;
+  } else {
+    return 0;
+  }
+
+  //
+  // Construct Disasm String
+  //
+  if (DisasmString != NULL) {
+    *DisasmString = EdbPreInstructionString ();
+
+    EdbPrintInstructionName (L"MOVrel");
+    switch (Modifiers & MOVI_M_DATAWIDTH) {
+    case MOVI_DATAWIDTH16:
+      EdbPrintInstructionName (L"w");
+      break;
+    case MOVI_DATAWIDTH32:
+      EdbPrintInstructionName (L"d");
+      break;
+    case MOVI_DATAWIDTH64:
+      EdbPrintInstructionName (L"q");
+      break;
+    }
+
+    EdbPrintRegister1 (Operands);
+
+    InstructionAddress += 2;
+    if (Operands & MOVI_M_IMMDATA) {
+      CopyMem (&Data16, (VOID *)(UINTN)(InstructionAddress), sizeof(UINT16));
+      InstructionAddress += 2;
+      EdbPrintRawIndexData16 (Data16);
+    }
+
+    EdbPrintComma ();
+
+    switch (Modifiers & MOVI_M_DATAWIDTH) {
+    case MOVI_DATAWIDTH16:
+      CopyMem (&Data16, (VOID *)(UINTN)(InstructionAddress), sizeof(UINT16));
+      Result = EdbFindAndPrintSymbol ((UINTN)(SavedInstructionAddress + Size + (INT16)Data16));
+      if (Result == 0) {
+        EdbPrintData16 (Data16);
+      }
+      break;
+    case MOVI_DATAWIDTH32:
+      CopyMem (&Data32, (VOID *)(UINTN)(InstructionAddress), sizeof(UINT32));
+      Result = EdbFindAndPrintSymbol ((UINTN)(SavedInstructionAddress + Size + (INT32)Data32));
+      if (Result == 0) {
+        EdbPrintData32 (Data32);
+      }
+      break;
+    case MOVI_DATAWIDTH64:
+      CopyMem (&Data64, (VOID *)(UINTN)(InstructionAddress), sizeof(UINT64));
+      if (sizeof(UINTN) == sizeof(UINT64)) {
+        Result = EdbFindAndPrintSymbol ((UINTN)(SavedInstructionAddress + Size + (INT64)Data64));
+      } else {
+        Result = 0;
+      }
+      if (Result == 0) {
+        EdbPrintData64 (Data64);
+      }
+      break;
+    }
+
+    EdbPostInstructionString ();
+  }
+
+  return Size;
+}
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbDisasm.h b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbDisasm.h
new file mode 100644
index 000000000000..2d86a090c6a9
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbDisasm.h
@@ -0,0 +1,42 @@
+/*++
+
+Copyright (c) 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.
+
+Module Name:
+
+  EdbDisasm.h
+
+Abstract:
+
+
+--*/
+
+#ifndef _EFI_EDB_DISASM_H_
+#define _EFI_EDB_DISASM_H_
+
+#include <Uefi.h>
+
+//
+// Definition for instruction OPCODE, MODIFIER, and OPERAND
+//
+#define GET_OPCODE(Addr)       (UINT8)((*(UINT8 *)(UINTN)(Addr)) & 0x3F)
+#define GET_MODIFIERS(Addr)    (UINT8)((*(UINT8 *)(UINTN)(Addr)) & 0xC0)
+#define GET_OPCODE_BYTE(Addr)  (UINT8)(*(UINT8 *)(UINTN)(Addr))
+#define GET_OPERANDS(Addr)     (UINT8)(*(UINT8 *)(UINTN)((Addr) + 1))
+
+typedef
+UINTN
+(* EDB_DISASM_INSTRUCTION) (
+  IN     EFI_PHYSICAL_ADDRESS      InstructionAddress,
+  IN     EFI_SYSTEM_CONTEXT        SystemContext,
+  OUT    CHAR16                    **DisAsmString
+  );
+
+#endif
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbDisasmSupport.c b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbDisasmSupport.c
new file mode 100644
index 000000000000..2f41ec3be7a8
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbDisasmSupport.c
@@ -0,0 +1,1461 @@
+/*++
+
+Copyright (c) 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.
+
+Module Name:
+
+  EdbDisasmSupport.c
+
+Abstract:
+
+
+--*/
+
+#include "Edb.h"
+
+extern EDB_DISASM_INSTRUCTION mEdbDisasmInstructionTable[];
+
+typedef struct {
+  CHAR16    Name[EDB_INSTRUCTION_NAME_MAX_LENGTH];
+  CHAR16    Content[EDB_INSTRUCTION_CONTENT_MAX_LENGTH];
+  CHAR16    Tail;
+} EDB_INSTRUCTION_STRING;
+
+EDB_INSTRUCTION_STRING mInstructionString;
+UINTN                  mInstructionNameOffset;
+UINTN                  mInstructionContentOffset;
+
+VOID
+EdbSetOffset (
+  IN UINTN InstructionNameOffset,
+  IN UINTN InstructionContentOffset
+  )
+/*++
+
+Routine Description:
+
+  Set offset for Instruction name and content
+
+Arguments:
+
+  InstructionNameOffset     - Instruction name offset
+  InstructionContentOffset  - Instruction content offset
+
+Returns:
+
+  None
+
+--*/
+{
+  mInstructionNameOffset = InstructionNameOffset;
+  mInstructionContentOffset = InstructionContentOffset;
+
+  return ;
+}
+
+CHAR16 *
+EdbPreInstructionString (
+  VOID
+  )
+/*++
+
+Routine Description:
+
+  Pre instruction string construction
+
+Arguments:
+
+  None
+
+Returns:
+
+  Instruction string
+
+--*/
+{
+  ZeroMem (&mInstructionString, sizeof(mInstructionString));
+  mInstructionNameOffset    = 0;
+  mInstructionContentOffset = 0;
+
+  return (CHAR16 *)&mInstructionString;
+}
+
+CHAR16 *
+EdbPostInstructionString (
+  VOID
+  )
+/*++
+
+Routine Description:
+
+  Post instruction string construction
+
+Arguments:
+
+  None
+
+Returns:
+
+  Instruction string
+
+--*/
+{
+  CHAR16 *Char;
+
+  for (Char = (CHAR16 *)&mInstructionString; Char < &mInstructionString.Tail; Char++) {
+    if (*Char == 0) {
+      *Char = L' ';
+    }
+  }
+  mInstructionString.Tail = 0;
+
+  mInstructionNameOffset    = 0;
+  mInstructionContentOffset = 0;
+
+  return (CHAR16 *)&mInstructionString;
+}
+
+BOOLEAN
+EdbGetNaturalIndex16 (
+  IN  UINT16  Data16,
+  OUT UINTN   *NaturalUnits,
+  OUT UINTN   *ConstantUnits
+  )
+/*++
+
+Routine Description:
+
+  Get Sign, NaturalUnits, and ConstantUnits of the WORD data
+
+Arguments:
+
+  Data16        - WORD data
+  NaturalUnits  - Natural Units of the WORD
+  ConstantUnits - Constant Units of the WORD
+
+Returns:
+
+  Sign value of WORD
+
+--*/
+{
+  BOOLEAN Sign;
+  UINTN   NaturalUnitBit;
+
+  Sign = (BOOLEAN)(Data16 >> 15);
+  NaturalUnitBit = (UINTN)((Data16 >> 12) & 0x7);
+  NaturalUnitBit *= 2;
+  Data16 = Data16 & 0xFFF;
+  *NaturalUnits = (UINTN)(Data16 & ((1 << NaturalUnitBit) - 1));
+  *ConstantUnits = (UINTN)((Data16 >> NaturalUnitBit) & ((1 << (12 - NaturalUnitBit)) - 1));
+
+  return Sign;
+}
+
+BOOLEAN
+EdbGetNaturalIndex32 (
+  IN  UINT32  Data32,
+  OUT UINTN   *NaturalUnits,
+  OUT UINTN   *ConstantUnits
+  )
+/*++
+
+Routine Description:
+
+  Get Sign, NaturalUnits, and ConstantUnits of the DWORD data
+
+Arguments:
+
+  Data32        - DWORD data
+  NaturalUnits  - Natural Units of the DWORD
+  ConstantUnits - Constant Units of the DWORD
+
+Returns:
+
+  Sign value of DWORD
+
+--*/
+{
+  BOOLEAN Sign;
+  UINTN   NaturalUnitBit;
+
+  Sign = (BOOLEAN)(Data32 >> 31);
+  NaturalUnitBit = (UINTN)((Data32 >> 28) & 0x7);
+  NaturalUnitBit *= 4;
+  Data32 = Data32 & 0xFFFFFFF;
+  *NaturalUnits = (UINTN)(Data32 & ((1 << NaturalUnitBit) - 1));
+  *ConstantUnits = (UINTN)((Data32 >> NaturalUnitBit) & ((1 << (28 - NaturalUnitBit)) - 1));
+
+  return Sign;
+}
+
+BOOLEAN
+EdbGetNaturalIndex64 (
+  IN  UINT64  Data64,
+  OUT UINT64  *NaturalUnits,
+  OUT UINT64  *ConstantUnits
+  )
+/*++
+
+Routine Description:
+
+  Get Sign, NaturalUnits, and ConstantUnits of the QWORD data
+
+Arguments:
+
+  Data64        - QWORD data
+  NaturalUnits  - Natural Units of the QWORD
+  ConstantUnits - Constant Units of the QWORD
+
+Returns:
+
+  Sign value of QWORD
+
+--*/
+{
+  BOOLEAN Sign;
+  UINTN   NaturalUnitBit;
+
+  Sign = (BOOLEAN)RShiftU64 (Data64, 63);
+  NaturalUnitBit = (UINTN)(RShiftU64 (Data64, 60) & 0x7);
+  NaturalUnitBit *= 8;
+  Data64 = RShiftU64 (LShiftU64 (Data64, 4), 4);
+  *NaturalUnits = (UINT64)(Data64 & (LShiftU64 (1, NaturalUnitBit) - 1));
+  *ConstantUnits = (UINT64)(RShiftU64 (Data64, NaturalUnitBit) & (LShiftU64 (1, (60 - NaturalUnitBit)) - 1));
+
+  return Sign;
+}
+
+UINT8
+EdbGetBitWidth (
+  IN UINT64  Value
+  )
+/*++
+
+Routine Description:
+
+  Get Bit Width of the value
+
+Arguments:
+
+  Value - data
+
+Returns:
+
+  Bit width
+
+--*/
+{
+  if (Value >= 10000000000000) {
+    return 14;
+  } else if (Value >= 1000000000000) {
+    return 13;
+  } else if (Value >= 100000000000) {
+    return 12;
+  } else if (Value >= 10000000000) {
+    return 11;
+  } else if (Value >= 1000000000) {
+    return 10;
+  } else if (Value >= 100000000) {
+    return 9;
+  } else if (Value >= 10000000) {
+    return 8;
+  } else if (Value >= 1000000) {
+    return 7;
+  } else if (Value >= 100000) {
+    return 6;
+  } else if (Value >= 10000) {
+    return 5;
+  } else if (Value >= 1000) {
+    return 4;
+  } else if (Value >= 100) {
+    return 3;
+  } else if (Value >= 10) {
+    return 2;
+  } else {
+    return 1;
+  }
+}
+
+UINTN
+EdbPrintInstructionName (
+  IN CHAR16                 *Name
+  )
+/*++
+
+Routine Description:
+
+  Print the instruction name
+
+Arguments:
+
+  Name - instruction name
+
+Returns:
+
+  Instruction name offset
+
+--*/
+{
+  EDBSPrintWithOffset (
+    mInstructionString.Name,
+    EDB_INSTRUCTION_NAME_MAX_SIZE,
+    mInstructionNameOffset,
+    L"%s",
+    Name
+    );
+  mInstructionNameOffset += StrLen (Name);
+
+  return mInstructionNameOffset;
+}
+
+UINTN
+EdbPrintRegister1 (
+  IN UINT8                  Operands
+  )
+/*++
+
+Routine Description:
+
+  Print register 1 in operands
+
+Arguments:
+
+  Operands - instruction operands
+
+Returns:
+
+  Instruction content offset
+
+--*/
+{
+  if (Operands & OPERAND_M_INDIRECT1) {
+    EDBSPrintWithOffset (
+      mInstructionString.Content,
+      EDB_INSTRUCTION_CONTENT_MAX_SIZE,
+      mInstructionContentOffset,
+      L"@"
+      );
+    mInstructionContentOffset += 1;
+  }
+  EDBSPrintWithOffset (
+    mInstructionString.Content,
+    EDB_INSTRUCTION_CONTENT_MAX_SIZE,
+    mInstructionContentOffset,
+    L"R%d",
+    (UINTN)(Operands & OPERAND_M_OP1)
+    );
+  mInstructionContentOffset += 2;
+
+  return mInstructionContentOffset;
+}
+
+UINTN
+EdbPrintRegister2 (
+  IN UINT8                  Operands
+  )
+/*++
+
+Routine Description:
+
+  Print register 2 in operands
+
+Arguments:
+
+  Operands - instruction operands
+
+Returns:
+
+  Instruction content offset
+
+--*/
+{
+  if (Operands & OPERAND_M_INDIRECT2) {
+    EDBSPrintWithOffset (
+      mInstructionString.Content,
+      EDB_INSTRUCTION_CONTENT_MAX_SIZE,
+      mInstructionContentOffset,
+      L"@"
+      );
+    mInstructionContentOffset += 1;
+  }
+  EDBSPrintWithOffset (
+    mInstructionString.Content,
+    EDB_INSTRUCTION_CONTENT_MAX_SIZE,
+    mInstructionContentOffset,
+    L"R%d",
+    (UINTN)((Operands & OPERAND_M_OP2) >> 4)
+    );
+  mInstructionContentOffset += 2;
+
+  return mInstructionContentOffset;
+}
+
+UINTN
+EdbPrintDedicatedRegister1 (
+  IN UINT8                  Operands
+  )
+/*++
+
+Routine Description:
+
+  Print dedicated register 1 in operands
+
+Arguments:
+
+  Operands - instruction operands
+
+Returns:
+
+  Instruction content offset
+
+--*/
+{
+  switch (Operands & OPERAND_M_OP1) {
+  case 0:
+    EDBSPrintWithOffset (
+      mInstructionString.Content,
+      EDB_INSTRUCTION_CONTENT_MAX_SIZE,
+      mInstructionContentOffset,
+      L"[FLAGS]"
+      );
+    mInstructionContentOffset += 7;
+    break;
+  case 1:
+    EDBSPrintWithOffset (
+      mInstructionString.Content,
+      EDB_INSTRUCTION_CONTENT_MAX_SIZE,
+      mInstructionContentOffset,
+      L"[IP]"
+      );
+    mInstructionContentOffset += 4;
+    break;
+  }
+
+  return mInstructionContentOffset;
+}
+
+UINTN
+EdbPrintDedicatedRegister2 (
+  IN UINT8                  Operands
+  )
+/*++
+
+Routine Description:
+
+  Print dedicated register 2 in operands
+
+Arguments:
+
+  Operands - instruction operands
+
+Returns:
+
+  Instruction content offset
+
+--*/
+{
+  switch ((Operands & OPERAND_M_OP2) >> 4) {
+  case 0:
+    EDBSPrintWithOffset (
+      mInstructionString.Content,
+      EDB_INSTRUCTION_CONTENT_MAX_SIZE,
+      mInstructionContentOffset,
+      L"[FLAGS]"
+      );
+    mInstructionContentOffset += 7;
+    break;
+  case 1:
+    EDBSPrintWithOffset (
+      mInstructionString.Content,
+      EDB_INSTRUCTION_CONTENT_MAX_SIZE,
+      mInstructionContentOffset,
+      L"[IP]"
+      );
+    mInstructionContentOffset += 4;
+    break;
+  }
+
+  return mInstructionContentOffset;
+}
+
+UINTN
+EdbPrintIndexData (
+  IN BOOLEAN                Sign,
+  IN UINTN                  NaturalUnits,
+  IN UINTN                  ConstantUnits
+  )
+/*++
+
+Routine Description:
+
+  Print the hexical UINTN index data to instruction content
+
+Arguments:
+
+  Sign          - Signed bit of UINTN data
+  NaturalUnits  - natural units of UINTN data
+  ConstantUnits - natural units of UINTN data
+
+Returns:
+
+  Instruction content offset
+
+--*/
+{
+  EDBSPrintWithOffset (
+    mInstructionString.Content,
+    EDB_INSTRUCTION_CONTENT_MAX_SIZE,
+    mInstructionContentOffset,
+    L"(%s%d,%s%d)",
+    Sign ? L"-" : L"+",
+    NaturalUnits,
+    Sign ? L"-" : L"+",
+    ConstantUnits
+    );
+  mInstructionContentOffset  = mInstructionContentOffset + 5 + EdbGetBitWidth (NaturalUnits) + EdbGetBitWidth (ConstantUnits);
+
+  return mInstructionContentOffset;
+}
+
+UINTN
+EdbPrintIndexData64 (
+  IN BOOLEAN                Sign,
+  IN UINT64                 NaturalUnits,
+  IN UINT64                 ConstantUnits
+  )
+/*++
+
+Routine Description:
+
+  Print the hexical QWORD index data to instruction content
+
+Arguments:
+
+  Sign          - Signed bit of QWORD data
+  NaturalUnits  - natural units of QWORD data
+  ConstantUnits - natural units of QWORD data
+
+Returns:
+
+  Instruction content offset
+
+--*/
+{
+  EDBSPrintWithOffset (
+    mInstructionString.Content,
+    EDB_INSTRUCTION_CONTENT_MAX_SIZE,
+    mInstructionContentOffset,
+    L"(%s%ld,%s%ld)",
+    Sign ? L"-" : L"+",
+    NaturalUnits,
+    Sign ? L"-" : L"+",
+    ConstantUnits
+    );
+  mInstructionContentOffset  = mInstructionContentOffset + 5 + EdbGetBitWidth (NaturalUnits) + EdbGetBitWidth (ConstantUnits);
+
+  return mInstructionContentOffset;
+}
+
+UINTN
+EdbPrintRawIndexData16 (
+  IN UINT16                 Data16
+  )
+/*++
+
+Routine Description:
+
+  Print the hexical WORD raw index data to instruction content
+
+Arguments:
+
+  Data16 - WORD data
+
+Returns:
+
+  Instruction content offset
+
+--*/
+{
+  BOOLEAN Sign;
+  UINTN   NaturalUnits;
+  UINTN   ConstantUnits;
+  UINTN   Offset;
+
+  Sign = EdbGetNaturalIndex16 (Data16, &NaturalUnits, &ConstantUnits);
+  Offset = EdbPrintIndexData (Sign, NaturalUnits, ConstantUnits);
+
+  return Offset;
+}
+
+UINTN
+EdbPrintRawIndexData32 (
+  IN UINT32                 Data32
+  )
+/*++
+
+Routine Description:
+
+  Print the hexical DWORD raw index data to instruction content
+
+Arguments:
+
+  Data32 - DWORD data
+
+Returns:
+
+  Instruction content offset
+
+--*/
+{
+  BOOLEAN Sign;
+  UINTN   NaturalUnits;
+  UINTN   ConstantUnits;
+  UINTN   Offset;
+
+  Sign = EdbGetNaturalIndex32 (Data32, &NaturalUnits, &ConstantUnits);
+  Offset = EdbPrintIndexData (Sign, NaturalUnits, ConstantUnits);
+
+  return Offset;
+}
+
+UINTN
+EdbPrintRawIndexData64 (
+  IN UINT64                 Data64
+  )
+/*++
+
+Routine Description:
+
+  Print the hexical QWORD raw index data to instruction content
+
+Arguments:
+
+  Data64 - QWORD data
+
+Returns:
+
+  Instruction content offset
+
+--*/
+{
+  BOOLEAN Sign;
+  UINT64  NaturalUnits;
+  UINT64  ConstantUnits;
+  UINTN   Offset;
+
+  Sign = EdbGetNaturalIndex64 (Data64, &NaturalUnits, &ConstantUnits);
+  Offset = EdbPrintIndexData64 (Sign, NaturalUnits, ConstantUnits);
+
+  return Offset;
+}
+
+UINTN
+EdbPrintImmData8 (
+  IN UINT8                  Data
+  )
+/*++
+
+Routine Description:
+
+  Print the hexical BYTE immediate data to instruction content
+
+Arguments:
+
+  Data - BYTE data
+
+Returns:
+
+  Instruction content offset
+
+--*/
+{
+  EDBSPrintWithOffset (
+    mInstructionString.Content,
+    EDB_INSTRUCTION_CONTENT_MAX_SIZE,
+    mInstructionContentOffset,
+    L"(0x%02x)",
+    (UINTN)Data
+    );
+  mInstructionContentOffset  += 6;
+
+  return mInstructionContentOffset;
+}
+
+UINTN
+EdbPrintImmData16 (
+  IN UINT16                 Data
+  )
+/*++
+
+Routine Description:
+
+  Print the hexical WORD immediate data to instruction content
+
+Arguments:
+
+  Data - WORD data
+
+Returns:
+
+  Instruction content offset
+
+--*/
+{
+  EDBSPrintWithOffset (
+    mInstructionString.Content,
+    EDB_INSTRUCTION_CONTENT_MAX_SIZE,
+    mInstructionContentOffset,
+    L"(0x%04x)",
+    (UINTN)Data
+    );
+  mInstructionContentOffset  += 8;
+
+  return mInstructionContentOffset;
+}
+
+UINTN
+EdbPrintImmData32 (
+  IN UINT32                 Data
+  )
+/*++
+
+Routine Description:
+
+  Print the hexical DWORD immediate data to instruction content
+
+Arguments:
+
+  Data - DWORD data
+
+Returns:
+
+  Instruction content offset
+
+--*/
+{
+  EDBSPrintWithOffset (
+    mInstructionString.Content,
+    EDB_INSTRUCTION_CONTENT_MAX_SIZE,
+    mInstructionContentOffset,
+    L"(0x%08x)",
+    (UINTN)Data
+    );
+  mInstructionContentOffset  += 12;
+
+  return mInstructionContentOffset;
+}
+
+UINTN
+EdbPrintImmData64 (
+  IN UINT64                 Data
+  )
+/*++
+
+Routine Description:
+
+  Print the hexical QWORD immediate data to instruction content
+
+Arguments:
+
+  Data - QWORD data
+
+Returns:
+
+  Instruction content offset
+
+--*/
+{
+  EDBSPrintWithOffset (
+    mInstructionString.Content,
+    EDB_INSTRUCTION_CONTENT_MAX_SIZE,
+    mInstructionContentOffset,
+    L"(0x%016lx)",
+    Data
+    );
+  mInstructionContentOffset  += 20;
+
+  return mInstructionContentOffset;
+}
+
+UINTN
+EdbPrintImmDatan (
+  IN UINTN                  Data
+  )
+/*++
+
+Routine Description:
+
+  Print the decimal UINTN immediate data to instruction content
+
+Arguments:
+
+  Data - UINTN data
+
+Returns:
+
+  Instruction content offset
+
+--*/
+{
+  EDBSPrintWithOffset (
+    mInstructionString.Content,
+    EDB_INSTRUCTION_CONTENT_MAX_SIZE,
+    mInstructionContentOffset,
+    L"(%d)",
+    (UINTN)Data
+    );
+  mInstructionContentOffset  = mInstructionContentOffset + 2 + EdbGetBitWidth (Data);
+
+  return mInstructionContentOffset;
+}
+
+UINTN
+EdbPrintImmData64n (
+  IN UINT64                 Data64
+  )
+/*++
+
+Routine Description:
+
+  Print the decimal QWORD immediate data to instruction content
+
+Arguments:
+
+  Data64 - QWORD data
+
+Returns:
+
+  Instruction content offset
+
+--*/
+{
+  EDBSPrintWithOffset (
+    mInstructionString.Content,
+    EDB_INSTRUCTION_CONTENT_MAX_SIZE,
+    mInstructionContentOffset,
+    L"(%ld)",
+    Data64
+    );
+  mInstructionContentOffset  = mInstructionContentOffset + 2 + EdbGetBitWidth (Data64);
+
+  return mInstructionContentOffset;
+}
+
+UINTN
+EdbPrintData8 (
+  IN UINT8                  Data8
+  )
+/*++
+
+Routine Description:
+
+  Print the hexical BYTE to instruction content
+
+Arguments:
+
+  Data8 - BYTE data
+
+Returns:
+
+  Instruction content offset
+
+--*/
+{
+  EDBSPrintWithOffset (
+    mInstructionString.Content,
+    EDB_INSTRUCTION_CONTENT_MAX_SIZE,
+    mInstructionContentOffset,
+    L"0x%02x",
+    (UINTN)Data8
+    );
+  mInstructionContentOffset += 4;
+
+  return mInstructionContentOffset;
+}
+
+UINTN
+EdbPrintData16 (
+  IN UINT16                 Data16
+  )
+/*++
+
+Routine Description:
+
+  Print the hexical WORD to instruction content
+
+Arguments:
+
+  Data16 - WORD data
+
+Returns:
+
+  Instruction content offset
+
+--*/
+{
+  EDBSPrintWithOffset (
+    mInstructionString.Content,
+    EDB_INSTRUCTION_CONTENT_MAX_SIZE,
+    mInstructionContentOffset,
+    L"0x%04x",
+    (UINTN)Data16
+    );
+  mInstructionContentOffset += 6;
+
+  return mInstructionContentOffset;
+}
+
+UINTN
+EdbPrintData32 (
+  IN UINT32                 Data32
+  )
+/*++
+
+Routine Description:
+
+  Print the hexical DWORD to instruction content
+
+Arguments:
+
+  Data32 - DWORD data
+
+Returns:
+
+  Instruction content offset
+
+--*/
+{
+  EDBSPrintWithOffset (
+    mInstructionString.Content,
+    EDB_INSTRUCTION_CONTENT_MAX_SIZE,
+    mInstructionContentOffset,
+    L"0x%08x",
+    (UINTN)Data32
+    );
+  mInstructionContentOffset += 10;
+
+  return mInstructionContentOffset;
+}
+
+UINTN
+EdbPrintData64 (
+  IN UINT64                 Data64
+  )
+/*++
+
+Routine Description:
+
+  Print the hexical QWORD to instruction content
+
+Arguments:
+
+  Data64 - QWORD data
+
+Returns:
+
+  Instruction content offset
+
+--*/
+{
+  EDBSPrintWithOffset (
+    mInstructionString.Content,
+    EDB_INSTRUCTION_CONTENT_MAX_SIZE,
+    mInstructionContentOffset,
+    L"0x%016lx",
+    (UINT64)Data64
+    );
+  mInstructionContentOffset += 18;
+
+  return mInstructionContentOffset;
+}
+
+UINTN
+EdbPrintDatan (
+  IN UINTN                  Data
+  )
+/*++
+
+Routine Description:
+
+  Print the decimal unsigned UINTN to instruction content
+
+Arguments:
+
+  Data - unsigned UINTN data
+
+Returns:
+
+  Instruction content offset
+
+--*/
+{
+  EDBSPrintWithOffset (
+    mInstructionString.Content,
+    EDB_INSTRUCTION_CONTENT_MAX_SIZE,
+    mInstructionContentOffset,
+    L"%d",
+    (UINTN)Data
+    );
+  mInstructionContentOffset = mInstructionContentOffset + EdbGetBitWidth (Data);
+
+  return mInstructionContentOffset;
+}
+
+UINTN
+EdbPrintData64n (
+  IN UINT64                 Data64
+  )
+/*++
+
+Routine Description:
+
+  Print the decimal unsigned QWORD to instruction content
+
+Arguments:
+
+  Data64 - unsigned QWORD data
+
+Returns:
+
+  Instruction content offset
+
+--*/
+{
+  EDBSPrintWithOffset (
+    mInstructionString.Content,
+    EDB_INSTRUCTION_CONTENT_MAX_SIZE,
+    mInstructionContentOffset,
+    L"%ld",
+    Data64
+    );
+  mInstructionContentOffset = mInstructionContentOffset + EdbGetBitWidth (Data64);
+
+  return mInstructionContentOffset;
+}
+
+UINTN
+EdbPrintData8s (
+  IN UINT8                  Data8
+  )
+/*++
+
+Routine Description:
+
+  Print the decimal signed BYTE to instruction content
+
+Arguments:
+
+  Data8 - signed BYTE data
+
+Returns:
+
+  Instruction content offset
+
+--*/
+{
+  BOOLEAN Sign;
+
+  Sign = (BOOLEAN)(Data8 >> 7);
+
+  EDBSPrintWithOffset (
+    mInstructionString.Content,
+    EDB_INSTRUCTION_CONTENT_MAX_SIZE,
+    mInstructionContentOffset,
+    L"%s%d",
+    Sign ? L"-" : L"+",
+    (UINTN)(Data8 & 0x7F)
+    );
+  mInstructionContentOffset = mInstructionContentOffset + 1 + EdbGetBitWidth (Data8 & 0x7F);
+
+  return mInstructionContentOffset;
+}
+
+UINTN
+EdbPrintData16s (
+  IN UINT16                 Data16
+  )
+/*++
+
+Routine Description:
+
+  Print the decimal signed WORD to instruction content
+
+Arguments:
+
+  Data16 - signed WORD data
+
+Returns:
+
+  Instruction content offset
+
+--*/
+{
+  BOOLEAN Sign;
+
+  Sign = (BOOLEAN)(Data16 >> 15);
+
+  EDBSPrintWithOffset (
+    mInstructionString.Content,
+    EDB_INSTRUCTION_CONTENT_MAX_SIZE,
+    mInstructionContentOffset,
+    L"%s%d",
+    Sign ? L"-" : L"+",
+    (UINTN)(Data16 & 0x7FFF)
+    );
+  mInstructionContentOffset = mInstructionContentOffset + 1 + EdbGetBitWidth (Data16 & 0x7FFF);
+
+  return mInstructionContentOffset;
+}
+
+UINTN
+EdbPrintData32s (
+  IN UINT32                 Data32
+  )
+/*++
+
+Routine Description:
+
+  Print the decimal signed DWORD to instruction content
+
+Arguments:
+
+  Data32 - signed DWORD data
+
+Returns:
+
+  Instruction content offset
+
+--*/
+{
+  BOOLEAN Sign;
+
+  Sign = (BOOLEAN)(Data32 >> 31);
+
+  EDBSPrintWithOffset (
+    mInstructionString.Content,
+    EDB_INSTRUCTION_CONTENT_MAX_SIZE,
+    mInstructionContentOffset,
+    L"%s%d",
+    Sign ? L"-" : L"+",
+    (UINTN)(Data32 & 0x7FFFFFFF)
+    );
+  mInstructionContentOffset = mInstructionContentOffset + 1 + EdbGetBitWidth (Data32 & 0x7FFFFFFF);
+
+  return mInstructionContentOffset;
+}
+
+UINTN
+EdbPrintData64s (
+  IN UINT64                 Data64
+  )
+/*++
+
+Routine Description:
+
+  Print the decimal signed QWORD to instruction content
+
+Arguments:
+
+  Data64 - signed QWORD data
+
+Returns:
+
+  Instruction content offset
+
+--*/
+{
+  BOOLEAN Sign;
+  INT64   Data64s;
+
+  Sign = (BOOLEAN)RShiftU64 (Data64, 63);
+  Data64s = (INT64)RShiftU64 (LShiftU64 (Data64, 1), 1);
+
+  EDBSPrintWithOffset (
+    mInstructionString.Content,
+    EDB_INSTRUCTION_CONTENT_MAX_SIZE,
+    mInstructionContentOffset,
+    L"%s%ld",
+    Sign ? L"-" : L"+",
+    (UINT64)Data64s
+    );
+  mInstructionContentOffset = mInstructionContentOffset + 1 + EdbGetBitWidth (Data64s);
+
+  return mInstructionContentOffset;
+}
+
+UINTN
+EdbPrintComma (
+  VOID
+  )
+/*++
+
+Routine Description:
+
+  Print the comma to instruction content
+
+Arguments:
+
+  None
+
+Returns:
+
+  Instruction content offset
+
+--*/
+{
+  EDBSPrintWithOffset (
+    mInstructionString.Content,
+    EDB_INSTRUCTION_CONTENT_MAX_SIZE,
+    mInstructionContentOffset,
+    L", "
+    );
+  mInstructionContentOffset += 2;
+
+  return mInstructionContentOffset;
+}
+
+UINTN
+EdbFindAndPrintSymbol (
+  IN UINTN                  Address
+  )
+/*++
+
+Routine Description:
+
+  Find the symbol string according to address, then print it
+
+Arguments:
+
+  Address - instruction address
+
+Returns:
+
+  1 - symbol string is found and printed
+  0 - symbol string not found
+
+--*/
+{
+  CHAR8 *SymbolStr;
+
+  SymbolStr = FindSymbolStr (Address);
+  if (SymbolStr != NULL) {
+    EDBSPrintWithOffset (
+      mInstructionString.Content,
+      EDB_INSTRUCTION_CONTENT_MAX_SIZE,
+      mInstructionContentOffset,
+      L"[%a]",
+      SymbolStr
+      );
+    return 1;
+  }
+
+  return 0;
+}
+
+VOID
+EdbPrintRaw (
+  IN EFI_PHYSICAL_ADDRESS   InstructionAddress,
+  IN UINTN                  InstructionNumber
+  )
+/*++
+
+Routine Description:
+
+  Print the EBC byte code
+
+Arguments:
+
+  InstructionAddress - instruction address
+  InstructionNumber  - instruction number
+
+Returns:
+
+  None
+
+--*/
+{
+  UINTN  LineNumber;
+  UINTN  ByteNumber;
+  UINTN  LineIndex;
+  UINTN  ByteIndex;
+  CHAR8  *SymbolStr;
+
+  if (InstructionNumber == 0) {
+    return ;
+  }
+
+  LineNumber = InstructionNumber / EDB_BYTECODE_NUMBER_IN_LINE;
+  ByteNumber = InstructionNumber % EDB_BYTECODE_NUMBER_IN_LINE;
+  if (ByteNumber == 0) {
+    LineNumber -= 1;
+    ByteNumber  = EDB_BYTECODE_NUMBER_IN_LINE;
+  }
+
+  //
+  // Print Symbol
+  //
+  SymbolStr = FindSymbolStr ((UINTN)InstructionAddress);
+  if (SymbolStr != NULL) {
+    EDBPrint (L"[%a]:\n", SymbolStr);
+  }
+
+  for (LineIndex = 0; LineIndex < LineNumber; LineIndex++) {
+    EDBPrint (EDB_PRINT_ADDRESS_FORMAT, (UINTN)InstructionAddress);
+    for (ByteIndex = 0; ByteIndex < EDB_BYTECODE_NUMBER_IN_LINE; ByteIndex++) {
+      EDBPrint (L"%02x ", *(UINT8 *)(UINTN)InstructionAddress);
+      InstructionAddress += 1;
+    }
+    EDBPrint (L"\n");
+  }
+
+  EDBPrint (EDB_PRINT_ADDRESS_FORMAT, (UINTN)InstructionAddress);
+  for (ByteIndex = 0; ByteIndex < ByteNumber; ByteIndex++) {
+    EDBPrint (L"%02x ", *(UINT8 *)(UINTN)InstructionAddress);
+    InstructionAddress += 1;
+  }
+  for (ByteIndex = 0; ByteIndex < EDB_BYTECODE_NUMBER_IN_LINE - ByteNumber; ByteIndex++) {
+    EDBPrint (L"   ");
+  }
+
+  return ;
+}
+
+EFI_STATUS
+EdbShowDisasm (
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_SYSTEM_CONTEXT        SystemContext
+  )
+/*++
+
+Routine Description:
+
+  Print the EBC asm code
+
+Arguments:
+
+  DebuggerPrivate - EBC Debugger private data structure
+  SystemContext   - EBC system context.
+
+Returns:
+
+  EFI_SUCCESS - show disasm successfully
+
+--*/
+{
+  EFI_PHYSICAL_ADDRESS    InstructionAddress;
+  UINTN                   InstructionNumber;
+  UINTN                   InstructionLength;
+  UINT8                   Opcode;
+  CHAR16                  *InstructionString;
+//  UINTN                   Result;
+
+  InstructionAddress = DebuggerPrivate->InstructionScope;
+  for (InstructionNumber = 0; InstructionNumber < DebuggerPrivate->InstructionNumber; InstructionNumber++) {
+
+    //
+    // Break each 0x10 instruction
+    //
+    if (((InstructionNumber % EFI_DEBUGGER_LINE_NUMBER_IN_PAGE) == 0) &&
+        (InstructionNumber != 0)) {
+      if (SetPageBreak ()) {
+        break;
+      }
+    }
+
+    Opcode = GET_OPCODE(InstructionAddress);
+    if ((Opcode < OPCODE_MAX) && (mEdbDisasmInstructionTable[Opcode] != NULL)) {
+      InstructionLength = mEdbDisasmInstructionTable [Opcode] (InstructionAddress, SystemContext, &InstructionString);
+      if (InstructionLength != 0) {
+
+        //
+        // Print Source
+        //
+//        Result = EdbPrintSource ((UINTN)InstructionAddress, FALSE);
+
+        if (!DebuggerPrivate->DebuggerSymbolContext.DisplayCodeOnly) {
+
+          EdbPrintRaw (InstructionAddress, InstructionLength);
+          if (InstructionString != NULL) {
+            EDBPrint (L"%s\n", InstructionString);
+          } else {
+            EDBPrint (L"%s\n", L"<Unknown Instruction>");
+          }
+        }
+
+        EdbPrintSource ((UINTN)InstructionAddress, TRUE);
+
+        InstructionAddress += InstructionLength;
+      } else {
+        //
+        // Something wrong with OPCODE
+        //
+        EdbPrintRaw (InstructionAddress, EDB_BYTECODE_NUMBER_IN_LINE);
+        EDBPrint (L"%s\n", L"<Bad Instruction>");
+        break;
+      }
+    } else {
+      //
+      // Something wrong with OPCODE
+      //
+      EdbPrintRaw (InstructionAddress, EDB_BYTECODE_NUMBER_IN_LINE);
+      EDBPrint (L"%s\n", L"<Bad Instruction>");
+      break;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+UINT64
+GetRegisterValue (
+  IN     EFI_SYSTEM_CONTEXT        SystemContext,
+  IN     UINT8                     Index
+  )
+/*++
+
+Routine Description:
+
+  Get register value accroding to the system context, and register index
+
+Arguments:
+
+  SystemContext   - EBC system context.
+  Index           - EBC register index
+
+Returns:
+
+  register value
+
+--*/
+{
+  switch (Index) {
+  case 0:
+    return SystemContext.SystemContextEbc->R0;
+  case 1:
+    return SystemContext.SystemContextEbc->R1;
+  case 2:
+    return SystemContext.SystemContextEbc->R2;
+  case 3:
+    return SystemContext.SystemContextEbc->R3;
+  case 4:
+    return SystemContext.SystemContextEbc->R4;
+  case 5:
+    return SystemContext.SystemContextEbc->R5;
+  case 6:
+    return SystemContext.SystemContextEbc->R6;
+  case 7:
+    return SystemContext.SystemContextEbc->R7;
+  default:
+    ASSERT (FALSE);
+    break;
+  }
+  return 0;
+}
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbDisasmSupport.h b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbDisasmSupport.h
new file mode 100644
index 000000000000..69e58502db5c
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbDisasmSupport.h
@@ -0,0 +1,241 @@
+/*++
+
+Copyright (c) 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.
+
+Module Name:
+
+  EdbDisasmSupport.h
+
+Abstract:
+
+
+--*/
+
+#ifndef _EFI_EDB_DISASM_SUPPORT_H_
+#define _EFI_EDB_DISASM_SUPPORT_H_
+
+#include <Uefi.h>
+
+#define EDB_BYTECODE_NUMBER_IN_LINE     5
+
+#ifdef EFI32
+#define EDB_PRINT_ADDRESS_FORMAT    L"%08x: "
+#else
+// To use 012l instead of 016l because space is not enough
+#define EDB_PRINT_ADDRESS_FORMAT    L"%012lx: "
+#endif
+
+#define OPCODE_MAX 0x40
+
+#define EDB_INSTRUCTION_NAME_MAX_LENGTH     10
+#define EDB_INSTRUCTION_NAME_MAX_SIZE       (EDB_INSTRUCTION_NAME_MAX_LENGTH * sizeof(CHAR16))
+#define EDB_INSTRUCTION_CONTENT_MAX_LENGTH  30
+#define EDB_INSTRUCTION_CONTENT_MAX_SIZE    (EDB_INSTRUCTION_CONTENT_MAX_LENGTH * sizeof(CHAR16))
+
+VOID
+EdbSetOffset (
+  IN UINTN InstructionNameOffset,
+  IN UINTN InstructionContentOffset
+  );
+
+CHAR16 *
+EdbPreInstructionString (
+  VOID
+  );
+
+CHAR16 *
+EdbPostInstructionString (
+  VOID
+  );
+
+UINTN
+EdbPrintInstructionName (
+  IN CHAR16                 *Name
+  );
+
+BOOLEAN
+EdbGetNaturalIndex16 (
+  IN  UINT16  Data16,
+  OUT UINTN   *NaturalUnits,
+  OUT UINTN   *ConstantUnits
+  );
+
+BOOLEAN
+EdbGetNaturalIndex32 (
+  IN  UINT32  Data32,
+  OUT UINTN   *NaturalUnits,
+  OUT UINTN   *ConstantUnits
+  );
+
+BOOLEAN
+EdbGetNaturalIndex64 (
+  IN  UINT64  Data64,
+  OUT UINT64  *NaturalUnits,
+  OUT UINT64  *ConstantUnits
+  );
+
+UINTN
+EdbPrintRawIndexData16 (
+  IN UINT16                 Data16
+  );
+
+UINTN
+EdbPrintRawIndexData32 (
+  IN UINT32                 Data32
+  );
+
+UINTN
+EdbPrintRawIndexData64 (
+  IN UINT64                 Data64
+  );
+
+UINTN
+EdbPrintRegister1 (
+  IN UINT8                  Operands
+  );
+
+UINTN
+EdbPrintRegister2 (
+  IN UINT8                  Operands
+  );
+
+UINTN
+EdbPrintDedicatedRegister1 (
+  IN UINT8                  Operands
+  );
+
+UINTN
+EdbPrintDedicatedRegister2 (
+  IN UINT8                  Operands
+  );
+
+UINTN
+EdbPrintIndexData (
+  IN BOOLEAN                Sign,
+  IN UINTN                  NaturalUnits,
+  IN UINTN                  ConstantUnits
+  );
+
+UINTN
+EdbPrintIndexData64 (
+  IN BOOLEAN                Sign,
+  IN UINT64                 NaturalUnits,
+  IN UINT64                 ConstantUnits
+  );
+
+UINTN
+EdbPrintImmData8 (
+  IN UINT8                  Data
+  );
+
+UINTN
+EdbPrintImmData16 (
+  IN UINT16                 Data
+  );
+
+UINTN
+EdbPrintImmData32 (
+  IN UINT32                 Data
+  );
+
+UINTN
+EdbPrintImmData64 (
+  IN UINT64                 Data
+  );
+
+UINTN
+EdbPrintImmDatan (
+  IN UINTN                  Data
+  );
+
+UINTN
+EdbPrintImmData64n (
+  IN UINT64                 Data64
+  );
+
+UINTN
+EdbPrintData8 (
+  IN UINT8                  Data8
+  );
+
+UINTN
+EdbPrintData16 (
+  IN UINT16                 Data16
+  );
+
+UINTN
+EdbPrintData32 (
+  IN UINT32                 Data32
+  );
+
+UINTN
+EdbPrintData64 (
+  IN UINT64                 Data64
+  );
+
+UINTN
+EdbPrintDatan (
+  IN UINTN                  Data
+  );
+
+UINTN
+EdbPrintData64n (
+  IN UINT64                 Data64
+  );
+
+UINTN
+EdbPrintData8s (
+  IN UINT8                  Data8
+  );
+
+UINTN
+EdbPrintData16s (
+  IN UINT16                 Data16
+  );
+
+UINTN
+EdbPrintData32s (
+  IN UINT32                 Data32
+  );
+
+UINTN
+EdbPrintData64s (
+  IN UINT64                 Data64
+  );
+
+UINTN
+EdbPrintComma (
+  VOID
+  );
+
+UINTN
+EdbFindAndPrintSymbol (
+  IN UINTN                  Address
+  );
+
+VOID
+EdbPrintRaw (
+  IN EFI_PHYSICAL_ADDRESS   InstructionAddress,
+  IN UINTN                  InstructionNumber
+  );
+
+EFI_STATUS
+EdbShowDisasm (
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     EFI_SYSTEM_CONTEXT        SystemContext
+  );
+
+UINT64
+GetRegisterValue (
+  IN     EFI_SYSTEM_CONTEXT        SystemContext,
+  IN     UINT8                     Index
+  );
+
+#endif
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbHook.c b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbHook.c
new file mode 100644
index 000000000000..c1431234672f
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbHook.c
@@ -0,0 +1,1003 @@
+/*++
+
+Copyright (c) 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.
+
+Module Name:
+
+  EdbHook.c
+
+Abstract:
+
+
+--*/
+
+#include "Edb.h"
+
+//
+// Hook support function
+//
+VOID
+EbcDebuggerCheckHookFlag (
+  IN VM_CONTEXT *VmPtr,
+  IN UINT32     Flag
+  )
+/*++
+
+Routine Description:
+
+  Check the Hook flag, and trigger exception if match.
+
+Arguments:
+
+  VmPtr        - EbcDebuggerCheckHookFlag
+  Flag         - Feature flag
+
+Returns:
+  None
+
+--*/
+{
+  if ((mDebuggerPrivate.FeatureFlags & Flag) == Flag) {
+    mDebuggerPrivate.StatusFlags = Flag;
+    EbcDebugSignalException (
+      EXCEPT_EBC_BREAKPOINT,
+      EXCEPTION_FLAG_NONE,
+      VmPtr
+      );
+  }
+  return ;
+}
+
+VOID
+EbcDebuggerPushCallstackSource (
+  IN UINT64                   SourceEntry,
+  IN EFI_DEBUGGER_BRANCH_TYPE Type
+  )
+/*++
+
+Routine Description:
+
+  It will record soruce address for Callstack entry.
+
+Arguments:
+
+  SourceEntry  - Source address
+  Type         - Branch type
+
+Returns:
+  None
+
+--*/
+{
+  if (mDebuggerPrivate.CallStackEntryCount > EFI_DEBUGGER_CALLSTACK_MAX) {
+    ASSERT (FALSE);
+    mDebuggerPrivate.CallStackEntryCount = EFI_DEBUGGER_CALLSTACK_MAX;
+  }
+  //
+  // Record the new callstack entry
+  //
+  mDebuggerPrivate.CallStackEntry[mDebuggerPrivate.CallStackEntryCount].SourceAddress = SourceEntry;
+  mDebuggerPrivate.CallStackEntry[mDebuggerPrivate.CallStackEntryCount].Type = Type;
+
+  //
+  // Do not change CallStackEntryCount
+  //
+
+  return ;
+}
+
+VOID
+EbcDebuggerPushCallstackParameter (
+  IN UINT64                   ParameterAddress,
+  IN EFI_DEBUGGER_BRANCH_TYPE Type
+  )
+/*++
+
+Routine Description:
+
+  It will record parameter for Callstack entry.
+
+Arguments:
+
+  ParameterAddress - The address for the parameter
+  Type             - Branch type
+
+Returns:
+  None
+
+--*/
+{
+  if (mDebuggerPrivate.CallStackEntryCount > EFI_DEBUGGER_CALLSTACK_MAX) {
+    ASSERT (FALSE);
+    mDebuggerPrivate.CallStackEntryCount = EFI_DEBUGGER_CALLSTACK_MAX;
+  }
+  //
+  // Record the new callstack parameter
+  //
+  mDebuggerPrivate.CallStackEntry[mDebuggerPrivate.CallStackEntryCount].ParameterAddr = (UINTN)ParameterAddress;
+  CopyMem (
+    mDebuggerPrivate.CallStackEntry[mDebuggerPrivate.CallStackEntryCount].Parameter,
+    (VOID *)(UINTN)ParameterAddress,
+    sizeof(mDebuggerPrivate.CallStackEntry[mDebuggerPrivate.CallStackEntryCount].Parameter)
+    );
+
+  //
+  // Do not change CallStackEntryCount
+  //
+
+  return ;
+}
+
+VOID
+EbcDebuggerPushCallstackDest (
+  IN UINT64                   DestEntry,
+  IN EFI_DEBUGGER_BRANCH_TYPE Type
+  )
+/*++
+
+Routine Description:
+
+  It will record source address for callstack entry.
+
+Arguments:
+
+  DestEntry    - Source address
+  Type         - Branch type
+
+Returns:
+  None
+
+--*/
+{
+  UINTN Index;
+
+  if (mDebuggerPrivate.CallStackEntryCount < EFI_DEBUGGER_CALLSTACK_MAX) {
+    //
+    // If there is empty entry for callstack, add it
+    //
+    ASSERT (mDebuggerPrivate.CallStackEntry[mDebuggerPrivate.CallStackEntryCount].Type == Type);
+    mDebuggerPrivate.CallStackEntry[mDebuggerPrivate.CallStackEntryCount].DestAddress = DestEntry;
+    mDebuggerPrivate.CallStackEntryCount ++;
+  } else {
+    //
+    // If there is no empty entry for callstack, throw the oldest one
+    //
+    ASSERT (mDebuggerPrivate.CallStackEntry[EFI_DEBUGGER_TRACE_MAX].Type == Type);
+    for (Index = 0; Index < EFI_DEBUGGER_CALLSTACK_MAX; Index++) {
+      mDebuggerPrivate.CallStackEntry[Index] = mDebuggerPrivate.CallStackEntry[Index + 1];
+    }
+    mDebuggerPrivate.CallStackEntry[EFI_DEBUGGER_CALLSTACK_MAX - 1].DestAddress = DestEntry;
+    mDebuggerPrivate.CallStackEntryCount = EFI_DEBUGGER_CALLSTACK_MAX;
+  }
+
+  return ;
+}
+
+VOID
+EbcDebuggerPopCallstack (
+  VOID
+  )
+/*++
+
+Routine Description:
+
+  It will throw the newest Callstack entry.
+
+Arguments:
+
+  None
+
+Returns:
+  None
+
+--*/
+{
+  if ((mDebuggerPrivate.CallStackEntryCount > 0) &&
+      (mDebuggerPrivate.CallStackEntryCount <= EFI_DEBUGGER_CALLSTACK_MAX)) {
+    //
+    // Throw the newest one
+    //
+    mDebuggerPrivate.CallStackEntryCount --;
+    mDebuggerPrivate.CallStackEntry[mDebuggerPrivate.CallStackEntryCount].SourceAddress = 0;
+    mDebuggerPrivate.CallStackEntry[mDebuggerPrivate.CallStackEntryCount].DestAddress = 0;
+  } else if (mDebuggerPrivate.CallStackEntryCount == 0) {
+    //
+    // NOT assert here because it is reasonable, because when we start to build
+    // callstack, we do not know how many function already called.
+    //
+  } else {
+    ASSERT (FALSE);
+  }
+
+  return ;
+}
+
+VOID
+EbcDebuggerPushTraceSourceEntry (
+  IN UINT64                   SourceEntry,
+  IN EFI_DEBUGGER_BRANCH_TYPE Type
+  )
+/*++
+
+Routine Description:
+
+  It will record source address for trace entry.
+
+Arguments:
+
+  SourceEntry  - Source address
+  Type         - Branch type
+
+Returns:
+  None
+
+--*/
+{
+  if (mDebuggerPrivate.TraceEntryCount > EFI_DEBUGGER_TRACE_MAX) {
+    ASSERT (FALSE);
+    mDebuggerPrivate.TraceEntryCount = EFI_DEBUGGER_TRACE_MAX;
+  }
+  //
+  // Record the new trace entry
+  //
+  mDebuggerPrivate.TraceEntry[mDebuggerPrivate.TraceEntryCount].SourceAddress = SourceEntry;
+  mDebuggerPrivate.TraceEntry[mDebuggerPrivate.TraceEntryCount].Type = Type;
+
+  //
+  // Do not change TraceEntryCount
+  //
+
+  return ;
+}
+
+VOID
+EbcDebuggerPushTraceDestEntry (
+  IN UINT64                   DestEntry,
+  IN EFI_DEBUGGER_BRANCH_TYPE Type
+  )
+/*++
+
+Routine Description:
+
+  It will record destination address for trace entry.
+
+Arguments:
+
+  DestEntry    - Destination address
+  Type         - Branch type
+
+Returns:
+  None
+
+--*/
+{
+  UINTN Index;
+
+  if (mDebuggerPrivate.TraceEntryCount < EFI_DEBUGGER_TRACE_MAX) {
+    //
+    // If there is empty entry for trace, add it
+    //
+    ASSERT (mDebuggerPrivate.TraceEntry[mDebuggerPrivate.TraceEntryCount].Type == Type);
+    mDebuggerPrivate.TraceEntry[mDebuggerPrivate.TraceEntryCount].DestAddress = DestEntry;
+    mDebuggerPrivate.TraceEntryCount ++;
+  } else {
+    //
+    // If there is no empty entry for trace, throw the oldest one
+    //
+    ASSERT (mDebuggerPrivate.TraceEntry[EFI_DEBUGGER_TRACE_MAX].Type == Type);
+    for (Index = 0; Index < EFI_DEBUGGER_TRACE_MAX; Index++) {
+      mDebuggerPrivate.TraceEntry[Index] = mDebuggerPrivate.TraceEntry[Index + 1];
+    }
+    mDebuggerPrivate.TraceEntry[EFI_DEBUGGER_CALLSTACK_MAX - 1].DestAddress = DestEntry;
+    mDebuggerPrivate.TraceEntryCount = EFI_DEBUGGER_TRACE_MAX;
+  }
+
+  return ;
+}
+
+VOID
+EbcDebuggerPushStepEntry (
+  IN UINT64                   Entry,
+  IN UINT64                   FramePtr,
+  IN UINT32                   Flag
+  )
+/*++
+
+Routine Description:
+
+  It will record address for StepEntry, if STEPOVER or STEPOUT is enabled.
+
+Arguments:
+
+  Entry    - Break Address
+  FramePtr - Break Frame pointer
+  Flag     - for STEPOVER or STEPOUT
+
+Returns:
+  None
+
+--*/
+{
+  //
+  // Check StepOver
+  //
+  if ((Flag == EFI_DEBUG_FLAG_EBC_STEPOVER) &&
+      ((mDebuggerPrivate.FeatureFlags & EFI_DEBUG_FLAG_EBC_STEPOVER) == EFI_DEBUG_FLAG_EBC_STEPOVER)) {
+    mDebuggerPrivate.StepContext.BreakAddress = Entry;
+    mDebuggerPrivate.StepContext.FramePointer = FramePtr;
+    mDebuggerPrivate.FeatureFlags &= ~EFI_DEBUG_FLAG_EBC_B_STEPOVER;
+  }
+  //
+  // Check StepOut
+  //
+  if ((Flag == EFI_DEBUG_FLAG_EBC_STEPOUT) &&
+      ((mDebuggerPrivate.FeatureFlags & EFI_DEBUG_FLAG_EBC_STEPOUT) == EFI_DEBUG_FLAG_EBC_STEPOUT)) {
+    mDebuggerPrivate.StepContext.BreakAddress = Entry;
+    mDebuggerPrivate.StepContext.FramePointer = FramePtr;
+    mDebuggerPrivate.FeatureFlags &= ~EFI_DEBUG_FLAG_EBC_B_STEPOUT;
+  }
+}
+
+VOID
+EFIAPI
+EbcDebuggerBreakEventFunc (
+  IN EFI_EVENT                Event,
+  IN VOID                     *Context
+  )
+{
+  EFI_STATUS  Status;
+
+  if ((mDebuggerPrivate.FeatureFlags & EFI_DEBUG_FLAG_EBC_BOK) != EFI_DEBUG_FLAG_EBC_BOK) {
+    return ;
+  }
+
+  Status = gBS->CheckEvent (gST->ConIn->WaitForKey);
+  if (Status == EFI_SUCCESS) {
+    mDebuggerPrivate.StatusFlags = EFI_DEBUG_FLAG_EBC_BOK;
+  }
+}
+
+//
+// Hook function implementation
+//
+VOID
+EbcDebuggerHookInit (
+  IN EFI_HANDLE                  Handle,
+  IN EFI_DEBUG_SUPPORT_PROTOCOL  *EbcDebugProtocol
+  )
+/*++
+
+Routine Description:
+
+  The hook in InitializeEbcDriver.
+  It will init the EbcDebuggerPrivate data structure.
+
+Arguments:
+
+  Handle           - The EbcDebugProtocol handle.
+  EbcDebugProtocol - The EbcDebugProtocol interface.
+
+Returns:
+  None
+
+--*/
+{
+  EFI_STATUS                 Status;
+  UINTN                      Index;
+  EFI_DEBUGGER_SYMBOL_OBJECT *Object;
+  EFI_DEBUGGER_SYMBOL_ENTRY  *Entry;
+
+
+  //
+  // Register all exception handler
+  //
+  for (Index = EXCEPT_EBC_UNDEFINED; Index <= EXCEPT_EBC_STEP; Index++) {
+    EbcDebugProtocol->RegisterExceptionCallback (
+      EbcDebugProtocol,
+      0,
+      NULL,
+      Index
+      );
+    EbcDebugProtocol->RegisterExceptionCallback (
+      EbcDebugProtocol,
+      0,
+      EdbExceptionHandler,
+      Index
+      );
+  }
+
+  //
+  // Init Symbol
+  //
+  Object = AllocateZeroPool (sizeof(EFI_DEBUGGER_SYMBOL_OBJECT) * EFI_DEBUGGER_SYMBOL_OBJECT_MAX);
+  ASSERT (Object != NULL);
+  mDebuggerPrivate.DebuggerSymbolContext.Object = Object;
+  mDebuggerPrivate.DebuggerSymbolContext.ObjectCount = 0;
+  mDebuggerPrivate.DebuggerSymbolContext.MaxObjectCount = EFI_DEBUGGER_SYMBOL_OBJECT_MAX;
+  for (Index = 0; Index < EFI_DEBUGGER_SYMBOL_OBJECT_MAX; Index++) {
+    Entry = AllocateZeroPool (sizeof(EFI_DEBUGGER_SYMBOL_ENTRY) * EFI_DEBUGGER_SYMBOL_ENTRY_MAX);
+    ASSERT (Entry != NULL);
+    Object[Index].Entry = Entry;
+    Object[Index].MaxEntryCount = EFI_DEBUGGER_SYMBOL_ENTRY_MAX;
+    Object[Index].SourceBuffer = AllocateZeroPool (sizeof(VOID *) * (EFI_DEBUGGER_SYMBOL_ENTRY_MAX + 1));
+    ASSERT (Object[Index].SourceBuffer != NULL);
+  }
+
+  //
+  // locate PciRootBridgeIo
+  //
+  Status = gBS->LocateProtocol (
+                  &gEfiPciRootBridgeIoProtocolGuid,
+                  NULL,
+                  (VOID**) &mDebuggerPrivate.PciRootBridgeIo
+                  );
+
+  //
+  // locate DebugImageInfoTable
+  //
+  Status = EfiGetSystemConfigurationTable (
+             &gEfiDebugImageInfoTableGuid,
+             (VOID**) &mDebuggerPrivate.DebugImageInfoTableHeader
+             );
+
+  //
+  // Create break event
+  //
+  Status = gBS->CreateEvent (
+                  EVT_TIMER | EVT_NOTIFY_SIGNAL,
+                  TPL_CALLBACK,
+                  EbcDebuggerBreakEventFunc,
+                  NULL,
+                  &mDebuggerPrivate.BreakEvent
+                  );
+  Status = gBS->SetTimer (
+                  mDebuggerPrivate.BreakEvent,
+                  TimerPeriodic,
+                  EFI_DEBUG_BREAK_TIMER_INTERVAL
+                  );
+
+  return ;
+}
+
+VOID
+EbcDebuggerHookUnload (
+  VOID
+  )
+/*++
+
+Routine Description:
+
+  The hook in UnloadImage for EBC Interpreter.
+  It clean up the environment.
+
+Arguments:
+
+  None
+
+Returns:
+  None
+
+--*/
+{
+  UINTN                      Index;
+  UINTN                      SubIndex;
+  EFI_DEBUGGER_SYMBOL_OBJECT *Object;
+
+  //
+  // Close the break event
+  //
+  gBS->CloseEvent (mDebuggerPrivate.BreakEvent);
+
+  //
+  // Clean up the symbol
+  //
+  Object = mDebuggerPrivate.DebuggerSymbolContext.Object;
+  for (Index = 0; Index < EFI_DEBUGGER_SYMBOL_OBJECT_MAX; Index++) {
+    //
+    // Clean up Entry
+    //
+    gBS->FreePool (Object[Index].Entry);
+    Object[Index].Entry = NULL;
+    Object[Index].EntryCount = 0;
+    //
+    // Clean up source buffer
+    //
+    for (SubIndex = 0; Object[Index].SourceBuffer[SubIndex] != NULL; SubIndex++) {
+      gBS->FreePool (Object[Index].SourceBuffer[SubIndex]);
+      Object[Index].SourceBuffer[SubIndex] = NULL;
+    }
+    gBS->FreePool (Object[Index].SourceBuffer);
+    Object[Index].SourceBuffer = NULL;
+  }
+
+  //
+  // Clean up Object
+  //
+  gBS->FreePool (Object);
+  mDebuggerPrivate.DebuggerSymbolContext.Object = NULL;
+  mDebuggerPrivate.DebuggerSymbolContext.ObjectCount = 0;
+
+  //
+  // Done
+  //
+  return ;
+}
+
+VOID
+EbcDebuggerHookEbcUnloadImage (
+  IN EFI_HANDLE                  Handle
+  )
+/*++
+
+Routine Description:
+
+  The hook in EbcUnloadImage.
+  Currently do nothing here.
+
+Arguments:
+
+  Handle           - The EbcImage handle.
+
+Returns:
+  None
+
+--*/
+{
+  return ;
+}
+
+VOID
+EbcDebuggerHookExecuteEbcImageEntryPoint (
+  IN VM_CONTEXT *VmPtr
+  )
+/*++
+
+Routine Description:
+
+  The hook in ExecuteEbcImageEntryPoint.
+  It will record the call-stack entry. (-1 means EbcImageEntryPoint call)
+  and trigger Exception if BOE enabled.
+
+Arguments:
+
+  VmPtr - pointer to VM context.
+
+Returns:
+  None
+
+--*/
+{
+  EbcDebuggerPushCallstackSource ((UINT64)(UINTN)-1, EfiDebuggerBranchTypeEbcCall);
+  EbcDebuggerPushCallstackParameter ((UINT64)(UINTN)VmPtr->Gpr[0], EfiDebuggerBranchTypeEbcCall);
+  EbcDebuggerPushCallstackDest ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCall);
+  EbcDebuggerCheckHookFlag (VmPtr, EFI_DEBUG_FLAG_EBC_BOE);
+  return ;
+}
+
+VOID
+EbcDebuggerHookEbcInterpret (
+  IN VM_CONTEXT *VmPtr
+  )
+/*++
+
+Routine Description:
+
+  The hook in ExecuteEbcImageEntryPoint.
+  It will record the call-stack entry. (-2 means EbcInterpret call)
+  and trigger Exception if BOT enabled.
+
+Arguments:
+
+  VmPtr - pointer to VM context.
+
+Returns:
+  None
+
+--*/
+{
+  EbcDebuggerPushCallstackSource ((UINT64)(UINTN)-2, EfiDebuggerBranchTypeEbcCall);
+  EbcDebuggerPushCallstackParameter ((UINT64)(UINTN)VmPtr->Gpr[0], EfiDebuggerBranchTypeEbcCall);
+  EbcDebuggerPushCallstackDest ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCall);
+  EbcDebuggerCheckHookFlag (VmPtr, EFI_DEBUG_FLAG_EBC_BOT);
+  return ;
+}
+
+VOID
+EbcDebuggerHookExecuteStart (
+  IN VM_CONTEXT *VmPtr
+  )
+/*++
+
+Routine Description:
+
+  The hook in EbcExecute, before ExecuteFunction.
+  It will trigger Exception if GoTil, StepOver, or StepOut hit.
+
+Arguments:
+
+  VmPtr - pointer to VM context.
+
+Returns:
+  None
+
+--*/
+{
+  EFI_TPL   CurrentTpl;
+
+  //
+  // Check Ip for GoTil
+  //
+  if (mDebuggerPrivate.GoTilContext.BreakAddress == (UINT64)(UINTN)VmPtr->Ip) {
+    mDebuggerPrivate.StatusFlags = EFI_DEBUG_FLAG_EBC_GT;
+    mDebuggerPrivate.GoTilContext.BreakAddress = 0;
+    EbcDebugSignalException (
+      EXCEPT_EBC_BREAKPOINT,
+      EXCEPTION_FLAG_NONE,
+      VmPtr
+      );
+    mDebuggerPrivate.StatusFlags &= ~EFI_DEBUG_FLAG_EBC_B_GT;
+    return ;
+  }
+  //
+  // Check ReturnAddress for StepOver
+  //
+  if ((mDebuggerPrivate.StepContext.BreakAddress == (UINT64)(UINTN)VmPtr->Ip) &&
+      (mDebuggerPrivate.StepContext.FramePointer == (UINT64)(UINTN)VmPtr->FramePtr)) {
+    mDebuggerPrivate.StatusFlags = EFI_DEBUG_FLAG_EBC_STEPOVER;
+    mDebuggerPrivate.StepContext.BreakAddress = 0;
+    mDebuggerPrivate.StepContext.FramePointer = 0;
+    EbcDebugSignalException (
+      EXCEPT_EBC_BREAKPOINT,
+      EXCEPTION_FLAG_NONE,
+      VmPtr
+      );
+    mDebuggerPrivate.StatusFlags &= ~EFI_DEBUG_FLAG_EBC_B_STEPOVER;
+  }
+  //
+  // Check FramePtr for StepOut
+  //
+  if (mDebuggerPrivate.StepContext.BreakAddress == (UINT64)(UINTN)VmPtr->FramePtr) {
+    mDebuggerPrivate.StatusFlags = EFI_DEBUG_FLAG_EBC_STEPOUT;
+    mDebuggerPrivate.StepContext.BreakAddress = 0;
+    mDebuggerPrivate.StepContext.FramePointer = 0;
+    EbcDebugSignalException (
+      EXCEPT_EBC_BREAKPOINT,
+      EXCEPTION_FLAG_NONE,
+      VmPtr
+      );
+    mDebuggerPrivate.StatusFlags &= ~EFI_DEBUG_FLAG_EBC_B_STEPOUT;
+  }
+  //
+  // Check Flags for BreakOnKey
+  //
+  if (mDebuggerPrivate.StatusFlags == EFI_DEBUG_FLAG_EBC_BOK) {
+    //
+    // Only break when the current TPL <= TPL_APPLICATION
+    //
+    CurrentTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
+    gBS->RestoreTPL (CurrentTpl);
+    if (CurrentTpl <= TPL_APPLICATION) {
+      EbcDebugSignalException (
+        EXCEPT_EBC_BREAKPOINT,
+        EXCEPTION_FLAG_NONE,
+        VmPtr
+        );
+      mDebuggerPrivate.StatusFlags &= ~EFI_DEBUG_FLAG_EBC_B_BOK;
+    }
+  }
+  return ;
+}
+
+VOID
+EbcDebuggerHookExecuteEnd (
+  IN VM_CONTEXT *VmPtr
+  )
+/*++
+
+Routine Description:
+
+  The hook in EbcExecute, after ExecuteFunction.
+  It will record StepOut Entry if need.
+
+Arguments:
+
+  VmPtr - pointer to VM context.
+
+Returns:
+  None
+
+--*/
+{
+  UINTN  Address;
+
+  //
+  // Use FramePtr as checkpoint for StepOut
+  //
+  CopyMem (&Address, (VOID *)((UINTN)VmPtr->FramePtr), sizeof(Address));
+  EbcDebuggerPushStepEntry (Address, (UINT64)(UINTN)VmPtr->FramePtr, EFI_DEBUG_FLAG_EBC_STEPOUT);
+
+  return ;
+}
+
+VOID
+EbcDebuggerHookCALLStart (
+  IN VM_CONTEXT *VmPtr
+  )
+/*++
+
+Routine Description:
+
+  The hook in ExecuteCALL, before move IP.
+  It will trigger Exception if BOC enabled,
+  and record Callstack, and trace information.
+
+Arguments:
+
+  VmPtr - pointer to VM context.
+
+Returns:
+  None
+
+--*/
+{
+  EbcDebuggerCheckHookFlag (VmPtr, EFI_DEBUG_FLAG_EBC_BOC);
+  EbcDebuggerPushCallstackSource ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCall);
+  EbcDebuggerPushCallstackParameter ((UINT64)(UINTN)VmPtr->Gpr[0], EfiDebuggerBranchTypeEbcCall);
+  EbcDebuggerPushTraceSourceEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCall);
+  return ;
+}
+
+VOID
+EbcDebuggerHookCALLEnd (
+  IN VM_CONTEXT *VmPtr
+  )
+/*++
+
+Routine Description:
+
+  The hook in ExecuteCALL, after move IP.
+  It will record Callstack, trace information
+  and record StepOver/StepOut Entry if need.
+
+Arguments:
+
+  VmPtr - pointer to VM context.
+
+Returns:
+  None
+
+--*/
+{
+  UINT64  Address;
+  UINTN   FramePtr;
+
+  EbcDebuggerPushCallstackDest ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCall);
+  EbcDebuggerPushTraceDestEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCall);
+
+  //
+  // Get Old FramePtr
+  //
+  CopyMem (&FramePtr, (VOID *)((UINTN)VmPtr->FramePtr), sizeof(FramePtr));
+
+  //
+  // Use ReturnAddress as checkpoint for StepOver
+  //
+  CopyMem (&Address, (VOID *)(UINTN)VmPtr->Gpr[0], sizeof(Address));
+  EbcDebuggerPushStepEntry (Address, FramePtr, EFI_DEBUG_FLAG_EBC_STEPOVER);
+
+  //
+  // Use FramePtr as checkpoint for StepOut
+  //
+  Address = 0;
+  CopyMem (&Address, (VOID *)(FramePtr), sizeof(UINTN));
+  EbcDebuggerPushStepEntry (Address, FramePtr, EFI_DEBUG_FLAG_EBC_STEPOUT);
+
+  return ;
+}
+
+VOID
+EbcDebuggerHookCALLEXStart (
+  IN VM_CONTEXT *VmPtr
+  )
+/*++
+
+Routine Description:
+
+  The hook in ExecuteCALL, before call EbcLLCALLEX.
+  It will trigger Exception if BOCX enabled,
+  and record Callstack information.
+
+Arguments:
+
+  VmPtr - pointer to VM context.
+
+Returns:
+  None
+
+--*/
+{
+  EbcDebuggerCheckHookFlag (VmPtr, EFI_DEBUG_FLAG_EBC_BOCX);
+//  EbcDebuggerPushCallstackSource ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCallEx);
+//  EbcDebuggerPushCallstackParameter ((UINT64)(UINTN)VmPtr->R[0], EfiDebuggerBranchTypeEbcCallEx);
+  EbcDebuggerPushTraceSourceEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCallEx);
+  return ;
+}
+
+VOID
+EbcDebuggerHookCALLEXEnd (
+  IN VM_CONTEXT *VmPtr
+  )
+/*++
+
+Routine Description:
+
+  The hook in ExecuteCALL, after call EbcLLCALLEX.
+  It will record trace information.
+
+Arguments:
+
+  VmPtr - pointer to VM context.
+
+Returns:
+  None
+
+--*/
+{
+//  EbcDebuggerPushCallstackDest ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCallEx);
+  EbcDebuggerPushTraceDestEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcCallEx);
+  return ;
+}
+
+VOID
+EbcDebuggerHookRETStart (
+  IN VM_CONTEXT *VmPtr
+  )
+/*++
+
+Routine Description:
+
+  The hook in ExecuteRET, before move IP.
+  It will trigger Exception if BOR enabled,
+  and record Callstack, and trace information.
+
+Arguments:
+
+  VmPtr - pointer to VM context.
+
+Returns:
+  None
+
+--*/
+{
+  EbcDebuggerCheckHookFlag (VmPtr, EFI_DEBUG_FLAG_EBC_BOR);
+  EbcDebuggerPopCallstack ();
+  EbcDebuggerPushTraceSourceEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcRet);
+  return ;
+}
+
+VOID
+EbcDebuggerHookRETEnd (
+  IN VM_CONTEXT *VmPtr
+  )
+/*++
+
+Routine Description:
+
+  The hook in ExecuteRET, after move IP.
+  It will record trace information.
+
+Arguments:
+
+  VmPtr - pointer to VM context.
+
+Returns:
+  None
+
+--*/
+{
+  EbcDebuggerPushTraceDestEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcRet);
+  return ;
+}
+
+VOID
+EbcDebuggerHookJMPStart (
+  IN VM_CONTEXT *VmPtr
+  )
+/*++
+
+Routine Description:
+
+  The hook in ExecuteJMP, before move IP.
+  It will record trace information.
+
+Arguments:
+
+  VmPtr - pointer to VM context.
+
+Returns:
+  None
+
+--*/
+{
+  EbcDebuggerPushTraceSourceEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcJmp);
+  return ;
+}
+
+VOID
+EbcDebuggerHookJMPEnd (
+  IN VM_CONTEXT *VmPtr
+  )
+/*++
+
+Routine Description:
+
+  The hook in ExecuteJMP, after move IP.
+  It will record trace information.
+
+Arguments:
+
+  VmPtr - pointer to VM context.
+
+Returns:
+  None
+
+--*/
+{
+  EbcDebuggerPushTraceDestEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcJmp);
+  return ;
+}
+
+VOID
+EbcDebuggerHookJMP8Start (
+  IN VM_CONTEXT *VmPtr
+  )
+/*++
+
+Routine Description:
+
+  The hook in ExecuteJMP8, before move IP.
+  It will record trace information.
+
+Arguments:
+
+  VmPtr - pointer to VM context.
+
+Returns:
+  None
+
+--*/
+{
+  EbcDebuggerPushTraceSourceEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcJmp8);
+  return ;
+}
+
+VOID
+EbcDebuggerHookJMP8End (
+  IN VM_CONTEXT *VmPtr
+  )
+/*++
+
+Routine Description:
+
+  The hook in ExecuteJMP8, after move IP.
+  It will record trace information.
+
+Arguments:
+
+  VmPtr - pointer to VM context.
+
+Returns:
+  None
+
+--*/
+{
+  EbcDebuggerPushTraceDestEntry ((UINT64)(UINTN)VmPtr->Ip, EfiDebuggerBranchTypeEbcJmp8);
+  return ;
+}
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbHook.h b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbHook.h
new file mode 100644
index 000000000000..3b67943f3f14
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbHook.h
@@ -0,0 +1,27 @@
+/*++
+
+Copyright (c) 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.
+
+Module Name:
+
+  EdbHook.h
+
+Abstract:
+
+
+--*/
+
+#ifndef _EFI_EDB_HOOKER_H_
+#define _EFI_EDB_HOOKER_H_
+
+#include <Uefi.h>
+#include "EbcDebuggerHook.h"
+
+#endif
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSupport.h b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSupport.h
new file mode 100644
index 000000000000..603af34e70cd
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSupport.h
@@ -0,0 +1,240 @@
+/*++
+
+Copyright (c) 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.
+
+Module Name:
+
+  EdbSupport.h
+
+Abstract:
+
+
+--*/
+
+#ifndef _EFI_EDB_SUPPORT_H_
+#define _EFI_EDB_SUPPORT_H_
+
+#include <Uefi.h>
+
+#define EFI_DEBUG_PROMPT_STRING      L"EDB > "
+#define EFI_DEBUG_PROMPT_COLUMN      5
+#define EFI_DEBUG_INPUS_BUFFER_SIZE  64
+
+#define EFI_DEBUGGER_LINE_NUMBER_IN_PAGE  0x10
+
+#define EFI_DEBUG_MAX_PRINT_BUFFER   (80 * 4)
+
+UINTN
+EFIAPI
+Xtoi (
+  CHAR16  *str
+  );
+
+UINT64
+EFIAPI
+LXtoi (
+  CHAR16  *str
+  );
+
+UINTN
+EFIAPI
+Atoi (
+  CHAR16  *str
+  );
+
+UINTN
+EFIAPI
+AsciiXtoi (
+  CHAR8  *str
+  );
+
+UINTN
+EFIAPI
+AsciiAtoi (
+  CHAR8  *str
+  );
+
+INTN
+EFIAPI
+StrCmpUnicodeAndAscii (
+  IN CHAR16   *String,
+  IN CHAR8    *String2
+  );
+
+INTN
+EFIAPI
+StriCmp (
+  IN CHAR16   *String,
+  IN CHAR16   *String2
+  );
+
+INTN
+EFIAPI
+StriCmpUnicodeAndAscii (
+  IN CHAR16   *String,
+  IN CHAR8    *String2
+  );
+
+BOOLEAN
+EFIAPI
+StrEndWith (
+  IN CHAR16                       *Str,
+  IN CHAR16                       *SubStr
+  );
+
+CHAR16 *
+EFIAPI
+StrDuplicate (
+  IN CHAR16   *Src
+  );
+
+CHAR16 *
+EFIAPI
+StrGetNewTokenLine (
+  IN CHAR16                       *String,
+  IN CHAR16                       *CharSet
+  );
+
+CHAR16 *
+EFIAPI
+StrGetNextTokenLine (
+  IN CHAR16                       *CharSet
+  );
+
+CHAR16 *
+EFIAPI
+StrGetNewTokenField (
+  IN CHAR16                       *String,
+  IN CHAR16                       *CharSet
+  );
+
+CHAR16 *
+EFIAPI
+StrGetNextTokenField (
+  IN CHAR16                       *CharSet
+  );
+
+VOID
+EFIAPI
+PatchForStrTokenAfter (
+  IN CHAR16    *Buffer,
+  IN CHAR16    Patch
+  );
+
+VOID
+EFIAPI
+PatchForStrTokenBefore (
+  IN CHAR16    *Buffer,
+  IN CHAR16    Patch
+  );
+
+CHAR8 *
+EFIAPI
+AsciiStrGetNewTokenLine (
+  IN CHAR8                       *String,
+  IN CHAR8                       *CharSet
+  );
+
+CHAR8 *
+EFIAPI
+AsciiStrGetNextTokenLine (
+  IN CHAR8                       *CharSet
+  );
+
+CHAR8 *
+EFIAPI
+AsciiStrGetNewTokenField (
+  IN CHAR8                       *String,
+  IN CHAR8                       *CharSet
+  );
+
+CHAR8 *
+EFIAPI
+AsciiStrGetNextTokenField (
+  IN CHAR8                       *CharSet
+  );
+
+VOID
+EFIAPI
+PatchForAsciiStrTokenAfter (
+  IN CHAR8    *Buffer,
+  IN CHAR8    Patch
+  );
+
+VOID
+EFIAPI
+PatchForAsciiStrTokenBefore (
+  IN CHAR8    *Buffer,
+  IN CHAR8    Patch
+  );
+
+//
+// Shell Library
+//
+VOID
+EFIAPI
+Input (
+  IN CHAR16    *Prompt OPTIONAL,
+  OUT CHAR16   *InStr,
+  IN UINTN     StrLen
+  );
+
+BOOLEAN
+EFIAPI
+SetPageBreak (
+  VOID
+  );
+
+UINTN
+EFIAPI
+EDBPrint (
+  IN CONST CHAR16  *Format,
+  ...
+  );
+
+UINTN
+EFIAPI
+EDBSPrint (
+  OUT CHAR16        *Buffer,
+  IN  INTN          BufferSize,
+  IN  CONST CHAR16  *Format,
+  ...
+  );
+
+UINTN
+EFIAPI
+EDBSPrintWithOffset (
+  OUT CHAR16        *Buffer,
+  IN  INTN          BufferSize,
+  IN  UINTN         Offset,
+  IN  CONST CHAR16  *Format,
+  ...
+  );
+
+EFI_STATUS
+EFIAPI
+ReadFileToBuffer (
+  IN  EFI_DEBUGGER_PRIVATE_DATA   *DebuggerPrivate,
+  IN  CHAR16                      *FileName,
+  OUT UINTN                       *BufferSize,
+  OUT VOID                        **Buffer,
+  IN  BOOLEAN                     ScanFs
+  );
+
+CHAR16 *
+EFIAPI
+GetFileNameUnderDir (
+  IN  EFI_DEBUGGER_PRIVATE_DATA   *DebuggerPrivate,
+  IN  CHAR16                      *DirName,
+  IN  CHAR16                      *FileName,
+  IN OUT UINTN                    *Index
+  );
+
+#endif
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSupportFile.c b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSupportFile.c
new file mode 100644
index 000000000000..0c3b586bf91c
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSupportFile.c
@@ -0,0 +1,415 @@
+/*++
+
+Copyright (c) 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.
+
+Module Name:
+
+  EdbSupportFile.c
+
+Abstract:
+
+
+--*/
+
+#include "Edb.h"
+
+EFI_STATUS
+EFIAPI
+ReadFileFromVol (
+  IN  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol,
+  IN  CHAR16                      *FileName,
+  OUT UINTN                       *BufferSize,
+  OUT VOID                        **Buffer
+  )
+/*++
+
+Routine Description:
+
+  Read a file.
+
+Arguments:
+
+  Vol             - File System Volume
+  FileName        - The file to be read.
+  BufferSize      - The file buffer size
+  Buffer          - The file buffer
+
+Returns:
+
+  EFI_SUCCESS    - read file successfully
+  EFI_NOT_FOUND  - file not found
+
+--*/
+{
+  EFI_STATUS                        Status;
+  EFI_FILE_HANDLE                   RootDir;
+  EFI_FILE_HANDLE                   Handle;
+  UINTN                             FileInfoSize;
+  EFI_FILE_INFO                     *FileInfo;
+  UINTN                             TempBufferSize;
+  VOID                              *TempBuffer;
+
+  //
+  // Open the root directory
+  //
+  Status = Vol->OpenVolume (Vol, &RootDir);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Open the file
+  //
+  Status = RootDir->Open (
+                      RootDir,
+                      &Handle,
+                      FileName,
+                      EFI_FILE_MODE_READ,
+                      0
+                      );
+  if (EFI_ERROR (Status)) {
+    RootDir->Close (RootDir);
+    return Status;
+  }
+
+  RootDir->Close (RootDir);
+
+  //
+  // Get the file information
+  //
+  FileInfoSize = sizeof(EFI_FILE_INFO) + 1024;
+
+  FileInfo = AllocateZeroPool (FileInfoSize);
+  if (FileInfo == NULL) {
+    Handle->Close (Handle);
+    return Status;
+  }
+
+  Status = Handle->GetInfo (
+                     Handle,
+                     &gEfiFileInfoGuid,
+                     &FileInfoSize,
+                     FileInfo
+                     );
+  if (EFI_ERROR (Status)) {
+    Handle->Close (Handle);
+    gBS->FreePool (FileInfo);
+    return Status;
+  }
+
+  //
+  // Allocate buffer for the file data. The last CHAR16 is for L'\0'
+  //
+  TempBufferSize = (UINTN) FileInfo->FileSize + sizeof(CHAR16);
+  TempBuffer = AllocateZeroPool (TempBufferSize);
+  if (TempBuffer == NULL) {
+    Handle->Close (Handle);
+    gBS->FreePool (FileInfo);
+    return Status;
+  }
+
+  gBS->FreePool (FileInfo);
+
+  //
+  // Read the file data to the buffer
+  //
+  Status = Handle->Read (
+                     Handle,
+                     &TempBufferSize,
+                     TempBuffer
+                     );
+  if (EFI_ERROR (Status)) {
+    Handle->Close (Handle);
+    gBS->FreePool (TempBuffer);
+    return Status;
+  }
+
+  Handle->Close (Handle);
+
+  *BufferSize = TempBufferSize;
+  *Buffer     = TempBuffer;
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+ReadFileToBuffer (
+  IN  EFI_DEBUGGER_PRIVATE_DATA   *DebuggerPrivate,
+  IN  CHAR16                      *FileName,
+  OUT UINTN                       *BufferSize,
+  OUT VOID                        **Buffer,
+  IN  BOOLEAN                     ScanFs
+  )
+/*++
+
+Routine Description:
+
+  Read a file.
+  If ScanFs is FLASE, it will use DebuggerPrivate->Vol as default Fs.
+  If ScanFs is TRUE, it will scan all FS and check the file.
+    If there is only one file match the name, it will be read.
+    If there is more than one file match the name, it will return Error.
+
+Arguments:
+
+  DebuggerPrivate - EBC Debugger private data structure
+  FileName        - The file to be read.
+  BufferSize      - The file buffer size
+  Buffer          - The file buffer
+  ScanFs          - Need Scan all FS
+
+Returns:
+
+  EFI_SUCCESS    - read file successfully
+  EFI_NOT_FOUND  - file not found
+  EFI_NO_MAPPING - there is duplicated files found
+
+--*/
+{
+  EFI_STATUS                        Status;
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
+  UINTN                             TempBufferSize;
+  VOID                              *TempBuffer;
+  UINTN                             NoHandles;
+  EFI_HANDLE                        *HandleBuffer;
+  UINTN                             Index;
+
+  //
+  // Check parameters
+  //
+  if ((FileName == NULL) || (Buffer == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // not scan fs
+  //
+  if (!ScanFs) {
+    if (DebuggerPrivate->Vol == NULL) {
+      return EFI_INVALID_PARAMETER;
+    }
+    //
+    // Read file directly from Vol
+    //
+    return ReadFileFromVol (DebuggerPrivate->Vol, FileName, BufferSize, Buffer);
+  }
+
+  //
+  // need scan fs
+  //
+
+  //
+  // Get all Vol handle
+  //
+  Status = gBS->LocateHandleBuffer (
+                   ByProtocol,
+                   &gEfiSimpleFileSystemProtocolGuid,
+                   NULL,
+                   &NoHandles,
+                   &HandleBuffer
+                   );
+  if (EFI_ERROR (Status) && (NoHandles == 0)) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Walk through each Vol
+  //
+  DebuggerPrivate->Vol = NULL;
+  *BufferSize = 0;
+  *Buffer     = NULL;
+  for (Index = 0; Index < NoHandles; Index++) {
+    Status = gBS->HandleProtocol (
+                    HandleBuffer[Index],
+                    &gEfiSimpleFileSystemProtocolGuid,
+                    (VOID**) &Vol
+                    );
+    if (EFI_ERROR(Status)) {
+      continue;
+    }
+
+    Status = ReadFileFromVol (Vol, FileName, &TempBufferSize, &TempBuffer);
+    if (!EFI_ERROR (Status)) {
+      //
+      // Read file OK, check duplication
+      //
+      if (DebuggerPrivate->Vol != NULL) {
+        //
+        // Find the duplicated file
+        //
+        gBS->FreePool (TempBuffer);
+        gBS->FreePool (*Buffer);
+        EDBPrint (L"Duplicated FileName found!\n");
+        return EFI_NO_MAPPING;
+      } else {
+        //
+        // Record value
+        //
+        DebuggerPrivate->Vol = Vol;
+        *BufferSize = TempBufferSize;
+        *Buffer     = TempBuffer;
+      }
+    }
+  }
+
+  //
+  // Scan Fs done
+  //
+  if (DebuggerPrivate->Vol == NULL) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Done
+  //
+  return EFI_SUCCESS;
+}
+
+CHAR16 *
+EFIAPI
+GetFileNameUnderDir (
+  IN  EFI_DEBUGGER_PRIVATE_DATA   *DebuggerPrivate,
+  IN  CHAR16                      *DirName,
+  IN  CHAR16                      *FileName,
+  IN OUT UINTN                    *Index
+  )
+/*++
+
+Routine Description:
+
+  Get file name under this dir with index
+
+Arguments:
+
+  DebuggerPrivate - EBC Debugger private data structure
+  DirName         - The dir to be read.
+  FileName        - The file name pattern under this dir
+  Index           - The file index under this dir
+
+Returns:
+
+  File Name which match the pattern and index.
+
+--*/
+{
+  EFI_STATUS                        Status;
+  EFI_FILE_HANDLE                   RootDir;
+  EFI_FILE_HANDLE                   Handle;
+  UINTN                             FileInfoSize;
+  EFI_FILE_INFO                     *FileInfo;
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL   *Vol;
+  VOID                              *TempName;
+  UINTN                             FileIndex;
+
+  if (DebuggerPrivate->Vol == NULL) {
+    Status = gBS->LocateProtocol (
+                    &gEfiSimpleFileSystemProtocolGuid,
+                    NULL,
+                    (VOID**) &DebuggerPrivate->Vol
+                    );
+    if (EFI_ERROR(Status)) {
+      return NULL;
+    }
+  }
+  Vol = DebuggerPrivate->Vol;
+
+  //
+  // Open the root directory
+  //
+  Status = Vol->OpenVolume (Vol, &RootDir);
+  if (EFI_ERROR (Status)) {
+    return NULL;
+  }
+
+  //
+  // Open the file
+  //
+  Status = RootDir->Open (
+                      RootDir,
+                      &Handle,
+                      DirName,
+                      EFI_FILE_MODE_READ,
+                      EFI_FILE_DIRECTORY
+                      );
+  if (EFI_ERROR (Status)) {
+    RootDir->Close (RootDir);
+    return NULL;
+  }
+  RootDir->Close (RootDir);
+
+  //
+  // Set Dir Position
+  //
+  Status = Handle->SetPosition (Handle, 0);
+  if (EFI_ERROR (Status)) {
+    Handle->Close (Handle);
+    return NULL;
+  }
+
+  //
+  // Get the file information
+  //
+  FileInfoSize = sizeof(EFI_FILE_INFO) + 1024;
+
+  FileInfo = AllocateZeroPool (FileInfoSize);
+  if (FileInfo == NULL) {
+    Handle->Close (Handle);
+    return NULL;
+  }
+
+  //
+  // Walk through each file in the directory
+  //
+  FileIndex = 0;
+  TempName = NULL;
+  while (TRUE) {
+    //
+    // Read a file entry
+    //
+    FileInfoSize = sizeof(EFI_FILE_INFO) + 1024;
+
+    Status = Handle->Read (
+                       Handle,
+                       &FileInfoSize,
+                       FileInfo
+                       );
+    if (EFI_ERROR (Status) || (FileInfoSize == 0)) {
+      break;
+    }
+
+    if ((FileInfo->Attribute & EFI_FILE_DIRECTORY) == 0) {
+      //
+      // This is a file
+      //
+
+      //
+      // Only deal with the EFI key file
+      //
+      if (!StrEndWith (FileInfo->FileName, FileName)) {
+        continue;
+      }
+
+      if (FileIndex == *Index) {
+        TempName = StrDuplicate (FileInfo->FileName);
+        *Index = *Index + 1;
+        break;
+      }
+      FileIndex ++;
+    }
+  }
+
+  //
+  // Free resources
+  //
+  gBS->FreePool (FileInfo);
+  Handle->Close (Handle);
+
+  return TempName;
+}
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSupportString.c b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSupportString.c
new file mode 100644
index 000000000000..c2afabdd4b7b
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSupportString.c
@@ -0,0 +1,991 @@
+/*++
+
+Copyright (c) 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.
+
+Module Name:
+
+  EdbSupportString.c
+
+Abstract:
+
+
+--*/
+
+#include "Edb.h"
+
+UINTN
+EFIAPI
+Xtoi (
+  CHAR16  *str
+  )
+/*++
+
+Routine Description:
+
+  Convert hex string to uint
+
+Arguments:
+
+  Str  -  The string
+
+Returns:
+
+--*/
+{
+  UINTN   u;
+  CHAR16  c;
+  UINTN   m;
+
+  ASSERT (str != NULL);
+
+  m = (UINTN) -1 >> 4;
+  //
+  // skip preceeding white space
+  //
+  while (*str && *str == ' ') {
+    str += 1;
+  }
+  //
+  // skip preceeding zeros
+  //
+  while (*str && *str == '0') {
+    str += 1;
+  }
+  //
+  // skip preceeding white space
+  //
+  if (*str && (*str == 'x' || *str == 'X')) {
+    str += 1;
+  }
+  //
+  // convert hex digits
+  //
+  u = 0;
+  c = *(str++);
+  while (c) {
+    if (c >= 'a' && c <= 'f') {
+      c -= 'a' - 'A';
+    }
+
+    if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) {
+      if (u > m) {
+        return (UINTN) -1;
+      }
+
+      u = (u << 4) | (c - (c >= 'A' ? 'A' - 10 : '0'));
+    } else {
+      break;
+    }
+
+    c = *(str++);
+  }
+
+  return u;
+}
+
+UINT64
+EFIAPI
+LXtoi (
+  CHAR16  *str
+  )
+/*++
+
+Routine Description:
+
+  Convert hex string to uint
+
+Arguments:
+
+  Str  -  The string
+
+Returns:
+
+--*/
+{
+  UINT64  u;
+  CHAR16  c;
+  UINT64  m;
+
+  ASSERT (str != NULL);
+
+  m = RShiftU64 ((UINT64) -1, 4);
+  //
+  // skip preceeding white space
+  //
+  while (*str && *str == ' ') {
+    str += 1;
+  }
+  //
+  // skip preceeding zeros
+  //
+  while (*str && *str == '0') {
+    str += 1;
+  }
+  //
+  // skip preceeding white space
+  //
+  if (*str && (*str == 'x' || *str == 'X')) {
+    str += 1;
+  }
+  //
+  // convert hex digits
+  //
+  u = 0;
+  c = *(str++);
+  while (c) {
+    if (c >= 'a' && c <= 'f') {
+      c -= 'a' - 'A';
+    }
+
+    if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) {
+      if (u > m) {
+        return (UINT64) -1;
+      }
+
+      u = LShiftU64 (u, 4);
+      u = u + (c - (c >= 'A' ? 'A' - 10 : '0'));
+    } else {
+      break;
+    }
+
+    c = *(str++);
+  }
+
+  return u;
+}
+
+UINTN
+EFIAPI
+Atoi (
+  CHAR16  *str
+  )
+/*++
+
+Routine Description:
+
+  Convert hex string to uint
+
+Arguments:
+
+  Str  -  The string
+
+Returns:
+
+--*/
+{
+  UINTN   u;
+  CHAR16  c;
+  UINTN   m;
+  UINTN   n;
+
+  ASSERT (str != NULL);
+
+  m = (UINTN) -1 / 10;
+  n = (UINTN) -1 % 10;
+  //
+  // skip preceeding white space
+  //
+  while (*str && *str == ' ') {
+    str += 1;
+  }
+  //
+  // convert digits
+  //
+  u = 0;
+  c = *(str++);
+  while (c) {
+    if (c >= '0' && c <= '9') {
+      if (u > m || (u == m && c - '0' > (INTN) n)) {
+        return (UINTN) -1;
+      }
+
+      u = (u * 10) + c - '0';
+    } else {
+      break;
+    }
+
+    c = *(str++);
+  }
+
+  return u;
+}
+
+UINTN
+EFIAPI
+AsciiXtoi (
+  CHAR8  *str
+  )
+/*++
+
+Routine Description:
+
+  Convert hex string to uint
+
+Arguments:
+
+  Str  -  The string
+
+Returns:
+
+--*/
+{
+  UINTN   u;
+  CHAR8   c;
+  UINTN   m;
+
+  ASSERT (str != NULL);
+
+  m = (UINTN) -1 >> 4;
+  //
+  // skip preceeding white space
+  //
+  while (*str && *str == ' ') {
+    str += 1;
+  }
+  //
+  // skip preceeding zeros
+  //
+  while (*str && *str == '0') {
+    str += 1;
+  }
+  //
+  // skip preceeding white space
+  //
+  if (*str && (*str == 'x' || *str == 'X')) {
+    str += 1;
+  }
+  //
+  // convert hex digits
+  //
+  u = 0;
+  c = *(str++);
+  while (c) {
+    if (c >= 'a' && c <= 'f') {
+      c -= 'a' - 'A';
+    }
+
+    if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) {
+      if (u > m) {
+        return (UINTN) -1;
+      }
+
+      u = (u << 4) | (c - (c >= 'A' ? 'A' - 10 : '0'));
+    } else {
+      break;
+    }
+
+    c = *(str++);
+  }
+
+  return u;
+}
+
+UINTN
+EFIAPI
+AsciiAtoi (
+  CHAR8  *str
+  )
+/*++
+
+Routine Description:
+
+  Convert hex string to uint
+
+Arguments:
+
+  Str  -  The string
+
+Returns:
+
+--*/
+{
+  UINTN   u;
+  CHAR8   c;
+  UINTN   m;
+  UINTN   n;
+
+  ASSERT (str != NULL);
+
+  m = (UINTN) -1 / 10;
+  n = (UINTN) -1 % 10;
+  //
+  // skip preceeding white space
+  //
+  while (*str && *str == ' ') {
+    str += 1;
+  }
+  //
+  // convert digits
+  //
+  u = 0;
+  c = *(str++);
+  while (c) {
+    if (c >= '0' && c <= '9') {
+      if (u > m || (u == m && c - '0' > (INTN) n)) {
+        return (UINTN) -1;
+      }
+
+      u = (u * 10) + c - '0';
+    } else {
+      break;
+    }
+
+    c = *(str++);
+  }
+
+  return u;
+}
+
+STATIC
+CHAR16
+UnicodeToUpper (
+  IN      CHAR16                    Chr
+  )
+{
+  return (Chr >= L'a' && Chr <= L'z') ? Chr - (L'a' - L'A') : Chr;
+}
+
+STATIC
+CHAR8
+AsciiToUpper (
+  IN      CHAR8                     Chr
+  )
+{
+  return (Chr >= 'a' && Chr <= 'z') ? Chr - ('a' - 'A') : Chr;
+}
+
+INTN
+EFIAPI
+StrCmpUnicodeAndAscii (
+  IN CHAR16   *String,
+  IN CHAR8    *String2
+  )
+/*++
+
+Routine Description:
+  Compare the Unicode and Ascii string pointed by String to the string pointed by String2.
+
+Arguments:
+  String - Unicode String to process
+
+  String2 - Ascii string to process
+
+Returns:
+  Return a positive integer if String is lexicall greater than String2; Zero if
+  the two strings are identical; and a negative interger if String is lexically
+  less than String2.
+
+--*/
+{
+  while (*String) {
+    if (*String != (CHAR16)*String2) {
+      break;
+    }
+
+    String += 1;
+    String2 += 1;
+  }
+
+  return (*String - (CHAR16)*String2);
+}
+
+INTN
+EFIAPI
+StriCmp (
+  IN CHAR16   *String,
+  IN CHAR16   *String2
+  )
+/*++
+
+Routine Description:
+  Compare the Unicode string pointed by String to the string pointed by String2.
+
+Arguments:
+  String - Unicode String to process
+  String2 - Unicode string to process
+
+Returns:
+  Return a positive integer if String is lexically greater than String2; Zero if
+  the two strings are identical; and a negative integer if String is lexically
+  less than String2.
+
+--*/
+{
+  while ((*String != L'\0') &&
+         (UnicodeToUpper (*String) == UnicodeToUpper (*String2))) {
+    String++;
+    String2++;
+  }
+
+  return UnicodeToUpper (*String) - UnicodeToUpper (*String2);
+}
+
+INTN
+EFIAPI
+StriCmpUnicodeAndAscii (
+  IN CHAR16   *String,
+  IN CHAR8    *String2
+  )
+/*++
+
+Routine Description:
+  Compare the Unicode and Ascii string pointed by String to the string pointed by String2.
+
+Arguments:
+  String - Unicode String to process
+
+  String2 - Ascii string to process
+
+Returns:
+  Return a positive integer if String is lexically greater than String2; Zero if
+  the two strings are identical; and a negative integer if String is lexically
+  less than String2.
+
+--*/
+{
+  while ((*String != L'\0') &&
+         (UnicodeToUpper (*String) == (CHAR16)AsciiToUpper (*String2))) {
+    String++;
+    String2++;
+  }
+
+  return UnicodeToUpper (*String) - (CHAR16)AsciiToUpper (*String2);
+}
+
+BOOLEAN
+EFIAPI
+StrEndWith (
+  IN CHAR16                       *Str,
+  IN CHAR16                       *SubStr
+  )
+/*++
+
+Routine Description:
+
+  Verify if the string is end with the sub string.
+
+--*/
+{
+  CHAR16  *Temp;
+
+  if ((Str == NULL) || (SubStr == NULL) || (StrLen(Str) < StrLen(SubStr))) {
+    return FALSE;
+  }
+
+  Temp = Str + StrLen(Str) - StrLen(SubStr);
+
+  //
+  // Compare
+  //
+  if (StriCmp (Temp, SubStr) == 0) {
+    return TRUE;
+  } else {
+    return FALSE;
+  }
+}
+
+CHAR16 *
+EFIAPI
+StrDuplicate (
+  IN CHAR16   *Src
+  )
+// duplicate a string
+{
+  CHAR16      *Dest;
+  UINTN       Size;
+
+  Size = (StrLen(Src) + 1) * sizeof(CHAR16);
+  Dest = AllocateZeroPool (Size);
+  if (Dest) {
+    CopyMem (Dest, Src, Size);
+  }
+  return Dest;
+}
+
+
+CHAR16  *mLineBuffer          = NULL;
+CHAR16  *mFieldBuffer         = NULL;
+
+UINTN
+EFIAPI
+StrSpn (
+  IN CHAR16                       *String,
+  IN CHAR16                       *CharSet
+  )
+/*++
+
+Routine Description:
+
+  Find the first substring.
+
+--*/
+{
+  UINTN   Count;
+  CHAR16  *Str1;
+  CHAR16  *Str2;
+
+  Count = 0;
+
+  for (Str1 = String; *Str1 != L'\0'; Str1 ++) {
+    for (Str2 = CharSet; *Str2 != L'\0'; Str2 ++) {
+      if (*Str1 == *Str2) {
+        break;
+      }
+    }
+
+    if (*Str2 == L'\0') {
+      return Count;
+    }
+
+    Count ++;
+  }
+
+  return Count;
+}
+
+
+CHAR16 *
+EFIAPI
+StrBrk (
+  IN CHAR16                       *String,
+  IN CHAR16                       *CharSet
+  )
+/*++
+
+Routine Description:
+
+  Searches a string for the first occurrence of a character contained in a
+  specified buffer.
+
+--*/
+{
+  CHAR16  *Str1;
+  CHAR16  *Str2;
+
+  for (Str1 = String; *Str1 != L'\0'; Str1 ++) {
+    for (Str2 = CharSet; *Str2 != L'\0'; Str2 ++) {
+      if (*Str1 == *Str2) {
+        return (CHAR16 *) Str1;
+      }
+    }
+  }
+
+  return NULL;
+}
+
+CHAR16 *
+EFIAPI
+StrTokenLine (
+  IN CHAR16                       *String OPTIONAL,
+  IN CHAR16                       *CharSet
+  )
+/*++
+
+Routine Description:
+
+  Find the next token after one or more specified characters.
+
+--*/
+{
+  CHAR16  *Begin;
+  CHAR16  *End;
+
+  Begin = (String == NULL) ? mLineBuffer : String;
+  if (Begin == NULL) {
+    return NULL;
+  }
+
+  Begin += StrSpn (Begin, CharSet);
+  if (*Begin == L'\0') {
+    mLineBuffer = NULL;
+    return NULL;
+  }
+
+  End = StrBrk (Begin, CharSet);
+  if ((End != NULL) && (*End != L'\0')) {
+    *End = L'\0';
+    End ++;
+  }
+
+  mLineBuffer = End;
+  return Begin;
+}
+
+
+CHAR16 *
+EFIAPI
+StrTokenField (
+  IN CHAR16                       *String OPTIONAL,
+  IN CHAR16                       *CharSet
+  )
+/*++
+
+Routine Description:
+
+  Find the next token after one specificed characters.
+
+--*/
+{
+  CHAR16  *Begin;
+  CHAR16  *End;
+
+
+  Begin = (String == NULL) ? mFieldBuffer : String;
+  if (Begin == NULL) {
+    return NULL;
+  }
+
+  if (*Begin == L'\0') {
+    mFieldBuffer = NULL;
+    return NULL;
+  }
+
+  End = StrBrk (Begin, CharSet);
+  if ((End != NULL) && (*End != L'\0')) {
+    *End = L'\0';
+    End ++;
+  }
+
+  mFieldBuffer = End;
+  return Begin;
+}
+
+CHAR16 *
+EFIAPI
+StrGetNewTokenLine (
+  IN CHAR16                       *String,
+  IN CHAR16                       *CharSet
+  )
+{
+  return StrTokenLine (String, CharSet);
+}
+
+CHAR16 *
+EFIAPI
+StrGetNextTokenLine (
+  IN CHAR16                       *CharSet
+  )
+{
+  return StrTokenLine (NULL, CharSet);
+}
+
+CHAR16 *
+EFIAPI
+StrGetNewTokenField (
+  IN CHAR16                       *String,
+  IN CHAR16                       *CharSet
+  )
+{
+  return StrTokenField (String, CharSet);
+}
+
+CHAR16 *
+EFIAPI
+StrGetNextTokenField (
+  IN CHAR16                       *CharSet
+  )
+{
+  return StrTokenField (NULL, CharSet);
+}
+
+VOID
+EFIAPI
+PatchForStrTokenAfter (
+  IN CHAR16    *Buffer,
+  IN CHAR16    Patch
+  )
+{
+  CHAR16 *Str;
+
+  if (Buffer == NULL) {
+    return ;
+  }
+
+  Str = Buffer;
+  while (*Str != 0) {
+    Str ++;
+  }
+  *Str = Patch;
+
+  while (*(Str ++)) {
+    if (*Str == 0) {
+      *Str = Patch;
+    } else {
+      break;
+    }
+  }
+
+  return ;
+}
+
+VOID
+EFIAPI
+PatchForStrTokenBefore (
+  IN CHAR16    *Buffer,
+  IN CHAR16    Patch
+  )
+{
+  CHAR16 *Str;
+
+  if (Buffer == NULL) {
+    return ;
+  }
+
+  Str = Buffer;
+  while (*(Str --)) {
+    if ((*Str == 0) || (*Str == Patch)) {
+      *Str = Patch;
+    } else {
+      break;
+    }
+  }
+
+  return ;
+}
+
+CHAR8  *mAsciiLineBuffer          = NULL;
+CHAR8  *mAsciiFieldBuffer         = NULL;
+
+UINTN
+EFIAPI
+AsciiStrSpn (
+  IN CHAR8                       *String,
+  IN CHAR8                       *CharSet
+  )
+/*++
+
+Routine Description:
+
+  Find the first substring.
+
+--*/
+{
+  UINTN   Count;
+  CHAR8  *Str1;
+  CHAR8  *Str2;
+
+  Count = 0;
+
+  for (Str1 = String; *Str1 != '\0'; Str1 ++) {
+    for (Str2 = CharSet; *Str2 != '\0'; Str2 ++) {
+      if (*Str1 == *Str2) {
+        break;
+      }
+    }
+
+    if (*Str2 == '\0') {
+      return Count;
+    }
+
+    Count ++;
+  }
+
+  return Count;
+}
+
+
+CHAR8 *
+EFIAPI
+AsciiStrBrk (
+  IN CHAR8                       *String,
+  IN CHAR8                       *CharSet
+  )
+/*++
+
+Routine Description:
+
+  Searches a string for the first occurrence of a character contained in a
+  specified buffer.
+
+--*/
+{
+  CHAR8  *Str1;
+  CHAR8  *Str2;
+
+  for (Str1 = String; *Str1 != '\0'; Str1 ++) {
+    for (Str2 = CharSet; *Str2 != '\0'; Str2 ++) {
+      if (*Str1 == *Str2) {
+        return (CHAR8 *) Str1;
+      }
+    }
+  }
+
+  return NULL;
+}
+
+CHAR8 *
+EFIAPI
+AsciiStrTokenLine (
+  IN CHAR8                       *String OPTIONAL,
+  IN CHAR8                       *CharSet
+  )
+/*++
+
+Routine Description:
+
+  Find the next token after one or more specified characters.
+
+--*/
+{
+  CHAR8  *Begin;
+  CHAR8  *End;
+
+  Begin = (String == NULL) ? mAsciiLineBuffer : String;
+  if (Begin == NULL) {
+    return NULL;
+  }
+
+  Begin += AsciiStrSpn (Begin, CharSet);
+  if (*Begin == '\0') {
+    mAsciiLineBuffer = NULL;
+    return NULL;
+  }
+
+  End = AsciiStrBrk (Begin, CharSet);
+  if ((End != NULL) && (*End != '\0')) {
+    *End = '\0';
+    End ++;
+  }
+
+  mAsciiLineBuffer = End;
+  return Begin;
+}
+
+
+CHAR8 *
+EFIAPI
+AsciiStrTokenField (
+  IN CHAR8                       *String OPTIONAL,
+  IN CHAR8                       *CharSet
+  )
+/*++
+
+Routine Description:
+
+  Find the next token after one specificed characters.
+
+--*/
+{
+  CHAR8  *Begin;
+  CHAR8  *End;
+
+
+  Begin = (String == NULL) ? mAsciiFieldBuffer : String;
+  if (Begin == NULL) {
+    return NULL;
+  }
+
+  if (*Begin == L'\0') {
+    mAsciiFieldBuffer = NULL;
+    return NULL;
+  }
+
+  End = AsciiStrBrk (Begin, CharSet);
+  if ((End != NULL) && (*End != '\0')) {
+    *End = '\0';
+    End ++;
+  }
+
+  mAsciiFieldBuffer = End;
+  return Begin;
+}
+
+CHAR8 *
+EFIAPI
+AsciiStrGetNewTokenLine (
+  IN CHAR8                       *String,
+  IN CHAR8                       *CharSet
+  )
+{
+  return AsciiStrTokenLine (String, CharSet);
+}
+
+CHAR8 *
+EFIAPI
+AsciiStrGetNextTokenLine (
+  IN CHAR8                       *CharSet
+  )
+{
+  return AsciiStrTokenLine (NULL, CharSet);
+}
+
+CHAR8 *
+EFIAPI
+AsciiStrGetNewTokenField (
+  IN CHAR8                       *String,
+  IN CHAR8                       *CharSet
+  )
+{
+  return AsciiStrTokenField (String, CharSet);
+}
+
+CHAR8 *
+EFIAPI
+AsciiStrGetNextTokenField (
+  IN CHAR8                       *CharSet
+  )
+{
+  return AsciiStrTokenField (NULL, CharSet);
+}
+
+VOID
+EFIAPI
+PatchForAsciiStrTokenAfter (
+  IN CHAR8    *Buffer,
+  IN CHAR8    Patch
+  )
+{
+  CHAR8 *Str;
+
+  if (Buffer == NULL) {
+    return ;
+  }
+
+  Str = Buffer;
+  while (*Str != 0) {
+    Str ++;
+  }
+  *Str = Patch;
+
+  while (*(Str ++)) {
+    if (*Str == 0) {
+      *Str = Patch;
+    } else {
+      break;
+    }
+  }
+
+  return ;
+}
+
+VOID
+EFIAPI
+PatchForAsciiStrTokenBefore (
+  IN CHAR8    *Buffer,
+  IN CHAR8    Patch
+  )
+{
+  CHAR8 *Str;
+
+  if (Buffer == NULL) {
+    return ;
+  }
+
+  Str = Buffer;
+  while (*(Str --)) {
+    if ((*Str == 0) || (*Str == Patch)) {
+      *Str = Patch;
+    } else {
+      break;
+    }
+  }
+
+  return ;
+}
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSupportUI.c b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSupportUI.c
new file mode 100644
index 000000000000..3637065cd999
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSupportUI.c
@@ -0,0 +1,708 @@
+/*++
+
+Copyright (c) 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.
+
+Module Name:
+
+  EdbSupportUI.c
+
+Abstract:
+
+
+--*/
+
+#include "Edb.h"
+
+VOID
+EFIAPI
+SetCursorPosition (
+  IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *ConOut,
+  IN  UINTN                           Column,
+  IN  INTN                            Row,
+  IN  UINTN                           LineLength,
+  IN  UINTN                           TotalRow,
+  IN  CHAR16                          *Str,
+  IN  UINTN                           StrPos,
+  IN  UINTN                           Len
+  );
+
+EFI_STATUS
+EFIAPI
+WaitForSingleEvent (
+  IN EFI_EVENT                  Event,
+  IN UINT64                     Timeout OPTIONAL
+  )
+/*++
+
+Routine Description:
+  Function waits for a given event to fire, or for an optional timeout to expire.
+
+Arguments:
+  Event            - The event to wait for
+
+  Timeout          - An optional timeout value in 100 ns units.
+
+Returns:
+
+  EFI_SUCCESS       - Event fired before Timeout expired.
+  EFI_TIME_OUT     - Timout expired before Event fired..
+
+--*/
+{
+  EFI_STATUS  Status;
+  UINTN       Index;
+  EFI_EVENT   TimerEvent;
+  EFI_EVENT   WaitList[2];
+
+  if (Timeout) {
+    //
+    // Create a timer event
+    //
+    Status = gBS->CreateEvent (EVT_TIMER, 0, NULL, NULL, &TimerEvent);
+    if (!EFI_ERROR (Status)) {
+      //
+      // Set the timer event
+      //
+      gBS->SetTimer (
+            TimerEvent,
+            TimerRelative,
+            Timeout
+            );
+
+      //
+      // Wait for the original event or the timer
+      //
+      WaitList[0] = Event;
+      WaitList[1] = TimerEvent;
+      Status      = gBS->WaitForEvent (2, WaitList, &Index);
+      gBS->CloseEvent (TimerEvent);
+
+      //
+      // If the timer expired, change the return to timed out
+      //
+      if (!EFI_ERROR (Status) && Index == 1) {
+        Status = EFI_TIMEOUT;
+      }
+    }
+  } else {
+    //
+    // No timeout... just wait on the event
+    //
+    Status = gBS->WaitForEvent (1, &Event, &Index);
+    ASSERT (!EFI_ERROR (Status));
+    ASSERT (Index == 0);
+  }
+
+  return Status;
+}
+
+VOID
+EFIAPI
+ConMoveCursorBackward (
+  IN     UINTN                   LineLength,
+  IN OUT UINTN                   *Column,
+  IN OUT UINTN                   *Row
+  )
+/*++
+
+Routine Description:
+  Move the cursor position one character backward.
+
+Arguments:
+  LineLength       Length of a line. Get it by calling QueryMode
+  Column           Current column of the cursor position
+  Row              Current row of the cursor position
+
+Returns:
+
+--*/
+{
+  ASSERT (Column != NULL);
+  ASSERT (Row != NULL);
+  //
+  // If current column is 0, move to the last column of the previous line,
+  // otherwise, just decrement column.
+  //
+  if (*Column == 0) {
+    (*Column) = LineLength - 1;
+    //
+    //   if (*Row > 0) {
+    //
+    (*Row)--;
+    //
+    // }
+    //
+  } else {
+    (*Column)--;
+  }
+}
+
+VOID
+EFIAPI
+ConMoveCursorForward (
+  IN     UINTN                   LineLength,
+  IN     UINTN                   TotalRow,
+  IN OUT UINTN                   *Column,
+  IN OUT UINTN                   *Row
+  )
+/*++
+
+Routine Description:
+  Move the cursor position one character backward.
+
+Arguments:
+  LineLength       Length of a line. Get it by calling QueryMode
+  TotalRow         Total row of a screen, get by calling QueryMode
+  Column           Current column of the cursor position
+  Row              Current row of the cursor position
+
+Returns:
+
+--*/
+{
+  ASSERT (Column != NULL);
+  ASSERT (Row != NULL);
+  //
+  // If current column is at line end, move to the first column of the nest
+  // line, otherwise, just increment column.
+  //
+  (*Column)++;
+  if (*Column >= LineLength) {
+    (*Column) = 0;
+    if ((*Row) < TotalRow - 1) {
+      (*Row)++;
+    }
+  }
+}
+
+CHAR16 mBackupSpace[EFI_DEBUG_INPUS_BUFFER_SIZE];
+CHAR16 mInputBufferHistory[EFI_DEBUG_INPUS_BUFFER_SIZE];
+
+VOID
+EFIAPI
+Input (
+  IN CHAR16    *Prompt OPTIONAL,
+  OUT CHAR16   *InStr,
+  IN UINTN     StrLength
+  )
+{
+  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL     *ConOut;
+  EFI_SIMPLE_TEXT_INPUT_PROTOCOL      *ConIn;
+  BOOLEAN       Done;
+  UINTN         Column;
+  UINTN         Row;
+  UINTN         StartColumn;
+  UINTN         Update;
+  UINTN         Delete;
+  UINTN         Len;
+  UINTN         StrPos;
+  UINTN         Index;
+  UINTN         LineLength;
+  UINTN         TotalRow;
+  UINTN         SkipLength;
+  UINTN         OutputLength;
+  UINTN         TailRow;
+  UINTN         TailColumn;
+  EFI_INPUT_KEY Key;
+  BOOLEAN       InsertMode;
+  BOOLEAN       NeedAdjust;
+  UINTN         SubIndex;
+  CHAR16        *CommandStr;
+
+  ConOut = gST->ConOut;
+  ConIn = gST->ConIn;
+
+  ASSERT (ConOut != NULL);
+  ASSERT (ConIn != NULL);
+  ASSERT (InStr != NULL);
+
+  if (Prompt) {
+    ConOut->OutputString (ConOut, Prompt);
+  }
+  //
+  // Read a line from the console
+  //
+  Len           = 0;
+  StrPos        = 0;
+  OutputLength  = 0;
+  Update        = 0;
+  Delete        = 0;
+  InsertMode    = TRUE;
+  NeedAdjust    = FALSE;
+
+  //
+  // If buffer is not large enough to hold a CHAR16, do nothing.
+  //
+  if (StrLength < 1) {
+    return ;
+  }
+  //
+  // Get the screen setting and the current cursor location
+  //
+  StartColumn = ConOut->Mode->CursorColumn;
+  Column      = StartColumn;
+  Row         = ConOut->Mode->CursorRow;
+  ConOut->QueryMode (ConOut, ConOut->Mode->Mode, &LineLength, &TotalRow);
+  if (LineLength == 0) {
+    return ;
+  }
+
+  SetMem (InStr, StrLength * sizeof (CHAR16), 0);
+  Done = FALSE;
+  do {
+    //
+    // Read a key
+    //
+    WaitForSingleEvent (ConIn->WaitForKey, 0);
+    ConIn->ReadKeyStroke (ConIn, &Key);
+
+    switch (Key.UnicodeChar) {
+    case CHAR_CARRIAGE_RETURN:
+      //
+      // All done, print a newline at the end of the string
+      //
+      TailRow     = Row + (Len - StrPos + Column) / LineLength;
+      TailColumn  = (Len - StrPos + Column) % LineLength;
+      Done        = TRUE;
+      break;
+
+    case CHAR_BACKSPACE:
+      if (StrPos) {
+        //
+        // If not move back beyond string beginning, move all characters behind
+        // the current position one character forward
+        //
+        StrPos -= 1;
+        Update  = StrPos;
+        Delete  = 1;
+        CopyMem (InStr + StrPos, InStr + StrPos + 1, sizeof (CHAR16) * (Len - StrPos));
+
+        //
+        // Adjust the current column and row
+        //
+        ConMoveCursorBackward (LineLength, &Column, &Row);
+
+        NeedAdjust = TRUE;
+      }
+      break;
+
+    default:
+      if (Key.UnicodeChar >= ' ') {
+        //
+        // If we are at the buffer's end, drop the key
+        //
+        if (Len == StrLength - 1 && (InsertMode || StrPos == Len)) {
+          break;
+        }
+        //
+        // If in insert mode, move all characters behind the current position
+        // one character backward to make space for this character. Then store
+        // the character.
+        //
+        if (InsertMode) {
+          for (Index = Len; Index > StrPos; Index -= 1) {
+            InStr[Index] = InStr[Index - 1];
+          }
+        }
+
+        InStr[StrPos] = Key.UnicodeChar;
+        Update        = StrPos;
+
+        StrPos += 1;
+        OutputLength = 1;
+      }
+      break;
+
+    case 0:
+      switch (Key.ScanCode) {
+      case SCAN_DELETE:
+        //
+        // Move characters behind current position one character forward
+        //
+        if (Len) {
+          Update  = StrPos;
+          Delete  = 1;
+          CopyMem (InStr + StrPos, InStr + StrPos + 1, sizeof (CHAR16) * (Len - StrPos));
+
+          NeedAdjust = TRUE;
+        }
+        break;
+
+      case SCAN_LEFT:
+        //
+        // Adjust current cursor position
+        //
+        if (StrPos) {
+          StrPos -= 1;
+          ConMoveCursorBackward (LineLength, &Column, &Row);
+        }
+        break;
+
+      case SCAN_RIGHT:
+        //
+        // Adjust current cursor position
+        //
+        if (StrPos < Len) {
+          StrPos += 1;
+          ConMoveCursorForward (LineLength, TotalRow, &Column, &Row);
+        }
+        break;
+
+      case SCAN_HOME:
+        //
+        // Move current cursor position to the beginning of the command line
+        //
+        Row -= (StrPos + StartColumn) / LineLength;
+        Column  = StartColumn;
+        StrPos  = 0;
+        break;
+
+      case SCAN_END:
+        //
+        // Move current cursor position to the end of the command line
+        //
+        TailRow     = Row + (Len - StrPos + Column) / LineLength;
+        TailColumn  = (Len - StrPos + Column) % LineLength;
+        Row         = TailRow;
+        Column      = TailColumn;
+        StrPos      = Len;
+        break;
+
+      case SCAN_ESC:
+        //
+        // Prepare to clear the current command line
+        //
+        InStr[0]  = 0;
+        Update    = 0;
+        Delete    = Len;
+        Row -= (StrPos + StartColumn) / LineLength;
+        Column        = StartColumn;
+        OutputLength  = 0;
+
+        NeedAdjust = TRUE;
+        break;
+
+      case SCAN_INSERT:
+        //
+        // Toggle the SEnvInsertMode flag
+        //
+        InsertMode = (BOOLEAN)!InsertMode;
+        break;
+
+      case SCAN_UP:
+      case SCAN_DOWN:
+        //
+        // show history
+        //
+        CopyMem (InStr, mInputBufferHistory, StrLength * sizeof(CHAR16));
+        StrPos       = StrLen (mInputBufferHistory);
+        Update       = 0;
+        Delete       = 0;
+        OutputLength = 0;
+
+        TailRow      = Row + (StrPos + StartColumn) / LineLength;
+        TailColumn   = (StrPos + StartColumn) % LineLength;
+        Row          = TailRow;
+        Column       = TailColumn;
+        NeedAdjust   = FALSE;
+
+        ConOut->SetCursorPosition (ConOut, StartColumn, Row);
+        for (SubIndex = 0; SubIndex < EFI_DEBUG_INPUS_BUFFER_SIZE - (StartColumn - EFI_DEBUG_PROMPT_COLUMN); SubIndex++) {
+          mBackupSpace[SubIndex] = L' ';
+        }
+        EDBPrint (mBackupSpace);
+        SetMem (mBackupSpace, (EFI_DEBUG_INPUS_BUFFER_SIZE - (StartColumn - EFI_DEBUG_PROMPT_COLUMN)) * sizeof(CHAR16), 0);
+
+        ConOut->SetCursorPosition (ConOut, StartColumn, Row);
+        Len = StrPos;
+
+        break;
+
+      case SCAN_F1:
+      case SCAN_F2:
+      case SCAN_F3:
+      case SCAN_F4:
+      case SCAN_F5:
+      case SCAN_F6:
+      case SCAN_F7:
+      case SCAN_F8:
+      case SCAN_F9:
+      case SCAN_F10:
+      case SCAN_F11:
+      case SCAN_F12:
+        CommandStr = GetCommandNameByKey (Key);
+        if (CommandStr != NULL) {
+          StrnCpyS (InStr, StrLength, CommandStr, StrLength - 1);
+          return ;
+        }
+        break;
+      }
+    }
+
+    if (Done) {
+      break;
+    }
+    //
+    // If we need to update the output do so now
+    //
+    if (Update != -1) {
+      if (NeedAdjust) {
+        ConOut->SetCursorPosition (ConOut, Column, Row);
+        for (SubIndex = 0; SubIndex < EFI_DEBUG_INPUS_BUFFER_SIZE - (Column - EFI_DEBUG_PROMPT_COLUMN); SubIndex++) {
+          mBackupSpace[SubIndex] = L' ';
+        }
+        EDBPrint (mBackupSpace);
+        SetMem (mBackupSpace, (EFI_DEBUG_INPUS_BUFFER_SIZE - (Column - EFI_DEBUG_PROMPT_COLUMN)) * sizeof(CHAR16), 0);
+        ConOut->SetCursorPosition (ConOut, Column, Row);
+        NeedAdjust = FALSE;
+      }
+      EDBPrint (InStr + Update);
+      Len = StrLen (InStr);
+
+      if (Delete) {
+        SetMem (InStr + Len, Delete * sizeof (CHAR16), 0x00);
+      }
+
+      if (StrPos > Len) {
+        StrPos = Len;
+      }
+
+      Update = (UINTN) -1;
+
+      //
+      // After using print to reflect newly updates, if we're not using
+      // BACKSPACE and DELETE, we need to move the cursor position forward,
+      // so adjust row and column here.
+      //
+      if (Key.UnicodeChar != CHAR_BACKSPACE && !(Key.UnicodeChar == 0 && Key.ScanCode == SCAN_DELETE)) {
+        //
+        // Calulate row and column of the tail of current string
+        //
+        TailRow     = Row + (Len - StrPos + Column + OutputLength) / LineLength;
+        TailColumn  = (Len - StrPos + Column + OutputLength) % LineLength;
+
+        //
+        // If the tail of string reaches screen end, screen rolls up, so if
+        // Row does not equal TailRow, Row should be decremented
+        //
+        // (if we are recalling commands using UPPER and DOWN key, and if the
+        // old command is too long to fit the screen, TailColumn must be 79.
+        //
+        if (TailColumn == 0 && TailRow >= TotalRow && (UINTN) Row != TailRow) {
+          Row--;
+        }
+        //
+        // Calculate the cursor position after current operation. If cursor
+        // reaches line end, update both row and column, otherwise, only
+        // column will be changed.
+        //
+        if (Column + OutputLength >= LineLength) {
+          SkipLength = OutputLength - (LineLength - Column);
+
+          Row += SkipLength / LineLength + 1;
+          if ((UINTN) Row > TotalRow - 1) {
+            Row = TotalRow - 1;
+          }
+
+          Column = SkipLength % LineLength;
+        } else {
+          Column += OutputLength;
+        }
+      }
+
+      Delete = 0;
+    }
+    //
+    // Set the cursor position for this key
+    //
+    SetCursorPosition (ConOut, Column, Row, LineLength, TotalRow, InStr, StrPos, Len);
+  } while (!Done);
+
+  CopyMem (mInputBufferHistory, InStr, StrLength * sizeof(CHAR16));
+
+  //
+  // Return the data to the caller
+  //
+  return ;
+}
+
+VOID
+EFIAPI
+SetCursorPosition (
+  IN  EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut,
+  IN  UINTN                           Column,
+  IN  INTN                            Row,
+  IN  UINTN                           LineLength,
+  IN  UINTN                           TotalRow,
+  IN  CHAR16                          *Str,
+  IN  UINTN                           StrPos,
+  IN  UINTN                           Len
+  )
+{
+  CHAR16  Backup;
+
+  ASSERT (ConOut != NULL);
+  ASSERT (Str != NULL);
+
+  Backup = 0;
+  if (Row >= 0) {
+    ConOut->SetCursorPosition (ConOut, Column, Row);
+    return ;
+  }
+
+  if (Len - StrPos > Column * Row) {
+    Backup                          = *(Str + StrPos + Column * Row);
+    *(Str + StrPos + Column * Row)  = 0;
+  }
+
+  EDBPrint (L"%s", Str + StrPos);
+  if (Len - StrPos > Column * Row) {
+    *(Str + StrPos + Column * Row) = Backup;
+  }
+
+  ConOut->SetCursorPosition (ConOut, 0, 0);
+}
+
+BOOLEAN
+EFIAPI
+SetPageBreak (
+  VOID
+  )
+{
+  EFI_INPUT_KEY Key;
+  CHAR16        Str[3];
+  BOOLEAN       OmitPrint;
+
+  //
+  // Check
+  //
+  if (!mDebuggerPrivate.EnablePageBreak) {
+    return FALSE;
+  }
+
+  gST->ConOut->OutputString (gST->ConOut, L"Press ENTER to continue, 'q' to exit:");
+
+  OmitPrint = FALSE;
+  //
+  // Wait for user input
+  //
+  Str[0]  = ' ';
+  Str[1]  = 0;
+  Str[2]  = 0;
+  for (;;) {
+    WaitForSingleEvent (gST->ConIn->WaitForKey, 0);
+    gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+
+    //
+    // handle control keys
+    //
+    if (Key.UnicodeChar == CHAR_NULL) {
+      if (Key.ScanCode == SCAN_ESC) {
+        gST->ConOut->OutputString (gST->ConOut, L"\r\n");
+        OmitPrint = TRUE;
+        break;
+      }
+
+      continue;
+    }
+
+    if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
+      gST->ConOut->OutputString (gST->ConOut, L"\r\n");
+      break;
+    }
+    //
+    // Echo input
+    //
+    Str[1] = Key.UnicodeChar;
+    if (Str[1] == CHAR_BACKSPACE) {
+      continue;
+    }
+
+    gST->ConOut->OutputString (gST->ConOut, Str);
+
+    if ((Str[1] == L'q') || (Str[1] == L'Q')) {
+      OmitPrint = TRUE;
+    } else {
+      OmitPrint = FALSE;
+    }
+
+    Str[0] = CHAR_BACKSPACE;
+  }
+
+  return OmitPrint;
+}
+
+UINTN
+EFIAPI
+EDBPrint (
+  IN CONST CHAR16  *Format,
+  ...
+  )
+{
+  UINTN   Return;
+  VA_LIST Marker;
+  CHAR16  Buffer[EFI_DEBUG_MAX_PRINT_BUFFER];
+
+  VA_START (Marker, Format);
+  Return = UnicodeVSPrint (Buffer, sizeof (Buffer), Format, Marker);
+  VA_END (Marker);
+
+  if (gST->ConOut != NULL) {
+    //
+    // To be extra safe make sure ConOut has been initialized
+    //
+    gST->ConOut->OutputString (gST->ConOut, Buffer);
+  }
+
+  return Return;
+}
+
+UINTN
+EFIAPI
+EDBSPrint (
+  OUT CHAR16        *Buffer,
+  IN  INTN          BufferSize,
+  IN  CONST CHAR16  *Format,
+  ...
+  )
+{
+  UINTN   Return;
+  VA_LIST Marker;
+
+  ASSERT (BufferSize > 0);
+
+  VA_START (Marker, Format);
+  Return = UnicodeVSPrint (Buffer, (UINTN)BufferSize, Format, Marker);
+  VA_END (Marker);
+
+  return Return;
+}
+
+UINTN
+EFIAPI
+EDBSPrintWithOffset (
+  OUT CHAR16        *Buffer,
+  IN  INTN          BufferSize,
+  IN  UINTN         Offset,
+  IN  CONST CHAR16  *Format,
+  ...
+  )
+{
+  UINTN   Return;
+  VA_LIST Marker;
+
+  ASSERT (BufferSize - (Offset * sizeof(CHAR16)) > 0);
+
+  VA_START (Marker, Format);
+  Return = UnicodeVSPrint (Buffer + Offset, (UINTN)(BufferSize - (Offset * sizeof(CHAR16))), Format, Marker);
+  VA_END (Marker);
+
+  return Return;
+}
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSymbol.c b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSymbol.c
new file mode 100644
index 000000000000..d0e2c5037067
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSymbol.c
@@ -0,0 +1,2669 @@
+/*++
+
+Copyright (c) 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.
+
+Module Name:
+
+  EdbSymbol.c
+
+Abstract:
+
+
+--*/
+
+#include "Edb.h"
+
+EFI_STATUS
+EdbLoadSymbolSingleEntry (
+  IN EFI_DEBUGGER_SYMBOL_OBJECT  *Object,
+  IN CHAR8                       *Name,
+  IN CHAR8                       *ObjName,
+  IN UINTN                       Address,
+  IN EFI_DEBUGGER_SYMBOL_TYPE    Type
+  )
+/*++
+
+Routine Description:
+
+  Load single symbol entry
+
+Arguments:
+
+  Object          - Symbol file object
+  Name            - Symbol name
+  ObjName         - Object name
+  Address         - Symbol address
+  Type            - Symbol type
+
+Returns:
+
+  EFI_SUCCESS - add single symbol entry successfully
+
+--*/
+{
+  EFI_DEBUGGER_SYMBOL_ENTRY  *Entry;
+
+  //
+  // Check Count VS MaxCount
+  //
+  if (Object->EntryCount >= Object->MaxEntryCount) {
+    //
+    // reallocate (for codebuffer too)
+    // TBD
+    //
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Entry = &Object->Entry[Object->EntryCount];
+
+  //
+  // Print Debug info
+  //
+  if (sizeof (UINTN) == sizeof(UINT64)) {
+    DEBUG ((EFI_D_ERROR, "  Symbol: %a, Address: 0x%016lx (%d)\n", Name, (UINT64)Address, (UINTN)Type));
+  } else {
+    DEBUG ((EFI_D_ERROR, "  Symbol: %a, Address: 0x%08x (%d)\n", Name, Address, (UINTN)Type));
+  }
+
+  //
+  // Fill the entry - name, RVA, type
+  //
+  AsciiStrnCpyS (Entry->Name, sizeof(Entry->Name), Name, sizeof(Entry->Name) - 1);
+  if (ObjName != NULL) {
+    AsciiStrnCpyS (Entry->ObjName, sizeof(Entry->ObjName), ObjName, sizeof(Entry->ObjName) - 1);
+  }
+  Entry->RVA = Address % EFI_DEBUGGER_DEFAULT_LINK_IMAGEBASE;
+  Entry->Type = Type;
+
+  //
+  // Increase Count
+  //
+  Object->EntryCount++;
+
+  //
+  // Done
+  //
+  return EFI_SUCCESS;
+}
+
+typedef enum {
+  EdbEbcMapParseStateUninitialized,
+  EdbEbcMapParseStateSymbolStart,
+  EdbEbcMapParseStateSeHandlerSymbol,
+  EdbEbcMapParseStateFunctionSymbol,
+  EdbEbcMapParseStateVarbssInitSymbol,
+  EdbEbcMapParseStateCrtSymbol,
+  EdbEbcMapParseStateVariableSymbol,
+  EdbEbcMapParseStateStaticFunctionSymbol,
+  EdbEbcMapParseStateMax,
+} EDB_EBC_MAP_PARSE_STATE;
+
+typedef enum {
+  EdbEbcSymbolParseStateUninitialized,
+  EdbEbcSymbolParseStateReadyForName,
+  EdbEbcSymbolParseStateReadyForRVA,
+  EdbEbcSymbolParseStateReadyForType,
+  EdbEbcSymbolParseStateReadyForObject,
+  EdbEbcSymbolParseStateMax,
+} EDB_EBC_SYMBOL_PARSE_STATE;
+
+/*++
+
+  The following code depends on the MAP file generated by IEC compiler (actually Microsoft linker).
+
+  Sample as follows: EbcTest.map
+===============================================================================
+  EbcTest
+
+ Timestamp is 45b02718 (Fri Jan 19 10:04:08 2007)
+
+ Preferred load address is 10000000
+
+ Start         Length     Name                   Class
+ 0001:00000000 00000370H .text                   CODE
+ 0002:00000000 00000030H _VARBSS_INIT            CODE
+ 0003:00000000 00000004H .CRT$TSA                DATA
+ 0003:00000004 00000004H .CRT$TSC                DATA
+ 0003:00000008 00000004H .CRT$X                  DATA
+ 0003:0000000c 00000008H .CRT$XCU                DATA
+ 0003:00000014 00000004H .CRT$Z                  DATA
+ 0003:00000020 0000001cH .rdata                  DATA
+ 0003:0000003c 00000000H .edata                  DATA
+ 0003:0000003c 00000056H .rdata$debug            DATA
+ 0004:00000000 00000070H .data                   DATA
+ 0004:00000070 00000020H .bss                    DATA
+
+  Address         Publics by Value              Rva+Base     Lib:Object
+
+ 0000:00000000       ___safe_se_handler_table   00000000     <absolute>
+ 0000:00000000       ___safe_se_handler_count   00000000     <absolute>
+ 0001:00000042       TestSubRoutine             10000442 f   EbcTest.obj
+ 0001:0000011a       EfiMain                    1000051a f   EbcTest.obj
+ 0001:00000200       TestSubRoutineSub          10000600 f   EbcTestSub.obj
+ 0001:00000220       EfiStart                   10000620 f   EbcLib:EbcLib.obj
+ 0002:00000000       varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest$c45b02717 10000800 f   EbcTest.obj
+ 0002:00000020       varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTestSub$c45af77f3 10000820 f   EbcTestSub.obj
+ 0003:00000000       CrtThunkBegin              10000a00     EbcLib:EbcLib.obj
+ 0003:00000004       CrtThunkEnd                10000a04     EbcLib:EbcLib.obj
+ 0003:00000008       CrtBegin                   10000a08     EbcLib:EbcLib.obj
+ 0003:00000014       CrtEnd                     10000a14     EbcLib:EbcLib.obj
+ 0004:00000070       TestStr                    10000c70     EbcTest.obj
+ 0004:00000078       TestVariable1              10000c78     EbcTest.obj
+ 0004:00000080       TestSubVariableSub         10000c80     EbcTestSub.obj
+
+ entry point at        0001:00000220
+
+ Static symbols
+
+ 0001:00000000       TestSubRoutine2            10000400 f   EbcTest.obj
+===============================================================================
+
+--*/
+EFI_STATUS
+EdbLoadSymbolEntryByIec (
+  IN EFI_DEBUGGER_SYMBOL_OBJECT  *Object,
+  IN UINTN                       BufferSize,
+  IN VOID                        *Buffer
+  )
+/*++
+
+Routine Description:
+
+  Load symbol entry by Iec
+
+Arguments:
+
+  DebuggerPrivate - EBC Debugger private data structure
+  Object          - Symbol file object
+  BufferSize      - Symbol file buffer size
+  Buffer          - Symbol file buffer
+
+Returns:
+
+  EFI_SUCCESS - add symbol entry successfully
+
+--*/
+{
+  CHAR8                      *LineBuffer;
+  CHAR8                      *FieldBuffer;
+  EFI_DEBUGGER_SYMBOL_ENTRY  *Entry;
+  EDB_EBC_MAP_PARSE_STATE    MapParseState;
+  EDB_EBC_SYMBOL_PARSE_STATE SymbolParseState;
+  CHAR8                      *Name;
+  CHAR8                      *ObjName;
+  UINTN                      Address;
+  EFI_DEBUGGER_SYMBOL_TYPE   Type;
+
+  Entry = Object->Entry;
+
+  //
+  // Begin to parse the Buffer
+  //
+  LineBuffer = AsciiStrGetNewTokenLine (Buffer, "\n\r");
+  MapParseState = EdbEbcMapParseStateUninitialized;
+  //
+  // Check each line
+  //
+  while (LineBuffer != NULL) {
+    FieldBuffer = AsciiStrGetNewTokenField (LineBuffer, " ");
+    SymbolParseState = EdbEbcSymbolParseStateUninitialized;
+    //
+    // Init entry value
+    //
+    Name = NULL;
+    ObjName = NULL;
+    Address = 0;
+    Type = EfiDebuggerSymbolTypeMax;
+    //
+    // Check each field
+    //
+    while (FieldBuffer != NULL) {
+      if (AsciiStrCmp (FieldBuffer, "") == 0) {
+        FieldBuffer = AsciiStrGetNextTokenField (" ");
+        continue;
+      }
+      //
+      // check "Address"
+      //
+      if (AsciiStrCmp (FieldBuffer, "Address") == 0) {
+        MapParseState = EdbEbcMapParseStateSymbolStart;
+        break;
+      }
+      //
+      // check "Static"
+      //
+      if (AsciiStrCmp (FieldBuffer, "Static") == 0) {
+        MapParseState = EdbEbcMapParseStateStaticFunctionSymbol;
+        break;
+      }
+
+      if (MapParseState == EdbEbcMapParseStateUninitialized) {
+        //
+        // Do not parse anything until get "Address" or "Static"
+        //
+        break;
+      }
+      if (AsciiStrCmp (FieldBuffer, "entry") == 0) {
+        //
+        // Skip entry point
+        //
+        break;
+      }
+
+      //
+      // Now we start to parse this line for Name, Address, and Object
+      //
+      switch (SymbolParseState) {
+      case  EdbEbcSymbolParseStateUninitialized:
+        //
+        // Get the Address
+        //
+        SymbolParseState = EdbEbcSymbolParseStateReadyForName;
+        break;
+      case  EdbEbcSymbolParseStateReadyForName:
+        //
+        // Get the Name
+        //
+        if (AsciiStrnCmp (FieldBuffer, "___safe_se_handler", AsciiStrLen ("___safe_se_handler")) == 0) {
+          //
+          // skip SeHandler
+          //
+          MapParseState = EdbEbcMapParseStateSeHandlerSymbol;
+          goto ExitFieldParse;
+        } else if (AsciiStrnCmp (FieldBuffer, "varbss_init", AsciiStrLen ("varbss_init")) == 0) {
+          //
+          // check VarbssInit
+          //
+          MapParseState = EdbEbcMapParseStateVarbssInitSymbol;
+//          goto ExitFieldParse;
+          Name = FieldBuffer;
+          SymbolParseState = EdbEbcSymbolParseStateReadyForRVA;
+        } else if (AsciiStrnCmp (FieldBuffer, "Crt", AsciiStrLen ("Crt")) == 0) {
+          //
+          // check Crt
+          //
+          MapParseState = EdbEbcMapParseStateCrtSymbol;
+//          goto ExitFieldParse;
+          Name = FieldBuffer;
+          SymbolParseState = EdbEbcSymbolParseStateReadyForRVA;
+        } else {
+          //
+          // Now, it is normal function
+          //
+          switch (MapParseState) {
+          case EdbEbcMapParseStateSeHandlerSymbol:
+            MapParseState = EdbEbcMapParseStateFunctionSymbol;
+            break;
+          case EdbEbcMapParseStateCrtSymbol:
+            MapParseState = EdbEbcMapParseStateVariableSymbol;
+            break;
+          case EdbEbcMapParseStateFunctionSymbol:
+          case EdbEbcMapParseStateVariableSymbol:
+          case EdbEbcMapParseStateStaticFunctionSymbol:
+            break;
+          default:
+            ASSERT (FALSE);
+            break;
+          }
+          Name = FieldBuffer;
+          SymbolParseState = EdbEbcSymbolParseStateReadyForRVA;
+        }
+        break;
+      case  EdbEbcSymbolParseStateReadyForRVA:
+        //
+        // Get the RVA
+        //
+        Address = AsciiXtoi (FieldBuffer);
+        SymbolParseState = EdbEbcSymbolParseStateReadyForType;
+        break;
+      case  EdbEbcSymbolParseStateReadyForType:
+        //
+        // Get the Type. This is optional, only for "f".
+        //
+        if (AsciiStrCmp (FieldBuffer, "f") == 0) {
+          SymbolParseState = EdbEbcSymbolParseStateReadyForObject;
+          switch (MapParseState) {
+          case EdbEbcMapParseStateFunctionSymbol:
+          case EdbEbcMapParseStateVarbssInitSymbol:
+            Type = EfiDebuggerSymbolFunction;
+            break;
+          case EdbEbcMapParseStateStaticFunctionSymbol:
+            Type = EfiDebuggerSymbolStaticFunction;
+            break;
+          default:
+            ASSERT (FALSE);
+            break;
+          }
+          break;
+        }
+        //
+        // Else it should be Object.
+        // let it bypass here
+        //
+      case  EdbEbcSymbolParseStateReadyForObject:
+        switch (Type) {
+        case EfiDebuggerSymbolTypeMax:
+          switch (MapParseState) {
+          case EdbEbcMapParseStateVariableSymbol:
+          case EdbEbcMapParseStateCrtSymbol:
+            Type = EfiDebuggerSymbolGlobalVariable;
+            break;
+          case EdbEbcMapParseStateSeHandlerSymbol:
+            //
+            // do nothing here
+            //
+            break;
+          default:
+            ASSERT (FALSE);
+            break;
+          }
+          break;
+        case EfiDebuggerSymbolFunction:
+        case EfiDebuggerSymbolStaticFunction:
+          break;
+        default:
+          ASSERT (FALSE);
+          break;
+        }
+        //
+        // Get the Object
+        //
+        ObjName = FieldBuffer;
+        SymbolParseState = EdbEbcSymbolParseStateUninitialized;
+        break;
+      default:
+        ASSERT (FALSE);
+        break;
+      }
+
+      //
+      // Get the next field
+      //
+      FieldBuffer = AsciiStrGetNextTokenField (" ");
+    }
+
+    //
+    // Add the entry if we get everything.
+    //
+    if ((Name != NULL) && (Type != EfiDebuggerSymbolTypeMax)) {
+      EdbLoadSymbolSingleEntry (Object, Name, ObjName, Address, Type);
+    }
+
+ExitFieldParse:
+    //
+    // Get the next line
+    //
+    LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
+  }
+
+  //
+  // Done
+  //
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EdbLoadSymbolEntry (
+  IN EFI_DEBUGGER_SYMBOL_OBJECT  *Object,
+  IN UINTN                       BufferSize,
+  IN VOID                        *Buffer
+  )
+/*++
+
+Routine Description:
+
+  Load symbol entry
+
+Arguments:
+
+  Object          - Symbol file object
+  BufferSize      - Symbol file buffer size
+  Buffer          - Symbol file buffer
+
+Returns:
+
+  EFI_SUCCESS - add symbol entry successfully
+
+--*/
+{
+  //
+  // MAP file format depends on the compiler (actually linker).
+  //
+  // It is possible to check the different MAP file format in this routine.
+  // Now only IEC is supported.
+  //
+  return EdbLoadSymbolEntryByIec (Object, BufferSize, Buffer);
+}
+
+EFI_DEBUGGER_SYMBOL_OBJECT *
+EdbFindSymbolFile (
+  IN EFI_DEBUGGER_PRIVATE_DATA   *DebuggerPrivate,
+  IN CHAR16                      *FileName,
+  IN OUT UINTN                   *Index OPTIONAL
+  )
+/*++
+
+Routine Description:
+
+  Find symbol file by name
+
+Arguments:
+
+  DebuggerPrivate - EBC Debugger private data structure
+  FileName        - Symbol file name
+  Index           - Symbol file index
+
+Returns:
+
+  Object
+
+--*/
+{
+  UINTN ObjectIndex;
+
+  //
+  // Check each Object
+  //
+  for (ObjectIndex = 0; ObjectIndex < DebuggerPrivate->DebuggerSymbolContext.ObjectCount; ObjectIndex++) {
+    if (StrCmp (FileName, DebuggerPrivate->DebuggerSymbolContext.Object[ObjectIndex].Name) == 0) {
+      //
+      // Name match, found it
+      //
+      if (Index != NULL) {
+        *Index = ObjectIndex;
+      }
+      return &DebuggerPrivate->DebuggerSymbolContext.Object[ObjectIndex];
+    }
+  }
+
+  //
+  // Not found
+  //
+  return NULL;
+}
+
+UINTN
+EbdFindSymbolAddress (
+  IN UINTN                       Address,
+  IN EDB_MATCH_SYMBOL_TYPE       Type,
+  OUT EFI_DEBUGGER_SYMBOL_OBJECT **RetObject,
+  OUT EFI_DEBUGGER_SYMBOL_ENTRY  **RetEntry
+  )
+/*++
+
+Routine Description:
+
+  Find symbol by address
+
+Arguments:
+
+  Address         - Symbol address
+  Type            - Search type
+  RetObject       - Symbol object
+  RetEntry        - Symbol entry
+
+Returns:
+
+  Nearest symbol address
+
+--*/
+{
+  UINTN                      Index;
+  UINTN                      SubIndex;
+  UINTN                      CandidateLowerAddress;
+  UINTN                      CandidateUpperAddress;
+  EFI_DEBUGGER_SYMBOL_OBJECT *Object;
+  EFI_DEBUGGER_SYMBOL_ENTRY  *Entry;
+  EFI_DEBUGGER_SYMBOL_ENTRY  *LowEntry;
+  EFI_DEBUGGER_SYMBOL_ENTRY  *UpperEntry;
+  EFI_DEBUGGER_SYMBOL_OBJECT *LowObject;
+  EFI_DEBUGGER_SYMBOL_OBJECT *UpperObject;
+
+  if ((Type < 0) || (Type >= EdbMatchSymbolTypeMax)) {
+    return 0;
+  }
+
+  //
+  // Init
+  //
+  CandidateLowerAddress = 0;
+  CandidateUpperAddress = (UINTN)-1;
+  LowEntry = NULL;
+  UpperEntry = NULL;
+  LowObject = NULL;
+  UpperObject = NULL;
+
+  //
+  // Go through each object
+  //
+  Object = mDebuggerPrivate.DebuggerSymbolContext.Object;
+  for (Index = 0; Index < mDebuggerPrivate.DebuggerSymbolContext.ObjectCount; Index++, Object++) {
+    if (Object->EntryCount == 0) {
+      continue;
+    }
+    //
+    // Go through each entry
+    //
+    Entry = Object->Entry;
+    for (SubIndex = 0; SubIndex < Object->EntryCount; SubIndex++, Entry++) {
+      if (Address != Entry->RVA + Object->BaseAddress) {
+        //
+        // Check for nearest address
+        //
+        if (Address > Entry->RVA + Object->BaseAddress) {
+          //
+          // Record it if Current RVA < Address
+          //
+          if (CandidateLowerAddress < Entry->RVA + Object->BaseAddress) {
+            CandidateLowerAddress = Entry->RVA + Object->BaseAddress;
+            LowEntry = Entry;
+            LowObject = Object;
+          }
+        } else {
+          //
+          // Record it if Current RVA > Address
+          //
+          if (CandidateUpperAddress > Entry->RVA + Object->BaseAddress) {
+            CandidateUpperAddress = Entry->RVA + Object->BaseAddress;
+            UpperEntry = Entry;
+            UpperObject = Object;
+          }
+        }
+        continue;
+      }
+      //
+      // address match, return directly
+      //
+      *RetEntry = Entry;
+      *RetObject = Object;
+      return Address;
+    }
+  }
+
+  //
+  // No Match, provide latest symbol
+  //
+
+  if ((Address - CandidateLowerAddress) < EFI_DEBUGGER_MAX_SYMBOL_ADDRESS_DELTA_VALUE) {
+    //
+    // Check for lower address
+    //
+    if (((Type == EdbMatchSymbolTypeNearestAddress) &&
+         ((CandidateUpperAddress - Address) > (Address - CandidateLowerAddress))) ||
+        (Type == EdbMatchSymbolTypeLowerAddress)) {
+      //
+      // return nearest lower address
+      //
+      *RetEntry = LowEntry;
+      *RetObject = LowObject;
+      return CandidateLowerAddress;
+    }
+  }
+
+  if ((CandidateUpperAddress - Address) < EFI_DEBUGGER_MAX_SYMBOL_ADDRESS_DELTA_VALUE) {
+    //
+    // Check for upper address
+    //
+    if (((Type == EdbMatchSymbolTypeNearestAddress) &&
+         ((CandidateUpperAddress - Address) < (Address - CandidateLowerAddress))) ||
+        (Type == EdbMatchSymbolTypeUpperAddress)) {
+      //
+      // return nearest upper address
+      //
+      *RetEntry = UpperEntry;
+      *RetObject = UpperObject;
+      return CandidateUpperAddress;
+    }
+  }
+
+  //
+  // No match and nearest one, return NULL
+  //
+  return 0;
+}
+
+EFI_STATUS
+EdbUnloadSymbol (
+  IN EFI_DEBUGGER_PRIVATE_DATA   *DebuggerPrivate,
+  IN CHAR16                      *FileName
+  )
+/*++
+
+Routine Description:
+
+  Unload symbol file by name
+
+Arguments:
+
+  DebuggerPrivate - EBC Debugger private data structure
+  FileName        - Symbol file name
+
+Returns:
+
+  EFI_SUCCESS - unload symbol successfully
+
+--*/
+{
+  EFI_DEBUGGER_SYMBOL_OBJECT *Object;
+  UINTN                      ObjectIndex;
+  UINTN                      Index;
+  EFI_DEBUGGER_SYMBOL_ENTRY  *OldEntry;
+  UINTN                      OldEntryCount;
+  UINTN                      MaxEntryCount;
+  VOID                       **OldSourceBuffer;
+
+  //
+  // Find Symbol
+  //
+  Object = EdbFindSymbolFile (DebuggerPrivate, FileName, &ObjectIndex);
+  if (Object == NULL) {
+    EDBPrint (L"SymbolFile is not loaded!\n");
+    return EFI_DEBUG_CONTINUE;
+  }
+
+  //
+  // Record old data
+  //
+  Object = DebuggerPrivate->DebuggerSymbolContext.Object;
+  OldEntry = Object->Entry;
+  OldSourceBuffer = Object->SourceBuffer;
+  MaxEntryCount = Object->MaxEntryCount;
+  OldEntryCount = Object->EntryCount;
+
+  //
+  // Remove the matched Object
+  //
+  for (Index = ObjectIndex; Index < DebuggerPrivate->DebuggerSymbolContext.ObjectCount - 1; Index++) {
+    CopyMem (&Object[Index], &Object[Index + 1], sizeof(EFI_DEBUGGER_SYMBOL_OBJECT));
+  }
+  ZeroMem (&Object[Index], sizeof(Object[Index]));
+
+  //
+  // Move old data to new place
+  //
+  Object[Index].Entry = OldEntry;
+  Object[Index].SourceBuffer = OldSourceBuffer;
+  Object[Index].MaxEntryCount = MaxEntryCount;
+  DebuggerPrivate->DebuggerSymbolContext.ObjectCount --;
+
+  //
+  // Clean old entry data
+  //
+  for (Index = 0; Index < OldEntryCount; Index++) {
+    ZeroMem (&OldEntry[Index], sizeof(OldEntry[Index]));
+  }
+
+  //
+  // Free OldSourceBuffer
+  //
+  for (Index = 0; OldSourceBuffer[Index] != NULL; Index++) {
+    gBS->FreePool (OldSourceBuffer[Index]);
+    OldSourceBuffer[Index] = NULL;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EdbLoadSymbol (
+  IN EFI_DEBUGGER_PRIVATE_DATA   *DebuggerPrivate,
+  IN CHAR16                      *FileName,
+  IN UINTN                       BufferSize,
+  IN VOID                        *Buffer
+  )
+/*++
+
+Routine Description:
+
+  Load symbol file by name
+
+Arguments:
+
+  DebuggerPrivate - EBC Debugger private data structure
+  FileName        - Symbol file name
+  BufferSize      - Symbol file buffer size
+  Buffer          - Symbol file buffer
+
+Returns:
+
+  EFI_SUCCESS - load symbol successfully
+
+--*/
+{
+  EFI_DEBUGGER_SYMBOL_OBJECT *Object;
+  EFI_STATUS                 Status;
+
+  //
+  // Check duplicated File
+  //
+  Object = EdbFindSymbolFile (DebuggerPrivate, FileName, NULL);
+  if (Object != NULL) {
+    Status = EdbUnloadSymbol (DebuggerPrivate, FileName);
+    if (EFI_ERROR(Status)) {
+      DEBUG ((EFI_D_ERROR, "Unload Duplicated Symbol File Error!\n"));
+      return Status;
+    }
+  }
+
+  //
+  // Check Count VS MaxCount
+  //
+  if (DebuggerPrivate->DebuggerSymbolContext.ObjectCount >= DebuggerPrivate->DebuggerSymbolContext.MaxObjectCount) {
+    //
+    // reallocate
+    // TBD
+    //
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  Object = &DebuggerPrivate->DebuggerSymbolContext.Object[DebuggerPrivate->DebuggerSymbolContext.ObjectCount];
+
+  //
+  // Init Object
+  //
+  Object->EntryCount = 0;
+  Object->MaxEntryCount = EFI_DEBUGGER_SYMBOL_ENTRY_MAX;
+
+  //
+  // Load SymbolEntry
+  //
+  DEBUG ((EFI_D_ERROR, "Symbol File: %s\n", FileName));
+  Status = EdbLoadSymbolEntry (Object, BufferSize, Buffer);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Fill Object value
+  //
+  StrnCpyS (Object->Name, sizeof(Object->Name) / sizeof(CHAR16),
+            FileName, (sizeof(Object->Name) / sizeof(CHAR16)) - 1);
+  Object->BaseAddress = 0;
+
+  //
+  // Increase the object count
+  //
+  DebuggerPrivate->DebuggerSymbolContext.ObjectCount ++;
+
+  return EFI_SUCCESS;
+}
+
+CHAR8 *
+GetPdbPath (
+  VOID *ImageBase
+  )
+/*++
+
+Routine Description:
+
+  Located PDB path name in PE image
+
+Arguments:
+
+  ImageBase - base of PE to search
+
+Returns:
+
+  Pointer into image at offset of PDB file name if PDB file name is found,
+  Otherwise a pointer to an empty string.
+
+--*/
+{
+  CHAR8                           *PdbPath;
+  UINT32                          DirCount;
+  EFI_IMAGE_DOS_HEADER            *DosHdr;
+  EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr;
+  EFI_IMAGE_OPTIONAL_HEADER32     *OptionalHdr32;
+  EFI_IMAGE_OPTIONAL_HEADER64     *OptionalHdr64;
+  EFI_IMAGE_DATA_DIRECTORY        *DirectoryEntry;
+  EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;
+  VOID                            *CodeViewEntryPointer;
+
+  //
+  // Init value
+  //
+  CodeViewEntryPointer  = NULL;
+  PdbPath               = NULL;
+  DosHdr                = ImageBase;
+
+  //
+  // Check magic
+  //
+  if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) {
+    return NULL;
+  }
+  NtHdr           = (EFI_IMAGE_OPTIONAL_HEADER_UNION *) ((UINT8 *) DosHdr + DosHdr->e_lfanew);
+  //
+  // Check Machine, filter for EBC
+  //
+  if (NtHdr->Pe32.FileHeader.Machine != EFI_IMAGE_MACHINE_EBC) {
+    //
+    // If not EBC, return NULL
+    //
+    return NULL;
+  }
+
+  //
+  // Get DirectoryEntry
+  // EBC spec says PE32+, but implementation uses PE32. So check dynamically here.
+  //
+  if (NtHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+    OptionalHdr32   = (VOID *) &NtHdr->Pe32.OptionalHeader;
+    DirectoryEntry  = (EFI_IMAGE_DATA_DIRECTORY *) &(OptionalHdr32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
+  } else if (NtHdr->Pe32Plus.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
+    OptionalHdr64   = (VOID *) &NtHdr->Pe32Plus.OptionalHeader;
+    DirectoryEntry  = (EFI_IMAGE_DATA_DIRECTORY *) &(OptionalHdr64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
+  } else {
+    return NULL;
+  }
+  if (DirectoryEntry->VirtualAddress == 0) {
+    return NULL;
+  }
+  //
+  // Go through DirectoryEntry
+  //
+  for (DirCount = 0;
+       (DirCount < DirectoryEntry->Size / sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)) && CodeViewEntryPointer == NULL;
+       DirCount++
+      ) {
+    DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (DirectoryEntry->VirtualAddress + (UINTN) ImageBase + DirCount * sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY));
+    if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
+      //
+      // Match DebugEntry, only CODEVIEW_SIGNATURE_NB10 and CODEVIEW_SIGNATURE_RSDS are supported.
+      //
+      CodeViewEntryPointer = (VOID *) ((UINTN) DebugEntry->RVA + (UINTN) ImageBase);
+      switch (*(UINT32 *) CodeViewEntryPointer) {
+      case CODEVIEW_SIGNATURE_NB10:
+        PdbPath = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);
+        break;
+      case CODEVIEW_SIGNATURE_RSDS:
+        PdbPath = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);
+        break;
+      default:
+        break;
+      }
+    }
+  }
+
+  //
+  // Done successfully
+  //
+  return PdbPath;
+}
+
+BOOLEAN
+MatchPdbAndMap (
+  IN CHAR8   *PdbFileName,
+  IN CHAR16  *MapFileName
+  )
+/*++
+
+Routine Description:
+
+  Check whether PDB file and MAP file have same name
+
+Arguments:
+
+  PdbFileName - PDB file name
+  MapFileName - MAP file name
+
+Returns:
+
+  TRUE  - PDB and MAP file name match
+  FALSE - PDB and MAP file name not match
+
+--*/
+{
+  UINTN   PdbNameSize;
+  UINTN   MapNameSize;
+  CHAR8   *PurePdbFileName;
+  UINTN   Index;
+
+  //
+  // remove dir name
+  //
+  PurePdbFileName = PdbFileName;
+  for (Index = 0; PdbFileName[Index] != 0; Index++) {
+    if (PdbFileName[Index] == '\\') {
+      PurePdbFileName = &PdbFileName[Index + 1];
+    }
+  }
+  PdbFileName = PurePdbFileName;
+
+  //
+  // get size
+  //
+  PdbNameSize = AsciiStrLen (PdbFileName);
+  MapNameSize = StrLen (MapFileName);
+
+  if (PdbNameSize != MapNameSize) {
+    return FALSE;
+  }
+
+  //
+  // check the name
+  //
+  for (Index = 0; Index < MapNameSize - 4; Index++) {
+    if ((PdbFileName[Index] | 0x20) != (MapFileName[Index] | 0x20)) {
+      return FALSE;
+    }
+  }
+
+  return TRUE;
+}
+
+//
+// BUGBUG: work-around start
+//
+typedef struct {
+  EFI_DEBUG_IMAGE_INFO  *EfiDebugImageInfoTable;
+  volatile UINT32       UpdateStatus;
+  UINT32                TableSize;
+} EFI_DEBUG_IMAGE_INFO_TABLE_HEADER_OLD;
+
+EFI_DEBUG_IMAGE_INFO_TABLE_HEADER  mDebugImageInfoTableHeader;
+
+VOID
+EdbFixDebugImageInfoTable (
+  IN OUT EFI_DEBUG_IMAGE_INFO_TABLE_HEADER **DebugImageInfoTableHeader
+  )
+/*
+For compatibility consideration, we handle 2 cases:
+
+1) IA32:
+  Old:                          New:
+  +------------------------+    +------------------------+
+  | EfiDebugImageInfoTable |    | UpdateStatus           |
+  +------------------------+    +------------------------+
+  | UpdateStatus           |    | TableSize              |
+  +------------------------+    +------------------------+
+  | TableSize              |    | EfiDebugImageInfoTable |
+  +------------------------+    +------------------------+
+
+2) X64 and IPF:
+  Old:                          New:
+  +------------------------+    +------------------------+
+  | EfiDebugImageInfoTable |    | UpdateStatus           |
+  |                        |    +------------------------+
+  |                        |    | TableSize              |
+  +------------------------+    +------------------------+
+  | UpdateStatus           |    | EfiDebugImageInfoTable |
+  +------------------------+    |                        |
+  | TableSize              |    |                        |
+  +------------------------+    +------------------------+
+
+*/
+{
+  mDebugImageInfoTableHeader.EfiDebugImageInfoTable = ((EFI_DEBUG_IMAGE_INFO_TABLE_HEADER_OLD *)(*DebugImageInfoTableHeader))->EfiDebugImageInfoTable;
+  mDebugImageInfoTableHeader.UpdateStatus           = ((EFI_DEBUG_IMAGE_INFO_TABLE_HEADER_OLD *)(*DebugImageInfoTableHeader))->UpdateStatus;
+  mDebugImageInfoTableHeader.TableSize              = ((EFI_DEBUG_IMAGE_INFO_TABLE_HEADER_OLD *)(*DebugImageInfoTableHeader))->TableSize;
+
+  if ((*DebugImageInfoTableHeader)->UpdateStatus > 3) {
+    *DebugImageInfoTableHeader = &mDebugImageInfoTableHeader;
+    return ;
+  }
+
+  if ((*DebugImageInfoTableHeader)->TableSize % (EFI_PAGE_SIZE / (sizeof (VOID *))) != 0) {
+    *DebugImageInfoTableHeader = &mDebugImageInfoTableHeader;
+    return ;
+  }
+
+  return ;
+}
+//
+// BUGBUG: work-around end
+//
+
+EFI_STATUS
+EdbPatchSymbolRVA (
+  IN EFI_DEBUGGER_PRIVATE_DATA     *DebuggerPrivate,
+  IN CHAR16                        *FileName,
+  IN EDB_EBC_IMAGE_RVA_SEARCH_TYPE SearchType
+  )
+/*++
+
+Routine Description:
+
+  Patch symbol RVA
+
+Arguments:
+
+  DebuggerPrivate - EBC Debugger private data structure
+  FileName        - Symbol file name
+  SearchType      - Search type for Object
+
+Returns:
+
+  EFI_SUCCESS   - Patch symbol RVA successfully
+  EFI_NOT_FOUND - Symbol RVA base not found
+
+--*/
+{
+  EFI_STATUS            Status;
+  UINTN                 ImageNumber;
+  EFI_DEBUG_IMAGE_INFO  *ImageTable;
+  CHAR8                 *PdbPath;
+  VOID                  *ImageBase;
+  VOID                  *CandidateImageBase;
+  EFI_DEBUGGER_SYMBOL_OBJECT *Object;
+
+  if (SearchType < 0 || SearchType >= EdbEbcImageRvaSearchTypeMax) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Get the related object
+  //
+  Object = EdbFindSymbolFile (DebuggerPrivate, FileName, NULL);
+  if (Object == NULL) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Try again to get DebugImageInfoTable
+  //
+  if (mDebuggerPrivate.DebugImageInfoTableHeader == NULL) {
+    Status = EfiGetSystemConfigurationTable (
+               &gEfiDebugImageInfoTableGuid,
+               (VOID **) &mDebuggerPrivate.DebugImageInfoTableHeader
+               );
+    if (EFI_ERROR (Status)) {
+      EDBPrint (L"DebugImageInfoTable not found!\n");
+      return Status;
+    }
+  }
+  DEBUG ((EFI_D_ERROR, "DebugImageInfoTableHeader: %x\n", mDebuggerPrivate.DebugImageInfoTableHeader));
+
+  //
+  // BUGBUG: work-around start
+  //
+  EdbFixDebugImageInfoTable (&mDebuggerPrivate.DebugImageInfoTableHeader);
+  //
+  // BUGBUG: work-around end
+  //
+
+  //
+  // Go through DebugImageInfoTable for each Image
+  //
+  CandidateImageBase = NULL;
+  ImageTable  = mDebuggerPrivate.DebugImageInfoTableHeader->EfiDebugImageInfoTable;
+  for (ImageNumber = 0; ImageNumber < mDebuggerPrivate.DebugImageInfoTableHeader->TableSize; ImageNumber++) {
+    if (ImageTable[ImageNumber].NormalImage == NULL) {
+      continue;
+    }
+    ImageBase = ImageTable[ImageNumber].NormalImage->LoadedImageProtocolInstance->ImageBase;
+    //
+    // Get PDB path
+    //
+    PdbPath   = GetPdbPath (ImageBase);
+    if (PdbPath == NULL) {
+      continue;
+    }
+    //
+    // Check PDB name
+    //
+    if (!MatchPdbAndMap (PdbPath, FileName)) {
+      continue;
+    }
+    DEBUG ((EFI_D_ERROR, "ImageBase: %x\n", ImageBase));
+
+    //
+    // Check SearchType
+    //
+    if (SearchType == EdbEbcImageRvaSearchTypeAny || SearchType == EdbEbcImageRvaSearchTypeFirst) {
+      //
+      // Assign base address and return
+      //
+      Object->BaseAddress = (UINTN)ImageBase;
+      return EFI_SUCCESS;
+    }
+
+    //
+    // Get CandidateImageBase for EdbEbcImageRvaSearchTypeLast
+    //
+    CandidateImageBase = ImageBase;
+  }
+
+  //
+  // Check EdbEbcImageRvaSearchTypeLast
+  //
+  if (SearchType == EdbEbcImageRvaSearchTypeLast) {
+    if (CandidateImageBase == NULL) {
+      return EFI_NOT_FOUND;
+    }
+    //
+    // Assign base address and return
+    //
+    Object->BaseAddress = (UINTN)CandidateImageBase;
+    return EFI_SUCCESS;
+  }
+
+  //
+  // No match
+  //
+  return EFI_NOT_FOUND;
+}
+
+BOOLEAN
+MatchObjAndCod (
+  IN CHAR8   *ObjFileName,
+  IN CHAR16  *CodFileName
+  )
+/*++
+
+Routine Description:
+
+  Check whether OBJ file and COD file have same name
+
+Arguments:
+
+  ObjFileName - OBJ file name
+  CodFileName - COD file name
+
+Returns:
+
+  TRUE  - OBJ and COD file name match
+  FALSE - OBJ and COD file name not match
+
+--*/
+{
+  UINTN   ObjNameSize;
+  UINTN   CodNameSize;
+  CHAR8   *PureObjFileName;
+  UINTN   Index;
+
+  //
+  // remove library name
+  //
+  PureObjFileName = ObjFileName;
+  for (Index = 0; ObjFileName[Index] != 0; Index++) {
+    if (ObjFileName[Index] == ':') {
+      PureObjFileName = &ObjFileName[Index + 1];
+      break;
+    }
+  }
+  ObjFileName = PureObjFileName;
+
+  //
+  // get size
+  //
+  ObjNameSize = AsciiStrLen (ObjFileName);
+  CodNameSize = StrLen (CodFileName);
+
+  if (ObjNameSize != CodNameSize) {
+    return FALSE;
+  }
+
+  //
+  // check the name
+  //
+  for (Index = 0; Index < CodNameSize - 4; Index++) {
+    if ((ObjFileName[Index] | 0x20) != (CodFileName[Index] | 0x20)) {
+      return FALSE;
+    }
+  }
+
+  return TRUE;
+}
+
+typedef enum {
+  EdbEbcCodParseStateUninitialized,
+  EdbEbcCodParseStateSymbolInitialized,
+  EdbEbcCodParseStateSymbolStart,
+  EdbEbcCodParseStateSymbolEnd,
+  EdbEbcCodParseStateMax,
+} EDB_EBC_COD_PARSE_STATE;
+
+/*++
+
+  The following code depends on the COD file generated by IEC compiler.
+
+  Sample as follows: EbcTest.cod
+===============================================================================
+; -- Machine type EFI
+; mark_description "Intel(R) C Compiler for EFI Byte Code, Version 1.2 Build 20040123";
+; mark_description "XXX";
+;ident "Intel(R) C Compiler for EFI Byte Code, Version 1.2 Build 20040123"
+;ident "XXX"
+	.686P
+ 	.387
+_TEXT	SEGMENT PARA PUBLIC USE32 'CODE'
+_TEXT	ENDS
+_DATA	SEGMENT PARA PUBLIC USE32 'DATA'
+	ALIGN 010H
+_DATA	ENDS
+_BSS	SEGMENT PARA PUBLIC USE32 'BSS'
+	ALIGN 010H
+_BSS	ENDS
+_VARBSS	SEGMENT PARA PUBLIC USE32 'BSS'
+	ALIGN 010H
+_VARBSS	ENDS
+	ASSUME	CS:FLAT,DS:FLAT,SS:FLAT
+_DATA	SEGMENT PARA PUBLIC USE32 'DATA'
+TestVariable2	DD 000000003H,000000000H	; u64
+_DATA	ENDS
+_DATA	SEGMENT PARA PUBLIC USE32 'DATA'
+_DATA	ENDS
+_TEXT	SEGMENT PARA PUBLIC USE32 'CODE'
+; -- Begin  EfiMain
+; mark_begin;
+	PUBLIC   EfiMain
+EfiMain	 PROC NEAR
+$B3$1:; 11a
+$LN45:
+
+;117 ; {
+
+  0011a 60 00 70 80         MOVqw     R0, R0(+0,-112)         ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:117
+$LN46:
+
+;118 ;   UINT16 test = 0x1234;
+
+  0011e 77 58 58 00 34
+        12                  MOVIww    @R0(+0,+88), +4660      ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:118
+$LN47:
+
+;121 ;   EFI_STATUS  Status;
+;121 ;
+;121 ;   SystemTable->ConOut->OutputString (
+
+  00124 72 87 01 12         MOVnw     R7, @R0(+1,+128)        ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:121
+  00128 72 f7 85 21         MOVnw     R7, @R7(+5,+24)         ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:121
+$LN48:
+
+;122 ;                          SystemTable->ConOut,
+
+  0012c 72 84 01 12         MOVnw     R4, @R0(+1,+128)        ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:122
+  00130 72 c8 85 21         MOVnw     @R0, @R4(+5,+24)        ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:122
+  00134 b9 34 00 00 00
+        00                  MOVreld   R4, __STRING$1          ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:122
+  0013a b2 48 01 10         MOVnw     @R0(+1,+0), R4          ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:122
+  0013e 83 2f 01 00 00
+        10                  CALLEX    @R7(+1,+0)              ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:122
+$B3$2:; 144
+$LN49:
+
+;125 ;                          L"Hello EBC Test!\n\r"
+;125 ;                          );
+;125 ;   EFI_BREAKPOINT ();
+
+  00144 00 03               BREAK     3                       ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:125
+$B3$3:; 146
+$LN50:
+
+;126 ;   TestVariable1 = 6;
+
+  00146 b9 37 00 00 00
+        00                  MOVreld   R7, TestVariable1       ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:126
+  0014c 78 0f 06 00         MOVInw    @R7, (0,6)              ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:126
+$LN51:
+
+;127 ;   TestSubRoutineSub (1, 5);
+
+  00150 78 08 01 00         MOVInw    @R0, (0,1)              ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:127
+  00154 78 48 01 10 05
+        00                  MOVInw    @R0(1,0), (0,5)         ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:127
+  0015a 83 10 00 00 00
+        00                  CALL      TestSubRoutineSub       ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:127
+$B3$4:; 160
+$LN52:
+
+;129 ;
+;129 ;   SystemTable->ConOut->OutputString (
+
+  00160 72 87 01 12         MOVnw     R7, @R0(+1,+128)        ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:129
+  00164 72 f7 85 21         MOVnw     R7, @R7(+5,+24)         ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:129
+$LN53:
+
+;130 ;                          SystemTable->ConOut,
+
+  00168 72 84 01 12         MOVnw     R4, @R0(+1,+128)        ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:130
+  0016c 72 c8 85 21         MOVnw     @R0, @R4(+5,+24)        ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:130
+$LN54:
+
+;131 ;                          TestStr
+
+  00170 b9 34 00 00 00
+        00                  MOVreld   R4, TestStr             ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:131
+  00176 b2 c8 01 10         MOVnw     @R0(+1, +0), @R4        ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:131
+  0017a 83 2f 01 00 00
+        10                  CALLEX    @R7(+1,+0)              ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:131
+$B3$5:; 180
+$LN55:
+
+;134 ;                          );
+;134 ;
+;134 ;   test = test & 0xFF;
+
+  00180 de 88 58 00 58
+        00                  MOVww     @R0(+0,+88), @R0(+0,+88) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:134
+$LN56:
+
+;139 ;   if (test != 0x34) {
+;139 ; //    EFI_BREAKPOINT ();
+;139 ;   }
+;139 ;
+;139 ;   Status = TestSubRoutine (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+
+  00186 78 08 01 00         MOVInw    @R0, (0,1)              ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
+  0018a 78 48 01 10 02
+        00                  MOVInw    @R0(1,0), (0,2)         ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
+  00190 78 48 02 10 03
+        00                  MOVInw    @R0(2,0), (0,3)         ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
+  00196 78 48 03 10 04
+        00                  MOVInw    @R0(3,0), (0,4)         ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
+  0019c 78 48 04 20 05
+        00                  MOVInw    @R0(4,0), (0,5)         ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
+  001a2 78 48 05 20 06
+        00                  MOVInw    @R0(5,0), (0,6)         ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
+  001a8 78 48 06 20 07
+        00                  MOVInw    @R0(6,0), (0,7)         ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
+  001ae 78 48 07 20 08
+        00                  MOVInw    @R0(7,0), (0,8)         ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
+  001b4 78 48 08 20 09
+        00                  MOVInw    @R0(8,0), (0,9)         ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
+  001ba 78 48 09 20 0a
+        00                  MOVInw    @R0(9,0), (0,10)        ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
+  001c0 83 10 00 00 00
+        00                  CALL      TestSubRoutine          ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
+$B3$10:; 1c6
+  001c6 b2 78 60 00         MOVnw     @R0(+0,+96), R7         ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
+$B3$6:; 1ca
+$LN57:
+  001ca f2 88 50 00 60
+        00                  MOVnw     @R0(+0,+80), @R0(+0,+96) ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:139
+$LN58:
+
+;141 ;
+;141 ;   SystemTable->ConOut->OutputString (
+
+  001d0 72 87 01 12         MOVnw     R7, @R0(+1,+128)        ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:141
+  001d4 72 f7 85 21         MOVnw     R7, @R7(+5,+24)         ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:141
+$LN59:
+
+;142 ;                          SystemTable->ConOut,
+
+  001d8 72 84 01 12         MOVnw     R4, @R0(+1,+128)        ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:142
+  001dc 72 c8 85 21         MOVnw     @R0, @R4(+5,+24)        ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:142
+  001e0 b9 34 00 00 00
+        00                  MOVreld   R4, __STRING$2          ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:142
+  001e6 b2 48 01 10         MOVnw     @R0(+1,+0), R4          ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:142
+  001ea 83 2f 01 00 00
+        10                  CALLEX    @R7(+1,+0)              ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:142
+$B3$7:; 1f0
+$LN60:
+
+;146 ;                          L"Goodbye EBC Test!\n\r"
+;146 ;                          );
+;146 ;
+;146 ;   return Status;
+
+  001f0 72 87 50 00         MOVnw     R7, @R0(+0,+80)         ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:146
+  001f4 60 00 70 00         MOVqw     R0, R0(+0,+112)         ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:146
+  001f8 04 00               RET                               ;C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest.c:146
+; mark_end;
+EfiMain ENDP
+_TEXT	ENDS
+_DATA	SEGMENT PARA PUBLIC USE32 'DATA'
+	DB 3 DUP (0)	; pad
+__STRING$2	DW 71	; u16
+	DW 111	; u16
+	DW 111	; u16
+	DW 100	; u16
+	DW 98	; u16
+	DW 121	; u16
+	DW 101	; u16
+	DW 32	; u16
+	DW 69	; u16
+	DW 66	; u16
+	DW 67	; u16
+	DW 32	; u16
+	DW 84	; u16
+	DW 101	; u16
+	DW 115	; u16
+	DW 116	; u16
+	DW 33	; u16
+	DW 10	; u16
+	DW 13	; u16
+	DW 0	; u16
+__STRING$1	DW 72	; u16
+	DW 101	; u16
+	DW 108	; u16
+	DW 108	; u16
+	DW 111	; u16
+	DW 32	; u16
+	DW 69	; u16
+	DW 66	; u16
+	DW 67	; u16
+	DW 32	; u16
+	DW 84	; u16
+	DW 101	; u16
+	DW 115	; u16
+	DW 116	; u16
+	DW 33	; u16
+	DW 10	; u16
+	DW 13	; u16
+	DW 0	; u16
+_DATA	ENDS
+_DATA	SEGMENT PARA PUBLIC USE32 'DATA'
+_DATA	ENDS
+; -- End  EfiMain
+_DATA	SEGMENT PARA PUBLIC USE32 'DATA'
+__STRING$0	DW 55	; u16
+	DW 56	; u16
+	DW 57	; u16
+	DW 52	; u16
+	DW 53	; u16
+	DW 54	; u16
+	DW 49	; u16
+	DW 50	; u16
+	DW 51	; u16
+	DW 13	; u16
+	DW 10	; u16
+	DW 0	; u16
+_DATA	ENDS
+_VARBSS	SEGMENT PARA PUBLIC USE32 'BSS'
+	PUBLIC TestStr
+TestStr	DD 2 DUP (?)	; pad
+	PUBLIC TestVariable1
+TestVariable1	DD 2 DUP (?)	; pad
+_VARBSS	ENDS
+_VARBSS_INIT	SEGMENT DWORD PUBLIC USE32 'CODE'
+; -- Begin varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest$c45b815d2
+	PUBLIC    varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest$c45b815d2
+varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest$c45b815d2	PROC NEAR
+  00000 b9 34 00 00 00
+        00                  MOVreld   R4, TestStr
+  00006 b9 35 00 00 00
+        00                  MOVreld   R5, __STRING$0
+  0000c 33 5c               MOVnd     @R4, R5
+  0000e b9 34 00 00 00
+        00                  MOVreld   R4, TestVariable1
+  00014 78 0c 04 00         MOVInw    @R4, (0,4)
+  00018 04 00               RET
+; -- End varbss_init_C:\efi_src\TIANO\Edk\Sample\Universal\Ebc\Dxe\EbcTest\EbcTest$c45b815d2
+_VARBSS_INIT	ENDS
+_DATA	SEGMENT PARA PUBLIC USE32 'DATA'
+_DATA	ENDS
+EXTRN	TestSubRoutineSub:PROC
+	END
+
+===============================================================================
+
+--*/
+CHAR8 *
+EdbLoadCodBySymbolByIec (
+  IN CHAR8                       *Name,
+  IN VOID                        *Buffer,
+  IN UINTN                       BufferSize,
+  OUT UINTN                      *CodeBufferSize,
+  OUT UINTN                      *FuncOffset
+  )
+/*++
+
+Routine Description:
+
+  Load code by symbol by Iec
+
+Arguments:
+
+  Name            - Symbol file name
+  BufferSize      - Symbol file buffer size
+  Buffer          - Symbol file buffer
+  CodeBufferSize  - Code buffer size
+  FuncOffset      - Code funcion offset
+
+Returns:
+
+  CodeBuffer
+
+--*/
+{
+  CHAR8                      *LineBuffer;
+  CHAR8                      *FieldBuffer;
+  VOID                       *BufferStart;
+  VOID                       *BufferEnd;
+  UINTN                      Offset;
+  EDB_EBC_COD_PARSE_STATE    CodParseState;
+  CHAR8                      Char[2] = {9, 0};
+
+  //
+  // Init
+  //
+  LineBuffer = AsciiStrGetNewTokenLine (Buffer, "\n\r");
+  Offset = (UINTN)-1;
+  BufferStart = NULL;
+  BufferEnd = NULL;
+  CodParseState = EdbEbcCodParseStateUninitialized;
+
+  //
+  // Check each line
+  //
+  while (LineBuffer != NULL) {
+    switch (CodParseState) {
+    case EdbEbcCodParseStateUninitialized:
+      //
+      // check mark_begin, begin to check line after this match
+      //
+      if (AsciiStrCmp (LineBuffer, "; mark_begin;") == 0) {
+        CodParseState = EdbEbcCodParseStateSymbolInitialized;
+      }
+      LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
+      PatchForAsciiStrTokenBefore (LineBuffer, '\n');
+      break;
+
+    case EdbEbcCodParseStateSymbolInitialized:
+      //
+      // check mark_end, not check line after this match
+      //
+      if (AsciiStrCmp (LineBuffer, "; mark_end;") == 0) {
+        CodParseState = EdbEbcCodParseStateUninitialized;
+        LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
+        PatchForAsciiStrTokenBefore (LineBuffer, '\n');
+        break;
+      }
+
+      //
+      // not check this line if the first char is as follows
+      //
+      if ((*LineBuffer == 0)   ||
+          (*LineBuffer == '$') ||
+          (*LineBuffer == ';') ||
+          (*LineBuffer == '_') ||
+          (*LineBuffer == ' ')) {
+        LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
+        PatchForAsciiStrTokenBefore (LineBuffer, '\n');
+        break;
+      }
+
+      //
+      // get function name, function name is followed by char 0x09.
+      //
+      FieldBuffer = AsciiStrGetNewTokenField (LineBuffer, Char);
+      if (AsciiStriCmp (FieldBuffer, Name) == 0) {
+        BufferStart = FieldBuffer;
+        CodParseState = EdbEbcCodParseStateSymbolStart;
+      }
+      PatchForAsciiStrTokenAfter (FieldBuffer, 0x9);
+
+      //
+      // Get next line
+      //
+      LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
+      PatchForAsciiStrTokenBefore (LineBuffer, '\n');
+      break;
+
+    case EdbEbcCodParseStateSymbolStart:
+      //
+      // check mark_end, if this match, means the function is found successfully.
+      //
+      if (AsciiStrCmp (LineBuffer, "; mark_end;") == 0) {
+        CodParseState = EdbEbcCodParseStateSymbolEnd;
+        //
+        // prepare CodeBufferSize, FuncOffset, and FuncStart to return
+        //
+        BufferEnd = LineBuffer + sizeof("; mark_end;") - 1;
+        *CodeBufferSize = (UINTN)BufferEnd - (UINTN)BufferStart;
+        *FuncOffset = Offset;
+        PatchForAsciiStrTokenAfter (LineBuffer, '\n');
+        return BufferStart;
+      }
+
+      //
+      // Get function offset
+      //
+      if ((Offset == (UINTN)-1) &&
+          (*LineBuffer == ' ')) {
+        FieldBuffer = AsciiStrGetNewTokenField (LineBuffer + 2, " ");
+        Offset = AsciiXtoi (FieldBuffer);
+        PatchForAsciiStrTokenAfter (FieldBuffer, ' ');
+      }
+
+      //
+      // Get next line
+      //
+      LineBuffer = AsciiStrGetNextTokenLine ("\n\r");
+      PatchForAsciiStrTokenBefore (LineBuffer, '\n');
+      break;
+
+    case EdbEbcCodParseStateSymbolEnd:
+      break;
+
+    default:
+      break;
+    }
+  }
+
+  //
+  // no function found
+  //
+  return NULL;
+}
+
+CHAR8 *
+EdbLoadCodBySymbol (
+  IN CHAR8                       *Name,
+  IN VOID                        *Buffer,
+  IN UINTN                       BufferSize,
+  OUT UINTN                      *CodeBufferSize,
+  OUT UINTN                      *FuncOffset
+  )
+/*++
+
+Routine Description:
+
+  Load code by symbol
+
+Arguments:
+
+  Name            - Symbol file name
+  BufferSize      - Symbol file buffer size
+  Buffer          - Symbol file buffer
+  CodeBufferSize  - Code buffer size
+  FuncOffset      - Code funcion offset
+
+Returns:
+
+  CodeBuffer
+
+--*/
+{
+  //
+  // COD file format depends on the compiler.
+  //
+  // It is possible to check the different COD file format in this routine.
+  // Now only IEC is supported.
+  //
+  return EdbLoadCodBySymbolByIec (Name, Buffer, BufferSize, CodeBufferSize, FuncOffset);
+}
+
+VOID *
+EdbFindCodeFromObject (
+  IN EFI_DEBUGGER_PRIVATE_DATA   *DebuggerPrivate,
+  IN EFI_DEBUGGER_SYMBOL_OBJECT  *Object,
+  IN CHAR16                      *FileName
+  )
+/*++
+
+Routine Description:
+
+  Find code from object
+
+Arguments:
+
+  Object          - Symbol object
+  FileName        - File name
+
+Returns:
+
+  CodeBuffer
+
+--*/
+{
+  UINTN                      EntryIndex;
+
+  //
+  // Go througn each Entry in this Object
+  //
+  for (EntryIndex = 0; EntryIndex < Object->EntryCount; EntryIndex++) {
+    //
+    // This check is for Function only
+    //
+    if ((Object->Entry[EntryIndex].Type != EfiDebuggerSymbolFunction) &&
+        (Object->Entry[EntryIndex].Type != EfiDebuggerSymbolStaticFunction)) {
+      continue;
+    }
+    //
+    // Skip match varbss_init function, because they has no source code
+    //
+    if (AsciiStrnCmp (Object->Entry[EntryIndex].Name, "varbss_init", sizeof("varbss_init") - 1) == 0) {
+      continue;
+    }
+    //
+    // check the name
+    //
+    if (!MatchObjAndCod (Object->Entry[EntryIndex].ObjName, FileName)) {
+      continue;
+    }
+    //
+    // found it, return source buffer
+    //
+    if (Object->Entry[EntryIndex].CodBuffer != NULL) {
+      return Object->Entry[EntryIndex].SourceBuffer;
+    }
+  }
+
+  //
+  // not found
+  //
+  return NULL;
+}
+
+EFI_STATUS
+EdbLoadCode (
+  IN EFI_DEBUGGER_PRIVATE_DATA   *DebuggerPrivate,
+  IN CHAR16                      *MapFileName,
+  IN CHAR16                      *FileName,
+  IN UINTN                       BufferSize,
+  IN VOID                        *Buffer
+  )
+/*++
+
+Routine Description:
+
+  Load code
+
+Arguments:
+
+  DebuggerPrivate - EBC Debugger private data structure
+  MapFileName     - Symbol file name
+  FileName        - Code file name
+  BufferSize      - Code file buffer size
+  Buffer          - Code file buffer
+
+Returns:
+
+  EFI_SUCCESS - Code loaded successfully
+
+--*/
+{
+  EFI_DEBUGGER_SYMBOL_OBJECT *Object;
+  UINTN                      ObjectIndex;
+  UINTN                      EntryIndex;
+  VOID                       *SourceBuffer;
+  EFI_STATUS                 Status;
+
+  //
+  // Find Symbol
+  //
+  Object = EdbFindSymbolFile (DebuggerPrivate, MapFileName, &ObjectIndex);
+  if (Object == NULL) {
+    EDBPrint (L"SymbolFile is not loaded!\n");
+    return EFI_NOT_FOUND;
+  } else {
+    //
+    // Check duplicated File
+    //
+    SourceBuffer = EdbFindCodeFromObject (DebuggerPrivate, Object, FileName);
+    if (SourceBuffer != NULL) {
+      //
+      // unnload duplicated code
+      //
+      Status = EdbUnloadCode (DebuggerPrivate, MapFileName, FileName, &SourceBuffer);
+      if (EFI_ERROR(Status)) {
+        DEBUG ((EFI_D_ERROR, "Unload Duplicated Code File Error!\n"));
+        return Status;
+      }
+      Status = EdbDeleteCodeBuffer (DebuggerPrivate, MapFileName, FileName, SourceBuffer);
+      if (EFI_ERROR(Status)) {
+        DEBUG ((EFI_D_ERROR, "Delete Duplicated Code File Error!\n"));
+        return Status;
+      }
+    }
+  }
+
+  //
+  // Go through each SymbolEntry
+  //
+  for (EntryIndex = 0; EntryIndex < Object->EntryCount; EntryIndex++) {
+    //
+    // load symbol for function only
+    //
+    if ((Object->Entry[EntryIndex].Type != EfiDebuggerSymbolFunction) &&
+        (Object->Entry[EntryIndex].Type != EfiDebuggerSymbolStaticFunction)) {
+      continue;
+    }
+    //
+    // skip varbss_init
+    //
+    if (AsciiStrnCmp (Object->Entry[EntryIndex].Name, "varbss_init", sizeof("varbss_init") - 1) == 0) {
+      continue;
+    }
+    //
+    // Check the name
+    //
+    if (!MatchObjAndCod (Object->Entry[EntryIndex].ObjName, FileName)) {
+      continue;
+    }
+    //
+    // load code for this symbol
+    //
+    Object->Entry[EntryIndex].CodBuffer = EdbLoadCodBySymbol (
+                                            Object->Entry[EntryIndex].Name,
+                                            Buffer,
+                                            BufferSize,
+                                            &Object->Entry[EntryIndex].CodBufferSize,
+                                            &Object->Entry[EntryIndex].FuncOffsetBase
+                                            );
+    if (Object->Entry[EntryIndex].CodBuffer != NULL) {
+      Object->Entry[EntryIndex].SourceBuffer = Buffer;
+    }
+  }
+
+  //
+  // patch end '\0' for each code buffer
+  //
+  for (EntryIndex = 0; EntryIndex < Object->EntryCount; EntryIndex++) {
+    if (Object->Entry[EntryIndex].CodBuffer != NULL) {
+      *((UINT8 *)Object->Entry[EntryIndex].CodBuffer + Object->Entry[EntryIndex].CodBufferSize) = 0;
+      DEBUG ((EFI_D_ERROR, "  CodeSymbol: %a, FuncOffset: 0x05%x\n", Object->Entry[EntryIndex].Name, Object->Entry[EntryIndex].FuncOffsetBase));
+//      DEBUG ((EFI_D_ERROR, "  [CODE]:\n%a\n", Object->Entry[EntryIndex].CodBuffer));
+    }
+  }
+
+  //
+  // Done
+  //
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EdbUnloadCode (
+  IN EFI_DEBUGGER_PRIVATE_DATA   *DebuggerPrivate,
+  IN CHAR16                      *MapFileName,
+  IN CHAR16                      *FileName,
+  OUT VOID                       **Buffer
+  )
+/*++
+
+Routine Description:
+
+  Unload code
+
+Arguments:
+
+  DebuggerPrivate - EBC Debugger private data structure
+  MapFileName     - Symbol file name
+  FileName        - Code file name
+  Buffer          - Code file buffer
+
+Returns:
+
+  EFI_SUCCESS - Code unloaded successfully
+
+--*/
+{
+  EFI_DEBUGGER_SYMBOL_OBJECT *Object;
+  UINTN                      ObjectIndex;
+  UINTN                      EntryIndex;
+
+  //
+  // Find Symbol
+  //
+  Object = EdbFindSymbolFile (DebuggerPrivate, MapFileName, &ObjectIndex);
+  if (Object == NULL) {
+    EDBPrint (L"SymbolFile is not loaded!\n");
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Find code
+  //
+  *Buffer = EdbFindCodeFromObject (DebuggerPrivate, Object, FileName);
+  if (*Buffer == NULL) {
+    EDBPrint (L"CodeFile is not loaded!\n");
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // go through each entry
+  //
+  for (EntryIndex = 0; EntryIndex < Object->EntryCount; EntryIndex++) {
+    if ((Object->Entry[EntryIndex].Type != EfiDebuggerSymbolFunction) &&
+        (Object->Entry[EntryIndex].Type != EfiDebuggerSymbolStaticFunction)) {
+      continue;
+    }
+    if (AsciiStrnCmp (Object->Entry[EntryIndex].Name, "varbss_init", sizeof("varbss_init") - 1) == 0) {
+      continue;
+    }
+    if (!MatchObjAndCod (Object->Entry[EntryIndex].ObjName, FileName)) {
+      continue;
+    }
+    //
+    // clean up the buffer
+    //
+    Object->Entry[EntryIndex].CodBuffer = NULL;
+    Object->Entry[EntryIndex].CodBufferSize = 0;
+    Object->Entry[EntryIndex].FuncOffsetBase = 0;
+    Object->Entry[EntryIndex].SourceBuffer = NULL;
+  }
+
+  //
+  // Done
+  //
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EdbAddCodeBuffer (
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     CHAR16                    *MapFileName,
+  IN     CHAR16                    *CodeFileName,
+  IN     UINTN                     SourceBufferSize,
+  IN     VOID                      *SourceBuffer
+  )
+/*++
+
+Routine Description:
+
+  Add code buffer
+
+Arguments:
+
+  DebuggerPrivate - EBC Debugger private data structure
+  MapFileName     - Symbol file name
+  CodeFileName    - Code file name
+  SourceBufferSize- Code buffer size
+  SourceBuffer    - Code buffer
+
+Returns:
+
+  EFI_SUCCESS - CodeBuffer added successfully
+
+--*/
+{
+  UINTN                      Index;
+  EFI_DEBUGGER_SYMBOL_OBJECT *Object;
+
+  //
+  // Find Symbol
+  //
+  Object = EdbFindSymbolFile (DebuggerPrivate, MapFileName, NULL);
+  if (Object == NULL) {
+    EDBPrint (L"SymbolFile is not loaded!\n");
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Add it to last entry
+  //
+  for (Index = 0; Object->SourceBuffer[Index] != NULL; Index++) {
+    ;
+  }
+  Object->SourceBuffer[Index] = SourceBuffer;
+
+  return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EdbDeleteCodeBuffer (
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     CHAR16                    *MapFileName,
+  IN     CHAR16                    *CodeFileName,
+  IN     VOID                      *SourceBuffer
+  )
+/*++
+
+Routine Description:
+
+  Delete code buffer
+
+Arguments:
+
+  DebuggerPrivate - EBC Debugger private data structure
+  MapFileName     - Symbol file name
+  CodeFileName    - Code file name
+  SourceBuffer    - Code buffer
+
+Returns:
+
+  EFI_SUCCESS - CodeBuffer deleted successfully
+
+--*/
+{
+  UINTN                      Index;
+  EFI_DEBUGGER_SYMBOL_OBJECT *Object;
+
+  //
+  // Find Symbol
+  //
+  Object = EdbFindSymbolFile (DebuggerPrivate, MapFileName, NULL);
+  if (Object == NULL) {
+    EDBPrint (L"SymbolFile is not loaded!\n");
+    return EFI_NOT_FOUND;
+  }
+
+  for (Index = 0; Object->SourceBuffer[Index] != NULL; Index++) {
+    //
+    // free the buffer if match
+    //
+    if (Object->SourceBuffer[Index] == SourceBuffer) {
+      gBS->FreePool (SourceBuffer);
+      break;
+    }
+  }
+
+  if (Object->SourceBuffer[Index] == NULL) {
+    //
+    // not return NOT_FOUND
+    //
+    return EFI_SUCCESS;
+  }
+
+  //
+  // remove the entry
+  //
+  Object->SourceBuffer[Index] = NULL;
+  for (Index = Index + 1; Object->SourceBuffer[Index] != NULL; Index++) {
+    Object->SourceBuffer[Index - 1] = Object->SourceBuffer[Index];
+  }
+  Object->SourceBuffer[Index - 1] = NULL;
+
+  return EFI_SUCCESS;
+}
+
+CHAR8 *
+FindSymbolStr (
+  IN UINTN Address
+  )
+/*++
+
+Routine Description:
+
+  Find the symbol string according to address
+
+Arguments:
+
+  Address         - Symbol address
+
+Returns:
+
+  Symbol string
+
+--*/
+{
+  UINTN                       ObjectIndex;
+  EFI_DEBUGGER_SYMBOL_OBJECT  *Object;
+  UINTN                       EntryIndex;
+  EFI_DEBUGGER_SYMBOL_ENTRY   *Entry;
+
+  //
+  // need we display symbol
+  //
+  if (!mDebuggerPrivate.DebuggerSymbolContext.DisplaySymbol) {
+    return NULL;
+  }
+
+  //
+  // Go through each object and entry
+  //
+  Object = mDebuggerPrivate.DebuggerSymbolContext.Object;
+  for (ObjectIndex = 0; ObjectIndex < mDebuggerPrivate.DebuggerSymbolContext.ObjectCount; ObjectIndex++) {
+    Entry = Object[ObjectIndex].Entry;
+    for (EntryIndex = 0; EntryIndex < Object[ObjectIndex].EntryCount; EntryIndex++) {
+      //
+      // if Address match, return Name
+      //
+      if (Address == (Entry[EntryIndex].RVA + Object[ObjectIndex].BaseAddress)) {
+        return Entry[EntryIndex].Name;
+      }
+    }
+  }
+
+  //
+  // not found
+  //
+  return NULL;
+}
+
+UINTN
+EdbGetLineNumberAndOffsetFromThisLine (
+  IN VOID     *Line,
+  OUT UINTN   *Offset
+  )
+/*++
+
+Routine Description:
+
+  Get line number and offset from this line in code file
+
+Arguments:
+
+  Line            - Line buffer in code file
+  Offset          - Offset to functin entry
+
+Returns:
+
+  Line number
+
+--*/
+{
+  UINTN  LineNumber;
+  CHAR8  *LineBuffer;
+  CHAR8  *FieldBuffer;
+
+  LineNumber = (UINTN)-1;
+  LineBuffer = Line;
+  *Offset = (UINTN)-1;
+
+  while (LineBuffer != NULL) {
+    //
+    // Check candidate
+    //
+    if (*LineBuffer != ' ') {
+      return (UINTN)-1;
+    }
+
+    //
+    // Get Offset
+    //
+    if (*(LineBuffer + 2) != ' ') {
+      if (*Offset == (UINTN)-1) {
+        FieldBuffer = AsciiStrGetNewTokenField (LineBuffer + 2, " ");
+        *Offset = AsciiXtoi (FieldBuffer);
+        PatchForAsciiStrTokenAfter (FieldBuffer, ' ');
+      }
+    }
+
+    //
+    // 1. assembly instruction
+    //
+    FieldBuffer = AsciiStrGetNewTokenField (LineBuffer, ":");
+    //
+    // 2. file path
+    //
+    FieldBuffer = AsciiStrGetNextTokenField (":");
+    PatchForAsciiStrTokenBefore (FieldBuffer, ':');
+    if (FieldBuffer == NULL) {
+      //
+      // candidate found
+      //
+      LineNumber = 0;
+      LineBuffer = AsciiStrGetNextTokenLine ("\n");
+      PatchForAsciiStrTokenBefore (LineBuffer, '\n');
+      continue;
+    }
+    //
+    // 3. line number
+    //
+    FieldBuffer = AsciiStrGetNextTokenField (":");
+    PatchForAsciiStrTokenBefore (FieldBuffer, ':');
+    if (FieldBuffer == NULL) {
+      //
+      // impossible, TBD?
+      //
+      LineBuffer = AsciiStrGetNextTokenLine ("\n");
+      PatchForAsciiStrTokenBefore (LineBuffer, '\n');
+      continue;
+    }
+
+    LineNumber = AsciiAtoi (FieldBuffer);
+    //
+    // Not patch after
+    //
+
+    return LineNumber;
+  }
+
+  return (UINTN)-1;
+}
+
+typedef enum {
+  EdbEbcLineSearchTypeAny,
+  EdbEbcLineSearchTypeFirst,
+  EdbEbcLineSearchTypeLast,
+  EdbEbcLineSearchTypeMax,
+} EDB_EBC_LINE_SEARCH_TYPE;
+
+UINTN
+EdbGetLineNumberFromCode (
+  IN EFI_DEBUGGER_SYMBOL_ENTRY  *Entry,
+  IN UINTN                      FuncOffset,
+  IN EDB_EBC_LINE_SEARCH_TYPE   SearchType
+  )
+/*++
+
+Routine Description:
+
+  Get line number from this code file
+
+Arguments:
+
+  Entry           - Symbol entry
+  FuncOffset      - Offset to functin entry
+  SearchType      - Search type for the code
+
+Returns:
+
+  Line number
+
+--*/
+{
+  CHAR8  *LineBuffer;
+  UINTN  LineNumber;
+  UINTN  Offset;
+  UINTN  CandidateLineNumber;
+  UINTN  CandidateOffset;
+
+  if (SearchType < 0 || SearchType >= EdbEbcLineSearchTypeMax) {
+    return (UINTN)-1;
+  }
+
+  LineNumber = (UINTN)-1;
+  CandidateLineNumber = (UINTN)-1;
+  CandidateOffset = (UINTN)-1;
+  LineBuffer = AsciiStrGetNewTokenLine (Entry->CodBuffer, "\n");
+  while (LineBuffer != NULL) {
+    if (*LineBuffer != ' ') {
+      LineBuffer = AsciiStrGetNextTokenLine ("\n");
+      PatchForAsciiStrTokenBefore (LineBuffer, '\n');
+      continue;
+    }
+
+    //
+    // Get Info
+    //
+    LineNumber = EdbGetLineNumberAndOffsetFromThisLine (LineBuffer, &Offset);
+
+    //
+    // Check offset
+    //
+    if (Offset != FuncOffset) {
+      //
+      // Check last offset match
+      //
+      if (CandidateOffset == FuncOffset) {
+        if (SearchType == EdbEbcLineSearchTypeLast) {
+          PatchForAsciiStrTokenAfter (LineBuffer, '\n');
+          if (CandidateLineNumber != LineNumber) {
+            return CandidateLineNumber;
+          } else {
+            return (UINTN)-1;
+          }
+        } else {
+          //
+          // impossible, TBD?
+          //
+        }
+      }
+
+      LineBuffer = AsciiStrGetNextTokenLine ("\n");
+      PatchForAsciiStrTokenBefore (LineBuffer, '\n');
+      CandidateLineNumber = LineNumber;
+      continue;
+    }
+
+    //
+    // Offset match, more check
+    //
+    if (SearchType == EdbEbcLineSearchTypeAny) {
+      PatchForAsciiStrTokenAfter (LineBuffer, '\n');
+      return LineNumber;
+    }
+
+    if (SearchType == EdbEbcLineSearchTypeFirst) {
+      //
+      // Check last line
+      //
+      PatchForAsciiStrTokenAfter (LineBuffer, '\n');
+      if (CandidateLineNumber != LineNumber) {
+        return LineNumber;
+      } else {
+        return (UINTN)-1;
+      }
+    }
+
+    CandidateLineNumber = LineNumber;
+    CandidateOffset = Offset;
+
+    LineBuffer = AsciiStrGetNextTokenLine ("\n");
+    PatchForAsciiStrTokenBefore (LineBuffer, '\n');
+  }
+
+  //
+  // Check last offset match
+  //
+  if (CandidateOffset == FuncOffset) {
+    if (SearchType == EdbEbcLineSearchTypeLast) {
+      return CandidateLineNumber;
+    }
+  }
+
+  return (UINTN)-1;
+}
+
+VOID *
+EdbGetSourceStrFromCodeByLine (
+  IN EFI_DEBUGGER_SYMBOL_ENTRY  *Entry,
+  IN UINTN                      LineNumber,
+  IN VOID                       **FuncEnd
+  )
+/*++
+
+Routine Description:
+
+  Get the source string from this code file by line
+
+Arguments:
+
+  Entry           - Symbol entry
+  LineNumber      - line number
+  FuncEnd         - Function end
+
+Returns:
+
+  Funtion start
+
+--*/
+{
+  CHAR8  *LineBuffer;
+  CHAR8  *FieldBuffer;
+  VOID   *FuncStart;
+  UINTN  Number;
+
+  FuncStart = NULL;
+  LineBuffer = AsciiStrGetNewTokenLine (Entry->CodBuffer, "\n");
+  while (LineBuffer != NULL) {
+    if (*LineBuffer != ';') {
+      if (FuncStart != NULL) {
+        //
+        // Over
+        //
+        *FuncEnd = LineBuffer - 1;
+        PatchForAsciiStrTokenAfter (LineBuffer, '\n');
+        return FuncStart;
+      }
+      LineBuffer = AsciiStrGetNextTokenLine ("\n");
+      PatchForAsciiStrTokenBefore (LineBuffer, '\n');
+      continue;
+    }
+
+    //
+    // Check LineNumber
+    //
+    FieldBuffer = AsciiStrGetNewTokenField (LineBuffer + 1, " ");
+    Number = AsciiAtoi (FieldBuffer);
+    PatchForAsciiStrTokenAfter (FieldBuffer, ' ');
+    if (Number != LineNumber) {
+      LineBuffer = AsciiStrGetNextTokenLine ("\n");
+      PatchForAsciiStrTokenBefore (LineBuffer, '\n');
+      continue;
+    }
+
+    //
+    // Line match, get line number
+    //
+    if (FuncStart == NULL) {
+      FuncStart = LineBuffer;
+    }
+
+    LineBuffer = AsciiStrGetNextTokenLine ("\n");
+    PatchForAsciiStrTokenBefore (LineBuffer, '\n');
+  }
+
+  return NULL;
+}
+
+VOID *
+EdbGetSourceStrFromCode (
+  IN EFI_DEBUGGER_SYMBOL_ENTRY  *Entry,
+  IN UINTN                      FuncOffset,
+  IN VOID                       **FuncEnd
+  )
+/*++
+
+Routine Description:
+
+  Get source string from this code file
+
+Arguments:
+
+  Entry           - Symbol entry
+  FuncOffset      - Offset to functin entry
+  FuncEnd         - Function end
+
+Returns:
+
+  Funtion start
+
+--*/
+{
+  UINTN  LineNumber;
+
+  //
+  // Only search the last line, then display
+  //
+  LineNumber = EdbGetLineNumberFromCode (Entry, FuncOffset, EdbEbcLineSearchTypeLast);
+  if (LineNumber == (UINTN)-1) {
+    return NULL;
+  }
+
+  return EdbGetSourceStrFromCodeByLine (Entry, LineNumber, FuncEnd);
+}
+
+UINTN
+EdbPrintSource (
+  IN UINTN     Address,
+  IN BOOLEAN   IsPrint
+  )
+/*++
+
+Routine Description:
+
+  Print source
+
+Arguments:
+
+  Address         - Instruction address
+  IsPrint         - Whether need to print
+
+Returns:
+
+  1 - find the source
+  0 - not find the source
+
+--*/
+{
+  UINTN                      SymbolAddress;
+  EFI_DEBUGGER_SYMBOL_OBJECT *RetObject;
+  EFI_DEBUGGER_SYMBOL_ENTRY  *RetEntry;
+  UINTN                      FuncOffset;
+  UINT8                      *FuncStart;
+  UINT8                      *FuncEnd;
+  UINT8                      *FuncIndex;
+  CHAR8                      Buffer[EFI_DEBUG_MAX_PRINT_BUFFER];
+  UINTN                      BufferSize;
+
+  //
+  // need we display symbol
+  //
+  if (!mDebuggerPrivate.DebuggerSymbolContext.DisplaySymbol) {
+    return 0 ;
+  }
+
+  //
+  // find the symbol address
+  //
+  SymbolAddress = EbdFindSymbolAddress (
+                    Address,
+                    EdbMatchSymbolTypeLowerAddress,
+                    &RetObject,
+                    &RetEntry
+                    );
+  if (SymbolAddress == 0) {
+    return 0 ;
+  }
+
+  FuncOffset = Address - SymbolAddress + RetEntry->FuncOffsetBase;
+
+  //
+  // Get Func String
+  //
+  FuncStart = EdbGetSourceStrFromCode (RetEntry, FuncOffset, (VOID**) &FuncEnd);
+  if (FuncStart == NULL) {
+    return 0 ;
+  }
+
+  //
+  // check whether need to real print
+  //
+  if (!IsPrint) {
+    return 1;
+  }
+
+  *(UINT8 *)FuncEnd = 0;
+
+  //
+  // seperate buffer by \n, so that \r can be added.
+  //
+  FuncIndex = FuncStart;
+  while (*FuncIndex != 0) {
+    if (*FuncIndex == '\n') {
+      if ((FuncIndex - FuncStart) < (EFI_DEBUG_MAX_PRINT_BUFFER - 3)) {
+        BufferSize = FuncIndex - FuncStart;
+      } else {
+        BufferSize = EFI_DEBUG_MAX_PRINT_BUFFER - 3;
+      }
+      if (BufferSize != 0) {
+        CopyMem (Buffer, FuncStart, BufferSize);
+      }
+      Buffer[BufferSize] = 0;
+      EDBPrint (L"%a\n", Buffer);
+      FuncStart = FuncIndex + 1;
+      FuncIndex = FuncStart;
+    } else {
+      FuncIndex ++;
+    }
+  }
+
+  //
+  // Patch the end
+  //
+  *(UINT8 *)FuncEnd = '\n';
+
+  return 1 ;
+}
+
+VOID
+GetMapfileAndSymbol (
+  IN CHAR16   *Symbol,
+  OUT CHAR16  **MapfileName,
+  OUT CHAR16  **SymbolName
+  )
+/*++
+
+Routine Description:
+
+  Get Mapfile and SymbolName from one symbol format: [MapFileName:]SymbolName
+
+Arguments:
+
+  Symbol          - whole Symbol name
+  MapfileName     - the mapfile name in the symbol
+  SymbolName      - the symbol name in the symbol
+
+Returns:
+
+  None
+
+--*/
+{
+  CHAR16  *Ch;
+
+  *MapfileName = NULL;
+  *SymbolName = Symbol;
+
+  for (Ch = Symbol; *Ch != 0; Ch++) {
+    //
+    // Find split char
+    //
+    if (*Ch == L':') {
+      *MapfileName = Symbol;
+      *Ch = 0;
+      *SymbolName = Ch + 1;
+      break;
+    }
+  }
+
+  return ;
+}
+
+EFI_STATUS
+Symboltoi (
+  IN CHAR16   *Symbol,
+  OUT UINTN   *Address
+  )
+/*++
+
+Routine Description:
+
+  Convert a symbol to an address
+
+Arguments:
+
+  Symbol          - Symbol name
+  Address         - Symbol address
+
+Returns:
+
+  EFI_SUCCESS    - symbol found and address returned.
+  EFI_NOT_FOUND  - symbol not found
+  EFI_NO_MAPPING - duplicated symbol not found
+
+--*/
+{
+  UINTN                       ObjectIndex;
+  EFI_DEBUGGER_SYMBOL_OBJECT  *Object;
+  UINTN                       EntryIndex;
+  EFI_DEBUGGER_SYMBOL_ENTRY   *Entry;
+  CHAR16                      *SymbolName;
+  CHAR16                      *MapfileName;
+
+  //
+  // Split one symbol to mapfile name and symbol name
+  //
+  GetMapfileAndSymbol (Symbol, &MapfileName, &SymbolName);
+
+  *Address = 0;
+  //
+  // Go through each object
+  //
+  Object = mDebuggerPrivate.DebuggerSymbolContext.Object;
+  for (ObjectIndex = 0; ObjectIndex < mDebuggerPrivate.DebuggerSymbolContext.ObjectCount; ObjectIndex++) {
+    //
+    // Check MapfileName
+    //
+    if ((MapfileName != NULL) && (StriCmp (Object[ObjectIndex].Name, MapfileName) != 0)) {
+      continue;
+    }
+    //
+    // Go through each entry
+    //
+    Entry = Object[ObjectIndex].Entry;
+    for (EntryIndex = 0; EntryIndex < Object[ObjectIndex].EntryCount; EntryIndex++) {
+      //
+      // Check SymbolName (case sensitive)
+      //
+      if (StrCmpUnicodeAndAscii (SymbolName, Entry[EntryIndex].Name) == 0) {
+        if ((*Address != 0) && (MapfileName == NULL)) {
+          //
+          // Find the duplicated symbol
+          //
+          EDBPrint (L"Duplicated Symbol found!\n");
+          return EFI_NO_MAPPING;
+        } else {
+          //
+          // record Address
+          //
+          *Address = (Entry[EntryIndex].RVA + Object[ObjectIndex].BaseAddress);
+        }
+      }
+    }
+  }
+
+  if (*Address == 0) {
+    //
+    // Not found
+    //
+    return EFI_NOT_FOUND;
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSymbol.h b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSymbol.h
new file mode 100644
index 000000000000..3ae030918db8
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbSymbol.h
@@ -0,0 +1,128 @@
+/*++
+
+Copyright (c) 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.
+
+Module Name:
+
+  EdbSymbol.h
+
+Abstract:
+
+
+--*/
+
+#ifndef _EFI_EDB_SYMBOL_H_
+#define _EFI_EDB_SYMBOL_H_
+
+#include <Uefi.h>
+
+//
+// The default base address is 0x10000000
+//
+#define EFI_DEBUGGER_DEFAULT_LINK_IMAGEBASE  0x10000000
+
+#define EFI_DEBUGGER_MAX_SYMBOL_ADDRESS_DELTA_VALUE  0x100000 // 1 M delta
+
+typedef enum {
+  EdbMatchSymbolTypeSameAdderss,
+  EdbMatchSymbolTypeNearestAddress,
+  EdbMatchSymbolTypeLowerAddress,
+  EdbMatchSymbolTypeUpperAddress,
+  EdbMatchSymbolTypeMax,
+} EDB_MATCH_SYMBOL_TYPE;
+
+typedef enum {
+  EdbEbcImageRvaSearchTypeAny,
+  EdbEbcImageRvaSearchTypeFirst,
+  EdbEbcImageRvaSearchTypeLast,
+  EdbEbcImageRvaSearchTypeMax,
+} EDB_EBC_IMAGE_RVA_SEARCH_TYPE;
+
+UINTN
+EbdFindSymbolAddress (
+  IN UINTN                       Address,
+  IN EDB_MATCH_SYMBOL_TYPE       Type,
+  OUT EFI_DEBUGGER_SYMBOL_OBJECT **Object,
+  OUT EFI_DEBUGGER_SYMBOL_ENTRY  **Entry
+  );
+
+EFI_STATUS
+EdbLoadSymbol (
+  IN EFI_DEBUGGER_PRIVATE_DATA   *DebuggerPrivate,
+  IN CHAR16                      *FileName,
+  IN UINTN                       BufferSize,
+  IN VOID                        *Buffer
+  );
+
+EFI_STATUS
+EdbUnloadSymbol (
+  IN EFI_DEBUGGER_PRIVATE_DATA   *DebuggerPrivate,
+  IN CHAR16                      *FileName
+  );
+
+EFI_STATUS
+EdbPatchSymbolRVA (
+  IN EFI_DEBUGGER_PRIVATE_DATA     *DebuggerPrivate,
+  IN CHAR16                        *FileName,
+  IN EDB_EBC_IMAGE_RVA_SEARCH_TYPE SearchType
+  );
+
+EFI_STATUS
+EdbLoadCode (
+  IN EFI_DEBUGGER_PRIVATE_DATA   *DebuggerPrivate,
+  IN CHAR16                      *MapFileName,
+  IN CHAR16                      *FileName,
+  IN UINTN                       BufferSize,
+  IN VOID                        *Buffer
+  );
+
+EFI_STATUS
+EdbUnloadCode (
+  IN EFI_DEBUGGER_PRIVATE_DATA   *DebuggerPrivate,
+  IN CHAR16                      *MapFileName,
+  IN CHAR16                      *FileName,
+  OUT VOID                       **Buffer
+  );
+
+EFI_STATUS
+EdbAddCodeBuffer (
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     CHAR16                    *MapFileName,
+  IN     CHAR16                    *CodeFileName,
+  IN     UINTN                     SourceBufferSize,
+  IN     VOID                      *SourceBuffer
+  );
+
+EFI_STATUS
+EdbDeleteCodeBuffer (
+  IN     EFI_DEBUGGER_PRIVATE_DATA *DebuggerPrivate,
+  IN     CHAR16                    *MapFileName,
+  IN     CHAR16                    *CodeFileName,
+  IN     VOID                      *SourceBuffer
+  );
+
+CHAR8 *
+FindSymbolStr (
+  IN UINTN Address
+  );
+
+UINTN
+EdbPrintSource (
+  IN UINTN     Address,
+  IN BOOLEAN   IsPrint
+  );
+
+EFI_STATUS
+Symboltoi (
+  IN CHAR16   *Symbol,
+  OUT UINTN   *Address
+  );
+
+#endif
diff --git a/MdeModulePkg/Universal/EbcDxe/EbcDebuggerExtra.uni b/MdeModulePkg/Universal/EbcDxe/EbcDebuggerExtra.uni
new file mode 100644
index 000000000000..73886ebeab41
--- /dev/null
+++ b/MdeModulePkg/Universal/EbcDxe/EbcDebuggerExtra.uni
@@ -0,0 +1,17 @@
+// /** @file
+// EFI Byte Code (EBC) Debugger
+//
+// Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
+//
+// 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.
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME 
+#language en-US 
+"EFI Byte Code (EBC) Debugger"
-- 
2.9.3.windows.2



  parent reply	other threads:[~2016-11-14 13:15 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-11-14 13:14 [PATCH (RESEND) v2 0/3] MdeModulePkg/EbcDxe: add EBC Debugger Pete Batard
2016-11-14 13:14 ` [PATCH (RESEND) v2 1/3] MdeModulePkg/EbcDxe: prepare support for " Pete Batard
2016-11-14 13:14 ` Pete Batard [this message]
2016-11-14 13:14 ` [PATCH (RESEND) v2 3/3] MdeModulePkg/EbcDxe: reorganize EBC header definitions Pete Batard
2016-11-14 13:22 ` [PATCH (RESEND) v2 0/3] MdeModulePkg/EbcDxe: add EBC Debugger Laszlo Ersek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20161114131418.11876-3-pete@akeo.ie \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox