]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/VariableAuthenticated/RuntimeDxe/Reclaim.c
Vlv2TbltDevicePkg: Use the merged Variable driver
[mirror_edk2.git] / SecurityPkg / VariableAuthenticated / RuntimeDxe / Reclaim.c
1 /** @file
2 Handles non-volatile variable store garbage collection, using FTW
3 (Fault Tolerant Write) protocol.
4
5 Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include "Variable.h"
17
18 /**
19 Gets LBA of block and offset by given address.
20
21 This function gets the Logical Block Address (LBA) of a firmware
22 volume block containing the given address, and the offset of the
23 address on the block.
24
25 @param Address Address which should be contained
26 by returned FVB handle.
27 @param Lba Pointer to LBA for output.
28 @param Offset Pointer to offset for output.
29
30 @retval EFI_SUCCESS LBA and offset successfully returned.
31 @retval EFI_NOT_FOUND Fail to find FVB handle by address.
32 @retval EFI_ABORTED Fail to find valid LBA and offset.
33
34 **/
35 EFI_STATUS
36 GetLbaAndOffsetByAddress (
37 IN EFI_PHYSICAL_ADDRESS Address,
38 OUT EFI_LBA *Lba,
39 OUT UINTN *Offset
40 )
41 {
42 EFI_STATUS Status;
43 EFI_PHYSICAL_ADDRESS FvbBaseAddress;
44 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
45 EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
46 EFI_FV_BLOCK_MAP_ENTRY *FvbMapEntry;
47 UINT32 LbaIndex;
48
49 *Lba = (EFI_LBA) (-1);
50 *Offset = 0;
51 Fvb = NULL;
52
53 //
54 // Get the proper FVB protocol.
55 //
56 Status = GetFvbInfoByAddress (Address, NULL, &Fvb);
57 if (EFI_ERROR (Status)) {
58 return Status;
59 }
60
61 //
62 // Get the Base Address of FV.
63 //
64 Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress);
65 if (EFI_ERROR (Status)) {
66 return Status;
67 }
68
69 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvbBaseAddress);
70
71 //
72 // Get the (LBA, Offset) of Address.
73 //
74 if ((FwVolHeader->FvLength) > (FwVolHeader->HeaderLength)) {
75 //
76 // BUGBUG: Assume one FV has one type of BlockLength.
77 //
78 FvbMapEntry = &FwVolHeader->BlockMap[0];
79 for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) {
80 if (Address < (FvbBaseAddress + FvbMapEntry->Length * LbaIndex)) {
81 //
82 // Found the (Lba, Offset).
83 //
84 *Lba = LbaIndex - 1;
85 *Offset = (UINTN) (Address - (FvbBaseAddress + FvbMapEntry->Length * (LbaIndex - 1)));
86 return EFI_SUCCESS;
87 }
88 }
89 }
90
91 return EFI_ABORTED;
92 }
93
94 /**
95 Writes a buffer to variable storage space, in the working block.
96
97 This function writes a buffer to variable storage space into a firmware
98 volume block device. The destination is specified by parameter
99 VariableBase. Fault Tolerant Write protocol is used for writing.
100
101 @param VariableBase Base address of variable to write
102 @param VariableBuffer Point to the variable data buffer.
103
104 @retval EFI_SUCCESS The function completed successfully.
105 @retval EFI_NOT_FOUND Fail to locate Fault Tolerant Write protocol.
106 @retval EFI_ABORTED The function could not complete successfully.
107
108 **/
109 EFI_STATUS
110 FtwVariableSpace (
111 IN EFI_PHYSICAL_ADDRESS VariableBase,
112 IN VARIABLE_STORE_HEADER *VariableBuffer
113 )
114 {
115 EFI_STATUS Status;
116 EFI_HANDLE FvbHandle;
117 EFI_LBA VarLba;
118 UINTN VarOffset;
119 UINTN FtwBufferSize;
120 EFI_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol;
121
122 //
123 // Locate fault tolerant write protocol.
124 //
125 Status = GetFtwProtocol((VOID **) &FtwProtocol);
126 if (EFI_ERROR (Status)) {
127 return EFI_NOT_FOUND;
128 }
129 //
130 // Locate Fvb handle by address.
131 //
132 Status = GetFvbInfoByAddress (VariableBase, &FvbHandle, NULL);
133 if (EFI_ERROR (Status)) {
134 return Status;
135 }
136 //
137 // Get LBA and Offset by address.
138 //
139 Status = GetLbaAndOffsetByAddress (VariableBase, &VarLba, &VarOffset);
140 if (EFI_ERROR (Status)) {
141 return EFI_ABORTED;
142 }
143
144 FtwBufferSize = ((VARIABLE_STORE_HEADER *) ((UINTN) VariableBase))->Size;
145 ASSERT (FtwBufferSize == VariableBuffer->Size);
146
147 //
148 // FTW write record.
149 //
150 Status = FtwProtocol->Write (
151 FtwProtocol,
152 VarLba, // LBA
153 VarOffset, // Offset
154 FtwBufferSize, // NumBytes
155 NULL, // PrivateData NULL
156 FvbHandle, // Fvb Handle
157 (VOID *) VariableBuffer // write buffer
158 );
159
160 return Status;
161 }