]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.c
Shellpkg/editor: Fix a bug that may modifies Line[-1]
[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 - 2017, 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 CharToUpper (
135 IN CHAR16 Char
136 )
137 {
138 if (Char >= L'a' && Char <= L'z') {
139 return (CHAR16) (Char - (L'a' - L'A'));
140 }
141
142 return Char;
143 }
144
145 /**
146 Function returns a system configuration table that is stored in the
147 EFI System Table based on the provided GUID.
148
149 @param[in] TableGuid A pointer to the table's GUID type.
150 @param[in, out] Table On exit, a pointer to a system configuration table.
151
152 @retval EFI_SUCCESS A configuration table matching TableGuid was found.
153 @retval EFI_NOT_FOUND A configuration table matching TableGuid was not found.
154 **/
155 EFI_STATUS
156 GetSystemConfigurationTable (
157 IN EFI_GUID *TableGuid,
158 IN OUT VOID **Table
159 )
160 {
161 UINTN Index;
162 ASSERT (Table != NULL);
163
164 for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
165 if (CompareGuid (TableGuid, &(gST->ConfigurationTable[Index].VendorGuid))) {
166 *Table = gST->ConfigurationTable[Index].VendorTable;
167 return EFI_SUCCESS;
168 }
169 }
170
171 return EFI_NOT_FOUND;
172 }
173
174 /**
175 Clear the line at the specified Row.
176
177 @param[in] Row The row number to be cleared ( start from 1 )
178 @param[in] LastCol The last printable column.
179 @param[in] LastRow The last printable row.
180 **/
181 VOID
182 EditorClearLine (
183 IN UINTN Row,
184 IN UINTN LastCol,
185 IN UINTN LastRow
186 )
187 {
188 UINTN Col;
189 CHAR16 Line[200];
190
191 if (Row == 0) {
192 Row = 1;
193 }
194
195 //
196 // prepare a blank line
197 // If max column is larger, split to multiple prints.
198 //
199 SetMem16 (Line, sizeof (Line), L' ');
200 Line[ARRAY_SIZE (Line) - 1] = CHAR_NULL;
201
202 for (Col = 1; Col <= LastCol; Col += ARRAY_SIZE (Line) - 1) {
203 if (Col + ARRAY_SIZE (Line) - 1 > LastCol) {
204 if (Row == LastRow) {
205 //
206 // if CHAR_NULL is still at position LastCol, it will cause first line error
207 //
208 Line[(LastCol - 1) % (ARRAY_SIZE (Line) - 1)] = CHAR_NULL;
209 } else {
210 Line[LastCol % (ARRAY_SIZE (Line) - 1)] = CHAR_NULL;
211 }
212 }
213
214 //
215 // print out the blank line
216 //
217 ShellPrintEx ((INT32) Col - 1, (INT32) Row - 1, Line);
218 }
219 }
220
221 /**
222 Determine if the character is valid for a filename.
223
224 @param[in] Ch The character to test.
225
226 @retval TRUE The character is valid.
227 @retval FALSE The character is not valid.
228 **/
229 BOOLEAN
230 IsValidFileNameChar (
231 IN CONST CHAR16 Ch
232 )
233 {
234 //
235 // See if there are any illegal characters within the name
236 //
237 if (Ch < 0x20 || Ch == L'\"' || Ch == L'*' || Ch == L'/' || Ch == L'<' || Ch == L'>' || Ch == L'?' || Ch == L'|') {
238 return FALSE;
239 }
240
241 return TRUE;
242 }
243
244 /**
245 Check if file name has illegal characters.
246
247 @param Name The filename to check.
248
249 @retval TRUE The filename is ok.
250 @retval FALSE The filename is not ok.
251 **/
252 BOOLEAN
253 IsValidFileName (
254 IN CONST CHAR16 *Name
255 )
256 {
257
258 UINTN Index;
259 UINTN Len;
260
261 //
262 // check the length of Name
263 //
264 for (Len = 0, Index = StrLen (Name) - 1; Index + 1 != 0; Index--, Len++) {
265 if (Name[Index] == '\\' || Name[Index] == ':') {
266 break;
267 }
268 }
269
270 if (Len == 0 || Len > 255) {
271 return FALSE;
272 }
273 //
274 // check whether any char in Name not appears in valid file name char
275 //
276 for (Index = 0; Index < StrLen (Name); Index++) {
277 if (!IsValidFileNameChar (Name[Index])) {
278 return FALSE;
279 }
280 }
281
282 return TRUE;
283 }
284
285 /**
286 Find a filename that is valid (not taken) with the given extension.
287
288 @param[in] Extension The file extension.
289
290 @retval NULL Something went wrong.
291 @return the valid filename.
292 **/
293 CHAR16 *
294 EditGetDefaultFileName (
295 IN CONST CHAR16 *Extension
296 )
297 {
298 EFI_STATUS Status;
299 UINTN Suffix;
300 CHAR16 *FileNameTmp;
301
302 Suffix = 0;
303
304 do {
305 FileNameTmp = CatSPrint (NULL, L"NewFile%d.%s", Suffix, Extension);
306
307 //
308 // after that filename changed to path
309 //
310 Status = ShellFileExists (FileNameTmp);
311
312 if (Status == EFI_NOT_FOUND) {
313 return FileNameTmp;
314 }
315
316 FreePool (FileNameTmp);
317 FileNameTmp = NULL;
318 Suffix++;
319 } while (Suffix != 0);
320
321 FreePool (FileNameTmp);
322 return NULL;
323 }
324
325 /**
326 Read a file into an allocated buffer. The buffer is the responsibility
327 of the caller to free.
328
329 @param[in] FileName The filename of the file to open.
330 @param[out] Buffer Upon successful return, the pointer to the
331 address of the allocated buffer.
332 @param[out] BufferSize If not NULL, then the pointer to the size
333 of the allocated buffer.
334 @param[out] ReadOnly Upon successful return TRUE if the file is
335 read only. FALSE otherwise.
336
337 @retval EFI_NOT_FOUND The filename did not represent a file in the
338 file system.
339 @retval EFI_SUCCESS The file was read into the buffer.
340 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
341 @retval EFI_LOAD_ERROR The file read operation failed.
342 @retval EFI_INVALID_PARAMETER A parameter was invalid.
343 @retval EFI_INVALID_PARAMETER FileName was NULL.
344 @retval EFI_INVALID_PARAMETER FileName was a directory.
345 **/
346 EFI_STATUS
347 ReadFileIntoBuffer (
348 IN CONST CHAR16 *FileName,
349 OUT VOID **Buffer,
350 OUT UINTN *BufferSize OPTIONAL,
351 OUT BOOLEAN *ReadOnly
352 )
353 {
354 VOID *InternalBuffer;
355 UINTN FileSize;
356 SHELL_FILE_HANDLE FileHandle;
357 BOOLEAN CreateFile;
358 EFI_STATUS Status;
359 EFI_FILE_INFO *Info;
360
361 InternalBuffer = NULL;
362 FileSize = 0;
363 FileHandle = NULL;
364 CreateFile = FALSE;
365 Status = EFI_SUCCESS;
366 Info = NULL;
367
368 if (FileName == NULL || Buffer == NULL || ReadOnly == NULL) {
369 return (EFI_INVALID_PARAMETER);
370 }
371
372 //
373 // try to open the file
374 //
375 Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ, 0);
376
377 if (!EFI_ERROR(Status)) {
378 ASSERT(CreateFile == FALSE);
379 if (FileHandle == NULL) {
380 return EFI_LOAD_ERROR;
381 }
382
383 Info = ShellGetFileInfo(FileHandle);
384
385 if (Info->Attribute & EFI_FILE_DIRECTORY) {
386 FreePool (Info);
387 return EFI_INVALID_PARAMETER;
388 }
389
390 if (Info->Attribute & EFI_FILE_READ_ONLY) {
391 *ReadOnly = TRUE;
392 } else {
393 *ReadOnly = FALSE;
394 }
395 //
396 // get file size
397 //
398 FileSize = (UINTN) Info->FileSize;
399
400 FreePool (Info);
401 } else if (Status == EFI_NOT_FOUND) {
402 //
403 // file not exists. add create and try again
404 //
405 Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);
406 if (EFI_ERROR (Status)) {
407 return Status;
408 } else {
409 //
410 // it worked. now delete it and move on with the name (now validated)
411 //
412 Status = ShellDeleteFile (&FileHandle);
413 if (Status == EFI_WARN_DELETE_FAILURE) {
414 Status = EFI_ACCESS_DENIED;
415 }
416 if (EFI_ERROR (Status)) {
417 return Status;
418 }
419 }
420 //
421 // file doesn't exist, so set CreateFile to TRUE and can't be read-only
422 //
423 CreateFile = TRUE;
424 *ReadOnly = FALSE;
425 }
426
427 //
428 // the file exists
429 //
430 if (!CreateFile) {
431 //
432 // allocate buffer to read file
433 //
434 InternalBuffer = AllocateZeroPool (FileSize);
435 if (InternalBuffer == NULL) {
436 return EFI_OUT_OF_RESOURCES;
437 }
438 //
439 // read file into InternalBuffer
440 //
441 Status = ShellReadFile (FileHandle, &FileSize, InternalBuffer);
442 ShellCloseFile(&FileHandle);
443 FileHandle = NULL;
444 if (EFI_ERROR (Status)) {
445 SHELL_FREE_NON_NULL (InternalBuffer);
446 return EFI_LOAD_ERROR;
447 }
448 }
449 *Buffer = InternalBuffer;
450 if (BufferSize != NULL) {
451 *BufferSize = FileSize;
452 }
453 return (EFI_SUCCESS);
454
455 }