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       AsciiStrToUnicodeStr (Argv[2], UnicodeFileName);
    120       if (UnicodeFileName[0] == '*') {
    121         // Handle *Name substring matching
    122         MatchSubString = &UnicodeFileName[1];
    123       }
    124 
    125       // Handle file type matchs
    126       if (Argc > 3) {
    127         // match a specific file type, always last argument
    128         Length = AsciiStrLen (Argv[3]);
    129         for (Index = 1, BestMatchCount = 0; Index < sizeof (gFvFileType)/sizeof (CHAR8 *); Index++) {
    130           if (AsciiStriCmp (gFvFileType[Index], Argv[3]) == 0) {
    131             // exact match
    132             SearchType = Index;
    133             break;
    134           }
    135 
    136           if (AsciiStrniCmp (Argv[3], gFvFileType[Index], Length) == 0) {
    137             // partial match, so keep looking to make sure there is only one partial match
    138             BestMatchCount++;
    139             SearchType = Index;
    140           }
    141         }
    142 
    143         if (BestMatchCount > 1) {
    144           SearchType = EFI_FV_FILETYPE_ALL;
    145         }
    146       }
    147     }
    148 
    149     TotalSize = 0;
    150     Fv = File->Fv;
    151     Key = 0;
    152     CurrentRow = 0;
    153     do {
    154       Type = SearchType;
    155       GetNextFileStatus = Fv->GetNextFile (
    156                                 Fv,
    157                                 &Key,
    158                                 &Type,
    159                                 &NameGuid,
    160                                 &Attributes,
    161                                 &Size
    162                                 );
    163       if (!EFI_ERROR (GetNextFileStatus)) {
    164         TotalSize += Size;
    165         // Calculate size of entire file
    166         Section = NULL;
    167         Size = 0;
    168         Status = Fv->ReadFile (
    169                       Fv,
    170                       &NameGuid,
    171                       Section,
    172                       &Size,
    173                       &Type,
    174                       &Attributes,
    175                       &AuthenticationStatus
    176                       );
    177         if (!((Status == EFI_BUFFER_TOO_SMALL) || !EFI_ERROR (Status))) {
    178           // EFI_SUCCESS or EFI_BUFFER_TOO_SMALL mean size is valid
    179           Size = 0;
    180         }
    181 
    182         TypeStr = (Type <= EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) ? gFvFileType[Type] : "UNKNOWN";
    183 
    184         // read the UI seciton to do a name match.
    185         Section = NULL;
    186         Status = Fv->ReadSection (
    187                         Fv,
    188                         &NameGuid,
    189                         EFI_SECTION_USER_INTERFACE,
    190                         0,
    191                         &Section,
    192                         &SectionSize,
    193                         &AuthenticationStatus
    194                         );
    195         if (!EFI_ERROR (Status)) {
    196           if (StrStr (Section, MatchSubString) != NULL) {
    197             AsciiPrint ("%,9d %7a %g %s\n", Size, TypeStr, &NameGuid, Section);
    198             if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {
    199               break;
    200             }
    201           }
    202           FreePool (Section);
    203         } else {
    204           if (*MatchSubString == '\0') {
    205             AsciiPrint ("%,9d %7a %g\n", Size, TypeStr, &NameGuid);
    206             if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {
    207               break;
    208             }
    209           }
    210         }
    211       }
    212     } while (!EFI_ERROR (GetNextFileStatus));
    213 
    214     if (SearchType == EFI_FV_FILETYPE_ALL) {
    215       AsciiPrint ("%,20d bytes in files %,d bytes free\n", TotalSize, File->FvSize - File->FvHeaderSize - TotalSize);
    216     }
    217 
    218 
    219   } else if ((File->Type == EfiOpenFileSystem) || (File->Type == EfiOpenBlockIo)) {
    220     // Simple File System DIR
    221 
    222     if (File->FsFileInfo ==  NULL) {
    223       return EFI_SUCCESS;
    224     }
    225 
    226     if (!(File->FsFileInfo->Attribute & EFI_FILE_DIRECTORY)) {
    227       return EFI_SUCCESS;
    228     }
    229 
    230     // Handle *Name substring matching
    231     MatchSubString = NULL;
    232     UnicodeFileName[0] = '\0';
    233     if (Argc > 2) {
    234       AsciiStrToUnicodeStr (Argv[2], UnicodeFileName);
    235       if (UnicodeFileName[0] == '*') {
    236         MatchSubString = &UnicodeFileName[1];
    237       }
    238     }
    239 
    240     File->FsFileHandle->SetPosition (File->FsFileHandle, 0);
    241     for (CurrentRow = 0;;) {
    242       // First read gets the size
    243       DirInfo = NULL;
    244       ReadSize = 0;
    245       Status = File->FsFileHandle->Read (File->FsFileHandle, &ReadSize, DirInfo);
    246       if (Status == EFI_BUFFER_TOO_SMALL) {
    247         // Allocate the buffer for the real read
    248         DirInfo = AllocatePool (ReadSize);
    249         if (DirInfo == NULL) {
    250           goto Done;
    251         }
    252 
    253         // Read the data
    254         Status = File->FsFileHandle->Read (File->FsFileHandle, &ReadSize, DirInfo);
    255         if ((EFI_ERROR (Status)) || (ReadSize == 0)) {
    256           break;
    257         }
    258       } else {
    259         break;
    260       }
    261 
    262       if (MatchSubString != NULL) {
    263         if (StrStr (&DirInfo->FileName[0], MatchSubString) == NULL) {
    264           // does not match *name argument, so skip
    265           continue;
    266         }
    267       } else if (UnicodeFileName[0] != '\0') {
    268         // is not an exact match for name argument, so skip
    269         if (StrCmp (&DirInfo->FileName[0], UnicodeFileName) != 0) {
    270           continue;
    271         }
    272       }
    273 
    274       if (DirInfo->Attribute & EFI_FILE_DIRECTORY) {
    275         AsciiPrint ("         <DIR> %s\n", &DirInfo->FileName[0]);
    276       } else {
    277         AsciiPrint ("%,14ld %s\n", DirInfo->FileSize, &DirInfo->FileName[0]);
    278       }
    279 
    280       if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {
    281         break;
    282       }
    283 
    284       FreePool (DirInfo);
    285     }
    286 
    287 Done:
    288     if (DirInfo != NULL) {
    289       FreePool (DirInfo);
    290     }
    291   }
    292 
    293   EfiClose (File);
    294 
    295   return EFI_SUCCESS;
    296 }
    297 
    298 /**
    299   Change the Current Working Directory
    300 
    301   Argv[0] - "cd"
    302   Argv[1] - Device Name:path. Path is optional
    303 
    304   @param  Argc   Number of command arguments in Argv
    305   @param  Argv   Array of strings that represent the parsed command line.
    306                  Argv[0] is the command name
    307 
    308   @return EFI_SUCCESS
    309 
    310 **/
    311 EFI_STATUS
    312 EFIAPI
    313 EblCdCmd (
    314   IN UINTN  Argc,
    315   IN CHAR8  **Argv
    316   )
    317 {
    318   if (Argc <= 1) {
    319     return EFI_SUCCESS;
    320   }
    321 
    322   return EfiSetCwd (Argv[1]);
    323 }
    324 
    325 
    326 
    327 GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdDirTemplate[] =
    328 {
    329   {
    330     "dir",
    331     " dirdev [*match]; directory listing of dirdev. opt match a substring",
    332     NULL,
    333     EblDirCmd
    334   },
    335   {
    336     "cd",
    337     " device - set the current working directory",
    338     NULL,
    339     EblCdCmd
    340   }
    341 };
    342 
    343 
    344 /**
    345   Initialize the commands in this in this file
    346 **/
    347 VOID
    348 EblInitializeDirCmd (
    349   VOID
    350   )
    351 {
    352   if (FeaturePcdGet (PcdEmbeddedDirCmd)) {
    353     EblAddCommands (mCmdDirTemplate, sizeof (mCmdDirTemplate)/sizeof (EBL_COMMAND_TABLE));
    354   }
    355 }
    356 
    357