Home | History | Annotate | Download | only in UefiShellDebug1CommandsLib
      1 /** @file
      2   Main file for SetVar shell Debug1 function.
      3 
      4   (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
      5   Copyright (c) 2010 - 2014, 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 
     18 STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
     19   {L"-guid", TypeValue},
     20   {L"-bs", TypeFlag},
     21   {L"-rt", TypeFlag},
     22   {L"-nv", TypeFlag},
     23   {NULL, TypeMax}
     24   };
     25 
     26 
     27 /**
     28   Check if the input is a (potentially empty) string of hexadecimal nibbles.
     29 
     30   @param[in] String  The CHAR16 string to check.
     31 
     32   @retval FALSE  A character has been found in String for which
     33                  ShellIsHexaDecimalDigitCharacter() returned FALSE.
     34 
     35   @retval TRUE   Otherwise. (Note that this covers the case when String is
     36                  empty.)
     37 **/
     38 BOOLEAN
     39 IsStringOfHexNibbles (
     40   IN CONST CHAR16  *String
     41   )
     42 {
     43   CONST CHAR16 *Pos;
     44 
     45   for (Pos = String; *Pos != L'\0'; ++Pos) {
     46     if (!ShellIsHexaDecimalDigitCharacter (*Pos)) {
     47       return FALSE;
     48     }
     49   }
     50   return TRUE;
     51 }
     52 
     53 
     54 /**
     55   Function for 'setvar' command.
     56 
     57   @param[in] ImageHandle  Handle to the Image (NULL if Internal).
     58   @param[in] SystemTable  Pointer to the System Table (NULL if Internal).
     59 **/
     60 SHELL_STATUS
     61 EFIAPI
     62 ShellCommandRunSetVar (
     63   IN EFI_HANDLE        ImageHandle,
     64   IN EFI_SYSTEM_TABLE  *SystemTable
     65   )
     66 {
     67   EFI_STATUS          Status;
     68   LIST_ENTRY          *Package;
     69   CHAR16              *ProblemParam;
     70   SHELL_STATUS        ShellStatus;
     71   CONST CHAR16        *VariableName;
     72   CONST CHAR16        *Data;
     73   EFI_GUID            Guid;
     74   CONST CHAR16        *StringGuid;
     75   UINT32              Attributes;
     76   VOID                *Buffer;
     77   UINTN               Size;
     78   UINTN               LoopVar;
     79   EFI_DEVICE_PATH_PROTOCOL           *DevPath;
     80 
     81   ShellStatus         = SHELL_SUCCESS;
     82   Status              = EFI_SUCCESS;
     83   Buffer              = NULL;
     84   Size                = 0;
     85   Attributes          = 0;
     86   DevPath             = NULL;
     87 
     88   //
     89   // initialize the shell lib (we must be in non-auto-init...)
     90   //
     91   Status = ShellInitialize();
     92   ASSERT_EFI_ERROR(Status);
     93 
     94   Status = CommandInit();
     95   ASSERT_EFI_ERROR(Status);
     96 
     97   //
     98   // parse the command line
     99   //
    100   Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
    101   if (EFI_ERROR(Status)) {
    102     if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
    103       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"setvar", ProblemParam);
    104       FreePool(ProblemParam);
    105       ShellStatus = SHELL_INVALID_PARAMETER;
    106     } else {
    107       ASSERT(FALSE);
    108     }
    109   } else {
    110     if (ShellCommandLineGetCount(Package) < 2) {
    111       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"setvar");
    112       ShellStatus = SHELL_INVALID_PARAMETER;
    113     } else if (ShellCommandLineGetCount(Package) > 3) {
    114       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"setvar");
    115       ShellStatus = SHELL_INVALID_PARAMETER;
    116     } else {
    117       VariableName  = ShellCommandLineGetRawValue(Package, 1);
    118       Data          = ShellCommandLineGetRawValue(Package, 2);
    119       if (!ShellCommandLineGetFlag(Package, L"-guid")){
    120         CopyGuid(&Guid, &gEfiGlobalVariableGuid);
    121       } else {
    122         StringGuid = ShellCommandLineGetValue(Package, L"-guid");
    123         Status = ConvertStringToGuid(StringGuid, &Guid);
    124         if (EFI_ERROR(Status)) {
    125           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"setvar", StringGuid);
    126           ShellStatus = SHELL_INVALID_PARAMETER;
    127         }
    128       }
    129       if (Data == NULL || Data[0] !=  L'=') {
    130         //
    131         // Display what's there
    132         //
    133         Status = gRT->GetVariable((CHAR16*)VariableName, &Guid, &Attributes, &Size, Buffer);
    134         if (Status == EFI_BUFFER_TOO_SMALL) {
    135           Buffer = AllocateZeroPool(Size);
    136           Status = gRT->GetVariable((CHAR16*)VariableName, &Guid, &Attributes, &Size, Buffer);
    137         }
    138         if (!EFI_ERROR(Status)&& Buffer != NULL) {
    139           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SETVAR_PRINT), gShellDebug1HiiHandle, &Guid, VariableName, Size);
    140           for (LoopVar = 0 ; LoopVar < Size ; LoopVar++) {
    141             ShellPrintEx(-1, -1, L"%02x ", ((UINT8*)Buffer)[LoopVar]);
    142           }
    143           ShellPrintEx(-1, -1, L"\r\n");
    144         } else {
    145           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SETVAR_ERROR_GET), gShellDebug1HiiHandle, L"setvar", &Guid, VariableName);
    146           ShellStatus = SHELL_ACCESS_DENIED;
    147         }
    148       } else if (StrCmp(Data, L"=") == 0) {
    149         //
    150         // Delete what's there!
    151         //
    152         Status = gRT->SetVariable((CHAR16*)VariableName, &Guid, Attributes, 0, NULL);
    153         if (EFI_ERROR(Status)) {
    154           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SETVAR_ERROR_SET), gShellDebug1HiiHandle, L"setvar", &Guid, VariableName);
    155           ShellStatus = SHELL_ACCESS_DENIED;
    156         } else {
    157           ASSERT(ShellStatus == SHELL_SUCCESS);
    158         }
    159       } else {
    160         //
    161         // Change what's there or create a new one.
    162         //
    163 
    164         ASSERT(Data[0] == L'=');
    165         Data++;
    166         ASSERT(Data[0] != L'\0');
    167 
    168         //
    169         // Determine if the variable exists and get the attributes
    170         //
    171         Status = gRT->GetVariable((CHAR16*)VariableName, &Guid, &Attributes, &Size, Buffer);
    172         if (Status == EFI_BUFFER_TOO_SMALL) {
    173           Buffer = AllocateZeroPool(Size);
    174           Status = gRT->GetVariable((CHAR16*)VariableName, &Guid, &Attributes, &Size, Buffer);
    175         }
    176 
    177         if (EFI_ERROR(Status) || Buffer == NULL) {
    178           //
    179           // Creating a new variable.  determine attributes from command line.
    180           //
    181           Attributes = 0;
    182           if (ShellCommandLineGetFlag(Package, L"-bs")) {
    183             Attributes |= EFI_VARIABLE_BOOTSERVICE_ACCESS;
    184           }
    185           if (ShellCommandLineGetFlag(Package, L"-rt")) {
    186             Attributes |= EFI_VARIABLE_RUNTIME_ACCESS |
    187                           EFI_VARIABLE_BOOTSERVICE_ACCESS;
    188           }
    189           if (ShellCommandLineGetFlag(Package, L"-nv")) {
    190             Attributes |= EFI_VARIABLE_NON_VOLATILE;
    191           }
    192         }
    193         SHELL_FREE_NON_NULL(Buffer);
    194 
    195         //
    196         // What type is the new data.
    197         //
    198         if (IsStringOfHexNibbles(Data)) {
    199           if (StrLen(Data) % 2 != 0) {
    200             ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"setvar", Data);
    201             ShellStatus = SHELL_INVALID_PARAMETER;
    202           } else {
    203             //
    204             // arbitrary buffer
    205             //
    206             Buffer = AllocateZeroPool((StrLen(Data) / 2));
    207             if (Buffer == NULL) {
    208               Status = EFI_OUT_OF_RESOURCES;
    209             } else {
    210               for (LoopVar = 0 ; LoopVar < (StrLen(Data) / 2) ; LoopVar++) {
    211                 ((UINT8*)Buffer)[LoopVar] = (UINT8)(HexCharToUintn(Data[LoopVar*2]) * 16);
    212                 ((UINT8*)Buffer)[LoopVar] = (UINT8)(((UINT8*)Buffer)[LoopVar] + HexCharToUintn(Data[LoopVar*2+1]));
    213               }
    214               Status = gRT->SetVariable((CHAR16*)VariableName, &Guid, Attributes, StrLen(Data) / 2, Buffer);
    215             }
    216             if (EFI_ERROR(Status)) {
    217               ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SETVAR_ERROR_SET), gShellDebug1HiiHandle, L"setvar", &Guid, VariableName);
    218               ShellStatus = SHELL_ACCESS_DENIED;
    219             } else {
    220               ASSERT(ShellStatus == SHELL_SUCCESS);
    221             }
    222           }
    223         } else if (StrnCmp(Data, L"\"", 1) == 0) {
    224           //
    225           // ascii text
    226           //
    227           Data++;
    228           Buffer = AllocateZeroPool(StrSize(Data) / 2);
    229           if (Buffer == NULL) {
    230             Status = EFI_OUT_OF_RESOURCES;
    231           } else {
    232             AsciiSPrint(Buffer, StrSize(Data) / 2, "%s", Data);
    233             ((CHAR8*)Buffer)[AsciiStrLen(Buffer)-1] = CHAR_NULL;
    234             Status = gRT->SetVariable((CHAR16*)VariableName, &Guid, Attributes, AsciiStrSize(Buffer)-sizeof(CHAR8), Buffer);
    235           }
    236           if (EFI_ERROR(Status)) {
    237             ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SETVAR_ERROR_SET), gShellDebug1HiiHandle, L"setvar", &Guid, VariableName);
    238             ShellStatus = SHELL_ACCESS_DENIED;
    239           } else {
    240             ASSERT(ShellStatus == SHELL_SUCCESS);
    241           }
    242         } else if (StrnCmp(Data, L"L\"", 2) == 0) {
    243           //
    244           // ucs2 text
    245           //
    246           Data++;
    247           Data++;
    248           Buffer = AllocateZeroPool(StrSize(Data));
    249           if (Buffer == NULL) {
    250             ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellDebug1HiiHandle, L"setvar");
    251             ShellStatus = SHELL_OUT_OF_RESOURCES;
    252           } else {
    253             UnicodeSPrint(Buffer, StrSize(Data), L"%s", Data);
    254             ((CHAR16*)Buffer)[StrLen(Buffer)-1] = CHAR_NULL;
    255 
    256             Status = gRT->SetVariable((CHAR16*)VariableName, &Guid, Attributes, StrSize(Buffer)-sizeof(CHAR16), Buffer);
    257             if (EFI_ERROR(Status)) {
    258               ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SETVAR_ERROR_SET), gShellDebug1HiiHandle, L"setvar", &Guid, VariableName);
    259               ShellStatus = SHELL_ACCESS_DENIED;
    260             } else {
    261               ASSERT(ShellStatus == SHELL_SUCCESS);
    262             }
    263           }
    264         } else if (StrnCmp(Data, L"--", 2) == 0) {
    265           //
    266           // device path in text format
    267           //
    268           Data++;
    269           Data++;
    270           DevPath = ConvertTextToDevicePath(Data);
    271           if (DevPath == NULL) {
    272             ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SETVAR_ERROR_DPFT), gShellDebug1HiiHandle, L"setvar");
    273             ShellStatus = SHELL_INVALID_PARAMETER;
    274           } else {
    275             Status = gRT->SetVariable((CHAR16*)VariableName, &Guid, Attributes, GetDevicePathSize(DevPath), DevPath);
    276             if (EFI_ERROR(Status)) {
    277               ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SETVAR_ERROR_SET), gShellDebug1HiiHandle, L"setvar", &Guid, VariableName);
    278               ShellStatus = SHELL_ACCESS_DENIED;
    279             } else {
    280               ASSERT(ShellStatus == SHELL_SUCCESS);
    281             }
    282           }
    283         } else {
    284           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"setvar", Data);
    285           ShellStatus = SHELL_INVALID_PARAMETER;
    286         }
    287       }
    288     }
    289     ShellCommandLineFreeVarList (Package);
    290   }
    291 
    292   if (Buffer != NULL) {
    293     FreePool(Buffer);
    294   }
    295 
    296   if (DevPath != NULL) {
    297     FreePool(DevPath);
    298   }
    299 
    300   return (ShellStatus);
    301 }
    302