2 Top level module for the EBC virtual machine implementation.
3 Provides auxiliary support routines for the VM. That is, routines
4 that are not particularly related to VM execution of EBC instructions.
6 Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
12 #include "EbcExecute.h"
13 #include "EbcDebuggerHook.h"
16 // We'll keep track of all thunks we create in a linked list. Each
17 // thunk is tied to an image handle, so we have a linked list of
18 // image handles, with each having a linked list of thunks allocated
19 // to that image handle.
21 typedef struct _EBC_THUNK_LIST EBC_THUNK_LIST
;
22 struct _EBC_THUNK_LIST
{
27 typedef struct _EBC_IMAGE_LIST EBC_IMAGE_LIST
;
28 struct _EBC_IMAGE_LIST
{
30 EFI_HANDLE ImageHandle
;
31 EBC_THUNK_LIST
*ThunkList
;
35 This routine is called by the core when an image is being unloaded from
36 memory. Basically we now have the opportunity to do any necessary cleanup.
37 Typically this will include freeing any memory allocated for thunk-creation.
39 @param This A pointer to the EFI_EBC_PROTOCOL instance.
40 @param ImageHandle Handle of image for which the thunk is being
43 @retval EFI_INVALID_PARAMETER The ImageHandle passed in was not found in the
44 internal list of EBC image handles.
45 @retval EFI_SUCCESS The function completed successfully.
51 IN EFI_EBC_PROTOCOL
*This
,
52 IN EFI_HANDLE ImageHandle
56 This is the top-level routine plugged into the EBC protocol. Since thunks
57 are very processor-specific, from here we dispatch directly to the very
58 processor-specific routine EbcCreateThunks().
60 @param This A pointer to the EFI_EBC_PROTOCOL instance.
61 @param ImageHandle Handle of image for which the thunk is being
62 created. The EBC interpreter may use this to
63 keep track of any resource allocations
64 performed in loading and executing the image.
65 @param EbcEntryPoint Address of the actual EBC entry point or
66 protocol service the thunk should call.
67 @param Thunk Returned pointer to a thunk created.
69 @retval EFI_SUCCESS The function completed successfully.
70 @retval EFI_INVALID_PARAMETER Image entry point is not 2-byte aligned.
71 @retval EFI_OUT_OF_RESOURCES Memory could not be allocated for the thunk.
77 IN EFI_EBC_PROTOCOL
*This
,
78 IN EFI_HANDLE ImageHandle
,
79 IN VOID
*EbcEntryPoint
,
84 Called to get the version of the interpreter.
86 @param This A pointer to the EFI_EBC_PROTOCOL instance.
87 @param Version Pointer to where to store the returned version
90 @retval EFI_SUCCESS The function completed successfully.
91 @retval EFI_INVALID_PARAMETER Version pointer is NULL.
97 IN EFI_EBC_PROTOCOL
*This
,
98 IN OUT UINT64
*Version
102 To install default Callback function for the VM interpreter.
104 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
107 @retval EFI_SUCCESS The function completed successfully.
108 @retval Others Some error occurs when creating periodic event.
113 InitializeEbcCallback (
114 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
118 The default Exception Callback for the VM interpreter.
119 In this function, we report status code, and print debug information
120 about EBC_CONTEXT, then dead loop.
122 @param InterruptType Interrupt type.
123 @param SystemContext EBC system context.
128 CommonEbcExceptionHandler (
129 IN EFI_EXCEPTION_TYPE InterruptType
,
130 IN EFI_SYSTEM_CONTEXT SystemContext
134 The periodic callback function for EBC VM interpreter, which is used
135 to support the EFI debug support protocol.
137 @param Event The Periodic Callback Event.
138 @param Context It should be the address of VM_CONTEXT pointer.
143 EbcPeriodicNotifyFunction (
149 The VM interpreter calls this function on a periodic basis to support
150 the EFI debug support protocol.
152 @param VmPtr Pointer to a VM context for passing info to the
155 @retval EFI_SUCCESS The function completed successfully.
165 // These two functions and the GUID are used to produce an EBC test protocol.
166 // This functionality is definitely not required for execution.
169 Produces an EBC VM test protocol that can be used for regression tests.
171 @param IHandle Handle on which to install the protocol.
173 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
174 @retval EFI_SUCCESS The function completed successfully.
178 InitEbcVmTestProtocol (
179 IN EFI_HANDLE
*IHandle
183 Returns the EFI_UNSUPPORTED Status.
185 @return EFI_UNSUPPORTED This function always return EFI_UNSUPPORTED status.
190 EbcVmTestUnsupported (
195 Registers a callback function that the EBC interpreter calls to flush the
196 processor instruction cache following creation of thunks.
198 @param This A pointer to the EFI_EBC_PROTOCOL instance.
199 @param Flush Pointer to a function of type EBC_ICACH_FLUSH.
201 @retval EFI_SUCCESS The function completed successfully.
206 EbcRegisterICacheFlush (
207 IN EFI_EBC_PROTOCOL
*This
,
208 IN EBC_ICACHE_FLUSH Flush
212 This EBC debugger protocol service is called by the debug agent
214 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
216 @param MaxProcessorIndex Pointer to a caller-allocated UINTN in which the
217 maximum supported processor index is returned.
219 @retval EFI_SUCCESS The function completed successfully.
224 EbcDebugGetMaximumProcessorIndex (
225 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
226 OUT UINTN
*MaxProcessorIndex
230 This protocol service is called by the debug agent to register a function
231 for us to call on a periodic basis.
233 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
235 @param ProcessorIndex Specifies which processor the callback function
237 @param PeriodicCallback A pointer to a function of type
238 PERIODIC_CALLBACK that is the main periodic
239 entry point of the debug agent. It receives as a
240 parameter a pointer to the full context of the
241 interrupted execution thread.
243 @retval EFI_SUCCESS The function completed successfully.
244 @retval EFI_ALREADY_STARTED Non-NULL PeriodicCallback parameter when a
245 callback function was previously registered.
246 @retval EFI_INVALID_PARAMETER Null PeriodicCallback parameter when no
247 callback function was previously registered.
252 EbcDebugRegisterPeriodicCallback (
253 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
254 IN UINTN ProcessorIndex
,
255 IN EFI_PERIODIC_CALLBACK PeriodicCallback
259 This protocol service is called by the debug agent to register a function
260 for us to call when we detect an exception.
262 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
264 @param ProcessorIndex Specifies which processor the callback function
266 @param ExceptionCallback A pointer to a function of type
267 EXCEPTION_CALLBACK that is called when the
268 processor exception specified by ExceptionType
269 occurs. Passing NULL unregisters any previously
270 registered function associated with
272 @param ExceptionType Specifies which processor exception to hook.
274 @retval EFI_SUCCESS The function completed successfully.
275 @retval EFI_ALREADY_STARTED Non-NULL ExceptionCallback parameter when a
276 callback function was previously registered.
277 @retval EFI_INVALID_PARAMETER ExceptionType parameter is negative or exceeds
279 @retval EFI_INVALID_PARAMETER Null ExceptionCallback parameter when no
280 callback function was previously registered.
285 EbcDebugRegisterExceptionCallback (
286 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
287 IN UINTN ProcessorIndex
,
288 IN EFI_EXCEPTION_CALLBACK ExceptionCallback
,
289 IN EFI_EXCEPTION_TYPE ExceptionType
293 This EBC debugger protocol service is called by the debug agent. Required
294 for DebugSupport compliance but is only stubbed out for EBC.
296 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
298 @param ProcessorIndex Specifies which processor the callback function
300 @param Start StartSpecifies the physical base of the memory
301 range to be invalidated.
302 @param Length Specifies the minimum number of bytes in the
303 processor's instruction cache to invalidate.
305 @retval EFI_SUCCESS The function completed successfully.
310 EbcDebugInvalidateInstructionCache (
311 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
312 IN UINTN ProcessorIndex
,
318 // We have one linked list of image handles for the whole world. Since
319 // there should only be one interpreter, make them global. They must
320 // also be global since the execution of an EBC image does not provide
323 EBC_IMAGE_LIST
*mEbcImageList
= NULL
;
326 // Callback function to flush the icache after thunk creation
328 EBC_ICACHE_FLUSH mEbcICacheFlush
;
331 // These get set via calls by the debug agent
333 EFI_PERIODIC_CALLBACK mDebugPeriodicCallback
= NULL
;
334 EFI_EXCEPTION_CALLBACK mDebugExceptionCallback
[MAX_EBC_EXCEPTION
+ 1] = {NULL
};
336 VOID
*mStackBuffer
[MAX_STACK_NUM
];
337 EFI_HANDLE mStackBufferIndex
[MAX_STACK_NUM
];
341 // Event for Periodic callback
343 EFI_EVENT mEbcPeriodicEvent
;
344 VM_CONTEXT
*mVmPtr
= NULL
;
348 Initializes the VM EFI interface. Allocates memory for the VM interface
349 and registers the VM protocol.
351 @param ImageHandle EFI image handle.
352 @param SystemTable Pointer to the EFI system table.
354 @return Standard EFI status code.
359 InitializeEbcDriver (
360 IN EFI_HANDLE ImageHandle
,
361 IN EFI_SYSTEM_TABLE
*SystemTable
364 EFI_EBC_PROTOCOL
*EbcProtocol
;
365 EFI_EBC_PROTOCOL
*OldEbcProtocol
;
367 EFI_DEBUG_SUPPORT_PROTOCOL
*EbcDebugProtocol
;
368 EFI_HANDLE
*HandleBuffer
;
374 EbcDebugProtocol
= NULL
;
377 // Allocate memory for our protocol. Then fill in the blanks.
379 EbcProtocol
= AllocatePool (sizeof (EFI_EBC_PROTOCOL
));
381 if (EbcProtocol
== NULL
) {
382 return EFI_OUT_OF_RESOURCES
;
385 EbcProtocol
->CreateThunk
= EbcCreateThunk
;
386 EbcProtocol
->UnloadImage
= EbcUnloadImage
;
387 EbcProtocol
->RegisterICacheFlush
= EbcRegisterICacheFlush
;
388 EbcProtocol
->GetVersion
= EbcGetVersion
;
389 mEbcICacheFlush
= NULL
;
392 // Find any already-installed EBC protocols and uninstall them
396 Status
= gBS
->LocateHandleBuffer (
398 &gEfiEbcProtocolGuid
,
403 if (Status
== EFI_SUCCESS
) {
405 // Loop through the handles
407 for (Index
= 0; Index
< NumHandles
; Index
++) {
408 Status
= gBS
->HandleProtocol (
410 &gEfiEbcProtocolGuid
,
411 (VOID
**) &OldEbcProtocol
413 if (Status
== EFI_SUCCESS
) {
414 if (gBS
->ReinstallProtocolInterface (
416 &gEfiEbcProtocolGuid
,
426 if (HandleBuffer
!= NULL
) {
427 FreePool (HandleBuffer
);
431 // Add the protocol so someone can locate us if we haven't already.
434 Status
= gBS
->InstallProtocolInterface (
436 &gEfiEbcProtocolGuid
,
437 EFI_NATIVE_INTERFACE
,
440 if (EFI_ERROR (Status
)) {
441 FreePool (EbcProtocol
);
446 Status
= InitEBCStack();
447 if (EFI_ERROR(Status
)) {
452 // Allocate memory for our debug protocol. Then fill in the blanks.
454 EbcDebugProtocol
= AllocatePool (sizeof (EFI_DEBUG_SUPPORT_PROTOCOL
));
456 if (EbcDebugProtocol
== NULL
) {
460 EbcDebugProtocol
->Isa
= IsaEbc
;
461 EbcDebugProtocol
->GetMaximumProcessorIndex
= EbcDebugGetMaximumProcessorIndex
;
462 EbcDebugProtocol
->RegisterPeriodicCallback
= EbcDebugRegisterPeriodicCallback
;
463 EbcDebugProtocol
->RegisterExceptionCallback
= EbcDebugRegisterExceptionCallback
;
464 EbcDebugProtocol
->InvalidateInstructionCache
= EbcDebugInvalidateInstructionCache
;
467 // Add the protocol so the debug agent can find us
469 Status
= gBS
->InstallProtocolInterface (
471 &gEfiDebugSupportProtocolGuid
,
472 EFI_NATIVE_INTERFACE
,
476 // This is recoverable, so free the memory and continue.
478 if (EFI_ERROR (Status
)) {
479 FreePool (EbcDebugProtocol
);
483 // Install EbcDebugSupport Protocol Successfully
484 // Now we need to initialize the Ebc default Callback
486 Status
= InitializeEbcCallback (EbcDebugProtocol
);
489 // Produce a VM test interface protocol. Not required for execution.
492 InitEbcVmTestProtocol (&ImageHandle
);
495 EbcDebuggerHookInit (ImageHandle
, EbcDebugProtocol
);
502 Status
= gBS
->LocateHandleBuffer (
504 &gEfiEbcProtocolGuid
,
509 if (Status
== EFI_SUCCESS
) {
511 // Loop through the handles
513 for (Index
= 0; Index
< NumHandles
; Index
++) {
514 Status
= gBS
->HandleProtocol (
516 &gEfiEbcProtocolGuid
,
517 (VOID
**) &OldEbcProtocol
519 if (Status
== EFI_SUCCESS
) {
520 gBS
->UninstallProtocolInterface (
522 &gEfiEbcProtocolGuid
,
529 if (HandleBuffer
!= NULL
) {
530 FreePool (HandleBuffer
);
534 FreePool (EbcProtocol
);
541 This is the top-level routine plugged into the EBC protocol. Since thunks
542 are very processor-specific, from here we dispatch directly to the very
543 processor-specific routine EbcCreateThunks().
545 @param This A pointer to the EFI_EBC_PROTOCOL instance.
546 @param ImageHandle Handle of image for which the thunk is being
547 created. The EBC interpreter may use this to
548 keep track of any resource allocations
549 performed in loading and executing the image.
550 @param EbcEntryPoint Address of the actual EBC entry point or
551 protocol service the thunk should call.
552 @param Thunk Returned pointer to a thunk created.
554 @retval EFI_SUCCESS The function completed successfully.
555 @retval EFI_INVALID_PARAMETER Image entry point is not 2-byte aligned.
556 @retval EFI_OUT_OF_RESOURCES Memory could not be allocated for the thunk.
562 IN EFI_EBC_PROTOCOL
*This
,
563 IN EFI_HANDLE ImageHandle
,
564 IN VOID
*EbcEntryPoint
,
570 Status
= EbcCreateThunks (
574 FLAG_THUNK_ENTRY_POINT
581 This EBC debugger protocol service is called by the debug agent
583 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
585 @param MaxProcessorIndex Pointer to a caller-allocated UINTN in which the
586 maximum supported processor index is returned.
588 @retval EFI_SUCCESS The function completed successfully.
593 EbcDebugGetMaximumProcessorIndex (
594 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
595 OUT UINTN
*MaxProcessorIndex
598 *MaxProcessorIndex
= 0;
604 This protocol service is called by the debug agent to register a function
605 for us to call on a periodic basis.
607 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
609 @param ProcessorIndex Specifies which processor the callback function
611 @param PeriodicCallback A pointer to a function of type
612 PERIODIC_CALLBACK that is the main periodic
613 entry point of the debug agent. It receives as a
614 parameter a pointer to the full context of the
615 interrupted execution thread.
617 @retval EFI_SUCCESS The function completed successfully.
618 @retval EFI_ALREADY_STARTED Non-NULL PeriodicCallback parameter when a
619 callback function was previously registered.
620 @retval EFI_INVALID_PARAMETER Null PeriodicCallback parameter when no
621 callback function was previously registered.
626 EbcDebugRegisterPeriodicCallback (
627 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
628 IN UINTN ProcessorIndex
,
629 IN EFI_PERIODIC_CALLBACK PeriodicCallback
632 if ((mDebugPeriodicCallback
== NULL
) && (PeriodicCallback
== NULL
)) {
633 return EFI_INVALID_PARAMETER
;
635 if ((mDebugPeriodicCallback
!= NULL
) && (PeriodicCallback
!= NULL
)) {
636 return EFI_ALREADY_STARTED
;
639 mDebugPeriodicCallback
= PeriodicCallback
;
645 This protocol service is called by the debug agent to register a function
646 for us to call when we detect an exception.
648 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
650 @param ProcessorIndex Specifies which processor the callback function
652 @param ExceptionCallback A pointer to a function of type
653 EXCEPTION_CALLBACK that is called when the
654 processor exception specified by ExceptionType
655 occurs. Passing NULL unregisters any previously
656 registered function associated with
658 @param ExceptionType Specifies which processor exception to hook.
660 @retval EFI_SUCCESS The function completed successfully.
661 @retval EFI_ALREADY_STARTED Non-NULL ExceptionCallback parameter when a
662 callback function was previously registered.
663 @retval EFI_INVALID_PARAMETER ExceptionType parameter is negative or exceeds
665 @retval EFI_INVALID_PARAMETER Null ExceptionCallback parameter when no
666 callback function was previously registered.
671 EbcDebugRegisterExceptionCallback (
672 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
673 IN UINTN ProcessorIndex
,
674 IN EFI_EXCEPTION_CALLBACK ExceptionCallback
,
675 IN EFI_EXCEPTION_TYPE ExceptionType
678 if ((ExceptionType
< 0) || (ExceptionType
> MAX_EBC_EXCEPTION
)) {
679 return EFI_INVALID_PARAMETER
;
681 if ((mDebugExceptionCallback
[ExceptionType
] == NULL
) && (ExceptionCallback
== NULL
)) {
682 return EFI_INVALID_PARAMETER
;
684 if ((mDebugExceptionCallback
[ExceptionType
] != NULL
) && (ExceptionCallback
!= NULL
)) {
685 return EFI_ALREADY_STARTED
;
687 mDebugExceptionCallback
[ExceptionType
] = ExceptionCallback
;
693 This EBC debugger protocol service is called by the debug agent. Required
694 for DebugSupport compliance but is only stubbed out for EBC.
696 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
698 @param ProcessorIndex Specifies which processor the callback function
700 @param Start StartSpecifies the physical base of the memory
701 range to be invalidated.
702 @param Length Specifies the minimum number of bytes in the
703 processor's instruction cache to invalidate.
705 @retval EFI_SUCCESS The function completed successfully.
710 EbcDebugInvalidateInstructionCache (
711 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
,
712 IN UINTN ProcessorIndex
,
722 The VM interpreter calls this function when an exception is detected.
724 @param ExceptionType Specifies the processor exception detected.
725 @param ExceptionFlags Specifies the exception context.
726 @param VmPtr Pointer to a VM context for passing info to the
729 @retval EFI_SUCCESS This function completed successfully.
733 EbcDebugSignalException (
734 IN EFI_EXCEPTION_TYPE ExceptionType
,
735 IN EXCEPTION_FLAGS ExceptionFlags
,
739 EFI_SYSTEM_CONTEXT_EBC EbcContext
;
740 EFI_SYSTEM_CONTEXT SystemContext
;
742 ASSERT ((ExceptionType
>= 0) && (ExceptionType
<= MAX_EBC_EXCEPTION
));
744 // Save the exception in the context passed in
746 VmPtr
->ExceptionFlags
|= ExceptionFlags
;
747 VmPtr
->LastException
= (UINTN
) ExceptionType
;
749 // If it's a fatal exception, then flag it in the VM context in case an
750 // attached debugger tries to return from it.
752 if ((ExceptionFlags
& EXCEPTION_FLAG_FATAL
) != 0) {
753 VmPtr
->StopFlags
|= STOPFLAG_APP_DONE
;
757 // If someone's registered for exception callbacks, then call them.
759 // EBC driver will register default exception callback to report the
760 // status code via the status code API
762 if (mDebugExceptionCallback
[ExceptionType
] != NULL
) {
765 // Initialize the context structure
767 EbcContext
.R0
= (UINT64
) VmPtr
->Gpr
[0];
768 EbcContext
.R1
= (UINT64
) VmPtr
->Gpr
[1];
769 EbcContext
.R2
= (UINT64
) VmPtr
->Gpr
[2];
770 EbcContext
.R3
= (UINT64
) VmPtr
->Gpr
[3];
771 EbcContext
.R4
= (UINT64
) VmPtr
->Gpr
[4];
772 EbcContext
.R5
= (UINT64
) VmPtr
->Gpr
[5];
773 EbcContext
.R6
= (UINT64
) VmPtr
->Gpr
[6];
774 EbcContext
.R7
= (UINT64
) VmPtr
->Gpr
[7];
775 EbcContext
.Ip
= (UINT64
)(UINTN
)VmPtr
->Ip
;
776 EbcContext
.Flags
= VmPtr
->Flags
;
777 EbcContext
.ControlFlags
= 0;
778 SystemContext
.SystemContextEbc
= &EbcContext
;
780 mDebugExceptionCallback
[ExceptionType
] (ExceptionType
, SystemContext
);
782 // Restore the context structure and continue to execute
784 VmPtr
->Gpr
[0] = EbcContext
.R0
;
785 VmPtr
->Gpr
[1] = EbcContext
.R1
;
786 VmPtr
->Gpr
[2] = EbcContext
.R2
;
787 VmPtr
->Gpr
[3] = EbcContext
.R3
;
788 VmPtr
->Gpr
[4] = EbcContext
.R4
;
789 VmPtr
->Gpr
[5] = EbcContext
.R5
;
790 VmPtr
->Gpr
[6] = EbcContext
.R6
;
791 VmPtr
->Gpr
[7] = EbcContext
.R7
;
792 VmPtr
->Ip
= (VMIP
)(UINTN
)EbcContext
.Ip
;
793 VmPtr
->Flags
= EbcContext
.Flags
;
801 To install default Callback function for the VM interpreter.
803 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL
806 @retval EFI_SUCCESS The function completed successfully.
807 @retval Others Some error occurs when creating periodic event.
812 InitializeEbcCallback (
813 IN EFI_DEBUG_SUPPORT_PROTOCOL
*This
820 // For ExceptionCallback
822 for (Index
= 0; Index
<= MAX_EBC_EXCEPTION
; Index
++) {
823 EbcDebugRegisterExceptionCallback (
826 CommonEbcExceptionHandler
,
832 // For PeriodicCallback
834 Status
= gBS
->CreateEvent (
835 EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
837 EbcPeriodicNotifyFunction
,
841 if (EFI_ERROR(Status
)) {
845 Status
= gBS
->SetTimer (
848 EBC_VM_PERIODIC_CALLBACK_RATE
850 if (EFI_ERROR(Status
)) {
859 The default Exception Callback for the VM interpreter.
860 In this function, we report status code, and print debug information
861 about EBC_CONTEXT, then dead loop.
863 @param InterruptType Interrupt type.
864 @param SystemContext EBC system context.
869 CommonEbcExceptionHandler (
870 IN EFI_EXCEPTION_TYPE InterruptType
,
871 IN EFI_SYSTEM_CONTEXT SystemContext
875 // We print debug information to let user know what happen.
879 "EBC Interrupter Version - 0x%016lx\n",
880 (UINT64
) (((VM_MAJOR_VERSION
& 0xFFFF) << 16) | ((VM_MINOR_VERSION
& 0xFFFF)))
884 "Exception Type - 0x%016lx\n",
885 (UINT64
)(UINTN
)InterruptType
889 " R0 - 0x%016lx, R1 - 0x%016lx\n",
890 SystemContext
.SystemContextEbc
->R0
,
891 SystemContext
.SystemContextEbc
->R1
895 " R2 - 0x%016lx, R3 - 0x%016lx\n",
896 SystemContext
.SystemContextEbc
->R2
,
897 SystemContext
.SystemContextEbc
->R3
901 " R4 - 0x%016lx, R5 - 0x%016lx\n",
902 SystemContext
.SystemContextEbc
->R4
,
903 SystemContext
.SystemContextEbc
->R5
907 " R6 - 0x%016lx, R7 - 0x%016lx\n",
908 SystemContext
.SystemContextEbc
->R6
,
909 SystemContext
.SystemContextEbc
->R7
913 " Flags - 0x%016lx\n",
914 SystemContext
.SystemContextEbc
->Flags
918 " ControlFlags - 0x%016lx\n",
919 SystemContext
.SystemContextEbc
->ControlFlags
923 " Ip - 0x%016lx\n\n",
924 SystemContext
.SystemContextEbc
->Ip
928 // We deadloop here to make it easy to debug this issue.
937 The periodic callback function for EBC VM interpreter, which is used
938 to support the EFI debug support protocol.
940 @param Event The Periodic Callback Event.
941 @param Context It should be the address of VM_CONTEXT pointer.
946 EbcPeriodicNotifyFunction (
953 VmPtr
= *(VM_CONTEXT
**)Context
;
956 EbcDebugPeriodic (VmPtr
);
964 The VM interpreter calls this function on a periodic basis to support
965 the EFI debug support protocol.
967 @param VmPtr Pointer to a VM context for passing info to the
970 @retval EFI_SUCCESS The function completed successfully.
979 EFI_SYSTEM_CONTEXT_EBC EbcContext
;
980 EFI_SYSTEM_CONTEXT SystemContext
;
983 // If someone's registered for periodic callbacks, then call them.
985 if (mDebugPeriodicCallback
!= NULL
) {
988 // Initialize the context structure
990 EbcContext
.R0
= (UINT64
) VmPtr
->Gpr
[0];
991 EbcContext
.R1
= (UINT64
) VmPtr
->Gpr
[1];
992 EbcContext
.R2
= (UINT64
) VmPtr
->Gpr
[2];
993 EbcContext
.R3
= (UINT64
) VmPtr
->Gpr
[3];
994 EbcContext
.R4
= (UINT64
) VmPtr
->Gpr
[4];
995 EbcContext
.R5
= (UINT64
) VmPtr
->Gpr
[5];
996 EbcContext
.R6
= (UINT64
) VmPtr
->Gpr
[6];
997 EbcContext
.R7
= (UINT64
) VmPtr
->Gpr
[7];
998 EbcContext
.Ip
= (UINT64
)(UINTN
)VmPtr
->Ip
;
999 EbcContext
.Flags
= VmPtr
->Flags
;
1000 EbcContext
.ControlFlags
= 0;
1001 SystemContext
.SystemContextEbc
= &EbcContext
;
1003 mDebugPeriodicCallback (SystemContext
);
1006 // Restore the context structure and continue to execute
1008 VmPtr
->Gpr
[0] = EbcContext
.R0
;
1009 VmPtr
->Gpr
[1] = EbcContext
.R1
;
1010 VmPtr
->Gpr
[2] = EbcContext
.R2
;
1011 VmPtr
->Gpr
[3] = EbcContext
.R3
;
1012 VmPtr
->Gpr
[4] = EbcContext
.R4
;
1013 VmPtr
->Gpr
[5] = EbcContext
.R5
;
1014 VmPtr
->Gpr
[6] = EbcContext
.R6
;
1015 VmPtr
->Gpr
[7] = EbcContext
.R7
;
1016 VmPtr
->Ip
= (VMIP
)(UINTN
)EbcContext
.Ip
;
1017 VmPtr
->Flags
= EbcContext
.Flags
;
1025 This routine is called by the core when an image is being unloaded from
1026 memory. Basically we now have the opportunity to do any necessary cleanup.
1027 Typically this will include freeing any memory allocated for thunk-creation.
1029 @param This A pointer to the EFI_EBC_PROTOCOL instance.
1030 @param ImageHandle Handle of image for which the thunk is being
1033 @retval EFI_INVALID_PARAMETER The ImageHandle passed in was not found in the
1034 internal list of EBC image handles.
1035 @retval EFI_SUCCESS The function completed successfully.
1041 IN EFI_EBC_PROTOCOL
*This
,
1042 IN EFI_HANDLE ImageHandle
1045 EBC_THUNK_LIST
*ThunkList
;
1046 EBC_THUNK_LIST
*NextThunkList
;
1047 EBC_IMAGE_LIST
*ImageList
;
1048 EBC_IMAGE_LIST
*PrevImageList
;
1050 // First go through our list of known image handles and see if we've already
1051 // created an image list element for this image handle.
1053 ReturnEBCStackByHandle(ImageHandle
);
1054 PrevImageList
= NULL
;
1055 for (ImageList
= mEbcImageList
; ImageList
!= NULL
; ImageList
= ImageList
->Next
) {
1056 if (ImageList
->ImageHandle
== ImageHandle
) {
1060 // Save the previous so we can connect the lists when we remove this one
1062 PrevImageList
= ImageList
;
1065 if (ImageList
== NULL
) {
1066 return EFI_INVALID_PARAMETER
;
1069 // Free up all the thunk buffers and thunks list elements for this image
1072 ThunkList
= ImageList
->ThunkList
;
1073 while (ThunkList
!= NULL
) {
1074 NextThunkList
= ThunkList
->Next
;
1075 FreePool (ThunkList
->ThunkBuffer
);
1076 FreePool (ThunkList
);
1077 ThunkList
= NextThunkList
;
1080 // Now remove this image list element from the chain
1082 if (PrevImageList
== NULL
) {
1086 mEbcImageList
= ImageList
->Next
;
1088 PrevImageList
->Next
= ImageList
->Next
;
1091 // Now free up the image list element
1093 FreePool (ImageList
);
1095 EbcDebuggerHookEbcUnloadImage (ImageHandle
);
1102 Add a thunk to our list of thunks for a given image handle.
1103 Also flush the instruction cache since we've written thunk code
1104 to memory that will be executed eventually.
1106 @param ImageHandle The image handle to which the thunk is tied.
1107 @param ThunkBuffer The buffer that has been created/allocated.
1108 @param ThunkSize The size of the thunk memory allocated.
1110 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
1111 @retval EFI_SUCCESS The function completed successfully.
1116 IN EFI_HANDLE ImageHandle
,
1117 IN VOID
*ThunkBuffer
,
1121 EBC_THUNK_LIST
*ThunkList
;
1122 EBC_IMAGE_LIST
*ImageList
;
1126 // It so far so good, then flush the instruction cache
1128 if (mEbcICacheFlush
!= NULL
) {
1129 Status
= mEbcICacheFlush ((EFI_PHYSICAL_ADDRESS
) (UINTN
) ThunkBuffer
, ThunkSize
);
1130 if (EFI_ERROR (Status
)) {
1135 // Go through our list of known image handles and see if we've already
1136 // created a image list element for this image handle.
1138 for (ImageList
= mEbcImageList
; ImageList
!= NULL
; ImageList
= ImageList
->Next
) {
1139 if (ImageList
->ImageHandle
== ImageHandle
) {
1144 if (ImageList
== NULL
) {
1146 // Allocate a new one
1148 ImageList
= AllocatePool (sizeof (EBC_IMAGE_LIST
));
1150 if (ImageList
== NULL
) {
1151 return EFI_OUT_OF_RESOURCES
;
1154 ImageList
->ThunkList
= NULL
;
1155 ImageList
->ImageHandle
= ImageHandle
;
1156 ImageList
->Next
= mEbcImageList
;
1157 mEbcImageList
= ImageList
;
1160 // Ok, now create a new thunk element to add to the list
1162 ThunkList
= AllocatePool (sizeof (EBC_THUNK_LIST
));
1164 if (ThunkList
== NULL
) {
1165 return EFI_OUT_OF_RESOURCES
;
1168 // Add it to the head of the list
1170 ThunkList
->Next
= ImageList
->ThunkList
;
1171 ThunkList
->ThunkBuffer
= ThunkBuffer
;
1172 ImageList
->ThunkList
= ThunkList
;
1177 Registers a callback function that the EBC interpreter calls to flush the
1178 processor instruction cache following creation of thunks.
1180 @param This A pointer to the EFI_EBC_PROTOCOL instance.
1181 @param Flush Pointer to a function of type EBC_ICACH_FLUSH.
1183 @retval EFI_SUCCESS The function completed successfully.
1188 EbcRegisterICacheFlush (
1189 IN EFI_EBC_PROTOCOL
*This
,
1190 IN EBC_ICACHE_FLUSH Flush
1193 mEbcICacheFlush
= Flush
;
1198 Called to get the version of the interpreter.
1200 @param This A pointer to the EFI_EBC_PROTOCOL instance.
1201 @param Version Pointer to where to store the returned version
1204 @retval EFI_SUCCESS The function completed successfully.
1205 @retval EFI_INVALID_PARAMETER Version pointer is NULL.
1211 IN EFI_EBC_PROTOCOL
*This
,
1212 IN OUT UINT64
*Version
1215 if (Version
== NULL
) {
1216 return EFI_INVALID_PARAMETER
;
1219 *Version
= GetVmVersion ();
1224 Returns the stack index and buffer assosicated with the Handle parameter.
1226 @param Handle The EFI handle as the index to the EBC stack.
1227 @param StackBuffer A pointer to hold the returned stack buffer.
1228 @param BufferIndex A pointer to hold the returned stack index.
1230 @retval EFI_OUT_OF_RESOURCES The Handle parameter does not correspond to any
1232 @retval EFI_SUCCESS The stack index and buffer were found and
1233 returned to the caller.
1238 IN EFI_HANDLE Handle
,
1239 OUT VOID
**StackBuffer
,
1240 OUT UINTN
*BufferIndex
1245 OldTpl
= gBS
->RaiseTPL(TPL_HIGH_LEVEL
);
1246 for (Index
= 0; Index
< mStackNum
; Index
++) {
1247 if (mStackBufferIndex
[Index
] == NULL
) {
1248 mStackBufferIndex
[Index
] = Handle
;
1252 gBS
->RestoreTPL(OldTpl
);
1253 if (Index
== mStackNum
) {
1254 return EFI_OUT_OF_RESOURCES
;
1256 *BufferIndex
= Index
;
1257 *StackBuffer
= mStackBuffer
[Index
];
1262 Returns from the EBC stack by stack Index.
1264 @param Index Specifies which EBC stack to return from.
1266 @retval EFI_SUCCESS The function completed successfully.
1274 mStackBufferIndex
[Index
] = NULL
;
1279 Returns from the EBC stack associated with the Handle parameter.
1281 @param Handle Specifies the EFI handle to find the EBC stack with.
1283 @retval EFI_SUCCESS The function completed successfully.
1287 ReturnEBCStackByHandle(
1288 IN EFI_HANDLE Handle
1292 for (Index
= 0; Index
< mStackNum
; Index
++) {
1293 if (mStackBufferIndex
[Index
] == Handle
) {
1297 if (Index
== mStackNum
) {
1298 return EFI_NOT_FOUND
;
1300 mStackBufferIndex
[Index
] = NULL
;
1305 Allocates memory to hold all the EBC stacks.
1307 @retval EFI_SUCCESS The EBC stacks were allocated successfully.
1308 @retval EFI_OUT_OF_RESOURCES Not enough memory available for EBC stacks.
1316 for (mStackNum
= 0; mStackNum
< MAX_STACK_NUM
; mStackNum
++) {
1317 mStackBuffer
[mStackNum
] = AllocatePool(STACK_POOL_SIZE
);
1318 mStackBufferIndex
[mStackNum
] = NULL
;
1319 if (mStackBuffer
[mStackNum
] == NULL
) {
1323 if (mStackNum
== 0) {
1324 return EFI_OUT_OF_RESOURCES
;
1331 Free all EBC stacks allocated before.
1333 @retval EFI_SUCCESS All the EBC stacks were freed.
1342 for (Index
= 0; Index
< mStackNum
; Index
++) {
1343 FreePool(mStackBuffer
[Index
]);
1349 Produces an EBC VM test protocol that can be used for regression tests.
1351 @param IHandle Handle on which to install the protocol.
1353 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
1354 @retval EFI_SUCCESS The function completed successfully.
1358 InitEbcVmTestProtocol (
1359 IN EFI_HANDLE
*IHandle
1364 EFI_EBC_VM_TEST_PROTOCOL
*EbcVmTestProtocol
;
1367 // Allocate memory for the protocol, then fill in the fields
1369 EbcVmTestProtocol
= AllocatePool (sizeof (EFI_EBC_VM_TEST_PROTOCOL
));
1370 if (EbcVmTestProtocol
== NULL
) {
1371 return EFI_OUT_OF_RESOURCES
;
1373 EbcVmTestProtocol
->Execute
= (EBC_VM_TEST_EXECUTE
) EbcExecuteInstructions
;
1375 DEBUG_CODE_BEGIN ();
1376 EbcVmTestProtocol
->Assemble
= (EBC_VM_TEST_ASM
) EbcVmTestUnsupported
;
1377 EbcVmTestProtocol
->Disassemble
= (EBC_VM_TEST_DASM
) EbcVmTestUnsupported
;
1381 // Publish the protocol
1384 Status
= gBS
->InstallProtocolInterface (&Handle
, &gEfiEbcVmTestProtocolGuid
, EFI_NATIVE_INTERFACE
, EbcVmTestProtocol
);
1385 if (EFI_ERROR (Status
)) {
1386 FreePool (EbcVmTestProtocol
);
1393 Returns the EFI_UNSUPPORTED Status.
1395 @return EFI_UNSUPPORTED This function always return EFI_UNSUPPORTED status.
1400 EbcVmTestUnsupported (
1404 return EFI_UNSUPPORTED
;
1408 Allocates a buffer of type EfiBootServicesCode.
1410 @param AllocationSize The number of bytes to allocate.
1412 @return A pointer to the allocated buffer or NULL if allocation fails.
1417 EbcAllocatePoolForThunk (
1418 IN UINTN AllocationSize
1424 Status
= gBS
->AllocatePool (EfiBootServicesCode
, AllocationSize
, &Buffer
);
1425 if (EFI_ERROR (Status
)) {