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 - 2010, 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.
194 EbcVmTestUnsupported (
199 Registers a callback function that the EBC interpreter calls to flush the
200 processor instruction cache following creation of thunks.
202 @param This A pointer to the EFI_EBC_PROTOCOL instance.
203 @param Flush Pointer to a function of type EBC_ICACH_FLUSH.
205 @retval EFI_SUCCESS The function completed successfully.
210 EbcRegisterICacheFlush (
211 IN EFI_EBC_PROTOCOL
*This
,
212 IN EBC_ICACHE_FLUSH Flush
216 This EBC debugger protocol service is called by the debug agent
218 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
220 @param MaxProcessorIndex Pointer to a caller-allocated UINTN in which the
221 maximum supported processor index is returned.
223 @retval EFI_SUCCESS The function completed successfully.
228 EbcDebugGetMaximumProcessorIndex (
229 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
230 OUT UINTN
*MaxProcessorIndex
234 This protocol service is called by the debug agent to register a function
235 for us to call on a periodic basis.
237 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
239 @param ProcessorIndex Specifies which processor the callback function
241 @param PeriodicCallback A pointer to a function of type
242 PERIODIC_CALLBACK that is the main periodic
243 entry point of the debug agent. It receives as a
244 parameter a pointer to the full context of the
245 interrupted execution thread.
247 @retval EFI_SUCCESS The function completed successfully.
248 @retval EFI_ALREADY_STARTED Non-NULL PeriodicCallback parameter when a
249 callback function was previously registered.
250 @retval EFI_INVALID_PARAMETER Null PeriodicCallback parameter when no
251 callback function was previously registered.
256 EbcDebugRegisterPeriodicCallback (
257 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
258 IN UINTN ProcessorIndex
,
259 IN EFI_PERIODIC_CALLBACK PeriodicCallback
263 This protocol service is called by the debug agent to register a function
264 for us to call when we detect an exception.
266 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
268 @param ProcessorIndex Specifies which processor the callback function
270 @param ExceptionCallback A pointer to a function of type
271 EXCEPTION_CALLBACK that is called when the
272 processor exception specified by ExceptionType
273 occurs. Passing NULL unregisters any previously
274 registered function associated with
276 @param ExceptionType Specifies which processor exception to hook.
278 @retval EFI_SUCCESS The function completed successfully.
279 @retval EFI_ALREADY_STARTED Non-NULL ExceptionCallback parameter when a
280 callback function was previously registered.
281 @retval EFI_INVALID_PARAMETER ExceptionType parameter is negative or exceeds
283 @retval EFI_INVALID_PARAMETER Null ExceptionCallback parameter when no
284 callback function was previously registered.
289 EbcDebugRegisterExceptionCallback (
290 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
291 IN UINTN ProcessorIndex
,
292 IN EFI_EXCEPTION_CALLBACK ExceptionCallback
,
293 IN EFI_EXCEPTION_TYPE ExceptionType
297 This EBC debugger protocol service is called by the debug agent. Required
298 for DebugSupport compliance but is only stubbed out for EBC.
300 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
302 @param ProcessorIndex Specifies which processor the callback function
304 @param Start StartSpecifies the physical base of the memory
305 range to be invalidated.
306 @param Length Specifies the minimum number of bytes in the
307 processor's instruction cache to invalidate.
309 @retval EFI_SUCCESS The function completed successfully.
314 EbcDebugInvalidateInstructionCache (
315 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
316 IN UINTN ProcessorIndex
,
322 // We have one linked list of image handles for the whole world. Since
323 // there should only be one interpreter, make them global. They must
324 // also be global since the execution of an EBC image does not provide
327 EBC_IMAGE_LIST
*mEbcImageList
= NULL
;
330 // Callback function to flush the icache after thunk creation
332 EBC_ICACHE_FLUSH mEbcICacheFlush
;
335 // These get set via calls by the debug agent
337 EFI_PERIODIC_CALLBACK mDebugPeriodicCallback
= NULL
;
338 EFI_EXCEPTION_CALLBACK mDebugExceptionCallback
[MAX_EBC_EXCEPTION
+ 1] = {NULL
};
339 EFI_GUID mEfiEbcVmTestProtocolGuid
= EFI_EBC_VM_TEST_PROTOCOL_GUID
;
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 deadloop here to make it easy to debug this issue.
887 The periodic callback function for EBC VM interpreter, which is used
888 to support the EFI debug support protocol.
890 @param Event The Periodic Callback Event.
891 @param Context It should be the address of VM_CONTEXT pointer.
896 EbcPeriodicNotifyFunction (
903 VmPtr
= *(VM_CONTEXT
**)Context
;
906 EbcDebugPeriodic (VmPtr
);
914 The VM interpreter calls this function on a periodic basis to support
915 the EFI debug support protocol.
917 @param VmPtr Pointer to a VM context for passing info to the
920 @retval EFI_SUCCESS The function completed successfully.
929 EFI_SYSTEM_CONTEXT_EBC EbcContext
;
930 EFI_SYSTEM_CONTEXT SystemContext
;
933 // If someone's registered for periodic callbacks, then call them.
935 if (mDebugPeriodicCallback
!= NULL
) {
938 // Initialize the context structure
940 EbcContext
.R0
= (UINT64
) VmPtr
->Gpr
[0];
941 EbcContext
.R1
= (UINT64
) VmPtr
->Gpr
[1];
942 EbcContext
.R2
= (UINT64
) VmPtr
->Gpr
[2];
943 EbcContext
.R3
= (UINT64
) VmPtr
->Gpr
[3];
944 EbcContext
.R4
= (UINT64
) VmPtr
->Gpr
[4];
945 EbcContext
.R5
= (UINT64
) VmPtr
->Gpr
[5];
946 EbcContext
.R6
= (UINT64
) VmPtr
->Gpr
[6];
947 EbcContext
.R7
= (UINT64
) VmPtr
->Gpr
[7];
948 EbcContext
.Ip
= (UINT64
)(UINTN
)VmPtr
->Ip
;
949 EbcContext
.Flags
= VmPtr
->Flags
;
950 EbcContext
.ControlFlags
= 0;
951 SystemContext
.SystemContextEbc
= &EbcContext
;
953 mDebugPeriodicCallback (SystemContext
);
956 // Restore the context structure and continue to execute
958 VmPtr
->Gpr
[0] = EbcContext
.R0
;
959 VmPtr
->Gpr
[1] = EbcContext
.R1
;
960 VmPtr
->Gpr
[2] = EbcContext
.R2
;
961 VmPtr
->Gpr
[3] = EbcContext
.R3
;
962 VmPtr
->Gpr
[4] = EbcContext
.R4
;
963 VmPtr
->Gpr
[5] = EbcContext
.R5
;
964 VmPtr
->Gpr
[6] = EbcContext
.R6
;
965 VmPtr
->Gpr
[7] = EbcContext
.R7
;
966 VmPtr
->Ip
= (VMIP
)(UINTN
)EbcContext
.Ip
;
967 VmPtr
->Flags
= EbcContext
.Flags
;
975 This routine is called by the core when an image is being unloaded from
976 memory. Basically we now have the opportunity to do any necessary cleanup.
977 Typically this will include freeing any memory allocated for thunk-creation.
979 @param This A pointer to the EFI_EBC_PROTOCOL instance.
980 @param ImageHandle Handle of image for which the thunk is being
983 @retval EFI_INVALID_PARAMETER The ImageHandle passed in was not found in the
984 internal list of EBC image handles.
985 @retval EFI_SUCCESS The function completed successfully.
991 IN EFI_EBC_PROTOCOL
*This
,
992 IN EFI_HANDLE ImageHandle
995 EBC_THUNK_LIST
*ThunkList
;
996 EBC_THUNK_LIST
*NextThunkList
;
997 EBC_IMAGE_LIST
*ImageList
;
998 EBC_IMAGE_LIST
*PrevImageList
;
1000 // First go through our list of known image handles and see if we've already
1001 // created an image list element for this image handle.
1003 ReturnEBCStackByHandle(ImageHandle
);
1004 PrevImageList
= NULL
;
1005 for (ImageList
= mEbcImageList
; ImageList
!= NULL
; ImageList
= ImageList
->Next
) {
1006 if (ImageList
->ImageHandle
== ImageHandle
) {
1010 // Save the previous so we can connect the lists when we remove this one
1012 PrevImageList
= ImageList
;
1015 if (ImageList
== NULL
) {
1016 return EFI_INVALID_PARAMETER
;
1019 // Free up all the thunk buffers and thunks list elements for this image
1022 ThunkList
= ImageList
->ThunkList
;
1023 while (ThunkList
!= NULL
) {
1024 NextThunkList
= ThunkList
->Next
;
1025 FreePool (ThunkList
->ThunkBuffer
);
1026 FreePool (ThunkList
);
1027 ThunkList
= NextThunkList
;
1030 // Now remove this image list element from the chain
1032 if (PrevImageList
== NULL
) {
1036 mEbcImageList
= ImageList
->Next
;
1038 PrevImageList
->Next
= ImageList
->Next
;
1041 // Now free up the image list element
1043 FreePool (ImageList
);
1049 Add a thunk to our list of thunks for a given image handle.
1050 Also flush the instruction cache since we've written thunk code
1051 to memory that will be executed eventually.
1053 @param ImageHandle The image handle to which the thunk is tied.
1054 @param ThunkBuffer The buffer that has been created/allocated.
1055 @param ThunkSize The size of the thunk memory allocated.
1057 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
1058 @retval EFI_SUCCESS The function completed successfully.
1063 IN EFI_HANDLE ImageHandle
,
1064 IN VOID
*ThunkBuffer
,
1068 EBC_THUNK_LIST
*ThunkList
;
1069 EBC_IMAGE_LIST
*ImageList
;
1073 // It so far so good, then flush the instruction cache
1075 if (mEbcICacheFlush
!= NULL
) {
1076 Status
= mEbcICacheFlush ((EFI_PHYSICAL_ADDRESS
) (UINTN
) ThunkBuffer
, ThunkSize
);
1077 if (EFI_ERROR (Status
)) {
1082 // Go through our list of known image handles and see if we've already
1083 // created a image list element for this image handle.
1085 for (ImageList
= mEbcImageList
; ImageList
!= NULL
; ImageList
= ImageList
->Next
) {
1086 if (ImageList
->ImageHandle
== ImageHandle
) {
1091 if (ImageList
== NULL
) {
1093 // Allocate a new one
1095 ImageList
= AllocatePool (sizeof (EBC_IMAGE_LIST
));
1097 if (ImageList
== NULL
) {
1098 return EFI_OUT_OF_RESOURCES
;
1101 ImageList
->ThunkList
= NULL
;
1102 ImageList
->ImageHandle
= ImageHandle
;
1103 ImageList
->Next
= mEbcImageList
;
1104 mEbcImageList
= ImageList
;
1107 // Ok, now create a new thunk element to add to the list
1109 ThunkList
= AllocatePool (sizeof (EBC_THUNK_LIST
));
1111 if (ThunkList
== NULL
) {
1112 return EFI_OUT_OF_RESOURCES
;
1115 // Add it to the head of the list
1117 ThunkList
->Next
= ImageList
->ThunkList
;
1118 ThunkList
->ThunkBuffer
= ThunkBuffer
;
1119 ImageList
->ThunkList
= ThunkList
;
1124 Registers a callback function that the EBC interpreter calls to flush the
1125 processor instruction cache following creation of thunks.
1127 @param This A pointer to the EFI_EBC_PROTOCOL instance.
1128 @param Flush Pointer to a function of type EBC_ICACH_FLUSH.
1130 @retval EFI_SUCCESS The function completed successfully.
1135 EbcRegisterICacheFlush (
1136 IN EFI_EBC_PROTOCOL
*This
,
1137 IN EBC_ICACHE_FLUSH Flush
1140 mEbcICacheFlush
= Flush
;
1145 Called to get the version of the interpreter.
1147 @param This A pointer to the EFI_EBC_PROTOCOL instance.
1148 @param Version Pointer to where to store the returned version
1151 @retval EFI_SUCCESS The function completed successfully.
1152 @retval EFI_INVALID_PARAMETER Version pointer is NULL.
1158 IN EFI_EBC_PROTOCOL
*This
,
1159 IN OUT UINT64
*Version
1162 if (Version
== NULL
) {
1163 return EFI_INVALID_PARAMETER
;
1166 *Version
= GetVmVersion ();
1171 Returns the stack index and buffer assosicated with the Handle parameter.
1173 @param Handle The EFI handle as the index to the EBC stack.
1174 @param StackBuffer A pointer to hold the returned stack buffer.
1175 @param BufferIndex A pointer to hold the returned stack index.
1177 @retval EFI_OUT_OF_RESOURCES The Handle parameter does not correspond to any
1179 @retval EFI_SUCCESS The stack index and buffer were found and
1180 returned to the caller.
1185 IN EFI_HANDLE Handle
,
1186 OUT VOID
**StackBuffer
,
1187 OUT UINTN
*BufferIndex
1192 OldTpl
= gBS
->RaiseTPL(TPL_HIGH_LEVEL
);
1193 for (Index
= 0; Index
< mStackNum
; Index
++) {
1194 if (mStackBufferIndex
[Index
] == NULL
) {
1195 mStackBufferIndex
[Index
] = Handle
;
1199 gBS
->RestoreTPL(OldTpl
);
1200 if (Index
== mStackNum
) {
1201 return EFI_OUT_OF_RESOURCES
;
1203 *BufferIndex
= Index
;
1204 *StackBuffer
= mStackBuffer
[Index
];
1209 Returns from the EBC stack by stack Index.
1211 @param Index Specifies which EBC stack to return from.
1213 @retval EFI_SUCCESS The function completed successfully.
1221 mStackBufferIndex
[Index
] = NULL
;
1226 Returns from the EBC stack associated with the Handle parameter.
1228 @param Handle Specifies the EFI handle to find the EBC stack with.
1230 @retval EFI_SUCCESS The function completed successfully.
1234 ReturnEBCStackByHandle(
1235 IN EFI_HANDLE Handle
1239 for (Index
= 0; Index
< mStackNum
; Index
++) {
1240 if (mStackBufferIndex
[Index
] == Handle
) {
1244 if (Index
== mStackNum
) {
1245 return EFI_NOT_FOUND
;
1247 mStackBufferIndex
[Index
] = NULL
;
1252 Allocates memory to hold all the EBC stacks.
1254 @retval EFI_SUCCESS The EBC stacks were allocated successfully.
1255 @retval EFI_OUT_OF_RESOURCES Not enough memory available for EBC stacks.
1263 for (mStackNum
= 0; mStackNum
< MAX_STACK_NUM
; mStackNum
++) {
1264 mStackBuffer
[mStackNum
] = AllocatePool(STACK_POOL_SIZE
);
1265 mStackBufferIndex
[mStackNum
] = NULL
;
1266 if (mStackBuffer
[mStackNum
] == NULL
) {
1270 if (mStackNum
== 0) {
1271 return EFI_OUT_OF_RESOURCES
;
1278 Free all EBC stacks allocated before.
1280 @retval EFI_SUCCESS All the EBC stacks were freed.
1289 for (Index
= 0; Index
< mStackNum
; Index
++) {
1290 FreePool(mStackBuffer
[Index
]);
1296 Produces an EBC VM test protocol that can be used for regression tests.
1298 @param IHandle Handle on which to install the protocol.
1300 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
1301 @retval EFI_SUCCESS The function completed successfully.
1305 InitEbcVmTestProtocol (
1306 IN EFI_HANDLE
*IHandle
1311 EFI_EBC_VM_TEST_PROTOCOL
*EbcVmTestProtocol
;
1314 // Allocate memory for the protocol, then fill in the fields
1316 EbcVmTestProtocol
= AllocatePool (sizeof (EFI_EBC_VM_TEST_PROTOCOL
));
1317 if (EbcVmTestProtocol
== NULL
) {
1318 return EFI_OUT_OF_RESOURCES
;
1320 EbcVmTestProtocol
->Execute
= (EBC_VM_TEST_EXECUTE
) EbcExecuteInstructions
;
1322 DEBUG_CODE_BEGIN ();
1323 EbcVmTestProtocol
->Assemble
= (EBC_VM_TEST_ASM
) EbcVmTestUnsupported
;
1324 EbcVmTestProtocol
->Disassemble
= (EBC_VM_TEST_DASM
) EbcVmTestUnsupported
;
1328 // Publish the protocol
1331 Status
= gBS
->InstallProtocolInterface (&Handle
, &mEfiEbcVmTestProtocolGuid
, EFI_NATIVE_INTERFACE
, EbcVmTestProtocol
);
1332 if (EFI_ERROR (Status
)) {
1333 FreePool (EbcVmTestProtocol
);
1340 Returns the EFI_UNSUPPORTED Status.
1342 @return EFI_UNSUPPORTED This function always return EFI_UNSUPPORTED status.
1346 EbcVmTestUnsupported (
1350 return EFI_UNSUPPORTED
;