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