TianoCore EDK2 master
Loading...
Searching...
No Matches
SerializeVariablesLib.c
Go to the documentation of this file.
1
10
51 IN VOID *Buffer,
52 IN UINTN MaxSize,
53 OUT CHAR16 **Name,
54 OUT UINT32 *NameSize,
55 OUT EFI_GUID **Guid,
56 OUT UINT32 *Attributes,
57 OUT UINT32 *DataSize,
58 OUT VOID **Data,
59 OUT UINTN *SizeUsed
60 )
61{
62 UINT8 *BytePtr;
63 UINTN Offset;
64
65 BytePtr = (UINT8 *)Buffer;
66 Offset = 0;
67
68 *NameSize = *(UINT32 *)(BytePtr + Offset);
69 Offset = Offset + sizeof (UINT32);
70
71 if (Offset > MaxSize) {
72 return EFI_INVALID_PARAMETER;
73 }
74
75 *Name = (CHAR16 *)(BytePtr + Offset);
76 Offset = Offset + *(UINT32 *)BytePtr;
77 if (Offset > MaxSize) {
78 return EFI_INVALID_PARAMETER;
79 }
80
81 *Guid = (EFI_GUID *)(BytePtr + Offset);
82 Offset = Offset + sizeof (EFI_GUID);
83 if (Offset > MaxSize) {
84 return EFI_INVALID_PARAMETER;
85 }
86
87 *Attributes = *(UINT32 *)(BytePtr + Offset);
88 Offset = Offset + sizeof (UINT32);
89 if (Offset > MaxSize) {
90 return EFI_INVALID_PARAMETER;
91 }
92
93 *DataSize = *(UINT32 *)(BytePtr + Offset);
94 Offset = Offset + sizeof (UINT32);
95 if (Offset > MaxSize) {
96 return EFI_INVALID_PARAMETER;
97 }
98
99 *Data = (VOID *)(BytePtr + Offset);
100 Offset = Offset + *DataSize;
101 if (Offset > MaxSize) {
102 return EFI_INVALID_PARAMETER;
103 }
104
105 *SizeUsed = Offset;
106
107 return EFI_SUCCESS;
108}
109
122STATIC
126 IN VOID *CallbackContext,
127 IN VOID *Buffer,
128 IN UINTN MaxSize
129 )
130{
131 RETURN_STATUS Status;
132 UINTN TotalSizeUsed;
133 UINTN SizeUsed;
134
135 CHAR16 *Name;
136 UINT32 NameSize;
137 CHAR16 *AlignedName;
138 UINT32 AlignedNameMaxSize;
139 EFI_GUID *Guid;
140 UINT32 Attributes;
141 UINT32 DataSize;
142 VOID *Data;
143
144 SizeUsed = 0;
145 AlignedName = NULL;
146 AlignedNameMaxSize = 0;
147 Name = NULL;
148 Guid = NULL;
149 Attributes = 0;
150 DataSize = 0;
151 Data = NULL;
152
153 for (
154 Status = EFI_SUCCESS, TotalSizeUsed = 0;
155 !EFI_ERROR (Status) && (TotalSizeUsed < MaxSize);
156 )
157 {
158 Status = UnpackVariableFromBuffer (
159 (VOID *)((UINT8 *)Buffer + TotalSizeUsed),
160 (MaxSize - TotalSizeUsed),
161 &Name,
162 &NameSize,
163 &Guid,
164 &Attributes,
165 &DataSize,
166 &Data,
167 &SizeUsed
168 );
169 if (EFI_ERROR (Status)) {
170 return Status;
171 }
172
173 //
174 // We copy the name to a separately allocated buffer,
175 // to be sure it is 16-bit aligned.
176 //
177 if (NameSize > AlignedNameMaxSize) {
178 if (AlignedName != NULL) {
179 FreePool (AlignedName);
180 }
181
182 AlignedName = AllocatePool (NameSize);
183 }
184
185 if (AlignedName == NULL) {
186 return EFI_OUT_OF_RESOURCES;
187 }
188
189 CopyMem (AlignedName, Name, NameSize);
190
191 TotalSizeUsed = TotalSizeUsed + SizeUsed;
192
193 //
194 // Run the callback function
195 //
196 Status = (*CallbackFunction)(
197 CallbackContext,
198 AlignedName,
199 Guid,
200 Attributes,
201 DataSize,
202 Data
203 );
204 }
205
206 if (AlignedName != NULL) {
207 FreePool (AlignedName);
208 }
209
210 //
211 // Make sure the entire buffer was used, or else return an error
212 //
213 if (TotalSizeUsed != MaxSize) {
214 DEBUG ((
215 DEBUG_ERROR,
216 "Deserialize variables error: TotalSizeUsed(%Lu) != MaxSize(%Lu)\n",
217 (UINT64)TotalSizeUsed,
218 (UINT64)MaxSize
219 ));
220 return EFI_INVALID_PARAMETER;
221 }
222
223 return EFI_SUCCESS;
224}
225
226STATIC
227RETURN_STATUS
228EFIAPI
229IterateVariablesCallbackNop (
230 IN VOID *Context,
231 IN CHAR16 *VariableName,
232 IN EFI_GUID *VendorGuid,
233 IN UINT32 Attributes,
234 IN UINTN DataSize,
235 IN VOID *Data
236 )
237{
238 return RETURN_SUCCESS;
239}
240
241STATIC
242RETURN_STATUS
243EFIAPI
244IterateVariablesCallbackSetInInstance (
245 IN VOID *Context,
246 IN CHAR16 *VariableName,
247 IN EFI_GUID *VendorGuid,
248 IN UINT32 Attributes,
249 IN UINTN DataSize,
250 IN VOID *Data
251 )
252{
253 EFI_HANDLE Instance;
254
255 Instance = (EFI_HANDLE)Context;
256
258 Instance,
259 VariableName,
260 VendorGuid,
261 Attributes,
262 DataSize,
263 Data
264 );
265}
266
267STATIC
268RETURN_STATUS
269EFIAPI
270IterateVariablesCallbackSetSystemVariable (
271 IN VOID *Context,
272 IN CHAR16 *VariableName,
273 IN EFI_GUID *VendorGuid,
274 IN UINT32 Attributes,
275 IN UINTN DataSize,
276 IN VOID *Data
277 )
278{
279 EFI_STATUS Status;
280 STATIC CONST UINT32 AuthMask =
283
284 Status = gRT->SetVariable (
285 VariableName,
286 VendorGuid,
287 Attributes,
288 DataSize,
289 Data
290 );
291
292 if ((Status == EFI_SECURITY_VIOLATION) && ((Attributes & AuthMask) != 0)) {
293 DEBUG ((
294 DEBUG_WARN,
295 "%a: setting authenticated variable \"%s\" "
296 "failed with EFI_SECURITY_VIOLATION, ignoring\n",
297 __func__,
298 VariableName
299 ));
300 Status = EFI_SUCCESS;
301 } else if (Status == EFI_WRITE_PROTECTED) {
302 DEBUG ((
303 DEBUG_WARN,
304 "%a: setting ReadOnly variable \"%s\" "
305 "failed with EFI_WRITE_PROTECTED, ignoring\n",
306 __func__,
307 VariableName
308 ));
309 Status = EFI_SUCCESS;
310 }
311
312 return Status;
313}
314
315STATIC
316RETURN_STATUS
317EnsureExtraBufferSpace (
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) {
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
351STATIC
352VOID
353AppendToBuffer (
354 IN SV_INSTANCE *Instance,
355 IN VOID *Data,
356 IN UINTN Size
357 )
358{
359 UINTN NewSize;
360
361 ASSERT (Instance != NULL);
362 ASSERT (Data != NULL);
363
364 NewSize = Instance->DataSize + Size;
365 ASSERT ((Instance->DataSize + Size) <= Instance->BufferSize);
366
367 CopyMem (
368 (VOID *)(((UINT8 *)(Instance->BufferPtr)) + Instance->DataSize),
369 Data,
370 Size
371 );
372
373 Instance->DataSize = NewSize;
374}
375
387RETURN_STATUS
388EFIAPI
390 OUT EFI_HANDLE *Handle
391 )
392{
393 SV_INSTANCE *New;
394
395 New = AllocateZeroPool (sizeof (*New));
396 if (New == NULL) {
398 }
399
400 New->Signature = SV_SIGNATURE;
401
402 *Handle = (EFI_HANDLE)New;
403 return RETURN_SUCCESS;
404}
405
417RETURN_STATUS
418EFIAPI
420 IN EFI_HANDLE Handle
421 )
422{
423 SV_INSTANCE *Instance;
424
425 Instance = SV_FROM_HANDLE (Handle);
426
427 if (Instance->Signature != SV_SIGNATURE) {
429 }
430
431 Instance->Signature = 0;
432
433 if (Instance->BufferPtr != NULL) {
434 FreePool (Instance->BufferPtr);
435 }
436
437 FreePool (Instance);
438
439 return RETURN_SUCCESS;
440}
441
459RETURN_STATUS
460EFIAPI
462 OUT EFI_HANDLE *Handle,
463 IN VOID *Buffer,
464 IN UINTN Size
465 )
466{
467 RETURN_STATUS Status;
468
469 Status = SerializeVariablesNewInstance (Handle);
470 if (RETURN_ERROR (Status)) {
471 return Status;
472 }
473
474 Status = IterateVariablesInBuffer (
475 IterateVariablesCallbackNop,
476 NULL,
477 Buffer,
478 Size
479 );
480 if (RETURN_ERROR (Status)) {
482 return Status;
483 }
484
485 Status = IterateVariablesInBuffer (
486 IterateVariablesCallbackSetInInstance,
487 (VOID *)*Handle,
488 Buffer,
489 Size
490 );
491 if (RETURN_ERROR (Status)) {
493 return Status;
494 }
495
496 return Status;
497}
498
513RETURN_STATUS
514EFIAPI
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
562 CopyMem (NewBuffer, VariableName, VariableNameBufferSize);
563 if (VariableName != NULL) {
564 FreePool (VariableName);
565 }
566
567 VariableName = NewBuffer;
568 VariableNameBufferSize = VariableNameSize;
569
570 //
571 // Try to get the next variable name again with the larger buffer.
572 //
573 Status = gRT->GetNextVariableName (
574 &VariableNameSize,
575 VariableName,
576 &VendorGuid
577 );
578 }
579
580 if (EFI_ERROR (Status)) {
581 if (Status == EFI_NOT_FOUND) {
582 Status = EFI_SUCCESS;
583 }
584
585 break;
586 }
587
588 //
589 // Get the variable data and attributes
590 //
591 VariableDataSize = VariableDataBufferSize;
592 Status = gRT->GetVariable (
593 VariableName,
594 &VendorGuid,
595 &VariableAttributes,
596 &VariableDataSize,
597 VariableData
598 );
599 if (Status == EFI_BUFFER_TOO_SMALL) {
600 //
601 // The currently allocated VariableData buffer is too small,
602 // so we allocate a larger buffer.
603 //
604 if (VariableDataBufferSize != 0) {
605 FreePool (VariableData);
606 VariableData = NULL;
607 VariableDataBufferSize = 0;
608 }
609
610 VariableData = AllocatePool (VariableDataSize);
611 if (VariableData == NULL) {
612 Status = EFI_OUT_OF_RESOURCES;
613 break;
614 }
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
630 if (EFI_ERROR (Status)) {
631 break;
632 }
633
634 //
635 // Run the callback function
636 //
637 Status = (*CallbackFunction)(
638 Context,
639 VariableName,
640 &VendorGuid,
641 VariableAttributes,
642 VariableDataSize,
643 VariableData
644 );
645 if (EFI_ERROR (Status)) {
646 break;
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
676RETURN_STATUS
677EFIAPI
679 IN EFI_HANDLE Handle,
681 IN VOID *Context
682 )
683{
684 SV_INSTANCE *Instance;
685
686 Instance = SV_FROM_HANDLE (Handle);
687
688 if ((Instance->BufferPtr != NULL) && (Instance->DataSize != 0)) {
691 Context,
692 Instance->BufferPtr,
693 Instance->DataSize
694 );
695 } else {
696 return RETURN_SUCCESS;
697 }
698}
699
712RETURN_STATUS
713EFIAPI
715 IN EFI_HANDLE Handle
716 )
717{
719 Handle,
720 IterateVariablesCallbackSetSystemVariable,
721 NULL
722 );
723}
724
743RETURN_STATUS
744EFIAPI
746 IN EFI_HANDLE Handle,
747 IN CHAR16 *VariableName,
748 IN EFI_GUID *VendorGuid,
749 IN UINT32 Attributes,
750 IN UINTN DataSize,
751 IN VOID *Data
752 )
753{
754 RETURN_STATUS Status;
755 SV_INSTANCE *Instance;
756 UINT32 SerializedNameSize;
757 UINT32 SerializedDataSize;
758 UINTN SerializedSize;
759
760 Instance = SV_FROM_HANDLE (Handle);
761
762 if ((Instance->Signature != SV_SIGNATURE) ||
763 (VariableName == NULL) || (VendorGuid == NULL) || (Data == NULL))
764 {
765 }
766
767 SerializedNameSize = (UINT32)StrSize (VariableName);
768
769 SerializedSize =
770 sizeof (SerializedNameSize) +
771 SerializedNameSize +
772 sizeof (*VendorGuid) +
773 sizeof (Attributes) +
774 sizeof (SerializedDataSize) +
775 DataSize;
776
777 Status = EnsureExtraBufferSpace (
778 Instance,
779 SerializedSize
780 );
781 if (RETURN_ERROR (Status)) {
782 return Status;
783 }
784
785 //
786 // Add name size (UINT32)
787 //
788 AppendToBuffer (Instance, (VOID *)&SerializedNameSize, sizeof (SerializedNameSize));
789
790 //
791 // Add variable unicode name string
792 //
793 AppendToBuffer (Instance, (VOID *)VariableName, SerializedNameSize);
794
795 //
796 // Add variable GUID
797 //
798 AppendToBuffer (Instance, (VOID *)VendorGuid, sizeof (*VendorGuid));
799
800 //
801 // Add variable attributes
802 //
803 AppendToBuffer (Instance, (VOID *)&Attributes, sizeof (Attributes));
804
805 //
806 // Add variable data size (UINT32)
807 //
808 SerializedDataSize = (UINT32)DataSize;
809 AppendToBuffer (Instance, (VOID *)&SerializedDataSize, sizeof (SerializedDataSize));
810
811 //
812 // Add variable data
813 //
814 AppendToBuffer (Instance, Data, DataSize);
815
816 return RETURN_SUCCESS;
817}
818
842RETURN_STATUS
843EFIAPI
845 IN EFI_HANDLE Handle,
846 OUT VOID *Buffer,
847 IN OUT UINTN *Size
848 )
849{
850 SV_INSTANCE *Instance;
851
852 Instance = SV_FROM_HANDLE (Handle);
853
854 if (Size == NULL) {
856 }
857
858 if (*Size < Instance->DataSize) {
859 *Size = Instance->DataSize;
861 }
862
863 if (Buffer == NULL) {
865 }
866
867 *Size = Instance->DataSize;
868 CopyMem (Buffer, Instance->BufferPtr, Instance->DataSize);
869
870 return RETURN_SUCCESS;
871}
UINT64 UINTN
UINTN EFIAPI StrSize(IN CONST CHAR16 *String)
Definition: String.c:72
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
RETURN_STATUS(EFIAPI * VARIABLE_SERIALIZATION_ITERATION_CALLBACK)(IN VOID *Context, IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, IN UINT32 Attributes, IN UINTN DataSize, IN VOID *Data)
EFI_RUNTIME_SERVICES * gRT
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define RETURN_BUFFER_TOO_SMALL
Definition: Base.h:1093
#define STATIC
Definition: Base.h:264
#define RETURN_ERROR(StatusCode)
Definition: Base.h:1061
#define RETURN_OUT_OF_RESOURCES
Definition: Base.h:1114
#define RETURN_SUCCESS
Definition: Base.h:1066
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define RETURN_INVALID_PARAMETER
Definition: Base.h:1076
#define DEBUG(Expression)
Definition: DebugLib.h:434
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
RETURN_STATUS EFIAPI SerializeVariablesIterateSystemVariables(IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK CallbackFunction, IN VOID *Context)
RETURN_STATUS EFIAPI SerializeVariablesFreeInstance(IN EFI_HANDLE Handle)
RETURN_STATUS EFIAPI SerializeVariablesNewInstanceFromBuffer(OUT EFI_HANDLE *Handle, IN VOID *Buffer, IN UINTN Size)
RETURN_STATUS EFIAPI SerializeVariablesAddVariable(IN EFI_HANDLE Handle, IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, IN UINT32 Attributes, IN UINTN DataSize, IN VOID *Data)
RETURN_STATUS EFIAPI SerializeVariablesToBuffer(IN EFI_HANDLE Handle, OUT VOID *Buffer, IN OUT UINTN *Size)
RETURN_STATUS EFIAPI SerializeVariablesNewInstance(OUT EFI_HANDLE *Handle)
STATIC EFI_STATUS IterateVariablesInBuffer(IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK CallbackFunction, IN VOID *CallbackContext, IN VOID *Buffer, IN UINTN MaxSize)
RETURN_STATUS EFIAPI SerializeVariablesSetSerializedVariables(IN EFI_HANDLE Handle)
RETURN_STATUS EFIAPI SerializeVariablesIterateInstanceVariables(IN EFI_HANDLE Handle, IN VARIABLE_SERIALIZATION_ITERATION_CALLBACK CallbackFunction, IN VOID *Context)
STATIC 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)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
GUID EFI_GUID
Definition: UefiBaseType.h:25
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
VOID EFIAPI CallbackFunction(IN EFI_EVENT Event, IN VOID *Context)
Definition: UsbCdcEcm.c:230
Definition: Base.h:213