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