blob: 8fbb06e11b1fb7a5c33710793406be4276ad2df6 [file]
/** @file
Main file for SerMode shell Debug1 function.
(C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "UefiShellDebug1CommandsLib.h"
#include <Library/ShellLib.h>
#include <Protocol/SerialIo.h>
//
// Name translation for the Parity Bit
//
STATIC CONST CHAR8 ParityBitName[] = {
[DefaultParity] = 'D',
[NoParity] = 'N',
[EvenParity] = 'E',
[OddParity] = 'O',
[MarkParity] = 'M',
[SpaceParity] = 'S',
};
//
// Name translation for the Stop Bits
//
STATIC CONST CHAR16 *StopBitsName[] = {
[DefaultStopBits] = L"Default",
[OneStopBit] = L"1",
[OneFiveStopBits] = L"1.5",
[TwoStopBits] = L"2",
};
/**
Display information about a serial device by it's handle.
If HandleValid is FALSE, do all devices.
@param[in] HandleIdx The handle index for the device.
@param[in] HandleValid TRUE if HandleIdx is valid.
@retval SHELL_INVALID_PARAMETER A parameter was invalid.
@retval SHELL_SUCCESS The operation was successful.
**/
SHELL_STATUS
DisplaySettings (
IN UINTN HandleIdx,
IN BOOLEAN HandleValid
)
{
EFI_SERIAL_IO_PROTOCOL *SerialIo;
UINTN NoHandles;
EFI_HANDLE *Handles;
EFI_STATUS Status;
UINTN Index;
CONST CHAR16 *StopBits;
CHAR16 Parity;
SHELL_STATUS ShellStatus;
Handles = NULL;
ShellStatus = SHELL_SUCCESS;
Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiSerialIoProtocolGuid, NULL, &NoHandles, &Handles);
if (EFI_ERROR (Status)) {
ShellPrintHiiDefaultEx (STRING_TOKEN (STR_SERMODE_NO_FOUND), gShellDebug1HiiHandle, L"sermode");
return SHELL_INVALID_PARAMETER;
}
for (Index = 0; Index < NoHandles; Index++) {
if (HandleValid) {
if (ConvertHandleIndexToHandle (HandleIdx) != Handles[Index]) {
continue;
}
}
Status = gBS->HandleProtocol (Handles[Index], &gEfiSerialIoProtocolGuid, (VOID **)&SerialIo);
if (EFI_ERROR (Status)) {
ShellPrintHiiDefaultEx (STRING_TOKEN (STR_SERMODE_NO_FOUND), gShellDebug1HiiHandle, L"sermode");
ShellStatus = SHELL_NOT_FOUND;
break;
}
if (SerialIo->Mode->Parity <= SpaceParity) {
Parity = ParityBitName[SerialIo->Mode->Parity];
} else {
Parity = 'U';
}
if (SerialIo->Mode->StopBits <= TwoStopBits) {
StopBits = StopBitsName[SerialIo->Mode->StopBits];
} else {
StopBits = L"Unknown";
}
ShellPrintHiiDefaultEx (
STRING_TOKEN (STR_SERMODE_DISPLAY),
gShellDebug1HiiHandle,
ConvertHandleToHandleIndex (Handles[Index]),
Handles[Index],
SerialIo->Mode->BaudRate,
Parity,
SerialIo->Mode->DataBits,
StopBits
);
if (HandleValid) {
break;
}
}
if (Index == NoHandles) {
if (((NoHandles != 0) && HandleValid) || (0 == NoHandles)) {
ShellPrintHiiDefaultEx (STRING_TOKEN (STR_SERMODE_NOT_FOUND), gShellDebug1HiiHandle, L"sermode");
ShellStatus = SHELL_NOT_FOUND;
}
}
return ShellStatus;
}
/**
Get the Parity Type.
@param[in] ParityChar Parity Type character.
@param[out] ParityType If success, contains the converted Parity type.
@retval SHELL_INVALID_PARAMETER A parameter was invalid.
@retval SHELL_SUCCESS The operation was successful.
**/
STATIC
EFI_STATUS
GetParityType (
IN CHAR16 ParityChar,
OUT EFI_PARITY_TYPE *ParityType
)
{
EFI_STATUS Status;
EFI_PARITY_TYPE Parity;
ASSERT (ParityType != NULL);
Status = EFI_SUCCESS;
switch (ParityChar) {
case 'd':
case 'D':
Parity = DefaultParity;
break;
case 'n':
case 'N':
Parity = NoParity;
break;
case 'e':
case 'E':
Parity = EvenParity;
break;
case 'o':
case 'O':
Parity = OddParity;
break;
case 'm':
case 'M':
Parity = MarkParity;
break;
case 's':
case 'S':
Parity = SpaceParity;
break;
default:
Parity = DefaultParity;
Status = EFI_INVALID_PARAMETER;
break;
}
*ParityType = Parity;
return Status;
}
/**
Get the Stop Bits.
@param[in] StopBitsInt Stop Bits integer.
@param[out] StopBitsType If success, contains the converted StopBits type.
@retval SHELL_INVALID_PARAMETER A parameter was invalid.
@retval SHELL_SUCCESS The operation was successful.
**/
STATIC
EFI_STATUS
GetStopBits (
IN UINTN StopBitsInt,
OUT EFI_STOP_BITS_TYPE *StopBitsType
)
{
EFI_STATUS Status;
EFI_STOP_BITS_TYPE StopBits;
ASSERT (StopBitsType != NULL);
Status = EFI_SUCCESS;
switch (StopBitsInt) {
case 0:
StopBits = DefaultStopBits;
break;
case 1:
StopBits = OneStopBit;
break;
case 2:
StopBits = TwoStopBits;
break;
case 15:
StopBits = OneFiveStopBits;
break;
default:
StopBits = DefaultStopBits;
Status = EFI_INVALID_PARAMETER;
break;
}
*StopBitsType = StopBits;
return Status;
}
/**
Check whether the Data Bits are valid.
@param[in] DataBitsInt Data Bits integer.
@return TRUE if the Data Bits are valid.
**/
STATIC
BOOLEAN
ValidDataBits (
IN UINTN DataBits
)
{
return (DataBits == 4) || (DataBits == 7) || (DataBits == 8);
}
/**
Function for 'sermode' command.
@param[in] ImageHandle Handle to the Image (NULL if Internal).
@param[in] SystemTable Pointer to the System Table (NULL if Internal).
**/
SHELL_STATUS
EFIAPI
ShellCommandRunSerMode (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
SHELL_STATUS ShellStatus;
UINTN Index;
UINTN NoHandles;
EFI_HANDLE *Handles;
EFI_PARITY_TYPE Parity;
EFI_STOP_BITS_TYPE StopBits;
UINTN HandleIdx;
UINTN BaudRate;
UINTN DataBits;
EFI_SERIAL_IO_PROTOCOL *SerialIo;
LIST_ENTRY *Package;
CHAR16 *ProblemParam;
CONST CHAR16 *Temp;
UINT64 Intermediate;
ShellStatus = SHELL_SUCCESS;
HandleIdx = 0;
Parity = DefaultParity;
Handles = NULL;
NoHandles = 0;
Index = 0;
Package = NULL;
Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);
if (EFI_ERROR (Status)) {
if ((Status == EFI_VOLUME_CORRUPTED) && (ProblemParam != NULL)) {
ShellPrintHiiDefaultEx (STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"sermode", ProblemParam);
FreePool (ProblemParam);
ShellStatus = SHELL_INVALID_PARAMETER;
} else {
ASSERT (FALSE);
}
} else {
if ((ShellCommandLineGetCount (Package) < 6) && (ShellCommandLineGetCount (Package) > 2)) {
ShellPrintHiiDefaultEx (STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"sermode");
ShellStatus = SHELL_INVALID_PARAMETER;
} else if (ShellCommandLineGetCount (Package) > 6) {
ShellPrintHiiDefaultEx (STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"sermode");
ShellStatus = SHELL_INVALID_PARAMETER;
} else {
Temp = ShellCommandLineGetRawValue (Package, 1);
if (Temp != NULL) {
Status = ShellConvertStringToUint64 (Temp, &Intermediate, TRUE, FALSE);
HandleIdx = (UINTN)Intermediate;
Temp = ShellCommandLineGetRawValue (Package, 2);
if (Temp == NULL) {
ShellStatus = DisplaySettings (HandleIdx, TRUE);
goto Done;
}
} else {
ShellStatus = DisplaySettings (0, FALSE);
goto Done;
}
Temp = ShellCommandLineGetRawValue (Package, 2);
if (Temp != NULL) {
BaudRate = ShellStrToUintn (Temp);
} else {
ASSERT (FALSE);
BaudRate = 0;
}
Temp = ShellCommandLineGetRawValue (Package, 3);
if ((Temp == NULL) || (StrLen (Temp) > 1)) {
ShellPrintHiiDefaultEx (STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"sermode", Temp);
ShellStatus = SHELL_INVALID_PARAMETER;
} else {
Status = GetParityType (Temp[0], &Parity);
if (EFI_ERROR (Status)) {
ShellPrintHiiDefaultEx (STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"sermode", Temp);
ShellStatus = SHELL_INVALID_PARAMETER;
goto Done;
}
}
Temp = ShellCommandLineGetRawValue (Package, 4);
if (Temp != NULL) {
DataBits = ShellStrToUintn (Temp);
} else {
//
// make sure this is some number not in the list below.
//
DataBits = 0;
}
if (!ValidDataBits (DataBits)) {
ShellPrintHiiDefaultEx (STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"sermode", Temp);
ShellStatus = SHELL_INVALID_PARAMETER;
goto Done;
}
Temp = ShellCommandLineGetRawValue (Package, 5);
if (Temp == NULL) {
ShellPrintHiiDefaultEx (STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"sermode");
ShellStatus = SHELL_INVALID_PARAMETER;
goto Done;
}
Status = GetStopBits (ShellStrToUintn (Temp), &StopBits);
if (EFI_ERROR (Status)) {
ShellPrintHiiDefaultEx (STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"sermode", Temp);
ShellStatus = SHELL_INVALID_PARAMETER;
goto Done;
}
Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiSerialIoProtocolGuid, NULL, &NoHandles, &Handles);
if (EFI_ERROR (Status)) {
ShellPrintHiiDefaultEx (STRING_TOKEN (STR_SERMODE_NO_FOUND), gShellDebug1HiiHandle, L"sermode");
ShellStatus = SHELL_INVALID_PARAMETER;
goto Done;
}
for (Index = 0; Index < NoHandles; Index++) {
if (ConvertHandleIndexToHandle (HandleIdx) != Handles[Index]) {
continue;
}
Status = gBS->HandleProtocol (Handles[Index], &gEfiSerialIoProtocolGuid, (VOID **)&SerialIo);
if (!EFI_ERROR (Status)) {
Status = SerialIo->SetAttributes (
SerialIo,
(UINT64)BaudRate,
SerialIo->Mode->ReceiveFifoDepth,
SerialIo->Mode->Timeout,
Parity,
(UINT8)DataBits,
StopBits
);
if (EFI_ERROR (Status)) {
if (Status == EFI_INVALID_PARAMETER) {
ShellPrintHiiDefaultEx (STRING_TOKEN (STR_SERMODE_SET_UNSUPPORTED), gShellDebug1HiiHandle, L"sermode", ConvertHandleToHandleIndex (Handles[Index]));
ShellStatus = SHELL_UNSUPPORTED;
} else if (Status == EFI_DEVICE_ERROR) {
ShellPrintHiiDefaultEx (STRING_TOKEN (STR_SERMODE_SET_DEV_ERROR), gShellDebug1HiiHandle, L"sermode", ConvertHandleToHandleIndex (Handles[Index]));
ShellStatus = SHELL_ACCESS_DENIED;
} else {
ShellPrintHiiDefaultEx (STRING_TOKEN (STR_SERMODE_SET_FAIL), gShellDebug1HiiHandle, L"sermode", ConvertHandleToHandleIndex (Handles[Index]));
ShellStatus = SHELL_ACCESS_DENIED;
}
} else {
ShellPrintHiiDefaultEx (STRING_TOKEN (STR_SERMODE_SET_HANDLE), gShellDebug1HiiHandle, ConvertHandleToHandleIndex (Handles[Index]));
}
break;
}
}
}
}
if ((ShellStatus == SHELL_SUCCESS) && (Index == NoHandles)) {
ShellPrintHiiDefaultEx (STRING_TOKEN (STR_SERMODE_BAD_HANDLE), gShellDebug1HiiHandle, L"sermode", HandleIdx);
ShellStatus = SHELL_INVALID_PARAMETER;
}
Done:
if (Package != NULL) {
ShellCommandLineFreeVarList (Package);
}
if (Handles != NULL) {
FreePool (Handles);
}
return ShellStatus;
}