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 } else if (Status == EFI_WRITE_PROTECTED) { 306 DEBUG ((DEBUG_WARN, "%a: setting ReadOnly variable \"%s\" " 307 "failed with EFI_WRITE_PROTECTED, ignoring\n", __FUNCTION__, 308 VariableName)); 309 Status = EFI_SUCCESS; 310 } 311 return Status; 312 } 313 314 315 STATIC 316 RETURN_STATUS 317 EnsureExtraBufferSpace ( 318 IN SV_INSTANCE *Instance, 319 IN UINTN Size 320 ) 321 { 322 VOID *NewBuffer; 323 UINTN NewSize; 324 325 NewSize = Instance->DataSize + Size; 326 if (NewSize <= Instance->BufferSize) { 327 return RETURN_SUCCESS; 328 } 329 330 // 331 // Double the required size to lessen the need to re-allocate in the future 332 // 333 NewSize = 2 * NewSize; 334 335 NewBuffer = AllocatePool (NewSize); 336 if (NewBuffer == NULL) { 337 return RETURN_OUT_OF_RESOURCES; 338 } 339 340 if (Instance->BufferPtr != NULL) { 341 CopyMem (NewBuffer, Instance->BufferPtr, Instance->DataSize); 342 FreePool (Instance->BufferPtr); 343 } 344 345 Instance->BufferPtr = NewBuffer; 346 Instance->BufferSize = NewSize; 347 348 return RETURN_SUCCESS; 349 } 350 351 352 STATIC 353 VOID 354 AppendToBuffer ( 355 IN SV_INSTANCE *Instance, 356 IN VOID *Data, 357 IN UINTN Size 358 ) 359 { 360 UINTN NewSize; 361 362 ASSERT (Instance != NULL); 363 ASSERT (Data != NULL); 364 365 NewSize = Instance->DataSize + Size; 366 ASSERT ((Instance->DataSize + Size) <= Instance->BufferSize); 367 368 CopyMem ( 369 (VOID*) (((UINT8*) (Instance->BufferPtr)) + Instance->DataSize), 370 Data, 371 Size 372 ); 373 374 Instance->DataSize = NewSize; 375 } 376 377 378 /** 379 Creates a new variable serialization instance 380 381 @param[out] Handle - Handle for a variable serialization instance 382 383 @retval RETURN_SUCCESS - The variable serialization instance was 384 successfully created. 385 @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to 386 create the variable serialization instance. 387 388 **/ 389 RETURN_STATUS 390 EFIAPI 391 SerializeVariablesNewInstance ( 392 OUT EFI_HANDLE *Handle 393 ) 394 { 395 SV_INSTANCE *New; 396 397 New = AllocateZeroPool (sizeof (*New)); 398 if (New == NULL) { 399 return RETURN_OUT_OF_RESOURCES; 400 } 401 402 New->Signature = SV_SIGNATURE; 403 404 *Handle = (EFI_HANDLE) New; 405 return RETURN_SUCCESS; 406 } 407 408 409 /** 410 Free memory associated with a variable serialization instance 411 412 @param[in] Handle - Handle for a variable serialization instance 413 414 @retval RETURN_SUCCESS - The variable serialization instance was 415 successfully freed. 416 @retval RETURN_INVALID_PARAMETER - Handle was not a valid 417 variable serialization instance. 418 419 **/ 420 RETURN_STATUS 421 EFIAPI 422 SerializeVariablesFreeInstance ( 423 IN EFI_HANDLE Handle 424 ) 425 { 426 SV_INSTANCE *Instance; 427 428 Instance = SV_FROM_HANDLE (Handle); 429 430 if (Instance->Signature != SV_SIGNATURE) { 431 return RETURN_INVALID_PARAMETER; 432 } 433 434 Instance->Signature = 0; 435 436 if (Instance->BufferPtr != NULL) { 437 FreePool (Instance->BufferPtr); 438 } 439 440 FreePool (Instance); 441 442 return RETURN_SUCCESS; 443 } 444 445 446 /** 447 Creates a new variable serialization instance using the given 448 binary representation of the variables to fill the new instance 449 450 @param[out] Handle - Handle for a variable serialization instance 451 @param[in] Buffer - A buffer with the serialized representation 452 of the variables. Must be the same format as produced 453 by SerializeVariablesToBuffer. 454 @param[in] Size - This is the size of the binary representation 455 of the variables. 456 457 @retval RETURN_SUCCESS - The binary representation was successfully 458 imported into a new variable serialization instance 459 @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to 460 create the new variable serialization instance 461 462 **/ 463 RETURN_STATUS 464 EFIAPI 465 SerializeVariablesNewInstanceFromBuffer ( 466 OUT EFI_HANDLE *Handle, 467 IN VOID *Buffer, 468 IN UINTN Size 469 ) 470 { 471 RETURN_STATUS Status; 472 473 Status = SerializeVariablesNewInstance (Handle); 474 if (RETURN_ERROR (Status)) { 475 return Status; 476 } 477 478 Status = IterateVariablesInBuffer ( 479 IterateVariablesCallbackNop, 480 NULL, 481 Buffer, 482 Size 483 ); 484 if (RETURN_ERROR (Status)) { 485 SerializeVariablesFreeInstance (*Handle); 486 return Status; 487 } 488 489 Status = IterateVariablesInBuffer ( 490 IterateVariablesCallbackSetInInstance, 491 (VOID*) *Handle, 492 Buffer, 493 Size 494 ); 495 if (RETURN_ERROR (Status)) { 496 SerializeVariablesFreeInstance (*Handle); 497 return Status; 498 } 499 500 return Status; 501 } 502 503 504 /** 505 Iterates all variables found with RuntimeServices GetNextVariableName 506 507 @param[in] CallbackFunction - Function called for each variable instance 508 @param[in] Context - Passed to each call of CallbackFunction 509 510 @retval RETURN_SUCCESS - All variables were iterated without the 511 CallbackFunction returning an error 512 @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to 513 iterate through the variables 514 @return Any of RETURN_ERROR indicates an error reading the variable 515 or an error was returned from CallbackFunction 516 517 **/ 518 RETURN_STATUS 519 EFIAPI 520 SerializeVariablesIterateSystemVariables ( 521 IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK CallbackFunction, 522 IN VOID *Context 523 ) 524 { 525 RETURN_STATUS Status; 526 UINTN VariableNameBufferSize; 527 UINTN VariableNameSize; 528 CHAR16 *VariableName; 529 EFI_GUID VendorGuid; 530 UINTN VariableDataBufferSize; 531 UINTN VariableDataSize; 532 VOID *VariableData; 533 UINT32 VariableAttributes; 534 VOID *NewBuffer; 535 536 // 537 // Initialize the variable name and data buffer variables. 538 // 539 VariableNameBufferSize = sizeof (CHAR16); 540 VariableName = AllocateZeroPool (VariableNameBufferSize); 541 542 VariableDataBufferSize = 0; 543 VariableData = NULL; 544 545 for (;;) { 546 // 547 // Get the next variable name and guid 548 // 549 VariableNameSize = VariableNameBufferSize; 550 Status = gRT->GetNextVariableName ( 551 &VariableNameSize, 552 VariableName, 553 &VendorGuid 554 ); 555 if (Status == EFI_BUFFER_TOO_SMALL) { 556 // 557 // The currently allocated VariableName buffer is too small, 558 // so we allocate a larger buffer, and copy the old buffer 559 // to it. 560 // 561 NewBuffer = AllocatePool (VariableNameSize); 562 if (NewBuffer == NULL) { 563 Status = EFI_OUT_OF_RESOURCES; 564 break; 565 } 566 CopyMem (NewBuffer, VariableName, VariableNameBufferSize); 567 if (VariableName != NULL) { 568 FreePool (VariableName); 569 } 570 VariableName = NewBuffer; 571 VariableNameBufferSize = VariableNameSize; 572 573 // 574 // Try to get the next variable name again with the larger buffer. 575 // 576 Status = gRT->GetNextVariableName ( 577 &VariableNameSize, 578 VariableName, 579 &VendorGuid 580 ); 581 } 582 583 if (EFI_ERROR (Status)) { 584 if (Status == EFI_NOT_FOUND) { 585 Status = EFI_SUCCESS; 586 } 587 break; 588 } 589 590 // 591 // Get the variable data and attributes 592 // 593 VariableDataSize = VariableDataBufferSize; 594 Status = gRT->GetVariable ( 595 VariableName, 596 &VendorGuid, 597 &VariableAttributes, 598 &VariableDataSize, 599 VariableData 600 ); 601 if (Status == EFI_BUFFER_TOO_SMALL) { 602 // 603 // The currently allocated VariableData buffer is too small, 604 // so we allocate a larger buffer. 605 // 606 if (VariableDataBufferSize != 0) { 607 FreePool (VariableData); 608 VariableData = NULL; 609 VariableDataBufferSize = 0; 610 } 611 VariableData = AllocatePool (VariableDataSize); 612 if (VariableData == NULL) { 613 Status = EFI_OUT_OF_RESOURCES; 614 break; 615 } 616 VariableDataBufferSize = VariableDataSize; 617 618 // 619 // Try to read the variable again with the larger buffer. 620 // 621 Status = gRT->GetVariable ( 622 VariableName, 623 &VendorGuid, 624 &VariableAttributes, 625 &VariableDataSize, 626 VariableData 627 ); 628 } 629 if (EFI_ERROR (Status)) { 630 break; 631 } 632 633 // 634 // Run the callback function 635 // 636 Status = (*CallbackFunction) ( 637 Context, 638 VariableName, 639 &VendorGuid, 640 VariableAttributes, 641 VariableDataSize, 642 VariableData 643 ); 644 if (EFI_ERROR (Status)) { 645 break; 646 } 647 648 } 649 650 if (VariableName != NULL) { 651 FreePool (VariableName); 652 } 653 654 if (VariableData != NULL) { 655 FreePool (VariableData); 656 } 657 658 return Status; 659 } 660 661 662 /** 663 Iterates all variables found in the variable serialization instance 664 665 @param[in] Handle - Handle for a variable serialization instance 666 @param[in] CallbackFunction - Function called for each variable instance 667 @param[in] Context - Passed to each call of CallbackFunction 668 669 @retval RETURN_SUCCESS - All variables were iterated without the 670 CallbackFunction returning an error 671 @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to 672 iterate through the variables 673 @return Any of RETURN_ERROR indicates an error reading the variable 674 or an error was returned from CallbackFunction 675 676 **/ 677 RETURN_STATUS 678 EFIAPI 679 SerializeVariablesIterateInstanceVariables ( 680 IN EFI_HANDLE Handle, 681 IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK CallbackFunction, 682 IN VOID *Context 683 ) 684 { 685 SV_INSTANCE *Instance; 686 687 Instance = SV_FROM_HANDLE (Handle); 688 689 if ((Instance->BufferPtr != NULL) && (Instance->DataSize != 0)) { 690 return IterateVariablesInBuffer ( 691 CallbackFunction, 692 Context, 693 Instance->BufferPtr, 694 Instance->DataSize 695 ); 696 } else { 697 return RETURN_SUCCESS; 698 } 699 } 700 701 702 /** 703 Sets all variables found in the variable serialization instance 704 705 @param[in] Handle - Handle for a variable serialization instance 706 707 @retval RETURN_SUCCESS - All variables were set successfully 708 @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to 709 set all the variables 710 @return Any of RETURN_ERROR indicates an error reading the variables 711 or in attempting to set a variable 712 713 **/ 714 RETURN_STATUS 715 EFIAPI 716 SerializeVariablesSetSerializedVariables ( 717 IN EFI_HANDLE Handle 718 ) 719 { 720 return SerializeVariablesIterateInstanceVariables ( 721 Handle, 722 IterateVariablesCallbackSetSystemVariable, 723 NULL 724 ); 725 } 726 727 728 /** 729 Adds a variable to the variable serialization instance 730 731 @param[in] Handle - Handle for a variable serialization instance 732 @param[in] VariableName - Refer to RuntimeServices GetVariable 733 @param[in] VendorGuid - Refer to RuntimeServices GetVariable 734 @param[in] Attributes - Refer to RuntimeServices GetVariable 735 @param[in] DataSize - Refer to RuntimeServices GetVariable 736 @param[in] Data - Refer to RuntimeServices GetVariable 737 738 @retval RETURN_SUCCESS - All variables were set successfully 739 @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to 740 add the variable 741 @retval RETURN_INVALID_PARAMETER - Handle was not a valid 742 variable serialization instance or 743 VariableName, VariableGuid or Data are NULL. 744 745 **/ 746 RETURN_STATUS 747 EFIAPI 748 SerializeVariablesAddVariable ( 749 IN EFI_HANDLE Handle, 750 IN CHAR16 *VariableName, 751 IN EFI_GUID *VendorGuid, 752 IN UINT32 Attributes, 753 IN UINTN DataSize, 754 IN VOID *Data 755 ) 756 { 757 RETURN_STATUS Status; 758 SV_INSTANCE *Instance; 759 UINT32 SerializedNameSize; 760 UINT32 SerializedDataSize; 761 UINTN SerializedSize; 762 763 Instance = SV_FROM_HANDLE (Handle); 764 765 if ((Instance->Signature != SV_SIGNATURE) || 766 (VariableName == NULL) || (VendorGuid == NULL) || (Data == NULL)) { 767 } 768 769 SerializedNameSize = (UINT32) StrSize (VariableName); 770 771 SerializedSize = 772 sizeof (SerializedNameSize) + 773 SerializedNameSize + 774 sizeof (*VendorGuid) + 775 sizeof (Attributes) + 776 sizeof (SerializedDataSize) + 777 DataSize; 778 779 Status = EnsureExtraBufferSpace ( 780 Instance, 781 SerializedSize 782 ); 783 if (RETURN_ERROR (Status)) { 784 return Status; 785 } 786 787 // 788 // Add name size (UINT32) 789 // 790 AppendToBuffer (Instance, (VOID*) &SerializedNameSize, sizeof (SerializedNameSize)); 791 792 // 793 // Add variable unicode name string 794 // 795 AppendToBuffer (Instance, (VOID*) VariableName, SerializedNameSize); 796 797 // 798 // Add variable GUID 799 // 800 AppendToBuffer (Instance, (VOID*) VendorGuid, sizeof (*VendorGuid)); 801 802 // 803 // Add variable attributes 804 // 805 AppendToBuffer (Instance, (VOID*) &Attributes, sizeof (Attributes)); 806 807 // 808 // Add variable data size (UINT32) 809 // 810 SerializedDataSize = (UINT32) DataSize; 811 AppendToBuffer (Instance, (VOID*) &SerializedDataSize, sizeof (SerializedDataSize)); 812 813 // 814 // Add variable data 815 // 816 AppendToBuffer (Instance, Data, DataSize); 817 818 return RETURN_SUCCESS; 819 } 820 821 822 /** 823 Serializes the variables known to this instance into the 824 provided buffer. 825 826 @param[in] Handle - Handle for a variable serialization instance 827 @param[out] Buffer - A buffer to store the binary representation 828 of the variables. 829 @param[in,out] Size - On input this is the size of the buffer. 830 On output this is the size of the binary representation 831 of the variables. 832 833 @retval RETURN_SUCCESS - The binary representation was successfully 834 completed and returned in the buffer. 835 @retval RETURN_OUT_OF_RESOURCES - There we not enough resources to 836 save the variables to the buffer. 837 @retval RETURN_INVALID_PARAMETER - Handle was not a valid 838 variable serialization instance or 839 Size or Buffer were NULL. 840 @retval RETURN_BUFFER_TOO_SMALL - The Buffer size as indicated by 841 the Size parameter was too small for the serialized 842 variable data. Size is returned with the required size. 843 844 **/ 845 RETURN_STATUS 846 EFIAPI 847 SerializeVariablesToBuffer ( 848 IN EFI_HANDLE Handle, 849 OUT VOID *Buffer, 850 IN OUT UINTN *Size 851 ) 852 { 853 SV_INSTANCE *Instance; 854 855 Instance = SV_FROM_HANDLE (Handle); 856 857 if (Size == NULL) { 858 return RETURN_INVALID_PARAMETER; 859 } 860 861 if (*Size < Instance->DataSize) { 862 *Size = Instance->DataSize; 863 return RETURN_BUFFER_TOO_SMALL; 864 } 865 866 if (Buffer == NULL) { 867 return RETURN_INVALID_PARAMETER; 868 } 869 870 *Size = Instance->DataSize; 871 CopyMem (Buffer, Instance->BufferPtr, Instance->DataSize); 872 873 return RETURN_SUCCESS; 874 } 875 876