fwvolio.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902
  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. fwvolio.c
  9. Abstract:
  10. This module implements support for firmware volume I/O.
  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. EFI_FV_FILE_ATTRIBUTES
  31. EfipFvConvertFfsAttributesToFileAttributes (
  32. EFI_FFS_FILE_ATTRIBUTES FfsAttributes
  33. );
  34. //
  35. // -------------------------------------------------------------------- Globals
  36. //
  37. //
  38. // Define the conversion between FFS alignments and FW volume alignments.
  39. //
  40. UINT8 EfiFvFfsAlignments[] = {0, 4, 7, 9, 10, 12, 15, 16};
  41. //
  42. // ------------------------------------------------------------------ Functions
  43. //
  44. EFIAPI
  45. EFI_STATUS
  46. EfiFvGetVolumeAttributes (
  47. CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
  48. EFI_FV_ATTRIBUTES *Attributes
  49. )
  50. /*++
  51. Routine Description:
  52. This routine returns the attributes and current settings of the firmware
  53. volume. Because of constraints imposed by the underlying firmware storage,
  54. an instance of the Firmware Volume Protocol may not be to able to support
  55. all possible variations of this architecture. These constraints and the
  56. current state of the firmware volume are exposed to the caller using the
  57. get volume attributes function. The get volume attributes function is
  58. callable only from TPL_NOTIFY and below. Behavior of this routine at any
  59. EFI_TPL above TPL_NOTIFY is undefined.
  60. Arguments:
  61. This - Supplies the protocol instance.
  62. Attributes - Supplies a pointer where the volume attributes and current
  63. settings are returned.
  64. Return Value:
  65. EFI_SUCCESS on success.
  66. --*/
  67. {
  68. EFI_FVB_ATTRIBUTES BlockAttributes;
  69. EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *BlockIo;
  70. PEFI_FIRMWARE_VOLUME Device;
  71. EFI_STATUS Status;
  72. Device = EFI_FIRMWARE_VOLUME_FROM_THIS(This);
  73. BlockIo = Device->BlockIo;
  74. //
  75. // Get the firmware volume block attributes, then mask out anything that's
  76. // irrelevant.
  77. //
  78. Status = BlockIo->GetAttributes(BlockIo, &BlockAttributes);
  79. BlockAttributes &= 0xFFFFF0FF;
  80. *Attributes = (EFI_FV_ATTRIBUTES)BlockAttributes;
  81. return Status;
  82. }
  83. EFIAPI
  84. EFI_STATUS
  85. EfiFvSetVolumeAttributes (
  86. CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
  87. EFI_FV_ATTRIBUTES *Attributes
  88. )
  89. /*++
  90. Routine Description:
  91. This routine modifies current settings of the firmware volume according to
  92. the input parameter. This function is used to set configurable firmware
  93. volume attributes. Only EFI_FV_READ_STATUS, EFI_FV_WRITE_STATUS, and
  94. EFI_FV_LOCK_STATUS may be modified, and then only in accordance with the
  95. declared capabilities. All other bits of FvAttributes are ignored on input.
  96. On successful return, all bits of *FvAttributes are valid and it contains
  97. the completed EFI_FV_ATTRIBUTES for the volume. To modify an attribute, the
  98. corresponding status bit in the EFI_FV_ATTRIBUTES is set to the desired
  99. value on input. The EFI_FV_LOCK_STATUS bit does not affect the ability to
  100. read or write the firmware volume. Rather, once the EFI_FV_LOCK_STATUS bit
  101. is set, it prevents further modification to all the attribute bits. This
  102. routine is callable only from TPL_NOTIFY and below. Behavior of this
  103. routine at any EFI_TPL above TPL_NOTIFY is undefined.
  104. Arguments:
  105. This - Supplies the protocol instance.
  106. Attributes - Supplies a that on input contains the attributes to set. On
  107. output, the new current settings of the firmware volume are returned.
  108. Return Value:
  109. EFI_SUCCESS on success.
  110. EFI_INVALID_PARAMETER if the device does not support the status bit
  111. settings.
  112. EFI_ACCESS_DENIED if the device is locked and does not allow modification.
  113. --*/
  114. {
  115. return EFI_UNSUPPORTED;
  116. }
  117. EFIAPI
  118. EFI_STATUS
  119. EfiFvGetVolumeInfo (
  120. CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
  121. CONST EFI_GUID *InformationType,
  122. UINTN *BufferSize,
  123. VOID *Buffer
  124. )
  125. /*++
  126. Routine Description:
  127. This routine returns information about a firmware volume. this routine
  128. returns information of the requested type for the requested firmware
  129. volume. If the volume does not support the requested information type, then
  130. EFI_UNSUPPORTED is returned. If the buffer is not large enough to hold the
  131. requested structure, EFI_BUFFER_TOO_SMALL is returned and the buffer size
  132. is set to the size of buffer that is required to make the request. The
  133. information types defined by this specification are required information
  134. types that all file systems must support.
  135. Arguments:
  136. This - Supplies the protocol instance.
  137. InformationType - Supplies a pointer to the GUID defining the type of
  138. information being requested.
  139. BufferSize - Supplies a pointer that on input contains the size of the
  140. buffer. On output, contains the size of the data, even if the buffer
  141. was too small.
  142. Buffer - Supplies the buffer where the information value will be returned.
  143. Return Value:
  144. EFI_SUCCESS on success.
  145. EFI_UNSUPPORTED if the information type is not known.
  146. EFI_NO_MEDIA if the device has no media inserted.
  147. EFI_DEVICE_ERROR if a hardware error occurred accessing the device.
  148. EFI_VOLUME_CORRUPTED if the file system structures are gonezo.
  149. EFI_BUFFER_TOO_SMALL if the supplied buffer was not large enough to hold
  150. the requested value. In this case the buffer size will have been updated
  151. to contain the needed value.
  152. --*/
  153. {
  154. return EFI_UNSUPPORTED;
  155. }
  156. EFIAPI
  157. EFI_STATUS
  158. EfiFvSetVolumeInfo (
  159. CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
  160. CONST EFI_GUID *InformationType,
  161. UINTN BufferSize,
  162. CONST VOID *Buffer
  163. )
  164. /*++
  165. Routine Description:
  166. This routine sets information about a firmware volume.
  167. Arguments:
  168. This - Supplies the protocol instance.
  169. InformationType - Supplies a pointer to the GUID defining the type of
  170. information being set.
  171. BufferSize - Supplies the size of the information value in bytes.
  172. Buffer - Supplies the information value.
  173. Return Value:
  174. EFI_SUCCESS on success.
  175. EFI_UNSUPPORTED if the information type is not known.
  176. EFI_NO_MEDIA if the device has no media inserted.
  177. EFI_DEVICE_ERROR if a hardware error occurred accessing the device.
  178. EFI_VOLUME_CORRUPTED if the file system structures are gonezo.
  179. EFI_WRITE_PROTECTED if the volume is read-only.
  180. EFI_BAD_BUFFER_SIZE if the buffer size was smaller than the size of the
  181. type indicated in the information type GUID.
  182. --*/
  183. {
  184. return EFI_UNSUPPORTED;
  185. }
  186. EFIAPI
  187. EFI_STATUS
  188. EfiFvReadFileSection (
  189. CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
  190. CONST EFI_GUID *NameGuid,
  191. EFI_SECTION_TYPE SectionType,
  192. UINTN SectionInstance,
  193. VOID **Buffer,
  194. UINTN *BufferSize,
  195. UINT32 *AuthenticationStatus
  196. )
  197. /*++
  198. Routine Description:
  199. This routine locates the requested section within a file and returns it in
  200. a buffer. This routine is used to retrieve a specific section from a file
  201. within a firmware volume. The section returned is determined using a
  202. depth-first, left-to-right search algorithm through all sections found in
  203. the specified file. The output buffer is specified by a double indirection
  204. of the buffer parameter. The input value of Buffer is used to determine if
  205. the output buffer is caller allocated or is dynamically allocated by this
  206. routine. If the input value of the buffer is not NULL, it indicates that
  207. the output buffer is caller allocated. In this case, the input value of
  208. *BufferSize indicates the size of the caller-allocated output buffer. If
  209. the output buffer is not large enough to contain the entire requested
  210. output, it is filled up to the point that the output buffer is exhausted
  211. and EFI_WARN_BUFFER_TOO_SMALL is returned, and then BufferSize is returned
  212. with the size that is required to successfully complete the read. All other
  213. output parameters are returned with valid values. If the input value of the
  214. buffer is NULL, it indicates the output buffer is to be allocated by this
  215. routine. In this case, this routine will allocate an appropriately sized
  216. buffer from boot services pool memory, which will be returned in the buffer
  217. value. The size of the new buffer is returned in *BufferSize and all other
  218. output parameters are returned with valid values. This routine is callable
  219. only from TPL_NOTIFY and below. Behavior of this routine at any EFI_TPL
  220. above TPL_NOTIFY is undefined.
  221. Arguments:
  222. This - Supplies the protocol instance.
  223. NameGuid - Supplies a pointer to a GUID containing the name of the file.
  224. All firmware file names are EFI_GUIDs. Each firmware volume file name
  225. must be unique.
  226. SectionType - Supplies the type of section to return.
  227. SectionInstance - Supplies the occurrence of the given section type to
  228. return.
  229. Buffer - Supplies a pointer to a buffer in which the file contents are
  230. returned, not including the file header.
  231. BufferSize - Supplies a pointer that on input indicates the size of the
  232. supplied buffer in bytes.
  233. AuthenticationStatus - Supplies a pointer where the file authentication
  234. status will be returned.
  235. Return Value:
  236. EFI_SUCCESS on success.
  237. EFI_WARN_TOO_SMALL if the buffer is too small to contain the requested
  238. output. The buffer is filled and truncated.
  239. EFI_OUT_OF_RESOURCES if an allocation failed.
  240. EFI_NOT_FOUND if the requested file or section was not found in the
  241. firmware volume or file.
  242. EFI_DEVICE_ERROR if a hardware error occurred accessing the device.
  243. EFI_ACCESS_DENIED if the firmware volume is configured to disallow reads.
  244. EFI_PROTOCOL_ERROR if the requested section was not found, but the file
  245. could not be fully parsed because a required
  246. GUIDED_SECTION_EXTRACTION_PROTOCOL was not found. The requested section
  247. might have been found if only it could be extracted.
  248. --*/
  249. {
  250. PEFI_FIRMWARE_VOLUME Device;
  251. PEFI_FFS_FILE_LIST_ENTRY FfsEntry;
  252. EFI_FV_FILE_ATTRIBUTES FileAttributes;
  253. UINT8 *FileBuffer;
  254. UINTN FileSize;
  255. EFI_FV_FILETYPE FileType;
  256. EFI_STATUS Status;
  257. if ((NameGuid == NULL) || (Buffer == NULL)) {
  258. return EFI_INVALID_PARAMETER;
  259. }
  260. Device = EFI_FIRMWARE_VOLUME_FROM_THIS(This);
  261. //
  262. // Read the whole file into a buffer.
  263. //
  264. FileBuffer = NULL;
  265. FileSize = 0;
  266. Status = EfiFvReadFile(This,
  267. NameGuid,
  268. (VOID **)&FileBuffer,
  269. &FileSize,
  270. &FileType,
  271. &FileAttributes,
  272. AuthenticationStatus);
  273. if (EFI_ERROR(Status)) {
  274. return Status;
  275. }
  276. //
  277. // Get the last key used by the call to read file as it is the FFS entry
  278. // for this file.
  279. //
  280. FfsEntry = (PEFI_FFS_FILE_LIST_ENTRY)(Device->LastKey);
  281. if (FileType == EFI_FV_FILETYPE_RAW) {
  282. Status = EFI_NOT_FOUND;
  283. goto FvReadSectionEnd;
  284. }
  285. if (FfsEntry->StreamHandle == 0) {
  286. Status = EfiFvOpenSectionStream(FileSize,
  287. FileBuffer,
  288. &(FfsEntry->StreamHandle));
  289. if (EFI_ERROR(Status)) {
  290. goto FvReadSectionEnd;
  291. }
  292. }
  293. //
  294. // If the section type is zero then the whole stream is needed.
  295. //
  296. if (SectionType == 0) {
  297. Status = EfiFvGetSection(FfsEntry->StreamHandle,
  298. NULL,
  299. NULL,
  300. 0,
  301. Buffer,
  302. BufferSize,
  303. AuthenticationStatus,
  304. Device->IsFfs3);
  305. } else {
  306. Status = EfiFvGetSection(FfsEntry->StreamHandle,
  307. &SectionType,
  308. NULL,
  309. SectionInstance,
  310. Buffer,
  311. BufferSize,
  312. AuthenticationStatus,
  313. Device->IsFfs3);
  314. }
  315. if (!EFI_ERROR(Status)) {
  316. Status = Device->AuthenticationStatus;
  317. }
  318. FvReadSectionEnd:
  319. EfiCoreFreePool(FileBuffer);
  320. return Status;
  321. }
  322. EFIAPI
  323. EFI_STATUS
  324. EfiFvReadFile (
  325. CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
  326. CONST EFI_GUID *NameGuid,
  327. VOID **Buffer,
  328. UINTN *BufferSize,
  329. EFI_FV_FILETYPE *FoundType,
  330. EFI_FV_FILE_ATTRIBUTES *FileAttributes,
  331. UINT32 *AuthenticationStatus
  332. )
  333. /*++
  334. Routine Description:
  335. This routine retrieves a file and/or file information from the firmware
  336. volume. This routine is used to retrieve any file from a firmware volume
  337. during the DXE phase. The actual binary encoding of the file in the
  338. firmware volume media may be in any arbitrary format as long as it does the
  339. following: It is accessed using the Firmware Volume Protocol. The image
  340. that is returned follows the image format defined in Code Definitions:
  341. PI Firmware File Format. If the input buffer is NULL, it indicates the
  342. caller is requesting only that the type, attributes, and size of the file
  343. be returned and that there is no output buffer. In this case, the following
  344. occurs:
  345. - BufferSize is returned with the size that is required to
  346. successfully complete the read.
  347. - The output parameters FoundType and *FileAttributes are
  348. returned with valid values.
  349. - The returned value of *AuthenticationStatus is undefined.
  350. If the input buffer is not NULL, the output buffer is specified by a double
  351. indirection of the Buffer parameter. The input value of *Buffer is used to
  352. determine if the output buffer is caller allocated or is dynamically
  353. allocated by this routine. If the input value of *Buffer is not NULL, it
  354. indicates the output buffer is caller allocated. In this case, the input
  355. value of *BufferSize indicates the size of the caller-allocated output
  356. buffer. If the output buffer is not large enough to contain the entire
  357. requested output, it is filled up to the point that the output buffer is
  358. exhausted and EFI_WARN_BUFFER_TOO_SMALL is returned, and then BufferSize is
  359. returned with the size required to successfully complete the read. All
  360. other output parameters are returned with valid values. If the input buffer
  361. is NULL, it indicates the output buffer is to be allocated by this routine.
  362. In this case, this routine will allocate an appropriately sized buffer from
  363. boot services pool memory, which will be returned in Buffer. The size of
  364. the new buffer is returned in the buffer size parameter and all other
  365. output parameters are returned with valid values. This routine is callable
  366. only from TPL_NOTIFY and below. Behavior of this routine at any EFI_TPL
  367. above TPL_NOTIFY is undefined.
  368. Arguments:
  369. This - Supplies the protocol instance.
  370. NameGuid - Supplies a pointer to a GUID containing the name of the file.
  371. All firmware file names are EFI_GUIDs. Each firmware volume file name
  372. must be unique.
  373. Buffer - Supplies a pointer to a buffer in which the file contents are
  374. returned, not including the file header.
  375. BufferSize - Supplies a pointer that on input indicates the size of the
  376. supplied buffer in bytes.
  377. FoundType - Supplies a pointer where the file type will be returned.
  378. FileAttributes - Supplies a pointer where the file attributes will be
  379. returned.
  380. AuthenticationStatus - Supplies a pointer where the file authentication
  381. status will be returned.
  382. Return Value:
  383. EFI_SUCCESS on success.
  384. EFI_WARN_TOO_SMALL if the buffer is too small to contain the requested
  385. output. The buffer is filled and truncated.
  386. EFI_OUT_OF_RESOURCES if an allocation failed.
  387. EFI_NOT_FOUND if the given name was not in the firmware volume.
  388. EFI_DEVICE_ERROR if a hardware error occurred accessing the device.
  389. EFI_ACCESS_DENIED if the firmware volume is configured to disallow reads.
  390. --*/
  391. {
  392. PEFI_FIRMWARE_VOLUME Device;
  393. EFI_FFS_FILE_HEADER *FfsHeader;
  394. UINTN FileSize;
  395. UINTN InputBufferSize;
  396. EFI_FV_FILE_ATTRIBUTES LocalAttributes;
  397. EFI_FV_FILETYPE LocalFoundType;
  398. EFI_GUID SearchNameGuid;
  399. UINT8 *SourcePointer;
  400. EFI_STATUS Status;
  401. if (NameGuid == NULL) {
  402. return EFI_INVALID_PARAMETER;
  403. }
  404. Device = EFI_FIRMWARE_VOLUME_FROM_THIS(This);
  405. //
  406. // Keep working until the matching name GUID is found. The key is really an
  407. // FFS file list entry.
  408. //
  409. Device->LastKey = NULL;
  410. do {
  411. LocalFoundType = 0;
  412. Status = EfiFvGetNextFile(This,
  413. &(Device->LastKey),
  414. &LocalFoundType,
  415. &SearchNameGuid,
  416. &LocalAttributes,
  417. &FileSize);
  418. if (EFI_ERROR(Status)) {
  419. return EFI_NOT_FOUND;
  420. }
  421. } while (EfiCoreCompareGuids(&SearchNameGuid, (EFI_GUID *)NameGuid) ==
  422. FALSE);
  423. FfsHeader = Device->LastKey->FileHeader;
  424. InputBufferSize = *BufferSize;
  425. *FoundType = FfsHeader->Type;
  426. *FileAttributes = EfipFvConvertFfsAttributesToFileAttributes(
  427. FfsHeader->Attributes);
  428. if ((Device->VolumeHeader->Attributes & EFI_FVB_MEMORY_MAPPED) != 0) {
  429. *FileAttributes |= EFI_FV_FILE_ATTRIB_MEMORY_MAPPED;
  430. }
  431. *AuthenticationStatus = 0;
  432. *BufferSize = FileSize;
  433. //
  434. // If the buffer is NULL, then just the information is needed.
  435. //
  436. if (Buffer == NULL) {
  437. return EFI_SUCCESS;
  438. }
  439. //
  440. // Skip over the file header.
  441. //
  442. if (EFI_IS_FFS_FILE2(FfsHeader)) {
  443. SourcePointer = ((UINT8 *)FfsHeader) + sizeof(EFI_FFS_FILE_HEADER2);
  444. } else {
  445. SourcePointer = ((UINT8 *)FfsHeader) + sizeof(EFI_FFS_FILE_HEADER);
  446. }
  447. Status = EFI_SUCCESS;
  448. if (*Buffer == NULL) {
  449. *Buffer = EfiCoreAllocateBootPool(FileSize);
  450. if (*Buffer == NULL) {
  451. return EFI_OUT_OF_RESOURCES;
  452. }
  453. } else if (FileSize > InputBufferSize) {
  454. Status = EFI_WARN_BUFFER_TOO_SMALL;
  455. FileSize = InputBufferSize;
  456. }
  457. EfiCoreCopyMemory(*Buffer, SourcePointer, FileSize);
  458. return Status;
  459. }
  460. EFIAPI
  461. EFI_STATUS
  462. EfiFvGetNextFile (
  463. CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
  464. VOID *Key,
  465. EFI_FV_FILETYPE *FileType,
  466. EFI_GUID *NameGuid,
  467. EFI_FV_FILE_ATTRIBUTES *Attributes,
  468. UINTN *Size
  469. )
  470. /*++
  471. Routine Description:
  472. This routine retrieves information about the next file in the firmware
  473. volume store that matches the search criteria. This routine is the
  474. interface that is used to search a firmware volume for a particular file.
  475. It is called successively until the desired file is located or the function
  476. returns EFI_NOT_FOUND. To filter uninteresting files from the output, the
  477. type of file to search for may be specified in FileType. For example, if the
  478. file type is EFI_FV_FILETYPE_DRIVER, only files of this type will be
  479. returned in the output. If the file type is EFI_FV_FILETYPE_ALL, no
  480. filtering of file types is done. The key parameter is used to indicate a
  481. starting point of the search. If the value of the key parameter is
  482. completely initialized to zero, the search re-initialized and starts at the
  483. beginning. Subsequent calls to this routine must maintain the value of *Key
  484. returned by the immediately previous call. The actual contents of *Key are
  485. implementation specific and no semantic content is implied. This routine is
  486. callable only from TPL_NOTIFY and below. Behavior of this routine at any
  487. EFI_TPL above TPL_NOTIFY is undefined.
  488. Arguments:
  489. This - Supplies the protocol instance.
  490. Key - Supplies a pointer to a caller-allocated buffer containing the
  491. implementation-specific data used to track the current position of the
  492. search. The size of the buffer must be at least This->KeySize bytes
  493. long. To re-initialize the search and begin from the beginning of the
  494. firmware volume, the entire buffer must be cleared to zero. Other than
  495. clearing the buffer to initiate a new search, the caller must not
  496. modify the data in the buffer between calls to this routine.
  497. FileType - Supplies a pointer that on input contains the filter of file
  498. types to search for. If a file is found, its type will be returned
  499. here.
  500. NameGuid - Supplies a pointer where the name GUID of the file will be
  501. returned on success.
  502. Attributes - Supplies a pointer where the file attributes will be returned
  503. on success.
  504. Size - Supplies a pointer where the size of the file is returned on success.
  505. Return Value:
  506. EFI_SUCCESS on success.
  507. EFI_NOT_FOUND if no files of the given file type were found.
  508. EFI_DEVICE_ERROR if a hardware error occurred accessing the device.
  509. EFI_ACCESS_DENIED if the firmware volume does not allow reads.
  510. --*/
  511. {
  512. PLIST_ENTRY CurrentEntry;
  513. PEFI_FIRMWARE_VOLUME Device;
  514. PEFI_FFS_FILE_LIST_ENTRY FfsEntry;
  515. EFI_FFS_FILE_HEADER *FfsHeader;
  516. UINTN *KeyValue;
  517. EFI_STATUS Status;
  518. EFI_FV_ATTRIBUTES VolumeAttributes;
  519. Device = EFI_FIRMWARE_VOLUME_FROM_THIS(This);
  520. Status = EfiFvGetVolumeAttributes(This, &VolumeAttributes);
  521. if (EFI_ERROR(Status)) {
  522. return Status;
  523. }
  524. //
  525. // Fail if the read operation is not enabled.
  526. //
  527. if ((VolumeAttributes & EFI_FV2_READ_STATUS) == 0) {
  528. return EFI_ACCESS_DENIED;
  529. }
  530. if (*FileType > EFI_FV_FILETYPE_SMM_CORE) {
  531. return EFI_NOT_FOUND;
  532. }
  533. KeyValue = (UINTN *)Key;
  534. while (TRUE) {
  535. if (*KeyValue == 0) {
  536. CurrentEntry = &(Device->FfsFileList);
  537. } else {
  538. CurrentEntry = (PLIST_ENTRY)(*KeyValue);
  539. }
  540. //
  541. // If the next entry is the end of the list then there are no more
  542. // files.
  543. //
  544. if (CurrentEntry->Next == &(Device->FfsFileList)) {
  545. return EFI_NOT_FOUND;
  546. }
  547. FfsEntry = LIST_VALUE(CurrentEntry->Next,
  548. EFI_FFS_FILE_LIST_ENTRY,
  549. ListEntry);
  550. FfsHeader = FfsEntry->FileHeader;
  551. //
  552. // Save the key.
  553. //
  554. *KeyValue = (UINTN)&(FfsEntry->ListEntry);
  555. //
  556. // Stop if there's a match. Ignore pad files.
  557. //
  558. if (FfsHeader->Type == EFI_FV_FILETYPE_FFS_PAD) {
  559. continue;
  560. }
  561. if ((*FileType == EFI_FV_FILETYPE_ALL) ||
  562. (*FileType == FfsHeader->Type)) {
  563. break;
  564. }
  565. }
  566. //
  567. // Populate the return values.
  568. //
  569. *FileType = FfsHeader->Type;
  570. EfiCoreCopyMemory(NameGuid, &(FfsHeader->Name), sizeof(EFI_GUID));
  571. *Attributes = EfipFvConvertFfsAttributesToFileAttributes(
  572. FfsHeader->Attributes);
  573. if ((Device->VolumeHeader->Attributes & EFI_FVB_MEMORY_MAPPED) != 0) {
  574. *Attributes |= EFI_FV_FILE_ATTRIB_MEMORY_MAPPED;
  575. }
  576. //
  577. // Subtract the size of the header.
  578. //
  579. if (EFI_IS_FFS_FILE2(FfsHeader)) {
  580. *Size = EFI_FFS_FILE2_SIZE(FfsHeader) - sizeof(EFI_FFS_FILE_HEADER2);
  581. } else {
  582. *Size = EFI_FFS_FILE_SIZE(FfsHeader) - sizeof(EFI_FFS_FILE_HEADER);
  583. }
  584. return EFI_SUCCESS;
  585. }
  586. EFIAPI
  587. EFI_STATUS
  588. EfiFvWriteFile (
  589. CONST EFI_FIRMWARE_VOLUME2_PROTOCOL *This,
  590. UINT32 NumberOfFiles,
  591. EFI_FV_WRITE_POLICY WritePolicy,
  592. EFI_FV_WRITE_FILE_DATA *FileData
  593. )
  594. /*++
  595. Routine Description:
  596. This routine is used to write one or more files to a firmware volume. Each
  597. file to be written is described by an EFI_FV_WRITE_FILE_DATA structure.
  598. The caller must ensure that any required alignment for all files listed in
  599. the file data array is compatible with the firmware volume. Firmware volume
  600. capabilities can be determined using the get volume attributes function.
  601. Similarly, if the write policy is set to EFI_FV_RELIABLE_WRITE, the caller
  602. must check the firmware volume capabilities to ensure EFI_FV_RELIABLE_WRITE
  603. is supported by the firmware volume. EFI_FV_UNRELIABLE_WRITE must always be
  604. supported. Writing a file with a size of zero (FileData[n].BufferSize == 0)
  605. deletes the file from the firmware volume if it exists. Deleting a file
  606. must be done one at a time. Deleting a file as part of a multiple file
  607. write is not allowed. This routine is callable only from TPL_NOTIFY and
  608. below. Behavior of this routine at any EFI_TPL above TPL_NOTIFY is
  609. undefined.
  610. Arguments:
  611. This - Supplies the protocol instance.
  612. NumberOfFiles - Supplies the number of elements in the write file data
  613. array.
  614. WritePolicy - Supplies the level of reliability for the write in the event
  615. of a power failure or other system failure during the write operation.
  616. FileData - Supplies a pointer to an array of file data structures, where
  617. each element represents a file to be written.
  618. Return Value:
  619. EFI_SUCCESS on success.
  620. EFI_OUT_OF_RESOURCES if an allocation failed.
  621. EFI_NOT_FOUND if a delete was requested but the specified file was not
  622. found.
  623. EFI_DEVICE_ERROR if a hardware error occurred accessing the device.
  624. EFI_WRITE_PROTECTED if the firmware volume is configured to disallow writes.
  625. EFI_INVALID_PARAMETER if a delete was requested with multiple file writes,
  626. the write policy was unsupported, an unknown file type was specified, or a
  627. file system specific error occurred.
  628. --*/
  629. {
  630. return EFI_UNSUPPORTED;
  631. }
  632. //
  633. // --------------------------------------------------------- Internal Functions
  634. //
  635. EFI_FV_FILE_ATTRIBUTES
  636. EfipFvConvertFfsAttributesToFileAttributes (
  637. EFI_FFS_FILE_ATTRIBUTES FfsAttributes
  638. )
  639. /*++
  640. Routine Description:
  641. This routine converts FFS file attributes into Firmware Volume file
  642. attributes.
  643. Arguments:
  644. FfsAttributes - Supplies the FFS file attributes.
  645. Return Value:
  646. Returns the file attributes.
  647. --*/
  648. {
  649. UINT8 DataAlignment;
  650. EFI_FV_FILE_ATTRIBUTES FileAttributes;
  651. DataAlignment = (UINT8)((FfsAttributes & FFS_ATTRIB_DATA_ALIGNMENT) >> 3);
  652. ASSERT(DataAlignment < 8);
  653. FileAttributes = EfiFvFfsAlignments[DataAlignment];
  654. if ((FfsAttributes & FFS_ATTRIB_FIXED) != 0) {
  655. FileAttributes |= EFI_FV_FILE_ATTRIB_FIXED;
  656. }
  657. return FileAttributes;
  658. }