Home | History | Annotate | Download | only in UefiShellLevel3CommandsLib
      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