1/** @file
2  Implementation functions and structures for var check uefi library.
3
4Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
5This program and the accompanying materials
6are licensed and made available under the terms and conditions of the BSD License
7which accompanies this distribution.  The full text of the license may be found at
8http://opensource.org/licenses/bsd-license.php
9
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13**/
14
15#include <Library/VarCheckLib.h>
16#include <Library/BaseLib.h>
17#include <Library/BaseMemoryLib.h>
18#include <Library/DebugLib.h>
19#include <Library/DevicePathLib.h>
20
21#include <Guid/VariableFormat.h>
22#include <Guid/GlobalVariable.h>
23#include <Guid/HardwareErrorVariable.h>
24#include <Guid/ImageAuthentication.h>
25
26typedef
27EFI_STATUS
28(EFIAPI *INTERNAL_VAR_CHECK_FUNCTION) (
29  IN VAR_CHECK_VARIABLE_PROPERTY    *Propery,
30  IN UINTN                          DataSize,
31  IN VOID                           *Data
32  );
33
34typedef struct {
35  CHAR16                        *Name;
36  VAR_CHECK_VARIABLE_PROPERTY   VariableProperty;
37  INTERNAL_VAR_CHECK_FUNCTION   CheckFunction;
38} UEFI_DEFINED_VARIABLE_ENTRY;
39
40/**
41  Internal check for load option.
42
43  @param[in] VariablePropery    Pointer to variable property.
44  @param[in] DataSize           Data size.
45  @param[in] Data               Pointer to data buffer.
46
47  @retval EFI_SUCCESS           The SetVariable check result was success.
48  @retval EFI_INVALID_PARAMETER The data buffer is not a valid load option.
49
50**/
51EFI_STATUS
52EFIAPI
53InternalVarCheckLoadOption (
54  IN VAR_CHECK_VARIABLE_PROPERTY    *VariablePropery,
55  IN UINTN                          DataSize,
56  IN VOID                           *Data
57  )
58{
59  UINT16                    FilePathListLength;
60  CHAR16                    *Description;
61  EFI_DEVICE_PATH_PROTOCOL  *FilePathList;
62
63  FilePathListLength = *((UINT16 *) ((UINTN) Data + sizeof (UINT32)));
64
65  //
66  // Check Description
67  //
68  Description = (CHAR16 *) ((UINTN) Data + sizeof (UINT32) + sizeof (UINT16));
69  while (Description < (CHAR16 *) ((UINTN) Data + DataSize)) {
70    if (*Description == L'\0') {
71      break;
72    }
73    Description++;
74  }
75  if ((UINTN) Description >= ((UINTN) Data + DataSize)) {
76    return EFI_INVALID_PARAMETER;
77  }
78  Description++;
79
80  //
81  // Check FilePathList
82  //
83  FilePathList = (EFI_DEVICE_PATH_PROTOCOL *) Description;
84  if ((UINTN) FilePathList > (MAX_ADDRESS - FilePathListLength)) {
85    return EFI_INVALID_PARAMETER;
86  }
87  if (((UINTN) FilePathList + FilePathListLength) > ((UINTN) Data + DataSize)) {
88    return EFI_INVALID_PARAMETER;
89  }
90  if (FilePathListLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
91    return EFI_INVALID_PARAMETER;
92  }
93  if (!IsDevicePathValid (FilePathList, FilePathListLength)) {
94    return EFI_INVALID_PARAMETER;
95  }
96
97  return EFI_SUCCESS;
98}
99
100/**
101  Internal check for key option.
102
103  @param[in] VariablePropery    Pointer to variable property.
104  @param[in] DataSize           Data size.
105  @param[in] Data               Pointer to data buffer.
106
107  @retval EFI_SUCCESS           The SetVariable check result was success.
108  @retval EFI_INVALID_PARAMETER The data buffer is not a valid key option.
109
110**/
111EFI_STATUS
112EFIAPI
113InternalVarCheckKeyOption (
114  IN VAR_CHECK_VARIABLE_PROPERTY    *VariablePropery,
115  IN UINTN                          DataSize,
116  IN VOID                           *Data
117  )
118{
119  if (((DataSize - sizeof (EFI_KEY_OPTION)) % sizeof (EFI_INPUT_KEY)) != 0) {
120    return EFI_INVALID_PARAMETER;
121  }
122
123  return EFI_SUCCESS;
124}
125
126/**
127  Internal check for device path.
128
129  @param[in] VariablePropery    Pointer to variable property.
130  @param[in] DataSize           Data size.
131  @param[in] Data               Pointer to data buffer.
132
133  @retval EFI_SUCCESS           The SetVariable check result was success.
134  @retval EFI_INVALID_PARAMETER The data buffer is not a valid device path.
135
136**/
137EFI_STATUS
138EFIAPI
139InternalVarCheckDevicePath (
140  IN VAR_CHECK_VARIABLE_PROPERTY    *VariablePropery,
141  IN UINTN                          DataSize,
142  IN VOID                           *Data
143  )
144{
145  if (!IsDevicePathValid ((EFI_DEVICE_PATH_PROTOCOL *) Data, DataSize)) {
146    return EFI_INVALID_PARAMETER;
147  }
148  return EFI_SUCCESS;
149}
150
151/**
152  Internal check for ASCII string.
153
154  @param[in] VariablePropery    Pointer to variable property.
155  @param[in] DataSize           Data size.
156  @param[in] Data               Pointer to data buffer.
157
158  @retval EFI_SUCCESS           The SetVariable check result was success.
159  @retval EFI_INVALID_PARAMETER The data buffer is not a Null-terminated ASCII string.
160
161**/
162EFI_STATUS
163EFIAPI
164InternalVarCheckAsciiString (
165  IN VAR_CHECK_VARIABLE_PROPERTY    *VariablePropery,
166  IN UINTN                          DataSize,
167  IN VOID                           *Data
168  )
169{
170  CHAR8     *String;
171  UINTN     Index;
172
173  String = (CHAR8 *) Data;
174  if (String[DataSize - 1] == '\0') {
175    return EFI_SUCCESS;
176  } else {
177    for (Index = 1; Index < DataSize && (String[DataSize - 1 - Index] != '\0'); Index++);
178    if (Index == DataSize) {
179      return EFI_INVALID_PARAMETER;
180    }
181  }
182  return EFI_SUCCESS;
183}
184
185/**
186  Internal check for size array.
187
188  @param[in] VariablePropery    Pointer to variable property.
189  @param[in] DataSize           Data size.
190  @param[in] Data               Pointer to data buffer.
191
192  @retval EFI_SUCCESS           The SetVariable check result was success.
193  @retval EFI_INVALID_PARAMETER The DataSize is not size array.
194
195**/
196EFI_STATUS
197EFIAPI
198InternalVarCheckSizeArray (
199  IN VAR_CHECK_VARIABLE_PROPERTY    *VariablePropery,
200  IN UINTN                          DataSize,
201  IN VOID                           *Data
202  )
203{
204  if ((DataSize % VariablePropery->MinSize) != 0) {
205    return EFI_INVALID_PARAMETER;
206  }
207  return EFI_SUCCESS;
208}
209
210//
211// To prevent name collisions with possible future globally defined variables,
212// other internal firmware data variables that are not defined here must be
213// saved with a unique VendorGuid other than EFI_GLOBAL_VARIABLE or
214// any other GUID defined by the UEFI Specification. Implementations must
215// only permit the creation of variables with a UEFI Specification-defined
216// VendorGuid when these variables are documented in the UEFI Specification.
217//
218UEFI_DEFINED_VARIABLE_ENTRY mGlobalVariableList[] = {
219  {
220    EFI_LANG_CODES_VARIABLE_NAME,
221    {
222      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
223      0,
224      VARIABLE_ATTRIBUTE_BS_RT,
225      1,
226      MAX_UINTN
227    },
228    InternalVarCheckAsciiString
229  },
230  {
231    EFI_LANG_VARIABLE_NAME,
232    {
233      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
234      0,
235      VARIABLE_ATTRIBUTE_NV_BS_RT,
236      1,
237      MAX_UINTN
238    },
239    InternalVarCheckAsciiString
240  },
241  {
242    EFI_TIME_OUT_VARIABLE_NAME,
243    {
244      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
245      0,
246      VARIABLE_ATTRIBUTE_NV_BS_RT,
247      sizeof (UINT16),
248      sizeof (UINT16)
249    },
250    NULL
251  },
252  {
253    EFI_PLATFORM_LANG_CODES_VARIABLE_NAME,
254    {
255      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
256      0,
257      VARIABLE_ATTRIBUTE_BS_RT,
258      1,
259      MAX_UINTN
260    },
261    InternalVarCheckAsciiString
262  },
263  {
264    EFI_PLATFORM_LANG_VARIABLE_NAME,
265    {
266      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
267      0,
268      VARIABLE_ATTRIBUTE_NV_BS_RT,
269      1,
270      MAX_UINTN
271    },
272    InternalVarCheckAsciiString
273  },
274  {
275    EFI_CON_IN_VARIABLE_NAME,
276    {
277      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
278      0,
279      VARIABLE_ATTRIBUTE_NV_BS_RT,
280      sizeof (EFI_DEVICE_PATH_PROTOCOL),
281      MAX_UINTN
282    },
283    InternalVarCheckDevicePath
284  },
285  {
286    EFI_CON_OUT_VARIABLE_NAME,
287    {
288      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
289      0,
290      VARIABLE_ATTRIBUTE_NV_BS_RT,
291      sizeof (EFI_DEVICE_PATH_PROTOCOL),
292      MAX_UINTN
293    },
294    InternalVarCheckDevicePath
295  },
296  {
297    EFI_ERR_OUT_VARIABLE_NAME,
298    {
299      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
300      0,
301      VARIABLE_ATTRIBUTE_NV_BS_RT,
302      sizeof (EFI_DEVICE_PATH_PROTOCOL),
303      MAX_UINTN
304    },
305    InternalVarCheckDevicePath
306  },
307  {
308    EFI_CON_IN_DEV_VARIABLE_NAME,
309    {
310      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
311      0,
312      VARIABLE_ATTRIBUTE_BS_RT,
313      sizeof (EFI_DEVICE_PATH_PROTOCOL),
314      MAX_UINTN
315    },
316    InternalVarCheckDevicePath
317  },
318  {
319    EFI_CON_OUT_DEV_VARIABLE_NAME,
320    {
321      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
322      0,
323      VARIABLE_ATTRIBUTE_BS_RT,
324      sizeof (EFI_DEVICE_PATH_PROTOCOL),
325      MAX_UINTN
326    },
327    InternalVarCheckDevicePath
328  },
329  {
330    EFI_ERR_OUT_DEV_VARIABLE_NAME,
331    {
332      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
333      0,
334      VARIABLE_ATTRIBUTE_BS_RT,
335      sizeof (EFI_DEVICE_PATH_PROTOCOL),
336      MAX_UINTN
337    },
338    InternalVarCheckDevicePath
339  },
340  {
341    EFI_BOOT_ORDER_VARIABLE_NAME,
342    {
343      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
344      0,
345      VARIABLE_ATTRIBUTE_NV_BS_RT,
346      sizeof (UINT16),
347      MAX_UINTN
348    },
349    InternalVarCheckSizeArray
350  },
351  {
352    EFI_BOOT_NEXT_VARIABLE_NAME,
353    {
354      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
355      0,
356      VARIABLE_ATTRIBUTE_NV_BS_RT,
357      sizeof (UINT16),
358      sizeof (UINT16)
359    },
360    NULL
361  },
362  {
363    EFI_BOOT_CURRENT_VARIABLE_NAME,
364    {
365      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
366      0,
367      VARIABLE_ATTRIBUTE_BS_RT,
368      sizeof (UINT16),
369      sizeof (UINT16)
370    },
371    NULL
372  },
373  {
374    EFI_BOOT_OPTION_SUPPORT_VARIABLE_NAME,
375    {
376      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
377      0,
378      VARIABLE_ATTRIBUTE_BS_RT,
379      sizeof (UINT32),
380      sizeof (UINT32)
381    },
382    NULL
383  },
384  {
385    EFI_DRIVER_ORDER_VARIABLE_NAME,
386    {
387      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
388      0,
389      VARIABLE_ATTRIBUTE_NV_BS_RT,
390      sizeof (UINT16),
391      MAX_UINTN
392    },
393    InternalVarCheckSizeArray
394  },
395  {
396    EFI_SYS_PREP_ORDER_VARIABLE_NAME,
397    {
398      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
399      0,
400      VARIABLE_ATTRIBUTE_NV_BS_RT,
401      sizeof (UINT16),
402      MAX_UINTN
403    },
404    InternalVarCheckSizeArray
405  },
406  {
407    EFI_HW_ERR_REC_SUPPORT_VARIABLE_NAME,
408    {
409      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
410      0,
411      VARIABLE_ATTRIBUTE_NV_BS_RT,
412      sizeof (UINT16),
413      sizeof (UINT16)
414    },
415    NULL
416  },
417  {
418    EFI_SETUP_MODE_NAME,
419    {
420      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
421      VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY,
422      VARIABLE_ATTRIBUTE_BS_RT,
423      sizeof (UINT8),
424      sizeof (UINT8)
425    },
426    NULL
427  },
428  {
429    EFI_AUDIT_MODE_NAME,
430    {
431      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
432      0,
433      VARIABLE_ATTRIBUTE_BS_RT,
434      sizeof (UINT8),
435      sizeof (UINT8)
436    },
437    NULL
438  },
439  {
440    EFI_DEPLOYED_MODE_NAME,
441    {
442      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
443      0,
444      VARIABLE_ATTRIBUTE_BS_RT,
445      sizeof (UINT8),
446      sizeof (UINT8)
447    },
448    NULL
449  },
450  {
451    EFI_KEY_EXCHANGE_KEY_NAME,
452    {
453      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
454      0,
455      VARIABLE_ATTRIBUTE_NV_BS_RT_AT,
456      1,
457      MAX_UINTN
458    },
459    NULL
460  },
461  {
462    EFI_PLATFORM_KEY_NAME,
463    {
464      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
465      0,
466      VARIABLE_ATTRIBUTE_NV_BS_RT_AT,
467      1,
468      MAX_UINTN
469    },
470    NULL
471  },
472  {
473    EFI_SIGNATURE_SUPPORT_NAME,
474    {
475      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
476      VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY,
477      VARIABLE_ATTRIBUTE_BS_RT,
478      sizeof (EFI_GUID),
479      MAX_UINTN
480    },
481    InternalVarCheckSizeArray
482  },
483  {
484    EFI_SECURE_BOOT_MODE_NAME,
485    {
486      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
487      VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY,
488      VARIABLE_ATTRIBUTE_BS_RT,
489      sizeof (UINT8),
490      sizeof (UINT8)
491    },
492    NULL
493  },
494  {
495    EFI_KEK_DEFAULT_VARIABLE_NAME,
496    {
497      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
498      VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY,
499      VARIABLE_ATTRIBUTE_BS_RT,
500      1,
501      MAX_UINTN
502    },
503    NULL
504  },
505  {
506    EFI_PK_DEFAULT_VARIABLE_NAME,
507    {
508      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
509      VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY,
510      VARIABLE_ATTRIBUTE_BS_RT,
511      1,
512      MAX_UINTN
513    },
514    NULL
515  },
516  {
517    EFI_DB_DEFAULT_VARIABLE_NAME,
518    {
519      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
520      VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY,
521      VARIABLE_ATTRIBUTE_BS_RT,
522      1,
523      MAX_UINTN
524    },
525    NULL
526  },
527  {
528    EFI_DBX_DEFAULT_VARIABLE_NAME,
529    {
530      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
531      VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY,
532      VARIABLE_ATTRIBUTE_BS_RT,
533      1,
534      MAX_UINTN
535    },
536    NULL
537  },
538  {
539    EFI_DBT_DEFAULT_VARIABLE_NAME,
540    {
541      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
542      VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY,
543      VARIABLE_ATTRIBUTE_BS_RT,
544      1,
545      MAX_UINTN
546    },
547    NULL
548  },
549  {
550    EFI_OS_INDICATIONS_SUPPORT_VARIABLE_NAME,
551    {
552      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
553      0,
554      VARIABLE_ATTRIBUTE_BS_RT,
555      sizeof (UINT64),
556      sizeof (UINT64)
557    },
558    NULL
559  },
560  {
561    EFI_OS_INDICATIONS_VARIABLE_NAME,
562    {
563      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
564      0,
565      VARIABLE_ATTRIBUTE_NV_BS_RT,
566      sizeof (UINT64),
567      sizeof (UINT64)
568    },
569    NULL
570  },
571  {
572    EFI_VENDOR_KEYS_VARIABLE_NAME,
573    {
574      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
575      VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY,
576      VARIABLE_ATTRIBUTE_BS_RT,
577      sizeof (UINT8),
578      sizeof (UINT8)
579    },
580    NULL
581  },
582};
583
584UEFI_DEFINED_VARIABLE_ENTRY mGlobalVariableList2[] = {
585  {
586    L"Boot####",
587    {
588      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
589      0,
590      VARIABLE_ATTRIBUTE_NV_BS_RT,
591      sizeof (UINT32) + sizeof (UINT16),
592      MAX_UINTN
593    },
594    InternalVarCheckLoadOption
595  },
596  {
597    L"Driver####",
598    {
599      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
600      0,
601      VARIABLE_ATTRIBUTE_NV_BS_RT,
602      sizeof (UINT32) + sizeof (UINT16),
603      MAX_UINTN
604    },
605    InternalVarCheckLoadOption
606  },
607  {
608    L"SysPrep####",
609    {
610      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
611      0,
612      VARIABLE_ATTRIBUTE_NV_BS_RT,
613      sizeof (UINT32) + sizeof (UINT16),
614      MAX_UINTN
615    },
616    InternalVarCheckLoadOption
617  },
618  {
619    L"Key####",
620    {
621      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
622      0,
623      VARIABLE_ATTRIBUTE_NV_BS_RT,
624      sizeof (EFI_KEY_OPTION),
625      sizeof (EFI_KEY_OPTION) + 3 * sizeof (EFI_INPUT_KEY)
626    },
627    InternalVarCheckKeyOption
628  },
629  {
630    L"PlatformRecovery####",
631    {
632      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
633      0,
634      VARIABLE_ATTRIBUTE_BS_RT,
635      sizeof (UINT32) + sizeof (UINT16),
636      MAX_UINTN
637    },
638    InternalVarCheckLoadOption
639  },
640};
641
642//
643// EFI_IMAGE_SECURITY_DATABASE_GUID
644//
645UEFI_DEFINED_VARIABLE_ENTRY mImageSecurityVariableList[] = {
646  {
647    EFI_IMAGE_SECURITY_DATABASE,
648    {
649      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
650      0,
651      VARIABLE_ATTRIBUTE_NV_BS_RT_AT,
652      1,
653      MAX_UINTN
654    },
655    NULL
656  },
657  {
658    EFI_IMAGE_SECURITY_DATABASE1,
659    {
660      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
661      0,
662      VARIABLE_ATTRIBUTE_NV_BS_RT_AT,
663      1,
664      MAX_UINTN
665    },
666    NULL
667  },
668  {
669    EFI_IMAGE_SECURITY_DATABASE2,
670    {
671      VAR_CHECK_VARIABLE_PROPERTY_REVISION,
672      0,
673      VARIABLE_ATTRIBUTE_NV_BS_RT_AT,
674      1,
675      MAX_UINTN
676    },
677    NULL
678  },
679};
680
681//
682// EFI_HARDWARE_ERROR_VARIABLE
683//
684UEFI_DEFINED_VARIABLE_ENTRY mHwErrRecVariable = {
685  L"HwErrRec####",
686  {
687    VAR_CHECK_VARIABLE_PROPERTY_REVISION,
688    0,
689    VARIABLE_ATTRIBUTE_NV_BS_RT_HR,
690    1,
691    MAX_UINTN
692  },
693  NULL
694};
695
696EFI_GUID *mUefiDefinedGuid[] = {
697  &gEfiGlobalVariableGuid,
698  &gEfiImageSecurityDatabaseGuid,
699  &gEfiHardwareErrorVariableGuid
700};
701
702/**
703  Check if a Unicode character is a hexadecimal character.
704
705  This function checks if a Unicode character is a
706  hexadecimal character.  The valid hexadecimal character is
707  L'0' to L'9', L'a' to L'f', or L'A' to L'F'.
708
709
710  @param[in] Char       The character to check against.
711
712  @retval TRUE          If the Char is a hexadecmial character.
713  @retval FALSE         If the Char is not a hexadecmial character.
714
715**/
716BOOLEAN
717EFIAPI
718VarCheckUefiIsHexaDecimalDigitCharacter (
719  IN CHAR16             Char
720  )
721{
722  return (BOOLEAN) ((Char >= L'0' && Char <= L'9') || (Char >= L'A' && Char <= L'F') || (Char >= L'a' && Char <= L'f'));
723}
724
725/**
726
727  This code checks if variable is hardware error record variable or not.
728
729  According to UEFI spec, hardware error record variable should use the EFI_HARDWARE_ERROR_VARIABLE VendorGuid
730  and have the L"HwErrRec####" name convention, #### is a printed hex value and no 0x or h is included in the hex value.
731
732  @param[in] VariableName   Pointer to variable name.
733  @param[in] VendorGuid     Variable Vendor Guid.
734
735  @retval TRUE              Variable is hardware error record variable.
736  @retval FALSE             Variable is not hardware error record variable.
737
738**/
739BOOLEAN
740EFIAPI
741IsHwErrRecVariable (
742  IN CHAR16             *VariableName,
743  IN EFI_GUID           *VendorGuid
744  )
745{
746  if (!CompareGuid (VendorGuid, &gEfiHardwareErrorVariableGuid) ||
747      (StrLen (VariableName) != StrLen (L"HwErrRec####")) ||
748      (StrnCmp(VariableName, L"HwErrRec", StrLen (L"HwErrRec")) != 0) ||
749      !VarCheckUefiIsHexaDecimalDigitCharacter (VariableName[0x8]) ||
750      !VarCheckUefiIsHexaDecimalDigitCharacter (VariableName[0x9]) ||
751      !VarCheckUefiIsHexaDecimalDigitCharacter (VariableName[0xA]) ||
752      !VarCheckUefiIsHexaDecimalDigitCharacter (VariableName[0xB])) {
753    return FALSE;
754  }
755
756  return TRUE;
757}
758
759/**
760  Get UEFI defined var check function.
761
762  @param[in]  VariableName      Pointer to variable name.
763  @param[in]  VendorGuid        Pointer to variable vendor GUID.
764  @param[out] VariableProperty  Pointer to variable property.
765
766  @return Internal var check function, NULL if no specific check function.
767
768**/
769INTERNAL_VAR_CHECK_FUNCTION
770GetUefiDefinedVarCheckFunction (
771  IN CHAR16                         *VariableName,
772  IN EFI_GUID                       *VendorGuid,
773  OUT VAR_CHECK_VARIABLE_PROPERTY   **VariableProperty
774  )
775{
776  UINTN     Index;
777  UINTN     NameLength;
778
779  if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid)) {
780    //
781    // Try list 1, exactly match.
782    //
783    for (Index = 0; Index < sizeof (mGlobalVariableList)/sizeof (mGlobalVariableList[0]); Index++) {
784      if (StrCmp (mGlobalVariableList[Index].Name, VariableName) == 0) {
785        *VariableProperty = &(mGlobalVariableList[Index].VariableProperty);
786        return mGlobalVariableList[Index].CheckFunction;
787      }
788    }
789
790    //
791    // Try list 2.
792    //
793    NameLength = StrLen (VariableName) - 4;
794    for (Index = 0; Index < sizeof (mGlobalVariableList2)/sizeof (mGlobalVariableList2[0]); Index++) {
795      if ((StrLen (VariableName) == StrLen (mGlobalVariableList2[Index].Name)) &&
796          (StrnCmp (VariableName, mGlobalVariableList2[Index].Name, NameLength) == 0) &&
797          VarCheckUefiIsHexaDecimalDigitCharacter (VariableName[NameLength]) &&
798          VarCheckUefiIsHexaDecimalDigitCharacter (VariableName[NameLength + 1]) &&
799          VarCheckUefiIsHexaDecimalDigitCharacter (VariableName[NameLength + 2]) &&
800          VarCheckUefiIsHexaDecimalDigitCharacter (VariableName[NameLength + 3])) {
801        *VariableProperty = &(mGlobalVariableList2[Index].VariableProperty);
802        return mGlobalVariableList2[Index].CheckFunction;
803      }
804    }
805  }
806
807  return NULL;
808}
809
810/**
811  SetVariable check handler UEFI defined.
812
813  @param[in] VariableName       Name of Variable to set.
814  @param[in] VendorGuid         Variable vendor GUID.
815  @param[in] Attributes         Attribute value of the variable.
816  @param[in] DataSize           Size of Data to set.
817  @param[in] Data               Data pointer.
818
819  @retval EFI_SUCCESS           The SetVariable check result was success.
820  @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits, name, GUID,
821                                DataSize and Data value was supplied.
822  @retval EFI_WRITE_PROTECTED   The variable in question is read-only.
823
824**/
825EFI_STATUS
826EFIAPI
827SetVariableCheckHandlerUefiDefined (
828  IN CHAR16     *VariableName,
829  IN EFI_GUID   *VendorGuid,
830  IN UINT32     Attributes,
831  IN UINTN      DataSize,
832  IN VOID       *Data
833  )
834{
835  EFI_STATUS                    Status;
836  UINTN                         Index;
837  VAR_CHECK_VARIABLE_PROPERTY   Property;
838  VAR_CHECK_VARIABLE_PROPERTY   *VarCheckProperty;
839  INTERNAL_VAR_CHECK_FUNCTION   VarCheckFunction;
840
841  if ((((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) && (DataSize == 0)) || (Attributes == 0)) {
842    //
843    // Do not check delete variable.
844    //
845    return EFI_SUCCESS;
846  }
847
848  if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
849    if (!IsHwErrRecVariable (VariableName, VendorGuid)) {
850      return EFI_INVALID_PARAMETER;
851    }
852  }
853
854  for (Index = 0; Index < sizeof (mUefiDefinedGuid)/sizeof (mUefiDefinedGuid[0]); Index++) {
855    if (CompareGuid (VendorGuid, mUefiDefinedGuid[Index])) {
856      if (VarCheckLibVariablePropertyGet (VariableName, VendorGuid, &Property) == EFI_NOT_FOUND) {
857        //
858        // To prevent name collisions with possible future globally defined variables,
859        // other internal firmware data variables that are not defined here must be
860        // saved with a unique VendorGuid other than EFI_GLOBAL_VARIABLE or
861        // any other GUID defined by the UEFI Specification. Implementations must
862        // only permit the creation of variables with a UEFI Specification-defined
863        // VendorGuid when these variables are documented in the UEFI Specification.
864        //
865        DEBUG ((EFI_D_INFO, "UEFI Variable Check fail %r - %s not in %g namespace\n", EFI_INVALID_PARAMETER, VariableName, VendorGuid));
866        return EFI_INVALID_PARAMETER;
867      }
868    }
869  }
870
871  if (DataSize == 0) {
872    return EFI_SUCCESS;
873  }
874
875  VarCheckProperty = NULL;
876  VarCheckFunction = GetUefiDefinedVarCheckFunction (VariableName, VendorGuid, &VarCheckProperty);
877  if (VarCheckFunction != NULL) {
878    Status = VarCheckFunction (
879               VarCheckProperty,
880               DataSize,
881               Data
882               );
883    if (EFI_ERROR (Status)) {
884      DEBUG ((EFI_D_INFO, "UEFI Variable Check function fail %r - %g:%s\n", Status, VendorGuid, VariableName));
885      return Status;
886    }
887  }
888
889  return EFI_SUCCESS;
890}
891
892/**
893  Variable property set for UEFI defined variables.
894
895**/
896VOID
897VariablePropertySetUefiDefined (
898  VOID
899  )
900{
901  UINTN     Index;
902
903  //
904  // EFI_GLOBAL_VARIABLE
905  //
906  for (Index = 0; Index < sizeof (mGlobalVariableList)/sizeof (mGlobalVariableList[0]); Index++) {
907    VarCheckLibVariablePropertySet (
908      mGlobalVariableList[Index].Name,
909      &gEfiGlobalVariableGuid,
910      &mGlobalVariableList[Index].VariableProperty
911      );
912  }
913  for (Index = 0; Index < sizeof (mGlobalVariableList2)/sizeof (mGlobalVariableList2[0]); Index++) {
914    VarCheckLibVariablePropertySet (
915      mGlobalVariableList2[Index].Name,
916      &gEfiGlobalVariableGuid,
917      &mGlobalVariableList2[Index].VariableProperty
918      );
919  }
920
921  //
922  // EFI_IMAGE_SECURITY_DATABASE_GUID
923  //
924  for (Index = 0; Index < sizeof (mImageSecurityVariableList)/sizeof (mImageSecurityVariableList[0]); Index++) {
925    VarCheckLibVariablePropertySet (
926      mImageSecurityVariableList[Index].Name,
927      &gEfiImageSecurityDatabaseGuid,
928      &mImageSecurityVariableList[Index].VariableProperty
929      );
930  }
931
932  //
933  // EFI_HARDWARE_ERROR_VARIABLE
934  //
935  VarCheckLibVariablePropertySet (
936    mHwErrRecVariable.Name,
937    &gEfiHardwareErrorVariableGuid,
938    &mHwErrRecVariable.VariableProperty
939    );
940}
941
942/**
943  Constructor function of VarCheckUefiLib to set property and
944  register SetVariable check handler for UEFI defined variables.
945
946  @param[in] ImageHandle    The firmware allocated handle for the EFI image.
947  @param[in] SystemTable    A pointer to the EFI System Table.
948
949  @retval EFI_SUCCESS       The constructor executed correctly.
950
951**/
952EFI_STATUS
953EFIAPI
954VarCheckUefiLibNullClassConstructor (
955  IN EFI_HANDLE             ImageHandle,
956  IN EFI_SYSTEM_TABLE       *SystemTable
957  )
958{
959  VariablePropertySetUefiDefined ();
960  VarCheckLibRegisterSetVariableCheckHandler (SetVariableCheckHandlerUefiDefined);
961
962  return EFI_SUCCESS;
963}
964