1 /** @file
2   Internal header file for Extended SAL variable service module.
3 
4 Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution.  The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9 
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #ifndef _VARIABLE_H_
16 #define _VARIABLE_H_
17 
18 #include <PiDxe.h>
19 
20 #include <Protocol/VariableWrite.h>
21 #include <Protocol/FaultTolerantWrite.h>
22 #include <Protocol/FirmwareVolumeBlock.h>
23 #include <Protocol/Variable.h>
24 #include <Protocol/ExtendedSalBootService.h>
25 #include <Protocol/ExtendedSalServiceClasses.h>
26 
27 #include <Guid/GlobalVariable.h>
28 #include <Guid/AuthenticatedVariableFormat.h>
29 #include <Guid/ImageAuthentication.h>
30 #include <Guid/EventGroup.h>
31 
32 #include <Library/PcdLib.h>
33 #include <Library/HobLib.h>
34 #include <Library/UefiDriverEntryPoint.h>
35 #include <Library/DxeServicesTableLib.h>
36 #include <Library/UefiRuntimeLib.h>
37 #include <Library/DebugLib.h>
38 #include <Library/BaseMemoryLib.h>
39 #include <Library/UefiBootServicesTableLib.h>
40 #include <Library/UefiLib.h>
41 #include <Library/BaseLib.h>
42 #include <Library/SynchronizationLib.h>
43 #include <Library/MemoryAllocationLib.h>
44 #include <Library/ExtendedSalLib.h>
45 #include <Library/BaseCryptLib.h>
46 
47 #define MAX_NAME_SIZE            0x100
48 #define NUM_VAR_NAME             9  // Number of pre-defined variable name to be referenced
49 #define VAR_PLATFORM_LANG_CODES  0  // Index of "PlatformLangCodes" variable
50 #define VAR_LANG_CODES           1  // Index of "LangCodes" variable
51 #define VAR_PLATFORM_LANG        2  // Index of "PlatformLang" variable
52 #define VAR_LANG                 3  // Index of "Lang" variable
53 #define VAR_HW_ERR_REC           4  // Index of "HwErrRecXXXX" variable
54 #define VAR_AUTH_KEY_DB          5  // Index of "AuthVarKeyDatabase" variable
55 #define VAR_SETUP_MODE           6  // Index of "SetupMode" variable
56 #define VAR_PLATFORM_KEY         7  // Index of "PK" variable
57 #define VAR_KEY_EXCHANGE_KEY     8  // Index of "KEK" variable
58 
59 ///
60 /// "AuthVarKeyDatabase" variable for the Public Key store.
61 ///
62 #define AUTHVAR_KEYDB_NAME      L"AuthVarKeyDatabase"
63 #define AUTHVAR_KEYDB_NAME_SIZE 38
64 
65 ///
66 /// The maximum size of the public key database, restricted by maximum individal EFI
67 /// varible size, and excluding the variable header and name size.
68 ///
69 #define MAX_KEYDB_SIZE  (FixedPcdGet32 (PcdMaxVariableSize) - sizeof (AUTHENTICATED_VARIABLE_HEADER) - AUTHVAR_KEYDB_NAME_SIZE)
70 #define MAX_KEY_NUM     (MAX_KEYDB_SIZE / EFI_CERT_TYPE_RSA2048_SIZE)
71 
72 ///
73 /// The size of a 3 character ISO639 language code.
74 ///
75 #define ISO_639_2_ENTRY_SIZE    3
76 
77 typedef enum {
78   Physical,
79   Virtual
80 } VARIABLE_POINTER_TYPE;
81 
82 typedef struct {
83   EFI_PHYSICAL_ADDRESS CurrPtr;
84   EFI_PHYSICAL_ADDRESS EndPtr;
85   EFI_PHYSICAL_ADDRESS StartPtr;
86   BOOLEAN              Volatile;
87 } VARIABLE_POINTER_TRACK;
88 
89 typedef struct {
90   EFI_PHYSICAL_ADDRESS  VolatileVariableBase;
91   EFI_PHYSICAL_ADDRESS  NonVolatileVariableBase;
92   EFI_LOCK              VariableServicesLock;
93 } VARIABLE_GLOBAL;
94 
95 typedef struct {
96   VARIABLE_GLOBAL VariableGlobal[2];
97   CHAR16          *VariableName[2][NUM_VAR_NAME];
98   EFI_GUID        *GlobalVariableGuid[2];
99   UINTN           VolatileLastVariableOffset;
100   UINTN           NonVolatileLastVariableOffset;
101   UINTN           CommonVariableTotalSize;
102   UINTN           HwErrVariableTotalSize;
103   CHAR8           *PlatformLangCodes[2];
104   CHAR8           *LangCodes[2];
105   CHAR8           *PlatformLang[2];
106   CHAR8           Lang[ISO_639_2_ENTRY_SIZE + 1];
107   UINT32          FvbInstance;
108   UINT32          ReentrantState;
109   EFI_GUID        *AuthenticatedVariableGuid[2];
110   EFI_GUID        *CertRsa2048Sha256Guid[2];
111   EFI_GUID        *ImageSecurityDatabaseGuid[2];
112   VOID            *HashContext[2];             // Hash context pointer
113   UINT8           KeyList[MAX_KEYDB_SIZE];     // Cached Platform Key list
114   UINT8           PubKeyStore[MAX_KEYDB_SIZE]; // Cached Public Key list
115 } ESAL_VARIABLE_GLOBAL;
116 
117 typedef struct {
118   EFI_GUID    *Guid;
119   CHAR16      *Name;
120   UINT32      Attributes;
121   UINTN       DataSize;
122   VOID        *Data;
123 } VARIABLE_CACHE_ENTRY;
124 
125 
126 extern ESAL_VARIABLE_GLOBAL  *mVariableModuleGlobal;
127 
128 //
129 // Functions
130 //
131 
132 /**
133   Initializes variable store area for non-volatile and volatile variable.
134 
135   This function allocates and initializes memory space for global context of ESAL
136   variable service and variable store area for non-volatile and volatile variable.
137 
138   @param[in]  ImageHandle       The Image handle of this driver.
139   @param[in]  SystemTable       The pointer of EFI_SYSTEM_TABLE.
140 
141   @retval EFI_SUCCESS           Function successfully executed.
142   @retval EFI_OUT_OF_RESOURCES  Failed to allocate enough memory resource.
143 
144 **/
145 EFI_STATUS
146 VariableCommonInitialize (
147   IN EFI_HANDLE         ImageHandle,
148   IN EFI_SYSTEM_TABLE   *SystemTable
149   );
150 
151 /**
152   Entry point of Extended SAL Variable service module.
153 
154   This function is the entry point of Extended SAL Variable service module.
155   It registers all functions of Extended SAL Variable class, initializes
156   variable store for non-volatile and volatile variables, and registers
157   notification function for EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
158 
159   @param[in]  ImageHandle   The Image handle of this driver.
160   @param[in]  SystemTable   The pointer of EFI_SYSTEM_TABLE.
161 
162   @retval     EFI_SUCCESS   Extended SAL Variable Services Class successfully registered.
163 
164 **/
165 EFI_STATUS
166 EFIAPI
167 VariableServiceInitialize (
168   IN EFI_HANDLE         ImageHandle,
169   IN EFI_SYSTEM_TABLE   *SystemTable
170   );
171 
172 /**
173   Notification function of EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE.
174 
175   This is a notification function registered on EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE event.
176   It convers pointer to new virtual address.
177 
178   @param[in]  Event        The event whose notification function is being invoked.
179   @param[in]  Context      The pointer to the notification function's context.
180 
181 **/
182 VOID
183 EFIAPI
184 VariableClassAddressChangeEvent (
185   IN EFI_EVENT        Event,
186   IN VOID             *Context
187   );
188 
189 /**
190   Implements EsalGetVariable function of Extended SAL Variable Services Class.
191 
192   This function implements EsalGetVariable function of Extended SAL Variable Services Class.
193   It is equivalent in functionality to the EFI Runtime Service GetVariable().
194 
195   @param[in]      VariableName    A Null-terminated Unicode string that is the name of
196                                   the vendor's variable.
197   @param[in]      VendorGuid      A unique identifier for the vendor.
198   @param[out]     Attributes      If not NULL, a pointer to the memory location to return the
199                                   attributes bitmask for the variable.
200   @param[in, out] DataSize        Size of Data found. If size is less than the
201                                   data, this value contains the required size.
202   @param[out]     Data            On input, the size in bytes of the return Data buffer.
203                                   On output, the size of data returned in Data.
204   @param[in]      VirtualMode     Current calling mode for this function.
205   @param[in]      Global          Context of this Extended SAL Variable Services Class call.
206 
207   @retval EFI_SUCCESS            The function completed successfully.
208   @retval EFI_NOT_FOUND          The variable was not found.
209   @retval EFI_BUFFER_TOO_SMALL   DataSize is too small for the result.  DataSize has
210                                  been updated with the size needed to complete the request.
211   @retval EFI_INVALID_PARAMETER  VariableName is NULL.
212   @retval EFI_INVALID_PARAMETER  VendorGuid is NULL.
213   @retval EFI_INVALID_PARAMETER  DataSize is NULL.
214   @retval EFI_INVALID_PARAMETER  DataSize is not too small and Data is NULL.
215   @retval EFI_DEVICE_ERROR       The variable could not be retrieved due to a hardware error.
216   @retval EFI_SECURITY_VIOLATION The variable could not be retrieved due to an authentication failure.
217 
218 **/
219 EFI_STATUS
220 EFIAPI
221 EsalGetVariable (
222   IN      CHAR16                *VariableName,
223   IN      EFI_GUID              *VendorGuid,
224   OUT     UINT32                *Attributes OPTIONAL,
225   IN OUT  UINTN                 *DataSize,
226   OUT     VOID                  *Data,
227   IN      BOOLEAN               VirtualMode,
228   IN      ESAL_VARIABLE_GLOBAL  *Global
229   );
230 
231 /**
232   Implements EsalGetNextVariableName function of Extended SAL Variable Services Class.
233 
234   This function implements EsalGetNextVariableName function of Extended SAL Variable Services Class.
235   It is equivalent in functionality to the EFI Runtime Service GetNextVariableName().
236 
237   @param[in, out] VariableNameSize Size of the variable
238   @param[in, out] VariableName     On input, supplies the last VariableName that was returned by GetNextVariableName().
239                                    On output, returns the Null-terminated Unicode string of the current variable.
240   @param[in, out] VendorGuid       On input, supplies the last VendorGuid that was returned by GetNextVariableName().
241                                    On output, returns the VendorGuid of the current variable.
242   @param[in]      VirtualMode      Current calling mode for this function.
243   @param[in]      Global           Context of this Extended SAL Variable Services Class call.
244 
245   @retval EFI_SUCCESS             The function completed successfully.
246   @retval EFI_NOT_FOUND           The next variable was not found.
247   @retval EFI_BUFFER_TOO_SMALL    VariableNameSize is too small for the result.
248                                   VariableNameSize has been updated with the size needed to complete the request.
249   @retval EFI_INVALID_PARAMETER   VariableNameSize is NULL.
250   @retval EFI_INVALID_PARAMETER   VariableName is NULL.
251   @retval EFI_INVALID_PARAMETER   VendorGuid is NULL.
252   @retval EFI_DEVICE_ERROR        The variable name could not be retrieved due to a hardware error.
253 
254 **/
255 EFI_STATUS
256 EFIAPI
257 EsalGetNextVariableName (
258   IN OUT  UINTN                 *VariableNameSize,
259   IN OUT  CHAR16                *VariableName,
260   IN OUT  EFI_GUID              *VendorGuid,
261   IN      BOOLEAN               VirtualMode,
262   IN      ESAL_VARIABLE_GLOBAL  *Global
263   );
264 
265 /**
266   Implements EsalSetVariable function of Extended SAL Variable Services Class.
267 
268   This function implements EsalSetVariable function of Extended SAL Variable Services Class.
269   It is equivalent in functionality to the EFI Runtime Service SetVariable().
270 
271   @param[in]  VariableName       A Null-terminated Unicode string that is the name of the vendor's
272                                  variable.  Each VariableName is unique for each
273                                  VendorGuid.  VariableName must contain 1 or more
274                                  Unicode characters.  If VariableName is an empty Unicode
275                                  string, then EFI_INVALID_PARAMETER is returned.
276   @param[in]  VendorGuid         A unique identifier for the vendor.
277   @param[in]  Attributes         Attributes bitmask to set for the variable.
278   @param[in]  DataSize           The size in bytes of the Data buffer.  A size of zero causes the
279                                  variable to be deleted.
280   @param[in]  Data               The contents for the variable.
281   @param[in]  VirtualMode        Current calling mode for this function.
282   @param[in]  Global             Context of this Extended SAL Variable Services Class call.
283 
284   @retval EFI_SUCCESS            The firmware has successfully stored the variable and its data as
285                                  defined by the Attributes.
286   @retval EFI_INVALID_PARAMETER  An invalid combination of attribute bits was supplied, or the
287                                  DataSize exceeds the maximum allowed.
288   @retval EFI_INVALID_PARAMETER  VariableName is an empty Unicode string.
289   @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the variable and its data.
290   @retval EFI_DEVICE_ERROR       The variable could not be saved due to a hardware failure.
291   @retval EFI_WRITE_PROTECTED    The variable in question is read-only.
292   @retval EFI_WRITE_PROTECTED    The variable in question cannot be deleted.
293   @retval EFI_SECURITY_VIOLATION The variable could not be retrieved due to an authentication failure.
294   @retval EFI_NOT_FOUND          The variable trying to be updated or deleted was not found.
295 
296 **/
297 EFI_STATUS
298 EFIAPI
299 EsalSetVariable (
300   IN CHAR16                  *VariableName,
301   IN EFI_GUID                *VendorGuid,
302   IN UINT32                  Attributes,
303   IN UINTN                   DataSize,
304   IN VOID                    *Data,
305   IN BOOLEAN                 VirtualMode,
306   IN ESAL_VARIABLE_GLOBAL    *Global
307   );
308 
309 /**
310   Implements EsalQueryVariableInfo function of Extended SAL Variable Services Class.
311 
312   This function implements EsalQueryVariableInfo function of Extended SAL Variable Services Class.
313   It is equivalent in functionality to the EFI Runtime Service QueryVariableInfo().
314 
315   @param[in]  Attributes                   Attributes bitmask to specify the type of variables
316                                            on which to return information.
317   @param[out] MaximumVariableStorageSize   On output the maximum size of the storage space available for
318                                            the EFI variables associated with the attributes specified.
319   @param[out] RemainingVariableStorageSize Returns the remaining size of the storage space available for EFI
320                                            variables associated with the attributes specified.
321   @param[out] MaximumVariableSize          Returns the maximum size of an individual EFI variable
322                                            associated with the attributes specified.
323   @param[in]  VirtualMode                  Current calling mode for this function
324   @param[in]  Global                       Context of this Extended SAL Variable Services Class call
325 
326   @retval EFI_SUCCESS                      Valid answer returned.
327   @retval EFI_INVALID_PARAMETER            An invalid combination of attribute bits was supplied.
328   @retval EFI_UNSUPPORTED                  The attribute is not supported on this platform, and the
329                                            MaximumVariableStorageSize, RemainingVariableStorageSize,
330                                            MaximumVariableSize are undefined.
331 **/
332 EFI_STATUS
333 EFIAPI
334 EsalQueryVariableInfo (
335   IN  UINT32                 Attributes,
336   OUT UINT64                 *MaximumVariableStorageSize,
337   OUT UINT64                 *RemainingVariableStorageSize,
338   OUT UINT64                 *MaximumVariableSize,
339   IN  BOOLEAN                VirtualMode,
340   IN  ESAL_VARIABLE_GLOBAL   *Global
341   );
342 
343 /**
344   Writes a buffer to variable storage space.
345 
346   This function writes a buffer to variable storage space into firmware
347   volume block device. The destination is specified by parameter
348   VariableBase. Fault Tolerant Write protocol is used for writing.
349 
350   @param[in] VariableBase The base address of the variable to write.
351   @param[in] Buffer       Points to the data buffer.
352   @param[in] BufferSize   The number of bytes of the data Buffer.
353 
354   @retval EFI_SUCCESS     The function completed successfully.
355   @retval EFI_NOT_FOUND   Fail to locate Fault Tolerant Write protocol.
356   @retval Other           The function could not complete successfully.
357 
358 **/
359 EFI_STATUS
360 FtwVariableSpace (
361   IN EFI_PHYSICAL_ADDRESS   VariableBase,
362   IN UINT8                  *Buffer,
363   IN UINTN                  BufferSize
364   );
365 
366 /**
367   Finds variable in volatile and non-volatile storage areas.
368 
369   This code finds variable in volatile and non-volatile storage areas.
370   If VariableName is an empty string, then we just return the first
371   qualified variable without comparing VariableName and VendorGuid.
372   Otherwise, VariableName and VendorGuid are compared.
373 
374   @param[in]  VariableName            Name of the variable to be found.
375   @param[in]  VendorGuid              Vendor GUID to be found.
376   @param[out] PtrTrack                VARIABLE_POINTER_TRACK structure for output,
377                                       including the range searched and the target position.
378   @param[in]  Global                  Pointer to VARIABLE_GLOBAL structure, including
379                                       base of volatile variable storage area, base of
380                                       NV variable storage area, and a lock.
381   @param[in]  Instance                Instance of FV Block services.
382 
383   @retval EFI_INVALID_PARAMETER       If VariableName is not an empty string, while
384                                       VendorGuid is NULL.
385   @retval EFI_SUCCESS                 Variable successfully found.
386   @retval EFI_INVALID_PARAMETER       Variable not found.
387 
388 **/
389 EFI_STATUS
390 FindVariable (
391   IN  CHAR16                  *VariableName,
392   IN  EFI_GUID                *VendorGuid,
393   OUT VARIABLE_POINTER_TRACK  *PtrTrack,
394   IN  VARIABLE_GLOBAL         *Global,
395   IN  UINTN                   Instance
396   );
397 
398 /**
399   Gets the pointer to variable data area.
400 
401   This function gets the pointer to variable data area.
402   The variable is specified by its variable header.
403 
404   @param[in]  VariableAddress    Start address of variable header.
405   @param[in]  Volatile           TRUE  - Variable is volatile.
406                                  FALSE - Variable is non-volatile.
407   @param[in]  Global             Pointer to VARAIBLE_GLOBAL structure.
408   @param[in]  Instance           Instance of FV Block services.
409   @param[out] VariableData       Buffer to hold variable data for output.
410 
411 **/
412 VOID
413 GetVariableDataPtr (
414   IN  EFI_PHYSICAL_ADDRESS   VariableAddress,
415   IN  BOOLEAN                Volatile,
416   IN  VARIABLE_GLOBAL        *Global,
417   IN  UINTN                  Instance,
418   OUT CHAR16                 *VariableData
419   );
420 
421 /**
422   Gets the size of variable data area.
423 
424   This function gets the size of variable data area.
425   The variable is specified by its variable header.
426   If variable header contains raw data, just return 0.
427 
428   @param[in]  Variable  Pointer to the variable header.
429 
430   @return               Size of variable data area in bytes.
431 
432 **/
433 UINTN
434 DataSizeOfVariable (
435   IN  AUTHENTICATED_VARIABLE_HEADER     *Variable
436   );
437 
438 /**
439   Update the variable region with Variable information. These are the same
440   arguments as the EFI Variable services.
441 
442   @param[in] VariableName       Name of variable.
443   @param[in] VendorGuid         Guid of variable.
444   @param[in] Data               Variable data.
445   @param[in] DataSize           Size of data. 0 means delete.
446   @param[in] Attributes         Attributes of the variable.
447   @param[in] KeyIndex           Index of associated public key.
448   @param[in] MonotonicCount     Value of associated monotonic count.
449   @param[in] VirtualMode        Current calling mode for this function.
450   @param[in] Global             Context of this Extended SAL Variable Services Class call.
451   @param[in] Variable           The variable information which is used to keep track of variable usage.
452 
453   @retval EFI_SUCCESS           The update operation is success.
454   @retval EFI_OUT_OF_RESOURCES  Variable region is full, can not write other data into this region.
455 
456 **/
457 EFI_STATUS
458 EFIAPI
459 UpdateVariable (
460   IN      CHAR16                  *VariableName,
461   IN      EFI_GUID                *VendorGuid,
462   IN      VOID                    *Data,
463   IN      UINTN                   DataSize,
464   IN      UINT32                  Attributes OPTIONAL,
465   IN      UINT32                  KeyIndex  OPTIONAL,
466   IN      UINT64                  MonotonicCount  OPTIONAL,
467   IN      BOOLEAN                 VirtualMode,
468   IN      ESAL_VARIABLE_GLOBAL    *Global,
469   IN      VARIABLE_POINTER_TRACK  *Variable
470   );
471 
472 /**
473   Checks variable header.
474 
475   This function checks if variable header is valid or not.
476 
477   @param[in]  VariableAddress    Start address of variable header.
478   @param[in]  Volatile           TRUE  - Variable is volatile.
479                                  FALSE - Variable is non-volatile.
480   @param[in]  Global             Pointer to VARAIBLE_GLOBAL structure.
481   @param[in]  Instance           Instance of FV Block services.
482   @param[out] VariableHeader     Pointer to AUTHENTICATED_VARIABLE_HEADER for output.
483 
484   @retval TRUE                   Variable header is valid.
485   @retval FALSE                  Variable header is not valid.
486 
487 **/
488 BOOLEAN
489 IsValidVariableHeader (
490   IN  EFI_PHYSICAL_ADDRESS              VariableAddress,
491   IN  BOOLEAN                           Volatile,
492   IN  VARIABLE_GLOBAL                   *Global,
493   IN  UINTN                             Instance,
494   OUT AUTHENTICATED_VARIABLE_HEADER     *VariableHeader  OPTIONAL
495   );
496 
497 /**
498   Flush the HOB variable to NV variable storage.
499 **/
500 VOID
501 FlushHob2Nv (
502   VOID
503   );
504 
505 #endif
506