]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Variable/RuntimeDxe/VarCheck.c
MdeModulePkg Variable: Add SysPrepOrder and SysPrep#### to global list.
[mirror_edk2.git] / MdeModulePkg / Universal / Variable / RuntimeDxe / VarCheck.c
1 /** @file
2 Implementation functions and structures for var check protocol.
3
4 Copyright (c) 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 #include "Variable.h"
16 #include <Library/DevicePathLib.h>
17
18 extern LIST_ENTRY mLockedVariableList;
19 extern BOOLEAN mEndOfDxe;
20 extern BOOLEAN mEnableLocking;
21
22 #define VAR_CHECK_HANDLER_TABLE_SIZE 0x8
23
24 UINT32 mNumberOfHandler = 0;
25 UINT32 mMaxNumberOfHandler = 0;
26 VAR_CHECK_SET_VARIABLE_CHECK_HANDLER *mHandlerTable = NULL;
27
28 typedef struct {
29 LIST_ENTRY Link;
30 EFI_GUID Guid;
31 VAR_CHECK_VARIABLE_PROPERTY VariableProperty;
32 //CHAR16 *Name;
33 } VAR_CHECK_VARIABLE_ENTRY;
34
35 LIST_ENTRY mVarCheckVariableList = INITIALIZE_LIST_HEAD_VARIABLE (mVarCheckVariableList);
36
37 typedef
38 EFI_STATUS
39 (EFIAPI *INTERNAL_VAR_CHECK_FUNCTION) (
40 IN VAR_CHECK_VARIABLE_PROPERTY *Propery,
41 IN UINTN DataSize,
42 IN VOID *Data
43 );
44
45 typedef struct {
46 CHAR16 *Name;
47 VAR_CHECK_VARIABLE_PROPERTY VariableProperty;
48 INTERNAL_VAR_CHECK_FUNCTION CheckFunction;
49 } UEFI_DEFINED_VARIABLE_ENTRY;
50
51 /**
52 Internal check for load option.
53
54 @param[in] VariablePropery Pointer to variable property.
55 @param[in] DataSize Data size.
56 @param[in] Data Pointer to data buffer.
57
58 @retval EFI_SUCCESS The SetVariable check result was success.
59 @retval EFI_INVALID_PARAMETER The data buffer is not a valid load option.
60
61 **/
62 EFI_STATUS
63 EFIAPI
64 InternalVarCheckLoadOption (
65 IN VAR_CHECK_VARIABLE_PROPERTY *VariablePropery,
66 IN UINTN DataSize,
67 IN VOID *Data
68 )
69 {
70 UINT16 FilePathListLength;
71 CHAR16 *Description;
72 EFI_DEVICE_PATH_PROTOCOL *FilePathList;
73
74 FilePathListLength = *((UINT16 *) ((UINTN) Data + sizeof (UINT32)));
75
76 //
77 // Check Description
78 //
79 Description = (CHAR16 *) ((UINTN) Data + sizeof (UINT32) + sizeof (UINT16));
80 while (Description < (CHAR16 *) ((UINTN) Data + DataSize)) {
81 if (*Description == L'\0') {
82 break;
83 }
84 Description++;
85 }
86 if ((UINTN) Description >= ((UINTN) Data + DataSize)) {
87 return EFI_INVALID_PARAMETER;
88 }
89 Description++;
90
91 //
92 // Check FilePathList
93 //
94 FilePathList = (EFI_DEVICE_PATH_PROTOCOL *) Description;
95 if ((UINTN) FilePathList > (MAX_ADDRESS - FilePathListLength)) {
96 return EFI_INVALID_PARAMETER;
97 }
98 if (((UINTN) FilePathList + FilePathListLength) > ((UINTN) Data + DataSize)) {
99 return EFI_INVALID_PARAMETER;
100 }
101 if (FilePathListLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) {
102 return EFI_INVALID_PARAMETER;
103 }
104 if (!IsDevicePathValid (FilePathList, FilePathListLength)) {
105 return EFI_INVALID_PARAMETER;
106 }
107
108 return EFI_SUCCESS;
109 }
110
111 /**
112 Internal check for key option.
113
114 @param[in] VariablePropery Pointer to variable property.
115 @param[in] DataSize Data size.
116 @param[in] Data Pointer to data buffer.
117
118 @retval EFI_SUCCESS The SetVariable check result was success.
119 @retval EFI_INVALID_PARAMETER The data buffer is not a valid key option.
120
121 **/
122 EFI_STATUS
123 EFIAPI
124 InternalVarCheckKeyOption (
125 IN VAR_CHECK_VARIABLE_PROPERTY *VariablePropery,
126 IN UINTN DataSize,
127 IN VOID *Data
128 )
129 {
130 if (((DataSize - sizeof (EFI_KEY_OPTION)) % sizeof (EFI_INPUT_KEY)) != 0) {
131 return EFI_INVALID_PARAMETER;
132 }
133
134 return EFI_SUCCESS;
135 }
136
137 /**
138 Internal check for device path.
139
140 @param[in] VariablePropery Pointer to variable property.
141 @param[in] DataSize Data size.
142 @param[in] Data Pointer to data buffer.
143
144 @retval EFI_SUCCESS The SetVariable check result was success.
145 @retval EFI_INVALID_PARAMETER The data buffer is not a valid device path.
146
147 **/
148 EFI_STATUS
149 EFIAPI
150 InternalVarCheckDevicePath (
151 IN VAR_CHECK_VARIABLE_PROPERTY *VariablePropery,
152 IN UINTN DataSize,
153 IN VOID *Data
154 )
155 {
156 if (!IsDevicePathValid ((EFI_DEVICE_PATH_PROTOCOL *) Data, DataSize)) {
157 return EFI_INVALID_PARAMETER;
158 }
159 return EFI_SUCCESS;
160 }
161
162 /**
163 Internal check for ASCII string.
164
165 @param[in] VariablePropery Pointer to variable property.
166 @param[in] DataSize Data size.
167 @param[in] Data Pointer to data buffer.
168
169 @retval EFI_SUCCESS The SetVariable check result was success.
170 @retval EFI_INVALID_PARAMETER The data buffer is not a Null-terminated ASCII string.
171
172 **/
173 EFI_STATUS
174 EFIAPI
175 InternalVarCheckAsciiString (
176 IN VAR_CHECK_VARIABLE_PROPERTY *VariablePropery,
177 IN UINTN DataSize,
178 IN VOID *Data
179 )
180 {
181 CHAR8 *String;
182 UINTN Index;
183
184 String = (CHAR8 *) Data;
185 if (String[DataSize - 1] == '\0') {
186 return EFI_SUCCESS;
187 } else {
188 for (Index = 1; Index < DataSize && (String[DataSize - 1 - Index] != '\0'); Index++);
189 if (Index == DataSize) {
190 return EFI_INVALID_PARAMETER;
191 }
192 }
193 return EFI_SUCCESS;
194 }
195
196 /**
197 Internal check for size array.
198
199 @param[in] VariablePropery Pointer to variable property.
200 @param[in] DataSize Data size.
201 @param[in] Data Pointer to data buffer.
202
203 @retval EFI_SUCCESS The SetVariable check result was success.
204 @retval EFI_INVALID_PARAMETER The DataSize is not size array.
205
206 **/
207 EFI_STATUS
208 EFIAPI
209 InternalVarCheckSizeArray (
210 IN VAR_CHECK_VARIABLE_PROPERTY *VariablePropery,
211 IN UINTN DataSize,
212 IN VOID *Data
213 )
214 {
215 if ((DataSize % VariablePropery->MinSize) != 0) {
216 return EFI_INVALID_PARAMETER;
217 }
218 return EFI_SUCCESS;
219 }
220
221 //
222 // To prevent name collisions with possible future globally defined variables,
223 // other internal firmware data variables that are not defined here must be
224 // saved with a unique VendorGuid other than EFI_GLOBAL_VARIABLE or
225 // any other GUID defined by the UEFI Specification. Implementations must
226 // only permit the creation of variables with a UEFI Specification-defined
227 // VendorGuid when these variables are documented in the UEFI Specification.
228 //
229 UEFI_DEFINED_VARIABLE_ENTRY mGlobalVariableList[] = {
230 {
231 EFI_LANG_CODES_VARIABLE_NAME,
232 {
233 VAR_CHECK_VARIABLE_PROPERTY_REVISION,
234 0,
235 VARIABLE_ATTRIBUTE_BS_RT,
236 1,
237 MAX_UINTN
238 },
239 InternalVarCheckAsciiString
240 },
241 {
242 EFI_LANG_VARIABLE_NAME,
243 {
244 VAR_CHECK_VARIABLE_PROPERTY_REVISION,
245 0,
246 VARIABLE_ATTRIBUTE_NV_BS_RT,
247 1,
248 MAX_UINTN
249 },
250 InternalVarCheckAsciiString
251 },
252 {
253 EFI_TIME_OUT_VARIABLE_NAME,
254 {
255 VAR_CHECK_VARIABLE_PROPERTY_REVISION,
256 0,
257 VARIABLE_ATTRIBUTE_NV_BS_RT,
258 sizeof (UINT16),
259 sizeof (UINT16)
260 },
261 NULL
262 },
263 {
264 EFI_PLATFORM_LANG_CODES_VARIABLE_NAME,
265 {
266 VAR_CHECK_VARIABLE_PROPERTY_REVISION,
267 0,
268 VARIABLE_ATTRIBUTE_BS_RT,
269 1,
270 MAX_UINTN
271 },
272 InternalVarCheckAsciiString
273 },
274 {
275 EFI_PLATFORM_LANG_VARIABLE_NAME,
276 {
277 VAR_CHECK_VARIABLE_PROPERTY_REVISION,
278 0,
279 VARIABLE_ATTRIBUTE_NV_BS_RT,
280 1,
281 MAX_UINTN
282 },
283 InternalVarCheckAsciiString
284 },
285 {
286 EFI_CON_IN_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_CON_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_ERR_OUT_VARIABLE_NAME,
309 {
310 VAR_CHECK_VARIABLE_PROPERTY_REVISION,
311 0,
312 VARIABLE_ATTRIBUTE_NV_BS_RT,
313 sizeof (EFI_DEVICE_PATH_PROTOCOL),
314 MAX_UINTN
315 },
316 InternalVarCheckDevicePath
317 },
318 {
319 EFI_CON_IN_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_CON_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_ERR_OUT_DEV_VARIABLE_NAME,
342 {
343 VAR_CHECK_VARIABLE_PROPERTY_REVISION,
344 0,
345 VARIABLE_ATTRIBUTE_BS_RT,
346 sizeof (EFI_DEVICE_PATH_PROTOCOL),
347 MAX_UINTN
348 },
349 InternalVarCheckDevicePath
350 },
351 {
352 EFI_BOOT_ORDER_VARIABLE_NAME,
353 {
354 VAR_CHECK_VARIABLE_PROPERTY_REVISION,
355 0,
356 VARIABLE_ATTRIBUTE_NV_BS_RT,
357 sizeof (UINT16),
358 MAX_UINTN
359 },
360 InternalVarCheckSizeArray
361 },
362 {
363 EFI_BOOT_NEXT_VARIABLE_NAME,
364 {
365 VAR_CHECK_VARIABLE_PROPERTY_REVISION,
366 0,
367 VARIABLE_ATTRIBUTE_NV_BS_RT,
368 sizeof (UINT16),
369 sizeof (UINT16)
370 },
371 NULL
372 },
373 {
374 EFI_BOOT_CURRENT_VARIABLE_NAME,
375 {
376 VAR_CHECK_VARIABLE_PROPERTY_REVISION,
377 0,
378 VARIABLE_ATTRIBUTE_BS_RT,
379 sizeof (UINT16),
380 sizeof (UINT16)
381 },
382 NULL
383 },
384 {
385 EFI_BOOT_OPTION_SUPPORT_VARIABLE_NAME,
386 {
387 VAR_CHECK_VARIABLE_PROPERTY_REVISION,
388 0,
389 VARIABLE_ATTRIBUTE_BS_RT,
390 sizeof (UINT32),
391 sizeof (UINT32)
392 },
393 NULL
394 },
395 {
396 EFI_DRIVER_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_SYS_PREP_ORDER_VARIABLE_NAME,
408 {
409 VAR_CHECK_VARIABLE_PROPERTY_REVISION,
410 0,
411 VARIABLE_ATTRIBUTE_NV_BS_RT,
412 sizeof (UINT16),
413 MAX_UINTN
414 },
415 InternalVarCheckSizeArray
416 },
417 {
418 EFI_HW_ERR_REC_SUPPORT_VARIABLE_NAME,
419 {
420 VAR_CHECK_VARIABLE_PROPERTY_REVISION,
421 0,
422 VARIABLE_ATTRIBUTE_NV_BS_RT,
423 sizeof (UINT16),
424 sizeof (UINT16)
425 },
426 NULL
427 },
428 {
429 EFI_SETUP_MODE_NAME,
430 {
431 VAR_CHECK_VARIABLE_PROPERTY_REVISION,
432 VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY,
433 VARIABLE_ATTRIBUTE_BS_RT,
434 sizeof (UINT8),
435 sizeof (UINT8)
436 },
437 NULL
438 },
439 {
440 EFI_KEY_EXCHANGE_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_PLATFORM_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_SIGNATURE_SUPPORT_NAME,
463 {
464 VAR_CHECK_VARIABLE_PROPERTY_REVISION,
465 VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY,
466 VARIABLE_ATTRIBUTE_BS_RT,
467 sizeof (EFI_GUID),
468 MAX_UINTN
469 },
470 InternalVarCheckSizeArray
471 },
472 {
473 EFI_SECURE_BOOT_MODE_NAME,
474 {
475 VAR_CHECK_VARIABLE_PROPERTY_REVISION,
476 VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY,
477 VARIABLE_ATTRIBUTE_BS_RT,
478 sizeof (UINT8),
479 sizeof (UINT8)
480 },
481 NULL
482 },
483 {
484 EFI_KEK_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_PK_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_DB_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_DBX_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_DBT_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_OS_INDICATIONS_SUPPORT_VARIABLE_NAME,
540 {
541 VAR_CHECK_VARIABLE_PROPERTY_REVISION,
542 0,
543 VARIABLE_ATTRIBUTE_BS_RT,
544 sizeof (UINT64),
545 sizeof (UINT64)
546 },
547 NULL
548 },
549 {
550 EFI_OS_INDICATIONS_VARIABLE_NAME,
551 {
552 VAR_CHECK_VARIABLE_PROPERTY_REVISION,
553 0,
554 VARIABLE_ATTRIBUTE_NV_BS_RT,
555 sizeof (UINT64),
556 sizeof (UINT64)
557 },
558 NULL
559 },
560 {
561 EFI_VENDOR_KEYS_VARIABLE_NAME,
562 {
563 VAR_CHECK_VARIABLE_PROPERTY_REVISION,
564 VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY,
565 VARIABLE_ATTRIBUTE_BS_RT,
566 sizeof (UINT8),
567 sizeof (UINT8)
568 },
569 NULL
570 },
571 };
572 UEFI_DEFINED_VARIABLE_ENTRY mGlobalVariableList2[] = {
573 {
574 L"Boot####",
575 {
576 VAR_CHECK_VARIABLE_PROPERTY_REVISION,
577 0,
578 VARIABLE_ATTRIBUTE_NV_BS_RT,
579 sizeof (UINT32) + sizeof (UINT16),
580 MAX_UINTN
581 },
582 InternalVarCheckLoadOption
583 },
584 {
585 L"Driver####",
586 {
587 VAR_CHECK_VARIABLE_PROPERTY_REVISION,
588 0,
589 VARIABLE_ATTRIBUTE_NV_BS_RT,
590 sizeof (UINT32) + sizeof (UINT16),
591 MAX_UINTN
592 },
593 InternalVarCheckLoadOption
594 },
595 {
596 L"SysPrep####",
597 {
598 VAR_CHECK_VARIABLE_PROPERTY_REVISION,
599 0,
600 VARIABLE_ATTRIBUTE_NV_BS_RT,
601 sizeof (UINT32) + sizeof (UINT16),
602 MAX_UINTN
603 },
604 InternalVarCheckLoadOption
605 },
606 {
607 L"Key####",
608 {
609 VAR_CHECK_VARIABLE_PROPERTY_REVISION,
610 0,
611 VARIABLE_ATTRIBUTE_NV_BS_RT,
612 sizeof (EFI_KEY_OPTION),
613 sizeof (EFI_KEY_OPTION) + 3 * sizeof (EFI_INPUT_KEY)
614 },
615 InternalVarCheckKeyOption
616 },
617 };
618
619 typedef struct {
620 EFI_GUID *Guid;
621 CHAR16 *Name;
622 VAR_CHECK_VARIABLE_PROPERTY VariableProperty;
623 } VARIABLE_DRIVER_VARIABLE_ENTRY;
624
625 VARIABLE_DRIVER_VARIABLE_ENTRY mVariableDriverVariableList[] = {
626 {
627 &gEdkiiVarErrorFlagGuid,
628 VAR_ERROR_FLAG_NAME,
629 {
630 VAR_CHECK_VARIABLE_PROPERTY_REVISION,
631 VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY,
632 VARIABLE_ATTRIBUTE_NV_BS_RT,
633 sizeof (VAR_ERROR_FLAG),
634 sizeof (VAR_ERROR_FLAG),
635 }
636 },
637 };
638
639 /**
640 Get UEFI defined global variable property.
641 The code will check if variable guid is global variable guid first.
642 If yes, further check if variable name is in mGlobalVariableList or mGlobalVariableList2.
643
644 @param[in] VariableName Pointer to variable name.
645 @param[in] VendorGuid Variable Vendor Guid.
646 @param[in] WildcardMatch Try wildcard match or not.
647 @param[out] VariableProperty Pointer to variable property.
648 @param[out] VarCheckFunction Pointer to check function.
649
650 @retval EFI_SUCCESS Variable is not global variable.
651 @retval EFI_INVALID_PARAMETER Variable is global variable, but variable name is not in the lists.
652
653 **/
654 EFI_STATUS
655 GetUefiDefinedVariableProperty (
656 IN CHAR16 *VariableName,
657 IN EFI_GUID *VendorGuid,
658 IN BOOLEAN WildcardMatch,
659 OUT VAR_CHECK_VARIABLE_PROPERTY **VariableProperty,
660 OUT INTERNAL_VAR_CHECK_FUNCTION *VarCheckFunction OPTIONAL
661 )
662 {
663 UINTN Index;
664 UINTN NameLength;
665
666 if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid)) {
667 //
668 // Try list 1, exactly match.
669 //
670 for (Index = 0; Index < sizeof (mGlobalVariableList)/sizeof (mGlobalVariableList[0]); Index++) {
671 if (StrCmp (mGlobalVariableList[Index].Name, VariableName) == 0) {
672 if (VarCheckFunction != NULL) {
673 *VarCheckFunction = mGlobalVariableList[Index].CheckFunction;
674 }
675 *VariableProperty = &mGlobalVariableList[Index].VariableProperty;
676 return EFI_SUCCESS;
677 }
678 }
679
680 //
681 // Try list 2.
682 //
683 NameLength = StrLen (VariableName) - 4;
684 for (Index = 0; Index < sizeof (mGlobalVariableList2)/sizeof (mGlobalVariableList2[0]); Index++) {
685 if (WildcardMatch) {
686 if ((StrLen (VariableName) == StrLen (mGlobalVariableList2[Index].Name)) &&
687 (StrnCmp (mGlobalVariableList2[Index].Name, VariableName, NameLength) == 0) &&
688 IsHexaDecimalDigitCharacter (VariableName[NameLength]) &&
689 IsHexaDecimalDigitCharacter (VariableName[NameLength + 1]) &&
690 IsHexaDecimalDigitCharacter (VariableName[NameLength + 2]) &&
691 IsHexaDecimalDigitCharacter (VariableName[NameLength + 3])) {
692 if (VarCheckFunction != NULL) {
693 *VarCheckFunction = mGlobalVariableList2[Index].CheckFunction;
694 }
695 *VariableProperty = &mGlobalVariableList2[Index].VariableProperty;
696 return EFI_SUCCESS;
697 }
698 }
699 if (StrCmp (mGlobalVariableList2[Index].Name, VariableName) == 0) {
700 if (VarCheckFunction != NULL) {
701 *VarCheckFunction = mGlobalVariableList2[Index].CheckFunction;
702 }
703 *VariableProperty = &mGlobalVariableList2[Index].VariableProperty;
704 return EFI_SUCCESS;
705 }
706 }
707
708 //
709 // The variable name is not in the lists.
710 //
711 return EFI_INVALID_PARAMETER;
712 }
713
714 //
715 // It is not global variable.
716 //
717 return EFI_SUCCESS;
718 }
719
720 /**
721 Get variable property for variables managed by Varaible driver.
722
723 @param[in] VariableName Pointer to variable name.
724 @param[in] VendorGuid Variable Vendor Guid.
725
726 @return Pointer to variable property.
727
728 **/
729 VAR_CHECK_VARIABLE_PROPERTY *
730 GetVariableDriverVariableProperty (
731 IN CHAR16 *VariableName,
732 IN EFI_GUID *VendorGuid
733 )
734 {
735 UINTN Index;
736
737 for (Index = 0; Index < sizeof (mVariableDriverVariableList)/sizeof (mVariableDriverVariableList[0]); Index++) {
738 if ((CompareGuid (mVariableDriverVariableList[Index].Guid, VendorGuid)) && (StrCmp (mVariableDriverVariableList[Index].Name, VariableName) == 0)) {
739 return &mVariableDriverVariableList[Index].VariableProperty;
740 }
741 }
742
743 return NULL;
744 }
745
746 /**
747 Internal SetVariable check.
748
749 @param[in] VariableName Name of Variable to set.
750 @param[in] VendorGuid Variable vendor GUID.
751 @param[in] Attributes Attribute value of the variable.
752 @param[in] DataSize Size of Data to set.
753 @param[in] Data Data pointer.
754
755 @retval EFI_SUCCESS The SetVariable check result was success.
756 @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits, name, and GUID was supplied,
757 or the DataSize exceeds the minimum or maximum allowed,
758 or the Data value is not following UEFI spec for UEFI defined variables.
759 @retval EFI_WRITE_PROTECTED The variable in question is read-only.
760 @retval Others The return status from check handler.
761
762 **/
763 EFI_STATUS
764 EFIAPI
765 InternalVarCheckSetVariableCheck (
766 IN CHAR16 *VariableName,
767 IN EFI_GUID *VendorGuid,
768 IN UINT32 Attributes,
769 IN UINTN DataSize,
770 IN VOID *Data
771 )
772 {
773 EFI_STATUS Status;
774 UINTN Index;
775 LIST_ENTRY *Link;
776 VAR_CHECK_VARIABLE_ENTRY *Entry;
777 CHAR16 *Name;
778 VAR_CHECK_VARIABLE_PROPERTY *Property;
779 INTERNAL_VAR_CHECK_FUNCTION VarCheckFunction;
780
781 if (!mEndOfDxe) {
782 //
783 // Only do check after End Of Dxe.
784 //
785 return EFI_SUCCESS;
786 }
787
788 Property = NULL;
789 VarCheckFunction = NULL;
790
791 for ( Link = GetFirstNode (&mVarCheckVariableList)
792 ; !IsNull (&mVarCheckVariableList, Link)
793 ; Link = GetNextNode (&mVarCheckVariableList, Link)
794 ) {
795 Entry = BASE_CR (Link, VAR_CHECK_VARIABLE_ENTRY, Link);
796 Name = (CHAR16 *) ((UINTN) Entry + sizeof (*Entry));
797 if (CompareGuid (&Entry->Guid, VendorGuid) && (StrCmp (Name, VariableName) == 0)) {
798 Property = &Entry->VariableProperty;
799 break;
800 }
801 }
802 if (Property == NULL) {
803 Property = GetVariableDriverVariableProperty (VariableName, VendorGuid);
804 }
805 if (Property == NULL) {
806 Status = GetUefiDefinedVariableProperty (VariableName, VendorGuid, TRUE, &Property, &VarCheckFunction);
807 if (EFI_ERROR (Status)) {
808 DEBUG ((EFI_D_INFO, "[Variable]: Var Check UEFI defined variable fail %r - %g:%s\n", Status, VendorGuid, VariableName));
809 return Status;
810 }
811 }
812 if (Property != NULL) {
813 if (mEnableLocking && ((Property->Property & VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY) != 0)) {
814 DEBUG ((EFI_D_INFO, "[Variable]: Var Check ReadOnly variable fail %r - %g:%s\n", EFI_WRITE_PROTECTED, VendorGuid, VariableName));
815 return EFI_WRITE_PROTECTED;
816 }
817 if (!((DataSize == 0) || (Attributes == 0))) {
818 //
819 // Not to delete variable.
820 //
821 if (Attributes != Property->Attributes) {
822 DEBUG ((EFI_D_INFO, "[Variable]: Var Check Attributes(0x%08x to 0x%08x) fail %r - %g:%s\n", Property->Attributes, Attributes, EFI_INVALID_PARAMETER, VendorGuid, VariableName));
823 return EFI_INVALID_PARAMETER;
824 }
825 if ((DataSize < Property->MinSize) || (DataSize > Property->MaxSize)) {
826 DEBUG ((EFI_D_INFO, "[Variable]: Var Check DataSize fail(0x%x not in 0x%x - 0x%x) %r - %g:%s\n", DataSize, Property->MinSize, Property->MaxSize, EFI_INVALID_PARAMETER, VendorGuid, VariableName));
827 return EFI_INVALID_PARAMETER;
828 }
829 if (VarCheckFunction != NULL) {
830 Status = VarCheckFunction (
831 Property,
832 DataSize,
833 Data
834 );
835 if (EFI_ERROR (Status)) {
836 DEBUG ((EFI_D_INFO, "[Variable]: Internal Var Check function fail %r - %g:%s\n", Status, VendorGuid, VariableName));
837 return Status;
838 }
839 }
840 }
841 }
842
843 for (Index = 0; Index < mNumberOfHandler; Index++) {
844 Status = mHandlerTable[Index] (
845 VariableName,
846 VendorGuid,
847 Attributes,
848 DataSize,
849 Data
850 );
851 if (EFI_ERROR (Status)) {
852 DEBUG ((EFI_D_INFO, "[Variable]: Var Check handler fail %r - %g:%s\n", Status, VendorGuid, VariableName));
853 return Status;
854 }
855 }
856 return EFI_SUCCESS;
857 }
858
859 /**
860 Reallocates more global memory to store the registered handler list.
861
862 @retval RETURN_SUCCESS Reallocate memory successfully.
863 @retval RETURN_OUT_OF_RESOURCES No enough memory to allocate.
864
865 **/
866 RETURN_STATUS
867 EFIAPI
868 ReallocateHandlerTable (
869 VOID
870 )
871 {
872 VAR_CHECK_SET_VARIABLE_CHECK_HANDLER *HandlerTable;
873
874 //
875 // Reallocate memory for check handler table.
876 //
877 HandlerTable = ReallocateRuntimePool (
878 mMaxNumberOfHandler * sizeof (VAR_CHECK_SET_VARIABLE_CHECK_HANDLER),
879 (mMaxNumberOfHandler + VAR_CHECK_HANDLER_TABLE_SIZE) * sizeof (VAR_CHECK_SET_VARIABLE_CHECK_HANDLER),
880 mHandlerTable
881 );
882
883 //
884 // No enough resource to allocate.
885 //
886 if (HandlerTable == NULL) {
887 return RETURN_OUT_OF_RESOURCES;
888 }
889
890 mHandlerTable = HandlerTable;
891 //
892 // Increase max handler number.
893 //
894 mMaxNumberOfHandler = mMaxNumberOfHandler + VAR_CHECK_HANDLER_TABLE_SIZE;
895 return RETURN_SUCCESS;
896 }
897
898 /**
899 Register SetVariable check handler.
900
901 @param[in] Handler Pointer to check handler.
902
903 @retval EFI_SUCCESS The SetVariable check handler was registered successfully.
904 @retval EFI_INVALID_PARAMETER Handler is NULL.
905 @retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has
906 already been signaled.
907 @retval EFI_OUT_OF_RESOURCES There is not enough resource for the SetVariable check handler register request.
908 @retval EFI_UNSUPPORTED This interface is not implemented.
909 For example, it is unsupported in VarCheck protocol if both VarCheck and SmmVarCheck protocols are present.
910
911 **/
912 EFI_STATUS
913 EFIAPI
914 VarCheckRegisterSetVariableCheckHandler (
915 IN VAR_CHECK_SET_VARIABLE_CHECK_HANDLER Handler
916 )
917 {
918 EFI_STATUS Status;
919
920 if (Handler == NULL) {
921 return EFI_INVALID_PARAMETER;
922 }
923
924 if (mEndOfDxe) {
925 return EFI_ACCESS_DENIED;
926 }
927
928 DEBUG ((EFI_D_INFO, "RegisterSetVariableCheckHandler - 0x%x\n", Handler));
929
930 //
931 // Check whether the handler list is enough to store new handler.
932 //
933 if (mNumberOfHandler == mMaxNumberOfHandler) {
934 //
935 // Allocate more resources for new handler.
936 //
937 Status = ReallocateHandlerTable();
938 if (EFI_ERROR (Status)) {
939 return Status;
940 }
941 }
942
943 //
944 // Register new handler into the handler list.
945 //
946 mHandlerTable[mNumberOfHandler] = Handler;
947 mNumberOfHandler++;
948
949 return EFI_SUCCESS;
950 }
951
952 /**
953 Variable property get function.
954
955 @param[in] Name Pointer to the variable name.
956 @param[in] Guid Pointer to the vendor GUID.
957 @param[in] WildcardMatch Try wildcard match or not.
958
959 @return Pointer to the property of variable specified by the Name and Guid.
960
961 **/
962 VAR_CHECK_VARIABLE_PROPERTY *
963 VariablePropertyGetFunction (
964 IN CHAR16 *Name,
965 IN EFI_GUID *Guid,
966 IN BOOLEAN WildcardMatch
967 )
968 {
969 LIST_ENTRY *Link;
970 VAR_CHECK_VARIABLE_ENTRY *Entry;
971 CHAR16 *VariableName;
972 VAR_CHECK_VARIABLE_PROPERTY *Property;
973
974 for ( Link = GetFirstNode (&mVarCheckVariableList)
975 ; !IsNull (&mVarCheckVariableList, Link)
976 ; Link = GetNextNode (&mVarCheckVariableList, Link)
977 ) {
978 Entry = BASE_CR (Link, VAR_CHECK_VARIABLE_ENTRY, Link);
979 VariableName = (CHAR16 *) ((UINTN) Entry + sizeof (*Entry));
980 if (CompareGuid (&Entry->Guid, Guid) && (StrCmp (VariableName, Name) == 0)) {
981 return &Entry->VariableProperty;
982 }
983 }
984
985 Property = GetVariableDriverVariableProperty (Name, Guid);
986 if (Property == NULL) {
987 GetUefiDefinedVariableProperty (Name, Guid, WildcardMatch, &Property, NULL);
988 }
989
990 return Property;
991 }
992
993 /**
994 Variable property set.
995
996 @param[in] Name Pointer to the variable name.
997 @param[in] Guid Pointer to the vendor GUID.
998 @param[in] VariableProperty Pointer to the input variable property.
999
1000 @retval EFI_SUCCESS The property of variable specified by the Name and Guid was set successfully.
1001 @retval EFI_INVALID_PARAMETER Name, Guid or VariableProperty is NULL, or Name is an empty string,
1002 or the fields of VariableProperty are not valid.
1003 @retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has
1004 already been signaled.
1005 @retval EFI_OUT_OF_RESOURCES There is not enough resource for the variable property set request.
1006
1007 **/
1008 EFI_STATUS
1009 EFIAPI
1010 VarCheckVariablePropertySet (
1011 IN CHAR16 *Name,
1012 IN EFI_GUID *Guid,
1013 IN VAR_CHECK_VARIABLE_PROPERTY *VariableProperty
1014 )
1015 {
1016 EFI_STATUS Status;
1017 VAR_CHECK_VARIABLE_ENTRY *Entry;
1018 CHAR16 *VariableName;
1019 VAR_CHECK_VARIABLE_PROPERTY *Property;
1020
1021 if (Name == NULL || Name[0] == 0 || Guid == NULL) {
1022 return EFI_INVALID_PARAMETER;
1023 }
1024
1025 if (VariableProperty == NULL) {
1026 return EFI_INVALID_PARAMETER;
1027 }
1028
1029 if (VariableProperty->Revision != VAR_CHECK_VARIABLE_PROPERTY_REVISION) {
1030 return EFI_INVALID_PARAMETER;
1031 }
1032
1033 if (mEndOfDxe) {
1034 return EFI_ACCESS_DENIED;
1035 }
1036
1037 Status = EFI_SUCCESS;
1038
1039 AcquireLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
1040
1041 Property = VariablePropertyGetFunction (Name, Guid, FALSE);
1042 if (Property != NULL) {
1043 CopyMem (Property, VariableProperty, sizeof (*VariableProperty));
1044 } else {
1045 Entry = AllocateRuntimeZeroPool (sizeof (*Entry) + StrSize (Name));
1046 if (Entry == NULL) {
1047 Status = EFI_OUT_OF_RESOURCES;
1048 goto Done;
1049 }
1050 VariableName = (CHAR16 *) ((UINTN) Entry + sizeof (*Entry));
1051 StrnCpy (VariableName, Name, StrLen (Name));
1052 CopyGuid (&Entry->Guid, Guid);
1053 CopyMem (&Entry->VariableProperty, VariableProperty, sizeof (*VariableProperty));
1054 InsertTailList (&mVarCheckVariableList, &Entry->Link);
1055 }
1056
1057 Done:
1058 ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
1059
1060 return Status;
1061 }
1062
1063 /**
1064 Internal variable property get.
1065
1066 @param[in] Name Pointer to the variable name.
1067 @param[in] Guid Pointer to the vendor GUID.
1068 @param[out] VariableProperty Pointer to the output variable property.
1069
1070 @retval EFI_SUCCESS The property of variable specified by the Name and Guid was got successfully.
1071 @retval EFI_NOT_FOUND The property of variable specified by the Name and Guid was not found.
1072
1073 **/
1074 EFI_STATUS
1075 EFIAPI
1076 InternalVarCheckVariablePropertyGet (
1077 IN CHAR16 *Name,
1078 IN EFI_GUID *Guid,
1079 OUT VAR_CHECK_VARIABLE_PROPERTY *VariableProperty
1080 )
1081 {
1082 LIST_ENTRY *Link;
1083 VARIABLE_ENTRY *Entry;
1084 CHAR16 *VariableName;
1085 BOOLEAN Found;
1086 VAR_CHECK_VARIABLE_PROPERTY *Property;
1087
1088 Found = FALSE;
1089
1090 Property = VariablePropertyGetFunction (Name, Guid, TRUE);
1091 if (Property != NULL) {
1092 CopyMem (VariableProperty, Property, sizeof (*VariableProperty));
1093 Found = TRUE;
1094 }
1095
1096 for ( Link = GetFirstNode (&mLockedVariableList)
1097 ; !IsNull (&mLockedVariableList, Link)
1098 ; Link = GetNextNode (&mLockedVariableList, Link)
1099 ) {
1100 Entry = BASE_CR (Link, VARIABLE_ENTRY, Link);
1101 VariableName = (CHAR16 *) ((UINTN) Entry + sizeof (*Entry));
1102 if (CompareGuid (&Entry->Guid, Guid) && (StrCmp (VariableName, Name) == 0)) {
1103 VariableProperty->Property |= VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY;
1104 if (!Found) {
1105 VariableProperty->Revision = VAR_CHECK_VARIABLE_PROPERTY_REVISION;
1106 Found = TRUE;
1107 }
1108 }
1109 }
1110
1111 return (Found ? EFI_SUCCESS : EFI_NOT_FOUND);
1112 }
1113
1114 /**
1115 Variable property get.
1116
1117 @param[in] Name Pointer to the variable name.
1118 @param[in] Guid Pointer to the vendor GUID.
1119 @param[out] VariableProperty Pointer to the output variable property.
1120
1121 @retval EFI_SUCCESS The property of variable specified by the Name and Guid was got successfully.
1122 @retval EFI_INVALID_PARAMETER Name, Guid or VariableProperty is NULL, or Name is an empty string.
1123 @retval EFI_NOT_FOUND The property of variable specified by the Name and Guid was not found.
1124
1125 **/
1126 EFI_STATUS
1127 EFIAPI
1128 VarCheckVariablePropertyGet (
1129 IN CHAR16 *Name,
1130 IN EFI_GUID *Guid,
1131 OUT VAR_CHECK_VARIABLE_PROPERTY *VariableProperty
1132 )
1133 {
1134 EFI_STATUS Status;
1135
1136 if (Name == NULL || Name[0] == 0 || Guid == NULL) {
1137 return EFI_INVALID_PARAMETER;
1138 }
1139
1140 if (VariableProperty == NULL) {
1141 return EFI_INVALID_PARAMETER;
1142 }
1143
1144 AcquireLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
1145
1146 Status = InternalVarCheckVariablePropertyGet (Name, Guid, VariableProperty);
1147
1148 ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
1149
1150 return Status;
1151 }
1152