]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Variable/RuntimeDxe/reclaim.c
Add comments and DoxyGen format for these files.
[mirror_edk2.git] / MdeModulePkg / Universal / Variable / RuntimeDxe / reclaim.c
CommitLineData
504214c4
LG
1/** @file\r
2 \r
3 Handles non-volatile variable store garbage collection, using FTW\r
4 (Fault Tolerant Write) protocol.\r
8d3a5c82 5\r
504214c4 6Copyright (c) 2006 - 2008, Intel Corporation\r
8d3a5c82 7All rights reserved. This program and the accompanying materials\r
8are licensed and made available under the terms and conditions of the BSD License\r
9which accompanies this distribution. The full text of the license may be found at\r
10http://opensource.org/licenses/bsd-license.php\r
11\r
12THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
504214c4 15**/\r
8d3a5c82 16\r
17\r
3cfb790c 18#include "Variable.h"\r
19#include <VariableFormat.h>\r
8d3a5c82 20\r
21EFI_STATUS\r
22GetFvbHandleByAddress (\r
23 IN EFI_PHYSICAL_ADDRESS Address,\r
24 OUT EFI_HANDLE *FvbHandle\r
25 )\r
26{\r
27 EFI_STATUS Status;\r
28 EFI_HANDLE *HandleBuffer;\r
29 UINTN HandleCount;\r
30 UINTN Index;\r
31 EFI_PHYSICAL_ADDRESS FvbBaseAddress;\r
32 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;\r
33 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
34\r
35 *FvbHandle = NULL;\r
36 //\r
37 // Locate all handles of Fvb protocol\r
38 //\r
39 Status = gBS->LocateHandleBuffer (\r
40 ByProtocol,\r
41 &gEfiFirmwareVolumeBlockProtocolGuid,\r
42 NULL,\r
43 &HandleCount,\r
44 &HandleBuffer\r
45 );\r
46 if (EFI_ERROR (Status)) {\r
47 return EFI_NOT_FOUND;\r
48 }\r
49 //\r
50 // Get the FVB to access variable store\r
51 //\r
52 for (Index = 0; Index < HandleCount; Index += 1) {\r
53 Status = gBS->HandleProtocol (\r
54 HandleBuffer[Index],\r
55 &gEfiFirmwareVolumeBlockProtocolGuid,\r
56 (VOID **) &Fvb\r
57 );\r
58 if (EFI_ERROR (Status)) {\r
59 Status = EFI_NOT_FOUND;\r
60 break;\r
61 }\r
62 //\r
63 // Compare the address and select the right one\r
64 //\r
65 Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress);\r
66 if (EFI_ERROR (Status)) {\r
67 continue;\r
68 }\r
69\r
70 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvbBaseAddress);\r
71 if ((Address >= FvbBaseAddress) && (Address <= (FvbBaseAddress + FwVolHeader->FvLength))) {\r
72 *FvbHandle = HandleBuffer[Index];\r
73 Status = EFI_SUCCESS;\r
74 break;\r
75 }\r
76 }\r
77\r
78 FreePool (HandleBuffer);\r
79 return Status;\r
80}\r
81\r
82STATIC\r
83EFI_STATUS\r
84GetLbaAndOffsetByAddress (\r
85 IN EFI_PHYSICAL_ADDRESS Address,\r
86 OUT EFI_LBA *Lba,\r
87 OUT UINTN *Offset\r
88 )\r
89{\r
90 EFI_STATUS Status;\r
91 EFI_HANDLE FvbHandle;\r
92 EFI_PHYSICAL_ADDRESS FvbBaseAddress;\r
93 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;\r
94 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
95 EFI_FV_BLOCK_MAP_ENTRY *FvbMapEntry;\r
96 UINT32 LbaIndex;\r
97\r
98 *Lba = (EFI_LBA) (-1);\r
99 *Offset = 0;\r
100\r
101 //\r
102 // Get the proper FVB\r
103 //\r
104 Status = GetFvbHandleByAddress (Address, &FvbHandle);\r
105 if (EFI_ERROR (Status)) {\r
106 return Status;\r
107 }\r
108\r
109 Status = gBS->HandleProtocol (\r
110 FvbHandle,\r
111 &gEfiFirmwareVolumeBlockProtocolGuid,\r
112 (VOID **) &Fvb\r
113 );\r
114 if (EFI_ERROR (Status)) {\r
115 return Status;\r
116 }\r
117 //\r
118 // Get the Base Address of FV\r
119 //\r
120 Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress);\r
121 if (EFI_ERROR (Status)) {\r
122 return Status;\r
123 }\r
124\r
125 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvbBaseAddress);\r
126\r
127 //\r
128 // Get the (LBA, Offset) of Address\r
129 //\r
130 if ((Address >= FvbBaseAddress) && (Address <= (FvbBaseAddress + FwVolHeader->FvLength))) {\r
131 if ((FwVolHeader->FvLength) > (FwVolHeader->HeaderLength)) {\r
132 //\r
133 // BUGBUG: Assume one FV has one type of BlockLength\r
134 //\r
135 FvbMapEntry = &FwVolHeader->BlockMap[0];\r
136 for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) {\r
137 if (Address < (FvbBaseAddress + FvbMapEntry->Length * LbaIndex)) {\r
138 //\r
139 // Found the (Lba, Offset)\r
140 //\r
141 *Lba = LbaIndex - 1;\r
142 *Offset = (UINTN) (Address - (FvbBaseAddress + FvbMapEntry->Length * (LbaIndex - 1)));\r
143 return EFI_SUCCESS;\r
144 }\r
145 }\r
146 }\r
147 }\r
148\r
149 return EFI_ABORTED;\r
150}\r
151\r
152EFI_STATUS\r
153FtwVariableSpace (\r
154 IN EFI_PHYSICAL_ADDRESS VariableBase,\r
155 IN UINT8 *Buffer,\r
156 IN UINTN BufferSize\r
157 )\r
158/*++\r
159\r
160Routine Description:\r
161 Write a buffer to Variable space, in the working block.\r
162\r
163Arguments:\r
164 FvbHandle - Indicates a handle to FVB to access variable store\r
165 Buffer - Point to the input buffer\r
166 BufferSize - The number of bytes of the input Buffer\r
167\r
168Returns:\r
169 EFI_SUCCESS - The function completed successfully\r
170 EFI_ABORTED - The function could not complete successfully\r
171 EFI_NOT_FOUND - Locate FVB protocol by handle fails\r
172\r
173--*/\r
174{\r
175 EFI_STATUS Status;\r
176 EFI_HANDLE FvbHandle;\r
177 EFI_FTW_LITE_PROTOCOL *FtwLiteProtocol;\r
178 EFI_LBA VarLba;\r
179 UINTN VarOffset;\r
180 UINT8 *FtwBuffer;\r
181 UINTN FtwBufferSize;\r
182\r
183 //\r
184 // Locate fault tolerant write protocol\r
185 //\r
186 Status = gBS->LocateProtocol (\r
187 &gEfiFaultTolerantWriteLiteProtocolGuid,\r
188 NULL,\r
189 (VOID **) &FtwLiteProtocol\r
190 );\r
191 if (EFI_ERROR (Status)) {\r
192 return EFI_NOT_FOUND;\r
193 }\r
194 //\r
195 // Locate Fvb handle by address\r
196 //\r
197 Status = GetFvbHandleByAddress (VariableBase, &FvbHandle);\r
198 if (EFI_ERROR (Status)) {\r
199 return Status;\r
200 }\r
201 //\r
202 // Get LBA and Offset by address\r
203 //\r
204 Status = GetLbaAndOffsetByAddress (VariableBase, &VarLba, &VarOffset);\r
205 if (EFI_ERROR (Status)) {\r
206 return EFI_ABORTED;\r
207 }\r
208 //\r
209 // Prepare for the variable data\r
210 //\r
211 FtwBufferSize = ((VARIABLE_STORE_HEADER *) ((UINTN) VariableBase))->Size;\r
212 FtwBuffer = AllocateRuntimePool (FtwBufferSize);\r
213 if (FtwBuffer == NULL) {\r
214 return EFI_OUT_OF_RESOURCES;\r
215 }\r
216\r
217 SetMem (FtwBuffer, FtwBufferSize, (UINT8) 0xff);\r
218 CopyMem (FtwBuffer, Buffer, BufferSize);\r
219\r
220 //\r
221 // FTW write record\r
222 //\r
223 Status = FtwLiteProtocol->Write (\r
224 FtwLiteProtocol,\r
225 FvbHandle,\r
226 VarLba, // LBA\r
227 VarOffset, // Offset\r
228 &FtwBufferSize, // NumBytes,\r
229 FtwBuffer\r
230 );\r
231\r
232 FreePool (FtwBuffer);\r
233 return Status;\r
234}\r