• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 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 #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 
26 typedef
27 EFI_STATUS
28 (EFIAPI *INTERNAL_VAR_CHECK_FUNCTION) (
29   IN VAR_CHECK_VARIABLE_PROPERTY    *Propery,
30   IN UINTN                          DataSize,
31   IN VOID                           *Data
32   );
33 
34 typedef 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 **/
51 EFI_STATUS
52 EFIAPI
InternalVarCheckLoadOption(IN VAR_CHECK_VARIABLE_PROPERTY * VariablePropery,IN UINTN DataSize,IN VOID * Data)53 InternalVarCheckLoadOption (
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 **/
111 EFI_STATUS
112 EFIAPI
InternalVarCheckKeyOption(IN VAR_CHECK_VARIABLE_PROPERTY * VariablePropery,IN UINTN DataSize,IN VOID * Data)113 InternalVarCheckKeyOption (
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 **/
137 EFI_STATUS
138 EFIAPI
InternalVarCheckDevicePath(IN VAR_CHECK_VARIABLE_PROPERTY * VariablePropery,IN UINTN DataSize,IN VOID * Data)139 InternalVarCheckDevicePath (
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 **/
162 EFI_STATUS
163 EFIAPI
InternalVarCheckAsciiString(IN VAR_CHECK_VARIABLE_PROPERTY * VariablePropery,IN UINTN DataSize,IN VOID * Data)164 InternalVarCheckAsciiString (
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 **/
196 EFI_STATUS
197 EFIAPI
InternalVarCheckSizeArray(IN VAR_CHECK_VARIABLE_PROPERTY * VariablePropery,IN UINTN DataSize,IN VOID * Data)198 InternalVarCheckSizeArray (
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 //
218 UEFI_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_KEY_EXCHANGE_KEY_NAME,
430     {
431       VAR_CHECK_VARIABLE_PROPERTY_REVISION,
432       0,
433       VARIABLE_ATTRIBUTE_NV_BS_RT_AT,
434       1,
435       MAX_UINTN
436     },
437     NULL
438   },
439   {
440     EFI_PLATFORM_KEY_NAME,
441     {
442       VAR_CHECK_VARIABLE_PROPERTY_REVISION,
443       0,
444       VARIABLE_ATTRIBUTE_NV_BS_RT_AT,
445       1,
446       MAX_UINTN
447     },
448     NULL
449   },
450   {
451     EFI_SIGNATURE_SUPPORT_NAME,
452     {
453       VAR_CHECK_VARIABLE_PROPERTY_REVISION,
454       VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY,
455       VARIABLE_ATTRIBUTE_BS_RT,
456       sizeof (EFI_GUID),
457       MAX_UINTN
458     },
459     InternalVarCheckSizeArray
460   },
461   {
462     EFI_SECURE_BOOT_MODE_NAME,
463     {
464       VAR_CHECK_VARIABLE_PROPERTY_REVISION,
465       VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY,
466       VARIABLE_ATTRIBUTE_BS_RT,
467       sizeof (UINT8),
468       sizeof (UINT8)
469     },
470     NULL
471   },
472   {
473     EFI_KEK_DEFAULT_VARIABLE_NAME,
474     {
475       VAR_CHECK_VARIABLE_PROPERTY_REVISION,
476       VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY,
477       VARIABLE_ATTRIBUTE_BS_RT,
478       1,
479       MAX_UINTN
480     },
481     NULL
482   },
483   {
484     EFI_PK_DEFAULT_VARIABLE_NAME,
485     {
486       VAR_CHECK_VARIABLE_PROPERTY_REVISION,
487       VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY,
488       VARIABLE_ATTRIBUTE_BS_RT,
489       1,
490       MAX_UINTN
491     },
492     NULL
493   },
494   {
495     EFI_DB_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_DBX_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_DBT_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_OS_INDICATIONS_SUPPORT_VARIABLE_NAME,
529     {
530       VAR_CHECK_VARIABLE_PROPERTY_REVISION,
531       0,
532       VARIABLE_ATTRIBUTE_BS_RT,
533       sizeof (UINT64),
534       sizeof (UINT64)
535     },
536     NULL
537   },
538   {
539     EFI_OS_INDICATIONS_VARIABLE_NAME,
540     {
541       VAR_CHECK_VARIABLE_PROPERTY_REVISION,
542       0,
543       VARIABLE_ATTRIBUTE_NV_BS_RT,
544       sizeof (UINT64),
545       sizeof (UINT64)
546     },
547     NULL
548   },
549   {
550     EFI_VENDOR_KEYS_VARIABLE_NAME,
551     {
552       VAR_CHECK_VARIABLE_PROPERTY_REVISION,
553       VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY,
554       VARIABLE_ATTRIBUTE_BS_RT,
555       sizeof (UINT8),
556       sizeof (UINT8)
557     },
558     NULL
559   },
560 };
561 
562 UEFI_DEFINED_VARIABLE_ENTRY mGlobalVariableList2[] = {
563   {
564     L"Boot####",
565     {
566       VAR_CHECK_VARIABLE_PROPERTY_REVISION,
567       0,
568       VARIABLE_ATTRIBUTE_NV_BS_RT,
569       sizeof (UINT32) + sizeof (UINT16),
570       MAX_UINTN
571     },
572     InternalVarCheckLoadOption
573   },
574   {
575     L"Driver####",
576     {
577       VAR_CHECK_VARIABLE_PROPERTY_REVISION,
578       0,
579       VARIABLE_ATTRIBUTE_NV_BS_RT,
580       sizeof (UINT32) + sizeof (UINT16),
581       MAX_UINTN
582     },
583     InternalVarCheckLoadOption
584   },
585   {
586     L"SysPrep####",
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"Key####",
598     {
599       VAR_CHECK_VARIABLE_PROPERTY_REVISION,
600       0,
601       VARIABLE_ATTRIBUTE_NV_BS_RT,
602       sizeof (EFI_KEY_OPTION),
603       sizeof (EFI_KEY_OPTION) + 3 * sizeof (EFI_INPUT_KEY)
604     },
605     InternalVarCheckKeyOption
606   },
607   {
608     L"PlatformRecovery####",
609     {
610       VAR_CHECK_VARIABLE_PROPERTY_REVISION,
611       0,
612       VARIABLE_ATTRIBUTE_BS_RT,
613       sizeof (UINT32) + sizeof (UINT16),
614       MAX_UINTN
615     },
616     InternalVarCheckLoadOption
617   },
618 };
619 
620 //
621 // EFI_IMAGE_SECURITY_DATABASE_GUID
622 //
623 UEFI_DEFINED_VARIABLE_ENTRY mImageSecurityVariableList[] = {
624   {
625     EFI_IMAGE_SECURITY_DATABASE,
626     {
627       VAR_CHECK_VARIABLE_PROPERTY_REVISION,
628       0,
629       VARIABLE_ATTRIBUTE_NV_BS_RT_AT,
630       1,
631       MAX_UINTN
632     },
633     NULL
634   },
635   {
636     EFI_IMAGE_SECURITY_DATABASE1,
637     {
638       VAR_CHECK_VARIABLE_PROPERTY_REVISION,
639       0,
640       VARIABLE_ATTRIBUTE_NV_BS_RT_AT,
641       1,
642       MAX_UINTN
643     },
644     NULL
645   },
646   {
647     EFI_IMAGE_SECURITY_DATABASE2,
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 
659 //
660 // EFI_HARDWARE_ERROR_VARIABLE
661 //
662 UEFI_DEFINED_VARIABLE_ENTRY mHwErrRecVariable = {
663   L"HwErrRec####",
664   {
665     VAR_CHECK_VARIABLE_PROPERTY_REVISION,
666     0,
667     VARIABLE_ATTRIBUTE_NV_BS_RT_HR,
668     1,
669     MAX_UINTN
670   },
671   NULL
672 };
673 
674 EFI_GUID *mUefiDefinedGuid[] = {
675   &gEfiGlobalVariableGuid,
676   &gEfiImageSecurityDatabaseGuid,
677   &gEfiHardwareErrorVariableGuid
678 };
679 
680 /**
681   Check if a Unicode character is an upper case hexadecimal character.
682 
683   This function checks if a Unicode character is an upper case
684   hexadecimal character.  The valid upper case hexadecimal character is
685   L'0' to L'9', or L'A' to L'F'.
686 
687 
688   @param[in] Char       The character to check against.
689 
690   @retval TRUE          If the Char is an upper case hexadecmial character.
691   @retval FALSE         If the Char is not an upper case hexadecmial character.
692 
693 **/
694 BOOLEAN
695 EFIAPI
VarCheckUefiIsHexaDecimalDigitCharacter(IN CHAR16 Char)696 VarCheckUefiIsHexaDecimalDigitCharacter (
697   IN CHAR16             Char
698   )
699 {
700   return (BOOLEAN) ((Char >= L'0' && Char <= L'9') || (Char >= L'A' && Char <= L'F'));
701 }
702 
703 /**
704 
705   This code checks if variable is hardware error record variable or not.
706 
707   According to UEFI spec, hardware error record variable should use the EFI_HARDWARE_ERROR_VARIABLE VendorGuid
708   and have the L"HwErrRec####" name convention, #### is a printed hex value and no 0x or h is included in the hex value.
709 
710   @param[in] VariableName   Pointer to variable name.
711   @param[in] VendorGuid     Variable Vendor Guid.
712 
713   @retval TRUE              Variable is hardware error record variable.
714   @retval FALSE             Variable is not hardware error record variable.
715 
716 **/
717 BOOLEAN
718 EFIAPI
IsHwErrRecVariable(IN CHAR16 * VariableName,IN EFI_GUID * VendorGuid)719 IsHwErrRecVariable (
720   IN CHAR16             *VariableName,
721   IN EFI_GUID           *VendorGuid
722   )
723 {
724   if (!CompareGuid (VendorGuid, &gEfiHardwareErrorVariableGuid) ||
725       (StrLen (VariableName) != StrLen (L"HwErrRec####")) ||
726       (StrnCmp(VariableName, L"HwErrRec", StrLen (L"HwErrRec")) != 0) ||
727       !VarCheckUefiIsHexaDecimalDigitCharacter (VariableName[0x8]) ||
728       !VarCheckUefiIsHexaDecimalDigitCharacter (VariableName[0x9]) ||
729       !VarCheckUefiIsHexaDecimalDigitCharacter (VariableName[0xA]) ||
730       !VarCheckUefiIsHexaDecimalDigitCharacter (VariableName[0xB])) {
731     return FALSE;
732   }
733 
734   return TRUE;
735 }
736 
737 /**
738   Get UEFI defined var check function.
739 
740   @param[in]  VariableName      Pointer to variable name.
741   @param[in]  VendorGuid        Pointer to variable vendor GUID.
742   @param[out] VariableProperty  Pointer to variable property.
743 
744   @return Internal var check function, NULL if no specific check function.
745 
746 **/
747 INTERNAL_VAR_CHECK_FUNCTION
GetUefiDefinedVarCheckFunction(IN CHAR16 * VariableName,IN EFI_GUID * VendorGuid,OUT VAR_CHECK_VARIABLE_PROPERTY ** VariableProperty)748 GetUefiDefinedVarCheckFunction (
749   IN CHAR16                         *VariableName,
750   IN EFI_GUID                       *VendorGuid,
751   OUT VAR_CHECK_VARIABLE_PROPERTY   **VariableProperty
752   )
753 {
754   UINTN     Index;
755   UINTN     NameLength;
756 
757   if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid)) {
758     //
759     // Try list 1, exactly match.
760     //
761     for (Index = 0; Index < sizeof (mGlobalVariableList)/sizeof (mGlobalVariableList[0]); Index++) {
762       if (StrCmp (mGlobalVariableList[Index].Name, VariableName) == 0) {
763         *VariableProperty = &(mGlobalVariableList[Index].VariableProperty);
764         return mGlobalVariableList[Index].CheckFunction;
765       }
766     }
767 
768     //
769     // Try list 2.
770     //
771     NameLength = StrLen (VariableName) - 4;
772     for (Index = 0; Index < sizeof (mGlobalVariableList2)/sizeof (mGlobalVariableList2[0]); Index++) {
773       if ((StrLen (VariableName) == StrLen (mGlobalVariableList2[Index].Name)) &&
774           (StrnCmp (VariableName, mGlobalVariableList2[Index].Name, NameLength) == 0) &&
775           VarCheckUefiIsHexaDecimalDigitCharacter (VariableName[NameLength]) &&
776           VarCheckUefiIsHexaDecimalDigitCharacter (VariableName[NameLength + 1]) &&
777           VarCheckUefiIsHexaDecimalDigitCharacter (VariableName[NameLength + 2]) &&
778           VarCheckUefiIsHexaDecimalDigitCharacter (VariableName[NameLength + 3])) {
779         *VariableProperty = &(mGlobalVariableList2[Index].VariableProperty);
780         return mGlobalVariableList2[Index].CheckFunction;
781       }
782     }
783   }
784 
785   return NULL;
786 }
787 
788 /**
789   SetVariable check handler UEFI defined.
790 
791   @param[in] VariableName       Name of Variable to set.
792   @param[in] VendorGuid         Variable vendor GUID.
793   @param[in] Attributes         Attribute value of the variable.
794   @param[in] DataSize           Size of Data to set.
795   @param[in] Data               Data pointer.
796 
797   @retval EFI_SUCCESS           The SetVariable check result was success.
798   @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits, name, GUID,
799                                 DataSize and Data value was supplied.
800   @retval EFI_WRITE_PROTECTED   The variable in question is read-only.
801 
802 **/
803 EFI_STATUS
804 EFIAPI
SetVariableCheckHandlerUefiDefined(IN CHAR16 * VariableName,IN EFI_GUID * VendorGuid,IN UINT32 Attributes,IN UINTN DataSize,IN VOID * Data)805 SetVariableCheckHandlerUefiDefined (
806   IN CHAR16     *VariableName,
807   IN EFI_GUID   *VendorGuid,
808   IN UINT32     Attributes,
809   IN UINTN      DataSize,
810   IN VOID       *Data
811   )
812 {
813   EFI_STATUS                    Status;
814   UINTN                         Index;
815   VAR_CHECK_VARIABLE_PROPERTY   Property;
816   VAR_CHECK_VARIABLE_PROPERTY   *VarCheckProperty;
817   INTERNAL_VAR_CHECK_FUNCTION   VarCheckFunction;
818 
819   if ((((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) && (DataSize == 0)) || (Attributes == 0)) {
820     //
821     // Do not check delete variable.
822     //
823     return EFI_SUCCESS;
824   }
825 
826   if ((Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) == EFI_VARIABLE_HARDWARE_ERROR_RECORD) {
827     if (!IsHwErrRecVariable (VariableName, VendorGuid)) {
828       return EFI_INVALID_PARAMETER;
829     }
830   }
831 
832   for (Index = 0; Index < sizeof (mUefiDefinedGuid)/sizeof (mUefiDefinedGuid[0]); Index++) {
833     if (CompareGuid (VendorGuid, mUefiDefinedGuid[Index])) {
834       if (VarCheckLibVariablePropertyGet (VariableName, VendorGuid, &Property) == EFI_NOT_FOUND) {
835         //
836         // To prevent name collisions with possible future globally defined variables,
837         // other internal firmware data variables that are not defined here must be
838         // saved with a unique VendorGuid other than EFI_GLOBAL_VARIABLE or
839         // any other GUID defined by the UEFI Specification. Implementations must
840         // only permit the creation of variables with a UEFI Specification-defined
841         // VendorGuid when these variables are documented in the UEFI Specification.
842         //
843         DEBUG ((EFI_D_INFO, "UEFI Variable Check fail %r - %s not in %g namespace\n", EFI_INVALID_PARAMETER, VariableName, VendorGuid));
844         return EFI_INVALID_PARAMETER;
845       }
846     }
847   }
848 
849   if (DataSize == 0) {
850     return EFI_SUCCESS;
851   }
852 
853   VarCheckProperty = NULL;
854   VarCheckFunction = GetUefiDefinedVarCheckFunction (VariableName, VendorGuid, &VarCheckProperty);
855   if (VarCheckFunction != NULL) {
856     Status = VarCheckFunction (
857                VarCheckProperty,
858                DataSize,
859                Data
860                );
861     if (EFI_ERROR (Status)) {
862       DEBUG ((EFI_D_INFO, "UEFI Variable Check function fail %r - %g:%s\n", Status, VendorGuid, VariableName));
863       return Status;
864     }
865   }
866 
867   return EFI_SUCCESS;
868 }
869 
870 /**
871   Variable property set for UEFI defined variables.
872 
873 **/
874 VOID
VariablePropertySetUefiDefined(VOID)875 VariablePropertySetUefiDefined (
876   VOID
877   )
878 {
879   UINTN     Index;
880 
881   //
882   // EFI_GLOBAL_VARIABLE
883   //
884   for (Index = 0; Index < sizeof (mGlobalVariableList)/sizeof (mGlobalVariableList[0]); Index++) {
885     VarCheckLibVariablePropertySet (
886       mGlobalVariableList[Index].Name,
887       &gEfiGlobalVariableGuid,
888       &mGlobalVariableList[Index].VariableProperty
889       );
890   }
891   for (Index = 0; Index < sizeof (mGlobalVariableList2)/sizeof (mGlobalVariableList2[0]); Index++) {
892     VarCheckLibVariablePropertySet (
893       mGlobalVariableList2[Index].Name,
894       &gEfiGlobalVariableGuid,
895       &mGlobalVariableList2[Index].VariableProperty
896       );
897   }
898 
899   //
900   // EFI_IMAGE_SECURITY_DATABASE_GUID
901   //
902   for (Index = 0; Index < sizeof (mImageSecurityVariableList)/sizeof (mImageSecurityVariableList[0]); Index++) {
903     VarCheckLibVariablePropertySet (
904       mImageSecurityVariableList[Index].Name,
905       &gEfiImageSecurityDatabaseGuid,
906       &mImageSecurityVariableList[Index].VariableProperty
907       );
908   }
909 
910   //
911   // EFI_HARDWARE_ERROR_VARIABLE
912   //
913   VarCheckLibVariablePropertySet (
914     mHwErrRecVariable.Name,
915     &gEfiHardwareErrorVariableGuid,
916     &mHwErrRecVariable.VariableProperty
917     );
918 }
919 
920 /**
921   Constructor function of VarCheckUefiLib to set property and
922   register SetVariable check handler for UEFI defined variables.
923 
924   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
925   @param[in] SystemTable    A pointer to the EFI System Table.
926 
927   @retval EFI_SUCCESS       The constructor executed correctly.
928 
929 **/
930 EFI_STATUS
931 EFIAPI
VarCheckUefiLibNullClassConstructor(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)932 VarCheckUefiLibNullClassConstructor (
933   IN EFI_HANDLE             ImageHandle,
934   IN EFI_SYSTEM_TABLE       *SystemTable
935   )
936 {
937   VariablePropertySetUefiDefined ();
938   VarCheckLibRegisterSetVariableCheckHandler (SetVariableCheckHandlerUefiDefined);
939 
940   return EFI_SUCCESS;
941 }
942