diff options
author | andrewfish <andrewfish@6f19259b-4bc3-4df7-8a09-765794883524> | 2011-02-02 22:35:30 +0000 |
---|---|---|
committer | andrewfish <andrewfish@6f19259b-4bc3-4df7-8a09-765794883524> | 2011-02-02 22:35:30 +0000 |
commit | 1bfda055dfbc52678655ab2ded721f9f7c0cd496 (patch) | |
tree | fbfa3654ec28d060955ff37e9e9365ad37179013 /ArmPkg/Library/BdsLib/BdsFilePath.c | |
parent | 7373d15a98fb571bf56688676c8ba950e6f62b8d (diff) | |
download | edk2-1bfda055dfbc52678655ab2ded721f9f7c0cd496.tar.gz |
Sync up ArmPkg with patch from mailing list. Changed name of BdsLib.h to BdsUnixLib.h and fixed a lot of issues with Xcode building.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11293 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'ArmPkg/Library/BdsLib/BdsFilePath.c')
-rw-r--r-- | ArmPkg/Library/BdsLib/BdsFilePath.c | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/ArmPkg/Library/BdsLib/BdsFilePath.c b/ArmPkg/Library/BdsLib/BdsFilePath.c new file mode 100644 index 0000000000..b1460b9c9d --- /dev/null +++ b/ArmPkg/Library/BdsLib/BdsFilePath.c @@ -0,0 +1,182 @@ +/** @file +* +* Copyright (c) 2011, ARM Limited. All rights reserved. +* +* This program and the accompanying materials +* are licensed and made available under the terms and conditions of the BSD License +* which accompanies this distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/ + +#include "BdsInternal.h" + +// Count the number of DevicePath Node +static UINTN NumberNodeFromDevicePath( + IN EFI_DEVICE_PATH_PROTOCOL* DevicePath +) { + UINTN NumberDevicePathNode = 0; + + while (!IsDevicePathEnd (DevicePath)) { + NumberDevicePathNode++; + DevicePath = NextDevicePathNode(DevicePath); + } + return NumberDevicePathNode; +} + +// Extract the FilePath from the Device Path +CHAR16* BdsExtractFilePathFromDevicePath( + IN CONST CHAR16 *StrDevicePath, + IN UINTN NumberDevicePathNode +) { + UINTN Node; + CHAR16 *Str; + + Str = (CHAR16*)StrDevicePath; + Node = 0; + while ((Str != NULL) && (*Str != L'\0') && (Node < NumberDevicePathNode)) { + if ((*Str == L'/') || (*Str == L'\\')) { + Node++; + } + Str++; + } + + if (*Str == L'\0') { + return NULL; + } else { + return Str; + } +} + +EFI_STATUS +BdsLoadDevicePath( + IN EFI_DEVICE_PATH_PROTOCOL* DevicePath, + OUT EFI_HANDLE *Handle +) { + EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath; + EFI_STATUS Status; + + if ((DevicePath == NULL) || (Handle == NULL)) { + return EFI_INVALID_PARAMETER; + } + + do { + RemainingDevicePath = DevicePath; + // The LocateDevicePath() function locates all devices on DevicePath that support Protocol and returns + // the handle to the device that is closest to DevicePath. On output, the device path pointer is modified + // to point to the remaining part of the device path + Status = gBS->LocateDevicePath(&gEfiDevicePathProtocolGuid,&RemainingDevicePath,Handle); + if (!EFI_ERROR (Status)) { + // Recursive = FALSE: We do not want to start all the device tree + Status = gBS->ConnectController (*Handle, NULL, RemainingDevicePath, FALSE); + } + + // We need to check if RemainingDevicePath does not point on the last node. Otherwise, calling + // NextDevicePathNode() will return an undetermined Device Path Node + if (!IsDevicePathEnd (RemainingDevicePath)) { + RemainingDevicePath = NextDevicePathNode (RemainingDevicePath); + } + } while (!EFI_ERROR (Status) && !IsDevicePathEnd (RemainingDevicePath)); + + if (!EFI_ERROR (Status)) { + // Now, we have got the whole Device Path connected, call again ConnectController to ensure all the supported Driver + // Binding Protocol are connected (such as DiskIo and SimpleFileSystem) + RemainingDevicePath = DevicePath; + Status = gBS->LocateDevicePath(&gEfiDevicePathProtocolGuid,&RemainingDevicePath,Handle); + if (!EFI_ERROR (Status)) { + Status = gBS->ConnectController (*Handle, NULL, RemainingDevicePath, FALSE); + if (EFI_ERROR (Status)) { + // If the last node is a Memory Map Device Path just return EFI_SUCCESS. + if ((RemainingDevicePath->Type == HARDWARE_DEVICE_PATH) && (RemainingDevicePath->SubType == HW_MEMMAP_DP)) { + Status = EFI_SUCCESS; + } + } + } + } else if (IsDevicePathEnd (RemainingDevicePath)) { + // Case when the DevicePath contains a MemoryMap Device Path Node and all drivers are connected. + // Ensure the Device Path exists + RemainingDevicePath = DevicePath; + Status = gBS->LocateDevicePath(&gEfiDevicePathProtocolGuid,&RemainingDevicePath,Handle); + } + + return Status; +} + + +EFI_STATUS +BdsLoadFilePath ( + IN CONST CHAR16 *DeviceFilePath, + OUT BDS_FILE *File +) { + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol; + EFI_STATUS Status; + EFI_HANDLE Handle; + UINTN NumberDevicePathNode; + CHAR16 *FilePath; + + //Do a sanity check on the Device file path + if (DeviceFilePath == NULL) { + return EFI_INVALID_PARAMETER; + } + + // Convert the Device Path String into Device Path Protocol + Status = gBS->LocateProtocol(&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID **)&EfiDevicePathFromTextProtocol); + ASSERT_EFI_ERROR(Status); + DevicePath = EfiDevicePathFromTextProtocol->ConvertTextToDevicePath(DeviceFilePath); + + //Do a sanity check on the Device Path + if (DevicePath == NULL) { + return EFI_INVALID_PARAMETER; + } + + // Count the number of DevicePath Node + NumberDevicePathNode = NumberNodeFromDevicePath(DevicePath); + // Extract the FilePath from the Device Path + FilePath = BdsExtractFilePathFromDevicePath(DeviceFilePath,NumberDevicePathNode); + + Status = BdsLoadDevicePath(DevicePath,&Handle); + if (EFI_ERROR (Status)) { + return Status; + } + + //If FilePath == NULL then let consider if a MemoryMap Device Path + if (FilePath == NULL) { + // Check if the Node is a MemoryMap Device Path + Status = BdsLoadFileFromMemMap(Handle,DevicePath,File); + } else { + Status = BdsLoadFileFromSimpleFileSystem(Handle,FilePath,File); + if (EFI_ERROR (Status)) { + Status = BdsLoadFileFromFirmwareVolume(Handle,FilePath,EFI_FV_FILETYPE_ALL,File); + } + } + + if (!EFI_ERROR (Status)) { + File->DevicePath = DevicePath; + } + + return Status; +} + +EFI_STATUS BdsCopyRawFileToRuntimeMemory( + IN BDS_FILE *File, + OUT VOID **FileImage, + OUT UINTN *FileSize +) { + if (File == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (File->Type == BDS_FILETYPE_FS) { + return BdsCopyRawFileToRuntimeMemoryFS(File->File.Fs.Handle,FileImage,FileSize); + } else if (File->Type == BDS_FILETYPE_FV) { + return BdsCopyRawFileToRuntimeMemoryFV(&(File->File.Fv),FileImage,FileSize); + } else if (File->Type == BDS_FILETYPE_MEM) { + return BdsCopyRawFileToRuntimeMemoryMemMap(&(File->File.Mem),FileImage,FileSize); + } else { + return EFI_INVALID_PARAMETER; + } +} |