-/*++\r
+/** @file\r
+ Handle services to image file.\r
\r
-Copyright (c) 2006, Intel Corporation \r
-All rights reserved. This program and the accompanying materials \r
-are licensed and made available under the terms and conditions of the BSD License \r
-which accompanies this distribution. The full text of the license may be found at \r
-http://opensource.org/licenses/bsd-license.php \r
- \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+Copyright (c) 2006 - 2008, Intel Corporation. <BR>\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
\r
-Module Name:\r
- \r
- ImageFile.c\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
\r
+**/\r
+\r
+#include "DxeMain.h"\r
+#include "Image.h"\r
+\r
+/**\r
+ Search a handle to a device on a specified device path that supports a specified protocol,\r
+ interface of that protocol on that handle is another output.\r
\r
-Abstract:\r
\r
- \r
\r
+ @param Protocol The protocol to search for\r
+ @param FilePath The specified device path\r
+ @param Interface Interface of the protocol on the handle\r
+ @param Handle The handle to the device on the specified device\r
+ path that supports the protocol.\r
\r
-Revision History\r
+ @return Status code.\r
\r
---*/\r
+**/\r
+EFI_STATUS\r
+CoreDevicePathToInterface (\r
+ IN EFI_GUID *Protocol,\r
+ IN EFI_DEVICE_PATH_PROTOCOL **FilePath,\r
+ OUT VOID **Interface,\r
+ OUT EFI_HANDLE *Handle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = CoreLocateDevicePath (Protocol, FilePath, Handle);\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = CoreHandleProtocol (*Handle, Protocol, Interface);\r
+ }\r
+ return Status;\r
+}\r
\r
-#include <DxeMain.h>\r
\r
+/**\r
+ Opens a file for (simple) reading. The simple read abstraction\r
+ will access the file either from a memory copy, from a file\r
+ system interface, or from the load file interface.\r
+\r
+ @param BootPolicy Policy for Open Image File.\r
+ @param SourceBuffer Pointer to the memory location containing copy\r
+ of the image to be loaded.\r
+ @param SourceSize The size in bytes of SourceBuffer.\r
+ @param FilePath The specific file path from which the image is\r
+ loaded\r
+ @param DeviceHandle Pointer to the return device handle.\r
+ @param ImageFileHandle Pointer to the image file handle.\r
+ @param AuthenticationStatus Pointer to a caller-allocated UINT32 in which\r
+ the authentication status is returned.\r
+\r
+ @retval EFI_SUCCESS Image file successfully opened.\r
+ @retval EFI_LOAD_ERROR If the caller passed a copy of the file, and\r
+ SourceSize is 0.\r
+ @retval EFI_INVALID_PARAMETER File path is not valid.\r
+ @retval EFI_NOT_FOUND File not found.\r
+\r
+**/\r
EFI_STATUS\r
CoreOpenImageFile (\r
IN BOOLEAN BootPolicy,\r
IN VOID *SourceBuffer OPTIONAL,\r
IN UINTN SourceSize,\r
- IN EFI_DEVICE_PATH_PROTOCOL *FilePath,\r
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath,\r
OUT EFI_HANDLE *DeviceHandle,\r
IN IMAGE_FILE_HANDLE *ImageFileHandle,\r
OUT UINT32 *AuthenticationStatus\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Opens a file for (simple) reading. The simple read abstraction\r
- will access the file either from a memory copy, from a file\r
- system interface, or from the load file interface.\r
-\r
-Arguments:\r
-\r
- BootPolicy - Policy for Open Image File.\r
- SourceBuffer - Pointer to the memory location containing copy\r
- of the image to be loaded.\r
- SourceSize - The size in bytes of SourceBuffer.\r
- FilePath - The specific file path from which the image is loaded\r
- DeviceHandle - Pointer to the return device handle.\r
- ImageFileHandle - Pointer to the image file handle.\r
- AuthenticationStatus - Pointer to a caller-allocated UINT32 in which the authentication status is returned. \r
- \r
-Returns:\r
-\r
- EFI_SUCCESS - Image file successfully opened.\r
- \r
- EFI_LOAD_ERROR - If the caller passed a copy of the file, and SourceSize is 0.\r
- \r
- EFI_INVALID_PARAMETER - File path is not valid.\r
- \r
- EFI_NOT_FOUND - File not found.\r
-\r
---*/\r
{\r
EFI_STATUS Status;\r
EFI_DEVICE_PATH_PROTOCOL *TempFilePath;\r
EFI_FILE_INFO *FileInfo;\r
UINTN FileInfoSize;\r
EFI_GUID *NameGuid;\r
+ FILEPATH_DEVICE_PATH *OriginalFilePathNode;\r
\r
+ OriginalFilePathNode = NULL;\r
*AuthenticationStatus = 0;\r
ZeroMem (ImageFileHandle, sizeof (IMAGE_FILE_HANDLE));\r
ImageFileHandle->Signature = IMAGE_FILE_HANDLE_SIGNATURE;\r
if (SourceBuffer != NULL) {\r
ImageFileHandle->Source = SourceBuffer;\r
ImageFileHandle->SourceSize = SourceSize;\r
- *DeviceHandle = NULL;\r
- CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, &FilePath, DeviceHandle);\r
+ *DeviceHandle = NULL;\r
+ CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, FilePath, DeviceHandle);\r
if (SourceSize > 0) {\r
Status = EFI_SUCCESS;\r
} else {\r
//\r
// Make sure FilePath is valid\r
//\r
- if (FilePath == NULL) {\r
+ if (*FilePath == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
//\r
// Check to see if it's in a Firmware Volume\r
//\r
- FwVolFilePathNode = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)FilePath;\r
+ FwVolFilePathNode = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) *FilePath;\r
Status = CoreDevicePathToInterface (\r
- &gEfiFirmwareVolume2ProtocolGuid, \r
- (EFI_DEVICE_PATH_PROTOCOL **)&FwVolFilePathNode, \r
- (VOID*)&FwVol, \r
+ &gEfiFirmwareVolume2ProtocolGuid,\r
+ (EFI_DEVICE_PATH_PROTOCOL **)&FwVolFilePathNode,\r
+ (VOID*)&FwVol,\r
DeviceHandle\r
);\r
if (!EFI_ERROR (Status)) {\r
SectionType = EFI_SECTION_PE32;\r
Pe32Buffer = NULL;\r
Status = FwVol->ReadSection (\r
- FwVol, \r
- NameGuid, \r
- SectionType, \r
+ FwVol,\r
+ NameGuid,\r
+ SectionType,\r
0,\r
(VOID **)&Pe32Buffer,\r
&Pe32BufferSize,\r
}\r
Pe32Buffer = NULL;\r
Status = FwVol->ReadFile (\r
- FwVol, \r
- NameGuid, \r
+ FwVol,\r
+ NameGuid,\r
(VOID **)&Pe32Buffer,\r
&Pe32BufferSize,\r
&Type,\r
AuthenticationStatus\r
);\r
}\r
- \r
+\r
if (!EFI_ERROR (Status)) {\r
//\r
// One of the reads passed so we are done\r
//\r
// Attempt to access the file via a file system interface\r
//\r
- FilePathNode = (FILEPATH_DEVICE_PATH *) FilePath;\r
+ FilePathNode = (FILEPATH_DEVICE_PATH *) *FilePath;\r
Status = CoreDevicePathToInterface (\r
- &gEfiSimpleFileSystemProtocolGuid, \r
- (EFI_DEVICE_PATH_PROTOCOL **)&FilePathNode, \r
- (VOID*)&Volume, \r
+ &gEfiSimpleFileSystemProtocolGuid,\r
+ (EFI_DEVICE_PATH_PROTOCOL **)&FilePathNode,\r
+ (VOID*)&Volume,\r
DeviceHandle\r
);\r
if (!EFI_ERROR (Status)) {\r
//\r
Status = Volume->OpenVolume (Volume, &FileHandle);\r
if (!EFI_ERROR (Status)) {\r
- \r
//\r
- // Parse each MEDIA_FILEPATH_DP node. There may be more than one, since the\r
- // directory information and filename can be seperate. The goal is to inch\r
- // our way down each device path node and close the previous node\r
+ // Duplicate the device path to avoid the access to unaligned device path node.\r
+ // Because the device path consists of one or more FILE PATH MEDIA DEVICE PATH\r
+ // nodes, It assures the fields in device path nodes are 2 byte aligned.\r
//\r
- while (!IsDevicePathEnd (&FilePathNode->Header)) {\r
- if (DevicePathType (&FilePathNode->Header) != MEDIA_DEVICE_PATH ||\r
- DevicePathSubType (&FilePathNode->Header) != MEDIA_FILEPATH_DP) {\r
- Status = EFI_UNSUPPORTED;\r
- }\r
+ FilePathNode = (FILEPATH_DEVICE_PATH *)DuplicateDevicePath((EFI_DEVICE_PATH_PROTOCOL *)(UINTN)FilePathNode);\r
+ if (FilePathNode == NULL) {\r
+ FileHandle->Close (FileHandle);\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ } else {\r
+ OriginalFilePathNode = FilePathNode;\r
+ //\r
+ // Parse each MEDIA_FILEPATH_DP node. There may be more than one, since the\r
+ // directory information and filename can be seperate. The goal is to inch\r
+ // our way down each device path node and close the previous node\r
+ //\r
+ while (!IsDevicePathEnd (&FilePathNode->Header)) {\r
+ if (DevicePathType (&FilePathNode->Header) != MEDIA_DEVICE_PATH ||\r
+ DevicePathSubType (&FilePathNode->Header) != MEDIA_FILEPATH_DP) {\r
+ Status = EFI_UNSUPPORTED;\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Exit loop on Error\r
+ //\r
+ break;\r
+ }\r
+\r
+ LastHandle = FileHandle;\r
+ FileHandle = NULL;\r
+\r
+ Status = LastHandle->Open (\r
+ LastHandle,\r
+ &FileHandle,\r
+ FilePathNode->PathName,\r
+ EFI_FILE_MODE_READ,\r
+ 0\r
+ );\r
\r
- if (EFI_ERROR (Status)) {\r
//\r
- // Exit loop on Error\r
+ // Close the previous node\r
//\r
- break;\r
- }\r
-\r
- LastHandle = FileHandle;\r
- FileHandle = NULL;\r
- Status = LastHandle->Open (\r
- LastHandle,\r
- &FileHandle,\r
- FilePathNode->PathName,\r
- EFI_FILE_MODE_READ,\r
- 0\r
- );\r
+ LastHandle->Close (LastHandle);\r
\r
+ FilePathNode = (FILEPATH_DEVICE_PATH *) NextDevicePathNode (&FilePathNode->Header);\r
+ }\r
//\r
- // Close the previous node\r
+ // Free the allocated memory pool\r
//\r
- LastHandle->Close (LastHandle);\r
-\r
- FilePathNode = (FILEPATH_DEVICE_PATH *) NextDevicePathNode (&FilePathNode->Header);\r
+ CoreFreePool(OriginalFilePathNode);\r
}\r
\r
if (!EFI_ERROR (Status)) {\r
// figure out how big the file is.\r
//\r
FileInfo = NULL;\r
- FileInfoSize = sizeof (EFI_FILE_INFO);\r
- while (CoreGrowBuffer (&Status, (VOID **)&FileInfo, FileInfoSize)) {\r
- //\r
- // Automatically allocate buffer of the correct size and make the call\r
- //\r
- Status = FileHandle->GetInfo (\r
- FileHandle,\r
- &gEfiFileInfoGuid,\r
- &FileInfoSize,\r
- FileInfo \r
- );\r
+ FileInfoSize = 0;\r
+ Status = FileHandle->GetInfo (\r
+ FileHandle,\r
+ &gEfiFileInfoGuid,\r
+ &FileInfoSize,\r
+ FileInfo\r
+ );\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ FileInfo = AllocatePool (FileInfoSize);\r
+ if (FileInfo != NULL) {\r
+ Status = FileHandle->GetInfo (\r
+ FileHandle,\r
+ &gEfiFileInfoGuid,\r
+ &FileInfoSize,\r
+ FileInfo\r
+ );\r
+ } else {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Done;\r
+ }\r
}\r
+ \r
if (!EFI_ERROR (Status)) {\r
//\r
// Allocate space for the file\r
//\r
- ImageFileHandle->Source = CoreAllocateBootServicesPool ((UINTN)FileInfo->FileSize);\r
+ ImageFileHandle->Source = AllocatePool ((UINTN)FileInfo->FileSize);\r
if (ImageFileHandle->Source != NULL) {\r
//\r
// Read the file into the buffer we allocated\r
//\r
- ImageFileHandle->SourceSize = (UINTN)FileInfo->FileSize;\r
+ ImageFileHandle->SourceSize = (UINTN) FileInfo->FileSize;\r
ImageFileHandle->FreeBuffer = TRUE;\r
Status = FileHandle->Read (FileHandle, &ImageFileHandle->SourceSize, ImageFileHandle->Source);\r
\r
// Close the file since we are done\r
//\r
FileHandle->Close (FileHandle);\r
+ CoreFreePool (FileInfo);\r
} else {\r
Status = EFI_OUT_OF_RESOURCES;\r
}\r
}\r
}\r
}\r
- } \r
+ }\r
\r
\r
//\r
// Try LoadFile style\r
//\r
\r
- TempFilePath = FilePath;\r
+ TempFilePath = *FilePath;\r
Status = CoreDevicePathToInterface (\r
- &gEfiLoadFileProtocolGuid,\r
- &TempFilePath,\r
- (VOID*)&LoadFile,\r
- DeviceHandle\r
- );\r
+ &gEfiLoadFileProtocolGuid,\r
+ &TempFilePath,\r
+ (VOID*) &LoadFile,\r
+ DeviceHandle\r
+ );\r
if (!EFI_ERROR (Status)) {\r
//\r
// Call LoadFile with the correct buffer size\r
//\r
- while (CoreGrowBuffer (&Status, (VOID **)&ImageFileHandle->Source, ImageFileHandle->SourceSize)) {\r
- Status = LoadFile->LoadFile (\r
- LoadFile,\r
- TempFilePath,\r
- BootPolicy,\r
- &ImageFileHandle->SourceSize,\r
- ImageFileHandle->Source\r
- );\r
- //\r
- // If success or other error happens, stop loop\r
- //\r
- if (Status != EFI_BUFFER_TOO_SMALL) {\r
- break;\r
+ ASSERT (ImageFileHandle->SourceSize == 0);\r
+ ASSERT (ImageFileHandle->Source == NULL);\r
+ Status = LoadFile->LoadFile (\r
+ LoadFile,\r
+ TempFilePath,\r
+ BootPolicy,\r
+ &ImageFileHandle->SourceSize,\r
+ ImageFileHandle->Source\r
+ );\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ ImageFileHandle->Source = AllocatePool (ImageFileHandle->SourceSize);\r
+ if (ImageFileHandle->Source == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ } else {\r
+ Status = LoadFile->LoadFile (\r
+ LoadFile,\r
+ TempFilePath,\r
+ BootPolicy,\r
+ &ImageFileHandle->SourceSize,\r
+ ImageFileHandle->Source\r
+ );\r
}\r
}\r
\r
- if (!EFI_ERROR (Status) || Status == EFI_ALREADY_STARTED) {\r
+ if (!EFI_ERROR (Status)) {\r
ImageFileHandle->FreeBuffer = TRUE;\r
goto Done;\r
}\r
//\r
// Nothing else to try\r
//\r
- DEBUG ((EFI_D_LOAD|EFI_D_WARN, "CoreOpenImageFile: Device did not support a known load protocol\n"));\r
+ DEBUG ((DEBUG_LOAD|DEBUG_WARN, "CoreOpenImageFile: Device did not support a known load protocol\n"));\r
Status = EFI_NOT_FOUND;\r
\r
Done:\r
-\r
//\r
// If the file was not accessed, clean up\r
//\r
- if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {\r
+ if (EFI_ERROR (Status)) {\r
if (ImageFileHandle->FreeBuffer) {\r
//\r
// Free the source buffer if we allocated it\r
\r
\r
\r
+/**\r
+ Read image file (specified by UserHandle) into user specified buffer with specified offset\r
+ and length.\r
+\r
+ @param UserHandle Image file handle\r
+ @param Offset Offset to the source file\r
+ @param ReadSize For input, pointer of size to read; For output,\r
+ pointer of size actually read.\r
+ @param Buffer Buffer to write into\r
+\r
+ @retval EFI_SUCCESS Successfully read the specified part of file\r
+ into buffer.\r
+\r
+**/\r
EFI_STATUS\r
EFIAPI\r
CoreReadImageFile (\r
IN OUT UINTN *ReadSize,\r
OUT VOID *Buffer\r
)\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Read image file (specified by UserHandle) into user specified buffer with specified offset\r
- and length.\r
-\r
-Arguments:\r
-\r
- UserHandle - Image file handle\r
- \r
- Offset - Offset to the source file\r
- \r
- ReadSize - For input, pointer of size to read;\r
- For output, pointer of size actually read.\r
- \r
- Buffer - Buffer to write into\r
-\r
-Returns:\r
-\r
- EFI_SUCCESS - Successfully read the specified part of file into buffer.\r
-\r
---*/\r
{\r
UINTN EndPosition;\r
IMAGE_FILE_HANDLE *FHand;\r
EndPosition = Offset + *ReadSize;\r
if (EndPosition > FHand->SourceSize) {\r
*ReadSize = (UINT32)(FHand->SourceSize - Offset);\r
- } \r
+ }\r
if (Offset >= FHand->SourceSize) {\r
*ReadSize = 0;\r
}\r
return EFI_SUCCESS;\r
}\r
\r
-EFI_STATUS\r
-CoreDevicePathToInterface (\r
- IN EFI_GUID *Protocol,\r
- IN EFI_DEVICE_PATH_PROTOCOL **FilePath,\r
- OUT VOID **Interface,\r
- OUT EFI_HANDLE *Handle\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Search a handle to a device on a specified device path that supports a specified protocol,\r
- interface of that protocol on that handle is another output.\r
-\r
-Arguments:\r
-\r
- Protocol - The protocol to search for\r
- \r
- FilePath - The specified device path\r
- \r
- Interface - Interface of the protocol on the handle\r
- \r
- Handle - The handle to the device on the specified device path that supports the protocol.\r
- \r
-Returns:\r
-\r
- Status code.\r
-\r
---*/\r
-{\r
- EFI_STATUS Status;\r
-\r
- Status = CoreLocateDevicePath (Protocol, FilePath, Handle);\r
- if (!EFI_ERROR (Status)) {\r
- Status = CoreHandleProtocol (*Handle, Protocol, Interface);\r
- }\r
- return Status;\r
-}\r
-\r
-BOOLEAN\r
-CoreGrowBuffer (\r
- IN OUT EFI_STATUS *Status,\r
- IN OUT VOID **Buffer,\r
- IN UINTN BufferSize\r
- )\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Helper function called as part of the code needed\r
- to allocate the proper sized buffer for various \r
- EFI interfaces.\r
-\r
-Arguments:\r
-\r
- Status - Current status\r
-\r
- Buffer - Current allocated buffer, or NULL\r
-\r
- BufferSize - Current buffer size needed\r
- \r
-Returns:\r
- \r
- TRUE - if the buffer was reallocated and the caller \r
- should try the API again.\r
-\r
- FALSE - buffer could not be allocated and the caller\r
- should not try the API again.\r
-\r
---*/\r
-{\r
- BOOLEAN TryAgain;\r
-\r
- TryAgain = FALSE;\r
- //\r
- // If this is an initial request, buffer will be null with a new buffer size\r
- //\r
- if (*Buffer == NULL) {\r
- *Status = EFI_BUFFER_TOO_SMALL;\r
- }\r
-\r
- if (BufferSize == 0) {\r
- return TRUE;\r
- }\r
-\r
- //\r
- // If the status code is "buffer too small", resize the buffer\r
- //\r
- \r
- if (*Status == EFI_BUFFER_TOO_SMALL) {\r
- if (*Buffer != NULL) {\r
- CoreFreePool (*Buffer);\r
- }\r
-\r
- *Buffer = CoreAllocateBootServicesPool (BufferSize);\r
- if (*Buffer != NULL) {\r
- TryAgain = TRUE;\r
- } else { \r
- *Status = EFI_OUT_OF_RESOURCES;\r
- } \r
- }\r
-\r
- //\r
- // If there's an error, free the buffer\r
- //\r
- if ((!TryAgain) && (EFI_ERROR (*Status)) && (*Buffer)) {\r
- CoreFreePool (*Buffer);\r
- *Buffer = NULL;\r
- }\r
-\r
- return TryAgain;\r
-}\r
-\r