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