]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellLevel3CommandsLib/Type.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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 //
85 // In case file begin with single line Feed or Line Feed (0xA) is
86 // encountered & Carriage Return (0xD) was not previous character,
87 // print CR and LF. This is because Shell 2.0 requires carriage
88 // return with line feed for displaying each new line from left.
89 //
90 ShellPrintEx (-1, -1, L"\r\n");
91 continue;
92 }
93 } else {
94 //
95 // For all other characters which are not printable, display '.'
96 //
97 if ((AsciiChar < 0x20) || (AsciiChar >= 0x7F)) {
98 AsciiChar = '.';
99 }
100 }
101
102 ShellPrintEx (-1, -1, L"%c", AsciiChar);
103 }
104 } else {
105 if (*(UINT16 *)Buffer == gUnicodeFileTag) {
106 //
107 // For unicode files, skip displaying the byte order marker.
108 //
109 Buffer = ((UINT16 *)Buffer) + 1;
110 LoopSize = (ReadSize / (sizeof (CHAR16))) - 1;
111 } else {
112 LoopSize = ReadSize / (sizeof (CHAR16));
113 }
114
115 for (LoopVar = 0; LoopVar < LoopSize; LoopVar++) {
116 //
117 // An invalid range of characters is 0x0-0x1F.
118 // Display "." when there is an invalid character.
119 //
120 Ucs2Char = CHAR_NULL;
121 Ucs2Char = ((CHAR16 *)Buffer)[LoopVar];
122 if ((Ucs2Char == '\r') || (Ucs2Char == '\n')) {
123 //
124 // Allow Line Feed (LF) (0xA) & Carriage Return (CR) (0xD)
125 // characters to be displayed as is.
126 //
127 if (((Ucs2Char == '\n') && (LoopVar == 0)) ||
128 ((Ucs2Char == '\n') && (((CHAR16 *)Buffer)[LoopVar-1] != '\r')))
129 {
130 //
131 // In case file begin with single line Feed or Line Feed (0xA) is
132 // encountered & Carriage Return (0xD) was not previous character,
133 // print CR and LF. This is because Shell 2.0 requires carriage
134 // return with line feed for displaying each new line from left.
135 //
136 ShellPrintEx (-1, -1, L"\r\n");
137 continue;
138 }
139 } else if (Ucs2Char < 0x20) {
140 //
141 // For all other characters which are not printable, display '.'
142 //
143 Ucs2Char = L'.';
144 }
145
146 ShellPrintEx (-1, -1, L"%c", Ucs2Char);
147 }
148 }
149
150 if (ShellGetExecutionBreakFlag ()) {
151 break;
152 }
153 }
154
155 FreePool (AllocatedBuffer);
156 ShellPrintEx (-1, -1, L"\r\n");
157 return (Status);
158 }
159
160 STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
161 { L"-a", TypeFlag },
162 { L"-u", TypeFlag },
163 { NULL, TypeMax }
164 };
165
166 /**
167 Function for 'type' command.
168
169 @param[in] ImageHandle Handle to the Image (NULL if Internal).
170 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
171 **/
172 SHELL_STATUS
173 EFIAPI
174 ShellCommandRunType (
175 IN EFI_HANDLE ImageHandle,
176 IN EFI_SYSTEM_TABLE *SystemTable
177 )
178 {
179 EFI_STATUS Status;
180 LIST_ENTRY *Package;
181 CHAR16 *ProblemParam;
182 CONST CHAR16 *Param;
183 SHELL_STATUS ShellStatus;
184 UINTN ParamCount;
185 EFI_SHELL_FILE_INFO *FileList;
186 EFI_SHELL_FILE_INFO *Node;
187 BOOLEAN AsciiMode;
188 BOOLEAN UnicodeMode;
189
190 ProblemParam = NULL;
191 ShellStatus = SHELL_SUCCESS;
192 ParamCount = 0;
193 FileList = NULL;
194
195 //
196 // initialize the shell lib (we must be in non-auto-init...)
197 //
198 Status = ShellInitialize ();
199 ASSERT_EFI_ERROR (Status);
200
201 Status = CommandInit ();
202 ASSERT_EFI_ERROR (Status);
203
204 //
205 // parse the command line
206 //
207 Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
208 if (EFI_ERROR (Status)) {
209 if ((Status == EFI_VOLUME_CORRUPTED) && (ProblemParam != NULL)) {
210 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, L"type", ProblemParam);
211 FreePool (ProblemParam);
212 ShellStatus = SHELL_INVALID_PARAMETER;
213 } else {
214 ASSERT (FALSE);
215 }
216 } else {
217 //
218 // check for "-?"
219 //
220 if (ShellCommandLineGetFlag (Package, L"-?")) {
221 ASSERT (FALSE);
222 }
223
224 AsciiMode = ShellCommandLineGetFlag (Package, L"-a");
225 UnicodeMode = ShellCommandLineGetFlag (Package, L"-u");
226
227 if (AsciiMode && UnicodeMode) {
228 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel3HiiHandle, L"type", L"-a & -u");
229 ShellStatus = SHELL_INVALID_PARAMETER;
230 } else if (ShellCommandLineGetRawValue (Package, 1) == NULL) {
231 //
232 // we insufficient parameters
233 //
234 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel3HiiHandle, L"type");
235 ShellStatus = SHELL_INVALID_PARAMETER;
236 } else {
237 //
238 // get a list with each file specified by parameters
239 // if parameter is a directory then add all the files below it to the list
240 //
241 for ( ParamCount = 1, Param = ShellCommandLineGetRawValue (Package, ParamCount)
242 ; Param != NULL
243 ; ParamCount++, Param = ShellCommandLineGetRawValue (Package, ParamCount)
244 )
245 {
246 Status = ShellOpenFileMetaArg ((CHAR16 *)Param, EFI_FILE_MODE_READ, &FileList);
247 if (EFI_ERROR (Status)) {
248 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel3HiiHandle, L"type", (CHAR16 *)Param);
249 ShellStatus = SHELL_NOT_FOUND;
250 break;
251 }
252
253 //
254 // make sure we completed the param parsing sucessfully...
255 // Also make sure that any previous action was sucessful
256 //
257 if (ShellStatus == SHELL_SUCCESS) {
258 //
259 // check that we have at least 1 file
260 //
261 if ((FileList == NULL) || IsListEmpty (&FileList->Link)) {
262 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel3HiiHandle, L"type", Param);
263 continue;
264 } else {
265 //
266 // loop through the list and make sure we are not aborting...
267 //
268 for ( Node = (EFI_SHELL_FILE_INFO *)GetFirstNode (&FileList->Link)
269 ; !IsNull (&FileList->Link, &Node->Link) && !ShellGetExecutionBreakFlag ()
270 ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode (&FileList->Link, &Node->Link)
271 )
272 {
273 if (ShellGetExecutionBreakFlag ()) {
274 break;
275 }
276
277 //
278 // make sure the file opened ok
279 //
280 if (EFI_ERROR (Node->Status)) {
281 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel3HiiHandle, L"type", Node->FileName);
282 ShellStatus = SHELL_NOT_FOUND;
283 continue;
284 }
285
286 //
287 // make sure its not a directory
288 //
289 if (FileHandleIsDirectory (Node->Handle) == EFI_SUCCESS) {
290 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_IS_DIR), gShellLevel3HiiHandle, L"type", Node->FileName);
291 ShellStatus = SHELL_NOT_FOUND;
292 continue;
293 }
294
295 //
296 // do it
297 //
298 Status = TypeFileByHandle (Node->Handle, AsciiMode, UnicodeMode);
299 if (EFI_ERROR (Status)) {
300 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_TYP_ERROR), gShellLevel3HiiHandle, L"type", Node->FileName);
301 ShellStatus = SHELL_INVALID_PARAMETER;
302 }
303
304 ASSERT (ShellStatus == SHELL_SUCCESS);
305 }
306 }
307 }
308
309 //
310 // Free the fileList
311 //
312 if ((FileList != NULL) && !IsListEmpty (&FileList->Link)) {
313 Status = ShellCloseFileMetaArg (&FileList);
314 }
315
316 ASSERT_EFI_ERROR (Status);
317 FileList = NULL;
318 }
319 }
320
321 //
322 // free the command line package
323 //
324 ShellCommandLineFreeVarList (Package);
325 }
326
327 if (ShellGetExecutionBreakFlag ()) {
328 return (SHELL_ABORTED);
329 }
330
331 return (ShellStatus);
332 }