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