2 MDE DXE Services Library provides functions that simplify the development of DXE Drivers.
3 These functions help access data from sections of FFS files or from file path.
5 Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.<BR>
6 (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php.
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include <Library/DebugLib.h>
19 #include <Library/MemoryAllocationLib.h>
20 #include <Library/UefiBootServicesTableLib.h>
21 #include <Library/DevicePathLib.h>
22 #include <Library/UefiLib.h>
23 #include <Library/DxeServicesLib.h>
24 #include <Protocol/FirmwareVolume2.h>
25 #include <Protocol/LoadedImage.h>
26 #include <Protocol/LoadFile2.h>
27 #include <Protocol/LoadFile.h>
28 #include <Protocol/SimpleFileSystem.h>
29 #include <Guid/FileInfo.h>
32 Identify the device handle from which the Image is loaded from. As this device handle is passed to
33 GetSectionFromFv as the identifier for a Firmware Volume, an EFI_FIRMWARE_VOLUME2_PROTOCOL
34 protocol instance should be located succesfully by calling gBS->HandleProtocol ().
36 This function locates the EFI_LOADED_IMAGE_PROTOCOL instance installed
37 on ImageHandle. It then returns EFI_LOADED_IMAGE_PROTOCOL.DeviceHandle.
39 If ImageHandle is NULL, then ASSERT ();
40 If failed to locate a EFI_LOADED_IMAGE_PROTOCOL on ImageHandle, then ASSERT ();
42 @param ImageHandle The firmware allocated handle for UEFI image.
44 @retval EFI_HANDLE The device handle from which the Image is loaded from.
48 InternalImageHandleToFvHandle (
49 EFI_HANDLE ImageHandle
53 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
55 ASSERT (ImageHandle
!= NULL
);
57 Status
= gBS
->HandleProtocol (
58 (EFI_HANDLE
*) ImageHandle
,
59 &gEfiLoadedImageProtocolGuid
,
60 (VOID
**) &LoadedImage
63 ASSERT_EFI_ERROR (Status
);
66 // The LoadedImage->DeviceHandle may be NULL.
67 // For example for DxeCore, there is LoadedImage protocol installed for it, but the
68 // LoadedImage->DeviceHandle could not be initialized before the FV2 (contain DxeCore)
69 // protocol is installed.
71 return LoadedImage
->DeviceHandle
;
76 Allocate and fill a buffer from a Firmware Section identified by a Firmware File GUID name, a Firmware
77 Section type and instance number from the specified Firmware Volume.
79 This functions first locate the EFI_FIRMWARE_VOLUME2_PROTOCOL protocol instance on FvHandle in order to
80 carry out the Firmware Volume read operation. The function then reads the Firmware Section found sepcifed
81 by NameGuid, SectionType and SectionInstance.
83 The details of this search order is defined in description of EFI_FIRMWARE_VOLUME2_PROTOCOL.ReadSection ()
84 found in PI Specification.
86 If SectionType is EFI_SECTION_TE, EFI_SECTION_TE is used as section type to start the search. If EFI_SECTION_TE section
87 is not found, EFI_SECTION_PE32 will be used to try the search again. If no EFI_SECTION_PE32 section is found, EFI_NOT_FOUND
90 The data and size is returned by Buffer and Size. The caller is responsible to free the Buffer allocated
91 by this function. This function can be only called at TPL_NOTIFY and below.
93 If NameGuid is NULL, then ASSERT();
94 If Buffer is NULL, then ASSERT();
95 If Size is NULL, then ASSERT().
97 @param FvHandle The device handle that contains a instance of
98 EFI_FIRMWARE_VOLUME2_PROTOCOL instance.
99 @param NameGuid The GUID name of a Firmware File.
100 @param SectionType The Firmware Section type.
101 @param SectionInstance The instance number of Firmware Section to
102 read from starting from 0.
103 @param Buffer On output, Buffer contains the the data read
104 from the section in the Firmware File found.
105 @param Size On output, the size of Buffer.
107 @retval EFI_SUCCESS The image is found and data and size is returned.
108 @retval EFI_NOT_FOUND The image specified by NameGuid and SectionType
110 @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate the
111 output data buffer or complete the operations.
112 @retval EFI_DEVICE_ERROR A hardware error occurs during reading from the
114 @retval EFI_ACCESS_DENIED The firmware volume containing the searched
115 Firmware File is configured to disallow reads.
119 InternalGetSectionFromFv (
120 IN EFI_HANDLE FvHandle
,
121 IN CONST EFI_GUID
*NameGuid
,
122 IN EFI_SECTION_TYPE SectionType
,
123 IN UINTN SectionInstance
,
129 EFI_FIRMWARE_VOLUME2_PROTOCOL
*Fv
;
130 UINT32 AuthenticationStatus
;
132 ASSERT (NameGuid
!= NULL
);
133 ASSERT (Buffer
!= NULL
);
134 ASSERT (Size
!= NULL
);
136 if (FvHandle
== NULL
) {
138 // Return EFI_NOT_FOUND directly for NULL FvHandle.
140 return EFI_NOT_FOUND
;
143 Status
= gBS
->HandleProtocol (
145 &gEfiFirmwareVolume2ProtocolGuid
,
148 if (EFI_ERROR (Status
)) {
149 return EFI_NOT_FOUND
;
153 // Read desired section content in NameGuid file
157 Status
= Fv
->ReadSection (
164 &AuthenticationStatus
167 if (EFI_ERROR (Status
) && (SectionType
== EFI_SECTION_TE
)) {
169 // Try reading PE32 section, if the required section is TE type
173 Status
= Fv
->ReadSection (
180 &AuthenticationStatus
188 Searches all the available firmware volumes and returns the first matching FFS section.
190 This function searches all the firmware volumes for FFS files with FV file type specified by FileType
191 The order that the firmware volumes is searched is not deterministic. For each available FV a search
192 is made for FFS file of type FileType. If the FV contains more than one FFS file with the same FileType,
193 the FileInstance instance will be the matched FFS file. For each FFS file found a search
194 is made for FFS sections of type SectionType. If the FFS file contains at least SectionInstance instances
195 of the FFS section specified by SectionType, then the SectionInstance instance is returned in Buffer.
196 Buffer is allocated using AllocatePool(), and the size of the allocated buffer is returned in Size.
197 It is the caller's responsibility to use FreePool() to free the allocated buffer.
198 See EFI_FIRMWARE_VOLUME2_PROTOCOL.ReadSection() for details on how sections
199 are retrieved from an FFS file based on SectionType and SectionInstance.
201 If SectionType is EFI_SECTION_TE, and the search with an FFS file fails,
202 the search will be retried with a section type of EFI_SECTION_PE32.
203 This function must be called with a TPL <= TPL_NOTIFY.
205 If Buffer is NULL, then ASSERT().
206 If Size is NULL, then ASSERT().
208 @param FileType Indicates the FV file type to search for within all
210 @param FileInstance Indicates which file instance within all available
211 FVs specified by FileType.
212 FileInstance starts from zero.
213 @param SectionType Indicates the FFS section type to search for
215 specified by FileType with FileInstance.
216 @param SectionInstance Indicates which section instance within the FFS file
217 specified by FileType with FileInstance to retrieve.
218 SectionInstance starts from zero.
219 @param Buffer On output, a pointer to a callee allocated buffer
220 containing the FFS file section that was found.
221 Is it the caller's responsibility to free this
222 buffer using FreePool().
223 @param Size On output, a pointer to the size, in bytes, of Buffer.
225 @retval EFI_SUCCESS The specified FFS section was returned.
226 @retval EFI_NOT_FOUND The specified FFS section could not be found.
227 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to retrieve
228 the matching FFS section.
229 @retval EFI_DEVICE_ERROR The FFS section could not be retrieves due to a
231 @retval EFI_ACCESS_DENIED The FFS section could not be retrieves because
232 the firmware volume that
233 contains the matching FFS section does not allow reads.
237 GetSectionFromAnyFvByFileType (
238 IN EFI_FV_FILETYPE FileType
,
239 IN UINTN FileInstance
,
240 IN EFI_SECTION_TYPE SectionType
,
241 IN UINTN SectionInstance
,
247 EFI_HANDLE
*HandleBuffer
;
253 EFI_FV_FILE_ATTRIBUTES Attributes
;
254 EFI_FIRMWARE_VOLUME2_PROTOCOL
*Fv
;
257 // Locate all available FVs.
260 Status
= gBS
->LocateHandleBuffer (
262 &gEfiFirmwareVolume2ProtocolGuid
,
267 if (EFI_ERROR (Status
)) {
272 // Go through FVs one by one to find the required section data.
274 for (IndexFv
= 0; IndexFv
< HandleCount
; IndexFv
++) {
275 Status
= gBS
->HandleProtocol (
276 HandleBuffer
[IndexFv
],
277 &gEfiFirmwareVolume2ProtocolGuid
,
280 if (EFI_ERROR (Status
)) {
285 // Use Firmware Volume 2 Protocol to search for a file of type FileType in all FVs.
287 IndexFile
= FileInstance
+ 1;
290 Status
= Fv
->GetNextFile (Fv
, &Key
, &FileType
, &NameGuid
, &Attributes
, Size
);
291 if (EFI_ERROR (Status
)) {
295 } while (IndexFile
> 0);
298 // Fv File with the required FV file type is found.
299 // Search the section file in the found FV file.
301 if (IndexFile
== 0) {
302 Status
= InternalGetSectionFromFv (
303 HandleBuffer
[IndexFv
],
311 if (!EFI_ERROR (Status
)) {
318 // The required FFS section file is not found.
320 if (IndexFv
== HandleCount
) {
321 Status
= EFI_NOT_FOUND
;
325 if (HandleBuffer
!= NULL
) {
326 FreePool(HandleBuffer
);
333 Searches all the availables firmware volumes and returns the first matching FFS section.
335 This function searches all the firmware volumes for FFS files with an FFS filename specified by NameGuid.
336 The order that the firmware volumes is searched is not deterministic. For each FFS file found a search
337 is made for FFS sections of type SectionType. If the FFS file contains at least SectionInstance instances
338 of the FFS section specified by SectionType, then the SectionInstance instance is returned in Buffer.
339 Buffer is allocated using AllocatePool(), and the size of the allocated buffer is returned in Size.
340 It is the caller's responsibility to use FreePool() to free the allocated buffer.
341 See EFI_FIRMWARE_VOLUME2_PROTOCOL.ReadSection() for details on how sections
342 are retrieved from an FFS file based on SectionType and SectionInstance.
344 If SectionType is EFI_SECTION_TE, and the search with an FFS file fails,
345 the search will be retried with a section type of EFI_SECTION_PE32.
346 This function must be called with a TPL <= TPL_NOTIFY.
348 If NameGuid is NULL, then ASSERT().
349 If Buffer is NULL, then ASSERT().
350 If Size is NULL, then ASSERT().
353 @param NameGuid A pointer to to the FFS filename GUID to search for
354 within any of the firmware volumes in the platform.
355 @param SectionType Indicates the FFS section type to search for within
356 the FFS file specified by NameGuid.
357 @param SectionInstance Indicates which section instance within the FFS file
358 specified by NameGuid to retrieve.
359 @param Buffer On output, a pointer to a callee allocated buffer
360 containing the FFS file section that was found.
361 Is it the caller's responsibility to free this buffer
363 @param Size On output, a pointer to the size, in bytes, of Buffer.
365 @retval EFI_SUCCESS The specified FFS section was returned.
366 @retval EFI_NOT_FOUND The specified FFS section could not be found.
367 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to
368 retrieve the matching FFS section.
369 @retval EFI_DEVICE_ERROR The FFS section could not be retrieves due to a
371 @retval EFI_ACCESS_DENIED The FFS section could not be retrieves because the
373 contains the matching FFS section does not allow reads.
377 GetSectionFromAnyFv (
378 IN CONST EFI_GUID
*NameGuid
,
379 IN EFI_SECTION_TYPE SectionType
,
380 IN UINTN SectionInstance
,
386 EFI_HANDLE
*HandleBuffer
;
392 // Search the FV that contain the caller's FFS first.
393 // FV builder can choose to build FFS into the this FV
394 // so that this implementation of GetSectionFromAnyFv
395 // will locate the FFS faster.
397 FvHandle
= InternalImageHandleToFvHandle (gImageHandle
);
398 Status
= InternalGetSectionFromFv (
406 if (!EFI_ERROR (Status
)) {
411 Status
= gBS
->LocateHandleBuffer (
413 &gEfiFirmwareVolume2ProtocolGuid
,
418 if (EFI_ERROR (Status
)) {
422 for (Index
= 0; Index
< HandleCount
; Index
++) {
424 // Skip the FV that contain the caller's FFS
426 if (HandleBuffer
[Index
] != FvHandle
) {
427 Status
= InternalGetSectionFromFv (
436 if (!EFI_ERROR (Status
)) {
443 if (Index
== HandleCount
) {
444 Status
= EFI_NOT_FOUND
;
449 if (HandleBuffer
!= NULL
) {
450 FreePool(HandleBuffer
);
457 Searches the firmware volume that the currently executing module was loaded from and returns the first matching FFS section.
459 This function searches the firmware volume that the currently executing module was loaded
460 from for an FFS file with an FFS filename specified by NameGuid. If the FFS file is found a search
461 is made for FFS sections of type SectionType. If the FFS file contains at least SectionInstance
462 instances of the FFS section specified by SectionType, then the SectionInstance instance is returned in Buffer.
463 Buffer is allocated using AllocatePool(), and the size of the allocated buffer is returned in Size.
464 It is the caller's responsibility to use FreePool() to free the allocated buffer.
465 See EFI_FIRMWARE_VOLUME2_PROTOCOL.ReadSection() for details on how sections are retrieved from
466 an FFS file based on SectionType and SectionInstance.
468 If the currently executing module was not loaded from a firmware volume, then EFI_NOT_FOUND is returned.
469 If SectionType is EFI_SECTION_TE, and the search with an FFS file fails,
470 the search will be retried with a section type of EFI_SECTION_PE32.
472 This function must be called with a TPL <= TPL_NOTIFY.
473 If NameGuid is NULL, then ASSERT().
474 If Buffer is NULL, then ASSERT().
475 If Size is NULL, then ASSERT().
477 @param NameGuid A pointer to to the FFS filename GUID to search for
478 within the firmware volumes that the currently
479 executing module was loaded from.
480 @param SectionType Indicates the FFS section type to search for within
481 the FFS file specified by NameGuid.
482 @param SectionInstance Indicates which section instance within the FFS file
483 specified by NameGuid to retrieve.
484 @param Buffer On output, a pointer to a callee allocated buffer
485 containing the FFS file section that was found.
486 Is it the caller's responsibility to free this buffer
488 @param Size On output, a pointer to the size, in bytes, of Buffer.
491 @retval EFI_SUCCESS The specified FFS section was returned.
492 @retval EFI_NOT_FOUND The specified FFS section could not be found.
493 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to retrieve
494 the matching FFS section.
495 @retval EFI_DEVICE_ERROR The FFS section could not be retrieves due to a
497 @retval EFI_ACCESS_DENIED The FFS section could not be retrieves because the
498 firmware volume that contains the matching FFS
499 section does not allow reads.
504 IN CONST EFI_GUID
*NameGuid
,
505 IN EFI_SECTION_TYPE SectionType
,
506 IN UINTN SectionInstance
,
511 return InternalGetSectionFromFv (
512 InternalImageHandleToFvHandle(gImageHandle
),
523 Searches the FFS file the the currently executing module was loaded from and returns the first matching FFS section.
525 This function searches the FFS file that the currently executing module was loaded from for a FFS sections of type SectionType.
526 If the FFS file contains at least SectionInstance instances of the FFS section specified by SectionType,
527 then the SectionInstance instance is returned in Buffer. Buffer is allocated using AllocatePool(),
528 and the size of the allocated buffer is returned in Size. It is the caller's responsibility
529 to use FreePool() to free the allocated buffer. See EFI_FIRMWARE_VOLUME2_PROTOCOL.ReadSection() for
530 details on how sections are retrieved from an FFS file based on SectionType and SectionInstance.
532 If the currently executing module was not loaded from an FFS file, then EFI_NOT_FOUND is returned.
533 If SectionType is EFI_SECTION_TE, and the search with an FFS file fails,
534 the search will be retried with a section type of EFI_SECTION_PE32.
535 This function must be called with a TPL <= TPL_NOTIFY.
537 If Buffer is NULL, then ASSERT().
538 If Size is NULL, then ASSERT().
541 @param SectionType Indicates the FFS section type to search for within
542 the FFS file that the currently executing module
544 @param SectionInstance Indicates which section instance to retrieve within
545 the FFS file that the currently executing module
547 @param Buffer On output, a pointer to a callee allocated buffer
548 containing the FFS file section that was found.
549 Is it the caller's responsibility to free this buffer
551 @param Size On output, a pointer to the size, in bytes, of Buffer.
553 @retval EFI_SUCCESS The specified FFS section was returned.
554 @retval EFI_NOT_FOUND The specified FFS section could not be found.
555 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to retrieve
556 the matching FFS section.
557 @retval EFI_DEVICE_ERROR The FFS section could not be retrieves due to a
559 @retval EFI_ACCESS_DENIED The FFS section could not be retrieves because the
560 firmware volume that contains the matching FFS
561 section does not allow reads.
567 IN EFI_SECTION_TYPE SectionType
,
568 IN UINTN SectionInstance
,
573 return InternalGetSectionFromFv(
574 InternalImageHandleToFvHandle(gImageHandle
),
585 Get the image file buffer data and buffer size by its device path.
587 Access the file either from a firmware volume, from a file system interface,
588 or from the load file interface.
590 Allocate memory to store the found image. The caller is responsible to free memory.
592 If FilePath is NULL, then NULL is returned.
593 If FileSize is NULL, then NULL is returned.
594 If AuthenticationStatus is NULL, then NULL is returned.
596 @param[in] BootPolicy Policy for Open Image File.If TRUE, indicates
597 that the request originates from the boot
598 manager, and that the boot manager is
599 attempting to load FilePath as a boot
600 selection. If FALSE, then FilePath must
601 match an exact file to be loaded.
602 @param[in] FilePath The pointer to the device path of the file
603 that is absracted to the file buffer.
604 @param[out] FileSize The pointer to the size of the abstracted
606 @param[out] AuthenticationStatus Pointer to the authentication status.
608 @retval NULL FilePath is NULL, or FileSize is NULL, or AuthenticationStatus is NULL, or the file can't be found.
609 @retval other The abstracted file buffer. The caller is responsible to free memory.
613 GetFileBufferByFilePath (
614 IN BOOLEAN BootPolicy
,
615 IN CONST EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
617 OUT UINT32
*AuthenticationStatus
620 EFI_DEVICE_PATH_PROTOCOL
*DevicePathNode
;
621 EFI_DEVICE_PATH_PROTOCOL
*OrigDevicePathNode
;
622 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePathNode
;
624 EFI_GUID
*FvNameGuid
;
625 EFI_FIRMWARE_VOLUME2_PROTOCOL
*FwVol
;
626 EFI_SECTION_TYPE SectionType
;
628 UINTN ImageBufferSize
;
629 EFI_FV_FILETYPE Type
;
630 EFI_FV_FILE_ATTRIBUTES Attrib
;
631 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*Volume
;
632 EFI_FILE_HANDLE FileHandle
;
633 EFI_FILE_HANDLE LastHandle
;
634 EFI_FILE_INFO
*FileInfo
;
636 EFI_LOAD_FILE_PROTOCOL
*LoadFile
;
637 EFI_LOAD_FILE2_PROTOCOL
*LoadFile2
;
641 // Check input File device path.
643 if (FilePath
== NULL
|| FileSize
== NULL
|| AuthenticationStatus
== NULL
) {
648 // Init local variable
650 TempDevicePathNode
= NULL
;
656 *AuthenticationStatus
= 0;
659 // Copy File Device Path
661 OrigDevicePathNode
= DuplicateDevicePath (FilePath
);
662 if (OrigDevicePathNode
== NULL
) {
667 // Check whether this device path support FV2 protocol.
668 // Is so, this device path may contain a Image.
670 DevicePathNode
= OrigDevicePathNode
;
671 Status
= gBS
->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid
, &DevicePathNode
, &Handle
);
672 if (!EFI_ERROR (Status
)) {
674 // For FwVol File system there is only a single file name that is a GUID.
676 FvNameGuid
= EfiGetNameGuidFromFwVolDevicePathNode ((CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) DevicePathNode
);
677 if (FvNameGuid
== NULL
) {
678 Status
= EFI_INVALID_PARAMETER
;
681 // Read image from the firmware file
683 Status
= gBS
->HandleProtocol (Handle
, &gEfiFirmwareVolume2ProtocolGuid
, (VOID
**)&FwVol
);
684 if (!EFI_ERROR (Status
)) {
685 SectionType
= EFI_SECTION_PE32
;
687 Status
= FwVol
->ReadSection (
692 (VOID
**)&ImageBuffer
,
696 if (EFI_ERROR (Status
)) {
698 // Try a raw file, since a PE32 SECTION does not exist
700 if (ImageBuffer
!= NULL
) {
701 FreePool (ImageBuffer
);
702 *AuthenticationStatus
= 0;
705 Status
= FwVol
->ReadFile (
708 (VOID
**)&ImageBuffer
,
717 if (!EFI_ERROR (Status
)) {
723 // Attempt to access the file via a file system interface
725 DevicePathNode
= OrigDevicePathNode
;
726 Status
= gBS
->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid
, &DevicePathNode
, &Handle
);
727 if (!EFI_ERROR (Status
)) {
728 Status
= gBS
->HandleProtocol (Handle
, &gEfiSimpleFileSystemProtocolGuid
, (VOID
**)&Volume
);
729 if (!EFI_ERROR (Status
)) {
731 // Open the Volume to get the File System handle
733 Status
= Volume
->OpenVolume (Volume
, &FileHandle
);
734 if (!EFI_ERROR (Status
)) {
736 // Duplicate the device path to avoid the access to unaligned device path node.
737 // Because the device path consists of one or more FILE PATH MEDIA DEVICE PATH
738 // nodes, It assures the fields in device path nodes are 2 byte aligned.
740 TempDevicePathNode
= DuplicateDevicePath (DevicePathNode
);
741 if (TempDevicePathNode
== NULL
) {
742 FileHandle
->Close (FileHandle
);
744 // Setting Status to an EFI_ERROR value will cause the rest of
745 // the file system support below to be skipped.
747 Status
= EFI_OUT_OF_RESOURCES
;
750 // Parse each MEDIA_FILEPATH_DP node. There may be more than one, since the
751 // directory information and filename can be seperate. The goal is to inch
752 // our way down each device path node and close the previous node
754 DevicePathNode
= TempDevicePathNode
;
755 while (!EFI_ERROR (Status
) && !IsDevicePathEnd (DevicePathNode
)) {
756 if (DevicePathType (DevicePathNode
) != MEDIA_DEVICE_PATH
||
757 DevicePathSubType (DevicePathNode
) != MEDIA_FILEPATH_DP
) {
758 Status
= EFI_UNSUPPORTED
;
762 LastHandle
= FileHandle
;
765 Status
= LastHandle
->Open (
768 ((FILEPATH_DEVICE_PATH
*) DevicePathNode
)->PathName
,
774 // Close the previous node
776 LastHandle
->Close (LastHandle
);
778 DevicePathNode
= NextDevicePathNode (DevicePathNode
);
781 if (!EFI_ERROR (Status
)) {
783 // We have found the file. Now we need to read it. Before we can read the file we need to
784 // figure out how big the file is.
788 Status
= FileHandle
->GetInfo (
795 if (Status
== EFI_BUFFER_TOO_SMALL
) {
796 FileInfo
= AllocatePool (FileInfoSize
);
797 if (FileInfo
== NULL
) {
798 Status
= EFI_OUT_OF_RESOURCES
;
800 Status
= FileHandle
->GetInfo (
809 if (!EFI_ERROR (Status
) && (FileInfo
!= NULL
)) {
810 if ((FileInfo
->Attribute
& EFI_FILE_DIRECTORY
) == 0) {
812 // Allocate space for the file
814 ImageBuffer
= AllocatePool ((UINTN
)FileInfo
->FileSize
);
815 if (ImageBuffer
== NULL
) {
816 Status
= EFI_OUT_OF_RESOURCES
;
819 // Read the file into the buffer we allocated
821 ImageBufferSize
= (UINTN
)FileInfo
->FileSize
;
822 Status
= FileHandle
->Read (FileHandle
, &ImageBufferSize
, ImageBuffer
);
828 // Close the file and Free FileInfo and TempDevicePathNode since we are done
830 if (FileInfo
!= NULL
) {
833 if (FileHandle
!= NULL
) {
834 FileHandle
->Close (FileHandle
);
836 if (TempDevicePathNode
!= NULL
) {
837 FreePool (TempDevicePathNode
);
841 if (!EFI_ERROR (Status
)) {
847 // Attempt to access the file via LoadFile2 interface
850 DevicePathNode
= OrigDevicePathNode
;
851 Status
= gBS
->LocateDevicePath (&gEfiLoadFile2ProtocolGuid
, &DevicePathNode
, &Handle
);
852 if (!EFI_ERROR (Status
)) {
853 Status
= gBS
->HandleProtocol (Handle
, &gEfiLoadFile2ProtocolGuid
, (VOID
**)&LoadFile2
);
854 if (!EFI_ERROR (Status
)) {
856 // Call LoadFile2 with the correct buffer size
860 Status
= LoadFile2
->LoadFile (
867 if (Status
== EFI_BUFFER_TOO_SMALL
) {
868 ImageBuffer
= AllocatePool (ImageBufferSize
);
869 if (ImageBuffer
== NULL
) {
870 Status
= EFI_OUT_OF_RESOURCES
;
872 Status
= LoadFile2
->LoadFile (
882 if (!EFI_ERROR (Status
)) {
889 // Attempt to access the file via LoadFile interface
891 DevicePathNode
= OrigDevicePathNode
;
892 Status
= gBS
->LocateDevicePath (&gEfiLoadFileProtocolGuid
, &DevicePathNode
, &Handle
);
893 if (!EFI_ERROR (Status
)) {
894 Status
= gBS
->HandleProtocol (Handle
, &gEfiLoadFileProtocolGuid
, (VOID
**)&LoadFile
);
895 if (!EFI_ERROR (Status
)) {
897 // Call LoadFile with the correct buffer size
901 Status
= LoadFile
->LoadFile (
908 if (Status
== EFI_BUFFER_TOO_SMALL
) {
909 ImageBuffer
= AllocatePool (ImageBufferSize
);
910 if (ImageBuffer
== NULL
) {
911 Status
= EFI_OUT_OF_RESOURCES
;
913 Status
= LoadFile
->LoadFile (
927 if (EFI_ERROR (Status
)) {
928 if (ImageBuffer
!= NULL
) {
929 FreePool (ImageBuffer
);
934 *FileSize
= ImageBufferSize
;
937 FreePool (OrigDevicePathNode
);
943 Searches all the available firmware volumes and returns the file device path of first matching
946 This function searches all the firmware volumes for FFS files with an FFS filename specified by NameGuid.
947 The order that the firmware volumes is searched is not deterministic. For each FFS file found a search
948 is made for FFS sections of type SectionType.
950 If SectionType is EFI_SECTION_TE, and the search with an FFS file fails,
951 the search will be retried with a section type of EFI_SECTION_PE32.
952 This function must be called with a TPL <= TPL_NOTIFY.
954 If NameGuid is NULL, then ASSERT().
956 @param NameGuid A pointer to to the FFS filename GUID to search for
957 within any of the firmware volumes in the platform.
958 @param SectionType Indicates the FFS section type to search for within
959 the FFS file specified by NameGuid.
960 @param SectionInstance Indicates which section instance within the FFS file
961 specified by NameGuid to retrieve.
962 @param FvFileDevicePath Device path for the target FFS
965 @retval EFI_SUCCESS The specified file device path of FFS section was returned.
966 @retval EFI_NOT_FOUND The specified file device path of FFS section could not be found.
967 @retval EFI_DEVICE_ERROR The FFS section could not be retrieves due to a
969 @retval EFI_ACCESS_DENIED The FFS section could not be retrieves because the
970 firmware volume that contains the matching FFS section does not
972 @retval EFI_INVALID_PARAMETER FvFileDevicePath is NULL.
977 GetFileDevicePathFromAnyFv (
978 IN CONST EFI_GUID
*NameGuid
,
979 IN EFI_SECTION_TYPE SectionType
,
980 IN UINTN SectionInstance
,
981 OUT EFI_DEVICE_PATH_PROTOCOL
**FvFileDevicePath
985 EFI_HANDLE
*HandleBuffer
;
989 EFI_DEVICE_PATH_PROTOCOL
*FvDevicePath
;
990 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*TempFvFileDevicePath
;
994 if (FvFileDevicePath
== NULL
) {
995 return EFI_INVALID_PARAMETER
;
1000 TempFvFileDevicePath
= NULL
;
1005 // Search the FV that contain the caller's FFS first.
1006 // FV builder can choose to build FFS into the this FV
1007 // so that this implementation of GetSectionFromAnyFv
1008 // will locate the FFS faster.
1010 FvHandle
= InternalImageHandleToFvHandle (gImageHandle
);
1011 Status
= InternalGetSectionFromFv (
1019 if (!EFI_ERROR (Status
)) {
1023 Status
= gBS
->LocateHandleBuffer (
1025 &gEfiFirmwareVolume2ProtocolGuid
,
1030 if (EFI_ERROR (Status
)) {
1034 for (Index
= 0; Index
< HandleCount
; Index
++) {
1036 // Skip the FV that contain the caller's FFS
1038 if (HandleBuffer
[Index
] != FvHandle
) {
1039 Status
= InternalGetSectionFromFv (
1040 HandleBuffer
[Index
],
1048 if (!EFI_ERROR (Status
)) {
1050 // Update FvHandle to the current handle.
1052 FvHandle
= HandleBuffer
[Index
];
1058 if (Index
== HandleCount
) {
1059 Status
= EFI_NOT_FOUND
;
1063 if (Status
== EFI_SUCCESS
) {
1065 // Build a device path to the file in the FV to pass into gBS->LoadImage
1067 Status
= gBS
->HandleProtocol (FvHandle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&FvDevicePath
);
1068 if (EFI_ERROR (Status
)) {
1069 *FvFileDevicePath
= NULL
;
1071 TempFvFileDevicePath
= AllocateZeroPool (sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
) + END_DEVICE_PATH_LENGTH
);
1072 if (TempFvFileDevicePath
== NULL
) {
1073 *FvFileDevicePath
= NULL
;
1074 return EFI_OUT_OF_RESOURCES
;
1076 EfiInitializeFwVolDevicepathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)TempFvFileDevicePath
, NameGuid
);
1077 SetDevicePathEndNode (NextDevicePathNode (TempFvFileDevicePath
));
1078 *FvFileDevicePath
= AppendDevicePath (
1080 (EFI_DEVICE_PATH_PROTOCOL
*)TempFvFileDevicePath
1082 FreePool (TempFvFileDevicePath
);
1086 if (Buffer
!= NULL
) {
1090 if (HandleBuffer
!= NULL
) {
1091 FreePool (HandleBuffer
);