pointer verification (not NULL) and buffer overrun fixes.
[mirror_edk2.git] / ShellPkg / Library / UefiShellDebug1CommandsLib / SetVar.c
1 /** @file\r
2   Main file for SetVar shell Debug1 function.\r
3 \r
4   Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>\r
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
15 #include "UefiShellDebug1CommandsLib.h"\r
16 \r
17 STATIC CONST SHELL_PARAM_ITEM ParamList[] = {\r
18   {L"-guid", TypeValue},\r
19   {L"-bs", TypeFlag},\r
20   {L"-rt", TypeFlag},\r
21   {L"-nv", TypeFlag},\r
22   {NULL, TypeMax}\r
23   };\r
24 \r
25 /**\r
26   Function for 'setvar' command.\r
27 \r
28   @param[in] ImageHandle  Handle to the Image (NULL if Internal).\r
29   @param[in] SystemTable  Pointer to the System Table (NULL if Internal).\r
30 **/\r
31 SHELL_STATUS\r
32 EFIAPI\r
33 ShellCommandRunSetVar (\r
34   IN EFI_HANDLE        ImageHandle,\r
35   IN EFI_SYSTEM_TABLE  *SystemTable\r
36   )\r
37 {\r
38   EFI_STATUS          Status;\r
39   LIST_ENTRY          *Package;\r
40   CHAR16              *ProblemParam;\r
41   SHELL_STATUS        ShellStatus;\r
42   CONST CHAR16        *VariableName;\r
43   CONST CHAR16        *Data;\r
44   EFI_GUID            Guid;\r
45   CONST CHAR16        *StringGuid;\r
46   UINT32              Attributes;\r
47   UINT32              Attributes2;\r
48   VOID                *Buffer;\r
49   UINTN               Size;\r
50   UINTN               LoopVar;\r
51   EFI_DEVICE_PATH_PROTOCOL           *DevPath;\r
52   EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL *DevPathFromText;\r
53 \r
54   ShellStatus         = SHELL_SUCCESS;\r
55   Status              = EFI_SUCCESS;\r
56   Buffer              = NULL;\r
57   Size                = 0;\r
58   Attributes          = 0;\r
59   DevPath             = NULL;\r
60 \r
61   //\r
62   // initialize the shell lib (we must be in non-auto-init...)\r
63   //\r
64   Status = ShellInitialize();\r
65   ASSERT_EFI_ERROR(Status);\r
66 \r
67   Status = CommandInit();\r
68   ASSERT_EFI_ERROR(Status);\r
69 \r
70   //\r
71   // parse the command line\r
72   //\r
73   Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);\r
74   if (EFI_ERROR(Status)) {\r
75     if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {\r
76       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, ProblemParam);\r
77       FreePool(ProblemParam);\r
78       ShellStatus = SHELL_INVALID_PARAMETER;\r
79     } else {\r
80       ASSERT(FALSE);\r
81     }\r
82   } else {\r
83     if (ShellCommandLineGetCount(Package) < 2) {\r
84       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle);\r
85       ShellStatus = SHELL_INVALID_PARAMETER;\r
86     } else if (ShellCommandLineGetCount(Package) > 3) {\r
87       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle);\r
88       ShellStatus = SHELL_INVALID_PARAMETER;\r
89     } else {\r
90       VariableName  = ShellCommandLineGetRawValue(Package, 1);\r
91       Data          = ShellCommandLineGetRawValue(Package, 2);\r
92       if (!ShellCommandLineGetFlag(Package, L"-guid")){\r
93         CopyGuid(&Guid, &gEfiGlobalVariableGuid);\r
94       } else {\r
95         StringGuid = ShellCommandLineGetValue(Package, L"-guid");\r
96         Status = ConvertStringToGuid(StringGuid, &Guid);\r
97         if (EFI_ERROR(Status)) {\r
98           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, StringGuid);\r
99           ShellStatus = SHELL_INVALID_PARAMETER;\r
100         }\r
101       }\r
102       if (Data == NULL) {\r
103         //\r
104         // Display what's there\r
105         //\r
106         Status = gRT->GetVariable((CHAR16*)VariableName, &Guid, &Attributes, &Size, Buffer);\r
107         if (Status == EFI_BUFFER_TOO_SMALL) {\r
108           Buffer = AllocateZeroPool(Size);\r
109           Status = gRT->GetVariable((CHAR16*)VariableName, &Guid, &Attributes, &Size, Buffer);\r
110         }\r
111         if (!EFI_ERROR(Status)&& Buffer != NULL) {\r
112           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SETVAR_PRINT), gShellDebug1HiiHandle, &Guid, VariableName, Size);\r
113           for (LoopVar = 0 ; LoopVar < Size ; LoopVar++) {\r
114             ShellPrintEx(-1, -1, L"%02x ", ((UINT8*)Buffer)[LoopVar]);\r
115           }\r
116           ShellPrintEx(-1, -1, L"\r\n");\r
117         } else {\r
118           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SETVAR_ERROR_GET), gShellDebug1HiiHandle, &Guid, VariableName, Status);\r
119           ShellStatus = SHELL_ACCESS_DENIED;\r
120         }\r
121       } else if (StrCmp(Data, L"=") == 0) {\r
122         //\r
123         // Delete what's there!\r
124         //\r
125         Status = gRT->SetVariable((CHAR16*)VariableName, &Guid, Attributes, 0, NULL);\r
126         if (EFI_ERROR(Status)) {\r
127           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SETVAR_ERROR_SET), gShellDebug1HiiHandle, &Guid, VariableName, Status);\r
128           ShellStatus = SHELL_ACCESS_DENIED;\r
129         } else {\r
130           ASSERT(ShellStatus == SHELL_SUCCESS);\r
131         }\r
132       } else {\r
133         if (Data[0] == L'=') {\r
134           Data++;\r
135         }\r
136         //\r
137         // Change what's there\r
138         //\r
139         if (ShellCommandLineGetFlag(Package, L"-bs")) {\r
140           Attributes |= EFI_VARIABLE_BOOTSERVICE_ACCESS;\r
141         }\r
142         if (ShellCommandLineGetFlag(Package, L"-rt")) {\r
143           Attributes |= EFI_VARIABLE_RUNTIME_ACCESS;\r
144         }\r
145         if (ShellCommandLineGetFlag(Package, L"-nv")) {\r
146           Attributes |= EFI_VARIABLE_NON_VOLATILE;\r
147         }\r
148         if (ShellIsHexOrDecimalNumber(Data, TRUE, FALSE)) {\r
149           if (StrLen(Data) % 2 != 0) {\r
150             ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellDebug1HiiHandle, Data);\r
151             ShellStatus = SHELL_INVALID_PARAMETER;\r
152           } else {\r
153             //\r
154             // arbitrary buffer\r
155             //\r
156             Buffer = AllocateZeroPool((StrLen(Data) / 2));\r
157             if (Buffer == NULL) {\r
158               Status = EFI_OUT_OF_RESOURCES;\r
159             } else {\r
160               for (LoopVar = 0 ; LoopVar < (StrLen(Data) / 2) ; LoopVar++) {\r
161                 ((UINT8*)Buffer)[LoopVar] = (UINT8)(HexCharToUintn(Data[LoopVar*2]) * 16);\r
162                 ((UINT8*)Buffer)[LoopVar] = (UINT8)(((UINT8*)Buffer)[LoopVar] + HexCharToUintn(Data[LoopVar*2+1]));\r
163               }\r
164               Status = gRT->SetVariable((CHAR16*)VariableName, &Guid, Attributes, StrLen(Data) / 2, Buffer);\r
165             }\r
166             if (EFI_ERROR(Status)) {\r
167               ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SETVAR_ERROR_SET), gShellDebug1HiiHandle, &Guid, VariableName, Status);\r
168               ShellStatus = SHELL_ACCESS_DENIED;\r
169             } else {\r
170               ASSERT(ShellStatus == SHELL_SUCCESS);\r
171             }\r
172           }\r
173         } else if (StrnCmp(Data, L"\"", 1) == 0) {\r
174           Size = 0;\r
175           Attributes2 = 0;\r
176           Status = gRT->GetVariable((CHAR16*)VariableName, &Guid, &Attributes2, &Size, Buffer);\r
177           if (Status == EFI_BUFFER_TOO_SMALL) {\r
178             Buffer = AllocateZeroPool(Size);\r
179             Status = gRT->GetVariable((CHAR16*)VariableName, &Guid, &Attributes2, &Size, Buffer);\r
180             FreePool(Buffer);\r
181             Attributes = Attributes2;\r
182           }          \r
183           //\r
184           // ascii text\r
185           //\r
186           Data++;\r
187           Buffer = AllocateZeroPool(StrSize(Data) / 2);\r
188           if (Buffer == NULL) {\r
189             Status = EFI_OUT_OF_RESOURCES;\r
190           } else {\r
191             AsciiSPrint(Buffer, StrSize(Data) / 2, "%s", Data);\r
192             ((CHAR8*)Buffer)[AsciiStrLen(Buffer)-1] = CHAR_NULL;\r
193             Status = gRT->SetVariable((CHAR16*)VariableName, &Guid, Attributes, AsciiStrSize(Buffer)-sizeof(CHAR8), Buffer);\r
194           }\r
195           if (EFI_ERROR(Status)) {\r
196             ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SETVAR_ERROR_SET), gShellDebug1HiiHandle, &Guid, VariableName, Status);\r
197             ShellStatus = SHELL_ACCESS_DENIED;\r
198           } else {\r
199             ASSERT(ShellStatus == SHELL_SUCCESS);\r
200           }\r
201         } else if (StrnCmp(Data, L"L\"", 2) == 0) {\r
202           //\r
203           // ucs2 text\r
204           //\r
205           Data++;\r
206           Data++;\r
207           Buffer = AllocateZeroPool(StrSize(Data));\r
208           UnicodeSPrint(Buffer, StrSize(Data), L"%s", Data);\r
209           ((CHAR16*)Buffer)[StrLen(Buffer)-1] = CHAR_NULL;\r
210 \r
211           Status = gRT->SetVariable((CHAR16*)VariableName, &Guid, Attributes, StrSize(Buffer)-sizeof(CHAR16), Buffer);\r
212           if (EFI_ERROR(Status)) {\r
213             ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SETVAR_ERROR_SET), gShellDebug1HiiHandle, &Guid, VariableName, Status);\r
214             ShellStatus = SHELL_ACCESS_DENIED;\r
215           } else {\r
216             ASSERT(ShellStatus == SHELL_SUCCESS);\r
217           }\r
218         } else if (StrnCmp(Data, L"--", 2) == 0) {\r
219           //\r
220           // device path in text format\r
221           //\r
222           Data++;\r
223           Data++;\r
224           Status = gBS->LocateProtocol(&gEfiDevicePathFromTextProtocolGuid, NULL, (VOID**)&DevPathFromText);\r
225           ASSERT_EFI_ERROR(Status);\r
226           DevPath = DevPathFromText->ConvertTextToDevicePath(Data);\r
227           if (DevPath == NULL) {\r
228             ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SETVAR_ERROR_DPFT), gShellDebug1HiiHandle, Status);\r
229             ShellStatus = SHELL_INVALID_PARAMETER;\r
230           } else {\r
231             Status = gRT->SetVariable((CHAR16*)VariableName, &Guid, Attributes, GetDevicePathSize(DevPath), DevPath);\r
232             if (EFI_ERROR(Status)) {\r
233               ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SETVAR_ERROR_SET), gShellDebug1HiiHandle, &Guid, VariableName, Status);\r
234               ShellStatus = SHELL_ACCESS_DENIED;\r
235             } else {\r
236               ASSERT(ShellStatus == SHELL_SUCCESS);\r
237             }\r
238           }\r
239         } else {\r
240           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, Data);\r
241           ShellStatus = SHELL_INVALID_PARAMETER;\r
242         }\r
243       }\r
244     }\r
245     ShellCommandLineFreeVarList (Package);\r
246   }\r
247 \r
248   if (Buffer != NULL) {\r
249     FreePool(Buffer);\r
250   }\r
251 \r
252   if (DevPath != NULL) {\r
253     FreePool(DevPath);\r
254   }\r
255 \r
256   return (ShellStatus);\r
257 }\r