SerializeVariablesLib.c 23 KB

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