Home | History | Annotate | Download | only in Ebl
      1 /** @file
      2   Dir for EBL (Embedded Boot Loader)
      3 
      4   Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>
      5   Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
      6   (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
      7 
      8 
      9   This program and the accompanying materials
     10   are licensed and made available under the terms and conditions of the BSD License
     11   which accompanies this distribution.  The full text of the license may be found at
     12   http://opensource.org/licenses/bsd-license.php
     13 
     14   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     15   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     16 
     17   Module Name:  CmdTemplate.c
     18 
     19   Search/Replace Dir with the name of your new command
     20 
     21 **/
     22 
     23 #include "Ebl.h"
     24 
     25 
     26 GLOBAL_REMOVE_IF_UNREFERENCED   CHAR8 *gFvFileType[] = {
     27   "All",
     28   "Bin",
     29   "section",
     30   "SEC",
     31   "PeiCore",
     32   "DxeCore",
     33   "PEIM",
     34   "Driver",
     35   "Combo",
     36   "App",
     37   "NULL",
     38   "FV"
     39 };
     40 
     41 
     42 /**
     43   Perform a dir on a device. The device must support Simple File System Protocol
     44   or the FV protocol.
     45 
     46   Argv[0] - "dir"
     47   Argv[1] - Device Name:path. Path is optional
     48   Argv[2] - Optional filename to match on. A leading * means match substring
     49   Argv[3] - Optional FV file type
     50 
     51   dir fs1:\efi      ; perform a dir on fs1: device in the efi directory
     52   dir fs1:\efi *.efi; perform a dir on fs1: device in the efi directory but
     53                       only print out files that contain the string *.efi
     54   dir fv1:\         ; perform a dir on fv1: device in the efi directory
     55                     NOTE: fv devices do not contain subdirs
     56   dir fv1:\ * PEIM  ; will match all files of type PEIM
     57 
     58   @param  Argc   Number of command arguments in Argv
     59   @param  Argv   Array of strings that represent the parsed command line.
     60                  Argv[0] is the command name
     61 
     62   @return EFI_SUCCESS
     63 
     64 **/
     65 EFI_STATUS
     66 EFIAPI
     67 EblDirCmd (
     68   IN UINTN  Argc,
     69   IN CHAR8  **Argv
     70   )
     71 {
     72   EFI_STATUS                    Status;
     73   EFI_OPEN_FILE                 *File;
     74   EFI_FILE_INFO                 *DirInfo;
     75   UINTN                         ReadSize;
     76   UINTN                         CurrentRow;
     77   CHAR16                        *MatchSubString;
     78   EFI_STATUS                    GetNextFileStatus;
     79   UINTN                         Key;
     80   EFI_FV_FILETYPE               SearchType;
     81   EFI_FV_FILETYPE               Type;
     82   EFI_FV_FILE_ATTRIBUTES        Attributes;
     83   UINTN                         Size;
     84   EFI_GUID                      NameGuid;
     85   EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
     86   UINT32                        AuthenticationStatus;
     87   VOID                          *Section;
     88   UINTN                         SectionSize;
     89   EFI_FV_FILETYPE               Index;
     90   UINTN                         Length;
     91   UINTN                         BestMatchCount;
     92   CHAR16                        UnicodeFileName[MAX_CMD_LINE];
     93   CHAR8                         *Path;
     94   CHAR8                         *TypeStr;
     95   UINTN                         TotalSize;
     96 
     97 
     98   if (Argc <= 1) {
     99     Path = EfiGetCwd ();
    100     if (Path == NULL) {
    101       return EFI_SUCCESS;
    102     }
    103   } else {
    104     Path = Argv[1];
    105   }
    106 
    107   File = EfiOpen (Path, EFI_FILE_MODE_READ, 0);
    108   if (File == NULL) {
    109     return EFI_SUCCESS;
    110   }
    111 
    112   if (File->Type == EfiOpenFirmwareVolume) {
    113     // FV Dir
    114 
    115     SearchType = EFI_FV_FILETYPE_ALL;
    116     UnicodeFileName[0] = '\0';
    117     MatchSubString = &UnicodeFileName[0];
    118     if (Argc > 2) {
    119       AsciiStrToUnicodeStrS (Argv[2], UnicodeFileName,
    120         ARRAY_SIZE (UnicodeFileName));
    121       if (UnicodeFileName[0] == '*') {
    122         // Handle *Name substring matching
    123         MatchSubString = &UnicodeFileName[1];
    124       }
    125 
    126       // Handle file type matchs
    127       if (Argc > 3) {
    128         // match a specific file type, always last argument
    129         Length = AsciiStrLen (Argv[3]);
    130         for (Index = 1, BestMatchCount = 0; Index < sizeof (gFvFileType)/sizeof (CHAR8 *); Index++) {
    131           if (AsciiStriCmp (gFvFileType[Index], Argv[3]) == 0) {
    132             // exact match
    133             SearchType = Index;
    134             break;
    135           }
    136 
    137           if (AsciiStrniCmp (Argv[3], gFvFileType[Index], Length) == 0) {
    138             // partial match, so keep looking to make sure there is only one partial match
    139             BestMatchCount++;
    140             SearchType = Index;
    141           }
    142         }
    143 
    144         if (BestMatchCount > 1) {
    145           SearchType = EFI_FV_FILETYPE_ALL;
    146         }
    147       }
    148     }
    149 
    150     TotalSize = 0;
    151     Fv = File->Fv;
    152     Key = 0;
    153     CurrentRow = 0;
    154     do {
    155       Type = SearchType;
    156       GetNextFileStatus = Fv->GetNextFile (
    157                                 Fv,
    158                                 &Key,
    159                                 &Type,
    160                                 &NameGuid,
    161                                 &Attributes,
    162                                 &Size
    163                                 );
    164       if (!EFI_ERROR (GetNextFileStatus)) {
    165         TotalSize += Size;
    166         // Calculate size of entire file
    167         Section = NULL;
    168         Size = 0;
    169         Status = Fv->ReadFile (
    170                       Fv,
    171                       &NameGuid,
    172                       Section,
    173                       &Size,
    174                       &Type,
    175                       &Attributes,
    176                       &AuthenticationStatus
    177                       );
    178         if (!((Status == EFI_BUFFER_TOO_SMALL) || !EFI_ERROR (Status))) {
    179           // EFI_SUCCESS or EFI_BUFFER_TOO_SMALL mean size is valid
    180           Size = 0;
    181         }
    182 
    183         TypeStr = (Type <= EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) ? gFvFileType[Type] : "UNKNOWN";
    184 
    185         // read the UI seciton to do a name match.
    186         Section = NULL;
    187         Status = Fv->ReadSection (
    188                         Fv,
    189                         &NameGuid,
    190                         EFI_SECTION_USER_INTERFACE,
    191                         0,
    192                         &Section,
    193                         &SectionSize,
    194                         &AuthenticationStatus
    195                         );
    196         if (!EFI_ERROR (Status)) {
    197           if (StrStr (Section, MatchSubString) != NULL) {
    198             AsciiPrint ("%,9d %7a %g %s\n", Size, TypeStr, &NameGuid, Section);
    199             if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {
    200               break;
    201             }
    202           }
    203           FreePool (Section);
    204         } else {
    205           if (*MatchSubString == '\0') {
    206             AsciiPrint ("%,9d %7a %g\n", Size, TypeStr, &NameGuid);
    207             if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {
    208               break;
    209             }
    210           }
    211         }
    212       }
    213     } while (!EFI_ERROR (GetNextFileStatus));
    214 
    215     if (SearchType == EFI_FV_FILETYPE_ALL) {
    216       AsciiPrint ("%,20d bytes in files %,d bytes free\n", TotalSize, File->FvSize - File->FvHeaderSize - TotalSize);
    217     }
    218 
    219 
    220   } else if ((File->Type == EfiOpenFileSystem) || (File->Type == EfiOpenBlockIo)) {
    221     // Simple File System DIR
    222 
    223     if (File->FsFileInfo ==  NULL) {
    224       return EFI_SUCCESS;
    225     }
    226 
    227     if (!(File->FsFileInfo->Attribute & EFI_FILE_DIRECTORY)) {
    228       return EFI_SUCCESS;
    229     }
    230 
    231     // Handle *Name substring matching
    232     MatchSubString = NULL;
    233     UnicodeFileName[0] = '\0';
    234     if (Argc > 2) {
    235       AsciiStrToUnicodeStrS (Argv[2], UnicodeFileName, MAX_CMD_LINE);
    236       if (UnicodeFileName[0] == '*') {
    237         MatchSubString = &UnicodeFileName[1];
    238       }
    239     }
    240 
    241     File->FsFileHandle->SetPosition (File->FsFileHandle, 0);
    242     for (CurrentRow = 0;;) {
    243       // First read gets the size
    244       DirInfo = NULL;
    245       ReadSize = 0;
    246       Status = File->FsFileHandle->Read (File->FsFileHandle, &ReadSize, DirInfo);
    247       if (Status == EFI_BUFFER_TOO_SMALL) {
    248         // Allocate the buffer for the real read
    249         DirInfo = AllocatePool (ReadSize);
    250         if (DirInfo == NULL) {
    251           goto Done;
    252         }
    253 
    254         // Read the data
    255         Status = File->FsFileHandle->Read (File->FsFileHandle, &ReadSize, DirInfo);
    256         if ((EFI_ERROR (Status)) || (ReadSize == 0)) {
    257           break;
    258         }
    259       } else {
    260         break;
    261       }
    262 
    263       if (MatchSubString != NULL) {
    264         if (StrStr (&DirInfo->FileName[0], MatchSubString) == NULL) {
    265           // does not match *name argument, so skip
    266           continue;
    267         }
    268       } else if (UnicodeFileName[0] != '\0') {
    269         // is not an exact match for name argument, so skip
    270         if (StrCmp (&DirInfo->FileName[0], UnicodeFileName) != 0) {
    271           continue;
    272         }
    273       }
    274 
    275       if (DirInfo->Attribute & EFI_FILE_DIRECTORY) {
    276         AsciiPrint ("         <DIR> %s\n", &DirInfo->FileName[0]);
    277       } else {
    278         AsciiPrint ("%,14ld %s\n", DirInfo->FileSize, &DirInfo->FileName[0]);
    279       }
    280 
    281       if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {
    282         break;
    283       }
    284 
    285       FreePool (DirInfo);
    286     }
    287 
    288 Done:
    289     if (DirInfo != NULL) {
    290       FreePool (DirInfo);
    291     }
    292   }
    293 
    294   EfiClose (File);
    295 
    296   return EFI_SUCCESS;
    297 }
    298 
    299 /**
    300   Change the Current Working Directory
    301 
    302   Argv[0] - "cd"
    303   Argv[1] - Device Name:path. Path is optional
    304 
    305   @param  Argc   Number of command arguments in Argv
    306   @param  Argv   Array of strings that represent the parsed command line.
    307                  Argv[0] is the command name
    308 
    309   @return EFI_SUCCESS
    310 
    311 **/
    312 EFI_STATUS
    313 EFIAPI
    314 EblCdCmd (
    315   IN UINTN  Argc,
    316   IN CHAR8  **Argv
    317   )
    318 {
    319   if (Argc <= 1) {
    320     return EFI_SUCCESS;
    321   }
    322 
    323   return EfiSetCwd (Argv[1]);
    324 }
    325 
    326 
    327 
    328 GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdDirTemplate[] =
    329 {
    330   {
    331     "dir",
    332     " dirdev [*match]; directory listing of dirdev. opt match a substring",
    333     NULL,
    334     EblDirCmd
    335   },
    336   {
    337     "cd",
    338     " device - set the current working directory",
    339     NULL,
    340     EblCdCmd
    341   }
    342 };
    343 
    344 
    345 /**
    346   Initialize the commands in this in this file
    347 **/
    348 VOID
    349 EblInitializeDirCmd (
    350   VOID
    351   )
    352 {
    353   if (FeaturePcdGet (PcdEmbeddedDirCmd)) {
    354     EblAddCommands (mCmdDirTemplate, sizeof (mCmdDirTemplate)/sizeof (EBL_COMMAND_TABLE));
    355   }
    356 }
    357 
    358