From af1a266670d040d2f4083ff309d732d648afba2a Mon Sep 17 00:00:00 2001 From: Angelos Mouzakitis Date: Tue, 10 Oct 2023 14:33:42 +0000 Subject: Add submodule dependency files Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec --- .../Universal/Variable/RuntimeDxe/Reclaim.c | 155 +++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 roms/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/Reclaim.c (limited to 'roms/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/Reclaim.c') diff --git a/roms/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/Reclaim.c b/roms/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/Reclaim.c new file mode 100644 index 000000000..1def8e249 --- /dev/null +++ b/roms/edk2/MdeModulePkg/Universal/Variable/RuntimeDxe/Reclaim.c @@ -0,0 +1,155 @@ +/** @file + Handles non-volatile variable store garbage collection, using FTW + (Fault Tolerant Write) protocol. + +Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.
+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; +} -- cgit 1.2.3-korg