]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPkg/Library/BdsLib/BdsFilePath.c
Sync up ArmPkg with patch from mailing list. Changed name of BdsLib.h to BdsUnixLib...
[mirror_edk2.git] / ArmPkg / Library / BdsLib / BdsFilePath.c
1 /** @file
2 *
3 * Copyright (c) 2011, ARM Limited. All rights reserved.
4 *
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
9 *
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.
12 *
13 **/
14
15 #include "BdsInternal.h"
16
17 // Count the number of DevicePath Node
18 static UINTN NumberNodeFromDevicePath(
19 IN EFI_DEVICE_PATH_PROTOCOL* DevicePath
20 ) {
21 UINTN NumberDevicePathNode = 0;
22
23 while (!IsDevicePathEnd (DevicePath)) {
24 NumberDevicePathNode++;
25 DevicePath = NextDevicePathNode(DevicePath);
26 }
27 return NumberDevicePathNode;
28 }
29
30 // Extract the FilePath from the Device Path
31 CHAR16* BdsExtractFilePathFromDevicePath(
32 IN CONST CHAR16 *StrDevicePath,
33 IN UINTN NumberDevicePathNode
34 ) {
35 UINTN Node;
36 CHAR16 *Str;
37
38 Str = (CHAR16*)StrDevicePath;
39 Node = 0;
40 while ((Str != NULL) && (*Str != L'\0') && (Node < NumberDevicePathNode)) {
41 if ((*Str == L'/') || (*Str == L'\\')) {
42 Node++;
43 }
44 Str++;
45 }
46
47 if (*Str == L'\0') {
48 return NULL;
49 } else {
50 return Str;
51 }
52 }
53
54 EFI_STATUS
55 BdsLoadDevicePath(
56 IN EFI_DEVICE_PATH_PROTOCOL* DevicePath,
57 OUT EFI_HANDLE *Handle
58 ) {
59 EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;
60 EFI_STATUS Status;
61
62 if ((DevicePath == NULL) || (Handle == NULL)) {
63 return EFI_INVALID_PARAMETER;
64 }
65
66 do {
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);
75 }
76
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);
81 }
82 } while (!EFI_ERROR (Status) && !IsDevicePathEnd (RemainingDevicePath));
83
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)) {
94 Status = EFI_SUCCESS;
95 }
96 }
97 }
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);
103 }
104
105 return Status;
106 }
107
108
109 EFI_STATUS
110 BdsLoadFilePath (
111 IN CONST CHAR16 *DeviceFilePath,
112 OUT BDS_FILE *File
113 ) {
114 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
115 EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *EfiDevicePathFromTextProtocol;
116 EFI_STATUS Status;
117 EFI_HANDLE Handle;
118 UINTN NumberDevicePathNode;
119 CHAR16 *FilePath;
120
121 //Do a sanity check on the Device file path
122 if (DeviceFilePath == NULL) {
123 return EFI_INVALID_PARAMETER;
124 }
125
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);
130
131 //Do a sanity check on the Device Path
132 if (DevicePath == NULL) {
133 return EFI_INVALID_PARAMETER;
134 }
135
136 // Count the number of DevicePath Node
137 NumberDevicePathNode = NumberNodeFromDevicePath(DevicePath);
138 // Extract the FilePath from the Device Path
139 FilePath = BdsExtractFilePathFromDevicePath(DeviceFilePath,NumberDevicePathNode);
140
141 Status = BdsLoadDevicePath(DevicePath,&Handle);
142 if (EFI_ERROR (Status)) {
143 return Status;
144 }
145
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);
150 } else {
151 Status = BdsLoadFileFromSimpleFileSystem(Handle,FilePath,File);
152 if (EFI_ERROR (Status)) {
153 Status = BdsLoadFileFromFirmwareVolume(Handle,FilePath,EFI_FV_FILETYPE_ALL,File);
154 }
155 }
156
157 if (!EFI_ERROR (Status)) {
158 File->DevicePath = DevicePath;
159 }
160
161 return Status;
162 }
163
164 EFI_STATUS BdsCopyRawFileToRuntimeMemory(
165 IN BDS_FILE *File,
166 OUT VOID **FileImage,
167 OUT UINTN *FileSize
168 ) {
169 if (File == NULL) {
170 return EFI_INVALID_PARAMETER;
171 }
172
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);
179 } else {
180 return EFI_INVALID_PARAMETER;
181 }
182 }