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