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