]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellDriver1CommandsLib/Connect.c
add more user input verification to connect and vol commands.
[mirror_edk2.git] / ShellPkg / Library / UefiShellDriver1CommandsLib / Connect.c
1 /** @file
2 Main file for connect shell Driver1 function.
3
4 Copyright (c) 2010 - 2011, 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"ConErrDev") == 0)
153 || (StrCmp(Key, L"ConOut") == 0)
154 || (StrCmp(Key, L"ConErr") == 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 if ((ShellCommandLineGetCount(Package) > 3)
281 ||((ShellCommandLineGetFlag(Package, L"-r") || ShellCommandLineGetFlag(Package, L"-c")) && ShellCommandLineGetCount(Package)>1)
282 ||(ShellCommandLineGetFlag(Package, L"-r") && ShellCommandLineGetFlag(Package, L"-c") )
283 ){
284 //
285 // error for too many parameters
286 //
287 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle);
288 ShellStatus = SHELL_INVALID_PARAMETER;
289 } else if (ShellCommandLineGetFlag(Package, L"-c")) {
290 //
291 // do the conin and conout from EFI variables
292 // if the first fails dont 'loose' the error
293 //
294 Status = ConnectFromDevPaths(L"ConInDev");
295 if (EFI_ERROR(Status)) {
296 ConnectFromDevPaths(L"ConOutDev");
297 } else {
298 Status = ConnectFromDevPaths(L"ConOutDev");
299 }
300 if (EFI_ERROR(Status)) {
301 ConnectFromDevPaths(L"ConErrDev");
302 } else {
303 Status = ConnectFromDevPaths(L"ConErrDev");
304 }
305 if (EFI_ERROR(Status)) {
306 ConnectFromDevPaths(L"ConErr");
307 } else {
308 Status = ConnectFromDevPaths(L"ConErr");
309 }
310 if (EFI_ERROR(Status)) {
311 ConnectFromDevPaths(L"ConIn");
312 } else {
313 Status = ConnectFromDevPaths(L"ConIn");
314 }
315 if (EFI_ERROR(Status)) {
316 ConnectFromDevPaths(L"ConOut");
317 } else {
318 Status = ConnectFromDevPaths(L"ConOut");
319 }
320 if (EFI_ERROR(Status)) {
321 ShellStatus = SHELL_DEVICE_ERROR;
322 }
323 } else {
324 //
325 // 0, 1, or 2 specific handles and possibly recursive
326 //
327 Param1 = ShellCommandLineGetRawValue(Package, 1);
328 Param2 = ShellCommandLineGetRawValue(Package, 2);
329 Count = ShellCommandLineGetCount(Package);
330
331 Status = ShellConvertStringToUint64(Param1, &Intermediate, TRUE, FALSE);
332 Handle1 = ConvertHandleIndexToHandle((UINTN)Intermediate);
333 if (EFI_ERROR(Status)) {
334 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, Param1);
335 ShellStatus = SHELL_INVALID_PARAMETER;
336 }
337 Status = ShellConvertStringToUint64(Param2, &Intermediate, TRUE, FALSE);
338 Handle2 = ConvertHandleIndexToHandle((UINTN)Intermediate);
339 if (EFI_ERROR(Status)) {
340 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, Param2);
341 ShellStatus = SHELL_INVALID_PARAMETER;
342 }
343
344 if (ShellStatus == SHELL_SUCCESS) {
345 if (Param1 != NULL && Handle1 == NULL){
346 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, Param1);
347 ShellStatus = SHELL_INVALID_PARAMETER;
348 } else if (Param2 != NULL && Handle2 == NULL) {
349 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, Param2);
350 ShellStatus = SHELL_INVALID_PARAMETER;
351 } else if (Handle2 != NULL && Handle1 != NULL && EFI_ERROR(gBS->OpenProtocol(Handle2, &gEfiDriverBindingProtocolGuid, NULL, gImageHandle, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) {
352 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, Param2);
353 ShellStatus = SHELL_INVALID_PARAMETER;
354 } else {
355 Status = ConvertAndConnectControllers(Handle1, Handle2, ShellCommandLineGetFlag(Package, L"-r"), (BOOLEAN)(Count!=0));
356 if (EFI_ERROR(Status)) {
357 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CONNECT_NONE), gShellDriver1HiiHandle);
358 ShellStatus = SHELL_DEVICE_ERROR;
359 }
360 }
361 }
362 }
363
364 ShellCommandLineFreeVarList (Package);
365 }
366 return (ShellStatus);
367 }
368