]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/EbcDxe/EbcInt.c
MdeModulePkg: INF/DEC file updates to EDK II packages
[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
fa97cbf4
JY
877 //\r
878 // We print debug information to let user know what happen.\r
879 //\r
880 DEBUG ((\r
881 EFI_D_ERROR,\r
882 "EBC Interrupter Version - 0x%016lx\n",\r
883 (UINT64) (((VM_MAJOR_VERSION & 0xFFFF) << 16) | ((VM_MINOR_VERSION & 0xFFFF)))\r
884 ));\r
885 DEBUG ((\r
886 EFI_D_ERROR,\r
887 "Exception Type - 0x%016lx\n",\r
888 (UINT64)(UINTN)InterruptType\r
889 ));\r
890 DEBUG ((\r
891 EFI_D_ERROR,\r
892 " R0 - 0x%016lx, R1 - 0x%016lx\n",\r
893 SystemContext.SystemContextEbc->R0,\r
894 SystemContext.SystemContextEbc->R1\r
895 ));\r
896 DEBUG ((\r
897 EFI_D_ERROR,\r
898 " R2 - 0x%016lx, R3 - 0x%016lx\n",\r
899 SystemContext.SystemContextEbc->R2,\r
900 SystemContext.SystemContextEbc->R3\r
901 ));\r
902 DEBUG ((\r
903 EFI_D_ERROR,\r
904 " R4 - 0x%016lx, R5 - 0x%016lx\n",\r
905 SystemContext.SystemContextEbc->R4,\r
906 SystemContext.SystemContextEbc->R5\r
907 ));\r
908 DEBUG ((\r
909 EFI_D_ERROR,\r
910 " R6 - 0x%016lx, R7 - 0x%016lx\n",\r
911 SystemContext.SystemContextEbc->R6,\r
912 SystemContext.SystemContextEbc->R7\r
913 ));\r
914 DEBUG ((\r
915 EFI_D_ERROR,\r
916 " Flags - 0x%016lx\n",\r
917 SystemContext.SystemContextEbc->Flags\r
918 ));\r
919 DEBUG ((\r
920 EFI_D_ERROR,\r
921 " ControlFlags - 0x%016lx\n",\r
922 SystemContext.SystemContextEbc->ControlFlags\r
923 ));\r
924 DEBUG ((\r
925 EFI_D_ERROR,\r
926 " Ip - 0x%016lx\n\n",\r
927 SystemContext.SystemContextEbc->Ip\r
928 ));\r
929\r
53c71d09 930 //\r
931 // We deadloop here to make it easy to debug this issue.\r
932 //\r
fa97cbf4 933 CpuDeadLoop ();\r
53c71d09 934\r
935 return ;\r
936}\r
937\r
fb0b259e 938\r
939/**\r
940 The periodic callback function for EBC VM interpreter, which is used\r
941 to support the EFI debug support protocol.\r
942\r
943 @param Event The Periodic Callback Event.\r
944 @param Context It should be the address of VM_CONTEXT pointer.\r
945\r
fb0b259e 946**/\r
53c71d09 947VOID\r
948EFIAPI\r
949EbcPeriodicNotifyFunction (\r
950 IN EFI_EVENT Event,\r
951 IN VOID *Context\r
952 )\r
53c71d09 953{\r
954 VM_CONTEXT *VmPtr;\r
955\r
956 VmPtr = *(VM_CONTEXT **)Context;\r
957\r
958 if (VmPtr != NULL) {\r
959 EbcDebugPeriodic (VmPtr);\r
960 }\r
961\r
962 return ;\r
963}\r
964\r
53c71d09 965\r
fb0b259e 966/**\r
53c71d09 967 The VM interpreter calls this function on a periodic basis to support\r
968 the EFI debug support protocol.\r
969\r
8e3bc754 970 @param VmPtr Pointer to a VM context for passing info to the\r
fb0b259e 971 debugger.\r
53c71d09 972\r
8e3bc754 973 @retval EFI_SUCCESS The function completed successfully.\r
53c71d09 974\r
fb0b259e 975**/\r
fb0b259e 976EFI_STATUS\r
8e3bc754 977EFIAPI\r
fb0b259e 978EbcDebugPeriodic (\r
979 IN VM_CONTEXT *VmPtr\r
980 )\r
53c71d09 981{\r
982 EFI_SYSTEM_CONTEXT_EBC EbcContext;\r
983 EFI_SYSTEM_CONTEXT SystemContext;\r
984\r
985 //\r
986 // If someone's registered for periodic callbacks, then call them.\r
987 //\r
988 if (mDebugPeriodicCallback != NULL) {\r
989\r
990 //\r
991 // Initialize the context structure\r
992 //\r
c9325700
ED
993 EbcContext.R0 = (UINT64) VmPtr->Gpr[0];\r
994 EbcContext.R1 = (UINT64) VmPtr->Gpr[1];\r
995 EbcContext.R2 = (UINT64) VmPtr->Gpr[2];\r
996 EbcContext.R3 = (UINT64) VmPtr->Gpr[3];\r
997 EbcContext.R4 = (UINT64) VmPtr->Gpr[4];\r
998 EbcContext.R5 = (UINT64) VmPtr->Gpr[5];\r
999 EbcContext.R6 = (UINT64) VmPtr->Gpr[6];\r
1000 EbcContext.R7 = (UINT64) VmPtr->Gpr[7];\r
53c71d09 1001 EbcContext.Ip = (UINT64)(UINTN)VmPtr->Ip;\r
1002 EbcContext.Flags = VmPtr->Flags;\r
1003 EbcContext.ControlFlags = 0;\r
1004 SystemContext.SystemContextEbc = &EbcContext;\r
1005\r
1006 mDebugPeriodicCallback (SystemContext);\r
1007\r
1008 //\r
1009 // Restore the context structure and continue to execute\r
1010 //\r
1ccdbf2a 1011 VmPtr->Gpr[0] = EbcContext.R0;\r
1012 VmPtr->Gpr[1] = EbcContext.R1;\r
1013 VmPtr->Gpr[2] = EbcContext.R2;\r
1014 VmPtr->Gpr[3] = EbcContext.R3;\r
1015 VmPtr->Gpr[4] = EbcContext.R4;\r
1016 VmPtr->Gpr[5] = EbcContext.R5;\r
1017 VmPtr->Gpr[6] = EbcContext.R6;\r
1018 VmPtr->Gpr[7] = EbcContext.R7;\r
53c71d09 1019 VmPtr->Ip = (VMIP)(UINTN)EbcContext.Ip;\r
1020 VmPtr->Flags = EbcContext.Flags;\r
1021 }\r
1022\r
1023 return EFI_SUCCESS;\r
1024}\r
1025\r
53c71d09 1026\r
fb0b259e 1027/**\r
53c71d09 1028 This routine is called by the core when an image is being unloaded from\r
1029 memory. Basically we now have the opportunity to do any necessary cleanup.\r
1030 Typically this will include freeing any memory allocated for thunk-creation.\r
1031\r
8e3bc754 1032 @param This A pointer to the EFI_EBC_PROTOCOL instance.\r
1033 @param ImageHandle Handle of image for which the thunk is being\r
1034 created.\r
53c71d09 1035\r
8e3bc754 1036 @retval EFI_INVALID_PARAMETER The ImageHandle passed in was not found in the\r
1037 internal list of EBC image handles.\r
1038 @retval EFI_SUCCESS The function completed successfully.\r
53c71d09 1039\r
fb0b259e 1040**/\r
fb0b259e 1041EFI_STATUS\r
1042EFIAPI\r
1043EbcUnloadImage (\r
1044 IN EFI_EBC_PROTOCOL *This,\r
1045 IN EFI_HANDLE ImageHandle\r
1046 )\r
53c71d09 1047{\r
1048 EBC_THUNK_LIST *ThunkList;\r
1049 EBC_THUNK_LIST *NextThunkList;\r
1050 EBC_IMAGE_LIST *ImageList;\r
1051 EBC_IMAGE_LIST *PrevImageList;\r
1052 //\r
1053 // First go through our list of known image handles and see if we've already\r
1054 // created an image list element for this image handle.\r
1055 //\r
1056 ReturnEBCStackByHandle(ImageHandle);\r
1057 PrevImageList = NULL;\r
1058 for (ImageList = mEbcImageList; ImageList != NULL; ImageList = ImageList->Next) {\r
1059 if (ImageList->ImageHandle == ImageHandle) {\r
1060 break;\r
1061 }\r
1062 //\r
1063 // Save the previous so we can connect the lists when we remove this one\r
1064 //\r
1065 PrevImageList = ImageList;\r
1066 }\r
1067\r
1068 if (ImageList == NULL) {\r
1069 return EFI_INVALID_PARAMETER;\r
1070 }\r
1071 //\r
1072 // Free up all the thunk buffers and thunks list elements for this image\r
1073 // handle.\r
1074 //\r
1075 ThunkList = ImageList->ThunkList;\r
1076 while (ThunkList != NULL) {\r
1077 NextThunkList = ThunkList->Next;\r
1078 FreePool (ThunkList->ThunkBuffer);\r
1079 FreePool (ThunkList);\r
1080 ThunkList = NextThunkList;\r
1081 }\r
1082 //\r
1083 // Now remove this image list element from the chain\r
1084 //\r
1085 if (PrevImageList == NULL) {\r
1086 //\r
1087 // Remove from head\r
1088 //\r
1089 mEbcImageList = ImageList->Next;\r
1090 } else {\r
1091 PrevImageList->Next = ImageList->Next;\r
1092 }\r
1093 //\r
1094 // Now free up the image list element\r
1095 //\r
1096 FreePool (ImageList);\r
1097 return EFI_SUCCESS;\r
1098}\r
1099\r
53c71d09 1100\r
fb0b259e 1101/**\r
53c71d09 1102 Add a thunk to our list of thunks for a given image handle.\r
1103 Also flush the instruction cache since we've written thunk code\r
1104 to memory that will be executed eventually.\r
1105\r
8e3bc754 1106 @param ImageHandle The image handle to which the thunk is tied.\r
1107 @param ThunkBuffer The buffer that has been created/allocated.\r
1108 @param ThunkSize The size of the thunk memory allocated.\r
53c71d09 1109\r
8e3bc754 1110 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
1111 @retval EFI_SUCCESS The function completed successfully.\r
53c71d09 1112\r
fb0b259e 1113**/\r
1114EFI_STATUS\r
1115EbcAddImageThunk (\r
1116 IN EFI_HANDLE ImageHandle,\r
1117 IN VOID *ThunkBuffer,\r
1118 IN UINT32 ThunkSize\r
1119 )\r
53c71d09 1120{\r
1121 EBC_THUNK_LIST *ThunkList;\r
1122 EBC_IMAGE_LIST *ImageList;\r
1123 EFI_STATUS Status;\r
1124\r
1125 //\r
1126 // It so far so good, then flush the instruction cache\r
1127 //\r
1128 if (mEbcICacheFlush != NULL) {\r
1129 Status = mEbcICacheFlush ((EFI_PHYSICAL_ADDRESS) (UINTN) ThunkBuffer, ThunkSize);\r
1130 if (EFI_ERROR (Status)) {\r
1131 return Status;\r
1132 }\r
1133 }\r
1134 //\r
1135 // Go through our list of known image handles and see if we've already\r
1136 // created a image list element for this image handle.\r
1137 //\r
1138 for (ImageList = mEbcImageList; ImageList != NULL; ImageList = ImageList->Next) {\r
1139 if (ImageList->ImageHandle == ImageHandle) {\r
1140 break;\r
1141 }\r
1142 }\r
1143\r
1144 if (ImageList == NULL) {\r
1145 //\r
1146 // Allocate a new one\r
1147 //\r
1148 ImageList = AllocatePool (sizeof (EBC_IMAGE_LIST));\r
1149\r
1150 if (ImageList == NULL) {\r
1151 return EFI_OUT_OF_RESOURCES;\r
1152 }\r
1153\r
1154 ImageList->ThunkList = NULL;\r
1155 ImageList->ImageHandle = ImageHandle;\r
1156 ImageList->Next = mEbcImageList;\r
1157 mEbcImageList = ImageList;\r
1158 }\r
1159 //\r
1160 // Ok, now create a new thunk element to add to the list\r
1161 //\r
1162 ThunkList = AllocatePool (sizeof (EBC_THUNK_LIST));\r
1163\r
1164 if (ThunkList == NULL) {\r
1165 return EFI_OUT_OF_RESOURCES;\r
1166 }\r
1167 //\r
1168 // Add it to the head of the list\r
1169 //\r
1170 ThunkList->Next = ImageList->ThunkList;\r
1171 ThunkList->ThunkBuffer = ThunkBuffer;\r
1172 ImageList->ThunkList = ThunkList;\r
1173 return EFI_SUCCESS;\r
1174}\r
1175\r
8e3bc754 1176/**\r
1177 Registers a callback function that the EBC interpreter calls to flush the\r
34e4e297 1178 processor instruction cache following creation of thunks.\r
8e3bc754 1179\r
1180 @param This A pointer to the EFI_EBC_PROTOCOL instance.\r
1181 @param Flush Pointer to a function of type EBC_ICACH_FLUSH.\r
34e4e297 1182\r
8e3bc754 1183 @retval EFI_SUCCESS The function completed successfully.\r
1184\r
1185**/\r
53c71d09 1186EFI_STATUS\r
1187EFIAPI\r
1188EbcRegisterICacheFlush (\r
1189 IN EFI_EBC_PROTOCOL *This,\r
1190 IN EBC_ICACHE_FLUSH Flush\r
1191 )\r
1192{\r
1193 mEbcICacheFlush = Flush;\r
1194 return EFI_SUCCESS;\r
1195}\r
1196\r
8e3bc754 1197/**\r
1198 Called to get the version of the interpreter.\r
1199\r
1200 @param This A pointer to the EFI_EBC_PROTOCOL instance.\r
1201 @param Version Pointer to where to store the returned version\r
1202 of the interpreter.\r
34e4e297 1203\r
8e3bc754 1204 @retval EFI_SUCCESS The function completed successfully.\r
1205 @retval EFI_INVALID_PARAMETER Version pointer is NULL.\r
1206\r
1207**/\r
53c71d09 1208EFI_STATUS\r
1209EFIAPI\r
1210EbcGetVersion (\r
1211 IN EFI_EBC_PROTOCOL *This,\r
1212 IN OUT UINT64 *Version\r
1213 )\r
1214{\r
1215 if (Version == NULL) {\r
1216 return EFI_INVALID_PARAMETER;\r
1217 }\r
1218\r
1219 *Version = GetVmVersion ();\r
1220 return EFI_SUCCESS;\r
1221}\r
1222\r
8e3bc754 1223/**\r
1224 Returns the stack index and buffer assosicated with the Handle parameter.\r
1225\r
34e4e297 1226 @param Handle The EFI handle as the index to the EBC stack.\r
8e3bc754 1227 @param StackBuffer A pointer to hold the returned stack buffer.\r
1228 @param BufferIndex A pointer to hold the returned stack index.\r
34e4e297 1229\r
8e3bc754 1230 @retval EFI_OUT_OF_RESOURCES The Handle parameter does not correspond to any\r
1231 existing EBC stack.\r
1232 @retval EFI_SUCCESS The stack index and buffer were found and\r
1233 returned to the caller.\r
1234\r
1235**/\r
53c71d09 1236EFI_STATUS\r
1237GetEBCStack(\r
8e3bc754 1238 IN EFI_HANDLE Handle,\r
1239 OUT VOID **StackBuffer,\r
1240 OUT UINTN *BufferIndex\r
53c71d09 1241 )\r
1242{\r
1243 UINTN Index;\r
1244 EFI_TPL OldTpl;\r
1245 OldTpl = gBS->RaiseTPL(TPL_HIGH_LEVEL);\r
1246 for (Index = 0; Index < mStackNum; Index ++) {\r
1247 if (mStackBufferIndex[Index] == NULL) {\r
1248 mStackBufferIndex[Index] = Handle;\r
1249 break;\r
1250 }\r
1251 }\r
1252 gBS->RestoreTPL(OldTpl);\r
1253 if (Index == mStackNum) {\r
1254 return EFI_OUT_OF_RESOURCES;\r
1255 }\r
1256 *BufferIndex = Index;\r
1257 *StackBuffer = mStackBuffer[Index];\r
1258 return EFI_SUCCESS;\r
1259}\r
1260\r
8e3bc754 1261/**\r
34e4e297 1262 Returns from the EBC stack by stack Index.\r
1263\r
8e3bc754 1264 @param Index Specifies which EBC stack to return from.\r
34e4e297 1265\r
8e3bc754 1266 @retval EFI_SUCCESS The function completed successfully.\r
1267\r
1268**/\r
53c71d09 1269EFI_STATUS\r
1270ReturnEBCStack(\r
8e3bc754 1271 IN UINTN Index\r
53c71d09 1272 )\r
1273{\r
8e3bc754 1274 mStackBufferIndex[Index] = NULL;\r
53c71d09 1275 return EFI_SUCCESS;\r
1276}\r
1277\r
8e3bc754 1278/**\r
34e4e297 1279 Returns from the EBC stack associated with the Handle parameter.\r
1280\r
8e3bc754 1281 @param Handle Specifies the EFI handle to find the EBC stack with.\r
34e4e297 1282\r
8e3bc754 1283 @retval EFI_SUCCESS The function completed successfully.\r
1284\r
1285**/\r
53c71d09 1286EFI_STATUS\r
1287ReturnEBCStackByHandle(\r
8e3bc754 1288 IN EFI_HANDLE Handle\r
53c71d09 1289 )\r
1290{\r
1291 UINTN Index;\r
1292 for (Index = 0; Index < mStackNum; Index ++) {\r
1293 if (mStackBufferIndex[Index] == Handle) {\r
1294 break;\r
1295 }\r
1296 }\r
1297 if (Index == mStackNum) {\r
1298 return EFI_NOT_FOUND;\r
1299 }\r
1300 mStackBufferIndex[Index] = NULL;\r
1301 return EFI_SUCCESS;\r
1302}\r
1303\r
8e3bc754 1304/**\r
1305 Allocates memory to hold all the EBC stacks.\r
1306\r
34e4e297 1307 @retval EFI_SUCCESS The EBC stacks were allocated successfully.\r
8e3bc754 1308 @retval EFI_OUT_OF_RESOURCES Not enough memory available for EBC stacks.\r
1309\r
1310**/\r
53c71d09 1311EFI_STATUS\r
1312InitEBCStack (\r
1313 VOID\r
1314 )\r
1315{\r
1316 for (mStackNum = 0; mStackNum < MAX_STACK_NUM; mStackNum ++) {\r
1317 mStackBuffer[mStackNum] = AllocatePool(STACK_POOL_SIZE);\r
1318 mStackBufferIndex[mStackNum] = NULL;\r
1319 if (mStackBuffer[mStackNum] == NULL) {\r
1320 break;\r
1321 }\r
1322 }\r
1323 if (mStackNum == 0) {\r
1324 return EFI_OUT_OF_RESOURCES;\r
1325 }\r
1326 return EFI_SUCCESS;\r
1327}\r
1328\r
8e3bc754 1329\r
1330/**\r
1331 Free all EBC stacks allocated before.\r
1332\r
1333 @retval EFI_SUCCESS All the EBC stacks were freed.\r
1334\r
1335**/\r
53c71d09 1336EFI_STATUS\r
1337FreeEBCStack(\r
1338 VOID\r
1339 )\r
1340{\r
1341 UINTN Index;\r
1342 for (Index = 0; Index < mStackNum; Index ++) {\r
1343 FreePool(mStackBuffer[Index]);\r
1344 }\r
1345 return EFI_SUCCESS;\r
1346}\r
53c71d09 1347\r
fb0b259e 1348/**\r
8e3bc754 1349 Produces an EBC VM test protocol that can be used for regression tests.\r
53c71d09 1350\r
8e3bc754 1351 @param IHandle Handle on which to install the protocol.\r
53c71d09 1352\r
8e3bc754 1353 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
1354 @retval EFI_SUCCESS The function completed successfully.\r
53c71d09 1355\r
fb0b259e 1356**/\r
fb0b259e 1357EFI_STATUS\r
1358InitEbcVmTestProtocol (\r
1359 IN EFI_HANDLE *IHandle\r
1360 )\r
53c71d09 1361{\r
1362 EFI_HANDLE Handle;\r
1363 EFI_STATUS Status;\r
1364 EFI_EBC_VM_TEST_PROTOCOL *EbcVmTestProtocol;\r
1365\r
1366 //\r
1367 // Allocate memory for the protocol, then fill in the fields\r
1368 //\r
1369 EbcVmTestProtocol = AllocatePool (sizeof (EFI_EBC_VM_TEST_PROTOCOL));\r
1370 if (EbcVmTestProtocol == NULL) {\r
1371 return EFI_OUT_OF_RESOURCES;\r
1372 }\r
1373 EbcVmTestProtocol->Execute = (EBC_VM_TEST_EXECUTE) EbcExecuteInstructions;\r
1374\r
1375 DEBUG_CODE_BEGIN ();\r
1376 EbcVmTestProtocol->Assemble = (EBC_VM_TEST_ASM) EbcVmTestUnsupported;\r
1377 EbcVmTestProtocol->Disassemble = (EBC_VM_TEST_DASM) EbcVmTestUnsupported;\r
1378 DEBUG_CODE_END ();\r
1379\r
1380 //\r
1381 // Publish the protocol\r
1382 //\r
1383 Handle = NULL;\r
c8ad2d7a 1384 Status = gBS->InstallProtocolInterface (&Handle, &gEfiEbcVmTestProtocolGuid, EFI_NATIVE_INTERFACE, EbcVmTestProtocol);\r
53c71d09 1385 if (EFI_ERROR (Status)) {\r
1386 FreePool (EbcVmTestProtocol);\r
1387 }\r
1388 return Status;\r
1389}\r
8e3bc754 1390\r
1391\r
1392/**\r
1393 Returns the EFI_UNSUPPORTED Status.\r
34e4e297 1394\r
8e3bc754 1395 @return EFI_UNSUPPORTED This function always return EFI_UNSUPPORTED status.\r
1396\r
1397**/\r
53c71d09 1398EFI_STATUS\r
c8ad2d7a 1399EFIAPI\r
8e3bc754 1400EbcVmTestUnsupported (\r
1401 VOID\r
1402 )\r
53c71d09 1403{\r
1404 return EFI_UNSUPPORTED;\r
1405}\r
1406\r