1 /** @file
2   Main file for SerMode shell Debug1 function.
3 
4   (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
5   Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
6   SPDX-License-Identifier: BSD-2-Clause-Patent
7 
8 **/
9 
10 #include "UefiShellDebug1CommandsLib.h"
11 #include <Library/ShellLib.h>
12 #include <Protocol/SerialIo.h>
13 
14 /**
15   Display information about a serial device by it's handle.
16 
17   If HandleValid is FALSE, do all devices.
18 
19   @param[in] HandleIdx      The handle index for the device.
20   @param[in] HandleValid    TRUE if HandleIdx is valid.
21 
22   @retval SHELL_INVALID_PARAMETER   A parameter was invalid.
23   @retval SHELL_SUCCESS             The operation was successful.
24 **/
25 SHELL_STATUS
DisplaySettings(IN UINTN HandleIdx,IN BOOLEAN HandleValid)26 DisplaySettings (
27   IN UINTN                   HandleIdx,
28   IN BOOLEAN                 HandleValid
29   )
30 {
31   EFI_SERIAL_IO_PROTOCOL  *SerialIo;
32   UINTN                   NoHandles;
33   EFI_HANDLE              *Handles;
34   EFI_STATUS              Status;
35   UINTN                   Index;
36   CHAR16                  *StopBits;
37   CHAR16                  Parity;
38   SHELL_STATUS            ShellStatus;
39 
40   Handles   = NULL;
41   StopBits  = NULL;
42 
43   ShellStatus = SHELL_SUCCESS;
44 
45   Status    = gBS->LocateHandleBuffer (ByProtocol, &gEfiSerialIoProtocolGuid, NULL, &NoHandles, &Handles);
46   if (EFI_ERROR (Status)) {
47     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SERMODE_NO_FOUND), gShellDebug1HiiHandle, L"sermode");
48     return SHELL_INVALID_PARAMETER;
49   }
50 
51   for (Index = 0; Index < NoHandles; Index++) {
52     if (HandleValid) {
53       if (ConvertHandleIndexToHandle(HandleIdx) != Handles[Index]) {
54         continue;
55       }
56     }
57 
58     Status = gBS->HandleProtocol (Handles[Index], &gEfiSerialIoProtocolGuid, (VOID**)&SerialIo);
59     if (!EFI_ERROR (Status)) {
60       switch (SerialIo->Mode->Parity) {
61       case DefaultParity:
62 
63         Parity = 'D';
64         break;
65 
66       case NoParity:
67 
68         Parity = 'N';
69         break;
70 
71       case EvenParity:
72 
73         Parity = 'E';
74         break;
75 
76       case OddParity:
77 
78         Parity = 'O';
79         break;
80 
81       case MarkParity:
82 
83         Parity = 'M';
84         break;
85 
86       case SpaceParity:
87 
88         Parity = 'S';
89         break;
90 
91       default:
92 
93         Parity = 'U';
94       }
95 
96       switch (SerialIo->Mode->StopBits) {
97       case DefaultStopBits:
98 
99         StopBits = L"Default";
100         break;
101 
102       case OneStopBit:
103 
104         StopBits = L"1";
105         break;
106 
107       case TwoStopBits:
108 
109         StopBits = L"2";
110         break;
111 
112       case OneFiveStopBits:
113 
114         StopBits = L"1.5";
115         break;
116 
117       default:
118 
119         StopBits = L"Unknown";
120       }
121       ShellPrintHiiEx(
122         -1,
123         -1,
124         NULL,
125         STRING_TOKEN (STR_SERMODE_DISPLAY),
126         gShellDebug1HiiHandle,
127         ConvertHandleToHandleIndex (Handles[Index]),
128         Handles[Index],
129         SerialIo->Mode->BaudRate,
130         Parity,
131         SerialIo->Mode->DataBits,
132         StopBits
133        );
134     } else {
135       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SERMODE_NO_FOUND), gShellDebug1HiiHandle, L"sermode");
136       ShellStatus = SHELL_NOT_FOUND;
137       break;
138     }
139 
140     if (HandleValid) {
141       break;
142     }
143   }
144 
145   if (Index == NoHandles) {
146     if ((NoHandles != 0 && HandleValid) || 0 == NoHandles) {
147       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SERMODE_NOT_FOUND), gShellDebug1HiiHandle, L"sermode");
148       ShellStatus = SHELL_NOT_FOUND;
149     }
150   }
151 
152   return ShellStatus;
153 }
154 
155 /**
156   Function for 'sermode' command.
157 
158   @param[in] ImageHandle  Handle to the Image (NULL if Internal).
159   @param[in] SystemTable  Pointer to the System Table (NULL if Internal).
160 **/
161 SHELL_STATUS
162 EFIAPI
ShellCommandRunSerMode(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)163 ShellCommandRunSerMode (
164   IN EFI_HANDLE        ImageHandle,
165   IN EFI_SYSTEM_TABLE  *SystemTable
166   )
167 {
168   EFI_STATUS              Status;
169   SHELL_STATUS            ShellStatus;
170   UINTN                   Index;
171   UINTN                   NoHandles;
172   EFI_HANDLE              *Handles;
173   EFI_PARITY_TYPE         Parity;
174   EFI_STOP_BITS_TYPE      StopBits;
175   UINTN                   HandleIdx;
176   UINTN                   BaudRate;
177   UINTN                   DataBits;
178   UINTN                   Value;
179   EFI_SERIAL_IO_PROTOCOL  *SerialIo;
180   LIST_ENTRY              *Package;
181   CHAR16                  *ProblemParam;
182   CONST CHAR16            *Temp;
183   UINT64                  Intermediate;
184 
185   ShellStatus = SHELL_SUCCESS;
186   HandleIdx   = 0;
187   Parity      = DefaultParity;
188   Handles     = NULL;
189   NoHandles   = 0;
190   Index       = 0;
191   Package     = NULL;
192 
193   Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);
194   if (EFI_ERROR(Status)) {
195     if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
196       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"sermode", ProblemParam);
197       FreePool(ProblemParam);
198       ShellStatus = SHELL_INVALID_PARAMETER;
199     } else {
200       ASSERT(FALSE);
201     }
202   } else {
203     if (ShellCommandLineGetCount(Package) < 6 && ShellCommandLineGetCount(Package) > 2) {
204       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"sermode");
205       ShellStatus = SHELL_INVALID_PARAMETER;
206     } else if (ShellCommandLineGetCount(Package) > 6) {
207       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"sermode");
208       ShellStatus = SHELL_INVALID_PARAMETER;
209     } else {
210       Temp = ShellCommandLineGetRawValue(Package, 1);
211       if (Temp != NULL) {
212         Status = ShellConvertStringToUint64(Temp, &Intermediate, TRUE, FALSE);
213         HandleIdx = (UINTN)Intermediate;
214         Temp = ShellCommandLineGetRawValue(Package, 2);
215         if (Temp == NULL) {
216           ShellStatus = DisplaySettings (HandleIdx, TRUE);
217           goto Done;
218         }
219       } else {
220         ShellStatus = DisplaySettings (0, FALSE);
221         goto Done;
222       }
223       Temp = ShellCommandLineGetRawValue(Package, 2);
224       if (Temp != NULL) {
225         BaudRate = ShellStrToUintn(Temp);
226       } else {
227         ASSERT(FALSE);
228         BaudRate = 0;
229       }
230       Temp = ShellCommandLineGetRawValue(Package, 3);
231       if (Temp == NULL || StrLen(Temp)>1) {
232         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"sermode", Temp);
233         ShellStatus = SHELL_INVALID_PARAMETER;
234       } else {
235         switch(Temp[0]){
236         case 'd':
237         case 'D':
238           Parity = DefaultParity;
239           break;
240         case 'n':
241         case 'N':
242           Parity = NoParity;
243           break;
244         case 'e':
245         case 'E':
246           Parity = EvenParity;
247           break;
248         case 'o':
249         case 'O':
250           Parity = OddParity;
251           break;
252         case 'm':
253         case 'M':
254           Parity = MarkParity;
255           break;
256         case 's':
257         case 'S':
258           Parity = SpaceParity;
259           break;
260         default:
261           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"sermode", Temp);
262           ShellStatus = SHELL_INVALID_PARAMETER;
263           goto Done;
264         }
265       }
266       Temp = ShellCommandLineGetRawValue(Package, 4);
267       if (Temp != NULL) {
268         DataBits = ShellStrToUintn(Temp);
269       } else {
270         //
271         // make sure this is some number not in the list below.
272         //
273         DataBits = 0;
274       }
275       switch (DataBits) {
276       case 4:
277       case 7:
278       case 8:
279         break;
280       default:
281         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"sermode", Temp);
282         ShellStatus = SHELL_INVALID_PARAMETER;
283         goto Done;
284       }
285       Temp = ShellCommandLineGetRawValue(Package, 5);
286       Value = ShellStrToUintn(Temp);
287       switch (Value) {
288       case 0:
289         StopBits = DefaultStopBits;
290         break;
291 
292       case 1:
293         StopBits = OneStopBit;
294         break;
295 
296       case 2:
297         StopBits = TwoStopBits;
298         break;
299 
300       case 15:
301         StopBits = OneFiveStopBits;
302         break;
303 
304       default:
305         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"sermode", Temp);
306         ShellStatus = SHELL_INVALID_PARAMETER;
307         goto Done;
308       }
309       Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiSerialIoProtocolGuid, NULL, &NoHandles, &Handles);
310       if (EFI_ERROR (Status)) {
311         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SERMODE_NO_FOUND), gShellDebug1HiiHandle, L"sermode");
312         ShellStatus = SHELL_INVALID_PARAMETER;
313         goto Done;
314       }
315 
316       for (Index = 0; Index < NoHandles; Index++) {
317         if (ConvertHandleIndexToHandle (HandleIdx) != Handles[Index]) {
318           continue;
319         }
320 
321         Status = gBS->HandleProtocol (Handles[Index], &gEfiSerialIoProtocolGuid, (VOID**)&SerialIo);
322         if (!EFI_ERROR (Status)) {
323           Status = SerialIo->SetAttributes (
324                               SerialIo,
325                               (UINT64) BaudRate,
326                               SerialIo->Mode->ReceiveFifoDepth,
327                               SerialIo->Mode->Timeout,
328                               Parity,
329                               (UINT8) DataBits,
330                               StopBits
331                              );
332           if (EFI_ERROR (Status)) {
333             if (Status == EFI_INVALID_PARAMETER) {
334               ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SERMODE_SET_UNSUPPORTED), gShellDebug1HiiHandle, L"sermode", ConvertHandleToHandleIndex(Handles[Index]));
335               ShellStatus = SHELL_UNSUPPORTED;
336             } else if (Status == EFI_DEVICE_ERROR) {
337               ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SERMODE_SET_DEV_ERROR), gShellDebug1HiiHandle, L"sermode", ConvertHandleToHandleIndex(Handles[Index]));
338               ShellStatus = SHELL_ACCESS_DENIED;
339             } else {
340               ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SERMODE_SET_FAIL), gShellDebug1HiiHandle, L"sermode", ConvertHandleToHandleIndex(Handles[Index]));
341               ShellStatus = SHELL_ACCESS_DENIED;
342             }
343           } else {
344             ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SERMODE_SET_HANDLE), gShellDebug1HiiHandle, ConvertHandleToHandleIndex(Handles[Index]));
345           }
346           break;
347         }
348       }
349     }
350   }
351 
352   if (ShellStatus == SHELL_SUCCESS && Index == NoHandles) {
353     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SERMODE_BAD_HANDLE), gShellDebug1HiiHandle, L"sermode", HandleIdx);
354     ShellStatus = SHELL_INVALID_PARAMETER;
355   }
356 
357 Done:
358   if (Package != NULL) {
359     ShellCommandLineFreeVarList (Package);
360   }
361   if (Handles != NULL) {
362     FreePool (Handles);
363   }
364   return ShellStatus;
365 }
366