runtime.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 529 行 · 第 1/2 页

C
529
字号
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_RUNTIME_EVENT_ENTRY       *RuntimeEvent;
  EFI_RUNTIME_IMAGE_ENTRY       *RuntimeImage;
  EFI_LIST_ENTRY                *Link;
  UINTN                         Index;
  UINTN                         Index1;
#if (EFI_SPECIFICATION_VERSION < 0x00020000)
  EFI_DRIVER_OS_HANDOFF_HEADER  *DriverOsHandoffHeader;
  EFI_DRIVER_OS_HANDOFF         *DriverOsHandoff;
#endif

#if (EFI_SPECIFICATION_VERSION >= 0x00020000)
  EFI_CAPSULE_TABLE             *CapsuleTable; 
#endif

  //
  // 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;
  }

  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
  //
  EfiReportStatusCode (
          EFI_PROGRESS_CODE,
          (EFI_SOFTWARE_EFI_BOOT_SERVICE | EFI_SW_RS_PC_SET_VIRTUAL_ADDRESS_MAP),
          0,
          &gEfiCallerIdGuid,
          NULL
          );

  //
  // 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 & EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE) == EFI_EVENT_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);
    RelocatePeImageForRuntime (RuntimeImage);
  }
  
  //
  // Convert all the Runtime Services except ConvertPointer() and SetVirtualAddressMap()
  // and recompute the CRC-32.
  //
  RuntimeDriverConvertInternalPointer ((VOID **) &mMyRT->GetTime);
  RuntimeDriverConvertInternalPointer ((VOID **) &mMyRT->SetTime);
  RuntimeDriverConvertInternalPointer ((VOID **) &mMyRT->GetWakeupTime);
  RuntimeDriverConvertInternalPointer ((VOID **) &mMyRT->SetWakeupTime);
  RuntimeDriverConvertInternalPointer ((VOID **) &mMyRT->ResetSystem);
#if (EFI_SPECIFICATION_VERSION < 0x00020000)
  RuntimeDriverConvertInternalPointer ((VOID **) &mMyRT->ReportStatusCode);
#endif
  RuntimeDriverConvertInternalPointer ((VOID **) &mMyRT->GetNextHighMonotonicCount);
  RuntimeDriverConvertInternalPointer ((VOID **) &mMyRT->GetVariable);
  RuntimeDriverConvertInternalPointer ((VOID **) &mMyRT->SetVariable);
  RuntimeDriverConvertInternalPointer ((VOID **) &mMyRT->GetNextVariableName);
#if (EFI_SPECIFICATION_VERSION >= 0x00020000)
  RuntimeDriverConvertInternalPointer ((VOID **) &mMyRT->QueryVariableInfo);
  RuntimeDriverConvertInternalPointer ((VOID **) &mMyRT->UpdateCapsule);
  RuntimeDriverConvertInternalPointer ((VOID **) &mMyRT->QueryCapsuleCapabilities);
#endif
  RuntimeDriverCalculateEfiHdrCrc (&mMyRT->Hdr);

  //
  // Convert the UGA OS Handoff Table if it is present in the Configuration Table.
  //
  for (Index = 0; Index < mMyST->NumberOfTableEntries; Index++) {
#if (EFI_SPECIFICATION_VERSION < 0x00020000)
    if (EfiCompareGuid (&mLocalEfiUgaIoProtocolGuid, &(mMyST->ConfigurationTable[Index].VendorGuid))) {
      DriverOsHandoffHeader = mMyST->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 **) &(mMyST->ConfigurationTable[Index].VendorTable));
    }
#endif

#if (EFI_SPECIFICATION_VERSION >= 0x00020000)
    if (EfiCompareGuid (&mEfiCapsuleHeaderGuid, &(mMyST->ConfigurationTable[Index].VendorGuid))) {
      CapsuleTable = mMyST->ConfigurationTable[Index].VendorTable;
      for (Index1 = 0; Index1 < CapsuleTable->CapsuleArrayNumber; Index1++) {
        RuntimeDriverConvertPointer (EFI_OPTIONAL_POINTER, (VOID **) &CapsuleTable->CapsulePtr[Index1]);
      }     
      RuntimeDriverConvertPointer (EFI_OPTIONAL_POINTER, (VOID **) &(mMyST->ConfigurationTable[Index].VendorTable));
    }
#endif
  }
  
  //
  // Convert the runtime fields of the EFI System Table and recompute the CRC-32.
  //
  RuntimeDriverConvertInternalPointer ((VOID **) &mMyST->FirmwareVendor);
  RuntimeDriverConvertInternalPointer ((VOID **) &mMyST->ConfigurationTable);
  RuntimeDriverConvertInternalPointer ((VOID **) &mMyST->RuntimeServices);
  RuntimeDriverCalculateEfiHdrCrc (&mMyST->Hdr);

  //
  // At this point, mMyRT and mMyST 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_DRIVER_ENTRY_POINT (RuntimeDriverInitialize)

EFI_STATUS
EFIAPI
RuntimeDriverInitialize (
  IN EFI_HANDLE             ImageHandle,
  IN EFI_SYSTEM_TABLE       *SystemTable
  )
/*++

Routine Description:

  Install Runtime AP. This code includes the EfiRuntimeLib, but it only 
  functions at RT in physical mode. 

Arguments:
  
  ImageHandle   - Image handle of this driver.
  SystemTable   - Pointer to the EFI System Table.

Returns:

  EFI_SUCEESS - Runtime Driver Architectural Protocol installed.

--*/
{
  EFI_STATUS                Status;
  EFI_LOADED_IMAGE_PROTOCOL *MyLoadedImage;

  //
  // Initialize EFI Runtime Driver.
  //
  EfiInitializeRuntimeDriverLib (ImageHandle, SystemTable, NULL);

  //
  // Save the EFI System Table and EFI Runtime Services Table into module globals
  // for use after ExitBootServices().
  //
  mMyST = SystemTable;
  mMyRT = SystemTable->RuntimeServices;

  //
  // 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,
                  &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;
  mMyRT->SetVirtualAddressMap = RuntimeDriverSetVirtualAddressMap;
  mMyRT->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;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?