Пример #1
0
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 ());
}
Пример #2
0
/**
  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;
}
Пример #3
0
/**
  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;
}
Пример #4
0
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;
}
Пример #5
0
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;
}
Пример #6
0
/**
  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;
}
Пример #7
0
/**
  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;
}
Пример #8
0
/**
  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;
}