1 /** @file 2 Implementation functions and structures for var check services. 3 4 Copyright (c) 2015 - 2016, 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 an upper case hexadecimal character. 100 101 This function checks if a Unicode character is an upper case 102 hexadecimal character. The valid upper case hexadecimal character is 103 L'0' to L'9', 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 an upper case hexadecmial character. 109 @retval FALSE If the Char is not an upper case hexadecmial character. 110 111 **/ 112 BOOLEAN 113 EFIAPI 114 VarCheckInternalIsHexaDecimalDigitCharacter ( 115 IN CHAR16 Char 116 ) 117 { 118 return (BOOLEAN) ((Char >= L'0' && Char <= L'9') || (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 * 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 * 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 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 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 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 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 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 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 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 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