2 function declarations for shell environment functions.
4 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
11 #define INIT_NAME_BUFFER_SIZE 128
12 #define INIT_DATA_BUFFER_SIZE 1024
15 // The list is used to cache the environment variables.
17 ENV_VAR_LIST gShellEnvVarList
;
20 Reports whether an environment variable is Volatile or Non-Volatile.
22 @param EnvVarName The name of the environment variable in question
23 @param Volatile Return TRUE if the environment variable is volatile
25 @retval EFI_SUCCESS The volatile attribute is returned successfully
26 @retval others Some errors happened.
30 IN CONST CHAR16
*EnvVarName
,
39 ASSERT (Volatile
!= NULL
);
47 Status
= gRT
->GetVariable (
54 if (Status
== EFI_BUFFER_TOO_SMALL
) {
55 Buffer
= AllocateZeroPool (Size
);
57 return EFI_OUT_OF_RESOURCES
;
60 Status
= gRT
->GetVariable (
71 // not found means volatile
73 if (Status
== EFI_NOT_FOUND
) {
78 if (EFI_ERROR (Status
)) {
83 // check for the Non Volatile bit
85 *Volatile
= !(BOOLEAN
)((Attribs
& EFI_VARIABLE_NON_VOLATILE
) == EFI_VARIABLE_NON_VOLATILE
);
90 free function for ENV_VAR_LIST objects.
92 @param[in] List The pointer to pointer to list.
95 FreeEnvironmentVariableList (
101 ASSERT (List
!= NULL
);
106 for ( Node
= (ENV_VAR_LIST
*)GetFirstNode (List
)
107 ; !IsListEmpty (List
)
108 ; Node
= (ENV_VAR_LIST
*)GetFirstNode (List
)
111 ASSERT (Node
!= NULL
);
112 RemoveEntryList (&Node
->Link
);
113 if (Node
->Key
!= NULL
) {
114 FreePool (Node
->Key
);
117 if (Node
->Val
!= NULL
) {
118 FreePool (Node
->Val
);
126 Creates a list of all Shell-Guid-based environment variables.
128 @param[in, out] ListHead The pointer to pointer to LIST ENTRY object for
131 @retval EFI_SUCCESS the list was created successfully.
134 GetEnvironmentVariableList (
135 IN OUT LIST_ENTRY
*ListHead
138 CHAR16
*VariableName
;
140 UINTN NameBufferSize
;
145 ENV_VAR_LIST
*VarList
;
147 if (ListHead
== NULL
) {
148 return (EFI_INVALID_PARAMETER
);
151 Status
= EFI_SUCCESS
;
153 ValBufferSize
= INIT_DATA_BUFFER_SIZE
;
154 NameBufferSize
= INIT_NAME_BUFFER_SIZE
;
155 VariableName
= AllocateZeroPool (NameBufferSize
);
156 if (VariableName
== NULL
) {
157 return (EFI_OUT_OF_RESOURCES
);
160 *VariableName
= CHAR_NULL
;
162 while (!EFI_ERROR (Status
)) {
163 NameSize
= NameBufferSize
;
164 Status
= gRT
->GetNextVariableName (&NameSize
, VariableName
, &Guid
);
165 if (Status
== EFI_NOT_FOUND
) {
166 Status
= EFI_SUCCESS
;
168 } else if (Status
== EFI_BUFFER_TOO_SMALL
) {
169 NameBufferSize
= NameSize
> NameBufferSize
* 2 ? NameSize
: NameBufferSize
* 2;
170 SHELL_FREE_NON_NULL (VariableName
);
171 VariableName
= AllocateZeroPool (NameBufferSize
);
172 if (VariableName
== NULL
) {
173 Status
= EFI_OUT_OF_RESOURCES
;
177 NameSize
= NameBufferSize
;
178 Status
= gRT
->GetNextVariableName (&NameSize
, VariableName
, &Guid
);
181 if (!EFI_ERROR (Status
) && CompareGuid (&Guid
, &gShellVariableGuid
)) {
182 VarList
= AllocateZeroPool (sizeof (ENV_VAR_LIST
));
183 if (VarList
== NULL
) {
184 Status
= EFI_OUT_OF_RESOURCES
;
186 ValSize
= ValBufferSize
;
188 // We need another CHAR16 to save '\0' in VarList->Val.
190 VarList
->Val
= AllocateZeroPool (ValSize
+ sizeof (CHAR16
));
191 if (VarList
->Val
== NULL
) {
192 SHELL_FREE_NON_NULL (VarList
);
193 Status
= EFI_OUT_OF_RESOURCES
;
197 Status
= SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES (VariableName
, &VarList
->Atts
, &ValSize
, VarList
->Val
);
198 if (Status
== EFI_BUFFER_TOO_SMALL
) {
199 ValBufferSize
= ValSize
> ValBufferSize
* 2 ? ValSize
: ValBufferSize
* 2;
200 SHELL_FREE_NON_NULL (VarList
->Val
);
202 // We need another CHAR16 to save '\0' in VarList->Val.
204 VarList
->Val
= AllocateZeroPool (ValBufferSize
+ sizeof (CHAR16
));
205 if (VarList
->Val
== NULL
) {
206 SHELL_FREE_NON_NULL (VarList
);
207 Status
= EFI_OUT_OF_RESOURCES
;
211 ValSize
= ValBufferSize
;
212 Status
= SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES (VariableName
, &VarList
->Atts
, &ValSize
, VarList
->Val
);
215 if (!EFI_ERROR (Status
)) {
216 VarList
->Key
= AllocateCopyPool (StrSize (VariableName
), VariableName
);
217 if (VarList
->Key
== NULL
) {
218 SHELL_FREE_NON_NULL (VarList
->Val
);
219 SHELL_FREE_NON_NULL (VarList
);
220 Status
= EFI_OUT_OF_RESOURCES
;
222 InsertTailList (ListHead
, &VarList
->Link
);
225 SHELL_FREE_NON_NULL (VarList
->Val
);
226 SHELL_FREE_NON_NULL (VarList
);
228 } // if (VarList == NULL) ... else ...
232 SHELL_FREE_NON_NULL (VariableName
);
234 if (EFI_ERROR (Status
)) {
235 FreeEnvironmentVariableList (ListHead
);
242 Sets a list of all Shell-Guid-based environment variables. this will
243 also eliminate all existing shell environment variables (even if they
244 are not on the list).
246 This function will also deallocate the memory from List.
248 @param[in] ListHead The pointer to LIST_ENTRY from
249 GetShellEnvVarList().
251 @retval EFI_SUCCESS the list was Set successfully.
254 SetEnvironmentVariableList (
255 IN LIST_ENTRY
*ListHead
258 ENV_VAR_LIST VarList
;
263 InitializeListHead (&VarList
.Link
);
266 // Delete all the current environment variables
268 Status
= GetEnvironmentVariableList (&VarList
.Link
);
269 ASSERT_EFI_ERROR (Status
);
271 for ( Node
= (ENV_VAR_LIST
*)GetFirstNode (&VarList
.Link
)
272 ; !IsNull (&VarList
.Link
, &Node
->Link
)
273 ; Node
= (ENV_VAR_LIST
*)GetNextNode (&VarList
.Link
, &Node
->Link
)
276 if (Node
->Key
!= NULL
) {
277 Status
= SHELL_DELETE_ENVIRONMENT_VARIABLE (Node
->Key
);
280 ASSERT_EFI_ERROR (Status
);
283 FreeEnvironmentVariableList (&VarList
.Link
);
286 // set all the variables from the list
288 for ( Node
= (ENV_VAR_LIST
*)GetFirstNode (ListHead
)
289 ; !IsNull (ListHead
, &Node
->Link
)
290 ; Node
= (ENV_VAR_LIST
*)GetNextNode (ListHead
, &Node
->Link
)
293 Size
= StrSize (Node
->Val
) - sizeof (CHAR16
);
294 if (Node
->Atts
& EFI_VARIABLE_NON_VOLATILE
) {
295 Status
= SHELL_SET_ENVIRONMENT_VARIABLE_NV (Node
->Key
, Size
, Node
->Val
);
297 Status
= SHELL_SET_ENVIRONMENT_VARIABLE_V (Node
->Key
, Size
, Node
->Val
);
300 ASSERT_EFI_ERROR (Status
);
303 FreeEnvironmentVariableList (ListHead
);
309 sets a list of all Shell-Guid-based environment variables.
311 @param Environment Points to a NULL-terminated array of environment
312 variables with the format 'x=y', where x is the
313 environment variable name and y is the value.
315 @retval EFI_SUCCESS The command executed successfully.
316 @retval EFI_INVALID_PARAMETER The parameter is invalid.
317 @retval EFI_OUT_OF_RESOURCES Out of resources.
319 @sa SetEnvironmentVariableList
322 SetEnvironmentVariables (
323 IN CONST CHAR16
**Environment
326 CONST CHAR16
*CurrentString
;
328 ENV_VAR_LIST
*VarList
;
333 if (Environment
== NULL
) {
334 return (EFI_INVALID_PARAMETER
);
338 // Build a list identical to the ones used for get/set list functions above
340 for ( CurrentCount
= 0
345 CurrentString
= Environment
[CurrentCount
];
346 if (CurrentString
== NULL
) {
350 ASSERT (StrStr (CurrentString
, L
"=") != NULL
);
351 Node
= AllocateZeroPool (sizeof (ENV_VAR_LIST
));
353 SetEnvironmentVariableList (&VarList
->Link
);
354 return (EFI_OUT_OF_RESOURCES
);
357 Node
->Key
= AllocateZeroPool ((StrStr (CurrentString
, L
"=") - CurrentString
+ 1) * sizeof (CHAR16
));
358 if (Node
->Key
== NULL
) {
359 SHELL_FREE_NON_NULL (Node
);
360 SetEnvironmentVariableList (&VarList
->Link
);
361 return (EFI_OUT_OF_RESOURCES
);
365 // Copy the string into the Key, leaving the last character allocated as NULL to terminate
369 StrStr (CurrentString
, L
"=") - CurrentString
+ 1,
371 StrStr (CurrentString
, L
"=") - CurrentString
375 // ValueSize = TotalSize - already removed size - size for '=' + size for terminator (the last 2 items cancel each other)
377 Node
->Val
= AllocateCopyPool (StrSize (CurrentString
) - StrSize (Node
->Key
), CurrentString
+ StrLen (Node
->Key
) + 1);
378 if (Node
->Val
== NULL
) {
379 SHELL_FREE_NON_NULL (Node
->Key
);
380 SHELL_FREE_NON_NULL (Node
);
381 SetEnvironmentVariableList (&VarList
->Link
);
382 return (EFI_OUT_OF_RESOURCES
);
385 Node
->Atts
= EFI_VARIABLE_BOOTSERVICE_ACCESS
;
387 if (VarList
== NULL
) {
388 VarList
= AllocateZeroPool (sizeof (ENV_VAR_LIST
));
389 if (VarList
== NULL
) {
390 SHELL_FREE_NON_NULL (Node
->Key
);
391 SHELL_FREE_NON_NULL (Node
->Val
);
392 SHELL_FREE_NON_NULL (Node
);
393 return (EFI_OUT_OF_RESOURCES
);
396 InitializeListHead (&VarList
->Link
);
399 InsertTailList (&VarList
->Link
, &Node
->Link
);
403 // set this new list as the set of all environment variables.
404 // this function also frees the memory and deletes all pre-existing
405 // shell-guid based environment variables.
407 return (SetEnvironmentVariableList (&VarList
->Link
));
411 Find an environment variable in the gShellEnvVarList.
413 @param Key The name of the environment variable.
414 @param Value The value of the environment variable, the buffer
415 shoule be freed by the caller.
416 @param ValueSize The size in bytes of the environment variable
417 including the tailing CHAR_NELL.
418 @param Atts The attributes of the variable.
420 @retval EFI_SUCCESS The command executed successfully.
421 @retval EFI_NOT_FOUND The environment variable is not found in
426 ShellFindEnvVarInList (
427 IN CONST CHAR16
*Key
,
429 OUT UINTN
*ValueSize
,
430 OUT UINT32
*Atts OPTIONAL
435 if ((Key
== NULL
) || (Value
== NULL
) || (ValueSize
== NULL
)) {
436 return SHELL_INVALID_PARAMETER
;
439 for ( Node
= (ENV_VAR_LIST
*)GetFirstNode (&gShellEnvVarList
.Link
)
440 ; !IsNull (&gShellEnvVarList
.Link
, &Node
->Link
)
441 ; Node
= (ENV_VAR_LIST
*)GetNextNode (&gShellEnvVarList
.Link
, &Node
->Link
)
444 if ((Node
->Key
!= NULL
) && (StrCmp (Key
, Node
->Key
) == 0)) {
445 *Value
= AllocateCopyPool (StrSize (Node
->Val
), Node
->Val
);
446 *ValueSize
= StrSize (Node
->Val
);
455 return EFI_NOT_FOUND
;
459 Add an environment variable into gShellEnvVarList.
461 @param Key The name of the environment variable.
462 @param Value The value of environment variable.
463 @param ValueSize The size in bytes of the environment variable
464 including the tailing CHAR_NULL
465 @param Atts The attributes of the variable.
467 @retval EFI_SUCCESS The environment variable was added to list successfully.
468 @retval others Some errors happened.
472 ShellAddEnvVarToList (
473 IN CONST CHAR16
*Key
,
474 IN CONST CHAR16
*Value
,
483 if ((Key
== NULL
) || (Value
== NULL
) || (ValueSize
== 0)) {
484 return EFI_INVALID_PARAMETER
;
487 LocalValue
= AllocateCopyPool (ValueSize
, Value
);
488 if (LocalValue
== NULL
) {
489 return EFI_OUT_OF_RESOURCES
;
493 // Update the variable value if it exists in gShellEnvVarList.
495 for ( Node
= (ENV_VAR_LIST
*)GetFirstNode (&gShellEnvVarList
.Link
)
496 ; !IsNull (&gShellEnvVarList
.Link
, &Node
->Link
)
497 ; Node
= (ENV_VAR_LIST
*)GetNextNode (&gShellEnvVarList
.Link
, &Node
->Link
)
500 if ((Node
->Key
!= NULL
) && (StrCmp (Key
, Node
->Key
) == 0)) {
502 SHELL_FREE_NON_NULL (Node
->Val
);
503 Node
->Val
= LocalValue
;
509 // If the environment variable key doesn't exist in list just insert
512 LocalKey
= AllocateCopyPool (StrSize (Key
), Key
);
513 if (LocalKey
== NULL
) {
514 FreePool (LocalValue
);
515 return EFI_OUT_OF_RESOURCES
;
518 Node
= (ENV_VAR_LIST
*)AllocateZeroPool (sizeof (ENV_VAR_LIST
));
521 FreePool (LocalValue
);
522 return EFI_OUT_OF_RESOURCES
;
525 Node
->Key
= LocalKey
;
526 Node
->Val
= LocalValue
;
528 InsertTailList (&gShellEnvVarList
.Link
, &Node
->Link
);
534 Remove a specified environment variable in gShellEnvVarList.
536 @param Key The name of the environment variable.
538 @retval EFI_SUCCESS The command executed successfully.
539 @retval EFI_NOT_FOUND The environment variable is not found in
543 ShellRemvoeEnvVarFromList (
550 return EFI_INVALID_PARAMETER
;
553 for ( Node
= (ENV_VAR_LIST
*)GetFirstNode (&gShellEnvVarList
.Link
)
554 ; !IsNull (&gShellEnvVarList
.Link
, &Node
->Link
)
555 ; Node
= (ENV_VAR_LIST
*)GetNextNode (&gShellEnvVarList
.Link
, &Node
->Link
)
558 if ((Node
->Key
!= NULL
) && (StrCmp (Key
, Node
->Key
) == 0)) {
559 SHELL_FREE_NON_NULL (Node
->Key
);
560 SHELL_FREE_NON_NULL (Node
->Val
);
561 RemoveEntryList (&Node
->Link
);
562 SHELL_FREE_NON_NULL (Node
);
567 return EFI_NOT_FOUND
;
571 Initialize the gShellEnvVarList and cache all Shell-Guid-based environment
576 ShellInitEnvVarList (
582 InitializeListHead (&gShellEnvVarList
.Link
);
583 Status
= GetEnvironmentVariableList (&gShellEnvVarList
.Link
);
589 Destructe the gShellEnvVarList.
593 ShellFreeEnvVarList (
597 FreeEnvironmentVariableList (&gShellEnvVarList
.Link
);
598 InitializeListHead (&gShellEnvVarList
.Link
);