3 Copyright (c) 2006, 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 CoreDevicePathToFileName (
31 IN FILEPATH_DEVICE_PATH
*FilePath
,
39 IN BOOLEAN BootPolicy
,
40 IN VOID
*SourceBuffer OPTIONAL
,
42 IN OUT EFI_DEVICE_PATH_PROTOCOL
*FilePath
,
43 OUT EFI_HANDLE
*DeviceHandle
,
44 IN IMAGE_FILE_HANDLE
*ImageFileHandle
,
45 OUT UINT32
*AuthenticationStatus
51 Opens a file for (simple) reading. The simple read abstraction
52 will access the file either from a memory copy, from a file
53 system interface, or from the load file interface.
57 BootPolicy - Policy for Open Image File.
58 SourceBuffer - Pointer to the memory location containing copy
59 of the image to be loaded.
60 SourceSize - The size in bytes of SourceBuffer.
61 FilePath - The specific file path from which the image is loaded
62 DeviceHandle - Pointer to the return device handle.
63 ImageFileHandle - Pointer to the image file handle.
64 AuthenticationStatus - Pointer to a caller-allocated UINT32 in which the authentication status is returned.
68 EFI_SUCCESS - Image file successfully opened.
70 EFI_LOAD_ERROR - If the caller passed a copy of the file, and SourceSize is 0.
72 EFI_INVALID_PARAMETER - File path is not valid.
74 EFI_NOT_FOUND - File not found.
79 EFI_DEVICE_PATH_PROTOCOL
*TempFilePath
;
80 FILEPATH_DEVICE_PATH
*FilePathNode
;
81 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FwVolFilePathNode
;
82 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*Volume
;
83 EFI_FILE_HANDLE FileHandle
;
84 EFI_FILE_HANDLE LastHandle
;
85 EFI_LOAD_FILE_PROTOCOL
*LoadFile
;
86 EFI_FIRMWARE_VOLUME_PROTOCOL
*FwVol
;
87 EFI_SECTION_TYPE SectionType
;
91 EFI_FV_FILE_ATTRIBUTES Attrib
;
92 EFI_FILE_INFO
*FileInfo
;
96 *AuthenticationStatus
= 0;
97 ZeroMem (ImageFileHandle
, sizeof (IMAGE_FILE_HANDLE
));
98 ImageFileHandle
->Signature
= IMAGE_FILE_HANDLE_SIGNATURE
;
101 // If the caller passed a copy of the file, then just use it
103 if (SourceBuffer
!= NULL
) {
104 ImageFileHandle
->Source
= SourceBuffer
;
105 ImageFileHandle
->SourceSize
= SourceSize
;
106 *DeviceHandle
= NULL
;
107 if (SourceSize
> 0) {
108 Status
= EFI_SUCCESS
;
110 Status
= EFI_LOAD_ERROR
;
116 // Make sure FilePath is valid
118 if (FilePath
== NULL
) {
119 return EFI_INVALID_PARAMETER
;
123 // Check to see if it's in a Firmware Volume
125 FwVolFilePathNode
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)FilePath
;
126 Status
= CoreDevicePathToInterface (
127 &gEfiFirmwareVolumeProtocolGuid
,
128 (EFI_DEVICE_PATH_PROTOCOL
**)&FwVolFilePathNode
,
132 if (!EFI_ERROR (Status
)) {
134 // For FwVol File system there is only a single file name that is a GUID.
136 NameGuid
= EfiGetNameGuidFromFwVolDevicePathNode (FwVolFilePathNode
);
137 if (NameGuid
!= NULL
) {
139 SectionType
= EFI_SECTION_PE32
;
141 Status
= FwVol
->ReadSection (
146 (VOID
**)&Pe32Buffer
,
150 if (EFI_ERROR (Status
)) {
152 // Try a raw file, since a PE32 SECTION does not exist
154 if (Pe32Buffer
!= NULL
) {
155 CoreFreePool (Pe32Buffer
);
156 *AuthenticationStatus
= 0;
159 Status
= FwVol
->ReadFile (
162 (VOID
**)&Pe32Buffer
,
170 if (!EFI_ERROR (Status
)) {
172 // One of the reads passed so we are done
174 ImageFileHandle
->Source
= Pe32Buffer
;
175 ImageFileHandle
->SourceSize
= Pe32BufferSize
;
176 ImageFileHandle
->FreeBuffer
= TRUE
;
183 // Attempt to access the file via a file system interface
185 FilePathNode
= (FILEPATH_DEVICE_PATH
*) FilePath
;
186 Status
= CoreDevicePathToInterface (
187 &gEfiSimpleFileSystemProtocolGuid
,
188 (EFI_DEVICE_PATH_PROTOCOL
**)&FilePathNode
,
192 if (!EFI_ERROR (Status
)) {
194 // Open the Volume to get the File System handle
196 Status
= Volume
->OpenVolume (Volume
, &FileHandle
);
197 if (!EFI_ERROR (Status
)) {
200 // Parse each MEDIA_FILEPATH_DP node. There may be more than one, since the
201 // directory information and filename can be seperate. The goal is to inch
202 // our way down each device path node and close the previous node
204 while (!IsDevicePathEnd (&FilePathNode
->Header
)) {
205 if (DevicePathType (&FilePathNode
->Header
) != MEDIA_DEVICE_PATH
||
206 DevicePathSubType (&FilePathNode
->Header
) != MEDIA_FILEPATH_DP
) {
207 Status
= EFI_UNSUPPORTED
;
210 if (EFI_ERROR (Status
)) {
212 // Exit loop on Error
217 LastHandle
= FileHandle
;
219 Status
= LastHandle
->Open (
222 FilePathNode
->PathName
,
228 // Close the previous node
230 LastHandle
->Close (LastHandle
);
232 FilePathNode
= (FILEPATH_DEVICE_PATH
*) NextDevicePathNode (&FilePathNode
->Header
);
235 if (!EFI_ERROR (Status
)) {
237 // We have found the file. Now we need to read it. Before we can read the file we need to
238 // figure out how big the file is.
241 FileInfoSize
= sizeof (EFI_FILE_INFO
);
242 while (CoreGrowBuffer (&Status
, (VOID
**)&FileInfo
, FileInfoSize
)) {
244 // Automatically allocate buffer of the correct size and make the call
246 Status
= FileHandle
->GetInfo (
253 if (!EFI_ERROR (Status
)) {
255 // Allocate space for the file
257 ImageFileHandle
->Source
= CoreAllocateBootServicesPool ((UINTN
)FileInfo
->FileSize
);
258 if (ImageFileHandle
->Source
!= NULL
) {
260 // Read the file into the buffer we allocated
262 ImageFileHandle
->SourceSize
= (UINTN
)FileInfo
->FileSize
;
263 ImageFileHandle
->FreeBuffer
= TRUE
;
264 Status
= FileHandle
->Read (FileHandle
, &ImageFileHandle
->SourceSize
, ImageFileHandle
->Source
);
267 // Close the file since we are done
269 FileHandle
->Close (FileHandle
);
271 Status
= EFI_OUT_OF_RESOURCES
;
282 // Try LoadFile style
285 TempFilePath
= FilePath
;
286 Status
= CoreDevicePathToInterface (
287 &gEfiLoadFileProtocolGuid
,
292 if (!EFI_ERROR (Status
)) {
294 // Call LoadFile with the correct buffer size
296 while (CoreGrowBuffer (&Status
, (VOID
**)&ImageFileHandle
->Source
, ImageFileHandle
->SourceSize
)) {
297 Status
= LoadFile
->LoadFile (
301 &ImageFileHandle
->SourceSize
,
302 ImageFileHandle
->Source
305 // If success or other error happens, stop loop
307 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
312 if (!EFI_ERROR (Status
) || Status
== EFI_ALREADY_STARTED
) {
313 ImageFileHandle
->FreeBuffer
= TRUE
;
319 // Nothing else to try
321 DEBUG ((EFI_D_LOAD
|EFI_D_WARN
, "CoreOpenImageFile: Device did not support a known load protocol\n"));
322 Status
= EFI_NOT_FOUND
;
327 // If the file was not accessed, clean up
329 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
330 if (ImageFileHandle
->FreeBuffer
) {
332 // Free the source buffer if we allocated it
334 CoreFreePool (ImageFileHandle
->Source
);
348 IN OUT UINTN
*ReadSize
,
355 Read image file (specified by UserHandle) into user specified buffer with specified offset
360 UserHandle - Image file handle
362 Offset - Offset to the source file
364 ReadSize - For input, pointer of size to read;
365 For output, pointer of size actually read.
367 Buffer - Buffer to write into
371 EFI_SUCCESS - Successfully read the specified part of file into buffer.
376 IMAGE_FILE_HANDLE
*FHand
;
378 FHand
= (IMAGE_FILE_HANDLE
*)UserHandle
;
379 ASSERT (FHand
->Signature
== IMAGE_FILE_HANDLE_SIGNATURE
);
382 // Move data from our local copy of the file
384 EndPosition
= Offset
+ *ReadSize
;
385 if (EndPosition
> FHand
->SourceSize
) {
386 *ReadSize
= (UINT32
)(FHand
->SourceSize
- Offset
);
388 if (Offset
>= FHand
->SourceSize
) {
392 CopyMem (Buffer
, (CHAR8
*)FHand
->Source
+ Offset
, *ReadSize
);
397 CoreDevicePathToInterface (
398 IN EFI_GUID
*Protocol
,
399 IN EFI_DEVICE_PATH_PROTOCOL
**FilePath
,
400 OUT VOID
**Interface
,
401 OUT EFI_HANDLE
*Handle
407 Search a handle to a device on a specified device path that supports a specified protocol,
408 interface of that protocol on that handle is another output.
412 Protocol - The protocol to search for
414 FilePath - The specified device path
416 Interface - Interface of the protocol on the handle
418 Handle - The handle to the device on the specified device path that supports the protocol.
428 Status
= CoreLocateDevicePath (Protocol
, FilePath
, Handle
);
429 if (!EFI_ERROR (Status
)) {
430 Status
= CoreHandleProtocol (*Handle
, Protocol
, Interface
);
437 CoreDevicePathToFileName (
438 IN FILEPATH_DEVICE_PATH
*FilePath
,
445 Transfer a device's full path a string.
449 FilePath - Device path
451 String - The string represent the device's full path
460 FILEPATH_DEVICE_PATH
*FilePathNode
;
465 FilePathNode
= FilePath
;
466 while (!IsDevicePathEnd (&FilePathNode
->Header
)) {
469 // For filesystem access each node should be a filepath component
471 if (DevicePathType (&FilePathNode
->Header
) != MEDIA_DEVICE_PATH
||
472 DevicePathSubType (&FilePathNode
->Header
) != MEDIA_FILEPATH_DP
) {
477 StringSize
+= StrLen (FilePathNode
->PathName
);
479 FilePathNode
= (FILEPATH_DEVICE_PATH
*) NextDevicePathNode (&FilePathNode
->Header
);
482 *String
= CoreAllocateBootServicesPool (StringSize
);
483 if (*String
== NULL
) {
487 FilePathNode
= FilePath
;
489 while (!IsDevicePathEnd (&FilePathNode
->Header
)) {
490 StrCat (Str
, FilePathNode
->PathName
);
491 FilePathNode
= (FILEPATH_DEVICE_PATH
*) NextDevicePathNode (&FilePathNode
->Header
);
498 IN OUT EFI_STATUS
*Status
,
499 IN OUT VOID
**Buffer
,
506 Helper function called as part of the code needed
507 to allocate the proper sized buffer for various
512 Status - Current status
514 Buffer - Current allocated buffer, or NULL
516 BufferSize - Current buffer size needed
520 TRUE - if the buffer was reallocated and the caller
521 should try the API again.
523 FALSE - buffer could not be allocated and the caller
524 should not try the API again.
532 // If this is an initial request, buffer will be null with a new buffer size
534 if (*Buffer
== NULL
) {
535 *Status
= EFI_BUFFER_TOO_SMALL
;
538 if (BufferSize
== 0) {
543 // If the status code is "buffer too small", resize the buffer
546 if (*Status
== EFI_BUFFER_TOO_SMALL
) {
547 if (*Buffer
!= NULL
) {
548 CoreFreePool (*Buffer
);
551 *Buffer
= CoreAllocateBootServicesPool (BufferSize
);
552 if (*Buffer
!= NULL
) {
555 *Status
= EFI_OUT_OF_RESOURCES
;
560 // If there's an error, free the buffer
562 if ((!TryAgain
) && (EFI_ERROR (*Status
)) && (*Buffer
)) {
563 CoreFreePool (*Buffer
);