]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Variable/RuntimeDxe/Reclaim.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Universal / Variable / RuntimeDxe / Reclaim.c
CommitLineData
504214c4 1/** @file\r
504214c4
LG
2 Handles non-volatile variable store garbage collection, using FTW\r
3 (Fault Tolerant Write) protocol.\r
8d3a5c82 4\r
fa0737a8 5Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>\r
9d510e61 6SPDX-License-Identifier: BSD-2-Clause-Patent\r
8d3a5c82 7\r
504214c4 8**/\r
8d3a5c82 9\r
3cfb790c 10#include "Variable.h"\r
8d3a5c82 11\r
7c80e839 12/**\r
13 Gets LBA of block and offset by given address.\r
14\r
8a2d4996 15 This function gets the Logical Block Address (LBA) of a firmware\r
16 volume block containing the given address, and the offset of the\r
7c80e839 17 address on the block.\r
18\r
19 @param Address Address which should be contained\r
8a2d4996 20 by returned FVB handle.\r
21 @param Lba Pointer to LBA for output.\r
22 @param Offset Pointer to offset for output.\r
7c80e839 23\r
8a2d4996 24 @retval EFI_SUCCESS LBA and offset successfully returned.\r
25 @retval EFI_NOT_FOUND Fail to find FVB handle by address.\r
26 @retval EFI_ABORTED Fail to find valid LBA and offset.\r
7c80e839 27\r
28**/\r
8d3a5c82 29EFI_STATUS\r
30GetLbaAndOffsetByAddress (\r
31 IN EFI_PHYSICAL_ADDRESS Address,\r
32 OUT EFI_LBA *Lba,\r
33 OUT UINTN *Offset\r
34 )\r
35{\r
36 EFI_STATUS Status;\r
8d3a5c82 37 EFI_PHYSICAL_ADDRESS FvbBaseAddress;\r
38 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;\r
39 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
40 EFI_FV_BLOCK_MAP_ENTRY *FvbMapEntry;\r
41 UINT32 LbaIndex;\r
42\r
4e1005ec 43 Fvb = NULL;\r
8d3a5c82 44 *Lba = (EFI_LBA) (-1);\r
45 *Offset = 0;\r
fa0737a8 46\r
8d3a5c82 47 //\r
8a2d4996 48 // Get the proper FVB protocol.\r
8d3a5c82 49 //\r
8a2d4996 50 Status = GetFvbInfoByAddress (Address, NULL, &Fvb);\r
8d3a5c82 51 if (EFI_ERROR (Status)) {\r
52 return Status;\r
53 }\r
54\r
8d3a5c82 55 //\r
8a2d4996 56 // Get the Base Address of FV.\r
8d3a5c82 57 //\r
58 Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress);\r
59 if (EFI_ERROR (Status)) {\r
60 return Status;\r
61 }\r
62\r
63 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvbBaseAddress);\r
64\r
65 //\r
8a2d4996 66 // Get the (LBA, Offset) of Address.\r
8d3a5c82 67 //\r
8a2d4996 68 if ((FwVolHeader->FvLength) > (FwVolHeader->HeaderLength)) {\r
69 //\r
70 // BUGBUG: Assume one FV has one type of BlockLength.\r
71 //\r
72 FvbMapEntry = &FwVolHeader->BlockMap[0];\r
73 for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) {\r
74 if (Address < (FvbBaseAddress + FvbMapEntry->Length * LbaIndex)) {\r
75 //\r
76 // Found the (Lba, Offset).\r
77 //\r
78 *Lba = LbaIndex - 1;\r
79 *Offset = (UINTN) (Address - (FvbBaseAddress + FvbMapEntry->Length * (LbaIndex - 1)));\r
80 return EFI_SUCCESS;\r
81 }\r
8d3a5c82 82 }\r
83 }\r
84\r
85 return EFI_ABORTED;\r
86}\r
87\r
7c80e839 88/**\r
89 Writes a buffer to variable storage space, in the working block.\r
90\r
8a2d4996 91 This function writes a buffer to variable storage space into a firmware\r
7c80e839 92 volume block device. The destination is specified by parameter\r
93 VariableBase. Fault Tolerant Write protocol is used for writing.\r
94\r
95 @param VariableBase Base address of variable to write\r
128ef095 96 @param VariableBuffer Point to the variable data buffer.\r
7c80e839 97\r
8a2d4996 98 @retval EFI_SUCCESS The function completed successfully.\r
99 @retval EFI_NOT_FOUND Fail to locate Fault Tolerant Write protocol.\r
100 @retval EFI_ABORTED The function could not complete successfully.\r
7c80e839 101\r
102**/\r
8d3a5c82 103EFI_STATUS\r
104FtwVariableSpace (\r
105 IN EFI_PHYSICAL_ADDRESS VariableBase,\r
128ef095 106 IN VARIABLE_STORE_HEADER *VariableBuffer\r
8d3a5c82 107 )\r
8d3a5c82 108{\r
88a5561c
LG
109 EFI_STATUS Status;\r
110 EFI_HANDLE FvbHandle;\r
111 EFI_LBA VarLba;\r
112 UINTN VarOffset;\r
88a5561c
LG
113 UINTN FtwBufferSize;\r
114 EFI_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol;\r
8d3a5c82 115\r
116 //\r
8a2d4996 117 // Locate fault tolerant write protocol.\r
8d3a5c82 118 //\r
8a2d4996 119 Status = GetFtwProtocol((VOID **) &FtwProtocol);\r
8d3a5c82 120 if (EFI_ERROR (Status)) {\r
121 return EFI_NOT_FOUND;\r
122 }\r
123 //\r
8a2d4996 124 // Locate Fvb handle by address.\r
8d3a5c82 125 //\r
8a2d4996 126 Status = GetFvbInfoByAddress (VariableBase, &FvbHandle, NULL);\r
8d3a5c82 127 if (EFI_ERROR (Status)) {\r
128 return Status;\r
129 }\r
130 //\r
8a2d4996 131 // Get LBA and Offset by address.\r
8d3a5c82 132 //\r
133 Status = GetLbaAndOffsetByAddress (VariableBase, &VarLba, &VarOffset);\r
134 if (EFI_ERROR (Status)) {\r
135 return EFI_ABORTED;\r
136 }\r
8d3a5c82 137\r
128ef095
SZ
138 FtwBufferSize = ((VARIABLE_STORE_HEADER *) ((UINTN) VariableBase))->Size;\r
139 ASSERT (FtwBufferSize == VariableBuffer->Size);\r
8d3a5c82 140\r
141 //\r
8a2d4996 142 // FTW write record.\r
8d3a5c82 143 //\r
88a5561c 144 Status = FtwProtocol->Write (\r
8a2d4996 145 FtwProtocol,\r
146 VarLba, // LBA\r
147 VarOffset, // Offset\r
148 FtwBufferSize, // NumBytes\r
149 NULL, // PrivateData NULL\r
150 FvbHandle, // Fvb Handle\r
128ef095 151 (VOID *) VariableBuffer // write buffer\r
8a2d4996 152 );\r
8d3a5c82 153\r
8d3a5c82 154 return Status;\r
155}\r