]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Variable/RuntimeDxe/Reclaim.c
fix build error on ICC compile.
[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
e5eed7d3
HT
6Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>\r
7This program and the accompanying materials\r
8d3a5c82 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
8d3a5c82 19\r
7c80e839 20/**\r
21 Gets firmware volume block handle by given address.\r
22\r
23 This function gets firmware volume block handle whose\r
24 address range contains the parameter Address.\r
25\r
26 @param Address Address which should be contained\r
27 by returned FVB handle\r
28 @param FvbHandle Pointer to FVB handle for output\r
29\r
30 @retval EFI_SUCCESS FVB handle successfully returned\r
31 @retval EFI_NOT_FOUND Fail to find FVB handle by address\r
32\r
33**/\r
8d3a5c82 34EFI_STATUS\r
35GetFvbHandleByAddress (\r
36 IN EFI_PHYSICAL_ADDRESS Address,\r
37 OUT EFI_HANDLE *FvbHandle\r
38 )\r
39{\r
40 EFI_STATUS Status;\r
41 EFI_HANDLE *HandleBuffer;\r
42 UINTN HandleCount;\r
43 UINTN Index;\r
44 EFI_PHYSICAL_ADDRESS FvbBaseAddress;\r
45 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;\r
46 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
8a9e0b72 47 EFI_FVB_ATTRIBUTES_2 Attributes;\r
8d3a5c82 48\r
49 *FvbHandle = NULL;\r
50 //\r
51 // Locate all handles of Fvb protocol\r
52 //\r
53 Status = gBS->LocateHandleBuffer (\r
54 ByProtocol,\r
55 &gEfiFirmwareVolumeBlockProtocolGuid,\r
56 NULL,\r
57 &HandleCount,\r
58 &HandleBuffer\r
59 );\r
60 if (EFI_ERROR (Status)) {\r
61 return EFI_NOT_FOUND;\r
62 }\r
63 //\r
64 // Get the FVB to access variable store\r
65 //\r
66 for (Index = 0; Index < HandleCount; Index += 1) {\r
67 Status = gBS->HandleProtocol (\r
68 HandleBuffer[Index],\r
69 &gEfiFirmwareVolumeBlockProtocolGuid,\r
70 (VOID **) &Fvb\r
71 );\r
72 if (EFI_ERROR (Status)) {\r
73 Status = EFI_NOT_FOUND;\r
74 break;\r
75 }\r
8a9e0b72 76\r
77 Status = Fvb->GetAttributes (Fvb, &Attributes);\r
78 if (EFI_ERROR (Status) || ((Attributes & EFI_FVB2_WRITE_STATUS) == 0)) {\r
79 continue; \r
80 }\r
8d3a5c82 81 //\r
82 // Compare the address and select the right one\r
83 //\r
84 Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress);\r
85 if (EFI_ERROR (Status)) {\r
86 continue;\r
87 }\r
88\r
89 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvbBaseAddress);\r
90 if ((Address >= FvbBaseAddress) && (Address <= (FvbBaseAddress + FwVolHeader->FvLength))) {\r
91 *FvbHandle = HandleBuffer[Index];\r
92 Status = EFI_SUCCESS;\r
93 break;\r
94 }\r
95 }\r
96\r
97 FreePool (HandleBuffer);\r
98 return Status;\r
99}\r
100\r
7c80e839 101/**\r
102 Gets LBA of block and offset by given address.\r
103\r
104 This function gets the Logical Block Address (LBA) of firmware\r
105 volume block containing the given address, and the offset of\r
106 address on the block.\r
107\r
108 @param Address Address which should be contained\r
109 by returned FVB handle\r
110 @param Lba Pointer to LBA for output\r
111 @param Offset Pointer to offset for output\r
112\r
113 @retval EFI_SUCCESS LBA and offset successfully returned\r
114 @retval EFI_NOT_FOUND Fail to find FVB handle by address\r
115 @retval EFI_ABORTED Fail to find valid LBA and offset\r
116\r
117**/\r
8d3a5c82 118EFI_STATUS\r
119GetLbaAndOffsetByAddress (\r
120 IN EFI_PHYSICAL_ADDRESS Address,\r
121 OUT EFI_LBA *Lba,\r
122 OUT UINTN *Offset\r
123 )\r
124{\r
125 EFI_STATUS Status;\r
126 EFI_HANDLE FvbHandle;\r
127 EFI_PHYSICAL_ADDRESS FvbBaseAddress;\r
128 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;\r
129 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
130 EFI_FV_BLOCK_MAP_ENTRY *FvbMapEntry;\r
131 UINT32 LbaIndex;\r
132\r
133 *Lba = (EFI_LBA) (-1);\r
134 *Offset = 0;\r
135\r
136 //\r
137 // Get the proper FVB\r
138 //\r
139 Status = GetFvbHandleByAddress (Address, &FvbHandle);\r
140 if (EFI_ERROR (Status)) {\r
141 return Status;\r
142 }\r
143\r
144 Status = gBS->HandleProtocol (\r
145 FvbHandle,\r
146 &gEfiFirmwareVolumeBlockProtocolGuid,\r
147 (VOID **) &Fvb\r
148 );\r
149 if (EFI_ERROR (Status)) {\r
150 return Status;\r
151 }\r
152 //\r
153 // Get the Base Address of FV\r
154 //\r
155 Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress);\r
156 if (EFI_ERROR (Status)) {\r
157 return Status;\r
158 }\r
159\r
160 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvbBaseAddress);\r
161\r
162 //\r
163 // Get the (LBA, Offset) of Address\r
164 //\r
165 if ((Address >= FvbBaseAddress) && (Address <= (FvbBaseAddress + FwVolHeader->FvLength))) {\r
166 if ((FwVolHeader->FvLength) > (FwVolHeader->HeaderLength)) {\r
167 //\r
168 // BUGBUG: Assume one FV has one type of BlockLength\r
169 //\r
170 FvbMapEntry = &FwVolHeader->BlockMap[0];\r
171 for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) {\r
172 if (Address < (FvbBaseAddress + FvbMapEntry->Length * LbaIndex)) {\r
173 //\r
174 // Found the (Lba, Offset)\r
175 //\r
176 *Lba = LbaIndex - 1;\r
177 *Offset = (UINTN) (Address - (FvbBaseAddress + FvbMapEntry->Length * (LbaIndex - 1)));\r
178 return EFI_SUCCESS;\r
179 }\r
180 }\r
181 }\r
182 }\r
183\r
184 return EFI_ABORTED;\r
185}\r
186\r
7c80e839 187/**\r
188 Writes a buffer to variable storage space, in the working block.\r
189\r
190 This function writes a buffer to variable storage space into firmware\r
191 volume block device. The destination is specified by parameter\r
192 VariableBase. Fault Tolerant Write protocol is used for writing.\r
193\r
194 @param VariableBase Base address of variable to write\r
195 @param Buffer Point to the data buffer\r
196 @param BufferSize The number of bytes of the data Buffer\r
197\r
198 @retval EFI_SUCCESS The function completed successfully\r
199 @retval EFI_NOT_FOUND Fail to locate Fault Tolerant Write protocol\r
200 @retval EFI_ABORTED The function could not complete successfully\r
201\r
202**/\r
8d3a5c82 203EFI_STATUS\r
204FtwVariableSpace (\r
205 IN EFI_PHYSICAL_ADDRESS VariableBase,\r
206 IN UINT8 *Buffer,\r
207 IN UINTN BufferSize\r
208 )\r
8d3a5c82 209{\r
88a5561c
LG
210 EFI_STATUS Status;\r
211 EFI_HANDLE FvbHandle;\r
212 EFI_LBA VarLba;\r
213 UINTN VarOffset;\r
214 UINT8 *FtwBuffer;\r
215 UINTN FtwBufferSize;\r
216 EFI_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol;\r
8d3a5c82 217\r
218 //\r
219 // Locate fault tolerant write protocol\r
220 //\r
221 Status = gBS->LocateProtocol (\r
88a5561c 222 &gEfiFaultTolerantWriteProtocolGuid,\r
8d3a5c82 223 NULL,\r
88a5561c 224 (VOID **) &FtwProtocol\r
8d3a5c82 225 );\r
226 if (EFI_ERROR (Status)) {\r
227 return EFI_NOT_FOUND;\r
228 }\r
229 //\r
230 // Locate Fvb handle by address\r
231 //\r
232 Status = GetFvbHandleByAddress (VariableBase, &FvbHandle);\r
233 if (EFI_ERROR (Status)) {\r
234 return Status;\r
235 }\r
236 //\r
237 // Get LBA and Offset by address\r
238 //\r
239 Status = GetLbaAndOffsetByAddress (VariableBase, &VarLba, &VarOffset);\r
240 if (EFI_ERROR (Status)) {\r
241 return EFI_ABORTED;\r
242 }\r
243 //\r
244 // Prepare for the variable data\r
245 //\r
246 FtwBufferSize = ((VARIABLE_STORE_HEADER *) ((UINTN) VariableBase))->Size;\r
247 FtwBuffer = AllocateRuntimePool (FtwBufferSize);\r
248 if (FtwBuffer == NULL) {\r
249 return EFI_OUT_OF_RESOURCES;\r
250 }\r
251\r
252 SetMem (FtwBuffer, FtwBufferSize, (UINT8) 0xff);\r
253 CopyMem (FtwBuffer, Buffer, BufferSize);\r
254\r
255 //\r
256 // FTW write record\r
257 //\r
88a5561c
LG
258 Status = FtwProtocol->Write (\r
259 FtwProtocol,\r
8d3a5c82 260 VarLba, // LBA\r
261 VarOffset, // Offset\r
88a5561c
LG
262 FtwBufferSize, // NumBytes\r
263 NULL, // PrivateData NULL\r
264 FvbHandle, // Fvb Handle\r
265 FtwBuffer // write buffer\r
8d3a5c82 266 );\r
267\r
268 FreePool (FtwBuffer);\r
269 return Status;\r
270}\r