fwvol.c 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348
  1. /*++
  2. Copyright (c) 2014 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. fwvol.c
  9. Abstract:
  10. This module implements UEFI core protocol support for firmware volumes.
  11. Author:
  12. Evan Green 11-Mar-2014
  13. Environment:
  14. Firmware
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include "ueficore.h"
  20. #include "fwvolp.h"
  21. //
  22. // ---------------------------------------------------------------- Definitions
  23. //
  24. //
  25. // ------------------------------------------------------ Data Type Definitions
  26. //
  27. //
  28. // ----------------------------------------------- Internal Function Prototypes
  29. //
  30. EFIAPI
  31. VOID
  32. EfipFvBlockNotify (
  33. EFI_EVENT Event,
  34. VOID *Context
  35. );
  36. EFI_STATUS
  37. EfipFvCheck (
  38. PEFI_FIRMWARE_VOLUME Device
  39. );
  40. VOID
  41. EfipFvFreeDeviceResource (
  42. PEFI_FIRMWARE_VOLUME Volume
  43. );
  44. BOOLEAN
  45. EfipFvIsBufferErased (
  46. UINT8 ErasePolarity,
  47. VOID *Buffer,
  48. UINTN BufferSize
  49. );
  50. BOOLEAN
  51. EfipFvIsValidFfsHeader (
  52. UINT8 ErasePolarity,
  53. EFI_FFS_FILE_HEADER *FfsHeader,
  54. EFI_FFS_FILE_STATE *FileState
  55. );
  56. BOOLEAN
  57. EfipFvIsValidFfsFile (
  58. UINT8 ErasePolarity,
  59. EFI_FFS_FILE_HEADER *FfsHeader
  60. );
  61. EFI_FFS_FILE_STATE
  62. EfipFvGetFileState (
  63. UINT8 ErasePolarity,
  64. EFI_FFS_FILE_HEADER *FfsHeader
  65. );
  66. BOOLEAN
  67. EfipFvVerifyFileHeaderChecksum (
  68. EFI_FFS_FILE_HEADER *FfsHeader
  69. );
  70. UINT16
  71. EfipFvCalculateSum16 (
  72. UINT16 *Buffer,
  73. UINTN Size
  74. );
  75. UINT8
  76. EfipFvCalculateChecksum8 (
  77. UINT8 *Buffer,
  78. UINTN Size
  79. );
  80. UINT8
  81. EfipFvCalculateSum8 (
  82. UINT8 *Buffer,
  83. UINTN Size
  84. );
  85. //
  86. // -------------------------------------------------------------------- Globals
  87. //
  88. //
  89. // Keep protocol notify related globals.
  90. //
  91. VOID *EfiFvBlockNotifyRegistration;
  92. EFI_EVENT EfiFvBlockEvent;
  93. EFI_GUID EfiFirmwareFileSystem2Guid = EFI_FIRMWARE_FILE_SYSTEM2_GUID;
  94. EFI_GUID EfiFirmwareFileSystem3Guid = EFI_FIRMWARE_FILE_SYSTEM3_GUID;
  95. EFI_GUID EfiFirmwareVolume2ProtocolGuid = EFI_FIRMWARE_VOLUME2_PROTOCOL_GUID;
  96. //
  97. // Store the template for firmware volumes.
  98. //
  99. EFI_FIRMWARE_VOLUME EfiFirmwareVolumeTemplate = {
  100. EFI_FIRMWARE_VOLUME_MAGIC,
  101. NULL,
  102. NULL,
  103. {
  104. EfiFvGetVolumeAttributes,
  105. EfiFvSetVolumeAttributes,
  106. EfiFvReadFile,
  107. EfiFvReadFileSection,
  108. EfiFvWriteFile,
  109. EfiFvGetNextFile,
  110. sizeof(UINTN),
  111. NULL,
  112. EfiFvGetVolumeInfo,
  113. EfiFvSetVolumeInfo,
  114. },
  115. NULL,
  116. NULL,
  117. NULL,
  118. NULL,
  119. {NULL, NULL},
  120. 0,
  121. FALSE,
  122. 0
  123. };
  124. //
  125. // ------------------------------------------------------------------ Functions
  126. //
  127. EFIAPI
  128. EFI_STATUS
  129. EfiFvDriverInit (
  130. EFI_HANDLE ImageHandle,
  131. EFI_SYSTEM_TABLE *SystemTable
  132. )
  133. /*++
  134. Routine Description:
  135. This routine initializes support for UEFI firmware volumes.
  136. Arguments:
  137. ImageHandle - Supplies the image handle for this driver. This is probably
  138. the firmware core image handle.
  139. SystemTable - Supplies a pointer to the system table.
  140. Return Value:
  141. EFI status code.
  142. --*/
  143. {
  144. //
  145. // Sign up to be notified whenever a new firmware volume block device
  146. // protocol crops up.
  147. //
  148. EfiFvBlockEvent = EfiCoreCreateProtocolNotifyEvent(
  149. &EfiFirmwareVolumeBlockProtocolGuid,
  150. TPL_CALLBACK,
  151. EfipFvBlockNotify,
  152. NULL,
  153. &EfiFvBlockNotifyRegistration);
  154. ASSERT(EfiFvBlockEvent != NULL);
  155. return EFI_SUCCESS;
  156. }
  157. EFI_STATUS
  158. EfiFvGetVolumeHeader (
  159. EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *BlockProtocol,
  160. EFI_FIRMWARE_VOLUME_HEADER **Header
  161. )
  162. /*++
  163. Routine Description:
  164. This routine returns the firmware volume header of the volume represented
  165. by the given block I/O interface.
  166. Arguments:
  167. BlockProtocol - Supplies an instance of the block I/O protocol.
  168. Header - Supplies a pointer where a pointer to the volume header allocated
  169. from pool will be returned on success.
  170. Return Value:
  171. EFI status code.
  172. --*/
  173. {
  174. UINT8 *Buffer;
  175. UINTN HeaderLength;
  176. EFI_FIRMWARE_VOLUME_HEADER LocalHeader;
  177. UINTN Offset;
  178. EFI_LBA StartLba;
  179. EFI_STATUS Status;
  180. //
  181. // Read the standard firmware volume header.
  182. //
  183. *Header = NULL;
  184. StartLba = 0;
  185. Offset = 0;
  186. HeaderLength = sizeof(EFI_FIRMWARE_VOLUME_HEADER);
  187. Status = EfiFvReadData(BlockProtocol,
  188. &StartLba,
  189. &Offset,
  190. HeaderLength,
  191. (UINT8 *)&LocalHeader);
  192. if (EFI_ERROR(Status)) {
  193. return Status;
  194. }
  195. if (LocalHeader.HeaderLength < sizeof(EFI_FIRMWARE_VOLUME_HEADER)) {
  196. return EFI_INVALID_PARAMETER;
  197. }
  198. //
  199. // Allocate a buffer for the header.
  200. //
  201. *Header = EfiCoreAllocateBootPool(LocalHeader.HeaderLength);
  202. if (*Header == NULL) {
  203. return EFI_OUT_OF_RESOURCES;
  204. }
  205. EfiCopyMem(*Header, &LocalHeader, sizeof(EFI_FIRMWARE_VOLUME_HEADER));
  206. //
  207. // Read the rest of the header.
  208. //
  209. HeaderLength = LocalHeader.HeaderLength -
  210. sizeof(EFI_FIRMWARE_VOLUME_HEADER);
  211. Buffer = (UINT8 *)*Header + sizeof(EFI_FIRMWARE_VOLUME_HEADER);
  212. Status = EfiFvReadData(BlockProtocol,
  213. &StartLba,
  214. &Offset,
  215. HeaderLength,
  216. Buffer);
  217. if (EFI_ERROR(Status)) {
  218. EfiCoreFreePool(*Header);
  219. *Header = NULL;
  220. }
  221. return Status;
  222. }
  223. EFI_STATUS
  224. EfiFvReadData (
  225. EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *BlockProtocol,
  226. EFI_LBA *StartLba,
  227. UINTN *Offset,
  228. UINTN DataSize,
  229. UINT8 *Data
  230. )
  231. /*++
  232. Routine Description:
  233. This routine reads data from the firmware volume represented by the given
  234. block I/O interface. This data may span multiple block ranges.
  235. Arguments:
  236. BlockProtocol - Supplies an instance of the block I/O protocol.
  237. StartLba - Supplies a pointer that on input contains the logical block
  238. address to read from. On output, this will contain the logical block
  239. address after reading.
  240. Offset - Supplies a pointer that on input contains the offset within the
  241. block to start reading. On output, the offset into the block after
  242. reading will be returned.
  243. DataSize - Supplies the size of the data to read in bytes.
  244. Data - Supplies a pointer where the read data will be returned.
  245. Return Value:
  246. EFI status code.
  247. --*/
  248. {
  249. UINTN BlockIndex;
  250. UINTN BlockSize;
  251. UINTN NumberOfBlocks;
  252. UINTN ReadDataSize;
  253. EFI_STATUS Status;
  254. //
  255. // Try to read data in the current block.
  256. //
  257. BlockIndex = 0;
  258. ReadDataSize = DataSize;
  259. Status = BlockProtocol->Read(BlockProtocol,
  260. *StartLba,
  261. *Offset,
  262. &ReadDataSize,
  263. Data);
  264. if (Status == EFI_SUCCESS) {
  265. *Offset += DataSize;
  266. return EFI_SUCCESS;
  267. } else if (Status != EFI_BAD_BUFFER_SIZE) {
  268. return Status;
  269. }
  270. //
  271. // The read cross block boundaries, so read data from the next block.
  272. //
  273. DataSize -= ReadDataSize;
  274. Data += ReadDataSize;
  275. *StartLba += 1;
  276. while (DataSize > 0) {
  277. Status = BlockProtocol->GetBlockSize(BlockProtocol,
  278. *StartLba,
  279. &BlockSize,
  280. &NumberOfBlocks);
  281. if (EFI_ERROR(Status)) {
  282. return Status;
  283. }
  284. //
  285. // Read data now that a block boundary was just crossed.
  286. //
  287. BlockIndex = 0;
  288. while ((BlockIndex < NumberOfBlocks) && (DataSize >= BlockSize)) {
  289. Status = BlockProtocol->Read(BlockProtocol,
  290. *StartLba + BlockIndex,
  291. 0,
  292. &BlockSize,
  293. Data);
  294. if (EFI_ERROR(Status)) {
  295. return Status;
  296. }
  297. Data += BlockSize;
  298. DataSize -= BlockSize;
  299. BlockIndex += 1;
  300. }
  301. //
  302. // If data doesn't exceed the block range, there's no need to loop
  303. // back around.
  304. //
  305. if (DataSize < BlockSize) {
  306. break;
  307. }
  308. //
  309. // Request block size information from the next range.
  310. //
  311. *StartLba += NumberOfBlocks;
  312. }
  313. //
  314. // Read the last partial block.
  315. //
  316. if (DataSize > 0) {
  317. Status = BlockProtocol->Read(BlockProtocol,
  318. *StartLba + BlockIndex,
  319. 0,
  320. &DataSize,
  321. Data);
  322. if (EFI_ERROR(Status)) {
  323. return Status;
  324. }
  325. }
  326. //
  327. // Update the LBA and offset used by the following read.
  328. //
  329. *StartLba += BlockIndex;
  330. *Offset = DataSize;
  331. return EFI_SUCCESS;
  332. }
  333. BOOLEAN
  334. EfiFvVerifyHeaderChecksum (
  335. EFI_FIRMWARE_VOLUME_HEADER *VolumeHeader
  336. )
  337. /*++
  338. Routine Description:
  339. This routine verifies the checksum of a firmware volume header.
  340. Arguments:
  341. VolumeHeader - Supplies a pointer to the volume header to verify.
  342. Return Value:
  343. TRUE if the checksum verification passed.
  344. FALSE if the checksum verification failed.
  345. --*/
  346. {
  347. UINT16 Checksum;
  348. Checksum = EfipFvCalculateSum16((UINT16 *)VolumeHeader,
  349. VolumeHeader->HeaderLength);
  350. if (Checksum == 0) {
  351. return TRUE;
  352. }
  353. return FALSE;
  354. }
  355. //
  356. // --------------------------------------------------------- Internal Functions
  357. //
  358. EFIAPI
  359. VOID
  360. EfipFvBlockNotify (
  361. EFI_EVENT Event,
  362. VOID *Context
  363. )
  364. /*++
  365. Routine Description:
  366. This routine is called when a new firmware volume block protocol appears
  367. in the system.
  368. Arguments:
  369. Event - Supplies a pointer to the event that fired.
  370. Context - Supplies an unused context pointer.
  371. Return Value:
  372. None.
  373. --*/
  374. {
  375. EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *BlockProtocol;
  376. UINTN BufferSize;
  377. PEFI_FIRMWARE_VOLUME Device;
  378. EFI_FIRMWARE_VOLUME2_PROTOCOL *FirmwareVolume;
  379. EFI_HANDLE Handle;
  380. BOOLEAN Match;
  381. EFI_STATUS Status;
  382. EFI_FIRMWARE_VOLUME_HEADER *VolumeHeader;
  383. //
  384. // Examine all new handles.
  385. //
  386. VolumeHeader = NULL;
  387. while (TRUE) {
  388. Status = EfiCoreLocateHandle(ByRegisterNotify,
  389. NULL,
  390. EfiFvBlockNotifyRegistration,
  391. &BufferSize,
  392. &Handle);
  393. if (Status == EFI_NOT_FOUND) {
  394. break;
  395. }
  396. if (EFI_ERROR(Status)) {
  397. continue;
  398. }
  399. //
  400. // Get the block protocol on the handle.
  401. //
  402. Status = EfiCoreHandleProtocol(Handle,
  403. &EfiFirmwareVolumeBlockProtocolGuid,
  404. (VOID **)&BlockProtocol);
  405. if (EFI_ERROR(Status)) {
  406. ASSERT(FALSE);
  407. continue;
  408. }
  409. ASSERT(BlockProtocol != NULL);
  410. Status = EfiFvGetVolumeHeader(BlockProtocol, &VolumeHeader);
  411. if (EFI_ERROR(Status)) {
  412. return;
  413. }
  414. ASSERT(VolumeHeader != NULL);
  415. Status = EfiFvVerifyHeaderChecksum(VolumeHeader);
  416. if (EFI_ERROR(Status)) {
  417. EfiCoreFreePool(VolumeHeader);
  418. return;
  419. }
  420. //
  421. // Skip file systems that aren't understood.
  422. //
  423. Match = EfiCoreCompareGuids(&(VolumeHeader->FileSystemGuid),
  424. &EfiFirmwareFileSystem2Guid);
  425. if (Match == FALSE) {
  426. Match = EfiCoreCompareGuids(&(VolumeHeader->FileSystemGuid),
  427. &EfiFirmwareFileSystem3Guid);
  428. }
  429. if (Match == FALSE) {
  430. continue;
  431. }
  432. //
  433. // Check to see if there is a firmware volume protocol already
  434. // installed on this handle.
  435. //
  436. Status = EfiCoreHandleProtocol(Handle,
  437. &EfiFirmwareVolume2ProtocolGuid,
  438. (VOID **)&FirmwareVolume);
  439. //
  440. // If there's a previously existing firmware volume protocol, then
  441. // update the block device if it was created by this driver.
  442. //
  443. if (!EFI_ERROR(Status)) {
  444. Device = PARENT_STRUCTURE(FirmwareVolume,
  445. EFI_FIRMWARE_VOLUME,
  446. VolumeProtocol);
  447. if (Device->Magic == EFI_FIRMWARE_VOLUME_MAGIC) {
  448. Device->BlockIo = BlockProtocol;
  449. }
  450. //
  451. // No firmware volume is present, create a new one.
  452. //
  453. } else {
  454. Device = EfiCoreAllocateBootPool(sizeof(EFI_FIRMWARE_VOLUME));
  455. if (Device == NULL) {
  456. return;
  457. }
  458. EfiCoreCopyMemory(Device,
  459. &EfiFirmwareVolumeTemplate,
  460. sizeof(EFI_FIRMWARE_VOLUME));
  461. Device->BlockIo = BlockProtocol;
  462. Device->Handle = Handle;
  463. Device->VolumeHeader = VolumeHeader;
  464. Match = EfiCoreCompareGuids(&(VolumeHeader->FileSystemGuid),
  465. &EfiFirmwareFileSystem3Guid);
  466. if (Match != FALSE) {
  467. Device->IsFfs3 = TRUE;
  468. }
  469. Device->VolumeProtocol.ParentHandle = BlockProtocol->ParentHandle;
  470. Status = EfipFvCheck(Device);
  471. if (!EFI_ERROR(Status)) {
  472. Status = EfiCoreInstallProtocolInterface(
  473. &Handle,
  474. &EfiFirmwareVolume2ProtocolGuid,
  475. EFI_NATIVE_INTERFACE,
  476. &(Device->VolumeProtocol));
  477. ASSERT(!EFI_ERROR(Status));
  478. }
  479. if (EFI_ERROR(Status)) {
  480. EfiCoreFreePool(Device);
  481. }
  482. }
  483. }
  484. return;
  485. }
  486. EFI_STATUS
  487. EfipFvCheck (
  488. PEFI_FIRMWARE_VOLUME Device
  489. )
  490. /*++
  491. Routine Description:
  492. This routine checks the given firmware volume for consistency and allocates
  493. a cache for it.
  494. Arguments:
  495. Device - Supplies a pointer to the device to check.
  496. Return Value:
  497. EFI status code.
  498. --*/
  499. {
  500. EFI_FVB_ATTRIBUTES Attributes;
  501. EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *BlockIo;
  502. EFI_FV_BLOCK_MAP_ENTRY *BlockMap;
  503. UINT8 *CacheLocation;
  504. BOOLEAN Erased;
  505. EFI_FFS_FILE_LIST_ENTRY *FfsFileEntry;
  506. EFI_FFS_FILE_HEADER *FfsHeader;
  507. EFI_FFS_FILE_STATE FileState;
  508. UINTN HeaderSize;
  509. UINTN Index;
  510. EFI_LBA LbaIndex;
  511. UINTN LbaOffset;
  512. UINTN Size;
  513. EFI_STATUS Status;
  514. UINTN TestLength;
  515. UINT8 *TopAddress;
  516. BOOLEAN Valid;
  517. EFI_FIRMWARE_VOLUME_HEADER *VolumeHeader;
  518. EFI_FIRMWARE_VOLUME_EXT_HEADER *VolumeHeaderExt;
  519. BlockIo = Device->BlockIo;
  520. VolumeHeader = Device->VolumeHeader;
  521. Status = BlockIo->GetAttributes(BlockIo, &Attributes);
  522. if (EFI_ERROR(Status)) {
  523. return Status;
  524. }
  525. Size = (UINTN)(VolumeHeader->Length - VolumeHeader->HeaderLength);
  526. Device->CachedVolume = EfiCoreAllocateBootPool(Size);
  527. if (Device->CachedVolume == NULL) {
  528. return EFI_OUT_OF_RESOURCES;
  529. }
  530. Device->EndOfCachedVolume = Device->CachedVolume + Size;
  531. //
  532. // Copy the firmware volume minus the header into memory using the block
  533. // map in the header.
  534. //
  535. BlockMap = VolumeHeader->BlockMap;
  536. CacheLocation = Device->CachedVolume;
  537. LbaIndex = 0;
  538. LbaOffset = 0;
  539. HeaderSize = VolumeHeader->HeaderLength;
  540. while ((BlockMap->BlockCount != 0) || (BlockMap->BlockLength != 0)) {
  541. Index = 0;
  542. Size = BlockMap->BlockLength;
  543. //
  544. // Skip the header.
  545. //
  546. if (HeaderSize > 0) {
  547. while ((Index < BlockMap->BlockCount) &&
  548. (HeaderSize >= BlockMap->BlockLength)) {
  549. HeaderSize -= BlockMap->BlockLength;
  550. LbaIndex += 1;
  551. Index += 1;
  552. }
  553. //
  554. // Check whether or not the header crosses a block boundary.
  555. //
  556. if (Index >= BlockMap->BlockCount) {
  557. BlockMap += 1;
  558. continue;
  559. } else if (HeaderSize > 0) {
  560. LbaOffset = HeaderSize;
  561. Size = BlockMap->BlockLength - HeaderSize;
  562. HeaderSize = 0;
  563. }
  564. }
  565. //
  566. // Read the firmware volume data.
  567. //
  568. while (Index < BlockMap->BlockCount) {
  569. Status = BlockIo->Read(BlockIo,
  570. LbaIndex,
  571. LbaOffset,
  572. &Size,
  573. CacheLocation);
  574. if (EFI_ERROR(Status)) {
  575. goto FvCheckEnd;
  576. }
  577. LbaIndex += 1;
  578. CacheLocation += Size;
  579. LbaOffset = 0;
  580. Size = BlockMap->BlockLength;
  581. Index += 1;
  582. }
  583. BlockMap += 1;
  584. }
  585. //
  586. // Check the free space and file list.
  587. //
  588. Device->ErasePolarity = 0;
  589. if ((Attributes & EFI_FVB_ERASE_POLARITY) != 0) {
  590. Device->ErasePolarity = 1;
  591. }
  592. //
  593. // Go through the entire firmware volume cache and check the consistency of
  594. // the firmware volume. Make a linked list of all the FFS file headers.
  595. //
  596. Status = EFI_SUCCESS;
  597. INITIALIZE_LIST_HEAD(&(Device->FfsFileList));
  598. if (VolumeHeader->ExtHeaderOffset != 0) {
  599. VolumeHeaderExt =
  600. (EFI_FIRMWARE_VOLUME_EXT_HEADER *)(Device->CachedVolume +
  601. (VolumeHeader->ExtHeaderOffset -
  602. VolumeHeader->HeaderLength));
  603. FfsHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)VolumeHeaderExt +
  604. VolumeHeaderExt->ExtHeaderSize);
  605. FfsHeader = (EFI_FFS_FILE_HEADER *)ALIGN_POINTER(FfsHeader, 8);
  606. } else {
  607. FfsHeader = (EFI_FFS_FILE_HEADER *)(Device->CachedVolume);
  608. }
  609. TopAddress = Device->EndOfCachedVolume;
  610. while ((UINT8 *)FfsHeader < TopAddress) {
  611. TestLength = TopAddress - ((UINT8 *)FfsHeader);
  612. if (TestLength > sizeof(EFI_FFS_FILE_HEADER)) {
  613. TestLength = sizeof(EFI_FFS_FILE_HEADER);
  614. }
  615. //
  616. // If this is all free space then that's it.
  617. //
  618. Erased = EfipFvIsBufferErased(Device->ErasePolarity,
  619. FfsHeader,
  620. TestLength);
  621. if (Erased != FALSE) {
  622. goto FvCheckEnd;
  623. }
  624. Valid = EfipFvIsValidFfsHeader(Device->ErasePolarity,
  625. FfsHeader,
  626. &FileState);
  627. if (Valid == FALSE) {
  628. if ((FileState == EFI_FILE_HEADER_INVALID) ||
  629. (FileState == EFI_FILE_HEADER_CONSTRUCTION)) {
  630. if (EFI_IS_FFS_FILE2(FfsHeader)) {
  631. if (Device->IsFfs3 == FALSE) {
  632. RtlDebugPrint("Warning: Found an FFS3 file in an FFS2 "
  633. "volume!\n");
  634. }
  635. FfsHeader =
  636. (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsHeader +
  637. sizeof(EFI_FFS_FILE_HEADER2));
  638. } else {
  639. FfsHeader =
  640. (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsHeader +
  641. sizeof(EFI_FFS_FILE_HEADER));
  642. }
  643. continue;
  644. } else {
  645. Status = EFI_VOLUME_CORRUPTED;
  646. goto FvCheckEnd;
  647. }
  648. }
  649. Valid = EfipFvIsValidFfsFile(Device->ErasePolarity, FfsHeader);
  650. if (Valid == FALSE) {
  651. Status = EFI_VOLUME_CORRUPTED;
  652. goto FvCheckEnd;
  653. }
  654. if (EFI_IS_FFS_FILE2(FfsHeader)) {
  655. ASSERT(EFI_FFS_FILE2_SIZE(FfsHeader) > MAX_FFS_SIZE);
  656. if (Device->IsFfs3 == FALSE) {
  657. RtlDebugPrint("Warning: Found an FFS3 file in an FFS2 "
  658. "volume!\n");
  659. //
  660. // Skip the file and align up the the next 8-byte boundary.
  661. //
  662. FfsHeader =
  663. (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsHeader +
  664. EFI_FFS_FILE2_SIZE(FfsHeader));
  665. FfsHeader = (EFI_FFS_FILE_HEADER *)ALIGN_POINTER(FfsHeader, 8);
  666. continue;
  667. }
  668. }
  669. FileState = EfipFvGetFileState(Device->ErasePolarity, FfsHeader);
  670. if (FileState != EFI_FILE_DELETED) {
  671. FfsFileEntry = EfiCoreAllocateBootPool(
  672. sizeof(EFI_FFS_FILE_LIST_ENTRY));
  673. if (FfsFileEntry == NULL) {
  674. Status = EFI_OUT_OF_RESOURCES;
  675. goto FvCheckEnd;
  676. }
  677. EfiCoreSetMemory(FfsFileEntry, sizeof(EFI_FFS_FILE_LIST_ENTRY), 0);
  678. FfsFileEntry->FileHeader = FfsHeader;
  679. INSERT_BEFORE(&(FfsFileEntry->ListEntry), &(Device->FfsFileList));
  680. }
  681. //
  682. // Move to the next file header (aligned to an 8-byte boundary).
  683. //
  684. if (EFI_IS_FFS_FILE2(FfsHeader)) {
  685. FfsHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsHeader +
  686. EFI_FFS_FILE2_SIZE(FfsHeader));
  687. } else {
  688. FfsHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsHeader +
  689. EFI_FFS_FILE_SIZE(FfsHeader));
  690. }
  691. FfsHeader = (EFI_FFS_FILE_HEADER *)ALIGN_POINTER(FfsHeader, 8);
  692. }
  693. FvCheckEnd:
  694. if (EFI_ERROR(Status)) {
  695. EfipFvFreeDeviceResource(Device);
  696. }
  697. return Status;
  698. }
  699. VOID
  700. EfipFvFreeDeviceResource (
  701. PEFI_FIRMWARE_VOLUME Volume
  702. )
  703. /*++
  704. Routine Description:
  705. This routine destroys a firmware device volume.
  706. Arguments:
  707. Volume - Supplies a pointer to the volume to destroy.
  708. Return Value:
  709. None.
  710. --*/
  711. {
  712. PEFI_FFS_FILE_LIST_ENTRY FfsFileEntry;
  713. //
  714. // Free all the FFS file list entries.
  715. //
  716. while (LIST_EMPTY(&(Volume->FfsFileList)) == FALSE) {
  717. FfsFileEntry = LIST_VALUE(Volume->FfsFileList.Next,
  718. EFI_FFS_FILE_LIST_ENTRY,
  719. ListEntry);
  720. if (FfsFileEntry->StreamHandle != 0) {
  721. EfiFvCloseSectionStream(FfsFileEntry->StreamHandle);
  722. }
  723. LIST_REMOVE(&(FfsFileEntry->ListEntry));
  724. EfiCoreFreePool(FfsFileEntry);
  725. }
  726. if (Volume->CachedVolume != NULL) {
  727. EfiCoreFreePool(Volume->CachedVolume);
  728. }
  729. if (Volume->VolumeHeader != NULL) {
  730. EfiCoreFreePool(Volume->VolumeHeader);
  731. }
  732. return;
  733. }
  734. BOOLEAN
  735. EfipFvIsBufferErased (
  736. UINT8 ErasePolarity,
  737. VOID *Buffer,
  738. UINTN BufferSize
  739. )
  740. /*++
  741. Routine Description:
  742. This routine determines if the given buffer is all erased data.
  743. Arguments:
  744. ErasePolarity - Supplies the erase polarity of the volume.
  745. Buffer - Supplies the buffer to be checked.
  746. BufferSize - Supplies the size of the buffer.
  747. Return Value:
  748. TRUE if the block of buffer is erased.
  749. FALSE if the block of buffer is not erased.
  750. --*/
  751. {
  752. UINT8 *CheckBuffer;
  753. UINTN Count;
  754. UINT8 EraseByte;
  755. EraseByte = 0;
  756. if (ErasePolarity != 0) {
  757. EraseByte = 0xFF;
  758. }
  759. CheckBuffer = Buffer;
  760. for (Count = 0; Count < BufferSize; Count += 1) {
  761. if (CheckBuffer[Count] != EraseByte) {
  762. return FALSE;
  763. }
  764. }
  765. return TRUE;
  766. }
  767. BOOLEAN
  768. EfipFvIsValidFfsHeader (
  769. UINT8 ErasePolarity,
  770. EFI_FFS_FILE_HEADER *FfsHeader,
  771. EFI_FFS_FILE_STATE *FileState
  772. )
  773. /*++
  774. Routine Description:
  775. This routine determines if the given supposed FFS file header is valid.
  776. Arguments:
  777. ErasePolarity - Supplies the erase polarity of the volume.
  778. FfsHeader - Supplies a pointer to the FFS file header to be checked.
  779. FileState - Supplies a pointer where the file state will be returned if the
  780. header is valid.
  781. Return Value:
  782. TRUE if the FFS file header is valid.
  783. FALSE if the header is not valid.
  784. --*/
  785. {
  786. *FileState = EfipFvGetFileState(ErasePolarity, FfsHeader);
  787. switch (*FileState) {
  788. //
  789. // If the file state looks good verify the header checksum.
  790. //
  791. case EFI_FILE_HEADER_VALID:
  792. case EFI_FILE_DATA_VALID:
  793. case EFI_FILE_MARKED_FOR_UPDATE:
  794. case EFI_FILE_DELETED:
  795. return EfipFvVerifyFileHeaderChecksum(FfsHeader);
  796. case EFI_FILE_HEADER_CONSTRUCTION:
  797. case EFI_FILE_HEADER_INVALID:
  798. default:
  799. break;
  800. }
  801. return FALSE;
  802. }
  803. BOOLEAN
  804. EfipFvIsValidFfsFile (
  805. UINT8 ErasePolarity,
  806. EFI_FFS_FILE_HEADER *FfsHeader
  807. )
  808. /*++
  809. Routine Description:
  810. This routine determines if the given supposed FFS file is valid.
  811. Arguments:
  812. ErasePolarity - Supplies the erase polarity of the volume.
  813. FfsHeader - Supplies a pointer to the FFS file header to be checked.
  814. Return Value:
  815. TRUE if the FFS file is valid.
  816. FALSE if the header is not valid.
  817. --*/
  818. {
  819. UINT8 DataChecksum;
  820. UINT8 *FileData;
  821. UINTN FileDataSize;
  822. EFI_FFS_FILE_STATE FileState;
  823. FileState = EfipFvGetFileState(ErasePolarity, FfsHeader);
  824. switch (FileState) {
  825. case EFI_FILE_DELETED:
  826. case EFI_FILE_DATA_VALID:
  827. case EFI_FILE_MARKED_FOR_UPDATE:
  828. DataChecksum = FFS_FIXED_CHECKSUM;
  829. if ((FfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) != 0) {
  830. if (EFI_IS_FFS_FILE2(FfsHeader)) {
  831. FileData = (UINT8 *)FfsHeader + sizeof(EFI_FFS_FILE_HEADER2);
  832. FileDataSize = EFI_FFS_FILE2_SIZE(FfsHeader) -
  833. sizeof(EFI_FFS_FILE_HEADER2);
  834. } else {
  835. FileData = (UINT8 *)FfsHeader + sizeof(EFI_FFS_FILE_HEADER);
  836. FileDataSize = EFI_FFS_FILE_SIZE(FfsHeader) -
  837. sizeof(EFI_FFS_FILE_HEADER);
  838. }
  839. DataChecksum = EfipFvCalculateChecksum8(FileData, FileDataSize);
  840. }
  841. if (FfsHeader->IntegrityCheck.Checksum.File == DataChecksum) {
  842. return TRUE;
  843. }
  844. break;
  845. default:
  846. break;
  847. }
  848. return FALSE;
  849. }
  850. EFI_FFS_FILE_STATE
  851. EfipFvGetFileState (
  852. UINT8 ErasePolarity,
  853. EFI_FFS_FILE_HEADER *FfsHeader
  854. )
  855. /*++
  856. Routine Description:
  857. This routine returns the FFS file state.
  858. Arguments:
  859. ErasePolarity - Supplies the erase polarity of the volume.
  860. FfsHeader - Supplies a pointer to the FFS file header.
  861. Return Value:
  862. Returns the FFS file state.
  863. --*/
  864. {
  865. EFI_FFS_FILE_STATE FileState;
  866. UINT8 HighestBit;
  867. FileState = FfsHeader->State;
  868. if (ErasePolarity != 0) {
  869. FileState = (EFI_FFS_FILE_STATE)~FileState;
  870. }
  871. HighestBit = 0x80;
  872. while ((HighestBit != 0) && ((HighestBit & FileState) == 0)) {
  873. HighestBit >>= 1;
  874. }
  875. return (EFI_FFS_FILE_STATE)HighestBit;
  876. }
  877. BOOLEAN
  878. EfipFvVerifyFileHeaderChecksum (
  879. EFI_FFS_FILE_HEADER *FfsHeader
  880. )
  881. /*++
  882. Routine Description:
  883. This routine verifies the checksum of an FFS file header.
  884. Arguments:
  885. FfsHeader - Supplies a pointer to the volume header to verify.
  886. Return Value:
  887. TRUE if the checksum verification passed.
  888. FALSE if the checksum verification failed.
  889. --*/
  890. {
  891. UINT8 HeaderChecksum;
  892. if (EFI_IS_FFS_FILE2(FfsHeader)) {
  893. HeaderChecksum = EfipFvCalculateSum8((UINT8 *)FfsHeader,
  894. sizeof(EFI_FFS_FILE_HEADER2));
  895. } else {
  896. HeaderChecksum = EfipFvCalculateSum8((UINT8 *)FfsHeader,
  897. sizeof(EFI_FFS_FILE_HEADER));
  898. }
  899. HeaderChecksum = (UINT8)(HeaderChecksum - FfsHeader->State -
  900. FfsHeader->IntegrityCheck.Checksum.File);
  901. if (HeaderChecksum == 0) {
  902. return TRUE;
  903. }
  904. return FALSE;
  905. }
  906. UINT16
  907. EfipFvCalculateSum16 (
  908. UINT16 *Buffer,
  909. UINTN Size
  910. )
  911. /*++
  912. Routine Description:
  913. This routine calculates the 16-bit checksum of the bytes in the given
  914. buffer.
  915. Arguments:
  916. Buffer - Supplies a pointer to a buffer containing byte data.
  917. Size - Supplies the size of the buffer in bytes.
  918. Return Value:
  919. Returns the 16-bit sum of the buffer words.
  920. --*/
  921. {
  922. UINTN Index;
  923. UINT16 Sum;
  924. Size = Size / sizeof(UINT16);
  925. Sum = 0;
  926. for (Index = 0; Index < Size; Index += 1) {
  927. Sum = (UINT16)(Sum + Buffer[Index]);
  928. }
  929. return Sum;
  930. }
  931. UINT8
  932. EfipFvCalculateChecksum8 (
  933. UINT8 *Buffer,
  934. UINTN Size
  935. )
  936. /*++
  937. Routine Description:
  938. This routine calculates the 8-bit checksum of the bytes in the given
  939. buffer.
  940. Arguments:
  941. Buffer - Supplies a pointer to a buffer containing byte data.
  942. Size - Supplies the size of the buffer.
  943. Return Value:
  944. Returns the 8-bit checksum of each byte in the buffer.
  945. --*/
  946. {
  947. return 0x100 - EfipFvCalculateSum8(Buffer, Size);
  948. }
  949. UINT8
  950. EfipFvCalculateSum8 (
  951. UINT8 *Buffer,
  952. UINTN Size
  953. )
  954. /*++
  955. Routine Description:
  956. This routine calculates the 8-bit sum of the bytes in the given buffer.
  957. Arguments:
  958. Buffer - Supplies a pointer to a buffer containing byte data.
  959. Size - Supplies the size of the buffer.
  960. Return Value:
  961. Returns the 8-bit checksum of each byte in the buffer.
  962. --*/
  963. {
  964. UINTN Index;
  965. UINT8 Sum;
  966. Sum = 0;
  967. for (Index = 0; Index < Size; Index += 1) {
  968. Sum = (UINT8)(Sum + Buffer[Index]);
  969. }
  970. return Sum;
  971. }