]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - ShellPkg/Application/Shell/ShellEnvVar.c
ShellPkg: Move FindFirstCharacter/GetNextParameter to ShellCommandLib
[mirror_edk2.git] / ShellPkg / Application / Shell / ShellEnvVar.c
... / ...
CommitLineData
1/** @file\r
2 function declarations for shell environment functions.\r
3\r
4 Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>\r
5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "Shell.h"\r
16\r
17#define INIT_NAME_BUFFER_SIZE 128\r
18#define INIT_DATA_BUFFER_SIZE 1024\r
19\r
20//\r
21// The list is used to cache the environment variables.\r
22//\r
23ENV_VAR_LIST gShellEnvVarList;\r
24\r
25/**\r
26 Reports whether an environment variable is Volatile or Non-Volatile.\r
27\r
28 @param EnvVarName The name of the environment variable in question\r
29 @param Volatile Return TRUE if the environment variable is volatile\r
30\r
31 @retval EFI_SUCCESS The volatile attribute is returned successfully\r
32 @retval others Some errors happened.\r
33**/\r
34EFI_STATUS\r
35IsVolatileEnv (\r
36 IN CONST CHAR16 *EnvVarName,\r
37 OUT BOOLEAN *Volatile\r
38 )\r
39{\r
40 EFI_STATUS Status;\r
41 UINTN Size;\r
42 VOID *Buffer;\r
43 UINT32 Attribs;\r
44\r
45 ASSERT (Volatile != NULL);\r
46\r
47 Size = 0;\r
48 Buffer = NULL;\r
49\r
50 //\r
51 // get the variable\r
52 //\r
53 Status = gRT->GetVariable((CHAR16*)EnvVarName,\r
54 &gShellVariableGuid,\r
55 &Attribs,\r
56 &Size,\r
57 Buffer);\r
58 if (Status == EFI_BUFFER_TOO_SMALL) {\r
59 Buffer = AllocateZeroPool(Size);\r
60 if (Buffer == NULL) {\r
61 return EFI_OUT_OF_RESOURCES;\r
62 }\r
63 Status = gRT->GetVariable((CHAR16*)EnvVarName,\r
64 &gShellVariableGuid,\r
65 &Attribs,\r
66 &Size,\r
67 Buffer);\r
68 FreePool(Buffer);\r
69 }\r
70 //\r
71 // not found means volatile\r
72 //\r
73 if (Status == EFI_NOT_FOUND) {\r
74 *Volatile = TRUE;\r
75 return EFI_SUCCESS;\r
76 }\r
77 if (EFI_ERROR (Status)) {\r
78 return Status;\r
79 }\r
80\r
81 //\r
82 // check for the Non Volatile bit\r
83 //\r
84 *Volatile = !(BOOLEAN) ((Attribs & EFI_VARIABLE_NON_VOLATILE) == EFI_VARIABLE_NON_VOLATILE);\r
85 return EFI_SUCCESS;\r
86}\r
87\r
88/**\r
89 free function for ENV_VAR_LIST objects.\r
90\r
91 @param[in] List The pointer to pointer to list.\r
92**/\r
93VOID\r
94EFIAPI\r
95FreeEnvironmentVariableList(\r
96 IN LIST_ENTRY *List\r
97 )\r
98{\r
99 ENV_VAR_LIST *Node;\r
100\r
101 ASSERT (List != NULL);\r
102 if (List == NULL) {\r
103 return;\r
104 }\r
105\r
106 for ( Node = (ENV_VAR_LIST*)GetFirstNode(List)\r
107 ; !IsListEmpty(List)\r
108 ; Node = (ENV_VAR_LIST*)GetFirstNode(List)\r
109 ){\r
110 ASSERT(Node != NULL);\r
111 RemoveEntryList(&Node->Link);\r
112 if (Node->Key != NULL) {\r
113 FreePool(Node->Key);\r
114 }\r
115 if (Node->Val != NULL) {\r
116 FreePool(Node->Val);\r
117 }\r
118 FreePool(Node);\r
119 }\r
120}\r
121\r
122/**\r
123 Creates a list of all Shell-Guid-based environment variables.\r
124\r
125 @param[in, out] ListHead The pointer to pointer to LIST ENTRY object for\r
126 storing this list.\r
127\r
128 @retval EFI_SUCCESS the list was created sucessfully.\r
129**/\r
130EFI_STATUS\r
131EFIAPI\r
132GetEnvironmentVariableList(\r
133 IN OUT LIST_ENTRY *ListHead\r
134 )\r
135{\r
136 CHAR16 *VariableName;\r
137 UINTN NameSize;\r
138 UINTN NameBufferSize;\r
139 EFI_STATUS Status;\r
140 EFI_GUID Guid;\r
141 UINTN ValSize;\r
142 UINTN ValBufferSize;\r
143 ENV_VAR_LIST *VarList;\r
144\r
145 if (ListHead == NULL) {\r
146 return (EFI_INVALID_PARAMETER);\r
147 }\r
148 \r
149 Status = EFI_SUCCESS;\r
150 \r
151 ValBufferSize = INIT_DATA_BUFFER_SIZE;\r
152 NameBufferSize = INIT_NAME_BUFFER_SIZE;\r
153 VariableName = AllocateZeroPool(NameBufferSize);\r
154 if (VariableName == NULL) {\r
155 return (EFI_OUT_OF_RESOURCES);\r
156 }\r
157 *VariableName = CHAR_NULL;\r
158\r
159 while (!EFI_ERROR(Status)) {\r
160 NameSize = NameBufferSize;\r
161 Status = gRT->GetNextVariableName(&NameSize, VariableName, &Guid);\r
162 if (Status == EFI_NOT_FOUND){\r
163 Status = EFI_SUCCESS;\r
164 break;\r
165 } else if (Status == EFI_BUFFER_TOO_SMALL) {\r
166 NameBufferSize = NameSize > NameBufferSize * 2 ? NameSize : NameBufferSize * 2;\r
167 SHELL_FREE_NON_NULL(VariableName);\r
168 VariableName = AllocateZeroPool(NameBufferSize);\r
169 if (VariableName == NULL) {\r
170 Status = EFI_OUT_OF_RESOURCES;\r
171 break;\r
172 }\r
173 NameSize = NameBufferSize;\r
174 Status = gRT->GetNextVariableName(&NameSize, VariableName, &Guid);\r
175 }\r
176 \r
177 if (!EFI_ERROR(Status) && CompareGuid(&Guid, &gShellVariableGuid)){\r
178 VarList = AllocateZeroPool(sizeof(ENV_VAR_LIST));\r
179 if (VarList == NULL) {\r
180 Status = EFI_OUT_OF_RESOURCES;\r
181 } else {\r
182 ValSize = ValBufferSize;\r
183 VarList->Val = AllocateZeroPool(ValSize);\r
184 if (VarList->Val == NULL) {\r
185 SHELL_FREE_NON_NULL(VarList);\r
186 Status = EFI_OUT_OF_RESOURCES;\r
187 break;\r
188 }\r
189 Status = SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(VariableName, &VarList->Atts, &ValSize, VarList->Val);\r
190 if (Status == EFI_BUFFER_TOO_SMALL){\r
191 ValBufferSize = ValSize > ValBufferSize * 2 ? ValSize : ValBufferSize * 2;\r
192 SHELL_FREE_NON_NULL (VarList->Val);\r
193 VarList->Val = AllocateZeroPool(ValBufferSize);\r
194 if (VarList->Val == NULL) {\r
195 SHELL_FREE_NON_NULL(VarList);\r
196 Status = EFI_OUT_OF_RESOURCES;\r
197 break;\r
198 }\r
199 \r
200 ValSize = ValBufferSize;\r
201 Status = SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(VariableName, &VarList->Atts, &ValSize, VarList->Val);\r
202 }\r
203 if (!EFI_ERROR(Status)) {\r
204 VarList->Key = AllocateCopyPool(StrSize(VariableName), VariableName);\r
205 if (VarList->Key == NULL) {\r
206 SHELL_FREE_NON_NULL(VarList->Val);\r
207 SHELL_FREE_NON_NULL(VarList);\r
208 Status = EFI_OUT_OF_RESOURCES;\r
209 } else {\r
210 InsertTailList(ListHead, &VarList->Link);\r
211 }\r
212 } else {\r
213 SHELL_FREE_NON_NULL(VarList->Val);\r
214 SHELL_FREE_NON_NULL(VarList);\r
215 }\r
216 } // if (VarList == NULL) ... else ...\r
217 } // compare guid\r
218 } // while\r
219 SHELL_FREE_NON_NULL (VariableName);\r
220\r
221 if (EFI_ERROR(Status)) {\r
222 FreeEnvironmentVariableList(ListHead);\r
223 }\r
224\r
225 return (Status);\r
226}\r
227\r
228/**\r
229 Sets a list of all Shell-Guid-based environment variables. this will\r
230 also eliminate all existing shell environment variables (even if they\r
231 are not on the list).\r
232\r
233 This function will also deallocate the memory from List.\r
234\r
235 @param[in] ListHead The pointer to LIST_ENTRY from\r
236 GetShellEnvVarList().\r
237\r
238 @retval EFI_SUCCESS the list was Set sucessfully.\r
239**/\r
240EFI_STATUS\r
241EFIAPI\r
242SetEnvironmentVariableList(\r
243 IN LIST_ENTRY *ListHead\r
244 )\r
245{\r
246 ENV_VAR_LIST VarList;\r
247 ENV_VAR_LIST *Node;\r
248 EFI_STATUS Status;\r
249 UINTN Size;\r
250\r
251 InitializeListHead(&VarList.Link);\r
252\r
253 //\r
254 // Delete all the current environment variables\r
255 //\r
256 Status = GetEnvironmentVariableList(&VarList.Link);\r
257 ASSERT_EFI_ERROR(Status);\r
258\r
259 for ( Node = (ENV_VAR_LIST*)GetFirstNode(&VarList.Link)\r
260 ; !IsNull(&VarList.Link, &Node->Link)\r
261 ; Node = (ENV_VAR_LIST*)GetNextNode(&VarList.Link, &Node->Link)\r
262 ){\r
263 if (Node->Key != NULL) {\r
264 Status = SHELL_DELETE_ENVIRONMENT_VARIABLE(Node->Key);\r
265 }\r
266 ASSERT_EFI_ERROR(Status);\r
267 }\r
268\r
269 FreeEnvironmentVariableList(&VarList.Link);\r
270\r
271 //\r
272 // set all the variables fron the list\r
273 //\r
274 for ( Node = (ENV_VAR_LIST*)GetFirstNode(ListHead)\r
275 ; !IsNull(ListHead, &Node->Link)\r
276 ; Node = (ENV_VAR_LIST*)GetNextNode(ListHead, &Node->Link)\r
277 ){\r
278 Size = StrSize(Node->Val);\r
279 if (Node->Atts & EFI_VARIABLE_NON_VOLATILE) {\r
280 Status = SHELL_SET_ENVIRONMENT_VARIABLE_NV(Node->Key, Size, Node->Val);\r
281 } else {\r
282 Status = SHELL_SET_ENVIRONMENT_VARIABLE_V (Node->Key, Size, Node->Val);\r
283 }\r
284 ASSERT_EFI_ERROR(Status);\r
285 }\r
286 FreeEnvironmentVariableList(ListHead);\r
287\r
288 return (Status);\r
289}\r
290\r
291/**\r
292 sets a list of all Shell-Guid-based environment variables.\r
293\r
294 @param Environment Points to a NULL-terminated array of environment\r
295 variables with the format 'x=y', where x is the\r
296 environment variable name and y is the value.\r
297\r
298 @retval EFI_SUCCESS The command executed successfully.\r
299 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
300 @retval EFI_OUT_OF_RESOURCES Out of resources.\r
301\r
302 @sa SetEnvironmentVariableList\r
303**/\r
304EFI_STATUS\r
305EFIAPI\r
306SetEnvironmentVariables(\r
307 IN CONST CHAR16 **Environment\r
308 )\r
309{\r
310 CONST CHAR16 *CurrentString;\r
311 UINTN CurrentCount;\r
312 ENV_VAR_LIST *VarList;\r
313 ENV_VAR_LIST *Node;\r
314\r
315 VarList = NULL;\r
316\r
317 if (Environment == NULL) {\r
318 return (EFI_INVALID_PARAMETER);\r
319 }\r
320\r
321 //\r
322 // Build a list identical to the ones used for get/set list functions above\r
323 //\r
324 for ( CurrentCount = 0\r
325 ;\r
326 ; CurrentCount++\r
327 ){\r
328 CurrentString = Environment[CurrentCount];\r
329 if (CurrentString == NULL) {\r
330 break;\r
331 }\r
332 ASSERT(StrStr(CurrentString, L"=") != NULL);\r
333 Node = AllocateZeroPool(sizeof(ENV_VAR_LIST));\r
334 if (Node == NULL) {\r
335 SetEnvironmentVariableList(&VarList->Link);\r
336 return (EFI_OUT_OF_RESOURCES);\r
337 }\r
338\r
339 Node->Key = AllocateZeroPool((StrStr(CurrentString, L"=") - CurrentString + 1) * sizeof(CHAR16));\r
340 if (Node->Key == NULL) {\r
341 SHELL_FREE_NON_NULL(Node);\r
342 SetEnvironmentVariableList(&VarList->Link);\r
343 return (EFI_OUT_OF_RESOURCES);\r
344 }\r
345\r
346 //\r
347 // Copy the string into the Key, leaving the last character allocated as NULL to terminate\r
348 //\r
349 StrnCpyS( Node->Key, \r
350 StrStr(CurrentString, L"=") - CurrentString + 1, \r
351 CurrentString,\r
352 StrStr(CurrentString, L"=") - CurrentString\r
353 );\r
354\r
355 //\r
356 // ValueSize = TotalSize - already removed size - size for '=' + size for terminator (the last 2 items cancel each other)\r
357 //\r
358 Node->Val = AllocateCopyPool(StrSize(CurrentString) - StrSize(Node->Key), CurrentString + StrLen(Node->Key) + 1);\r
359 if (Node->Val == NULL) {\r
360 SHELL_FREE_NON_NULL(Node->Key);\r
361 SHELL_FREE_NON_NULL(Node);\r
362 SetEnvironmentVariableList(&VarList->Link);\r
363 return (EFI_OUT_OF_RESOURCES);\r
364 }\r
365\r
366 Node->Atts = EFI_VARIABLE_BOOTSERVICE_ACCESS;\r
367\r
368 if (VarList == NULL) {\r
369 VarList = AllocateZeroPool(sizeof(ENV_VAR_LIST));\r
370 if (VarList == NULL) {\r
371 SHELL_FREE_NON_NULL(Node->Key);\r
372 SHELL_FREE_NON_NULL(Node->Val);\r
373 SHELL_FREE_NON_NULL(Node);\r
374 return (EFI_OUT_OF_RESOURCES);\r
375 }\r
376 InitializeListHead(&VarList->Link);\r
377 }\r
378 InsertTailList(&VarList->Link, &Node->Link);\r
379\r
380 } // for loop\r
381\r
382 //\r
383 // set this new list as the set of all environment variables.\r
384 // this function also frees the memory and deletes all pre-existing\r
385 // shell-guid based environment variables.\r
386 //\r
387 return (SetEnvironmentVariableList(&VarList->Link));\r
388}\r
389\r
390/**\r
391 Find an environment variable in the gShellEnvVarList.\r
392\r
393 @param Key The name of the environment variable.\r
394 @param Value The value of the environment variable, the buffer\r
395 shoule be freed by the caller.\r
396 @param ValueSize The size in bytes of the environment variable\r
397 including the tailing CHAR_NELL.\r
398 @param Atts The attributes of the variable.\r
399\r
400 @retval EFI_SUCCESS The command executed successfully.\r
401 @retval EFI_NOT_FOUND The environment variable is not found in\r
402 gShellEnvVarList.\r
403\r
404**/\r
405EFI_STATUS\r
406ShellFindEnvVarInList (\r
407 IN CONST CHAR16 *Key,\r
408 OUT CHAR16 **Value,\r
409 OUT UINTN *ValueSize,\r
410 OUT UINT32 *Atts OPTIONAL\r
411 )\r
412{\r
413 ENV_VAR_LIST *Node;\r
414 \r
415 if (Key == NULL || Value == NULL || ValueSize == NULL) {\r
416 return SHELL_INVALID_PARAMETER;\r
417 }\r
418\r
419 for ( Node = (ENV_VAR_LIST*)GetFirstNode(&gShellEnvVarList.Link)\r
420 ; !IsNull(&gShellEnvVarList.Link, &Node->Link)\r
421 ; Node = (ENV_VAR_LIST*)GetNextNode(&gShellEnvVarList.Link, &Node->Link)\r
422 ){\r
423 if (Node->Key != NULL && StrCmp(Key, Node->Key) == 0) {\r
424 *Value = AllocateCopyPool(StrSize(Node->Val), Node->Val);\r
425 *ValueSize = StrSize(Node->Val);\r
426 if (Atts != NULL) {\r
427 *Atts = Node->Atts;\r
428 }\r
429 return EFI_SUCCESS;\r
430 }\r
431 }\r
432\r
433 return EFI_NOT_FOUND;\r
434}\r
435\r
436/**\r
437 Add an environment variable into gShellEnvVarList.\r
438\r
439 @param Key The name of the environment variable.\r
440 @param Value The value of environment variable.\r
441 @param ValueSize The size in bytes of the environment variable\r
442 including the tailing CHAR_NULL\r
443 @param Atts The attributes of the variable.\r
444\r
445 @retval EFI_SUCCESS The environment variable was added to list successfully.\r
446 @retval others Some errors happened.\r
447\r
448**/\r
449EFI_STATUS\r
450ShellAddEnvVarToList (\r
451 IN CONST CHAR16 *Key,\r
452 IN CONST CHAR16 *Value,\r
453 IN UINTN ValueSize,\r
454 IN UINT32 Atts\r
455 )\r
456{\r
457 ENV_VAR_LIST *Node;\r
458 CHAR16 *LocalKey;\r
459 CHAR16 *LocalValue;\r
460 \r
461 if (Key == NULL || Value == NULL || ValueSize == 0) {\r
462 return EFI_INVALID_PARAMETER;\r
463 }\r
464\r
465 LocalValue = AllocateCopyPool (ValueSize, Value);\r
466 if (LocalValue == NULL) {\r
467 return EFI_OUT_OF_RESOURCES;\r
468 }\r
469\r
470 //\r
471 // Update the variable value if it exists in gShellEnvVarList.\r
472 //\r
473 for ( Node = (ENV_VAR_LIST*)GetFirstNode(&gShellEnvVarList.Link)\r
474 ; !IsNull(&gShellEnvVarList.Link, &Node->Link)\r
475 ; Node = (ENV_VAR_LIST*)GetNextNode(&gShellEnvVarList.Link, &Node->Link)\r
476 ){\r
477 if (Node->Key != NULL && StrCmp(Key, Node->Key) == 0) {\r
478 Node->Atts = Atts;\r
479 SHELL_FREE_NON_NULL(Node->Val);\r
480 Node->Val = LocalValue;\r
481 return EFI_SUCCESS;\r
482 }\r
483 }\r
484\r
485 //\r
486 // If the environment varialbe key doesn't exist in list just insert\r
487 // a new node.\r
488 //\r
489 LocalKey = AllocateCopyPool (StrSize(Key), Key);\r
490 if (LocalKey == NULL) {\r
491 FreePool (LocalValue);\r
492 return EFI_OUT_OF_RESOURCES;\r
493 }\r
494 Node = (ENV_VAR_LIST*)AllocateZeroPool (sizeof(ENV_VAR_LIST));\r
495 if (Node == NULL) {\r
496 FreePool (LocalKey);\r
497 FreePool (LocalValue);\r
498 return EFI_OUT_OF_RESOURCES;\r
499 }\r
500 Node->Key = LocalKey;\r
501 Node->Val = LocalValue;\r
502 Node->Atts = Atts;\r
503 InsertTailList(&gShellEnvVarList.Link, &Node->Link);\r
504\r
505 return EFI_SUCCESS;\r
506}\r
507\r
508/**\r
509 Remove a specified environment variable in gShellEnvVarList.\r
510\r
511 @param Key The name of the environment variable.\r
512 \r
513 @retval EFI_SUCCESS The command executed successfully.\r
514 @retval EFI_NOT_FOUND The environment variable is not found in\r
515 gShellEnvVarList.\r
516**/\r
517EFI_STATUS\r
518ShellRemvoeEnvVarFromList (\r
519 IN CONST CHAR16 *Key\r
520 )\r
521{\r
522 ENV_VAR_LIST *Node;\r
523\r
524 if (Key == NULL) {\r
525 return EFI_INVALID_PARAMETER;\r
526 }\r
527\r
528 for ( Node = (ENV_VAR_LIST*)GetFirstNode(&gShellEnvVarList.Link)\r
529 ; !IsNull(&gShellEnvVarList.Link, &Node->Link)\r
530 ; Node = (ENV_VAR_LIST*)GetNextNode(&gShellEnvVarList.Link, &Node->Link)\r
531 ){\r
532 if (Node->Key != NULL && StrCmp(Key, Node->Key) == 0) {\r
533 SHELL_FREE_NON_NULL(Node->Key);\r
534 SHELL_FREE_NON_NULL(Node->Val);\r
535 RemoveEntryList(&Node->Link);\r
536 SHELL_FREE_NON_NULL(Node);\r
537 return EFI_SUCCESS;\r
538 }\r
539 }\r
540\r
541 return EFI_NOT_FOUND;\r
542}\r
543\r
544/**\r
545 Initialize the gShellEnvVarList and cache all Shell-Guid-based environment\r
546 variables.\r
547 \r
548**/\r
549EFI_STATUS\r
550ShellInitEnvVarList (\r
551 VOID\r
552 )\r
553{\r
554 EFI_STATUS Status;\r
555\r
556 InitializeListHead(&gShellEnvVarList.Link);\r
557 Status = GetEnvironmentVariableList (&gShellEnvVarList.Link);\r
558\r
559 return Status;\r
560}\r
561\r
562/**\r
563 Destructe the gShellEnvVarList.\r
564\r
565**/\r
566VOID\r
567ShellFreeEnvVarList (\r
568 VOID\r
569 )\r
570{\r
571 FreeEnvironmentVariableList (&gShellEnvVarList.Link);\r
572 InitializeListHead(&gShellEnvVarList.Link);\r
573\r
574 return;\r
575}\r
576\r