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