TianoCore EDK2 master
Loading...
Searching...
No Matches
ShellEnvVar.c
Go to the documentation of this file.
1
9#include "Shell.h"
10
11#define INIT_NAME_BUFFER_SIZE 128
12#define INIT_DATA_BUFFER_SIZE 1024
13
14//
15// The list is used to cache the environment variables.
16//
17ENV_VAR_LIST gShellEnvVarList;
18
30 IN CONST CHAR16 *EnvVarName,
31 OUT BOOLEAN *Volatile
32 )
33{
34 EFI_STATUS Status;
35 UINTN Size;
36 VOID *Buffer;
37 UINT32 Attribs;
38
39 ASSERT (Volatile != NULL);
40
41 Size = 0;
42 Buffer = NULL;
43
44 //
45 // get the variable
46 //
47 Status = gRT->GetVariable (
48 (CHAR16 *)EnvVarName,
49 &gShellVariableGuid,
50 &Attribs,
51 &Size,
52 Buffer
53 );
54 if (Status == EFI_BUFFER_TOO_SMALL) {
55 Buffer = AllocateZeroPool (Size);
56 if (Buffer == NULL) {
57 return EFI_OUT_OF_RESOURCES;
58 }
59
60 Status = gRT->GetVariable (
61 (CHAR16 *)EnvVarName,
62 &gShellVariableGuid,
63 &Attribs,
64 &Size,
65 Buffer
66 );
67 FreePool (Buffer);
68 }
69
70 //
71 // not found means volatile
72 //
73 if (Status == EFI_NOT_FOUND) {
74 *Volatile = TRUE;
75 return EFI_SUCCESS;
76 }
77
78 if (EFI_ERROR (Status)) {
79 return Status;
80 }
81
82 //
83 // check for the Non Volatile bit
84 //
85 *Volatile = !(BOOLEAN)((Attribs & EFI_VARIABLE_NON_VOLATILE) == EFI_VARIABLE_NON_VOLATILE);
86 return EFI_SUCCESS;
87}
88
94VOID
96 IN LIST_ENTRY *List
97 )
98{
99 ENV_VAR_LIST *Node;
100
101 ASSERT (List != NULL);
102 if (List == NULL) {
103 return;
104 }
105
106 for ( Node = (ENV_VAR_LIST *)GetFirstNode (List)
107 ; !IsListEmpty (List)
108 ; Node = (ENV_VAR_LIST *)GetFirstNode (List)
109 )
110 {
111 ASSERT (Node != NULL);
112 RemoveEntryList (&Node->Link);
113 if (Node->Key != NULL) {
114 FreePool (Node->Key);
115 }
116
117 if (Node->Val != NULL) {
118 FreePool (Node->Val);
119 }
120
121 FreePool (Node);
122 }
123}
124
135 IN OUT LIST_ENTRY *ListHead
136 )
137{
138 CHAR16 *VariableName;
139 UINTN NameSize;
140 UINTN NameBufferSize;
141 EFI_STATUS Status;
142 EFI_GUID Guid;
143 UINTN ValSize;
144 UINTN ValBufferSize;
145 ENV_VAR_LIST *VarList;
146
147 if (ListHead == NULL) {
148 return (EFI_INVALID_PARAMETER);
149 }
150
151 Status = EFI_SUCCESS;
152
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);
158 }
159
160 *VariableName = CHAR_NULL;
161
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;
167 break;
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;
174 break;
175 }
176
177 NameSize = NameBufferSize;
178 Status = gRT->GetNextVariableName (&NameSize, VariableName, &Guid);
179 }
180
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;
185 } else {
186 ValSize = ValBufferSize;
187 //
188 // We need another CHAR16 to save '\0' in VarList->Val.
189 //
190 VarList->Val = AllocateZeroPool (ValSize + sizeof (CHAR16));
191 if (VarList->Val == NULL) {
192 SHELL_FREE_NON_NULL (VarList);
193 Status = EFI_OUT_OF_RESOURCES;
194 break;
195 }
196
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);
201 //
202 // We need another CHAR16 to save '\0' in VarList->Val.
203 //
204 VarList->Val = AllocateZeroPool (ValBufferSize + sizeof (CHAR16));
205 if (VarList->Val == NULL) {
206 SHELL_FREE_NON_NULL (VarList);
207 Status = EFI_OUT_OF_RESOURCES;
208 break;
209 }
210
211 ValSize = ValBufferSize;
212 Status = SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES (VariableName, &VarList->Atts, &ValSize, VarList->Val);
213 }
214
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;
221 } else {
222 InsertTailList (ListHead, &VarList->Link);
223 }
224 } else {
225 SHELL_FREE_NON_NULL (VarList->Val);
226 SHELL_FREE_NON_NULL (VarList);
227 }
228 } // if (VarList == NULL) ... else ...
229 } // compare guid
230 } // while
231
232 SHELL_FREE_NON_NULL (VariableName);
233
234 if (EFI_ERROR (Status)) {
236 }
237
238 return (Status);
239}
240
255 IN LIST_ENTRY *ListHead
256 )
257{
258 ENV_VAR_LIST VarList;
259 ENV_VAR_LIST *Node;
260 EFI_STATUS Status;
261 UINTN Size;
262
263 InitializeListHead (&VarList.Link);
264
265 //
266 // Delete all the current environment variables
267 //
268 Status = GetEnvironmentVariableList (&VarList.Link);
269 ASSERT_EFI_ERROR (Status);
270
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)
274 )
275 {
276 if (Node->Key != NULL) {
277 Status = SHELL_DELETE_ENVIRONMENT_VARIABLE (Node->Key);
278 }
279
280 ASSERT_EFI_ERROR (Status);
281 }
282
283 FreeEnvironmentVariableList (&VarList.Link);
284
285 //
286 // set all the variables from the list
287 //
288 for ( Node = (ENV_VAR_LIST *)GetFirstNode (ListHead)
289 ; !IsNull (ListHead, &Node->Link)
290 ; Node = (ENV_VAR_LIST *)GetNextNode (ListHead, &Node->Link)
291 )
292 {
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);
296 } else {
297 Status = SHELL_SET_ENVIRONMENT_VARIABLE_V (Node->Key, Size, Node->Val);
298 }
299
300 ASSERT_EFI_ERROR (Status);
301 }
302
304
305 return (Status);
306}
307
323 IN CONST CHAR16 **Environment
324 )
325{
326 CONST CHAR16 *CurrentString;
327 UINTN CurrentCount;
328 ENV_VAR_LIST *VarList;
329 ENV_VAR_LIST *Node;
330
331 VarList = NULL;
332
333 if (Environment == NULL) {
334 return (EFI_INVALID_PARAMETER);
335 }
336
337 //
338 // Build a list identical to the ones used for get/set list functions above
339 //
340 for ( CurrentCount = 0
341 ;
342 ; CurrentCount++
343 )
344 {
345 CurrentString = Environment[CurrentCount];
346 if (CurrentString == NULL) {
347 break;
348 }
349
350 ASSERT (StrStr (CurrentString, L"=") != NULL);
351 Node = AllocateZeroPool (sizeof (ENV_VAR_LIST));
352 if (Node == NULL) {
353 SetEnvironmentVariableList (&VarList->Link);
354 return (EFI_OUT_OF_RESOURCES);
355 }
356
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);
362 }
363
364 //
365 // Copy the string into the Key, leaving the last character allocated as NULL to terminate
366 //
367 StrnCpyS (
368 Node->Key,
369 StrStr (CurrentString, L"=") - CurrentString + 1,
370 CurrentString,
371 StrStr (CurrentString, L"=") - CurrentString
372 );
373
374 //
375 // ValueSize = TotalSize - already removed size - size for '=' + size for terminator (the last 2 items cancel each other)
376 //
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);
383 }
384
385 Node->Atts = EFI_VARIABLE_BOOTSERVICE_ACCESS;
386
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);
394 }
395
396 InitializeListHead (&VarList->Link);
397 }
398
399 InsertTailList (&VarList->Link, &Node->Link);
400 } // for loop
401
402 //
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.
406 //
407 return (SetEnvironmentVariableList (&VarList->Link));
408}
409
427 IN CONST CHAR16 *Key,
428 OUT CHAR16 **Value,
429 OUT UINTN *ValueSize,
430 OUT UINT32 *Atts OPTIONAL
431 )
432{
433 ENV_VAR_LIST *Node;
434
435 if ((Key == NULL) || (Value == NULL) || (ValueSize == NULL)) {
437 }
438
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)
442 )
443 {
444 if ((Node->Key != NULL) && (StrCmp (Key, Node->Key) == 0)) {
445 *Value = AllocateCopyPool (StrSize (Node->Val), Node->Val);
446 *ValueSize = StrSize (Node->Val);
447 if (Atts != NULL) {
448 *Atts = Node->Atts;
449 }
450
451 return EFI_SUCCESS;
452 }
453 }
454
455 return EFI_NOT_FOUND;
456}
457
473 IN CONST CHAR16 *Key,
474 IN CONST CHAR16 *Value,
475 IN UINTN ValueSize,
476 IN UINT32 Atts
477 )
478{
479 ENV_VAR_LIST *Node;
480 CHAR16 *LocalKey;
481 CHAR16 *LocalValue;
482
483 if ((Key == NULL) || (Value == NULL) || (ValueSize == 0)) {
484 return EFI_INVALID_PARAMETER;
485 }
486
487 LocalValue = AllocateCopyPool (ValueSize, Value);
488 if (LocalValue == NULL) {
489 return EFI_OUT_OF_RESOURCES;
490 }
491
492 //
493 // Update the variable value if it exists in gShellEnvVarList.
494 //
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)
498 )
499 {
500 if ((Node->Key != NULL) && (StrCmp (Key, Node->Key) == 0)) {
501 Node->Atts = Atts;
502 SHELL_FREE_NON_NULL (Node->Val);
503 Node->Val = LocalValue;
504 return EFI_SUCCESS;
505 }
506 }
507
508 //
509 // If the environment variable key doesn't exist in list just insert
510 // a new node.
511 //
512 LocalKey = AllocateCopyPool (StrSize (Key), Key);
513 if (LocalKey == NULL) {
514 FreePool (LocalValue);
515 return EFI_OUT_OF_RESOURCES;
516 }
517
518 Node = (ENV_VAR_LIST *)AllocateZeroPool (sizeof (ENV_VAR_LIST));
519 if (Node == NULL) {
520 FreePool (LocalKey);
521 FreePool (LocalValue);
522 return EFI_OUT_OF_RESOURCES;
523 }
524
525 Node->Key = LocalKey;
526 Node->Val = LocalValue;
527 Node->Atts = Atts;
528 InsertTailList (&gShellEnvVarList.Link, &Node->Link);
529
530 return EFI_SUCCESS;
531}
532
544 IN CONST CHAR16 *Key
545 )
546{
547 ENV_VAR_LIST *Node;
548
549 if (Key == NULL) {
550 return EFI_INVALID_PARAMETER;
551 }
552
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)
556 )
557 {
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);
563 return EFI_SUCCESS;
564 }
565 }
566
567 return EFI_NOT_FOUND;
568}
569
577 VOID
578 )
579{
580 EFI_STATUS Status;
581
582 InitializeListHead (&gShellEnvVarList.Link);
583 Status = GetEnvironmentVariableList (&gShellEnvVarList.Link);
584
585 return Status;
586}
587
592VOID
594 VOID
595 )
596{
597 FreeEnvironmentVariableList (&gShellEnvVarList.Link);
598 InitializeListHead (&gShellEnvVarList.Link);
599
600 return;
601}
UINT64 UINTN
BOOLEAN EFIAPI IsNull(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:443
UINTN EFIAPI StrSize(IN CONST CHAR16 *String)
Definition: String.c:72
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
LIST_ENTRY *EFIAPI GetNextNode(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:333
INTN EFIAPI StrCmp(IN CONST CHAR16 *FirstString, IN CONST CHAR16 *SecondString)
Definition: String.c:109
LIST_ENTRY *EFIAPI GetFirstNode(IN CONST LIST_ENTRY *List)
Definition: LinkedList.c:298
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
Definition: LinkedList.c:590
LIST_ENTRY *EFIAPI InitializeListHead(IN OUT LIST_ENTRY *ListHead)
Definition: LinkedList.c:182
RETURN_STATUS EFIAPI StrnCpyS(OUT CHAR16 *Destination, IN UINTN DestMax, IN CONST CHAR16 *Source, IN UINTN Length)
Definition: SafeString.c:310
UINTN EFIAPI StrLen(IN CONST CHAR16 *String)
Definition: String.c:30
CHAR16 *EFIAPI StrStr(IN CONST CHAR16 *String, IN CONST CHAR16 *SearchString)
Definition: String.c:224
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:259
BOOLEAN EFIAPI CompareGuid(IN CONST GUID *Guid1, IN CONST GUID *Guid2)
Definition: MemLibGuid.c:73
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID *EFIAPI AllocateCopyPool(IN UINTN AllocationSize, IN CONST VOID *Buffer)
EFI_RUNTIME_SERVICES * gRT
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define TRUE
Definition: Base.h:301
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
@ SHELL_INVALID_PARAMETER
Definition: Shell.h:35
EFI_STATUS ShellFindEnvVarInList(IN CONST CHAR16 *Key, OUT CHAR16 **Value, OUT UINTN *ValueSize, OUT UINT32 *Atts OPTIONAL)
Definition: ShellEnvVar.c:426
EFI_STATUS ShellInitEnvVarList(VOID)
Definition: ShellEnvVar.c:576
EFI_STATUS IsVolatileEnv(IN CONST CHAR16 *EnvVarName, OUT BOOLEAN *Volatile)
Definition: ShellEnvVar.c:29
EFI_STATUS GetEnvironmentVariableList(IN OUT LIST_ENTRY *ListHead)
Definition: ShellEnvVar.c:134
EFI_STATUS ShellAddEnvVarToList(IN CONST CHAR16 *Key, IN CONST CHAR16 *Value, IN UINTN ValueSize, IN UINT32 Atts)
Definition: ShellEnvVar.c:472
EFI_STATUS ShellRemvoeEnvVarFromList(IN CONST CHAR16 *Key)
Definition: ShellEnvVar.c:543
VOID FreeEnvironmentVariableList(IN LIST_ENTRY *List)
Definition: ShellEnvVar.c:95
EFI_STATUS SetEnvironmentVariableList(IN LIST_ENTRY *ListHead)
Definition: ShellEnvVar.c:254
VOID ShellFreeEnvVarList(VOID)
Definition: ShellEnvVar.c:593
EFI_STATUS SetEnvironmentVariables(IN CONST CHAR16 **Environment)
Definition: ShellEnvVar.c:322
#define SHELL_SET_ENVIRONMENT_VARIABLE_NV(EnvVarName, BufferSize, Buffer)
Definition: ShellEnvVar.h:75
#define SHELL_DELETE_ENVIRONMENT_VARIABLE(EnvVarName)
Definition: ShellEnvVar.h:55
#define SHELL_SET_ENVIRONMENT_VARIABLE_V(EnvVarName, BufferSize, Buffer)
Definition: ShellEnvVar.h:136
#define SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(EnvVarName, Atts, BufferSize, Buffer)
Definition: ShellEnvVar.h:116
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
#define EFI_VARIABLE_NON_VOLATILE
Definition: Base.h:213