dxe Foundation 的firmware volume block驱动是只读版本的,所以协议中所有写相关的函数setAttribute()
write(), EraseBlock() 都只是简单的返回EFI_UNSUPPORTED.
FwVolBlockDriverInit() 函数
FwVolBlockDriverInit()函数是内置的Firmware Volume Block 驱动的入口函数。
//
// Core needs Firmware Volumes to function
//
FvHob.Raw = GetHobList();
while (( FvHob.Raw = GetNextHob (EFI_HOB_TYPE_FV, FvHob.Raw)) != NULL){
//
// Produce an FVB protocol for it
//
ProduceFVBProtocolOnBuffer(FvHob.FirmwareVolume->BaseAddress, FvHob.FirmwareVoluem-Length, NULL, NULL);
FvHob.Raw = GET_NEXT_HOB(FvHob);
}
return EFI_SUCCESS;
函数很简单,取得HOB 表头,然后依次为每一个FV HOB 报告的FV 调用ProduceFVBProtocolOnBuffer() 函数安装Firmware
Volume Block协议。
CoreProcessFirmwareVolume()函数
CoreProcessFirmwareVolume()函数是ProcessFirmwareVolume() DXE Service的实现。这个DXE Service 主要用来处理
Capsule 中的FV.
此函数检查内存中的一个缓冲区中的内容,如果是一个合法的FV, 创建一个新句柄,并在上面安装Firmware Volume 2 协议和
FV device path 协议。新的句柄被返回给调用者。
*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 // 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, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&pTR);
if (EFI_ERROR(Status) || (Ptr == NULL)) {
return EFI_VOLUME_CORRUPTED;
}
return EFI_SUCCESS;
}
return Status;
预设返回的句柄为NULL。
调用ProduceFVBProtocolOnBuffer() 函数为指定的内存中的FV安装Firmware Volume Block协议的实例。
ProduceFVBProtocolOnBuffer() 函数
此函数为指定的一块内存缓冲区产生Firmware Volume Block2协议。
FvAlignment = 0;
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;
}
首先检查FV头的签名,如果签名不对,返回卷损坏错误码。
//
// Get FvHeader alignment
//
FvAlignment = 1 << ((FwVolHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16);
//
// FvAlignment must be greater than or equal to 8 bytes of the minimum FFS alignment value.
//
if (FvAlignment < 8) {
FvAlignment = 8;
}
if ((UINTN)BaseAddress & FvAlignment != 0) {
//
// FvImage buffer is not at its required alignment.
//
return EFI_VOLUME_CORRUPTED;
}
根据FV属性中的对齐信息算出实际FV对齐值。
PI 规范规定FFS文件头相对于FV的基地址为8字节对齐。所以FV的对齐值必须大于8.否则无法保证
FFS文件的对齐。
检查FV的基地址是否满足对齐要求,不满足的话,返回卷损坏错误。
//
// Allocate EFI_FW_VOL_BLOCK_DEVICE
FvDev = AllocateCopyPool(sizeof(EFI_VOL_BLOCK_DEVICE), & mFwVolBlock);
if (FvDev == NULL) {
return EFI_OUT_OF_RESOURCES;
}
FvbDev->BaseAddress = BaseAddress;
FvbDev->FvbAttributes = FwVolHeader->Attributes;
FvDev->FwVolBlockInstance.ParentHandle = ParentHandle;
为Firmware Volume Block 2协议私有数据结构分配内存,并以m