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