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. <BR>
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.
54 IN EFI_EBC_PROTOCOL
*This
,
55 IN EFI_HANDLE ImageHandle
59 This is the top-level routine plugged into the EBC protocol. Since thunks
60 are very processor-specific, from here we dispatch directly to the very
61 processor-specific routine EbcCreateThunks().
63 @param This A pointer to the EFI_EBC_PROTOCOL instance.
64 @param ImageHandle Handle of image for which the thunk is being
65 created. The EBC interpreter may use this to
66 keep track of any resource allocations
67 performed in loading and executing the image.
68 @param EbcEntryPoint Address of the actual EBC entry point or
69 protocol service the thunk should call.
70 @param Thunk Returned pointer to a thunk created.
72 @retval EFI_SUCCESS The function completed successfully.
73 @retval EFI_INVALID_PARAMETER Image entry point is not 2-byte aligned.
74 @retval EFI_OUT_OF_RESOURCES Memory could not be allocated for the thunk.
80 IN EFI_EBC_PROTOCOL
*This
,
81 IN EFI_HANDLE ImageHandle
,
82 IN VOID
*EbcEntryPoint
,
87 Called to get the version of the interpreter.
89 @param This A pointer to the EFI_EBC_PROTOCOL instance.
90 @param Version Pointer to where to store the returned version
93 @retval EFI_SUCCESS The function completed successfully.
94 @retval EFI_INVALID_PARAMETER Version pointer is NULL.
100 IN EFI_EBC_PROTOCOL
*This
,
101 IN OUT UINT64
*Version
105 To install default Callback function for the VM interpreter.
107 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
110 @retval EFI_SUCCESS The function completed successfully.
111 @retval Others Some error occurs when creating periodic event.
116 InitializeEbcCallback (
117 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
121 The default Exception Callback for the VM interpreter.
122 In this function, we report status code, and print debug information
123 about EBC_CONTEXT, then dead loop.
125 @param InterruptType Interrupt type.
126 @param SystemContext EBC system context.
131 CommonEbcExceptionHandler (
132 IN EFI_EXCEPTION_TYPE InterruptType
,
133 IN EFI_SYSTEM_CONTEXT SystemContext
137 The periodic callback function for EBC VM interpreter, which is used
138 to support the EFI debug support protocol.
140 @param Event The Periodic Callback Event.
141 @param Context It should be the address of VM_CONTEXT pointer.
146 EbcPeriodicNotifyFunction (
152 The VM interpreter calls this function on a periodic basis to support
153 the EFI debug support protocol.
155 @param VmPtr Pointer to a VM context for passing info to the
158 @retval EFI_SUCCESS The function completed successfully.
168 // These two functions and the GUID are used to produce an EBC test protocol.
169 // This functionality is definitely not required for execution.
172 Produces an EBC VM test protocol that can be used for regression tests.
174 @param IHandle Handle on which to install the protocol.
176 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
177 @retval EFI_SUCCESS The function completed successfully.
181 InitEbcVmTestProtocol (
182 IN EFI_HANDLE
*IHandle
186 Returns the EFI_UNSUPPORTED Status.
188 @return EFI_UNSUPPORTED This function always return EFI_UNSUPPORTED status.
192 EbcVmTestUnsupported (
197 Registers a callback function that the EBC interpreter calls to flush the
198 processor instruction cache following creation of thunks.
200 @param This A pointer to the EFI_EBC_PROTOCOL instance.
201 @param Flush Pointer to a function of type EBC_ICACH_FLUSH.
203 @retval EFI_SUCCESS The function completed successfully.
208 EbcRegisterICacheFlush (
209 IN EFI_EBC_PROTOCOL
*This
,
210 IN EBC_ICACHE_FLUSH Flush
214 This EBC debugger protocol service is called by the debug agent
216 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
218 @param MaxProcessorIndex Pointer to a caller-allocated UINTN in which the
219 maximum supported processor index is returned.
221 @retval EFI_SUCCESS The function completed successfully.
226 EbcDebugGetMaximumProcessorIndex (
227 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
228 OUT UINTN
*MaxProcessorIndex
232 This protocol service is called by the debug agent to register a function
233 for us to call on a periodic basis.
235 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
237 @param ProcessorIndex Specifies which processor the callback function
239 @param PeriodicCallback A pointer to a function of type
240 PERIODIC_CALLBACK that is the main periodic
241 entry point of the debug agent. It receives as a
242 parameter a pointer to the full context of the
243 interrupted execution thread.
245 @retval EFI_SUCCESS The function completed successfully.
246 @retval EFI_ALREADY_STARTED Non-NULL PeriodicCallback parameter when a
247 callback function was previously registered.
248 @retval EFI_INVALID_PARAMETER Null PeriodicCallback parameter when no
249 callback function was previously registered.
254 EbcDebugRegisterPeriodicCallback (
255 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
256 IN UINTN ProcessorIndex
,
257 IN EFI_PERIODIC_CALLBACK PeriodicCallback
261 This protocol service is called by the debug agent to register a function
262 for us to call when we detect an exception.
264 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
266 @param ProcessorIndex Specifies which processor the callback function
268 @param ExceptionCallback A pointer to a function of type
269 EXCEPTION_CALLBACK that is called when the
270 processor exception specified by ExceptionType
271 occurs. Passing NULL unregisters any previously
272 registered function associated with
274 @param ExceptionType Specifies which processor exception to hook.
276 @retval EFI_SUCCESS The function completed successfully.
277 @retval EFI_ALREADY_STARTED Non-NULL ExceptionCallback parameter when a
278 callback function was previously registered.
279 @retval EFI_INVALID_PARAMETER ExceptionType parameter is negative or exceeds
281 @retval EFI_INVALID_PARAMETER Null ExceptionCallback parameter when no
282 callback function was previously registered.
287 EbcDebugRegisterExceptionCallback (
288 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
289 IN UINTN ProcessorIndex
,
290 IN EFI_EXCEPTION_CALLBACK ExceptionCallback
,
291 IN EFI_EXCEPTION_TYPE ExceptionType
295 This EBC debugger protocol service is called by the debug agent. Required
296 for DebugSupport compliance but is only stubbed out for EBC.
298 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
300 @param ProcessorIndex Specifies which processor the callback function
302 @param Start StartSpecifies the physical base of the memory
303 range to be invalidated.
304 @param Length Specifies the minimum number of bytes in the
305 processor's instruction cache to invalidate.
307 @retval EFI_SUCCESS The function completed successfully.
312 EbcDebugInvalidateInstructionCache (
313 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
314 IN UINTN ProcessorIndex
,
320 // We have one linked list of image handles for the whole world. Since
321 // there should only be one interpreter, make them global. They must
322 // also be global since the execution of an EBC image does not provide
325 EBC_IMAGE_LIST
*mEbcImageList
= NULL
;
328 // Callback function to flush the icache after thunk creation
330 EBC_ICACHE_FLUSH mEbcICacheFlush
;
333 // These get set via calls by the debug agent
335 EFI_PERIODIC_CALLBACK mDebugPeriodicCallback
= NULL
;
336 EFI_EXCEPTION_CALLBACK mDebugExceptionCallback
[MAX_EBC_EXCEPTION
+ 1] = {NULL
};
337 EFI_GUID mEfiEbcVmTestProtocolGuid
= EFI_EBC_VM_TEST_PROTOCOL_GUID
;
339 VOID
*mStackBuffer
[MAX_STACK_NUM
];
340 EFI_HANDLE mStackBufferIndex
[MAX_STACK_NUM
];
344 // Event for Periodic callback
346 EFI_EVENT mEbcPeriodicEvent
;
347 VM_CONTEXT
*mVmPtr
= NULL
;
351 Initializes the VM EFI interface. Allocates memory for the VM interface
352 and registers the VM protocol.
354 @param ImageHandle EFI image handle.
355 @param SystemTable Pointer to the EFI system table.
357 @return Standard EFI status code.
362 InitializeEbcDriver (
363 IN EFI_HANDLE ImageHandle
,
364 IN EFI_SYSTEM_TABLE
*SystemTable
367 EFI_EBC_PROTOCOL
*EbcProtocol
;
368 EFI_EBC_PROTOCOL
*OldEbcProtocol
;
370 EFI_DEBUG_SUPPORT_PROTOCOL
*EbcDebugProtocol
;
371 EFI_HANDLE
*HandleBuffer
;
377 EbcDebugProtocol
= NULL
;
380 // Allocate memory for our protocol. Then fill in the blanks.
382 EbcProtocol
= AllocatePool (sizeof (EFI_EBC_PROTOCOL
));
384 if (EbcProtocol
== NULL
) {
385 return EFI_OUT_OF_RESOURCES
;
388 EbcProtocol
->CreateThunk
= EbcCreateThunk
;
389 EbcProtocol
->UnloadImage
= EbcUnloadImage
;
390 EbcProtocol
->RegisterICacheFlush
= EbcRegisterICacheFlush
;
391 EbcProtocol
->GetVersion
= EbcGetVersion
;
392 mEbcICacheFlush
= NULL
;
395 // Find any already-installed EBC protocols and uninstall them
399 Status
= gBS
->LocateHandleBuffer (
401 &gEfiEbcProtocolGuid
,
406 if (Status
== EFI_SUCCESS
) {
408 // Loop through the handles
410 for (Index
= 0; Index
< NumHandles
; Index
++) {
411 Status
= gBS
->HandleProtocol (
413 &gEfiEbcProtocolGuid
,
414 (VOID
**) &OldEbcProtocol
416 if (Status
== EFI_SUCCESS
) {
417 if (gBS
->ReinstallProtocolInterface (
419 &gEfiEbcProtocolGuid
,
429 if (HandleBuffer
!= NULL
) {
430 FreePool (HandleBuffer
);
434 // Add the protocol so someone can locate us if we haven't already.
437 Status
= gBS
->InstallProtocolInterface (
439 &gEfiEbcProtocolGuid
,
440 EFI_NATIVE_INTERFACE
,
443 if (EFI_ERROR (Status
)) {
444 FreePool (EbcProtocol
);
449 Status
= InitEBCStack();
450 if (EFI_ERROR(Status
)) {
455 // Allocate memory for our debug protocol. Then fill in the blanks.
457 EbcDebugProtocol
= AllocatePool (sizeof (EFI_DEBUG_SUPPORT_PROTOCOL
));
459 if (EbcDebugProtocol
== NULL
) {
463 EbcDebugProtocol
->Isa
= IsaEbc
;
464 EbcDebugProtocol
->GetMaximumProcessorIndex
= EbcDebugGetMaximumProcessorIndex
;
465 EbcDebugProtocol
->RegisterPeriodicCallback
= EbcDebugRegisterPeriodicCallback
;
466 EbcDebugProtocol
->RegisterExceptionCallback
= EbcDebugRegisterExceptionCallback
;
467 EbcDebugProtocol
->InvalidateInstructionCache
= EbcDebugInvalidateInstructionCache
;
470 // Add the protocol so the debug agent can find us
472 Status
= gBS
->InstallProtocolInterface (
474 &gEfiDebugSupportProtocolGuid
,
475 EFI_NATIVE_INTERFACE
,
479 // This is recoverable, so free the memory and continue.
481 if (EFI_ERROR (Status
)) {
482 FreePool (EbcDebugProtocol
);
486 // Install EbcDebugSupport Protocol Successfully
487 // Now we need to initialize the Ebc default Callback
489 Status
= InitializeEbcCallback (EbcDebugProtocol
);
492 // Produce a VM test interface protocol. Not required for execution.
495 InitEbcVmTestProtocol (&ImageHandle
);
503 Status
= gBS
->LocateHandleBuffer (
505 &gEfiEbcProtocolGuid
,
510 if (Status
== EFI_SUCCESS
) {
512 // Loop through the handles
514 for (Index
= 0; Index
< NumHandles
; Index
++) {
515 Status
= gBS
->HandleProtocol (
517 &gEfiEbcProtocolGuid
,
518 (VOID
**) &OldEbcProtocol
520 if (Status
== EFI_SUCCESS
) {
521 gBS
->UninstallProtocolInterface (
523 &gEfiEbcProtocolGuid
,
530 if (HandleBuffer
!= NULL
) {
531 FreePool (HandleBuffer
);
535 FreePool (EbcProtocol
);
542 This is the top-level routine plugged into the EBC protocol. Since thunks
543 are very processor-specific, from here we dispatch directly to the very
544 processor-specific routine EbcCreateThunks().
546 @param This A pointer to the EFI_EBC_PROTOCOL instance.
547 @param ImageHandle Handle of image for which the thunk is being
548 created. The EBC interpreter may use this to
549 keep track of any resource allocations
550 performed in loading and executing the image.
551 @param EbcEntryPoint Address of the actual EBC entry point or
552 protocol service the thunk should call.
553 @param Thunk Returned pointer to a thunk created.
555 @retval EFI_SUCCESS The function completed successfully.
556 @retval EFI_INVALID_PARAMETER Image entry point is not 2-byte aligned.
557 @retval EFI_OUT_OF_RESOURCES Memory could not be allocated for the thunk.
563 IN EFI_EBC_PROTOCOL
*This
,
564 IN EFI_HANDLE ImageHandle
,
565 IN VOID
*EbcEntryPoint
,
571 Status
= EbcCreateThunks (
575 FLAG_THUNK_ENTRY_POINT
582 This EBC debugger protocol service is called by the debug agent
584 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
586 @param MaxProcessorIndex Pointer to a caller-allocated UINTN in which the
587 maximum supported processor index is returned.
589 @retval EFI_SUCCESS The function completed successfully.
594 EbcDebugGetMaximumProcessorIndex (
595 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
596 OUT UINTN
*MaxProcessorIndex
599 *MaxProcessorIndex
= 0;
605 This protocol service is called by the debug agent to register a function
606 for us to call on a periodic basis.
608 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
610 @param ProcessorIndex Specifies which processor the callback function
612 @param PeriodicCallback A pointer to a function of type
613 PERIODIC_CALLBACK that is the main periodic
614 entry point of the debug agent. It receives as a
615 parameter a pointer to the full context of the
616 interrupted execution thread.
618 @retval EFI_SUCCESS The function completed successfully.
619 @retval EFI_ALREADY_STARTED Non-NULL PeriodicCallback parameter when a
620 callback function was previously registered.
621 @retval EFI_INVALID_PARAMETER Null PeriodicCallback parameter when no
622 callback function was previously registered.
627 EbcDebugRegisterPeriodicCallback (
628 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
629 IN UINTN ProcessorIndex
,
630 IN EFI_PERIODIC_CALLBACK PeriodicCallback
633 if ((mDebugPeriodicCallback
== NULL
) && (PeriodicCallback
== NULL
)) {
634 return EFI_INVALID_PARAMETER
;
636 if ((mDebugPeriodicCallback
!= NULL
) && (PeriodicCallback
!= NULL
)) {
637 return EFI_ALREADY_STARTED
;
640 mDebugPeriodicCallback
= PeriodicCallback
;
646 This protocol service is called by the debug agent to register a function
647 for us to call when we detect an exception.
649 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
651 @param ProcessorIndex Specifies which processor the callback function
653 @param ExceptionCallback A pointer to a function of type
654 EXCEPTION_CALLBACK that is called when the
655 processor exception specified by ExceptionType
656 occurs. Passing NULL unregisters any previously
657 registered function associated with
659 @param ExceptionType Specifies which processor exception to hook.
661 @retval EFI_SUCCESS The function completed successfully.
662 @retval EFI_ALREADY_STARTED Non-NULL ExceptionCallback parameter when a
663 callback function was previously registered.
664 @retval EFI_INVALID_PARAMETER ExceptionType parameter is negative or exceeds
666 @retval EFI_INVALID_PARAMETER Null ExceptionCallback parameter when no
667 callback function was previously registered.
672 EbcDebugRegisterExceptionCallback (
673 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
674 IN UINTN ProcessorIndex
,
675 IN EFI_EXCEPTION_CALLBACK ExceptionCallback
,
676 IN EFI_EXCEPTION_TYPE ExceptionType
679 if ((ExceptionType
< 0) || (ExceptionType
> MAX_EBC_EXCEPTION
)) {
680 return EFI_INVALID_PARAMETER
;
682 if ((mDebugExceptionCallback
[ExceptionType
] == NULL
) && (ExceptionCallback
== NULL
)) {
683 return EFI_INVALID_PARAMETER
;
685 if ((mDebugExceptionCallback
[ExceptionType
] != NULL
) && (ExceptionCallback
!= NULL
)) {
686 return EFI_ALREADY_STARTED
;
688 mDebugExceptionCallback
[ExceptionType
] = ExceptionCallback
;
694 This EBC debugger protocol service is called by the debug agent. Required
695 for DebugSupport compliance but is only stubbed out for EBC.
697 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
699 @param ProcessorIndex Specifies which processor the callback function
701 @param Start StartSpecifies the physical base of the memory
702 range to be invalidated.
703 @param Length Specifies the minimum number of bytes in the
704 processor's instruction cache to invalidate.
706 @retval EFI_SUCCESS The function completed successfully.
711 EbcDebugInvalidateInstructionCache (
712 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
713 IN UINTN ProcessorIndex
,
723 The VM interpreter calls this function when an exception is detected.
725 @param ExceptionType Specifies the processor exception detected.
726 @param ExceptionFlags Specifies the exception context.
727 @param VmPtr Pointer to a VM context for passing info to the
730 @retval EFI_SUCCESS This function completed successfully.
734 EbcDebugSignalException (
735 IN EFI_EXCEPTION_TYPE ExceptionType
,
736 IN EXCEPTION_FLAGS ExceptionFlags
,
740 EFI_SYSTEM_CONTEXT_EBC EbcContext
;
741 EFI_SYSTEM_CONTEXT SystemContext
;
743 ASSERT ((ExceptionType
>= 0) && (ExceptionType
<= MAX_EBC_EXCEPTION
));
745 // Save the exception in the context passed in
747 VmPtr
->ExceptionFlags
|= ExceptionFlags
;
748 VmPtr
->LastException
= ExceptionType
;
750 // If it's a fatal exception, then flag it in the VM context in case an
751 // attached debugger tries to return from it.
753 if ((ExceptionFlags
& EXCEPTION_FLAG_FATAL
) != 0) {
754 VmPtr
->StopFlags
|= STOPFLAG_APP_DONE
;
758 // If someone's registered for exception callbacks, then call them.
760 // EBC driver will register default exception callback to report the
761 // status code via the status code API
763 if (mDebugExceptionCallback
[ExceptionType
] != NULL
) {
766 // Initialize the context structure
768 EbcContext
.R0
= VmPtr
->R
[0];
769 EbcContext
.R1
= VmPtr
->R
[1];
770 EbcContext
.R2
= VmPtr
->R
[2];
771 EbcContext
.R3
= VmPtr
->R
[3];
772 EbcContext
.R4
= VmPtr
->R
[4];
773 EbcContext
.R5
= VmPtr
->R
[5];
774 EbcContext
.R6
= VmPtr
->R
[6];
775 EbcContext
.R7
= VmPtr
->R
[7];
776 EbcContext
.Ip
= (UINT64
)(UINTN
)VmPtr
->Ip
;
777 EbcContext
.Flags
= VmPtr
->Flags
;
778 EbcContext
.ControlFlags
= 0;
779 SystemContext
.SystemContextEbc
= &EbcContext
;
781 mDebugExceptionCallback
[ExceptionType
] (ExceptionType
, SystemContext
);
783 // Restore the context structure and continue to execute
785 VmPtr
->R
[0] = EbcContext
.R0
;
786 VmPtr
->R
[1] = EbcContext
.R1
;
787 VmPtr
->R
[2] = EbcContext
.R2
;
788 VmPtr
->R
[3] = EbcContext
.R3
;
789 VmPtr
->R
[4] = EbcContext
.R4
;
790 VmPtr
->R
[5] = EbcContext
.R5
;
791 VmPtr
->R
[6] = EbcContext
.R6
;
792 VmPtr
->R
[7] = EbcContext
.R7
;
793 VmPtr
->Ip
= (VMIP
)(UINTN
)EbcContext
.Ip
;
794 VmPtr
->Flags
= EbcContext
.Flags
;
802 To install default Callback function for the VM interpreter.
804 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
807 @retval EFI_SUCCESS The function completed successfully.
808 @retval Others Some error occurs when creating periodic event.
813 InitializeEbcCallback (
814 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
821 // For ExceptionCallback
823 for (Index
= 0; Index
<= MAX_EBC_EXCEPTION
; Index
++) {
824 EbcDebugRegisterExceptionCallback (
827 CommonEbcExceptionHandler
,
833 // For PeriodicCallback
835 Status
= gBS
->CreateEvent (
836 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
838 EbcPeriodicNotifyFunction
,
842 if (EFI_ERROR(Status
)) {
846 Status
= gBS
->SetTimer (
849 EBC_VM_PERIODIC_CALLBACK_RATE
851 if (EFI_ERROR(Status
)) {
860 The default Exception Callback for the VM interpreter.
861 In this function, we report status code, and print debug information
862 about EBC_CONTEXT, then dead loop.
864 @param InterruptType Interrupt type.
865 @param SystemContext EBC system context.
870 CommonEbcExceptionHandler (
871 IN EFI_EXCEPTION_TYPE InterruptType
,
872 IN EFI_SYSTEM_CONTEXT SystemContext
876 // We deadloop here to make it easy to debug this issue.
885 The periodic callback function for EBC VM interpreter, which is used
886 to support the EFI debug support protocol.
888 @param Event The Periodic Callback Event.
889 @param Context It should be the address of VM_CONTEXT pointer.
894 EbcPeriodicNotifyFunction (
901 VmPtr
= *(VM_CONTEXT
**)Context
;
904 EbcDebugPeriodic (VmPtr
);
912 The VM interpreter calls this function on a periodic basis to support
913 the EFI debug support protocol.
915 @param VmPtr Pointer to a VM context for passing info to the
918 @retval EFI_SUCCESS The function completed successfully.
927 EFI_SYSTEM_CONTEXT_EBC EbcContext
;
928 EFI_SYSTEM_CONTEXT SystemContext
;
931 // If someone's registered for periodic callbacks, then call them.
933 if (mDebugPeriodicCallback
!= NULL
) {
936 // Initialize the context structure
938 EbcContext
.R0
= VmPtr
->R
[0];
939 EbcContext
.R1
= VmPtr
->R
[1];
940 EbcContext
.R2
= VmPtr
->R
[2];
941 EbcContext
.R3
= VmPtr
->R
[3];
942 EbcContext
.R4
= VmPtr
->R
[4];
943 EbcContext
.R5
= VmPtr
->R
[5];
944 EbcContext
.R6
= VmPtr
->R
[6];
945 EbcContext
.R7
= VmPtr
->R
[7];
946 EbcContext
.Ip
= (UINT64
)(UINTN
)VmPtr
->Ip
;
947 EbcContext
.Flags
= VmPtr
->Flags
;
948 EbcContext
.ControlFlags
= 0;
949 SystemContext
.SystemContextEbc
= &EbcContext
;
951 mDebugPeriodicCallback (SystemContext
);
954 // Restore the context structure and continue to execute
956 VmPtr
->R
[0] = EbcContext
.R0
;
957 VmPtr
->R
[1] = EbcContext
.R1
;
958 VmPtr
->R
[2] = EbcContext
.R2
;
959 VmPtr
->R
[3] = EbcContext
.R3
;
960 VmPtr
->R
[4] = EbcContext
.R4
;
961 VmPtr
->R
[5] = EbcContext
.R5
;
962 VmPtr
->R
[6] = EbcContext
.R6
;
963 VmPtr
->R
[7] = EbcContext
.R7
;
964 VmPtr
->Ip
= (VMIP
)(UINTN
)EbcContext
.Ip
;
965 VmPtr
->Flags
= EbcContext
.Flags
;
973 This routine is called by the core when an image is being unloaded from
974 memory. Basically we now have the opportunity to do any necessary cleanup.
975 Typically this will include freeing any memory allocated for thunk-creation.
977 @param This A pointer to the EFI_EBC_PROTOCOL instance.
978 @param ImageHandle Handle of image for which the thunk is being
981 @retval EFI_INVALID_PARAMETER The ImageHandle passed in was not found in the
982 internal list of EBC image handles.
983 @retval EFI_SUCCESS The function completed successfully.
989 IN EFI_EBC_PROTOCOL
*This
,
990 IN EFI_HANDLE ImageHandle
993 EBC_THUNK_LIST
*ThunkList
;
994 EBC_THUNK_LIST
*NextThunkList
;
995 EBC_IMAGE_LIST
*ImageList
;
996 EBC_IMAGE_LIST
*PrevImageList
;
998 // First go through our list of known image handles and see if we've already
999 // created an image list element for this image handle.
1001 ReturnEBCStackByHandle(ImageHandle
);
1002 PrevImageList
= NULL
;
1003 for (ImageList
= mEbcImageList
; ImageList
!= NULL
; ImageList
= ImageList
->Next
) {
1004 if (ImageList
->ImageHandle
== ImageHandle
) {
1008 // Save the previous so we can connect the lists when we remove this one
1010 PrevImageList
= ImageList
;
1013 if (ImageList
== NULL
) {
1014 return EFI_INVALID_PARAMETER
;
1017 // Free up all the thunk buffers and thunks list elements for this image
1020 ThunkList
= ImageList
->ThunkList
;
1021 while (ThunkList
!= NULL
) {
1022 NextThunkList
= ThunkList
->Next
;
1023 FreePool (ThunkList
->ThunkBuffer
);
1024 FreePool (ThunkList
);
1025 ThunkList
= NextThunkList
;
1028 // Now remove this image list element from the chain
1030 if (PrevImageList
== NULL
) {
1034 mEbcImageList
= ImageList
->Next
;
1036 PrevImageList
->Next
= ImageList
->Next
;
1039 // Now free up the image list element
1041 FreePool (ImageList
);
1047 Add a thunk to our list of thunks for a given image handle.
1048 Also flush the instruction cache since we've written thunk code
1049 to memory that will be executed eventually.
1051 @param ImageHandle The image handle to which the thunk is tied.
1052 @param ThunkBuffer The buffer that has been created/allocated.
1053 @param ThunkSize The size of the thunk memory allocated.
1055 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
1056 @retval EFI_SUCCESS The function completed successfully.
1061 IN EFI_HANDLE ImageHandle
,
1062 IN VOID
*ThunkBuffer
,
1066 EBC_THUNK_LIST
*ThunkList
;
1067 EBC_IMAGE_LIST
*ImageList
;
1071 // It so far so good, then flush the instruction cache
1073 if (mEbcICacheFlush
!= NULL
) {
1074 Status
= mEbcICacheFlush ((EFI_PHYSICAL_ADDRESS
) (UINTN
) ThunkBuffer
, ThunkSize
);
1075 if (EFI_ERROR (Status
)) {
1080 // Go through our list of known image handles and see if we've already
1081 // created a image list element for this image handle.
1083 for (ImageList
= mEbcImageList
; ImageList
!= NULL
; ImageList
= ImageList
->Next
) {
1084 if (ImageList
->ImageHandle
== ImageHandle
) {
1089 if (ImageList
== NULL
) {
1091 // Allocate a new one
1093 ImageList
= AllocatePool (sizeof (EBC_IMAGE_LIST
));
1095 if (ImageList
== NULL
) {
1096 return EFI_OUT_OF_RESOURCES
;
1099 ImageList
->ThunkList
= NULL
;
1100 ImageList
->ImageHandle
= ImageHandle
;
1101 ImageList
->Next
= mEbcImageList
;
1102 mEbcImageList
= ImageList
;
1105 // Ok, now create a new thunk element to add to the list
1107 ThunkList
= AllocatePool (sizeof (EBC_THUNK_LIST
));
1109 if (ThunkList
== NULL
) {
1110 return EFI_OUT_OF_RESOURCES
;
1113 // Add it to the head of the list
1115 ThunkList
->Next
= ImageList
->ThunkList
;
1116 ThunkList
->ThunkBuffer
= ThunkBuffer
;
1117 ImageList
->ThunkList
= ThunkList
;
1122 Registers a callback function that the EBC interpreter calls to flush the
1123 processor instruction cache following creation of thunks.
1125 @param This A pointer to the EFI_EBC_PROTOCOL instance.
1126 @param Flush Pointer to a function of type EBC_ICACH_FLUSH.
1128 @retval EFI_SUCCESS The function completed successfully.
1133 EbcRegisterICacheFlush (
1134 IN EFI_EBC_PROTOCOL
*This
,
1135 IN EBC_ICACHE_FLUSH Flush
1138 mEbcICacheFlush
= Flush
;
1143 Called to get the version of the interpreter.
1145 @param This A pointer to the EFI_EBC_PROTOCOL instance.
1146 @param Version Pointer to where to store the returned version
1149 @retval EFI_SUCCESS The function completed successfully.
1150 @retval EFI_INVALID_PARAMETER Version pointer is NULL.
1156 IN EFI_EBC_PROTOCOL
*This
,
1157 IN OUT UINT64
*Version
1160 if (Version
== NULL
) {
1161 return EFI_INVALID_PARAMETER
;
1164 *Version
= GetVmVersion ();
1169 Returns the stack index and buffer assosicated with the Handle parameter.
1171 @param Handle The EFI handle as the index to the EBC stack.
1172 @param StackBuffer A pointer to hold the returned stack buffer.
1173 @param BufferIndex A pointer to hold the returned stack index.
1175 @retval EFI_OUT_OF_RESOURCES The Handle parameter does not correspond to any
1177 @retval EFI_SUCCESS The stack index and buffer were found and
1178 returned to the caller.
1183 IN EFI_HANDLE Handle
,
1184 OUT VOID
**StackBuffer
,
1185 OUT UINTN
*BufferIndex
1190 OldTpl
= gBS
->RaiseTPL(TPL_HIGH_LEVEL
);
1191 for (Index
= 0; Index
< mStackNum
; Index
++) {
1192 if (mStackBufferIndex
[Index
] == NULL
) {
1193 mStackBufferIndex
[Index
] = Handle
;
1197 gBS
->RestoreTPL(OldTpl
);
1198 if (Index
== mStackNum
) {
1199 return EFI_OUT_OF_RESOURCES
;
1201 *BufferIndex
= Index
;
1202 *StackBuffer
= mStackBuffer
[Index
];
1207 Returns from the EBC stack by stack Index.
1209 @param Index Specifies which EBC stack to return from.
1211 @retval EFI_SUCCESS The function completed successfully.
1219 mStackBufferIndex
[Index
] = NULL
;
1224 Returns from the EBC stack associated with the Handle parameter.
1226 @param Handle Specifies the EFI handle to find the EBC stack with.
1228 @retval EFI_SUCCESS The function completed successfully.
1232 ReturnEBCStackByHandle(
1233 IN EFI_HANDLE Handle
1237 for (Index
= 0; Index
< mStackNum
; Index
++) {
1238 if (mStackBufferIndex
[Index
] == Handle
) {
1242 if (Index
== mStackNum
) {
1243 return EFI_NOT_FOUND
;
1245 mStackBufferIndex
[Index
] = NULL
;
1250 Allocates memory to hold all the EBC stacks.
1252 @retval EFI_SUCCESS The EBC stacks were allocated successfully.
1253 @retval EFI_OUT_OF_RESOURCES Not enough memory available for EBC stacks.
1261 for (mStackNum
= 0; mStackNum
< MAX_STACK_NUM
; mStackNum
++) {
1262 mStackBuffer
[mStackNum
] = AllocatePool(STACK_POOL_SIZE
);
1263 mStackBufferIndex
[mStackNum
] = NULL
;
1264 if (mStackBuffer
[mStackNum
] == NULL
) {
1268 if (mStackNum
== 0) {
1269 return EFI_OUT_OF_RESOURCES
;
1276 Free all EBC stacks allocated before.
1278 @retval EFI_SUCCESS All the EBC stacks were freed.
1287 for (Index
= 0; Index
< mStackNum
; Index
++) {
1288 FreePool(mStackBuffer
[Index
]);
1294 Produces an EBC VM test protocol that can be used for regression tests.
1296 @param IHandle Handle on which to install the protocol.
1298 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
1299 @retval EFI_SUCCESS The function completed successfully.
1303 InitEbcVmTestProtocol (
1304 IN EFI_HANDLE
*IHandle
1309 EFI_EBC_VM_TEST_PROTOCOL
*EbcVmTestProtocol
;
1312 // Allocate memory for the protocol, then fill in the fields
1314 EbcVmTestProtocol
= AllocatePool (sizeof (EFI_EBC_VM_TEST_PROTOCOL
));
1315 if (EbcVmTestProtocol
== NULL
) {
1316 return EFI_OUT_OF_RESOURCES
;
1318 EbcVmTestProtocol
->Execute
= (EBC_VM_TEST_EXECUTE
) EbcExecuteInstructions
;
1320 DEBUG_CODE_BEGIN ();
1321 EbcVmTestProtocol
->Assemble
= (EBC_VM_TEST_ASM
) EbcVmTestUnsupported
;
1322 EbcVmTestProtocol
->Disassemble
= (EBC_VM_TEST_DASM
) EbcVmTestUnsupported
;
1326 // Publish the protocol
1329 Status
= gBS
->InstallProtocolInterface (&Handle
, &mEfiEbcVmTestProtocolGuid
, EFI_NATIVE_INTERFACE
, EbcVmTestProtocol
);
1330 if (EFI_ERROR (Status
)) {
1331 FreePool (EbcVmTestProtocol
);
1338 Returns the EFI_UNSUPPORTED Status.
1340 @return EFI_UNSUPPORTED This function always return EFI_UNSUPPORTED status.
1344 EbcVmTestUnsupported (
1348 return EFI_UNSUPPORTED
;