3 Copyright (c) 2006 - 2008, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
30 IN BOOLEAN BootPolicy
,
31 IN VOID
*SourceBuffer OPTIONAL
,
33 IN OUT EFI_DEVICE_PATH_PROTOCOL
**FilePath
,
34 OUT EFI_HANDLE
*DeviceHandle
,
35 IN IMAGE_FILE_HANDLE
*ImageFileHandle
,
36 OUT UINT32
*AuthenticationStatus
42 Opens a file for (simple) reading. The simple read abstraction
43 will access the file either from a memory copy, from a file
44 system interface, or from the load file interface.
48 BootPolicy - Policy for Open Image File.
49 SourceBuffer - Pointer to the memory location containing copy
50 of the image to be loaded.
51 SourceSize - The size in bytes of SourceBuffer.
52 FilePath - The specific file path from which the image is loaded
53 DeviceHandle - Pointer to the return device handle.
54 ImageFileHandle - Pointer to the image file handle.
55 AuthenticationStatus - Pointer to a caller-allocated UINT32 in which the authentication status is returned.
59 EFI_SUCCESS - Image file successfully opened.
61 EFI_LOAD_ERROR - If the caller passed a copy of the file, and SourceSize is 0.
63 EFI_INVALID_PARAMETER - File path is not valid.
65 EFI_NOT_FOUND - File not found.
70 EFI_DEVICE_PATH_PROTOCOL
*TempFilePath
;
71 FILEPATH_DEVICE_PATH
*FilePathNode
;
72 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FwVolFilePathNode
;
73 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*Volume
;
74 EFI_FILE_HANDLE FileHandle
;
75 EFI_FILE_HANDLE LastHandle
;
76 EFI_LOAD_FILE_PROTOCOL
*LoadFile
;
77 EFI_FIRMWARE_VOLUME2_PROTOCOL
*FwVol
;
78 EFI_SECTION_TYPE SectionType
;
82 EFI_FV_FILE_ATTRIBUTES Attrib
;
83 EFI_FILE_INFO
*FileInfo
;
86 FILEPATH_DEVICE_PATH
*OriginalFilePathNode
;
88 OriginalFilePathNode
= NULL
;
89 *AuthenticationStatus
= 0;
90 ZeroMem (ImageFileHandle
, sizeof (IMAGE_FILE_HANDLE
));
91 ImageFileHandle
->Signature
= IMAGE_FILE_HANDLE_SIGNATURE
;
94 // If the caller passed a copy of the file, then just use it
96 if (SourceBuffer
!= NULL
) {
97 ImageFileHandle
->Source
= SourceBuffer
;
98 ImageFileHandle
->SourceSize
= SourceSize
;
100 CoreLocateDevicePath (&gEfiDevicePathProtocolGuid
, FilePath
, DeviceHandle
);
101 if (SourceSize
> 0) {
102 Status
= EFI_SUCCESS
;
104 Status
= EFI_LOAD_ERROR
;
110 // Make sure FilePath is valid
112 if (*FilePath
== NULL
) {
113 return EFI_INVALID_PARAMETER
;
117 // Check to see if it's in a Firmware Volume
119 FwVolFilePathNode
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) *FilePath
;
120 Status
= CoreDevicePathToInterface (
121 &gEfiFirmwareVolume2ProtocolGuid
,
122 (EFI_DEVICE_PATH_PROTOCOL
**)&FwVolFilePathNode
,
126 if (!EFI_ERROR (Status
)) {
128 // For FwVol File system there is only a single file name that is a GUID.
130 NameGuid
= EfiGetNameGuidFromFwVolDevicePathNode (FwVolFilePathNode
);
131 if (NameGuid
!= NULL
) {
133 SectionType
= EFI_SECTION_PE32
;
135 Status
= FwVol
->ReadSection (
140 (VOID
**)&Pe32Buffer
,
144 if (EFI_ERROR (Status
)) {
146 // Try a raw file, since a PE32 SECTION does not exist
148 if (Pe32Buffer
!= NULL
) {
149 CoreFreePool (Pe32Buffer
);
150 *AuthenticationStatus
= 0;
153 Status
= FwVol
->ReadFile (
156 (VOID
**)&Pe32Buffer
,
164 if (!EFI_ERROR (Status
)) {
166 // One of the reads passed so we are done
168 ImageFileHandle
->Source
= Pe32Buffer
;
169 ImageFileHandle
->SourceSize
= Pe32BufferSize
;
170 ImageFileHandle
->FreeBuffer
= TRUE
;
177 // Attempt to access the file via a file system interface
179 FilePathNode
= (FILEPATH_DEVICE_PATH
*) *FilePath
;
180 Status
= CoreDevicePathToInterface (
181 &gEfiSimpleFileSystemProtocolGuid
,
182 (EFI_DEVICE_PATH_PROTOCOL
**)&FilePathNode
,
186 if (!EFI_ERROR (Status
)) {
188 // Open the Volume to get the File System handle
190 Status
= Volume
->OpenVolume (Volume
, &FileHandle
);
191 if (!EFI_ERROR (Status
)) {
193 // Duplicate the device path to avoid the access to unaligned device path node.
194 // Because the device path consists of one or more FILE PATH MEDIA DEVICE PATH
195 // nodes, It assures the fields in device path nodes are 2 byte aligned.
197 FilePathNode
= (FILEPATH_DEVICE_PATH
*)CoreDuplicateDevicePath((EFI_DEVICE_PATH_PROTOCOL
*)(UINTN
)FilePathNode
);
198 if (FilePathNode
== NULL
) {
199 FileHandle
->Close (FileHandle
);
200 Status
= EFI_OUT_OF_RESOURCES
;
202 OriginalFilePathNode
= FilePathNode
;
204 // Parse each MEDIA_FILEPATH_DP node. There may be more than one, since the
205 // directory information and filename can be seperate. The goal is to inch
206 // our way down each device path node and close the previous node
208 while (!IsDevicePathEnd (&FilePathNode
->Header
)) {
209 if (DevicePathType (&FilePathNode
->Header
) != MEDIA_DEVICE_PATH
||
210 DevicePathSubType (&FilePathNode
->Header
) != MEDIA_FILEPATH_DP
) {
211 Status
= EFI_UNSUPPORTED
;
214 if (EFI_ERROR (Status
)) {
216 // Exit loop on Error
221 LastHandle
= FileHandle
;
224 Status
= LastHandle
->Open (
227 FilePathNode
->PathName
,
233 // Close the previous node
235 LastHandle
->Close (LastHandle
);
237 FilePathNode
= (FILEPATH_DEVICE_PATH
*) NextDevicePathNode (&FilePathNode
->Header
);
240 // Free the allocated memory pool
242 CoreFreePool(OriginalFilePathNode
);
245 if (!EFI_ERROR (Status
)) {
247 // We have found the file. Now we need to read it. Before we can read the file we need to
248 // figure out how big the file is.
251 FileInfoSize
= sizeof (EFI_FILE_INFO
);
252 while (CoreGrowBuffer (&Status
, (VOID
**)&FileInfo
, FileInfoSize
)) {
254 // Automatically allocate buffer of the correct size and make the call
256 Status
= FileHandle
->GetInfo (
263 if (!EFI_ERROR (Status
)) {
265 // Allocate space for the file
267 ImageFileHandle
->Source
= CoreAllocateBootServicesPool ((UINTN
)FileInfo
->FileSize
);
268 if (ImageFileHandle
->Source
!= NULL
) {
270 // Read the file into the buffer we allocated
272 ImageFileHandle
->SourceSize
= (UINTN
)FileInfo
->FileSize
;
273 ImageFileHandle
->FreeBuffer
= TRUE
;
274 Status
= FileHandle
->Read (FileHandle
, &ImageFileHandle
->SourceSize
, ImageFileHandle
->Source
);
277 // Close the file since we are done
279 FileHandle
->Close (FileHandle
);
281 Status
= EFI_OUT_OF_RESOURCES
;
292 // Try LoadFile style
295 TempFilePath
= *FilePath
;
296 Status
= CoreDevicePathToInterface (
297 &gEfiLoadFileProtocolGuid
,
302 if (!EFI_ERROR (Status
)) {
304 // Call LoadFile with the correct buffer size
306 while (CoreGrowBuffer (&Status
, (VOID
**)&ImageFileHandle
->Source
, ImageFileHandle
->SourceSize
)) {
307 Status
= LoadFile
->LoadFile (
311 &ImageFileHandle
->SourceSize
,
312 ImageFileHandle
->Source
315 // If success or other error happens, stop loop
317 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
322 if (!EFI_ERROR (Status
) || Status
== EFI_ALREADY_STARTED
) {
323 ImageFileHandle
->FreeBuffer
= TRUE
;
329 // Nothing else to try
331 DEBUG ((EFI_D_LOAD
|EFI_D_WARN
, "CoreOpenImageFile: Device did not support a known load protocol\n"));
332 Status
= EFI_NOT_FOUND
;
337 // If the file was not accessed, clean up
339 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
340 if (ImageFileHandle
->FreeBuffer
) {
342 // Free the source buffer if we allocated it
344 CoreFreePool (ImageFileHandle
->Source
);
358 IN OUT UINTN
*ReadSize
,
365 Read image file (specified by UserHandle) into user specified buffer with specified offset
370 UserHandle - Image file handle
372 Offset - Offset to the source file
374 ReadSize - For input, pointer of size to read;
375 For output, pointer of size actually read.
377 Buffer - Buffer to write into
381 EFI_SUCCESS - Successfully read the specified part of file into buffer.
386 IMAGE_FILE_HANDLE
*FHand
;
388 FHand
= (IMAGE_FILE_HANDLE
*)UserHandle
;
389 ASSERT (FHand
->Signature
== IMAGE_FILE_HANDLE_SIGNATURE
);
392 // Move data from our local copy of the file
394 EndPosition
= Offset
+ *ReadSize
;
395 if (EndPosition
> FHand
->SourceSize
) {
396 *ReadSize
= (UINT32
)(FHand
->SourceSize
- Offset
);
398 if (Offset
>= FHand
->SourceSize
) {
402 CopyMem (Buffer
, (CHAR8
*)FHand
->Source
+ Offset
, *ReadSize
);
407 CoreDevicePathToInterface (
408 IN EFI_GUID
*Protocol
,
409 IN EFI_DEVICE_PATH_PROTOCOL
**FilePath
,
410 OUT VOID
**Interface
,
411 OUT EFI_HANDLE
*Handle
417 Search a handle to a device on a specified device path that supports a specified protocol,
418 interface of that protocol on that handle is another output.
422 Protocol - The protocol to search for
424 FilePath - The specified device path
426 Interface - Interface of the protocol on the handle
428 Handle - The handle to the device on the specified device path that supports the protocol.
438 Status
= CoreLocateDevicePath (Protocol
, FilePath
, Handle
);
439 if (!EFI_ERROR (Status
)) {
440 Status
= CoreHandleProtocol (*Handle
, Protocol
, Interface
);
447 IN OUT EFI_STATUS
*Status
,
448 IN OUT VOID
**Buffer
,
455 Helper function called as part of the code needed
456 to allocate the proper sized buffer for various
461 Status - Current status
463 Buffer - Current allocated buffer, or NULL
465 BufferSize - Current buffer size needed
469 TRUE - if the buffer was reallocated and the caller
470 should try the API again.
472 FALSE - buffer could not be allocated and the caller
473 should not try the API again.
481 // If this is an initial request, buffer will be null with a new buffer size
483 if (*Buffer
== NULL
) {
484 *Status
= EFI_BUFFER_TOO_SMALL
;
487 if (BufferSize
== 0) {
492 // If the status code is "buffer too small", resize the buffer
495 if (*Status
== EFI_BUFFER_TOO_SMALL
) {
496 if (*Buffer
!= NULL
) {
497 CoreFreePool (*Buffer
);
500 *Buffer
= CoreAllocateBootServicesPool (BufferSize
);
501 if (*Buffer
!= NULL
) {
504 *Status
= EFI_OUT_OF_RESOURCES
;
509 // If there's an error, free the buffer
511 if ((!TryAgain
) && (EFI_ERROR (*Status
)) && (*Buffer
)) {
512 CoreFreePool (*Buffer
);