mirror of
				https://git.proxmox.com/git/mirror_edk2
				synced 2025-10-31 05:28:13 +00:00 
			
		
		
		
	 878ddf1fc3
			
		
	
	
		878ddf1fc3
		
	
	
	
	
		
			
			git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			575 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			575 lines
		
	
	
		
			19 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"
 | |
| 
 | |
| //
 | |
| // This is a only short term solution.
 | |
| // There is a change coming to the Runtime AP that
 | |
| // will make it so the Runtime driver will not have to allocate any buffers. 
 | |
| //
 | |
| #define MAX_RUNTIME_IMAGE_NUM (64)
 | |
| #define MAX_RUNTIME_EVENT_NUM (64)
 | |
| RUNTIME_IMAGE_RELOCATION_DATA mRuntimeImageBuffer[MAX_RUNTIME_IMAGE_NUM];
 | |
| RUNTIME_NOTIFY_EVENT_DATA     mRuntimeEventBuffer[MAX_RUNTIME_EVENT_NUM];
 | |
| UINTN                         mRuntimeImageNumber;
 | |
| UINTN                         mRuntimeEventNumber;
 | |
| 
 | |
| //
 | |
| // 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 = {
 | |
|   RuntimeDriverRegisterImage,
 | |
|   RuntimeDriverRegisterEvent
 | |
| };
 | |
| 
 | |
| //
 | |
| // Global Variables
 | |
| //
 | |
| LIST_ENTRY                    mRelocationList             = INITIALIZE_LIST_HEAD_VARIABLE(mRelocationList);
 | |
| LIST_ENTRY                    mEventList                  = INITIALIZE_LIST_HEAD_VARIABLE(mEventList);
 | |
| BOOLEAN                       mEfiVirtualMode             = FALSE;
 | |
| EFI_GUID                      mLocalEfiUgaIoProtocolGuid  = EFI_UGA_IO_PROTOCOL_GUID;
 | |
| EFI_MEMORY_DESCRIPTOR         *mVirtualMap                = NULL;
 | |
| UINTN                         mVirtualMapDescriptorSize;
 | |
| UINTN                         mVirtualMapMaxIndex;
 | |
| 
 | |
| EFI_LOADED_IMAGE_PROTOCOL     *mMyLoadedImage;
 | |
| 
 | |
| //
 | |
| // Worker Functions
 | |
| //
 | |
| 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
 | |
| RuntimeDriverRegisterImage (
 | |
|   IN  EFI_RUNTIME_ARCH_PROTOCOL  *This,
 | |
|   IN  EFI_PHYSICAL_ADDRESS       ImageBase,
 | |
|   IN  UINTN                      ImageSize,
 | |
|   IN  VOID                       *RelocationData
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   When a SetVirtualAddressMap() is performed all the runtime images loaded by 
 | |
|   DXE must be fixed up with the new virtual address map. To facilitate this the 
 | |
|   Runtime Architectural Protocol needs to be informed of every runtime driver 
 | |
|   that is registered.  All the runtime images loaded by DXE should be registered 
 | |
|   with this service by the DXE Core when ExitBootServices() is called.  The 
 | |
|   images that are registered with this service must have successfully been 
 | |
|   loaded into memory with the Boot Service LoadImage().  As a result, no 
 | |
|   parameter checking needs to be performed.
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   This           - The EFI_RUNTIME_ARCH_PROTOCOL instance. 
 | |
| 
 | |
|   ImageBase      - Start of image that has been loaded in memory. It is either 
 | |
|                    a pointer to the DOS or PE header of the image.
 | |
| 
 | |
|   ImageSize      - Size of the image in bytes.
 | |
| 
 | |
|   RelocationData - Information about the fixups that were performed on ImageBase 
 | |
|                    when it was loaded into memory. This information is needed 
 | |
|                    when the virtual mode fix-ups are reapplied so that data that 
 | |
|                    has been programmatically updated will not be fixed up. If 
 | |
|                    code updates a global variable the code is responsible for 
 | |
|                    fixing up the variable for virtual mode.
 | |
| 
 | |
| Returns: 
 | |
| 
 | |
|   EFI_SUCCESS          - The ImageBase has been registered.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   RUNTIME_IMAGE_RELOCATION_DATA *RuntimeImage;
 | |
| 
 | |
|   if (mMyLoadedImage->ImageBase == (VOID *) (UINTN) ImageBase) {
 | |
|     //
 | |
|     // We don't want to relocate our selves, as we only run in physical mode.
 | |
|     //
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   RuntimeImage = &mRuntimeImageBuffer[mRuntimeImageNumber];
 | |
|   mRuntimeImageNumber++;
 | |
|   ASSERT (mRuntimeImageNumber < MAX_RUNTIME_IMAGE_NUM);
 | |
| 
 | |
|   RuntimeImage->Valid           = TRUE;
 | |
|   RuntimeImage->ImageBase       = ImageBase;
 | |
|   RuntimeImage->ImageSize       = ImageSize;
 | |
|   RuntimeImage->RelocationData  = RelocationData;
 | |
| 
 | |
|   InsertTailList (&mRelocationList, &RuntimeImage->Link);
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| RuntimeDriverRegisterEvent (
 | |
|   IN EFI_RUNTIME_ARCH_PROTOCOL  *This,
 | |
|   IN UINT32                     Type,
 | |
|   IN EFI_TPL                    NotifyTpl,
 | |
|   IN EFI_EVENT_NOTIFY           NotifyFunction,
 | |
|   IN VOID                       *NotifyContext,
 | |
|   IN EFI_EVENT                  *Event
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   This function is used to support the required runtime events. Currently only 
 | |
|   runtime events of type EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE needs to be 
 | |
|   registered with this service.  All the runtime events that exist in the DXE 
 | |
|   Core should be registered with this service when ExitBootServices() is called.  
 | |
|   All the events that are registered with this service must have been created 
 | |
|   with the Boot Service CreateEvent().  As a result, no parameter checking needs 
 | |
|   to be performed.
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   This           - The EFI_RUNTIME_ARCH_PROTOCOL instance. 
 | |
| 
 | |
|   Type           - The same as Type passed into CreateEvent().
 | |
| 
 | |
|   NotifyTpl      - The same as NotifyTpl passed into CreateEvent().
 | |
| 
 | |
|   NotifyFunction - The same as NotifyFunction passed into CreateEvent().
 | |
| 
 | |
|   NotifyContext  - The same as NotifyContext passed into CreateEvent().
 | |
| 
 | |
|   Event          - The EFI_EVENT returned by CreateEvent().  Event must be in 
 | |
|                    runtime memory.
 | |
| 
 | |
| Returns: 
 | |
| 
 | |
|   EFI_SUCCESS          - The Event has been registered.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   RUNTIME_NOTIFY_EVENT_DATA *RuntimeEvent;
 | |
| 
 | |
|   RuntimeEvent = &mRuntimeEventBuffer[mRuntimeEventNumber];
 | |
|   mRuntimeEventNumber++;
 | |
|   ASSERT (mRuntimeEventNumber < MAX_RUNTIME_EVENT_NUM);
 | |
| 
 | |
|   RuntimeEvent->Type            = Type;
 | |
|   RuntimeEvent->NotifyTpl       = NotifyTpl;
 | |
|   RuntimeEvent->NotifyFunction  = NotifyFunction;
 | |
|   RuntimeEvent->NotifyContext   = NotifyContext;
 | |
|   RuntimeEvent->Event           = Event;
 | |
| 
 | |
|   InsertTailList (&mEventList, &RuntimeEvent->Link);
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| RuntimeDriverConvertPointer (
 | |
|   IN     UINTN  DebugDisposition,
 | |
|   IN OUT VOID   **ConvertAddress
 | |
|   )
 | |
| {
 | |
|   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 ((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;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| RuntimeDriverConvertInternalPointer (
 | |
|   IN OUT VOID   **ConvertAddress
 | |
|   )
 | |
| {
 | |
|   return RuntimeDriverConvertPointer (0x0, ConvertAddress);
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| RuntimeDriverSetVirtualAddressMap (
 | |
|   IN UINTN                  MemoryMapSize,
 | |
|   IN UINTN                  DescriptorSize,
 | |
|   IN UINT32                 DescriptorVersion,
 | |
|   IN EFI_MEMORY_DESCRIPTOR  *VirtualMap
 | |
|   )
 | |
| {
 | |
|   RUNTIME_NOTIFY_EVENT_DATA     *RuntimeEvent;
 | |
|   RUNTIME_IMAGE_RELOCATION_DATA *RuntimeImage;
 | |
|   LIST_ENTRY                    *Link;
 | |
|   UINTN                         Index;
 | |
|   UINTN                         Index1;
 | |
|   EFI_DRIVER_OS_HANDOFF_HEADER  *DriverOsHandoffHeader;
 | |
|   EFI_DRIVER_OS_HANDOFF         *DriverOsHandoff;
 | |
| 
 | |
|   //
 | |
|   // Can only switch to virtual addresses once the memory map is locked down,
 | |
|   // and can only set it once
 | |
|   //
 | |
|   if (!EfiAtRuntime () || mEfiVirtualMode) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
|   //
 | |
|   // Only understand the original descriptor format
 | |
|   //
 | |
|   if (DescriptorVersion != EFI_MEMORY_DESCRIPTOR_VERSION || DescriptorSize < sizeof (EFI_MEMORY_DESCRIPTOR)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
|   //
 | |
|   // BugBug: Add code here to verify the memory map. We should
 | |
|   //  cache a copy of the system memory map in the EFI System Table
 | |
|   //  as a GUID pointer pair.
 | |
|   //
 | |
|   //
 | |
|   // Make sure all virtual translations are satisfied
 | |
|   //
 | |
|   mVirtualMapMaxIndex = MemoryMapSize / DescriptorSize;
 | |
| 
 | |
|   //
 | |
|   // BugBug :The following code does not work hence commented out.
 | |
|   // Need to be replaced by something that works.
 | |
|   //
 | |
|   //  VirtEntry = VirtualMap;
 | |
|   //  for (Index = 0; Index < mVirtualMapMaxIndex; Index++) {
 | |
|   //    if (((VirtEntry->Attribute & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME) &&
 | |
|   //        (VirtEntry->VirtualStart != 0) ) {
 | |
|   //        return EFI_NO_MAPPING;
 | |
|   //    }
 | |
|   //    VirtEntry = NextMemoryDescriptor(VirtEntry, DescriptorSize);
 | |
|   //  }
 | |
|   //
 | |
|   // We are now committed to go to virtual mode, so lets get to it!
 | |
|   //
 | |
|   mEfiVirtualMode = TRUE;
 | |
| 
 | |
|   //
 | |
|   // ConvertPointer() needs this mVirtualMap to do the conversion. So set up
 | |
|   // globals we need to parse the virtual address map.
 | |
|   //
 | |
|   mVirtualMapDescriptorSize = DescriptorSize;
 | |
|   mVirtualMap               = VirtualMap;
 | |
| 
 | |
|   //
 | |
|   // Signal all the EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE events.
 | |
|   // The core call RuntimeDriverRegisterEvent() for
 | |
|   // every runtime event and we stored them in the mEventList
 | |
|   //
 | |
|   //
 | |
|   // 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)
 | |
|           );
 | |
| 
 | |
|   //
 | |
|   // BugBug - Commented out for now because the status code driver is not
 | |
|   // ready for runtime yet. The Status Code driver calls data hub with does
 | |
|   // a bunch of Boot Service things (locks, AllocatePool) and hangs somewhere
 | |
|   // on the way.
 | |
|   //
 | |
|   //  ReportStatusCode (
 | |
|   //        EfiProgressCode,  EfiMaxErrorSeverity,
 | |
|   //        0x03, 0x01, 12, // ReadyToBoot Progress code
 | |
|   //        0x00, 30, L"ConvertPointer"
 | |
|   //        );
 | |
|   //
 | |
|   for (Link = mEventList.ForwardLink; Link != &mEventList; Link = Link->ForwardLink) {
 | |
|     RuntimeEvent = _CR (Link, RUNTIME_NOTIFY_EVENT_DATA, Link);
 | |
|     if ((RuntimeEvent->Type & EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE) == EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE) {
 | |
|       RuntimeEvent->NotifyFunction (
 | |
|                       RuntimeEvent->Event,
 | |
|                       RuntimeEvent->NotifyContext
 | |
|                       );
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // Relocate runtime images. Runtime images loaded before the runtime AP was
 | |
|   // started will not be relocated, since they would not have gotten registered.
 | |
|   // This includes the code in this file.
 | |
|   //
 | |
|   for (Link = mRelocationList.ForwardLink; Link != &mRelocationList; Link = Link->ForwardLink) {
 | |
|     RuntimeImage = _CR (Link, RUNTIME_IMAGE_RELOCATION_DATA, Link);
 | |
|     if (RuntimeImage->Valid) {
 | |
|       RelocatePeImageForRuntime (RuntimeImage);
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // 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);
 | |
|   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 (&mLocalEfiUgaIoProtocolGuid, &(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));
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // 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;
 | |
| 
 | |
|   //
 | |
|   // 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 **) &mMyLoadedImage
 | |
|                   );
 | |
|   ASSERT_EFI_ERROR (Status);
 | |
| 
 | |
|   //
 | |
|   // 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);
 | |
| 
 | |
|   mRuntimeImageNumber = 0;
 | |
|   mRuntimeEventNumber = 0;
 | |
| 
 | |
|   return Status;
 | |
| }
 |