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 + -
显示快捷键?