https://bugzilla.tianocore.org/show_bug.cgi?id=1373 Replace BSD 2-Clause License with BSD+Patent License. This change is based on the following emails: https://lists.01.org/pipermail/edk2-devel/2019-February/036260.html https://lists.01.org/pipermail/edk2-devel/2018-October/030385.html RFCs with detailed process for the license change: V3: https://lists.01.org/pipermail/edk2-devel/2019-March/038116.html V2: https://lists.01.org/pipermail/edk2-devel/2019-March/037669.html V1: https://lists.01.org/pipermail/edk2-devel/2019-March/037500.html Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com> Reviewed-by: Hao Wu <hao.a.wu@intel.com> Reviewed-by: Jian J Wang <jian.j.wang@intel.com>
		
			
				
	
	
		
			156 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			156 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Handles non-volatile variable store garbage collection, using FTW
 | 
						|
  (Fault Tolerant Write) protocol.
 | 
						|
 | 
						|
Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
 | 
						|
SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "Variable.h"
 | 
						|
 | 
						|
/**
 | 
						|
  Gets LBA of block and offset by given address.
 | 
						|
 | 
						|
  This function gets the Logical Block Address (LBA) of a firmware
 | 
						|
  volume block containing the given address, and the offset of the
 | 
						|
  address on the block.
 | 
						|
 | 
						|
  @param  Address        Address which should be contained
 | 
						|
                         by returned FVB handle.
 | 
						|
  @param  Lba            Pointer to LBA for output.
 | 
						|
  @param  Offset         Pointer to offset for output.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS    LBA and offset successfully returned.
 | 
						|
  @retval EFI_NOT_FOUND  Fail to find FVB handle by address.
 | 
						|
  @retval EFI_ABORTED    Fail to find valid LBA and offset.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
GetLbaAndOffsetByAddress (
 | 
						|
  IN  EFI_PHYSICAL_ADDRESS   Address,
 | 
						|
  OUT EFI_LBA                *Lba,
 | 
						|
  OUT UINTN                  *Offset
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                          Status;
 | 
						|
  EFI_PHYSICAL_ADDRESS                FvbBaseAddress;
 | 
						|
  EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL  *Fvb;
 | 
						|
  EFI_FIRMWARE_VOLUME_HEADER          *FwVolHeader;
 | 
						|
  EFI_FV_BLOCK_MAP_ENTRY              *FvbMapEntry;
 | 
						|
  UINT32                              LbaIndex;
 | 
						|
 | 
						|
  Fvb     = NULL;
 | 
						|
  *Lba    = (EFI_LBA) (-1);
 | 
						|
  *Offset = 0;
 | 
						|
 | 
						|
  //
 | 
						|
  // Get the proper FVB protocol.
 | 
						|
  //
 | 
						|
  Status = GetFvbInfoByAddress (Address, NULL, &Fvb);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Get the Base Address of FV.
 | 
						|
  //
 | 
						|
  Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvbBaseAddress);
 | 
						|
 | 
						|
  //
 | 
						|
  // Get the (LBA, Offset) of Address.
 | 
						|
  //
 | 
						|
  if ((FwVolHeader->FvLength) > (FwVolHeader->HeaderLength)) {
 | 
						|
    //
 | 
						|
    // BUGBUG: Assume one FV has one type of BlockLength.
 | 
						|
    //
 | 
						|
    FvbMapEntry = &FwVolHeader->BlockMap[0];
 | 
						|
    for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) {
 | 
						|
      if (Address < (FvbBaseAddress + FvbMapEntry->Length * LbaIndex)) {
 | 
						|
        //
 | 
						|
        // Found the (Lba, Offset).
 | 
						|
        //
 | 
						|
        *Lba    = LbaIndex - 1;
 | 
						|
        *Offset = (UINTN) (Address - (FvbBaseAddress + FvbMapEntry->Length * (LbaIndex - 1)));
 | 
						|
        return EFI_SUCCESS;
 | 
						|
     }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_ABORTED;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Writes a buffer to variable storage space, in the working block.
 | 
						|
 | 
						|
  This function writes a buffer to variable storage space into a firmware
 | 
						|
  volume block device. The destination is specified by parameter
 | 
						|
  VariableBase. Fault Tolerant Write protocol is used for writing.
 | 
						|
 | 
						|
  @param  VariableBase   Base address of variable to write
 | 
						|
  @param  VariableBuffer Point to the variable data buffer.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS    The function completed successfully.
 | 
						|
  @retval EFI_NOT_FOUND  Fail to locate Fault Tolerant Write protocol.
 | 
						|
  @retval EFI_ABORTED    The function could not complete successfully.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
FtwVariableSpace (
 | 
						|
  IN EFI_PHYSICAL_ADDRESS   VariableBase,
 | 
						|
  IN VARIABLE_STORE_HEADER  *VariableBuffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                         Status;
 | 
						|
  EFI_HANDLE                         FvbHandle;
 | 
						|
  EFI_LBA                            VarLba;
 | 
						|
  UINTN                              VarOffset;
 | 
						|
  UINTN                              FtwBufferSize;
 | 
						|
  EFI_FAULT_TOLERANT_WRITE_PROTOCOL  *FtwProtocol;
 | 
						|
 | 
						|
  //
 | 
						|
  // Locate fault tolerant write protocol.
 | 
						|
  //
 | 
						|
  Status = GetFtwProtocol((VOID **) &FtwProtocol);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Locate Fvb handle by address.
 | 
						|
  //
 | 
						|
  Status = GetFvbInfoByAddress (VariableBase, &FvbHandle, NULL);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Get LBA and Offset by address.
 | 
						|
  //
 | 
						|
  Status = GetLbaAndOffsetByAddress (VariableBase, &VarLba, &VarOffset);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return EFI_ABORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  FtwBufferSize = ((VARIABLE_STORE_HEADER *) ((UINTN) VariableBase))->Size;
 | 
						|
  ASSERT (FtwBufferSize == VariableBuffer->Size);
 | 
						|
 | 
						|
  //
 | 
						|
  // FTW write record.
 | 
						|
  //
 | 
						|
  Status = FtwProtocol->Write (
 | 
						|
                          FtwProtocol,
 | 
						|
                          VarLba,         // LBA
 | 
						|
                          VarOffset,      // Offset
 | 
						|
                          FtwBufferSize,  // NumBytes
 | 
						|
                          NULL,           // PrivateData NULL
 | 
						|
                          FvbHandle,      // Fvb Handle
 | 
						|
                          (VOID *) VariableBuffer // write buffer
 | 
						|
                          );
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 |