+++ /dev/null
-/*++\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
-\r
-Module Name:\r
- \r
- ImageFile.c\r
-\r
-\r
-Abstract:\r
-\r
- \r
-\r
-\r
-Revision History\r
-\r
---*/\r
-\r
-#include <DxeMain.h>\r
-\r
-EFI_STATUS\r
-CoreOpenImageFile (\r
- IN BOOLEAN BootPolicy,\r
- IN VOID *SourceBuffer OPTIONAL,\r
- IN UINTN SourceSize,\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
- FILEPATH_DEVICE_PATH *FilePathNode;\r
- MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FwVolFilePathNode;\r
- EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;\r
- EFI_FILE_HANDLE FileHandle;\r
- EFI_FILE_HANDLE LastHandle;\r
- EFI_LOAD_FILE_PROTOCOL *LoadFile;\r
- EFI_FIRMWARE_VOLUME_PROTOCOL *FwVol;\r
- EFI_SECTION_TYPE SectionType;\r
- UINT8 *Pe32Buffer;\r
- UINTN Pe32BufferSize;\r
- EFI_FV_FILETYPE Type;\r
- EFI_FV_FILE_ATTRIBUTES Attrib;\r
- EFI_FILE_INFO *FileInfo;\r
- UINTN FileInfoSize;\r
- EFI_GUID *NameGuid;\r
-\r
- *AuthenticationStatus = 0;\r
- ZeroMem (ImageFileHandle, sizeof (IMAGE_FILE_HANDLE));\r
- ImageFileHandle->Signature = IMAGE_FILE_HANDLE_SIGNATURE;\r
-\r
- //\r
- // If the caller passed a copy of the file, then just use it\r
- //\r
- if (SourceBuffer != NULL) {\r
- ImageFileHandle->Source = SourceBuffer;\r
- ImageFileHandle->SourceSize = SourceSize;\r
- *DeviceHandle = NULL;\r
- if (SourceSize > 0) {\r
- Status = EFI_SUCCESS;\r
- } else {\r
- Status = EFI_LOAD_ERROR;\r
- }\r
- goto Done;\r
- }\r
-\r
- //\r
- // Make sure FilePath is valid\r
- //\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
- Status = CoreDevicePathToInterface (\r
- &gEfiFirmwareVolumeProtocolGuid, \r
- (EFI_DEVICE_PATH_PROTOCOL **)&FwVolFilePathNode, \r
- (VOID*)&FwVol, \r
- DeviceHandle\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // For FwVol File system there is only a single file name that is a GUID.\r
- //\r
- NameGuid = EfiGetNameGuidFromFwVolDevicePathNode (FwVolFilePathNode);\r
- if (NameGuid != NULL) {\r
-\r
- SectionType = EFI_SECTION_PE32;\r
- Pe32Buffer = NULL;\r
- Status = FwVol->ReadSection (\r
- FwVol, \r
- NameGuid, \r
- SectionType, \r
- 0,\r
- (VOID **)&Pe32Buffer,\r
- &Pe32BufferSize,\r
- AuthenticationStatus\r
- );\r
- if (EFI_ERROR (Status)) {\r
- //\r
- // Try a raw file, since a PE32 SECTION does not exist\r
- //\r
- if (Pe32Buffer != NULL) {\r
- CoreFreePool (Pe32Buffer);\r
- *AuthenticationStatus = 0;\r
- }\r
- Pe32Buffer = NULL;\r
- Status = FwVol->ReadFile (\r
- FwVol, \r
- NameGuid, \r
- (VOID **)&Pe32Buffer,\r
- &Pe32BufferSize,\r
- &Type,\r
- &Attrib,\r
- AuthenticationStatus\r
- );\r
- }\r
- \r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // One of the reads passed so we are done\r
- //\r
- ImageFileHandle->Source = Pe32Buffer;\r
- ImageFileHandle->SourceSize = Pe32BufferSize;\r
- ImageFileHandle->FreeBuffer = TRUE;\r
- goto Done;\r
- }\r
- }\r
- }\r
-\r
- //\r
- // Attempt to access the file via a file system interface\r
- //\r
- FilePathNode = (FILEPATH_DEVICE_PATH *) FilePath;\r
- Status = CoreDevicePathToInterface (\r
- &gEfiSimpleFileSystemProtocolGuid, \r
- (EFI_DEVICE_PATH_PROTOCOL **)&FilePathNode, \r
- (VOID*)&Volume, \r
- DeviceHandle\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // Open the Volume to get the File System handle\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
- //\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
- Status = LastHandle->Open (\r
- LastHandle,\r
- &FileHandle,\r
- FilePathNode->PathName,\r
- EFI_FILE_MODE_READ,\r
- 0\r
- );\r
-\r
- //\r
- // Close the previous node\r
- //\r
- LastHandle->Close (LastHandle);\r
-\r
- FilePathNode = (FILEPATH_DEVICE_PATH *) NextDevicePathNode (&FilePathNode->Header);\r
- }\r
-\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // We have found the file. Now we need to read it. Before we can read the file we need to\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
- }\r
- if (!EFI_ERROR (Status)) {\r
- //\r
- // Allocate space for the file\r
- //\r
- ImageFileHandle->Source = CoreAllocateBootServicesPool ((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->FreeBuffer = TRUE;\r
- Status = FileHandle->Read (FileHandle, &ImageFileHandle->SourceSize, ImageFileHandle->Source);\r
-\r
- //\r
- // Close the file since we are done\r
- //\r
- FileHandle->Close (FileHandle);\r
- } else {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- goto Done;\r
- }\r
- }\r
- }\r
- } \r
-\r
-\r
- //\r
- // Try LoadFile style\r
- //\r
-\r
- TempFilePath = FilePath;\r
- Status = CoreDevicePathToInterface (\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
- }\r
- }\r
-\r
- if (!EFI_ERROR (Status) || Status == EFI_ALREADY_STARTED) {\r
- ImageFileHandle->FreeBuffer = TRUE;\r
- goto Done;\r
- }\r
- }\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
- 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 (ImageFileHandle->FreeBuffer) {\r
- //\r
- // Free the source buffer if we allocated it\r
- //\r
- CoreFreePool (ImageFileHandle->Source);\r
- }\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-\r
-\r
-EFI_STATUS\r
-EFIAPI\r
-CoreReadImageFile (\r
- IN VOID *UserHandle,\r
- IN UINTN Offset,\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
-\r
- FHand = (IMAGE_FILE_HANDLE *)UserHandle;\r
- ASSERT (FHand->Signature == IMAGE_FILE_HANDLE_SIGNATURE);\r
-\r
- //\r
- // Move data from our local copy of the file\r
- //\r
- EndPosition = Offset + *ReadSize;\r
- if (EndPosition > FHand->SourceSize) {\r
- *ReadSize = (UINT32)(FHand->SourceSize - Offset);\r
- } \r
- if (Offset >= FHand->SourceSize) {\r
- *ReadSize = 0;\r
- }\r
-\r
- CopyMem (Buffer, (CHAR8 *)FHand->Source + Offset, *ReadSize);\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