udk2010.up2.shell initial release.
[mirror_edk2.git] / ShellPkg / Library / UefiShellDriver1CommandsLib / Connect.c
1 /** @file\r
2   Main file for connect shell Driver1 function.\r
3 \r
4   Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
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 #include <Guid/GlobalVariable.h>\r
17 #include <Guid/ConsoleInDevice.h>\r
18 #include <Guid/ConsoleOutDevice.h>\r
19 \r
20 EFI_STATUS\r
21 EFIAPI\r
22 ConnectControllers (\r
23   IN CONST EFI_HANDLE ControllerHandle,\r
24   IN CONST EFI_HANDLE DriverHandle,\r
25   IN CONST BOOLEAN    Recursive,\r
26   IN CONST BOOLEAN    Output\r
27   ){\r
28   EFI_STATUS Status;\r
29   EFI_HANDLE *ControllerHandleList;\r
30   EFI_HANDLE *DriverHandleList;\r
31   EFI_HANDLE *HandleWalker;\r
32 \r
33   ControllerHandleList  = NULL;\r
34   Status                = EFI_NOT_FOUND;\r
35 \r
36   //\r
37   // If we have a single handle to connect make that a 'list'\r
38   //\r
39   if (DriverHandle == NULL) {\r
40     DriverHandleList = NULL;\r
41   } else {\r
42     DriverHandleList = AllocatePool(2*sizeof(EFI_HANDLE));\r
43     DriverHandleList[0] = DriverHandle;\r
44     DriverHandleList[1] = NULL;\r
45   }\r
46 \r
47   //\r
48   // do we connect all controllers (with a loop) or a single one...\r
49   // This is where we call the gBS->ConnectController function.\r
50   //\r
51   if (ControllerHandle == NULL) {\r
52     ControllerHandleList = GetHandleListByPotocol(&gEfiDevicePathProtocolGuid);\r
53     for (HandleWalker = ControllerHandleList\r
54       ;  HandleWalker != NULL && *HandleWalker != NULL\r
55       ;  HandleWalker++\r
56       ){\r
57       Status = gBS->ConnectController(*HandleWalker, DriverHandleList, NULL, Recursive);\r
58       if (Output) {\r
59         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_CON_RESULT), gShellDriver1HiiHandle, *HandleWalker, Status);\r
60       }\r
61     }\r
62   } else {\r
63     Status = gBS->ConnectController(ControllerHandle, DriverHandleList, NULL, Recursive);\r
64     ASSERT(Output == FALSE);\r
65   }\r
66 \r
67   //\r
68   // Free any memory we allocated.\r
69   //\r
70   if (ControllerHandleList != NULL) {\r
71     FreePool(ControllerHandleList);\r
72   }\r
73   if (DriverHandleList     != NULL) {\r
74     FreePool(DriverHandleList);\r
75   }\r
76   return (Status);\r
77 }\r
78 \r
79 EFI_STATUS\r
80 EFIAPI\r
81 ConnectFromDevPaths (\r
82   IN CONST CHAR16 *Key\r
83   ){\r
84   EFI_DEVICE_PATH_PROTOCOL  *DevPath;\r
85   EFI_DEVICE_PATH_PROTOCOL  *DevPathWalker;\r
86   UINTN                     Length;\r
87   EFI_HANDLE                Handle;\r
88   EFI_STATUS                Status;\r
89 \r
90   DevPath = NULL;\r
91   Length  = 0;\r
92 \r
93   //\r
94   // Get the DevicePath buffer from the variable...\r
95   //\r
96   Status = gRT->GetVariable((CHAR16*)Key, (EFI_GUID*)&gEfiGlobalVariableGuid, NULL, &Length, DevPath);\r
97   if (Status == EFI_BUFFER_TOO_SMALL) {\r
98     DevPath = AllocatePool(Length);\r
99     Status = gRT->GetVariable((CHAR16*)Key, (EFI_GUID*)&gEfiGlobalVariableGuid, NULL, &Length, DevPath);\r
100   }\r
101 \r
102   //\r
103   // walk the list of devices and connect them\r
104   //\r
105   for (DevPathWalker = DevPath\r
106     ;  DevPathWalker < (DevPath + Length) && !EFI_ERROR(Status) && DevPath != NULL\r
107     ;  DevPathWalker += GetDevicePathSize(DevPathWalker)\r
108     ){\r
109     //\r
110     // get the correct handle from a given device path\r
111     //\r
112     if (StrCmp(Key, L"ConInDev") == 0) {\r
113       Status = gBS->LocateDevicePath((EFI_GUID*)&gEfiConsoleInDeviceGuid, &DevPathWalker, &Handle);\r
114     } else if (StrCmp(Key, L"ConOutDev") == 0) {\r
115       Status = gBS->LocateDevicePath((EFI_GUID*)&gEfiConsoleOutDeviceGuid, &DevPathWalker, &Handle);\r
116     } else {\r
117       Handle = NULL;\r
118       Status = EFI_INVALID_PARAMETER;\r
119       ASSERT(FALSE);\r
120     }\r
121     if (!EFI_ERROR(Status)) {\r
122       Status = ConnectControllers(Handle, NULL, FALSE, FALSE);\r
123     }\r
124   }\r
125 \r
126   if (DevPath != NULL) {\r
127     FreePool(DevPath);\r
128   }\r
129   return (Status);\r
130 }\r
131 \r
132 EFI_STATUS\r
133 EFIAPI\r
134 ConvertAndConnectControllers (\r
135   IN CONST CHAR16   *StringHandle1,\r
136   IN CONST CHAR16   *StringHandle2 OPTIONAL,\r
137   IN CONST BOOLEAN  Recursive,\r
138   IN CONST BOOLEAN  Output\r
139   ){\r
140   EFI_HANDLE Handle1;\r
141   EFI_HANDLE Handle2;\r
142 \r
143   //\r
144   // Convert the command line parameters to HANDLES.  They must be in HEX according to spec.\r
145   //\r
146   if (StringHandle1 != NULL) {\r
147     Handle1 = (EFI_HANDLE)StrHexToUintn(StringHandle1);\r
148   } else {\r
149     Handle1 = NULL;\r
150   }\r
151   if (StringHandle2 != NULL) {\r
152     Handle2 = (EFI_HANDLE)StrHexToUintn(StringHandle2);\r
153   } else {\r
154     Handle2 = NULL;\r
155   }\r
156 \r
157   //\r
158   // if only one is NULL verify it's the proper one...\r
159   //\r
160   if ( (Handle1 == NULL && Handle2 != NULL)\r
161     || (Handle1 != NULL && Handle2 == NULL)\r
162     ){\r
163     //\r
164     // Figure out which one should be NULL and move the handle to the right place.\r
165     // If Handle1 is NULL then test Handle2 and vise versa.\r
166     // The one that DOES has driver binding must be Handle2\r
167     //\r
168     if (Handle1 == NULL) {\r
169       if (EFI_ERROR(gBS->OpenProtocol(Handle2, &gEfiDriverBindingProtocolGuid, NULL, NULL, gImageHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) {\r
170         // swap\r
171         Handle1 = Handle2;\r
172         Handle2 = NULL;\r
173       } else {\r
174         // We're all good...\r
175       }\r
176     } else {\r
177       if (EFI_ERROR(gBS->OpenProtocol(Handle1, &gEfiDriverBindingProtocolGuid, NULL, NULL, gImageHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) {\r
178         // We're all good...\r
179       } else {\r
180         // swap\r
181         Handle2 = Handle1;\r
182         Handle1 = NULL;\r
183       }\r
184     }\r
185   }\r
186 \r
187   return (ConnectControllers(Handle1, Handle2, Recursive, Output));\r
188 }\r
189 \r
190 STATIC CONST SHELL_PARAM_ITEM ParamList[] = {\r
191   {L"-c", TypeFlag},\r
192   {L"-r", TypeFlag},\r
193   {NULL, TypeMax}\r
194   };\r
195 \r
196 SHELL_STATUS\r
197 EFIAPI\r
198 ShellCommandRunConnect (\r
199   VOID                *RESERVED\r
200   ) {\r
201   EFI_STATUS          Status;\r
202   LIST_ENTRY          *Package;\r
203   CHAR16              *ProblemParam;\r
204   SHELL_STATUS        ShellStatus;\r
205 \r
206   ShellStatus         = SHELL_SUCCESS;\r
207 \r
208   //\r
209   // initialize the shell lib (we must be in non-auto-init...)\r
210   //\r
211   Status = ShellInitialize();\r
212   ASSERT_EFI_ERROR(Status);\r
213 \r
214   Status = CommandInit();\r
215   ASSERT_EFI_ERROR(Status);\r
216 \r
217   //\r
218   // parse the command line\r
219   //\r
220   Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);\r
221   if EFI_ERROR(Status) {\r
222     if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {\r
223       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, ProblemParam);\r
224       FreePool(ProblemParam);\r
225       ShellStatus = SHELL_INVALID_PARAMETER;\r
226     } else {\r
227       ASSERT(FALSE);\r
228     }\r
229   } else {\r
230     //\r
231     // 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
232     //\r
233     if ((ShellCommandLineGetCount() > 3)\r
234       ||((ShellCommandLineGetFlag(Package, L"-r") != FALSE || ShellCommandLineGetFlag(Package, L"-c") != FALSE) && ShellCommandLineGetCount()!=0)\r
235       ){\r
236       //\r
237       // error for too many parameters\r
238       //\r
239       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle);\r
240       ShellStatus = SHELL_INVALID_PARAMETER;\r
241     } else if (ShellCommandLineGetFlag(Package, L"-c") != FALSE) {\r
242       //\r
243       // do the conin and conout from EFI variables\r
244       // if the first fails dont 'loose' the error\r
245       //\r
246       Status = ConnectFromDevPaths(L"ConInDev");\r
247       if (EFI_ERROR(Status)) {\r
248         ConnectFromDevPaths(L"ConOutDev");\r
249       } else {\r
250         Status = ConnectFromDevPaths(L"ConOutDev");\r
251       }\r
252       ShellStatus = Status & (~MAX_BIT);\r
253     } else {\r
254       //\r
255       // 0, 1, or 2 specific handles and possibly recursive\r
256       //\r
257       if (ShellCommandLineGetRawValue(Package, 1) != NULL && CommandLibGetHandleValue(StrHexToUintn(ShellCommandLineGetRawValue(Package, 1))) == NULL){\r
258         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, ShellCommandLineGetRawValue(Package, 1));\r
259         ShellStatus = SHELL_INVALID_PARAMETER;\r
260       } else if (ShellCommandLineGetRawValue(Package, 2) != NULL && CommandLibGetHandleValue(StrHexToUintn(ShellCommandLineGetRawValue(Package, 2))) == NULL) {\r
261         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, ShellCommandLineGetRawValue(Package, 2));\r
262         ShellStatus = SHELL_INVALID_PARAMETER;\r
263       } else {\r
264         Status = ConvertAndConnectControllers(ShellCommandLineGetRawValue(Package, 1), ShellCommandLineGetRawValue(Package, 2), ShellCommandLineGetFlag(Package, L"-r"), (BOOLEAN)(ShellCommandLineGetCount()!=0));\r
265         ShellStatus = Status & (~MAX_BIT);\r
266       }\r
267     }\r
268 \r
269     ShellCommandLineFreeVarList (Package);\r
270   }\r
271   return (ShellStatus);\r
272 }\r
273 \r