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