]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Variable/RuntimeDxe/reclaim.c
Patch to remove STATIC modifier. This is on longer recommended by EFI Framework codin...
[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
8d3a5c82 82EFI_STATUS\r
83GetLbaAndOffsetByAddress (\r
84 IN EFI_PHYSICAL_ADDRESS Address,\r
85 OUT EFI_LBA *Lba,\r
86 OUT UINTN *Offset\r
87 )\r
88{\r
89 EFI_STATUS Status;\r
90 EFI_HANDLE FvbHandle;\r
91 EFI_PHYSICAL_ADDRESS FvbBaseAddress;\r
92 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;\r
93 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;\r
94 EFI_FV_BLOCK_MAP_ENTRY *FvbMapEntry;\r
95 UINT32 LbaIndex;\r
96\r
97 *Lba = (EFI_LBA) (-1);\r
98 *Offset = 0;\r
99\r
100 //\r
101 // Get the proper FVB\r
102 //\r
103 Status = GetFvbHandleByAddress (Address, &FvbHandle);\r
104 if (EFI_ERROR (Status)) {\r
105 return Status;\r
106 }\r
107\r
108 Status = gBS->HandleProtocol (\r
109 FvbHandle,\r
110 &gEfiFirmwareVolumeBlockProtocolGuid,\r
111 (VOID **) &Fvb\r
112 );\r
113 if (EFI_ERROR (Status)) {\r
114 return Status;\r
115 }\r
116 //\r
117 // Get the Base Address of FV\r
118 //\r
119 Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress);\r
120 if (EFI_ERROR (Status)) {\r
121 return Status;\r
122 }\r
123\r
124 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvbBaseAddress);\r
125\r
126 //\r
127 // Get the (LBA, Offset) of Address\r
128 //\r
129 if ((Address >= FvbBaseAddress) && (Address <= (FvbBaseAddress + FwVolHeader->FvLength))) {\r
130 if ((FwVolHeader->FvLength) > (FwVolHeader->HeaderLength)) {\r
131 //\r
132 // BUGBUG: Assume one FV has one type of BlockLength\r
133 //\r
134 FvbMapEntry = &FwVolHeader->BlockMap[0];\r
135 for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) {\r
136 if (Address < (FvbBaseAddress + FvbMapEntry->Length * LbaIndex)) {\r
137 //\r
138 // Found the (Lba, Offset)\r
139 //\r
140 *Lba = LbaIndex - 1;\r
141 *Offset = (UINTN) (Address - (FvbBaseAddress + FvbMapEntry->Length * (LbaIndex - 1)));\r
142 return EFI_SUCCESS;\r
143 }\r
144 }\r
145 }\r
146 }\r
147\r
148 return EFI_ABORTED;\r
149}\r
150\r
151EFI_STATUS\r
152FtwVariableSpace (\r
153 IN EFI_PHYSICAL_ADDRESS VariableBase,\r
154 IN UINT8 *Buffer,\r
155 IN UINTN BufferSize\r
156 )\r
157/*++\r
158\r
159Routine Description:\r
160 Write a buffer to Variable space, in the working block.\r
161\r
162Arguments:\r
163 FvbHandle - Indicates a handle to FVB to access variable store\r
164 Buffer - Point to the input buffer\r
165 BufferSize - The number of bytes of the input Buffer\r
166\r
167Returns:\r
168 EFI_SUCCESS - The function completed successfully\r
169 EFI_ABORTED - The function could not complete successfully\r
170 EFI_NOT_FOUND - Locate FVB protocol by handle fails\r
171\r
172--*/\r
173{\r
174 EFI_STATUS Status;\r
175 EFI_HANDLE FvbHandle;\r
176 EFI_FTW_LITE_PROTOCOL *FtwLiteProtocol;\r
177 EFI_LBA VarLba;\r
178 UINTN VarOffset;\r
179 UINT8 *FtwBuffer;\r
180 UINTN FtwBufferSize;\r
181\r
182 //\r
183 // Locate fault tolerant write protocol\r
184 //\r
185 Status = gBS->LocateProtocol (\r
186 &gEfiFaultTolerantWriteLiteProtocolGuid,\r
187 NULL,\r
188 (VOID **) &FtwLiteProtocol\r
189 );\r
190 if (EFI_ERROR (Status)) {\r
191 return EFI_NOT_FOUND;\r
192 }\r
193 //\r
194 // Locate Fvb handle by address\r
195 //\r
196 Status = GetFvbHandleByAddress (VariableBase, &FvbHandle);\r
197 if (EFI_ERROR (Status)) {\r
198 return Status;\r
199 }\r
200 //\r
201 // Get LBA and Offset by address\r
202 //\r
203 Status = GetLbaAndOffsetByAddress (VariableBase, &VarLba, &VarOffset);\r
204 if (EFI_ERROR (Status)) {\r
205 return EFI_ABORTED;\r
206 }\r
207 //\r
208 // Prepare for the variable data\r
209 //\r
210 FtwBufferSize = ((VARIABLE_STORE_HEADER *) ((UINTN) VariableBase))->Size;\r
211 FtwBuffer = AllocateRuntimePool (FtwBufferSize);\r
212 if (FtwBuffer == NULL) {\r
213 return EFI_OUT_OF_RESOURCES;\r
214 }\r
215\r
216 SetMem (FtwBuffer, FtwBufferSize, (UINT8) 0xff);\r
217 CopyMem (FtwBuffer, Buffer, BufferSize);\r
218\r
219 //\r
220 // FTW write record\r
221 //\r
222 Status = FtwLiteProtocol->Write (\r
223 FtwLiteProtocol,\r
224 FvbHandle,\r
225 VarLba, // LBA\r
226 VarOffset, // Offset\r
227 &FtwBufferSize, // NumBytes,\r
228 FtwBuffer\r
229 );\r
230\r
231 FreePool (FtwBuffer);\r
232 return Status;\r
233}\r