Changed old event definitions reference to these new event definitions. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2729 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			509 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			509 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*++
 | |
| 
 | |
| Copyright (c) 2006, Intel Corporation
 | |
| All rights reserved. This program and the accompanying materials
 | |
| are licensed and made available under the terms and conditions of the BSD License
 | |
| which accompanies this distribution.  The full text of the license may be found at
 | |
| http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
| Module Name:
 | |
| 
 | |
|   Runtime.c
 | |
| 
 | |
| Abstract:
 | |
| 
 | |
|   Runtime Architectural Protocol as defined in the DXE CIS
 | |
| 
 | |
|   This code is used to produce the EFI runtime virtual switch over
 | |
| 
 | |
|   THIS IS VERY DANGEROUS CODE BE VERY CAREFUL IF YOU CHANGE IT
 | |
| 
 | |
|   The transition for calling EFI Runtime functions in physical mode to calling
 | |
|   them in virtual mode is very very complex. Every pointer in needs to be
 | |
|   converted from physical mode to virtual mode. Be very careful walking linked
 | |
|   lists! Then to make it really hard the code it's self needs be relocated into
 | |
|   the new virtual address space.
 | |
| 
 | |
|   So here is the concept. The code in this module will never ever be called in
 | |
|   virtual mode. This is the code that collects the information needed to convert
 | |
|   to virtual mode (DXE core registers runtime stuff with this code). Since this
 | |
|   code is used to fixup all runtime images, it CAN NOT fix it's self up. So some
 | |
|   code has to stay behind and that is us.
 | |
| 
 | |
|   Also you need to be careful about when you allocate memory, as once we are in
 | |
|   runtime (including our EVT_SIGNAL_EXIT_BOOT_SERVICES event) you can no longer
 | |
|   allocate memory.
 | |
| 
 | |
|   Any runtime driver that gets loaded before us will not be callable in virtual
 | |
|   mode. This is due to the fact that the DXE core can not register the info
 | |
|   needed with us. This is good, since it keeps the code in this file from
 | |
|   getting registered.
 | |
| 
 | |
| 
 | |
| Revision History:
 | |
| 
 | |
|   - Move the CalculateCrc32 function from Runtime Arch Protocol to Boot Service.
 | |
|   Runtime Arch Protocol definition no longer contains CalculateCrc32. Boot Service
 | |
|   Table now contains an item named CalculateCrc32.
 | |
| 
 | |
| --*/
 | |
| 
 | |
| 
 | |
| #include "Runtime.h"
 | |
| 
 | |
| //
 | |
| // Global Variables
 | |
| //
 | |
| EFI_MEMORY_DESCRIPTOR         *mVirtualMap                = NULL;
 | |
| UINTN                         mVirtualMapDescriptorSize;
 | |
| UINTN                         mVirtualMapMaxIndex;
 | |
| VOID                          *mMyImageBase;
 | |
| 
 | |
| //
 | |
| // The handle onto which the Runtime Architectural Protocol instance is installed
 | |
| //
 | |
| EFI_HANDLE                    mRuntimeHandle = NULL;
 | |
| 
 | |
| //
 | |
| // The Runtime Architectural Protocol instance produced by this driver
 | |
| //
 | |
| EFI_RUNTIME_ARCH_PROTOCOL     mRuntime = {
 | |
|   INITIALIZE_LIST_HEAD_VARIABLE (mRuntime.ImageHead),
 | |
|   INITIALIZE_LIST_HEAD_VARIABLE (mRuntime.EventHead),
 | |
| 
 | |
|   //
 | |
|   // Make sure Size != sizeof (EFI_MEMORY_DESCRIPTOR). This will
 | |
|   // prevent people from having pointer math bugs in their code.
 | |
|   // now you have to use *DescriptorSize to make things work.
 | |
|   //
 | |
|   sizeof (EFI_MEMORY_DESCRIPTOR) + sizeof (UINT64) - (sizeof (EFI_MEMORY_DESCRIPTOR) % sizeof (UINT64)),
 | |
|   EFI_MEMORY_DESCRIPTOR_VERSION,
 | |
|   0,
 | |
|   NULL,
 | |
|   NULL,
 | |
|   FALSE,
 | |
|   FALSE
 | |
| };
 | |
| 
 | |
| //
 | |
| // Worker Functions
 | |
| //
 | |
| STATIC
 | |
| VOID
 | |
| RuntimeDriverCalculateEfiHdrCrc (
 | |
|   IN OUT EFI_TABLE_HEADER  *Hdr
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Calcualte the 32-bit CRC in a EFI table using the Runtime Drivers
 | |
|   internal function.  The EFI Boot Services Table can not be used because
 | |
|   the EFI Boot Services Table was destroyed at ExitBootServices()
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   Hdr  - Pointer to an EFI standard header
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   None
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   UINT32  Crc;
 | |
| 
 | |
|   Hdr->CRC32  = 0;
 | |
| 
 | |
|   Crc         = 0;
 | |
|   RuntimeDriverCalculateCrc32 ((UINT8 *) Hdr, Hdr->HeaderSize, &Crc);
 | |
|   Hdr->CRC32 = Crc;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| RuntimeDriverConvertPointer (
 | |
|   IN     UINTN  DebugDisposition,
 | |
|   IN OUT VOID   **ConvertAddress
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Determines the new virtual address that is to be used on subsequent memory accesses.
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   DebugDisposition    - Supplies type information for the pointer being converted.
 | |
|   ConvertAddress      - A pointer to a pointer that is to be fixed to be the value needed
 | |
|                         for the new virtual address mappings being applied.
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS             - The pointer pointed to by Address was modified.
 | |
|   EFI_NOT_FOUND           - The pointer pointed to by Address was not found to be part
 | |
|                             of the current memory map. This is normally fatal.
 | |
|   EFI_INVALID_PARAMETER   - One of the parameters has an invalid value.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   UINTN                 Address;
 | |
|   VOID                  *PlabelConvertAddress;
 | |
|   UINT64                VirtEndOfRange;
 | |
|   EFI_MEMORY_DESCRIPTOR *VirtEntry;
 | |
|   UINTN                 Index;
 | |
| 
 | |
|   //
 | |
|   // Make sure ConvertAddress is a valid pointer
 | |
|   //
 | |
|   if (ConvertAddress == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
|   //
 | |
|   // Get the address to convert
 | |
|   //
 | |
|   Address = (UINTN) *ConvertAddress;
 | |
| 
 | |
|   //
 | |
|   // If this is a null pointer, return if it's allowed
 | |
|   //
 | |
|   if (Address == 0) {
 | |
|     if (DebugDisposition & EFI_OPTIONAL_POINTER) {
 | |
|       return EFI_SUCCESS;
 | |
|     }
 | |
| 
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   PlabelConvertAddress  = NULL;
 | |
|   VirtEntry             = mVirtualMap;
 | |
|   for (Index = 0; Index < mVirtualMapMaxIndex; Index++) {
 | |
|     //
 | |
|     // To prevent the inclusion of 64-bit math functions a UINTN was placed in
 | |
|     //  front of VirtEntry->NumberOfPages to cast it to a 32-bit thing on IA-32
 | |
|     //  platforms. If you get this ASSERT remove the UINTN and do a 64-bit
 | |
|     //  multiply.
 | |
|     //
 | |
|     ASSERT (((UINTN) VirtEntry->NumberOfPages < 0xffffffff) || (sizeof (UINTN) > 4));
 | |
| 
 | |
|     if ((VirtEntry->Attribute & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME) {
 | |
|       if (Address >= VirtEntry->PhysicalStart) {
 | |
|         VirtEndOfRange = VirtEntry->PhysicalStart + (((UINTN) VirtEntry->NumberOfPages) * EFI_PAGE_SIZE);
 | |
|         if (Address < VirtEndOfRange) {
 | |
|           //
 | |
|           // Compute new address
 | |
|           //
 | |
|           *ConvertAddress = (VOID *) (Address - (UINTN) VirtEntry->PhysicalStart + (UINTN) VirtEntry->VirtualStart);
 | |
|           return EFI_SUCCESS;
 | |
|         } else if (Address < (VirtEndOfRange + 0x200000)) {
 | |
|           //
 | |
|           // On Itanium GP defines a window +/- 2 MB inside an image.
 | |
|           // The compiler may asign a GP value outside of the image. Thus
 | |
|           // it could fall out side of any of our valid regions
 | |
|           //
 | |
|           PlabelConvertAddress = (VOID *) (Address - (UINTN) VirtEntry->PhysicalStart + (UINTN) VirtEntry->VirtualStart);
 | |
|         }
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     VirtEntry = NextMemoryDescriptor (VirtEntry, mVirtualMapDescriptorSize);
 | |
|   }
 | |
| 
 | |
|   if (DebugDisposition & EFI_IPF_GP_POINTER) {
 | |
|     //
 | |
|     // If it's an IPF GP and the GP was outside the image handle that case.
 | |
|     //
 | |
|     if (PlabelConvertAddress != NULL) {
 | |
|       *ConvertAddress = PlabelConvertAddress;
 | |
|       return EFI_SUCCESS;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return EFI_NOT_FOUND;
 | |
| }
 | |
| 
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| RuntimeDriverConvertInternalPointer (
 | |
|   IN OUT VOID   **ConvertAddress
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Determines the new virtual address that is to be used on subsequent memory accesses
 | |
|   for internal pointers.
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   ConvertAddress  - A pointer to a pointer that is to be fixed to be the value needed
 | |
|                     for the new virtual address mappings being applied.
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS             - The pointer pointed to by Address was modified.
 | |
|   EFI_NOT_FOUND           - The pointer pointed to by Address was not found to be part
 | |
|                             of the current memory map. This is normally fatal.
 | |
|   EFI_INVALID_PARAMETER   - One of the parameters has an invalid value.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   return RuntimeDriverConvertPointer (0x0, ConvertAddress);
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| RuntimeDriverSetVirtualAddressMap (
 | |
|   IN UINTN                  MemoryMapSize,
 | |
|   IN UINTN                  DescriptorSize,
 | |
|   IN UINT32                 DescriptorVersion,
 | |
|   IN EFI_MEMORY_DESCRIPTOR  *VirtualMap
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Changes the runtime addressing mode of EFI firmware from physical to virtual.
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   MemoryMapSize     - The size in bytes of VirtualMap.
 | |
|   DescriptorSize    - The size in bytes of an entry in the VirtualMap.
 | |
|   DescriptorVersion - The version of the structure entries in VirtualMap.
 | |
|   VirtualMap        - An array of memory descriptors which contain new virtual
 | |
|                       address mapping information for all runtime ranges.
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCCESS           - The virtual address map has been applied.
 | |
|   EFI_UNSUPPORTED       - EFI firmware is not at runtime, or the EFI firmware is already in
 | |
|                           virtual address mapped mode.
 | |
|   EFI_INVALID_PARAMETER - DescriptorSize or DescriptorVersion is invalid.
 | |
|   EFI_NO_MAPPING        - A virtual address was not supplied for a range in the memory
 | |
|                           map that requires a mapping.
 | |
|   EFI_NOT_FOUND         - A virtual address was supplied for an address that is not found
 | |
|                           in the memory map.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS                    Status;
 | |
|   EFI_RUNTIME_EVENT_ENTRY       *RuntimeEvent;
 | |
|   EFI_RUNTIME_IMAGE_ENTRY       *RuntimeImage;
 | |
|   LIST_ENTRY                    *Link;
 | |
|   UINTN                         Index;
 | |
|   UINTN                         Index1;
 | |
|   EFI_DRIVER_OS_HANDOFF_HEADER  *DriverOsHandoffHeader;
 | |
|   EFI_DRIVER_OS_HANDOFF         *DriverOsHandoff;
 | |
|   EFI_PHYSICAL_ADDRESS          VirtImageBase;
 | |
|   EFI_CAPSULE_TABLE             *CapsuleTable;
 | |
| 
 | |
|   //
 | |
|   // Can only switch to virtual addresses once the memory map is locked down,
 | |
|   // and can only set it once
 | |
|   //
 | |
|   if (!mRuntime.AtRuntime || mRuntime.VirtualMode) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
|   //
 | |
|   // Only understand the original descriptor format
 | |
|   //
 | |
|   if (DescriptorVersion != EFI_MEMORY_DESCRIPTOR_VERSION || DescriptorSize < sizeof (EFI_MEMORY_DESCRIPTOR)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
|   //
 | |
|   // We are now committed to go to virtual mode, so lets get to it!
 | |
|   //
 | |
|   mRuntime.VirtualMode = TRUE;
 | |
| 
 | |
|   //
 | |
|   // ConvertPointer() needs this mVirtualMap to do the conversion. So set up
 | |
|   // globals we need to parse the virtual address map.
 | |
|   //
 | |
|   mVirtualMapDescriptorSize = DescriptorSize;
 | |
|   mVirtualMapMaxIndex       = MemoryMapSize / DescriptorSize;
 | |
|   mVirtualMap               = VirtualMap;
 | |
| 
 | |
|   //
 | |
|   // Currently the bug in StatusCode/RuntimeLib has been fixed, it will
 | |
|   // check whether in Runtime or not (this is judged by looking at
 | |
|   // mEfiAtRuntime global So this ReportStatusCode will work
 | |
|   //
 | |
|   REPORT_STATUS_CODE (
 | |
|           EFI_PROGRESS_CODE,
 | |
|           (EFI_SOFTWARE_EFI_BOOT_SERVICE | EFI_SW_RS_PC_SET_VIRTUAL_ADDRESS_MAP)
 | |
|           );
 | |
| 
 | |
|   //
 | |
|   // Signal all the EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE events.
 | |
|   // All runtime events are stored in a list in Runtime AP.
 | |
|   //
 | |
|   for (Link = mRuntime.EventHead.ForwardLink; Link != &mRuntime.EventHead; Link = Link->ForwardLink) {
 | |
|     RuntimeEvent = _CR (Link, EFI_RUNTIME_EVENT_ENTRY, Link);
 | |
|     if ((RuntimeEvent->Type & EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE) == EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE) {
 | |
|       RuntimeEvent->NotifyFunction (
 | |
|                       RuntimeEvent->Event,
 | |
|                       RuntimeEvent->NotifyContext
 | |
|                       );
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Relocate runtime images. All runtime images are stored in a list in Runtime AP.
 | |
|   //
 | |
|   for (Link = mRuntime.ImageHead.ForwardLink; Link != &mRuntime.ImageHead; Link = Link->ForwardLink) {
 | |
|     RuntimeImage = _CR (Link, EFI_RUNTIME_IMAGE_ENTRY, Link);
 | |
|     //
 | |
|     // We don't want to relocate our selves, as we only run in physical mode.
 | |
|     //
 | |
|     if (mMyImageBase != RuntimeImage->ImageBase) {
 | |
| 
 | |
|       VirtImageBase = (EFI_PHYSICAL_ADDRESS) (UINTN) RuntimeImage->ImageBase;
 | |
|       Status  = RuntimeDriverConvertPointer (0, (VOID **) &VirtImageBase);
 | |
|       ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|       PeCoffLoaderRelocateImageForRuntime (
 | |
|         (EFI_PHYSICAL_ADDRESS) (UINTN) RuntimeImage->ImageBase,
 | |
|         VirtImageBase,
 | |
|         (UINTN) RuntimeImage->ImageSize,
 | |
|         RuntimeImage->RelocationData
 | |
|         );
 | |
| 
 | |
|       InvalidateInstructionCacheRange (RuntimeImage->ImageBase, (UINTN)RuntimeImage->ImageSize);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Convert all the Runtime Services except ConvertPointer() and SetVirtualAddressMap()
 | |
|   // and recompute the CRC-32
 | |
|   //
 | |
|   RuntimeDriverConvertInternalPointer ((VOID **) &gRT->GetTime);
 | |
|   RuntimeDriverConvertInternalPointer ((VOID **) &gRT->SetTime);
 | |
|   RuntimeDriverConvertInternalPointer ((VOID **) &gRT->GetWakeupTime);
 | |
|   RuntimeDriverConvertInternalPointer ((VOID **) &gRT->SetWakeupTime);
 | |
|   RuntimeDriverConvertInternalPointer ((VOID **) &gRT->ResetSystem);
 | |
|   RuntimeDriverConvertInternalPointer ((VOID **) &gRT->GetNextHighMonotonicCount);
 | |
|   RuntimeDriverConvertInternalPointer ((VOID **) &gRT->GetVariable);
 | |
|   RuntimeDriverConvertInternalPointer ((VOID **) &gRT->SetVariable);
 | |
|   RuntimeDriverConvertInternalPointer ((VOID **) &gRT->GetNextVariableName);
 | |
|   RuntimeDriverConvertInternalPointer ((VOID **) &gRT->QueryVariableInfo);
 | |
|   RuntimeDriverConvertInternalPointer ((VOID **) &gRT->UpdateCapsule);
 | |
|   RuntimeDriverConvertInternalPointer ((VOID **) &gRT->QueryCapsuleCapabilities);
 | |
|   RuntimeDriverCalculateEfiHdrCrc (&gRT->Hdr);
 | |
| 
 | |
|   //
 | |
|   // Convert the UGA OS Handoff Table if it is present in the Configuration Table
 | |
|   //
 | |
|   for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
 | |
|     if (CompareGuid (&gEfiUgaIoProtocolGuid, &(gST->ConfigurationTable[Index].VendorGuid))) {
 | |
|       DriverOsHandoffHeader = gST->ConfigurationTable[Index].VendorTable;
 | |
|       for (Index1 = 0; Index1 < DriverOsHandoffHeader->NumberOfEntries; Index1++) {
 | |
|         DriverOsHandoff = (EFI_DRIVER_OS_HANDOFF *)
 | |
|           (
 | |
|             (UINTN) DriverOsHandoffHeader +
 | |
|             DriverOsHandoffHeader->HeaderSize +
 | |
|             Index1 *
 | |
|             DriverOsHandoffHeader->SizeOfEntries
 | |
|           );
 | |
|         RuntimeDriverConvertPointer (EFI_OPTIONAL_POINTER, (VOID **) &DriverOsHandoff->DevicePath);
 | |
|         RuntimeDriverConvertPointer (EFI_OPTIONAL_POINTER, (VOID **) &DriverOsHandoff->PciRomImage);
 | |
|       }
 | |
| 
 | |
|       RuntimeDriverConvertPointer (EFI_OPTIONAL_POINTER, (VOID **) &(gST->ConfigurationTable[Index].VendorTable));
 | |
|     }
 | |
| 
 | |
|     if (CompareGuid (&gEfiCapsuleGuid, &(gST->ConfigurationTable[Index].VendorGuid))) {
 | |
|       CapsuleTable = gST->ConfigurationTable[Index].VendorTable;
 | |
|       for (Index1 = 0; Index1 < CapsuleTable->CapsuleArrayNumber; Index1++) {
 | |
|         RuntimeDriverConvertPointer (EFI_OPTIONAL_POINTER, (VOID **) &CapsuleTable->CapsulePtr[Index1]);
 | |
|       }
 | |
|       RuntimeDriverConvertPointer (EFI_OPTIONAL_POINTER, (VOID **) &(gST->ConfigurationTable[Index].VendorTable));
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // Convert the runtime fields of the EFI System Table and recompute the CRC-32
 | |
|   //
 | |
|   RuntimeDriverConvertInternalPointer ((VOID **) &gST->FirmwareVendor);
 | |
|   RuntimeDriverConvertInternalPointer ((VOID **) &gST->ConfigurationTable);
 | |
|   RuntimeDriverConvertInternalPointer ((VOID **) &gST->RuntimeServices);
 | |
|   RuntimeDriverCalculateEfiHdrCrc (&gST->Hdr);
 | |
| 
 | |
|   //
 | |
|   // At this point, gRT and gST are physical pointers, but the contents of these tables
 | |
|   // have been converted to runtime.
 | |
|   //
 | |
|   //
 | |
|   // mVirtualMap is only valid during SetVirtualAddressMap() call
 | |
|   //
 | |
|   mVirtualMap = NULL;
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| RuntimeDriverInitialize (
 | |
|   IN EFI_HANDLE                            ImageHandle,
 | |
|   IN EFI_SYSTEM_TABLE                      *SystemTable
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
|   Install Runtime AP. This code includes the EfiDriverLib, but it functions at
 | |
|   RT in physical mode. The only Lib services are gBS, gRT, and the DEBUG and
 | |
|   ASSERT macros (they do ReportStatusCode).
 | |
| 
 | |
| Arguments:
 | |
|   (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   EFI_SUCEESS - Runtime Driver Architectural Protocol Installed
 | |
| 
 | |
|   Other       - Return value from gBS->InstallMultipleProtocolInterfaces
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS                Status;
 | |
|   EFI_LOADED_IMAGE_PROTOCOL *MyLoadedImage;
 | |
| 
 | |
|   //
 | |
|   // This image needs to be exclued from relocation for virtual mode, so cache
 | |
|   // a copy of the Loaded Image protocol to test later.
 | |
|   //
 | |
|   Status = gBS->HandleProtocol (
 | |
|                   ImageHandle,
 | |
|                   &gEfiLoadedImageProtocolGuid,
 | |
|                   (VOID**)&MyLoadedImage
 | |
|                   );
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
|   mMyImageBase = MyLoadedImage->ImageBase;
 | |
| 
 | |
|   //
 | |
|   // Initialize the table used to compute 32-bit CRCs
 | |
|   //
 | |
|   RuntimeDriverInitializeCrc32Table ();
 | |
| 
 | |
|   //
 | |
|   // Fill in the entries of the EFI Boot Services and EFI Runtime Services Tables
 | |
|   //
 | |
|   gBS->CalculateCrc32       = RuntimeDriverCalculateCrc32;
 | |
|   gRT->SetVirtualAddressMap = RuntimeDriverSetVirtualAddressMap;
 | |
|   gRT->ConvertPointer       = RuntimeDriverConvertPointer;
 | |
| 
 | |
|   //
 | |
|   // Install the Runtime Architectural Protocol onto a new handle
 | |
|   //
 | |
|   Status = gBS->InstallMultipleProtocolInterfaces (
 | |
|                   &mRuntimeHandle,
 | |
|                   &gEfiRuntimeArchProtocolGuid,
 | |
|                   &mRuntime,
 | |
|                   NULL
 | |
|                   );
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 |