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