EFI_STATUS EFIAPI FvbProtocolGetAttributes ( IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, OUT EFI_FVB_ATTRIBUTES_2 *Attributes ) /*++ Routine Description: Retrieves 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 FvbGetVolumeAttributes (FvbDevice->Instance, Attributes, mFvbModuleGlobal, EfiGoneVirtual ()); }
/** 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; }
/** 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; }
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; }
/** 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; }
/** 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; }