FwBlockService.c 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135
  1. /**@file
  2. Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
  3. SPDX-License-Identifier: BSD-2-Clause-Patent
  4. Module Name:
  5. FWBlockService.c
  6. Abstract:
  7. Revision History
  8. **/
  9. //
  10. // The protocols, PPI and GUID definitions for this module
  11. //
  12. #include <Protocol/DevicePath.h>
  13. #include <Protocol/FirmwareVolumeBlock.h>
  14. //
  15. // The Library classes this module consumes
  16. //
  17. #include <Library/BaseLib.h>
  18. #include <Library/BaseMemoryLib.h>
  19. #include <Library/DebugLib.h>
  20. #include <Library/DevicePathLib.h>
  21. #include <Library/DxeServicesTableLib.h>
  22. #include <Library/MemoryAllocationLib.h>
  23. #include <Library/UefiBootServicesTableLib.h>
  24. #include "FwBlockService.h"
  25. #include "QemuFlash.h"
  26. #define EFI_FVB2_STATUS \
  27. (EFI_FVB2_READ_STATUS | EFI_FVB2_WRITE_STATUS | EFI_FVB2_LOCK_STATUS)
  28. ESAL_FWB_GLOBAL *mFvbModuleGlobal;
  29. FV_MEMMAP_DEVICE_PATH mFvMemmapDevicePathTemplate = {
  30. {
  31. {
  32. HARDWARE_DEVICE_PATH,
  33. HW_MEMMAP_DP,
  34. {
  35. (UINT8)(sizeof (MEMMAP_DEVICE_PATH)),
  36. (UINT8)(sizeof (MEMMAP_DEVICE_PATH) >> 8)
  37. }
  38. },
  39. EfiMemoryMappedIO,
  40. (EFI_PHYSICAL_ADDRESS)0,
  41. (EFI_PHYSICAL_ADDRESS)0,
  42. },
  43. {
  44. END_DEVICE_PATH_TYPE,
  45. END_ENTIRE_DEVICE_PATH_SUBTYPE,
  46. {
  47. END_DEVICE_PATH_LENGTH,
  48. 0
  49. }
  50. }
  51. };
  52. FV_PIWG_DEVICE_PATH mFvPIWGDevicePathTemplate = {
  53. {
  54. {
  55. MEDIA_DEVICE_PATH,
  56. MEDIA_PIWG_FW_VOL_DP,
  57. {
  58. (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH)),
  59. (UINT8)(sizeof (MEDIA_FW_VOL_DEVICE_PATH) >> 8)
  60. }
  61. },
  62. { 0 }
  63. },
  64. {
  65. END_DEVICE_PATH_TYPE,
  66. END_ENTIRE_DEVICE_PATH_SUBTYPE,
  67. {
  68. END_DEVICE_PATH_LENGTH,
  69. 0
  70. }
  71. }
  72. };
  73. EFI_FW_VOL_BLOCK_DEVICE mFvbDeviceTemplate = {
  74. FVB_DEVICE_SIGNATURE,
  75. NULL,
  76. 0,
  77. {
  78. FvbProtocolGetAttributes,
  79. FvbProtocolSetAttributes,
  80. FvbProtocolGetPhysicalAddress,
  81. FvbProtocolGetBlockSize,
  82. FvbProtocolRead,
  83. FvbProtocolWrite,
  84. FvbProtocolEraseBlocks,
  85. NULL
  86. }
  87. };
  88. EFI_STATUS
  89. GetFvbInstance (
  90. IN UINTN Instance,
  91. IN ESAL_FWB_GLOBAL *Global,
  92. OUT EFI_FW_VOL_INSTANCE **FwhInstance
  93. )
  94. /*++
  95. Routine Description:
  96. Retrieves the physical address of a memory mapped FV
  97. Arguments:
  98. Instance - The FV instance whose base address is going to be
  99. returned
  100. Global - Pointer to ESAL_FWB_GLOBAL that contains all
  101. instance data
  102. FwhInstance - The EFI_FW_VOL_INSTANCE firmware instance structure
  103. Returns:
  104. EFI_SUCCESS - Successfully returns
  105. EFI_INVALID_PARAMETER - Instance not found
  106. --*/
  107. {
  108. EFI_FW_VOL_INSTANCE *FwhRecord;
  109. *FwhInstance = NULL;
  110. if (Instance >= Global->NumFv) {
  111. return EFI_INVALID_PARAMETER;
  112. }
  113. //
  114. // Find the right instance of the FVB private data
  115. //
  116. FwhRecord = Global->FvInstance;
  117. while (Instance > 0) {
  118. FwhRecord = (EFI_FW_VOL_INSTANCE *)
  119. (
  120. (UINTN)((UINT8 *)FwhRecord) + FwhRecord->VolumeHeader.HeaderLength +
  121. (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER))
  122. );
  123. Instance--;
  124. }
  125. *FwhInstance = FwhRecord;
  126. return EFI_SUCCESS;
  127. }
  128. EFI_STATUS
  129. FvbGetPhysicalAddress (
  130. IN UINTN Instance,
  131. OUT EFI_PHYSICAL_ADDRESS *Address,
  132. IN ESAL_FWB_GLOBAL *Global
  133. )
  134. /*++
  135. Routine Description:
  136. Retrieves the physical address of a memory mapped FV
  137. Arguments:
  138. Instance - The FV instance whose base address is going to be
  139. returned
  140. Address - Pointer to a caller allocated EFI_PHYSICAL_ADDRESS
  141. that on successful return, contains the base
  142. address of the firmware volume.
  143. Global - Pointer to ESAL_FWB_GLOBAL that contains all
  144. instance data
  145. Returns:
  146. EFI_SUCCESS - Successfully returns
  147. EFI_INVALID_PARAMETER - Instance not found
  148. --*/
  149. {
  150. EFI_FW_VOL_INSTANCE *FwhInstance;
  151. EFI_STATUS Status;
  152. //
  153. // Find the right instance of the FVB private data
  154. //
  155. Status = GetFvbInstance (Instance, Global, &FwhInstance);
  156. ASSERT_EFI_ERROR (Status);
  157. *Address = FwhInstance->FvBase;
  158. return EFI_SUCCESS;
  159. }
  160. EFI_STATUS
  161. FvbGetVolumeAttributes (
  162. IN UINTN Instance,
  163. OUT EFI_FVB_ATTRIBUTES_2 *Attributes,
  164. IN ESAL_FWB_GLOBAL *Global
  165. )
  166. /*++
  167. Routine Description:
  168. Retrieves attributes, insures positive polarity of attribute bits, returns
  169. resulting attributes in output parameter
  170. Arguments:
  171. Instance - The FV instance whose attributes is going to be
  172. returned
  173. Attributes - Output buffer which contains attributes
  174. Global - Pointer to ESAL_FWB_GLOBAL that contains all
  175. instance data
  176. Returns:
  177. EFI_SUCCESS - Successfully returns
  178. EFI_INVALID_PARAMETER - Instance not found
  179. --*/
  180. {
  181. EFI_FW_VOL_INSTANCE *FwhInstance;
  182. EFI_STATUS Status;
  183. //
  184. // Find the right instance of the FVB private data
  185. //
  186. Status = GetFvbInstance (Instance, Global, &FwhInstance);
  187. ASSERT_EFI_ERROR (Status);
  188. *Attributes = FwhInstance->VolumeHeader.Attributes;
  189. return EFI_SUCCESS;
  190. }
  191. EFI_STATUS
  192. FvbGetLbaAddress (
  193. IN UINTN Instance,
  194. IN EFI_LBA Lba,
  195. OUT UINTN *LbaAddress,
  196. OUT UINTN *LbaLength,
  197. OUT UINTN *NumOfBlocks,
  198. IN ESAL_FWB_GLOBAL *Global
  199. )
  200. /*++
  201. Routine Description:
  202. Retrieves the starting address of an LBA in an FV
  203. Arguments:
  204. Instance - The FV instance which the Lba belongs to
  205. Lba - The logical block address
  206. LbaAddress - On output, contains the physical starting address
  207. of the Lba
  208. LbaLength - On output, contains the length of the block
  209. NumOfBlocks - A pointer to a caller allocated UINTN in which the
  210. number of consecutive blocks starting with Lba is
  211. returned. All blocks in this range have a size of
  212. BlockSize
  213. Global - Pointer to ESAL_FWB_GLOBAL that contains all
  214. instance data
  215. Returns:
  216. EFI_SUCCESS - Successfully returns
  217. EFI_INVALID_PARAMETER - Instance not found
  218. --*/
  219. {
  220. UINT32 NumBlocks;
  221. UINT32 BlockLength;
  222. UINTN Offset;
  223. EFI_LBA StartLba;
  224. EFI_LBA NextLba;
  225. EFI_FW_VOL_INSTANCE *FwhInstance;
  226. EFI_FV_BLOCK_MAP_ENTRY *BlockMap;
  227. EFI_STATUS Status;
  228. //
  229. // Find the right instance of the FVB private data
  230. //
  231. Status = GetFvbInstance (Instance, Global, &FwhInstance);
  232. ASSERT_EFI_ERROR (Status);
  233. StartLba = 0;
  234. Offset = 0;
  235. BlockMap = &(FwhInstance->VolumeHeader.BlockMap[0]);
  236. //
  237. // Parse the blockmap of the FV to find which map entry the Lba belongs to
  238. //
  239. while (TRUE) {
  240. NumBlocks = BlockMap->NumBlocks;
  241. BlockLength = BlockMap->Length;
  242. if ((NumBlocks == 0) || (BlockLength == 0)) {
  243. return EFI_INVALID_PARAMETER;
  244. }
  245. NextLba = StartLba + NumBlocks;
  246. //
  247. // The map entry found
  248. //
  249. if ((Lba >= StartLba) && (Lba < NextLba)) {
  250. Offset = Offset + (UINTN)MultU64x32 ((Lba - StartLba), BlockLength);
  251. if (LbaAddress != NULL) {
  252. *LbaAddress = FwhInstance->FvBase + Offset;
  253. }
  254. if (LbaLength != NULL) {
  255. *LbaLength = BlockLength;
  256. }
  257. if (NumOfBlocks != NULL) {
  258. *NumOfBlocks = (UINTN)(NextLba - Lba);
  259. }
  260. return EFI_SUCCESS;
  261. }
  262. StartLba = NextLba;
  263. Offset = Offset + NumBlocks * BlockLength;
  264. BlockMap++;
  265. }
  266. }
  267. EFI_STATUS
  268. FvbSetVolumeAttributes (
  269. IN UINTN Instance,
  270. IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes,
  271. IN ESAL_FWB_GLOBAL *Global
  272. )
  273. /*++
  274. Routine Description:
  275. Modifies the current settings of the firmware volume according to the
  276. input parameter, and returns the new setting of the volume
  277. Arguments:
  278. Instance - The FV instance whose attributes is going to be
  279. modified
  280. Attributes - On input, it is a pointer to EFI_FVB_ATTRIBUTES_2
  281. containing the desired firmware volume settings.
  282. On successful return, it contains the new settings
  283. of the firmware volume
  284. Global - Pointer to ESAL_FWB_GLOBAL that contains all
  285. instance data
  286. Returns:
  287. EFI_SUCCESS - Successfully returns
  288. EFI_ACCESS_DENIED - The volume setting is locked and cannot be modified
  289. EFI_INVALID_PARAMETER - Instance not found, or The attributes requested are
  290. in conflict with the capabilities as declared in
  291. the firmware volume header
  292. --*/
  293. {
  294. EFI_FW_VOL_INSTANCE *FwhInstance;
  295. EFI_FVB_ATTRIBUTES_2 OldAttributes;
  296. EFI_FVB_ATTRIBUTES_2 *AttribPtr;
  297. UINT32 Capabilities;
  298. UINT32 OldStatus;
  299. UINT32 NewStatus;
  300. EFI_STATUS Status;
  301. EFI_FVB_ATTRIBUTES_2 UnchangedAttributes;
  302. //
  303. // Find the right instance of the FVB private data
  304. //
  305. Status = GetFvbInstance (Instance, Global, &FwhInstance);
  306. ASSERT_EFI_ERROR (Status);
  307. AttribPtr =
  308. (EFI_FVB_ATTRIBUTES_2 *)&(FwhInstance->VolumeHeader.Attributes);
  309. OldAttributes = *AttribPtr;
  310. Capabilities = OldAttributes & (EFI_FVB2_READ_DISABLED_CAP | \
  311. EFI_FVB2_READ_ENABLED_CAP | \
  312. EFI_FVB2_WRITE_DISABLED_CAP | \
  313. EFI_FVB2_WRITE_ENABLED_CAP | \
  314. EFI_FVB2_LOCK_CAP \
  315. );
  316. OldStatus = OldAttributes & EFI_FVB2_STATUS;
  317. NewStatus = *Attributes & EFI_FVB2_STATUS;
  318. UnchangedAttributes = EFI_FVB2_READ_DISABLED_CAP | \
  319. EFI_FVB2_READ_ENABLED_CAP | \
  320. EFI_FVB2_WRITE_DISABLED_CAP | \
  321. EFI_FVB2_WRITE_ENABLED_CAP | \
  322. EFI_FVB2_LOCK_CAP | \
  323. EFI_FVB2_STICKY_WRITE | \
  324. EFI_FVB2_MEMORY_MAPPED | \
  325. EFI_FVB2_ERASE_POLARITY | \
  326. EFI_FVB2_READ_LOCK_CAP | \
  327. EFI_FVB2_WRITE_LOCK_CAP | \
  328. EFI_FVB2_ALIGNMENT;
  329. //
  330. // Some attributes of FV is read only can *not* be set
  331. //
  332. if ((OldAttributes & UnchangedAttributes) ^
  333. (*Attributes & UnchangedAttributes))
  334. {
  335. return EFI_INVALID_PARAMETER;
  336. }
  337. //
  338. // If firmware volume is locked, no status bit can be updated
  339. //
  340. if (OldAttributes & EFI_FVB2_LOCK_STATUS) {
  341. if (OldStatus ^ NewStatus) {
  342. return EFI_ACCESS_DENIED;
  343. }
  344. }
  345. //
  346. // Test read disable
  347. //
  348. if ((Capabilities & EFI_FVB2_READ_DISABLED_CAP) == 0) {
  349. if ((NewStatus & EFI_FVB2_READ_STATUS) == 0) {
  350. return EFI_INVALID_PARAMETER;
  351. }
  352. }
  353. //
  354. // Test read enable
  355. //
  356. if ((Capabilities & EFI_FVB2_READ_ENABLED_CAP) == 0) {
  357. if (NewStatus & EFI_FVB2_READ_STATUS) {
  358. return EFI_INVALID_PARAMETER;
  359. }
  360. }
  361. //
  362. // Test write disable
  363. //
  364. if ((Capabilities & EFI_FVB2_WRITE_DISABLED_CAP) == 0) {
  365. if ((NewStatus & EFI_FVB2_WRITE_STATUS) == 0) {
  366. return EFI_INVALID_PARAMETER;
  367. }
  368. }
  369. //
  370. // Test write enable
  371. //
  372. if ((Capabilities & EFI_FVB2_WRITE_ENABLED_CAP) == 0) {
  373. if (NewStatus & EFI_FVB2_WRITE_STATUS) {
  374. return EFI_INVALID_PARAMETER;
  375. }
  376. }
  377. //
  378. // Test lock
  379. //
  380. if ((Capabilities & EFI_FVB2_LOCK_CAP) == 0) {
  381. if (NewStatus & EFI_FVB2_LOCK_STATUS) {
  382. return EFI_INVALID_PARAMETER;
  383. }
  384. }
  385. *AttribPtr = (*AttribPtr) & (0xFFFFFFFF & (~EFI_FVB2_STATUS));
  386. *AttribPtr = (*AttribPtr) | NewStatus;
  387. *Attributes = *AttribPtr;
  388. return EFI_SUCCESS;
  389. }
  390. //
  391. // FVB protocol APIs
  392. //
  393. EFI_STATUS
  394. EFIAPI
  395. FvbProtocolGetPhysicalAddress (
  396. IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
  397. OUT EFI_PHYSICAL_ADDRESS *Address
  398. )
  399. /*++
  400. Routine Description:
  401. Retrieves the physical address of the device.
  402. Arguments:
  403. This - Calling context
  404. Address - Output buffer containing the address.
  405. Returns:
  406. EFI_SUCCESS - Successfully returns
  407. --*/
  408. {
  409. EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
  410. FvbDevice = FVB_DEVICE_FROM_THIS (This);
  411. return FvbGetPhysicalAddress (
  412. FvbDevice->Instance,
  413. Address,
  414. mFvbModuleGlobal
  415. );
  416. }
  417. EFI_STATUS
  418. EFIAPI
  419. FvbProtocolGetBlockSize (
  420. IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
  421. IN CONST EFI_LBA Lba,
  422. OUT UINTN *BlockSize,
  423. OUT UINTN *NumOfBlocks
  424. )
  425. /*++
  426. Routine Description:
  427. Retrieve the size of a logical block
  428. Arguments:
  429. This - Calling context
  430. Lba - Indicates which block to return the size for.
  431. BlockSize - A pointer to a caller allocated UINTN in which
  432. the size of the block is returned
  433. NumOfBlocks - a pointer to a caller allocated UINTN in which the
  434. number of consecutive blocks starting with Lba is
  435. returned. All blocks in this range have a size of
  436. BlockSize
  437. Returns:
  438. EFI_SUCCESS - The firmware volume was read successfully and
  439. contents are in Buffer
  440. --*/
  441. {
  442. EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
  443. FvbDevice = FVB_DEVICE_FROM_THIS (This);
  444. return FvbGetLbaAddress (
  445. FvbDevice->Instance,
  446. Lba,
  447. NULL,
  448. BlockSize,
  449. NumOfBlocks,
  450. mFvbModuleGlobal
  451. );
  452. }
  453. EFI_STATUS
  454. EFIAPI
  455. FvbProtocolGetAttributes (
  456. IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
  457. OUT EFI_FVB_ATTRIBUTES_2 *Attributes
  458. )
  459. /*++
  460. Routine Description:
  461. Retrieves Volume attributes. No polarity translations are done.
  462. Arguments:
  463. This - Calling context
  464. Attributes - output buffer which contains attributes
  465. Returns:
  466. EFI_SUCCESS - Successfully returns
  467. --*/
  468. {
  469. EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
  470. FvbDevice = FVB_DEVICE_FROM_THIS (This);
  471. return FvbGetVolumeAttributes (
  472. FvbDevice->Instance,
  473. Attributes,
  474. mFvbModuleGlobal
  475. );
  476. }
  477. EFI_STATUS
  478. EFIAPI
  479. FvbProtocolSetAttributes (
  480. IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
  481. IN OUT EFI_FVB_ATTRIBUTES_2 *Attributes
  482. )
  483. /*++
  484. Routine Description:
  485. Sets Volume attributes. No polarity translations are done.
  486. Arguments:
  487. This - Calling context
  488. Attributes - output buffer which contains attributes
  489. Returns:
  490. EFI_SUCCESS - Successfully returns
  491. --*/
  492. {
  493. EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
  494. FvbDevice = FVB_DEVICE_FROM_THIS (This);
  495. return FvbSetVolumeAttributes (
  496. FvbDevice->Instance,
  497. Attributes,
  498. mFvbModuleGlobal
  499. );
  500. }
  501. EFI_STATUS
  502. EFIAPI
  503. FvbProtocolEraseBlocks (
  504. IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
  505. ...
  506. )
  507. /*++
  508. Routine Description:
  509. The EraseBlock() function erases one or more blocks as denoted by the
  510. variable argument list. The entire parameter list of blocks must be
  511. verified prior to erasing any blocks. If a block is requested that does
  512. not exist within the associated firmware volume (it has a larger index than
  513. the last block of the firmware volume), the EraseBlock() function must
  514. return EFI_INVALID_PARAMETER without modifying the contents of the firmware
  515. volume.
  516. Arguments:
  517. This - Calling context
  518. ... - Starting LBA followed by Number of Lba to erase.
  519. a -1 to terminate the list.
  520. Returns:
  521. EFI_SUCCESS - The erase request was successfully completed
  522. EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state
  523. EFI_DEVICE_ERROR - The block device is not functioning correctly and
  524. could not be written. Firmware device may have been
  525. partially erased
  526. --*/
  527. {
  528. EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
  529. EFI_FW_VOL_INSTANCE *FwhInstance;
  530. UINTN NumOfBlocks;
  531. VA_LIST args;
  532. EFI_LBA StartingLba;
  533. UINTN NumOfLba;
  534. EFI_STATUS Status;
  535. FvbDevice = FVB_DEVICE_FROM_THIS (This);
  536. Status = GetFvbInstance (
  537. FvbDevice->Instance,
  538. mFvbModuleGlobal,
  539. &FwhInstance
  540. );
  541. ASSERT_EFI_ERROR (Status);
  542. NumOfBlocks = FwhInstance->NumOfBlocks;
  543. VA_START (args, This);
  544. do {
  545. StartingLba = VA_ARG (args, EFI_LBA);
  546. if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
  547. break;
  548. }
  549. NumOfLba = VA_ARG (args, UINTN);
  550. //
  551. // Check input parameters
  552. //
  553. if ((NumOfLba == 0) || ((StartingLba + NumOfLba) > NumOfBlocks)) {
  554. VA_END (args);
  555. return EFI_INVALID_PARAMETER;
  556. }
  557. } while (1);
  558. VA_END (args);
  559. VA_START (args, This);
  560. do {
  561. StartingLba = VA_ARG (args, EFI_LBA);
  562. if (StartingLba == EFI_LBA_LIST_TERMINATOR) {
  563. break;
  564. }
  565. NumOfLba = VA_ARG (args, UINTN);
  566. while (NumOfLba > 0) {
  567. Status = QemuFlashEraseBlock (StartingLba);
  568. if (EFI_ERROR (Status)) {
  569. VA_END (args);
  570. return Status;
  571. }
  572. StartingLba++;
  573. NumOfLba--;
  574. }
  575. } while (1);
  576. VA_END (args);
  577. return EFI_SUCCESS;
  578. }
  579. EFI_STATUS
  580. EFIAPI
  581. FvbProtocolWrite (
  582. IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
  583. IN EFI_LBA Lba,
  584. IN UINTN Offset,
  585. IN OUT UINTN *NumBytes,
  586. IN UINT8 *Buffer
  587. )
  588. /*++
  589. Routine Description:
  590. Writes data beginning at Lba:Offset from FV. The write terminates either
  591. when *NumBytes of data have been written, or when a block boundary is
  592. reached. *NumBytes is updated to reflect the actual number of bytes
  593. written. The write operation does not include erase. This routine will
  594. attempt to write only the specified bytes. If the writes do not stick,
  595. it will return an error.
  596. Arguments:
  597. This - Calling context
  598. Lba - Block in which to begin write
  599. Offset - Offset in the block at which to begin write
  600. NumBytes - On input, indicates the requested write size. On
  601. output, indicates the actual number of bytes
  602. written
  603. Buffer - Buffer containing source data for the write.
  604. Returns:
  605. EFI_SUCCESS - The firmware volume was written successfully
  606. EFI_BAD_BUFFER_SIZE - Write attempted across a LBA boundary. On output,
  607. NumBytes contains the total number of bytes
  608. actually written
  609. EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state
  610. EFI_DEVICE_ERROR - The block device is not functioning correctly and
  611. could not be written
  612. EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL
  613. --*/
  614. {
  615. return QemuFlashWrite (
  616. (EFI_LBA)Lba,
  617. (UINTN)Offset,
  618. NumBytes,
  619. (UINT8 *)Buffer
  620. );
  621. }
  622. EFI_STATUS
  623. EFIAPI
  624. FvbProtocolRead (
  625. IN CONST EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This,
  626. IN CONST EFI_LBA Lba,
  627. IN CONST UINTN Offset,
  628. IN OUT UINTN *NumBytes,
  629. IN UINT8 *Buffer
  630. )
  631. /*++
  632. Routine Description:
  633. Reads data beginning at Lba:Offset from FV. The Read terminates either
  634. when *NumBytes of data have been read, or when a block boundary is
  635. reached. *NumBytes is updated to reflect the actual number of bytes
  636. written. The write operation does not include erase. This routine will
  637. attempt to write only the specified bytes. If the writes do not stick,
  638. it will return an error.
  639. Arguments:
  640. This - Calling context
  641. Lba - Block in which to begin Read
  642. Offset - Offset in the block at which to begin Read
  643. NumBytes - On input, indicates the requested write size. On
  644. output, indicates the actual number of bytes Read
  645. Buffer - Buffer containing source data for the Read.
  646. Returns:
  647. EFI_SUCCESS - The firmware volume was read successfully and
  648. contents are in Buffer
  649. EFI_BAD_BUFFER_SIZE - Read attempted across a LBA boundary. On output,
  650. NumBytes contains the total number of bytes
  651. returned in Buffer
  652. EFI_ACCESS_DENIED - The firmware volume is in the ReadDisabled state
  653. EFI_DEVICE_ERROR - The block device is not functioning correctly and
  654. could not be read
  655. EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL
  656. --*/
  657. {
  658. return QemuFlashRead (
  659. (EFI_LBA)Lba,
  660. (UINTN)Offset,
  661. NumBytes,
  662. (UINT8 *)Buffer
  663. );
  664. }
  665. EFI_STATUS
  666. ValidateFvHeader (
  667. EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader
  668. )
  669. /*++
  670. Routine Description:
  671. Check the integrity of firmware volume header
  672. Arguments:
  673. FwVolHeader - A pointer to a firmware volume header
  674. Returns:
  675. EFI_SUCCESS - The firmware volume is consistent
  676. EFI_NOT_FOUND - The firmware volume has corrupted. So it is not an
  677. FV
  678. --*/
  679. {
  680. UINT16 Checksum;
  681. //
  682. // Verify the header revision, header signature, length
  683. // Length of FvBlock cannot be 2**64-1
  684. // HeaderLength cannot be an odd number
  685. //
  686. if ((FwVolHeader->Revision != EFI_FVH_REVISION) ||
  687. (FwVolHeader->Signature != EFI_FVH_SIGNATURE) ||
  688. (FwVolHeader->FvLength == ((UINTN)-1)) ||
  689. ((FwVolHeader->HeaderLength & 0x01) != 0)
  690. )
  691. {
  692. return EFI_NOT_FOUND;
  693. }
  694. //
  695. // Verify the header checksum
  696. //
  697. Checksum = CalculateSum16 (
  698. (UINT16 *)FwVolHeader,
  699. FwVolHeader->HeaderLength
  700. );
  701. if (Checksum != 0) {
  702. UINT16 Expected;
  703. Expected =
  704. (UINT16)(((UINTN)FwVolHeader->Checksum + 0x10000 - Checksum) & 0xffff);
  705. DEBUG ((
  706. DEBUG_INFO,
  707. "FV@%p Checksum is 0x%x, expected 0x%x\n",
  708. FwVolHeader,
  709. FwVolHeader->Checksum,
  710. Expected
  711. ));
  712. return EFI_NOT_FOUND;
  713. }
  714. return EFI_SUCCESS;
  715. }
  716. STATIC
  717. EFI_STATUS
  718. InitializeVariableFvHeader (
  719. VOID
  720. )
  721. {
  722. EFI_STATUS Status;
  723. EFI_FIRMWARE_VOLUME_HEADER *GoodFwVolHeader;
  724. EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
  725. UINTN Length;
  726. UINTN WriteLength;
  727. UINTN BlockSize;
  728. FwVolHeader =
  729. (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)
  730. PcdGet32 (PcdOvmfFlashNvStorageVariableBase);
  731. Length =
  732. (FixedPcdGet32 (PcdFlashNvStorageVariableSize) +
  733. FixedPcdGet32 (PcdFlashNvStorageFtwWorkingSize) +
  734. FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize) +
  735. FixedPcdGet32 (PcdOvmfFlashNvStorageEventLogSize));
  736. BlockSize = PcdGet32 (PcdOvmfFirmwareBlockSize);
  737. Status = ValidateFvHeader (FwVolHeader);
  738. if (!EFI_ERROR (Status)) {
  739. if ((FwVolHeader->FvLength != Length) ||
  740. (FwVolHeader->BlockMap[0].Length != BlockSize))
  741. {
  742. Status = EFI_VOLUME_CORRUPTED;
  743. }
  744. }
  745. if (EFI_ERROR (Status)) {
  746. UINTN Offset;
  747. UINTN Start;
  748. DEBUG ((
  749. DEBUG_INFO,
  750. "Variable FV header is not valid. It will be reinitialized.\n"
  751. ));
  752. //
  753. // Get FvbInfo to provide in FwhInstance.
  754. //
  755. Status = GetFvbInfo (Length, &GoodFwVolHeader);
  756. ASSERT (!EFI_ERROR (Status));
  757. Start = (UINTN)(UINT8 *)FwVolHeader - PcdGet32 (PcdOvmfFdBaseAddress);
  758. ASSERT (Start % BlockSize == 0 && Length % BlockSize == 0);
  759. ASSERT (GoodFwVolHeader->HeaderLength <= BlockSize);
  760. //
  761. // Erase all the blocks
  762. //
  763. for (Offset = Start; Offset < Start + Length; Offset += BlockSize) {
  764. Status = QemuFlashEraseBlock (Offset / BlockSize);
  765. ASSERT_EFI_ERROR (Status);
  766. }
  767. //
  768. // Write good FV header
  769. //
  770. WriteLength = GoodFwVolHeader->HeaderLength;
  771. Status = QemuFlashWrite (
  772. Start / BlockSize,
  773. 0,
  774. &WriteLength,
  775. (UINT8 *)GoodFwVolHeader
  776. );
  777. ASSERT_EFI_ERROR (Status);
  778. ASSERT (WriteLength == GoodFwVolHeader->HeaderLength);
  779. }
  780. return Status;
  781. }
  782. EFI_STATUS
  783. EFIAPI
  784. FvbInitialize (
  785. IN EFI_HANDLE ImageHandle,
  786. IN EFI_SYSTEM_TABLE *SystemTable
  787. )
  788. /*++
  789. Routine Description:
  790. This function does common initialization for FVB services
  791. Arguments:
  792. Returns:
  793. --*/
  794. {
  795. EFI_STATUS Status;
  796. EFI_FW_VOL_INSTANCE *FwhInstance;
  797. EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader;
  798. UINT32 BufferSize;
  799. EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry;
  800. EFI_FW_VOL_BLOCK_DEVICE *FvbDevice;
  801. UINT32 MaxLbaSize;
  802. EFI_PHYSICAL_ADDRESS BaseAddress;
  803. UINTN Length;
  804. UINTN NumOfBlocks;
  805. RETURN_STATUS PcdStatus;
  806. if (EFI_ERROR (QemuFlashInitialize ())) {
  807. //
  808. // Return an error so image will be unloaded
  809. //
  810. DEBUG ((
  811. DEBUG_INFO,
  812. "QEMU flash was not detected. Writable FVB is not being installed.\n"
  813. ));
  814. return EFI_WRITE_PROTECTED;
  815. }
  816. //
  817. // Allocate runtime services data for global variable, which contains
  818. // the private data of all firmware volume block instances
  819. //
  820. mFvbModuleGlobal = AllocateRuntimePool (sizeof (ESAL_FWB_GLOBAL));
  821. ASSERT (mFvbModuleGlobal != NULL);
  822. BaseAddress = (UINTN)PcdGet32 (PcdOvmfFdBaseAddress);
  823. Length = PcdGet32 (PcdOvmfFirmwareFdSize);
  824. Status = InitializeVariableFvHeader ();
  825. if (EFI_ERROR (Status)) {
  826. DEBUG ((
  827. DEBUG_INFO,
  828. "QEMU Flash: Unable to initialize variable FV header\n"
  829. ));
  830. return EFI_WRITE_PROTECTED;
  831. }
  832. FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)BaseAddress;
  833. Status = ValidateFvHeader (FwVolHeader);
  834. if (EFI_ERROR (Status)) {
  835. //
  836. // Get FvbInfo
  837. //
  838. Status = GetFvbInfo (Length, &FwVolHeader);
  839. if (EFI_ERROR (Status)) {
  840. DEBUG ((DEBUG_INFO, "EFI_ERROR (GetFvbInfo (Length, &FwVolHeader))\n"));
  841. return EFI_WRITE_PROTECTED;
  842. }
  843. }
  844. BufferSize = (sizeof (EFI_FW_VOL_INSTANCE) +
  845. FwVolHeader->HeaderLength -
  846. sizeof (EFI_FIRMWARE_VOLUME_HEADER)
  847. );
  848. mFvbModuleGlobal->FvInstance = AllocateRuntimePool (BufferSize);
  849. ASSERT (mFvbModuleGlobal->FvInstance != NULL);
  850. FwhInstance = mFvbModuleGlobal->FvInstance;
  851. mFvbModuleGlobal->NumFv = 0;
  852. MaxLbaSize = 0;
  853. FwVolHeader =
  854. (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)
  855. PcdGet32 (PcdOvmfFlashNvStorageVariableBase);
  856. FwhInstance->FvBase = (UINTN)BaseAddress;
  857. CopyMem (
  858. (UINTN *)&(FwhInstance->VolumeHeader),
  859. (UINTN *)FwVolHeader,
  860. FwVolHeader->HeaderLength
  861. );
  862. FwVolHeader = &(FwhInstance->VolumeHeader);
  863. NumOfBlocks = 0;
  864. for (PtrBlockMapEntry = FwVolHeader->BlockMap;
  865. PtrBlockMapEntry->NumBlocks != 0;
  866. PtrBlockMapEntry++)
  867. {
  868. //
  869. // Get the maximum size of a block.
  870. //
  871. if (MaxLbaSize < PtrBlockMapEntry->Length) {
  872. MaxLbaSize = PtrBlockMapEntry->Length;
  873. }
  874. NumOfBlocks = NumOfBlocks + PtrBlockMapEntry->NumBlocks;
  875. }
  876. //
  877. // The total number of blocks in the FV.
  878. //
  879. FwhInstance->NumOfBlocks = NumOfBlocks;
  880. //
  881. // Add a FVB Protocol Instance
  882. //
  883. FvbDevice = AllocateRuntimePool (sizeof (EFI_FW_VOL_BLOCK_DEVICE));
  884. ASSERT (FvbDevice != NULL);
  885. CopyMem (FvbDevice, &mFvbDeviceTemplate, sizeof (EFI_FW_VOL_BLOCK_DEVICE));
  886. FvbDevice->Instance = mFvbModuleGlobal->NumFv;
  887. mFvbModuleGlobal->NumFv++;
  888. //
  889. // Set up the devicepath
  890. //
  891. if (FwVolHeader->ExtHeaderOffset == 0) {
  892. FV_MEMMAP_DEVICE_PATH *FvMemmapDevicePath;
  893. //
  894. // FV does not contains extension header, then produce MEMMAP_DEVICE_PATH
  895. //
  896. FvMemmapDevicePath = AllocateCopyPool (
  897. sizeof (FV_MEMMAP_DEVICE_PATH),
  898. &mFvMemmapDevicePathTemplate
  899. );
  900. FvMemmapDevicePath->MemMapDevPath.StartingAddress = BaseAddress;
  901. FvMemmapDevicePath->MemMapDevPath.EndingAddress =
  902. BaseAddress + FwVolHeader->FvLength - 1;
  903. FvbDevice->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)FvMemmapDevicePath;
  904. } else {
  905. FV_PIWG_DEVICE_PATH *FvPiwgDevicePath;
  906. FvPiwgDevicePath = AllocateCopyPool (
  907. sizeof (FV_PIWG_DEVICE_PATH),
  908. &mFvPIWGDevicePathTemplate
  909. );
  910. CopyGuid (
  911. &FvPiwgDevicePath->FvDevPath.FvName,
  912. (GUID *)(UINTN)(BaseAddress + FwVolHeader->ExtHeaderOffset)
  913. );
  914. FvbDevice->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)FvPiwgDevicePath;
  915. }
  916. //
  917. // Module type specific hook.
  918. //
  919. InstallProtocolInterfaces (FvbDevice);
  920. MarkIoMemoryRangeForRuntimeAccess (BaseAddress, Length);
  921. SetPcdFlashNvStorageBaseAddresses ();
  922. FwhInstance = (EFI_FW_VOL_INSTANCE *)
  923. (
  924. (UINTN)((UINT8 *)FwhInstance) + FwVolHeader->HeaderLength +
  925. (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER))
  926. );
  927. //
  928. // Module type specific hook.
  929. //
  930. InstallVirtualAddressChangeHandler ();
  931. PcdStatus = PcdSetBoolS (PcdOvmfFlashVariablesEnable, TRUE);
  932. ASSERT_RETURN_ERROR (PcdStatus);
  933. return EFI_SUCCESS;
  934. }