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