]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - MdeModulePkg/Universal/EbcDxe/EbcInt.c
Clean up the private GUID definition in module Level.
[mirror_edk2.git] / MdeModulePkg / Universal / EbcDxe / EbcInt.c
... / ...
CommitLineData
1/** @file\r
2 Top level module for the EBC virtual machine implementation.\r
3 Provides auxiliary support routines for the VM. That is, routines\r
4 that are not particularly related to VM execution of EBC instructions.\r
5\r
6Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
7This program and the accompanying materials\r
8are licensed and made available under the terms and conditions of the BSD License\r
9which accompanies this distribution. The full text of the license may be found at\r
10http://opensource.org/licenses/bsd-license.php\r
11\r
12THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
16\r
17#include "EbcInt.h"\r
18#include "EbcExecute.h"\r
19\r
20//\r
21// We'll keep track of all thunks we create in a linked list. Each\r
22// thunk is tied to an image handle, so we have a linked list of\r
23// image handles, with each having a linked list of thunks allocated\r
24// to that image handle.\r
25//\r
26typedef struct _EBC_THUNK_LIST EBC_THUNK_LIST;\r
27struct _EBC_THUNK_LIST {\r
28 VOID *ThunkBuffer;\r
29 EBC_THUNK_LIST *Next;\r
30};\r
31\r
32typedef struct _EBC_IMAGE_LIST EBC_IMAGE_LIST;\r
33struct _EBC_IMAGE_LIST {\r
34 EBC_IMAGE_LIST *Next;\r
35 EFI_HANDLE ImageHandle;\r
36 EBC_THUNK_LIST *ThunkList;\r
37};\r
38\r
39/**\r
40 This routine is called by the core when an image is being unloaded from\r
41 memory. Basically we now have the opportunity to do any necessary cleanup.\r
42 Typically this will include freeing any memory allocated for thunk-creation.\r
43\r
44 @param This A pointer to the EFI_EBC_PROTOCOL instance.\r
45 @param ImageHandle Handle of image for which the thunk is being\r
46 created.\r
47\r
48 @retval EFI_INVALID_PARAMETER The ImageHandle passed in was not found in the\r
49 internal list of EBC image handles.\r
50 @retval EFI_SUCCESS The function completed successfully.\r
51\r
52**/\r
53EFI_STATUS\r
54EFIAPI\r
55EbcUnloadImage (\r
56 IN EFI_EBC_PROTOCOL *This,\r
57 IN EFI_HANDLE ImageHandle\r
58 );\r
59\r
60/**\r
61 This is the top-level routine plugged into the EBC protocol. Since thunks\r
62 are very processor-specific, from here we dispatch directly to the very\r
63 processor-specific routine EbcCreateThunks().\r
64\r
65 @param This A pointer to the EFI_EBC_PROTOCOL instance.\r
66 @param ImageHandle Handle of image for which the thunk is being\r
67 created. The EBC interpreter may use this to\r
68 keep track of any resource allocations\r
69 performed in loading and executing the image.\r
70 @param EbcEntryPoint Address of the actual EBC entry point or\r
71 protocol service the thunk should call.\r
72 @param Thunk Returned pointer to a thunk created.\r
73\r
74 @retval EFI_SUCCESS The function completed successfully.\r
75 @retval EFI_INVALID_PARAMETER Image entry point is not 2-byte aligned.\r
76 @retval EFI_OUT_OF_RESOURCES Memory could not be allocated for the thunk.\r
77\r
78**/\r
79EFI_STATUS\r
80EFIAPI\r
81EbcCreateThunk (\r
82 IN EFI_EBC_PROTOCOL *This,\r
83 IN EFI_HANDLE ImageHandle,\r
84 IN VOID *EbcEntryPoint,\r
85 OUT VOID **Thunk\r
86 );\r
87\r
88/**\r
89 Called to get the version of the interpreter.\r
90\r
91 @param This A pointer to the EFI_EBC_PROTOCOL instance.\r
92 @param Version Pointer to where to store the returned version\r
93 of the interpreter.\r
94\r
95 @retval EFI_SUCCESS The function completed successfully.\r
96 @retval EFI_INVALID_PARAMETER Version pointer is NULL.\r
97\r
98**/\r
99EFI_STATUS\r
100EFIAPI\r
101EbcGetVersion (\r
102 IN EFI_EBC_PROTOCOL *This,\r
103 IN OUT UINT64 *Version\r
104 );\r
105\r
106/**\r
107 To install default Callback function for the VM interpreter.\r
108\r
109 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL\r
110 instance.\r
111\r
112 @retval EFI_SUCCESS The function completed successfully.\r
113 @retval Others Some error occurs when creating periodic event.\r
114\r
115**/\r
116EFI_STATUS\r
117EFIAPI\r
118InitializeEbcCallback (\r
119 IN EFI_DEBUG_SUPPORT_PROTOCOL *This\r
120 );\r
121\r
122/**\r
123 The default Exception Callback for the VM interpreter.\r
124 In this function, we report status code, and print debug information\r
125 about EBC_CONTEXT, then dead loop.\r
126\r
127 @param InterruptType Interrupt type.\r
128 @param SystemContext EBC system context.\r
129\r
130**/\r
131VOID\r
132EFIAPI\r
133CommonEbcExceptionHandler (\r
134 IN EFI_EXCEPTION_TYPE InterruptType,\r
135 IN EFI_SYSTEM_CONTEXT SystemContext\r
136 );\r
137\r
138/**\r
139 The periodic callback function for EBC VM interpreter, which is used\r
140 to support the EFI debug support protocol.\r
141\r
142 @param Event The Periodic Callback Event.\r
143 @param Context It should be the address of VM_CONTEXT pointer.\r
144\r
145**/\r
146VOID\r
147EFIAPI\r
148EbcPeriodicNotifyFunction (\r
149 IN EFI_EVENT Event,\r
150 IN VOID *Context\r
151 );\r
152\r
153/**\r
154 The VM interpreter calls this function on a periodic basis to support\r
155 the EFI debug support protocol.\r
156\r
157 @param VmPtr Pointer to a VM context for passing info to the\r
158 debugger.\r
159\r
160 @retval EFI_SUCCESS The function completed successfully.\r
161\r
162**/\r
163EFI_STATUS\r
164EFIAPI\r
165EbcDebugPeriodic (\r
166 IN VM_CONTEXT *VmPtr\r
167 );\r
168\r
169//\r
170// These two functions and the GUID are used to produce an EBC test protocol.\r
171// This functionality is definitely not required for execution.\r
172//\r
173/**\r
174 Produces an EBC VM test protocol that can be used for regression tests.\r
175\r
176 @param IHandle Handle on which to install the protocol.\r
177\r
178 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
179 @retval EFI_SUCCESS The function completed successfully.\r
180\r
181**/\r
182EFI_STATUS\r
183InitEbcVmTestProtocol (\r
184 IN EFI_HANDLE *IHandle\r
185 );\r
186\r
187/**\r
188 Returns the EFI_UNSUPPORTED Status.\r
189\r
190 @return EFI_UNSUPPORTED This function always return EFI_UNSUPPORTED status.\r
191\r
192**/\r
193EFI_STATUS\r
194EFIAPI\r
195EbcVmTestUnsupported (\r
196 VOID\r
197 );\r
198\r
199/**\r
200 Registers a callback function that the EBC interpreter calls to flush the\r
201 processor instruction cache following creation of thunks.\r
202\r
203 @param This A pointer to the EFI_EBC_PROTOCOL instance.\r
204 @param Flush Pointer to a function of type EBC_ICACH_FLUSH.\r
205\r
206 @retval EFI_SUCCESS The function completed successfully.\r
207\r
208**/\r
209EFI_STATUS\r
210EFIAPI\r
211EbcRegisterICacheFlush (\r
212 IN EFI_EBC_PROTOCOL *This,\r
213 IN EBC_ICACHE_FLUSH Flush\r
214 );\r
215\r
216/**\r
217 This EBC debugger protocol service is called by the debug agent\r
218\r
219 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL\r
220 instance.\r
221 @param MaxProcessorIndex Pointer to a caller-allocated UINTN in which the\r
222 maximum supported processor index is returned.\r
223\r
224 @retval EFI_SUCCESS The function completed successfully.\r
225\r
226**/\r
227EFI_STATUS\r
228EFIAPI\r
229EbcDebugGetMaximumProcessorIndex (\r
230 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
231 OUT UINTN *MaxProcessorIndex\r
232 );\r
233\r
234/**\r
235 This protocol service is called by the debug agent to register a function\r
236 for us to call on a periodic basis.\r
237\r
238 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL\r
239 instance.\r
240 @param ProcessorIndex Specifies which processor the callback function\r
241 applies to.\r
242 @param PeriodicCallback A pointer to a function of type\r
243 PERIODIC_CALLBACK that is the main periodic\r
244 entry point of the debug agent. It receives as a\r
245 parameter a pointer to the full context of the\r
246 interrupted execution thread.\r
247\r
248 @retval EFI_SUCCESS The function completed successfully.\r
249 @retval EFI_ALREADY_STARTED Non-NULL PeriodicCallback parameter when a\r
250 callback function was previously registered.\r
251 @retval EFI_INVALID_PARAMETER Null PeriodicCallback parameter when no\r
252 callback function was previously registered.\r
253\r
254**/\r
255EFI_STATUS\r
256EFIAPI\r
257EbcDebugRegisterPeriodicCallback (\r
258 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
259 IN UINTN ProcessorIndex,\r
260 IN EFI_PERIODIC_CALLBACK PeriodicCallback\r
261 );\r
262\r
263/**\r
264 This protocol service is called by the debug agent to register a function\r
265 for us to call when we detect an exception.\r
266\r
267 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL\r
268 instance.\r
269 @param ProcessorIndex Specifies which processor the callback function\r
270 applies to.\r
271 @param ExceptionCallback A pointer to a function of type\r
272 EXCEPTION_CALLBACK that is called when the\r
273 processor exception specified by ExceptionType\r
274 occurs. Passing NULL unregisters any previously\r
275 registered function associated with\r
276 ExceptionType.\r
277 @param ExceptionType Specifies which processor exception to hook.\r
278\r
279 @retval EFI_SUCCESS The function completed successfully.\r
280 @retval EFI_ALREADY_STARTED Non-NULL ExceptionCallback parameter when a\r
281 callback function was previously registered.\r
282 @retval EFI_INVALID_PARAMETER ExceptionType parameter is negative or exceeds\r
283 MAX_EBC_EXCEPTION.\r
284 @retval EFI_INVALID_PARAMETER Null ExceptionCallback parameter when no\r
285 callback function was previously registered.\r
286\r
287**/\r
288EFI_STATUS\r
289EFIAPI\r
290EbcDebugRegisterExceptionCallback (\r
291 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
292 IN UINTN ProcessorIndex,\r
293 IN EFI_EXCEPTION_CALLBACK ExceptionCallback,\r
294 IN EFI_EXCEPTION_TYPE ExceptionType\r
295 );\r
296\r
297/**\r
298 This EBC debugger protocol service is called by the debug agent. Required\r
299 for DebugSupport compliance but is only stubbed out for EBC.\r
300\r
301 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL\r
302 instance.\r
303 @param ProcessorIndex Specifies which processor the callback function\r
304 applies to.\r
305 @param Start StartSpecifies the physical base of the memory\r
306 range to be invalidated.\r
307 @param Length Specifies the minimum number of bytes in the\r
308 processor's instruction cache to invalidate.\r
309\r
310 @retval EFI_SUCCESS The function completed successfully.\r
311\r
312**/\r
313EFI_STATUS\r
314EFIAPI\r
315EbcDebugInvalidateInstructionCache (\r
316 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
317 IN UINTN ProcessorIndex,\r
318 IN VOID *Start,\r
319 IN UINT64 Length\r
320 );\r
321\r
322//\r
323// We have one linked list of image handles for the whole world. Since\r
324// there should only be one interpreter, make them global. They must\r
325// also be global since the execution of an EBC image does not provide\r
326// a This pointer.\r
327//\r
328EBC_IMAGE_LIST *mEbcImageList = NULL;\r
329\r
330//\r
331// Callback function to flush the icache after thunk creation\r
332//\r
333EBC_ICACHE_FLUSH mEbcICacheFlush;\r
334\r
335//\r
336// These get set via calls by the debug agent\r
337//\r
338EFI_PERIODIC_CALLBACK mDebugPeriodicCallback = NULL;\r
339EFI_EXCEPTION_CALLBACK mDebugExceptionCallback[MAX_EBC_EXCEPTION + 1] = {NULL};\r
340\r
341VOID *mStackBuffer[MAX_STACK_NUM];\r
342EFI_HANDLE mStackBufferIndex[MAX_STACK_NUM];\r
343UINTN mStackNum = 0;\r
344\r
345//\r
346// Event for Periodic callback\r
347//\r
348EFI_EVENT mEbcPeriodicEvent;\r
349VM_CONTEXT *mVmPtr = NULL;\r
350\r
351\r
352/**\r
353 Initializes the VM EFI interface. Allocates memory for the VM interface\r
354 and registers the VM protocol.\r
355\r
356 @param ImageHandle EFI image handle.\r
357 @param SystemTable Pointer to the EFI system table.\r
358\r
359 @return Standard EFI status code.\r
360\r
361**/\r
362EFI_STATUS\r
363EFIAPI\r
364InitializeEbcDriver (\r
365 IN EFI_HANDLE ImageHandle,\r
366 IN EFI_SYSTEM_TABLE *SystemTable\r
367 )\r
368{\r
369 EFI_EBC_PROTOCOL *EbcProtocol;\r
370 EFI_EBC_PROTOCOL *OldEbcProtocol;\r
371 EFI_STATUS Status;\r
372 EFI_DEBUG_SUPPORT_PROTOCOL *EbcDebugProtocol;\r
373 EFI_HANDLE *HandleBuffer;\r
374 UINTN NumHandles;\r
375 UINTN Index;\r
376 BOOLEAN Installed;\r
377\r
378 EbcProtocol = NULL;\r
379 EbcDebugProtocol = NULL;\r
380\r
381 //\r
382 // Allocate memory for our protocol. Then fill in the blanks.\r
383 //\r
384 EbcProtocol = AllocatePool (sizeof (EFI_EBC_PROTOCOL));\r
385\r
386 if (EbcProtocol == NULL) {\r
387 return EFI_OUT_OF_RESOURCES;\r
388 }\r
389\r
390 EbcProtocol->CreateThunk = EbcCreateThunk;\r
391 EbcProtocol->UnloadImage = EbcUnloadImage;\r
392 EbcProtocol->RegisterICacheFlush = EbcRegisterICacheFlush;\r
393 EbcProtocol->GetVersion = EbcGetVersion;\r
394 mEbcICacheFlush = NULL;\r
395\r
396 //\r
397 // Find any already-installed EBC protocols and uninstall them\r
398 //\r
399 Installed = FALSE;\r
400 HandleBuffer = NULL;\r
401 Status = gBS->LocateHandleBuffer (\r
402 ByProtocol,\r
403 &gEfiEbcProtocolGuid,\r
404 NULL,\r
405 &NumHandles,\r
406 &HandleBuffer\r
407 );\r
408 if (Status == EFI_SUCCESS) {\r
409 //\r
410 // Loop through the handles\r
411 //\r
412 for (Index = 0; Index < NumHandles; Index++) {\r
413 Status = gBS->HandleProtocol (\r
414 HandleBuffer[Index],\r
415 &gEfiEbcProtocolGuid,\r
416 (VOID **) &OldEbcProtocol\r
417 );\r
418 if (Status == EFI_SUCCESS) {\r
419 if (gBS->ReinstallProtocolInterface (\r
420 HandleBuffer[Index],\r
421 &gEfiEbcProtocolGuid,\r
422 OldEbcProtocol,\r
423 EbcProtocol\r
424 ) == EFI_SUCCESS) {\r
425 Installed = TRUE;\r
426 }\r
427 }\r
428 }\r
429 }\r
430\r
431 if (HandleBuffer != NULL) {\r
432 FreePool (HandleBuffer);\r
433 HandleBuffer = NULL;\r
434 }\r
435 //\r
436 // Add the protocol so someone can locate us if we haven't already.\r
437 //\r
438 if (!Installed) {\r
439 Status = gBS->InstallProtocolInterface (\r
440 &ImageHandle,\r
441 &gEfiEbcProtocolGuid,\r
442 EFI_NATIVE_INTERFACE,\r
443 EbcProtocol\r
444 );\r
445 if (EFI_ERROR (Status)) {\r
446 FreePool (EbcProtocol);\r
447 return Status;\r
448 }\r
449 }\r
450\r
451 Status = InitEBCStack();\r
452 if (EFI_ERROR(Status)) {\r
453 goto ErrorExit;\r
454 }\r
455\r
456 //\r
457 // Allocate memory for our debug protocol. Then fill in the blanks.\r
458 //\r
459 EbcDebugProtocol = AllocatePool (sizeof (EFI_DEBUG_SUPPORT_PROTOCOL));\r
460\r
461 if (EbcDebugProtocol == NULL) {\r
462 goto ErrorExit;\r
463 }\r
464\r
465 EbcDebugProtocol->Isa = IsaEbc;\r
466 EbcDebugProtocol->GetMaximumProcessorIndex = EbcDebugGetMaximumProcessorIndex;\r
467 EbcDebugProtocol->RegisterPeriodicCallback = EbcDebugRegisterPeriodicCallback;\r
468 EbcDebugProtocol->RegisterExceptionCallback = EbcDebugRegisterExceptionCallback;\r
469 EbcDebugProtocol->InvalidateInstructionCache = EbcDebugInvalidateInstructionCache;\r
470\r
471 //\r
472 // Add the protocol so the debug agent can find us\r
473 //\r
474 Status = gBS->InstallProtocolInterface (\r
475 &ImageHandle,\r
476 &gEfiDebugSupportProtocolGuid,\r
477 EFI_NATIVE_INTERFACE,\r
478 EbcDebugProtocol\r
479 );\r
480 //\r
481 // This is recoverable, so free the memory and continue.\r
482 //\r
483 if (EFI_ERROR (Status)) {\r
484 FreePool (EbcDebugProtocol);\r
485 goto ErrorExit;\r
486 }\r
487 //\r
488 // Install EbcDebugSupport Protocol Successfully\r
489 // Now we need to initialize the Ebc default Callback\r
490 //\r
491 Status = InitializeEbcCallback (EbcDebugProtocol);\r
492\r
493 //\r
494 // Produce a VM test interface protocol. Not required for execution.\r
495 //\r
496 DEBUG_CODE_BEGIN ();\r
497 InitEbcVmTestProtocol (&ImageHandle);\r
498 DEBUG_CODE_END ();\r
499\r
500 return EFI_SUCCESS;\r
501\r
502ErrorExit:\r
503 FreeEBCStack();\r
504 HandleBuffer = NULL;\r
505 Status = gBS->LocateHandleBuffer (\r
506 ByProtocol,\r
507 &gEfiEbcProtocolGuid,\r
508 NULL,\r
509 &NumHandles,\r
510 &HandleBuffer\r
511 );\r
512 if (Status == EFI_SUCCESS) {\r
513 //\r
514 // Loop through the handles\r
515 //\r
516 for (Index = 0; Index < NumHandles; Index++) {\r
517 Status = gBS->HandleProtocol (\r
518 HandleBuffer[Index],\r
519 &gEfiEbcProtocolGuid,\r
520 (VOID **) &OldEbcProtocol\r
521 );\r
522 if (Status == EFI_SUCCESS) {\r
523 gBS->UninstallProtocolInterface (\r
524 HandleBuffer[Index],\r
525 &gEfiEbcProtocolGuid,\r
526 OldEbcProtocol\r
527 );\r
528 }\r
529 }\r
530 }\r
531\r
532 if (HandleBuffer != NULL) {\r
533 FreePool (HandleBuffer);\r
534 HandleBuffer = NULL;\r
535 }\r
536\r
537 FreePool (EbcProtocol);\r
538\r
539 return Status;\r
540}\r
541\r
542\r
543/**\r
544 This is the top-level routine plugged into the EBC protocol. Since thunks\r
545 are very processor-specific, from here we dispatch directly to the very\r
546 processor-specific routine EbcCreateThunks().\r
547\r
548 @param This A pointer to the EFI_EBC_PROTOCOL instance.\r
549 @param ImageHandle Handle of image for which the thunk is being\r
550 created. The EBC interpreter may use this to\r
551 keep track of any resource allocations\r
552 performed in loading and executing the image.\r
553 @param EbcEntryPoint Address of the actual EBC entry point or\r
554 protocol service the thunk should call.\r
555 @param Thunk Returned pointer to a thunk created.\r
556\r
557 @retval EFI_SUCCESS The function completed successfully.\r
558 @retval EFI_INVALID_PARAMETER Image entry point is not 2-byte aligned.\r
559 @retval EFI_OUT_OF_RESOURCES Memory could not be allocated for the thunk.\r
560\r
561**/\r
562EFI_STATUS\r
563EFIAPI\r
564EbcCreateThunk (\r
565 IN EFI_EBC_PROTOCOL *This,\r
566 IN EFI_HANDLE ImageHandle,\r
567 IN VOID *EbcEntryPoint,\r
568 OUT VOID **Thunk\r
569 )\r
570{\r
571 EFI_STATUS Status;\r
572\r
573 Status = EbcCreateThunks (\r
574 ImageHandle,\r
575 EbcEntryPoint,\r
576 Thunk,\r
577 FLAG_THUNK_ENTRY_POINT\r
578 );\r
579 return Status;\r
580}\r
581\r
582\r
583/**\r
584 This EBC debugger protocol service is called by the debug agent\r
585\r
586 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL\r
587 instance.\r
588 @param MaxProcessorIndex Pointer to a caller-allocated UINTN in which the\r
589 maximum supported processor index is returned.\r
590\r
591 @retval EFI_SUCCESS The function completed successfully.\r
592\r
593**/\r
594EFI_STATUS\r
595EFIAPI\r
596EbcDebugGetMaximumProcessorIndex (\r
597 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
598 OUT UINTN *MaxProcessorIndex\r
599 )\r
600{\r
601 *MaxProcessorIndex = 0;\r
602 return EFI_SUCCESS;\r
603}\r
604\r
605\r
606/**\r
607 This protocol service is called by the debug agent to register a function\r
608 for us to call on a periodic basis.\r
609\r
610 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL\r
611 instance.\r
612 @param ProcessorIndex Specifies which processor the callback function\r
613 applies to.\r
614 @param PeriodicCallback A pointer to a function of type\r
615 PERIODIC_CALLBACK that is the main periodic\r
616 entry point of the debug agent. It receives as a\r
617 parameter a pointer to the full context of the\r
618 interrupted execution thread.\r
619\r
620 @retval EFI_SUCCESS The function completed successfully.\r
621 @retval EFI_ALREADY_STARTED Non-NULL PeriodicCallback parameter when a\r
622 callback function was previously registered.\r
623 @retval EFI_INVALID_PARAMETER Null PeriodicCallback parameter when no\r
624 callback function was previously registered.\r
625\r
626**/\r
627EFI_STATUS\r
628EFIAPI\r
629EbcDebugRegisterPeriodicCallback (\r
630 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
631 IN UINTN ProcessorIndex,\r
632 IN EFI_PERIODIC_CALLBACK PeriodicCallback\r
633 )\r
634{\r
635 if ((mDebugPeriodicCallback == NULL) && (PeriodicCallback == NULL)) {\r
636 return EFI_INVALID_PARAMETER;\r
637 }\r
638 if ((mDebugPeriodicCallback != NULL) && (PeriodicCallback != NULL)) {\r
639 return EFI_ALREADY_STARTED;\r
640 }\r
641\r
642 mDebugPeriodicCallback = PeriodicCallback;\r
643 return EFI_SUCCESS;\r
644}\r
645\r
646\r
647/**\r
648 This protocol service is called by the debug agent to register a function\r
649 for us to call when we detect an exception.\r
650\r
651 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL\r
652 instance.\r
653 @param ProcessorIndex Specifies which processor the callback function\r
654 applies to.\r
655 @param ExceptionCallback A pointer to a function of type\r
656 EXCEPTION_CALLBACK that is called when the\r
657 processor exception specified by ExceptionType\r
658 occurs. Passing NULL unregisters any previously\r
659 registered function associated with\r
660 ExceptionType.\r
661 @param ExceptionType Specifies which processor exception to hook.\r
662\r
663 @retval EFI_SUCCESS The function completed successfully.\r
664 @retval EFI_ALREADY_STARTED Non-NULL ExceptionCallback parameter when a\r
665 callback function was previously registered.\r
666 @retval EFI_INVALID_PARAMETER ExceptionType parameter is negative or exceeds\r
667 MAX_EBC_EXCEPTION.\r
668 @retval EFI_INVALID_PARAMETER Null ExceptionCallback parameter when no\r
669 callback function was previously registered.\r
670\r
671**/\r
672EFI_STATUS\r
673EFIAPI\r
674EbcDebugRegisterExceptionCallback (\r
675 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
676 IN UINTN ProcessorIndex,\r
677 IN EFI_EXCEPTION_CALLBACK ExceptionCallback,\r
678 IN EFI_EXCEPTION_TYPE ExceptionType\r
679 )\r
680{\r
681 if ((ExceptionType < 0) || (ExceptionType > MAX_EBC_EXCEPTION)) {\r
682 return EFI_INVALID_PARAMETER;\r
683 }\r
684 if ((mDebugExceptionCallback[ExceptionType] == NULL) && (ExceptionCallback == NULL)) {\r
685 return EFI_INVALID_PARAMETER;\r
686 }\r
687 if ((mDebugExceptionCallback[ExceptionType] != NULL) && (ExceptionCallback != NULL)) {\r
688 return EFI_ALREADY_STARTED;\r
689 }\r
690 mDebugExceptionCallback[ExceptionType] = ExceptionCallback;\r
691 return EFI_SUCCESS;\r
692}\r
693\r
694\r
695/**\r
696 This EBC debugger protocol service is called by the debug agent. Required\r
697 for DebugSupport compliance but is only stubbed out for EBC.\r
698\r
699 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL\r
700 instance.\r
701 @param ProcessorIndex Specifies which processor the callback function\r
702 applies to.\r
703 @param Start StartSpecifies the physical base of the memory\r
704 range to be invalidated.\r
705 @param Length Specifies the minimum number of bytes in the\r
706 processor's instruction cache to invalidate.\r
707\r
708 @retval EFI_SUCCESS The function completed successfully.\r
709\r
710**/\r
711EFI_STATUS\r
712EFIAPI\r
713EbcDebugInvalidateInstructionCache (\r
714 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
715 IN UINTN ProcessorIndex,\r
716 IN VOID *Start,\r
717 IN UINT64 Length\r
718 )\r
719{\r
720 return EFI_SUCCESS;\r
721}\r
722\r
723\r
724/**\r
725 The VM interpreter calls this function when an exception is detected.\r
726\r
727 @param ExceptionType Specifies the processor exception detected.\r
728 @param ExceptionFlags Specifies the exception context.\r
729 @param VmPtr Pointer to a VM context for passing info to the\r
730 EFI debugger.\r
731\r
732 @retval EFI_SUCCESS This function completed successfully.\r
733\r
734**/\r
735EFI_STATUS\r
736EbcDebugSignalException (\r
737 IN EFI_EXCEPTION_TYPE ExceptionType,\r
738 IN EXCEPTION_FLAGS ExceptionFlags,\r
739 IN VM_CONTEXT *VmPtr\r
740 )\r
741{\r
742 EFI_SYSTEM_CONTEXT_EBC EbcContext;\r
743 EFI_SYSTEM_CONTEXT SystemContext;\r
744\r
745 ASSERT ((ExceptionType >= 0) && (ExceptionType <= MAX_EBC_EXCEPTION));\r
746 //\r
747 // Save the exception in the context passed in\r
748 //\r
749 VmPtr->ExceptionFlags |= ExceptionFlags;\r
750 VmPtr->LastException = (UINTN) ExceptionType;\r
751 //\r
752 // If it's a fatal exception, then flag it in the VM context in case an\r
753 // attached debugger tries to return from it.\r
754 //\r
755 if ((ExceptionFlags & EXCEPTION_FLAG_FATAL) != 0) {\r
756 VmPtr->StopFlags |= STOPFLAG_APP_DONE;\r
757 }\r
758\r
759 //\r
760 // If someone's registered for exception callbacks, then call them.\r
761 //\r
762 // EBC driver will register default exception callback to report the\r
763 // status code via the status code API\r
764 //\r
765 if (mDebugExceptionCallback[ExceptionType] != NULL) {\r
766\r
767 //\r
768 // Initialize the context structure\r
769 //\r
770 EbcContext.R0 = (UINT64) VmPtr->Gpr[0];\r
771 EbcContext.R1 = (UINT64) VmPtr->Gpr[1];\r
772 EbcContext.R2 = (UINT64) VmPtr->Gpr[2];\r
773 EbcContext.R3 = (UINT64) VmPtr->Gpr[3];\r
774 EbcContext.R4 = (UINT64) VmPtr->Gpr[4];\r
775 EbcContext.R5 = (UINT64) VmPtr->Gpr[5];\r
776 EbcContext.R6 = (UINT64) VmPtr->Gpr[6];\r
777 EbcContext.R7 = (UINT64) VmPtr->Gpr[7];\r
778 EbcContext.Ip = (UINT64)(UINTN)VmPtr->Ip;\r
779 EbcContext.Flags = VmPtr->Flags;\r
780 EbcContext.ControlFlags = 0;\r
781 SystemContext.SystemContextEbc = &EbcContext;\r
782\r
783 mDebugExceptionCallback[ExceptionType] (ExceptionType, SystemContext);\r
784 //\r
785 // Restore the context structure and continue to execute\r
786 //\r
787 VmPtr->Gpr[0] = EbcContext.R0;\r
788 VmPtr->Gpr[1] = EbcContext.R1;\r
789 VmPtr->Gpr[2] = EbcContext.R2;\r
790 VmPtr->Gpr[3] = EbcContext.R3;\r
791 VmPtr->Gpr[4] = EbcContext.R4;\r
792 VmPtr->Gpr[5] = EbcContext.R5;\r
793 VmPtr->Gpr[6] = EbcContext.R6;\r
794 VmPtr->Gpr[7] = EbcContext.R7;\r
795 VmPtr->Ip = (VMIP)(UINTN)EbcContext.Ip;\r
796 VmPtr->Flags = EbcContext.Flags;\r
797 }\r
798\r
799 return EFI_SUCCESS;\r
800}\r
801\r
802\r
803/**\r
804 To install default Callback function for the VM interpreter.\r
805\r
806 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL\r
807 instance.\r
808\r
809 @retval EFI_SUCCESS The function completed successfully.\r
810 @retval Others Some error occurs when creating periodic event.\r
811\r
812**/\r
813EFI_STATUS\r
814EFIAPI\r
815InitializeEbcCallback (\r
816 IN EFI_DEBUG_SUPPORT_PROTOCOL *This\r
817 )\r
818{\r
819 INTN Index;\r
820 EFI_STATUS Status;\r
821\r
822 //\r
823 // For ExceptionCallback\r
824 //\r
825 for (Index = 0; Index <= MAX_EBC_EXCEPTION; Index++) {\r
826 EbcDebugRegisterExceptionCallback (\r
827 This,\r
828 0,\r
829 CommonEbcExceptionHandler,\r
830 Index\r
831 );\r
832 }\r
833\r
834 //\r
835 // For PeriodicCallback\r
836 //\r
837 Status = gBS->CreateEvent (\r
838 EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
839 TPL_NOTIFY,\r
840 EbcPeriodicNotifyFunction,\r
841 &mVmPtr,\r
842 &mEbcPeriodicEvent\r
843 );\r
844 if (EFI_ERROR(Status)) {\r
845 return Status;\r
846 }\r
847\r
848 Status = gBS->SetTimer (\r
849 mEbcPeriodicEvent,\r
850 TimerPeriodic,\r
851 EBC_VM_PERIODIC_CALLBACK_RATE\r
852 );\r
853 if (EFI_ERROR(Status)) {\r
854 return Status;\r
855 }\r
856\r
857 return EFI_SUCCESS;\r
858}\r
859\r
860\r
861/**\r
862 The default Exception Callback for the VM interpreter.\r
863 In this function, we report status code, and print debug information\r
864 about EBC_CONTEXT, then dead loop.\r
865\r
866 @param InterruptType Interrupt type.\r
867 @param SystemContext EBC system context.\r
868\r
869**/\r
870VOID\r
871EFIAPI\r
872CommonEbcExceptionHandler (\r
873 IN EFI_EXCEPTION_TYPE InterruptType,\r
874 IN EFI_SYSTEM_CONTEXT SystemContext\r
875 )\r
876{\r
877 //\r
878 // We deadloop here to make it easy to debug this issue.\r
879 //\r
880 ASSERT (FALSE);\r
881\r
882 return ;\r
883}\r
884\r
885\r
886/**\r
887 The periodic callback function for EBC VM interpreter, which is used\r
888 to support the EFI debug support protocol.\r
889\r
890 @param Event The Periodic Callback Event.\r
891 @param Context It should be the address of VM_CONTEXT pointer.\r
892\r
893**/\r
894VOID\r
895EFIAPI\r
896EbcPeriodicNotifyFunction (\r
897 IN EFI_EVENT Event,\r
898 IN VOID *Context\r
899 )\r
900{\r
901 VM_CONTEXT *VmPtr;\r
902\r
903 VmPtr = *(VM_CONTEXT **)Context;\r
904\r
905 if (VmPtr != NULL) {\r
906 EbcDebugPeriodic (VmPtr);\r
907 }\r
908\r
909 return ;\r
910}\r
911\r
912\r
913/**\r
914 The VM interpreter calls this function on a periodic basis to support\r
915 the EFI debug support protocol.\r
916\r
917 @param VmPtr Pointer to a VM context for passing info to the\r
918 debugger.\r
919\r
920 @retval EFI_SUCCESS The function completed successfully.\r
921\r
922**/\r
923EFI_STATUS\r
924EFIAPI\r
925EbcDebugPeriodic (\r
926 IN VM_CONTEXT *VmPtr\r
927 )\r
928{\r
929 EFI_SYSTEM_CONTEXT_EBC EbcContext;\r
930 EFI_SYSTEM_CONTEXT SystemContext;\r
931\r
932 //\r
933 // If someone's registered for periodic callbacks, then call them.\r
934 //\r
935 if (mDebugPeriodicCallback != NULL) {\r
936\r
937 //\r
938 // Initialize the context structure\r
939 //\r
940 EbcContext.R0 = (UINT64) VmPtr->Gpr[0];\r
941 EbcContext.R1 = (UINT64) VmPtr->Gpr[1];\r
942 EbcContext.R2 = (UINT64) VmPtr->Gpr[2];\r
943 EbcContext.R3 = (UINT64) VmPtr->Gpr[3];\r
944 EbcContext.R4 = (UINT64) VmPtr->Gpr[4];\r
945 EbcContext.R5 = (UINT64) VmPtr->Gpr[5];\r
946 EbcContext.R6 = (UINT64) VmPtr->Gpr[6];\r
947 EbcContext.R7 = (UINT64) VmPtr->Gpr[7];\r
948 EbcContext.Ip = (UINT64)(UINTN)VmPtr->Ip;\r
949 EbcContext.Flags = VmPtr->Flags;\r
950 EbcContext.ControlFlags = 0;\r
951 SystemContext.SystemContextEbc = &EbcContext;\r
952\r
953 mDebugPeriodicCallback (SystemContext);\r
954\r
955 //\r
956 // Restore the context structure and continue to execute\r
957 //\r
958 VmPtr->Gpr[0] = EbcContext.R0;\r
959 VmPtr->Gpr[1] = EbcContext.R1;\r
960 VmPtr->Gpr[2] = EbcContext.R2;\r
961 VmPtr->Gpr[3] = EbcContext.R3;\r
962 VmPtr->Gpr[4] = EbcContext.R4;\r
963 VmPtr->Gpr[5] = EbcContext.R5;\r
964 VmPtr->Gpr[6] = EbcContext.R6;\r
965 VmPtr->Gpr[7] = EbcContext.R7;\r
966 VmPtr->Ip = (VMIP)(UINTN)EbcContext.Ip;\r
967 VmPtr->Flags = EbcContext.Flags;\r
968 }\r
969\r
970 return EFI_SUCCESS;\r
971}\r
972\r
973\r
974/**\r
975 This routine is called by the core when an image is being unloaded from\r
976 memory. Basically we now have the opportunity to do any necessary cleanup.\r
977 Typically this will include freeing any memory allocated for thunk-creation.\r
978\r
979 @param This A pointer to the EFI_EBC_PROTOCOL instance.\r
980 @param ImageHandle Handle of image for which the thunk is being\r
981 created.\r
982\r
983 @retval EFI_INVALID_PARAMETER The ImageHandle passed in was not found in the\r
984 internal list of EBC image handles.\r
985 @retval EFI_SUCCESS The function completed successfully.\r
986\r
987**/\r
988EFI_STATUS\r
989EFIAPI\r
990EbcUnloadImage (\r
991 IN EFI_EBC_PROTOCOL *This,\r
992 IN EFI_HANDLE ImageHandle\r
993 )\r
994{\r
995 EBC_THUNK_LIST *ThunkList;\r
996 EBC_THUNK_LIST *NextThunkList;\r
997 EBC_IMAGE_LIST *ImageList;\r
998 EBC_IMAGE_LIST *PrevImageList;\r
999 //\r
1000 // First go through our list of known image handles and see if we've already\r
1001 // created an image list element for this image handle.\r
1002 //\r
1003 ReturnEBCStackByHandle(ImageHandle);\r
1004 PrevImageList = NULL;\r
1005 for (ImageList = mEbcImageList; ImageList != NULL; ImageList = ImageList->Next) {\r
1006 if (ImageList->ImageHandle == ImageHandle) {\r
1007 break;\r
1008 }\r
1009 //\r
1010 // Save the previous so we can connect the lists when we remove this one\r
1011 //\r
1012 PrevImageList = ImageList;\r
1013 }\r
1014\r
1015 if (ImageList == NULL) {\r
1016 return EFI_INVALID_PARAMETER;\r
1017 }\r
1018 //\r
1019 // Free up all the thunk buffers and thunks list elements for this image\r
1020 // handle.\r
1021 //\r
1022 ThunkList = ImageList->ThunkList;\r
1023 while (ThunkList != NULL) {\r
1024 NextThunkList = ThunkList->Next;\r
1025 FreePool (ThunkList->ThunkBuffer);\r
1026 FreePool (ThunkList);\r
1027 ThunkList = NextThunkList;\r
1028 }\r
1029 //\r
1030 // Now remove this image list element from the chain\r
1031 //\r
1032 if (PrevImageList == NULL) {\r
1033 //\r
1034 // Remove from head\r
1035 //\r
1036 mEbcImageList = ImageList->Next;\r
1037 } else {\r
1038 PrevImageList->Next = ImageList->Next;\r
1039 }\r
1040 //\r
1041 // Now free up the image list element\r
1042 //\r
1043 FreePool (ImageList);\r
1044 return EFI_SUCCESS;\r
1045}\r
1046\r
1047\r
1048/**\r
1049 Add a thunk to our list of thunks for a given image handle.\r
1050 Also flush the instruction cache since we've written thunk code\r
1051 to memory that will be executed eventually.\r
1052\r
1053 @param ImageHandle The image handle to which the thunk is tied.\r
1054 @param ThunkBuffer The buffer that has been created/allocated.\r
1055 @param ThunkSize The size of the thunk memory allocated.\r
1056\r
1057 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
1058 @retval EFI_SUCCESS The function completed successfully.\r
1059\r
1060**/\r
1061EFI_STATUS\r
1062EbcAddImageThunk (\r
1063 IN EFI_HANDLE ImageHandle,\r
1064 IN VOID *ThunkBuffer,\r
1065 IN UINT32 ThunkSize\r
1066 )\r
1067{\r
1068 EBC_THUNK_LIST *ThunkList;\r
1069 EBC_IMAGE_LIST *ImageList;\r
1070 EFI_STATUS Status;\r
1071\r
1072 //\r
1073 // It so far so good, then flush the instruction cache\r
1074 //\r
1075 if (mEbcICacheFlush != NULL) {\r
1076 Status = mEbcICacheFlush ((EFI_PHYSICAL_ADDRESS) (UINTN) ThunkBuffer, ThunkSize);\r
1077 if (EFI_ERROR (Status)) {\r
1078 return Status;\r
1079 }\r
1080 }\r
1081 //\r
1082 // Go through our list of known image handles and see if we've already\r
1083 // created a image list element for this image handle.\r
1084 //\r
1085 for (ImageList = mEbcImageList; ImageList != NULL; ImageList = ImageList->Next) {\r
1086 if (ImageList->ImageHandle == ImageHandle) {\r
1087 break;\r
1088 }\r
1089 }\r
1090\r
1091 if (ImageList == NULL) {\r
1092 //\r
1093 // Allocate a new one\r
1094 //\r
1095 ImageList = AllocatePool (sizeof (EBC_IMAGE_LIST));\r
1096\r
1097 if (ImageList == NULL) {\r
1098 return EFI_OUT_OF_RESOURCES;\r
1099 }\r
1100\r
1101 ImageList->ThunkList = NULL;\r
1102 ImageList->ImageHandle = ImageHandle;\r
1103 ImageList->Next = mEbcImageList;\r
1104 mEbcImageList = ImageList;\r
1105 }\r
1106 //\r
1107 // Ok, now create a new thunk element to add to the list\r
1108 //\r
1109 ThunkList = AllocatePool (sizeof (EBC_THUNK_LIST));\r
1110\r
1111 if (ThunkList == NULL) {\r
1112 return EFI_OUT_OF_RESOURCES;\r
1113 }\r
1114 //\r
1115 // Add it to the head of the list\r
1116 //\r
1117 ThunkList->Next = ImageList->ThunkList;\r
1118 ThunkList->ThunkBuffer = ThunkBuffer;\r
1119 ImageList->ThunkList = ThunkList;\r
1120 return EFI_SUCCESS;\r
1121}\r
1122\r
1123/**\r
1124 Registers a callback function that the EBC interpreter calls to flush the\r
1125 processor instruction cache following creation of thunks.\r
1126\r
1127 @param This A pointer to the EFI_EBC_PROTOCOL instance.\r
1128 @param Flush Pointer to a function of type EBC_ICACH_FLUSH.\r
1129\r
1130 @retval EFI_SUCCESS The function completed successfully.\r
1131\r
1132**/\r
1133EFI_STATUS\r
1134EFIAPI\r
1135EbcRegisterICacheFlush (\r
1136 IN EFI_EBC_PROTOCOL *This,\r
1137 IN EBC_ICACHE_FLUSH Flush\r
1138 )\r
1139{\r
1140 mEbcICacheFlush = Flush;\r
1141 return EFI_SUCCESS;\r
1142}\r
1143\r
1144/**\r
1145 Called to get the version of the interpreter.\r
1146\r
1147 @param This A pointer to the EFI_EBC_PROTOCOL instance.\r
1148 @param Version Pointer to where to store the returned version\r
1149 of the interpreter.\r
1150\r
1151 @retval EFI_SUCCESS The function completed successfully.\r
1152 @retval EFI_INVALID_PARAMETER Version pointer is NULL.\r
1153\r
1154**/\r
1155EFI_STATUS\r
1156EFIAPI\r
1157EbcGetVersion (\r
1158 IN EFI_EBC_PROTOCOL *This,\r
1159 IN OUT UINT64 *Version\r
1160 )\r
1161{\r
1162 if (Version == NULL) {\r
1163 return EFI_INVALID_PARAMETER;\r
1164 }\r
1165\r
1166 *Version = GetVmVersion ();\r
1167 return EFI_SUCCESS;\r
1168}\r
1169\r
1170/**\r
1171 Returns the stack index and buffer assosicated with the Handle parameter.\r
1172\r
1173 @param Handle The EFI handle as the index to the EBC stack.\r
1174 @param StackBuffer A pointer to hold the returned stack buffer.\r
1175 @param BufferIndex A pointer to hold the returned stack index.\r
1176\r
1177 @retval EFI_OUT_OF_RESOURCES The Handle parameter does not correspond to any\r
1178 existing EBC stack.\r
1179 @retval EFI_SUCCESS The stack index and buffer were found and\r
1180 returned to the caller.\r
1181\r
1182**/\r
1183EFI_STATUS\r
1184GetEBCStack(\r
1185 IN EFI_HANDLE Handle,\r
1186 OUT VOID **StackBuffer,\r
1187 OUT UINTN *BufferIndex\r
1188 )\r
1189{\r
1190 UINTN Index;\r
1191 EFI_TPL OldTpl;\r
1192 OldTpl = gBS->RaiseTPL(TPL_HIGH_LEVEL);\r
1193 for (Index = 0; Index < mStackNum; Index ++) {\r
1194 if (mStackBufferIndex[Index] == NULL) {\r
1195 mStackBufferIndex[Index] = Handle;\r
1196 break;\r
1197 }\r
1198 }\r
1199 gBS->RestoreTPL(OldTpl);\r
1200 if (Index == mStackNum) {\r
1201 return EFI_OUT_OF_RESOURCES;\r
1202 }\r
1203 *BufferIndex = Index;\r
1204 *StackBuffer = mStackBuffer[Index];\r
1205 return EFI_SUCCESS;\r
1206}\r
1207\r
1208/**\r
1209 Returns from the EBC stack by stack Index.\r
1210\r
1211 @param Index Specifies which EBC stack to return from.\r
1212\r
1213 @retval EFI_SUCCESS The function completed successfully.\r
1214\r
1215**/\r
1216EFI_STATUS\r
1217ReturnEBCStack(\r
1218 IN UINTN Index\r
1219 )\r
1220{\r
1221 mStackBufferIndex[Index] = NULL;\r
1222 return EFI_SUCCESS;\r
1223}\r
1224\r
1225/**\r
1226 Returns from the EBC stack associated with the Handle parameter.\r
1227\r
1228 @param Handle Specifies the EFI handle to find the EBC stack with.\r
1229\r
1230 @retval EFI_SUCCESS The function completed successfully.\r
1231\r
1232**/\r
1233EFI_STATUS\r
1234ReturnEBCStackByHandle(\r
1235 IN EFI_HANDLE Handle\r
1236 )\r
1237{\r
1238 UINTN Index;\r
1239 for (Index = 0; Index < mStackNum; Index ++) {\r
1240 if (mStackBufferIndex[Index] == Handle) {\r
1241 break;\r
1242 }\r
1243 }\r
1244 if (Index == mStackNum) {\r
1245 return EFI_NOT_FOUND;\r
1246 }\r
1247 mStackBufferIndex[Index] = NULL;\r
1248 return EFI_SUCCESS;\r
1249}\r
1250\r
1251/**\r
1252 Allocates memory to hold all the EBC stacks.\r
1253\r
1254 @retval EFI_SUCCESS The EBC stacks were allocated successfully.\r
1255 @retval EFI_OUT_OF_RESOURCES Not enough memory available for EBC stacks.\r
1256\r
1257**/\r
1258EFI_STATUS\r
1259InitEBCStack (\r
1260 VOID\r
1261 )\r
1262{\r
1263 for (mStackNum = 0; mStackNum < MAX_STACK_NUM; mStackNum ++) {\r
1264 mStackBuffer[mStackNum] = AllocatePool(STACK_POOL_SIZE);\r
1265 mStackBufferIndex[mStackNum] = NULL;\r
1266 if (mStackBuffer[mStackNum] == NULL) {\r
1267 break;\r
1268 }\r
1269 }\r
1270 if (mStackNum == 0) {\r
1271 return EFI_OUT_OF_RESOURCES;\r
1272 }\r
1273 return EFI_SUCCESS;\r
1274}\r
1275\r
1276\r
1277/**\r
1278 Free all EBC stacks allocated before.\r
1279\r
1280 @retval EFI_SUCCESS All the EBC stacks were freed.\r
1281\r
1282**/\r
1283EFI_STATUS\r
1284FreeEBCStack(\r
1285 VOID\r
1286 )\r
1287{\r
1288 UINTN Index;\r
1289 for (Index = 0; Index < mStackNum; Index ++) {\r
1290 FreePool(mStackBuffer[Index]);\r
1291 }\r
1292 return EFI_SUCCESS;\r
1293}\r
1294\r
1295/**\r
1296 Produces an EBC VM test protocol that can be used for regression tests.\r
1297\r
1298 @param IHandle Handle on which to install the protocol.\r
1299\r
1300 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
1301 @retval EFI_SUCCESS The function completed successfully.\r
1302\r
1303**/\r
1304EFI_STATUS\r
1305InitEbcVmTestProtocol (\r
1306 IN EFI_HANDLE *IHandle\r
1307 )\r
1308{\r
1309 EFI_HANDLE Handle;\r
1310 EFI_STATUS Status;\r
1311 EFI_EBC_VM_TEST_PROTOCOL *EbcVmTestProtocol;\r
1312\r
1313 //\r
1314 // Allocate memory for the protocol, then fill in the fields\r
1315 //\r
1316 EbcVmTestProtocol = AllocatePool (sizeof (EFI_EBC_VM_TEST_PROTOCOL));\r
1317 if (EbcVmTestProtocol == NULL) {\r
1318 return EFI_OUT_OF_RESOURCES;\r
1319 }\r
1320 EbcVmTestProtocol->Execute = (EBC_VM_TEST_EXECUTE) EbcExecuteInstructions;\r
1321\r
1322 DEBUG_CODE_BEGIN ();\r
1323 EbcVmTestProtocol->Assemble = (EBC_VM_TEST_ASM) EbcVmTestUnsupported;\r
1324 EbcVmTestProtocol->Disassemble = (EBC_VM_TEST_DASM) EbcVmTestUnsupported;\r
1325 DEBUG_CODE_END ();\r
1326\r
1327 //\r
1328 // Publish the protocol\r
1329 //\r
1330 Handle = NULL;\r
1331 Status = gBS->InstallProtocolInterface (&Handle, &gEfiEbcVmTestProtocolGuid, EFI_NATIVE_INTERFACE, EbcVmTestProtocol);\r
1332 if (EFI_ERROR (Status)) {\r
1333 FreePool (EbcVmTestProtocol);\r
1334 }\r
1335 return Status;\r
1336}\r
1337\r
1338\r
1339/**\r
1340 Returns the EFI_UNSUPPORTED Status.\r
1341\r
1342 @return EFI_UNSUPPORTED This function always return EFI_UNSUPPORTED status.\r
1343\r
1344**/\r
1345EFI_STATUS\r
1346EFIAPI\r
1347EbcVmTestUnsupported (\r
1348 VOID\r
1349 )\r
1350{\r
1351 return EFI_UNSUPPORTED;\r
1352}\r
1353\r