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 - 2011, Intel Corporation. All rights reserved. <BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include "UefiShellLevel3CommandsLib.h"
17
18 #include <Library/ShellLib.h>
19
20 /**
21 Display a single file to StdOut.
22
23 If both Ascii and UCS2 are FALSE attempt to discover the file type.
24
25 @param[in] Handle The handle to the file to display.
26 @param[in] Ascii TRUE to force ASCII, FALSE othewise.
27 @param[in] UCS2 TRUE to force UCS2, FALSE othewise.
28
29 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
30 @retval EFI_SUCCESS The operation was successful.
31 **/
32 EFI_STATUS
TypeFileByHandle(IN SHELL_FILE_HANDLE Handle,IN BOOLEAN Ascii,IN BOOLEAN UCS2)33 TypeFileByHandle (
34 IN SHELL_FILE_HANDLE Handle,
35 IN BOOLEAN Ascii,
36 IN BOOLEAN UCS2
37 )
38 {
39 UINTN ReadSize;
40 VOID *Buffer;
41 VOID *AllocatedBuffer;
42 EFI_STATUS Status;
43 UINTN LoopVar;
44 UINTN LoopSize;
45 CHAR16 AsciiChar;
46 CHAR16 Ucs2Char;
47
48 ReadSize = PcdGet32(PcdShellFileOperationSize);
49 AllocatedBuffer = AllocateZeroPool(ReadSize);
50 if (AllocatedBuffer == NULL) {
51 return (EFI_OUT_OF_RESOURCES);
52 }
53
54 Status = ShellSetFilePosition(Handle, 0);
55 ASSERT_EFI_ERROR(Status);
56
57 while (ReadSize == ((UINTN)PcdGet32(PcdShellFileOperationSize))) {
58 Buffer = AllocatedBuffer;
59 ZeroMem(Buffer, ReadSize);
60 Status = ShellReadFile(Handle, &ReadSize, Buffer);
61 if (EFI_ERROR(Status)){
62 break;
63 }
64
65 if (!(Ascii|UCS2)) {
66 if (*(UINT16*)Buffer == gUnicodeFileTag) {
67 UCS2 = TRUE;
68 } else {
69 Ascii = TRUE;
70 }
71 }
72
73 if (Ascii) {
74 LoopSize = ReadSize;
75 for (LoopVar = 0 ; LoopVar < LoopSize ; LoopVar++) {
76 //
77 // The valid range of ASCII characters is 0x20-0x7E.
78 // Display "." when there is an invalid character.
79 //
80 AsciiChar = CHAR_NULL;
81 AsciiChar = ((CHAR8*)Buffer)[LoopVar];
82 if (AsciiChar == '\r' || AsciiChar == '\n') {
83 //
84 // Allow Line Feed (LF) (0xA) & Carriage Return (CR) (0xD)
85 // characters to be displayed as is.
86 //
87 if (AsciiChar == '\n' && ((CHAR8*)Buffer)[LoopVar-1] != '\r') {
88 //
89 // In case Line Feed (0xA) is encountered & Carriage Return (0xD)
90 // was not the previous character, print CR and LF. This is because
91 // Shell 2.0 requires carriage return with line feed for displaying
92 // each new line from left.
93 //
94 ShellPrintEx (-1, -1, L"\r\n");
95 continue;
96 }
97 } else {
98 //
99 // For all other characters which are not printable, display '.'
100 //
101 if (AsciiChar < 0x20 || AsciiChar >= 0x7F) {
102 AsciiChar = '.';
103 }
104 }
105 ShellPrintEx (-1, -1, L"%c", AsciiChar);
106 }
107 } else {
108 if (*(UINT16*)Buffer == gUnicodeFileTag) {
109 //
110 // For unicode files, skip displaying the byte order marker.
111 //
112 Buffer = ((UINT16*)Buffer) + 1;
113 LoopSize = (ReadSize / (sizeof (CHAR16))) - 1;
114 } else {
115 LoopSize = ReadSize / (sizeof (CHAR16));
116 }
117
118 for (LoopVar = 0 ; LoopVar < LoopSize ; LoopVar++) {
119 //
120 // An invalid range of characters is 0x0-0x1F.
121 // Display "." when there is an invalid character.
122 //
123 Ucs2Char = CHAR_NULL;
124 Ucs2Char = ((CHAR16*)Buffer)[LoopVar];
125 if (Ucs2Char == '\r' || Ucs2Char == '\n') {
126 //
127 // Allow Line Feed (LF) (0xA) & Carriage Return (CR) (0xD)
128 // characters to be displayed as is.
129 //
130 if (Ucs2Char == '\n' && ((CHAR16*)Buffer)[LoopVar-1] != '\r') {
131 //
132 // In case Line Feed (0xA) is encountered & Carriage Return (0xD)
133 // was not the previous character, print CR and LF. This is because
134 // Shell 2.0 requires carriage return with line feed for displaying
135 // each new line from left.
136 //
137 ShellPrintEx (-1, -1, L"\r\n");
138 continue;
139 }
140 }
141 else if (Ucs2Char < 0x20) {
142 //
143 // For all other characters which are not printable, display '.'
144 //
145 Ucs2Char = L'.';
146 }
147 ShellPrintEx (-1, -1, L"%c", Ucs2Char);
148 }
149 }
150
151 if (ShellGetExecutionBreakFlag()) {
152 break;
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
ShellCommandRunType(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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 AsciiMode = ShellCommandLineGetFlag(Package, L"-a");
224 UnicodeMode = ShellCommandLineGetFlag(Package, L"-u");
225
226 if (AsciiMode && UnicodeMode) {
227 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel3HiiHandle, L"type", L"-a & -u");
228 ShellStatus = SHELL_INVALID_PARAMETER;
229 } else if (ShellCommandLineGetRawValue(Package, 1) == NULL) {
230 //
231 // we insufficient parameters
232 //
233 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel3HiiHandle, L"type");
234 ShellStatus = SHELL_INVALID_PARAMETER;
235 } else {
236 //
237 // get a list with each file specified by parameters
238 // if parameter is a directory then add all the files below it to the list
239 //
240 for ( ParamCount = 1, Param = ShellCommandLineGetRawValue(Package, ParamCount)
241 ; Param != NULL
242 ; ParamCount++, Param = ShellCommandLineGetRawValue(Package, ParamCount)
243 ){
244 Status = ShellOpenFileMetaArg((CHAR16*)Param, EFI_FILE_MODE_READ, &FileList);
245 if (EFI_ERROR(Status)) {
246 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel3HiiHandle, L"type", (CHAR16*)Param);
247 ShellStatus = SHELL_NOT_FOUND;
248 break;
249 }
250 //
251 // make sure we completed the param parsing sucessfully...
252 // Also make sure that any previous action was sucessful
253 //
254 if (ShellStatus == SHELL_SUCCESS) {
255 //
256 // check that we have at least 1 file
257 //
258 if (FileList == NULL || IsListEmpty(&FileList->Link)) {
259 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel3HiiHandle, L"type", Param);
260 continue;
261 } else {
262 //
263 // loop through the list and make sure we are not aborting...
264 //
265 for ( Node = (EFI_SHELL_FILE_INFO*)GetFirstNode(&FileList->Link)
266 ; !IsNull(&FileList->Link, &Node->Link) && !ShellGetExecutionBreakFlag()
267 ; Node = (EFI_SHELL_FILE_INFO*)GetNextNode(&FileList->Link, &Node->Link)
268 ){
269
270 if (ShellGetExecutionBreakFlag()) {
271 break;
272 }
273
274 //
275 // make sure the file opened ok
276 //
277 if (EFI_ERROR(Node->Status)){
278 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel3HiiHandle, L"type", Node->FileName);
279 ShellStatus = SHELL_NOT_FOUND;
280 continue;
281 }
282
283 //
284 // make sure its not a directory
285 //
286 if (FileHandleIsDirectory(Node->Handle) == EFI_SUCCESS) {
287 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_IS_DIR), gShellLevel3HiiHandle, L"type", Node->FileName);
288 ShellStatus = SHELL_NOT_FOUND;
289 continue;
290 }
291
292 //
293 // do it
294 //
295 Status = TypeFileByHandle (Node->Handle, AsciiMode, UnicodeMode);
296 if (EFI_ERROR(Status)) {
297 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TYP_ERROR), gShellLevel3HiiHandle, L"type", Node->FileName);
298 ShellStatus = SHELL_INVALID_PARAMETER;
299 }
300 ASSERT(ShellStatus == SHELL_SUCCESS);
301 }
302 }
303 }
304 //
305 // Free the fileList
306 //
307 if (FileList != NULL && !IsListEmpty(&FileList->Link)) {
308 Status = ShellCloseFileMetaArg(&FileList);
309 }
310 ASSERT_EFI_ERROR(Status);
311 FileList = NULL;
312 }
313 }
314
315 //
316 // free the command line package
317 //
318 ShellCommandLineFreeVarList (Package);
319 }
320
321 if (ShellGetExecutionBreakFlag()) {
322 return (SHELL_ABORTED);
323 }
324
325 return (ShellStatus);
326 }
327
328