]>
Commit | Line | Data |
---|---|---|
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;\r | |
288 | STATIC CONST UINT32 AuthMask =\r | |
289 | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS |\r | |
290 | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;\r | |
291 | \r | |
292 | Status = gRT->SetVariable (\r | |
293 | VariableName,\r | |
294 | VendorGuid,\r | |
295 | Attributes,\r | |
296 | DataSize,\r | |
297 | Data\r | |
298 | );\r | |
299 | \r | |
300 | if (Status == EFI_SECURITY_VIOLATION && (Attributes & AuthMask) != 0) {\r | |
301 | DEBUG ((DEBUG_WARN, "%a: setting authenticated variable \"%s\" "\r | |
302 | "failed with EFI_SECURITY_VIOLATION, ignoring\n", __FUNCTION__,\r | |
303 | VariableName));\r | |
304 | Status = EFI_SUCCESS;\r | |
305 | }\r | |
306 | return Status;\r | |
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 |