FwBlockService.c 32 KB

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