3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Top level module for the EBC virtual machine implementation.
19 Provides auxilliary support routines for the VM. That is, routines
20 that are not particularly related to VM execution of EBC instructions.
25 #include "EbcExecute.h"
28 // We'll keep track of all thunks we create in a linked list. Each
29 // thunk is tied to an image handle, so we have a linked list of
30 // image handles, with each having a linked list of thunks allocated
31 // to that image handle.
33 typedef struct _EBC_THUNK_LIST
{
35 struct _EBC_THUNK_LIST
*Next
;
38 typedef struct _EBC_IMAGE_LIST
{
39 struct _EBC_IMAGE_LIST
*Next
;
40 EFI_HANDLE ImageHandle
;
41 EBC_THUNK_LIST
*ThunkList
;
48 IN EFI_EBC_PROTOCOL
*This
,
49 IN EFI_HANDLE ImageHandle
56 IN EFI_EBC_PROTOCOL
*This
,
57 IN EFI_HANDLE ImageHandle
,
58 IN VOID
*EbcEntryPoint
,
66 IN EFI_EBC_PROTOCOL
*This
,
67 IN OUT UINT64
*Version
73 InitializeEbcCallback (
74 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
80 CommonEbcExceptionHandler (
81 IN EFI_EXCEPTION_TYPE InterruptType
,
82 IN EFI_SYSTEM_CONTEXT SystemContext
88 EbcPeriodicNotifyFunction (
101 // These two functions and the GUID are used to produce an EBC test protocol.
102 // This functionality is definitely not required for execution.
106 InitEbcVmTestProtocol (
107 IN EFI_HANDLE
*Handle
112 EbcVmTestUnsupported (
119 EbcRegisterICacheFlush (
120 IN EFI_EBC_PROTOCOL
*This
,
121 IN EBC_ICACHE_FLUSH Flush
127 EbcDebugGetMaximumProcessorIndex (
128 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
129 OUT UINTN
*MaxProcessorIndex
135 EbcDebugRegisterPeriodicCallback (
136 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
137 IN UINTN ProcessorIndex
,
138 IN EFI_PERIODIC_CALLBACK PeriodicCallback
144 EbcDebugRegisterExceptionCallback (
145 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
146 IN UINTN ProcessorIndex
,
147 IN EFI_EXCEPTION_CALLBACK ExceptionCallback
,
148 IN EFI_EXCEPTION_TYPE ExceptionType
154 EbcDebugInvalidateInstructionCache (
155 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
156 IN UINTN ProcessorIndex
,
162 // We have one linked list of image handles for the whole world. Since
163 // there should only be one interpreter, make them global. They must
164 // also be global since the execution of an EBC image does not provide
167 static EBC_IMAGE_LIST
*mEbcImageList
= NULL
;
170 // Callback function to flush the icache after thunk creation
172 static EBC_ICACHE_FLUSH mEbcICacheFlush
;
175 // These get set via calls by the debug agent
177 static EFI_PERIODIC_CALLBACK mDebugPeriodicCallback
= NULL
;
178 static EFI_EXCEPTION_CALLBACK mDebugExceptionCallback
[MAX_EBC_EXCEPTION
+ 1] = {NULL
};
179 static EFI_GUID mEfiEbcVmTestProtocolGuid
= EFI_EBC_VM_TEST_PROTOCOL_GUID
;
182 // Event for Periodic callback
184 static EFI_EVENT mEbcPeriodicEvent
;
185 VM_CONTEXT
*mVmPtr
= NULL
;
189 InitializeEbcDriver (
190 IN EFI_HANDLE ImageHandle
,
191 IN EFI_SYSTEM_TABLE
*SystemTable
197 Initializes the VM EFI interface. Allocates memory for the VM interface
198 and registers the VM protocol.
202 ImageHandle - EFI image handle.
203 SystemTable - Pointer to the EFI system table.
206 Standard EFI status code.
210 EFI_EBC_PROTOCOL
*EbcProtocol
;
211 EFI_EBC_PROTOCOL
*OldEbcProtocol
;
213 EFI_DEBUG_SUPPORT_PROTOCOL
*EbcDebugProtocol
;
214 EFI_HANDLE
*HandleBuffer
;
220 EbcDebugProtocol
= NULL
;
223 // Allocate memory for our protocol. Then fill in the blanks.
225 Status
= gBS
->AllocatePool (
227 sizeof (EFI_EBC_PROTOCOL
),
228 (VOID
**) &EbcProtocol
230 if (Status
!= EFI_SUCCESS
) {
231 return EFI_OUT_OF_RESOURCES
;
234 EbcProtocol
->CreateThunk
= EbcCreateThunk
;
235 EbcProtocol
->UnloadImage
= EbcUnloadImage
;
236 EbcProtocol
->RegisterICacheFlush
= EbcRegisterICacheFlush
;
237 EbcProtocol
->GetVersion
= EbcGetVersion
;
238 mEbcICacheFlush
= NULL
;
241 // Find any already-installed EBC protocols and uninstall them
245 Status
= gBS
->LocateHandleBuffer (
247 &gEfiEbcProtocolGuid
,
252 if (Status
== EFI_SUCCESS
) {
254 // Loop through the handles
256 for (Index
= 0; Index
< NumHandles
; Index
++) {
257 Status
= gBS
->HandleProtocol (
259 &gEfiEbcProtocolGuid
,
260 (VOID
**) &OldEbcProtocol
262 if (Status
== EFI_SUCCESS
) {
263 if (gBS
->ReinstallProtocolInterface (
265 &gEfiEbcProtocolGuid
,
275 if (HandleBuffer
!= NULL
) {
276 gBS
->FreePool (HandleBuffer
);
280 // Add the protocol so someone can locate us if we haven't already.
283 Status
= gBS
->InstallProtocolInterface (
285 &gEfiEbcProtocolGuid
,
286 EFI_NATIVE_INTERFACE
,
289 if (EFI_ERROR (Status
)) {
290 gBS
->FreePool (EbcProtocol
);
295 // Allocate memory for our debug protocol. Then fill in the blanks.
297 Status
= gBS
->AllocatePool (
299 sizeof (EFI_DEBUG_SUPPORT_PROTOCOL
),
300 (VOID
**) &EbcDebugProtocol
302 if (Status
!= EFI_SUCCESS
) {
306 EbcDebugProtocol
->Isa
= IsaEbc
;
307 EbcDebugProtocol
->GetMaximumProcessorIndex
= EbcDebugGetMaximumProcessorIndex
;
308 EbcDebugProtocol
->RegisterPeriodicCallback
= EbcDebugRegisterPeriodicCallback
;
309 EbcDebugProtocol
->RegisterExceptionCallback
= EbcDebugRegisterExceptionCallback
;
310 EbcDebugProtocol
->InvalidateInstructionCache
= EbcDebugInvalidateInstructionCache
;
313 // Add the protocol so the debug agent can find us
315 Status
= gBS
->InstallProtocolInterface (
317 &gEfiDebugSupportProtocolGuid
,
318 EFI_NATIVE_INTERFACE
,
322 // This is recoverable, so free the memory and continue.
324 if (EFI_ERROR (Status
)) {
325 gBS
->FreePool (EbcDebugProtocol
);
329 // Install EbcDebugSupport Protocol Successfully
330 // Now we need to initialize the Ebc default Callback
332 Status
= InitializeEbcCallback (EbcDebugProtocol
);
335 // Produce a VM test interface protocol. Not required for execution.
338 InitEbcVmTestProtocol (&ImageHandle
);
345 Status
= gBS
->LocateHandleBuffer (
347 &gEfiEbcProtocolGuid
,
352 if (Status
== EFI_SUCCESS
) {
354 // Loop through the handles
356 for (Index
= 0; Index
< NumHandles
; Index
++) {
357 Status
= gBS
->HandleProtocol (
359 &gEfiEbcProtocolGuid
,
360 (VOID
**) &OldEbcProtocol
362 if (Status
== EFI_SUCCESS
) {
363 gBS
->UninstallProtocolInterface (
365 &gEfiEbcProtocolGuid
,
372 if (HandleBuffer
!= NULL
) {
373 gBS
->FreePool (HandleBuffer
);
377 gBS
->FreePool (EbcProtocol
);
386 IN EFI_EBC_PROTOCOL
*This
,
387 IN EFI_HANDLE ImageHandle
,
388 IN VOID
*EbcEntryPoint
,
395 This is the top-level routine plugged into the EBC protocol. Since thunks
396 are very processor-specific, from here we dispatch directly to the very
397 processor-specific routine EbcCreateThunks().
401 This - protocol instance pointer
402 ImageHandle - handle to the image. The EBC interpreter may use this to keep
403 track of any resource allocations performed in loading and
405 EbcEntryPoint - the entry point for the image (as defined in the file header)
406 Thunk - pointer to thunk pointer where the address of the created
417 Status
= EbcCreateThunks (
421 FLAG_THUNK_ENTRY_POINT
429 EbcDebugGetMaximumProcessorIndex (
430 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
431 OUT UINTN
*MaxProcessorIndex
437 This EBC debugger protocol service is called by the debug agent
441 This - pointer to the caller's debug support protocol interface
442 MaxProcessorIndex - pointer to a caller allocated UINTN in which the maximum
443 processor index is returned.
451 *MaxProcessorIndex
= 0;
458 EbcDebugRegisterPeriodicCallback (
459 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
460 IN UINTN ProcessorIndex
,
461 IN EFI_PERIODIC_CALLBACK PeriodicCallback
467 This protocol service is called by the debug agent to register a function
468 for us to call on a periodic basis.
473 This - pointer to the caller's debug support protocol interface
474 PeriodicCallback - pointer to the function to call periodically
482 if ((mDebugPeriodicCallback
== NULL
) && (PeriodicCallback
== NULL
)) {
483 return EFI_INVALID_PARAMETER
;
485 if ((mDebugPeriodicCallback
!= NULL
) && (PeriodicCallback
!= NULL
)) {
486 return EFI_ALREADY_STARTED
;
489 mDebugPeriodicCallback
= PeriodicCallback
;
496 EbcDebugRegisterExceptionCallback (
497 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
498 IN UINTN ProcessorIndex
,
499 IN EFI_EXCEPTION_CALLBACK ExceptionCallback
,
500 IN EFI_EXCEPTION_TYPE ExceptionType
506 This protocol service is called by the debug agent to register a function
507 for us to call when we detect an exception.
512 This - pointer to the caller's debug support protocol interface
513 PeriodicCallback - pointer to the function to call periodically
521 if ((ExceptionType
< 0) || (ExceptionType
> MAX_EBC_EXCEPTION
)) {
522 return EFI_INVALID_PARAMETER
;
524 if ((mDebugExceptionCallback
[ExceptionType
] == NULL
) && (ExceptionCallback
== NULL
)) {
525 return EFI_INVALID_PARAMETER
;
527 if ((mDebugExceptionCallback
[ExceptionType
] != NULL
) && (ExceptionCallback
!= NULL
)) {
528 return EFI_ALREADY_STARTED
;
530 mDebugExceptionCallback
[ExceptionType
] = ExceptionCallback
;
537 EbcDebugInvalidateInstructionCache (
538 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
539 IN UINTN ProcessorIndex
,
547 This EBC debugger protocol service is called by the debug agent. Required
548 for DebugSupport compliance but is only stubbed out for EBC.
562 EbcDebugSignalException (
563 IN EFI_EXCEPTION_TYPE ExceptionType
,
564 IN EXCEPTION_FLAGS ExceptionFlags
,
571 The VM interpreter calls this function when an exception is detected.
575 VmPtr - pointer to a VM context for passing info to the EFI debugger.
579 EFI_SUCCESS if it returns at all
583 EFI_SYSTEM_CONTEXT_EBC EbcContext
;
584 EFI_SYSTEM_CONTEXT SystemContext
;
586 ASSERT ((ExceptionType
>= 0) && (ExceptionType
<= MAX_EBC_EXCEPTION
));
588 // Save the exception in the context passed in
590 VmPtr
->ExceptionFlags
|= ExceptionFlags
;
591 VmPtr
->LastException
= ExceptionType
;
593 // If it's a fatal exception, then flag it in the VM context in case an
594 // attached debugger tries to return from it.
596 if (ExceptionFlags
& EXCEPTION_FLAG_FATAL
) {
597 VmPtr
->StopFlags
|= STOPFLAG_APP_DONE
;
601 // If someone's registered for exception callbacks, then call them.
603 // EBC driver will register default exception callback to report the
604 // status code via the status code API
606 if (mDebugExceptionCallback
[ExceptionType
] != NULL
) {
609 // Initialize the context structure
611 EbcContext
.R0
= VmPtr
->R
[0];
612 EbcContext
.R1
= VmPtr
->R
[1];
613 EbcContext
.R2
= VmPtr
->R
[2];
614 EbcContext
.R3
= VmPtr
->R
[3];
615 EbcContext
.R4
= VmPtr
->R
[4];
616 EbcContext
.R5
= VmPtr
->R
[5];
617 EbcContext
.R6
= VmPtr
->R
[6];
618 EbcContext
.R7
= VmPtr
->R
[7];
619 EbcContext
.Ip
= (UINT64
)(UINTN
)VmPtr
->Ip
;
620 EbcContext
.Flags
= VmPtr
->Flags
;
621 EbcContext
.ControlFlags
= 0;
622 SystemContext
.SystemContextEbc
= &EbcContext
;
624 mDebugExceptionCallback
[ExceptionType
] (ExceptionType
, SystemContext
);
626 // Restore the context structure and continue to execute
628 VmPtr
->R
[0] = EbcContext
.R0
;
629 VmPtr
->R
[1] = EbcContext
.R1
;
630 VmPtr
->R
[2] = EbcContext
.R2
;
631 VmPtr
->R
[3] = EbcContext
.R3
;
632 VmPtr
->R
[4] = EbcContext
.R4
;
633 VmPtr
->R
[5] = EbcContext
.R5
;
634 VmPtr
->R
[6] = EbcContext
.R6
;
635 VmPtr
->R
[7] = EbcContext
.R7
;
636 VmPtr
->Ip
= (VMIP
)(UINTN
)EbcContext
.Ip
;
637 VmPtr
->Flags
= EbcContext
.Flags
;
645 InitializeEbcCallback (
646 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
652 To install default Callback function for the VM interpreter.
656 This - pointer to the instance of DebugSupport protocol
668 // For ExceptionCallback
670 for (Index
= 0; Index
<= MAX_EBC_EXCEPTION
; Index
++) {
671 EbcDebugRegisterExceptionCallback (
674 CommonEbcExceptionHandler
,
680 // For PeriodicCallback
682 Status
= gBS
->CreateEvent (
683 EFI_EVENT_TIMER
| EFI_EVENT_NOTIFY_SIGNAL
,
685 EbcPeriodicNotifyFunction
,
689 if (EFI_ERROR(Status
)) {
693 Status
= gBS
->SetTimer (
696 EBC_VM_PERIODIC_CALLBACK_RATE
698 if (EFI_ERROR(Status
)) {
707 CommonEbcExceptionHandler (
708 IN EFI_EXCEPTION_TYPE InterruptType
,
709 IN EFI_SYSTEM_CONTEXT SystemContext
715 The default Exception Callback for the VM interpreter.
716 In this function, we report status code, and print debug information
717 about EBC_CONTEXT, then dead loop.
721 InterruptType - Interrupt type.
722 SystemContext - EBC system context.
731 // We deadloop here to make it easy to debug this issue.
741 EbcPeriodicNotifyFunction (
749 The periodic callback function for EBC VM interpreter, which is used
750 to support the EFI debug support protocol.
754 Event - The Periodic Callback Event.
755 Context - It should be the address of VM_CONTEXT pointer.
765 VmPtr
= *(VM_CONTEXT
**)Context
;
768 EbcDebugPeriodic (VmPtr
);
783 The VM interpreter calls this function on a periodic basis to support
784 the EFI debug support protocol.
788 VmPtr - pointer to a VM context for passing info to the debugger.
796 EFI_SYSTEM_CONTEXT_EBC EbcContext
;
797 EFI_SYSTEM_CONTEXT SystemContext
;
800 // If someone's registered for periodic callbacks, then call them.
802 if (mDebugPeriodicCallback
!= NULL
) {
805 // Initialize the context structure
807 EbcContext
.R0
= VmPtr
->R
[0];
808 EbcContext
.R1
= VmPtr
->R
[1];
809 EbcContext
.R2
= VmPtr
->R
[2];
810 EbcContext
.R3
= VmPtr
->R
[3];
811 EbcContext
.R4
= VmPtr
->R
[4];
812 EbcContext
.R5
= VmPtr
->R
[5];
813 EbcContext
.R6
= VmPtr
->R
[6];
814 EbcContext
.R7
= VmPtr
->R
[7];
815 EbcContext
.Ip
= (UINT64
)(UINTN
)VmPtr
->Ip
;
816 EbcContext
.Flags
= VmPtr
->Flags
;
817 EbcContext
.ControlFlags
= 0;
818 SystemContext
.SystemContextEbc
= &EbcContext
;
820 mDebugPeriodicCallback (SystemContext
);
823 // Restore the context structure and continue to execute
825 VmPtr
->R
[0] = EbcContext
.R0
;
826 VmPtr
->R
[1] = EbcContext
.R1
;
827 VmPtr
->R
[2] = EbcContext
.R2
;
828 VmPtr
->R
[3] = EbcContext
.R3
;
829 VmPtr
->R
[4] = EbcContext
.R4
;
830 VmPtr
->R
[5] = EbcContext
.R5
;
831 VmPtr
->R
[6] = EbcContext
.R6
;
832 VmPtr
->R
[7] = EbcContext
.R7
;
833 VmPtr
->Ip
= (VMIP
)(UINTN
)EbcContext
.Ip
;
834 VmPtr
->Flags
= EbcContext
.Flags
;
844 IN EFI_EBC_PROTOCOL
*This
,
845 IN EFI_HANDLE ImageHandle
851 This routine is called by the core when an image is being unloaded from
852 memory. Basically we now have the opportunity to do any necessary cleanup.
853 Typically this will include freeing any memory allocated for thunk-creation.
857 This - protocol instance pointer
858 ImageHandle - handle to the image being unloaded.
862 EFI_INVALID_PARAMETER - the ImageHandle passed in was not found in
863 the internal list of EBC image handles.
864 EFI_STATUS - completed successfully
868 EBC_THUNK_LIST
*ThunkList
;
869 EBC_THUNK_LIST
*NextThunkList
;
870 EBC_IMAGE_LIST
*ImageList
;
871 EBC_IMAGE_LIST
*PrevImageList
;
873 // First go through our list of known image handles and see if we've already
874 // created an image list element for this image handle.
876 PrevImageList
= NULL
;
877 for (ImageList
= mEbcImageList
; ImageList
!= NULL
; ImageList
= ImageList
->Next
) {
878 if (ImageList
->ImageHandle
== ImageHandle
) {
882 // Save the previous so we can connect the lists when we remove this one
884 PrevImageList
= ImageList
;
887 if (ImageList
== NULL
) {
888 return EFI_INVALID_PARAMETER
;
891 // Free up all the thunk buffers and thunks list elements for this image
894 ThunkList
= ImageList
->ThunkList
;
895 while (ThunkList
!= NULL
) {
896 NextThunkList
= ThunkList
->Next
;
897 gBS
->FreePool (ThunkList
->ThunkBuffer
);
898 gBS
->FreePool (ThunkList
);
899 ThunkList
= NextThunkList
;
902 // Now remove this image list element from the chain
904 if (PrevImageList
== NULL
) {
908 mEbcImageList
= ImageList
->Next
;
910 PrevImageList
->Next
= ImageList
->Next
;
913 // Now free up the image list element
915 gBS
->FreePool (ImageList
);
921 IN EFI_HANDLE ImageHandle
,
922 IN VOID
*ThunkBuffer
,
929 Add a thunk to our list of thunks for a given image handle.
930 Also flush the instruction cache since we've written thunk code
931 to memory that will be executed eventually.
935 ImageHandle - the image handle to which the thunk is tied
936 ThunkBuffer - the buffer we've created/allocated
937 ThunkSize - the size of the thunk memory allocated
941 EFI_OUT_OF_RESOURCES - memory allocation failed
942 EFI_SUCCESS - successful completion
946 EBC_THUNK_LIST
*ThunkList
;
947 EBC_IMAGE_LIST
*ImageList
;
951 // It so far so good, then flush the instruction cache
953 if (mEbcICacheFlush
!= NULL
) {
954 Status
= mEbcICacheFlush ((EFI_PHYSICAL_ADDRESS
) (UINTN
) ThunkBuffer
, ThunkSize
);
955 if (EFI_ERROR (Status
)) {
960 // Go through our list of known image handles and see if we've already
961 // created a image list element for this image handle.
963 for (ImageList
= mEbcImageList
; ImageList
!= NULL
; ImageList
= ImageList
->Next
) {
964 if (ImageList
->ImageHandle
== ImageHandle
) {
969 if (ImageList
== NULL
) {
971 // Allocate a new one
973 Status
= gBS
->AllocatePool (
975 sizeof (EBC_IMAGE_LIST
),
978 if (Status
!= EFI_SUCCESS
) {
979 return EFI_OUT_OF_RESOURCES
;
982 ImageList
->ThunkList
= NULL
;
983 ImageList
->ImageHandle
= ImageHandle
;
984 ImageList
->Next
= mEbcImageList
;
985 mEbcImageList
= ImageList
;
988 // Ok, now create a new thunk element to add to the list
990 Status
= gBS
->AllocatePool (
992 sizeof (EBC_THUNK_LIST
),
995 if (Status
!= EFI_SUCCESS
) {
996 return EFI_OUT_OF_RESOURCES
;
999 // Add it to the head of the list
1001 ThunkList
->Next
= ImageList
->ThunkList
;
1002 ThunkList
->ThunkBuffer
= ThunkBuffer
;
1003 ImageList
->ThunkList
= ThunkList
;
1010 EbcRegisterICacheFlush (
1011 IN EFI_EBC_PROTOCOL
*This
,
1012 IN EBC_ICACHE_FLUSH Flush
1015 mEbcICacheFlush
= Flush
;
1023 IN EFI_EBC_PROTOCOL
*This
,
1024 IN OUT UINT64
*Version
1027 if (Version
== NULL
) {
1028 return EFI_INVALID_PARAMETER
;
1031 *Version
= GetVmVersion ();
1037 InitEbcVmTestProtocol (
1038 IN EFI_HANDLE
*IHandle
1042 Routine Description:
1044 Produce an EBC VM test protocol that can be used for regression tests.
1048 IHandle - handle on which to install the protocol.
1052 EFI_OUT_OF_RESOURCES - memory allocation failed
1053 EFI_SUCCESS - successful completion
1059 EFI_EBC_VM_TEST_PROTOCOL
*EbcVmTestProtocol
;
1062 // Allocate memory for the protocol, then fill in the fields
1064 Status
= gBS
->AllocatePool (EfiBootServicesData
, sizeof (EFI_EBC_VM_TEST_PROTOCOL
), (VOID
**) &EbcVmTestProtocol
);
1065 if (Status
!= EFI_SUCCESS
) {
1066 return EFI_OUT_OF_RESOURCES
;
1068 EbcVmTestProtocol
->Execute
= (EBC_VM_TEST_EXECUTE
) EbcExecuteInstructions
;
1070 DEBUG_CODE_BEGIN ();
1071 EbcVmTestProtocol
->Assemble
= (EBC_VM_TEST_ASM
) EbcVmTestUnsupported
;
1072 EbcVmTestProtocol
->Disassemble
= (EBC_VM_TEST_DASM
) EbcVmTestUnsupported
;
1076 // Publish the protocol
1079 Status
= gBS
->InstallProtocolInterface (&Handle
, &mEfiEbcVmTestProtocolGuid
, EFI_NATIVE_INTERFACE
, EbcVmTestProtocol
);
1080 if (EFI_ERROR (Status
)) {
1081 gBS
->FreePool (EbcVmTestProtocol
);
1087 EbcVmTestUnsupported ()
1089 return EFI_UNSUPPORTED
;