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