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