1a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey/** @file
2a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  function declarations for shell environment functions.
3a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
4654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin  Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
5a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  This program and the accompanying materials
6a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  are licensed and made available under the terms and conditions of the BSD License
7a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  which accompanies this distribution.  The full text of the license may be found at
8a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  http://opensource.org/licenses/bsd-license.php
9a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
10a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
13a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey**/
14a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
150406a5717b3b3760a7bf6b5cc1a5efe7aa7a76b1jcarsey#include "Shell.h"
16a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
17654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin#define INIT_NAME_BUFFER_SIZE  128
18654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin#define INIT_DATA_BUFFER_SIZE  1024
19654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin
20a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey/**
21a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  Reports whether an environment variable is Volatile or Non-Volatile.
22a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
23a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  @param EnvVarName             The name of the environment variable in question
24a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
25a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  @retval TRUE                  This environment variable is Volatile
26a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  @retval FALSE                 This environment variable is NON-Volatile
27a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey**/
28a405b86d274d32b92f69842bfb9a1ab143128f57jcarseyBOOLEAN
29a405b86d274d32b92f69842bfb9a1ab143128f57jcarseyEFIAPI
30a405b86d274d32b92f69842bfb9a1ab143128f57jcarseyIsVolatileEnv (
31a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  IN CONST CHAR16 *EnvVarName
32a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  )
33a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey{
34a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  EFI_STATUS  Status;
35a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  UINTN       Size;
36a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  VOID        *Buffer;
37a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  UINT32      Attribs;
38a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
39a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  Size = 0;
40a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  Buffer = NULL;
41a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
42a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  //
43a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  // get the variable
44a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  //
45a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  Status = gRT->GetVariable((CHAR16*)EnvVarName,
46a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey                            &gShellVariableGuid,
47a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey                            &Attribs,
48a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey                            &Size,
49a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey                            Buffer);
50a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  if (Status == EFI_BUFFER_TOO_SMALL) {
51733f138d84a25a5993bc32ffe016c364daba686cjcarsey    Buffer = AllocateZeroPool(Size);
52a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    ASSERT(Buffer != NULL);
53a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    Status = gRT->GetVariable((CHAR16*)EnvVarName,
54a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey                              &gShellVariableGuid,
55a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey                              &Attribs,
56a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey                              &Size,
57a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey                              Buffer);
58a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    FreePool(Buffer);
59a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  }
60a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  //
61a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  // not found means volatile
62a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  //
63a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  if (Status == EFI_NOT_FOUND) {
64a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    return (TRUE);
65a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  }
66a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  ASSERT_EFI_ERROR(Status);
67a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
68a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  //
69a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  // check for the Non Volatile bit
70a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  //
71a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  if ((Attribs & EFI_VARIABLE_NON_VOLATILE) == EFI_VARIABLE_NON_VOLATILE) {
72a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    return (FALSE);
73a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  }
74a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
75a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  //
76a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  // everything else is volatile
77a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  //
78a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  return (TRUE);
79a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey}
80a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
81a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey/**
82a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  free function for ENV_VAR_LIST objects.
83a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
84a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  @param[in] List               The pointer to pointer to list.
85a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey**/
86a405b86d274d32b92f69842bfb9a1ab143128f57jcarseyVOID
87a405b86d274d32b92f69842bfb9a1ab143128f57jcarseyEFIAPI
88a405b86d274d32b92f69842bfb9a1ab143128f57jcarseyFreeEnvironmentVariableList(
89a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  IN LIST_ENTRY *List
90a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  )
91a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey{
92a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  ENV_VAR_LIST *Node;
93a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
94a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  ASSERT (List != NULL);
95a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  if (List == NULL) {
96a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    return;
97a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  }
98a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
99a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  for ( Node = (ENV_VAR_LIST*)GetFirstNode(List)
1003f869579a47a0c48119e256a5309526f41092812jcarsey      ; !IsListEmpty(List)
101a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      ; Node = (ENV_VAR_LIST*)GetFirstNode(List)
102a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey     ){
103a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    ASSERT(Node != NULL);
104a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    RemoveEntryList(&Node->Link);
105a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    if (Node->Key != NULL) {
106a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      FreePool(Node->Key);
107a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    }
108a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    if (Node->Val != NULL) {
109a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      FreePool(Node->Val);
110a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    }
111a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    FreePool(Node);
112a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  }
113a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey}
114a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
115a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey/**
116a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  Creates a list of all Shell-Guid-based environment variables.
117a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
1184ff7e37b4f7e336a8ecb7080b8f48eef4b52d396ydong  @param[in, out] ListHead       The pointer to pointer to LIST ENTRY object for
1194ff7e37b4f7e336a8ecb7080b8f48eef4b52d396ydong                                 storing this list.
120a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
121a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  @retval EFI_SUCCESS           the list was created sucessfully.
122a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey**/
123a405b86d274d32b92f69842bfb9a1ab143128f57jcarseyEFI_STATUS
124a405b86d274d32b92f69842bfb9a1ab143128f57jcarseyEFIAPI
125a405b86d274d32b92f69842bfb9a1ab143128f57jcarseyGetEnvironmentVariableList(
126a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  IN OUT LIST_ENTRY *ListHead
127a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  )
128a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey{
129a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  CHAR16            *VariableName;
130a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  UINTN             NameSize;
131654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin  UINTN             NameBufferSize;
132a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  EFI_STATUS        Status;
133a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  EFI_GUID          Guid;
134a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  UINTN             ValSize;
135654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin  UINTN             ValBufferSize;
136a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  ENV_VAR_LIST      *VarList;
137a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
1383c865f2064d37eaccd1693b878596d5138b0b38ejcarsey  if (ListHead == NULL) {
1393c865f2064d37eaccd1693b878596d5138b0b38ejcarsey    return (EFI_INVALID_PARAMETER);
1403c865f2064d37eaccd1693b878596d5138b0b38ejcarsey  }
141654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin
142654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin  Status = EFI_SUCCESS;
143654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin
144654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin  ValBufferSize = INIT_DATA_BUFFER_SIZE;
145654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin  NameBufferSize = INIT_NAME_BUFFER_SIZE;
146654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin  VariableName = AllocateZeroPool(NameBufferSize);
1473c865f2064d37eaccd1693b878596d5138b0b38ejcarsey  if (VariableName == NULL) {
1483c865f2064d37eaccd1693b878596d5138b0b38ejcarsey    return (EFI_OUT_OF_RESOURCES);
1493c865f2064d37eaccd1693b878596d5138b0b38ejcarsey  }
1507f79b01e8ef43901785dbccc1f4676cdf9a53d31Jaben Carsey  *VariableName = CHAR_NULL;
151a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
1523c865f2064d37eaccd1693b878596d5138b0b38ejcarsey  while (!EFI_ERROR(Status)) {
153654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin    NameSize = NameBufferSize;
154a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    Status = gRT->GetNextVariableName(&NameSize, VariableName, &Guid);
155a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    if (Status == EFI_NOT_FOUND){
156a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      Status = EFI_SUCCESS;
157a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      break;
158654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin    } else if (Status == EFI_BUFFER_TOO_SMALL) {
159654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin      NameBufferSize = NameSize > NameBufferSize * 2 ? NameSize : NameBufferSize * 2;
160654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin      SHELL_FREE_NON_NULL(VariableName);
161654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin      VariableName = AllocateZeroPool(NameBufferSize);
162654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin      if (VariableName == NULL) {
163654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin        Status = EFI_OUT_OF_RESOURCES;
164654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin        break;
165654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin      }
166654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin      NameSize = NameBufferSize;
167654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin      Status = gRT->GetNextVariableName(&NameSize, VariableName, &Guid);
168a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    }
169654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin
1703c865f2064d37eaccd1693b878596d5138b0b38ejcarsey    if (!EFI_ERROR(Status) && CompareGuid(&Guid, &gShellVariableGuid)){
171a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      VarList = AllocateZeroPool(sizeof(ENV_VAR_LIST));
1728be0ba36fc347bac7199e7dbb8d373ea5e4bf0afjcarsey      if (VarList == NULL) {
1738be0ba36fc347bac7199e7dbb8d373ea5e4bf0afjcarsey        Status = EFI_OUT_OF_RESOURCES;
1748be0ba36fc347bac7199e7dbb8d373ea5e4bf0afjcarsey      } else {
175654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin        ValSize = ValBufferSize;
176654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin        VarList->Val = AllocateZeroPool(ValSize);
177654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin        if (VarList->Val == NULL) {
178654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin            SHELL_FREE_NON_NULL(VarList);
179654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin            Status = EFI_OUT_OF_RESOURCES;
180654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin            break;
181654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin        }
182a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey        Status = SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(VariableName, &VarList->Atts, &ValSize, VarList->Val);
1838be0ba36fc347bac7199e7dbb8d373ea5e4bf0afjcarsey        if (Status == EFI_BUFFER_TOO_SMALL){
184654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin          ValBufferSize = ValSize > ValBufferSize * 2 ? ValSize : ValBufferSize * 2;
185654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin          SHELL_FREE_NON_NULL (VarList->Val);
186654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin          VarList->Val = AllocateZeroPool(ValBufferSize);
1878be0ba36fc347bac7199e7dbb8d373ea5e4bf0afjcarsey          if (VarList->Val == NULL) {
1888be0ba36fc347bac7199e7dbb8d373ea5e4bf0afjcarsey            SHELL_FREE_NON_NULL(VarList);
1898be0ba36fc347bac7199e7dbb8d373ea5e4bf0afjcarsey            Status = EFI_OUT_OF_RESOURCES;
190654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin            break;
1918be0ba36fc347bac7199e7dbb8d373ea5e4bf0afjcarsey          }
192654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin
193654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin          ValSize = ValBufferSize;
194654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin          Status = SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(VariableName, &VarList->Atts, &ValSize, VarList->Val);
1958be0ba36fc347bac7199e7dbb8d373ea5e4bf0afjcarsey        }
196654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin        if (!EFI_ERROR(Status)) {
1977f79b01e8ef43901785dbccc1f4676cdf9a53d31Jaben Carsey          VarList->Key = AllocateCopyPool(StrSize(VariableName), VariableName);
1988be0ba36fc347bac7199e7dbb8d373ea5e4bf0afjcarsey          if (VarList->Key == NULL) {
1998be0ba36fc347bac7199e7dbb8d373ea5e4bf0afjcarsey            SHELL_FREE_NON_NULL(VarList->Val);
2008be0ba36fc347bac7199e7dbb8d373ea5e4bf0afjcarsey            SHELL_FREE_NON_NULL(VarList);
2018be0ba36fc347bac7199e7dbb8d373ea5e4bf0afjcarsey            Status = EFI_OUT_OF_RESOURCES;
2028be0ba36fc347bac7199e7dbb8d373ea5e4bf0afjcarsey          } else {
2038be0ba36fc347bac7199e7dbb8d373ea5e4bf0afjcarsey            InsertTailList(ListHead, &VarList->Link);
2048be0ba36fc347bac7199e7dbb8d373ea5e4bf0afjcarsey          }
205654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin        } else {
206654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin          SHELL_FREE_NON_NULL(VarList->Val);
207654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin          SHELL_FREE_NON_NULL(VarList);
2088be0ba36fc347bac7199e7dbb8d373ea5e4bf0afjcarsey        }
209654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin      } // if (VarList == NULL) ... else ...
210a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    } // compare guid
211a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  } // while
212654a012ba5e99c7439df392ed44b3b4e02aaca2fQiu Shumin  SHELL_FREE_NON_NULL (VariableName);
213a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
214a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  if (EFI_ERROR(Status)) {
215a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    FreeEnvironmentVariableList(ListHead);
216a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  }
217a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
218a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  return (Status);
219a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey}
220a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
221a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey/**
222a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  Sets a list of all Shell-Guid-based environment variables.  this will
223a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  also eliminate all existing shell environment variables (even if they
224a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  are not on the list).
225a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
226a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  This function will also deallocate the memory from List.
227a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
228a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  @param[in] ListHead           The pointer to LIST_ENTRY from
229a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey                                GetShellEnvVarList().
230a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
231a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  @retval EFI_SUCCESS           the list was Set sucessfully.
232a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey**/
233a405b86d274d32b92f69842bfb9a1ab143128f57jcarseyEFI_STATUS
234a405b86d274d32b92f69842bfb9a1ab143128f57jcarseyEFIAPI
235a405b86d274d32b92f69842bfb9a1ab143128f57jcarseySetEnvironmentVariableList(
236a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  IN LIST_ENTRY *ListHead
237a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  )
238a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey{
239a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  ENV_VAR_LIST      VarList;
240a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  ENV_VAR_LIST      *Node;
241a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  EFI_STATUS        Status;
242a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  UINTN             Size;
243a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
244a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  InitializeListHead(&VarList.Link);
245a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
246a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  //
247a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  // Delete all the current environment variables
248a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  //
249a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  Status = GetEnvironmentVariableList(&VarList.Link);
250a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  ASSERT_EFI_ERROR(Status);
251a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
252a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  for ( Node = (ENV_VAR_LIST*)GetFirstNode(&VarList.Link)
253a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      ; !IsNull(&VarList.Link, &Node->Link)
254a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      ; Node = (ENV_VAR_LIST*)GetNextNode(&VarList.Link, &Node->Link)
255a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey     ){
256a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    if (Node->Key != NULL) {
257a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      Status = SHELL_DELETE_ENVIRONMENT_VARIABLE(Node->Key);
258a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    }
259a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    ASSERT_EFI_ERROR(Status);
260a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  }
261a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
262a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  FreeEnvironmentVariableList(&VarList.Link);
263a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
264a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  //
265a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  // set all the variables fron the list
266a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  //
267a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  for ( Node = (ENV_VAR_LIST*)GetFirstNode(ListHead)
268a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      ; !IsNull(ListHead, &Node->Link)
269a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      ; Node = (ENV_VAR_LIST*)GetNextNode(ListHead, &Node->Link)
270a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey     ){
271a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    Size = StrSize(Node->Val);
272a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    if (Node->Atts & EFI_VARIABLE_NON_VOLATILE) {
273a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      Status = SHELL_SET_ENVIRONMENT_VARIABLE_NV(Node->Key, Size, Node->Val);
274a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    } else {
275a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      Status = SHELL_SET_ENVIRONMENT_VARIABLE_V (Node->Key, Size, Node->Val);
276a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    }
277a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    ASSERT_EFI_ERROR(Status);
278a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  }
279a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  FreeEnvironmentVariableList(ListHead);
280a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
281a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  return (Status);
282a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey}
283a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
284a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey/**
285a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  sets a list of all Shell-Guid-based environment variables.
286a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
287a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  @param Environment        Points to a NULL-terminated array of environment
288a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey                            variables with the format 'x=y', where x is the
289a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey                            environment variable name and y is the value.
290a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
291a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  @retval EFI_SUCCESS       The command executed successfully.
292a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  @retval EFI_INVALID_PARAMETER The parameter is invalid.
293a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  @retval EFI_OUT_OF_RESOURCES Out of resources.
294a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
295a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  @sa SetEnvironmentVariableList
296a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey**/
297a405b86d274d32b92f69842bfb9a1ab143128f57jcarseyEFI_STATUS
298a405b86d274d32b92f69842bfb9a1ab143128f57jcarseyEFIAPI
299a405b86d274d32b92f69842bfb9a1ab143128f57jcarseySetEnvironmentVariables(
300a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  IN CONST CHAR16 **Environment
301a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  )
302a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey{
303a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  CONST CHAR16  *CurrentString;
304a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  UINTN         CurrentCount;
305a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  ENV_VAR_LIST  *VarList;
306a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  ENV_VAR_LIST  *Node;
307a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
308a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  VarList = NULL;
309a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
310a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  if (Environment == NULL) {
311a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    return (EFI_INVALID_PARAMETER);
312a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  }
313a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
314a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  //
315a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  // Build a list identical to the ones used for get/set list functions above
316a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  //
317a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  for ( CurrentCount = 0
318a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      ;
319a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      ; CurrentCount++
320a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey     ){
321a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    CurrentString = Environment[CurrentCount];
322a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    if (CurrentString == NULL) {
323a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      break;
324a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    }
325a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    ASSERT(StrStr(CurrentString, L"=") != NULL);
326733f138d84a25a5993bc32ffe016c364daba686cjcarsey    Node = AllocateZeroPool(sizeof(ENV_VAR_LIST));
3277f79b01e8ef43901785dbccc1f4676cdf9a53d31Jaben Carsey    if (Node == NULL) {
3287f79b01e8ef43901785dbccc1f4676cdf9a53d31Jaben Carsey      SetEnvironmentVariableList(&VarList->Link);
3297f79b01e8ef43901785dbccc1f4676cdf9a53d31Jaben Carsey      return (EFI_OUT_OF_RESOURCES);
3307f79b01e8ef43901785dbccc1f4676cdf9a53d31Jaben Carsey    }
3317f79b01e8ef43901785dbccc1f4676cdf9a53d31Jaben Carsey
332a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    Node->Key = AllocateZeroPool((StrStr(CurrentString, L"=") - CurrentString + 1) * sizeof(CHAR16));
3337f79b01e8ef43901785dbccc1f4676cdf9a53d31Jaben Carsey    if (Node->Key == NULL) {
3347f79b01e8ef43901785dbccc1f4676cdf9a53d31Jaben Carsey      SHELL_FREE_NON_NULL(Node);
3357f79b01e8ef43901785dbccc1f4676cdf9a53d31Jaben Carsey      SetEnvironmentVariableList(&VarList->Link);
3367f79b01e8ef43901785dbccc1f4676cdf9a53d31Jaben Carsey      return (EFI_OUT_OF_RESOURCES);
3377f79b01e8ef43901785dbccc1f4676cdf9a53d31Jaben Carsey    }
3387f79b01e8ef43901785dbccc1f4676cdf9a53d31Jaben Carsey
3397f79b01e8ef43901785dbccc1f4676cdf9a53d31Jaben Carsey    //
3407f79b01e8ef43901785dbccc1f4676cdf9a53d31Jaben Carsey    // Copy the string into the Key, leaving the last character allocated as NULL to terminate
3417f79b01e8ef43901785dbccc1f4676cdf9a53d31Jaben Carsey    //
342490ce43d92132653a6664971218e1cb330556391Qiu Shumin    StrnCpyS( Node->Key,
343e75390f02971bcd4d67a9696508050bee4936a01Qiu Shumin              StrStr(CurrentString, L"=") - CurrentString + 1,
344490ce43d92132653a6664971218e1cb330556391Qiu Shumin              CurrentString,
345490ce43d92132653a6664971218e1cb330556391Qiu Shumin              StrStr(CurrentString, L"=") - CurrentString
346e75390f02971bcd4d67a9696508050bee4936a01Qiu Shumin              );
3477f79b01e8ef43901785dbccc1f4676cdf9a53d31Jaben Carsey
3487f79b01e8ef43901785dbccc1f4676cdf9a53d31Jaben Carsey    //
3497f79b01e8ef43901785dbccc1f4676cdf9a53d31Jaben Carsey    // ValueSize = TotalSize - already removed size - size for '=' + size for terminator (the last 2 items cancel each other)
3507f79b01e8ef43901785dbccc1f4676cdf9a53d31Jaben Carsey    //
3517f79b01e8ef43901785dbccc1f4676cdf9a53d31Jaben Carsey    Node->Val = AllocateCopyPool(StrSize(CurrentString) - StrSize(Node->Key), CurrentString + StrLen(Node->Key) + 1);
3527f79b01e8ef43901785dbccc1f4676cdf9a53d31Jaben Carsey    if (Node->Val == NULL) {
3537f79b01e8ef43901785dbccc1f4676cdf9a53d31Jaben Carsey      SHELL_FREE_NON_NULL(Node->Key);
3547f79b01e8ef43901785dbccc1f4676cdf9a53d31Jaben Carsey      SHELL_FREE_NON_NULL(Node);
3557f79b01e8ef43901785dbccc1f4676cdf9a53d31Jaben Carsey      SetEnvironmentVariableList(&VarList->Link);
3567f79b01e8ef43901785dbccc1f4676cdf9a53d31Jaben Carsey      return (EFI_OUT_OF_RESOURCES);
3577f79b01e8ef43901785dbccc1f4676cdf9a53d31Jaben Carsey    }
3587f79b01e8ef43901785dbccc1f4676cdf9a53d31Jaben Carsey
359a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    Node->Atts = EFI_VARIABLE_BOOTSERVICE_ACCESS;
360a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
361a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    if (VarList == NULL) {
362a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      VarList = AllocateZeroPool(sizeof(ENV_VAR_LIST));
3637f79b01e8ef43901785dbccc1f4676cdf9a53d31Jaben Carsey      if (VarList == NULL) {
3647f79b01e8ef43901785dbccc1f4676cdf9a53d31Jaben Carsey        SHELL_FREE_NON_NULL(Node->Key);
3657f79b01e8ef43901785dbccc1f4676cdf9a53d31Jaben Carsey        SHELL_FREE_NON_NULL(Node->Val);
3667f79b01e8ef43901785dbccc1f4676cdf9a53d31Jaben Carsey        SHELL_FREE_NON_NULL(Node);
3677f79b01e8ef43901785dbccc1f4676cdf9a53d31Jaben Carsey        return (EFI_OUT_OF_RESOURCES);
3687f79b01e8ef43901785dbccc1f4676cdf9a53d31Jaben Carsey      }
369a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey      InitializeListHead(&VarList->Link);
370a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    }
371a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey    InsertTailList(&VarList->Link, &Node->Link);
372a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
373a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  } // for loop
374a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey
375a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  //
376a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  // set this new list as the set of all environment variables.
377a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  // this function also frees the memory and deletes all pre-existing
378a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  // shell-guid based environment variables.
379a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  //
380a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey  return (SetEnvironmentVariableList(&VarList->Link));
381a405b86d274d32b92f69842bfb9a1ab143128f57jcarsey}
382