]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Application/Shell/ShellEnvVar.c
a8f177e6adae3dd7cc8100e589a6eb5bebbc3fe9
[mirror_edk2.git] / ShellPkg / Application / Shell / ShellEnvVar.c
1 /** @file
2 function declarations for shell environment functions.
3
4 Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "Shell.h"
16
17 #define INIT_NAME_BUFFER_SIZE 128
18 #define INIT_DATA_BUFFER_SIZE 1024
19
20 /**
21 Reports whether an environment variable is Volatile or Non-Volatile.
22
23 @param EnvVarName The name of the environment variable in question
24
25 @retval TRUE This environment variable is Volatile
26 @retval FALSE This environment variable is NON-Volatile
27 **/
28 BOOLEAN
29 EFIAPI
30 IsVolatileEnv (
31 IN CONST CHAR16 *EnvVarName
32 )
33 {
34 EFI_STATUS Status;
35 UINTN Size;
36 VOID *Buffer;
37 UINT32 Attribs;
38
39 Size = 0;
40 Buffer = NULL;
41
42 //
43 // get the variable
44 //
45 Status = gRT->GetVariable((CHAR16*)EnvVarName,
46 &gShellVariableGuid,
47 &Attribs,
48 &Size,
49 Buffer);
50 if (Status == EFI_BUFFER_TOO_SMALL) {
51 Buffer = AllocateZeroPool(Size);
52 ASSERT(Buffer != NULL);
53 Status = gRT->GetVariable((CHAR16*)EnvVarName,
54 &gShellVariableGuid,
55 &Attribs,
56 &Size,
57 Buffer);
58 FreePool(Buffer);
59 }
60 //
61 // not found means volatile
62 //
63 if (Status == EFI_NOT_FOUND) {
64 return (TRUE);
65 }
66 ASSERT_EFI_ERROR(Status);
67
68 //
69 // check for the Non Volatile bit
70 //
71 if ((Attribs & EFI_VARIABLE_NON_VOLATILE) == EFI_VARIABLE_NON_VOLATILE) {
72 return (FALSE);
73 }
74
75 //
76 // everything else is volatile
77 //
78 return (TRUE);
79 }
80
81 /**
82 free function for ENV_VAR_LIST objects.
83
84 @param[in] List The pointer to pointer to list.
85 **/
86 VOID
87 EFIAPI
88 FreeEnvironmentVariableList(
89 IN LIST_ENTRY *List
90 )
91 {
92 ENV_VAR_LIST *Node;
93
94 ASSERT (List != NULL);
95 if (List == NULL) {
96 return;
97 }
98
99 for ( Node = (ENV_VAR_LIST*)GetFirstNode(List)
100 ; !IsListEmpty(List)
101 ; Node = (ENV_VAR_LIST*)GetFirstNode(List)
102 ){
103 ASSERT(Node != NULL);
104 RemoveEntryList(&Node->Link);
105 if (Node->Key != NULL) {
106 FreePool(Node->Key);
107 }
108 if (Node->Val != NULL) {
109 FreePool(Node->Val);
110 }
111 FreePool(Node);
112 }
113 }
114
115 /**
116 Creates a list of all Shell-Guid-based environment variables.
117
118 @param[in, out] ListHead The pointer to pointer to LIST ENTRY object for
119 storing this list.
120
121 @retval EFI_SUCCESS the list was created sucessfully.
122 **/
123 EFI_STATUS
124 EFIAPI
125 GetEnvironmentVariableList(
126 IN OUT LIST_ENTRY *ListHead
127 )
128 {
129 CHAR16 *VariableName;
130 UINTN NameSize;
131 UINTN NameBufferSize;
132 EFI_STATUS Status;
133 EFI_GUID Guid;
134 UINTN ValSize;
135 UINTN ValBufferSize;
136 ENV_VAR_LIST *VarList;
137
138 if (ListHead == NULL) {
139 return (EFI_INVALID_PARAMETER);
140 }
141
142 Status = EFI_SUCCESS;
143
144 ValBufferSize = INIT_DATA_BUFFER_SIZE;
145 NameBufferSize = INIT_NAME_BUFFER_SIZE;
146 VariableName = AllocateZeroPool(NameBufferSize);
147 if (VariableName == NULL) {
148 return (EFI_OUT_OF_RESOURCES);
149 }
150 *VariableName = CHAR_NULL;
151
152 while (!EFI_ERROR(Status)) {
153 NameSize = NameBufferSize;
154 Status = gRT->GetNextVariableName(&NameSize, VariableName, &Guid);
155 if (Status == EFI_NOT_FOUND){
156 Status = EFI_SUCCESS;
157 break;
158 } else if (Status == EFI_BUFFER_TOO_SMALL) {
159 NameBufferSize = NameSize > NameBufferSize * 2 ? NameSize : NameBufferSize * 2;
160 SHELL_FREE_NON_NULL(VariableName);
161 VariableName = AllocateZeroPool(NameBufferSize);
162 if (VariableName == NULL) {
163 Status = EFI_OUT_OF_RESOURCES;
164 break;
165 }
166 NameSize = NameBufferSize;
167 Status = gRT->GetNextVariableName(&NameSize, VariableName, &Guid);
168 }
169
170 if (!EFI_ERROR(Status) && CompareGuid(&Guid, &gShellVariableGuid)){
171 VarList = AllocateZeroPool(sizeof(ENV_VAR_LIST));
172 if (VarList == NULL) {
173 Status = EFI_OUT_OF_RESOURCES;
174 } else {
175 ValSize = ValBufferSize;
176 VarList->Val = AllocateZeroPool(ValSize);
177 if (VarList->Val == NULL) {
178 SHELL_FREE_NON_NULL(VarList);
179 Status = EFI_OUT_OF_RESOURCES;
180 break;
181 }
182 Status = SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(VariableName, &VarList->Atts, &ValSize, VarList->Val);
183 if (Status == EFI_BUFFER_TOO_SMALL){
184 ValBufferSize = ValSize > ValBufferSize * 2 ? ValSize : ValBufferSize * 2;
185 SHELL_FREE_NON_NULL (VarList->Val);
186 VarList->Val = AllocateZeroPool(ValBufferSize);
187 if (VarList->Val == NULL) {
188 SHELL_FREE_NON_NULL(VarList);
189 Status = EFI_OUT_OF_RESOURCES;
190 break;
191 }
192
193 ValSize = ValBufferSize;
194 Status = SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(VariableName, &VarList->Atts, &ValSize, VarList->Val);
195 }
196 if (!EFI_ERROR(Status)) {
197 VarList->Key = AllocateCopyPool(StrSize(VariableName), VariableName);
198 if (VarList->Key == NULL) {
199 SHELL_FREE_NON_NULL(VarList->Val);
200 SHELL_FREE_NON_NULL(VarList);
201 Status = EFI_OUT_OF_RESOURCES;
202 } else {
203 InsertTailList(ListHead, &VarList->Link);
204 }
205 } else {
206 SHELL_FREE_NON_NULL(VarList->Val);
207 SHELL_FREE_NON_NULL(VarList);
208 }
209 } // if (VarList == NULL) ... else ...
210 } // compare guid
211 } // while
212 SHELL_FREE_NON_NULL (VariableName);
213
214 if (EFI_ERROR(Status)) {
215 FreeEnvironmentVariableList(ListHead);
216 }
217
218 return (Status);
219 }
220
221 /**
222 Sets a list of all Shell-Guid-based environment variables. this will
223 also eliminate all existing shell environment variables (even if they
224 are not on the list).
225
226 This function will also deallocate the memory from List.
227
228 @param[in] ListHead The pointer to LIST_ENTRY from
229 GetShellEnvVarList().
230
231 @retval EFI_SUCCESS the list was Set sucessfully.
232 **/
233 EFI_STATUS
234 EFIAPI
235 SetEnvironmentVariableList(
236 IN LIST_ENTRY *ListHead
237 )
238 {
239 ENV_VAR_LIST VarList;
240 ENV_VAR_LIST *Node;
241 EFI_STATUS Status;
242 UINTN Size;
243
244 InitializeListHead(&VarList.Link);
245
246 //
247 // Delete all the current environment variables
248 //
249 Status = GetEnvironmentVariableList(&VarList.Link);
250 ASSERT_EFI_ERROR(Status);
251
252 for ( Node = (ENV_VAR_LIST*)GetFirstNode(&VarList.Link)
253 ; !IsNull(&VarList.Link, &Node->Link)
254 ; Node = (ENV_VAR_LIST*)GetNextNode(&VarList.Link, &Node->Link)
255 ){
256 if (Node->Key != NULL) {
257 Status = SHELL_DELETE_ENVIRONMENT_VARIABLE(Node->Key);
258 }
259 ASSERT_EFI_ERROR(Status);
260 }
261
262 FreeEnvironmentVariableList(&VarList.Link);
263
264 //
265 // set all the variables fron the list
266 //
267 for ( Node = (ENV_VAR_LIST*)GetFirstNode(ListHead)
268 ; !IsNull(ListHead, &Node->Link)
269 ; Node = (ENV_VAR_LIST*)GetNextNode(ListHead, &Node->Link)
270 ){
271 Size = StrSize(Node->Val);
272 if (Node->Atts & EFI_VARIABLE_NON_VOLATILE) {
273 Status = SHELL_SET_ENVIRONMENT_VARIABLE_NV(Node->Key, Size, Node->Val);
274 } else {
275 Status = SHELL_SET_ENVIRONMENT_VARIABLE_V (Node->Key, Size, Node->Val);
276 }
277 ASSERT_EFI_ERROR(Status);
278 }
279 FreeEnvironmentVariableList(ListHead);
280
281 return (Status);
282 }
283
284 /**
285 sets a list of all Shell-Guid-based environment variables.
286
287 @param Environment Points to a NULL-terminated array of environment
288 variables with the format 'x=y', where x is the
289 environment variable name and y is the value.
290
291 @retval EFI_SUCCESS The command executed successfully.
292 @retval EFI_INVALID_PARAMETER The parameter is invalid.
293 @retval EFI_OUT_OF_RESOURCES Out of resources.
294
295 @sa SetEnvironmentVariableList
296 **/
297 EFI_STATUS
298 EFIAPI
299 SetEnvironmentVariables(
300 IN CONST CHAR16 **Environment
301 )
302 {
303 CONST CHAR16 *CurrentString;
304 UINTN CurrentCount;
305 ENV_VAR_LIST *VarList;
306 ENV_VAR_LIST *Node;
307
308 VarList = NULL;
309
310 if (Environment == NULL) {
311 return (EFI_INVALID_PARAMETER);
312 }
313
314 //
315 // Build a list identical to the ones used for get/set list functions above
316 //
317 for ( CurrentCount = 0
318 ;
319 ; CurrentCount++
320 ){
321 CurrentString = Environment[CurrentCount];
322 if (CurrentString == NULL) {
323 break;
324 }
325 ASSERT(StrStr(CurrentString, L"=") != NULL);
326 Node = AllocateZeroPool(sizeof(ENV_VAR_LIST));
327 if (Node == NULL) {
328 SetEnvironmentVariableList(&VarList->Link);
329 return (EFI_OUT_OF_RESOURCES);
330 }
331
332 Node->Key = AllocateZeroPool((StrStr(CurrentString, L"=") - CurrentString + 1) * sizeof(CHAR16));
333 if (Node->Key == NULL) {
334 SHELL_FREE_NON_NULL(Node);
335 SetEnvironmentVariableList(&VarList->Link);
336 return (EFI_OUT_OF_RESOURCES);
337 }
338
339 //
340 // Copy the string into the Key, leaving the last character allocated as NULL to terminate
341 //
342 StrnCpyS( Node->Key,
343 StrStr(CurrentString, L"=") - CurrentString + 1,
344 CurrentString,
345 StrStr(CurrentString, L"=") - CurrentString
346 );
347
348 //
349 // ValueSize = TotalSize - already removed size - size for '=' + size for terminator (the last 2 items cancel each other)
350 //
351 Node->Val = AllocateCopyPool(StrSize(CurrentString) - StrSize(Node->Key), CurrentString + StrLen(Node->Key) + 1);
352 if (Node->Val == NULL) {
353 SHELL_FREE_NON_NULL(Node->Key);
354 SHELL_FREE_NON_NULL(Node);
355 SetEnvironmentVariableList(&VarList->Link);
356 return (EFI_OUT_OF_RESOURCES);
357 }
358
359 Node->Atts = EFI_VARIABLE_BOOTSERVICE_ACCESS;
360
361 if (VarList == NULL) {
362 VarList = AllocateZeroPool(sizeof(ENV_VAR_LIST));
363 if (VarList == NULL) {
364 SHELL_FREE_NON_NULL(Node->Key);
365 SHELL_FREE_NON_NULL(Node->Val);
366 SHELL_FREE_NON_NULL(Node);
367 return (EFI_OUT_OF_RESOURCES);
368 }
369 InitializeListHead(&VarList->Link);
370 }
371 InsertTailList(&VarList->Link, &Node->Link);
372
373 } // for loop
374
375 //
376 // set this new list as the set of all environment variables.
377 // this function also frees the memory and deletes all pre-existing
378 // shell-guid based environment variables.
379 //
380 return (SetEnvironmentVariableList(&VarList->Link));
381 }