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 - 2018, 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
;
256 ASSERT (Buffer
!= NULL
);
257 ASSERT (Size
!= NULL
);
260 // Locate all available FVs.
263 Status
= gBS
->LocateHandleBuffer (
265 &gEfiFirmwareVolume2ProtocolGuid
,
270 if (EFI_ERROR (Status
)) {
275 // Go through FVs one by one to find the required section data.
277 for (IndexFv
= 0; IndexFv
< HandleCount
; IndexFv
++) {
278 Status
= gBS
->HandleProtocol (
279 HandleBuffer
[IndexFv
],
280 &gEfiFirmwareVolume2ProtocolGuid
,
283 if (EFI_ERROR (Status
)) {
288 // Use Firmware Volume 2 Protocol to search for a file of type FileType in all FVs.
290 IndexFile
= FileInstance
+ 1;
293 Status
= Fv
->GetNextFile (Fv
, &Key
, &FileType
, &NameGuid
, &Attributes
, Size
);
294 if (EFI_ERROR (Status
)) {
298 } while (IndexFile
> 0);
301 // Fv File with the required FV file type is found.
302 // Search the section file in the found FV file.
304 if (IndexFile
== 0) {
305 Status
= InternalGetSectionFromFv (
306 HandleBuffer
[IndexFv
],
314 if (!EFI_ERROR (Status
)) {
321 // The required FFS section file is not found.
323 if (IndexFv
== HandleCount
) {
324 Status
= EFI_NOT_FOUND
;
328 if (HandleBuffer
!= NULL
) {
329 FreePool(HandleBuffer
);
336 Searches all the availables firmware volumes and returns the first matching FFS section.
338 This function searches all the firmware volumes for FFS files with an FFS filename specified by NameGuid.
339 The order that the firmware volumes is searched is not deterministic. For each FFS file found a search
340 is made for FFS sections of type SectionType. If the FFS file contains at least SectionInstance instances
341 of the FFS section specified by SectionType, then the SectionInstance instance is returned in Buffer.
342 Buffer is allocated using AllocatePool(), and the size of the allocated buffer is returned in Size.
343 It is the caller's responsibility to use FreePool() to free the allocated buffer.
344 See EFI_FIRMWARE_VOLUME2_PROTOCOL.ReadSection() for details on how sections
345 are retrieved from an FFS file based on SectionType and SectionInstance.
347 If SectionType is EFI_SECTION_TE, and the search with an FFS file fails,
348 the search will be retried with a section type of EFI_SECTION_PE32.
349 This function must be called with a TPL <= TPL_NOTIFY.
351 If NameGuid is NULL, then ASSERT().
352 If Buffer is NULL, then ASSERT().
353 If Size is NULL, then ASSERT().
356 @param NameGuid A pointer to to the FFS filename GUID to search for
357 within any of the firmware volumes in the platform.
358 @param SectionType Indicates the FFS section type to search for within
359 the FFS file specified by NameGuid.
360 @param SectionInstance Indicates which section instance within the FFS file
361 specified by NameGuid to retrieve.
362 @param Buffer On output, a pointer to a callee allocated buffer
363 containing the FFS file section that was found.
364 Is it the caller's responsibility to free this buffer
366 @param Size On output, a pointer to the size, in bytes, of Buffer.
368 @retval EFI_SUCCESS The specified FFS section was returned.
369 @retval EFI_NOT_FOUND The specified FFS section could not be found.
370 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to
371 retrieve the matching FFS section.
372 @retval EFI_DEVICE_ERROR The FFS section could not be retrieves due to a
374 @retval EFI_ACCESS_DENIED The FFS section could not be retrieves because the
376 contains the matching FFS section does not allow reads.
380 GetSectionFromAnyFv (
381 IN CONST EFI_GUID
*NameGuid
,
382 IN EFI_SECTION_TYPE SectionType
,
383 IN UINTN SectionInstance
,
389 EFI_HANDLE
*HandleBuffer
;
395 // Search the FV that contain the caller's FFS first.
396 // FV builder can choose to build FFS into the this FV
397 // so that this implementation of GetSectionFromAnyFv
398 // will locate the FFS faster.
400 FvHandle
= InternalImageHandleToFvHandle (gImageHandle
);
401 Status
= InternalGetSectionFromFv (
409 if (!EFI_ERROR (Status
)) {
414 Status
= gBS
->LocateHandleBuffer (
416 &gEfiFirmwareVolume2ProtocolGuid
,
421 if (EFI_ERROR (Status
)) {
425 for (Index
= 0; Index
< HandleCount
; Index
++) {
427 // Skip the FV that contain the caller's FFS
429 if (HandleBuffer
[Index
] != FvHandle
) {
430 Status
= InternalGetSectionFromFv (
439 if (!EFI_ERROR (Status
)) {
446 if (Index
== HandleCount
) {
447 Status
= EFI_NOT_FOUND
;
452 if (HandleBuffer
!= NULL
) {
453 FreePool(HandleBuffer
);
460 Searches the firmware volume that the currently executing module was loaded from and returns the first matching FFS section.
462 This function searches the firmware volume that the currently executing module was loaded
463 from for an FFS file with an FFS filename specified by NameGuid. If the FFS file is found a search
464 is made for FFS sections of type SectionType. If the FFS file contains at least SectionInstance
465 instances of the FFS section specified by SectionType, then the SectionInstance instance is returned in Buffer.
466 Buffer is allocated using AllocatePool(), and the size of the allocated buffer is returned in Size.
467 It is the caller's responsibility to use FreePool() to free the allocated buffer.
468 See EFI_FIRMWARE_VOLUME2_PROTOCOL.ReadSection() for details on how sections are retrieved from
469 an FFS file based on SectionType and SectionInstance.
471 If the currently executing module was not loaded from a firmware volume, then EFI_NOT_FOUND is returned.
472 If SectionType is EFI_SECTION_TE, and the search with an FFS file fails,
473 the search will be retried with a section type of EFI_SECTION_PE32.
475 This function must be called with a TPL <= TPL_NOTIFY.
476 If NameGuid is NULL, then ASSERT().
477 If Buffer is NULL, then ASSERT().
478 If Size is NULL, then ASSERT().
480 @param NameGuid A pointer to to the FFS filename GUID to search for
481 within the firmware volumes that the currently
482 executing module was loaded from.
483 @param SectionType Indicates the FFS section type to search for within
484 the FFS file specified by NameGuid.
485 @param SectionInstance Indicates which section instance within the FFS file
486 specified by NameGuid to retrieve.
487 @param Buffer On output, a pointer to a callee allocated buffer
488 containing the FFS file section that was found.
489 Is it the caller's responsibility to free this buffer
491 @param Size On output, a pointer to the size, in bytes, of Buffer.
494 @retval EFI_SUCCESS The specified FFS section was returned.
495 @retval EFI_NOT_FOUND The specified FFS section could not be found.
496 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to retrieve
497 the matching FFS section.
498 @retval EFI_DEVICE_ERROR The FFS section could not be retrieves due to a
500 @retval EFI_ACCESS_DENIED The FFS section could not be retrieves because the
501 firmware volume that contains the matching FFS
502 section does not allow reads.
507 IN CONST EFI_GUID
*NameGuid
,
508 IN EFI_SECTION_TYPE SectionType
,
509 IN UINTN SectionInstance
,
514 return InternalGetSectionFromFv (
515 InternalImageHandleToFvHandle(gImageHandle
),
526 Searches the FFS file the the currently executing module was loaded from and returns the first matching FFS section.
528 This function searches the FFS file that the currently executing module was loaded from for a FFS sections of type SectionType.
529 If the FFS file contains at least SectionInstance instances of the FFS section specified by SectionType,
530 then the SectionInstance instance is returned in Buffer. Buffer is allocated using AllocatePool(),
531 and the size of the allocated buffer is returned in Size. It is the caller's responsibility
532 to use FreePool() to free the allocated buffer. See EFI_FIRMWARE_VOLUME2_PROTOCOL.ReadSection() for
533 details on how sections are retrieved from an FFS file based on SectionType and SectionInstance.
535 If the currently executing module was not loaded from an FFS file, then EFI_NOT_FOUND is returned.
536 If SectionType is EFI_SECTION_TE, and the search with an FFS file fails,
537 the search will be retried with a section type of EFI_SECTION_PE32.
538 This function must be called with a TPL <= TPL_NOTIFY.
540 If Buffer is NULL, then ASSERT().
541 If Size is NULL, then ASSERT().
544 @param SectionType Indicates the FFS section type to search for within
545 the FFS file that the currently executing module
547 @param SectionInstance Indicates which section instance to retrieve within
548 the FFS file that the currently executing module
550 @param Buffer On output, a pointer to a callee allocated buffer
551 containing the FFS file section that was found.
552 Is it the caller's responsibility to free this buffer
554 @param Size On output, a pointer to the size, in bytes, of Buffer.
556 @retval EFI_SUCCESS The specified FFS section was returned.
557 @retval EFI_NOT_FOUND The specified FFS section could not be found.
558 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to retrieve
559 the matching FFS section.
560 @retval EFI_DEVICE_ERROR The FFS section could not be retrieves due to a
562 @retval EFI_ACCESS_DENIED The FFS section could not be retrieves because the
563 firmware volume that contains the matching FFS
564 section does not allow reads.
570 IN EFI_SECTION_TYPE SectionType
,
571 IN UINTN SectionInstance
,
576 return InternalGetSectionFromFv(
577 InternalImageHandleToFvHandle(gImageHandle
),
588 Get the image file buffer data and buffer size by its device path.
590 Access the file either from a firmware volume, from a file system interface,
591 or from the load file interface.
593 Allocate memory to store the found image. The caller is responsible to free memory.
595 If FilePath is NULL, then NULL is returned.
596 If FileSize is NULL, then NULL is returned.
597 If AuthenticationStatus is NULL, then NULL is returned.
599 @param[in] BootPolicy Policy for Open Image File.If TRUE, indicates
600 that the request originates from the boot
601 manager, and that the boot manager is
602 attempting to load FilePath as a boot
603 selection. If FALSE, then FilePath must
604 match an exact file to be loaded.
605 @param[in] FilePath The pointer to the device path of the file
606 that is absracted to the file buffer.
607 @param[out] FileSize The pointer to the size of the abstracted
609 @param[out] AuthenticationStatus Pointer to the authentication status.
611 @retval NULL FilePath is NULL, or FileSize is NULL, or AuthenticationStatus is NULL, or the file can't be found.
612 @retval other The abstracted file buffer. The caller is responsible to free memory.
616 GetFileBufferByFilePath (
617 IN BOOLEAN BootPolicy
,
618 IN CONST EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
620 OUT UINT32
*AuthenticationStatus
623 EFI_DEVICE_PATH_PROTOCOL
*DevicePathNode
;
624 EFI_DEVICE_PATH_PROTOCOL
*OrigDevicePathNode
;
625 EFI_DEVICE_PATH_PROTOCOL
*TempDevicePathNode
;
627 EFI_GUID
*FvNameGuid
;
628 EFI_FIRMWARE_VOLUME2_PROTOCOL
*FwVol
;
629 EFI_SECTION_TYPE SectionType
;
631 UINTN ImageBufferSize
;
632 EFI_FV_FILETYPE Type
;
633 EFI_FV_FILE_ATTRIBUTES Attrib
;
634 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*Volume
;
635 EFI_FILE_HANDLE FileHandle
;
636 EFI_FILE_HANDLE LastHandle
;
637 EFI_FILE_INFO
*FileInfo
;
639 EFI_LOAD_FILE_PROTOCOL
*LoadFile
;
640 EFI_LOAD_FILE2_PROTOCOL
*LoadFile2
;
644 // Check input File device path.
646 if (FilePath
== NULL
|| FileSize
== NULL
|| AuthenticationStatus
== NULL
) {
651 // Init local variable
653 TempDevicePathNode
= NULL
;
659 *AuthenticationStatus
= 0;
662 // Copy File Device Path
664 OrigDevicePathNode
= DuplicateDevicePath (FilePath
);
665 if (OrigDevicePathNode
== NULL
) {
670 // Check whether this device path support FV2 protocol.
671 // Is so, this device path may contain a Image.
673 DevicePathNode
= OrigDevicePathNode
;
674 Status
= gBS
->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid
, &DevicePathNode
, &Handle
);
675 if (!EFI_ERROR (Status
)) {
677 // For FwVol File system there is only a single file name that is a GUID.
679 FvNameGuid
= EfiGetNameGuidFromFwVolDevicePathNode ((CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) DevicePathNode
);
680 if (FvNameGuid
== NULL
) {
681 Status
= EFI_INVALID_PARAMETER
;
684 // Read image from the firmware file
686 Status
= gBS
->HandleProtocol (Handle
, &gEfiFirmwareVolume2ProtocolGuid
, (VOID
**)&FwVol
);
687 if (!EFI_ERROR (Status
)) {
688 SectionType
= EFI_SECTION_PE32
;
690 Status
= FwVol
->ReadSection (
695 (VOID
**)&ImageBuffer
,
699 if (EFI_ERROR (Status
)) {
701 // Try a raw file, since a PE32 SECTION does not exist
703 if (ImageBuffer
!= NULL
) {
704 FreePool (ImageBuffer
);
705 *AuthenticationStatus
= 0;
708 Status
= FwVol
->ReadFile (
711 (VOID
**)&ImageBuffer
,
720 if (!EFI_ERROR (Status
)) {
726 // Attempt to access the file via a file system interface
728 DevicePathNode
= OrigDevicePathNode
;
729 Status
= gBS
->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid
, &DevicePathNode
, &Handle
);
730 if (!EFI_ERROR (Status
)) {
731 Status
= gBS
->HandleProtocol (Handle
, &gEfiSimpleFileSystemProtocolGuid
, (VOID
**)&Volume
);
732 if (!EFI_ERROR (Status
)) {
734 // Open the Volume to get the File System handle
736 Status
= Volume
->OpenVolume (Volume
, &FileHandle
);
737 if (!EFI_ERROR (Status
)) {
739 // Duplicate the device path to avoid the access to unaligned device path node.
740 // Because the device path consists of one or more FILE PATH MEDIA DEVICE PATH
741 // nodes, It assures the fields in device path nodes are 2 byte aligned.
743 TempDevicePathNode
= DuplicateDevicePath (DevicePathNode
);
744 if (TempDevicePathNode
== NULL
) {
745 FileHandle
->Close (FileHandle
);
747 // Setting Status to an EFI_ERROR value will cause the rest of
748 // the file system support below to be skipped.
750 Status
= EFI_OUT_OF_RESOURCES
;
753 // Parse each MEDIA_FILEPATH_DP node. There may be more than one, since the
754 // directory information and filename can be seperate. The goal is to inch
755 // our way down each device path node and close the previous node
757 DevicePathNode
= TempDevicePathNode
;
758 while (!EFI_ERROR (Status
) && !IsDevicePathEnd (DevicePathNode
)) {
759 if (DevicePathType (DevicePathNode
) != MEDIA_DEVICE_PATH
||
760 DevicePathSubType (DevicePathNode
) != MEDIA_FILEPATH_DP
) {
761 Status
= EFI_UNSUPPORTED
;
765 LastHandle
= FileHandle
;
768 Status
= LastHandle
->Open (
771 ((FILEPATH_DEVICE_PATH
*) DevicePathNode
)->PathName
,
777 // Close the previous node
779 LastHandle
->Close (LastHandle
);
781 DevicePathNode
= NextDevicePathNode (DevicePathNode
);
784 if (!EFI_ERROR (Status
)) {
786 // We have found the file. Now we need to read it. Before we can read the file we need to
787 // figure out how big the file is.
791 Status
= FileHandle
->GetInfo (
798 if (Status
== EFI_BUFFER_TOO_SMALL
) {
799 FileInfo
= AllocatePool (FileInfoSize
);
800 if (FileInfo
== NULL
) {
801 Status
= EFI_OUT_OF_RESOURCES
;
803 Status
= FileHandle
->GetInfo (
812 if (!EFI_ERROR (Status
) && (FileInfo
!= NULL
)) {
813 if ((FileInfo
->Attribute
& EFI_FILE_DIRECTORY
) == 0) {
815 // Allocate space for the file
817 ImageBuffer
= AllocatePool ((UINTN
)FileInfo
->FileSize
);
818 if (ImageBuffer
== NULL
) {
819 Status
= EFI_OUT_OF_RESOURCES
;
822 // Read the file into the buffer we allocated
824 ImageBufferSize
= (UINTN
)FileInfo
->FileSize
;
825 Status
= FileHandle
->Read (FileHandle
, &ImageBufferSize
, ImageBuffer
);
831 // Close the file and Free FileInfo and TempDevicePathNode since we are done
833 if (FileInfo
!= NULL
) {
836 if (FileHandle
!= NULL
) {
837 FileHandle
->Close (FileHandle
);
839 if (TempDevicePathNode
!= NULL
) {
840 FreePool (TempDevicePathNode
);
844 if (!EFI_ERROR (Status
)) {
850 // Attempt to access the file via LoadFile2 interface
853 DevicePathNode
= OrigDevicePathNode
;
854 Status
= gBS
->LocateDevicePath (&gEfiLoadFile2ProtocolGuid
, &DevicePathNode
, &Handle
);
855 if (!EFI_ERROR (Status
)) {
856 Status
= gBS
->HandleProtocol (Handle
, &gEfiLoadFile2ProtocolGuid
, (VOID
**)&LoadFile2
);
857 if (!EFI_ERROR (Status
)) {
859 // Call LoadFile2 with the correct buffer size
863 Status
= LoadFile2
->LoadFile (
870 if (Status
== EFI_BUFFER_TOO_SMALL
) {
871 ImageBuffer
= AllocatePool (ImageBufferSize
);
872 if (ImageBuffer
== NULL
) {
873 Status
= EFI_OUT_OF_RESOURCES
;
875 Status
= LoadFile2
->LoadFile (
885 if (!EFI_ERROR (Status
)) {
892 // Attempt to access the file via LoadFile interface
894 DevicePathNode
= OrigDevicePathNode
;
895 Status
= gBS
->LocateDevicePath (&gEfiLoadFileProtocolGuid
, &DevicePathNode
, &Handle
);
896 if (!EFI_ERROR (Status
)) {
897 Status
= gBS
->HandleProtocol (Handle
, &gEfiLoadFileProtocolGuid
, (VOID
**)&LoadFile
);
898 if (!EFI_ERROR (Status
)) {
900 // Call LoadFile with the correct buffer size
904 Status
= LoadFile
->LoadFile (
911 if (Status
== EFI_BUFFER_TOO_SMALL
) {
912 ImageBuffer
= AllocatePool (ImageBufferSize
);
913 if (ImageBuffer
== NULL
) {
914 Status
= EFI_OUT_OF_RESOURCES
;
916 Status
= LoadFile
->LoadFile (
930 if (EFI_ERROR (Status
)) {
931 if (ImageBuffer
!= NULL
) {
932 FreePool (ImageBuffer
);
937 *FileSize
= ImageBufferSize
;
940 FreePool (OrigDevicePathNode
);
946 Searches all the available firmware volumes and returns the file device path of first matching
949 This function searches all the firmware volumes for FFS files with an FFS filename specified by NameGuid.
950 The order that the firmware volumes is searched is not deterministic. For each FFS file found a search
951 is made for FFS sections of type SectionType.
953 If SectionType is EFI_SECTION_TE, and the search with an FFS file fails,
954 the search will be retried with a section type of EFI_SECTION_PE32.
955 This function must be called with a TPL <= TPL_NOTIFY.
957 If NameGuid is NULL, then ASSERT().
959 @param NameGuid A pointer to to the FFS filename GUID to search for
960 within any of the firmware volumes in the platform.
961 @param SectionType Indicates the FFS section type to search for within
962 the FFS file specified by NameGuid.
963 @param SectionInstance Indicates which section instance within the FFS file
964 specified by NameGuid to retrieve.
965 @param FvFileDevicePath Device path for the target FFS
968 @retval EFI_SUCCESS The specified file device path of FFS section was returned.
969 @retval EFI_NOT_FOUND The specified file device path of FFS section could not be found.
970 @retval EFI_DEVICE_ERROR The FFS section could not be retrieves due to a
972 @retval EFI_ACCESS_DENIED The FFS section could not be retrieves because the
973 firmware volume that contains the matching FFS section does not
975 @retval EFI_INVALID_PARAMETER FvFileDevicePath is NULL.
980 GetFileDevicePathFromAnyFv (
981 IN CONST EFI_GUID
*NameGuid
,
982 IN EFI_SECTION_TYPE SectionType
,
983 IN UINTN SectionInstance
,
984 OUT EFI_DEVICE_PATH_PROTOCOL
**FvFileDevicePath
988 EFI_HANDLE
*HandleBuffer
;
992 EFI_DEVICE_PATH_PROTOCOL
*FvDevicePath
;
993 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*TempFvFileDevicePath
;
997 if (FvFileDevicePath
== NULL
) {
998 return EFI_INVALID_PARAMETER
;
1001 HandleBuffer
= NULL
;
1002 FvDevicePath
= NULL
;
1003 TempFvFileDevicePath
= NULL
;
1008 // Search the FV that contain the caller's FFS first.
1009 // FV builder can choose to build FFS into the this FV
1010 // so that this implementation of GetSectionFromAnyFv
1011 // will locate the FFS faster.
1013 FvHandle
= InternalImageHandleToFvHandle (gImageHandle
);
1014 Status
= InternalGetSectionFromFv (
1022 if (!EFI_ERROR (Status
)) {
1026 Status
= gBS
->LocateHandleBuffer (
1028 &gEfiFirmwareVolume2ProtocolGuid
,
1033 if (EFI_ERROR (Status
)) {
1037 for (Index
= 0; Index
< HandleCount
; Index
++) {
1039 // Skip the FV that contain the caller's FFS
1041 if (HandleBuffer
[Index
] != FvHandle
) {
1042 Status
= InternalGetSectionFromFv (
1043 HandleBuffer
[Index
],
1051 if (!EFI_ERROR (Status
)) {
1053 // Update FvHandle to the current handle.
1055 FvHandle
= HandleBuffer
[Index
];
1061 if (Index
== HandleCount
) {
1062 Status
= EFI_NOT_FOUND
;
1066 if (Status
== EFI_SUCCESS
) {
1068 // Build a device path to the file in the FV to pass into gBS->LoadImage
1070 Status
= gBS
->HandleProtocol (FvHandle
, &gEfiDevicePathProtocolGuid
, (VOID
**)&FvDevicePath
);
1071 if (EFI_ERROR (Status
)) {
1072 *FvFileDevicePath
= NULL
;
1074 TempFvFileDevicePath
= AllocateZeroPool (sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
) + END_DEVICE_PATH_LENGTH
);
1075 if (TempFvFileDevicePath
== NULL
) {
1076 *FvFileDevicePath
= NULL
;
1077 return EFI_OUT_OF_RESOURCES
;
1079 EfiInitializeFwVolDevicepathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)TempFvFileDevicePath
, NameGuid
);
1080 SetDevicePathEndNode (NextDevicePathNode (TempFvFileDevicePath
));
1081 *FvFileDevicePath
= AppendDevicePath (
1083 (EFI_DEVICE_PATH_PROTOCOL
*)TempFvFileDevicePath
1085 FreePool (TempFvFileDevicePath
);
1089 if (Buffer
!= NULL
) {
1093 if (HandleBuffer
!= NULL
) {
1094 FreePool (HandleBuffer
);