b02048302e6d64cc387667892507a1259a1c646d
[mirror_edk2.git] / ShellPkg / Library / UefiShellDebug1CommandsLib / DmpStore.c
1 /** @file
2 Main file for DmpStore shell Debug1 function.
3
4 Copyright (c) 2005 - 2014, 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 "UefiShellDebug1CommandsLib.h"
16
17 /**
18 Base on the input attribute value to return the attribute string.
19
20 @param[in] Atts The input attribute value
21
22 @retval The attribute string info.
23 **/
24 CHAR16 *
25 EFIAPI
26 GetAttrType (
27 IN CONST UINT32 Atts
28 )
29 {
30 UINTN BufLen;
31 CHAR16 *RetString;
32
33 BufLen = 0;
34 RetString = NULL;
35
36 if ((Atts & EFI_VARIABLE_NON_VOLATILE) != 0) {
37 StrnCatGrow (&RetString, &BufLen, L"+NV", 0);
38 }
39 if ((Atts & EFI_VARIABLE_RUNTIME_ACCESS) != 0) {
40 StrnCatGrow (&RetString, &BufLen, L"+RS+BS", 0);
41 } else if ((Atts & EFI_VARIABLE_BOOTSERVICE_ACCESS) != 0) {
42 StrnCatGrow (&RetString, &BufLen, L"+BS", 0);
43 }
44 if ((Atts & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != 0) {
45 StrnCatGrow (&RetString, &BufLen, L"+HR", 0);
46 }
47 if ((Atts & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {
48 StrnCatGrow (&RetString, &BufLen, L"+AW", 0);
49 }
50 if ((Atts & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {
51 StrnCatGrow (&RetString, &BufLen, L"+AT", 0);
52 }
53
54 if (RetString == NULL) {
55 RetString = StrnCatGrow(&RetString, &BufLen, L"Invalid", 0);
56 }
57
58 if ((RetString != NULL) && (RetString[0] == L'+')) {
59 CopyMem(RetString, RetString + 1, StrSize(RetString + 1));
60 }
61
62 return RetString;
63 }
64
65 /**
66 Recursive function to display or delete variables.
67
68 This function will call itself to create a stack-based list of allt he variables to process,
69 then fromt he last to the first, they will do either printing or deleting.
70
71 This is necessary since once a delete happens GetNextVariableName() will work.
72
73 @param[in] VariableName The variable name of the EFI variable (or NULL).
74 @param[in] Guid The GUID of the variable set (or NULL).
75 @param[in] Delete TRUE to delete, FALSE otherwise.
76 @param[in] PrevName The previous variable name from GetNextVariableName. L"" to start.
77 @param[in] FoundVarGuid The previous GUID from GetNextVariableName. ignored at start.
78 @param[in] FoundOne If a VariableName or Guid was specified and one was printed or
79 deleted, then set this to TRUE, otherwise ignored.
80
81 @retval SHELL_SUCCESS The operation was successful.
82 @retval SHELL_OUT_OF_RESOURCES A memorty allocation failed.
83 @retval SHELL_ABORTED The abort message was received.
84 @retval SHELL_DEVICE_ERROR UEFI Variable Services returned an error.
85 @retval SHELL_NOT_FOUND the Name/Guid pair could not be found.
86 **/
87 SHELL_STATUS
88 EFIAPI
89 CascadeProcessVariables (
90 IN CONST CHAR16 *VariableName OPTIONAL,
91 IN CONST EFI_GUID *Guid OPTIONAL,
92 IN BOOLEAN Delete,
93 IN CONST CHAR16 * CONST PrevName,
94 IN EFI_GUID FoundVarGuid,
95 IN BOOLEAN *FoundOne
96 )
97 {
98 EFI_STATUS Status;
99 CHAR16 *FoundVarName;
100 UINT8 *DataBuffer;
101 UINTN DataSize;
102 UINT32 Atts;
103 SHELL_STATUS ShellStatus;
104 UINTN NameSize;
105 CHAR16 *RetString;
106
107 if (ShellGetExecutionBreakFlag()) {
108 return (SHELL_ABORTED);
109 }
110
111 NameSize = 0;
112 FoundVarName = NULL;
113
114 if (PrevName!=NULL) {
115 StrnCatGrow(&FoundVarName, &NameSize, PrevName, 0);
116 } else {
117 FoundVarName = AllocateZeroPool(sizeof(CHAR16));
118 }
119
120 Status = gRT->GetNextVariableName (&NameSize, FoundVarName, &FoundVarGuid);
121 if (Status == EFI_BUFFER_TOO_SMALL) {
122 SHELL_FREE_NON_NULL(FoundVarName);
123 FoundVarName = AllocateZeroPool (NameSize);
124 if (FoundVarName != NULL) {
125 if (PrevName != NULL) {
126 StrCpy(FoundVarName, PrevName);
127 }
128
129 Status = gRT->GetNextVariableName (&NameSize, FoundVarName, &FoundVarGuid);
130 } else {
131 Status = EFI_OUT_OF_RESOURCES;
132 }
133 }
134
135 //
136 // No more is fine.
137 //
138 if (Status == EFI_NOT_FOUND) {
139 SHELL_FREE_NON_NULL(FoundVarName);
140 return (SHELL_SUCCESS);
141 } else if (EFI_ERROR(Status)) {
142 SHELL_FREE_NON_NULL(FoundVarName);
143 return (SHELL_DEVICE_ERROR);
144 }
145
146 //
147 // Recurse to the next iteration. We know "our" variable's name.
148 //
149 ShellStatus = CascadeProcessVariables(VariableName, Guid, Delete, FoundVarName, FoundVarGuid, FoundOne);
150
151 //
152 // No matter what happened we process our own variable
153 // Only continue if Guid and VariableName are each either NULL or a match
154 //
155 if ( ( VariableName == NULL
156 || gUnicodeCollation->MetaiMatch(gUnicodeCollation, FoundVarName, (CHAR16*)VariableName) )
157 && ( Guid == NULL
158 || CompareGuid(&FoundVarGuid, Guid) )
159 ) {
160 DataSize = 0;
161 DataBuffer = NULL;
162 //
163 // do the print or delete
164 //
165 *FoundOne = TRUE;
166 Status = gRT->GetVariable (FoundVarName, &FoundVarGuid, &Atts, &DataSize, DataBuffer);
167 if (Status == EFI_BUFFER_TOO_SMALL) {
168 SHELL_FREE_NON_NULL (DataBuffer);
169 DataBuffer = AllocatePool (DataSize);
170 if (DataBuffer == NULL) {
171 Status = EFI_OUT_OF_RESOURCES;
172 } else {
173 Status = gRT->GetVariable (FoundVarName, &FoundVarGuid, &Atts, &DataSize, DataBuffer);
174 }
175 }
176 if (!Delete) {
177 //
178 // Last error check then print this variable out.
179 //
180 if (!EFI_ERROR(Status) && DataBuffer != NULL) {
181 RetString = GetAttrType(Atts);
182 ShellPrintHiiEx(
183 -1,
184 -1,
185 NULL,
186 STRING_TOKEN(STR_DMPSTORE_HEADER_LINE),
187 gShellDebug1HiiHandle,
188 RetString,
189 &FoundVarGuid,
190 FoundVarName,
191 DataSize);
192 DumpHex(2, 0, DataSize, DataBuffer);
193 SHELL_FREE_NON_NULL(RetString);
194 }
195 } else {
196 //
197 // We only need name to delete it...
198 //
199 ShellPrintHiiEx(
200 -1,
201 -1,
202 NULL,
203 STRING_TOKEN(STR_DMPSTORE_DELETE_LINE),
204 gShellDebug1HiiHandle,
205 &FoundVarGuid,
206 FoundVarName);
207 ShellPrintHiiEx(
208 -1,
209 -1,
210 NULL,
211 STRING_TOKEN(STR_DMPSTORE_DELETE_DONE),
212 gShellDebug1HiiHandle,
213 gRT->SetVariable(FoundVarName, &FoundVarGuid, Atts, 0, NULL));
214 }
215 SHELL_FREE_NON_NULL(DataBuffer);
216 }
217
218 SHELL_FREE_NON_NULL(FoundVarName);
219
220 if (Status == EFI_DEVICE_ERROR) {
221 ShellStatus = SHELL_DEVICE_ERROR;
222 } else if (Status == EFI_SECURITY_VIOLATION) {
223 ShellStatus = SHELL_SECURITY_VIOLATION;
224 } else if (EFI_ERROR(Status)) {
225 ShellStatus = SHELL_NOT_READY;
226 }
227
228 return (ShellStatus);
229 }
230
231 /**
232 Function to display or delete variables. This will set up and call into the recursive function.
233
234 @param[in] VariableName The variable name of the EFI variable (or NULL).
235 @param[in] Guid The GUID of the variable set (or NULL).
236 @param[in] Delete TRUE to delete, FALSE otherwise.
237
238 @retval SHELL_SUCCESS The operation was successful.
239 @retval SHELL_OUT_OF_RESOURCES A memorty allocation failed.
240 @retval SHELL_ABORTED The abort message was received.
241 @retval SHELL_DEVICE_ERROR UEFI Variable Services returned an error.
242 @retval SHELL_NOT_FOUND the Name/Guid pair could not be found.
243 **/
244 SHELL_STATUS
245 EFIAPI
246 ProcessVariables (
247 IN CONST CHAR16 *VariableName OPTIONAL,
248 IN CONST EFI_GUID *Guid OPTIONAL,
249 IN BOOLEAN Delete
250 )
251 {
252 SHELL_STATUS ShellStatus;
253 BOOLEAN Found;
254 EFI_GUID FoundVarGuid;
255
256 Found = FALSE;
257 ShellStatus = SHELL_SUCCESS;
258 ZeroMem (&FoundVarGuid, sizeof(EFI_GUID));
259
260 ShellStatus = CascadeProcessVariables(VariableName, Guid, Delete, NULL, FoundVarGuid, &Found);
261
262 if (!Found) {
263 if (ShellStatus == SHELL_OUT_OF_RESOURCES) {
264 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellDebug1HiiHandle);
265 return (ShellStatus);
266 } else if (VariableName != NULL && Guid == NULL) {
267 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND_N), gShellDebug1HiiHandle, VariableName);
268 } else if (VariableName != NULL && Guid != NULL) {
269 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND_GN), gShellDebug1HiiHandle, Guid, VariableName);
270 } else if (VariableName == NULL && Guid == NULL) {
271 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND), gShellDebug1HiiHandle);
272 } else if (VariableName == NULL && Guid != NULL) {
273 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND_G), gShellDebug1HiiHandle, Guid);
274 }
275 return (SHELL_NOT_FOUND);
276 }
277 return (ShellStatus);
278 }
279
280 STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
281 {L"-d", TypeFlag},
282 {L"-l", TypeFlag},
283 {L"-s", TypeFlag},
284 {L"-all", TypeFlag},
285 {L"-guid", TypeValue},
286 {NULL, TypeMax}
287 };
288
289 /**
290 Function for 'dmpstore' command.
291
292 @param[in] ImageHandle Handle to the Image (NULL if Internal).
293 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
294 **/
295 SHELL_STATUS
296 EFIAPI
297 ShellCommandRunDmpStore (
298 IN EFI_HANDLE ImageHandle,
299 IN EFI_SYSTEM_TABLE *SystemTable
300 )
301 {
302 EFI_STATUS Status;
303 LIST_ENTRY *Package;
304 CHAR16 *ProblemParam;
305 SHELL_STATUS ShellStatus;
306 CONST CHAR16 *Temp;
307 EFI_GUID *Guid;
308 EFI_GUID GuidData;
309 CONST CHAR16 *VariableName;
310
311 ShellStatus = SHELL_SUCCESS;
312 Package = NULL;
313
314 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
315 if (EFI_ERROR(Status)) {
316 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
317 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, ProblemParam);
318 FreePool(ProblemParam);
319 ShellStatus = SHELL_INVALID_PARAMETER;
320 } else {
321 ASSERT(FALSE);
322 }
323 } else {
324 if (ShellCommandLineGetCount(Package) > 2) {
325 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle);
326 ShellStatus = SHELL_INVALID_PARAMETER;
327 } else if (ShellCommandLineGetFlag(Package, L"-all") && ShellCommandLineGetFlag(Package, L"-guid")) {
328 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CONFLICT), gShellDebug1HiiHandle, L"-all", L"-guid");
329 ShellStatus = SHELL_INVALID_PARAMETER;
330 } else if ((ShellCommandLineGetFlag(Package, L"-s") || ShellCommandLineGetFlag(Package, L"-l")) && ShellCommandLineGetFlag(Package, L"-d")) {
331 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CONFLICT), gShellDebug1HiiHandle, L"-l or -s", L"-d");
332 ShellStatus = SHELL_INVALID_PARAMETER;
333 } else {
334 if (!ShellCommandLineGetFlag(Package, L"-all")) {
335 Temp = ShellCommandLineGetValue(Package, L"-guid");
336 if (Temp != NULL) {
337 Status = ConvertStringToGuid(Temp, &GuidData);
338 if (EFI_ERROR(Status)) {
339 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, Temp);
340 ShellStatus = SHELL_INVALID_PARAMETER;
341 }
342 Guid = &GuidData;
343 } else {
344 Guid = &gEfiGlobalVariableGuid;
345 }
346 VariableName = ShellCommandLineGetRawValue(Package, 1);
347 } else {
348 VariableName = NULL;
349 Guid = NULL;
350 }
351 if (ShellStatus == SHELL_SUCCESS) {
352 if (ShellCommandLineGetFlag(Package, L"-s") || ShellCommandLineGetFlag(Package, L"-l")) {
353 ///@todo fix this after lib ready...
354 ShellPrintEx(-1, -1, L"Not implemeneted yet.\r\n");
355 ShellStatus = SHELL_UNSUPPORTED;
356 } else {
357 ShellStatus = ProcessVariables (VariableName, Guid, ShellCommandLineGetFlag(Package, L"-d"));
358 }
359 }
360 }
361 }
362
363 if (Package != NULL) {
364 ShellCommandLineFreeVarList (Package);
365 }
366 return ShellStatus;
367 }
368