var.c 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360
  1. /*++
  2. Copyright (c) 2014 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. var.c
  5. Abstract:
  6. This module implements UEFI runtime core variable services.
  7. Author:
  8. Evan Green 18-Mar-2014
  9. Environment:
  10. Firmware
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include "rtlib.h"
  16. #include "varback.h"
  17. //
  18. // ---------------------------------------------------------------- Definitions
  19. //
  20. #define EFI_VARIABLE_HEADER_MAGIC 0x73726156
  21. #define EFI_VARIABLE_HEADER_VERSION 0x00010000
  22. //
  23. // Define the default allocation size for EFI variable storages.
  24. //
  25. #define EFI_DEFAULT_VARIABLE_SPACE_PAGE_COUNT 0x10
  26. //
  27. // Define the size of the header to CRC.
  28. //
  29. #define EFI_VARIABLE_HEADER_CRC_SIZE OFFSET_OF(EFI_VARIABLE_HEADER, HeaderCrc32)
  30. //
  31. // This flag is set if the variable storage area has been written to but not
  32. // flushed to non-volatile storage.
  33. //
  34. #define EFI_VARIABLE_FLAG_DIRTY 0x00000001
  35. //
  36. // ------------------------------------------------------ Data Type Definitions
  37. //
  38. /*++
  39. Structure Description:
  40. This structure sits at the head of the variable storage area.
  41. Members:
  42. Magic - Stores the constant value EFI_VARIABLE_HEADER_MAGIC.
  43. Version - Stores the version of the storage format. Set to
  44. EFI_VARIABLE_HEADER_VERSION.
  45. Flags - Stores a bitfield of flags describing the variable state. See
  46. EFI_VARIABLE_FLAG_* definitions.
  47. DataSize - Stores the size of the region of valid data following this
  48. header, including the header itself.
  49. FreeSize - Stores the amount of space that's free data. This may not be
  50. contiguous.
  51. HeaderCrc32 - Stores the CRC32 of the header, up to this field. Use the
  52. EFI_VARIABLE_HEADER_CRC_SIZE define.
  53. DataCrc32 - Stores the CRC32 of the data portion, not including this header.
  54. --*/
  55. typedef struct _EFI_VARIABLE_HEADER {
  56. UINT32 Magic;
  57. UINT32 Version;
  58. UINT32 Flags;
  59. UINT32 DataSize;
  60. UINT32 FreeSize;
  61. UINT32 HeaderCrc32;
  62. UINT32 DataCrc32;
  63. } EFI_VARIABLE_HEADER, *PEFI_VARIABLE_HEADER;
  64. /*++
  65. Structure Description:
  66. This structure defines the layout of an EFI variable. This structure
  67. is laid out in an array, but there's variable length data off the end of
  68. each structure.
  69. Members:
  70. VendorGuid - Stores the vendor GUID of the variable.
  71. Attributes - Stores the variable attributes.
  72. NameSize - Stores the size of the name that immediately follows this
  73. structure, in bytes, including the null terminator.
  74. DataSize - Stores the size of the data that immediately follows the name
  75. data, in bytes.
  76. --*/
  77. typedef struct _EFI_VARIABLE_ENTRY {
  78. EFI_GUID VendorGuid;
  79. UINT32 Attributes;
  80. UINT32 NameSize;
  81. UINT32 DataSize;
  82. } EFI_VARIABLE_ENTRY, *PEFI_VARIABLE_ENTRY;
  83. //
  84. // ----------------------------------------------- Internal Function Prototypes
  85. //
  86. EFI_STATUS
  87. EfiVariableBackendSetData (
  88. EFI_VARIABLE_BACKEND_PROTOCOL *This,
  89. VOID *Data,
  90. UINTN DataSize,
  91. BOOLEAN Replace
  92. );
  93. EFIAPI
  94. EFI_STATUS
  95. EfiVariableBackendGetData (
  96. EFI_VARIABLE_BACKEND_PROTOCOL *This,
  97. VOID **Data,
  98. UINTN *DataSize
  99. );
  100. BOOLEAN
  101. EfipValidateVariableSpace (
  102. PEFI_VARIABLE_HEADER Header,
  103. UINTN TotalSize
  104. );
  105. EFI_STATUS
  106. EfipWriteVariableData (
  107. PEFI_VARIABLE_HEADER Header
  108. );
  109. EFI_STATUS
  110. EfipSetVariableDataCrc (
  111. PEFI_VARIABLE_HEADER Header
  112. );
  113. PEFI_VARIABLE_ENTRY
  114. EfipCoreGetVariableEntry (
  115. CHAR16 *VariableName,
  116. EFI_GUID *VendorGuid,
  117. VOID **Data
  118. );
  119. VOID
  120. EfipCoreDeleteVariableEntry (
  121. PEFI_VARIABLE_ENTRY Entry
  122. );
  123. PEFI_VARIABLE_ENTRY
  124. EfipCoreAddVariableEntry (
  125. CHAR16 *VariableName,
  126. EFI_GUID *VendorGuid,
  127. UINT32 Attributes,
  128. UINTN DataSize,
  129. VOID *Data
  130. );
  131. //
  132. // -------------------------------------------------------------------- Globals
  133. //
  134. //
  135. // Define the space reserved for EFI variables. This can be overridden by the
  136. // platform-specific portion of the binary.
  137. //
  138. UINTN EfiVariableAllocationPageCount = EFI_DEFAULT_VARIABLE_SPACE_PAGE_COUNT;
  139. //
  140. // Define the physical address for variable storage. If zero, any pages are
  141. // allocated. The platform-specific code can set this to reserve a region of
  142. // memory just for variables.
  143. //
  144. EFI_PHYSICAL_ADDRESS EfiVariableAllocationAddress = 0;
  145. //
  146. // Define the pointer to the variable region.
  147. //
  148. PEFI_VARIABLE_HEADER EfiVariableHeader;
  149. PEFI_VARIABLE_ENTRY EfiVariableEnd;
  150. PEFI_VARIABLE_ENTRY EfiVariableNextFree;
  151. //
  152. // Remember if the variables have changed.
  153. //
  154. BOOLEAN EfiVariablesChanged = FALSE;
  155. //
  156. // Store the single instance of the variable backend protocol.
  157. //
  158. EFI_GUID EfiVariableBackendProtocolGuid = EFI_VARIABLE_BACKEND_PROTOCOL_GUID;
  159. EFI_VARIABLE_BACKEND_PROTOCOL EfiVariableBackendProtocol = {
  160. EfiVariableBackendSetData,
  161. EfiVariableBackendGetData
  162. };
  163. EFI_HANDLE EfiVariableBackendHandle;
  164. //
  165. // ------------------------------------------------------------------ Functions
  166. //
  167. EFIAPI
  168. EFI_STATUS
  169. EfiCoreSetVariable (
  170. CHAR16 *VariableName,
  171. EFI_GUID *VendorGuid,
  172. UINT32 Attributes,
  173. UINTN DataSize,
  174. VOID *Data
  175. )
  176. /*++
  177. Routine Description:
  178. This routine sets the value of a variable.
  179. Arguments:
  180. VariableName - Supplies a pointer to a null-terminated string containing
  181. the name of the vendor's variable. Each variable name is unique for a
  182. particular vendor GUID. A variable name must be at least one character
  183. in length.
  184. VendorGuid - Supplies a pointer to the unique GUID for the vendor.
  185. Attributes - Supplies the attributes for this variable. See EFI_VARIABLE_*
  186. definitions.
  187. DataSize - Supplies the size of the data buffer. Unless the
  188. EFI_VARIABLE_APPEND_WRITE, EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, or
  189. EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS attribute is set, a
  190. size of zero causes the variable to be deleted. When the
  191. EFI_VARIABLE_APPEND_WRITE attribute is set, then a set variable call
  192. with a data size of zero will not cause any change to the variable
  193. value (the timestamp associated with the variable may be updated
  194. however even if no new data value is provided,see the description of
  195. the EFI_VARIABLE_AUTHENTICATION_2 descriptor below. In this case the
  196. data size will not be zero since the EFI_VARIABLE_AUTHENTICATION_2
  197. descriptor will be populated).
  198. Data - Supplies the contents of the variable.
  199. Return Value:
  200. EFI_SUCCESS on success.
  201. EFI_NOT_FOUND if the variable being updated or deleted was not found.
  202. EFI_INVALID_PARAMETER if an invalid combination of attribute bits, name,
  203. and GUID was suplied, data size exceeds the maximum, or the variable name
  204. is an empty string.
  205. EFI_DEVICE_ERROR if a hardware error occurred trying to access the variable.
  206. EFI_WRITE_PROTECTED if the variable is read-only or cannot be deleted.
  207. EFI_SECURITY_VIOLATION if variable could not be written due to
  208. EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS or
  209. EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACESS being set, but the
  210. authorization information does NOT pass the validation check carried out by
  211. the firmware.
  212. --*/
  213. {
  214. PEFI_VARIABLE_ENTRY Entry;
  215. VOID *InternalData;
  216. if ((EfiIsAtRuntime() != FALSE) &&
  217. ((Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) {
  218. return EFI_NOT_FOUND;
  219. }
  220. Entry = EfipCoreGetVariableEntry(VariableName, VendorGuid, &InternalData);
  221. if (Entry == NULL) {
  222. if (DataSize == 0) {
  223. return EFI_NOT_FOUND;
  224. }
  225. Entry = EfipCoreAddVariableEntry(VariableName,
  226. VendorGuid,
  227. Attributes,
  228. DataSize,
  229. Data);
  230. if (Entry == NULL) {
  231. return EFI_OUT_OF_RESOURCES;
  232. }
  233. //
  234. // The variable is there and has a zero size, so delete it.
  235. //
  236. } else if (DataSize == 0) {
  237. EfipCoreDeleteVariableEntry(Entry);
  238. //
  239. // The variable data size hasn't changed, so just smash over the data.
  240. //
  241. } else if (DataSize == Entry->DataSize) {
  242. Entry->Attributes |= Attributes;
  243. EfiCoreCopyMemory(InternalData, Data, DataSize);
  244. EfiVariableHeader->Flags |= EFI_VARIABLE_FLAG_DIRTY;
  245. EfiVariablesChanged = TRUE;
  246. //
  247. // Delete the entry and add it back. Don't lose the old attributes.
  248. //
  249. } else {
  250. Attributes |= Entry->Attributes;
  251. EfipCoreDeleteVariableEntry(Entry);
  252. Entry = EfipCoreAddVariableEntry(VariableName,
  253. VendorGuid,
  254. Attributes,
  255. DataSize,
  256. Data);
  257. if (Entry == NULL) {
  258. return EFI_OUT_OF_RESOURCES;
  259. }
  260. }
  261. //
  262. // If at runtime, try to write this out to non-volatile storage immediately.
  263. //
  264. if (EfiIsAtRuntime() != FALSE) {
  265. EfipWriteVariableData(EfiVariableHeader);
  266. }
  267. return EFI_SUCCESS;
  268. }
  269. EFIAPI
  270. EFI_STATUS
  271. EfiCoreGetNextVariableName (
  272. UINTN *VariableNameSize,
  273. CHAR16 *VariableName,
  274. EFI_GUID *VendorGuid
  275. )
  276. /*++
  277. Routine Description:
  278. This routine enumerates the current variable names.
  279. Arguments:
  280. VariableNameSize - Supplies a pointer that on input contains the size of
  281. the variable name buffer. On output, will contain the size of the
  282. variable name.
  283. VariableName - Supplies a pointer that on input contains the last variable
  284. name that was returned. On output, returns the null terminated string
  285. of the current variable.
  286. VendorGuid - Supplies a pointer that on input contains the last vendor GUID
  287. returned by this routine. On output, returns the vendor GUID of the
  288. current variable.
  289. Return Value:
  290. EFI_SUCCESS on success.
  291. EFI_NOT_FOUND if the next variable was not found.
  292. EFI_BUFFER_TOO_SMALL if the supplied buffer is not big enough.
  293. EFI_INVALID_PARAMETER if the variable name, vendor GUID, or data size is
  294. NULL.
  295. EFI_DEVICE_ERROR if a hardware error occurred trying to read the variable.
  296. --*/
  297. {
  298. BOOLEAN Done;
  299. PEFI_VARIABLE_ENTRY Entry;
  300. VOID *InternalData;
  301. UINTN StringSize;
  302. Done = FALSE;
  303. while (Done == FALSE) {
  304. Entry = EfipCoreGetVariableEntry(VariableName,
  305. VendorGuid,
  306. &InternalData);
  307. if (Entry == NULL) {
  308. return EFI_NOT_FOUND;
  309. }
  310. //
  311. // If at runtime and the variable doesn't have runtime access, skip it.
  312. //
  313. Done = TRUE;
  314. if ((EfiIsAtRuntime() != FALSE) &&
  315. ((Entry->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0)) {
  316. Done = FALSE;
  317. }
  318. }
  319. StringSize = Entry->NameSize;
  320. Entry = (PEFI_VARIABLE_ENTRY)((UINT8 *)Entry +
  321. sizeof(EFI_VARIABLE_ENTRY) +
  322. StringSize +
  323. Entry->DataSize);
  324. if (Entry >= EfiVariableEnd) {
  325. return EFI_NOT_FOUND;
  326. }
  327. if (*VariableNameSize < StringSize) {
  328. *VariableNameSize = StringSize;
  329. return EFI_BUFFER_TOO_SMALL;
  330. }
  331. *VariableNameSize = StringSize;
  332. EfiCoreCopyMemory(VariableName, (CHAR16 *)(Entry + 1), StringSize);
  333. EfiCoreCopyMemory(VendorGuid, &(Entry->VendorGuid), sizeof(EFI_GUID));
  334. return EFI_SUCCESS;
  335. }
  336. EFIAPI
  337. EFI_STATUS
  338. EfiCoreGetVariable (
  339. CHAR16 *VariableName,
  340. EFI_GUID *VendorGuid,
  341. UINT32 *Attributes,
  342. UINTN *DataSize,
  343. VOID *Data
  344. )
  345. /*++
  346. Routine Description:
  347. This routine returns the value of a variable.
  348. Arguments:
  349. VariableName - Supplies a pointer to a null-terminated string containing
  350. the name of the vendor's variable.
  351. VendorGuid - Supplies a pointer to the unique GUID for the vendor.
  352. Attributes - Supplies an optional pointer where the attribute mask for the
  353. variable will be returned.
  354. DataSize - Supplies a pointer that on input contains the size of the data
  355. buffer. On output, the actual size of the data will be returned.
  356. Data - Supplies a pointer where the variable value will be returned.
  357. Return Value:
  358. EFI_SUCCESS on success.
  359. EFI_NOT_FOUND if the variable was not found.
  360. EFI_BUFFER_TOO_SMALL if the supplied buffer is not big enough.
  361. EFI_INVALID_PARAMETER if the variable name, vendor GUID, or data size is
  362. NULL.
  363. EFI_DEVICE_ERROR if a hardware error occurred trying to read the variable.
  364. EFI_SECURITY_VIOLATION if the variable could not be retrieved due to an
  365. authentication failure.
  366. --*/
  367. {
  368. PEFI_VARIABLE_ENTRY Entry;
  369. VOID *InternalData;
  370. if ((EfiIsAtRuntime() != FALSE) && (Attributes != NULL)) {
  371. if ((*Attributes & EFI_VARIABLE_RUNTIME_ACCESS) == 0) {
  372. return EFI_NOT_FOUND;
  373. }
  374. }
  375. Entry = EfipCoreGetVariableEntry(VariableName, VendorGuid, &InternalData);
  376. if (Entry == NULL) {
  377. return EFI_NOT_FOUND;
  378. }
  379. if (*DataSize < Entry->DataSize) {
  380. *DataSize = Entry->DataSize;
  381. return EFI_BUFFER_TOO_SMALL;
  382. }
  383. *DataSize = Entry->DataSize;
  384. if (Attributes != NULL) {
  385. *Attributes = Entry->Attributes;
  386. }
  387. EfiCoreCopyMemory(Data, InternalData, *DataSize);
  388. return EFI_SUCCESS;
  389. }
  390. EFIAPI
  391. EFI_STATUS
  392. EfiCoreQueryVariableInfo (
  393. UINT32 Attributes,
  394. UINT64 *MaximumVariableStorageSize,
  395. UINT64 *RemainingVariableStorageSize,
  396. UINT64 *MaximumVariableSize
  397. )
  398. /*++
  399. Routine Description:
  400. This routine returns information about EFI variables.
  401. Arguments:
  402. Attributes - Supplies a bitmask of attributes specifying the type of
  403. variables on which to return information.
  404. MaximumVariableStorageSize - Supplies a pointer where the maximum size of
  405. storage space for EFI variables with the given attributes will be
  406. returned.
  407. RemainingVariableStorageSize - Supplies a pointer where the remaining size
  408. of the storage space available for EFI variables associated with the
  409. attributes specified will be returned.
  410. MaximumVariableSize - Supplies a pointer where the maximum size of an
  411. individual variable will be returned on success.
  412. Return Value:
  413. EFI_SUCCESS if a valid answer was returned.
  414. EFI_UNSUPPORTED if the attribute is not supported on this platform.
  415. EFI_INVALID_PARAMETER if an invalid combination of attributes was supplied.
  416. --*/
  417. {
  418. if (EfiVariableHeader == NULL) {
  419. return EFI_UNSUPPORTED;
  420. }
  421. *MaximumVariableStorageSize = EfiVariableHeader->DataSize;
  422. *RemainingVariableStorageSize = EfiVariableHeader->FreeSize;
  423. *MaximumVariableSize = EfiVariableHeader->FreeSize;
  424. return EFI_SUCCESS;
  425. }
  426. EFIAPI
  427. EFI_STATUS
  428. EfiCoreFlushVariableData (
  429. VOID
  430. )
  431. /*++
  432. Routine Description:
  433. This routine attempts to write variable data out to non-volatile storage.
  434. Arguments:
  435. None.
  436. Return Value:
  437. EFI status code.
  438. --*/
  439. {
  440. if (EfiVariableHeader == NULL) {
  441. return EFI_NOT_READY;
  442. }
  443. return EfipWriteVariableData(EfiVariableHeader);
  444. }
  445. EFI_STATUS
  446. EfipCoreInitializeVariableServices (
  447. VOID
  448. )
  449. /*++
  450. Routine Description:
  451. This routine initialize core variable services.
  452. Arguments:
  453. None.
  454. Return Value:
  455. EFI Status code.
  456. --*/
  457. {
  458. EFI_PHYSICAL_ADDRESS Address;
  459. UINTN FreeOffset;
  460. PEFI_VARIABLE_HEADER Header;
  461. EFI_STATUS Status;
  462. UINTN TotalSize;
  463. EFI_ALLOCATE_TYPE Type;
  464. Address = 0;
  465. if (EfiVariableAllocationAddress != 0) {
  466. Type = AllocateAddress;
  467. Address = EfiVariableAllocationAddress;
  468. } else {
  469. Type = AllocateAnyPages;
  470. }
  471. if (EfiVariableAllocationPageCount == 0) {
  472. return EFI_UNSUPPORTED;
  473. }
  474. Status = EfiAllocatePages(Type,
  475. EfiRuntimeServicesData,
  476. EfiVariableAllocationPageCount,
  477. &Address);
  478. if (EFI_ERROR(Status)) {
  479. return Status;
  480. }
  481. Header = (PEFI_VARIABLE_HEADER)(UINTN)Address;
  482. TotalSize = EfiVariableAllocationPageCount << EFI_PAGE_SHIFT;
  483. EfiVariableHeader = Header;
  484. EfiVariableEnd = (PEFI_VARIABLE_ENTRY)((UINT8 *)Header + TotalSize);
  485. EfiVariableNextFree = (PEFI_VARIABLE_ENTRY)(Header + 1);
  486. //
  487. // Look to see if there's already valid data in this region. If it's dirty,
  488. // try to write it out right now, as it may have come from a previous boot.
  489. //
  490. if (EfipValidateVariableSpace(Header, TotalSize) != FALSE) {
  491. if ((Header->Flags & EFI_VARIABLE_FLAG_DIRTY) != 0) {
  492. EfipWriteVariableData(Header);
  493. }
  494. //
  495. // Find the next free entry.
  496. //
  497. FreeOffset = Header->DataSize -
  498. sizeof(EFI_VARIABLE_HEADER) - Header->FreeSize;
  499. EfiVariableNextFree =
  500. (PEFI_VARIABLE_ENTRY)(((UINT8 *)(Header + 1)) + FreeOffset);
  501. Status = EFI_SUCCESS;
  502. goto InitializeVariableServicesEnd;
  503. }
  504. //
  505. // Try to read from non-volatile storage. If it worked and it's valid, then
  506. // use it.
  507. //
  508. Status = EfiPlatformReadNonVolatileData(Header, TotalSize);
  509. if (!EFI_ERROR(Status)) {
  510. if (EfipValidateVariableSpace(Header, TotalSize) != FALSE) {
  511. //
  512. // The dirty flag really should already be cleared, but clear it
  513. // anyway.
  514. //
  515. if ((Header->Flags & EFI_VARIABLE_FLAG_DIRTY) != 0) {
  516. Header->Flags &= ~EFI_VARIABLE_FLAG_DIRTY;
  517. EfiVariablesChanged = TRUE;
  518. }
  519. //
  520. // Find the next free entry.
  521. //
  522. FreeOffset = Header->DataSize -
  523. sizeof(EFI_VARIABLE_HEADER) - Header->FreeSize;
  524. EfiVariableNextFree =
  525. (PEFI_VARIABLE_ENTRY)(((UINT8 *)(Header + 1)) + FreeOffset);
  526. Status = EFI_SUCCESS;
  527. goto InitializeVariableServicesEnd;
  528. }
  529. }
  530. //
  531. // Initialize the variable area to be empty.
  532. //
  533. EfiSetMem(Header, TotalSize, 0);
  534. Header->Magic = EFI_VARIABLE_HEADER_MAGIC;
  535. Header->Version = EFI_VARIABLE_HEADER_VERSION;
  536. Header->Flags = 0;
  537. Header->DataSize = TotalSize;
  538. Header->FreeSize = TotalSize - sizeof(EFI_VARIABLE_HEADER);
  539. Header->HeaderCrc32 = 0;
  540. Header->DataCrc32 = 0;
  541. EfiVariablesChanged = TRUE;
  542. Status = EFI_SUCCESS;
  543. InitializeVariableServicesEnd:
  544. //
  545. // If everything worked, publish the variable backend protocol.
  546. //
  547. if (!EFI_ERROR(Status)) {
  548. Status = EfiInstallMultipleProtocolInterfaces(
  549. &EfiVariableBackendHandle,
  550. &EfiVariableBackendProtocolGuid,
  551. &EfiVariableBackendProtocol,
  552. NULL);
  553. }
  554. return Status;
  555. }
  556. VOID
  557. EfipCoreVariableHandleExitBootServices (
  558. VOID
  559. )
  560. /*++
  561. Routine Description:
  562. This routine is called when leaving boot services.
  563. Arguments:
  564. None.
  565. Return Value:
  566. None.
  567. --*/
  568. {
  569. EfipWriteVariableData(EfiVariableHeader);
  570. return;
  571. }
  572. VOID
  573. EfipCoreVariableHandleVirtualAddressChange (
  574. VOID
  575. )
  576. /*++
  577. Routine Description:
  578. This routine is called to change from physical to virtual mode.
  579. Arguments:
  580. None.
  581. Return Value:
  582. None.
  583. --*/
  584. {
  585. //
  586. // Not so bad, eh?
  587. //
  588. EfiConvertPointer(0, (VOID **)&EfiVariableHeader);
  589. EfiConvertPointer(0, (VOID **)&EfiVariableNextFree);
  590. EfiConvertPointer(0, (VOID **)&EfiVariableEnd);
  591. return;
  592. }
  593. //
  594. // --------------------------------------------------------- Internal Functions
  595. //
  596. EFI_STATUS
  597. EfiVariableBackendSetData (
  598. EFI_VARIABLE_BACKEND_PROTOCOL *This,
  599. VOID *Data,
  600. UINTN DataSize,
  601. BOOLEAN Replace
  602. )
  603. /*++
  604. Routine Description:
  605. This routine adds or replaces the current EFI variables with the given
  606. serialized variable buffer.
  607. Arguments:
  608. This - Supplies a pointer to the protocol instance.
  609. Data - Supplies a pointer to the serialized EFI variable data.
  610. DataSize - Supplies the size of the data buffer in bytes.
  611. Replace - Supplies a boolean indicating if the contents of this buffer
  612. should be merged with the current variables (FALSE) or if all current
  613. variables should be destroyed before adding these (TRUE).
  614. Return Value:
  615. EFI status code.
  616. --*/
  617. {
  618. PEFI_VARIABLE_ENTRY End;
  619. PEFI_VARIABLE_ENTRY Entry;
  620. PEFI_VARIABLE_HEADER Header;
  621. BOOLEAN Valid;
  622. VOID *VariableData;
  623. Valid = EfipValidateVariableSpace(Data, DataSize);
  624. if (Valid == FALSE) {
  625. return EFI_COMPROMISED_DATA;
  626. }
  627. if (Replace != FALSE) {
  628. EfiVariableHeader->FreeSize = EfiVariableHeader->DataSize;
  629. EfiVariablesChanged = TRUE;
  630. EfiVariableHeader->Flags |= EFI_VARIABLE_FLAG_DIRTY;
  631. EfiVariableNextFree = (PEFI_VARIABLE_ENTRY)(EfiVariableHeader + 1);
  632. }
  633. Header = Data;
  634. Entry = (PEFI_VARIABLE_ENTRY)(Header + 1);
  635. End = (PEFI_VARIABLE_ENTRY)((UINTN)Entry +
  636. (Header->DataSize - Header->FreeSize));
  637. while (Entry + 1 <= End) {
  638. if ((Entry->NameSize == 0) || (Entry->DataSize == 0)) {
  639. break;
  640. }
  641. VariableData = (UINT8 *)(Entry + 1) + Entry->NameSize;
  642. if (VariableData + Entry->DataSize > (VOID *)End) {
  643. break;
  644. }
  645. EfiCoreSetVariable((CHAR16 *)(Entry + 1),
  646. &(Entry->VendorGuid),
  647. Entry->Attributes,
  648. Entry->DataSize,
  649. VariableData);
  650. Entry = (PEFI_VARIABLE_ENTRY)(VariableData + Entry->DataSize);
  651. Entry = ALIGN_POINTER(Entry, 4);
  652. }
  653. return EFI_SUCCESS;
  654. }
  655. EFIAPI
  656. EFI_STATUS
  657. EfiVariableBackendGetData (
  658. EFI_VARIABLE_BACKEND_PROTOCOL *This,
  659. VOID **Data,
  660. UINTN *DataSize
  661. )
  662. /*++
  663. Routine Description:
  664. This routine returns a serialized form of the given variables. The caller
  665. must ensure no variable changes are made while using this buffer.
  666. Arguments:
  667. This - Supplies a pointer to the protocol instance.
  668. Data - Supplies a pointer where a pointer will be returned to the
  669. serialized variable data. This data may be live, so the caller may not
  670. modify it.
  671. DataSize - Supplies a pointer where the size of the data will be returned
  672. on success.
  673. Return Value:
  674. EFI status code.
  675. --*/
  676. {
  677. if ((Data == NULL) || (DataSize == NULL)) {
  678. return EFI_INVALID_PARAMETER;
  679. }
  680. if ((EfiVariableHeader == NULL) || (EfiVariableEnd == NULL)) {
  681. return EFI_NOT_READY;
  682. }
  683. EfipSetVariableDataCrc(EfiVariableHeader);
  684. *Data = EfiVariableHeader;
  685. *DataSize = (UINTN)EfiVariableEnd - (UINTN)EfiVariableHeader;
  686. return EFI_SUCCESS;
  687. }
  688. BOOLEAN
  689. EfipValidateVariableSpace (
  690. PEFI_VARIABLE_HEADER Header,
  691. UINTN TotalSize
  692. )
  693. /*++
  694. Routine Description:
  695. This routine validates the EFI variable region.
  696. Arguments:
  697. Header - Supplies a pointer to the header to validate.
  698. TotalSize - Supplies the total size in bytes of the variable region.
  699. Return Value:
  700. TRUE if the variable region is valid.
  701. FALSE if the variable region is not valid.
  702. --*/
  703. {
  704. UINT32 ComputedCrc;
  705. EFI_STATUS Status;
  706. if (TotalSize < sizeof(EFI_VARIABLE_HEADER)) {
  707. return FALSE;
  708. }
  709. if ((Header->Magic != EFI_VARIABLE_HEADER_MAGIC) ||
  710. (Header->Version != EFI_VARIABLE_HEADER_VERSION)) {
  711. return FALSE;
  712. }
  713. //
  714. // Compute the header CRC before examining the length.
  715. //
  716. Status = EfiCalculateCrc32(Header,
  717. EFI_VARIABLE_HEADER_CRC_SIZE,
  718. &ComputedCrc);
  719. if ((EFI_ERROR(Status)) || (ComputedCrc != Header->HeaderCrc32)) {
  720. return FALSE;
  721. }
  722. //
  723. // Compute the CRC of the data.
  724. //
  725. if (Header->DataSize > TotalSize) {
  726. return FALSE;
  727. }
  728. if (Header->FreeSize > Header->DataSize) {
  729. return FALSE;
  730. }
  731. EfiCalculateCrc32(Header + 1,
  732. Header->DataSize - sizeof(EFI_VARIABLE_HEADER),
  733. &ComputedCrc);
  734. if (Header->DataCrc32 != ComputedCrc) {
  735. return FALSE;
  736. }
  737. return TRUE;
  738. }
  739. EFI_STATUS
  740. EfipWriteVariableData (
  741. PEFI_VARIABLE_HEADER Header
  742. )
  743. /*++
  744. Routine Description:
  745. This routine attempts to write the variable data to a non-volatile platform
  746. area.
  747. Arguments:
  748. Header - Supplies a pointer to the data.
  749. Return Value:
  750. EFI status code.
  751. --*/
  752. {
  753. EFI_STATUS Status;
  754. //
  755. // Mark the variable region as clean for the flush out to storage.
  756. //
  757. if ((Header->Flags & EFI_VARIABLE_FLAG_DIRTY) != 0) {
  758. Header->Flags &= ~EFI_VARIABLE_FLAG_DIRTY;
  759. EfiVariablesChanged = TRUE;
  760. }
  761. //
  762. // If nothing has changed then return successfully.
  763. //
  764. if (EfiVariablesChanged == FALSE) {
  765. return EFI_SUCCESS;
  766. }
  767. //
  768. // Recompute the CRCs if anything has changed.
  769. //
  770. Status = EfipSetVariableDataCrc(Header);
  771. if (EFI_ERROR(Status)) {
  772. Header->Flags |= EFI_VARIABLE_FLAG_DIRTY;
  773. return Status;
  774. }
  775. Status = EfiPlatformWriteNonVolatileData(Header, Header->DataSize);
  776. if (EFI_ERROR(Status)) {
  777. Header->Flags |= EFI_VARIABLE_FLAG_DIRTY;
  778. } else {
  779. EfiVariablesChanged = FALSE;
  780. }
  781. return Status;
  782. }
  783. EFI_STATUS
  784. EfipSetVariableDataCrc (
  785. PEFI_VARIABLE_HEADER Header
  786. )
  787. /*++
  788. Routine Description:
  789. This routine writes the CRC of the current variable data.
  790. Arguments:
  791. Header - Supplies a pointer to the data.
  792. Return Value:
  793. EFI status code.
  794. --*/
  795. {
  796. UINT32 OriginalCrc;
  797. EFI_STATUS Status;
  798. //
  799. // Recompute the CRCs if anything has changed.
  800. //
  801. OriginalCrc = Header->HeaderCrc32;
  802. Header->HeaderCrc32 = 0;
  803. Status = EfiCoreCalculateCrc32(Header,
  804. EFI_VARIABLE_HEADER_CRC_SIZE,
  805. &(Header->HeaderCrc32));
  806. if (EFI_ERROR(Status)) {
  807. Header->HeaderCrc32 = OriginalCrc;
  808. return Status;
  809. }
  810. Header->DataCrc32 = 0;
  811. Status = EfiCoreCalculateCrc32(
  812. Header + 1,
  813. Header->DataSize - sizeof(EFI_VARIABLE_HEADER),
  814. &(Header->DataCrc32));
  815. return Status;
  816. }
  817. PEFI_VARIABLE_ENTRY
  818. EfipCoreGetVariableEntry (
  819. CHAR16 *VariableName,
  820. EFI_GUID *VendorGuid,
  821. VOID **Data
  822. )
  823. /*++
  824. Routine Description:
  825. This routine returns the variable entry corresponding with the given name
  826. and vendor GUID.
  827. Arguments:
  828. VariableName - Supplies a pointer to the variable name to find.
  829. VendorGuid - Supplies a pointer to the vendor GUID to find.
  830. Data - Supplies a pointer where the variable data pointer will be
  831. returned.
  832. Return Value:
  833. Returns a pointer to the variable entry on success.
  834. NULL if not found.
  835. --*/
  836. {
  837. INTN CompareResult;
  838. PEFI_VARIABLE_ENTRY Entry;
  839. UINTN Size;
  840. //
  841. // The first entry is a null terminated string.
  842. //
  843. Entry = (PEFI_VARIABLE_ENTRY)(EfiVariableHeader + 1);
  844. if (*VariableName == L'\0') {
  845. if (Entry == EfiVariableNextFree) {
  846. return NULL;
  847. }
  848. return Entry;
  849. }
  850. while (Entry + 1 <= EfiVariableNextFree) {
  851. if ((Entry->DataSize != 0) &&
  852. (EfiCoreCompareGuids(VendorGuid, &(Entry->VendorGuid)) != FALSE)) {
  853. CompareResult = EfiCoreCompareMemory(VariableName,
  854. (CHAR16 *)(Entry + 1),
  855. Entry->NameSize);
  856. if (CompareResult == 0) {
  857. *Data = (VOID *)((UINT8 *)Entry +
  858. sizeof(EFI_VARIABLE_ENTRY) +
  859. Entry->NameSize);
  860. return Entry;
  861. }
  862. }
  863. Size = sizeof(EFI_VARIABLE_ENTRY) + Entry->NameSize + Entry->DataSize;
  864. Size = ALIGN_VALUE(Size, 4);
  865. Entry = (PEFI_VARIABLE_ENTRY)((UINT8 *)Entry + Size);
  866. }
  867. return NULL;
  868. }
  869. VOID
  870. EfipCoreDeleteVariableEntry (
  871. PEFI_VARIABLE_ENTRY Entry
  872. )
  873. /*++
  874. Routine Description:
  875. This routine deletes the given variable entry.
  876. Arguments:
  877. Entry - Supplies a pointer to the variable entry to delete.
  878. Return Value:
  879. None.
  880. --*/
  881. {
  882. EFI_TPL CurrentTpl;
  883. UINT8 *Data;
  884. UINTN Size;
  885. CurrentTpl = TPL_HIGH_LEVEL;
  886. Size = sizeof(EFI_VARIABLE_ENTRY) + Entry->NameSize + Entry->DataSize;
  887. Size = ALIGN_VALUE(Size, 4);
  888. Data = ((UINT8 *)Entry) + Size;
  889. EfiCoreCopyMemory(Entry, Data, (UINTN)EfiVariableNextFree - (UINTN)Data);
  890. if (EfiIsAtRuntime() == FALSE) {
  891. CurrentTpl = EfiRaiseTPL(TPL_HIGH_LEVEL);
  892. }
  893. EfiVariableHeader->FreeSize += Size;
  894. EfiVariableNextFree =
  895. (PEFI_VARIABLE_ENTRY)(((UINT8 *)EfiVariableNextFree) - Size);
  896. EfiVariablesChanged = TRUE;
  897. EfiVariableHeader->Flags |= EFI_VARIABLE_FLAG_DIRTY;
  898. if (EfiIsAtRuntime() == FALSE) {
  899. EfiRestoreTPL(CurrentTpl);
  900. }
  901. return;
  902. }
  903. PEFI_VARIABLE_ENTRY
  904. EfipCoreAddVariableEntry (
  905. CHAR16 *VariableName,
  906. EFI_GUID *VendorGuid,
  907. UINT32 Attributes,
  908. UINTN DataSize,
  909. VOID *Data
  910. )
  911. /*++
  912. Routine Description:
  913. This routine adds a new variable entry.
  914. Arguments:
  915. VariableName - Supplies a pointer to a null-terminated string containing
  916. the name of the vendor's variable. Each variable name is unique for a
  917. particular vendor GUID. A variable name must be at least one character
  918. in length.
  919. VendorGuid - Supplies a pointer to the unique GUID for the vendor.
  920. Attributes - Supplies the attributes for this variable. See EFI_VARIABLE_*
  921. definitions.
  922. DataSize - Supplies the size of the data buffer. The size must not be zero.
  923. Data - Supplies the contents of the variable.
  924. Return Value:
  925. Returns a pointer to the new entry on success.
  926. NULL on failure.
  927. --*/
  928. {
  929. PEFI_VARIABLE_ENTRY Entry;
  930. EFI_TPL OldTpl;
  931. UINTN Size;
  932. UINTN StringSize;
  933. StringSize = (EfiCoreStringLength(VariableName) + 1) * sizeof(CHAR16);
  934. Size = sizeof(EFI_VARIABLE_ENTRY) + StringSize + DataSize;
  935. Size = ALIGN_VALUE(Size, 4);
  936. if ((PEFI_VARIABLE_ENTRY)(((UINT8 *)EfiVariableNextFree) + Size) >
  937. EfiVariableEnd) {
  938. return NULL;
  939. }
  940. OldTpl = TPL_HIGH_LEVEL;
  941. if (EfiIsAtRuntime() == FALSE) {
  942. OldTpl = EfiRaiseTPL(TPL_HIGH_LEVEL);
  943. }
  944. Entry = EfiVariableNextFree;
  945. EfiCoreCopyMemory(&(Entry->VendorGuid), VendorGuid, sizeof(EFI_GUID));
  946. Entry->Attributes = Attributes;
  947. Entry->DataSize = DataSize;
  948. Entry->NameSize = StringSize;
  949. EfiCoreCopyMemory(Entry + 1, VariableName, StringSize);
  950. EfiCoreCopyMemory(((UINT8 *)(Entry + 1)) + Entry->NameSize, Data, DataSize);
  951. EfiVariableNextFree = (PEFI_VARIABLE_ENTRY)(((UINT8 *)Entry) + Size);
  952. EfiVariableHeader->FreeSize -= Size;
  953. EfiVariableHeader->Flags |= EFI_VARIABLE_FLAG_DIRTY;
  954. EfiVariablesChanged = TRUE;
  955. if (EfiIsAtRuntime() == FALSE) {
  956. EfiRestoreTPL(OldTpl);
  957. }
  958. return Entry;
  959. }