Get rid of calls to unsafe string functions. These are deprecated and may be removed in the future. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Reviewed-by: Laszlo Ersek <lersek@redhat.com> Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
		
			
				
	
	
		
			358 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			358 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Dir for EBL (Embedded Boot Loader)
 | |
| 
 | |
|   Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>
 | |
|   Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
 | |
|   (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
 | |
| 
 | |
| 
 | |
|   This program and the accompanying materials
 | |
|   are licensed and made available under the terms and conditions of the BSD License
 | |
|   which accompanies this distribution.  The full text of the license may be found at
 | |
|   http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
|   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
|   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
|   Module Name:  CmdTemplate.c
 | |
| 
 | |
|   Search/Replace Dir with the name of your new command
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "Ebl.h"
 | |
| 
 | |
| 
 | |
| GLOBAL_REMOVE_IF_UNREFERENCED   CHAR8 *gFvFileType[] = {
 | |
|   "All",
 | |
|   "Bin",
 | |
|   "section",
 | |
|   "SEC",
 | |
|   "PeiCore",
 | |
|   "DxeCore",
 | |
|   "PEIM",
 | |
|   "Driver",
 | |
|   "Combo",
 | |
|   "App",
 | |
|   "NULL",
 | |
|   "FV"
 | |
| };
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Perform a dir on a device. The device must support Simple File System Protocol
 | |
|   or the FV protocol.
 | |
| 
 | |
|   Argv[0] - "dir"
 | |
|   Argv[1] - Device Name:path. Path is optional
 | |
|   Argv[2] - Optional filename to match on. A leading * means match substring
 | |
|   Argv[3] - Optional FV file type
 | |
| 
 | |
|   dir fs1:\efi      ; perform a dir on fs1: device in the efi directory
 | |
|   dir fs1:\efi *.efi; perform a dir on fs1: device in the efi directory but
 | |
|                       only print out files that contain the string *.efi
 | |
|   dir fv1:\         ; perform a dir on fv1: device in the efi directory
 | |
|                     NOTE: fv devices do not contain subdirs
 | |
|   dir fv1:\ * PEIM  ; will match all files of type PEIM
 | |
| 
 | |
|   @param  Argc   Number of command arguments in Argv
 | |
|   @param  Argv   Array of strings that represent the parsed command line.
 | |
|                  Argv[0] is the command name
 | |
| 
 | |
|   @return EFI_SUCCESS
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| EblDirCmd (
 | |
|   IN UINTN  Argc,
 | |
|   IN CHAR8  **Argv
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                    Status;
 | |
|   EFI_OPEN_FILE                 *File;
 | |
|   EFI_FILE_INFO                 *DirInfo;
 | |
|   UINTN                         ReadSize;
 | |
|   UINTN                         CurrentRow;
 | |
|   CHAR16                        *MatchSubString;
 | |
|   EFI_STATUS                    GetNextFileStatus;
 | |
|   UINTN                         Key;
 | |
|   EFI_FV_FILETYPE               SearchType;
 | |
|   EFI_FV_FILETYPE               Type;
 | |
|   EFI_FV_FILE_ATTRIBUTES        Attributes;
 | |
|   UINTN                         Size;
 | |
|   EFI_GUID                      NameGuid;
 | |
|   EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
 | |
|   UINT32                        AuthenticationStatus;
 | |
|   VOID                          *Section;
 | |
|   UINTN                         SectionSize;
 | |
|   EFI_FV_FILETYPE               Index;
 | |
|   UINTN                         Length;
 | |
|   UINTN                         BestMatchCount;
 | |
|   CHAR16                        UnicodeFileName[MAX_CMD_LINE];
 | |
|   CHAR8                         *Path;
 | |
|   CHAR8                         *TypeStr;
 | |
|   UINTN                         TotalSize;
 | |
| 
 | |
| 
 | |
|   if (Argc <= 1) {
 | |
|     Path = EfiGetCwd ();
 | |
|     if (Path == NULL) {
 | |
|       return EFI_SUCCESS;
 | |
|     }
 | |
|   } else {
 | |
|     Path = Argv[1];
 | |
|   }
 | |
| 
 | |
|   File = EfiOpen (Path, EFI_FILE_MODE_READ, 0);
 | |
|   if (File == NULL) {
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   if (File->Type == EfiOpenFirmwareVolume) {
 | |
|     // FV Dir
 | |
| 
 | |
|     SearchType = EFI_FV_FILETYPE_ALL;
 | |
|     UnicodeFileName[0] = '\0';
 | |
|     MatchSubString = &UnicodeFileName[0];
 | |
|     if (Argc > 2) {
 | |
|       AsciiStrToUnicodeStrS (Argv[2], UnicodeFileName,
 | |
|         ARRAY_SIZE (UnicodeFileName));
 | |
|       if (UnicodeFileName[0] == '*') {
 | |
|         // Handle *Name substring matching
 | |
|         MatchSubString = &UnicodeFileName[1];
 | |
|       }
 | |
| 
 | |
|       // Handle file type matchs
 | |
|       if (Argc > 3) {
 | |
|         // match a specific file type, always last argument
 | |
|         Length = AsciiStrLen (Argv[3]);
 | |
|         for (Index = 1, BestMatchCount = 0; Index < sizeof (gFvFileType)/sizeof (CHAR8 *); Index++) {
 | |
|           if (AsciiStriCmp (gFvFileType[Index], Argv[3]) == 0) {
 | |
|             // exact match
 | |
|             SearchType = Index;
 | |
|             break;
 | |
|           }
 | |
| 
 | |
|           if (AsciiStrniCmp (Argv[3], gFvFileType[Index], Length) == 0) {
 | |
|             // partial match, so keep looking to make sure there is only one partial match
 | |
|             BestMatchCount++;
 | |
|             SearchType = Index;
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         if (BestMatchCount > 1) {
 | |
|           SearchType = EFI_FV_FILETYPE_ALL;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     TotalSize = 0;
 | |
|     Fv = File->Fv;
 | |
|     Key = 0;
 | |
|     CurrentRow = 0;
 | |
|     do {
 | |
|       Type = SearchType;
 | |
|       GetNextFileStatus = Fv->GetNextFile (
 | |
|                                 Fv,
 | |
|                                 &Key,
 | |
|                                 &Type,
 | |
|                                 &NameGuid,
 | |
|                                 &Attributes,
 | |
|                                 &Size
 | |
|                                 );
 | |
|       if (!EFI_ERROR (GetNextFileStatus)) {
 | |
|         TotalSize += Size;
 | |
|         // Calculate size of entire file
 | |
|         Section = NULL;
 | |
|         Size = 0;
 | |
|         Status = Fv->ReadFile (
 | |
|                       Fv,
 | |
|                       &NameGuid,
 | |
|                       Section,
 | |
|                       &Size,
 | |
|                       &Type,
 | |
|                       &Attributes,
 | |
|                       &AuthenticationStatus
 | |
|                       );
 | |
|         if (!((Status == EFI_BUFFER_TOO_SMALL) || !EFI_ERROR (Status))) {
 | |
|           // EFI_SUCCESS or EFI_BUFFER_TOO_SMALL mean size is valid
 | |
|           Size = 0;
 | |
|         }
 | |
| 
 | |
|         TypeStr = (Type <= EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) ? gFvFileType[Type] : "UNKNOWN";
 | |
| 
 | |
|         // read the UI seciton to do a name match.
 | |
|         Section = NULL;
 | |
|         Status = Fv->ReadSection (
 | |
|                         Fv,
 | |
|                         &NameGuid,
 | |
|                         EFI_SECTION_USER_INTERFACE,
 | |
|                         0,
 | |
|                         &Section,
 | |
|                         &SectionSize,
 | |
|                         &AuthenticationStatus
 | |
|                         );
 | |
|         if (!EFI_ERROR (Status)) {
 | |
|           if (StrStr (Section, MatchSubString) != NULL) {
 | |
|             AsciiPrint ("%,9d %7a %g %s\n", Size, TypeStr, &NameGuid, Section);
 | |
|             if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {
 | |
|               break;
 | |
|             }
 | |
|           }
 | |
|           FreePool (Section);
 | |
|         } else {
 | |
|           if (*MatchSubString == '\0') {
 | |
|             AsciiPrint ("%,9d %7a %g\n", Size, TypeStr, &NameGuid);
 | |
|             if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {
 | |
|               break;
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     } while (!EFI_ERROR (GetNextFileStatus));
 | |
| 
 | |
|     if (SearchType == EFI_FV_FILETYPE_ALL) {
 | |
|       AsciiPrint ("%,20d bytes in files %,d bytes free\n", TotalSize, File->FvSize - File->FvHeaderSize - TotalSize);
 | |
|     }
 | |
| 
 | |
| 
 | |
|   } else if ((File->Type == EfiOpenFileSystem) || (File->Type == EfiOpenBlockIo)) {
 | |
|     // Simple File System DIR
 | |
| 
 | |
|     if (File->FsFileInfo ==  NULL) {
 | |
|       return EFI_SUCCESS;
 | |
|     }
 | |
| 
 | |
|     if (!(File->FsFileInfo->Attribute & EFI_FILE_DIRECTORY)) {
 | |
|       return EFI_SUCCESS;
 | |
|     }
 | |
| 
 | |
|     // Handle *Name substring matching
 | |
|     MatchSubString = NULL;
 | |
|     UnicodeFileName[0] = '\0';
 | |
|     if (Argc > 2) {
 | |
|       AsciiStrToUnicodeStrS (Argv[2], UnicodeFileName, MAX_CMD_LINE);
 | |
|       if (UnicodeFileName[0] == '*') {
 | |
|         MatchSubString = &UnicodeFileName[1];
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     File->FsFileHandle->SetPosition (File->FsFileHandle, 0);
 | |
|     for (CurrentRow = 0;;) {
 | |
|       // First read gets the size
 | |
|       DirInfo = NULL;
 | |
|       ReadSize = 0;
 | |
|       Status = File->FsFileHandle->Read (File->FsFileHandle, &ReadSize, DirInfo);
 | |
|       if (Status == EFI_BUFFER_TOO_SMALL) {
 | |
|         // Allocate the buffer for the real read
 | |
|         DirInfo = AllocatePool (ReadSize);
 | |
|         if (DirInfo == NULL) {
 | |
|           goto Done;
 | |
|         }
 | |
| 
 | |
|         // Read the data
 | |
|         Status = File->FsFileHandle->Read (File->FsFileHandle, &ReadSize, DirInfo);
 | |
|         if ((EFI_ERROR (Status)) || (ReadSize == 0)) {
 | |
|           break;
 | |
|         }
 | |
|       } else {
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       if (MatchSubString != NULL) {
 | |
|         if (StrStr (&DirInfo->FileName[0], MatchSubString) == NULL) {
 | |
|           // does not match *name argument, so skip
 | |
|           continue;
 | |
|         }
 | |
|       } else if (UnicodeFileName[0] != '\0') {
 | |
|         // is not an exact match for name argument, so skip
 | |
|         if (StrCmp (&DirInfo->FileName[0], UnicodeFileName) != 0) {
 | |
|           continue;
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       if (DirInfo->Attribute & EFI_FILE_DIRECTORY) {
 | |
|         AsciiPrint ("         <DIR> %s\n", &DirInfo->FileName[0]);
 | |
|       } else {
 | |
|         AsciiPrint ("%,14ld %s\n", DirInfo->FileSize, &DirInfo->FileName[0]);
 | |
|       }
 | |
| 
 | |
|       if (EblAnyKeyToContinueQtoQuit (&CurrentRow, FALSE)) {
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       FreePool (DirInfo);
 | |
|     }
 | |
| 
 | |
| Done:
 | |
|     if (DirInfo != NULL) {
 | |
|       FreePool (DirInfo);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   EfiClose (File);
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Change the Current Working Directory
 | |
| 
 | |
|   Argv[0] - "cd"
 | |
|   Argv[1] - Device Name:path. Path is optional
 | |
| 
 | |
|   @param  Argc   Number of command arguments in Argv
 | |
|   @param  Argv   Array of strings that represent the parsed command line.
 | |
|                  Argv[0] is the command name
 | |
| 
 | |
|   @return EFI_SUCCESS
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| EblCdCmd (
 | |
|   IN UINTN  Argc,
 | |
|   IN CHAR8  **Argv
 | |
|   )
 | |
| {
 | |
|   if (Argc <= 1) {
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   return EfiSetCwd (Argv[1]);
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdDirTemplate[] =
 | |
| {
 | |
|   {
 | |
|     "dir",
 | |
|     " dirdev [*match]; directory listing of dirdev. opt match a substring",
 | |
|     NULL,
 | |
|     EblDirCmd
 | |
|   },
 | |
|   {
 | |
|     "cd",
 | |
|     " device - set the current working directory",
 | |
|     NULL,
 | |
|     EblCdCmd
 | |
|   }
 | |
| };
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Initialize the commands in this in this file
 | |
| **/
 | |
| VOID
 | |
| EblInitializeDirCmd (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   if (FeaturePcdGet (PcdEmbeddedDirCmd)) {
 | |
|     EblAddCommands (mCmdDirTemplate, sizeof (mCmdDirTemplate)/sizeof (EBL_COMMAND_TABLE));
 | |
|   }
 | |
| }
 | |
| 
 |