fwblockservice.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,943 行 · 第 1/4 页
C
1,943 行
//
Dest = (UINT8 *) WriteAddress;
Src = Buffer;
for (Count = 0; Count < *NumBytes; Count++, Dest++, Src++) {
HubCommand = FWH_WRITE_SETUP_COMMAND;
FvbMemWrite8 ((UINT64) ((UINTN) Dest), HubCommand);
FvbMemWrite8 ((UINT64) ((UINTN) Dest), *Src);
//
// Device error if time out occurs
//
RetryTimes = 0;
while (RetryTimes < FVB_MAX_RETRY_TIMES) {
HubCommand = FWH_READ_STATUS_COMMAND;
FvbMemWrite8 ((UINT64) ((UINTN) Dest), HubCommand);
EfiMemRead (EfiCpuIoWidthUint8, (UINT64) ((UINTN) Dest), 0x1, &HubData);
if (HubData & FWH_WRITE_STATE_STATUS) {
break;
}
RetryTimes++;
}
if (RetryTimes >= FVB_MAX_RETRY_TIMES) {
*NumBytes = Count;
Status = EFI_DEVICE_ERROR;
break;
}
}
//
// Clear status register
//
HubCommand = FWH_CLEAR_STATUS_COMMAND;
FvbMemWrite8 ((UINT64) ((UINTN) WriteAddress), HubCommand);
//
// Issue read array command to return the FWH state machine to the
// normal operational state
//
HubCommand = FWH_READ_ARRAY_COMMAND;
FvbMemWrite8 ((UINT64) ((UINTN) WriteAddress), HubCommand);
//
// Flush the changed area to make the cache consistent
//
EfiCpuFlushCache (WriteAddress, *NumBytes);
//
// End of critical code section, release lock.
//
// EfiReleaseLock(&(FwhInstance->FvbDevLock));
//
EnableFvbWrites (FALSE);
return Status;
}
EFI_STATUS
FlashFdErase (
IN UINTN WriteAddress,
IN UINTN Address,
IN UINTN LbaLength
)
/*++
Routine Description:
Erase a certain block from address LbaWriteAddress
Arguments:
Returns:
--*/
{
EFI_STATUS Status;
UINT8 HubCommand;
UINT8 HubData;
UINTN RetryTimes;
Status = EFI_SUCCESS;
EnableFvbWrites (TRUE);
//
// Grab the lock before entering critical code section
//
// EfiAcquireLock(&(FwhInstance->FvbDevLock));
//
// Send erase commands to FWH
//
HubCommand = FWH_BLOCK_ERASE_SETUP_COMMAND;
FvbMemWrite8 ((UINT64) WriteAddress, HubCommand);
HubCommand = FWH_BLOCK_ERASE_CONFIRM_COMMAND;
FvbMemWrite8 ((UINT64) WriteAddress, HubCommand);
//
// Wait for completion. Indicated by FWH_WRITE_STATE_STATUS bit becoming 0
// Device error if time out occurs
//
RetryTimes = 0;
while (RetryTimes < FVB_MAX_RETRY_TIMES) {
HubCommand = FWH_READ_STATUS_COMMAND;
FvbMemWrite8 ((UINT64) WriteAddress, HubCommand);
EfiMemRead (EfiCpuIoWidthUint8, (UINT64) WriteAddress, 0x1, &HubData);
if (HubData & FWH_WRITE_STATE_STATUS) {
break;
}
RetryTimes++;
}
if (RetryTimes >= FVB_MAX_RETRY_TIMES) {
Status = EFI_DEVICE_ERROR;
}
//
// Clear status register
//
HubCommand = FWH_CLEAR_STATUS_COMMAND;
FvbMemWrite8 ((UINT64) WriteAddress, HubCommand);
//
// Issue read array command to return the FWH state machine to the normal op state
//
HubCommand = FWH_READ_ARRAY_COMMAND;
FvbMemWrite8 ((UINT64) ((UINTN) WriteAddress), HubCommand);
EfiCpuFlushCache (Address, LbaLength);
//
// End of critical code section, release lock.
//
// EfiReleaseLock(&(FwhInstance->FvbDevLock));
//
EnableFvbWrites (FALSE);
return Status;
}
EFI_STATUS
FvbWriteBlock (
IN UINTN Instance,
IN EFI_LBA Lba,
IN UINTN BlockOffset,
IN OUT UINTN *NumBytes,
IN UINT8 *Buffer,
IN ESAL_FWB_GLOBAL *Global,
IN BOOLEAN Virtual
)
/*++
Routine Description:
Writes specified number of bytes from the input buffer to the block
Arguments:
Instance - The FV instance to be written to
Lba - The starting logical block index to write to
BlockOffset - Offset into the block at which to begin writing
NumBytes - Pointer that on input contains the total size of
the buffer. On output, it contains the total number
of bytes actually written
Buffer - Pointer to a caller allocated buffer that contains
the source for the write
Global - Pointer to ESAL_FWB_GLOBAL that contains all
instance data
Virtual - Whether CPU is in virtual or physical mode
Returns:
EFI_SUCCESS - The firmware volume was written successfully
EFI_BAD_BUFFER_SIZE - Write attempted across a LBA boundary. On output,
NumBytes contains the total number of bytes
actually written
EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state
EFI_DEVICE_ERROR - The block device is not functioning correctly and
could not be written
EFI_INVALID_PARAMETER - Instance not found, or NumBytes, Buffer are NULL
--*/
{
EFI_FVB_ATTRIBUTES Attributes;
UINTN LbaAddress;
UINTN LbaWriteAddress;
UINTN LbaLength;
EFI_FW_VOL_INSTANCE *FwhInstance;
EFI_STATUS Status;
EFI_STATUS ReturnStatus;
//
// Find the right instance of the FVB private data
//
Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);
ASSERT_EFI_ERROR (Status);
//
// Writes are enabled in the init routine itself
//
if (!FwhInstance->WriteEnabled) {
return EFI_ACCESS_DENIED;
}
//
// Check for invalid conditions
//
if ((NumBytes == NULL) || (Buffer == NULL)) {
return EFI_INVALID_PARAMETER;
}
if (*NumBytes == 0) {
return EFI_INVALID_PARAMETER;
}
Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaWriteAddress, &LbaLength, NULL, Global, Virtual);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Check if the FV is write enabled
//
FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual);
if ((Attributes & EFI_FVB_WRITE_STATUS) == 0) {
return EFI_ACCESS_DENIED;
}
//
// Perform boundary checks and adjust NumBytes
//
if (BlockOffset > LbaLength) {
return EFI_INVALID_PARAMETER;
}
if (LbaLength < (*NumBytes + BlockOffset)) {
*NumBytes = (UINT32) (LbaLength - BlockOffset);
Status = EFI_BAD_BUFFER_SIZE;
}
ReturnStatus = FlashFdWrite (
LbaWriteAddress + BlockOffset,
LbaAddress,
NumBytes,
Buffer,
LbaLength
);
if (EFI_ERROR (ReturnStatus)) {
return ReturnStatus;
}
return Status;
}
EFI_STATUS
FvbEraseBlock (
IN UINTN Instance,
IN EFI_LBA Lba,
IN ESAL_FWB_GLOBAL *Global,
IN BOOLEAN Virtual
)
/*++
Routine Description:
Erases and initializes a firmware volume block
Arguments:
Instance - The FV instance to be erased
Lba - The logical block index to be erased
Global - Pointer to ESAL_FWB_GLOBAL that contains all
instance data
Virtual - Whether CPU is in virtual or physical mode
Returns:
EFI_SUCCESS - The erase request was successfully completed
EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state
EFI_DEVICE_ERROR - The block device is not functioning correctly and
could not be written. Firmware device may have been
partially erased
EFI_INVALID_PARAMETER - Instance not found
--*/
{
EFI_FVB_ATTRIBUTES Attributes;
UINTN LbaAddress;
UINTN LbaWriteAddress;
EFI_FW_VOL_INSTANCE *FwhInstance;
UINTN LbaLength;
EFI_STATUS Status;
//
// Find the right instance of the FVB private data
//
Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);
ASSERT_EFI_ERROR (Status);
//
// Writes are enabled in the init routine itself
//
if (!FwhInstance->WriteEnabled) {
return EFI_ACCESS_DENIED;
}
//
// Check if the FV is write enabled
//
FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual);
if ((Attributes & EFI_FVB_WRITE_STATUS) == 0) {
return EFI_ACCESS_DENIED;
}
//
// Get the starting address of the block for erase. For debug reasons,
// LbaWriteAddress may not be the same as LbaAddress.
//
Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaWriteAddress, &LbaLength, NULL, Global, Virtual);
if (EFI_ERROR (Status)) {
return Status;
}
return FlashFdErase (
LbaWriteAddress,
LbaAddress,
LbaLength
);
}
EFI_STATUS
FvbEraseCustomBlockRange (
IN UINTN Instance,
IN EFI_LBA StartLba,
IN UINTN OffsetStartLba,
IN EFI_LBA LastLba,
IN UINTN OffsetLastLba,
IN ESAL_FWB_GLOBAL *Global,
IN BOOLEAN Virtual
)
/*++
Routine Description:
Erases and initializes a specified range of a firmware volume
Arguments:
Instance - The FV instance to be erased
StartLba - The starting logical block index to be erased
OffsetStartLba - Offset into the starting block at which to
begin erasing
LastLba - The last logical block index to be erased
OffsetStartLba - Offset into the last block at which to end erasing
Global - Pointer to ESAL_FWB_GLOBAL that contains all
instance data
Virtual - Whether CPU is in virtual or physical mode
Returns:
EFI_SUCCESS - The firmware volume was erased successfully
EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state
EFI_DEVICE_ERROR - The block device is not functioning correctly and
could not be written. Firmware device may have been
partially erased
EFI_INVALID_PARAMETER - Instance not found
--*/
{
EFI_LBA Index;
UINTN LbaSize;
UINTN ScratchLbaSizeData;
//
// First LBA.
//
FvbGetLbaAddress (Instance, StartLba, NULL, NULL, &LbaSize, NULL, Global, Virtual);
//
// Use the scratch space as the intermediate buffer to transfer data
// Back up the first LBA in scratch space.
//
FvbReadBlock (Instance, StartLba, 0, &LbaSize, Global->FvbScratchSpace[Virtual], Global, Virtual);
//
// erase now
//
FvbEraseBlock (Instance, StartLba, Global, Virtual);
ScratchLbaSizeData = OffsetStartLba;
//
// write the data back to the first block
//
if (ScratchLbaSizeData > 0) {
FvbWriteBlock (Instance, StartLba, 0, &ScratchLbaSizeData, Global->FvbScratchSpace[Virtual], Global, Virtual);
}
//
// Middle LBAs
//
if (LastLba > (StartLba + 1)) {
for (Index = (StartLba + 1); Index <= (LastLba - 1); Index++) {
FvbEraseBlock (Instance, Index, Global, Virtual);
}
}
//
// Last LBAs, the same as first LBAs
//
if (LastLba > StartLba) {
FvbGetLbaAddress (Instance, LastLba, NULL, NULL, &LbaSize, NULL, Global, Virtual);
FvbReadBlock (Instance, LastLba, 0, &LbaSize, Global->FvbScratchSpace[Virtual], Global, Virtual);
FvbEraseBlock (Instance, LastLba, Global, Virtual);
}
ScratchLbaSizeData = LbaSize - (OffsetStartLba + 1);
return FvbWriteBlock (
Instance,
LastLba,
(OffsetLastLba + 1),
&ScratchLbaSizeData,
Global->FvbScratchSpace[Virtual],
Global,
Virtual
);
}
EFI_STATUS
FvbSetVolumeAttributes (
IN UINTN Instance,
IN OUT EFI_FVB_ATTRIBUTES *Attributes,
IN ESAL_FWB_GLOBAL *Global,
IN BOOLEAN Virtual
)
/*++
Routine Description:
Modifies the current settings of the firmware volume according to the
input parameter, and returns the new setting of the volume
Arguments:
Instance - The FV instance whose attributes is going to be
modified
Attributes - On input, it is a pointer to EFI_FVB_ATTRIBUTES
containing the desired firmware volume settings.
On successful return, it contains the new settings
of the firmware volume
Global - Pointer to ESAL_FWB_GLOBAL that contains all
instance data
Virtual - Whether CPU is in virtual or physical mode
Returns:
EFI_SUCCESS - Successfully returns
EFI_ACCESS_DENIED - The volume setting is locked and cannot be modified
EFI_INVALID_PARAMETER - Instance not found, or The attributes requested are
in conflict with the capabilities as declared in the
firmware volume header
--*/
{
EFI_FW_VOL_INSTANCE *FwhInstance;
EFI_FVB_ATTRIBUTES OldAttributes;
EFI_FVB_ATTRIBUTES *AttribPtr;
UINT32 Capabilities;
UINT32 OldStatus;
UINT32 NewStatus;
EFI_STATUS Status;
//
// Find the right instance of the FVB private data
//
Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);
ASSERT_EFI_ERROR (Status);
AttribPtr = (EFI_FVB_ATTRIBUTES *) &(FwhInstance->VolumeHeader.Attributes);
OldAttributes = *AttribPtr;
Capabilities = OldAttributes & EFI_FVB_CAPABILITIES;
OldStatus = OldAttributes & EFI_FVB_STATUS;
NewStatus = *Attributes & EFI_FVB_STATUS;
//
// If firmware volume is locked, no status bit can be updated
//
if (OldAttributes & EFI_FVB_LOCK_STATUS) {
if (OldStatus ^ NewStatus) {
return EFI_ACCESS_DENIED;
}
}
//
// Test read disable
//
if ((Capabilities & EFI_FVB_READ_DISABLED_CAP) == 0) {
if ((NewStatus & EFI_FVB_READ_STATUS) == 0) {
return EFI_INVALID_PARAMETER;
}
}
//
// Test read enable
//
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?