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