]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Variable/RuntimeDxe/Reclaim.c
MdeModulePkg: INF/DEC file updates to EDK II packages
[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 - 2014, Intel Corporation. All rights reserved.<BR>
7 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 #include "Variable.h"
18
19 /**
20 Gets LBA of block and offset by given address.
21
22 This function gets the Logical Block Address (LBA) of a firmware
23 volume block containing the given address, and the offset of the
24 address on the block.
25
26 @param Address Address which should be contained
27 by returned FVB handle.
28 @param Lba Pointer to LBA for output.
29 @param Offset Pointer to offset for output.
30
31 @retval EFI_SUCCESS LBA and offset successfully returned.
32 @retval EFI_NOT_FOUND Fail to find FVB handle by address.
33 @retval EFI_ABORTED Fail to find valid LBA and offset.
34
35 **/
36 EFI_STATUS
37 GetLbaAndOffsetByAddress (
38 IN EFI_PHYSICAL_ADDRESS Address,
39 OUT EFI_LBA *Lba,
40 OUT UINTN *Offset
41 )
42 {
43 EFI_STATUS Status;
44 EFI_PHYSICAL_ADDRESS FvbBaseAddress;
45 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
46 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
47 EFI_FV_BLOCK_MAP_ENTRY *FvbMapEntry;
48 UINT32 LbaIndex;
49
50 Fvb = NULL;
51 *Lba = (EFI_LBA) (-1);
52 *Offset = 0;
53
54 //
55 // Get the proper FVB protocol.
56 //
57 Status = GetFvbInfoByAddress (Address, NULL, &Fvb);
58 if (EFI_ERROR (Status)) {
59 return Status;
60 }
61
62 //
63 // Get the Base Address of FV.
64 //
65 Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress);
66 if (EFI_ERROR (Status)) {
67 return Status;
68 }
69
70 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvbBaseAddress);
71
72 //
73 // Get the (LBA, Offset) of Address.
74 //
75 if ((FwVolHeader->FvLength) > (FwVolHeader->HeaderLength)) {
76 //
77 // BUGBUG: Assume one FV has one type of BlockLength.
78 //
79 FvbMapEntry = &FwVolHeader->BlockMap[0];
80 for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) {
81 if (Address < (FvbBaseAddress + FvbMapEntry->Length * LbaIndex)) {
82 //
83 // Found the (Lba, Offset).
84 //
85 *Lba = LbaIndex - 1;
86 *Offset = (UINTN) (Address - (FvbBaseAddress + FvbMapEntry->Length * (LbaIndex - 1)));
87 return EFI_SUCCESS;
88 }
89 }
90 }
91
92 return EFI_ABORTED;
93 }
94
95 /**
96 Writes a buffer to variable storage space, in the working block.
97
98 This function writes a buffer to variable storage space into a firmware
99 volume block device. The destination is specified by parameter
100 VariableBase. Fault Tolerant Write protocol is used for writing.
101
102 @param VariableBase Base address of variable to write
103 @param VariableBuffer Point to the variable data buffer.
104
105 @retval EFI_SUCCESS The function completed successfully.
106 @retval EFI_NOT_FOUND Fail to locate Fault Tolerant Write protocol.
107 @retval EFI_ABORTED The function could not complete successfully.
108
109 **/
110 EFI_STATUS
111 FtwVariableSpace (
112 IN EFI_PHYSICAL_ADDRESS VariableBase,
113 IN VARIABLE_STORE_HEADER *VariableBuffer
114 )
115 {
116 EFI_STATUS Status;
117 EFI_HANDLE FvbHandle;
118 EFI_LBA VarLba;
119 UINTN VarOffset;
120 UINTN FtwBufferSize;
121 EFI_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol;
122
123 //
124 // Locate fault tolerant write protocol.
125 //
126 Status = GetFtwProtocol((VOID **) &FtwProtocol);
127 if (EFI_ERROR (Status)) {
128 return EFI_NOT_FOUND;
129 }
130 //
131 // Locate Fvb handle by address.
132 //
133 Status = GetFvbInfoByAddress (VariableBase, &FvbHandle, NULL);
134 if (EFI_ERROR (Status)) {
135 return Status;
136 }
137 //
138 // Get LBA and Offset by address.
139 //
140 Status = GetLbaAndOffsetByAddress (VariableBase, &VarLba, &VarOffset);
141 if (EFI_ERROR (Status)) {
142 return EFI_ABORTED;
143 }
144
145 FtwBufferSize = ((VARIABLE_STORE_HEADER *) ((UINTN) VariableBase))->Size;
146 ASSERT (FtwBufferSize == VariableBuffer->Size);
147
148 //
149 // FTW write record.
150 //
151 Status = FtwProtocol->Write (
152 FtwProtocol,
153 VarLba, // LBA
154 VarOffset, // Offset
155 FtwBufferSize, // NumBytes
156 NULL, // PrivateData NULL
157 FvbHandle, // Fvb Handle
158 (VOID *) VariableBuffer // write buffer
159 );
160
161 return Status;
162 }