]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.c
1814564c12db16cdc900875717aebf6829810c6f
[mirror_edk2.git] / ShellPkg / Library / UefiShellDebug1CommandsLib / UefiShellDebug1CommandsLib.c
1 /** @file
2 Main file for NULL named library for debug1 profile shell command functions.
3
4 Copyright (c) 2010 - 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 "UefiShellDebug1CommandsLib.h"
16 #include <Library/BcfgCommandLib.h>
17
18 STATIC CONST CHAR16 mFileName[] = L"Debug1Commands";
19 EFI_HANDLE gShellDebug1HiiHandle = NULL;
20
21 /**
22 Gets the debug file name. This will be used if HII is not working.
23
24 @retval NULL No file is available.
25 @return The NULL-terminated filename to get help from.
26 **/
27 CONST CHAR16*
28 EFIAPI
29 ShellCommandGetManFileNameDebug1 (
30 VOID
31 )
32 {
33 return (mFileName);
34 }
35
36 /**
37 Constructor for the Shell Debug1 Commands library.
38
39 @param ImageHandle the image handle of the process
40 @param SystemTable the EFI System Table pointer
41
42 @retval EFI_SUCCESS the shell command handlers were installed sucessfully
43 @retval EFI_UNSUPPORTED the shell level required was not found.
44 **/
45 EFI_STATUS
46 EFIAPI
47 UefiShellDebug1CommandsLibConstructor (
48 IN EFI_HANDLE ImageHandle,
49 IN EFI_SYSTEM_TABLE *SystemTable
50 )
51 {
52 //
53 // check our bit of the profiles mask
54 //
55 if ((PcdGet8(PcdShellProfileMask) & BIT1) == 0) {
56 return (EFI_SUCCESS);
57 }
58
59 //
60 // install the HII stuff.
61 //
62 gShellDebug1HiiHandle = HiiAddPackages (&gShellDebug1HiiGuid, gImageHandle, UefiShellDebug1CommandsLibStrings, NULL);
63 if (gShellDebug1HiiHandle == NULL) {
64 return (EFI_DEVICE_ERROR);
65 }
66
67 //
68 // install our shell command handlers that are always installed
69 //
70 ShellCommandRegisterCommandName(L"setsize", ShellCommandRunSetSize , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_SETSIZE) );
71 ShellCommandRegisterCommandName(L"comp", ShellCommandRunComp , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_COMP) );
72 ShellCommandRegisterCommandName(L"mode", ShellCommandRunMode , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_MODE) );
73 ShellCommandRegisterCommandName(L"memmap", ShellCommandRunMemMap , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_MEMMAP) );
74 ShellCommandRegisterCommandName(L"eficompress", ShellCommandRunEfiCompress , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_EFICOMPRESS) );
75 ShellCommandRegisterCommandName(L"efidecompress", ShellCommandRunEfiDecompress , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_EFIDCOMPRESS) );
76 ShellCommandRegisterCommandName(L"dmem", ShellCommandRunDmem , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_DMEM) );
77 ShellCommandRegisterCommandName(L"loadpcirom", ShellCommandRunLoadPciRom , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_LOAD_PCI_ROM) );
78 ShellCommandRegisterCommandName(L"mm", ShellCommandRunMm , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_MM) );
79 ShellCommandRegisterCommandName(L"setvar", ShellCommandRunSetVar , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_SETVAR) );
80 ShellCommandRegisterCommandName(L"sermode", ShellCommandRunSerMode , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_SERMODE) );
81 ShellCommandRegisterCommandName(L"pci", ShellCommandRunPci , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_PCI) );
82 ShellCommandRegisterCommandName(L"smbiosview", ShellCommandRunSmbiosView , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_SMBIOSVIEW) );
83 ShellCommandRegisterCommandName(L"dmpstore", ShellCommandRunDmpStore , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_DMPSTORE) );
84 ShellCommandRegisterCommandName(L"dblk", ShellCommandRunDblk , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_DBLK) );
85 ShellCommandRegisterCommandName(L"edit", ShellCommandRunEdit , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_EDIT) );
86 ShellCommandRegisterCommandName(L"hexedit", ShellCommandRunHexEdit , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_HEXEDIT) );
87
88 ShellCommandRegisterAlias(L"dmem", L"mem");
89
90 BcfgLibraryRegisterBcfgCommand(ImageHandle, SystemTable, L"Debug1");
91
92 return (EFI_SUCCESS);
93 }
94
95 /**
96 Destructor for the library. free any resources.
97
98 @param ImageHandle The image handle of the process.
99 @param SystemTable The EFI System Table pointer.
100 **/
101 EFI_STATUS
102 EFIAPI
103 UefiShellDebug1CommandsLibDestructor (
104 IN EFI_HANDLE ImageHandle,
105 IN EFI_SYSTEM_TABLE *SystemTable
106 )
107 {
108 if (gShellDebug1HiiHandle != NULL) {
109 HiiRemovePackages(gShellDebug1HiiHandle);
110 }
111
112 BcfgLibraryUnregisterBcfgCommand(ImageHandle, SystemTable);
113 return (EFI_SUCCESS);
114 }
115
116 /**
117 Convert a Unicode character to upper case only if
118 it maps to a valid small-case ASCII character.
119
120 This internal function only deal with Unicode character
121 which maps to a valid small-case ASCII character, i.e.
122 L'a' to L'z'. For other Unicode character, the input character
123 is returned directly.
124
125 @param Char The character to convert.
126
127 @retval LowerCharacter If the Char is with range L'a' to L'z'.
128 @retval Unchanged Otherwise.
129
130
131 //Stolen from MdePkg Baselib
132 **/
133 CHAR16
134 EFIAPI
135 CharToUpper (
136 IN CHAR16 Char
137 )
138 {
139 if (Char >= L'a' && Char <= L'z') {
140 return (CHAR16) (Char - (L'a' - L'A'));
141 }
142
143 return Char;
144 }
145
146 /**
147 Function returns a system configuration table that is stored in the
148 EFI System Table based on the provided GUID.
149
150 @param[in] TableGuid A pointer to the table's GUID type.
151 @param[in, out] Table On exit, a pointer to a system configuration table.
152
153 @retval EFI_SUCCESS A configuration table matching TableGuid was found.
154 @retval EFI_NOT_FOUND A configuration table matching TableGuid was not found.
155 **/
156 EFI_STATUS
157 EFIAPI
158 GetSystemConfigurationTable (
159 IN EFI_GUID *TableGuid,
160 IN OUT VOID **Table
161 )
162 {
163 UINTN Index;
164 ASSERT (Table != NULL);
165
166 for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
167 if (CompareGuid (TableGuid, &(gST->ConfigurationTable[Index].VendorGuid))) {
168 *Table = gST->ConfigurationTable[Index].VendorTable;
169 return EFI_SUCCESS;
170 }
171 }
172
173 return EFI_NOT_FOUND;
174 }
175
176 /**
177 Convert a Unicode character to numerical value.
178
179 This internal function only deal with Unicode character
180 which maps to a valid hexadecimal ASII character, i.e.
181 L'0' to L'9', L'a' to L'f' or L'A' to L'F'. For other
182 Unicode character, the value returned does not make sense.
183
184 @param Char The character to convert.
185
186 @return The numerical value converted.
187
188 **/
189 UINTN
190 EFIAPI
191 HexCharToUintn (
192 IN CHAR16 Char
193 )
194 {
195 if (Char >= L'0' && Char <= L'9') {
196 return Char - L'0';
197 }
198
199 return (UINTN) (10 + CharToUpper (Char) - L'A');
200 }
201
202 /**
203 Convert a string representation of a guid to a Guid value.
204
205 @param[in] StringGuid The pointer to the string of a guid.
206 @param[in, out] Guid The pointer to the GUID structure to populate.
207
208 @retval EFI_INVALID_PARAMETER A parameter was invalid.
209 @retval EFI_SUCCESS The conversion was successful.
210 **/
211 EFI_STATUS
212 EFIAPI
213 ConvertStringToGuid (
214 IN CONST CHAR16 *StringGuid,
215 IN OUT EFI_GUID *Guid
216 )
217 {
218 CHAR16 *TempCopy;
219 CHAR16 *TempSpot;
220 CHAR16 *Walker;
221 UINT64 TempVal;
222 EFI_STATUS Status;
223
224 if (StringGuid == NULL) {
225 return (EFI_INVALID_PARAMETER);
226 } else if (StrLen(StringGuid) != 36) {
227 return (EFI_INVALID_PARAMETER);
228 }
229 TempCopy = NULL;
230 TempCopy = StrnCatGrow(&TempCopy, NULL, StringGuid, 0);
231 if (TempCopy == NULL) {
232 return (EFI_OUT_OF_RESOURCES);
233 }
234 Walker = TempCopy;
235 TempSpot = StrStr(Walker, L"-");
236 if (TempSpot != NULL) {
237 *TempSpot = CHAR_NULL;
238 }
239 Status = ShellConvertStringToUint64(Walker, &TempVal, TRUE, FALSE);
240 if (EFI_ERROR(Status)) {
241 FreePool(TempCopy);
242 return (Status);
243 }
244 Guid->Data1 = (UINT32)TempVal;
245 Walker += 9;
246 TempSpot = StrStr(Walker, L"-");
247 if (TempSpot != NULL) {
248 *TempSpot = CHAR_NULL;
249 }
250 Status = ShellConvertStringToUint64(Walker, &TempVal, TRUE, FALSE);
251 if (EFI_ERROR(Status)) {
252 FreePool(TempCopy);
253 return (Status);
254 }
255 Guid->Data2 = (UINT16)TempVal;
256 Walker += 5;
257 TempSpot = StrStr(Walker, L"-");
258 if (TempSpot != NULL) {
259 *TempSpot = CHAR_NULL;
260 }
261 Status = ShellConvertStringToUint64(Walker, &TempVal, TRUE, FALSE);
262 if (EFI_ERROR(Status)) {
263 FreePool(TempCopy);
264 return (Status);
265 }
266 Guid->Data3 = (UINT16)TempVal;
267 Walker += 5;
268 Guid->Data4[0] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
269 Guid->Data4[0] = (UINT8)(Guid->Data4[0]+ (UINT8)HexCharToUintn(Walker[1]));
270 Walker += 2;
271 Guid->Data4[1] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
272 Guid->Data4[1] = (UINT8)(Guid->Data4[1] + (UINT8)HexCharToUintn(Walker[1]));
273 Walker += 3;
274 Guid->Data4[2] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
275 Guid->Data4[2] = (UINT8)(Guid->Data4[2] + (UINT8)HexCharToUintn(Walker[1]));
276 Walker += 2;
277 Guid->Data4[3] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
278 Guid->Data4[3] = (UINT8)(Guid->Data4[3] + (UINT8)HexCharToUintn(Walker[1]));
279 Walker += 2;
280 Guid->Data4[4] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
281 Guid->Data4[4] = (UINT8)(Guid->Data4[4] + (UINT8)HexCharToUintn(Walker[1]));
282 Walker += 2;
283 Guid->Data4[5] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
284 Guid->Data4[5] = (UINT8)(Guid->Data4[5] + (UINT8)HexCharToUintn(Walker[1]));
285 Walker += 2;
286 Guid->Data4[6] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
287 Guid->Data4[6] = (UINT8)(Guid->Data4[6] + (UINT8)HexCharToUintn(Walker[1]));
288 Walker += 2;
289 Guid->Data4[7] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
290 Guid->Data4[7] = (UINT8)(Guid->Data4[7] + (UINT8)HexCharToUintn(Walker[1]));
291 FreePool(TempCopy);
292 return (EFI_SUCCESS);
293 }
294
295 /**
296 Clear the line at the specified Row.
297
298 @param[in] Row The row number to be cleared ( start from 1 )
299 @param[in] LastCol The last printable column.
300 @param[in] LastRow The last printable row.
301 **/
302 VOID
303 EFIAPI
304 EditorClearLine (
305 IN UINTN Row,
306 IN UINTN LastCol,
307 IN UINTN LastRow
308 )
309 {
310 CHAR16 Line[200];
311
312 if (Row == 0) {
313 Row = 1;
314 }
315
316 //
317 // prepare a blank line
318 //
319 SetMem16(Line, LastCol*sizeof(CHAR16), L' ');
320
321 if (Row == LastRow) {
322 //
323 // if CHAR_NULL is still at position 80, it will cause first line error
324 //
325 Line[LastCol - 1] = CHAR_NULL;
326 } else {
327 Line[LastCol] = CHAR_NULL;
328 }
329
330 //
331 // print out the blank line
332 //
333 ShellPrintEx (0, ((INT32)Row) - 1, Line);
334 }
335
336 /**
337 Determine if the character is valid for a filename.
338
339 @param[in] Ch The character to test.
340
341 @retval TRUE The character is valid.
342 @retval FALSE The character is not valid.
343 **/
344 BOOLEAN
345 EFIAPI
346 IsValidFileNameChar (
347 IN CONST CHAR16 Ch
348 )
349 {
350 //
351 // See if there are any illegal characters within the name
352 //
353 if (Ch < 0x20 || Ch == L'\"' || Ch == L'*' || Ch == L'/' || Ch == L'<' || Ch == L'>' || Ch == L'?' || Ch == L'|') {
354 return FALSE;
355 }
356
357 return TRUE;
358 }
359
360 /**
361 Check if file name has illegal characters.
362
363 @param Name The filename to check.
364
365 @retval TRUE The filename is ok.
366 @retval FALSE The filename is not ok.
367 **/
368 BOOLEAN
369 EFIAPI
370 IsValidFileName (
371 IN CONST CHAR16 *Name
372 )
373 {
374
375 UINTN Index;
376 UINTN Len;
377
378 //
379 // check the length of Name
380 //
381 for (Len = 0, Index = StrLen (Name) - 1; Index + 1 != 0; Index--, Len++) {
382 if (Name[Index] == '\\' || Name[Index] == ':') {
383 break;
384 }
385 }
386
387 if (Len == 0 || Len > 255) {
388 return FALSE;
389 }
390 //
391 // check whether any char in Name not appears in valid file name char
392 //
393 for (Index = 0; Index < StrLen (Name); Index++) {
394 if (!IsValidFileNameChar (Name[Index])) {
395 return FALSE;
396 }
397 }
398
399 return TRUE;
400 }
401
402 /**
403 Find a filename that is valid (not taken) with the given extension.
404
405 @param[in] Extension The file extension.
406
407 @retval NULL Something went wrong.
408 @return the valid filename.
409 **/
410 CHAR16 *
411 EFIAPI
412 EditGetDefaultFileName (
413 IN CONST CHAR16 *Extension
414 )
415 {
416 EFI_STATUS Status;
417 UINTN Suffix;
418 CHAR16 *FileNameTmp;
419
420 Suffix = 0;
421
422 do {
423 FileNameTmp = CatSPrint (NULL, L"NewFile%d.%s", Suffix, Extension);
424
425 //
426 // after that filename changed to path
427 //
428 Status = ShellFileExists (FileNameTmp);
429
430 if (Status == EFI_NOT_FOUND) {
431 return FileNameTmp;
432 }
433
434 FreePool (FileNameTmp);
435 FileNameTmp = NULL;
436 Suffix++;
437 } while (Suffix != 0);
438
439 FreePool (FileNameTmp);
440 return NULL;
441 }
442
443 /**
444 Read a file into an allocated buffer. The buffer is the responsibility
445 of the caller to free.
446
447 @param[in] FileName The filename of the file to open.
448 @param[out] Buffer Upon successful return, the pointer to the
449 address of the allocated buffer.
450 @param[out] BufferSize If not NULL, then the pointer to the size
451 of the allocated buffer.
452 @param[out] ReadOnly Upon successful return TRUE if the file is
453 read only. FALSE otherwise.
454
455 @retval EFI_NOT_FOUND The filename did not represent a file in the
456 file system.
457 @retval EFI_SUCCESS The file was read into the buffer.
458 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
459 @retval EFI_LOAD_ERROR The file read operation failed.
460 @retval EFI_INVALID_PARAMETER A parameter was invalid.
461 @retval EFI_INVALID_PARAMETER FileName was NULL.
462 @retval EFI_INVALID_PARAMETER FileName was a directory.
463 **/
464 EFI_STATUS
465 EFIAPI
466 ReadFileIntoBuffer (
467 IN CONST CHAR16 *FileName,
468 OUT VOID **Buffer,
469 OUT UINTN *BufferSize OPTIONAL,
470 OUT BOOLEAN *ReadOnly
471 )
472 {
473 VOID *InternalBuffer;
474 UINTN FileSize;
475 SHELL_FILE_HANDLE FileHandle;
476 BOOLEAN CreateFile;
477 EFI_STATUS Status;
478 EFI_FILE_INFO *Info;
479
480 InternalBuffer = NULL;
481 FileSize = 0;
482 FileHandle = NULL;
483 CreateFile = FALSE;
484 Status = EFI_SUCCESS;
485 Info = NULL;
486
487 if (FileName == NULL || Buffer == NULL || ReadOnly == NULL) {
488 return (EFI_INVALID_PARAMETER);
489 }
490
491 //
492 // try to open the file
493 //
494 Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ, 0);
495
496 if (!EFI_ERROR(Status)) {
497 ASSERT(CreateFile == FALSE);
498 if (FileHandle == NULL) {
499 return EFI_LOAD_ERROR;
500 }
501
502 Info = ShellGetFileInfo(FileHandle);
503
504 if (Info->Attribute & EFI_FILE_DIRECTORY) {
505 FreePool (Info);
506 return EFI_INVALID_PARAMETER;
507 }
508
509 if (Info->Attribute & EFI_FILE_READ_ONLY) {
510 *ReadOnly = TRUE;
511 } else {
512 *ReadOnly = FALSE;
513 }
514 //
515 // get file size
516 //
517 FileSize = (UINTN) Info->FileSize;
518
519 FreePool (Info);
520 } else if (Status == EFI_NOT_FOUND) {
521 //
522 // file not exists. add create and try again
523 //
524 Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);
525 if (EFI_ERROR (Status)) {
526 return Status;
527 } else {
528 //
529 // it worked. now delete it and move on with the name (now validated)
530 //
531 Status = ShellDeleteFile (&FileHandle);
532 if (Status == EFI_WARN_DELETE_FAILURE) {
533 Status = EFI_ACCESS_DENIED;
534 }
535 if (EFI_ERROR (Status)) {
536 return Status;
537 }
538 }
539 //
540 // file doesn't exist, so set CreateFile to TRUE and can't be read-only
541 //
542 CreateFile = TRUE;
543 *ReadOnly = FALSE;
544 }
545
546 //
547 // the file exists
548 //
549 if (!CreateFile) {
550 //
551 // allocate buffer to read file
552 //
553 InternalBuffer = AllocateZeroPool (FileSize);
554 if (InternalBuffer == NULL) {
555 return EFI_OUT_OF_RESOURCES;
556 }
557 //
558 // read file into InternalBuffer
559 //
560 Status = ShellReadFile (FileHandle, &FileSize, InternalBuffer);
561 ShellCloseFile(&FileHandle);
562 FileHandle = NULL;
563 if (EFI_ERROR (Status)) {
564 SHELL_FREE_NON_NULL (InternalBuffer);
565 return EFI_LOAD_ERROR;
566 }
567 }
568 *Buffer = InternalBuffer;
569 if (BufferSize != NULL) {
570 *BufferSize = FileSize;
571 }
572 return (EFI_SUCCESS);
573
574 }