]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellLevel3CommandsLib/Type.c
ShellPkg/Type.c: Add value check before (LoopVar - 1)
[mirror_edk2.git] / ShellPkg / Library / UefiShellLevel3CommandsLib / Type.c
1 /** @file
2 Main file for Type shell level 3 function.
3
4 (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
5 Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved. <BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7
8 **/
9
10 #include "UefiShellLevel3CommandsLib.h"
11
12 #include <Library/ShellLib.h>
13
14 /**
15 Display a single file to StdOut.
16
17 If both Ascii and UCS2 are FALSE attempt to discover the file type.
18
19 @param[in] Handle The handle to the file to display.
20 @param[in] Ascii TRUE to force ASCII, FALSE othewise.
21 @param[in] UCS2 TRUE to force UCS2, FALSE othewise.
22
23 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
24 @retval EFI_SUCCESS The operation was successful.
25 **/
26 EFI_STATUS
27 TypeFileByHandle (
28 IN SHELL_FILE_HANDLE Handle,
29 IN BOOLEAN Ascii,
30 IN BOOLEAN UCS2
31 )
32 {
33 UINTN ReadSize;
34 VOID *Buffer;
35 VOID *AllocatedBuffer;
36 EFI_STATUS Status;
37 UINTN LoopVar;
38 UINTN LoopSize;
39 CHAR16 AsciiChar;
40 CHAR16 Ucs2Char;
41
42 ReadSize = PcdGet32(PcdShellFileOperationSize);
43 AllocatedBuffer = AllocateZeroPool(ReadSize);
44 if (AllocatedBuffer == NULL) {
45 return (EFI_OUT_OF_RESOURCES);
46 }
47
48 Status = ShellSetFilePosition(Handle, 0);
49 ASSERT_EFI_ERROR(Status);
50
51 while (ReadSize == ((UINTN)PcdGet32(PcdShellFileOperationSize))) {
52 Buffer = AllocatedBuffer;
53 ZeroMem(Buffer, ReadSize);
54 Status = ShellReadFile(Handle, &ReadSize, Buffer);
55 if (EFI_ERROR(Status)){
56 break;
57 }
58
59 if (!(Ascii|UCS2)) {
60 if (*(UINT16*)Buffer == gUnicodeFileTag) {
61 UCS2 = TRUE;
62 } else {
63 Ascii = TRUE;
64 }
65 }
66
67 if (Ascii) {
68 LoopSize = ReadSize;
69 for (LoopVar = 0 ; LoopVar < LoopSize ; LoopVar++) {
70 //
71 // The valid range of ASCII characters is 0x20-0x7E.
72 // Display "." when there is an invalid character.
73 //
74 AsciiChar = CHAR_NULL;
75 AsciiChar = ((CHAR8*)Buffer)[LoopVar];
76 if (AsciiChar == '\r' || AsciiChar == '\n') {
77 //
78 // Allow Line Feed (LF) (0xA) & Carriage Return (CR) (0xD)
79 // characters to be displayed as is.
80 //
81 if ((AsciiChar == '\n' && LoopVar == 0) ||
82 (AsciiChar == '\n' && ((CHAR8*)Buffer)[LoopVar-1] != '\r')) {
83 //
84 // In case file begin with single line Feed or Line Feed (0xA) is
85 // encountered & Carriage Return (0xD) was not previous character,
86 // print CR and LF. This is because Shell 2.0 requires carriage
87 // return with line feed for displaying each new line from left.
88 //
89 ShellPrintEx (-1, -1, L"\r\n");
90 continue;
91 }
92 } else {
93 //
94 // For all other characters which are not printable, display '.'
95 //
96 if (AsciiChar < 0x20 || AsciiChar >= 0x7F) {
97 AsciiChar = '.';
98 }
99 }
100 ShellPrintEx (-1, -1, L"%c", AsciiChar);
101 }
102 } else {
103 if (*(UINT16*)Buffer == gUnicodeFileTag) {
104 //
105 // For unicode files, skip displaying the byte order marker.
106 //
107 Buffer = ((UINT16*)Buffer) + 1;
108 LoopSize = (ReadSize / (sizeof (CHAR16))) - 1;
109 } else {
110 LoopSize = ReadSize / (sizeof (CHAR16));
111 }
112
113 for (LoopVar = 0 ; LoopVar < LoopSize ; LoopVar++) {
114 //
115 // An invalid range of characters is 0x0-0x1F.
116 // Display "." when there is an invalid character.
117 //
118 Ucs2Char = CHAR_NULL;
119 Ucs2Char = ((CHAR16*)Buffer)[LoopVar];
120 if (Ucs2Char == '\r' || Ucs2Char == '\n') {
121 //
122 // Allow Line Feed (LF) (0xA) & Carriage Return (CR) (0xD)
123 // characters to be displayed as is.
124 //
125 if ((Ucs2Char == '\n' && LoopVar == 0) ||
126 (Ucs2Char == '\n' && ((CHAR16*)Buffer)[LoopVar-1] != '\r')) {
127 //
128 // In case file begin with single line Feed or Line Feed (0xA) is
129 // encountered & Carriage Return (0xD) was not previous character,
130 // print CR and LF. This is because Shell 2.0 requires carriage
131 // return with line feed for displaying each new line from left.
132 //
133 ShellPrintEx (-1, -1, L"\r\n");
134 continue;
135 }
136 }
137 else if (Ucs2Char < 0x20) {
138 //
139 // For all other characters which are not printable, display '.'
140 //
141 Ucs2Char = L'.';
142 }
143 ShellPrintEx (-1, -1, L"%c", Ucs2Char);
144 }
145 }
146
147 if (ShellGetExecutionBreakFlag()) {
148 break;
149 }
150 }
151 FreePool (AllocatedBuffer);
152 ShellPrintEx (-1, -1, L"\r\n");
153 return (Status);
154 }
155
156 STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
157 {L"-a", TypeFlag},
158 {L"-u", TypeFlag},
159 {NULL, TypeMax}
160 };
161
162 /**
163 Function for 'type' command.
164
165 @param[in] ImageHandle Handle to the Image (NULL if Internal).
166 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
167 **/
168 SHELL_STATUS
169 EFIAPI
170 ShellCommandRunType (
171 IN EFI_HANDLE ImageHandle,
172 IN EFI_SYSTEM_TABLE *SystemTable
173 )
174 {
175 EFI_STATUS Status;
176 LIST_ENTRY *Package;
177 CHAR16 *ProblemParam;
178 CONST CHAR16 *Param;
179 SHELL_STATUS ShellStatus;
180 UINTN ParamCount;
181 EFI_SHELL_FILE_INFO *FileList;
182 EFI_SHELL_FILE_INFO *Node;
183 BOOLEAN AsciiMode;
184 BOOLEAN UnicodeMode;
185
186 ProblemParam = NULL;
187 ShellStatus = SHELL_SUCCESS;
188 ParamCount = 0;
189 FileList = NULL;
190
191 //
192 // initialize the shell lib (we must be in non-auto-init...)
193 //
194 Status = ShellInitialize();
195 ASSERT_EFI_ERROR(Status);
196
197 Status = CommandInit();
198 ASSERT_EFI_ERROR(Status);
199
200 //
201 // parse the command line
202 //
203 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
204 if (EFI_ERROR(Status)) {
205 if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
206 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, L"type", ProblemParam);
207 FreePool(ProblemParam);
208 ShellStatus = SHELL_INVALID_PARAMETER;
209 } else {
210 ASSERT(FALSE);
211 }
212 } else {
213 //
214 // check for "-?"
215 //
216 if (ShellCommandLineGetFlag(Package, L"-?")) {
217 ASSERT(FALSE);
218 }
219 AsciiMode = ShellCommandLineGetFlag(Package, L"-a");
220 UnicodeMode = ShellCommandLineGetFlag(Package, L"-u");
221
222 if (AsciiMode && UnicodeMode) {
223 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel3HiiHandle, L"type", L"-a & -u");
224 ShellStatus = SHELL_INVALID_PARAMETER;
225 } else if (ShellCommandLineGetRawValue(Package, 1) == NULL) {
226 //
227 // we insufficient parameters
228 //
229 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel3HiiHandle, L"type");
230 ShellStatus = SHELL_INVALID_PARAMETER;
231 } else {
232 //
233 // get a list with each file specified by parameters
234 // if parameter is a directory then add all the files below it to the list
235 //
236 for ( ParamCount = 1, Param = ShellCommandLineGetRawValue(Package, ParamCount)
237 ; Param != NULL
238 ; ParamCount++, Param = ShellCommandLineGetRawValue(Package, ParamCount)
239 ){
240 Status = ShellOpenFileMetaArg((CHAR16*)Param, EFI_FILE_MODE_READ, &FileList);
241 if (EFI_ERROR(Status)) {
242 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel3HiiHandle, L"type", (CHAR16*)Param);
243 ShellStatus = SHELL_NOT_FOUND;
244 break;
245 }
246 //
247 // make sure we completed the param parsing sucessfully...
248 // Also make sure that any previous action was sucessful
249 //
250 if (ShellStatus == SHELL_SUCCESS) {
251 //
252 // check that we have at least 1 file
253 //
254 if (FileList == NULL || IsListEmpty(&FileList->Link)) {
255 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel3HiiHandle, L"type", Param);
256 continue;
257 } else {
258 //
259 // loop through the list and make sure we are not aborting...
260 //
261 for ( Node = (EFI_SHELL_FILE_INFO*)GetFirstNode(&FileList->Link)
262 ; !IsNull(&FileList->Link, &Node->Link) && !ShellGetExecutionBreakFlag()
263 ; Node = (EFI_SHELL_FILE_INFO*)GetNextNode(&FileList->Link, &Node->Link)
264 ){
265
266 if (ShellGetExecutionBreakFlag()) {
267 break;
268 }
269
270 //
271 // make sure the file opened ok
272 //
273 if (EFI_ERROR(Node->Status)){
274 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel3HiiHandle, L"type", Node->FileName);
275 ShellStatus = SHELL_NOT_FOUND;
276 continue;
277 }
278
279 //
280 // make sure its not a directory
281 //
282 if (FileHandleIsDirectory(Node->Handle) == EFI_SUCCESS) {
283 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_IS_DIR), gShellLevel3HiiHandle, L"type", Node->FileName);
284 ShellStatus = SHELL_NOT_FOUND;
285 continue;
286 }
287
288 //
289 // do it
290 //
291 Status = TypeFileByHandle (Node->Handle, AsciiMode, UnicodeMode);
292 if (EFI_ERROR(Status)) {
293 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TYP_ERROR), gShellLevel3HiiHandle, L"type", Node->FileName);
294 ShellStatus = SHELL_INVALID_PARAMETER;
295 }
296 ASSERT(ShellStatus == SHELL_SUCCESS);
297 }
298 }
299 }
300 //
301 // Free the fileList
302 //
303 if (FileList != NULL && !IsListEmpty(&FileList->Link)) {
304 Status = ShellCloseFileMetaArg(&FileList);
305 }
306 ASSERT_EFI_ERROR(Status);
307 FileList = NULL;
308 }
309 }
310
311 //
312 // free the command line package
313 //
314 ShellCommandLineFreeVarList (Package);
315 }
316
317 if (ShellGetExecutionBreakFlag()) {
318 return (SHELL_ABORTED);
319 }
320
321 return (ShellStatus);
322 }
323