1 /** @file
2 Implementation functions and structures for var check services.
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 <Library/VarCheckLib.h>
16 #include <Library/BaseLib.h>
17 #include <Library/BaseMemoryLib.h>
18 #include <Library/DebugLib.h>
19 #include <Library/MemoryAllocationLib.h>
20
21 #include <Guid/GlobalVariable.h>
22 #include <Guid/HardwareErrorVariable.h>
23
24 BOOLEAN mVarCheckLibEndOfDxe = FALSE;
25
26 #define VAR_CHECK_TABLE_SIZE 0x8
27
28 UINTN mVarCheckLibEndOfDxeCallbackCount = 0;
29 UINTN mVarCheckLibEndOfDxeCallbackMaxCount = 0;
30 VAR_CHECK_END_OF_DXE_CALLBACK *mVarCheckLibEndOfDxeCallback = NULL;
31
32 UINTN mVarCheckLibAddressPointerCount = 0;
33 UINTN mVarCheckLibAddressPointerMaxCount = 0;
34 VOID ***mVarCheckLibAddressPointer = NULL;
35
36 UINTN mNumberOfVarCheckHandler = 0;
37 UINTN mMaxNumberOfVarCheckHandler = 0;
38 VAR_CHECK_SET_VARIABLE_CHECK_HANDLER *mVarCheckHandlerTable = NULL;
39
40 typedef struct {
41 EFI_GUID Guid;
42 VAR_CHECK_VARIABLE_PROPERTY VariableProperty;
43 //CHAR16 *Name;
44 } VAR_CHECK_VARIABLE_ENTRY;
45
46 UINTN mNumberOfVarCheckVariable = 0;
47 UINTN mMaxNumberOfVarCheckVariable = 0;
48 VARIABLE_ENTRY_PROPERTY **mVarCheckVariableTable = NULL;
49
50 //
51 // Handle variables with wildcard name specially.
52 //
53 VARIABLE_ENTRY_PROPERTY mVarCheckVariableWithWildcardName[] = {
54 {
55 &gEfiGlobalVariableGuid,
56 L"Boot####",
57 {
58 0
59 },
60 },
61 {
62 &gEfiGlobalVariableGuid,
63 L"Driver####",
64 {
65 0
66 },
67 },
68 {
69 &gEfiGlobalVariableGuid,
70 L"SysPrep####",
71 {
72 0
73 },
74 },
75 {
76 &gEfiGlobalVariableGuid,
77 L"Key####",
78 {
79 0
80 },
81 },
82 {
83 &gEfiGlobalVariableGuid,
84 L"PlatformRecovery####",
85 {
86 0
87 },
88 },
89 {
90 &gEfiHardwareErrorVariableGuid,
91 L"HwErrRec####",
92 {
93 0
94 },
95 },
96 };
97
98 /**
99 Check if a Unicode character is a hexadecimal character.
100
101 This function checks if a Unicode character is a
102 hexadecimal character. The valid hexadecimal character is
103 L'0' to L'9', L'a' to L'f', or L'A' to L'F'.
104
105
106 @param[in] Char The character to check against.
107
108 @retval TRUE If the Char is a hexadecmial character.
109 @retval FALSE If the Char is not a hexadecmial character.
110
111 **/
112 BOOLEAN
113 EFIAPI
VarCheckInternalIsHexaDecimalDigitCharacter(IN CHAR16 Char)114 VarCheckInternalIsHexaDecimalDigitCharacter (
115 IN CHAR16 Char
116 )
117 {
118 return (BOOLEAN) ((Char >= L'0' && Char <= L'9') || (Char >= L'A' && Char <= L'F') || (Char >= L'a' && Char <= L'f'));
119 }
120
121 /**
122 Variable property get with wildcard name.
123
124 @param[in] VariableName Pointer to variable name.
125 @param[in] VendorGuid Pointer to variable vendor GUID.
126 @param[in] WildcardMatch Try wildcard match or not.
127
128 @return Pointer to variable property.
129
130 **/
131 VAR_CHECK_VARIABLE_PROPERTY *
VariablePropertyGetWithWildcardName(IN CHAR16 * VariableName,IN EFI_GUID * VendorGuid,IN BOOLEAN WildcardMatch)132 VariablePropertyGetWithWildcardName (
133 IN CHAR16 *VariableName,
134 IN EFI_GUID *VendorGuid,
135 IN BOOLEAN WildcardMatch
136 )
137 {
138 UINTN Index;
139 UINTN NameLength;
140
141 NameLength = StrLen (VariableName) - 4;
142 for (Index = 0; Index < sizeof (mVarCheckVariableWithWildcardName)/sizeof (mVarCheckVariableWithWildcardName[0]); Index++) {
143 if (CompareGuid (mVarCheckVariableWithWildcardName[Index].Guid, VendorGuid)){
144 if (WildcardMatch) {
145 if ((StrLen (VariableName) == StrLen (mVarCheckVariableWithWildcardName[Index].Name)) &&
146 (StrnCmp (VariableName, mVarCheckVariableWithWildcardName[Index].Name, NameLength) == 0) &&
147 VarCheckInternalIsHexaDecimalDigitCharacter (VariableName[NameLength]) &&
148 VarCheckInternalIsHexaDecimalDigitCharacter (VariableName[NameLength + 1]) &&
149 VarCheckInternalIsHexaDecimalDigitCharacter (VariableName[NameLength + 2]) &&
150 VarCheckInternalIsHexaDecimalDigitCharacter (VariableName[NameLength + 3])) {
151 return &mVarCheckVariableWithWildcardName[Index].VariableProperty;
152 }
153 }
154 if (StrCmp (mVarCheckVariableWithWildcardName[Index].Name, VariableName) == 0) {
155 return &mVarCheckVariableWithWildcardName[Index].VariableProperty;
156 }
157 }
158 }
159
160 return NULL;
161 }
162
163 /**
164 Variable property get function.
165
166 @param[in] Name Pointer to the variable name.
167 @param[in] Guid Pointer to the vendor GUID.
168 @param[in] WildcardMatch Try wildcard match or not.
169
170 @return Pointer to the property of variable specified by the Name and Guid.
171
172 **/
173 VAR_CHECK_VARIABLE_PROPERTY *
VariablePropertyGetFunction(IN CHAR16 * Name,IN EFI_GUID * Guid,IN BOOLEAN WildcardMatch)174 VariablePropertyGetFunction (
175 IN CHAR16 *Name,
176 IN EFI_GUID *Guid,
177 IN BOOLEAN WildcardMatch
178 )
179 {
180 UINTN Index;
181 VAR_CHECK_VARIABLE_ENTRY *Entry;
182 CHAR16 *VariableName;
183
184 for (Index = 0; Index < mNumberOfVarCheckVariable; Index++) {
185 Entry = (VAR_CHECK_VARIABLE_ENTRY *) mVarCheckVariableTable[Index];
186 VariableName = (CHAR16 *) ((UINTN) Entry + sizeof (*Entry));
187 if (CompareGuid (&Entry->Guid, Guid) && (StrCmp (VariableName, Name) == 0)) {
188 return &Entry->VariableProperty;
189 }
190 }
191
192 return VariablePropertyGetWithWildcardName (Name, Guid, WildcardMatch);
193 }
194
195 /**
196 Var check add table entry.
197
198 @param[in, out] Table Pointer to table buffer.
199 @param[in, out] MaxNumber Pointer to maximum number of entry in the table.
200 @param[in, out] CurrentNumber Pointer to current number of entry in the table.
201 @param[in] Entry Entry will be added to the table.
202
203 @retval EFI_SUCCESS Reallocate memory successfully.
204 @retval EFI_OUT_OF_RESOURCES No enough memory to allocate.
205
206 **/
207 EFI_STATUS
VarCheckAddTableEntry(IN OUT UINTN ** Table,IN OUT UINTN * MaxNumber,IN OUT UINTN * CurrentNumber,IN UINTN Entry)208 VarCheckAddTableEntry (
209 IN OUT UINTN **Table,
210 IN OUT UINTN *MaxNumber,
211 IN OUT UINTN *CurrentNumber,
212 IN UINTN Entry
213 )
214 {
215 UINTN *TempTable;
216
217 //
218 // Check whether the table is enough to store new entry.
219 //
220 if (*CurrentNumber == *MaxNumber) {
221 //
222 // Reallocate memory for the table.
223 //
224 TempTable = ReallocateRuntimePool (
225 *MaxNumber * sizeof (UINTN),
226 (*MaxNumber + VAR_CHECK_TABLE_SIZE) * sizeof (UINTN),
227 *Table
228 );
229
230 //
231 // No enough resource to allocate.
232 //
233 if (TempTable == NULL) {
234 return EFI_OUT_OF_RESOURCES;
235 }
236
237 *Table = TempTable;
238 //
239 // Increase max number.
240 //
241 *MaxNumber += VAR_CHECK_TABLE_SIZE;
242 }
243
244 //
245 // Add entry to the table.
246 //
247 (*Table)[*CurrentNumber] = Entry;
248 (*CurrentNumber)++;
249
250 return EFI_SUCCESS;
251 }
252
253 /**
254 Register END_OF_DXE callback.
255 The callback will be invoked by VarCheckLibInitializeAtEndOfDxe().
256
257 @param[in] Callback END_OF_DXE callback.
258
259 @retval EFI_SUCCESS The callback was registered successfully.
260 @retval EFI_INVALID_PARAMETER Callback is NULL.
261 @retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has
262 already been signaled.
263 @retval EFI_OUT_OF_RESOURCES There is not enough resource for the callback register request.
264
265 **/
266 EFI_STATUS
267 EFIAPI
VarCheckLibRegisterEndOfDxeCallback(IN VAR_CHECK_END_OF_DXE_CALLBACK Callback)268 VarCheckLibRegisterEndOfDxeCallback (
269 IN VAR_CHECK_END_OF_DXE_CALLBACK Callback
270 )
271 {
272 EFI_STATUS Status;
273
274 if (Callback == NULL) {
275 return EFI_INVALID_PARAMETER;
276 }
277
278 if (mVarCheckLibEndOfDxe) {
279 return EFI_ACCESS_DENIED;
280 }
281
282 Status = VarCheckAddTableEntry (
283 (UINTN **) &mVarCheckLibEndOfDxeCallback,
284 &mVarCheckLibEndOfDxeCallbackMaxCount,
285 &mVarCheckLibEndOfDxeCallbackCount,
286 (UINTN) Callback
287 );
288
289 DEBUG ((EFI_D_INFO, "VarCheckLibRegisterEndOfDxeCallback - 0x%x %r\n", Callback, Status));
290
291 return Status;
292 }
293
294 /**
295 Var check initialize at END_OF_DXE.
296
297 This function needs to be called at END_OF_DXE.
298 Address pointers may be returned,
299 and caller needs to ConvertPointer() for the pointers.
300
301 @param[in, out] AddressPointerCount Output pointer to address pointer count.
302
303 @return Address pointer buffer, NULL if input AddressPointerCount is NULL.
304
305 **/
306 VOID ***
307 EFIAPI
VarCheckLibInitializeAtEndOfDxe(IN OUT UINTN * AddressPointerCount OPTIONAL)308 VarCheckLibInitializeAtEndOfDxe (
309 IN OUT UINTN *AddressPointerCount OPTIONAL
310 )
311 {
312 VOID *TempTable;
313 UINTN TotalCount;
314 UINTN Index;
315
316 for (Index = 0; Index < mVarCheckLibEndOfDxeCallbackCount; Index++) {
317 //
318 // Invoke the callback registered by VarCheckLibRegisterEndOfDxeCallback().
319 //
320 mVarCheckLibEndOfDxeCallback[Index] ();
321 }
322 if (mVarCheckLibEndOfDxeCallback != NULL) {
323 //
324 // Free the callback buffer.
325 //
326 mVarCheckLibEndOfDxeCallbackCount = 0;
327 mVarCheckLibEndOfDxeCallbackMaxCount = 0;
328 FreePool ((VOID *) mVarCheckLibEndOfDxeCallback);
329 mVarCheckLibEndOfDxeCallback = NULL;
330 }
331
332 mVarCheckLibEndOfDxe = TRUE;
333
334 if (AddressPointerCount == NULL) {
335 if (mVarCheckLibAddressPointer != NULL) {
336 //
337 // Free the address pointer buffer.
338 //
339 mVarCheckLibAddressPointerCount = 0;
340 mVarCheckLibAddressPointerMaxCount = 0;
341 FreePool ((VOID *) mVarCheckLibAddressPointer);
342 mVarCheckLibAddressPointer = NULL;
343 }
344 return NULL;
345 }
346
347 //
348 // Get the total count needed.
349 // Also cover VarCheckHandler and the entries, and VarCheckVariable and the entries.
350 //
351 TotalCount = mVarCheckLibAddressPointerCount + (mNumberOfVarCheckHandler + 1) + (mNumberOfVarCheckVariable + 1);
352 TempTable = ReallocateRuntimePool (
353 mVarCheckLibAddressPointerMaxCount * sizeof (VOID **),
354 TotalCount * sizeof (VOID **),
355 (VOID *) mVarCheckLibAddressPointer
356 );
357
358 if (TempTable != NULL) {
359 mVarCheckLibAddressPointer = (VOID ***) TempTable;
360
361 //
362 // Cover VarCheckHandler and the entries.
363 //
364 mVarCheckLibAddressPointer[mVarCheckLibAddressPointerCount++] = (VOID **) &mVarCheckHandlerTable;
365 for (Index = 0; Index < mNumberOfVarCheckHandler; Index++) {
366 mVarCheckLibAddressPointer[mVarCheckLibAddressPointerCount++] = (VOID **) &mVarCheckHandlerTable[Index];
367 }
368
369 //
370 // Cover VarCheckVariable and the entries.
371 //
372 mVarCheckLibAddressPointer[mVarCheckLibAddressPointerCount++] = (VOID **) &mVarCheckVariableTable;
373 for (Index = 0; Index < mNumberOfVarCheckVariable; Index++) {
374 mVarCheckLibAddressPointer[mVarCheckLibAddressPointerCount++] = (VOID **) &mVarCheckVariableTable[Index];
375 }
376
377 ASSERT (mVarCheckLibAddressPointerCount == TotalCount);
378 mVarCheckLibAddressPointerMaxCount = mVarCheckLibAddressPointerCount;
379 }
380
381 *AddressPointerCount = mVarCheckLibAddressPointerCount;
382 return mVarCheckLibAddressPointer;
383 }
384
385 /**
386 Register address pointer.
387 The AddressPointer may be returned by VarCheckLibInitializeAtEndOfDxe().
388
389 @param[in] AddressPointer Address pointer.
390
391 @retval EFI_SUCCESS The address pointer was registered successfully.
392 @retval EFI_INVALID_PARAMETER AddressPointer is NULL.
393 @retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has
394 already been signaled.
395 @retval EFI_OUT_OF_RESOURCES There is not enough resource for the address pointer register request.
396
397 **/
398 EFI_STATUS
399 EFIAPI
VarCheckLibRegisterAddressPointer(IN VOID ** AddressPointer)400 VarCheckLibRegisterAddressPointer (
401 IN VOID **AddressPointer
402 )
403 {
404 EFI_STATUS Status;
405
406 if (AddressPointer == NULL) {
407 return EFI_INVALID_PARAMETER;
408 }
409
410 if (mVarCheckLibEndOfDxe) {
411 return EFI_ACCESS_DENIED;
412 }
413
414 Status = VarCheckAddTableEntry(
415 (UINTN **) &mVarCheckLibAddressPointer,
416 &mVarCheckLibAddressPointerMaxCount,
417 &mVarCheckLibAddressPointerCount,
418 (UINTN) AddressPointer
419 );
420
421 DEBUG ((EFI_D_INFO, "VarCheckLibRegisterAddressPointer - 0x%x %r\n", AddressPointer, Status));
422
423 return Status;
424 }
425
426 /**
427 Register SetVariable check handler.
428
429 @param[in] Handler Pointer to check handler.
430
431 @retval EFI_SUCCESS The SetVariable check handler was registered successfully.
432 @retval EFI_INVALID_PARAMETER Handler is NULL.
433 @retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has
434 already been signaled.
435 @retval EFI_OUT_OF_RESOURCES There is not enough resource for the SetVariable check handler register request.
436 @retval EFI_UNSUPPORTED This interface is not implemented.
437 For example, it is unsupported in VarCheck protocol if both VarCheck and SmmVarCheck protocols are present.
438
439 **/
440 EFI_STATUS
441 EFIAPI
VarCheckLibRegisterSetVariableCheckHandler(IN VAR_CHECK_SET_VARIABLE_CHECK_HANDLER Handler)442 VarCheckLibRegisterSetVariableCheckHandler (
443 IN VAR_CHECK_SET_VARIABLE_CHECK_HANDLER Handler
444 )
445 {
446 EFI_STATUS Status;
447
448 if (Handler == NULL) {
449 return EFI_INVALID_PARAMETER;
450 }
451
452 if (mVarCheckLibEndOfDxe) {
453 return EFI_ACCESS_DENIED;
454 }
455
456 Status = VarCheckAddTableEntry(
457 (UINTN **) &mVarCheckHandlerTable,
458 &mMaxNumberOfVarCheckHandler,
459 &mNumberOfVarCheckHandler,
460 (UINTN) Handler
461 );
462
463 DEBUG ((EFI_D_INFO, "VarCheckLibRegisterSetVariableCheckHandler - 0x%x %r\n", Handler, Status));
464
465 return Status;
466 }
467
468 /**
469 Variable property set.
470
471 @param[in] Name Pointer to the variable name.
472 @param[in] Guid Pointer to the vendor GUID.
473 @param[in] VariableProperty Pointer to the input variable property.
474
475 @retval EFI_SUCCESS The property of variable specified by the Name and Guid was set successfully.
476 @retval EFI_INVALID_PARAMETER Name, Guid or VariableProperty is NULL, or Name is an empty string,
477 or the fields of VariableProperty are not valid.
478 @retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has
479 already been signaled.
480 @retval EFI_OUT_OF_RESOURCES There is not enough resource for the variable property set request.
481
482 **/
483 EFI_STATUS
484 EFIAPI
VarCheckLibVariablePropertySet(IN CHAR16 * Name,IN EFI_GUID * Guid,IN VAR_CHECK_VARIABLE_PROPERTY * VariableProperty)485 VarCheckLibVariablePropertySet (
486 IN CHAR16 *Name,
487 IN EFI_GUID *Guid,
488 IN VAR_CHECK_VARIABLE_PROPERTY *VariableProperty
489 )
490 {
491 EFI_STATUS Status;
492 VAR_CHECK_VARIABLE_ENTRY *Entry;
493 CHAR16 *VariableName;
494 VAR_CHECK_VARIABLE_PROPERTY *Property;
495
496 if (Name == NULL || Name[0] == 0 || Guid == NULL) {
497 return EFI_INVALID_PARAMETER;
498 }
499
500 if (VariableProperty == NULL) {
501 return EFI_INVALID_PARAMETER;
502 }
503
504 if (VariableProperty->Revision != VAR_CHECK_VARIABLE_PROPERTY_REVISION) {
505 return EFI_INVALID_PARAMETER;
506 }
507
508 if (mVarCheckLibEndOfDxe) {
509 return EFI_ACCESS_DENIED;
510 }
511
512 Status = EFI_SUCCESS;
513
514 //
515 // Get the pointer of property data for set.
516 //
517 Property = VariablePropertyGetFunction (Name, Guid, FALSE);
518 if (Property != NULL) {
519 CopyMem (Property, VariableProperty, sizeof (*VariableProperty));
520 } else {
521 Entry = AllocateRuntimeZeroPool (sizeof (*Entry) + StrSize (Name));
522 if (Entry == NULL) {
523 return EFI_OUT_OF_RESOURCES;
524 }
525 VariableName = (CHAR16 *) ((UINTN) Entry + sizeof (*Entry));
526 StrCpyS (VariableName, StrSize (Name)/sizeof (CHAR16), Name);
527 CopyGuid (&Entry->Guid, Guid);
528 CopyMem (&Entry->VariableProperty, VariableProperty, sizeof (*VariableProperty));
529
530 Status = VarCheckAddTableEntry(
531 (UINTN **) &mVarCheckVariableTable,
532 &mMaxNumberOfVarCheckVariable,
533 &mNumberOfVarCheckVariable,
534 (UINTN) Entry
535 );
536
537 if (EFI_ERROR (Status)) {
538 FreePool (Entry);
539 }
540 }
541
542 return Status;
543 }
544
545 /**
546 Variable property get.
547
548 @param[in] Name Pointer to the variable name.
549 @param[in] Guid Pointer to the vendor GUID.
550 @param[out] VariableProperty Pointer to the output variable property.
551
552 @retval EFI_SUCCESS The property of variable specified by the Name and Guid was got successfully.
553 @retval EFI_INVALID_PARAMETER Name, Guid or VariableProperty is NULL, or Name is an empty string.
554 @retval EFI_NOT_FOUND The property of variable specified by the Name and Guid was not found.
555
556 **/
557 EFI_STATUS
558 EFIAPI
VarCheckLibVariablePropertyGet(IN CHAR16 * Name,IN EFI_GUID * Guid,OUT VAR_CHECK_VARIABLE_PROPERTY * VariableProperty)559 VarCheckLibVariablePropertyGet (
560 IN CHAR16 *Name,
561 IN EFI_GUID *Guid,
562 OUT VAR_CHECK_VARIABLE_PROPERTY *VariableProperty
563 )
564 {
565 VAR_CHECK_VARIABLE_PROPERTY *Property;
566
567 if (Name == NULL || Name[0] == 0 || Guid == NULL) {
568 return EFI_INVALID_PARAMETER;
569 }
570
571 if (VariableProperty == NULL) {
572 return EFI_INVALID_PARAMETER;
573 }
574
575 Property = VariablePropertyGetFunction (Name, Guid, TRUE);
576 //
577 // Also check the property revision before using the property data.
578 // There is no property set to this variable(wildcard name)
579 // if the revision is not VAR_CHECK_VARIABLE_PROPERTY_REVISION.
580 //
581 if ((Property != NULL) && (Property->Revision == VAR_CHECK_VARIABLE_PROPERTY_REVISION)) {
582 CopyMem (VariableProperty, Property, sizeof (*VariableProperty));
583 return EFI_SUCCESS;
584 }
585
586 return EFI_NOT_FOUND;
587 }
588
589 /**
590 SetVariable check.
591
592 @param[in] VariableName Name of Variable to set.
593 @param[in] VendorGuid Variable vendor GUID.
594 @param[in] Attributes Attribute value of the variable.
595 @param[in] DataSize Size of Data to set.
596 @param[in] Data Data pointer.
597 @param[in] RequestSource Request source.
598
599 @retval EFI_SUCCESS The SetVariable check result was success.
600 @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits, name, GUID,
601 DataSize and Data value was supplied.
602 @retval EFI_WRITE_PROTECTED The variable in question is read-only.
603 @retval Others The other return status from check handler.
604
605 **/
606 EFI_STATUS
607 EFIAPI
VarCheckLibSetVariableCheck(IN CHAR16 * VariableName,IN EFI_GUID * VendorGuid,IN UINT32 Attributes,IN UINTN DataSize,IN VOID * Data,IN VAR_CHECK_REQUEST_SOURCE RequestSource)608 VarCheckLibSetVariableCheck (
609 IN CHAR16 *VariableName,
610 IN EFI_GUID *VendorGuid,
611 IN UINT32 Attributes,
612 IN UINTN DataSize,
613 IN VOID *Data,
614 IN VAR_CHECK_REQUEST_SOURCE RequestSource
615 )
616 {
617 EFI_STATUS Status;
618 UINTN Index;
619 VAR_CHECK_VARIABLE_PROPERTY *Property;
620
621 if (!mVarCheckLibEndOfDxe) {
622 //
623 // Only do check after End Of Dxe.
624 //
625 return EFI_SUCCESS;
626 }
627
628 Property = VariablePropertyGetFunction (VariableName, VendorGuid, TRUE);
629 //
630 // Also check the property revision before using the property data.
631 // There is no property set to this variable(wildcard name)
632 // if the revision is not VAR_CHECK_VARIABLE_PROPERTY_REVISION.
633 //
634 if ((Property != NULL) && (Property->Revision == VAR_CHECK_VARIABLE_PROPERTY_REVISION)) {
635 if ((RequestSource != VarCheckFromTrusted) && ((Property->Property & VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY) != 0)) {
636 DEBUG ((EFI_D_INFO, "Variable Check ReadOnly variable fail %r - %g:%s\n", EFI_WRITE_PROTECTED, VendorGuid, VariableName));
637 return EFI_WRITE_PROTECTED;
638 }
639 if (!((((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0) && (DataSize == 0)) || (Attributes == 0))) {
640 //
641 // Not to delete variable.
642 //
643 if ((Property->Attributes != 0) && ((Attributes & (~EFI_VARIABLE_APPEND_WRITE)) != Property->Attributes)) {
644 DEBUG ((EFI_D_INFO, "Variable Check Attributes(0x%08x to 0x%08x) fail %r - %g:%s\n", Property->Attributes, Attributes, EFI_INVALID_PARAMETER, VendorGuid, VariableName));
645 return EFI_INVALID_PARAMETER;
646 }
647 if (DataSize != 0) {
648 if ((DataSize < Property->MinSize) || (DataSize > Property->MaxSize)) {
649 DEBUG ((EFI_D_INFO, "Variable 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));
650 return EFI_INVALID_PARAMETER;
651 }
652 }
653 }
654 }
655
656 for (Index = 0; Index < mNumberOfVarCheckHandler; Index++) {
657 Status = mVarCheckHandlerTable[Index] (
658 VariableName,
659 VendorGuid,
660 Attributes,
661 DataSize,
662 Data
663 );
664 if (EFI_ERROR (Status)) {
665 DEBUG ((EFI_D_INFO, "Variable Check handler fail %r - %g:%s\n", Status, VendorGuid, VariableName));
666 return Status;
667 }
668 }
669 return EFI_SUCCESS;
670 }
671