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