2 Top level module for the EBC virtual machine implementation.
3 Provides auxiliary support routines for the VM. That is, routines
4 that are not particularly related to VM execution of EBC instructions.
6 Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include "EbcExecute.h"
21 // We'll keep track of all thunks we create in a linked list. Each
22 // thunk is tied to an image handle, so we have a linked list of
23 // image handles, with each having a linked list of thunks allocated
24 // to that image handle.
26 typedef struct _EBC_THUNK_LIST EBC_THUNK_LIST
;
27 struct _EBC_THUNK_LIST
{
32 typedef struct _EBC_IMAGE_LIST EBC_IMAGE_LIST
;
33 struct _EBC_IMAGE_LIST
{
35 EFI_HANDLE ImageHandle
;
36 EBC_THUNK_LIST
*ThunkList
;
40 This routine is called by the core when an image is being unloaded from
41 memory. Basically we now have the opportunity to do any necessary cleanup.
42 Typically this will include freeing any memory allocated for thunk-creation.
44 @param This A pointer to the EFI_EBC_PROTOCOL instance.
45 @param ImageHandle Handle of image for which the thunk is being
48 @retval EFI_INVALID_PARAMETER The ImageHandle passed in was not found in the
49 internal list of EBC image handles.
50 @retval EFI_SUCCESS The function completed successfully.
56 IN EFI_EBC_PROTOCOL
*This
,
57 IN EFI_HANDLE ImageHandle
61 This is the top-level routine plugged into the EBC protocol. Since thunks
62 are very processor-specific, from here we dispatch directly to the very
63 processor-specific routine EbcCreateThunks().
65 @param This A pointer to the EFI_EBC_PROTOCOL instance.
66 @param ImageHandle Handle of image for which the thunk is being
67 created. The EBC interpreter may use this to
68 keep track of any resource allocations
69 performed in loading and executing the image.
70 @param EbcEntryPoint Address of the actual EBC entry point or
71 protocol service the thunk should call.
72 @param Thunk Returned pointer to a thunk created.
74 @retval EFI_SUCCESS The function completed successfully.
75 @retval EFI_INVALID_PARAMETER Image entry point is not 2-byte aligned.
76 @retval EFI_OUT_OF_RESOURCES Memory could not be allocated for the thunk.
82 IN EFI_EBC_PROTOCOL
*This
,
83 IN EFI_HANDLE ImageHandle
,
84 IN VOID
*EbcEntryPoint
,
89 Called to get the version of the interpreter.
91 @param This A pointer to the EFI_EBC_PROTOCOL instance.
92 @param Version Pointer to where to store the returned version
95 @retval EFI_SUCCESS The function completed successfully.
96 @retval EFI_INVALID_PARAMETER Version pointer is NULL.
102 IN EFI_EBC_PROTOCOL
*This
,
103 IN OUT UINT64
*Version
107 To install default Callback function for the VM interpreter.
109 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
112 @retval EFI_SUCCESS The function completed successfully.
113 @retval Others Some error occurs when creating periodic event.
118 InitializeEbcCallback (
119 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
123 The default Exception Callback for the VM interpreter.
124 In this function, we report status code, and print debug information
125 about EBC_CONTEXT, then dead loop.
127 @param InterruptType Interrupt type.
128 @param SystemContext EBC system context.
133 CommonEbcExceptionHandler (
134 IN EFI_EXCEPTION_TYPE InterruptType
,
135 IN EFI_SYSTEM_CONTEXT SystemContext
139 The periodic callback function for EBC VM interpreter, which is used
140 to support the EFI debug support protocol.
142 @param Event The Periodic Callback Event.
143 @param Context It should be the address of VM_CONTEXT pointer.
148 EbcPeriodicNotifyFunction (
154 The VM interpreter calls this function on a periodic basis to support
155 the EFI debug support protocol.
157 @param VmPtr Pointer to a VM context for passing info to the
160 @retval EFI_SUCCESS The function completed successfully.
170 // These two functions and the GUID are used to produce an EBC test protocol.
171 // This functionality is definitely not required for execution.
174 Produces an EBC VM test protocol that can be used for regression tests.
176 @param IHandle Handle on which to install the protocol.
178 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
179 @retval EFI_SUCCESS The function completed successfully.
183 InitEbcVmTestProtocol (
184 IN EFI_HANDLE
*IHandle
188 Returns the EFI_UNSUPPORTED Status.
190 @return EFI_UNSUPPORTED This function always return EFI_UNSUPPORTED status.
195 EbcVmTestUnsupported (
200 Registers a callback function that the EBC interpreter calls to flush the
201 processor instruction cache following creation of thunks.
203 @param This A pointer to the EFI_EBC_PROTOCOL instance.
204 @param Flush Pointer to a function of type EBC_ICACH_FLUSH.
206 @retval EFI_SUCCESS The function completed successfully.
211 EbcRegisterICacheFlush (
212 IN EFI_EBC_PROTOCOL
*This
,
213 IN EBC_ICACHE_FLUSH Flush
217 This EBC debugger protocol service is called by the debug agent
219 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
221 @param MaxProcessorIndex Pointer to a caller-allocated UINTN in which the
222 maximum supported processor index is returned.
224 @retval EFI_SUCCESS The function completed successfully.
229 EbcDebugGetMaximumProcessorIndex (
230 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
231 OUT UINTN
*MaxProcessorIndex
235 This protocol service is called by the debug agent to register a function
236 for us to call on a periodic basis.
238 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
240 @param ProcessorIndex Specifies which processor the callback function
242 @param PeriodicCallback A pointer to a function of type
243 PERIODIC_CALLBACK that is the main periodic
244 entry point of the debug agent. It receives as a
245 parameter a pointer to the full context of the
246 interrupted execution thread.
248 @retval EFI_SUCCESS The function completed successfully.
249 @retval EFI_ALREADY_STARTED Non-NULL PeriodicCallback parameter when a
250 callback function was previously registered.
251 @retval EFI_INVALID_PARAMETER Null PeriodicCallback parameter when no
252 callback function was previously registered.
257 EbcDebugRegisterPeriodicCallback (
258 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
259 IN UINTN ProcessorIndex
,
260 IN EFI_PERIODIC_CALLBACK PeriodicCallback
264 This protocol service is called by the debug agent to register a function
265 for us to call when we detect an exception.
267 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
269 @param ProcessorIndex Specifies which processor the callback function
271 @param ExceptionCallback A pointer to a function of type
272 EXCEPTION_CALLBACK that is called when the
273 processor exception specified by ExceptionType
274 occurs. Passing NULL unregisters any previously
275 registered function associated with
277 @param ExceptionType Specifies which processor exception to hook.
279 @retval EFI_SUCCESS The function completed successfully.
280 @retval EFI_ALREADY_STARTED Non-NULL ExceptionCallback parameter when a
281 callback function was previously registered.
282 @retval EFI_INVALID_PARAMETER ExceptionType parameter is negative or exceeds
284 @retval EFI_INVALID_PARAMETER Null ExceptionCallback parameter when no
285 callback function was previously registered.
290 EbcDebugRegisterExceptionCallback (
291 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
292 IN UINTN ProcessorIndex
,
293 IN EFI_EXCEPTION_CALLBACK ExceptionCallback
,
294 IN EFI_EXCEPTION_TYPE ExceptionType
298 This EBC debugger protocol service is called by the debug agent. Required
299 for DebugSupport compliance but is only stubbed out for EBC.
301 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
303 @param ProcessorIndex Specifies which processor the callback function
305 @param Start StartSpecifies the physical base of the memory
306 range to be invalidated.
307 @param Length Specifies the minimum number of bytes in the
308 processor's instruction cache to invalidate.
310 @retval EFI_SUCCESS The function completed successfully.
315 EbcDebugInvalidateInstructionCache (
316 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
317 IN UINTN ProcessorIndex
,
323 // We have one linked list of image handles for the whole world. Since
324 // there should only be one interpreter, make them global. They must
325 // also be global since the execution of an EBC image does not provide
328 EBC_IMAGE_LIST
*mEbcImageList
= NULL
;
331 // Callback function to flush the icache after thunk creation
333 EBC_ICACHE_FLUSH mEbcICacheFlush
;
336 // These get set via calls by the debug agent
338 EFI_PERIODIC_CALLBACK mDebugPeriodicCallback
= NULL
;
339 EFI_EXCEPTION_CALLBACK mDebugExceptionCallback
[MAX_EBC_EXCEPTION
+ 1] = {NULL
};
341 VOID
*mStackBuffer
[MAX_STACK_NUM
];
342 EFI_HANDLE mStackBufferIndex
[MAX_STACK_NUM
];
346 // Event for Periodic callback
348 EFI_EVENT mEbcPeriodicEvent
;
349 VM_CONTEXT
*mVmPtr
= NULL
;
353 Initializes the VM EFI interface. Allocates memory for the VM interface
354 and registers the VM protocol.
356 @param ImageHandle EFI image handle.
357 @param SystemTable Pointer to the EFI system table.
359 @return Standard EFI status code.
364 InitializeEbcDriver (
365 IN EFI_HANDLE ImageHandle
,
366 IN EFI_SYSTEM_TABLE
*SystemTable
369 EFI_EBC_PROTOCOL
*EbcProtocol
;
370 EFI_EBC_PROTOCOL
*OldEbcProtocol
;
372 EFI_DEBUG_SUPPORT_PROTOCOL
*EbcDebugProtocol
;
373 EFI_HANDLE
*HandleBuffer
;
379 EbcDebugProtocol
= NULL
;
382 // Allocate memory for our protocol. Then fill in the blanks.
384 EbcProtocol
= AllocatePool (sizeof (EFI_EBC_PROTOCOL
));
386 if (EbcProtocol
== NULL
) {
387 return EFI_OUT_OF_RESOURCES
;
390 EbcProtocol
->CreateThunk
= EbcCreateThunk
;
391 EbcProtocol
->UnloadImage
= EbcUnloadImage
;
392 EbcProtocol
->RegisterICacheFlush
= EbcRegisterICacheFlush
;
393 EbcProtocol
->GetVersion
= EbcGetVersion
;
394 mEbcICacheFlush
= NULL
;
397 // Find any already-installed EBC protocols and uninstall them
401 Status
= gBS
->LocateHandleBuffer (
403 &gEfiEbcProtocolGuid
,
408 if (Status
== EFI_SUCCESS
) {
410 // Loop through the handles
412 for (Index
= 0; Index
< NumHandles
; Index
++) {
413 Status
= gBS
->HandleProtocol (
415 &gEfiEbcProtocolGuid
,
416 (VOID
**) &OldEbcProtocol
418 if (Status
== EFI_SUCCESS
) {
419 if (gBS
->ReinstallProtocolInterface (
421 &gEfiEbcProtocolGuid
,
431 if (HandleBuffer
!= NULL
) {
432 FreePool (HandleBuffer
);
436 // Add the protocol so someone can locate us if we haven't already.
439 Status
= gBS
->InstallProtocolInterface (
441 &gEfiEbcProtocolGuid
,
442 EFI_NATIVE_INTERFACE
,
445 if (EFI_ERROR (Status
)) {
446 FreePool (EbcProtocol
);
451 Status
= InitEBCStack();
452 if (EFI_ERROR(Status
)) {
457 // Allocate memory for our debug protocol. Then fill in the blanks.
459 EbcDebugProtocol
= AllocatePool (sizeof (EFI_DEBUG_SUPPORT_PROTOCOL
));
461 if (EbcDebugProtocol
== NULL
) {
465 EbcDebugProtocol
->Isa
= IsaEbc
;
466 EbcDebugProtocol
->GetMaximumProcessorIndex
= EbcDebugGetMaximumProcessorIndex
;
467 EbcDebugProtocol
->RegisterPeriodicCallback
= EbcDebugRegisterPeriodicCallback
;
468 EbcDebugProtocol
->RegisterExceptionCallback
= EbcDebugRegisterExceptionCallback
;
469 EbcDebugProtocol
->InvalidateInstructionCache
= EbcDebugInvalidateInstructionCache
;
472 // Add the protocol so the debug agent can find us
474 Status
= gBS
->InstallProtocolInterface (
476 &gEfiDebugSupportProtocolGuid
,
477 EFI_NATIVE_INTERFACE
,
481 // This is recoverable, so free the memory and continue.
483 if (EFI_ERROR (Status
)) {
484 FreePool (EbcDebugProtocol
);
488 // Install EbcDebugSupport Protocol Successfully
489 // Now we need to initialize the Ebc default Callback
491 Status
= InitializeEbcCallback (EbcDebugProtocol
);
494 // Produce a VM test interface protocol. Not required for execution.
497 InitEbcVmTestProtocol (&ImageHandle
);
505 Status
= gBS
->LocateHandleBuffer (
507 &gEfiEbcProtocolGuid
,
512 if (Status
== EFI_SUCCESS
) {
514 // Loop through the handles
516 for (Index
= 0; Index
< NumHandles
; Index
++) {
517 Status
= gBS
->HandleProtocol (
519 &gEfiEbcProtocolGuid
,
520 (VOID
**) &OldEbcProtocol
522 if (Status
== EFI_SUCCESS
) {
523 gBS
->UninstallProtocolInterface (
525 &gEfiEbcProtocolGuid
,
532 if (HandleBuffer
!= NULL
) {
533 FreePool (HandleBuffer
);
537 FreePool (EbcProtocol
);
544 This is the top-level routine plugged into the EBC protocol. Since thunks
545 are very processor-specific, from here we dispatch directly to the very
546 processor-specific routine EbcCreateThunks().
548 @param This A pointer to the EFI_EBC_PROTOCOL instance.
549 @param ImageHandle Handle of image for which the thunk is being
550 created. The EBC interpreter may use this to
551 keep track of any resource allocations
552 performed in loading and executing the image.
553 @param EbcEntryPoint Address of the actual EBC entry point or
554 protocol service the thunk should call.
555 @param Thunk Returned pointer to a thunk created.
557 @retval EFI_SUCCESS The function completed successfully.
558 @retval EFI_INVALID_PARAMETER Image entry point is not 2-byte aligned.
559 @retval EFI_OUT_OF_RESOURCES Memory could not be allocated for the thunk.
565 IN EFI_EBC_PROTOCOL
*This
,
566 IN EFI_HANDLE ImageHandle
,
567 IN VOID
*EbcEntryPoint
,
573 Status
= EbcCreateThunks (
577 FLAG_THUNK_ENTRY_POINT
584 This EBC debugger protocol service is called by the debug agent
586 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
588 @param MaxProcessorIndex Pointer to a caller-allocated UINTN in which the
589 maximum supported processor index is returned.
591 @retval EFI_SUCCESS The function completed successfully.
596 EbcDebugGetMaximumProcessorIndex (
597 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
598 OUT UINTN
*MaxProcessorIndex
601 *MaxProcessorIndex
= 0;
607 This protocol service is called by the debug agent to register a function
608 for us to call on a periodic basis.
610 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
612 @param ProcessorIndex Specifies which processor the callback function
614 @param PeriodicCallback A pointer to a function of type
615 PERIODIC_CALLBACK that is the main periodic
616 entry point of the debug agent. It receives as a
617 parameter a pointer to the full context of the
618 interrupted execution thread.
620 @retval EFI_SUCCESS The function completed successfully.
621 @retval EFI_ALREADY_STARTED Non-NULL PeriodicCallback parameter when a
622 callback function was previously registered.
623 @retval EFI_INVALID_PARAMETER Null PeriodicCallback parameter when no
624 callback function was previously registered.
629 EbcDebugRegisterPeriodicCallback (
630 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
631 IN UINTN ProcessorIndex
,
632 IN EFI_PERIODIC_CALLBACK PeriodicCallback
635 if ((mDebugPeriodicCallback
== NULL
) && (PeriodicCallback
== NULL
)) {
636 return EFI_INVALID_PARAMETER
;
638 if ((mDebugPeriodicCallback
!= NULL
) && (PeriodicCallback
!= NULL
)) {
639 return EFI_ALREADY_STARTED
;
642 mDebugPeriodicCallback
= PeriodicCallback
;
648 This protocol service is called by the debug agent to register a function
649 for us to call when we detect an exception.
651 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
653 @param ProcessorIndex Specifies which processor the callback function
655 @param ExceptionCallback A pointer to a function of type
656 EXCEPTION_CALLBACK that is called when the
657 processor exception specified by ExceptionType
658 occurs. Passing NULL unregisters any previously
659 registered function associated with
661 @param ExceptionType Specifies which processor exception to hook.
663 @retval EFI_SUCCESS The function completed successfully.
664 @retval EFI_ALREADY_STARTED Non-NULL ExceptionCallback parameter when a
665 callback function was previously registered.
666 @retval EFI_INVALID_PARAMETER ExceptionType parameter is negative or exceeds
668 @retval EFI_INVALID_PARAMETER Null ExceptionCallback parameter when no
669 callback function was previously registered.
674 EbcDebugRegisterExceptionCallback (
675 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
676 IN UINTN ProcessorIndex
,
677 IN EFI_EXCEPTION_CALLBACK ExceptionCallback
,
678 IN EFI_EXCEPTION_TYPE ExceptionType
681 if ((ExceptionType
< 0) || (ExceptionType
> MAX_EBC_EXCEPTION
)) {
682 return EFI_INVALID_PARAMETER
;
684 if ((mDebugExceptionCallback
[ExceptionType
] == NULL
) && (ExceptionCallback
== NULL
)) {
685 return EFI_INVALID_PARAMETER
;
687 if ((mDebugExceptionCallback
[ExceptionType
] != NULL
) && (ExceptionCallback
!= NULL
)) {
688 return EFI_ALREADY_STARTED
;
690 mDebugExceptionCallback
[ExceptionType
] = ExceptionCallback
;
696 This EBC debugger protocol service is called by the debug agent. Required
697 for DebugSupport compliance but is only stubbed out for EBC.
699 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
701 @param ProcessorIndex Specifies which processor the callback function
703 @param Start StartSpecifies the physical base of the memory
704 range to be invalidated.
705 @param Length Specifies the minimum number of bytes in the
706 processor's instruction cache to invalidate.
708 @retval EFI_SUCCESS The function completed successfully.
713 EbcDebugInvalidateInstructionCache (
714 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
715 IN UINTN ProcessorIndex
,
725 The VM interpreter calls this function when an exception is detected.
727 @param ExceptionType Specifies the processor exception detected.
728 @param ExceptionFlags Specifies the exception context.
729 @param VmPtr Pointer to a VM context for passing info to the
732 @retval EFI_SUCCESS This function completed successfully.
736 EbcDebugSignalException (
737 IN EFI_EXCEPTION_TYPE ExceptionType
,
738 IN EXCEPTION_FLAGS ExceptionFlags
,
742 EFI_SYSTEM_CONTEXT_EBC EbcContext
;
743 EFI_SYSTEM_CONTEXT SystemContext
;
745 ASSERT ((ExceptionType
>= 0) && (ExceptionType
<= MAX_EBC_EXCEPTION
));
747 // Save the exception in the context passed in
749 VmPtr
->ExceptionFlags
|= ExceptionFlags
;
750 VmPtr
->LastException
= (UINTN
) ExceptionType
;
752 // If it's a fatal exception, then flag it in the VM context in case an
753 // attached debugger tries to return from it.
755 if ((ExceptionFlags
& EXCEPTION_FLAG_FATAL
) != 0) {
756 VmPtr
->StopFlags
|= STOPFLAG_APP_DONE
;
760 // If someone's registered for exception callbacks, then call them.
762 // EBC driver will register default exception callback to report the
763 // status code via the status code API
765 if (mDebugExceptionCallback
[ExceptionType
] != NULL
) {
768 // Initialize the context structure
770 EbcContext
.R0
= (UINT64
) VmPtr
->Gpr
[0];
771 EbcContext
.R1
= (UINT64
) VmPtr
->Gpr
[1];
772 EbcContext
.R2
= (UINT64
) VmPtr
->Gpr
[2];
773 EbcContext
.R3
= (UINT64
) VmPtr
->Gpr
[3];
774 EbcContext
.R4
= (UINT64
) VmPtr
->Gpr
[4];
775 EbcContext
.R5
= (UINT64
) VmPtr
->Gpr
[5];
776 EbcContext
.R6
= (UINT64
) VmPtr
->Gpr
[6];
777 EbcContext
.R7
= (UINT64
) VmPtr
->Gpr
[7];
778 EbcContext
.Ip
= (UINT64
)(UINTN
)VmPtr
->Ip
;
779 EbcContext
.Flags
= VmPtr
->Flags
;
780 EbcContext
.ControlFlags
= 0;
781 SystemContext
.SystemContextEbc
= &EbcContext
;
783 mDebugExceptionCallback
[ExceptionType
] (ExceptionType
, SystemContext
);
785 // Restore the context structure and continue to execute
787 VmPtr
->Gpr
[0] = EbcContext
.R0
;
788 VmPtr
->Gpr
[1] = EbcContext
.R1
;
789 VmPtr
->Gpr
[2] = EbcContext
.R2
;
790 VmPtr
->Gpr
[3] = EbcContext
.R3
;
791 VmPtr
->Gpr
[4] = EbcContext
.R4
;
792 VmPtr
->Gpr
[5] = EbcContext
.R5
;
793 VmPtr
->Gpr
[6] = EbcContext
.R6
;
794 VmPtr
->Gpr
[7] = EbcContext
.R7
;
795 VmPtr
->Ip
= (VMIP
)(UINTN
)EbcContext
.Ip
;
796 VmPtr
->Flags
= EbcContext
.Flags
;
804 To install default Callback function for the VM interpreter.
806 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
809 @retval EFI_SUCCESS The function completed successfully.
810 @retval Others Some error occurs when creating periodic event.
815 InitializeEbcCallback (
816 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
823 // For ExceptionCallback
825 for (Index
= 0; Index
<= MAX_EBC_EXCEPTION
; Index
++) {
826 EbcDebugRegisterExceptionCallback (
829 CommonEbcExceptionHandler
,
835 // For PeriodicCallback
837 Status
= gBS
->CreateEvent (
838 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
840 EbcPeriodicNotifyFunction
,
844 if (EFI_ERROR(Status
)) {
848 Status
= gBS
->SetTimer (
851 EBC_VM_PERIODIC_CALLBACK_RATE
853 if (EFI_ERROR(Status
)) {
862 The default Exception Callback for the VM interpreter.
863 In this function, we report status code, and print debug information
864 about EBC_CONTEXT, then dead loop.
866 @param InterruptType Interrupt type.
867 @param SystemContext EBC system context.
872 CommonEbcExceptionHandler (
873 IN EFI_EXCEPTION_TYPE InterruptType
,
874 IN EFI_SYSTEM_CONTEXT SystemContext
878 // We print debug information to let user know what happen.
882 "EBC Interrupter Version - 0x%016lx\n",
883 (UINT64
) (((VM_MAJOR_VERSION
& 0xFFFF) << 16) | ((VM_MINOR_VERSION
& 0xFFFF)))
887 "Exception Type - 0x%016lx\n",
888 (UINT64
)(UINTN
)InterruptType
892 " R0 - 0x%016lx, R1 - 0x%016lx\n",
893 SystemContext
.SystemContextEbc
->R0
,
894 SystemContext
.SystemContextEbc
->R1
898 " R2 - 0x%016lx, R3 - 0x%016lx\n",
899 SystemContext
.SystemContextEbc
->R2
,
900 SystemContext
.SystemContextEbc
->R3
904 " R4 - 0x%016lx, R5 - 0x%016lx\n",
905 SystemContext
.SystemContextEbc
->R4
,
906 SystemContext
.SystemContextEbc
->R5
910 " R6 - 0x%016lx, R7 - 0x%016lx\n",
911 SystemContext
.SystemContextEbc
->R6
,
912 SystemContext
.SystemContextEbc
->R7
916 " Flags - 0x%016lx\n",
917 SystemContext
.SystemContextEbc
->Flags
921 " ControlFlags - 0x%016lx\n",
922 SystemContext
.SystemContextEbc
->ControlFlags
926 " Ip - 0x%016lx\n\n",
927 SystemContext
.SystemContextEbc
->Ip
931 // We deadloop here to make it easy to debug this issue.
940 The periodic callback function for EBC VM interpreter, which is used
941 to support the EFI debug support protocol.
943 @param Event The Periodic Callback Event.
944 @param Context It should be the address of VM_CONTEXT pointer.
949 EbcPeriodicNotifyFunction (
956 VmPtr
= *(VM_CONTEXT
**)Context
;
959 EbcDebugPeriodic (VmPtr
);
967 The VM interpreter calls this function on a periodic basis to support
968 the EFI debug support protocol.
970 @param VmPtr Pointer to a VM context for passing info to the
973 @retval EFI_SUCCESS The function completed successfully.
982 EFI_SYSTEM_CONTEXT_EBC EbcContext
;
983 EFI_SYSTEM_CONTEXT SystemContext
;
986 // If someone's registered for periodic callbacks, then call them.
988 if (mDebugPeriodicCallback
!= NULL
) {
991 // Initialize the context structure
993 EbcContext
.R0
= (UINT64
) VmPtr
->Gpr
[0];
994 EbcContext
.R1
= (UINT64
) VmPtr
->Gpr
[1];
995 EbcContext
.R2
= (UINT64
) VmPtr
->Gpr
[2];
996 EbcContext
.R3
= (UINT64
) VmPtr
->Gpr
[3];
997 EbcContext
.R4
= (UINT64
) VmPtr
->Gpr
[4];
998 EbcContext
.R5
= (UINT64
) VmPtr
->Gpr
[5];
999 EbcContext
.R6
= (UINT64
) VmPtr
->Gpr
[6];
1000 EbcContext
.R7
= (UINT64
) VmPtr
->Gpr
[7];
1001 EbcContext
.Ip
= (UINT64
)(UINTN
)VmPtr
->Ip
;
1002 EbcContext
.Flags
= VmPtr
->Flags
;
1003 EbcContext
.ControlFlags
= 0;
1004 SystemContext
.SystemContextEbc
= &EbcContext
;
1006 mDebugPeriodicCallback (SystemContext
);
1009 // Restore the context structure and continue to execute
1011 VmPtr
->Gpr
[0] = EbcContext
.R0
;
1012 VmPtr
->Gpr
[1] = EbcContext
.R1
;
1013 VmPtr
->Gpr
[2] = EbcContext
.R2
;
1014 VmPtr
->Gpr
[3] = EbcContext
.R3
;
1015 VmPtr
->Gpr
[4] = EbcContext
.R4
;
1016 VmPtr
->Gpr
[5] = EbcContext
.R5
;
1017 VmPtr
->Gpr
[6] = EbcContext
.R6
;
1018 VmPtr
->Gpr
[7] = EbcContext
.R7
;
1019 VmPtr
->Ip
= (VMIP
)(UINTN
)EbcContext
.Ip
;
1020 VmPtr
->Flags
= EbcContext
.Flags
;
1028 This routine is called by the core when an image is being unloaded from
1029 memory. Basically we now have the opportunity to do any necessary cleanup.
1030 Typically this will include freeing any memory allocated for thunk-creation.
1032 @param This A pointer to the EFI_EBC_PROTOCOL instance.
1033 @param ImageHandle Handle of image for which the thunk is being
1036 @retval EFI_INVALID_PARAMETER The ImageHandle passed in was not found in the
1037 internal list of EBC image handles.
1038 @retval EFI_SUCCESS The function completed successfully.
1044 IN EFI_EBC_PROTOCOL
*This
,
1045 IN EFI_HANDLE ImageHandle
1048 EBC_THUNK_LIST
*ThunkList
;
1049 EBC_THUNK_LIST
*NextThunkList
;
1050 EBC_IMAGE_LIST
*ImageList
;
1051 EBC_IMAGE_LIST
*PrevImageList
;
1053 // First go through our list of known image handles and see if we've already
1054 // created an image list element for this image handle.
1056 ReturnEBCStackByHandle(ImageHandle
);
1057 PrevImageList
= NULL
;
1058 for (ImageList
= mEbcImageList
; ImageList
!= NULL
; ImageList
= ImageList
->Next
) {
1059 if (ImageList
->ImageHandle
== ImageHandle
) {
1063 // Save the previous so we can connect the lists when we remove this one
1065 PrevImageList
= ImageList
;
1068 if (ImageList
== NULL
) {
1069 return EFI_INVALID_PARAMETER
;
1072 // Free up all the thunk buffers and thunks list elements for this image
1075 ThunkList
= ImageList
->ThunkList
;
1076 while (ThunkList
!= NULL
) {
1077 NextThunkList
= ThunkList
->Next
;
1078 FreePool (ThunkList
->ThunkBuffer
);
1079 FreePool (ThunkList
);
1080 ThunkList
= NextThunkList
;
1083 // Now remove this image list element from the chain
1085 if (PrevImageList
== NULL
) {
1089 mEbcImageList
= ImageList
->Next
;
1091 PrevImageList
->Next
= ImageList
->Next
;
1094 // Now free up the image list element
1096 FreePool (ImageList
);
1102 Add a thunk to our list of thunks for a given image handle.
1103 Also flush the instruction cache since we've written thunk code
1104 to memory that will be executed eventually.
1106 @param ImageHandle The image handle to which the thunk is tied.
1107 @param ThunkBuffer The buffer that has been created/allocated.
1108 @param ThunkSize The size of the thunk memory allocated.
1110 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
1111 @retval EFI_SUCCESS The function completed successfully.
1116 IN EFI_HANDLE ImageHandle
,
1117 IN VOID
*ThunkBuffer
,
1121 EBC_THUNK_LIST
*ThunkList
;
1122 EBC_IMAGE_LIST
*ImageList
;
1126 // It so far so good, then flush the instruction cache
1128 if (mEbcICacheFlush
!= NULL
) {
1129 Status
= mEbcICacheFlush ((EFI_PHYSICAL_ADDRESS
) (UINTN
) ThunkBuffer
, ThunkSize
);
1130 if (EFI_ERROR (Status
)) {
1135 // Go through our list of known image handles and see if we've already
1136 // created a image list element for this image handle.
1138 for (ImageList
= mEbcImageList
; ImageList
!= NULL
; ImageList
= ImageList
->Next
) {
1139 if (ImageList
->ImageHandle
== ImageHandle
) {
1144 if (ImageList
== NULL
) {
1146 // Allocate a new one
1148 ImageList
= AllocatePool (sizeof (EBC_IMAGE_LIST
));
1150 if (ImageList
== NULL
) {
1151 return EFI_OUT_OF_RESOURCES
;
1154 ImageList
->ThunkList
= NULL
;
1155 ImageList
->ImageHandle
= ImageHandle
;
1156 ImageList
->Next
= mEbcImageList
;
1157 mEbcImageList
= ImageList
;
1160 // Ok, now create a new thunk element to add to the list
1162 ThunkList
= AllocatePool (sizeof (EBC_THUNK_LIST
));
1164 if (ThunkList
== NULL
) {
1165 return EFI_OUT_OF_RESOURCES
;
1168 // Add it to the head of the list
1170 ThunkList
->Next
= ImageList
->ThunkList
;
1171 ThunkList
->ThunkBuffer
= ThunkBuffer
;
1172 ImageList
->ThunkList
= ThunkList
;
1177 Registers a callback function that the EBC interpreter calls to flush the
1178 processor instruction cache following creation of thunks.
1180 @param This A pointer to the EFI_EBC_PROTOCOL instance.
1181 @param Flush Pointer to a function of type EBC_ICACH_FLUSH.
1183 @retval EFI_SUCCESS The function completed successfully.
1188 EbcRegisterICacheFlush (
1189 IN EFI_EBC_PROTOCOL
*This
,
1190 IN EBC_ICACHE_FLUSH Flush
1193 mEbcICacheFlush
= Flush
;
1198 Called to get the version of the interpreter.
1200 @param This A pointer to the EFI_EBC_PROTOCOL instance.
1201 @param Version Pointer to where to store the returned version
1204 @retval EFI_SUCCESS The function completed successfully.
1205 @retval EFI_INVALID_PARAMETER Version pointer is NULL.
1211 IN EFI_EBC_PROTOCOL
*This
,
1212 IN OUT UINT64
*Version
1215 if (Version
== NULL
) {
1216 return EFI_INVALID_PARAMETER
;
1219 *Version
= GetVmVersion ();
1224 Returns the stack index and buffer assosicated with the Handle parameter.
1226 @param Handle The EFI handle as the index to the EBC stack.
1227 @param StackBuffer A pointer to hold the returned stack buffer.
1228 @param BufferIndex A pointer to hold the returned stack index.
1230 @retval EFI_OUT_OF_RESOURCES The Handle parameter does not correspond to any
1232 @retval EFI_SUCCESS The stack index and buffer were found and
1233 returned to the caller.
1238 IN EFI_HANDLE Handle
,
1239 OUT VOID
**StackBuffer
,
1240 OUT UINTN
*BufferIndex
1245 OldTpl
= gBS
->RaiseTPL(TPL_HIGH_LEVEL
);
1246 for (Index
= 0; Index
< mStackNum
; Index
++) {
1247 if (mStackBufferIndex
[Index
] == NULL
) {
1248 mStackBufferIndex
[Index
] = Handle
;
1252 gBS
->RestoreTPL(OldTpl
);
1253 if (Index
== mStackNum
) {
1254 return EFI_OUT_OF_RESOURCES
;
1256 *BufferIndex
= Index
;
1257 *StackBuffer
= mStackBuffer
[Index
];
1262 Returns from the EBC stack by stack Index.
1264 @param Index Specifies which EBC stack to return from.
1266 @retval EFI_SUCCESS The function completed successfully.
1274 mStackBufferIndex
[Index
] = NULL
;
1279 Returns from the EBC stack associated with the Handle parameter.
1281 @param Handle Specifies the EFI handle to find the EBC stack with.
1283 @retval EFI_SUCCESS The function completed successfully.
1287 ReturnEBCStackByHandle(
1288 IN EFI_HANDLE Handle
1292 for (Index
= 0; Index
< mStackNum
; Index
++) {
1293 if (mStackBufferIndex
[Index
] == Handle
) {
1297 if (Index
== mStackNum
) {
1298 return EFI_NOT_FOUND
;
1300 mStackBufferIndex
[Index
] = NULL
;
1305 Allocates memory to hold all the EBC stacks.
1307 @retval EFI_SUCCESS The EBC stacks were allocated successfully.
1308 @retval EFI_OUT_OF_RESOURCES Not enough memory available for EBC stacks.
1316 for (mStackNum
= 0; mStackNum
< MAX_STACK_NUM
; mStackNum
++) {
1317 mStackBuffer
[mStackNum
] = AllocatePool(STACK_POOL_SIZE
);
1318 mStackBufferIndex
[mStackNum
] = NULL
;
1319 if (mStackBuffer
[mStackNum
] == NULL
) {
1323 if (mStackNum
== 0) {
1324 return EFI_OUT_OF_RESOURCES
;
1331 Free all EBC stacks allocated before.
1333 @retval EFI_SUCCESS All the EBC stacks were freed.
1342 for (Index
= 0; Index
< mStackNum
; Index
++) {
1343 FreePool(mStackBuffer
[Index
]);
1349 Produces an EBC VM test protocol that can be used for regression tests.
1351 @param IHandle Handle on which to install the protocol.
1353 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
1354 @retval EFI_SUCCESS The function completed successfully.
1358 InitEbcVmTestProtocol (
1359 IN EFI_HANDLE
*IHandle
1364 EFI_EBC_VM_TEST_PROTOCOL
*EbcVmTestProtocol
;
1367 // Allocate memory for the protocol, then fill in the fields
1369 EbcVmTestProtocol
= AllocatePool (sizeof (EFI_EBC_VM_TEST_PROTOCOL
));
1370 if (EbcVmTestProtocol
== NULL
) {
1371 return EFI_OUT_OF_RESOURCES
;
1373 EbcVmTestProtocol
->Execute
= (EBC_VM_TEST_EXECUTE
) EbcExecuteInstructions
;
1375 DEBUG_CODE_BEGIN ();
1376 EbcVmTestProtocol
->Assemble
= (EBC_VM_TEST_ASM
) EbcVmTestUnsupported
;
1377 EbcVmTestProtocol
->Disassemble
= (EBC_VM_TEST_DASM
) EbcVmTestUnsupported
;
1381 // Publish the protocol
1384 Status
= gBS
->InstallProtocolInterface (&Handle
, &gEfiEbcVmTestProtocolGuid
, EFI_NATIVE_INTERFACE
, EbcVmTestProtocol
);
1385 if (EFI_ERROR (Status
)) {
1386 FreePool (EbcVmTestProtocol
);
1393 Returns the EFI_UNSUPPORTED Status.
1395 @return EFI_UNSUPPORTED This function always return EFI_UNSUPPORTED status.
1400 EbcVmTestUnsupported (
1404 return EFI_UNSUPPORTED
;