/** Erases and initializes a firmware volume block @param[in] Instance The FV instance to be erased @param[in] Lba The logical block index to be erased @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 @retval EFI_INVALID_PARAMETER Instance not found **/ EFI_STATUS FvbEraseBlock ( IN UINTN Instance, IN EFI_LBA Lba ) { EFI_FVB_ATTRIBUTES_2 Attributes; UINTN LbaAddress; EFI_FW_VOL_INSTANCE *FwhInstance; UINTN LbaLength; EFI_STATUS Status; EFI_STATUS Status1; UINTN FlashAddress; // // Find the right instance of the FVB private data // FwhInstance = GetFvbInstance (Instance); // // Check if the FV is write enabled // Attributes = FvbGetVolumeAttributes (Instance); if ((Attributes & EFI_FVB2_WRITE_STATUS) == 0) { return EFI_ACCESS_DENIED; } // // Get the starting address of the block for erase. // Status = FvbGetLbaAddress (Instance, Lba, &FlashAddress, &LbaAddress, &LbaLength, NULL); if (EFI_ERROR (Status)) { return EFI_INVALID_PARAMETER; } // // Perform erase. // mSpiDeviceProtocol->SpiLock (FlashAddress, LbaLength, FALSE); Status1 = mSpiDeviceProtocol->SpiErase (FlashAddress, LbaLength); mSpiDeviceProtocol->SpiLock (FlashAddress, LbaLength, TRUE); WriteBackInvalidateDataCacheRange ((VOID *) LbaAddress, LbaLength); // // Check to see if the erase was successful. If not return a device error to // meet PI required return values. // if (Status1 == EFI_DEVICE_ERROR) { return Status1; } return EFI_SUCCESS; }
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 ); }
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_2 Attributes; UINTN LbaAddress; UINTN LbaLength; EFI_STATUS Status; UINT8 Data; // // Check if the FV is write enabled // FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual); if ((Attributes & EFI_FVB2_WRITE_STATUS) == 0) { return EFI_ACCESS_DENIED; } // // Get the starting address of the block for erase. // Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NULL, Global, Virtual); if (EFI_ERROR (Status)) { return Status; } if ((Attributes & EFI_FVB2_ERASE_POLARITY) != 0) { Data = 0xFF; } else { Data = 0x0; } SetMem ((UINT8 *) LbaAddress, LbaLength, Data); return EFI_SUCCESS; }
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_2 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, &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_FVB2_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; } // // Write data // CopyMem ((UINT8 *) (LbaAddress + BlockOffset), Buffer, (UINTN) (*NumBytes)); return Status; }
/** Writes specified number of bytes from the input buffer to the block @param[in] Instance The FV instance to be written to @param[in] Lba The starting logical block index to write to @param[in] BlockOffset Offset into the block at which to begin writing @param[in] NumBytes Pointer that on input contains the total size of the buffer. On output, it contains the total number of bytes actually written @param[in] Buffer Pointer to a caller allocated buffer that contains the source 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 Instance not found, or NumBytes, Buffer are NULL **/ EFI_STATUS FvbWriteBlock ( IN UINTN Instance, IN EFI_LBA Lba, IN UINTN BlockOffset, IN OUT UINTN *NumBytes, IN UINT8 *Buffer ) { EFI_FVB_ATTRIBUTES_2 Attributes; UINTN LbaAddress; UINTN LbaLength; EFI_FW_VOL_INSTANCE *FwhInstance; EFI_STATUS Status; EFI_STATUS Status1; UINTN FlashAddress; // // Validate input parameters. // if ((NumBytes == NULL) || (Buffer == NULL)) { return (EFI_INVALID_PARAMETER); } if (*NumBytes == 0) { return (EFI_INVALID_PARAMETER); } // // Get the information for the FV specified. // FwhInstance = GetFvbInstance (Instance); Status = FvbGetLbaAddress (Instance, Lba, &FlashAddress, &LbaAddress, &LbaLength, NULL); if (EFI_ERROR (Status)) { return EFI_INVALID_PARAMETER; } // // Check if the FV is write enabled // Attributes = FvbGetVolumeAttributes (Instance); if ((Attributes & EFI_FVB2_WRITE_STATUS) == 0) { return EFI_ACCESS_DENIED; } // // Perform boundary checks and adjust NumBytes if needed. // if (BlockOffset > LbaLength) { return EFI_INVALID_PARAMETER; } if ( LbaLength < ( *NumBytes + BlockOffset ) ) { *NumBytes = (UINT32) (LbaLength - BlockOffset); Status = EFI_BAD_BUFFER_SIZE; } // // Perform the write and flush the cache. // mSpiDeviceProtocol->SpiLock (FlashAddress, LbaLength, FALSE); Status1 = mSpiDeviceProtocol->SpiWrite (FlashAddress + BlockOffset, NumBytes, Buffer); mSpiDeviceProtocol->SpiLock (FlashAddress, LbaLength, TRUE); WriteBackInvalidateDataCacheRange ((VOID *) (LbaAddress + BlockOffset), *NumBytes); // // Determine the error to return based on PI spec. // if (Status1 == EFI_DEVICE_ERROR) { return Status1; } return Status; }
/** Reads specified number of bytes into a buffer from the specified block @param[in] Instance The FV instance to be read from @param[in] Lba The logical block address to be read from @param[in] BlockOffset Offset into the block at which to begin reading @param[in] NumBytes Pointer that on input contains the total size of the buffer. On output, it contains the total number of bytes read @param[in] Buffer Pointer to a caller allocated buffer that will be used to hold the data read @retval EFI_SUCCESS The firmware volume was read successfully and contents are in Buffer @retval EFI_BAD_BUFFER_SIZE Read attempted across a 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 @retval EFI_INVALID_PARAMETER Instance not found, or NumBytes, Buffer are NULL **/ STATIC EFI_STATUS FvbReadBlock ( IN UINTN Instance, IN EFI_LBA Lba, IN UINTN BlockOffset, IN OUT UINTN *NumBytes, IN UINT8 *Buffer ) { EFI_FVB_ATTRIBUTES_2 Attributes; UINTN LbaLength; EFI_STATUS Status; EFI_STATUS Status1; UINTN FlashAddress; // // Validate input parameters. // if ((NumBytes == NULL) || (Buffer == NULL)) { return (EFI_INVALID_PARAMETER); } if (*NumBytes == 0) { return (EFI_INVALID_PARAMETER); } // // Get information for the specific LBA. // Status = FvbGetLbaAddress (Instance, Lba, &FlashAddress, NULL, &LbaLength, NULL); if (EFI_ERROR (Status)) { return EFI_INVALID_PARAMETER; } // // Check if operation can happen in the current state. // Attributes = FvbGetVolumeAttributes (Instance); if ((Attributes & EFI_FVB2_READ_STATUS) == 0) { return EFI_ACCESS_DENIED; } // // Check to make sure that block information is valid for the current FV and // correct it if needed. // if (BlockOffset > LbaLength) { return EFI_INVALID_PARAMETER; } if (LbaLength < (*NumBytes + BlockOffset)) { *NumBytes = (UINT32) (LbaLength - BlockOffset); Status = EFI_BAD_BUFFER_SIZE; } // // Perform read. // Status1 = mSpiDeviceProtocol->SpiRead (FlashAddress + BlockOffset, NumBytes, Buffer); if (Status1 == EFI_DEVICE_ERROR) { return Status1; } return Status; }