357 lines
9.9 KiB
C
357 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) {
|
|
AsciiStrToUnicodeStr (Argv[2], 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) {
|
|
AsciiStrToUnicodeStr (Argv[2], UnicodeFileName);
|
|
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));
|
|
}
|
|
}
|
|
|