1 /** @file 2 Serialize Variables Library implementation 3 4 Copyright (c) 2004 - 2011, 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 "SerializeVariablesLib.h" 16 17 /** 18 Serialization format: 19 20 The SerializeVariablesLib interface does not specify a format 21 for the serialization of the variable data. This library uses 22 a packed array of a non-uniformly sized data structure elements. 23 24 Each variable is stored (packed) as: 25 UINT32 VendorNameSize; // Name size in bytes 26 CHAR16 VendorName[?]; // The variable unicode name including the 27 // null terminating character. 28 EFI_GUID VendorGuid; // The variable GUID 29 UINT32 DataSize; // The size of variable data in bytes 30 UINT8 Data[?]; // The variable data 31 32 **/ 33 34 35 /** 36 Unpacks the next variable from the buffer 37 38 @param[in] Buffer - Buffer pointing to the next variable instance 39 On subsequent calls, the pointer should be incremented 40 by the returned SizeUsed value. 41 @param[in] MaxSize - Max allowable size for the variable data 42 On subsequent calls, this should be decremented 43 by the returned SizeUsed value. 44 @param[out] Name - Variable name string (address in Buffer) 45 @param[out] NameSize - Size of Name in bytes 46 @param[out] Guid - GUID of variable (address in Buffer) 47 @param[out] Attributes - Attributes of variable 48 @param[out] Data - Buffer containing Data for variable (address in Buffer) 49 @param[out] DataSize - Size of Data in bytes 50 @param[out] SizeUsed - Total size used for this variable instance in Buffer 51 52 @return EFI_STATUS based on the success or failure of the operation 53 54 **/ 55 STATIC 56 EFI_STATUS 57 UnpackVariableFromBuffer ( 58 IN VOID *Buffer, 59 IN UINTN MaxSize, 60 OUT CHAR16 **Name, 61 OUT UINT32 *NameSize, 62 OUT EFI_GUID **Guid, 63 OUT UINT32 *Attributes, 64 OUT UINT32 *DataSize, 65 OUT VOID **Data, 66 OUT UINTN *SizeUsed 67 ) 68 { 69 UINT8 *BytePtr; 70 UINTN Offset; 71 72 BytePtr = (UINT8*)Buffer; 73 Offset = 0; 74 75 *NameSize = *(UINT32*) (BytePtr + Offset); 76 Offset = Offset + sizeof (UINT32); 77 78 if (Offset > MaxSize) { 79 return EFI_INVALID_PARAMETER; 80 } 81 82 *Name = (CHAR16*) (BytePtr + Offset); 83 Offset = Offset + *(UINT32*)BytePtr; 84 if (Offset > MaxSize) { 85 return EFI_INVALID_PARAMETER; 86 } 87 88 *Guid = (EFI_GUID*) (BytePtr + Offset); 89 Offset = Offset + sizeof (EFI_GUID); 90 if (Offset > MaxSize) { 91 return EFI_INVALID_PARAMETER; 92 } 93 94 *Attributes = *(UINT32*) (BytePtr + Offset); 95 Offset = Offset + sizeof (UINT32); 96 if (Offset > MaxSize) { 97 return EFI_INVALID_PARAMETER; 98 } 99 100 *DataSize = *(UINT32*) (BytePtr + Offset); 101 Offset = Offset + sizeof (UINT32); 102 if (Offset > MaxSize) { 103 return EFI_INVALID_PARAMETER; 104 } 105 106 *Data = (VOID*) (BytePtr + Offset); 107 Offset = Offset + *DataSize; 108 if (Offset > MaxSize) { 109 return EFI_INVALID_PARAMETER; 110 } 111 112 *SizeUsed = Offset; 113 114 return EFI_SUCCESS; 115 } 116 117 118 /** 119 Iterates through the variables in the buffer, and calls a callback 120 function for each variable found. 121 122 @param[in] CallbackFunction - Function called for each variable instance 123 @param[in] Context - Passed to each call of CallbackFunction 124 @param[in] Buffer - Buffer containing serialized variables 125 @param[in] MaxSize - Size of Buffer in bytes 126 127 @return EFI_STATUS based on the success or failure of the operation 128 129 **/ 130 STATIC 131 EFI_STATUS 132 IterateVariablesInBuffer ( 133 IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK CallbackFunction, 134 IN VOID *CallbackContext, 135 IN VOID *Buffer, 136 IN UINTN MaxSize 137 ) 138 { 139 RETURN_STATUS Status; 140 UINTN TotalSizeUsed; 141 UINTN SizeUsed; 142 143 CHAR16 *Name; 144 UINT32 NameSize; 145 CHAR16 *AlignedName; 146 UINT32 AlignedNameMaxSize; 147 EFI_GUID *Guid; 148 UINT32 Attributes; 149 UINT32 DataSize; 150 VOID *Data; 151 152 SizeUsed = 0; 153 AlignedName = NULL; 154 AlignedNameMaxSize = 0; 155 Name = NULL; 156 Guid = NULL; 157 Attributes = 0; 158 DataSize = 0; 159 Data = NULL; 160 161 for ( 162 Status = EFI_SUCCESS, TotalSizeUsed = 0; 163 !EFI_ERROR (Status) && (TotalSizeUsed < MaxSize); 164 ) { 165 Status = UnpackVariableFromBuffer ( 166 (VOID*) ((UINT8*) Buffer + TotalSizeUsed), 167 (MaxSize - TotalSizeUsed), 168 &Name, 169 &NameSize, 170 &Guid, 171 &Attributes, 172 &DataSize, 173 &Data, 174 &SizeUsed 175 ); 176 if (EFI_ERROR (Status)) { 177 return Status; 178 } 179 180 // 181 // We copy the name to a separately allocated buffer, 182 // to be sure it is 16-bit aligned. 183 // 184 if (NameSize > AlignedNameMaxSize) { 185 if (AlignedName != NULL) { 186 FreePool (AlignedName); 187 } 188 AlignedName = AllocatePool (NameSize); 189 } 190 if (AlignedName == NULL) { 191 return EFI_OUT_OF_RESOURCES; 192 } 193 CopyMem (AlignedName, Name, NameSize); 194 195 TotalSizeUsed = TotalSizeUsed + SizeUsed; 196 197 // 198 // Run the callback function 199 // 200 Status = (*CallbackFunction) ( 201 CallbackContext, 202 AlignedName, 203 Guid, 204 Attributes, 205 DataSize, 206 Data 207 ); 208 209 } 210 211 if (AlignedName != NULL) { 212 FreePool (AlignedName); 213 } 214 215 // 216 // Make sure the entire buffer was used, or else return an error 217 // 218 if (TotalSizeUsed != MaxSize) { 219 DEBUG (( 220 EFI_D_ERROR, 221 "Deserialize variables error: TotalSizeUsed(%Lu) != MaxSize(%Lu)\n", 222 (UINT64)TotalSizeUsed, 223 (UINT64)MaxSize 224 )); 225 return EFI_INVALID_PARAMETER; 226 } 227 228 return EFI_SUCCESS; 229 } 230 231 232 STATIC 233 RETURN_STATUS 234 EFIAPI 235 IterateVariablesCallbackNop ( 236 IN VOID *Context, 237 IN CHAR16 *VariableName, 238 IN EFI_GUID *VendorGuid, 239 IN UINT32 Attributes, 240 IN UINTN DataSize, 241 IN VOID *Data 242 ) 243 { 244 return RETURN_SUCCESS; 245 } 246 247 248 STATIC 249 RETURN_STATUS 250 EFIAPI 251 IterateVariablesCallbackSetInInstance ( 252 IN VOID *Context, 253 IN CHAR16 *VariableName, 254 IN EFI_GUID *VendorGuid, 255 IN UINT32 Attributes, 256 IN UINTN DataSize, 257 IN VOID *Data 258 ) 259 { 260 EFI_HANDLE Instance; 261 262 Instance = (EFI_HANDLE) Context; 263 264 return SerializeVariablesAddVariable ( 265 Instance, 266 VariableName, 267 VendorGuid, 268 Attributes, 269 DataSize, 270 Data 271 ); 272 } 273 274 275 STATIC 276 RETURN_STATUS 277 EFIAPI 278 IterateVariablesCallbackSetSystemVariable ( 279 IN VOID *Context, 280 IN CHAR16 *VariableName, 281 IN EFI_GUID *VendorGuid, 282 IN UINT32 Attributes, 283 IN UINTN DataSize, 284 IN VOID *Data 285 ) 286 { 287 EFI_STATUS Status; 288 STATIC CONST UINT32 AuthMask = 289 EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | 290 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; 291 292 Status = gRT->SetVariable ( 293 VariableName, 294 VendorGuid, 295 Attributes, 296 DataSize, 297 Data 298 ); 299 300 if (Status == EFI_SECURITY_VIOLATION && (Attributes & AuthMask) != 0) { 301 DEBUG ((DEBUG_WARN, "%a: setting authenticated variable \"%s\" " 302 "failed with EFI_SECURITY_VIOLATION, ignoring\n", __FUNCTION__, 303 VariableName)); 304 Status = EFI_SUCCESS; 305 } 306 return Status; 307 } 308 309 310 STATIC 311 RETURN_STATUS 312 EnsureExtraBufferSpace ( 313 IN SV_INSTANCE *Instance, 314 IN UINTN Size 315 ) 316 { 317 VOID *NewBuffer; 318 UINTN NewSize; 319 320 NewSize = Instance->DataSize + Size; 321 if (NewSize <= Instance->BufferSize) { 322 return RETURN_SUCCESS; 323 } 324 325 // 326 // Double the required size to lessen the need to re-allocate in the future 327 // 328 NewSize = 2 * NewSize; 329 330 NewBuffer = AllocatePool (NewSize); 331 if (NewBuffer == NULL) { 332 return RETURN_OUT_OF_RESOURCES; 333 } 334 335 if (Instance->BufferPtr != NULL) { 336 CopyMem (NewBuffer, Instance->BufferPtr, Instance->DataSize); 337 FreePool (Instance->BufferPtr); 338 } 339 340 Instance->BufferPtr = NewBuffer; 341 Instance->BufferSize = NewSize; 342 343 return RETURN_SUCCESS; 344 } 345 346 347 STATIC 348 VOID 349 AppendToBuffer ( 350 IN SV_INSTANCE *Instance, 351 IN VOID *Data, 352 IN UINTN Size 353 ) 354 { 355 UINTN NewSize; 356 357 ASSERT (Instance != NULL); 358 ASSERT (Data != NULL); 359 360 NewSize = Instance->DataSize + Size; 361 ASSERT ((Instance->DataSize + Size) <= Instance->BufferSize); 362 363 CopyMem ( 364 (VOID*) (((UINT8*) (Instance->BufferPtr)) + Instance->DataSize), 365 Data, 366 Size 367 ); 368 369 Instance->DataSize = NewSize; 370 } 371 372 373 /** 374 Creates a new variable serialization instance 375 376 @param[out] Handle - Handle for a variable serialization instance 377 378 @retval RETURN_SUCCESS - The variable serialization instance was 379 successfully created. 380 @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to 381 create the variable serialization instance. 382 383 **/ 384 RETURN_STATUS 385 EFIAPI 386 SerializeVariablesNewInstance ( 387 OUT EFI_HANDLE *Handle 388 ) 389 { 390 SV_INSTANCE *New; 391 392 New = AllocateZeroPool (sizeof (*New)); 393 if (New == NULL) { 394 return RETURN_OUT_OF_RESOURCES; 395 } 396 397 New->Signature = SV_SIGNATURE; 398 399 *Handle = (EFI_HANDLE) New; 400 return RETURN_SUCCESS; 401 } 402 403 404 /** 405 Free memory associated with a variable serialization instance 406 407 @param[in] Handle - Handle for a variable serialization instance 408 409 @retval RETURN_SUCCESS - The variable serialization instance was 410 successfully freed. 411 @retval RETURN_INVALID_PARAMETER - Handle was not a valid 412 variable serialization instance. 413 414 **/ 415 RETURN_STATUS 416 EFIAPI 417 SerializeVariablesFreeInstance ( 418 IN EFI_HANDLE Handle 419 ) 420 { 421 SV_INSTANCE *Instance; 422 423 Instance = SV_FROM_HANDLE (Handle); 424 425 if (Instance->Signature != SV_SIGNATURE) { 426 return RETURN_INVALID_PARAMETER; 427 } 428 429 Instance->Signature = 0; 430 431 if (Instance->BufferPtr != NULL) { 432 FreePool (Instance->BufferPtr); 433 } 434 435 FreePool (Instance); 436 437 return RETURN_SUCCESS; 438 } 439 440 441 /** 442 Creates a new variable serialization instance using the given 443 binary representation of the variables to fill the new instance 444 445 @param[out] Handle - Handle for a variable serialization instance 446 @param[in] Buffer - A buffer with the serialized representation 447 of the variables. Must be the same format as produced 448 by SerializeVariablesToBuffer. 449 @param[in] Size - This is the size of the binary representation 450 of the variables. 451 452 @retval RETURN_SUCCESS - The binary representation was successfully 453 imported into a new variable serialization instance 454 @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to 455 create the new variable serialization instance 456 457 **/ 458 RETURN_STATUS 459 EFIAPI 460 SerializeVariablesNewInstanceFromBuffer ( 461 OUT EFI_HANDLE *Handle, 462 IN VOID *Buffer, 463 IN UINTN Size 464 ) 465 { 466 RETURN_STATUS Status; 467 468 Status = SerializeVariablesNewInstance (Handle); 469 if (RETURN_ERROR (Status)) { 470 return Status; 471 } 472 473 Status = IterateVariablesInBuffer ( 474 IterateVariablesCallbackNop, 475 NULL, 476 Buffer, 477 Size 478 ); 479 if (RETURN_ERROR (Status)) { 480 SerializeVariablesFreeInstance (*Handle); 481 return Status; 482 } 483 484 Status = IterateVariablesInBuffer ( 485 IterateVariablesCallbackSetInInstance, 486 (VOID*) *Handle, 487 Buffer, 488 Size 489 ); 490 if (RETURN_ERROR (Status)) { 491 SerializeVariablesFreeInstance (*Handle); 492 return Status; 493 } 494 495 return Status; 496 } 497 498 499 /** 500 Iterates all variables found with RuntimeServices GetNextVariableName 501 502 @param[in] CallbackFunction - Function called for each variable instance 503 @param[in] Context - Passed to each call of CallbackFunction 504 505 @retval RETURN_SUCCESS - All variables were iterated without the 506 CallbackFunction returning an error 507 @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to 508 iterate through the variables 509 @return Any of RETURN_ERROR indicates an error reading the variable 510 or an error was returned from CallbackFunction 511 512 **/ 513 RETURN_STATUS 514 EFIAPI 515 SerializeVariablesIterateSystemVariables ( 516 IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK CallbackFunction, 517 IN VOID *Context 518 ) 519 { 520 RETURN_STATUS Status; 521 UINTN VariableNameBufferSize; 522 UINTN VariableNameSize; 523 CHAR16 *VariableName; 524 EFI_GUID VendorGuid; 525 UINTN VariableDataBufferSize; 526 UINTN VariableDataSize; 527 VOID *VariableData; 528 UINT32 VariableAttributes; 529 VOID *NewBuffer; 530 531 // 532 // Initialize the variable name and data buffer variables. 533 // 534 VariableNameBufferSize = sizeof (CHAR16); 535 VariableName = AllocateZeroPool (VariableNameBufferSize); 536 537 VariableDataBufferSize = 0; 538 VariableData = NULL; 539 540 for (;;) { 541 // 542 // Get the next variable name and guid 543 // 544 VariableNameSize = VariableNameBufferSize; 545 Status = gRT->GetNextVariableName ( 546 &VariableNameSize, 547 VariableName, 548 &VendorGuid 549 ); 550 if (Status == EFI_BUFFER_TOO_SMALL) { 551 // 552 // The currently allocated VariableName buffer is too small, 553 // so we allocate a larger buffer, and copy the old buffer 554 // to it. 555 // 556 NewBuffer = AllocatePool (VariableNameSize); 557 if (NewBuffer == NULL) { 558 Status = EFI_OUT_OF_RESOURCES; 559 break; 560 } 561 CopyMem (NewBuffer, VariableName, VariableNameBufferSize); 562 if (VariableName != NULL) { 563 FreePool (VariableName); 564 } 565 VariableName = NewBuffer; 566 VariableNameBufferSize = VariableNameSize; 567 568 // 569 // Try to get the next variable name again with the larger buffer. 570 // 571 Status = gRT->GetNextVariableName ( 572 &VariableNameSize, 573 VariableName, 574 &VendorGuid 575 ); 576 } 577 578 if (EFI_ERROR (Status)) { 579 if (Status == EFI_NOT_FOUND) { 580 Status = EFI_SUCCESS; 581 } 582 break; 583 } 584 585 // 586 // Get the variable data and attributes 587 // 588 VariableDataSize = VariableDataBufferSize; 589 Status = gRT->GetVariable ( 590 VariableName, 591 &VendorGuid, 592 &VariableAttributes, 593 &VariableDataSize, 594 VariableData 595 ); 596 if (Status == EFI_BUFFER_TOO_SMALL) { 597 // 598 // The currently allocated VariableData buffer is too small, 599 // so we allocate a larger buffer. 600 // 601 if (VariableDataBufferSize != 0) { 602 FreePool (VariableData); 603 VariableData = NULL; 604 VariableDataBufferSize = 0; 605 } 606 VariableData = AllocatePool (VariableDataSize); 607 if (VariableData == NULL) { 608 Status = EFI_OUT_OF_RESOURCES; 609 break; 610 } 611 VariableDataBufferSize = VariableDataSize; 612 613 // 614 // Try to read the variable again with the larger buffer. 615 // 616 Status = gRT->GetVariable ( 617 VariableName, 618 &VendorGuid, 619 &VariableAttributes, 620 &VariableDataSize, 621 VariableData 622 ); 623 } 624 if (EFI_ERROR (Status)) { 625 break; 626 } 627 628 // 629 // Run the callback function 630 // 631 Status = (*CallbackFunction) ( 632 Context, 633 VariableName, 634 &VendorGuid, 635 VariableAttributes, 636 VariableDataSize, 637 VariableData 638 ); 639 if (EFI_ERROR (Status)) { 640 break; 641 } 642 643 } 644 645 if (VariableName != NULL) { 646 FreePool (VariableName); 647 } 648 649 if (VariableData != NULL) { 650 FreePool (VariableData); 651 } 652 653 return Status; 654 } 655 656 657 /** 658 Iterates all variables found in the variable serialization instance 659 660 @param[in] Handle - Handle for a variable serialization instance 661 @param[in] CallbackFunction - Function called for each variable instance 662 @param[in] Context - Passed to each call of CallbackFunction 663 664 @retval RETURN_SUCCESS - All variables were iterated without the 665 CallbackFunction returning an error 666 @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to 667 iterate through the variables 668 @return Any of RETURN_ERROR indicates an error reading the variable 669 or an error was returned from CallbackFunction 670 671 **/ 672 RETURN_STATUS 673 EFIAPI 674 SerializeVariablesIterateInstanceVariables ( 675 IN EFI_HANDLE Handle, 676 IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK CallbackFunction, 677 IN VOID *Context 678 ) 679 { 680 SV_INSTANCE *Instance; 681 682 Instance = SV_FROM_HANDLE (Handle); 683 684 if ((Instance->BufferPtr != NULL) && (Instance->DataSize != 0)) { 685 return IterateVariablesInBuffer ( 686 CallbackFunction, 687 Context, 688 Instance->BufferPtr, 689 Instance->DataSize 690 ); 691 } else { 692 return RETURN_SUCCESS; 693 } 694 } 695 696 697 /** 698 Sets all variables found in the variable serialization instance 699 700 @param[in] Handle - Handle for a variable serialization instance 701 702 @retval RETURN_SUCCESS - All variables were set successfully 703 @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to 704 set all the variables 705 @return Any of RETURN_ERROR indicates an error reading the variables 706 or in attempting to set a variable 707 708 **/ 709 RETURN_STATUS 710 EFIAPI 711 SerializeVariablesSetSerializedVariables ( 712 IN EFI_HANDLE Handle 713 ) 714 { 715 return SerializeVariablesIterateInstanceVariables ( 716 Handle, 717 IterateVariablesCallbackSetSystemVariable, 718 NULL 719 ); 720 } 721 722 723 /** 724 Adds a variable to the variable serialization instance 725 726 @param[in] Handle - Handle for a variable serialization instance 727 @param[in] VariableName - Refer to RuntimeServices GetVariable 728 @param[in] VendorGuid - Refer to RuntimeServices GetVariable 729 @param[in] Attributes - Refer to RuntimeServices GetVariable 730 @param[in] DataSize - Refer to RuntimeServices GetVariable 731 @param[in] Data - Refer to RuntimeServices GetVariable 732 733 @retval RETURN_SUCCESS - All variables were set successfully 734 @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to 735 add the variable 736 @retval RETURN_INVALID_PARAMETER - Handle was not a valid 737 variable serialization instance or 738 VariableName, VariableGuid or Data are NULL. 739 740 **/ 741 RETURN_STATUS 742 EFIAPI 743 SerializeVariablesAddVariable ( 744 IN EFI_HANDLE Handle, 745 IN CHAR16 *VariableName, 746 IN EFI_GUID *VendorGuid, 747 IN UINT32 Attributes, 748 IN UINTN DataSize, 749 IN VOID *Data 750 ) 751 { 752 RETURN_STATUS Status; 753 SV_INSTANCE *Instance; 754 UINT32 SerializedNameSize; 755 UINT32 SerializedDataSize; 756 UINTN SerializedSize; 757 758 Instance = SV_FROM_HANDLE (Handle); 759 760 if ((Instance->Signature != SV_SIGNATURE) || 761 (VariableName == NULL) || (VendorGuid == NULL) || (Data == NULL)) { 762 } 763 764 SerializedNameSize = (UINT32) StrSize (VariableName); 765 766 SerializedSize = 767 sizeof (SerializedNameSize) + 768 SerializedNameSize + 769 sizeof (*VendorGuid) + 770 sizeof (Attributes) + 771 sizeof (SerializedDataSize) + 772 DataSize; 773 774 Status = EnsureExtraBufferSpace ( 775 Instance, 776 SerializedSize 777 ); 778 if (RETURN_ERROR (Status)) { 779 return Status; 780 } 781 782 // 783 // Add name size (UINT32) 784 // 785 AppendToBuffer (Instance, (VOID*) &SerializedNameSize, sizeof (SerializedNameSize)); 786 787 // 788 // Add variable unicode name string 789 // 790 AppendToBuffer (Instance, (VOID*) VariableName, SerializedNameSize); 791 792 // 793 // Add variable GUID 794 // 795 AppendToBuffer (Instance, (VOID*) VendorGuid, sizeof (*VendorGuid)); 796 797 // 798 // Add variable attributes 799 // 800 AppendToBuffer (Instance, (VOID*) &Attributes, sizeof (Attributes)); 801 802 // 803 // Add variable data size (UINT32) 804 // 805 SerializedDataSize = (UINT32) DataSize; 806 AppendToBuffer (Instance, (VOID*) &SerializedDataSize, sizeof (SerializedDataSize)); 807 808 // 809 // Add variable data 810 // 811 AppendToBuffer (Instance, Data, DataSize); 812 813 return RETURN_SUCCESS; 814 } 815 816 817 /** 818 Serializes the variables known to this instance into the 819 provided buffer. 820 821 @param[in] Handle - Handle for a variable serialization instance 822 @param[out] Buffer - A buffer to store the binary representation 823 of the variables. 824 @param[in,out] Size - On input this is the size of the buffer. 825 On output this is the size of the binary representation 826 of the variables. 827 828 @retval RETURN_SUCCESS - The binary representation was successfully 829 completed and returned in the buffer. 830 @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to 831 save the variables to the buffer. 832 @retval RETURN_INVALID_PARAMETER - Handle was not a valid 833 variable serialization instance or 834 Size or Buffer were NULL. 835 @retval RETURN_BUFFER_TOO_SMALL - The Buffer size as indicated by 836 the Size parameter was too small for the serialized 837 variable data. Size is returned with the required size. 838 839 **/ 840 RETURN_STATUS 841 EFIAPI 842 SerializeVariablesToBuffer ( 843 IN EFI_HANDLE Handle, 844 OUT VOID *Buffer, 845 IN OUT UINTN *Size 846 ) 847 { 848 SV_INSTANCE *Instance; 849 850 Instance = SV_FROM_HANDLE (Handle); 851 852 if (Size == NULL) { 853 return RETURN_INVALID_PARAMETER; 854 } 855 856 if (*Size < Instance->DataSize) { 857 *Size = Instance->DataSize; 858 return RETURN_BUFFER_TOO_SMALL; 859 } 860 861 if (Buffer == NULL) { 862 return RETURN_INVALID_PARAMETER; 863 } 864 865 *Size = Instance->DataSize; 866 CopyMem (Buffer, Instance->BufferPtr, Instance->DataSize); 867 868 return RETURN_SUCCESS; 869 } 870 871