1 /** @file
2 
3   Implment all four UEFI runtime variable services and
4   install variable architeture protocol.
5 
6 Copyright (c) 2006 - 2016, 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 EFI_EVENT   mVirtualAddressChangeEvent = NULL;
20 
21 /**
22 
23   This code finds variable in storage blocks (Volatile or Non-Volatile).
24 
25   @param VariableName               Name of Variable to be found.
26   @param VendorGuid                 Variable vendor GUID.
27   @param Attributes                 Attribute value of the variable found.
28   @param DataSize                   Size of Data found. If size is less than the
29                                     data, this value contains the required size.
30   @param Data                       The buffer to return the contents of the variable. May be NULL
31                                     with a zero DataSize in order to determine the size buffer needed.
32 
33   @return EFI_INVALID_PARAMETER     Invalid parameter
34   @return EFI_SUCCESS               Find the specified variable
35   @return EFI_NOT_FOUND             Not found
36   @return EFI_BUFFER_TO_SMALL       DataSize is too small for the result
37 
38 **/
39 EFI_STATUS
40 EFIAPI
RuntimeServiceGetVariable(IN CHAR16 * VariableName,IN EFI_GUID * VendorGuid,OUT UINT32 * Attributes OPTIONAL,IN OUT UINTN * DataSize,OUT VOID * Data OPTIONAL)41 RuntimeServiceGetVariable (
42   IN CHAR16        *VariableName,
43   IN EFI_GUID      *VendorGuid,
44   OUT UINT32       *Attributes OPTIONAL,
45   IN OUT UINTN     *DataSize,
46   OUT VOID         *Data OPTIONAL
47   )
48 {
49   return EmuGetVariable (
50           VariableName,
51           VendorGuid,
52           Attributes OPTIONAL,
53           DataSize,
54           Data,
55           &mVariableModuleGlobal->VariableGlobal[Physical]
56           );
57 }
58 
59 /**
60 
61   This code Finds the Next available variable.
62 
63   @param VariableNameSize           Size of the variable name
64   @param VariableName               Pointer to variable name
65   @param VendorGuid                 Variable Vendor Guid
66 
67   @return EFI_INVALID_PARAMETER     Invalid parameter
68   @return EFI_SUCCESS               Find the specified variable
69   @return EFI_NOT_FOUND             Not found
70   @return EFI_BUFFER_TO_SMALL       DataSize is too small for the result
71 
72 **/
73 EFI_STATUS
74 EFIAPI
RuntimeServiceGetNextVariableName(IN OUT UINTN * VariableNameSize,IN OUT CHAR16 * VariableName,IN OUT EFI_GUID * VendorGuid)75 RuntimeServiceGetNextVariableName (
76   IN OUT UINTN     *VariableNameSize,
77   IN OUT CHAR16    *VariableName,
78   IN OUT EFI_GUID  *VendorGuid
79   )
80 {
81   return EmuGetNextVariableName (
82           VariableNameSize,
83           VariableName,
84           VendorGuid,
85           &mVariableModuleGlobal->VariableGlobal[Physical]
86           );
87 }
88 
89 /**
90 
91   This code sets variable in storage blocks (Volatile or Non-Volatile).
92 
93   @param VariableName                     Name of Variable to be found
94   @param VendorGuid                       Variable vendor GUID
95   @param Attributes                       Attribute value of the variable found
96   @param DataSize                         Size of Data found. If size is less than the
97                                           data, this value contains the required size.
98   @param Data                             Data pointer
99 
100   @return EFI_INVALID_PARAMETER           Invalid parameter
101   @return EFI_SUCCESS                     Set successfully
102   @return EFI_OUT_OF_RESOURCES            Resource not enough to set variable
103   @return EFI_NOT_FOUND                   Not found
104   @return EFI_WRITE_PROTECTED             Variable is read-only
105 
106 **/
107 EFI_STATUS
108 EFIAPI
RuntimeServiceSetVariable(IN CHAR16 * VariableName,IN EFI_GUID * VendorGuid,IN UINT32 Attributes,IN UINTN DataSize,IN VOID * Data)109 RuntimeServiceSetVariable (
110   IN CHAR16        *VariableName,
111   IN EFI_GUID      *VendorGuid,
112   IN UINT32        Attributes,
113   IN UINTN         DataSize,
114   IN VOID          *Data
115   )
116 {
117   return EmuSetVariable (
118           VariableName,
119           VendorGuid,
120           Attributes,
121           DataSize,
122           Data,
123           &mVariableModuleGlobal->VariableGlobal[Physical],
124           &mVariableModuleGlobal->VolatileLastVariableOffset,
125           &mVariableModuleGlobal->NonVolatileLastVariableOffset
126           );
127 }
128 
129 /**
130 
131   This code returns information about the EFI variables.
132 
133   @param Attributes                     Attributes bitmask to specify the type of variables
134                                         on which to return information.
135   @param MaximumVariableStorageSize     Pointer to the maximum size of the storage space available
136                                         for the EFI variables associated with the attributes specified.
137   @param RemainingVariableStorageSize   Pointer to the remaining size of the storage space available
138                                         for EFI variables associated with the attributes specified.
139   @param MaximumVariableSize            Pointer to the maximum size of an individual EFI variables
140                                         associated with the attributes specified.
141 
142   @return EFI_INVALID_PARAMETER         An invalid combination of attribute bits was supplied.
143   @return EFI_SUCCESS                   Query successfully.
144   @return EFI_UNSUPPORTED               The attribute is not supported on this platform.
145 
146 **/
147 EFI_STATUS
148 EFIAPI
RuntimeServiceQueryVariableInfo(IN UINT32 Attributes,OUT UINT64 * MaximumVariableStorageSize,OUT UINT64 * RemainingVariableStorageSize,OUT UINT64 * MaximumVariableSize)149 RuntimeServiceQueryVariableInfo (
150   IN  UINT32                 Attributes,
151   OUT UINT64                 *MaximumVariableStorageSize,
152   OUT UINT64                 *RemainingVariableStorageSize,
153   OUT UINT64                 *MaximumVariableSize
154   )
155 {
156   return EmuQueryVariableInfo (
157           Attributes,
158           MaximumVariableStorageSize,
159           RemainingVariableStorageSize,
160           MaximumVariableSize,
161           &mVariableModuleGlobal->VariableGlobal[Physical]
162           );
163 }
164 
165 /**
166   Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
167 
168   This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
169   It convers pointer to new virtual address.
170 
171   @param  Event        Event whose notification function is being invoked.
172   @param  Context      Pointer to the notification function's context.
173 
174 **/
175 VOID
176 EFIAPI
VariableClassAddressChangeEvent(IN EFI_EVENT Event,IN VOID * Context)177 VariableClassAddressChangeEvent (
178   IN EFI_EVENT        Event,
179   IN VOID             *Context
180   )
181 {
182   EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->PlatformLangCodes);
183   EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->LangCodes);
184   EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal->PlatformLang);
185   EfiConvertPointer (
186     0x0,
187     (VOID **) &mVariableModuleGlobal->VariableGlobal[Physical].NonVolatileVariableBase
188     );
189   EfiConvertPointer (
190     0x0,
191     (VOID **) &mVariableModuleGlobal->VariableGlobal[Physical].VolatileVariableBase
192     );
193   EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal);
194 }
195 
196 /**
197   EmuVariable Driver main entry point. The Variable driver places the 4 EFI
198   runtime services in the EFI System Table and installs arch protocols
199   for variable read and write services being available. It also registers
200   notification function for EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
201 
202   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
203   @param[in] SystemTable    A pointer to the EFI System Table.
204 
205   @retval EFI_SUCCESS       Variable service successfully initialized.
206 
207 **/
208 EFI_STATUS
209 EFIAPI
VariableServiceInitialize(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)210 VariableServiceInitialize (
211   IN EFI_HANDLE         ImageHandle,
212   IN EFI_SYSTEM_TABLE   *SystemTable
213   )
214 {
215   EFI_HANDLE  NewHandle;
216   EFI_STATUS  Status;
217 
218   Status = VariableCommonInitialize (ImageHandle, SystemTable);
219   ASSERT_EFI_ERROR (Status);
220 
221   SystemTable->RuntimeServices->GetVariable         = RuntimeServiceGetVariable;
222   SystemTable->RuntimeServices->GetNextVariableName = RuntimeServiceGetNextVariableName;
223   SystemTable->RuntimeServices->SetVariable         = RuntimeServiceSetVariable;
224   SystemTable->RuntimeServices->QueryVariableInfo   = RuntimeServiceQueryVariableInfo;
225 
226   //
227   // Now install the Variable Runtime Architectural Protocol on a new handle
228   //
229   NewHandle = NULL;
230   Status = gBS->InstallMultipleProtocolInterfaces (
231                   &NewHandle,
232                   &gEfiVariableArchProtocolGuid,
233                   NULL,
234                   &gEfiVariableWriteArchProtocolGuid,
235                   NULL,
236                   NULL
237                   );
238   ASSERT_EFI_ERROR (Status);
239 
240   Status = gBS->CreateEventEx (
241                   EVT_NOTIFY_SIGNAL,
242                   TPL_NOTIFY,
243                   VariableClassAddressChangeEvent,
244                   NULL,
245                   &gEfiEventVirtualAddressChangeGuid,
246                   &mVirtualAddressChangeEvent
247                   );
248   ASSERT_EFI_ERROR (Status);
249 
250   return EFI_SUCCESS;
251 }
252