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
UnpackVariableFromBuffer(IN VOID * Buffer,IN UINTN MaxSize,OUT CHAR16 ** Name,OUT UINT32 * NameSize,OUT EFI_GUID ** Guid,OUT UINT32 * Attributes,OUT UINT32 * DataSize,OUT VOID ** Data,OUT UINTN * SizeUsed)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
IterateVariablesInBuffer(IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK CallbackFunction,IN VOID * CallbackContext,IN VOID * Buffer,IN UINTN MaxSize)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
IterateVariablesCallbackNop(IN VOID * Context,IN CHAR16 * VariableName,IN EFI_GUID * VendorGuid,IN UINT32 Attributes,IN UINTN DataSize,IN VOID * Data)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
IterateVariablesCallbackSetInInstance(IN VOID * Context,IN CHAR16 * VariableName,IN EFI_GUID * VendorGuid,IN UINT32 Attributes,IN UINTN DataSize,IN VOID * Data)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
IterateVariablesCallbackSetSystemVariable(IN VOID * Context,IN CHAR16 * VariableName,IN EFI_GUID * VendorGuid,IN UINT32 Attributes,IN UINTN DataSize,IN VOID * Data)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
EnsureExtraBufferSpace(IN SV_INSTANCE * Instance,IN UINTN Size)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
AppendToBuffer(IN SV_INSTANCE * Instance,IN VOID * Data,IN UINTN Size)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
SerializeVariablesNewInstance(OUT EFI_HANDLE * Handle)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
SerializeVariablesFreeInstance(IN EFI_HANDLE Handle)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
SerializeVariablesNewInstanceFromBuffer(OUT EFI_HANDLE * Handle,IN VOID * Buffer,IN UINTN Size)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
SerializeVariablesIterateSystemVariables(IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK CallbackFunction,IN VOID * Context)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
SerializeVariablesIterateInstanceVariables(IN EFI_HANDLE Handle,IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK CallbackFunction,IN VOID * Context)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
SerializeVariablesSetSerializedVariables(IN EFI_HANDLE Handle)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
SerializeVariablesAddVariable(IN EFI_HANDLE Handle,IN CHAR16 * VariableName,IN EFI_GUID * VendorGuid,IN UINT32 Attributes,IN UINTN DataSize,IN VOID * Data)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
SerializeVariablesToBuffer(IN EFI_HANDLE Handle,OUT VOID * Buffer,IN OUT UINTN * Size)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