fwvolblock.c

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

C
622
字号
  FvbDevice = FVB_DEVICE_FROM_THIS (This);
  
  if (FvbDevice->FvbAttributes & EFI_FVB_MEMORY_MAPPED) {
    *Address = FvbDevice->BaseAddress;
    return EFI_SUCCESS;
  }
  
  return EFI_UNSUPPORTED;
}


EFI_STATUS
EFIAPI
FwVolBlockGetBlockSize (
  IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL   *This,
  IN EFI_LBA                              Lba,
  OUT UINTN                               *BlockSize,
  OUT UINTN                               *NumberOfBlocks
  )
/*++

Routine Description:
  Retrieves the size in bytes of a specific block within a firmware volume.

Arguments:
  This            -  Indicates the calling context.
  Lba             -  Indicates the block for which to return the size.
  BlockSize       -  Pointer to a caller-allocated UINTN in which the size of the
                     block is returned.
  NumberOfBlocks  -  Pointer to a caller-allocated UINTN in which the number of
                     consecutive blocks starting with Lba is returned. All blocks
                     in this range have a size of BlockSize.   
Returns:
  EFI_SUCCESS  -  The firmware volume base address is returned.
  EFI_INVALID_PARAMETER  -  The requested LBA is out of range.
--*/
{
  UINTN                                 TotalBlocks;
  EFI_FW_VOL_BLOCK_DEVICE               *FvbDevice;
  EFI_FV_BLOCK_MAP_ENTRY                *PtrBlockMapEntry;
  EFI_FIRMWARE_VOLUME_HEADER            *FwVolHeader;
  
  FvbDevice = FVB_DEVICE_FROM_THIS (This);
  
  //
  // Do parameter checking
  //
  if (Lba >= FvbDevice->NumBlocks) {
    return EFI_INVALID_PARAMETER;
  }
  
  FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)FvbDevice->BaseAddress);
  
  PtrBlockMapEntry = FwVolHeader->FvBlockMap;
  
  //
  // Search the block map for the given block
  //
  TotalBlocks = 0;
  while ((PtrBlockMapEntry->NumBlocks != 0) || (PtrBlockMapEntry->BlockLength !=0 )) {
    TotalBlocks += PtrBlockMapEntry->NumBlocks;
    if (Lba < TotalBlocks) {
      //
      // We find the range
      //
      break;
    }
    
    PtrBlockMapEntry++;
  }
  
  *BlockSize = PtrBlockMapEntry->BlockLength;
  *NumberOfBlocks = TotalBlocks - (UINTN)Lba;
  
  return EFI_SUCCESS;
}


EFI_STATUS
ProduceFVBProtocolOnBuffer (
  IN EFI_PHYSICAL_ADDRESS   BaseAddress,
  IN UINT64                 Length,
  IN EFI_HANDLE             ParentHandle,
  OUT EFI_HANDLE            *FvProtocol  OPTIONAL
  )
/*++

Routine Description:
    This routine produces a firmware volume block protocol on a given
    buffer. 

Arguments:
    BaseAddress     - base address of the firmware volume image
    Length          - length of the firmware volume image
    ParentHandle    - handle of parent firmware volume, if this
                      image came from an FV image file in another
                      firmware volume (ala capsules)
    FvProtocol      - Firmware volume block protocol produced.
    
Returns:
    EFI_VOLUME_CORRUPTED    - Volume corrupted.
    EFI_OUT_OF_RESOURCES    - No enough buffer to be allocated.
    EFI_SUCCESS             - Successfully produced a FVB protocol on given buffer.
                     
--*/
{
  EFI_STATUS                    Status;
  EFI_FW_VOL_BLOCK_DEVICE       *FvbDev;
  EFI_FIRMWARE_VOLUME_HEADER    *FwVolHeader;
  UINTN                         BlockIndex;
  UINTN                         BlockIndex2;
  UINTN                         LinearOffset;
  EFI_FV_BLOCK_MAP_ENTRY        *PtrBlockMapEntry;

  FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)BaseAddress;
  //
  // Validate FV Header, if not as expected, return
  //
  if (FwVolHeader->Signature != EFI_FVH_SIGNATURE) {
    return EFI_VOLUME_CORRUPTED;
  }
  //
  // Allocate EFI_FW_VOL_BLOCK_DEVICE 
  //
  FvbDev = CoreAllocateCopyPool (sizeof (EFI_FW_VOL_BLOCK_DEVICE), &mFwVolBlock);
  if (FvbDev == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  FvbDev->BaseAddress   = BaseAddress;
  FvbDev->FvbAttributes = FwVolHeader->Attributes;
  FvbDev->FwVolBlockInstance.ParentHandle = ParentHandle;

  //
  // Init the block caching fields of the device
  // First, count the number of blocks
  //
  FvbDev->NumBlocks = 0;
  for (PtrBlockMapEntry = FwVolHeader->FvBlockMap;
        PtrBlockMapEntry->NumBlocks != 0;
        PtrBlockMapEntry++) {
    FvbDev->NumBlocks += PtrBlockMapEntry->NumBlocks;
  }
  //
  // Second, allocate the cache
  //
  FvbDev->LbaCache = CoreAllocateBootServicesPool (FvbDev->NumBlocks * sizeof (LBA_CACHE));
  if (FvbDev->LbaCache == NULL) {
    CoreFreePool (FvbDev);
    return EFI_OUT_OF_RESOURCES;
  }
  //
  // Last, fill in the cache with the linear address of the blocks
  //
  BlockIndex = 0;
  LinearOffset = 0;
  for (PtrBlockMapEntry = FwVolHeader->FvBlockMap;
        PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) {
    for (BlockIndex2 = 0; BlockIndex2 < PtrBlockMapEntry->NumBlocks; BlockIndex2++) {
      FvbDev->LbaCache[BlockIndex].Base = LinearOffset;
      FvbDev->LbaCache[BlockIndex].Length = PtrBlockMapEntry->BlockLength;
      LinearOffset += PtrBlockMapEntry->BlockLength;
      BlockIndex++;
    }
  }

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

  //
  //
  // Attach FvVolBlock Protocol to new handle
  //
  Status = CoreInstallMultipleProtocolInterfaces (
            &FvbDev->Handle,
            &gEfiFirmwareVolumeBlockProtocolGuid,     &FvbDev->FwVolBlockInstance,
            &gEfiDevicePathProtocolGuid,              &FvbDev->DevicePath,
            &gEfiFirmwareVolumeDispatchProtocolGuid,  NULL,
            NULL
            );

  //
  // If they want the handle back, set it.
  //
  if (FvProtocol != NULL) {
    *FvProtocol = FvbDev->Handle;
  }

  return Status;
}


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

Routine Description:
    This routine is the driver initialization entry point.  It initializes the
    libraries, consumes FV hobs and NT_NON_MM_FV environment variable and
    produces instances of FW_VOL_BLOCK_PROTOCOL as appropriate.
Arguments:
    ImageHandle   - The image handle.
    SystemTable   - The system table.
Returns:
    EFI_SUCCESS   - Successfully initialized firmware volume block driver.
--*/
{
  EFI_STATUS                    Status;
  VOID                          *HobList;
  EFI_PHYSICAL_ADDRESS          BaseAddress;
  UINT64                        Length;
  EFI_STATUS                    HobStatus;

  //
  // First walk hobs and create appropriate FVs.
  //
  Status = CoreGetConfigTable (&gEfiHobListGuid, &HobList);
  //
  // Core Needs Firmware Volumes to function
  //
  ASSERT_EFI_ERROR (Status);

  BaseAddress = 0;
  Length      = 0;
  HobStatus = GetNextFirmwareVolumeHob (
                  &HobList,
                  &BaseAddress,
                  &Length
                  );
  while (!EFI_ERROR (HobStatus)) {
    //
    // Produce an FVB protocol for it
    //
    ProduceFVBProtocolOnBuffer (BaseAddress, Length, NULL, NULL);
    HobStatus = GetNextFirmwareVolumeHob (
                  &HobList,
                  &BaseAddress,
                  &Length
                  );
  }
  
  return EFI_SUCCESS;
}


EFI_STATUS
CoreProcessFirmwareVolume (
  IN VOID                             *FvHeader,
  IN UINTN                            Size, 
  OUT EFI_HANDLE                      *FVProtocolHandle
  )
/*++

Routine Description:
    This DXE service routine is used to process a firmware volume. In
    particular, it can be called by BDS to process a single firmware
    volume found in a capsule. 

Arguments:
    FvHeader              - pointer to a firmware volume header
    Size                  - the size of the buffer pointed to by FvHeader
    FVProtocolHandle      - the handle on which a firmware volume protocol
                            was produced for the firmware volume passed in.

Returns:
    EFI_OUT_OF_RESOURCES  - if an FVB could not be produced due to lack of 
                            system resources
    EFI_VOLUME_CORRUPTED  - if the volume was corrupted
    EFI_SUCCESS           - a firmware volume protocol was produced for the
                            firmware volume

--*/
{
  VOID        *Ptr;
  EFI_STATUS  Status;

  *FVProtocolHandle = NULL;
  Status = ProduceFVBProtocolOnBuffer ( 
            (EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader, 
            (UINT64)Size, 
            NULL, 
            FVProtocolHandle
            );
  //
  // Since in our implementation we use register-protocol-notify to put a
  // FV protocol on the FVB protocol handle, we can't directly verify that
  // the FV protocol was produced. Therefore here we will check the handle
  // and make sure an FV protocol is on it. This indicates that all went 
  // well. Otherwise we have to assume that the volume was corrupted 
  // somehow.
  //
  if (!EFI_ERROR(Status)) {
    Ptr = NULL;
    Status = CoreHandleProtocol (*FVProtocolHandle, &gEfiFirmwareVolumeProtocolGuid, &Ptr);
    if (EFI_ERROR(Status) || (Ptr == NULL)) {
      return EFI_VOLUME_CORRUPTED;
    }
    return EFI_SUCCESS;
  }
  return Status;
}


⌨️ 快捷键说明

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