summaryrefslogtreecommitdiff
path: root/ArmPkg/Library/BdsLib/BdsFilePath.c
diff options
context:
space:
mode:
authorandrewfish <andrewfish@6f19259b-4bc3-4df7-8a09-765794883524>2011-02-02 22:35:30 +0000
committerandrewfish <andrewfish@6f19259b-4bc3-4df7-8a09-765794883524>2011-02-02 22:35:30 +0000
commit1bfda055dfbc52678655ab2ded721f9f7c0cd496 (patch)
treefbfa3654ec28d060955ff37e9e9365ad37179013 /ArmPkg/Library/BdsLib/BdsFilePath.c
parent7373d15a98fb571bf56688676c8ba950e6f62b8d (diff)
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.c182
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;
+ }
+}