1 /** @file
2 *
3 *  Copyright (c) 2011, ARM Limited. All rights reserved.
4 *  (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
5 *
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 "Ebl.h"
17 
18 #include <Guid/GlobalVariable.h>
19 
20 EFI_STATUS
21 EFIAPI
EblGetCmd(IN UINTN Argc,IN CHAR8 ** Argv)22 EblGetCmd (
23   IN UINTN  Argc,
24   IN CHAR8  **Argv
25   )
26 {
27   EFI_STATUS        Status = EFI_INVALID_PARAMETER;
28   UINTN       Size;
29   VOID*       Value;
30   CHAR8*      AsciiVariableName = NULL;
31   CHAR16*     VariableName;
32   UINT32      Index;
33 
34   if (Argc == 1) {
35     AsciiPrint("Variable name is missing.\n");
36     return Status;
37   }
38 
39   for (Index = 1; Index < Argc; Index++) {
40     if (Argv[Index][0] == '-') {
41       AsciiPrint("Warning: '%a' not recognized.\n",Argv[Index]);
42     } else {
43       AsciiVariableName = Argv[Index];
44     }
45   }
46 
47   if (AsciiVariableName == NULL) {
48     AsciiPrint("Variable name is missing.\n");
49     return Status;
50   } else {
51     VariableName = AllocatePool((AsciiStrLen (AsciiVariableName) + 1) * sizeof (CHAR16));
52     AsciiStrToUnicodeStr (AsciiVariableName,VariableName);
53   }
54 
55   // Try to get the variable size.
56   Value = NULL;
57   Size = 0;
58   Status = gRT->GetVariable (VariableName, &gEfiGlobalVariableGuid, NULL, &Size, Value);
59   if (Status == EFI_NOT_FOUND) {
60     AsciiPrint("Variable name '%s' not found.\n",VariableName);
61   } else if (Status == EFI_BUFFER_TOO_SMALL) {
62     // Get the environment variable value
63     Value = AllocatePool (Size);
64     if (Value == NULL) {
65       return EFI_OUT_OF_RESOURCES;
66     }
67 
68     Status = gRT->GetVariable ((CHAR16 *)VariableName, &gEfiGlobalVariableGuid, NULL, &Size, Value);
69     if (EFI_ERROR (Status)) {
70       AsciiPrint("Error: '%r'\n",Status);
71     } else {
72       AsciiPrint("%a=%a\n",AsciiVariableName,Value);
73     }
74     FreePool(Value);
75   } else {
76     AsciiPrint("Error: '%r'\n",Status);
77   }
78 
79   FreePool(VariableName);
80   return Status;
81 }
82 
83 EFI_STATUS
84 EFIAPI
EblSetCmd(IN UINTN Argc,IN CHAR8 ** Argv)85 EblSetCmd (
86   IN UINTN  Argc,
87   IN CHAR8  **Argv
88   )
89 {
90   EFI_STATUS    Status = EFI_INVALID_PARAMETER;
91   CHAR8*        AsciiVariableSetting = NULL;
92   CHAR8*        AsciiVariableName;
93   CHAR8*        AsciiValue;
94   UINT32        AsciiValueLength;
95   CHAR16*       VariableName;
96   UINT32        Index;
97   UINT32        EscapedQuotes = 0;
98   BOOLEAN       Volatile = FALSE;
99 
100   if (Argc == 1) {
101     AsciiPrint("Variable name is missing.\n");
102     return Status;
103   }
104 
105   for (Index = 1; Index < Argc; Index++) {
106     if (AsciiStrCmp(Argv[Index],"-v") == 0) {
107       Volatile = 0;
108     } else if (Argv[Index][0] == '-') {
109       AsciiPrint("Warning: '%a' not recognized.\n",Argv[Index]);
110     } else {
111       AsciiVariableSetting = Argv[Index];
112     }
113   }
114 
115   if (AsciiVariableSetting == NULL) {
116     AsciiPrint("Variable name is missing.\n");
117     return Status;
118   }
119 
120   // Check if it is a valid variable setting
121   AsciiValue = AsciiStrStr (AsciiVariableSetting,"=");
122   if (AsciiValue == NULL) {
123     //
124     // There is no value. It means this variable will be deleted
125     //
126 
127     // Convert VariableName into Unicode
128     VariableName = AllocatePool((AsciiStrLen (AsciiVariableSetting) + 1) * sizeof (CHAR16));
129     AsciiStrToUnicodeStr (AsciiVariableSetting,VariableName);
130 
131     Status = gRT->SetVariable (
132                           VariableName,
133                           &gEfiGlobalVariableGuid,
134                           ( !Volatile ? EFI_VARIABLE_NON_VOLATILE : 0) |
135                           EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
136                           0,
137                           NULL
138                           );
139     if (!EFI_ERROR(Status)) {
140       AsciiPrint("Variable '%s' deleted\n",VariableName);
141     } else {
142       AsciiPrint("Variable setting is incorrect. It should be VariableName=Value\n");
143     }
144     return Status;
145   }
146 
147   AsciiValue[0] = '\0';
148   AsciiVariableName = AsciiVariableSetting;
149   AsciiValue++;
150 
151   // Clean AsciiValue from quote
152   if (AsciiValue[0] == '"') {
153     AsciiValue++;
154   }
155   AsciiValueLength = AsciiStrLen (AsciiValue);
156   if ((AsciiValue[AsciiValueLength-2] != '\\') && (AsciiValue[AsciiValueLength-1] == '"')) {
157     AsciiValue[AsciiValueLength-1] = '\0';
158   }
159 
160   // Clean AsciiValue from escaped quotes
161   for (Index = 0; Index < AsciiValueLength; Index++) {
162     if ((Index > 0) && (AsciiValue[Index-1] == '\\') && (AsciiValue[Index] == '"')) {
163       EscapedQuotes++;
164     }
165     AsciiValue[Index-EscapedQuotes] = AsciiValue[Index];
166   }
167   // Fill the end of the value with '\0'
168   for (Index = 0; Index < EscapedQuotes; Index++) {
169     AsciiValue[AsciiValueLength-1-Index] = '\0';
170   }
171 
172   // Convert VariableName into Unicode
173   VariableName = AllocatePool((AsciiStrLen (AsciiVariableName) + 1) * sizeof (CHAR16));
174   AsciiStrToUnicodeStr (AsciiVariableName,VariableName);
175 
176   Status = gRT->SetVariable (
177                       VariableName,
178                       &gEfiGlobalVariableGuid,
179                       ( !Volatile ? EFI_VARIABLE_NON_VOLATILE : 0) |
180                       EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
181                       AsciiStrLen (AsciiValue)+1,
182                       AsciiValue
183                       );
184   if (!EFI_ERROR(Status)) {
185     AsciiPrint("'%a'='%a'\n",AsciiVariableName,AsciiValue);
186   }
187 
188   return Status;
189 }
190 
191 GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdVariableTemplate[] =
192 {
193   {
194     "get",
195     " ; get UEFI variable\n\r   [v]; verbose",
196     NULL,
197     EblGetCmd
198   },
199   {
200     "set",
201     " ; set UEFI variable\n\r   [v]; create volatile variable",
202     NULL,
203     EblSetCmd
204   }
205 };
206 
207 /**
208   Initialize the commands in this in this file
209 **/
210 VOID
EblInitializeVariableCmds(VOID)211 EblInitializeVariableCmds (
212   VOID
213   )
214 {
215   EblAddCommands (mCmdVariableTemplate, sizeof (mCmdVariableTemplate)/sizeof (EBL_COMMAND_TABLE));
216 }
217