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 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 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