]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Application/Shell/ShellEnvVar.c
ShellPkg: Refactor string manipulation
[mirror_edk2.git] / ShellPkg / Application / Shell / ShellEnvVar.c
1 /** @file
2 function declarations for shell environment functions.
3
4 Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "Shell.h"
16
17 /**
18 Reports whether an environment variable is Volatile or Non-Volatile.
19
20 @param EnvVarName The name of the environment variable in question
21
22 @retval TRUE This environment variable is Volatile
23 @retval FALSE This environment variable is NON-Volatile
24 **/
25 BOOLEAN
26 EFIAPI
27 IsVolatileEnv (
28 IN CONST CHAR16 *EnvVarName
29 )
30 {
31 EFI_STATUS Status;
32 UINTN Size;
33 VOID *Buffer;
34 UINT32 Attribs;
35
36 Size = 0;
37 Buffer = NULL;
38
39 //
40 // get the variable
41 //
42 Status = gRT->GetVariable((CHAR16*)EnvVarName,
43 &gShellVariableGuid,
44 &Attribs,
45 &Size,
46 Buffer);
47 if (Status == EFI_BUFFER_TOO_SMALL) {
48 Buffer = AllocateZeroPool(Size);
49 ASSERT(Buffer != NULL);
50 Status = gRT->GetVariable((CHAR16*)EnvVarName,
51 &gShellVariableGuid,
52 &Attribs,
53 &Size,
54 Buffer);
55 FreePool(Buffer);
56 }
57 //
58 // not found means volatile
59 //
60 if (Status == EFI_NOT_FOUND) {
61 return (TRUE);
62 }
63 ASSERT_EFI_ERROR(Status);
64
65 //
66 // check for the Non Volatile bit
67 //
68 if ((Attribs & EFI_VARIABLE_NON_VOLATILE) == EFI_VARIABLE_NON_VOLATILE) {
69 return (FALSE);
70 }
71
72 //
73 // everything else is volatile
74 //
75 return (TRUE);
76 }
77
78 /**
79 free function for ENV_VAR_LIST objects.
80
81 @param[in] List The pointer to pointer to list.
82 **/
83 VOID
84 EFIAPI
85 FreeEnvironmentVariableList(
86 IN LIST_ENTRY *List
87 )
88 {
89 ENV_VAR_LIST *Node;
90
91 ASSERT (List != NULL);
92 if (List == NULL) {
93 return;
94 }
95
96 for ( Node = (ENV_VAR_LIST*)GetFirstNode(List)
97 ; !IsListEmpty(List)
98 ; Node = (ENV_VAR_LIST*)GetFirstNode(List)
99 ){
100 ASSERT(Node != NULL);
101 RemoveEntryList(&Node->Link);
102 if (Node->Key != NULL) {
103 FreePool(Node->Key);
104 }
105 if (Node->Val != NULL) {
106 FreePool(Node->Val);
107 }
108 FreePool(Node);
109 }
110 }
111
112 /**
113 Creates a list of all Shell-Guid-based environment variables.
114
115 @param[in, out] ListHead The pointer to pointer to LIST ENTRY object for
116 storing this list.
117
118 @retval EFI_SUCCESS the list was created sucessfully.
119 **/
120 EFI_STATUS
121 EFIAPI
122 GetEnvironmentVariableList(
123 IN OUT LIST_ENTRY *ListHead
124 )
125 {
126 CHAR16 *VariableName;
127 UINTN NameSize;
128 UINT64 MaxStorSize;
129 UINT64 RemStorSize;
130 UINT64 MaxVarSize;
131 EFI_STATUS Status;
132 EFI_GUID Guid;
133 UINTN ValSize;
134 ENV_VAR_LIST *VarList;
135
136 if (ListHead == NULL) {
137 return (EFI_INVALID_PARAMETER);
138 }
139
140 if (gRT->Hdr.Revision >= EFI_2_00_SYSTEM_TABLE_REVISION) {
141 Status = gRT->QueryVariableInfo(EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS, &MaxStorSize, &RemStorSize, &MaxVarSize);
142 if (EFI_ERROR(Status)) {
143 return (Status);
144 }
145 } else {
146 Status = EFI_SUCCESS;
147 MaxVarSize = 16384;
148 }
149
150 NameSize = (UINTN)MaxVarSize;
151 VariableName = AllocateZeroPool(NameSize);
152 if (VariableName == NULL) {
153 return (EFI_OUT_OF_RESOURCES);
154 }
155 *VariableName = CHAR_NULL;
156
157 while (!EFI_ERROR(Status)) {
158 NameSize = (UINTN)MaxVarSize;
159 Status = gRT->GetNextVariableName(&NameSize, VariableName, &Guid);
160 if (Status == EFI_NOT_FOUND){
161 Status = EFI_SUCCESS;
162 break;
163 }
164 if (!EFI_ERROR(Status) && CompareGuid(&Guid, &gShellVariableGuid)){
165 VarList = AllocateZeroPool(sizeof(ENV_VAR_LIST));
166 if (VarList == NULL) {
167 Status = EFI_OUT_OF_RESOURCES;
168 } else {
169 ValSize = 0;
170 Status = SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(VariableName, &VarList->Atts, &ValSize, VarList->Val);
171 if (Status == EFI_BUFFER_TOO_SMALL){
172 VarList->Val = AllocateZeroPool(ValSize);
173 if (VarList->Val == NULL) {
174 SHELL_FREE_NON_NULL(VarList);
175 Status = EFI_OUT_OF_RESOURCES;
176 } else {
177 Status = SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(VariableName, &VarList->Atts, &ValSize, VarList->Val);
178 }
179 }
180 if (!EFI_ERROR(Status) && VarList != NULL) {
181 VarList->Key = AllocateCopyPool(StrSize(VariableName), VariableName);
182 if (VarList->Key == NULL) {
183 SHELL_FREE_NON_NULL(VarList->Val);
184 SHELL_FREE_NON_NULL(VarList);
185 Status = EFI_OUT_OF_RESOURCES;
186 } else {
187 InsertTailList(ListHead, &VarList->Link);
188 }
189 }
190 }
191 } // compare guid
192 } // while
193 FreePool(VariableName);
194
195 if (EFI_ERROR(Status)) {
196 FreeEnvironmentVariableList(ListHead);
197 }
198
199 return (Status);
200 }
201
202 /**
203 Sets a list of all Shell-Guid-based environment variables. this will
204 also eliminate all existing shell environment variables (even if they
205 are not on the list).
206
207 This function will also deallocate the memory from List.
208
209 @param[in] ListHead The pointer to LIST_ENTRY from
210 GetShellEnvVarList().
211
212 @retval EFI_SUCCESS the list was Set sucessfully.
213 **/
214 EFI_STATUS
215 EFIAPI
216 SetEnvironmentVariableList(
217 IN LIST_ENTRY *ListHead
218 )
219 {
220 ENV_VAR_LIST VarList;
221 ENV_VAR_LIST *Node;
222 EFI_STATUS Status;
223 UINTN Size;
224
225 InitializeListHead(&VarList.Link);
226
227 //
228 // Delete all the current environment variables
229 //
230 Status = GetEnvironmentVariableList(&VarList.Link);
231 ASSERT_EFI_ERROR(Status);
232
233 for ( Node = (ENV_VAR_LIST*)GetFirstNode(&VarList.Link)
234 ; !IsNull(&VarList.Link, &Node->Link)
235 ; Node = (ENV_VAR_LIST*)GetNextNode(&VarList.Link, &Node->Link)
236 ){
237 if (Node->Key != NULL) {
238 Status = SHELL_DELETE_ENVIRONMENT_VARIABLE(Node->Key);
239 }
240 ASSERT_EFI_ERROR(Status);
241 }
242
243 FreeEnvironmentVariableList(&VarList.Link);
244
245 //
246 // set all the variables fron the list
247 //
248 for ( Node = (ENV_VAR_LIST*)GetFirstNode(ListHead)
249 ; !IsNull(ListHead, &Node->Link)
250 ; Node = (ENV_VAR_LIST*)GetNextNode(ListHead, &Node->Link)
251 ){
252 Size = StrSize(Node->Val);
253 if (Node->Atts & EFI_VARIABLE_NON_VOLATILE) {
254 Status = SHELL_SET_ENVIRONMENT_VARIABLE_NV(Node->Key, Size, Node->Val);
255 } else {
256 Status = SHELL_SET_ENVIRONMENT_VARIABLE_V (Node->Key, Size, Node->Val);
257 }
258 ASSERT_EFI_ERROR(Status);
259 }
260 FreeEnvironmentVariableList(ListHead);
261
262 return (Status);
263 }
264
265 /**
266 sets a list of all Shell-Guid-based environment variables.
267
268 @param Environment Points to a NULL-terminated array of environment
269 variables with the format 'x=y', where x is the
270 environment variable name and y is the value.
271
272 @retval EFI_SUCCESS The command executed successfully.
273 @retval EFI_INVALID_PARAMETER The parameter is invalid.
274 @retval EFI_OUT_OF_RESOURCES Out of resources.
275
276 @sa SetEnvironmentVariableList
277 **/
278 EFI_STATUS
279 EFIAPI
280 SetEnvironmentVariables(
281 IN CONST CHAR16 **Environment
282 )
283 {
284 CONST CHAR16 *CurrentString;
285 UINTN CurrentCount;
286 ENV_VAR_LIST *VarList;
287 ENV_VAR_LIST *Node;
288
289 VarList = NULL;
290
291 if (Environment == NULL) {
292 return (EFI_INVALID_PARAMETER);
293 }
294
295 //
296 // Build a list identical to the ones used for get/set list functions above
297 //
298 for ( CurrentCount = 0
299 ;
300 ; CurrentCount++
301 ){
302 CurrentString = Environment[CurrentCount];
303 if (CurrentString == NULL) {
304 break;
305 }
306 ASSERT(StrStr(CurrentString, L"=") != NULL);
307 Node = AllocateZeroPool(sizeof(ENV_VAR_LIST));
308 if (Node == NULL) {
309 SetEnvironmentVariableList(&VarList->Link);
310 return (EFI_OUT_OF_RESOURCES);
311 }
312
313 Node->Key = AllocateZeroPool((StrStr(CurrentString, L"=") - CurrentString + 1) * sizeof(CHAR16));
314 if (Node->Key == NULL) {
315 SHELL_FREE_NON_NULL(Node);
316 SetEnvironmentVariableList(&VarList->Link);
317 return (EFI_OUT_OF_RESOURCES);
318 }
319
320 //
321 // Copy the string into the Key, leaving the last character allocated as NULL to terminate
322 //
323 StrnCpy(Node->Key, CurrentString, StrStr(CurrentString, L"=") - CurrentString);
324
325 //
326 // ValueSize = TotalSize - already removed size - size for '=' + size for terminator (the last 2 items cancel each other)
327 //
328 Node->Val = AllocateCopyPool(StrSize(CurrentString) - StrSize(Node->Key), CurrentString + StrLen(Node->Key) + 1);
329 if (Node->Val == NULL) {
330 SHELL_FREE_NON_NULL(Node->Key);
331 SHELL_FREE_NON_NULL(Node);
332 SetEnvironmentVariableList(&VarList->Link);
333 return (EFI_OUT_OF_RESOURCES);
334 }
335
336 Node->Atts = EFI_VARIABLE_BOOTSERVICE_ACCESS;
337
338 if (VarList == NULL) {
339 VarList = AllocateZeroPool(sizeof(ENV_VAR_LIST));
340 if (VarList == NULL) {
341 SHELL_FREE_NON_NULL(Node->Key);
342 SHELL_FREE_NON_NULL(Node->Val);
343 SHELL_FREE_NON_NULL(Node);
344 return (EFI_OUT_OF_RESOURCES);
345 }
346 InitializeListHead(&VarList->Link);
347 }
348 InsertTailList(&VarList->Link, &Node->Link);
349
350 } // for loop
351
352 //
353 // set this new list as the set of all environment variables.
354 // this function also frees the memory and deletes all pre-existing
355 // shell-guid based environment variables.
356 //
357 return (SetEnvironmentVariableList(&VarList->Link));
358 }