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