]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/EbcDxe/EbcInt.c
Clean up the private GUID definition in module Level.
[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
c8ad2d7a 6Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 7This program and the accompanying materials\r
53c71d09 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
1ccdbf2a 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
53c71d09 38\r
8e3bc754 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
53c71d09 53EFI_STATUS\r
54EFIAPI\r
55EbcUnloadImage (\r
ea7cb08c 56 IN EFI_EBC_PROTOCOL *This,\r
57 IN EFI_HANDLE ImageHandle\r
53c71d09 58 );\r
59\r
8e3bc754 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
53c71d09 79EFI_STATUS\r
80EFIAPI\r
81EbcCreateThunk (\r
ea7cb08c 82 IN EFI_EBC_PROTOCOL *This,\r
83 IN EFI_HANDLE ImageHandle,\r
84 IN VOID *EbcEntryPoint,\r
85 OUT VOID **Thunk\r
53c71d09 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
34e4e297 94\r
8e3bc754 95 @retval EFI_SUCCESS The function completed successfully.\r
96 @retval EFI_INVALID_PARAMETER Version pointer is NULL.\r
97\r
98**/\r
53c71d09 99EFI_STATUS\r
100EFIAPI\r
101EbcGetVersion (\r
ea7cb08c 102 IN EFI_EBC_PROTOCOL *This,\r
103 IN OUT UINT64 *Version\r
53c71d09 104 );\r
105\r
8e3bc754 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
53c71d09 116EFI_STATUS\r
117EFIAPI\r
118InitializeEbcCallback (\r
119 IN EFI_DEBUG_SUPPORT_PROTOCOL *This\r
120 );\r
121\r
8e3bc754 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
53c71d09 131VOID\r
132EFIAPI\r
133CommonEbcExceptionHandler (\r
134 IN EFI_EXCEPTION_TYPE InterruptType,\r
135 IN EFI_SYSTEM_CONTEXT SystemContext\r
136 );\r
137\r
8e3bc754 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
53c71d09 146VOID\r
147EFIAPI\r
148EbcPeriodicNotifyFunction (\r
149 IN EFI_EVENT Event,\r
150 IN VOID *Context\r
151 );\r
152\r
8e3bc754 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
53c71d09 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
8e3bc754 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
53c71d09 182EFI_STATUS\r
183InitEbcVmTestProtocol (\r
ea7cb08c 184 IN EFI_HANDLE *IHandle\r
53c71d09 185 );\r
186\r
8e3bc754 187/**\r
188 Returns the EFI_UNSUPPORTED Status.\r
34e4e297 189\r
8e3bc754 190 @return EFI_UNSUPPORTED This function always return EFI_UNSUPPORTED status.\r
191\r
192**/\r
53c71d09 193EFI_STATUS\r
c8ad2d7a 194EFIAPI\r
53c71d09 195EbcVmTestUnsupported (\r
196 VOID\r
197 );\r
198\r
8e3bc754 199/**\r
200 Registers a callback function that the EBC interpreter calls to flush the\r
34e4e297 201 processor instruction cache following creation of thunks.\r
8e3bc754 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
34e4e297 205\r
8e3bc754 206 @retval EFI_SUCCESS The function completed successfully.\r
207\r
208**/\r
53c71d09 209EFI_STATUS\r
210EFIAPI\r
211EbcRegisterICacheFlush (\r
ea7cb08c 212 IN EFI_EBC_PROTOCOL *This,\r
213 IN EBC_ICACHE_FLUSH Flush\r
53c71d09 214 );\r
215\r
8e3bc754 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
53c71d09 227EFI_STATUS\r
228EFIAPI\r
229EbcDebugGetMaximumProcessorIndex (\r
ea7cb08c 230 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
231 OUT UINTN *MaxProcessorIndex\r
53c71d09 232 );\r
233\r
8e3bc754 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
53c71d09 255EFI_STATUS\r
256EFIAPI\r
257EbcDebugRegisterPeriodicCallback (\r
ea7cb08c 258 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
259 IN UINTN ProcessorIndex,\r
260 IN EFI_PERIODIC_CALLBACK PeriodicCallback\r
53c71d09 261 );\r
262\r
8e3bc754 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
53c71d09 288EFI_STATUS\r
289EFIAPI\r
290EbcDebugRegisterExceptionCallback (\r
ea7cb08c 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
53c71d09 295 );\r
296\r
8e3bc754 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
34e4e297 308 processor's instruction cache to invalidate.\r
8e3bc754 309\r
310 @retval EFI_SUCCESS The function completed successfully.\r
311\r
312**/\r
53c71d09 313EFI_STATUS\r
314EFIAPI\r
315EbcDebugInvalidateInstructionCache (\r
ea7cb08c 316 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
317 IN UINTN ProcessorIndex,\r
318 IN VOID *Start,\r
319 IN UINT64 Length\r
53c71d09 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
34e4e297 328EBC_IMAGE_LIST *mEbcImageList = NULL;\r
53c71d09 329\r
330//\r
331// Callback function to flush the icache after thunk creation\r
332//\r
34e4e297 333EBC_ICACHE_FLUSH mEbcICacheFlush;\r
53c71d09 334\r
335//\r
336// These get set via calls by the debug agent\r
337//\r
34e4e297 338EFI_PERIODIC_CALLBACK mDebugPeriodicCallback = NULL;\r
339EFI_EXCEPTION_CALLBACK mDebugExceptionCallback[MAX_EBC_EXCEPTION + 1] = {NULL};\r
53c71d09 340\r
34e4e297 341VOID *mStackBuffer[MAX_STACK_NUM];\r
342EFI_HANDLE mStackBufferIndex[MAX_STACK_NUM];\r
343UINTN mStackNum = 0;\r
53c71d09 344\r
345//\r
346// Event for Periodic callback\r
347//\r
34e4e297 348EFI_EVENT mEbcPeriodicEvent;\r
349VM_CONTEXT *mVmPtr = NULL;\r
53c71d09 350\r
53c71d09 351\r
fb0b259e 352/**\r
53c71d09 353 Initializes the VM EFI interface. Allocates memory for the VM interface\r
354 and registers the VM protocol.\r
355\r
fb0b259e 356 @param ImageHandle EFI image handle.\r
357 @param SystemTable Pointer to the EFI system table.\r
53c71d09 358\r
fb0b259e 359 @return Standard EFI status code.\r
53c71d09 360\r
fb0b259e 361**/\r
362EFI_STATUS\r
363EFIAPI\r
364InitializeEbcDriver (\r
365 IN EFI_HANDLE ImageHandle,\r
366 IN EFI_SYSTEM_TABLE *SystemTable\r
367 )\r
53c71d09 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
fb0b259e 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
8e3bc754 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
fb0b259e 556\r
8e3bc754 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
fb0b259e 560\r
561**/\r
53c71d09 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
53c71d09 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
fb0b259e 582\r
583/**\r
584 This EBC debugger protocol service is called by the debug agent\r
585\r
8e3bc754 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
fb0b259e 590\r
8e3bc754 591 @retval EFI_SUCCESS The function completed successfully.\r
fb0b259e 592\r
593**/\r
53c71d09 594EFI_STATUS\r
595EFIAPI\r
596EbcDebugGetMaximumProcessorIndex (\r
597 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
598 OUT UINTN *MaxProcessorIndex\r
599 )\r
53c71d09 600{\r
601 *MaxProcessorIndex = 0;\r
602 return EFI_SUCCESS;\r
603}\r
604\r
fb0b259e 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
8e3bc754 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
fb0b259e 625\r
626**/\r
53c71d09 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
53c71d09 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
fb0b259e 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
8e3bc754 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
fb0b259e 670\r
671**/\r
53c71d09 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
53c71d09 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
fb0b259e 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
8e3bc754 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
34e4e297 706 processor's instruction cache to invalidate.\r
fb0b259e 707\r
8e3bc754 708 @retval EFI_SUCCESS The function completed successfully.\r
fb0b259e 709\r
710**/\r
53c71d09 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
fb0b259e 719{\r
720 return EFI_SUCCESS;\r
721}\r
53c71d09 722\r
53c71d09 723\r
fb0b259e 724/**\r
725 The VM interpreter calls this function when an exception is detected.\r
53c71d09 726\r
8e3bc754 727 @param ExceptionType Specifies the processor exception detected.\r
34e4e297 728 @param ExceptionFlags Specifies the exception context.\r
8e3bc754 729 @param VmPtr Pointer to a VM context for passing info to the\r
fb0b259e 730 EFI debugger.\r
53c71d09 731\r
8e3bc754 732 @retval EFI_SUCCESS This function completed successfully.\r
53c71d09 733\r
fb0b259e 734**/\r
53c71d09 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
53c71d09 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
fbe12b79 750 VmPtr->LastException = (UINTN) ExceptionType;\r
53c71d09 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
366219ab 755 if ((ExceptionFlags & EXCEPTION_FLAG_FATAL) != 0) {\r
53c71d09 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
c9325700
ED
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
53c71d09 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
1ccdbf2a 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
53c71d09 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
53c71d09 802\r
fb0b259e 803/**\r
53c71d09 804 To install default Callback function for the VM interpreter.\r
805\r
8e3bc754 806 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL\r
807 instance.\r
53c71d09 808\r
8e3bc754 809 @retval EFI_SUCCESS The function completed successfully.\r
810 @retval Others Some error occurs when creating periodic event.\r
53c71d09 811\r
fb0b259e 812**/\r
fb0b259e 813EFI_STATUS\r
8e3bc754 814EFIAPI\r
fb0b259e 815InitializeEbcCallback (\r
816 IN EFI_DEBUG_SUPPORT_PROTOCOL *This\r
817 )\r
53c71d09 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
53c71d09 860\r
fb0b259e 861/**\r
53c71d09 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
fb0b259e 866 @param InterruptType Interrupt type.\r
867 @param SystemContext EBC system context.\r
53c71d09 868\r
fb0b259e 869**/\r
fb0b259e 870VOID\r
8e3bc754 871EFIAPI\r
fb0b259e 872CommonEbcExceptionHandler (\r
873 IN EFI_EXCEPTION_TYPE InterruptType,\r
874 IN EFI_SYSTEM_CONTEXT SystemContext\r
875 )\r
53c71d09 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
fb0b259e 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
fb0b259e 893**/\r
53c71d09 894VOID\r
895EFIAPI\r
896EbcPeriodicNotifyFunction (\r
897 IN EFI_EVENT Event,\r
898 IN VOID *Context\r
899 )\r
53c71d09 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
53c71d09 912\r
fb0b259e 913/**\r
53c71d09 914 The VM interpreter calls this function on a periodic basis to support\r
915 the EFI debug support protocol.\r
916\r
8e3bc754 917 @param VmPtr Pointer to a VM context for passing info to the\r
fb0b259e 918 debugger.\r
53c71d09 919\r
8e3bc754 920 @retval EFI_SUCCESS The function completed successfully.\r
53c71d09 921\r
fb0b259e 922**/\r
fb0b259e 923EFI_STATUS\r
8e3bc754 924EFIAPI\r
fb0b259e 925EbcDebugPeriodic (\r
926 IN VM_CONTEXT *VmPtr\r
927 )\r
53c71d09 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
c9325700
ED
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
53c71d09 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
1ccdbf2a 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
53c71d09 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
53c71d09 973\r
fb0b259e 974/**\r
53c71d09 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
8e3bc754 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
53c71d09 982\r
8e3bc754 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
53c71d09 986\r
fb0b259e 987**/\r
fb0b259e 988EFI_STATUS\r
989EFIAPI\r
990EbcUnloadImage (\r
991 IN EFI_EBC_PROTOCOL *This,\r
992 IN EFI_HANDLE ImageHandle\r
993 )\r
53c71d09 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
53c71d09 1047\r
fb0b259e 1048/**\r
53c71d09 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
8e3bc754 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
53c71d09 1056\r
8e3bc754 1057 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
1058 @retval EFI_SUCCESS The function completed successfully.\r
53c71d09 1059\r
fb0b259e 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
53c71d09 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
8e3bc754 1123/**\r
1124 Registers a callback function that the EBC interpreter calls to flush the\r
34e4e297 1125 processor instruction cache following creation of thunks.\r
8e3bc754 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
34e4e297 1129\r
8e3bc754 1130 @retval EFI_SUCCESS The function completed successfully.\r
1131\r
1132**/\r
53c71d09 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
8e3bc754 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
34e4e297 1150\r
8e3bc754 1151 @retval EFI_SUCCESS The function completed successfully.\r
1152 @retval EFI_INVALID_PARAMETER Version pointer is NULL.\r
1153\r
1154**/\r
53c71d09 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
8e3bc754 1170/**\r
1171 Returns the stack index and buffer assosicated with the Handle parameter.\r
1172\r
34e4e297 1173 @param Handle The EFI handle as the index to the EBC stack.\r
8e3bc754 1174 @param StackBuffer A pointer to hold the returned stack buffer.\r
1175 @param BufferIndex A pointer to hold the returned stack index.\r
34e4e297 1176\r
8e3bc754 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
53c71d09 1183EFI_STATUS\r
1184GetEBCStack(\r
8e3bc754 1185 IN EFI_HANDLE Handle,\r
1186 OUT VOID **StackBuffer,\r
1187 OUT UINTN *BufferIndex\r
53c71d09 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
8e3bc754 1208/**\r
34e4e297 1209 Returns from the EBC stack by stack Index.\r
1210\r
8e3bc754 1211 @param Index Specifies which EBC stack to return from.\r
34e4e297 1212\r
8e3bc754 1213 @retval EFI_SUCCESS The function completed successfully.\r
1214\r
1215**/\r
53c71d09 1216EFI_STATUS\r
1217ReturnEBCStack(\r
8e3bc754 1218 IN UINTN Index\r
53c71d09 1219 )\r
1220{\r
8e3bc754 1221 mStackBufferIndex[Index] = NULL;\r
53c71d09 1222 return EFI_SUCCESS;\r
1223}\r
1224\r
8e3bc754 1225/**\r
34e4e297 1226 Returns from the EBC stack associated with the Handle parameter.\r
1227\r
8e3bc754 1228 @param Handle Specifies the EFI handle to find the EBC stack with.\r
34e4e297 1229\r
8e3bc754 1230 @retval EFI_SUCCESS The function completed successfully.\r
1231\r
1232**/\r
53c71d09 1233EFI_STATUS\r
1234ReturnEBCStackByHandle(\r
8e3bc754 1235 IN EFI_HANDLE Handle\r
53c71d09 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
8e3bc754 1251/**\r
1252 Allocates memory to hold all the EBC stacks.\r
1253\r
34e4e297 1254 @retval EFI_SUCCESS The EBC stacks were allocated successfully.\r
8e3bc754 1255 @retval EFI_OUT_OF_RESOURCES Not enough memory available for EBC stacks.\r
1256\r
1257**/\r
53c71d09 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
8e3bc754 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
53c71d09 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
53c71d09 1294\r
fb0b259e 1295/**\r
8e3bc754 1296 Produces an EBC VM test protocol that can be used for regression tests.\r
53c71d09 1297\r
8e3bc754 1298 @param IHandle Handle on which to install the protocol.\r
53c71d09 1299\r
8e3bc754 1300 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
1301 @retval EFI_SUCCESS The function completed successfully.\r
53c71d09 1302\r
fb0b259e 1303**/\r
fb0b259e 1304EFI_STATUS\r
1305InitEbcVmTestProtocol (\r
1306 IN EFI_HANDLE *IHandle\r
1307 )\r
53c71d09 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
c8ad2d7a 1331 Status = gBS->InstallProtocolInterface (&Handle, &gEfiEbcVmTestProtocolGuid, EFI_NATIVE_INTERFACE, EbcVmTestProtocol);\r
53c71d09 1332 if (EFI_ERROR (Status)) {\r
1333 FreePool (EbcVmTestProtocol);\r
1334 }\r
1335 return Status;\r
1336}\r
8e3bc754 1337\r
1338\r
1339/**\r
1340 Returns the EFI_UNSUPPORTED Status.\r
34e4e297 1341\r
8e3bc754 1342 @return EFI_UNSUPPORTED This function always return EFI_UNSUPPORTED status.\r
1343\r
1344**/\r
53c71d09 1345EFI_STATUS\r
c8ad2d7a 1346EFIAPI\r
8e3bc754 1347EbcVmTestUnsupported (\r
1348 VOID\r
1349 )\r
53c71d09 1350{\r
1351 return EFI_UNSUPPORTED;\r
1352}\r
1353\r