]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/EbcDxe/EbcInt.c
MdeModulePkg/String.c: Zero memory before free (CVE-2019-14558)
[mirror_edk2.git] / MdeModulePkg / Universal / EbcDxe / EbcInt.c
index 37a2b7f6b005f9008d9c6f352ae0302079bfcad9..eced1d5c7f1e2a1639198061d375db261e4e5f45 100644 (file)
@@ -1,21 +1,16 @@
 /** @file\r
   Top level module for the EBC virtual machine implementation.\r
-  Provides auxilliary support routines for the VM. That is, routines\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, Intel Corporation\r
-All rights reserved. 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
+#include "EbcDebuggerHook.h"\r
 \r
 //\r
 // We'll keep track of all thunks we create in a linked list. Each\r
@@ -23,51 +18,111 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 // image handles, with each having a linked list of thunks allocated\r
 // to that image handle.\r
 //\r
-typedef struct _EBC_THUNK_LIST {\r
-  VOID                    *ThunkBuffer;\r
-  struct _EBC_THUNK_LIST  *Next;\r
-} EBC_THUNK_LIST;\r
-\r
-typedef struct _EBC_IMAGE_LIST {\r
-  struct _EBC_IMAGE_LIST  *Next;\r
-  EFI_HANDLE              ImageHandle;\r
-  EBC_THUNK_LIST          *ThunkList;\r
-} EBC_IMAGE_LIST;\r
-\r
-STATIC\r
+typedef struct _EBC_THUNK_LIST EBC_THUNK_LIST;\r
+struct _EBC_THUNK_LIST {\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
+  EBC_IMAGE_LIST  *Next;\r
+  EFI_HANDLE      ImageHandle;\r
+  EBC_THUNK_LIST  *ThunkList;\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
+  Typically this will include freeing any memory allocated for thunk-creation.\r
+\r
+  @param  This                  A pointer to the EFI_EBC_PROTOCOL instance.\r
+  @param  ImageHandle           Handle of image for which the thunk is being\r
+                                created.\r
+\r
+  @retval EFI_INVALID_PARAMETER The ImageHandle passed in was not found in the\r
+                                internal list of EBC image handles.\r
+  @retval EFI_SUCCESS           The function completed successfully.\r
+\r
+**/\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
-STATIC\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
+  processor-specific routine EbcCreateThunks().\r
+\r
+  @param  This                  A pointer to the EFI_EBC_PROTOCOL instance.\r
+  @param  ImageHandle           Handle of image for which the thunk is being\r
+                                created. The EBC interpreter may use this to\r
+                                keep track of any resource allocations\r
+                                performed in loading and executing the image.\r
+  @param  EbcEntryPoint         Address of the actual EBC entry point or\r
+                                protocol service the thunk should call.\r
+  @param  Thunk                 Returned pointer to a thunk created.\r
+\r
+  @retval EFI_SUCCESS           The function completed successfully.\r
+  @retval EFI_INVALID_PARAMETER Image entry point is not 2-byte aligned.\r
+  @retval EFI_OUT_OF_RESOURCES  Memory could not be allocated for the thunk.\r
+\r
+**/\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
-STATIC\r
+/**\r
+  Called to get the version of the interpreter.\r
+\r
+  @param  This                  A pointer to the EFI_EBC_PROTOCOL instance.\r
+  @param  Version               Pointer to where to store the returned version\r
+                                of the interpreter.\r
+\r
+  @retval EFI_SUCCESS           The function completed successfully.\r
+  @retval EFI_INVALID_PARAMETER Version pointer is NULL.\r
+\r
+**/\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
-STATIC\r
+/**\r
+  To install default Callback function for the VM interpreter.\r
+\r
+  @param  This                  A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL\r
+                                instance.\r
+\r
+  @retval EFI_SUCCESS           The function completed successfully.\r
+  @retval Others                Some error occurs when creating periodic event.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 InitializeEbcCallback (\r
   IN EFI_DEBUG_SUPPORT_PROTOCOL  *This\r
   );\r
 \r
-STATIC\r
+/**\r
+  The default Exception Callback for the VM interpreter.\r
+  In this function, we report status code, and print debug information\r
+  about EBC_CONTEXT, then dead loop.\r
+\r
+  @param  InterruptType          Interrupt type.\r
+  @param  SystemContext          EBC system context.\r
+\r
+**/\r
 VOID\r
 EFIAPI\r
 CommonEbcExceptionHandler (\r
@@ -75,7 +130,14 @@ CommonEbcExceptionHandler (
   IN EFI_SYSTEM_CONTEXT   SystemContext\r
   );\r
 \r
-STATIC\r
+/**\r
+  The periodic callback function for EBC VM interpreter, which is used\r
+  to support the EFI debug support protocol.\r
+\r
+  @param  Event                  The Periodic Callback Event.\r
+  @param  Context                It should be the address of VM_CONTEXT pointer.\r
+\r
+**/\r
 VOID\r
 EFIAPI\r
 EbcPeriodicNotifyFunction (\r
@@ -83,7 +145,16 @@ EbcPeriodicNotifyFunction (
   IN VOID          *Context\r
   );\r
 \r
-STATIC\r
+/**\r
+  The VM interpreter calls this function on a periodic basis to support\r
+  the EFI debug support protocol.\r
+\r
+  @param  VmPtr                  Pointer to a VM context for passing info to the\r
+                                 debugger.\r
+\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 EbcDebugPeriodic (\r
@@ -94,61 +165,153 @@ EbcDebugPeriodic (
 // 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
-STATIC\r
+/**\r
+  Produces an EBC VM test protocol that can be used for regression tests.\r
+\r
+  @param  IHandle                Handle on which to install the protocol.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES   Memory allocation failed.\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
+\r
+**/\r
 EFI_STATUS\r
 InitEbcVmTestProtocol (\r
-  IN EFI_HANDLE     *Handle\r
+  IN EFI_HANDLE     *IHandle\r
   );\r
 \r
-STATIC\r
+/**\r
+  Returns the EFI_UNSUPPORTED Status.\r
+\r
+  @return EFI_UNSUPPORTED  This function always return EFI_UNSUPPORTED status.\r
+\r
+**/\r
 EFI_STATUS\r
+EFIAPI\r
 EbcVmTestUnsupported (\r
   VOID\r
   );\r
 \r
-STATIC\r
+/**\r
+  Registers a callback function that the EBC interpreter calls to flush the\r
+  processor instruction cache following creation of thunks.\r
+\r
+  @param  This        A pointer to the EFI_EBC_PROTOCOL instance.\r
+  @param  Flush       Pointer to a function of type EBC_ICACH_FLUSH.\r
+\r
+  @retval EFI_SUCCESS The function completed successfully.\r
+\r
+**/\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
-STATIC\r
+/**\r
+  This EBC debugger protocol service is called by the debug agent\r
+\r
+  @param  This                  A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL\r
+                                instance.\r
+  @param  MaxProcessorIndex     Pointer to a caller-allocated UINTN in which the\r
+                                maximum supported processor index is returned.\r
+\r
+  @retval EFI_SUCCESS           The function completed successfully.\r
+\r
+**/\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
-STATIC\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
+  @param  This                  A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL\r
+                                instance.\r
+  @param  ProcessorIndex        Specifies which processor the callback function\r
+                                applies to.\r
+  @param  PeriodicCallback      A pointer to a function of type\r
+                                PERIODIC_CALLBACK that is the main periodic\r
+                                entry point of the debug agent. It receives as a\r
+                                parameter a pointer to the full context of the\r
+                                interrupted execution thread.\r
+\r
+  @retval EFI_SUCCESS           The function completed successfully.\r
+  @retval EFI_ALREADY_STARTED   Non-NULL PeriodicCallback parameter when a\r
+                                callback function was previously registered.\r
+  @retval EFI_INVALID_PARAMETER Null PeriodicCallback parameter when no\r
+                                callback function was previously registered.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 EbcDebugRegisterPeriodicCallback (\r
-  IN EFI_DEBUG_SUPPORT_PROTOCOL     *This,\r
-  IN UINTN                          ProcessorIndex,\r
-  IN EFI_PERIODIC_CALLBACK          PeriodicCallback\r
+  IN EFI_DEBUG_SUPPORT_PROTOCOL  *This,\r
+  IN UINTN                       ProcessorIndex,\r
+  IN EFI_PERIODIC_CALLBACK       PeriodicCallback\r
   );\r
 \r
-STATIC\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
+  @param  This                  A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL\r
+                                instance.\r
+  @param  ProcessorIndex        Specifies which processor the callback function\r
+                                applies to.\r
+  @param  ExceptionCallback     A pointer to a function of type\r
+                                EXCEPTION_CALLBACK that is called when the\r
+                                processor exception specified by ExceptionType\r
+                                occurs. Passing NULL unregisters any previously\r
+                                registered function associated with\r
+                                ExceptionType.\r
+  @param  ExceptionType         Specifies which processor exception to hook.\r
+\r
+  @retval EFI_SUCCESS           The function completed successfully.\r
+  @retval EFI_ALREADY_STARTED   Non-NULL ExceptionCallback parameter when a\r
+                                callback function was previously registered.\r
+  @retval EFI_INVALID_PARAMETER ExceptionType parameter is negative or exceeds\r
+                                MAX_EBC_EXCEPTION.\r
+  @retval EFI_INVALID_PARAMETER Null ExceptionCallback parameter when no\r
+                                callback function was previously registered.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 EbcDebugRegisterExceptionCallback (\r
-  IN EFI_DEBUG_SUPPORT_PROTOCOL     *This,\r
-  IN UINTN                          ProcessorIndex,\r
-  IN EFI_EXCEPTION_CALLBACK         ExceptionCallback,\r
-  IN EFI_EXCEPTION_TYPE             ExceptionType\r
+  IN EFI_DEBUG_SUPPORT_PROTOCOL  *This,\r
+  IN UINTN                       ProcessorIndex,\r
+  IN EFI_EXCEPTION_CALLBACK      ExceptionCallback,\r
+  IN EFI_EXCEPTION_TYPE          ExceptionType\r
   );\r
 \r
-STATIC\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
+  @param  This                  A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL\r
+                                instance.\r
+  @param  ProcessorIndex        Specifies which processor the callback function\r
+                                applies to.\r
+  @param  Start                 StartSpecifies the physical base of the memory\r
+                                range to be invalidated.\r
+  @param  Length                Specifies the minimum number of bytes in the\r
+                                processor's instruction cache to invalidate.\r
+\r
+  @retval EFI_SUCCESS           The function completed successfully.\r
+\r
+**/\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
@@ -157,30 +320,142 @@ EbcDebugInvalidateInstructionCache (
 // also be global since the execution of an EBC image does not provide\r
 // a This pointer.\r
 //\r
-static 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
-static EBC_ICACHE_FLUSH       mEbcICacheFlush;\r
+EBC_ICACHE_FLUSH       mEbcICacheFlush;\r
 \r
 //\r
 // These get set via calls by the debug agent\r
 //\r
-static EFI_PERIODIC_CALLBACK  mDebugPeriodicCallback                            = NULL;\r
-static EFI_EXCEPTION_CALLBACK mDebugExceptionCallback[MAX_EBC_EXCEPTION + 1] = {NULL};\r
-static 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
-static VOID*      mStackBuffer[MAX_STACK_NUM];\r
-static EFI_HANDLE mStackBufferIndex[MAX_STACK_NUM];\r
-static 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
-static 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
+  @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
+    return FALSE;\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 (ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION ||\r
+            ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER);\r
+  DEBUG_CODE_END ();\r
+\r
+  EbcRegisterICacheFlush (NULL,\r
+    (EBC_ICACHE_FLUSH)InvalidateInstructionCacheRange);\r
+\r
+  return EbcCreateThunk (NULL, (VOID *)(UINTN)ImageBase,\r
+           (VOID *)(UINTN)*EntryPoint, (VOID **)EntryPoint);\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
@@ -269,11 +544,11 @@ InitializeEbcDriver (
   // 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
-                    EFI_NATIVE_INTERFACE,\r
-                    EbcProtocol\r
+                    &gEfiEbcProtocolGuid, EbcProtocol,\r
+                    &gEdkiiPeCoffImageEmulatorProtocolGuid, &mPeCoffEmuProtocol,\r
+                    NULL\r
                     );\r
     if (EFI_ERROR (Status)) {\r
       FreePool (EbcProtocol);\r
@@ -330,6 +605,8 @@ InitializeEbcDriver (
     InitEbcVmTestProtocol (&ImageHandle);\r
   DEBUG_CODE_END ();\r
 \r
+  EbcDebuggerHookInit (ImageHandle, EbcDebugProtocol);\r
+\r
   return EFI_SUCCESS;\r
 \r
 ErrorExit:\r
@@ -378,19 +655,20 @@ ErrorExit:
   are very processor-specific, from here we dispatch directly to the very\r
   processor-specific routine EbcCreateThunks().\r
 \r
-  @param  This                   protocol instance pointer\r
-  @param  ImageHandle            handle to the image. The EBC interpreter may use\r
-                                 this to keep track of any resource allocations\r
-                                 performed in loading and executing the image.\r
-  @param  EbcEntryPoint          the entry point for the image (as defined in the\r
-                                 file header)\r
-  @param  Thunk                  pointer to thunk pointer where the address of the\r
-                                 created thunk is returned.\r
+  @param  This                  A pointer to the EFI_EBC_PROTOCOL instance.\r
+  @param  ImageHandle           Handle of image for which the thunk is being\r
+                                created. The EBC interpreter may use this to\r
+                                keep track of any resource allocations\r
+                                performed in loading and executing the image.\r
+  @param  EbcEntryPoint         Address of the actual EBC entry point or\r
+                                protocol service the thunk should call.\r
+  @param  Thunk                 Returned pointer to a thunk created.\r
 \r
-  @return EFI_STATUS\r
+  @retval EFI_SUCCESS           The function completed successfully.\r
+  @retval EFI_INVALID_PARAMETER Image entry point is not 2-byte aligned.\r
+  @retval EFI_OUT_OF_RESOURCES  Memory could not be allocated for the thunk.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 EbcCreateThunk (\r
@@ -415,15 +693,14 @@ EbcCreateThunk (
 /**\r
   This EBC debugger protocol service is called by the debug agent\r
 \r
-  @param  This                   pointer to the caller's debug support protocol\r
-                                 interface\r
-  @param  MaxProcessorIndex      pointer to a caller allocated UINTN in which the\r
-                                 maximum processor index is returned.\r
+  @param  This                  A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL\r
+                                instance.\r
+  @param  MaxProcessorIndex     Pointer to a caller-allocated UINTN in which the\r
+                                maximum supported processor index is returned.\r
 \r
-  @return Standard EFI_STATUS\r
+  @retval EFI_SUCCESS           The function completed successfully.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 EbcDebugGetMaximumProcessorIndex (\r
@@ -440,14 +717,23 @@ EbcDebugGetMaximumProcessorIndex (
   This protocol service is called by the debug agent to register a function\r
   for us to call on a periodic basis.\r
 \r
-  @param  This                   pointer to the caller's debug support protocol\r
-                                 interface\r
-  @param  PeriodicCallback       pointer to the function to call periodically\r
-\r
-  @return Always EFI_SUCCESS\r
+  @param  This                  A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL\r
+                                instance.\r
+  @param  ProcessorIndex        Specifies which processor the callback function\r
+                                applies to.\r
+  @param  PeriodicCallback      A pointer to a function of type\r
+                                PERIODIC_CALLBACK that is the main periodic\r
+                                entry point of the debug agent. It receives as a\r
+                                parameter a pointer to the full context of the\r
+                                interrupted execution thread.\r
+\r
+  @retval EFI_SUCCESS           The function completed successfully.\r
+  @retval EFI_ALREADY_STARTED   Non-NULL PeriodicCallback parameter when a\r
+                                callback function was previously registered.\r
+  @retval EFI_INVALID_PARAMETER Null PeriodicCallback parameter when no\r
+                                callback function was previously registered.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 EbcDebugRegisterPeriodicCallback (\r
@@ -472,14 +758,27 @@ EbcDebugRegisterPeriodicCallback (
   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
-  @param  This                   pointer to the caller's debug support protocol\r
-                                 interface\r
-  @param  ExceptionCallback      pointer to the function to the exception\r
-\r
-  @return Always EFI_SUCCESS\r
+  @param  This                  A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL\r
+                                instance.\r
+  @param  ProcessorIndex        Specifies which processor the callback function\r
+                                applies to.\r
+  @param  ExceptionCallback     A pointer to a function of type\r
+                                EXCEPTION_CALLBACK that is called when the\r
+                                processor exception specified by ExceptionType\r
+                                occurs. Passing NULL unregisters any previously\r
+                                registered function associated with\r
+                                ExceptionType.\r
+  @param  ExceptionType         Specifies which processor exception to hook.\r
+\r
+  @retval EFI_SUCCESS           The function completed successfully.\r
+  @retval EFI_ALREADY_STARTED   Non-NULL ExceptionCallback parameter when a\r
+                                callback function was previously registered.\r
+  @retval EFI_INVALID_PARAMETER ExceptionType parameter is negative or exceeds\r
+                                MAX_EBC_EXCEPTION.\r
+  @retval EFI_INVALID_PARAMETER Null ExceptionCallback parameter when no\r
+                                callback function was previously registered.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 EbcDebugRegisterExceptionCallback (\r
@@ -507,11 +806,18 @@ EbcDebugRegisterExceptionCallback (
   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
+  @param  This                  A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL\r
+                                instance.\r
+  @param  ProcessorIndex        Specifies which processor the callback function\r
+                                applies to.\r
+  @param  Start                 StartSpecifies the physical base of the memory\r
+                                range to be invalidated.\r
+  @param  Length                Specifies the minimum number of bytes in the\r
+                                processor's instruction cache to invalidate.\r
 \r
-  @return EFI_SUCCESS\r
+  @retval EFI_SUCCESS           The function completed successfully.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 EbcDebugInvalidateInstructionCache (\r
@@ -528,10 +834,12 @@ EbcDebugInvalidateInstructionCache (
 /**\r
   The VM interpreter calls this function when an exception is detected.\r
 \r
-  @param  VmPtr                  pointer to a VM context for passing info to the\r
+  @param  ExceptionType          Specifies the processor exception detected.\r
+  @param  ExceptionFlags         Specifies the exception context.\r
+  @param  VmPtr                  Pointer to a VM context for passing info to the\r
                                  EFI debugger.\r
 \r
-  @return EFI_SUCCESS if it returns at all\r
+  @retval EFI_SUCCESS            This function completed successfully.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -549,12 +857,12 @@ EbcDebugSignalException (
   // 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 (ExceptionFlags & EXCEPTION_FLAG_FATAL) {\r
+  if ((ExceptionFlags & EXCEPTION_FLAG_FATAL) != 0) {\r
     VmPtr->StopFlags |= STOPFLAG_APP_DONE;\r
   }\r
 \r
@@ -569,14 +877,14 @@ EbcDebugSignalException (
     //\r
     // Initialize the context structure\r
     //\r
-    EbcContext.R0                   = VmPtr->R[0];\r
-    EbcContext.R1                   = VmPtr->R[1];\r
-    EbcContext.R2                   = VmPtr->R[2];\r
-    EbcContext.R3                   = VmPtr->R[3];\r
-    EbcContext.R4                   = VmPtr->R[4];\r
-    EbcContext.R5                   = VmPtr->R[5];\r
-    EbcContext.R6                   = VmPtr->R[6];\r
-    EbcContext.R7                   = VmPtr->R[7];\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
@@ -586,14 +894,14 @@ EbcDebugSignalException (
     //\r
     // Restore the context structure and continue to execute\r
     //\r
-    VmPtr->R[0]  = EbcContext.R0;\r
-    VmPtr->R[1]  = EbcContext.R1;\r
-    VmPtr->R[2]  = EbcContext.R2;\r
-    VmPtr->R[3]  = EbcContext.R3;\r
-    VmPtr->R[4]  = EbcContext.R4;\r
-    VmPtr->R[5]  = EbcContext.R5;\r
-    VmPtr->R[6]  = EbcContext.R6;\r
-    VmPtr->R[7]  = EbcContext.R7;\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
@@ -605,13 +913,15 @@ EbcDebugSignalException (
 /**\r
   To install default Callback function for the VM interpreter.\r
 \r
-  @param  This                   pointer to the instance of DebugSupport protocol\r
+  @param  This                  A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL\r
+                                instance.\r
 \r
-  @return None\r
+  @retval EFI_SUCCESS           The function completed successfully.\r
+  @retval Others                Some error occurs when creating periodic event.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
+EFIAPI\r
 InitializeEbcCallback (\r
   IN EFI_DEBUG_SUPPORT_PROTOCOL  *This\r
   )\r
@@ -666,20 +976,71 @@ InitializeEbcCallback (
   @param  InterruptType          Interrupt type.\r
   @param  SystemContext          EBC system context.\r
 \r
-  @return None\r
-\r
 **/\r
-STATIC\r
 VOID\r
+EFIAPI\r
 CommonEbcExceptionHandler (\r
   IN EFI_EXCEPTION_TYPE   InterruptType,\r
   IN EFI_SYSTEM_CONTEXT   SystemContext\r
   )\r
 {\r
+  //\r
+  // We print debug information to let user know what happen.\r
+  //\r
+  DEBUG ((\r
+    EFI_D_ERROR,\r
+    "EBC Interrupter Version - 0x%016lx\n",\r
+    (UINT64) (((VM_MAJOR_VERSION & 0xFFFF) << 16) | ((VM_MINOR_VERSION & 0xFFFF)))\r
+    ));\r
+  DEBUG ((\r
+    EFI_D_ERROR,\r
+    "Exception Type - 0x%016lx\n",\r
+    (UINT64)(UINTN)InterruptType\r
+    ));\r
+  DEBUG ((\r
+    EFI_D_ERROR,\r
+    "  R0 - 0x%016lx, R1 - 0x%016lx\n",\r
+    SystemContext.SystemContextEbc->R0,\r
+    SystemContext.SystemContextEbc->R1\r
+    ));\r
+  DEBUG ((\r
+    EFI_D_ERROR,\r
+    "  R2 - 0x%016lx, R3 - 0x%016lx\n",\r
+    SystemContext.SystemContextEbc->R2,\r
+    SystemContext.SystemContextEbc->R3\r
+    ));\r
+  DEBUG ((\r
+    EFI_D_ERROR,\r
+    "  R4 - 0x%016lx, R5 - 0x%016lx\n",\r
+    SystemContext.SystemContextEbc->R4,\r
+    SystemContext.SystemContextEbc->R5\r
+    ));\r
+  DEBUG ((\r
+    EFI_D_ERROR,\r
+    "  R6 - 0x%016lx, R7 - 0x%016lx\n",\r
+    SystemContext.SystemContextEbc->R6,\r
+    SystemContext.SystemContextEbc->R7\r
+    ));\r
+  DEBUG ((\r
+    EFI_D_ERROR,\r
+    "  Flags - 0x%016lx\n",\r
+    SystemContext.SystemContextEbc->Flags\r
+    ));\r
+  DEBUG ((\r
+    EFI_D_ERROR,\r
+    "  ControlFlags - 0x%016lx\n",\r
+    SystemContext.SystemContextEbc->ControlFlags\r
+    ));\r
+  DEBUG ((\r
+    EFI_D_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
-  ASSERT (FALSE);\r
+  CpuDeadLoop ();\r
 \r
   return ;\r
 }\r
@@ -692,10 +1053,7 @@ CommonEbcExceptionHandler (
   @param  Event                  The Periodic Callback Event.\r
   @param  Context                It should be the address of VM_CONTEXT pointer.\r
 \r
-  @return None.\r
-\r
 **/\r
-STATIC\r
 VOID\r
 EFIAPI\r
 EbcPeriodicNotifyFunction (\r
@@ -719,14 +1077,14 @@ EbcPeriodicNotifyFunction (
   The VM interpreter calls this function on a periodic basis to support\r
   the EFI debug support protocol.\r
 \r
-  @param  VmPtr                  pointer to a VM context for passing info to the\r
+  @param  VmPtr                  Pointer to a VM context for passing info to the\r
                                  debugger.\r
 \r
-  @return Standard EFI status.\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
+EFIAPI\r
 EbcDebugPeriodic (\r
   IN VM_CONTEXT *VmPtr\r
   )\r
@@ -742,14 +1100,14 @@ EbcDebugPeriodic (
     //\r
     // Initialize the context structure\r
     //\r
-    EbcContext.R0                   = VmPtr->R[0];\r
-    EbcContext.R1                   = VmPtr->R[1];\r
-    EbcContext.R2                   = VmPtr->R[2];\r
-    EbcContext.R3                   = VmPtr->R[3];\r
-    EbcContext.R4                   = VmPtr->R[4];\r
-    EbcContext.R5                   = VmPtr->R[5];\r
-    EbcContext.R6                   = VmPtr->R[6];\r
-    EbcContext.R7                   = VmPtr->R[7];\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
@@ -760,14 +1118,14 @@ EbcDebugPeriodic (
     //\r
     // Restore the context structure and continue to execute\r
     //\r
-    VmPtr->R[0]  = EbcContext.R0;\r
-    VmPtr->R[1]  = EbcContext.R1;\r
-    VmPtr->R[2]  = EbcContext.R2;\r
-    VmPtr->R[3]  = EbcContext.R3;\r
-    VmPtr->R[4]  = EbcContext.R4;\r
-    VmPtr->R[5]  = EbcContext.R5;\r
-    VmPtr->R[6]  = EbcContext.R6;\r
-    VmPtr->R[7]  = EbcContext.R7;\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
@@ -781,15 +1139,15 @@ EbcDebugPeriodic (
   memory. Basically we now have the opportunity to do any necessary cleanup.\r
   Typically this will include freeing any memory allocated for thunk-creation.\r
 \r
-  @param  This                   protocol instance pointer\r
-  @param  ImageHandle            handle to the image being unloaded.\r
+  @param  This                  A pointer to the EFI_EBC_PROTOCOL instance.\r
+  @param  ImageHandle           Handle of image for which the thunk is being\r
+                                created.\r
 \r
-  @retval EFI_INVALID_PARAMETER  the ImageHandle passed in was not found in the\r
-                                 internal list of EBC image handles.\r
-  @retval EFI_STATUS             completed successfully\r
+  @retval EFI_INVALID_PARAMETER The ImageHandle passed in was not found in the\r
+                                internal list of EBC image handles.\r
+  @retval EFI_SUCCESS           The function completed successfully.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 EbcUnloadImage (\r
@@ -846,6 +1204,9 @@ EbcUnloadImage (
   // Now free up the image list element\r
   //\r
   FreePool (ImageList);\r
+\r
+  EbcDebuggerHookEbcUnloadImage (ImageHandle);\r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -855,12 +1216,12 @@ EbcUnloadImage (
   Also flush the instruction cache since we've written thunk code\r
   to memory that will be executed eventually.\r
 \r
-  @param  ImageHandle            the image handle to which the thunk is tied\r
-  @param  ThunkBuffer            the buffer we've created/allocated\r
-  @param  ThunkSize              the size of the thunk memory allocated\r
+  @param  ImageHandle            The image handle to which the thunk is tied.\r
+  @param  ThunkBuffer            The buffer that has been created/allocated.\r
+  @param  ThunkSize              The size of the thunk memory allocated.\r
 \r
-  @retval EFI_OUT_OF_RESOURCES   memory allocation failed\r
-  @retval EFI_SUCCESS            successful completion\r
+  @retval EFI_OUT_OF_RESOURCES   Memory allocation failed.\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -925,7 +1286,16 @@ EbcAddImageThunk (
   return EFI_SUCCESS;\r
 }\r
 \r
-STATIC\r
+/**\r
+  Registers a callback function that the EBC interpreter calls to flush the\r
+  processor instruction cache following creation of thunks.\r
+\r
+  @param  This        A pointer to the EFI_EBC_PROTOCOL instance.\r
+  @param  Flush       Pointer to a function of type EBC_ICACH_FLUSH.\r
+\r
+  @retval EFI_SUCCESS The function completed successfully.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 EbcRegisterICacheFlush (\r
@@ -937,7 +1307,17 @@ EbcRegisterICacheFlush (
   return EFI_SUCCESS;\r
 }\r
 \r
-STATIC\r
+/**\r
+  Called to get the version of the interpreter.\r
+\r
+  @param  This                  A pointer to the EFI_EBC_PROTOCOL instance.\r
+  @param  Version               Pointer to where to store the returned version\r
+                                of the interpreter.\r
+\r
+  @retval EFI_SUCCESS           The function completed successfully.\r
+  @retval EFI_INVALID_PARAMETER Version pointer is NULL.\r
+\r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 EbcGetVersion (\r
@@ -953,11 +1333,24 @@ EbcGetVersion (
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Returns the stack index and buffer assosicated with the Handle parameter.\r
+\r
+  @param  Handle                The EFI handle as the index to the EBC stack.\r
+  @param  StackBuffer           A pointer to hold the returned stack buffer.\r
+  @param  BufferIndex           A pointer to hold the returned stack index.\r
+\r
+  @retval EFI_OUT_OF_RESOURCES  The Handle parameter does not correspond to any\r
+                                existing EBC stack.\r
+  @retval EFI_SUCCESS           The stack index and buffer were found and\r
+                                returned to the caller.\r
+\r
+**/\r
 EFI_STATUS\r
 GetEBCStack(\r
-  EFI_HANDLE Handle,\r
-  VOID       **StackBuffer,\r
-  UINTN      *BufferIndex\r
+  IN  EFI_HANDLE Handle,\r
+  OUT VOID       **StackBuffer,\r
+  OUT UINTN      *BufferIndex\r
   )\r
 {\r
   UINTN   Index;\r
@@ -978,18 +1371,34 @@ GetEBCStack(
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Returns from the EBC stack by stack Index.\r
+\r
+  @param  Index        Specifies which EBC stack to return from.\r
+\r
+  @retval EFI_SUCCESS  The function completed successfully.\r
+\r
+**/\r
 EFI_STATUS\r
 ReturnEBCStack(\r
-  UINTN Index\r
+  IN UINTN Index\r
   )\r
 {\r
-  mStackBufferIndex[Index] =NULL;\r
+  mStackBufferIndex[Index] = NULL;\r
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Returns from the EBC stack associated with the Handle parameter.\r
+\r
+  @param  Handle      Specifies the EFI handle to find the EBC stack with.\r
+\r
+  @retval EFI_SUCCESS The function completed successfully.\r
+\r
+**/\r
 EFI_STATUS\r
 ReturnEBCStackByHandle(\r
-  EFI_HANDLE Handle\r
+  IN EFI_HANDLE Handle\r
   )\r
 {\r
   UINTN Index;\r
@@ -1005,6 +1414,13 @@ ReturnEBCStackByHandle(
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Allocates memory to hold all the EBC stacks.\r
+\r
+  @retval EFI_SUCCESS          The EBC stacks were allocated successfully.\r
+  @retval EFI_OUT_OF_RESOURCES Not enough memory available for EBC stacks.\r
+\r
+**/\r
 EFI_STATUS\r
 InitEBCStack (\r
   VOID\r
@@ -1023,6 +1439,13 @@ InitEBCStack (
   return EFI_SUCCESS;\r
 }\r
 \r
+\r
+/**\r
+  Free all EBC stacks allocated before.\r
+\r
+  @retval EFI_SUCCESS   All the EBC stacks were freed.\r
+\r
+**/\r
 EFI_STATUS\r
 FreeEBCStack(\r
   VOID\r
@@ -1036,15 +1459,14 @@ FreeEBCStack(
 }\r
 \r
 /**\r
-  Produce an EBC VM test protocol that can be used for regression tests.\r
+  Produces an EBC VM test protocol that can be used for regression tests.\r
 \r
-  @param  IHandle                handle on which to install the protocol.\r
+  @param  IHandle                Handle on which to install the protocol.\r
 \r
-  @retval EFI_OUT_OF_RESOURCES   memory allocation failed\r
-  @retval EFI_SUCCESS            successful completion\r
+  @retval EFI_OUT_OF_RESOURCES   Memory allocation failed.\r
+  @retval EFI_SUCCESS            The function completed successfully.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 InitEbcVmTestProtocol (\r
   IN EFI_HANDLE     *IHandle\r
@@ -1072,16 +1494,49 @@ InitEbcVmTestProtocol (
   // Publish the protocol\r
   //\r
   Handle  = NULL;\r
-  Status  = gBS->InstallProtocolInterface (&Handle, &mEfiEbcVmTestProtocolGuid, EFI_NATIVE_INTERFACE, EbcVmTestProtocol);\r
+  Status  = gBS->InstallProtocolInterface (&Handle, &gEfiEbcVmTestProtocolGuid, EFI_NATIVE_INTERFACE, EbcVmTestProtocol);\r
   if (EFI_ERROR (Status)) {\r
     FreePool (EbcVmTestProtocol);\r
   }\r
   return Status;\r
 }\r
-STATIC\r
+\r
+\r
+/**\r
+  Returns the EFI_UNSUPPORTED Status.\r
+\r
+  @return EFI_UNSUPPORTED  This function always return EFI_UNSUPPORTED status.\r
+\r
+**/\r
 EFI_STATUS\r
-EbcVmTestUnsupported ()\r
+EFIAPI\r
+EbcVmTestUnsupported (\r
+  VOID\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
+  return Buffer;\r
+}\r