3 Handles non-volatile variable store garbage collection, using FTW
4 (Fault Tolerant Write) protocol.
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
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.
21 Gets firmware volume block handle by given address.
23 This function gets firmware volume block handle whose
24 address range contains the parameter Address.
26 @param Address Address which should be contained
27 by returned FVB handle
28 @param FvbHandle Pointer to FVB handle for output
30 @retval EFI_SUCCESS FVB handle successfully returned
31 @retval EFI_NOT_FOUND Fail to find FVB handle by address
35 GetFvbHandleByAddress (
36 IN EFI_PHYSICAL_ADDRESS Address
,
37 OUT EFI_HANDLE
*FvbHandle
41 EFI_HANDLE
*HandleBuffer
;
44 EFI_PHYSICAL_ADDRESS FvbBaseAddress
;
45 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*Fvb
;
46 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
47 EFI_FVB_ATTRIBUTES_2 Attributes
;
51 // Locate all handles of Fvb protocol
53 Status
= gBS
->LocateHandleBuffer (
55 &gEfiFirmwareVolumeBlockProtocolGuid
,
60 if (EFI_ERROR (Status
)) {
64 // Get the FVB to access variable store
66 for (Index
= 0; Index
< HandleCount
; Index
+= 1) {
67 Status
= gBS
->HandleProtocol (
69 &gEfiFirmwareVolumeBlockProtocolGuid
,
72 if (EFI_ERROR (Status
)) {
73 Status
= EFI_NOT_FOUND
;
77 Status
= Fvb
->GetAttributes (Fvb
, &Attributes
);
78 if (EFI_ERROR (Status
) || ((Attributes
& EFI_FVB2_WRITE_STATUS
) == 0)) {
82 // Compare the address and select the right one
84 Status
= Fvb
->GetPhysicalAddress (Fvb
, &FvbBaseAddress
);
85 if (EFI_ERROR (Status
)) {
89 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) FvbBaseAddress
);
90 if ((Address
>= FvbBaseAddress
) && (Address
<= (FvbBaseAddress
+ FwVolHeader
->FvLength
))) {
91 *FvbHandle
= HandleBuffer
[Index
];
97 FreePool (HandleBuffer
);
102 Gets LBA of block and offset by given address.
104 This function gets the Logical Block Address (LBA) of firmware
105 volume block containing the given address, and the offset of
106 address on the block.
108 @param Address Address which should be contained
109 by returned FVB handle
110 @param Lba Pointer to LBA for output
111 @param Offset Pointer to offset for output
113 @retval EFI_SUCCESS LBA and offset successfully returned
114 @retval EFI_NOT_FOUND Fail to find FVB handle by address
115 @retval EFI_ABORTED Fail to find valid LBA and offset
119 GetLbaAndOffsetByAddress (
120 IN EFI_PHYSICAL_ADDRESS Address
,
126 EFI_HANDLE FvbHandle
;
127 EFI_PHYSICAL_ADDRESS FvbBaseAddress
;
128 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL
*Fvb
;
129 EFI_FIRMWARE_VOLUME_HEADER
*FwVolHeader
;
130 EFI_FV_BLOCK_MAP_ENTRY
*FvbMapEntry
;
133 *Lba
= (EFI_LBA
) (-1);
137 // Get the proper FVB
139 Status
= GetFvbHandleByAddress (Address
, &FvbHandle
);
140 if (EFI_ERROR (Status
)) {
144 Status
= gBS
->HandleProtocol (
146 &gEfiFirmwareVolumeBlockProtocolGuid
,
149 if (EFI_ERROR (Status
)) {
153 // Get the Base Address of FV
155 Status
= Fvb
->GetPhysicalAddress (Fvb
, &FvbBaseAddress
);
156 if (EFI_ERROR (Status
)) {
160 FwVolHeader
= (EFI_FIRMWARE_VOLUME_HEADER
*) ((UINTN
) FvbBaseAddress
);
163 // Get the (LBA, Offset) of Address
165 if ((Address
>= FvbBaseAddress
) && (Address
<= (FvbBaseAddress
+ FwVolHeader
->FvLength
))) {
166 if ((FwVolHeader
->FvLength
) > (FwVolHeader
->HeaderLength
)) {
168 // BUGBUG: Assume one FV has one type of BlockLength
170 FvbMapEntry
= &FwVolHeader
->BlockMap
[0];
171 for (LbaIndex
= 1; LbaIndex
<= FvbMapEntry
->NumBlocks
; LbaIndex
+= 1) {
172 if (Address
< (FvbBaseAddress
+ FvbMapEntry
->Length
* LbaIndex
)) {
174 // Found the (Lba, Offset)
177 *Offset
= (UINTN
) (Address
- (FvbBaseAddress
+ FvbMapEntry
->Length
* (LbaIndex
- 1)));
188 Writes a buffer to variable storage space, in the working block.
190 This function writes a buffer to variable storage space into firmware
191 volume block device. The destination is specified by parameter
192 VariableBase. Fault Tolerant Write protocol is used for writing.
194 @param VariableBase Base address of variable to write
195 @param Buffer Point to the data buffer
196 @param BufferSize The number of bytes of the data Buffer
198 @retval EFI_SUCCESS The function completed successfully
199 @retval EFI_NOT_FOUND Fail to locate Fault Tolerant Write protocol
200 @retval EFI_ABORTED The function could not complete successfully
205 IN EFI_PHYSICAL_ADDRESS VariableBase
,
211 EFI_HANDLE FvbHandle
;
216 EFI_FAULT_TOLERANT_WRITE_PROTOCOL
*FtwProtocol
;
219 // Locate fault tolerant write protocol
221 Status
= gBS
->LocateProtocol (
222 &gEfiFaultTolerantWriteProtocolGuid
,
224 (VOID
**) &FtwProtocol
226 if (EFI_ERROR (Status
)) {
227 return EFI_NOT_FOUND
;
230 // Locate Fvb handle by address
232 Status
= GetFvbHandleByAddress (VariableBase
, &FvbHandle
);
233 if (EFI_ERROR (Status
)) {
237 // Get LBA and Offset by address
239 Status
= GetLbaAndOffsetByAddress (VariableBase
, &VarLba
, &VarOffset
);
240 if (EFI_ERROR (Status
)) {
244 // Prepare for the variable data
246 FtwBufferSize
= ((VARIABLE_STORE_HEADER
*) ((UINTN
) VariableBase
))->Size
;
247 FtwBuffer
= AllocateRuntimePool (FtwBufferSize
);
248 if (FtwBuffer
== NULL
) {
249 return EFI_OUT_OF_RESOURCES
;
252 SetMem (FtwBuffer
, FtwBufferSize
, (UINT8
) 0xff);
253 CopyMem (FtwBuffer
, Buffer
, BufferSize
);
258 Status
= FtwProtocol
->Write (
262 FtwBufferSize
, // NumBytes
263 NULL
, // PrivateData NULL
264 FvbHandle
, // Fvb Handle
265 FtwBuffer
// write buffer
268 FreePool (FtwBuffer
);