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 - 2008, Intel Corporation
7 All rights reserved. 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
{
28 struct _EBC_THUNK_LIST
*Next
;
31 typedef struct _EBC_IMAGE_LIST
{
32 struct _EBC_IMAGE_LIST
*Next
;
33 EFI_HANDLE ImageHandle
;
34 EBC_THUNK_LIST
*ThunkList
;
38 This routine is called by the core when an image is being unloaded from
39 memory. Basically we now have the opportunity to do any necessary cleanup.
40 Typically this will include freeing any memory allocated for thunk-creation.
42 @param This A pointer to the EFI_EBC_PROTOCOL instance.
43 @param ImageHandle Handle of image for which the thunk is being
46 @retval EFI_INVALID_PARAMETER The ImageHandle passed in was not found in the
47 internal list of EBC image handles.
48 @retval EFI_SUCCESS The function completed successfully.
55 IN EFI_EBC_PROTOCOL
*This
,
56 IN EFI_HANDLE ImageHandle
60 This is the top-level routine plugged into the EBC protocol. Since thunks
61 are very processor-specific, from here we dispatch directly to the very
62 processor-specific routine EbcCreateThunks().
64 @param This A pointer to the EFI_EBC_PROTOCOL instance.
65 @param ImageHandle Handle of image for which the thunk is being
66 created. The EBC interpreter may use this to
67 keep track of any resource allocations
68 performed in loading and executing the image.
69 @param EbcEntryPoint Address of the actual EBC entry point or
70 protocol service the thunk should call.
71 @param Thunk Returned pointer to a thunk created.
73 @retval EFI_SUCCESS The function completed successfully.
74 @retval EFI_INVALID_PARAMETER Image entry point is not 2-byte aligned.
75 @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.
103 IN EFI_EBC_PROTOCOL
*This
,
104 IN OUT UINT64
*Version
108 To install default Callback function for the VM interpreter.
110 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
113 @retval EFI_SUCCESS The function completed successfully.
114 @retval Others Some error occurs when creating periodic event.
120 InitializeEbcCallback (
121 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
125 The default Exception Callback for the VM interpreter.
126 In this function, we report status code, and print debug information
127 about EBC_CONTEXT, then dead loop.
129 @param InterruptType Interrupt type.
130 @param SystemContext EBC system context.
136 CommonEbcExceptionHandler (
137 IN EFI_EXCEPTION_TYPE InterruptType
,
138 IN EFI_SYSTEM_CONTEXT SystemContext
142 The periodic callback function for EBC VM interpreter, which is used
143 to support the EFI debug support protocol.
145 @param Event The Periodic Callback Event.
146 @param Context It should be the address of VM_CONTEXT pointer.
152 EbcPeriodicNotifyFunction (
158 The VM interpreter calls this function on a periodic basis to support
159 the EFI debug support protocol.
161 @param VmPtr Pointer to a VM context for passing info to the
164 @retval EFI_SUCCESS The function completed successfully.
175 // These two functions and the GUID are used to produce an EBC test protocol.
176 // This functionality is definitely not required for execution.
179 Produces an EBC VM test protocol that can be used for regression tests.
181 @param IHandle Handle on which to install the protocol.
183 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
184 @retval EFI_SUCCESS The function completed successfully.
189 InitEbcVmTestProtocol (
190 IN EFI_HANDLE
*Handle
194 Returns the EFI_UNSUPPORTED Status.
196 @return EFI_UNSUPPORTED This function always return EFI_UNSUPPORTED status.
201 EbcVmTestUnsupported (
206 Registers a callback function that the EBC interpreter calls to flush the
207 processor instruction cache following creation of thunks.
209 @param This A pointer to the EFI_EBC_PROTOCOL instance.
210 @param Flush Pointer to a function of type EBC_ICACH_FLUSH.
212 @retval EFI_SUCCESS The function completed successfully.
218 EbcRegisterICacheFlush (
219 IN EFI_EBC_PROTOCOL
*This
,
220 IN EBC_ICACHE_FLUSH Flush
224 This EBC debugger protocol service is called by the debug agent
226 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
228 @param MaxProcessorIndex Pointer to a caller-allocated UINTN in which the
229 maximum supported processor index is returned.
231 @retval EFI_SUCCESS The function completed successfully.
237 EbcDebugGetMaximumProcessorIndex (
238 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
239 OUT UINTN
*MaxProcessorIndex
243 This protocol service is called by the debug agent to register a function
244 for us to call on a periodic basis.
246 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
248 @param ProcessorIndex Specifies which processor the callback function
250 @param PeriodicCallback A pointer to a function of type
251 PERIODIC_CALLBACK that is the main periodic
252 entry point of the debug agent. It receives as a
253 parameter a pointer to the full context of the
254 interrupted execution thread.
256 @retval EFI_SUCCESS The function completed successfully.
257 @retval EFI_ALREADY_STARTED Non-NULL PeriodicCallback parameter when a
258 callback function was previously registered.
259 @retval EFI_INVALID_PARAMETER Null PeriodicCallback parameter when no
260 callback function was previously registered.
266 EbcDebugRegisterPeriodicCallback (
267 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
268 IN UINTN ProcessorIndex
,
269 IN EFI_PERIODIC_CALLBACK PeriodicCallback
273 This protocol service is called by the debug agent to register a function
274 for us to call when we detect an exception.
276 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
278 @param ProcessorIndex Specifies which processor the callback function
280 @param ExceptionCallback A pointer to a function of type
281 EXCEPTION_CALLBACK that is called when the
282 processor exception specified by ExceptionType
283 occurs. Passing NULL unregisters any previously
284 registered function associated with
286 @param ExceptionType Specifies which processor exception to hook.
288 @retval EFI_SUCCESS The function completed successfully.
289 @retval EFI_ALREADY_STARTED Non-NULL ExceptionCallback parameter when a
290 callback function was previously registered.
291 @retval EFI_INVALID_PARAMETER ExceptionType parameter is negative or exceeds
293 @retval EFI_INVALID_PARAMETER Null ExceptionCallback parameter when no
294 callback function was previously registered.
300 EbcDebugRegisterExceptionCallback (
301 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
302 IN UINTN ProcessorIndex
,
303 IN EFI_EXCEPTION_CALLBACK ExceptionCallback
,
304 IN EFI_EXCEPTION_TYPE ExceptionType
308 This EBC debugger protocol service is called by the debug agent. Required
309 for DebugSupport compliance but is only stubbed out for EBC.
311 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
313 @param ProcessorIndex Specifies which processor the callback function
315 @param Start StartSpecifies the physical base of the memory
316 range to be invalidated.
317 @param Length Specifies the minimum number of bytes in the
318 processor's instruction cache to invalidate.
320 @retval EFI_SUCCESS The function completed successfully.
326 EbcDebugInvalidateInstructionCache (
327 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
328 IN UINTN ProcessorIndex
,
334 // We have one linked list of image handles for the whole world. Since
335 // there should only be one interpreter, make them global. They must
336 // also be global since the execution of an EBC image does not provide
339 STATIC EBC_IMAGE_LIST
*mEbcImageList
= NULL
;
342 // Callback function to flush the icache after thunk creation
344 STATIC EBC_ICACHE_FLUSH mEbcICacheFlush
;
347 // These get set via calls by the debug agent
349 STATIC EFI_PERIODIC_CALLBACK mDebugPeriodicCallback
= NULL
;
350 STATIC EFI_EXCEPTION_CALLBACK mDebugExceptionCallback
[MAX_EBC_EXCEPTION
+ 1] = {NULL
};
351 STATIC EFI_GUID mEfiEbcVmTestProtocolGuid
= EFI_EBC_VM_TEST_PROTOCOL_GUID
;
353 STATIC VOID
* mStackBuffer
[MAX_STACK_NUM
];
354 STATIC EFI_HANDLE mStackBufferIndex
[MAX_STACK_NUM
];
355 STATIC UINTN mStackNum
= 0;
358 // Event for Periodic callback
360 STATIC EFI_EVENT mEbcPeriodicEvent
;
361 VM_CONTEXT
*mVmPtr
= NULL
;
365 Initializes the VM EFI interface. Allocates memory for the VM interface
366 and registers the VM protocol.
368 @param ImageHandle EFI image handle.
369 @param SystemTable Pointer to the EFI system table.
371 @return Standard EFI status code.
376 InitializeEbcDriver (
377 IN EFI_HANDLE ImageHandle
,
378 IN EFI_SYSTEM_TABLE
*SystemTable
381 EFI_EBC_PROTOCOL
*EbcProtocol
;
382 EFI_EBC_PROTOCOL
*OldEbcProtocol
;
384 EFI_DEBUG_SUPPORT_PROTOCOL
*EbcDebugProtocol
;
385 EFI_HANDLE
*HandleBuffer
;
391 EbcDebugProtocol
= NULL
;
394 // Allocate memory for our protocol. Then fill in the blanks.
396 EbcProtocol
= AllocatePool (sizeof (EFI_EBC_PROTOCOL
));
398 if (EbcProtocol
== NULL
) {
399 return EFI_OUT_OF_RESOURCES
;
402 EbcProtocol
->CreateThunk
= EbcCreateThunk
;
403 EbcProtocol
->UnloadImage
= EbcUnloadImage
;
404 EbcProtocol
->RegisterICacheFlush
= EbcRegisterICacheFlush
;
405 EbcProtocol
->GetVersion
= EbcGetVersion
;
406 mEbcICacheFlush
= NULL
;
409 // Find any already-installed EBC protocols and uninstall them
413 Status
= gBS
->LocateHandleBuffer (
415 &gEfiEbcProtocolGuid
,
420 if (Status
== EFI_SUCCESS
) {
422 // Loop through the handles
424 for (Index
= 0; Index
< NumHandles
; Index
++) {
425 Status
= gBS
->HandleProtocol (
427 &gEfiEbcProtocolGuid
,
428 (VOID
**) &OldEbcProtocol
430 if (Status
== EFI_SUCCESS
) {
431 if (gBS
->ReinstallProtocolInterface (
433 &gEfiEbcProtocolGuid
,
443 if (HandleBuffer
!= NULL
) {
444 FreePool (HandleBuffer
);
448 // Add the protocol so someone can locate us if we haven't already.
451 Status
= gBS
->InstallProtocolInterface (
453 &gEfiEbcProtocolGuid
,
454 EFI_NATIVE_INTERFACE
,
457 if (EFI_ERROR (Status
)) {
458 FreePool (EbcProtocol
);
463 Status
= InitEBCStack();
464 if (EFI_ERROR(Status
)) {
469 // Allocate memory for our debug protocol. Then fill in the blanks.
471 EbcDebugProtocol
= AllocatePool (sizeof (EFI_DEBUG_SUPPORT_PROTOCOL
));
473 if (EbcDebugProtocol
== NULL
) {
477 EbcDebugProtocol
->Isa
= IsaEbc
;
478 EbcDebugProtocol
->GetMaximumProcessorIndex
= EbcDebugGetMaximumProcessorIndex
;
479 EbcDebugProtocol
->RegisterPeriodicCallback
= EbcDebugRegisterPeriodicCallback
;
480 EbcDebugProtocol
->RegisterExceptionCallback
= EbcDebugRegisterExceptionCallback
;
481 EbcDebugProtocol
->InvalidateInstructionCache
= EbcDebugInvalidateInstructionCache
;
484 // Add the protocol so the debug agent can find us
486 Status
= gBS
->InstallProtocolInterface (
488 &gEfiDebugSupportProtocolGuid
,
489 EFI_NATIVE_INTERFACE
,
493 // This is recoverable, so free the memory and continue.
495 if (EFI_ERROR (Status
)) {
496 FreePool (EbcDebugProtocol
);
500 // Install EbcDebugSupport Protocol Successfully
501 // Now we need to initialize the Ebc default Callback
503 Status
= InitializeEbcCallback (EbcDebugProtocol
);
506 // Produce a VM test interface protocol. Not required for execution.
509 InitEbcVmTestProtocol (&ImageHandle
);
517 Status
= gBS
->LocateHandleBuffer (
519 &gEfiEbcProtocolGuid
,
524 if (Status
== EFI_SUCCESS
) {
526 // Loop through the handles
528 for (Index
= 0; Index
< NumHandles
; Index
++) {
529 Status
= gBS
->HandleProtocol (
531 &gEfiEbcProtocolGuid
,
532 (VOID
**) &OldEbcProtocol
534 if (Status
== EFI_SUCCESS
) {
535 gBS
->UninstallProtocolInterface (
537 &gEfiEbcProtocolGuid
,
544 if (HandleBuffer
!= NULL
) {
545 FreePool (HandleBuffer
);
549 FreePool (EbcProtocol
);
556 This is the top-level routine plugged into the EBC protocol. Since thunks
557 are very processor-specific, from here we dispatch directly to the very
558 processor-specific routine EbcCreateThunks().
560 @param This A pointer to the EFI_EBC_PROTOCOL instance.
561 @param ImageHandle Handle of image for which the thunk is being
562 created. The EBC interpreter may use this to
563 keep track of any resource allocations
564 performed in loading and executing the image.
565 @param EbcEntryPoint Address of the actual EBC entry point or
566 protocol service the thunk should call.
567 @param Thunk Returned pointer to a thunk created.
569 @retval EFI_SUCCESS The function completed successfully.
570 @retval EFI_INVALID_PARAMETER Image entry point is not 2-byte aligned.
571 @retval EFI_OUT_OF_RESOURCES Memory could not be allocated for the thunk.
578 IN EFI_EBC_PROTOCOL
*This
,
579 IN EFI_HANDLE ImageHandle
,
580 IN VOID
*EbcEntryPoint
,
586 Status
= EbcCreateThunks (
590 FLAG_THUNK_ENTRY_POINT
597 This EBC debugger protocol service is called by the debug agent
599 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
601 @param MaxProcessorIndex Pointer to a caller-allocated UINTN in which the
602 maximum supported processor index is returned.
604 @retval EFI_SUCCESS The function completed successfully.
610 EbcDebugGetMaximumProcessorIndex (
611 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
612 OUT UINTN
*MaxProcessorIndex
615 *MaxProcessorIndex
= 0;
621 This protocol service is called by the debug agent to register a function
622 for us to call on a periodic basis.
624 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
626 @param ProcessorIndex Specifies which processor the callback function
628 @param PeriodicCallback A pointer to a function of type
629 PERIODIC_CALLBACK that is the main periodic
630 entry point of the debug agent. It receives as a
631 parameter a pointer to the full context of the
632 interrupted execution thread.
634 @retval EFI_SUCCESS The function completed successfully.
635 @retval EFI_ALREADY_STARTED Non-NULL PeriodicCallback parameter when a
636 callback function was previously registered.
637 @retval EFI_INVALID_PARAMETER Null PeriodicCallback parameter when no
638 callback function was previously registered.
644 EbcDebugRegisterPeriodicCallback (
645 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
646 IN UINTN ProcessorIndex
,
647 IN EFI_PERIODIC_CALLBACK PeriodicCallback
650 if ((mDebugPeriodicCallback
== NULL
) && (PeriodicCallback
== NULL
)) {
651 return EFI_INVALID_PARAMETER
;
653 if ((mDebugPeriodicCallback
!= NULL
) && (PeriodicCallback
!= NULL
)) {
654 return EFI_ALREADY_STARTED
;
657 mDebugPeriodicCallback
= PeriodicCallback
;
663 This protocol service is called by the debug agent to register a function
664 for us to call when we detect an exception.
666 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
668 @param ProcessorIndex Specifies which processor the callback function
670 @param ExceptionCallback A pointer to a function of type
671 EXCEPTION_CALLBACK that is called when the
672 processor exception specified by ExceptionType
673 occurs. Passing NULL unregisters any previously
674 registered function associated with
676 @param ExceptionType Specifies which processor exception to hook.
678 @retval EFI_SUCCESS The function completed successfully.
679 @retval EFI_ALREADY_STARTED Non-NULL ExceptionCallback parameter when a
680 callback function was previously registered.
681 @retval EFI_INVALID_PARAMETER ExceptionType parameter is negative or exceeds
683 @retval EFI_INVALID_PARAMETER Null ExceptionCallback parameter when no
684 callback function was previously registered.
690 EbcDebugRegisterExceptionCallback (
691 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
692 IN UINTN ProcessorIndex
,
693 IN EFI_EXCEPTION_CALLBACK ExceptionCallback
,
694 IN EFI_EXCEPTION_TYPE ExceptionType
697 if ((ExceptionType
< 0) || (ExceptionType
> MAX_EBC_EXCEPTION
)) {
698 return EFI_INVALID_PARAMETER
;
700 if ((mDebugExceptionCallback
[ExceptionType
] == NULL
) && (ExceptionCallback
== NULL
)) {
701 return EFI_INVALID_PARAMETER
;
703 if ((mDebugExceptionCallback
[ExceptionType
] != NULL
) && (ExceptionCallback
!= NULL
)) {
704 return EFI_ALREADY_STARTED
;
706 mDebugExceptionCallback
[ExceptionType
] = ExceptionCallback
;
712 This EBC debugger protocol service is called by the debug agent. Required
713 for DebugSupport compliance but is only stubbed out for EBC.
715 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
717 @param ProcessorIndex Specifies which processor the callback function
719 @param Start StartSpecifies the physical base of the memory
720 range to be invalidated.
721 @param Length Specifies the minimum number of bytes in the
722 processor's instruction cache to invalidate.
724 @retval EFI_SUCCESS The function completed successfully.
730 EbcDebugInvalidateInstructionCache (
731 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
732 IN UINTN ProcessorIndex
,
742 The VM interpreter calls this function when an exception is detected.
744 @param ExceptionType Specifies the processor exception detected.
745 @param ExceptionFlags Specifies the exception context.
746 @param VmPtr Pointer to a VM context for passing info to the
749 @retval EFI_SUCCESS This function completed successfully.
753 EbcDebugSignalException (
754 IN EFI_EXCEPTION_TYPE ExceptionType
,
755 IN EXCEPTION_FLAGS ExceptionFlags
,
759 EFI_SYSTEM_CONTEXT_EBC EbcContext
;
760 EFI_SYSTEM_CONTEXT SystemContext
;
762 ASSERT ((ExceptionType
>= 0) && (ExceptionType
<= MAX_EBC_EXCEPTION
));
764 // Save the exception in the context passed in
766 VmPtr
->ExceptionFlags
|= ExceptionFlags
;
767 VmPtr
->LastException
= ExceptionType
;
769 // If it's a fatal exception, then flag it in the VM context in case an
770 // attached debugger tries to return from it.
772 if ((ExceptionFlags
& EXCEPTION_FLAG_FATAL
) != 0) {
773 VmPtr
->StopFlags
|= STOPFLAG_APP_DONE
;
777 // If someone's registered for exception callbacks, then call them.
779 // EBC driver will register default exception callback to report the
780 // status code via the status code API
782 if (mDebugExceptionCallback
[ExceptionType
] != NULL
) {
785 // Initialize the context structure
787 EbcContext
.R0
= VmPtr
->R
[0];
788 EbcContext
.R1
= VmPtr
->R
[1];
789 EbcContext
.R2
= VmPtr
->R
[2];
790 EbcContext
.R3
= VmPtr
->R
[3];
791 EbcContext
.R4
= VmPtr
->R
[4];
792 EbcContext
.R5
= VmPtr
->R
[5];
793 EbcContext
.R6
= VmPtr
->R
[6];
794 EbcContext
.R7
= VmPtr
->R
[7];
795 EbcContext
.Ip
= (UINT64
)(UINTN
)VmPtr
->Ip
;
796 EbcContext
.Flags
= VmPtr
->Flags
;
797 EbcContext
.ControlFlags
= 0;
798 SystemContext
.SystemContextEbc
= &EbcContext
;
800 mDebugExceptionCallback
[ExceptionType
] (ExceptionType
, SystemContext
);
802 // Restore the context structure and continue to execute
804 VmPtr
->R
[0] = EbcContext
.R0
;
805 VmPtr
->R
[1] = EbcContext
.R1
;
806 VmPtr
->R
[2] = EbcContext
.R2
;
807 VmPtr
->R
[3] = EbcContext
.R3
;
808 VmPtr
->R
[4] = EbcContext
.R4
;
809 VmPtr
->R
[5] = EbcContext
.R5
;
810 VmPtr
->R
[6] = EbcContext
.R6
;
811 VmPtr
->R
[7] = EbcContext
.R7
;
812 VmPtr
->Ip
= (VMIP
)(UINTN
)EbcContext
.Ip
;
813 VmPtr
->Flags
= EbcContext
.Flags
;
821 To install default Callback function for the VM interpreter.
823 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
826 @retval EFI_SUCCESS The function completed successfully.
827 @retval Others Some error occurs when creating periodic event.
833 InitializeEbcCallback (
834 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
841 // For ExceptionCallback
843 for (Index
= 0; Index
<= MAX_EBC_EXCEPTION
; Index
++) {
844 EbcDebugRegisterExceptionCallback (
847 CommonEbcExceptionHandler
,
853 // For PeriodicCallback
855 Status
= gBS
->CreateEvent (
856 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
858 EbcPeriodicNotifyFunction
,
862 if (EFI_ERROR(Status
)) {
866 Status
= gBS
->SetTimer (
869 EBC_VM_PERIODIC_CALLBACK_RATE
871 if (EFI_ERROR(Status
)) {
880 The default Exception Callback for the VM interpreter.
881 In this function, we report status code, and print debug information
882 about EBC_CONTEXT, then dead loop.
884 @param InterruptType Interrupt type.
885 @param SystemContext EBC system context.
891 CommonEbcExceptionHandler (
892 IN EFI_EXCEPTION_TYPE InterruptType
,
893 IN EFI_SYSTEM_CONTEXT SystemContext
897 // We deadloop here to make it easy to debug this issue.
906 The periodic callback function for EBC VM interpreter, which is used
907 to support the EFI debug support protocol.
909 @param Event The Periodic Callback Event.
910 @param Context It should be the address of VM_CONTEXT pointer.
916 EbcPeriodicNotifyFunction (
923 VmPtr
= *(VM_CONTEXT
**)Context
;
926 EbcDebugPeriodic (VmPtr
);
934 The VM interpreter calls this function on a periodic basis to support
935 the EFI debug support protocol.
937 @param VmPtr Pointer to a VM context for passing info to the
940 @retval EFI_SUCCESS The function completed successfully.
950 EFI_SYSTEM_CONTEXT_EBC EbcContext
;
951 EFI_SYSTEM_CONTEXT SystemContext
;
954 // If someone's registered for periodic callbacks, then call them.
956 if (mDebugPeriodicCallback
!= NULL
) {
959 // Initialize the context structure
961 EbcContext
.R0
= VmPtr
->R
[0];
962 EbcContext
.R1
= VmPtr
->R
[1];
963 EbcContext
.R2
= VmPtr
->R
[2];
964 EbcContext
.R3
= VmPtr
->R
[3];
965 EbcContext
.R4
= VmPtr
->R
[4];
966 EbcContext
.R5
= VmPtr
->R
[5];
967 EbcContext
.R6
= VmPtr
->R
[6];
968 EbcContext
.R7
= VmPtr
->R
[7];
969 EbcContext
.Ip
= (UINT64
)(UINTN
)VmPtr
->Ip
;
970 EbcContext
.Flags
= VmPtr
->Flags
;
971 EbcContext
.ControlFlags
= 0;
972 SystemContext
.SystemContextEbc
= &EbcContext
;
974 mDebugPeriodicCallback (SystemContext
);
977 // Restore the context structure and continue to execute
979 VmPtr
->R
[0] = EbcContext
.R0
;
980 VmPtr
->R
[1] = EbcContext
.R1
;
981 VmPtr
->R
[2] = EbcContext
.R2
;
982 VmPtr
->R
[3] = EbcContext
.R3
;
983 VmPtr
->R
[4] = EbcContext
.R4
;
984 VmPtr
->R
[5] = EbcContext
.R5
;
985 VmPtr
->R
[6] = EbcContext
.R6
;
986 VmPtr
->R
[7] = EbcContext
.R7
;
987 VmPtr
->Ip
= (VMIP
)(UINTN
)EbcContext
.Ip
;
988 VmPtr
->Flags
= EbcContext
.Flags
;
996 This routine is called by the core when an image is being unloaded from
997 memory. Basically we now have the opportunity to do any necessary cleanup.
998 Typically this will include freeing any memory allocated for thunk-creation.
1000 @param This A pointer to the EFI_EBC_PROTOCOL instance.
1001 @param ImageHandle Handle of image for which the thunk is being
1004 @retval EFI_INVALID_PARAMETER The ImageHandle passed in was not found in the
1005 internal list of EBC image handles.
1006 @retval EFI_SUCCESS The function completed successfully.
1013 IN EFI_EBC_PROTOCOL
*This
,
1014 IN EFI_HANDLE ImageHandle
1017 EBC_THUNK_LIST
*ThunkList
;
1018 EBC_THUNK_LIST
*NextThunkList
;
1019 EBC_IMAGE_LIST
*ImageList
;
1020 EBC_IMAGE_LIST
*PrevImageList
;
1022 // First go through our list of known image handles and see if we've already
1023 // created an image list element for this image handle.
1025 ReturnEBCStackByHandle(ImageHandle
);
1026 PrevImageList
= NULL
;
1027 for (ImageList
= mEbcImageList
; ImageList
!= NULL
; ImageList
= ImageList
->Next
) {
1028 if (ImageList
->ImageHandle
== ImageHandle
) {
1032 // Save the previous so we can connect the lists when we remove this one
1034 PrevImageList
= ImageList
;
1037 if (ImageList
== NULL
) {
1038 return EFI_INVALID_PARAMETER
;
1041 // Free up all the thunk buffers and thunks list elements for this image
1044 ThunkList
= ImageList
->ThunkList
;
1045 while (ThunkList
!= NULL
) {
1046 NextThunkList
= ThunkList
->Next
;
1047 FreePool (ThunkList
->ThunkBuffer
);
1048 FreePool (ThunkList
);
1049 ThunkList
= NextThunkList
;
1052 // Now remove this image list element from the chain
1054 if (PrevImageList
== NULL
) {
1058 mEbcImageList
= ImageList
->Next
;
1060 PrevImageList
->Next
= ImageList
->Next
;
1063 // Now free up the image list element
1065 FreePool (ImageList
);
1071 Add a thunk to our list of thunks for a given image handle.
1072 Also flush the instruction cache since we've written thunk code
1073 to memory that will be executed eventually.
1075 @param ImageHandle The image handle to which the thunk is tied.
1076 @param ThunkBuffer The buffer that has been created/allocated.
1077 @param ThunkSize The size of the thunk memory allocated.
1079 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
1080 @retval EFI_SUCCESS The function completed successfully.
1085 IN EFI_HANDLE ImageHandle
,
1086 IN VOID
*ThunkBuffer
,
1090 EBC_THUNK_LIST
*ThunkList
;
1091 EBC_IMAGE_LIST
*ImageList
;
1095 // It so far so good, then flush the instruction cache
1097 if (mEbcICacheFlush
!= NULL
) {
1098 Status
= mEbcICacheFlush ((EFI_PHYSICAL_ADDRESS
) (UINTN
) ThunkBuffer
, ThunkSize
);
1099 if (EFI_ERROR (Status
)) {
1104 // Go through our list of known image handles and see if we've already
1105 // created a image list element for this image handle.
1107 for (ImageList
= mEbcImageList
; ImageList
!= NULL
; ImageList
= ImageList
->Next
) {
1108 if (ImageList
->ImageHandle
== ImageHandle
) {
1113 if (ImageList
== NULL
) {
1115 // Allocate a new one
1117 ImageList
= AllocatePool (sizeof (EBC_IMAGE_LIST
));
1119 if (ImageList
== NULL
) {
1120 return EFI_OUT_OF_RESOURCES
;
1123 ImageList
->ThunkList
= NULL
;
1124 ImageList
->ImageHandle
= ImageHandle
;
1125 ImageList
->Next
= mEbcImageList
;
1126 mEbcImageList
= ImageList
;
1129 // Ok, now create a new thunk element to add to the list
1131 ThunkList
= AllocatePool (sizeof (EBC_THUNK_LIST
));
1133 if (ThunkList
== NULL
) {
1134 return EFI_OUT_OF_RESOURCES
;
1137 // Add it to the head of the list
1139 ThunkList
->Next
= ImageList
->ThunkList
;
1140 ThunkList
->ThunkBuffer
= ThunkBuffer
;
1141 ImageList
->ThunkList
= ThunkList
;
1146 Registers a callback function that the EBC interpreter calls to flush the
1147 processor instruction cache following creation of thunks.
1149 @param This A pointer to the EFI_EBC_PROTOCOL instance.
1150 @param Flush Pointer to a function of type EBC_ICACH_FLUSH.
1152 @retval EFI_SUCCESS The function completed successfully.
1158 EbcRegisterICacheFlush (
1159 IN EFI_EBC_PROTOCOL
*This
,
1160 IN EBC_ICACHE_FLUSH Flush
1163 mEbcICacheFlush
= Flush
;
1168 Called to get the version of the interpreter.
1170 @param This A pointer to the EFI_EBC_PROTOCOL instance.
1171 @param Version Pointer to where to store the returned version
1174 @retval EFI_SUCCESS The function completed successfully.
1175 @retval EFI_INVALID_PARAMETER Version pointer is NULL.
1182 IN EFI_EBC_PROTOCOL
*This
,
1183 IN OUT UINT64
*Version
1186 if (Version
== NULL
) {
1187 return EFI_INVALID_PARAMETER
;
1190 *Version
= GetVmVersion ();
1195 Returns the stack index and buffer assosicated with the Handle parameter.
1197 @param Handle The EFI handle as the index to the EBC stack.
1198 @param StackBuffer A pointer to hold the returned stack buffer.
1199 @param BufferIndex A pointer to hold the returned stack index.
1201 @retval EFI_OUT_OF_RESOURCES The Handle parameter does not correspond to any
1203 @retval EFI_SUCCESS The stack index and buffer were found and
1204 returned to the caller.
1209 IN EFI_HANDLE Handle
,
1210 OUT VOID
**StackBuffer
,
1211 OUT UINTN
*BufferIndex
1216 OldTpl
= gBS
->RaiseTPL(TPL_HIGH_LEVEL
);
1217 for (Index
= 0; Index
< mStackNum
; Index
++) {
1218 if (mStackBufferIndex
[Index
] == NULL
) {
1219 mStackBufferIndex
[Index
] = Handle
;
1223 gBS
->RestoreTPL(OldTpl
);
1224 if (Index
== mStackNum
) {
1225 return EFI_OUT_OF_RESOURCES
;
1227 *BufferIndex
= Index
;
1228 *StackBuffer
= mStackBuffer
[Index
];
1233 Returns from the EBC stack by stack Index.
1235 @param Index Specifies which EBC stack to return from.
1237 @retval EFI_SUCCESS The function completed successfully.
1245 mStackBufferIndex
[Index
] = NULL
;
1250 Returns from the EBC stack associated with the Handle parameter.
1252 @param Handle Specifies the EFI handle to find the EBC stack with.
1254 @retval EFI_SUCCESS The function completed successfully.
1258 ReturnEBCStackByHandle(
1259 IN EFI_HANDLE Handle
1263 for (Index
= 0; Index
< mStackNum
; Index
++) {
1264 if (mStackBufferIndex
[Index
] == Handle
) {
1268 if (Index
== mStackNum
) {
1269 return EFI_NOT_FOUND
;
1271 mStackBufferIndex
[Index
] = NULL
;
1276 Allocates memory to hold all the EBC stacks.
1278 @retval EFI_SUCCESS The EBC stacks were allocated successfully.
1279 @retval EFI_OUT_OF_RESOURCES Not enough memory available for EBC stacks.
1287 for (mStackNum
= 0; mStackNum
< MAX_STACK_NUM
; mStackNum
++) {
1288 mStackBuffer
[mStackNum
] = AllocatePool(STACK_POOL_SIZE
);
1289 mStackBufferIndex
[mStackNum
] = NULL
;
1290 if (mStackBuffer
[mStackNum
] == NULL
) {
1294 if (mStackNum
== 0) {
1295 return EFI_OUT_OF_RESOURCES
;
1302 Free all EBC stacks allocated before.
1304 @retval EFI_SUCCESS All the EBC stacks were freed.
1313 for (Index
= 0; Index
< mStackNum
; Index
++) {
1314 FreePool(mStackBuffer
[Index
]);
1320 Produces an EBC VM test protocol that can be used for regression tests.
1322 @param IHandle Handle on which to install the protocol.
1324 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
1325 @retval EFI_SUCCESS The function completed successfully.
1330 InitEbcVmTestProtocol (
1331 IN EFI_HANDLE
*IHandle
1336 EFI_EBC_VM_TEST_PROTOCOL
*EbcVmTestProtocol
;
1339 // Allocate memory for the protocol, then fill in the fields
1341 EbcVmTestProtocol
= AllocatePool (sizeof (EFI_EBC_VM_TEST_PROTOCOL
));
1342 if (EbcVmTestProtocol
== NULL
) {
1343 return EFI_OUT_OF_RESOURCES
;
1345 EbcVmTestProtocol
->Execute
= (EBC_VM_TEST_EXECUTE
) EbcExecuteInstructions
;
1347 DEBUG_CODE_BEGIN ();
1348 EbcVmTestProtocol
->Assemble
= (EBC_VM_TEST_ASM
) EbcVmTestUnsupported
;
1349 EbcVmTestProtocol
->Disassemble
= (EBC_VM_TEST_DASM
) EbcVmTestUnsupported
;
1353 // Publish the protocol
1356 Status
= gBS
->InstallProtocolInterface (&Handle
, &mEfiEbcVmTestProtocolGuid
, EFI_NATIVE_INTERFACE
, EbcVmTestProtocol
);
1357 if (EFI_ERROR (Status
)) {
1358 FreePool (EbcVmTestProtocol
);
1365 Returns the EFI_UNSUPPORTED Status.
1367 @return EFI_UNSUPPORTED This function always return EFI_UNSUPPORTED status.
1372 EbcVmTestUnsupported (
1376 return EFI_UNSUPPORTED
;