]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/VariableAuthenticated/RuntimeDxe/Reclaim.c
MdeModulePkg and SecurityPkg Variable: Optimize the code to reduce some SMRAM consump...
[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 - 2013, 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
52 //
53 // Get the proper FVB protocol.
54 //
55 Status = GetFvbInfoByAddress (Address, NULL, &Fvb);
56 if (EFI_ERROR (Status)) {
57 return Status;
58 }
59
60 //
61 // Get the Base Address of FV.
62 //
63 Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress);
64 if (EFI_ERROR (Status)) {
65 return Status;
66 }
67
68 FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvbBaseAddress);
69
70 //
71 // Get the (LBA, Offset) of Address.
72 //
73 if ((FwVolHeader->FvLength) > (FwVolHeader->HeaderLength)) {
74 //
75 // BUGBUG: Assume one FV has one type of BlockLength.
76 //
77 FvbMapEntry = &FwVolHeader->BlockMap[0];
78 for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) {
79 if (Address < (FvbBaseAddress + FvbMapEntry->Length * LbaIndex)) {
80 //
81 // Found the (Lba, Offset).
82 //
83 *Lba = LbaIndex - 1;
84 *Offset = (UINTN) (Address - (FvbBaseAddress + FvbMapEntry->Length * (LbaIndex - 1)));
85 return EFI_SUCCESS;
86 }
87 }
88 }
89
90 return EFI_ABORTED;
91 }
92
93 /**
94 Writes a buffer to variable storage space, in the working block.
95
96 This function writes a buffer to variable storage space into a firmware
97 volume block device. The destination is specified by parameter
98 VariableBase. Fault Tolerant Write protocol is used for writing.
99
100 @param VariableBase Base address of variable to write
101 @param VariableBuffer Point to the variable data buffer.
102
103 @retval EFI_SUCCESS The function completed successfully.
104 @retval EFI_NOT_FOUND Fail to locate Fault Tolerant Write protocol.
105 @retval EFI_ABORTED The function could not complete successfully.
106
107 **/
108 EFI_STATUS
109 FtwVariableSpace (
110 IN EFI_PHYSICAL_ADDRESS VariableBase,
111 IN VARIABLE_STORE_HEADER *VariableBuffer
112 )
113 {
114 EFI_STATUS Status;
115 EFI_HANDLE FvbHandle;
116 EFI_LBA VarLba;
117 UINTN VarOffset;
118 UINTN FtwBufferSize;
119 EFI_FAULT_TOLERANT_WRITE_PROTOCOL *FtwProtocol;
120
121 //
122 // Locate fault tolerant write protocol.
123 //
124 Status = GetFtwProtocol((VOID **) &FtwProtocol);
125 if (EFI_ERROR (Status)) {
126 return EFI_NOT_FOUND;
127 }
128 //
129 // Locate Fvb handle by address.
130 //
131 Status = GetFvbInfoByAddress (VariableBase, &FvbHandle, NULL);
132 if (EFI_ERROR (Status)) {
133 return Status;
134 }
135 //
136 // Get LBA and Offset by address.
137 //
138 Status = GetLbaAndOffsetByAddress (VariableBase, &VarLba, &VarOffset);
139 if (EFI_ERROR (Status)) {
140 return EFI_ABORTED;
141 }
142
143 FtwBufferSize = ((VARIABLE_STORE_HEADER *) ((UINTN) VariableBase))->Size;
144 ASSERT (FtwBufferSize == VariableBuffer->Size);
145
146 //
147 // FTW write record.
148 //
149 Status = FtwProtocol->Write (
150 FtwProtocol,
151 VarLba, // LBA
152 VarOffset, // Offset
153 FtwBufferSize, // NumBytes
154 NULL, // PrivateData NULL
155 FvbHandle, // Fvb Handle
156 (VOID *) VariableBuffer // write buffer
157 );
158
159 return Status;
160 }