]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Library/UefiShellDriver1CommandsLib/Connect.c
ShellPkg: Move a function into shared location
[mirror_edk2.git] / ShellPkg / Library / UefiShellDriver1CommandsLib / Connect.c
CommitLineData
4ba49616 1/** @file\r
2 Main file for connect shell Driver1 function.\r
3\r
4ccd9214 4 Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>\r
4ba49616 5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "UefiShellDriver1CommandsLib.h"\r
16\r
17/**\r
361a8267 18 Connect controller(s) and driver(s).\r
19\r
20 @param[in] ControllerHandle The handle to the controller. Should have driver binding on it.\r
21 @param[in] DriverHandle The handle to the driver. Should have driver binding.\r
22 @param[in] Recursive TRUE to connect recursively, FALSE otherwise.\r
23 @param[in] Output TRUE to have info on the screen, FALSE otherwise.\r
24 @param[in] AlwaysOutput Override Output for errors.\r
25\r
26 @retval EFI_SUCCESS The operation was successful.\r
4ba49616 27**/\r
28EFI_STATUS\r
29EFIAPI\r
30ConnectControllers (\r
31 IN CONST EFI_HANDLE ControllerHandle OPTIONAL,\r
32 IN CONST EFI_HANDLE DriverHandle OPTIONAL,\r
33 IN CONST BOOLEAN Recursive,\r
34 IN CONST BOOLEAN Output,\r
35 IN CONST BOOLEAN AlwaysOutput\r
36 )\r
37{\r
38 EFI_STATUS Status;\r
39 EFI_STATUS Status2;\r
40 EFI_HANDLE *ControllerHandleList;\r
41 EFI_HANDLE *DriverHandleList;\r
42 EFI_HANDLE *HandleWalker;\r
43\r
44 ControllerHandleList = NULL;\r
45 Status = EFI_NOT_FOUND;\r
46 Status2 = EFI_NOT_FOUND;\r
47\r
48 //\r
49 // If we have a single handle to connect make that a 'list'\r
50 //\r
51 if (DriverHandle == NULL) {\r
52 DriverHandleList = NULL;\r
53 } else {\r
361a8267 54 DriverHandleList = AllocateZeroPool(2*sizeof(EFI_HANDLE));\r
4ba49616 55 if (DriverHandleList == NULL) {\r
56 return (EFI_OUT_OF_RESOURCES);\r
57 }\r
58 DriverHandleList[0] = DriverHandle;\r
59 DriverHandleList[1] = NULL;\r
60 }\r
61\r
62 //\r
63 // do we connect all controllers (with a loop) or a single one...\r
64 // This is where we call the gBS->ConnectController function.\r
65 //\r
66 if (ControllerHandle == NULL) {\r
67 ControllerHandleList = GetHandleListByProtocol(&gEfiDevicePathProtocolGuid);\r
68 for (HandleWalker = ControllerHandleList\r
69 ; HandleWalker != NULL && *HandleWalker != NULL\r
70 ; HandleWalker++\r
71 ){\r
72 Status = gBS->ConnectController(*HandleWalker, DriverHandleList, NULL, Recursive);\r
73 if (!EFI_ERROR(Status)) {\r
74 Status2 = EFI_SUCCESS;\r
75 }\r
76 if ((Output && !EFI_ERROR(Status)) || AlwaysOutput) {\r
77 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_HANDLE_RESULT), gShellDriver1HiiHandle, L"Connect", ConvertHandleToHandleIndex(*HandleWalker), Status);\r
78 }\r
79 }\r
80 } else {\r
81 Status = gBS->ConnectController(ControllerHandle, DriverHandleList, NULL, Recursive);\r
82 if (!EFI_ERROR(Status)) {\r
83 Status2 = EFI_SUCCESS;\r
84 }\r
85 if ((Output && !EFI_ERROR(Status)) || AlwaysOutput) {\r
86 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_HANDLE_RESULT), gShellDriver1HiiHandle, L"Connect", ConvertHandleToHandleIndex(ControllerHandle), Status);\r
87 }\r
88 }\r
89\r
90 //\r
91 // Free any memory we allocated.\r
92 //\r
93 if (ControllerHandleList != NULL) {\r
94 FreePool(ControllerHandleList);\r
95 }\r
96 if (DriverHandleList != NULL) {\r
97 FreePool(DriverHandleList);\r
98 }\r
99 return (Status2);\r
100}\r
101\r
361a8267 102/**\r
103 Do a connect from an EFI variable via it's key name.\r
104\r
105 @param[in] Key The name of the EFI Variable.\r
106\r
107 @retval EFI_SUCCESS The operation was successful.\r
108**/\r
4ba49616 109EFI_STATUS\r
110EFIAPI\r
111ConnectFromDevPaths (\r
112 IN CONST CHAR16 *Key\r
113 )\r
114{\r
115 EFI_DEVICE_PATH_PROTOCOL *DevPath;\r
116 EFI_DEVICE_PATH_PROTOCOL *DevPathWalker;\r
117 UINTN Length;\r
118 EFI_HANDLE Handle;\r
119 EFI_STATUS Status;\r
120\r
121 DevPath = NULL;\r
122 Length = 0;\r
123\r
124 //\r
125 // Get the DevicePath buffer from the variable...\r
126 //\r
127 Status = gRT->GetVariable((CHAR16*)Key, (EFI_GUID*)&gEfiGlobalVariableGuid, NULL, &Length, DevPath);\r
128 if (Status == EFI_BUFFER_TOO_SMALL) {\r
361a8267 129 DevPath = AllocateZeroPool(Length);\r
4ba49616 130 Status = gRT->GetVariable((CHAR16*)Key, (EFI_GUID*)&gEfiGlobalVariableGuid, NULL, &Length, DevPath);\r
131 }\r
132\r
133 Status = EFI_NOT_FOUND;\r
134 //\r
135 // walk the list of devices and connect them\r
136 //\r
137 for (DevPathWalker = DevPath\r
138 ; DevPathWalker < (DevPath + Length) && EFI_ERROR(Status) && DevPath != NULL\r
139 ; DevPathWalker += GetDevicePathSize(DevPathWalker)\r
140 ){\r
141 //\r
142 // get the correct handle from a given device path\r
143 //\r
144 if ((StrCmp(Key, L"ConInDev") == 0)\r
145 ||(StrCmp(Key, L"ConIn") == 0)\r
146 ){\r
147 Status = gBS->LocateDevicePath((EFI_GUID*)&gEfiConsoleInDeviceGuid, &DevPathWalker, &Handle);\r
148 if (!EFI_ERROR(Status)) {\r
149 Status = ConnectControllers(NULL, Handle, FALSE, TRUE, FALSE);\r
150 }\r
151 } else if ((StrCmp(Key, L"ConOutDev") == 0) \r
4ccd9214 152 || (StrCmp(Key, L"ErrOutDev") == 0) \r
4ba49616 153 || (StrCmp(Key, L"ConOut") == 0) \r
4ccd9214 154 || (StrCmp(Key, L"ErrOut") == 0)\r
4ba49616 155 ){\r
156 Status = gBS->LocateDevicePath((EFI_GUID*)&gEfiConsoleOutDeviceGuid, &DevPathWalker, &Handle);\r
157 if (!EFI_ERROR(Status)) {\r
158 Status = ConnectControllers(NULL, Handle, FALSE, TRUE, FALSE);\r
159 }\r
160 }\r
161 }\r
162\r
163 if (DevPath != NULL) {\r
164 FreePool(DevPath);\r
165 }\r
166 return (Status);\r
167}\r
168\r
361a8267 169/**\r
170 Convert the handle identifiers from strings and then connect them.\r
171\r
172 One of them should have driver binding and either can be NULL.\r
173\r
174 @param[in] Handle1 The first handle.\r
175 @param[in] Handle2 The second handle.\r
176 @param[in] Recursive TRUE to do connect recursively. FALSE otherwise.\r
177 @param[in] Output TRUE to have output to screen. FALSE otherwise.\r
178\r
179 @retval EFI_SUCCESS The operation was successful.\r
180**/\r
4ba49616 181EFI_STATUS\r
182EFIAPI\r
183ConvertAndConnectControllers (\r
361a8267 184 IN EFI_HANDLE *Handle1 OPTIONAL,\r
185 IN EFI_HANDLE *Handle2 OPTIONAL,\r
4ba49616 186 IN CONST BOOLEAN Recursive,\r
187 IN CONST BOOLEAN Output\r
188 )\r
189{\r
4ba49616 190 //\r
191 // if only one is NULL verify it's the proper one...\r
192 //\r
193 if ( (Handle1 == NULL && Handle2 != NULL)\r
194 || (Handle1 != NULL && Handle2 == NULL)\r
195 ){\r
196 //\r
197 // Figure out which one should be NULL and move the handle to the right place.\r
198 // If Handle1 is NULL then test Handle2 and vise versa.\r
199 // The one that DOES has driver binding must be Handle2\r
200 //\r
201 if (Handle1 == NULL) {\r
202 if (EFI_ERROR(gBS->OpenProtocol(Handle2, &gEfiDriverBindingProtocolGuid, NULL, NULL, gImageHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) {\r
203 // swap\r
204 Handle1 = Handle2;\r
205 Handle2 = NULL;\r
206 } else {\r
207 // We're all good...\r
208 }\r
209 } else {\r
210 if (EFI_ERROR(gBS->OpenProtocol(Handle1, &gEfiDriverBindingProtocolGuid, NULL, NULL, gImageHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) {\r
211 // We're all good...\r
212 } else {\r
213 // swap\r
214 Handle2 = Handle1;\r
215 Handle1 = NULL;\r
216 }\r
217 }\r
218 }\r
219\r
361a8267 220 return (ConnectControllers(Handle1, Handle2, Recursive, Output, (BOOLEAN)(Handle2 != NULL && Handle1 != NULL)));\r
4ba49616 221}\r
222\r
223STATIC CONST SHELL_PARAM_ITEM ParamList[] = {\r
224 {L"-c", TypeFlag},\r
225 {L"-r", TypeFlag},\r
226 {NULL, TypeMax}\r
227 };\r
228\r
229/**\r
230 Function for 'connect' command.\r
231\r
232 @param[in] ImageHandle Handle to the Image (NULL if Internal).\r
233 @param[in] SystemTable Pointer to the System Table (NULL if Internal).\r
234**/\r
235SHELL_STATUS\r
236EFIAPI\r
237ShellCommandRunConnect (\r
238 IN EFI_HANDLE ImageHandle,\r
239 IN EFI_SYSTEM_TABLE *SystemTable\r
240 )\r
241{\r
242 EFI_STATUS Status;\r
243 LIST_ENTRY *Package;\r
244 CHAR16 *ProblemParam;\r
245 SHELL_STATUS ShellStatus;\r
246 CONST CHAR16 *Param1;\r
247 CONST CHAR16 *Param2;\r
248 UINTN Count;\r
361a8267 249 EFI_HANDLE Handle1;\r
250 EFI_HANDLE Handle2;\r
251 UINT64 Intermediate;\r
4ba49616 252\r
253 ShellStatus = SHELL_SUCCESS;\r
254\r
255 //\r
256 // initialize the shell lib (we must be in non-auto-init...)\r
257 //\r
258 Status = ShellInitialize();\r
259 ASSERT_EFI_ERROR(Status);\r
260\r
261 Status = CommandInit();\r
262 ASSERT_EFI_ERROR(Status);\r
263\r
264 //\r
265 // parse the command line\r
266 //\r
267 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);\r
268 if (EFI_ERROR(Status)) {\r
269 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {\r
270 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, ProblemParam);\r
271 FreePool(ProblemParam);\r
272 ShellStatus = SHELL_INVALID_PARAMETER;\r
273 } else {\r
274 ASSERT(FALSE);\r
275 }\r
276 } else {\r
277 //\r
278 // if more than 2 'value' parameters (plus the name one) or either -r or -c with any value parameters we have too many parameters\r
279 //\r
6878e7a7 280 Count = (gInReconnect?0x4:0x3);\r
281 if ((ShellCommandLineGetCount(Package) > Count)\r
4ba49616 282 ||((ShellCommandLineGetFlag(Package, L"-r") || ShellCommandLineGetFlag(Package, L"-c")) && ShellCommandLineGetCount(Package)>1)\r
283 ||(ShellCommandLineGetFlag(Package, L"-r") && ShellCommandLineGetFlag(Package, L"-c") )\r
284 ){\r
285 //\r
286 // error for too many parameters\r
287 //\r
288 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle);\r
289 ShellStatus = SHELL_INVALID_PARAMETER;\r
290 } else if (ShellCommandLineGetFlag(Package, L"-c")) {\r
291 //\r
292 // do the conin and conout from EFI variables\r
293 // if the first fails dont 'loose' the error\r
294 //\r
295 Status = ConnectFromDevPaths(L"ConInDev");\r
296 if (EFI_ERROR(Status)) {\r
297 ConnectFromDevPaths(L"ConOutDev");\r
298 } else {\r
299 Status = ConnectFromDevPaths(L"ConOutDev");\r
300 }\r
301 if (EFI_ERROR(Status)) {\r
4ccd9214 302 ConnectFromDevPaths(L"ErrOutDev");\r
4ba49616 303 } else {\r
4ccd9214 304 Status = ConnectFromDevPaths(L"ErrOutDev");\r
4ba49616 305 }\r
306 if (EFI_ERROR(Status)) {\r
4ccd9214 307 ConnectFromDevPaths(L"ErrOut");\r
4ba49616 308 } else {\r
4ccd9214 309 Status = ConnectFromDevPaths(L"ErrOut");\r
4ba49616 310 }\r
311 if (EFI_ERROR(Status)) {\r
312 ConnectFromDevPaths(L"ConIn");\r
313 } else {\r
314 Status = ConnectFromDevPaths(L"ConIn");\r
315 }\r
316 if (EFI_ERROR(Status)) {\r
317 ConnectFromDevPaths(L"ConOut");\r
318 } else {\r
319 Status = ConnectFromDevPaths(L"ConOut");\r
320 }\r
321 if (EFI_ERROR(Status)) {\r
322 ShellStatus = SHELL_DEVICE_ERROR;\r
323 }\r
324 } else {\r
325 //\r
326 // 0, 1, or 2 specific handles and possibly recursive\r
327 //\r
361a8267 328 Param1 = ShellCommandLineGetRawValue(Package, 1);\r
329 Param2 = ShellCommandLineGetRawValue(Package, 2);\r
330 Count = ShellCommandLineGetCount(Package);\r
331\r
6878e7a7 332 if (Param1 != NULL) {\r
333 Status = ShellConvertStringToUint64(Param1, &Intermediate, TRUE, FALSE);\r
334 Handle1 = ConvertHandleIndexToHandle((UINTN)Intermediate);\r
335 if (EFI_ERROR(Status)) {\r
336 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, Param1);\r
337 ShellStatus = SHELL_INVALID_PARAMETER;\r
338 }\r
339 } else {\r
340 Handle1 = NULL;\r
361a8267 341 }\r
6878e7a7 342\r
343 if (Param2 != NULL) {\r
344 Status = ShellConvertStringToUint64(Param2, &Intermediate, TRUE, FALSE);\r
345 Handle2 = ConvertHandleIndexToHandle((UINTN)Intermediate);\r
346 if (EFI_ERROR(Status)) {\r
347 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, Param2);\r
348 ShellStatus = SHELL_INVALID_PARAMETER;\r
349 }\r
350 } else {\r
351 Handle2 = NULL;\r
361a8267 352 }\r
353 \r
354 if (ShellStatus == SHELL_SUCCESS) {\r
355 if (Param1 != NULL && Handle1 == NULL){\r
356 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, Param1);\r
357 ShellStatus = SHELL_INVALID_PARAMETER;\r
358 } else if (Param2 != NULL && Handle2 == NULL) {\r
359 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, Param2);\r
360 ShellStatus = SHELL_INVALID_PARAMETER;\r
6b825919 361 } else if (Handle2 != NULL && Handle1 != NULL && EFI_ERROR(gBS->OpenProtocol(Handle2, &gEfiDriverBindingProtocolGuid, NULL, gImageHandle, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) {\r
362 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, Param2);\r
363 ShellStatus = SHELL_INVALID_PARAMETER;\r
361a8267 364 } else {\r
365 Status = ConvertAndConnectControllers(Handle1, Handle2, ShellCommandLineGetFlag(Package, L"-r"), (BOOLEAN)(Count!=0));\r
366 if (EFI_ERROR(Status)) {\r
367 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CONNECT_NONE), gShellDriver1HiiHandle);\r
368 ShellStatus = SHELL_DEVICE_ERROR;\r
369 }\r
4ba49616 370 }\r
371 }\r
372 }\r
373\r
374 ShellCommandLineFreeVarList (Package);\r
375 }\r
376 return (ShellStatus);\r
377}\r
378\r