• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 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
GetLbaAndOffsetByAddress(IN EFI_PHYSICAL_ADDRESS Address,OUT EFI_LBA * Lba,OUT UINTN * Offset)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   Fvb     = NULL;
50   *Lba    = (EFI_LBA) (-1);
51   *Offset = 0;
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
FtwVariableSpace(IN EFI_PHYSICAL_ADDRESS VariableBase,IN VARIABLE_STORE_HEADER * VariableBuffer)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 }
162