fwblockservice.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,943 行 · 第 1/4 页
C
1,943 行
/*++
Copyright (c) 2004 - 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
FWBlockService.c
Abstract:
Revision History
--*/
#include "FWBlockService.h"
#include "EfiFlashMap.h"
#include EFI_GUID_DEFINITION (FlashMapHob)
ESAL_FWB_GLOBAL *mFvbModuleGlobal;
EFI_FW_VOL_BLOCK_DEVICE mFvbDeviceTemplate = {
FVB_DEVICE_SIGNATURE,
{
{
{
HARDWARE_DEVICE_PATH,
HW_MEMMAP_DP,
{
sizeof (MEMMAP_DEVICE_PATH),
0
}
},
EfiMemoryMappedIO,
0,
0,
},
{
END_DEVICE_PATH_TYPE,
END_ENTIRE_DEVICE_PATH_SUBTYPE,
{
sizeof (EFI_DEVICE_PATH_PROTOCOL),
0
}
}
},
0,
{
FvbProtocolGetAttributes,
FvbProtocolSetAttributes,
FvbProtocolGetPhysicalAddress,
FvbProtocolGetBlockSize,
FvbProtocolRead,
FvbProtocolWrite,
FvbProtocolEraseBlocks,
NULL
},
{
FvbExtendProtocolEraseCustomBlockRange
}
};
EFI_DRIVER_ENTRY_POINT (FvbInitialize)
EFI_RUNTIMESERVICE
VOID
EFIAPI
FvbVirtualddressChangeEvent (
IN EFI_EVENT Event,
IN VOID *Context
)
/*++
Routine Description:
Fixup internal data so that EFI and SAL can be call in virtual mode.
Call the passed in Child Notify event and convert the mFvbModuleGlobal
date items to there virtual address.
mFvbModuleGlobal->FvInstance[FVB_PHYSICAL] - Physical copy of instance data
mFvbModuleGlobal->FvInstance[FVB_VIRTUAL] - Virtual pointer to common
instance data.
Arguments:
(Standard EFI notify event - EFI_EVENT_NOTIFY)
Returns:
None
--*/
{
EFI_FW_VOL_INSTANCE *FwhInstance;
UINTN Index;
EfiConvertPointer (EFI_INTERNAL_POINTER, (VOID **) &mFvbModuleGlobal->FvInstance[FVB_VIRTUAL]);
//
// Convert the base address of all the instances
//
Index = 0;
FwhInstance = mFvbModuleGlobal->FvInstance[FVB_PHYSICAL];
while (Index < mFvbModuleGlobal->NumFv) {
EfiConvertPointer (EFI_INTERNAL_POINTER, (VOID **) &FwhInstance->FvBase[FVB_VIRTUAL]);
EfiConvertPointer (EFI_INTERNAL_POINTER, (VOID **) &FwhInstance->FvWriteBase[FVB_VIRTUAL]);
FwhInstance = (EFI_FW_VOL_INSTANCE *) ((UINTN)((UINT8 *)FwhInstance) + FwhInstance->VolumeHeader.HeaderLength
+ (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)));
Index++;
}
EfiConvertPointer (EFI_INTERNAL_POINTER, (VOID **) &mFvbModuleGlobal->FvbScratchSpace[FVB_VIRTUAL]);
EfiConvertPointer (EFI_INTERNAL_POINTER, (VOID **) &mFvbModuleGlobal);
}
VOID
FvbMemWrite8 (
IN UINT64 Dest,
IN UINT8 Byte
)
{
EfiMemWrite (EfiCpuIoWidthUint8, Dest, 1, &Byte);
return ;
}
EFI_STATUS
GetFvbInstance (
IN UINTN Instance,
IN ESAL_FWB_GLOBAL *Global,
OUT EFI_FW_VOL_INSTANCE **FwhInstance,
IN BOOLEAN Virtual
)
/*++
Routine Description:
Retrieves the physical address of a memory mapped FV
Arguments:
Instance - The FV instance whose base address is going to be
returned
Global - Pointer to ESAL_FWB_GLOBAL that contains all
instance data
FwhInstance - The EFI_FW_VOL_INSTANCE fimrware instance structure
Virtual - Whether CPU is in virtual or physical mode
Returns:
EFI_SUCCESS - Successfully returns
EFI_INVALID_PARAMETER - Instance not found
--*/
{
EFI_FW_VOL_INSTANCE *FwhRecord;
if (Instance >= Global->NumFv) {
return EFI_INVALID_PARAMETER;
}
//
// Find the right instance of the FVB private data
//
FwhRecord = Global->FvInstance[Virtual];
while (Instance > 0) {
FwhRecord = (EFI_FW_VOL_INSTANCE *) ((UINTN)((UINT8 *)FwhRecord) + FwhRecord->VolumeHeader.HeaderLength
+ (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)));
Instance--;
}
*FwhInstance = FwhRecord;
return EFI_SUCCESS;
}
EFI_STATUS
FvbGetPhysicalAddress (
IN UINTN Instance,
OUT EFI_PHYSICAL_ADDRESS *Address,
IN ESAL_FWB_GLOBAL *Global,
IN BOOLEAN Virtual
)
/*++
Routine Description:
Retrieves the physical address of a memory mapped FV
Arguments:
Instance - The FV instance whose base address is going to be
returned
Address - Pointer to a caller allocated EFI_PHYSICAL_ADDRESS
that on successful return, contains the base address
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_INVALID_PARAMETER - Instance not found
--*/
{
EFI_FW_VOL_INSTANCE *FwhInstance;
EFI_STATUS Status;
//
// Find the right instance of the FVB private data
//
Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);
ASSERT_EFI_ERROR (Status);
*Address = FwhInstance->FvBase[Virtual];
return EFI_SUCCESS;
}
EFI_STATUS
FvbGetVolumeAttributes (
IN UINTN Instance,
OUT EFI_FVB_ATTRIBUTES *Attributes,
IN ESAL_FWB_GLOBAL *Global,
IN BOOLEAN Virtual
)
/*++
Routine Description:
Retrieves attributes, insures positive polarity of attribute bits, returns
resulting attributes in output parameter
Arguments:
Instance - The FV instance whose attributes is going to be
returned
Attributes - Output buffer which contains attributes
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_INVALID_PARAMETER - Instance not found
--*/
{
EFI_FW_VOL_INSTANCE *FwhInstance;
EFI_STATUS Status;
//
// Find the right instance of the FVB private data
//
Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);
ASSERT_EFI_ERROR (Status);
*Attributes = FwhInstance->VolumeHeader.Attributes;
return EFI_SUCCESS;
}
EFI_STATUS
FvbGetLbaAddress (
IN UINTN Instance,
IN EFI_LBA Lba,
OUT UINTN *LbaAddress,
OUT UINTN *LbaWriteAddress,
OUT UINTN *LbaLength,
OUT UINTN *NumOfBlocks,
IN ESAL_FWB_GLOBAL *Global,
IN BOOLEAN Virtual
)
/*++
Routine Description:
Retrieves the starting address of an LBA in an FV
Arguments:
Instance - The FV instance which the Lba belongs to
Lba - The logical block address
LbaAddress - On output, contains the physical starting address
of the Lba
LbaWriteAddress - On output, contains the physical starting address
of the Lba for writing
LbaLength - On output, contains the length of the block
NumOfBlocks - A 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
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_INVALID_PARAMETER - Instance not found
--*/
{
UINT32 NumBlocks;
UINT32 BlockLength;
UINTN Offset;
EFI_LBA StartLba;
EFI_LBA NextLba;
EFI_FW_VOL_INSTANCE *FwhInstance;
EFI_FV_BLOCK_MAP_ENTRY *BlockMap;
EFI_STATUS Status;
//
// Find the right instance of the FVB private data
//
Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual);
ASSERT_EFI_ERROR (Status);
StartLba = 0;
Offset = 0;
BlockMap = &(FwhInstance->VolumeHeader.FvBlockMap[0]);
//
// Parse the blockmap of the FV to find which map entry the Lba belongs to
//
while (TRUE) {
NumBlocks = BlockMap->NumBlocks;
BlockLength = BlockMap->BlockLength;
if (NumBlocks == 0 || BlockLength == 0) {
return EFI_INVALID_PARAMETER;
}
NextLba = StartLba + NumBlocks;
//
// The map entry found
//
if (Lba >= StartLba && Lba < NextLba) {
Offset = Offset + (UINTN) MultU64x32 ((Lba - StartLba), BlockLength);
if (LbaAddress) {
*LbaAddress = FwhInstance->FvBase[Virtual] + Offset;
}
if (LbaWriteAddress) {
*LbaWriteAddress = FwhInstance->FvWriteBase[Virtual] + Offset;
}
if (LbaLength) {
*LbaLength = BlockLength;
}
if (NumOfBlocks) {
*NumOfBlocks = (UINTN) (NextLba - Lba);
}
return EFI_SUCCESS;
}
StartLba = NextLba;
Offset = Offset + NumBlocks * BlockLength;
BlockMap++;
}
}
EFI_STATUS
FvbReadBlock (
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:
Reads specified number of bytes into a buffer from the specified block
Arguments:
Instance - The FV instance to be read from
Lba - The logical block address to be read from
BlockOffset - Offset into the block at which to begin reading
NumBytes - Pointer that on input contains the total size of
the buffer. On output, it contains the total number
of bytes read
Buffer - Pointer to a caller allocated buffer that will be
used to hold the data read
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 read successfully and
contents are in Buffer
EFI_BAD_BUFFER_SIZE - Read attempted across a LBA boundary. On output,
NumBytes contains the total number of bytes returned
in Buffer
EFI_ACCESS_DENIED - The firmware volume is in the ReadDisabled state
EFI_DEVICE_ERROR - The block device is not functioning correctly and
could not be read
EFI_INVALID_PARAMETER - Instance not found, or NumBytes, Buffer are NULL
--*/
{
EFI_FVB_ATTRIBUTES Attributes;
UINTN LbaAddress;
UINTN LbaLength;
EFI_STATUS Status;
//
// 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, NULL, &LbaLength, NULL, Global, Virtual);
if (EFI_ERROR (Status)) {
return Status;
}
//
// Check if the FV is read enabled
//
FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual);
if ((Attributes & EFI_FVB_READ_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;
}
EfiMemRead (EfiCpuIoWidthUint8, LbaAddress + BlockOffset, (UINTN) *NumBytes, Buffer);
return Status;
}
EFI_STATUS
FlashFdWrite (
IN UINTN WriteAddress,
IN UINTN Address,
IN OUT UINTN *NumBytes,
IN UINT8 *Buffer,
IN UINTN LbaLength
)
/*++
Routine Description:
Writes specified number of bytes from the input buffer to the address
Arguments:
Returns:
--*/
{
UINT8 *Src;
UINT8 *Dest;
UINTN Count;
EFI_STATUS Status;
UINT8 HubCommand;
UINT8 HubData;
UINTN RetryTimes;
Status = EFI_SUCCESS;
EnableFvbWrites (TRUE);
//
// Grab the lock before entering critical code section
//
// bugbug
// Commented out since locking mechanisium is not correctly implemented
// on IA32 so that it will assert in runtime environment.
//
// EfiAcquireLock(&(FwhInstance->FvbDevLock));
//
// Write data one byte at a time, don't write if the src and dest bytes match
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?