3 * Copyright (c) 2011, ARM Limited. All rights reserved.
5 * 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.
15 #include "BdsInternal.h"
17 // Count the number of DevicePath Node
18 static UINTN
NumberNodeFromDevicePath(
19 IN EFI_DEVICE_PATH_PROTOCOL
* DevicePath
21 UINTN NumberDevicePathNode
= 0;
23 while (!IsDevicePathEnd (DevicePath
)) {
24 NumberDevicePathNode
++;
25 DevicePath
= NextDevicePathNode(DevicePath
);
27 return NumberDevicePathNode
;
30 // Extract the FilePath from the Device Path
31 CHAR16
* BdsExtractFilePathFromDevicePath(
32 IN CONST CHAR16
*StrDevicePath
,
33 IN UINTN NumberDevicePathNode
38 Str
= (CHAR16
*)StrDevicePath
;
40 while ((Str
!= NULL
) && (*Str
!= L
'\0') && (Node
< NumberDevicePathNode
)) {
41 if ((*Str
== L
'/') || (*Str
== L
'\\')) {
56 IN EFI_DEVICE_PATH_PROTOCOL
* DevicePath
,
57 OUT EFI_HANDLE
*Handle
59 EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
;
62 if ((DevicePath
== NULL
) || (Handle
== NULL
)) {
63 return EFI_INVALID_PARAMETER
;
67 RemainingDevicePath
= DevicePath
;
68 // The LocateDevicePath() function locates all devices on DevicePath that support Protocol and returns
69 // the handle to the device that is closest to DevicePath. On output, the device path pointer is modified
70 // to point to the remaining part of the device path
71 Status
= gBS
->LocateDevicePath(&gEfiDevicePathProtocolGuid
,&RemainingDevicePath
,Handle
);
72 if (!EFI_ERROR (Status
)) {
73 // Recursive = FALSE: We do not want to start all the device tree
74 Status
= gBS
->ConnectController (*Handle
, NULL
, RemainingDevicePath
, FALSE
);
77 // We need to check if RemainingDevicePath does not point on the last node. Otherwise, calling
78 // NextDevicePathNode() will return an undetermined Device Path Node
79 if (!IsDevicePathEnd (RemainingDevicePath
)) {
80 RemainingDevicePath
= NextDevicePathNode (RemainingDevicePath
);
82 } while (!EFI_ERROR (Status
) && !IsDevicePathEnd (RemainingDevicePath
));
84 if (!EFI_ERROR (Status
)) {
85 // Now, we have got the whole Device Path connected, call again ConnectController to ensure all the supported Driver
86 // Binding Protocol are connected (such as DiskIo and SimpleFileSystem)
87 RemainingDevicePath
= DevicePath
;
88 Status
= gBS
->LocateDevicePath(&gEfiDevicePathProtocolGuid
,&RemainingDevicePath
,Handle
);
89 if (!EFI_ERROR (Status
)) {
90 Status
= gBS
->ConnectController (*Handle
, NULL
, RemainingDevicePath
, FALSE
);
91 if (EFI_ERROR (Status
)) {
92 // If the last node is a Memory Map Device Path just return EFI_SUCCESS.
93 if ((RemainingDevicePath
->Type
== HARDWARE_DEVICE_PATH
) && (RemainingDevicePath
->SubType
== HW_MEMMAP_DP
)) {
98 } else if (IsDevicePathEnd (RemainingDevicePath
)) {
99 // Case when the DevicePath contains a MemoryMap Device Path Node and all drivers are connected.
100 // Ensure the Device Path exists
101 RemainingDevicePath
= DevicePath
;
102 Status
= gBS
->LocateDevicePath(&gEfiDevicePathProtocolGuid
,&RemainingDevicePath
,Handle
);
111 IN CONST CHAR16
*DeviceFilePath
,
114 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
115 EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL
*EfiDevicePathFromTextProtocol
;
118 UINTN NumberDevicePathNode
;
121 //Do a sanity check on the Device file path
122 if (DeviceFilePath
== NULL
) {
123 return EFI_INVALID_PARAMETER
;
126 // Convert the Device Path String into Device Path Protocol
127 Status
= gBS
->LocateProtocol(&gEfiDevicePathFromTextProtocolGuid
, NULL
, (VOID
**)&EfiDevicePathFromTextProtocol
);
128 ASSERT_EFI_ERROR(Status
);
129 DevicePath
= EfiDevicePathFromTextProtocol
->ConvertTextToDevicePath(DeviceFilePath
);
131 //Do a sanity check on the Device Path
132 if (DevicePath
== NULL
) {
133 return EFI_INVALID_PARAMETER
;
136 // Count the number of DevicePath Node
137 NumberDevicePathNode
= NumberNodeFromDevicePath(DevicePath
);
138 // Extract the FilePath from the Device Path
139 FilePath
= BdsExtractFilePathFromDevicePath(DeviceFilePath
,NumberDevicePathNode
);
141 Status
= BdsLoadDevicePath(DevicePath
,&Handle
);
142 if (EFI_ERROR (Status
)) {
146 //If FilePath == NULL then let consider if a MemoryMap Device Path
147 if (FilePath
== NULL
) {
148 // Check if the Node is a MemoryMap Device Path
149 Status
= BdsLoadFileFromMemMap(Handle
,DevicePath
,File
);
151 Status
= BdsLoadFileFromSimpleFileSystem(Handle
,FilePath
,File
);
152 if (EFI_ERROR (Status
)) {
153 Status
= BdsLoadFileFromFirmwareVolume(Handle
,FilePath
,EFI_FV_FILETYPE_ALL
,File
);
157 if (!EFI_ERROR (Status
)) {
158 File
->DevicePath
= DevicePath
;
164 EFI_STATUS
BdsCopyRawFileToRuntimeMemory(
166 OUT VOID
**FileImage
,
170 return EFI_INVALID_PARAMETER
;
173 if (File
->Type
== BDS_FILETYPE_FS
) {
174 return BdsCopyRawFileToRuntimeMemoryFS(File
->File
.Fs
.Handle
,FileImage
,FileSize
);
175 } else if (File
->Type
== BDS_FILETYPE_FV
) {
176 return BdsCopyRawFileToRuntimeMemoryFV(&(File
->File
.Fv
),FileImage
,FileSize
);
177 } else if (File
->Type
== BDS_FILETYPE_MEM
) {
178 return BdsCopyRawFileToRuntimeMemoryMemMap(&(File
->File
.Mem
),FileImage
,FileSize
);
180 return EFI_INVALID_PARAMETER
;