2 Handle services to image file.
4 Copyright (c) 2006 - 2008, Intel Corporation. <BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 Search a handle to a device on a specified device path that supports a specified protocol,
20 interface of that protocol on that handle is another output.
24 @param Protocol The protocol to search for
25 @param FilePath The specified device path
26 @param Interface Interface of the protocol on the handle
27 @param Handle The handle to the device on the specified device
28 path that supports the protocol.
34 CoreDevicePathToInterface (
35 IN EFI_GUID
*Protocol
,
36 IN EFI_DEVICE_PATH_PROTOCOL
**FilePath
,
38 OUT EFI_HANDLE
*Handle
43 Status
= CoreLocateDevicePath (Protocol
, FilePath
, Handle
);
44 if (!EFI_ERROR (Status
)) {
45 Status
= CoreHandleProtocol (*Handle
, Protocol
, Interface
);
52 Opens a file for (simple) reading. The simple read abstraction
53 will access the file either from a memory copy, from a file
54 system interface, or from the load file interface.
56 @param BootPolicy Policy for Open Image File.
57 @param SourceBuffer Pointer to the memory location containing copy
58 of the image to be loaded.
59 @param SourceSize The size in bytes of SourceBuffer.
60 @param FilePath The specific file path from which the image is
62 @param DeviceHandle Pointer to the return device handle.
63 @param ImageFileHandle Pointer to the image file handle.
64 @param AuthenticationStatus Pointer to a caller-allocated UINT32 in which
65 the authentication status is returned.
67 @retval EFI_SUCCESS Image file successfully opened.
68 @retval EFI_LOAD_ERROR If the caller passed a copy of the file, and
70 @retval EFI_INVALID_PARAMETER File path is not valid.
71 @retval EFI_NOT_FOUND File not found.
76 IN BOOLEAN BootPolicy
,
77 IN VOID
*SourceBuffer OPTIONAL
,
79 IN OUT EFI_DEVICE_PATH_PROTOCOL
**FilePath
,
80 OUT EFI_HANDLE
*DeviceHandle
,
81 IN IMAGE_FILE_HANDLE
*ImageFileHandle
,
82 OUT UINT32
*AuthenticationStatus
86 EFI_DEVICE_PATH_PROTOCOL
*TempFilePath
;
87 FILEPATH_DEVICE_PATH
*FilePathNode
;
88 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FwVolFilePathNode
;
89 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*Volume
;
90 EFI_FILE_HANDLE FileHandle
;
91 EFI_FILE_HANDLE LastHandle
;
92 EFI_LOAD_FILE_PROTOCOL
*LoadFile
;
93 EFI_FIRMWARE_VOLUME2_PROTOCOL
*FwVol
;
94 EFI_SECTION_TYPE SectionType
;
98 EFI_FV_FILE_ATTRIBUTES Attrib
;
99 EFI_FILE_INFO
*FileInfo
;
102 FILEPATH_DEVICE_PATH
*OriginalFilePathNode
;
104 OriginalFilePathNode
= NULL
;
105 *AuthenticationStatus
= 0;
106 ZeroMem (ImageFileHandle
, sizeof (IMAGE_FILE_HANDLE
));
107 ImageFileHandle
->Signature
= IMAGE_FILE_HANDLE_SIGNATURE
;
110 // If the caller passed a copy of the file, then just use it
112 if (SourceBuffer
!= NULL
) {
113 ImageFileHandle
->Source
= SourceBuffer
;
114 ImageFileHandle
->SourceSize
= SourceSize
;
115 *DeviceHandle
= NULL
;
116 CoreLocateDevicePath (&gEfiDevicePathProtocolGuid
, FilePath
, DeviceHandle
);
117 if (SourceSize
> 0) {
118 Status
= EFI_SUCCESS
;
120 Status
= EFI_LOAD_ERROR
;
126 // Make sure FilePath is valid
128 if (*FilePath
== NULL
) {
129 return EFI_INVALID_PARAMETER
;
133 // Check to see if it's in a Firmware Volume
135 FwVolFilePathNode
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) *FilePath
;
136 Status
= CoreDevicePathToInterface (
137 &gEfiFirmwareVolume2ProtocolGuid
,
138 (EFI_DEVICE_PATH_PROTOCOL
**)&FwVolFilePathNode
,
142 if (!EFI_ERROR (Status
)) {
144 // For FwVol File system there is only a single file name that is a GUID.
146 NameGuid
= EfiGetNameGuidFromFwVolDevicePathNode (FwVolFilePathNode
);
147 if (NameGuid
!= NULL
) {
149 SectionType
= EFI_SECTION_PE32
;
151 Status
= FwVol
->ReadSection (
156 (VOID
**)&Pe32Buffer
,
160 if (EFI_ERROR (Status
)) {
162 // Try a raw file, since a PE32 SECTION does not exist
164 if (Pe32Buffer
!= NULL
) {
165 CoreFreePool (Pe32Buffer
);
166 *AuthenticationStatus
= 0;
169 Status
= FwVol
->ReadFile (
172 (VOID
**)&Pe32Buffer
,
180 if (!EFI_ERROR (Status
)) {
182 // One of the reads passed so we are done
184 ImageFileHandle
->Source
= Pe32Buffer
;
185 ImageFileHandle
->SourceSize
= Pe32BufferSize
;
186 ImageFileHandle
->FreeBuffer
= TRUE
;
193 // Attempt to access the file via a file system interface
195 FilePathNode
= (FILEPATH_DEVICE_PATH
*) *FilePath
;
196 Status
= CoreDevicePathToInterface (
197 &gEfiSimpleFileSystemProtocolGuid
,
198 (EFI_DEVICE_PATH_PROTOCOL
**)&FilePathNode
,
202 if (!EFI_ERROR (Status
)) {
204 // Open the Volume to get the File System handle
206 Status
= Volume
->OpenVolume (Volume
, &FileHandle
);
207 if (!EFI_ERROR (Status
)) {
209 // Duplicate the device path to avoid the access to unaligned device path node.
210 // Because the device path consists of one or more FILE PATH MEDIA DEVICE PATH
211 // nodes, It assures the fields in device path nodes are 2 byte aligned.
213 FilePathNode
= (FILEPATH_DEVICE_PATH
*)DuplicateDevicePath((EFI_DEVICE_PATH_PROTOCOL
*)(UINTN
)FilePathNode
);
214 if (FilePathNode
== NULL
) {
215 FileHandle
->Close (FileHandle
);
216 Status
= EFI_OUT_OF_RESOURCES
;
218 OriginalFilePathNode
= FilePathNode
;
220 // Parse each MEDIA_FILEPATH_DP node. There may be more than one, since the
221 // directory information and filename can be seperate. The goal is to inch
222 // our way down each device path node and close the previous node
224 while (!IsDevicePathEnd (&FilePathNode
->Header
)) {
225 if (DevicePathType (&FilePathNode
->Header
) != MEDIA_DEVICE_PATH
||
226 DevicePathSubType (&FilePathNode
->Header
) != MEDIA_FILEPATH_DP
) {
227 Status
= EFI_UNSUPPORTED
;
230 if (EFI_ERROR (Status
)) {
232 // Exit loop on Error
237 LastHandle
= FileHandle
;
240 Status
= LastHandle
->Open (
243 FilePathNode
->PathName
,
249 // Close the previous node
251 LastHandle
->Close (LastHandle
);
253 FilePathNode
= (FILEPATH_DEVICE_PATH
*) NextDevicePathNode (&FilePathNode
->Header
);
256 // Free the allocated memory pool
258 CoreFreePool(OriginalFilePathNode
);
261 if (!EFI_ERROR (Status
)) {
263 // We have found the file. Now we need to read it. Before we can read the file we need to
264 // figure out how big the file is.
268 Status
= FileHandle
->GetInfo (
274 if (Status
== EFI_BUFFER_TOO_SMALL
) {
275 FileInfo
= AllocatePool (FileInfoSize
);
276 if (FileInfo
!= NULL
) {
277 Status
= FileHandle
->GetInfo (
284 Status
= EFI_OUT_OF_RESOURCES
;
289 if (!EFI_ERROR (Status
)) {
291 // Allocate space for the file
293 ASSERT (FileInfo
!= NULL
);
294 ImageFileHandle
->Source
= AllocatePool ((UINTN
)FileInfo
->FileSize
);
295 if (ImageFileHandle
->Source
!= NULL
) {
297 // Read the file into the buffer we allocated
299 ImageFileHandle
->SourceSize
= (UINTN
) FileInfo
->FileSize
;
300 ImageFileHandle
->FreeBuffer
= TRUE
;
301 Status
= FileHandle
->Read (FileHandle
, &ImageFileHandle
->SourceSize
, ImageFileHandle
->Source
);
304 // Close the file since we are done
306 FileHandle
->Close (FileHandle
);
307 CoreFreePool (FileInfo
);
309 Status
= EFI_OUT_OF_RESOURCES
;
320 // Try LoadFile style
323 TempFilePath
= *FilePath
;
324 Status
= CoreDevicePathToInterface (
325 &gEfiLoadFileProtocolGuid
,
330 if (!EFI_ERROR (Status
)) {
332 // Call LoadFile with the correct buffer size
334 ASSERT (ImageFileHandle
->SourceSize
== 0);
335 ASSERT (ImageFileHandle
->Source
== NULL
);
336 Status
= LoadFile
->LoadFile (
340 &ImageFileHandle
->SourceSize
,
341 ImageFileHandle
->Source
343 if (Status
== EFI_BUFFER_TOO_SMALL
) {
344 ImageFileHandle
->Source
= AllocatePool (ImageFileHandle
->SourceSize
);
345 if (ImageFileHandle
->Source
== NULL
) {
346 Status
= EFI_OUT_OF_RESOURCES
;
348 Status
= LoadFile
->LoadFile (
352 &ImageFileHandle
->SourceSize
,
353 ImageFileHandle
->Source
358 if (!EFI_ERROR (Status
)) {
359 ImageFileHandle
->FreeBuffer
= TRUE
;
365 // Nothing else to try
367 DEBUG ((DEBUG_LOAD
|DEBUG_WARN
, "CoreOpenImageFile: Device did not support a known load protocol\n"));
368 Status
= EFI_NOT_FOUND
;
372 // If the file was not accessed, clean up
374 if (EFI_ERROR (Status
)) {
375 if (ImageFileHandle
->FreeBuffer
) {
377 // Free the source buffer if we allocated it
379 CoreFreePool (ImageFileHandle
->Source
);
389 Read image file (specified by UserHandle) into user specified buffer with specified offset
392 @param UserHandle Image file handle
393 @param Offset Offset to the source file
394 @param ReadSize For input, pointer of size to read; For output,
395 pointer of size actually read.
396 @param Buffer Buffer to write into
398 @retval EFI_SUCCESS Successfully read the specified part of file
407 IN OUT UINTN
*ReadSize
,
412 IMAGE_FILE_HANDLE
*FHand
;
414 FHand
= (IMAGE_FILE_HANDLE
*)UserHandle
;
415 ASSERT (FHand
->Signature
== IMAGE_FILE_HANDLE_SIGNATURE
);
418 // Move data from our local copy of the file
420 EndPosition
= Offset
+ *ReadSize
;
421 if (EndPosition
> FHand
->SourceSize
) {
422 *ReadSize
= (UINT32
)(FHand
->SourceSize
- Offset
);
424 if (Offset
>= FHand
->SourceSize
) {
428 CopyMem (Buffer
, (CHAR8
*)FHand
->Source
+ Offset
, *ReadSize
);