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