EFI_STATUS EFIAPI FvbProtocolSetAttributes ( IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes ) /*++ Routine Description: Sets Volume attributes. No polarity translations are done. Arguments: This - Calling context Attributes - output buffer which contains attributes Returns: EFI_SUCCESS - Successfully returns **/ { EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; FvbDevice = FVB_DEVICE_FROM_THIS (This); return FvbSetVolumeAttributes (FvbDevice->Instance, Attributes, mFvbModuleGlobal, EfiGoneVirtual ()); }
/** Reads the specified number of bytes into a buffer from the specified block. The Read() function reads the requested number of bytes from the requested block and stores them in the provided buffer. Implementations should be mindful that the firmware volume might be in the ReadDisabled state. If it is in this state, the Read() function must return the status code EFI_ACCESS_DENIED without modifying the contents of the buffer. The Read() function must also prevent spanning block boundaries. If a read is requested that would span a block boundary, the read must read up to the boundary but not beyond. The output parameter NumBytes must be set to correctly indicate the number of bytes actually read. The caller must be aware that a read may be partially completed. @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. @param Lba The starting logical block index from which to read. @param Offset Offset into the block at which to begin reading. @param NumBytes Pointer to a UINTN. At entry, *NumBytes contains the total size of the buffer. At exit, *NumBytes contains the total number of bytes read. @param Buffer Pointer to a caller-allocated buffer that will be used to hold the data that is read. @retval EFI_SUCCESS The firmware volume was read successfully and contents are in Buffer. @retval EFI_BAD_BUFFER_SIZE Read attempted across an LBA boundary. On output, NumBytes contains the total number of bytes returned in Buffer. @retval EFI_ACCESS_DENIED The firmware volume is in the ReadDisabled state. @retval EFI_DEVICE_ERROR The block device is not functioning correctly and could not be read. **/ EFI_STATUS EFIAPI FvbProtocolRead ( IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, IN EFI_LBA Lba, IN UINTN Offset, IN OUT UINTN *NumBytes, IN OUT UINT8 *Buffer ) { EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; UINT8 *FvbDataPtr; FvbDevice = FVB_DEVICE_FROM_THIS (This); if ((Lba > 1) || (Offset > FvbDevice->BlockSize)) { return EFI_INVALID_PARAMETER; } if ((Offset + *NumBytes) > FvbDevice->BlockSize) { *NumBytes = FvbDevice->BlockSize - Offset; } FvbDataPtr = (UINT8*) FvbDevice->BufferPtr + MultU64x32 (Lba, (UINT32) FvbDevice->BlockSize) + Offset; if (*NumBytes > 0) { CopyMem (Buffer, FvbDataPtr, *NumBytes); PlatformFvbDataRead (This, Lba, Offset, *NumBytes, Buffer); } return EFI_SUCCESS; }
EFI_STATUS EFIAPI FwVolBlockGetPhysicalAddress ( IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, OUT EFI_PHYSICAL_ADDRESS *Address ) /*++ Routine Description: Get Fvb's base address. Arguments: This - Indicates the calling context. Address - Fvb device base address. Returns: EFI_SUCCESS - Successfully got Fvb's base address. EFI_UNSUPPORTED - Not supported. --*/ { EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; FvbDevice = FVB_DEVICE_FROM_THIS (This); if (FvbDevice->FvbAttributes & EFI_FVB_MEMORY_MAPPED) { *Address = FvbDevice->BaseAddress; return EFI_SUCCESS; } return EFI_UNSUPPORTED; }
// // FVB protocol APIs // EFI_STATUS EFIAPI FvbProtocolGetPhysicalAddress ( IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, OUT EFI_PHYSICAL_ADDRESS *Address ) /*++ Routine Description: Retrieves the physical address of the device. Arguments: This - Calling context Address - Output buffer containing the address. Returns: Returns: EFI_SUCCESS - Successfully returns **/ { EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; FvbDevice = FVB_DEVICE_FROM_THIS (This); return FvbGetPhysicalAddress (FvbDevice->Instance, Address, mFvbModuleGlobal, EfiGoneVirtual ()); }
EFI_STATUS EFIAPI FwVolBlockGetAttributes ( IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, OUT EFI_FVB_ATTRIBUTES *Attributes ) /*++ Routine Description: Retrieves Volume attributes. No polarity translations are done. Arguments: This - Calling context Attributes - output buffer which contains attributes Returns: EFI_SUCCESS - The firmware volume attributes were returned. --*/ { EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; FvbDevice = FVB_DEVICE_FROM_THIS (This); // // Since we are read only, it's safe to get attributes data from our in-memory copy. // *Attributes = FvbDevice->FvbAttributes; return EFI_SUCCESS; }
/** Retrieves Volume attributes. No polarity translations are done. @param[in] This Calling context @param[out] Attributes Output buffer which contains attributes @retval EFI_SUCCESS The function always return successfully. **/ EFI_STATUS EFIAPI FvbProtocolGetAttributes ( IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, OUT EFI_FVB_ATTRIBUTES_2 *Attributes ) { EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; FvbDevice = FVB_DEVICE_FROM_THIS (This); *Attributes = FvbGetVolumeAttributes (FvbDevice->Instance); return EFI_SUCCESS; }
/** Retrieves the physical address of the device. @param[in] This A pointer to EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL. @param[out] Address Output buffer containing the address. retval EFI_SUCCESS The function always return successfully. **/ EFI_STATUS EFIAPI FvbProtocolGetPhysicalAddress ( IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, OUT EFI_PHYSICAL_ADDRESS *Address ) { EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; FvbDevice = FVB_DEVICE_FROM_THIS (This); *Address = GetFvbInstance (FvbDevice->Instance)->FvBase; return EFI_SUCCESS; }
/** Sets Volume attributes. No polarity translations are done. @param[in] This Calling context @param[out] Attributes Output buffer which contains attributes @retval EFI_SUCCESS The function always return successfully. **/ EFI_STATUS EFIAPI FvbProtocolSetAttributes ( IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes ) { EFI_STATUS Status; EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; FvbDevice = FVB_DEVICE_FROM_THIS (This); Status = FvbSetVolumeAttributes (FvbDevice->Instance, Attributes); return Status; }
/** The GetPhysicalAddress() function retrieves the base address of a memory-mapped firmware volume. This function should be called only for memory-mapped firmware volumes. @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. @param Address Pointer to a caller-allocated EFI_PHYSICAL_ADDRESS that, on successful return from GetPhysicalAddress(), contains the base address of the firmware volume. @retval EFI_SUCCESS The firmware volume base address is returned. @retval EFI_NOT_SUPPORTED The firmware volume is not memory mapped. **/ EFI_STATUS EFIAPI FvbProtocolGetPhysicalAddress ( IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, OUT EFI_PHYSICAL_ADDRESS *Address ) { EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; FvbDevice = FVB_DEVICE_FROM_THIS (This); *Address = (EFI_PHYSICAL_ADDRESS)(UINTN) FvbDevice->BufferPtr; return EFI_SUCCESS; }
EFI_STATUS EFIAPI FvbProtocolRead ( IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, IN EFI_LBA Lba, IN UINTN Offset, IN OUT UINTN *NumBytes, IN UINT8 *Buffer ) /*++ Routine Description: Reads data beginning at Lba:Offset from FV. The Read terminates either when *NumBytes of data have been read, or when a block boundary is reached. *NumBytes is updated to reflect the actual number of bytes written. The write opertion does not include erase. This routine will attempt to write only the specified bytes. If the writes do not stick, it will return an error. Arguments: This - Calling context Lba - Block in which to begin Read Offset - Offset in the block at which to begin Read NumBytes - On input, indicates the requested write size. On output, indicates the actual number of bytes Read Buffer - Buffer containing source data for the Read. 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 - NumBytes or Buffer are NULL **/ { EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; FvbDevice = FVB_DEVICE_FROM_THIS (This); return FvbReadBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buffer, mFvbModuleGlobal, EfiGoneVirtual ()); }
/** Retrieves the size in bytes of a specific block within a firmware volume. @param This Indicates the calling context. @param Lba Indicates the block for which to return the size. @param BlockSize Pointer to a caller-allocated UINTN in which the size of the block is returned. @param 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. @retval EFI_SUCCESS The firmware volume base address is returned. @retval EFI_INVALID_PARAMETER The requested LBA is out of range. **/ EFI_STATUS EFIAPI FwVolBlockGetBlockSize ( IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, IN CONST EFI_LBA Lba, IN OUT UINTN *BlockSize, IN OUT UINTN *NumberOfBlocks ) { 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->BlockMap; // // Search the block map for the given block // TotalBlocks = 0; while ((PtrBlockMapEntry->NumBlocks != 0) || (PtrBlockMapEntry->Length !=0 )) { TotalBlocks += PtrBlockMapEntry->NumBlocks; if (Lba < TotalBlocks) { // // We find the range // break; } PtrBlockMapEntry++; } *BlockSize = PtrBlockMapEntry->Length; *NumberOfBlocks = TotalBlocks - (UINTN)Lba; return EFI_SUCCESS; }
/** Retrieves Volume attributes. No polarity translations are done. @param This Calling context @param Attributes output buffer which contains attributes @retval EFI_SUCCESS The firmware volume attributes were returned. **/ EFI_STATUS EFIAPI FwVolBlockGetAttributes ( IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, OUT EFI_FVB_ATTRIBUTES_2 *Attributes ) { EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; FvbDevice = FVB_DEVICE_FROM_THIS (This); // // Since we are read only, it's safe to get attributes data from our in-memory copy. // *Attributes = FvbDevice->FvbAttributes & ~EFI_FVB2_WRITE_STATUS; return EFI_SUCCESS; }
/** Get Fvb's base address. @param This Indicates the calling context. @param Address Fvb device base address. @retval EFI_SUCCESS Successfully got Fvb's base address. @retval EFI_UNSUPPORTED Not supported. **/ EFI_STATUS EFIAPI FwVolBlockGetPhysicalAddress ( IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, OUT EFI_PHYSICAL_ADDRESS *Address ) { EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; FvbDevice = FVB_DEVICE_FROM_THIS (This); if ((FvbDevice->FvbAttributes & EFI_FVB2_MEMORY_MAPPED) != 0) { *Address = FvbDevice->BaseAddress; return EFI_SUCCESS; } return EFI_UNSUPPORTED; }
/** Writes data beginning at Lba:Offset from FV. The write terminates either when *NumBytes of data have been written, or when a block boundary is reached. *NumBytes is updated to reflect the actual number of bytes written. The write opertion does not include erase. This routine will attempt to write only the specified bytes. If the writes do not stick, it will return an error. @param[in] This Calling context @param[in] Lba Block in which to begin write @param[in] Offset Offset in the block at which to begin write @param[in, out] NumBytes On input, indicates the requested write size. On output, indicates the actual number of bytes written @param[in] Buffer Buffer containing source data for the write. @retval EFI_SUCCESS The firmware volume was written successfully @retval EFI_BAD_BUFFER_SIZE Write attempted across a LBA boundary. On output, NumBytes contains the total number of bytes actually written @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state @retval EFI_DEVICE_ERROR The block device is not functioning correctly and could not be written @retval EFI_INVALID_PARAMETER NumBytes or Buffer are NULL **/ EFI_STATUS EFIAPI FvbProtocolWrite ( IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, IN EFI_LBA Lba, IN UINTN Offset, IN OUT UINTN *NumBytes, IN UINT8 *Buffer ) { EFI_STATUS Status; EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; FvbDevice = FVB_DEVICE_FROM_THIS (This); Status = FvbWriteBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buffer); return Status; }
EFI_STATUS EFIAPI FvbProtocolGetBlockSize ( IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, IN EFI_LBA Lba, OUT UINTN *BlockSize, OUT UINTN *NumOfBlocks ) /*++ Routine Description: Retrieve the size of a logical block Arguments: This - Calling context Lba - Indicates which block to return the size for. BlockSize - A pointer to a caller allocated UINTN in which the size of the block is returned 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 Returns: EFI_SUCCESS - The firmware volume was read successfully and contents are in Buffer **/ { EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; FvbDevice = FVB_DEVICE_FROM_THIS (This); return FvbGetLbaAddress ( FvbDevice->Instance, Lba, NULL, BlockSize, NumOfBlocks, mFvbModuleGlobal, EfiGoneVirtual () ); }
/** Retrieve the size of a logical block @param[in] This Calling context @param[in] Lba Indicates which block to return the size for. @param[out] BlockSize A pointer to a caller allocated UINTN in which the size of the block is returned @param[out] 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 @retval EFI_SUCCESS The function always return successfully. **/ EFI_STATUS EFIAPI FvbProtocolGetBlockSize ( IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, IN EFI_LBA Lba, OUT UINTN *BlockSize, OUT UINTN *NumOfBlocks ) { EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; FvbDevice = FVB_DEVICE_FROM_THIS (This); return FvbGetLbaAddress ( FvbDevice->Instance, Lba, NULL, NULL, BlockSize, NumOfBlocks ); }
/** The GetBlockSize() function retrieves the size of the requested block. It also returns the number of additional blocks with the identical size. The GetBlockSize() function is used to retrieve the block map (see EFI_FIRMWARE_VOLUME_HEADER). @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. @param Lba Indicates the block for which to return the size. @param BlockSize Pointer to a caller-allocated UINTN in which the size of the block is returned. @param 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. @retval EFI_SUCCESS The firmware volume base address is returned. @retval EFI_INVALID_PARAMETER The requested LBA is out of range. **/ EFI_STATUS EFIAPI FvbProtocolGetBlockSize ( IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, IN EFI_LBA Lba, OUT UINTN *BlockSize, OUT UINTN *NumberOfBlocks ) { EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; if (Lba > 1) { return EFI_INVALID_PARAMETER; } FvbDevice = FVB_DEVICE_FROM_THIS (This); *BlockSize = FvbDevice->BlockSize; *NumberOfBlocks = (UINTN) (2 - (UINTN) Lba); return EFI_SUCCESS; }
/** Read the specified number of bytes from the block to the input buffer. @param This Indicates the calling context. @param Lba The starting logical block index to read. @param Offset Offset into the block at which to begin reading. @param NumBytes Pointer to a UINT32. At entry, *NumBytes contains the total size of the buffer. At exit, *NumBytes contains the total number of bytes actually read. @param Buffer Pinter to a caller-allocated buffer that contains the destine for the read. @retval EFI_SUCCESS The firmware volume was read successfully. @retval EFI_BAD_BUFFER_SIZE The read was attempted across an LBA boundary. @retval EFI_ACCESS_DENIED Access denied. @retval EFI_DEVICE_ERROR The block device is malfunctioning and could not be read. **/ EFI_STATUS EFIAPI FwVolBlockReadBlock ( IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, IN CONST EFI_LBA Lba, IN CONST UINTN Offset, IN OUT UINTN *NumBytes, IN OUT UINT8 *Buffer ) { EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; UINT8 *LbaOffset; UINTN LbaStart; UINTN NumOfBytesRead; UINTN LbaIndex; FvbDevice = FVB_DEVICE_FROM_THIS (This); // // Check if This FW can be read // if ((FvbDevice->FvbAttributes & EFI_FVB2_READ_STATUS) == 0) { return EFI_ACCESS_DENIED; } LbaIndex = (UINTN) Lba; if (LbaIndex >= FvbDevice->NumBlocks) { // // Invalid Lba, read nothing. // *NumBytes = 0; return EFI_BAD_BUFFER_SIZE; } if (Offset > FvbDevice->LbaCache[LbaIndex].Length) { // // all exceed boundry, read nothing. // *NumBytes = 0; return EFI_BAD_BUFFER_SIZE; } NumOfBytesRead = *NumBytes; if (Offset + NumOfBytesRead > FvbDevice->LbaCache[LbaIndex].Length) { // // partial exceed boundry, read data from current postion to end. // NumOfBytesRead = FvbDevice->LbaCache[LbaIndex].Length - Offset; } LbaStart = FvbDevice->LbaCache[LbaIndex].Base; FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN) FvbDevice->BaseAddress); LbaOffset = (UINT8 *) FwVolHeader + LbaStart + Offset; // // Perform read operation // CopyMem (Buffer, LbaOffset, NumOfBytesRead); if (NumOfBytesRead == *NumBytes) { return EFI_SUCCESS; } *NumBytes = NumOfBytesRead; return EFI_BAD_BUFFER_SIZE; }
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 EFIAPI FwVolBlockReadBlock ( IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, IN EFI_LBA Lba, IN UINTN Offset, IN OUT UINTN *NumBytes, IN UINT8 *Buffer ) /*++ Routine Description: Read the specified number of bytes from the block to the input buffer. Arguments: This - Indicates the calling context. Lba - The starting logical block index to read. Offset - Offset into the block at which to begin reading. NumBytes - Pointer to a UINT32. At entry, *NumBytes contains the total size of the buffer. At exit, *NumBytes contains the total number of bytes actually read. Buffer - Pinter to a caller-allocated buffer that contains the destine for the read. Returns: EFI_SUCCESS - The firmware volume was read successfully. EFI_BAD_BUFFER_SIZE - The read was attempted across an LBA boundary. EFI_ACCESS_DENIED - Access denied. EFI_DEVICE_ERROR - The block device is malfunctioning and could not be read. --*/ { EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; UINT8 *LbaOffset; UINTN LbaStart; UINTN NumOfBytesRead; UINTN LbaIndex; FvbDevice = FVB_DEVICE_FROM_THIS (This); // // Check if This FW can be read // if ((FvbDevice->FvbAttributes & EFI_FVB_READ_STATUS) == 0) { return EFI_ACCESS_DENIED; } LbaIndex = (UINTN)Lba; if (LbaIndex >= FvbDevice->NumBlocks) { // // Invalid Lba, read nothing. // *NumBytes = 0; return EFI_BAD_BUFFER_SIZE; } if (Offset > FvbDevice->LbaCache[LbaIndex].Length) { // // all exceed boundry, read nothing. // *NumBytes = 0; return EFI_BAD_BUFFER_SIZE; } NumOfBytesRead = *NumBytes; if (Offset + NumOfBytesRead > FvbDevice->LbaCache[LbaIndex].Length) { // // partial exceed boundry, read data from current postion to end. // NumOfBytesRead = FvbDevice->LbaCache[LbaIndex].Length - Offset; } LbaStart = FvbDevice->LbaCache[LbaIndex].Base; FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)FvbDevice->BaseAddress); LbaOffset = (UINT8 *)FwVolHeader + LbaStart + Offset; // // Perform read operation // EfiCommonLibCopyMem (Buffer, LbaOffset, NumOfBytesRead); if (NumOfBytesRead == *NumBytes) { return EFI_SUCCESS; } *NumBytes = NumOfBytesRead; return EFI_BAD_BUFFER_SIZE; }
/** The EraseBlock() function erases one or more blocks as denoted by the variable argument list. The entire parameter list of blocks must be verified prior to erasing any blocks. If a block is requested that does not exist within the associated firmware volume (it has a larger index than the last block of the firmware volume), the EraseBlock() function must return EFI_INVALID_PARAMETER without modifying the contents of the firmware volume. @param[in] This Calling context @param[in] ... Starting LBA followed by Number of Lba to erase. a -1 to terminate the list. @retval EFI_SUCCESS The erase request was successfully completed @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state @retval EFI_DEVICE_ERROR The block device is not functioning correctly and could not be written. Firmware device may have been partially erased **/ EFI_STATUS EFIAPI FvbProtocolEraseBlocks ( IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, ... ) { EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; EFI_FW_VOL_INSTANCE *FwhInstance; UINTN NumOfBlocks; VA_LIST args; EFI_LBA StartingLba; UINTN NumOfLba; EFI_STATUS Status; EFI_FVB_ATTRIBUTES_2 Attributes; // // Initialize data. // FvbDevice = FVB_DEVICE_FROM_THIS (This); FwhInstance = GetFvbInstance (FvbDevice->Instance); NumOfBlocks = FwhInstance->NumOfBlocks; // // Check if this FV can be written to. // Attributes = FvbGetVolumeAttributes (FvbDevice->Instance); if ((Attributes & EFI_FVB2_WRITE_STATUS) == 0) { return EFI_ACCESS_DENIED; } // // Validate LBA information passed in by caller. // VA_START (args, This); do { // // Check for last entry in variable argument list. // StartingLba = VA_ARG (args, EFI_LBA); if (StartingLba == EFI_LBA_LIST_TERMINATOR) { break; } // // Get parameter from stack. // NumOfLba = VA_ARG (args, UINT32); // // Check input parameters // if (NumOfLba == 0) { VA_END (args); return EFI_INVALID_PARAMETER; } if ((StartingLba + NumOfLba) > NumOfBlocks) { VA_END (args); return EFI_INVALID_PARAMETER; } } while (1); VA_END (args); // // Perform erase operation on all selected LBA. // VA_START (args, This); do { // // Check for last entry in variable argument list. // StartingLba = VA_ARG (args, EFI_LBA); if (StartingLba == EFI_LBA_LIST_TERMINATOR) { break; } // // Get parameter from stack. // NumOfLba = VA_ARG (args, UINT32); // // Perform the erase operation for the specific LBA. // while (NumOfLba > 0) { Status = FvbEraseBlock (FvbDevice->Instance, StartingLba); if (EFI_ERROR (Status)) { VA_END (args); return Status; } StartingLba ++; NumOfLba --; } } while (1); VA_END (args); return EFI_SUCCESS; }
/** Erases and initializes a firmware volume block. The EraseBlocks() function erases one or more blocks as denoted by the variable argument list. The entire parameter list of blocks must be verified before erasing any blocks. If a block is requested that does not exist within the associated firmware volume (it has a larger index than the last block of the firmware volume), the EraseBlocks() function must return the status code EFI_INVALID_PARAMETER without modifying the contents of the firmware volume. Implementations should be mindful that the firmware volume might be in the WriteDisabled state. If it is in this state, the EraseBlocks() function must return the status code EFI_ACCESS_DENIED without modifying the contents of the firmware volume. All calls to EraseBlocks() must be fully flushed to the hardware before the EraseBlocks() service returns. @param This Indicates the EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL instance. @param ... The variable argument list is a list of tuples. Each tuple describes a range of LBAs to erase and consists of the following: - An EFI_LBA that indicates the starting LBA - A UINTN that indicates the number of blocks to erase The list is terminated with an EFI_LBA_LIST_TERMINATOR. For example, the following indicates that two ranges of blocks (5-7 and 10-11) are to be erased: EraseBlocks (This, 5, 3, 10, 2, EFI_LBA_LIST_TERMINATOR); @retval EFI_SUCCESS The erase request was successfully completed. @retval EFI_ACCESS_DENIED The firmware volume is in the WriteDisabled state. @retval EFI_DEVICE_ERROR The block device is not functioning correctly and could not be written. The firmware device may have been partially erased. @retval EFI_INVALID_PARAMETER One or more of the LBAs listed in the variable argument list do not exist in the firmware volume. **/ EFI_STATUS EFIAPI FvbProtocolEraseBlocks ( IN CONST EFI_FIRMWARE_VOLUME_BLOCK2_PROTOCOL *This, ... ) { EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; VA_LIST args; EFI_LBA StartingLba; UINTN NumOfLba; UINT8 Erase; VOID *ErasePtr; UINTN EraseSize; FvbDevice = FVB_DEVICE_FROM_THIS (This); Erase = 0; VA_START (args, This); do { StartingLba = VA_ARG (args, EFI_LBA); if (StartingLba == EFI_LBA_LIST_TERMINATOR) { break; } NumOfLba = VA_ARG (args, UINT32); // // Check input parameters // if ((NumOfLba == 0) || (StartingLba > 1) || ((StartingLba + NumOfLba) > 2)) { VA_END (args); return EFI_INVALID_PARAMETER; } if (StartingLba == 0) { Erase = (UINT8) (Erase | BIT0); } if ((StartingLba + NumOfLba) == 2) { Erase = (UINT8) (Erase | BIT1); } } while (1); VA_END (args); ErasePtr = (UINT8*) FvbDevice->BufferPtr; EraseSize = 0; if ((Erase & BIT0) != 0) { EraseSize = EraseSize + FvbDevice->BlockSize; } else { ErasePtr = (VOID*) ((UINT8*)ErasePtr + FvbDevice->BlockSize); } if ((Erase & BIT1) != 0) { EraseSize = EraseSize + FvbDevice->BlockSize; } if (EraseSize != 0) { SetMem ( (VOID*) ErasePtr, EraseSize, ERASED_UINT8 ); VA_START (args, This); PlatformFvbBlocksErased (This, args); VA_END (args); } return EFI_SUCCESS; }
EFI_STATUS EFIAPI FvbProtocolEraseBlocks ( IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, ... ) /*++ Routine Description: The EraseBlock() function erases one or more blocks as denoted by the variable argument list. The entire parameter list of blocks must be verified prior to erasing any blocks. If a block is requested that does not exist within the associated firmware volume (it has a larger index than the last block of the firmware volume), the EraseBlock() function must return EFI_INVALID_PARAMETER without modifying the contents of the firmware volume. Arguments: This - Calling context ... - Starting LBA followed by Number of Lba to erase. a -1 to terminate the list. 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_FW_VOL_BLOCK_DEVICE *FvbDevice; EFI_FW_VOL_INSTANCE *FwhInstance = NULL; UINTN NumOfBlocks; VA_LIST args; EFI_LBA StartingLba; UINTN NumOfLba; EFI_STATUS Status; FvbDevice = FVB_DEVICE_FROM_THIS (This); Status = GetFvbInstance (FvbDevice->Instance, mFvbModuleGlobal, &FwhInstance, EfiGoneVirtual ()); ASSERT_EFI_ERROR (Status); NumOfBlocks = FwhInstance->NumOfBlocks; VA_START (args, This); do { StartingLba = VA_ARG (args, EFI_LBA); if (StartingLba == EFI_LBA_LIST_TERMINATOR) { break; } NumOfLba = VA_ARG (args, UINTN); // // Check input parameters // if (NumOfLba == 0 || (StartingLba + NumOfLba) > NumOfBlocks) { VA_END (args); return EFI_INVALID_PARAMETER; } } while (1); VA_END (args); VA_START (args, This); do { StartingLba = VA_ARG (args, EFI_LBA); if (StartingLba == EFI_LBA_LIST_TERMINATOR) { break; } NumOfLba = VA_ARG (args, UINTN); while (NumOfLba > 0) { Status = FvbEraseBlock (FvbDevice->Instance, StartingLba, mFvbModuleGlobal, EfiGoneVirtual ()); if (EFI_ERROR (Status)) { VA_END (args); return Status; } StartingLba++; NumOfLba--; } } while (1); VA_END (args); return EFI_SUCCESS; }