]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Universal/Ebc/Dxe/EbcInt.c
Replace the original Fat.FFS to fix issue which causes to read some hard-disk slowly.
[mirror_edk2.git] / EdkModulePkg / Universal / Ebc / Dxe / EbcInt.c
CommitLineData
878ddf1f 1/*++\r
2\r
3Copyright (c) 2006, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name: \r
13\r
14 EbcInt.c\r
15 \r
16Abstract:\r
17\r
18 Top level module for the EBC virtual machine implementation.\r
19 Provides auxilliary support routines for the VM. That is, routines\r
20 that are not particularly related to VM execution of EBC instructions.\r
21 \r
22--*/\r
23\r
24#include "EbcInt.h"\r
25#include "EbcExecute.h"\r
26\r
27//\r
28// We'll keep track of all thunks we create in a linked list. Each\r
29// thunk is tied to an image handle, so we have a linked list of\r
30// image handles, with each having a linked list of thunks allocated\r
31// to that image handle.\r
32//\r
33typedef struct _EBC_THUNK_LIST {\r
34 VOID *ThunkBuffer;\r
35 struct _EBC_THUNK_LIST *Next;\r
36} EBC_THUNK_LIST;\r
37\r
38typedef struct _EBC_IMAGE_LIST {\r
39 struct _EBC_IMAGE_LIST *Next;\r
40 EFI_HANDLE ImageHandle;\r
41 EBC_THUNK_LIST *ThunkList;\r
42} EBC_IMAGE_LIST;\r
43\r
44//\r
45// Function prototypes\r
46//\r
47EFI_STATUS\r
48EFIAPI\r
49InitializeEbcDriver (\r
50 IN EFI_HANDLE ImageHandle,\r
51 IN EFI_SYSTEM_TABLE *SystemTable\r
52 );\r
53\r
54STATIC\r
55EFI_STATUS\r
56EFIAPI\r
57EbcUnloadImage (\r
58 IN EFI_EBC_PROTOCOL *This,\r
59 IN EFI_HANDLE ImageHandle\r
60 );\r
61\r
62STATIC\r
63EFI_STATUS\r
64EFIAPI\r
65EbcCreateThunk (\r
66 IN EFI_EBC_PROTOCOL *This,\r
67 IN EFI_HANDLE ImageHandle,\r
68 IN VOID *EbcEntryPoint,\r
69 OUT VOID **Thunk\r
70 );\r
71\r
72STATIC\r
73EFI_STATUS\r
74EFIAPI\r
75EbcGetVersion (\r
76 IN EFI_EBC_PROTOCOL *This,\r
77 IN OUT UINT64 *Version\r
78 );\r
79\r
80//\r
81// These two functions and the GUID are used to produce an EBC test protocol.\r
82// This functionality is definitely not required for execution.\r
83//\r
84STATIC\r
85EFI_STATUS\r
86InitEbcVmTestProtocol (\r
87 IN EFI_HANDLE *Handle\r
88 );\r
89\r
90STATIC\r
91EFI_STATUS\r
92EbcVmTestUnsupported (\r
93 VOID\r
94 );\r
95\r
96STATIC\r
97EFI_STATUS\r
98EFIAPI\r
99EbcRegisterICacheFlush (\r
100 IN EFI_EBC_PROTOCOL *This,\r
101 IN EBC_ICACHE_FLUSH Flush\r
102 );\r
103\r
104STATIC\r
105EFI_STATUS\r
106EFIAPI\r
107EbcDebugGetMaximumProcessorIndex (\r
108 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
109 OUT UINTN *MaxProcessorIndex\r
110 );\r
111\r
112STATIC\r
113EFI_STATUS\r
114EFIAPI\r
115EbcDebugRegisterPeriodicCallback (\r
116 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
117 IN UINTN ProcessorIndex,\r
118 IN EFI_PERIODIC_CALLBACK PeriodicCallback\r
119 );\r
120\r
121STATIC\r
122EFI_STATUS\r
123EFIAPI\r
124EbcDebugRegisterExceptionCallback (\r
125 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
126 IN UINTN ProcessorIndex,\r
127 IN EFI_EXCEPTION_CALLBACK ExceptionCallback,\r
128 IN EFI_EXCEPTION_TYPE ExceptionType\r
129 );\r
130\r
131STATIC\r
132EFI_STATUS\r
133EFIAPI\r
134EbcDebugInvalidateInstructionCache (\r
135 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
136 IN UINTN ProcessorIndex,\r
137 IN VOID *Start,\r
138 IN UINT64 Length\r
139 );\r
140\r
141//\r
142// We have one linked list of image handles for the whole world. Since\r
143// there should only be one interpreter, make them global. They must\r
144// also be global since the execution of an EBC image does not provide\r
145// a This pointer.\r
146//\r
147static EBC_IMAGE_LIST *mEbcImageList = NULL;\r
148\r
149//\r
150// Callback function to flush the icache after thunk creation\r
151//\r
152static EBC_ICACHE_FLUSH mEbcICacheFlush;\r
153\r
154//\r
155// These get set via calls by the debug agent\r
156//\r
157static EFI_PERIODIC_CALLBACK mDebugPeriodicCallback = NULL;\r
158static EFI_EXCEPTION_CALLBACK mDebugExceptionCallback = NULL;\r
159static EFI_GUID mEfiEbcVmTestProtocolGuid = EFI_EBC_VM_TEST_PROTOCOL_GUID;\r
160\r
161EFI_STATUS\r
162EFIAPI\r
163InitializeEbcDriver (\r
164 IN EFI_HANDLE ImageHandle,\r
165 IN EFI_SYSTEM_TABLE *SystemTable\r
166 )\r
167/*++\r
168\r
169Routine Description: \r
170\r
171 Initializes the VM EFI interface. Allocates memory for the VM interface \r
172 and registers the VM protocol.\r
173\r
174Arguments: \r
175\r
176 ImageHandle - EFI image handle.\r
177 SystemTable - Pointer to the EFI system table.\r
178\r
179Returns: \r
180 Standard EFI status code.\r
181\r
182--*/\r
183{\r
184 EFI_EBC_PROTOCOL *EbcProtocol;\r
185 EFI_EBC_PROTOCOL *OldEbcProtocol;\r
186 EFI_STATUS Status;\r
187 EFI_DEBUG_SUPPORT_PROTOCOL *EbcDebugProtocol;\r
188 EFI_HANDLE *HandleBuffer;\r
189 UINTN NumHandles;\r
190 UINTN Index;\r
191 BOOLEAN Installed;\r
192\r
193 //\r
194 // Allocate memory for our protocol. Then fill in the blanks.\r
195 //\r
196 Status = gBS->AllocatePool (\r
197 EfiBootServicesData,\r
198 sizeof (EFI_EBC_PROTOCOL),\r
199 (VOID **) &EbcProtocol\r
200 );\r
201 if (Status != EFI_SUCCESS) {\r
202 return EFI_OUT_OF_RESOURCES;\r
203 }\r
204\r
205 EbcProtocol->CreateThunk = EbcCreateThunk;\r
206 EbcProtocol->UnloadImage = EbcUnloadImage;\r
207 EbcProtocol->RegisterICacheFlush = EbcRegisterICacheFlush;\r
208 EbcProtocol->GetVersion = EbcGetVersion;\r
209 mEbcICacheFlush = NULL;\r
210\r
211 //\r
212 // Find any already-installed EBC protocols and uninstall them\r
213 //\r
214 Installed = FALSE;\r
215 HandleBuffer = NULL;\r
216 Status = gBS->LocateHandleBuffer (\r
217 ByProtocol,\r
218 &gEfiEbcProtocolGuid,\r
219 NULL,\r
220 &NumHandles,\r
221 &HandleBuffer\r
222 );\r
223 if (Status == EFI_SUCCESS) {\r
224 //\r
225 // Loop through the handles\r
226 //\r
227 for (Index = 0; Index < NumHandles; Index++) {\r
228 Status = gBS->HandleProtocol (\r
229 HandleBuffer[Index],\r
230 &gEfiEbcProtocolGuid,\r
231 (VOID **) &OldEbcProtocol\r
232 );\r
233 if (Status == EFI_SUCCESS) {\r
234 if (gBS->ReinstallProtocolInterface (\r
235 HandleBuffer[Index],\r
236 &gEfiEbcProtocolGuid,\r
237 OldEbcProtocol,\r
238 EbcProtocol\r
239 ) == EFI_SUCCESS) {\r
240 Installed = TRUE;\r
241 }\r
242 }\r
243 }\r
244 }\r
245\r
246 if (HandleBuffer != NULL) {\r
247 gBS->FreePool (HandleBuffer);\r
248 HandleBuffer = NULL;\r
249 }\r
250 //\r
251 // Add the protocol so someone can locate us if we haven't already.\r
252 //\r
253 if (!Installed) {\r
254 Status = gBS->InstallProtocolInterface (\r
255 &ImageHandle,\r
256 &gEfiEbcProtocolGuid,\r
257 EFI_NATIVE_INTERFACE,\r
258 EbcProtocol\r
259 );\r
260 if (EFI_ERROR (Status)) {\r
261 gBS->FreePool (EbcProtocol);\r
262 return Status;\r
263 }\r
264 }\r
265 //\r
266 // Allocate memory for our debug protocol. Then fill in the blanks.\r
267 //\r
268 Status = gBS->AllocatePool (\r
269 EfiBootServicesData,\r
270 sizeof (EFI_DEBUG_SUPPORT_PROTOCOL),\r
271 (VOID **) &EbcDebugProtocol\r
272 );\r
273 if (Status != EFI_SUCCESS) {\r
274 return EFI_OUT_OF_RESOURCES;\r
275 }\r
276\r
277 EbcDebugProtocol->Isa = IsaEbc;\r
278 EbcDebugProtocol->GetMaximumProcessorIndex = EbcDebugGetMaximumProcessorIndex;\r
279 EbcDebugProtocol->RegisterPeriodicCallback = EbcDebugRegisterPeriodicCallback;\r
280 EbcDebugProtocol->RegisterExceptionCallback = EbcDebugRegisterExceptionCallback;\r
281 EbcDebugProtocol->InvalidateInstructionCache = EbcDebugInvalidateInstructionCache;\r
282\r
283 //\r
284 // Add the protocol so the debug agent can find us\r
285 //\r
286 Status = gBS->InstallProtocolInterface (\r
287 &ImageHandle,\r
288 &gEfiDebugSupportProtocolGuid,\r
289 EFI_NATIVE_INTERFACE,\r
290 EbcDebugProtocol\r
291 );\r
292 //\r
293 // This is recoverable, so free the memory and continue.\r
294 //\r
295 if (EFI_ERROR (Status)) {\r
296 gBS->FreePool (EbcDebugProtocol);\r
297 }\r
298 //\r
299 // Produce a VM test interface protocol. Not required for execution.\r
300 //\r
301 DEBUG_CODE (\r
302 InitEbcVmTestProtocol (&ImageHandle);\r
303 );\r
304\r
305 return Status;\r
306}\r
307\r
308STATIC\r
309EFI_STATUS\r
310EFIAPI\r
311EbcCreateThunk (\r
312 IN EFI_EBC_PROTOCOL *This,\r
313 IN EFI_HANDLE ImageHandle,\r
314 IN VOID *EbcEntryPoint,\r
315 OUT VOID **Thunk\r
316 )\r
317/*++\r
318\r
319Routine Description:\r
320 \r
321 This is the top-level routine plugged into the EBC protocol. Since thunks\r
322 are very processor-specific, from here we dispatch directly to the very \r
323 processor-specific routine EbcCreateThunks().\r
324\r
325Arguments:\r
326\r
327 This - protocol instance pointer\r
328 ImageHandle - handle to the image. The EBC interpreter may use this to keep\r
329 track of any resource allocations performed in loading and\r
330 executing the image.\r
331 EbcEntryPoint - the entry point for the image (as defined in the file header)\r
332 Thunk - pointer to thunk pointer where the address of the created\r
333 thunk is returned.\r
334\r
335Returns:\r
336\r
337 EFI_STATUS\r
338\r
339--*/\r
340{\r
341 EFI_STATUS Status;\r
342\r
343 Status = EbcCreateThunks (\r
344 ImageHandle,\r
345 EbcEntryPoint,\r
346 Thunk,\r
347 FLAG_THUNK_ENTRY_POINT\r
348 );\r
349 return Status;\r
350}\r
351\r
352STATIC\r
353EFI_STATUS\r
354EFIAPI\r
355EbcDebugGetMaximumProcessorIndex (\r
356 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
357 OUT UINTN *MaxProcessorIndex\r
358 )\r
359/*++\r
360\r
361Routine Description:\r
362 \r
363 This EBC debugger protocol service is called by the debug agent\r
364\r
365Arguments:\r
366\r
367 This - pointer to the caller's debug support protocol interface\r
368 MaxProcessorIndex - pointer to a caller allocated UINTN in which the maximum\r
369 processor index is returned.\r
370 \r
371Returns:\r
372\r
373 Standard EFI_STATUS\r
374\r
375--*/\r
376{\r
377 *MaxProcessorIndex = 0;\r
378 return EFI_SUCCESS;\r
379}\r
380\r
381STATIC\r
382EFI_STATUS\r
383EFIAPI\r
384EbcDebugRegisterPeriodicCallback (\r
385 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
386 IN UINTN ProcessorIndex,\r
387 IN EFI_PERIODIC_CALLBACK PeriodicCallback\r
388 )\r
389/*++\r
390\r
391Routine Description:\r
392 \r
393 This protocol service is called by the debug agent to register a function\r
394 for us to call on a periodic basis.\r
395 \r
396\r
397Arguments:\r
398\r
399 This - pointer to the caller's debug support protocol interface\r
400 PeriodicCallback - pointer to the function to call periodically\r
401\r
402Returns:\r
403\r
404 Always EFI_SUCCESS\r
405\r
406--*/\r
407{\r
408 mDebugPeriodicCallback = PeriodicCallback;\r
409 return EFI_SUCCESS;\r
410}\r
411\r
412STATIC\r
413EFI_STATUS\r
414EFIAPI\r
415EbcDebugRegisterExceptionCallback (\r
416 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
417 IN UINTN ProcessorIndex,\r
418 IN EFI_EXCEPTION_CALLBACK ExceptionCallback,\r
419 IN EFI_EXCEPTION_TYPE ExceptionType\r
420 )\r
421/*++\r
422\r
423Routine Description:\r
424 \r
425 This protocol service is called by the debug agent to register a function\r
426 for us to call when we detect an exception.\r
427 \r
428\r
429Arguments:\r
430\r
431 This - pointer to the caller's debug support protocol interface\r
432 PeriodicCallback - pointer to the function to call periodically\r
433\r
434Returns:\r
435\r
436 Always EFI_SUCCESS\r
437\r
438--*/\r
439{\r
440 mDebugExceptionCallback = ExceptionCallback;\r
441 return EFI_SUCCESS;\r
442}\r
443\r
444STATIC\r
445EFI_STATUS\r
446EFIAPI\r
447EbcDebugInvalidateInstructionCache (\r
448 IN EFI_DEBUG_SUPPORT_PROTOCOL *This,\r
449 IN UINTN ProcessorIndex,\r
450 IN VOID *Start,\r
451 IN UINT64 Length\r
452 )\r
453/*++\r
454\r
455Routine Description:\r
456 \r
457 This EBC debugger protocol service is called by the debug agent. Required\r
458 for DebugSupport compliance but is only stubbed out for EBC.\r
459\r
460Arguments:\r
461 \r
462Returns:\r
463\r
464 EFI_SUCCESS\r
465\r
466--*/\r
467{\r
468 return EFI_SUCCESS;\r
469}\r
470\r
471EFI_STATUS\r
472EbcDebugSignalException (\r
473 IN EFI_EXCEPTION_TYPE ExceptionType,\r
474 IN EXCEPTION_FLAGS ExceptionFlags,\r
475 IN VM_CONTEXT *VmPtr\r
476 )\r
477/*++\r
478\r
479Routine Description:\r
480\r
481 The VM interpreter calls this function when an exception is detected.\r
482 \r
483Arguments:\r
484\r
485 VmPtr - pointer to a VM context for passing info to the EFI debugger.\r
486\r
487Returns:\r
488\r
489 EFI_SUCCESS if it returns at all\r
490 \r
491--*/\r
492{\r
493 EFI_SYSTEM_CONTEXT_EBC EbcContext;\r
494 EFI_SYSTEM_CONTEXT SystemContext;\r
495 EFI_STATUS_CODE_VALUE StatusCodeValue;\r
496 BOOLEAN Report;\r
497 //\r
498 // Save the exception in the context passed in\r
499 //\r
500 VmPtr->ExceptionFlags |= ExceptionFlags;\r
501 VmPtr->LastException = ExceptionType;\r
502 //\r
503 // If it's a fatal exception, then flag it in the VM context in case an\r
504 // attached debugger tries to return from it.\r
505 //\r
506 if (ExceptionFlags & EXCEPTION_FLAG_FATAL) {\r
507 VmPtr->StopFlags |= STOPFLAG_APP_DONE;\r
508 }\r
509 //\r
510 // Initialize the context structure\r
511 //\r
512 EbcContext.R0 = VmPtr->R[0];\r
513 EbcContext.R1 = VmPtr->R[1];\r
514 EbcContext.R2 = VmPtr->R[2];\r
515 EbcContext.R3 = VmPtr->R[3];\r
516 EbcContext.R4 = VmPtr->R[4];\r
517 EbcContext.R5 = VmPtr->R[5];\r
518 EbcContext.R6 = VmPtr->R[6];\r
519 EbcContext.R7 = VmPtr->R[7];\r
520 EbcContext.Ip = (UINT64) (UINTN) VmPtr->Ip;\r
521 EbcContext.Flags = VmPtr->Flags;\r
522 SystemContext.SystemContextEbc = &EbcContext;\r
523 //\r
524 // If someone's registered for exception callbacks, then call them.\r
525 // Otherwise report the status code via the status code API\r
526 //\r
527 if (mDebugExceptionCallback != NULL) {\r
528 mDebugExceptionCallback (ExceptionType, SystemContext);\r
529 }\r
530 //\r
531 // Determine if we should report the exception. We report all of them by default,\r
532 // but if a debugger is attached don't report the breakpoint, debug, and step exceptions.\r
533 // Note that EXCEPT_EBC_OVERFLOW is never reported by this VM implementation, so is\r
534 // not included in the switch statement.\r
535 //\r
536 Report = TRUE;\r
537 switch (ExceptionType) {\r
538 case EXCEPT_EBC_UNDEFINED:\r
539 StatusCodeValue = EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_EC_EBC_UNDEFINED;\r
540 break;\r
541\r
542 case EXCEPT_EBC_DIVIDE_ERROR:\r
543 StatusCodeValue = EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_EC_EBC_DIVIDE_ERROR;\r
544 break;\r
545\r
546 case EXCEPT_EBC_DEBUG:\r
547 StatusCodeValue = EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_EC_EBC_DEBUG;\r
548 Report = (BOOLEAN) ((mDebugExceptionCallback == NULL) ? TRUE : FALSE);\r
549 break;\r
550\r
551 case EXCEPT_EBC_BREAKPOINT:\r
552 StatusCodeValue = EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_EC_EBC_BREAKPOINT;\r
553 Report = (BOOLEAN) ((mDebugExceptionCallback == NULL) ? TRUE : FALSE);\r
554 break;\r
555\r
556 case EXCEPT_EBC_INVALID_OPCODE:\r
557 StatusCodeValue = EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_EC_EBC_INVALID_OPCODE;\r
558 break;\r
559\r
560 case EXCEPT_EBC_STACK_FAULT:\r
561 StatusCodeValue = EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_EC_EBC_STACK_FAULT;\r
562 break;\r
563\r
564 case EXCEPT_EBC_ALIGNMENT_CHECK:\r
565 StatusCodeValue = EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_EC_EBC_ALIGNMENT_CHECK;\r
566 break;\r
567\r
568 case EXCEPT_EBC_INSTRUCTION_ENCODING:\r
569 StatusCodeValue = EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_EC_EBC_INSTRUCTION_ENCODING;\r
570 break;\r
571\r
572 case EXCEPT_EBC_BAD_BREAK:\r
573 StatusCodeValue = EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_EC_EBC_BAD_BREAK;\r
574 break;\r
575\r
576 case EXCEPT_EBC_STEP:\r
577 StatusCodeValue = EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_EC_EBC_STEP;\r
578 Report = (BOOLEAN) ((mDebugExceptionCallback == NULL) ? TRUE : FALSE);\r
579 break;\r
580\r
581 default:\r
582 StatusCodeValue = EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_EC_NON_SPECIFIC;\r
583 break;\r
584 }\r
585 //\r
586 // If we determined that we should report the condition, then do so now.\r
587 //\r
588 if (Report) {\r
589 REPORT_STATUS_CODE (EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED, StatusCodeValue);\r
590 }\r
591\r
592 switch (ExceptionType) {\r
593 //\r
594 // If ReportStatusCode returned, then for most exceptions we do an assert. The\r
595 // ExceptionType++ is done simply to force the ASSERT() condition to be met.\r
596 // For breakpoints, assume a debugger did not insert a software breakpoint\r
597 // and skip the instruction.\r
598 //\r
599 case EXCEPT_EBC_BREAKPOINT:\r
600 VmPtr->Ip += 2;\r
601 break;\r
602\r
603 case EXCEPT_EBC_STEP:\r
604 break;\r
605\r
606 case EXCEPT_EBC_UNDEFINED:\r
607 ExceptionType++;\r
608 ASSERT (ExceptionType == EXCEPT_EBC_UNDEFINED);\r
609 break;\r
610\r
611 case EXCEPT_EBC_DIVIDE_ERROR:\r
612 ExceptionType++;\r
613 ASSERT (ExceptionType == EXCEPT_EBC_DIVIDE_ERROR);\r
614 break;\r
615\r
616 case EXCEPT_EBC_DEBUG:\r
617 ExceptionType++;\r
618 ASSERT (ExceptionType == EXCEPT_EBC_DEBUG);\r
619 break;\r
620\r
621 case EXCEPT_EBC_INVALID_OPCODE:\r
622 ExceptionType++;\r
623 ASSERT (ExceptionType == EXCEPT_EBC_INVALID_OPCODE);\r
624 break;\r
625\r
626 case EXCEPT_EBC_STACK_FAULT:\r
627 ExceptionType++;\r
628 ASSERT (ExceptionType == EXCEPT_EBC_STACK_FAULT);\r
629 break;\r
630\r
631 case EXCEPT_EBC_ALIGNMENT_CHECK:\r
632 ExceptionType++;\r
633 ASSERT (ExceptionType == EXCEPT_EBC_ALIGNMENT_CHECK);\r
634 break;\r
635\r
636 case EXCEPT_EBC_INSTRUCTION_ENCODING:\r
637 ExceptionType++;\r
638 ASSERT (ExceptionType == EXCEPT_EBC_INSTRUCTION_ENCODING);\r
639 break;\r
640\r
641 case EXCEPT_EBC_BAD_BREAK:\r
642 ExceptionType++;\r
643 ASSERT (ExceptionType == EXCEPT_EBC_BAD_BREAK);\r
644 break;\r
645\r
646 default:\r
647 //\r
648 // Unknown\r
649 //\r
650 ASSERT (0);\r
651 break;\r
652 }\r
653\r
654 return EFI_SUCCESS;\r
655}\r
656\r
657EFI_STATUS\r
658EbcDebugPeriodic (\r
659 IN VM_CONTEXT *VmPtr\r
660 )\r
661/*++\r
662\r
663Routine Description:\r
664\r
665 The VM interpreter calls this function on a periodic basis to support\r
666 the EFI debug support protocol.\r
667 \r
668Arguments:\r
669\r
670 VmPtr - pointer to a VM context for passing info to the debugger.\r
671\r
672Returns:\r
673\r
674 Standard EFI status.\r
675 \r
676--*/\r
677{\r
678 return EFI_SUCCESS;\r
679}\r
680\r
681STATIC\r
682EFI_STATUS\r
683EFIAPI\r
684EbcUnloadImage (\r
685 IN EFI_EBC_PROTOCOL *This,\r
686 IN EFI_HANDLE ImageHandle\r
687 )\r
688/*++\r
689\r
690Routine Description:\r
691 \r
692 This routine is called by the core when an image is being unloaded from \r
693 memory. Basically we now have the opportunity to do any necessary cleanup.\r
694 Typically this will include freeing any memory allocated for thunk-creation.\r
695\r
696Arguments:\r
697\r
698 This - protocol instance pointer\r
699 ImageHandle - handle to the image being unloaded.\r
700\r
701Returns:\r
702\r
703 EFI_INVALID_PARAMETER - the ImageHandle passed in was not found in\r
704 the internal list of EBC image handles.\r
705 EFI_STATUS - completed successfully\r
706\r
707--*/\r
708{\r
709 EBC_THUNK_LIST *ThunkList;\r
710 EBC_THUNK_LIST *NextThunkList;\r
711 EBC_IMAGE_LIST *ImageList;\r
712 EBC_IMAGE_LIST *PrevImageList;\r
713 //\r
714 // First go through our list of known image handles and see if we've already\r
715 // created an image list element for this image handle.\r
716 //\r
717 PrevImageList = NULL;\r
718 for (ImageList = mEbcImageList; ImageList != NULL; ImageList = ImageList->Next) {\r
719 if (ImageList->ImageHandle == ImageHandle) {\r
720 break;\r
721 }\r
722 //\r
723 // Save the previous so we can connect the lists when we remove this one\r
724 //\r
725 PrevImageList = ImageList;\r
726 }\r
727\r
728 if (ImageList == NULL) {\r
729 return EFI_INVALID_PARAMETER;\r
730 }\r
731 //\r
732 // Free up all the thunk buffers and thunks list elements for this image\r
733 // handle.\r
734 //\r
735 ThunkList = ImageList->ThunkList;\r
736 while (ThunkList != NULL) {\r
737 NextThunkList = ThunkList->Next;\r
738 gBS->FreePool (ThunkList->ThunkBuffer);\r
739 gBS->FreePool (ThunkList);\r
740 ThunkList = NextThunkList;\r
741 }\r
742 //\r
743 // Now remove this image list element from the chain\r
744 //\r
745 if (PrevImageList == NULL) {\r
746 //\r
747 // Remove from head\r
748 //\r
749 mEbcImageList = ImageList->Next;\r
750 } else {\r
751 PrevImageList->Next = ImageList->Next;\r
752 }\r
753 //\r
754 // Now free up the image list element\r
755 //\r
756 gBS->FreePool (ImageList);\r
757 return EFI_SUCCESS;\r
758}\r
759\r
760EFI_STATUS\r
761EbcAddImageThunk (\r
762 IN EFI_HANDLE ImageHandle,\r
763 IN VOID *ThunkBuffer,\r
764 IN UINT32 ThunkSize\r
765 )\r
766/*++\r
767\r
768Routine Description:\r
769 \r
770 Add a thunk to our list of thunks for a given image handle. \r
771 Also flush the instruction cache since we've written thunk code\r
772 to memory that will be executed eventually.\r
773\r
774Arguments:\r
775\r
776 ImageHandle - the image handle to which the thunk is tied\r
777 ThunkBuffer - the buffer we've created/allocated\r
778 ThunkSize - the size of the thunk memory allocated\r
779\r
780Returns:\r
781 \r
782 EFI_OUT_OF_RESOURCES - memory allocation failed\r
783 EFI_SUCCESS - successful completion\r
784\r
785--*/\r
786{\r
787 EBC_THUNK_LIST *ThunkList;\r
788 EBC_IMAGE_LIST *ImageList;\r
789 EFI_STATUS Status;\r
790\r
791 //\r
792 // It so far so good, then flush the instruction cache\r
793 //\r
794 if (mEbcICacheFlush != NULL) {\r
795 Status = mEbcICacheFlush ((EFI_PHYSICAL_ADDRESS) (UINTN) ThunkBuffer, ThunkSize);\r
796 if (EFI_ERROR (Status)) {\r
797 return Status;\r
798 }\r
799 }\r
800 //\r
801 // Go through our list of known image handles and see if we've already\r
802 // created a image list element for this image handle.\r
803 //\r
804 for (ImageList = mEbcImageList; ImageList != NULL; ImageList = ImageList->Next) {\r
805 if (ImageList->ImageHandle == ImageHandle) {\r
806 break;\r
807 }\r
808 }\r
809\r
810 if (ImageList == NULL) {\r
811 //\r
812 // Allocate a new one\r
813 //\r
814 Status = gBS->AllocatePool (\r
815 EfiBootServicesData,\r
816 sizeof (EBC_IMAGE_LIST),\r
817 (VOID **) &ImageList\r
818 );\r
819 if (Status != EFI_SUCCESS) {\r
820 return EFI_OUT_OF_RESOURCES;\r
821 }\r
822\r
823 ImageList->ThunkList = NULL;\r
824 ImageList->ImageHandle = ImageHandle;\r
825 ImageList->Next = mEbcImageList;\r
826 mEbcImageList = ImageList;\r
827 }\r
828 //\r
829 // Ok, now create a new thunk element to add to the list\r
830 //\r
831 Status = gBS->AllocatePool (\r
832 EfiBootServicesData,\r
833 sizeof (EBC_THUNK_LIST),\r
834 (VOID **) &ThunkList\r
835 );\r
836 if (Status != EFI_SUCCESS) {\r
837 return EFI_OUT_OF_RESOURCES;\r
838 }\r
839 //\r
840 // Add it to the head of the list\r
841 //\r
842 ThunkList->Next = ImageList->ThunkList;\r
843 ThunkList->ThunkBuffer = ThunkBuffer;\r
844 ImageList->ThunkList = ThunkList;\r
845 return EFI_SUCCESS;\r
846}\r
847\r
848STATIC\r
849EFI_STATUS\r
850EFIAPI\r
851EbcRegisterICacheFlush (\r
852 IN EFI_EBC_PROTOCOL *This,\r
853 IN EBC_ICACHE_FLUSH Flush\r
854 )\r
855{\r
856 mEbcICacheFlush = Flush;\r
857 return EFI_SUCCESS;\r
858}\r
859\r
860STATIC\r
861EFI_STATUS\r
862EFIAPI\r
863EbcGetVersion (\r
864 IN EFI_EBC_PROTOCOL *This,\r
865 IN OUT UINT64 *Version\r
866 )\r
867{\r
868 if (Version == NULL) {\r
869 return EFI_INVALID_PARAMETER;\r
870 }\r
871\r
872 *Version = GetVmVersion ();\r
873 return EFI_SUCCESS;\r
874}\r
875\r
876STATIC\r
877EFI_STATUS\r
878InitEbcVmTestProtocol (\r
879 IN EFI_HANDLE *IHandle\r
880 )\r
881/*++\r
882\r
883Routine Description:\r
884 \r
885 Produce an EBC VM test protocol that can be used for regression tests.\r
886\r
887Arguments:\r
888\r
889 IHandle - handle on which to install the protocol.\r
890\r
891Returns:\r
892\r
893 EFI_OUT_OF_RESOURCES - memory allocation failed\r
894 EFI_SUCCESS - successful completion\r
895\r
896--*/\r
897{\r
898 EFI_HANDLE Handle;\r
899 EFI_STATUS Status;\r
900 EFI_EBC_VM_TEST_PROTOCOL *EbcVmTestProtocol;\r
901\r
902 //\r
903 // Allocate memory for the protocol, then fill in the fields\r
904 //\r
905 Status = gBS->AllocatePool (EfiBootServicesData, sizeof (EFI_EBC_VM_TEST_PROTOCOL), (VOID **) &EbcVmTestProtocol);\r
906 if (Status != EFI_SUCCESS) {\r
907 return EFI_OUT_OF_RESOURCES;\r
908 }\r
909 EbcVmTestProtocol->Execute = (EBC_VM_TEST_EXECUTE) EbcExecuteInstructions;\r
910\r
911 DEBUG_CODE(\r
912 EbcVmTestProtocol->Assemble = (EBC_VM_TEST_ASM) EbcVmTestUnsupported;\r
913 EbcVmTestProtocol->Disassemble = (EBC_VM_TEST_DASM) EbcVmTestUnsupported;\r
914 );\r
915\r
916 //\r
917 // Publish the protocol\r
918 //\r
919 Handle = NULL;\r
920 Status = gBS->InstallProtocolInterface (&Handle, &mEfiEbcVmTestProtocolGuid, EFI_NATIVE_INTERFACE, EbcVmTestProtocol);\r
921 if (EFI_ERROR (Status)) {\r
922 gBS->FreePool (EbcVmTestProtocol);\r
923 }\r
924 return Status;\r
925}\r
926STATIC\r
927EFI_STATUS\r
928EbcVmTestUnsupported ()\r
929{\r
930 return EFI_UNSUPPORTED;\r
931}\r
932\r