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