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