]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/EbcDxe/EbcInt.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / MdeModulePkg / Universal / EbcDxe / EbcInt.c
index 9357dcd26e936200720f8a4169dea3d82ae6b66d..d2254c2765b6b9a642a9f4eb2e1a5fe2b7eb215c 100644 (file)
@@ -3,19 +3,14 @@
   Provides auxiliary support routines for the VM. That is, routines\r
   that are not particularly related to VM execution of EBC instructions.\r
 \r
   Provides auxiliary support routines for the VM. That is, routines\r
   that are not particularly related to VM execution of EBC instructions.\r
 \r
-Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution.  The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
 #include "EbcInt.h"\r
 #include "EbcExecute.h"\r
 \r
 **/\r
 \r
 #include "EbcInt.h"\r
 #include "EbcExecute.h"\r
+#include "EbcDebuggerHook.h"\r
 \r
 //\r
 // We'll keep track of all thunks we create in a linked list. Each\r
 \r
 //\r
 // We'll keep track of all thunks we create in a linked list. Each\r
@@ -25,15 +20,15 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 //\r
 typedef struct _EBC_THUNK_LIST EBC_THUNK_LIST;\r
 struct _EBC_THUNK_LIST {\r
 //\r
 typedef struct _EBC_THUNK_LIST EBC_THUNK_LIST;\r
 struct _EBC_THUNK_LIST {\r
-  VOID            *ThunkBuffer;\r
-  EBC_THUNK_LIST  *Next;\r
+  VOID              *ThunkBuffer;\r
+  EBC_THUNK_LIST    *Next;\r
 };\r
 \r
 typedef struct _EBC_IMAGE_LIST EBC_IMAGE_LIST;\r
 struct _EBC_IMAGE_LIST {\r
 };\r
 \r
 typedef struct _EBC_IMAGE_LIST EBC_IMAGE_LIST;\r
 struct _EBC_IMAGE_LIST {\r
-  EBC_IMAGE_LIST  *Next;\r
-  EFI_HANDLE      ImageHandle;\r
-  EBC_THUNK_LIST  *ThunkList;\r
+  EBC_IMAGE_LIST    *Next;\r
+  EFI_HANDLE        ImageHandle;\r
+  EBC_THUNK_LIST    *ThunkList;\r
 };\r
 \r
 /**\r
 };\r
 \r
 /**\r
@@ -53,8 +48,8 @@ struct _EBC_IMAGE_LIST {
 EFI_STATUS\r
 EFIAPI\r
 EbcUnloadImage (\r
 EFI_STATUS\r
 EFIAPI\r
 EbcUnloadImage (\r
-  IN EFI_EBC_PROTOCOL   *This,\r
-  IN EFI_HANDLE         ImageHandle\r
+  IN EFI_EBC_PROTOCOL  *This,\r
+  IN EFI_HANDLE        ImageHandle\r
   );\r
 \r
 /**\r
   );\r
 \r
 /**\r
@@ -79,10 +74,10 @@ EbcUnloadImage (
 EFI_STATUS\r
 EFIAPI\r
 EbcCreateThunk (\r
 EFI_STATUS\r
 EFIAPI\r
 EbcCreateThunk (\r
-  IN EFI_EBC_PROTOCOL   *This,\r
-  IN EFI_HANDLE         ImageHandle,\r
-  IN VOID               *EbcEntryPoint,\r
-  OUT VOID              **Thunk\r
+  IN EFI_EBC_PROTOCOL  *This,\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN VOID              *EbcEntryPoint,\r
+  OUT VOID             **Thunk\r
   );\r
 \r
 /**\r
   );\r
 \r
 /**\r
@@ -99,8 +94,8 @@ EbcCreateThunk (
 EFI_STATUS\r
 EFIAPI\r
 EbcGetVersion (\r
 EFI_STATUS\r
 EFIAPI\r
 EbcGetVersion (\r
-  IN EFI_EBC_PROTOCOL   *This,\r
-  IN OUT UINT64         *Version\r
+  IN EFI_EBC_PROTOCOL  *This,\r
+  IN OUT UINT64        *Version\r
   );\r
 \r
 /**\r
   );\r
 \r
 /**\r
@@ -131,8 +126,8 @@ InitializeEbcCallback (
 VOID\r
 EFIAPI\r
 CommonEbcExceptionHandler (\r
 VOID\r
 EFIAPI\r
 CommonEbcExceptionHandler (\r
-  IN EFI_EXCEPTION_TYPE   InterruptType,\r
-  IN EFI_SYSTEM_CONTEXT   SystemContext\r
+  IN EFI_EXCEPTION_TYPE  InterruptType,\r
+  IN EFI_SYSTEM_CONTEXT  SystemContext\r
   );\r
 \r
 /**\r
   );\r
 \r
 /**\r
@@ -146,8 +141,8 @@ CommonEbcExceptionHandler (
 VOID\r
 EFIAPI\r
 EbcPeriodicNotifyFunction (\r
 VOID\r
 EFIAPI\r
 EbcPeriodicNotifyFunction (\r
-  IN EFI_EVENT     Event,\r
-  IN VOID          *Context\r
+  IN EFI_EVENT  Event,\r
+  IN VOID       *Context\r
   );\r
 \r
 /**\r
   );\r
 \r
 /**\r
@@ -163,13 +158,14 @@ EbcPeriodicNotifyFunction (
 EFI_STATUS\r
 EFIAPI\r
 EbcDebugPeriodic (\r
 EFI_STATUS\r
 EFIAPI\r
 EbcDebugPeriodic (\r
-  IN VM_CONTEXT *VmPtr\r
+  IN VM_CONTEXT  *VmPtr\r
   );\r
 \r
 //\r
 // These two functions and the  GUID are used to produce an EBC test protocol.\r
 // This functionality is definitely not required for execution.\r
 //\r
   );\r
 \r
 //\r
 // These two functions and the  GUID are used to produce an EBC test protocol.\r
 // This functionality is definitely not required for execution.\r
 //\r
+\r
 /**\r
   Produces an EBC VM test protocol that can be used for regression tests.\r
 \r
 /**\r
   Produces an EBC VM test protocol that can be used for regression tests.\r
 \r
@@ -181,7 +177,7 @@ EbcDebugPeriodic (
 **/\r
 EFI_STATUS\r
 InitEbcVmTestProtocol (\r
 **/\r
 EFI_STATUS\r
 InitEbcVmTestProtocol (\r
-  IN EFI_HANDLE     *IHandle\r
+  IN EFI_HANDLE  *IHandle\r
   );\r
 \r
 /**\r
   );\r
 \r
 /**\r
@@ -191,6 +187,7 @@ InitEbcVmTestProtocol (
 \r
 **/\r
 EFI_STATUS\r
 \r
 **/\r
 EFI_STATUS\r
+EFIAPI\r
 EbcVmTestUnsupported (\r
   VOID\r
   );\r
 EbcVmTestUnsupported (\r
   VOID\r
   );\r
@@ -208,8 +205,8 @@ EbcVmTestUnsupported (
 EFI_STATUS\r
 EFIAPI\r
 EbcRegisterICacheFlush (\r
 EFI_STATUS\r
 EFIAPI\r
 EbcRegisterICacheFlush (\r
-  IN EFI_EBC_PROTOCOL   *This,\r
-  IN EBC_ICACHE_FLUSH   Flush\r
+  IN EFI_EBC_PROTOCOL  *This,\r
+  IN EBC_ICACHE_FLUSH  Flush\r
   );\r
 \r
 /**\r
   );\r
 \r
 /**\r
@@ -226,8 +223,8 @@ EbcRegisterICacheFlush (
 EFI_STATUS\r
 EFIAPI\r
 EbcDebugGetMaximumProcessorIndex (\r
 EFI_STATUS\r
 EFIAPI\r
 EbcDebugGetMaximumProcessorIndex (\r
-  IN EFI_DEBUG_SUPPORT_PROTOCOL          *This,\r
-  OUT UINTN                              *MaxProcessorIndex\r
+  IN EFI_DEBUG_SUPPORT_PROTOCOL  *This,\r
+  OUT UINTN                      *MaxProcessorIndex\r
   );\r
 \r
 /**\r
   );\r
 \r
 /**\r
@@ -312,10 +309,10 @@ EbcDebugRegisterExceptionCallback (
 EFI_STATUS\r
 EFIAPI\r
 EbcDebugInvalidateInstructionCache (\r
 EFI_STATUS\r
 EFIAPI\r
 EbcDebugInvalidateInstructionCache (\r
-  IN EFI_DEBUG_SUPPORT_PROTOCOL          *This,\r
-  IN UINTN                               ProcessorIndex,\r
-  IN VOID                                *Start,\r
-  IN UINT64                              Length\r
+  IN EFI_DEBUG_SUPPORT_PROTOCOL  *This,\r
+  IN UINTN                       ProcessorIndex,\r
+  IN VOID                        *Start,\r
+  IN UINT64                      Length\r
   );\r
 \r
 //\r
   );\r
 \r
 //\r
@@ -324,30 +321,152 @@ EbcDebugInvalidateInstructionCache (
 // also be global since the execution of an EBC image does not provide\r
 // a This pointer.\r
 //\r
 // also be global since the execution of an EBC image does not provide\r
 // a This pointer.\r
 //\r
-EBC_IMAGE_LIST         *mEbcImageList = NULL;\r
+EBC_IMAGE_LIST  *mEbcImageList = NULL;\r
 \r
 //\r
 // Callback function to flush the icache after thunk creation\r
 //\r
 \r
 //\r
 // Callback function to flush the icache after thunk creation\r
 //\r
-EBC_ICACHE_FLUSH       mEbcICacheFlush;\r
+EBC_ICACHE_FLUSH  mEbcICacheFlush;\r
 \r
 //\r
 // These get set via calls by the debug agent\r
 //\r
 \r
 //\r
 // These get set via calls by the debug agent\r
 //\r
-EFI_PERIODIC_CALLBACK  mDebugPeriodicCallback = NULL;\r
-EFI_EXCEPTION_CALLBACK mDebugExceptionCallback[MAX_EBC_EXCEPTION + 1] = {NULL};\r
-EFI_GUID               mEfiEbcVmTestProtocolGuid = EFI_EBC_VM_TEST_PROTOCOL_GUID;\r
+EFI_PERIODIC_CALLBACK   mDebugPeriodicCallback                         = NULL;\r
+EFI_EXCEPTION_CALLBACK  mDebugExceptionCallback[MAX_EBC_EXCEPTION + 1] = { NULL };\r
 \r
 \r
-VOID                   *mStackBuffer[MAX_STACK_NUM];\r
-EFI_HANDLE             mStackBufferIndex[MAX_STACK_NUM];\r
-UINTN                  mStackNum = 0;\r
+VOID        *mStackBuffer[MAX_STACK_NUM];\r
+EFI_HANDLE  mStackBufferIndex[MAX_STACK_NUM];\r
+UINTN       mStackNum = 0;\r
 \r
 //\r
 // Event for Periodic callback\r
 //\r
 \r
 //\r
 // Event for Periodic callback\r
 //\r
-EFI_EVENT              mEbcPeriodicEvent;\r
-VM_CONTEXT             *mVmPtr = NULL;\r
+EFI_EVENT   mEbcPeriodicEvent;\r
+VM_CONTEXT  *mVmPtr = NULL;\r
+\r
+/**\r
+  Check whether the emulator supports executing a certain PE/COFF image\r
+\r
+  @param[in] This         This pointer for EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL\r
+                          structure\r
+  @param[in] ImageType    Whether the image is an application, a boot time\r
+                          driver or a runtime driver.\r
+  @param[in] DevicePath   Path to device where the image originated\r
+                          (e.g., a PCI option ROM)\r
 \r
 \r
+  @retval TRUE            The image is supported by the emulator\r
+  @retval FALSE           The image is not supported by the emulator.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+EbcIsImageSupported (\r
+  IN  EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL  *This,\r
+  IN  UINT16                                ImageType,\r
+  IN  EFI_DEVICE_PATH_PROTOCOL              *DevicePath   OPTIONAL\r
+  )\r
+{\r
+  if ((ImageType != EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) &&\r
+      (ImageType != EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER))\r
+  {\r
+    return FALSE;\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  Register a supported PE/COFF image with the emulator. After this call\r
+  completes successfully, the PE/COFF image may be started as usual, and\r
+  it is the responsibility of the emulator implementation that any branch\r
+  into the code section of the image (including returns from functions called\r
+  from the foreign code) is executed as if it were running on the machine\r
+  type it was built for.\r
+\r
+  @param[in]      This          This pointer for\r
+                                EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL structure\r
+  @param[in]      ImageBase     The base address in memory of the PE/COFF image\r
+  @param[in]      ImageSize     The size in memory of the PE/COFF image\r
+  @param[in,out]  EntryPoint    The entry point of the PE/COFF image. Passed by\r
+                                reference so that the emulator may modify it.\r
+\r
+  @retval EFI_SUCCESS           The image was registered with the emulator and\r
+                                can be started as usual.\r
+  @retval other                 The image could not be registered.\r
+\r
+  If the PE/COFF machine type or image type are not supported by the emulator,\r
+  then ASSERT().\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EbcRegisterImage (\r
+  IN      EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL  *This,\r
+  IN      EFI_PHYSICAL_ADDRESS                  ImageBase,\r
+  IN      UINT64                                ImageSize,\r
+  IN  OUT EFI_IMAGE_ENTRY_POINT                 *EntryPoint\r
+  )\r
+{\r
+  DEBUG_CODE_BEGIN ();\r
+  PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;\r
+  EFI_STATUS                    Status;\r
+\r
+  ZeroMem (&ImageContext, sizeof (ImageContext));\r
+\r
+  ImageContext.Handle    = (VOID *)(UINTN)ImageBase;\r
+  ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;\r
+\r
+  Status = PeCoffLoaderGetImageInfo (&ImageContext);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  ASSERT (ImageContext.Machine == EFI_IMAGE_MACHINE_EBC);\r
+  ASSERT (\r
+    ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION ||\r
+    ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER\r
+    );\r
+  DEBUG_CODE_END ();\r
+\r
+  EbcRegisterICacheFlush (\r
+    NULL,\r
+    (EBC_ICACHE_FLUSH)InvalidateInstructionCacheRange\r
+    );\r
+\r
+  return EbcCreateThunk (\r
+           NULL,\r
+           (VOID *)(UINTN)ImageBase,\r
+           (VOID *)(UINTN)*EntryPoint,\r
+           (VOID **)EntryPoint\r
+           );\r
+}\r
+\r
+/**\r
+  Unregister a PE/COFF image that has been registered with the emulator.\r
+  This should be done before the image is unloaded from memory.\r
+\r
+  @param[in] This         This pointer for EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL\r
+                          structure\r
+  @param[in] ImageBase    The base address in memory of the PE/COFF image\r
+\r
+  @retval EFI_SUCCESS     The image was unregistered with the emulator.\r
+  @retval other           Image could not be unloaded.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EbcUnregisterImage (\r
+  IN  EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL  *This,\r
+  IN  EFI_PHYSICAL_ADDRESS                  ImageBase\r
+  )\r
+{\r
+  return EbcUnloadImage (NULL, (VOID *)(UINTN)ImageBase);\r
+}\r
+\r
+STATIC EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL  mPeCoffEmuProtocol = {\r
+  EbcIsImageSupported,\r
+  EbcRegisterImage,\r
+  EbcUnregisterImage,\r
+  EDKII_PECOFF_IMAGE_EMULATOR_VERSION,\r
+  EFI_IMAGE_MACHINE_EBC\r
+};\r
 \r
 /**\r
   Initializes the VM EFI interface.  Allocates memory for the VM interface\r
 \r
 /**\r
   Initializes the VM EFI interface.  Allocates memory for the VM interface\r
@@ -362,8 +481,8 @@ VM_CONTEXT             *mVmPtr = NULL;
 EFI_STATUS\r
 EFIAPI\r
 InitializeEbcDriver (\r
 EFI_STATUS\r
 EFIAPI\r
 InitializeEbcDriver (\r
-  IN EFI_HANDLE           ImageHandle,\r
-  IN EFI_SYSTEM_TABLE     *SystemTable\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
   )\r
 {\r
   EFI_EBC_PROTOCOL            *EbcProtocol;\r
   )\r
 {\r
   EFI_EBC_PROTOCOL            *EbcProtocol;\r
@@ -387,24 +506,24 @@ InitializeEbcDriver (
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  EbcProtocol->CreateThunk          = EbcCreateThunk;\r
-  EbcProtocol->UnloadImage          = EbcUnloadImage;\r
-  EbcProtocol->RegisterICacheFlush  = EbcRegisterICacheFlush;\r
-  EbcProtocol->GetVersion           = EbcGetVersion;\r
-  mEbcICacheFlush                   = NULL;\r
+  EbcProtocol->CreateThunk         = EbcCreateThunk;\r
+  EbcProtocol->UnloadImage         = EbcUnloadImage;\r
+  EbcProtocol->RegisterICacheFlush = EbcRegisterICacheFlush;\r
+  EbcProtocol->GetVersion          = EbcGetVersion;\r
+  mEbcICacheFlush                  = NULL;\r
 \r
   //\r
   // Find any already-installed EBC protocols and uninstall them\r
   //\r
 \r
   //\r
   // Find any already-installed EBC protocols and uninstall them\r
   //\r
-  Installed     = FALSE;\r
-  HandleBuffer  = NULL;\r
-  Status = gBS->LocateHandleBuffer (\r
-                  ByProtocol,\r
-                  &gEfiEbcProtocolGuid,\r
-                  NULL,\r
-                  &NumHandles,\r
-                  &HandleBuffer\r
-                  );\r
+  Installed    = FALSE;\r
+  HandleBuffer = NULL;\r
+  Status       = gBS->LocateHandleBuffer (\r
+                        ByProtocol,\r
+                        &gEfiEbcProtocolGuid,\r
+                        NULL,\r
+                        &NumHandles,\r
+                        &HandleBuffer\r
+                        );\r
   if (Status == EFI_SUCCESS) {\r
     //\r
     // Loop through the handles\r
   if (Status == EFI_SUCCESS) {\r
     //\r
     // Loop through the handles\r
@@ -413,15 +532,16 @@ InitializeEbcDriver (
       Status = gBS->HandleProtocol (\r
                       HandleBuffer[Index],\r
                       &gEfiEbcProtocolGuid,\r
       Status = gBS->HandleProtocol (\r
                       HandleBuffer[Index],\r
                       &gEfiEbcProtocolGuid,\r
-                      (VOID **) &OldEbcProtocol\r
+                      (VOID **)&OldEbcProtocol\r
                       );\r
       if (Status == EFI_SUCCESS) {\r
         if (gBS->ReinstallProtocolInterface (\r
                       );\r
       if (Status == EFI_SUCCESS) {\r
         if (gBS->ReinstallProtocolInterface (\r
-                  HandleBuffer[Index],\r
-                  &gEfiEbcProtocolGuid,\r
-                  OldEbcProtocol,\r
-                  EbcProtocol\r
-                  ) == EFI_SUCCESS) {\r
+                   HandleBuffer[Index],\r
+                   &gEfiEbcProtocolGuid,\r
+                   OldEbcProtocol,\r
+                   EbcProtocol\r
+                   ) == EFI_SUCCESS)\r
+        {\r
           Installed = TRUE;\r
         }\r
       }\r
           Installed = TRUE;\r
         }\r
       }\r
@@ -432,15 +552,18 @@ InitializeEbcDriver (
     FreePool (HandleBuffer);\r
     HandleBuffer = NULL;\r
   }\r
     FreePool (HandleBuffer);\r
     HandleBuffer = NULL;\r
   }\r
+\r
   //\r
   // Add the protocol so someone can locate us if we haven't already.\r
   //\r
   if (!Installed) {\r
   //\r
   // Add the protocol so someone can locate us if we haven't already.\r
   //\r
   if (!Installed) {\r
-    Status = gBS->InstallProtocolInterface (\r
+    Status = gBS->InstallMultipleProtocolInterfaces (\r
                     &ImageHandle,\r
                     &gEfiEbcProtocolGuid,\r
                     &ImageHandle,\r
                     &gEfiEbcProtocolGuid,\r
-                    EFI_NATIVE_INTERFACE,\r
-                    EbcProtocol\r
+                    EbcProtocol,\r
+                    &gEdkiiPeCoffImageEmulatorProtocolGuid,\r
+                    &mPeCoffEmuProtocol,\r
+                    NULL\r
                     );\r
     if (EFI_ERROR (Status)) {\r
       FreePool (EbcProtocol);\r
                     );\r
     if (EFI_ERROR (Status)) {\r
       FreePool (EbcProtocol);\r
@@ -448,8 +571,8 @@ InitializeEbcDriver (
     }\r
   }\r
 \r
     }\r
   }\r
 \r
-  Status = InitEBCStack();\r
-  if (EFI_ERROR(Status)) {\r
+  Status = InitEBCStack ();\r
+  if (EFI_ERROR (Status)) {\r
     goto ErrorExit;\r
   }\r
 \r
     goto ErrorExit;\r
   }\r
 \r
@@ -462,11 +585,11 @@ InitializeEbcDriver (
     goto ErrorExit;\r
   }\r
 \r
     goto ErrorExit;\r
   }\r
 \r
-  EbcDebugProtocol->Isa                         = IsaEbc;\r
-  EbcDebugProtocol->GetMaximumProcessorIndex    = EbcDebugGetMaximumProcessorIndex;\r
-  EbcDebugProtocol->RegisterPeriodicCallback    = EbcDebugRegisterPeriodicCallback;\r
-  EbcDebugProtocol->RegisterExceptionCallback   = EbcDebugRegisterExceptionCallback;\r
-  EbcDebugProtocol->InvalidateInstructionCache  = EbcDebugInvalidateInstructionCache;\r
+  EbcDebugProtocol->Isa                        = IsaEbc;\r
+  EbcDebugProtocol->GetMaximumProcessorIndex   = EbcDebugGetMaximumProcessorIndex;\r
+  EbcDebugProtocol->RegisterPeriodicCallback   = EbcDebugRegisterPeriodicCallback;\r
+  EbcDebugProtocol->RegisterExceptionCallback  = EbcDebugRegisterExceptionCallback;\r
+  EbcDebugProtocol->InvalidateInstructionCache = EbcDebugInvalidateInstructionCache;\r
 \r
   //\r
   // Add the protocol so the debug agent can find us\r
 \r
   //\r
   // Add the protocol so the debug agent can find us\r
@@ -484,6 +607,7 @@ InitializeEbcDriver (
     FreePool (EbcDebugProtocol);\r
     goto ErrorExit;\r
   }\r
     FreePool (EbcDebugProtocol);\r
     goto ErrorExit;\r
   }\r
+\r
   //\r
   // Install EbcDebugSupport Protocol Successfully\r
   // Now we need to initialize the Ebc default Callback\r
   //\r
   // Install EbcDebugSupport Protocol Successfully\r
   // Now we need to initialize the Ebc default Callback\r
@@ -494,21 +618,23 @@ InitializeEbcDriver (
   // Produce a VM test interface protocol. Not required for execution.\r
   //\r
   DEBUG_CODE_BEGIN ();\r
   // Produce a VM test interface protocol. Not required for execution.\r
   //\r
   DEBUG_CODE_BEGIN ();\r
-    InitEbcVmTestProtocol (&ImageHandle);\r
+  InitEbcVmTestProtocol (&ImageHandle);\r
   DEBUG_CODE_END ();\r
 \r
   DEBUG_CODE_END ();\r
 \r
+  EbcDebuggerHookInit (ImageHandle, EbcDebugProtocol);\r
+\r
   return EFI_SUCCESS;\r
 \r
 ErrorExit:\r
   return EFI_SUCCESS;\r
 \r
 ErrorExit:\r
-  FreeEBCStack();\r
-  HandleBuffer  = NULL;\r
-  Status = gBS->LocateHandleBuffer (\r
-                  ByProtocol,\r
-                  &gEfiEbcProtocolGuid,\r
-                  NULL,\r
-                  &NumHandles,\r
-                  &HandleBuffer\r
-                  );\r
+  FreeEBCStack ();\r
+  HandleBuffer = NULL;\r
+  Status       = gBS->LocateHandleBuffer (\r
+                        ByProtocol,\r
+                        &gEfiEbcProtocolGuid,\r
+                        NULL,\r
+                        &NumHandles,\r
+                        &HandleBuffer\r
+                        );\r
   if (Status == EFI_SUCCESS) {\r
     //\r
     // Loop through the handles\r
   if (Status == EFI_SUCCESS) {\r
     //\r
     // Loop through the handles\r
@@ -517,7 +643,7 @@ ErrorExit:
       Status = gBS->HandleProtocol (\r
                       HandleBuffer[Index],\r
                       &gEfiEbcProtocolGuid,\r
       Status = gBS->HandleProtocol (\r
                       HandleBuffer[Index],\r
                       &gEfiEbcProtocolGuid,\r
-                      (VOID **) &OldEbcProtocol\r
+                      (VOID **)&OldEbcProtocol\r
                       );\r
       if (Status == EFI_SUCCESS) {\r
         gBS->UninstallProtocolInterface (\r
                       );\r
       if (Status == EFI_SUCCESS) {\r
         gBS->UninstallProtocolInterface (\r
@@ -539,7 +665,6 @@ ErrorExit:
   return Status;\r
 }\r
 \r
   return Status;\r
 }\r
 \r
-\r
 /**\r
   This is the top-level routine plugged into the EBC protocol. Since thunks\r
   are very processor-specific, from here we dispatch directly to the very\r
 /**\r
   This is the top-level routine plugged into the EBC protocol. Since thunks\r
   are very processor-specific, from here we dispatch directly to the very\r
@@ -562,24 +687,23 @@ ErrorExit:
 EFI_STATUS\r
 EFIAPI\r
 EbcCreateThunk (\r
 EFI_STATUS\r
 EFIAPI\r
 EbcCreateThunk (\r
-  IN EFI_EBC_PROTOCOL   *This,\r
-  IN EFI_HANDLE         ImageHandle,\r
-  IN VOID               *EbcEntryPoint,\r
-  OUT VOID              **Thunk\r
+  IN EFI_EBC_PROTOCOL  *This,\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN VOID              *EbcEntryPoint,\r
+  OUT VOID             **Thunk\r
   )\r
 {\r
   EFI_STATUS  Status;\r
 \r
   Status = EbcCreateThunks (\r
   )\r
 {\r
   EFI_STATUS  Status;\r
 \r
   Status = EbcCreateThunks (\r
-            ImageHandle,\r
-            EbcEntryPoint,\r
-            Thunk,\r
-            FLAG_THUNK_ENTRY_POINT\r
-            );\r
+             ImageHandle,\r
+             EbcEntryPoint,\r
+             Thunk,\r
+             FLAG_THUNK_ENTRY_POINT\r
+             );\r
   return Status;\r
 }\r
 \r
   return Status;\r
 }\r
 \r
-\r
 /**\r
   This EBC debugger protocol service is called by the debug agent\r
 \r
 /**\r
   This EBC debugger protocol service is called by the debug agent\r
 \r
@@ -594,15 +718,14 @@ EbcCreateThunk (
 EFI_STATUS\r
 EFIAPI\r
 EbcDebugGetMaximumProcessorIndex (\r
 EFI_STATUS\r
 EFIAPI\r
 EbcDebugGetMaximumProcessorIndex (\r
-  IN EFI_DEBUG_SUPPORT_PROTOCOL          *This,\r
-  OUT UINTN                              *MaxProcessorIndex\r
+  IN EFI_DEBUG_SUPPORT_PROTOCOL  *This,\r
+  OUT UINTN                      *MaxProcessorIndex\r
   )\r
 {\r
   *MaxProcessorIndex = 0;\r
   return EFI_SUCCESS;\r
 }\r
 \r
   )\r
 {\r
   *MaxProcessorIndex = 0;\r
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   This protocol service is called by the debug agent to register a function\r
   for us to call on a periodic basis.\r
 /**\r
   This protocol service is called by the debug agent to register a function\r
   for us to call on a periodic basis.\r
@@ -635,6 +758,7 @@ EbcDebugRegisterPeriodicCallback (
   if ((mDebugPeriodicCallback == NULL) && (PeriodicCallback == NULL)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
   if ((mDebugPeriodicCallback == NULL) && (PeriodicCallback == NULL)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
+\r
   if ((mDebugPeriodicCallback != NULL) && (PeriodicCallback != NULL)) {\r
     return EFI_ALREADY_STARTED;\r
   }\r
   if ((mDebugPeriodicCallback != NULL) && (PeriodicCallback != NULL)) {\r
     return EFI_ALREADY_STARTED;\r
   }\r
@@ -643,7 +767,6 @@ EbcDebugRegisterPeriodicCallback (
   return EFI_SUCCESS;\r
 }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   This protocol service is called by the debug agent to register a function\r
   for us to call when we detect an exception.\r
 /**\r
   This protocol service is called by the debug agent to register a function\r
   for us to call when we detect an exception.\r
@@ -681,17 +804,19 @@ EbcDebugRegisterExceptionCallback (
   if ((ExceptionType < 0) || (ExceptionType > MAX_EBC_EXCEPTION)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
   if ((ExceptionType < 0) || (ExceptionType > MAX_EBC_EXCEPTION)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
+\r
   if ((mDebugExceptionCallback[ExceptionType] == NULL) && (ExceptionCallback == NULL)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
   if ((mDebugExceptionCallback[ExceptionType] == NULL) && (ExceptionCallback == NULL)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
+\r
   if ((mDebugExceptionCallback[ExceptionType] != NULL) && (ExceptionCallback != NULL)) {\r
     return EFI_ALREADY_STARTED;\r
   }\r
   if ((mDebugExceptionCallback[ExceptionType] != NULL) && (ExceptionCallback != NULL)) {\r
     return EFI_ALREADY_STARTED;\r
   }\r
+\r
   mDebugExceptionCallback[ExceptionType] = ExceptionCallback;\r
   return EFI_SUCCESS;\r
 }\r
 \r
   mDebugExceptionCallback[ExceptionType] = ExceptionCallback;\r
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   This EBC debugger protocol service is called by the debug agent.  Required\r
   for DebugSupport compliance but is only stubbed out for EBC.\r
 /**\r
   This EBC debugger protocol service is called by the debug agent.  Required\r
   for DebugSupport compliance but is only stubbed out for EBC.\r
@@ -711,16 +836,15 @@ EbcDebugRegisterExceptionCallback (
 EFI_STATUS\r
 EFIAPI\r
 EbcDebugInvalidateInstructionCache (\r
 EFI_STATUS\r
 EFIAPI\r
 EbcDebugInvalidateInstructionCache (\r
-  IN EFI_DEBUG_SUPPORT_PROTOCOL          *This,\r
-  IN UINTN                               ProcessorIndex,\r
-  IN VOID                                *Start,\r
-  IN UINT64                              Length\r
+  IN EFI_DEBUG_SUPPORT_PROTOCOL  *This,\r
+  IN UINTN                       ProcessorIndex,\r
+  IN VOID                        *Start,\r
+  IN UINT64                      Length\r
   )\r
 {\r
   return EFI_SUCCESS;\r
 }\r
 \r
   )\r
 {\r
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   The VM interpreter calls this function when an exception is detected.\r
 \r
 /**\r
   The VM interpreter calls this function when an exception is detected.\r
 \r
@@ -734,9 +858,9 @@ EbcDebugInvalidateInstructionCache (
 **/\r
 EFI_STATUS\r
 EbcDebugSignalException (\r
 **/\r
 EFI_STATUS\r
 EbcDebugSignalException (\r
-  IN EFI_EXCEPTION_TYPE                   ExceptionType,\r
-  IN EXCEPTION_FLAGS                      ExceptionFlags,\r
-  IN VM_CONTEXT                           *VmPtr\r
+  IN EFI_EXCEPTION_TYPE  ExceptionType,\r
+  IN EXCEPTION_FLAGS     ExceptionFlags,\r
+  IN VM_CONTEXT          *VmPtr\r
   )\r
 {\r
   EFI_SYSTEM_CONTEXT_EBC  EbcContext;\r
   )\r
 {\r
   EFI_SYSTEM_CONTEXT_EBC  EbcContext;\r
@@ -747,7 +871,7 @@ EbcDebugSignalException (
   // Save the exception in the context passed in\r
   //\r
   VmPtr->ExceptionFlags |= ExceptionFlags;\r
   // Save the exception in the context passed in\r
   //\r
   VmPtr->ExceptionFlags |= ExceptionFlags;\r
-  VmPtr->LastException ExceptionType;\r
+  VmPtr->LastException   = (UINTN)ExceptionType;\r
   //\r
   // If it's a fatal exception, then flag it in the VM context in case an\r
   // attached debugger tries to return from it.\r
   //\r
   // If it's a fatal exception, then flag it in the VM context in case an\r
   // attached debugger tries to return from it.\r
@@ -763,43 +887,41 @@ EbcDebugSignalException (
   // status code via the status code API\r
   //\r
   if (mDebugExceptionCallback[ExceptionType] != NULL) {\r
   // status code via the status code API\r
   //\r
   if (mDebugExceptionCallback[ExceptionType] != NULL) {\r
-\r
     //\r
     // Initialize the context structure\r
     //\r
     //\r
     // Initialize the context structure\r
     //\r
-    EbcContext.R0                   = VmPtr->Gpr[0];\r
-    EbcContext.R1                   = VmPtr->Gpr[1];\r
-    EbcContext.R2                   = VmPtr->Gpr[2];\r
-    EbcContext.R3                   = VmPtr->Gpr[3];\r
-    EbcContext.R4                   = VmPtr->Gpr[4];\r
-    EbcContext.R5                   = VmPtr->Gpr[5];\r
-    EbcContext.R6                   = VmPtr->Gpr[6];\r
-    EbcContext.R7                   = VmPtr->Gpr[7];\r
-    EbcContext.Ip                   = (UINT64)(UINTN)VmPtr->Ip;\r
-    EbcContext.Flags                = VmPtr->Flags;\r
-    EbcContext.ControlFlags         = 0;\r
-    SystemContext.SystemContextEbc  = &EbcContext;\r
-\r
-    mDebugExceptionCallback[ExceptionType] (ExceptionType, SystemContext);\r
+    EbcContext.R0                  = (UINT64)VmPtr->Gpr[0];\r
+    EbcContext.R1                  = (UINT64)VmPtr->Gpr[1];\r
+    EbcContext.R2                  = (UINT64)VmPtr->Gpr[2];\r
+    EbcContext.R3                  = (UINT64)VmPtr->Gpr[3];\r
+    EbcContext.R4                  = (UINT64)VmPtr->Gpr[4];\r
+    EbcContext.R5                  = (UINT64)VmPtr->Gpr[5];\r
+    EbcContext.R6                  = (UINT64)VmPtr->Gpr[6];\r
+    EbcContext.R7                  = (UINT64)VmPtr->Gpr[7];\r
+    EbcContext.Ip                  = (UINT64)(UINTN)VmPtr->Ip;\r
+    EbcContext.Flags               = VmPtr->Flags;\r
+    EbcContext.ControlFlags        = 0;\r
+    SystemContext.SystemContextEbc = &EbcContext;\r
+\r
+    mDebugExceptionCallback[ExceptionType](ExceptionType, SystemContext);\r
     //\r
     // Restore the context structure and continue to execute\r
     //\r
     //\r
     // Restore the context structure and continue to execute\r
     //\r
-    VmPtr->Gpr[0]  = EbcContext.R0;\r
-    VmPtr->Gpr[1]  = EbcContext.R1;\r
-    VmPtr->Gpr[2]  = EbcContext.R2;\r
-    VmPtr->Gpr[3]  = EbcContext.R3;\r
-    VmPtr->Gpr[4]  = EbcContext.R4;\r
-    VmPtr->Gpr[5]  = EbcContext.R5;\r
-    VmPtr->Gpr[6]  = EbcContext.R6;\r
-    VmPtr->Gpr[7]  = EbcContext.R7;\r
-    VmPtr->Ip    = (VMIP)(UINTN)EbcContext.Ip;\r
-    VmPtr->Flags = EbcContext.Flags;\r
+    VmPtr->Gpr[0] = EbcContext.R0;\r
+    VmPtr->Gpr[1] = EbcContext.R1;\r
+    VmPtr->Gpr[2] = EbcContext.R2;\r
+    VmPtr->Gpr[3] = EbcContext.R3;\r
+    VmPtr->Gpr[4] = EbcContext.R4;\r
+    VmPtr->Gpr[5] = EbcContext.R5;\r
+    VmPtr->Gpr[6] = EbcContext.R6;\r
+    VmPtr->Gpr[7] = EbcContext.R7;\r
+    VmPtr->Ip     = (VMIP)(UINTN)EbcContext.Ip;\r
+    VmPtr->Flags  = EbcContext.Flags;\r
   }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
   }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   To install default Callback function for the VM interpreter.\r
 \r
 /**\r
   To install default Callback function for the VM interpreter.\r
 \r
@@ -816,8 +938,8 @@ InitializeEbcCallback (
   IN EFI_DEBUG_SUPPORT_PROTOCOL  *This\r
   )\r
 {\r
   IN EFI_DEBUG_SUPPORT_PROTOCOL  *This\r
   )\r
 {\r
-  INTN       Index;\r
-  EFI_STATUS Status;\r
+  INTN        Index;\r
+  EFI_STATUS  Status;\r
 \r
   //\r
   // For ExceptionCallback\r
 \r
   //\r
   // For ExceptionCallback\r
@@ -841,7 +963,7 @@ InitializeEbcCallback (
                   &mVmPtr,\r
                   &mEbcPeriodicEvent\r
                   );\r
                   &mVmPtr,\r
                   &mEbcPeriodicEvent\r
                   );\r
-  if (EFI_ERROR(Status)) {\r
+  if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
 \r
     return Status;\r
   }\r
 \r
@@ -850,14 +972,13 @@ InitializeEbcCallback (
                   TimerPeriodic,\r
                   EBC_VM_PERIODIC_CALLBACK_RATE\r
                   );\r
                   TimerPeriodic,\r
                   EBC_VM_PERIODIC_CALLBACK_RATE\r
                   );\r
-  if (EFI_ERROR(Status)) {\r
+  if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
     return Status;\r
   }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   The default Exception Callback for the VM interpreter.\r
   In this function, we report status code, and print debug information\r
 /**\r
   The default Exception Callback for the VM interpreter.\r
   In this function, we report status code, and print debug information\r
@@ -870,19 +991,71 @@ InitializeEbcCallback (
 VOID\r
 EFIAPI\r
 CommonEbcExceptionHandler (\r
 VOID\r
 EFIAPI\r
 CommonEbcExceptionHandler (\r
-  IN EFI_EXCEPTION_TYPE   InterruptType,\r
-  IN EFI_SYSTEM_CONTEXT   SystemContext\r
+  IN EFI_EXCEPTION_TYPE  InterruptType,\r
+  IN EFI_SYSTEM_CONTEXT  SystemContext\r
   )\r
 {\r
   )\r
 {\r
+  //\r
+  // We print debug information to let user know what happen.\r
+  //\r
+  DEBUG ((\r
+    DEBUG_ERROR,\r
+    "EBC Interrupter Version - 0x%016lx\n",\r
+    (UINT64)(((VM_MAJOR_VERSION & 0xFFFF) << 16) | ((VM_MINOR_VERSION & 0xFFFF)))\r
+    ));\r
+  DEBUG ((\r
+    DEBUG_ERROR,\r
+    "Exception Type - 0x%016lx\n",\r
+    (UINT64)(UINTN)InterruptType\r
+    ));\r
+  DEBUG ((\r
+    DEBUG_ERROR,\r
+    "  R0 - 0x%016lx, R1 - 0x%016lx\n",\r
+    SystemContext.SystemContextEbc->R0,\r
+    SystemContext.SystemContextEbc->R1\r
+    ));\r
+  DEBUG ((\r
+    DEBUG_ERROR,\r
+    "  R2 - 0x%016lx, R3 - 0x%016lx\n",\r
+    SystemContext.SystemContextEbc->R2,\r
+    SystemContext.SystemContextEbc->R3\r
+    ));\r
+  DEBUG ((\r
+    DEBUG_ERROR,\r
+    "  R4 - 0x%016lx, R5 - 0x%016lx\n",\r
+    SystemContext.SystemContextEbc->R4,\r
+    SystemContext.SystemContextEbc->R5\r
+    ));\r
+  DEBUG ((\r
+    DEBUG_ERROR,\r
+    "  R6 - 0x%016lx, R7 - 0x%016lx\n",\r
+    SystemContext.SystemContextEbc->R6,\r
+    SystemContext.SystemContextEbc->R7\r
+    ));\r
+  DEBUG ((\r
+    DEBUG_ERROR,\r
+    "  Flags - 0x%016lx\n",\r
+    SystemContext.SystemContextEbc->Flags\r
+    ));\r
+  DEBUG ((\r
+    DEBUG_ERROR,\r
+    "  ControlFlags - 0x%016lx\n",\r
+    SystemContext.SystemContextEbc->ControlFlags\r
+    ));\r
+  DEBUG ((\r
+    DEBUG_ERROR,\r
+    "  Ip - 0x%016lx\n\n",\r
+    SystemContext.SystemContextEbc->Ip\r
+    ));\r
+\r
   //\r
   // We deadloop here to make it easy to debug this issue.\r
   //\r
   //\r
   // We deadloop here to make it easy to debug this issue.\r
   //\r
-  ASSERT (FALSE);\r
+  CpuDeadLoop ();\r
 \r
 \r
-  return ;\r
+  return;\r
 }\r
 \r
 }\r
 \r
-\r
 /**\r
   The periodic callback function for EBC VM interpreter, which is used\r
   to support the EFI debug support protocol.\r
 /**\r
   The periodic callback function for EBC VM interpreter, which is used\r
   to support the EFI debug support protocol.\r
@@ -894,11 +1067,11 @@ CommonEbcExceptionHandler (
 VOID\r
 EFIAPI\r
 EbcPeriodicNotifyFunction (\r
 VOID\r
 EFIAPI\r
 EbcPeriodicNotifyFunction (\r
-  IN EFI_EVENT     Event,\r
-  IN VOID          *Context\r
+  IN EFI_EVENT  Event,\r
+  IN VOID       *Context\r
   )\r
 {\r
   )\r
 {\r
-  VM_CONTEXT *VmPtr;\r
+  VM_CONTEXT  *VmPtr;\r
 \r
   VmPtr = *(VM_CONTEXT **)Context;\r
 \r
 \r
   VmPtr = *(VM_CONTEXT **)Context;\r
 \r
@@ -906,10 +1079,9 @@ EbcPeriodicNotifyFunction (
     EbcDebugPeriodic (VmPtr);\r
   }\r
 \r
     EbcDebugPeriodic (VmPtr);\r
   }\r
 \r
-  return ;\r
+  return;\r
 }\r
 \r
 }\r
 \r
-\r
 /**\r
   The VM interpreter calls this function on a periodic basis to support\r
   the EFI debug support protocol.\r
 /**\r
   The VM interpreter calls this function on a periodic basis to support\r
   the EFI debug support protocol.\r
@@ -923,54 +1095,52 @@ EbcPeriodicNotifyFunction (
 EFI_STATUS\r
 EFIAPI\r
 EbcDebugPeriodic (\r
 EFI_STATUS\r
 EFIAPI\r
 EbcDebugPeriodic (\r
-  IN VM_CONTEXT *VmPtr\r
+  IN VM_CONTEXT  *VmPtr\r
   )\r
 {\r
   )\r
 {\r
-  EFI_SYSTEM_CONTEXT_EBC   EbcContext;\r
-  EFI_SYSTEM_CONTEXT       SystemContext;\r
+  EFI_SYSTEM_CONTEXT_EBC  EbcContext;\r
+  EFI_SYSTEM_CONTEXT      SystemContext;\r
 \r
   //\r
   // If someone's registered for periodic callbacks, then call them.\r
   //\r
   if (mDebugPeriodicCallback != NULL) {\r
 \r
   //\r
   // If someone's registered for periodic callbacks, then call them.\r
   //\r
   if (mDebugPeriodicCallback != NULL) {\r
-\r
     //\r
     // Initialize the context structure\r
     //\r
     //\r
     // Initialize the context structure\r
     //\r
-    EbcContext.R0                   = VmPtr->Gpr[0];\r
-    EbcContext.R1                   = VmPtr->Gpr[1];\r
-    EbcContext.R2                   = VmPtr->Gpr[2];\r
-    EbcContext.R3                   = VmPtr->Gpr[3];\r
-    EbcContext.R4                   = VmPtr->Gpr[4];\r
-    EbcContext.R5                   = VmPtr->Gpr[5];\r
-    EbcContext.R6                   = VmPtr->Gpr[6];\r
-    EbcContext.R7                   = VmPtr->Gpr[7];\r
-    EbcContext.Ip                   = (UINT64)(UINTN)VmPtr->Ip;\r
-    EbcContext.Flags                = VmPtr->Flags;\r
-    EbcContext.ControlFlags         = 0;\r
-    SystemContext.SystemContextEbc  = &EbcContext;\r
+    EbcContext.R0                  = (UINT64)VmPtr->Gpr[0];\r
+    EbcContext.R1                  = (UINT64)VmPtr->Gpr[1];\r
+    EbcContext.R2                  = (UINT64)VmPtr->Gpr[2];\r
+    EbcContext.R3                  = (UINT64)VmPtr->Gpr[3];\r
+    EbcContext.R4                  = (UINT64)VmPtr->Gpr[4];\r
+    EbcContext.R5                  = (UINT64)VmPtr->Gpr[5];\r
+    EbcContext.R6                  = (UINT64)VmPtr->Gpr[6];\r
+    EbcContext.R7                  = (UINT64)VmPtr->Gpr[7];\r
+    EbcContext.Ip                  = (UINT64)(UINTN)VmPtr->Ip;\r
+    EbcContext.Flags               = VmPtr->Flags;\r
+    EbcContext.ControlFlags        = 0;\r
+    SystemContext.SystemContextEbc = &EbcContext;\r
 \r
     mDebugPeriodicCallback (SystemContext);\r
 \r
     //\r
     // Restore the context structure and continue to execute\r
     //\r
 \r
     mDebugPeriodicCallback (SystemContext);\r
 \r
     //\r
     // Restore the context structure and continue to execute\r
     //\r
-    VmPtr->Gpr[0]  = EbcContext.R0;\r
-    VmPtr->Gpr[1]  = EbcContext.R1;\r
-    VmPtr->Gpr[2]  = EbcContext.R2;\r
-    VmPtr->Gpr[3]  = EbcContext.R3;\r
-    VmPtr->Gpr[4]  = EbcContext.R4;\r
-    VmPtr->Gpr[5]  = EbcContext.R5;\r
-    VmPtr->Gpr[6]  = EbcContext.R6;\r
-    VmPtr->Gpr[7]  = EbcContext.R7;\r
-    VmPtr->Ip    = (VMIP)(UINTN)EbcContext.Ip;\r
-    VmPtr->Flags = EbcContext.Flags;\r
+    VmPtr->Gpr[0] = EbcContext.R0;\r
+    VmPtr->Gpr[1] = EbcContext.R1;\r
+    VmPtr->Gpr[2] = EbcContext.R2;\r
+    VmPtr->Gpr[3] = EbcContext.R3;\r
+    VmPtr->Gpr[4] = EbcContext.R4;\r
+    VmPtr->Gpr[5] = EbcContext.R5;\r
+    VmPtr->Gpr[6] = EbcContext.R6;\r
+    VmPtr->Gpr[7] = EbcContext.R7;\r
+    VmPtr->Ip     = (VMIP)(UINTN)EbcContext.Ip;\r
+    VmPtr->Flags  = EbcContext.Flags;\r
   }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
   }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   This routine is called by the core when an image is being unloaded from\r
   memory. Basically we now have the opportunity to do any necessary cleanup.\r
 /**\r
   This routine is called by the core when an image is being unloaded from\r
   memory. Basically we now have the opportunity to do any necessary cleanup.\r
@@ -988,24 +1158,26 @@ EbcDebugPeriodic (
 EFI_STATUS\r
 EFIAPI\r
 EbcUnloadImage (\r
 EFI_STATUS\r
 EFIAPI\r
 EbcUnloadImage (\r
-  IN EFI_EBC_PROTOCOL   *This,\r
-  IN EFI_HANDLE         ImageHandle\r
+  IN EFI_EBC_PROTOCOL  *This,\r
+  IN EFI_HANDLE        ImageHandle\r
   )\r
 {\r
   EBC_THUNK_LIST  *ThunkList;\r
   EBC_THUNK_LIST  *NextThunkList;\r
   EBC_IMAGE_LIST  *ImageList;\r
   EBC_IMAGE_LIST  *PrevImageList;\r
   )\r
 {\r
   EBC_THUNK_LIST  *ThunkList;\r
   EBC_THUNK_LIST  *NextThunkList;\r
   EBC_IMAGE_LIST  *ImageList;\r
   EBC_IMAGE_LIST  *PrevImageList;\r
+\r
   //\r
   // First go through our list of known image handles and see if we've already\r
   // created an image list element for this image handle.\r
   //\r
   //\r
   // First go through our list of known image handles and see if we've already\r
   // created an image list element for this image handle.\r
   //\r
-  ReturnEBCStackByHandle(ImageHandle);\r
+  ReturnEBCStackByHandle (ImageHandle);\r
   PrevImageList = NULL;\r
   for (ImageList = mEbcImageList; ImageList != NULL; ImageList = ImageList->Next) {\r
     if (ImageList->ImageHandle == ImageHandle) {\r
       break;\r
     }\r
   PrevImageList = NULL;\r
   for (ImageList = mEbcImageList; ImageList != NULL; ImageList = ImageList->Next) {\r
     if (ImageList->ImageHandle == ImageHandle) {\r
       break;\r
     }\r
+\r
     //\r
     // Save the previous so we can connect the lists when we remove this one\r
     //\r
     //\r
     // Save the previous so we can connect the lists when we remove this one\r
     //\r
@@ -1015,6 +1187,7 @@ EbcUnloadImage (
   if (ImageList == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
   if (ImageList == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
+\r
   //\r
   // Free up all the thunk buffers and thunks list elements for this image\r
   // handle.\r
   //\r
   // Free up all the thunk buffers and thunks list elements for this image\r
   // handle.\r
@@ -1026,6 +1199,7 @@ EbcUnloadImage (
     FreePool (ThunkList);\r
     ThunkList = NextThunkList;\r
   }\r
     FreePool (ThunkList);\r
     ThunkList = NextThunkList;\r
   }\r
+\r
   //\r
   // Now remove this image list element from the chain\r
   //\r
   //\r
   // Now remove this image list element from the chain\r
   //\r
@@ -1037,14 +1211,17 @@ EbcUnloadImage (
   } else {\r
     PrevImageList->Next = ImageList->Next;\r
   }\r
   } else {\r
     PrevImageList->Next = ImageList->Next;\r
   }\r
+\r
   //\r
   // Now free up the image list element\r
   //\r
   FreePool (ImageList);\r
   //\r
   // Now free up the image list element\r
   //\r
   FreePool (ImageList);\r
+\r
+  EbcDebuggerHookEbcUnloadImage (ImageHandle);\r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Add a thunk to our list of thunks for a given image handle.\r
   Also flush the instruction cache since we've written thunk code\r
 /**\r
   Add a thunk to our list of thunks for a given image handle.\r
   Also flush the instruction cache since we've written thunk code\r
@@ -1060,9 +1237,9 @@ EbcUnloadImage (
 **/\r
 EFI_STATUS\r
 EbcAddImageThunk (\r
 **/\r
 EFI_STATUS\r
 EbcAddImageThunk (\r
-  IN EFI_HANDLE      ImageHandle,\r
-  IN VOID            *ThunkBuffer,\r
-  IN UINT32          ThunkSize\r
+  IN EFI_HANDLE  ImageHandle,\r
+  IN VOID        *ThunkBuffer,\r
+  IN UINT32      ThunkSize\r
   )\r
 {\r
   EBC_THUNK_LIST  *ThunkList;\r
   )\r
 {\r
   EBC_THUNK_LIST  *ThunkList;\r
@@ -1073,11 +1250,12 @@ EbcAddImageThunk (
   // It so far so good, then flush the instruction cache\r
   //\r
   if (mEbcICacheFlush != NULL) {\r
   // It so far so good, then flush the instruction cache\r
   //\r
   if (mEbcICacheFlush != NULL) {\r
-    Status = mEbcICacheFlush ((EFI_PHYSICAL_ADDRESS) (UINTN) ThunkBuffer, ThunkSize);\r
+    Status = mEbcICacheFlush ((EFI_PHYSICAL_ADDRESS)(UINTN)ThunkBuffer, ThunkSize);\r
     if (EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
   }\r
     if (EFI_ERROR (Status)) {\r
       return Status;\r
     }\r
   }\r
+\r
   //\r
   // Go through our list of known image handles and see if we've already\r
   // created a image list element for this image handle.\r
   //\r
   // Go through our list of known image handles and see if we've already\r
   // created a image list element for this image handle.\r
@@ -1098,11 +1276,12 @@ EbcAddImageThunk (
       return EFI_OUT_OF_RESOURCES;\r
     }\r
 \r
       return EFI_OUT_OF_RESOURCES;\r
     }\r
 \r
-    ImageList->ThunkList    = NULL;\r
-    ImageList->ImageHandle  = ImageHandle;\r
-    ImageList->Next         = mEbcImageList;\r
-    mEbcImageList           = ImageList;\r
+    ImageList->ThunkList   = NULL;\r
+    ImageList->ImageHandle = ImageHandle;\r
+    ImageList->Next        = mEbcImageList;\r
+    mEbcImageList          = ImageList;\r
   }\r
   }\r
+\r
   //\r
   // Ok, now create a new thunk element to add to the list\r
   //\r
   //\r
   // Ok, now create a new thunk element to add to the list\r
   //\r
@@ -1111,12 +1290,13 @@ EbcAddImageThunk (
   if (ThunkList == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
   if (ThunkList == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
+\r
   //\r
   // Add it to the head of the list\r
   //\r
   //\r
   // Add it to the head of the list\r
   //\r
-  ThunkList->Next         = ImageList->ThunkList;\r
-  ThunkList->ThunkBuffer  = ThunkBuffer;\r
-  ImageList->ThunkList    = ThunkList;\r
+  ThunkList->Next        = ImageList->ThunkList;\r
+  ThunkList->ThunkBuffer = ThunkBuffer;\r
+  ImageList->ThunkList   = ThunkList;\r
   return EFI_SUCCESS;\r
 }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -1133,8 +1313,8 @@ EbcAddImageThunk (
 EFI_STATUS\r
 EFIAPI\r
 EbcRegisterICacheFlush (\r
 EFI_STATUS\r
 EFIAPI\r
 EbcRegisterICacheFlush (\r
-  IN EFI_EBC_PROTOCOL   *This,\r
-  IN EBC_ICACHE_FLUSH   Flush\r
+  IN EFI_EBC_PROTOCOL  *This,\r
+  IN EBC_ICACHE_FLUSH  Flush\r
   )\r
 {\r
   mEbcICacheFlush = Flush;\r
   )\r
 {\r
   mEbcICacheFlush = Flush;\r
@@ -1155,8 +1335,8 @@ EbcRegisterICacheFlush (
 EFI_STATUS\r
 EFIAPI\r
 EbcGetVersion (\r
 EFI_STATUS\r
 EFIAPI\r
 EbcGetVersion (\r
-  IN EFI_EBC_PROTOCOL   *This,\r
-  IN OUT UINT64         *Version\r
+  IN EFI_EBC_PROTOCOL  *This,\r
+  IN OUT UINT64        *Version\r
   )\r
 {\r
   if (Version == NULL) {\r
   )\r
 {\r
   if (Version == NULL) {\r
@@ -1181,25 +1361,28 @@ EbcGetVersion (
 \r
 **/\r
 EFI_STATUS\r
 \r
 **/\r
 EFI_STATUS\r
-GetEBCStack(\r
-  IN  EFI_HANDLE Handle,\r
-  OUT VOID       **StackBuffer,\r
-  OUT UINTN      *BufferIndex\r
+GetEBCStack (\r
+  IN  EFI_HANDLE  Handle,\r
+  OUT VOID        **StackBuffer,\r
+  OUT UINTN       *BufferIndex\r
   )\r
 {\r
   )\r
 {\r
-  UINTN   Index;\r
-  EFI_TPL OldTpl;\r
-  OldTpl = gBS->RaiseTPL(TPL_HIGH_LEVEL);\r
-  for (Index = 0; Index < mStackNum; Index ++) {\r
+  UINTN    Index;\r
+  EFI_TPL  OldTpl;\r
+\r
+  OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
+  for (Index = 0; Index < mStackNum; Index++) {\r
     if (mStackBufferIndex[Index] == NULL) {\r
       mStackBufferIndex[Index] = Handle;\r
       break;\r
     }\r
   }\r
     if (mStackBufferIndex[Index] == NULL) {\r
       mStackBufferIndex[Index] = Handle;\r
       break;\r
     }\r
   }\r
-  gBS->RestoreTPL(OldTpl);\r
+\r
+  gBS->RestoreTPL (OldTpl);\r
   if (Index == mStackNum) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
   if (Index == mStackNum) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
+\r
   *BufferIndex = Index;\r
   *StackBuffer = mStackBuffer[Index];\r
   return EFI_SUCCESS;\r
   *BufferIndex = Index;\r
   *StackBuffer = mStackBuffer[Index];\r
   return EFI_SUCCESS;\r
@@ -1214,8 +1397,8 @@ GetEBCStack(
 \r
 **/\r
 EFI_STATUS\r
 \r
 **/\r
 EFI_STATUS\r
-ReturnEBCStack(\r
-  IN UINTN Index\r
+ReturnEBCStack (\r
+  IN UINTN  Index\r
   )\r
 {\r
   mStackBufferIndex[Index] = NULL;\r
   )\r
 {\r
   mStackBufferIndex[Index] = NULL;\r
@@ -1231,19 +1414,22 @@ ReturnEBCStack(
 \r
 **/\r
 EFI_STATUS\r
 \r
 **/\r
 EFI_STATUS\r
-ReturnEBCStackByHandle(\r
-  IN EFI_HANDLE Handle\r
+ReturnEBCStackByHandle (\r
+  IN EFI_HANDLE  Handle\r
   )\r
 {\r
   )\r
 {\r
-  UINTN Index;\r
-  for (Index = 0; Index < mStackNum; Index ++) {\r
+  UINTN  Index;\r
+\r
+  for (Index = 0; Index < mStackNum; Index++) {\r
     if (mStackBufferIndex[Index] == Handle) {\r
       break;\r
     }\r
   }\r
     if (mStackBufferIndex[Index] == Handle) {\r
       break;\r
     }\r
   }\r
+\r
   if (Index == mStackNum) {\r
     return EFI_NOT_FOUND;\r
   }\r
   if (Index == mStackNum) {\r
     return EFI_NOT_FOUND;\r
   }\r
+\r
   mStackBufferIndex[Index] = NULL;\r
   return EFI_SUCCESS;\r
 }\r
   mStackBufferIndex[Index] = NULL;\r
   return EFI_SUCCESS;\r
 }\r
@@ -1260,20 +1446,21 @@ InitEBCStack (
   VOID\r
   )\r
 {\r
   VOID\r
   )\r
 {\r
-  for (mStackNum = 0; mStackNum < MAX_STACK_NUM; mStackNum ++) {\r
-    mStackBuffer[mStackNum] = AllocatePool(STACK_POOL_SIZE);\r
+  for (mStackNum = 0; mStackNum < MAX_STACK_NUM; mStackNum++) {\r
+    mStackBuffer[mStackNum]      = AllocatePool (STACK_POOL_SIZE);\r
     mStackBufferIndex[mStackNum] = NULL;\r
     if (mStackBuffer[mStackNum] == NULL) {\r
       break;\r
     }\r
   }\r
     mStackBufferIndex[mStackNum] = NULL;\r
     if (mStackBuffer[mStackNum] == NULL) {\r
       break;\r
     }\r
   }\r
+\r
   if (mStackNum == 0) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
   if (mStackNum == 0) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Free all EBC stacks allocated before.\r
 \r
 /**\r
   Free all EBC stacks allocated before.\r
 \r
@@ -1281,14 +1468,16 @@ InitEBCStack (
 \r
 **/\r
 EFI_STATUS\r
 \r
 **/\r
 EFI_STATUS\r
-FreeEBCStack(\r
+FreeEBCStack (\r
   VOID\r
   )\r
 {\r
   VOID\r
   )\r
 {\r
-  UINTN Index;\r
-  for (Index = 0; Index < mStackNum; Index ++) {\r
-    FreePool(mStackBuffer[Index]);\r
+  UINTN  Index;\r
+\r
+  for (Index = 0; Index < mStackNum; Index++) {\r
+    FreePool (mStackBuffer[Index]);\r
   }\r
   }\r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -1303,12 +1492,12 @@ FreeEBCStack(
 **/\r
 EFI_STATUS\r
 InitEbcVmTestProtocol (\r
 **/\r
 EFI_STATUS\r
 InitEbcVmTestProtocol (\r
-  IN EFI_HANDLE     *IHandle\r
+  IN EFI_HANDLE  *IHandle\r
   )\r
 {\r
   )\r
 {\r
-  EFI_HANDLE Handle;\r
-  EFI_STATUS Status;\r
-  EFI_EBC_VM_TEST_PROTOCOL *EbcVmTestProtocol;\r
+  EFI_HANDLE                Handle;\r
+  EFI_STATUS                Status;\r
+  EFI_EBC_VM_TEST_PROTOCOL  *EbcVmTestProtocol;\r
 \r
   //\r
   // Allocate memory for the protocol, then fill in the fields\r
 \r
   //\r
   // Allocate memory for the protocol, then fill in the fields\r
@@ -1317,25 +1506,26 @@ InitEbcVmTestProtocol (
   if (EbcVmTestProtocol == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
   if (EbcVmTestProtocol == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
-  EbcVmTestProtocol->Execute      = (EBC_VM_TEST_EXECUTE) EbcExecuteInstructions;\r
+\r
+  EbcVmTestProtocol->Execute = (EBC_VM_TEST_EXECUTE)EbcExecuteInstructions;\r
 \r
   DEBUG_CODE_BEGIN ();\r
 \r
   DEBUG_CODE_BEGIN ();\r
-    EbcVmTestProtocol->Assemble     = (EBC_VM_TEST_ASM) EbcVmTestUnsupported;\r
-    EbcVmTestProtocol->Disassemble  = (EBC_VM_TEST_DASM) EbcVmTestUnsupported;\r
+  EbcVmTestProtocol->Assemble    = (EBC_VM_TEST_ASM)EbcVmTestUnsupported;\r
+  EbcVmTestProtocol->Disassemble = (EBC_VM_TEST_DASM)EbcVmTestUnsupported;\r
   DEBUG_CODE_END ();\r
 \r
   //\r
   // Publish the protocol\r
   //\r
   DEBUG_CODE_END ();\r
 \r
   //\r
   // Publish the protocol\r
   //\r
-  Handle  = NULL;\r
-  Status  = gBS->InstallProtocolInterface (&Handle, &mEfiEbcVmTestProtocolGuid, EFI_NATIVE_INTERFACE, EbcVmTestProtocol);\r
+  Handle = NULL;\r
+  Status = gBS->InstallProtocolInterface (&Handle, &gEfiEbcVmTestProtocolGuid, EFI_NATIVE_INTERFACE, EbcVmTestProtocol);\r
   if (EFI_ERROR (Status)) {\r
     FreePool (EbcVmTestProtocol);\r
   }\r
   if (EFI_ERROR (Status)) {\r
     FreePool (EbcVmTestProtocol);\r
   }\r
+\r
   return Status;\r
 }\r
 \r
   return Status;\r
 }\r
 \r
-\r
 /**\r
   Returns the EFI_UNSUPPORTED Status.\r
 \r
 /**\r
   Returns the EFI_UNSUPPORTED Status.\r
 \r
@@ -1343,6 +1533,7 @@ InitEbcVmTestProtocol (
 \r
 **/\r
 EFI_STATUS\r
 \r
 **/\r
 EFI_STATUS\r
+EFIAPI\r
 EbcVmTestUnsupported (\r
   VOID\r
   )\r
 EbcVmTestUnsupported (\r
   VOID\r
   )\r
@@ -1350,3 +1541,27 @@ EbcVmTestUnsupported (
   return EFI_UNSUPPORTED;\r
 }\r
 \r
   return EFI_UNSUPPORTED;\r
 }\r
 \r
+/**\r
+  Allocates a buffer of type EfiBootServicesCode.\r
+\r
+  @param  AllocationSize        The number of bytes to allocate.\r
+\r
+  @return A pointer to the allocated buffer or NULL if allocation fails.\r
+\r
+**/\r
+VOID *\r
+EFIAPI\r
+EbcAllocatePoolForThunk (\r
+  IN UINTN  AllocationSize\r
+  )\r
+{\r
+  VOID        *Buffer;\r
+  EFI_STATUS  Status;\r
+\r
+  Status = gBS->AllocatePool (EfiBootServicesCode, AllocationSize, &Buffer);\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+\r
+  return Buffer;\r
+}\r