fwblockservice.c

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

C
1,514
字号
                          could not be written. Firmware device may have been
                          partially erased

--*/
{
  EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;

  FvbDevice = FVB_EXTEND_DEVICE_FROM_THIS (This);

  return FvbEraseCustomBlockRange (
          FvbDevice->Instance,
          StartLba,
          OffsetStartLba,
          LastLba,
          OffsetLastLba,
          mFvbModuleGlobal,
          EfiGoneVirtual ()
          );
}

STATIC
EFI_STATUS
ValidateFvHeader (
  EFI_FIRMWARE_VOLUME_HEADER            *FwVolHeader
  )
/*++

Routine Description:
  Check the integrity of firmware volume header

Arguments:
  FwVolHeader           - A pointer to a firmware volume header

Returns: 
  EFI_SUCCESS           - The firmware volume is consistent
  EFI_NOT_FOUND         - The firmware volume has corrupted. So it is not an FV

--*/
{
  UINT16  *Ptr;
  UINT16  HeaderLength;
  UINT16  Checksum;

  //
  // Verify the header revision, header signature, length
  // Length of FvBlock cannot be 2**64-1
  // HeaderLength cannot be an odd number
  //
  if ((FwVolHeader->Revision != EFI_FVH_REVISION) ||
      (FwVolHeader->Signature != EFI_FVH_SIGNATURE) ||
      (FwVolHeader->FvLength == ((UINTN) -1)) ||
      ((FwVolHeader->HeaderLength & 0x01) != 0)
      ) {
    return EFI_NOT_FOUND;
  }
  //
  // Verify the header checksum
  //
  HeaderLength  = (UINT16) (FwVolHeader->HeaderLength / 2);
  Ptr           = (UINT16 *) FwVolHeader;
  Checksum      = 0;
  while (HeaderLength > 0) {
    Checksum = Checksum + (*Ptr);
    Ptr ++;
    HeaderLength --;
  }

  if (Checksum != 0) {
    return EFI_NOT_FOUND;
  }

  return EFI_SUCCESS;
}

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

Routine Description:
  This function does common initialization for FVB services

Arguments:

Returns:

--*/
{
  EFI_STATUS                          Status;
  EFI_FW_VOL_INSTANCE                 *FwhInstance;
  EFI_FIRMWARE_VOLUME_HEADER          *FwVolHeader;
  VOID                                *HobList;
  EFI_DXE_SERVICES                    *DxeServices;
  VOID                                *FirmwareVolumeHobList;
  EFI_GCD_MEMORY_SPACE_DESCRIPTOR     Descriptor;
  UINT32                              BufferSize;
  EFI_FV_BLOCK_MAP_ENTRY              *PtrBlockMapEntry;
  EFI_HANDLE                          FwbHandle;
  EFI_FW_VOL_BLOCK_DEVICE             *FvbDevice;
  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *OldFwbInterface;
  EFI_DEVICE_PATH_PROTOCOL            *TempFwbDevicePath;
  FV_DEVICE_PATH                      TempFvbDevicePathData;
  UINT32                              MaxLbaSize;
  EFI_PHYSICAL_ADDRESS                BaseAddress;
  UINT64                              Length;
  UINTN                               NumOfBlocks;

  EfiInitializeRuntimeDriverLib (ImageHandle, SystemTable, FvbVirtualddressChangeEvent);

  Status = EfiLibGetSystemConfigurationTable (&gEfiHobListGuid, &HobList);
  //
  // No FV HOBs found
  //
  ASSERT_EFI_ERROR (Status);

  //
  // Get the DXE services table
  //
  DxeServices = NULL;
  Status      = EfiLibGetSystemConfigurationTable (&gEfiDxeServicesTableGuid, (VOID **) &DxeServices);;
  ASSERT_EFI_ERROR (Status);

  //
  // Allocate runtime services data for global variable, which contains
  // the private data of all firmware volume block instances
  //
  Status = gBS->AllocatePool (
                  EfiRuntimeServicesData,
                  sizeof (ESAL_FWB_GLOBAL),
                  &mFvbModuleGlobal
                  );
  ASSERT_EFI_ERROR (Status);

  //
  // Calculate the total size for all firmware volume block instances
  //
  BufferSize            = 0;
  FirmwareVolumeHobList = HobList;
  do {
    Status = GetNextFirmwareVolumeHob (
              &FirmwareVolumeHobList,
              &BaseAddress,
              &Length
              );
    if (EFI_ERROR (Status)) {
      break;
    }
    //
    // Check if it is a "real" flash
    //
    Status = DxeServices->GetMemorySpaceDescriptor (
                            BaseAddress,
                            &Descriptor
                            );
    if (EFI_ERROR (Status)) {
      break;
    }

    if (Descriptor.GcdMemoryType != EfiGcdMemoryTypeMemoryMappedIo) {
      continue;
    }

    FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) BaseAddress;
    Status      = ValidateFvHeader (FwVolHeader);
    if (EFI_ERROR (Status)) {
      //
      // Get FvbInfo
      //
      Status = GetFvbInfo (Length, &FwVolHeader);
      if (EFI_ERROR (Status)) {
        continue;
      }
    }

    BufferSize += (sizeof (EFI_FW_VOL_INSTANCE) + FwVolHeader->HeaderLength - sizeof (EFI_FIRMWARE_VOLUME_HEADER));
  } while (TRUE);

  //
  // Only need to allocate once. There is only one copy of physical memory for
  // the private data of each FV instance. But in virtual mode or in physical
  // mode, the address of the the physical memory may be different.
  //
  Status = gBS->AllocatePool (
                  EfiRuntimeServicesData,
                  BufferSize,
                  &mFvbModuleGlobal->FvInstance[FVB_PHYSICAL]
                  );
  ASSERT_EFI_ERROR (Status);

  //
  // Make a virtual copy of the FvInstance pointer.
  //
  FwhInstance = mFvbModuleGlobal->FvInstance[FVB_PHYSICAL];
  mFvbModuleGlobal->FvInstance[FVB_VIRTUAL] = FwhInstance;

  mFvbModuleGlobal->NumFv                   = 0;
  FirmwareVolumeHobList                     = HobList;
  MaxLbaSize = 0;

  //
  // Fill in the private data of each firmware volume block instance
  //
  do {
    Status = GetNextFirmwareVolumeHob (
              &FirmwareVolumeHobList,
              &BaseAddress,
              &Length
              );
    if (EFI_ERROR (Status)) {
      break;
    }
    //
    // Check if it is a "real" flash
    //
    Status = DxeServices->GetMemorySpaceDescriptor (
                            BaseAddress,
                            &Descriptor
                            );
    if (EFI_ERROR (Status)) {
      break;
    }

    if (Descriptor.GcdMemoryType != EfiGcdMemoryTypeMemoryMappedIo) {
      continue;
    }

    FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) BaseAddress;
    Status      = ValidateFvHeader (FwVolHeader);
    if (EFI_ERROR (Status)) {
      //
      // Get FvbInfo to provide in FwhInstance.
      //
      Status = GetFvbInfo (Length, &FwVolHeader);
      if (EFI_ERROR (Status)) {
        continue;
      }
      //
      //  Write healthy FV header back.
      //
      EfiCopyMem (
        (VOID *) (UINTN) BaseAddress,
        (VOID *) FwVolHeader,
        FwVolHeader->HeaderLength
        );
    }

    FwhInstance->FvBase[FVB_PHYSICAL] = (UINTN) BaseAddress;
    FwhInstance->FvBase[FVB_VIRTUAL]  = (UINTN) BaseAddress;

    EfiCopyMem ((UINTN *) &(FwhInstance->VolumeHeader), (UINTN *) FwVolHeader, FwVolHeader->HeaderLength);
    FwVolHeader = &(FwhInstance->VolumeHeader);
    EfiInitializeLock (&(FwhInstance->FvbDevLock), EFI_TPL_HIGH_LEVEL);

    NumOfBlocks = 0;

    for (PtrBlockMapEntry = FwVolHeader->FvBlockMap; PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) {
      //
      // Get the maximum size of a block. The size will be used to allocate
      // buffer for Scratch space, the intermediate buffer for FVB extension
      // protocol
      //
      if (MaxLbaSize < PtrBlockMapEntry->BlockLength) {
        MaxLbaSize = PtrBlockMapEntry->BlockLength;
      }

      NumOfBlocks = NumOfBlocks + PtrBlockMapEntry->NumBlocks;
    }
    //
    // The total number of blocks in the FV.
    //
    FwhInstance->NumOfBlocks = NumOfBlocks;

    //
    // Add a FVB Protocol Instance
    //
    Status = gBS->AllocatePool (
                    EfiRuntimeServicesData,
                    sizeof (EFI_FW_VOL_BLOCK_DEVICE),
                    &FvbDevice
                    );
    ASSERT_EFI_ERROR (Status);

    EfiCopyMem (FvbDevice, &mFvbDeviceTemplate, sizeof (EFI_FW_VOL_BLOCK_DEVICE));

    FvbDevice->Instance = mFvbModuleGlobal->NumFv;
    mFvbModuleGlobal->NumFv++;

    //
    // Set up the devicepath
    //
    FvbDevice->DevicePath.MemMapDevPath.StartingAddress = BaseAddress;
    FvbDevice->DevicePath.MemMapDevPath.EndingAddress   = BaseAddress + (FwVolHeader->FvLength - 1);

    //
    // Find a handle with a matching device path that has supports FW Block protocol
    //
    TempFwbDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) &TempFvbDevicePathData;
    EfiCopyMem (TempFwbDevicePath, &FvbDevice->DevicePath, sizeof (FV_DEVICE_PATH));
    Status = gBS->LocateDevicePath (&gEfiFirmwareVolumeBlockProtocolGuid, &TempFwbDevicePath, &FwbHandle);
    if (EFI_ERROR (Status)) {
      //
      // LocateDevicePath fails so install a new interface and device path
      //
      FwbHandle = NULL;
      Status = gBS->InstallMultipleProtocolInterfaces (
                      &FwbHandle,
                      &gEfiFirmwareVolumeBlockProtocolGuid,
                      &FvbDevice->FwVolBlockInstance,
                      &gEfiDevicePathProtocolGuid,
                      &FvbDevice->DevicePath,
                      NULL
                      );
      ASSERT_EFI_ERROR (Status);
    } else if (EfiIsDevicePathEnd (TempFwbDevicePath)) {
      //
      // Device allready exists, so reinstall the FVB protocol
      //
      Status = gBS->HandleProtocol (
                      FwbHandle,
                      &gEfiFirmwareVolumeBlockProtocolGuid,
                      &OldFwbInterface
                      );
      ASSERT_EFI_ERROR (Status);

      Status = gBS->ReinstallProtocolInterface (
                      FwbHandle,
                      &gEfiFirmwareVolumeBlockProtocolGuid,
                      OldFwbInterface,
                      &FvbDevice->FwVolBlockInstance
                      );
      ASSERT_EFI_ERROR (Status);

    } else {
      //
      // There was a FVB protocol on an End Device Path node
      //
      ASSERT (FALSE);
    }
    //
    // Install FVB Extension Protocol on the same handle
    //
    Status = gBS->InstallMultipleProtocolInterfaces (
                    &FwbHandle,
                    &gEfiFvbExtensionProtocolGuid,
                    &FvbDevice->FvbExtension,
                    &gEfiAlternateFvBlockGuid,
                    NULL,
                    NULL
                    );

    ASSERT_EFI_ERROR (Status);

    FwhInstance = (EFI_FW_VOL_INSTANCE *)
      (
        (UINTN) ((UINT8 *) FwhInstance) + FwVolHeader->HeaderLength +
          (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER))
      );
  } while (TRUE);

  //
  // Allocate for scratch space, an intermediate buffer for FVB extention
  //
  Status = gBS->AllocatePool (
                  EfiRuntimeServicesData,
                  MaxLbaSize,
                  &mFvbModuleGlobal->FvbScratchSpace[FVB_PHYSICAL]
                  );
  ASSERT_EFI_ERROR (Status);

  mFvbModuleGlobal->FvbScratchSpace[FVB_VIRTUAL] = mFvbModuleGlobal->FvbScratchSpace[FVB_PHYSICAL];

  return EFI_SUCCESS;
}

⌨️ 快捷键说明

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