1/** @file 2 Implementation functions and structures for var check services. 3 4Copyright (c) 2015, Intel Corporation. All rights reserved.<BR> 5This program and the accompanying materials 6are licensed and made available under the terms and conditions of the BSD License 7which accompanies this distribution. The full text of the license may be found at 8http://opensource.org/licenses/bsd-license.php 9 10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11WITHOUT 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 24BOOLEAN mVarCheckLibEndOfDxe = FALSE; 25 26#define VAR_CHECK_TABLE_SIZE 0x8 27 28UINTN mVarCheckLibEndOfDxeCallbackCount = 0; 29UINTN mVarCheckLibEndOfDxeCallbackMaxCount = 0; 30VAR_CHECK_END_OF_DXE_CALLBACK *mVarCheckLibEndOfDxeCallback = NULL; 31 32UINTN mVarCheckLibAddressPointerCount = 0; 33UINTN mVarCheckLibAddressPointerMaxCount = 0; 34VOID ***mVarCheckLibAddressPointer = NULL; 35 36UINTN mNumberOfVarCheckHandler = 0; 37UINTN mMaxNumberOfVarCheckHandler = 0; 38VAR_CHECK_SET_VARIABLE_CHECK_HANDLER *mVarCheckHandlerTable = NULL; 39 40typedef struct { 41 EFI_GUID Guid; 42 VAR_CHECK_VARIABLE_PROPERTY VariableProperty; 43 //CHAR16 *Name; 44} VAR_CHECK_VARIABLE_ENTRY; 45 46UINTN mNumberOfVarCheckVariable = 0; 47UINTN mMaxNumberOfVarCheckVariable = 0; 48VARIABLE_ENTRY_PROPERTY **mVarCheckVariableTable = NULL; 49 50// 51// Handle variables with wildcard name specially. 52// 53VARIABLE_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**/ 112BOOLEAN 113EFIAPI 114VarCheckInternalIsHexaDecimalDigitCharacter ( 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**/ 131VAR_CHECK_VARIABLE_PROPERTY * 132VariablePropertyGetWithWildcardName ( 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**/ 173VAR_CHECK_VARIABLE_PROPERTY * 174VariablePropertyGetFunction ( 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**/ 207EFI_STATUS 208VarCheckAddTableEntry ( 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**/ 266EFI_STATUS 267EFIAPI 268VarCheckLibRegisterEndOfDxeCallback ( 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**/ 306VOID *** 307EFIAPI 308VarCheckLibInitializeAtEndOfDxe ( 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**/ 398EFI_STATUS 399EFIAPI 400VarCheckLibRegisterAddressPointer ( 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**/ 440EFI_STATUS 441EFIAPI 442VarCheckLibRegisterSetVariableCheckHandler ( 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**/ 483EFI_STATUS 484EFIAPI 485VarCheckLibVariablePropertySet ( 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**/ 557EFI_STATUS 558EFIAPI 559VarCheckLibVariablePropertyGet ( 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**/ 606EFI_STATUS 607EFIAPI 608VarCheckLibSetVariableCheck ( 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