]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/EbcDxe/EbcInt.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[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
9d510e61 7SPDX-License-Identifier: BSD-2-Clause-Patent\r
53c71d09 8\r
fb0b259e 9**/\r
53c71d09 10\r
11#include "EbcInt.h"\r
12#include "EbcExecute.h"\r
6f0a3cd2 13#include "EbcDebuggerHook.h"\r
53c71d09 14\r
15//\r
16// We'll keep track of all thunks we create in a linked list. Each\r
17// thunk is tied to an image handle, so we have a linked list of\r
18// image handles, with each having a linked list of thunks allocated\r
19// to that image handle.\r
20//\r
1ccdbf2a 21typedef struct _EBC_THUNK_LIST EBC_THUNK_LIST;\r
22struct _EBC_THUNK_LIST {\r
23 VOID *ThunkBuffer;\r
24 EBC_THUNK_LIST *Next;\r
25};\r
26\r
27typedef struct _EBC_IMAGE_LIST EBC_IMAGE_LIST;\r
28struct _EBC_IMAGE_LIST {\r
29 EBC_IMAGE_LIST *Next;\r
30 EFI_HANDLE ImageHandle;\r
31 EBC_THUNK_LIST *ThunkList;\r
32};\r
53c71d09 33\r
8e3bc754 34/**\r
35 This routine is called by the core when an image is being unloaded from\r
36 memory. Basically we now have the opportunity to do any necessary cleanup.\r
37 Typically this will include freeing any memory allocated for thunk-creation.\r
38\r
39 @param This A pointer to the EFI_EBC_PROTOCOL instance.\r
40 @param ImageHandle Handle of image for which the thunk is being\r
41 created.\r
42\r
43 @retval EFI_INVALID_PARAMETER The ImageHandle passed in was not found in the\r
44 internal list of EBC image handles.\r
45 @retval EFI_SUCCESS The function completed successfully.\r
46\r
47**/\r
53c71d09 48EFI_STATUS\r
49EFIAPI\r
50EbcUnloadImage (\r
ea7cb08c 51 IN EFI_EBC_PROTOCOL *This,\r
52 IN EFI_HANDLE ImageHandle\r
53c71d09 53 );\r
54\r
8e3bc754 55/**\r
56 This is the top-level routine plugged into the EBC protocol. Since thunks\r
57 are very processor-specific, from here we dispatch directly to the very\r
58 processor-specific routine EbcCreateThunks().\r
59\r
60 @param This A pointer to the EFI_EBC_PROTOCOL instance.\r
61 @param ImageHandle Handle of image for which the thunk is being\r
62 created. The EBC interpreter may use this to\r
63 keep track of any resource allocations\r
64 performed in loading and executing the image.\r
65 @param EbcEntryPoint Address of the actual EBC entry point or\r
66 protocol service the thunk should call.\r
67 @param Thunk Returned pointer to a thunk created.\r
68\r
69 @retval EFI_SUCCESS The function completed successfully.\r
70 @retval EFI_INVALID_PARAMETER Image entry point is not 2-byte aligned.\r
71 @retval EFI_OUT_OF_RESOURCES Memory could not be allocated for the thunk.\r
72\r
73**/\r
53c71d09 74EFI_STATUS\r
75EFIAPI\r
76EbcCreateThunk (\r
ea7cb08c 77 IN EFI_EBC_PROTOCOL *This,\r
78 IN EFI_HANDLE ImageHandle,\r
79 IN VOID *EbcEntryPoint,\r
80 OUT VOID **Thunk\r
53c71d09 81 );\r
82\r
8e3bc754 83/**\r
84 Called to get the version of the interpreter.\r
85\r
86 @param This A pointer to the EFI_EBC_PROTOCOL instance.\r
87 @param Version Pointer to where to store the returned version\r
88 of the interpreter.\r
34e4e297 89\r
8e3bc754 90 @retval EFI_SUCCESS The function completed successfully.\r
91 @retval EFI_INVALID_PARAMETER Version pointer is NULL.\r
92\r
93**/\r
53c71d09 94EFI_STATUS\r
95EFIAPI\r
96EbcGetVersion (\r
ea7cb08c 97 IN EFI_EBC_PROTOCOL *This,\r
98 IN OUT UINT64 *Version\r
53c71d09 99 );\r
100\r
8e3bc754 101/**\r
102 To install default Callback function for the VM interpreter.\r
103\r
104 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL\r
105 instance.\r
106\r
107 @retval EFI_SUCCESS The function completed successfully.\r
108 @retval Others Some error occurs when creating periodic event.\r
109\r
110**/\r
53c71d09 111EFI_STATUS\r
112EFIAPI\r
113InitializeEbcCallback (\r
114 IN EFI_DEBUG_SUPPORT_PROTOCOL *This\r
115 );\r
116\r
8e3bc754 117/**\r
118 The default Exception Callback for the VM interpreter.\r
119 In this function, we report status code, and print debug information\r
120 about EBC_CONTEXT, then dead loop.\r
121\r
122 @param InterruptType Interrupt type.\r
123 @param SystemContext EBC system context.\r
124\r
125**/\r
53c71d09 126VOID\r
127EFIAPI\r
128CommonEbcExceptionHandler (\r
129 IN EFI_EXCEPTION_TYPE InterruptType,\r
130 IN EFI_SYSTEM_CONTEXT SystemContext\r
131 );\r
132\r
8e3bc754 133/**\r
134 The periodic callback function for EBC VM interpreter, which is used\r
135 to support the EFI debug support protocol.\r
136\r
137 @param Event The Periodic Callback Event.\r
138 @param Context It should be the address of VM_CONTEXT pointer.\r
139\r
140**/\r
53c71d09 141VOID\r
142EFIAPI\r
143EbcPeriodicNotifyFunction (\r
144 IN EFI_EVENT Event,\r
145 IN VOID *Context\r
146 );\r
147\r
8e3bc754 148/**\r
149 The VM interpreter calls this function on a periodic basis to support\r
150 the EFI debug support protocol.\r
151\r
152 @param VmPtr Pointer to a VM context for passing info to the\r
153 debugger.\r
154\r
155 @retval EFI_SUCCESS The function completed successfully.\r
156\r
157**/\r
53c71d09 158EFI_STATUS\r
159EFIAPI\r
160EbcDebugPeriodic (\r
161 IN VM_CONTEXT *VmPtr\r
162 );\r
163\r
164//\r
165// These two functions and the GUID are used to produce an EBC test protocol.\r
166// This functionality is definitely not required for execution.\r
167//\r
8e3bc754 168/**\r
169 Produces an EBC VM test protocol that can be used for regression tests.\r
170\r
171 @param IHandle Handle on which to install the protocol.\r
172\r
173 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
174 @retval EFI_SUCCESS The function completed successfully.\r
175\r
176**/\r
53c71d09 177EFI_STATUS\r
178InitEbcVmTestProtocol (\r
ea7cb08c 179 IN EFI_HANDLE *IHandle\r
53c71d09 180 );\r
181\r
8e3bc754 182/**\r
183 Returns the EFI_UNSUPPORTED Status.\r
34e4e297 184\r
8e3bc754 185 @return EFI_UNSUPPORTED This function always return EFI_UNSUPPORTED status.\r
186\r
187**/\r
53c71d09 188EFI_STATUS\r
c8ad2d7a 189EFIAPI\r
53c71d09 190EbcVmTestUnsupported (\r
191 VOID\r
192 );\r
193\r
8e3bc754 194/**\r
195 Registers a callback function that the EBC interpreter calls to flush the\r
34e4e297 196 processor instruction cache following creation of thunks.\r
8e3bc754 197\r
198 @param This A pointer to the EFI_EBC_PROTOCOL instance.\r
199 @param Flush Pointer to a function of type EBC_ICACH_FLUSH.\r
34e4e297 200\r
8e3bc754 201 @retval EFI_SUCCESS The function completed successfully.\r
202\r
203**/\r
53c71d09 204EFI_STATUS\r
205EFIAPI\r
206EbcRegisterICacheFlush (\r
ea7cb08c 207 IN EFI_EBC_PROTOCOL *This,\r
208 IN EBC_ICACHE_FLUSH Flush\r
53c71d09 209 );\r
210\r
8e3bc754 211/**\r
212 This EBC debugger protocol service is called by the debug agent\r
213\r
214 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL\r
215 instance.\r
216 @param MaxProcessorIndex Pointer to a caller-allocated UINTN in which the\r
217 maximum supported processor index is returned.\r
218\r
219 @retval EFI_SUCCESS The function completed successfully.\r
220\r
221**/\r
53c71d09 222EFI_STATUS\r
223EFIAPI\r
224EbcDebugGetMaximumProcessorIndex (\r
ea7cb08c 225 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
226 OUT UINTN *MaxProcessorIndex\r
53c71d09 227 );\r
228\r
8e3bc754 229/**\r
230 This protocol service is called by the debug agent to register a function\r
231 for us to call on a periodic basis.\r
232\r
233 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL\r
234 instance.\r
235 @param ProcessorIndex Specifies which processor the callback function\r
236 applies to.\r
237 @param PeriodicCallback A pointer to a function of type\r
238 PERIODIC_CALLBACK that is the main periodic\r
239 entry point of the debug agent. It receives as a\r
240 parameter a pointer to the full context of the\r
241 interrupted execution thread.\r
242\r
243 @retval EFI_SUCCESS The function completed successfully.\r
244 @retval EFI_ALREADY_STARTED Non-NULL PeriodicCallback parameter when a\r
245 callback function was previously registered.\r
246 @retval EFI_INVALID_PARAMETER Null PeriodicCallback parameter when no\r
247 callback function was previously registered.\r
248\r
249**/\r
53c71d09 250EFI_STATUS\r
251EFIAPI\r
252EbcDebugRegisterPeriodicCallback (\r
ea7cb08c 253 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
254 IN UINTN ProcessorIndex,\r
255 IN EFI_PERIODIC_CALLBACK PeriodicCallback\r
53c71d09 256 );\r
257\r
8e3bc754 258/**\r
259 This protocol service is called by the debug agent to register a function\r
260 for us to call when we detect an exception.\r
261\r
262 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL\r
263 instance.\r
264 @param ProcessorIndex Specifies which processor the callback function\r
265 applies to.\r
266 @param ExceptionCallback A pointer to a function of type\r
267 EXCEPTION_CALLBACK that is called when the\r
268 processor exception specified by ExceptionType\r
269 occurs. Passing NULL unregisters any previously\r
270 registered function associated with\r
271 ExceptionType.\r
272 @param ExceptionType Specifies which processor exception to hook.\r
273\r
274 @retval EFI_SUCCESS The function completed successfully.\r
275 @retval EFI_ALREADY_STARTED Non-NULL ExceptionCallback parameter when a\r
276 callback function was previously registered.\r
277 @retval EFI_INVALID_PARAMETER ExceptionType parameter is negative or exceeds\r
278 MAX_EBC_EXCEPTION.\r
279 @retval EFI_INVALID_PARAMETER Null ExceptionCallback parameter when no\r
280 callback function was previously registered.\r
281\r
282**/\r
53c71d09 283EFI_STATUS\r
284EFIAPI\r
285EbcDebugRegisterExceptionCallback (\r
ea7cb08c 286 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
287 IN UINTN ProcessorIndex,\r
288 IN EFI_EXCEPTION_CALLBACK ExceptionCallback,\r
289 IN EFI_EXCEPTION_TYPE ExceptionType\r
53c71d09 290 );\r
291\r
8e3bc754 292/**\r
293 This EBC debugger protocol service is called by the debug agent. Required\r
294 for DebugSupport compliance but is only stubbed out for EBC.\r
295\r
296 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL\r
297 instance.\r
298 @param ProcessorIndex Specifies which processor the callback function\r
299 applies to.\r
300 @param Start StartSpecifies the physical base of the memory\r
301 range to be invalidated.\r
302 @param Length Specifies the minimum number of bytes in the\r
34e4e297 303 processor's instruction cache to invalidate.\r
8e3bc754 304\r
305 @retval EFI_SUCCESS The function completed successfully.\r
306\r
307**/\r
53c71d09 308EFI_STATUS\r
309EFIAPI\r
310EbcDebugInvalidateInstructionCache (\r
ea7cb08c 311 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
312 IN UINTN ProcessorIndex,\r
313 IN VOID *Start,\r
314 IN UINT64 Length\r
53c71d09 315 );\r
316\r
317//\r
318// We have one linked list of image handles for the whole world. Since\r
319// there should only be one interpreter, make them global. They must\r
320// also be global since the execution of an EBC image does not provide\r
321// a This pointer.\r
322//\r
34e4e297 323EBC_IMAGE_LIST *mEbcImageList = NULL;\r
53c71d09 324\r
325//\r
326// Callback function to flush the icache after thunk creation\r
327//\r
34e4e297 328EBC_ICACHE_FLUSH mEbcICacheFlush;\r
53c71d09 329\r
330//\r
331// These get set via calls by the debug agent\r
332//\r
34e4e297 333EFI_PERIODIC_CALLBACK mDebugPeriodicCallback = NULL;\r
334EFI_EXCEPTION_CALLBACK mDebugExceptionCallback[MAX_EBC_EXCEPTION + 1] = {NULL};\r
53c71d09 335\r
34e4e297 336VOID *mStackBuffer[MAX_STACK_NUM];\r
337EFI_HANDLE mStackBufferIndex[MAX_STACK_NUM];\r
338UINTN mStackNum = 0;\r
53c71d09 339\r
340//\r
341// Event for Periodic callback\r
342//\r
34e4e297 343EFI_EVENT mEbcPeriodicEvent;\r
344VM_CONTEXT *mVmPtr = NULL;\r
53c71d09 345\r
53c71d09 346\r
fb0b259e 347/**\r
53c71d09 348 Initializes the VM EFI interface. Allocates memory for the VM interface\r
349 and registers the VM protocol.\r
350\r
fb0b259e 351 @param ImageHandle EFI image handle.\r
352 @param SystemTable Pointer to the EFI system table.\r
53c71d09 353\r
fb0b259e 354 @return Standard EFI status code.\r
53c71d09 355\r
fb0b259e 356**/\r
357EFI_STATUS\r
358EFIAPI\r
359InitializeEbcDriver (\r
360 IN EFI_HANDLE ImageHandle,\r
361 IN EFI_SYSTEM_TABLE *SystemTable\r
362 )\r
53c71d09 363{\r
364 EFI_EBC_PROTOCOL *EbcProtocol;\r
365 EFI_EBC_PROTOCOL *OldEbcProtocol;\r
366 EFI_STATUS Status;\r
367 EFI_DEBUG_SUPPORT_PROTOCOL *EbcDebugProtocol;\r
368 EFI_HANDLE *HandleBuffer;\r
369 UINTN NumHandles;\r
370 UINTN Index;\r
371 BOOLEAN Installed;\r
372\r
373 EbcProtocol = NULL;\r
374 EbcDebugProtocol = NULL;\r
375\r
376 //\r
377 // Allocate memory for our protocol. Then fill in the blanks.\r
378 //\r
379 EbcProtocol = AllocatePool (sizeof (EFI_EBC_PROTOCOL));\r
380\r
381 if (EbcProtocol == NULL) {\r
382 return EFI_OUT_OF_RESOURCES;\r
383 }\r
384\r
385 EbcProtocol->CreateThunk = EbcCreateThunk;\r
386 EbcProtocol->UnloadImage = EbcUnloadImage;\r
387 EbcProtocol->RegisterICacheFlush = EbcRegisterICacheFlush;\r
388 EbcProtocol->GetVersion = EbcGetVersion;\r
389 mEbcICacheFlush = NULL;\r
390\r
391 //\r
392 // Find any already-installed EBC protocols and uninstall them\r
393 //\r
394 Installed = FALSE;\r
395 HandleBuffer = NULL;\r
396 Status = gBS->LocateHandleBuffer (\r
397 ByProtocol,\r
398 &gEfiEbcProtocolGuid,\r
399 NULL,\r
400 &NumHandles,\r
401 &HandleBuffer\r
402 );\r
403 if (Status == EFI_SUCCESS) {\r
404 //\r
405 // Loop through the handles\r
406 //\r
407 for (Index = 0; Index < NumHandles; Index++) {\r
408 Status = gBS->HandleProtocol (\r
409 HandleBuffer[Index],\r
410 &gEfiEbcProtocolGuid,\r
411 (VOID **) &OldEbcProtocol\r
412 );\r
413 if (Status == EFI_SUCCESS) {\r
414 if (gBS->ReinstallProtocolInterface (\r
415 HandleBuffer[Index],\r
416 &gEfiEbcProtocolGuid,\r
417 OldEbcProtocol,\r
418 EbcProtocol\r
419 ) == EFI_SUCCESS) {\r
420 Installed = TRUE;\r
421 }\r
422 }\r
423 }\r
424 }\r
425\r
426 if (HandleBuffer != NULL) {\r
427 FreePool (HandleBuffer);\r
428 HandleBuffer = NULL;\r
429 }\r
430 //\r
431 // Add the protocol so someone can locate us if we haven't already.\r
432 //\r
433 if (!Installed) {\r
434 Status = gBS->InstallProtocolInterface (\r
435 &ImageHandle,\r
436 &gEfiEbcProtocolGuid,\r
437 EFI_NATIVE_INTERFACE,\r
438 EbcProtocol\r
439 );\r
440 if (EFI_ERROR (Status)) {\r
441 FreePool (EbcProtocol);\r
442 return Status;\r
443 }\r
444 }\r
445\r
446 Status = InitEBCStack();\r
447 if (EFI_ERROR(Status)) {\r
448 goto ErrorExit;\r
449 }\r
450\r
451 //\r
452 // Allocate memory for our debug protocol. Then fill in the blanks.\r
453 //\r
454 EbcDebugProtocol = AllocatePool (sizeof (EFI_DEBUG_SUPPORT_PROTOCOL));\r
455\r
456 if (EbcDebugProtocol == NULL) {\r
457 goto ErrorExit;\r
458 }\r
459\r
460 EbcDebugProtocol->Isa = IsaEbc;\r
461 EbcDebugProtocol->GetMaximumProcessorIndex = EbcDebugGetMaximumProcessorIndex;\r
462 EbcDebugProtocol->RegisterPeriodicCallback = EbcDebugRegisterPeriodicCallback;\r
463 EbcDebugProtocol->RegisterExceptionCallback = EbcDebugRegisterExceptionCallback;\r
464 EbcDebugProtocol->InvalidateInstructionCache = EbcDebugInvalidateInstructionCache;\r
465\r
466 //\r
467 // Add the protocol so the debug agent can find us\r
468 //\r
469 Status = gBS->InstallProtocolInterface (\r
470 &ImageHandle,\r
471 &gEfiDebugSupportProtocolGuid,\r
472 EFI_NATIVE_INTERFACE,\r
473 EbcDebugProtocol\r
474 );\r
475 //\r
476 // This is recoverable, so free the memory and continue.\r
477 //\r
478 if (EFI_ERROR (Status)) {\r
479 FreePool (EbcDebugProtocol);\r
480 goto ErrorExit;\r
481 }\r
482 //\r
483 // Install EbcDebugSupport Protocol Successfully\r
484 // Now we need to initialize the Ebc default Callback\r
485 //\r
486 Status = InitializeEbcCallback (EbcDebugProtocol);\r
487\r
488 //\r
489 // Produce a VM test interface protocol. Not required for execution.\r
490 //\r
491 DEBUG_CODE_BEGIN ();\r
492 InitEbcVmTestProtocol (&ImageHandle);\r
493 DEBUG_CODE_END ();\r
494\r
6f0a3cd2
PB
495 EbcDebuggerHookInit (ImageHandle, EbcDebugProtocol);\r
496\r
53c71d09 497 return EFI_SUCCESS;\r
498\r
499ErrorExit:\r
500 FreeEBCStack();\r
501 HandleBuffer = NULL;\r
502 Status = gBS->LocateHandleBuffer (\r
503 ByProtocol,\r
504 &gEfiEbcProtocolGuid,\r
505 NULL,\r
506 &NumHandles,\r
507 &HandleBuffer\r
508 );\r
509 if (Status == EFI_SUCCESS) {\r
510 //\r
511 // Loop through the handles\r
512 //\r
513 for (Index = 0; Index < NumHandles; Index++) {\r
514 Status = gBS->HandleProtocol (\r
515 HandleBuffer[Index],\r
516 &gEfiEbcProtocolGuid,\r
517 (VOID **) &OldEbcProtocol\r
518 );\r
519 if (Status == EFI_SUCCESS) {\r
520 gBS->UninstallProtocolInterface (\r
521 HandleBuffer[Index],\r
522 &gEfiEbcProtocolGuid,\r
523 OldEbcProtocol\r
524 );\r
525 }\r
526 }\r
527 }\r
528\r
529 if (HandleBuffer != NULL) {\r
530 FreePool (HandleBuffer);\r
531 HandleBuffer = NULL;\r
532 }\r
533\r
534 FreePool (EbcProtocol);\r
535\r
536 return Status;\r
537}\r
538\r
fb0b259e 539\r
540/**\r
541 This is the top-level routine plugged into the EBC protocol. Since thunks\r
542 are very processor-specific, from here we dispatch directly to the very\r
543 processor-specific routine EbcCreateThunks().\r
544\r
8e3bc754 545 @param This A pointer to the EFI_EBC_PROTOCOL instance.\r
546 @param ImageHandle Handle of image for which the thunk is being\r
547 created. The EBC interpreter may use this to\r
548 keep track of any resource allocations\r
549 performed in loading and executing the image.\r
550 @param EbcEntryPoint Address of the actual EBC entry point or\r
551 protocol service the thunk should call.\r
552 @param Thunk Returned pointer to a thunk created.\r
fb0b259e 553\r
8e3bc754 554 @retval EFI_SUCCESS The function completed successfully.\r
555 @retval EFI_INVALID_PARAMETER Image entry point is not 2-byte aligned.\r
556 @retval EFI_OUT_OF_RESOURCES Memory could not be allocated for the thunk.\r
fb0b259e 557\r
558**/\r
53c71d09 559EFI_STATUS\r
560EFIAPI\r
561EbcCreateThunk (\r
562 IN EFI_EBC_PROTOCOL *This,\r
563 IN EFI_HANDLE ImageHandle,\r
564 IN VOID *EbcEntryPoint,\r
565 OUT VOID **Thunk\r
566 )\r
53c71d09 567{\r
568 EFI_STATUS Status;\r
569\r
570 Status = EbcCreateThunks (\r
571 ImageHandle,\r
572 EbcEntryPoint,\r
573 Thunk,\r
574 FLAG_THUNK_ENTRY_POINT\r
575 );\r
576 return Status;\r
577}\r
578\r
fb0b259e 579\r
580/**\r
581 This EBC debugger protocol service is called by the debug agent\r
582\r
8e3bc754 583 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL\r
584 instance.\r
585 @param MaxProcessorIndex Pointer to a caller-allocated UINTN in which the\r
586 maximum supported processor index is returned.\r
fb0b259e 587\r
8e3bc754 588 @retval EFI_SUCCESS The function completed successfully.\r
fb0b259e 589\r
590**/\r
53c71d09 591EFI_STATUS\r
592EFIAPI\r
593EbcDebugGetMaximumProcessorIndex (\r
594 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
595 OUT UINTN *MaxProcessorIndex\r
596 )\r
53c71d09 597{\r
598 *MaxProcessorIndex = 0;\r
599 return EFI_SUCCESS;\r
600}\r
601\r
fb0b259e 602\r
603/**\r
604 This protocol service is called by the debug agent to register a function\r
605 for us to call on a periodic basis.\r
606\r
8e3bc754 607 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL\r
608 instance.\r
609 @param ProcessorIndex Specifies which processor the callback function\r
610 applies to.\r
611 @param PeriodicCallback A pointer to a function of type\r
612 PERIODIC_CALLBACK that is the main periodic\r
613 entry point of the debug agent. It receives as a\r
614 parameter a pointer to the full context of the\r
615 interrupted execution thread.\r
616\r
617 @retval EFI_SUCCESS The function completed successfully.\r
618 @retval EFI_ALREADY_STARTED Non-NULL PeriodicCallback parameter when a\r
619 callback function was previously registered.\r
620 @retval EFI_INVALID_PARAMETER Null PeriodicCallback parameter when no\r
621 callback function was previously registered.\r
fb0b259e 622\r
623**/\r
53c71d09 624EFI_STATUS\r
625EFIAPI\r
626EbcDebugRegisterPeriodicCallback (\r
627 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
628 IN UINTN ProcessorIndex,\r
629 IN EFI_PERIODIC_CALLBACK PeriodicCallback\r
630 )\r
53c71d09 631{\r
632 if ((mDebugPeriodicCallback == NULL) && (PeriodicCallback == NULL)) {\r
633 return EFI_INVALID_PARAMETER;\r
634 }\r
635 if ((mDebugPeriodicCallback != NULL) && (PeriodicCallback != NULL)) {\r
636 return EFI_ALREADY_STARTED;\r
637 }\r
638\r
639 mDebugPeriodicCallback = PeriodicCallback;\r
640 return EFI_SUCCESS;\r
641}\r
642\r
fb0b259e 643\r
644/**\r
645 This protocol service is called by the debug agent to register a function\r
646 for us to call when we detect an exception.\r
647\r
8e3bc754 648 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL\r
649 instance.\r
650 @param ProcessorIndex Specifies which processor the callback function\r
651 applies to.\r
652 @param ExceptionCallback A pointer to a function of type\r
653 EXCEPTION_CALLBACK that is called when the\r
654 processor exception specified by ExceptionType\r
655 occurs. Passing NULL unregisters any previously\r
656 registered function associated with\r
657 ExceptionType.\r
658 @param ExceptionType Specifies which processor exception to hook.\r
659\r
660 @retval EFI_SUCCESS The function completed successfully.\r
661 @retval EFI_ALREADY_STARTED Non-NULL ExceptionCallback parameter when a\r
662 callback function was previously registered.\r
663 @retval EFI_INVALID_PARAMETER ExceptionType parameter is negative or exceeds\r
664 MAX_EBC_EXCEPTION.\r
665 @retval EFI_INVALID_PARAMETER Null ExceptionCallback parameter when no\r
666 callback function was previously registered.\r
fb0b259e 667\r
668**/\r
53c71d09 669EFI_STATUS\r
670EFIAPI\r
671EbcDebugRegisterExceptionCallback (\r
672 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
673 IN UINTN ProcessorIndex,\r
674 IN EFI_EXCEPTION_CALLBACK ExceptionCallback,\r
675 IN EFI_EXCEPTION_TYPE ExceptionType\r
676 )\r
53c71d09 677{\r
678 if ((ExceptionType < 0) || (ExceptionType > MAX_EBC_EXCEPTION)) {\r
679 return EFI_INVALID_PARAMETER;\r
680 }\r
681 if ((mDebugExceptionCallback[ExceptionType] == NULL) && (ExceptionCallback == NULL)) {\r
682 return EFI_INVALID_PARAMETER;\r
683 }\r
684 if ((mDebugExceptionCallback[ExceptionType] != NULL) && (ExceptionCallback != NULL)) {\r
685 return EFI_ALREADY_STARTED;\r
686 }\r
687 mDebugExceptionCallback[ExceptionType] = ExceptionCallback;\r
688 return EFI_SUCCESS;\r
689}\r
690\r
fb0b259e 691\r
692/**\r
693 This EBC debugger protocol service is called by the debug agent. Required\r
694 for DebugSupport compliance but is only stubbed out for EBC.\r
695\r
8e3bc754 696 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL\r
697 instance.\r
698 @param ProcessorIndex Specifies which processor the callback function\r
699 applies to.\r
700 @param Start StartSpecifies the physical base of the memory\r
701 range to be invalidated.\r
702 @param Length Specifies the minimum number of bytes in the\r
34e4e297 703 processor's instruction cache to invalidate.\r
fb0b259e 704\r
8e3bc754 705 @retval EFI_SUCCESS The function completed successfully.\r
fb0b259e 706\r
707**/\r
53c71d09 708EFI_STATUS\r
709EFIAPI\r
710EbcDebugInvalidateInstructionCache (\r
711 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
712 IN UINTN ProcessorIndex,\r
713 IN VOID *Start,\r
714 IN UINT64 Length\r
715 )\r
fb0b259e 716{\r
717 return EFI_SUCCESS;\r
718}\r
53c71d09 719\r
53c71d09 720\r
fb0b259e 721/**\r
722 The VM interpreter calls this function when an exception is detected.\r
53c71d09 723\r
8e3bc754 724 @param ExceptionType Specifies the processor exception detected.\r
34e4e297 725 @param ExceptionFlags Specifies the exception context.\r
8e3bc754 726 @param VmPtr Pointer to a VM context for passing info to the\r
fb0b259e 727 EFI debugger.\r
53c71d09 728\r
8e3bc754 729 @retval EFI_SUCCESS This function completed successfully.\r
53c71d09 730\r
fb0b259e 731**/\r
53c71d09 732EFI_STATUS\r
733EbcDebugSignalException (\r
734 IN EFI_EXCEPTION_TYPE ExceptionType,\r
735 IN EXCEPTION_FLAGS ExceptionFlags,\r
736 IN VM_CONTEXT *VmPtr\r
737 )\r
53c71d09 738{\r
739 EFI_SYSTEM_CONTEXT_EBC EbcContext;\r
740 EFI_SYSTEM_CONTEXT SystemContext;\r
741\r
742 ASSERT ((ExceptionType >= 0) && (ExceptionType <= MAX_EBC_EXCEPTION));\r
743 //\r
744 // Save the exception in the context passed in\r
745 //\r
746 VmPtr->ExceptionFlags |= ExceptionFlags;\r
fbe12b79 747 VmPtr->LastException = (UINTN) ExceptionType;\r
53c71d09 748 //\r
749 // If it's a fatal exception, then flag it in the VM context in case an\r
750 // attached debugger tries to return from it.\r
751 //\r
366219ab 752 if ((ExceptionFlags & EXCEPTION_FLAG_FATAL) != 0) {\r
53c71d09 753 VmPtr->StopFlags |= STOPFLAG_APP_DONE;\r
754 }\r
755\r
756 //\r
757 // If someone's registered for exception callbacks, then call them.\r
758 //\r
759 // EBC driver will register default exception callback to report the\r
760 // status code via the status code API\r
761 //\r
762 if (mDebugExceptionCallback[ExceptionType] != NULL) {\r
763\r
764 //\r
765 // Initialize the context structure\r
766 //\r
c9325700
ED
767 EbcContext.R0 = (UINT64) VmPtr->Gpr[0];\r
768 EbcContext.R1 = (UINT64) VmPtr->Gpr[1];\r
769 EbcContext.R2 = (UINT64) VmPtr->Gpr[2];\r
770 EbcContext.R3 = (UINT64) VmPtr->Gpr[3];\r
771 EbcContext.R4 = (UINT64) VmPtr->Gpr[4];\r
772 EbcContext.R5 = (UINT64) VmPtr->Gpr[5];\r
773 EbcContext.R6 = (UINT64) VmPtr->Gpr[6];\r
774 EbcContext.R7 = (UINT64) VmPtr->Gpr[7];\r
53c71d09 775 EbcContext.Ip = (UINT64)(UINTN)VmPtr->Ip;\r
776 EbcContext.Flags = VmPtr->Flags;\r
777 EbcContext.ControlFlags = 0;\r
778 SystemContext.SystemContextEbc = &EbcContext;\r
779\r
780 mDebugExceptionCallback[ExceptionType] (ExceptionType, SystemContext);\r
781 //\r
782 // Restore the context structure and continue to execute\r
783 //\r
1ccdbf2a 784 VmPtr->Gpr[0] = EbcContext.R0;\r
785 VmPtr->Gpr[1] = EbcContext.R1;\r
786 VmPtr->Gpr[2] = EbcContext.R2;\r
787 VmPtr->Gpr[3] = EbcContext.R3;\r
788 VmPtr->Gpr[4] = EbcContext.R4;\r
789 VmPtr->Gpr[5] = EbcContext.R5;\r
790 VmPtr->Gpr[6] = EbcContext.R6;\r
791 VmPtr->Gpr[7] = EbcContext.R7;\r
53c71d09 792 VmPtr->Ip = (VMIP)(UINTN)EbcContext.Ip;\r
793 VmPtr->Flags = EbcContext.Flags;\r
794 }\r
795\r
796 return EFI_SUCCESS;\r
797}\r
798\r
53c71d09 799\r
fb0b259e 800/**\r
53c71d09 801 To install default Callback function for the VM interpreter.\r
802\r
8e3bc754 803 @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL\r
804 instance.\r
53c71d09 805\r
8e3bc754 806 @retval EFI_SUCCESS The function completed successfully.\r
807 @retval Others Some error occurs when creating periodic event.\r
53c71d09 808\r
fb0b259e 809**/\r
fb0b259e 810EFI_STATUS\r
8e3bc754 811EFIAPI\r
fb0b259e 812InitializeEbcCallback (\r
813 IN EFI_DEBUG_SUPPORT_PROTOCOL *This\r
814 )\r
53c71d09 815{\r
816 INTN Index;\r
817 EFI_STATUS Status;\r
818\r
819 //\r
820 // For ExceptionCallback\r
821 //\r
822 for (Index = 0; Index <= MAX_EBC_EXCEPTION; Index++) {\r
823 EbcDebugRegisterExceptionCallback (\r
824 This,\r
825 0,\r
826 CommonEbcExceptionHandler,\r
827 Index\r
828 );\r
829 }\r
830\r
831 //\r
832 // For PeriodicCallback\r
833 //\r
834 Status = gBS->CreateEvent (\r
835 EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
836 TPL_NOTIFY,\r
837 EbcPeriodicNotifyFunction,\r
838 &mVmPtr,\r
839 &mEbcPeriodicEvent\r
840 );\r
841 if (EFI_ERROR(Status)) {\r
842 return Status;\r
843 }\r
844\r
845 Status = gBS->SetTimer (\r
846 mEbcPeriodicEvent,\r
847 TimerPeriodic,\r
848 EBC_VM_PERIODIC_CALLBACK_RATE\r
849 );\r
850 if (EFI_ERROR(Status)) {\r
851 return Status;\r
852 }\r
853\r
854 return EFI_SUCCESS;\r
855}\r
856\r
53c71d09 857\r
fb0b259e 858/**\r
53c71d09 859 The default Exception Callback for the VM interpreter.\r
860 In this function, we report status code, and print debug information\r
861 about EBC_CONTEXT, then dead loop.\r
862\r
fb0b259e 863 @param InterruptType Interrupt type.\r
864 @param SystemContext EBC system context.\r
53c71d09 865\r
fb0b259e 866**/\r
fb0b259e 867VOID\r
8e3bc754 868EFIAPI\r
fb0b259e 869CommonEbcExceptionHandler (\r
870 IN EFI_EXCEPTION_TYPE InterruptType,\r
871 IN EFI_SYSTEM_CONTEXT SystemContext\r
872 )\r
53c71d09 873{\r
fa97cbf4
JY
874 //\r
875 // We print debug information to let user know what happen.\r
876 //\r
877 DEBUG ((\r
878 EFI_D_ERROR,\r
879 "EBC Interrupter Version - 0x%016lx\n",\r
880 (UINT64) (((VM_MAJOR_VERSION & 0xFFFF) << 16) | ((VM_MINOR_VERSION & 0xFFFF)))\r
881 ));\r
882 DEBUG ((\r
883 EFI_D_ERROR,\r
884 "Exception Type - 0x%016lx\n",\r
885 (UINT64)(UINTN)InterruptType\r
886 ));\r
887 DEBUG ((\r
888 EFI_D_ERROR,\r
889 " R0 - 0x%016lx, R1 - 0x%016lx\n",\r
890 SystemContext.SystemContextEbc->R0,\r
891 SystemContext.SystemContextEbc->R1\r
892 ));\r
893 DEBUG ((\r
894 EFI_D_ERROR,\r
895 " R2 - 0x%016lx, R3 - 0x%016lx\n",\r
896 SystemContext.SystemContextEbc->R2,\r
897 SystemContext.SystemContextEbc->R3\r
898 ));\r
899 DEBUG ((\r
900 EFI_D_ERROR,\r
901 " R4 - 0x%016lx, R5 - 0x%016lx\n",\r
902 SystemContext.SystemContextEbc->R4,\r
903 SystemContext.SystemContextEbc->R5\r
904 ));\r
905 DEBUG ((\r
906 EFI_D_ERROR,\r
907 " R6 - 0x%016lx, R7 - 0x%016lx\n",\r
908 SystemContext.SystemContextEbc->R6,\r
909 SystemContext.SystemContextEbc->R7\r
910 ));\r
911 DEBUG ((\r
912 EFI_D_ERROR,\r
913 " Flags - 0x%016lx\n",\r
914 SystemContext.SystemContextEbc->Flags\r
915 ));\r
916 DEBUG ((\r
917 EFI_D_ERROR,\r
918 " ControlFlags - 0x%016lx\n",\r
919 SystemContext.SystemContextEbc->ControlFlags\r
920 ));\r
921 DEBUG ((\r
922 EFI_D_ERROR,\r
923 " Ip - 0x%016lx\n\n",\r
924 SystemContext.SystemContextEbc->Ip\r
925 ));\r
926\r
53c71d09 927 //\r
928 // We deadloop here to make it easy to debug this issue.\r
929 //\r
fa97cbf4 930 CpuDeadLoop ();\r
53c71d09 931\r
932 return ;\r
933}\r
934\r
fb0b259e 935\r
936/**\r
937 The periodic callback function for EBC VM interpreter, which is used\r
938 to support the EFI debug support protocol.\r
939\r
940 @param Event The Periodic Callback Event.\r
941 @param Context It should be the address of VM_CONTEXT pointer.\r
942\r
fb0b259e 943**/\r
53c71d09 944VOID\r
945EFIAPI\r
946EbcPeriodicNotifyFunction (\r
947 IN EFI_EVENT Event,\r
948 IN VOID *Context\r
949 )\r
53c71d09 950{\r
951 VM_CONTEXT *VmPtr;\r
952\r
953 VmPtr = *(VM_CONTEXT **)Context;\r
954\r
955 if (VmPtr != NULL) {\r
956 EbcDebugPeriodic (VmPtr);\r
957 }\r
958\r
959 return ;\r
960}\r
961\r
53c71d09 962\r
fb0b259e 963/**\r
53c71d09 964 The VM interpreter calls this function on a periodic basis to support\r
965 the EFI debug support protocol.\r
966\r
8e3bc754 967 @param VmPtr Pointer to a VM context for passing info to the\r
fb0b259e 968 debugger.\r
53c71d09 969\r
8e3bc754 970 @retval EFI_SUCCESS The function completed successfully.\r
53c71d09 971\r
fb0b259e 972**/\r
fb0b259e 973EFI_STATUS\r
8e3bc754 974EFIAPI\r
fb0b259e 975EbcDebugPeriodic (\r
976 IN VM_CONTEXT *VmPtr\r
977 )\r
53c71d09 978{\r
979 EFI_SYSTEM_CONTEXT_EBC EbcContext;\r
980 EFI_SYSTEM_CONTEXT SystemContext;\r
981\r
982 //\r
983 // If someone's registered for periodic callbacks, then call them.\r
984 //\r
985 if (mDebugPeriodicCallback != NULL) {\r
986\r
987 //\r
988 // Initialize the context structure\r
989 //\r
c9325700
ED
990 EbcContext.R0 = (UINT64) VmPtr->Gpr[0];\r
991 EbcContext.R1 = (UINT64) VmPtr->Gpr[1];\r
992 EbcContext.R2 = (UINT64) VmPtr->Gpr[2];\r
993 EbcContext.R3 = (UINT64) VmPtr->Gpr[3];\r
994 EbcContext.R4 = (UINT64) VmPtr->Gpr[4];\r
995 EbcContext.R5 = (UINT64) VmPtr->Gpr[5];\r
996 EbcContext.R6 = (UINT64) VmPtr->Gpr[6];\r
997 EbcContext.R7 = (UINT64) VmPtr->Gpr[7];\r
53c71d09 998 EbcContext.Ip = (UINT64)(UINTN)VmPtr->Ip;\r
999 EbcContext.Flags = VmPtr->Flags;\r
1000 EbcContext.ControlFlags = 0;\r
1001 SystemContext.SystemContextEbc = &EbcContext;\r
1002\r
1003 mDebugPeriodicCallback (SystemContext);\r
1004\r
1005 //\r
1006 // Restore the context structure and continue to execute\r
1007 //\r
1ccdbf2a 1008 VmPtr->Gpr[0] = EbcContext.R0;\r
1009 VmPtr->Gpr[1] = EbcContext.R1;\r
1010 VmPtr->Gpr[2] = EbcContext.R2;\r
1011 VmPtr->Gpr[3] = EbcContext.R3;\r
1012 VmPtr->Gpr[4] = EbcContext.R4;\r
1013 VmPtr->Gpr[5] = EbcContext.R5;\r
1014 VmPtr->Gpr[6] = EbcContext.R6;\r
1015 VmPtr->Gpr[7] = EbcContext.R7;\r
53c71d09 1016 VmPtr->Ip = (VMIP)(UINTN)EbcContext.Ip;\r
1017 VmPtr->Flags = EbcContext.Flags;\r
1018 }\r
1019\r
1020 return EFI_SUCCESS;\r
1021}\r
1022\r
53c71d09 1023\r
fb0b259e 1024/**\r
53c71d09 1025 This routine is called by the core when an image is being unloaded from\r
1026 memory. Basically we now have the opportunity to do any necessary cleanup.\r
1027 Typically this will include freeing any memory allocated for thunk-creation.\r
1028\r
8e3bc754 1029 @param This A pointer to the EFI_EBC_PROTOCOL instance.\r
1030 @param ImageHandle Handle of image for which the thunk is being\r
1031 created.\r
53c71d09 1032\r
8e3bc754 1033 @retval EFI_INVALID_PARAMETER The ImageHandle passed in was not found in the\r
1034 internal list of EBC image handles.\r
1035 @retval EFI_SUCCESS The function completed successfully.\r
53c71d09 1036\r
fb0b259e 1037**/\r
fb0b259e 1038EFI_STATUS\r
1039EFIAPI\r
1040EbcUnloadImage (\r
1041 IN EFI_EBC_PROTOCOL *This,\r
1042 IN EFI_HANDLE ImageHandle\r
1043 )\r
53c71d09 1044{\r
1045 EBC_THUNK_LIST *ThunkList;\r
1046 EBC_THUNK_LIST *NextThunkList;\r
1047 EBC_IMAGE_LIST *ImageList;\r
1048 EBC_IMAGE_LIST *PrevImageList;\r
1049 //\r
1050 // First go through our list of known image handles and see if we've already\r
1051 // created an image list element for this image handle.\r
1052 //\r
1053 ReturnEBCStackByHandle(ImageHandle);\r
1054 PrevImageList = NULL;\r
1055 for (ImageList = mEbcImageList; ImageList != NULL; ImageList = ImageList->Next) {\r
1056 if (ImageList->ImageHandle == ImageHandle) {\r
1057 break;\r
1058 }\r
1059 //\r
1060 // Save the previous so we can connect the lists when we remove this one\r
1061 //\r
1062 PrevImageList = ImageList;\r
1063 }\r
1064\r
1065 if (ImageList == NULL) {\r
1066 return EFI_INVALID_PARAMETER;\r
1067 }\r
1068 //\r
1069 // Free up all the thunk buffers and thunks list elements for this image\r
1070 // handle.\r
1071 //\r
1072 ThunkList = ImageList->ThunkList;\r
1073 while (ThunkList != NULL) {\r
1074 NextThunkList = ThunkList->Next;\r
1075 FreePool (ThunkList->ThunkBuffer);\r
1076 FreePool (ThunkList);\r
1077 ThunkList = NextThunkList;\r
1078 }\r
1079 //\r
1080 // Now remove this image list element from the chain\r
1081 //\r
1082 if (PrevImageList == NULL) {\r
1083 //\r
1084 // Remove from head\r
1085 //\r
1086 mEbcImageList = ImageList->Next;\r
1087 } else {\r
1088 PrevImageList->Next = ImageList->Next;\r
1089 }\r
1090 //\r
1091 // Now free up the image list element\r
1092 //\r
1093 FreePool (ImageList);\r
6f0a3cd2
PB
1094\r
1095 EbcDebuggerHookEbcUnloadImage (ImageHandle);\r
1096\r
53c71d09 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
16dc5b68
AB
1407/**\r
1408 Allocates a buffer of type EfiBootServicesCode.\r
1409\r
1410 @param AllocationSize The number of bytes to allocate.\r
1411\r
1412 @return A pointer to the allocated buffer or NULL if allocation fails.\r
1413\r
1414**/\r
1415VOID *\r
1416EFIAPI\r
1417EbcAllocatePoolForThunk (\r
1418 IN UINTN AllocationSize\r
1419 )\r
1420{\r
1421 VOID *Buffer;\r
1422 EFI_STATUS Status;\r
1423\r
1424 Status = gBS->AllocatePool (EfiBootServicesCode, AllocationSize, &Buffer);\r
1425 if (EFI_ERROR (Status)) {\r
1426 return NULL;\r
1427 }\r
1428 return Buffer;\r
1429}\r