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