summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--EmbeddedPkg/Ebl/Dir.c45
-rw-r--r--EmbeddedPkg/Ebl/Main.c7
-rw-r--r--EmbeddedPkg/Include/Library/EfiFileLib.h2
-rw-r--r--EmbeddedPkg/Library/EfiFileLib/EfiFileLib.c168
4 files changed, 204 insertions, 18 deletions
diff --git a/EmbeddedPkg/Ebl/Dir.c b/EmbeddedPkg/Ebl/Dir.c
index 4e9f7b9..ff1b557 100644
--- a/EmbeddedPkg/Ebl/Dir.c
+++ b/EmbeddedPkg/Ebl/Dir.c
@@ -52,7 +52,7 @@ GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 *gFvFileType[] = {
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 contian subdirs
- dir fv1:\ * PEIM ; will match all files of type SEC
+ 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.
@@ -88,14 +88,19 @@ EblDirCmd (
UINTN Length;
UINTN BestMatchCount;
CHAR16 UnicodeFileName[MAX_CMD_LINE];
+ CHAR8 *Path;
if (Argc <= 1) {
- // CWD not currently supported
- return EFI_SUCCESS;
+ Path = EfiGetCwd ();
+ if (Path == NULL) {
+ return EFI_SUCCESS;
+ }
+ } else {
+ Path = Argv[1];
}
- File = EfiOpen (Argv[1], EFI_FILE_MODE_READ, 0);
+ File = EfiOpen (Path, EFI_FILE_MODE_READ, 0);
if (File == NULL) {
return EFI_SUCCESS;
}
@@ -277,6 +282,32 @@ Done:
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 comamnd name
+
+ @return EFI_SUCCESS
+
+**/
+EFI_STATUS
+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[] =
@@ -286,6 +317,12 @@ GLOBAL_REMOVE_IF_UNREFERENCED const EBL_COMMAND_TABLE mCmdDirTemplate[] =
" dirdev [*match]; directory listing of dirdev. opt match a substring",
NULL,
EblDirCmd
+ },
+ {
+ "cd",
+ " device - set the current working directory",
+ NULL,
+ EblCdCmd
}
};
diff --git a/EmbeddedPkg/Ebl/Main.c b/EmbeddedPkg/Ebl/Main.c
index d3dcc58..ed2104c 100644
--- a/EmbeddedPkg/Ebl/Main.c
+++ b/EmbeddedPkg/Ebl/Main.c
@@ -464,7 +464,7 @@ EblPrompt (
)
{
EblSetTextColor (EFI_YELLOW);
- AsciiPrint ((CHAR8 *)PcdGetPtr (PcdEmbeddedPrompt));
+ AsciiPrint ((CHAR8 *)PcdGetPtr (PcdEmbeddedPrompt), EfiGetCwd ());
EblSetTextColor (0);
AsciiPrint ("%a", ">");
}
@@ -559,6 +559,9 @@ EdkBootLoaderEntry (
EblInitializeExternalCmd ();
EblInitializeNetworkCmd();
+ // Disable the 5 minute EFI watchdog time so we don't get automatically reset
+ gBS->SetWatchdogTimer (0, 0, 0, NULL);
+
if (FeaturePcdGet (PcdEmbeddedMacBoot)) {
// A MAC will boot in graphics mode, so turn it back to text here
// This protocol was removed from edk2. It is only an edk thing. We need to make our own copy.
@@ -567,8 +570,6 @@ EdkBootLoaderEntry (
// Enable the biggest output screen size possible
gST->ConOut->SetMode (gST->ConOut, (UINTN)gST->ConOut->Mode->MaxMode - 1);
- // Disable the 5 minute EFI watchdog time so we don't get automatically reset
- gBS->SetWatchdogTimer (0, 0, 0, NULL);
}
// Save current screen mode
diff --git a/EmbeddedPkg/Include/Library/EfiFileLib.h b/EmbeddedPkg/Include/Library/EfiFileLib.h
index 4e3c80d..4bbb1b2 100644
--- a/EmbeddedPkg/Include/Library/EfiFileLib.h
+++ b/EmbeddedPkg/Include/Library/EfiFileLib.h
@@ -341,7 +341,7 @@ EfiSetCwd (
**/
CHAR8 *
-EfiGettCwd (
+EfiGetCwd (
VOID
);
diff --git a/EmbeddedPkg/Library/EfiFileLib/EfiFileLib.c b/EmbeddedPkg/Library/EfiFileLib/EfiFileLib.c
index cbe2aee..c58d21e 100644
--- a/EmbeddedPkg/Library/EfiFileLib/EfiFileLib.c
+++ b/EmbeddedPkg/Library/EfiFileLib/EfiFileLib.c
@@ -647,7 +647,7 @@ EfiOpen (
File->FvSectionType = SectionType;
StrLen = AsciiStrSize (PathName);
- if (StrLen <= 2) {
+ if (StrLen <= 1) {
// Smallest valid path is 1 char and a null
return NULL;
}
@@ -659,7 +659,7 @@ EfiOpen (
}
}
- if (FileStart == 0) {
+ if (FileStart == StrLen) {
if (gCwd == NULL) {
// No CWD
return NULL;
@@ -671,8 +671,31 @@ EfiOpen (
return NULL;
}
- AsciiStrCpy (CwdPlusPathName, gCwd);
+ if ((PathName[0] == '/') || (PathName[0] == '\\')) {
+ // PathName starts in / so this means we go to the root of the device in the CWD.
+ CwdPlusPathName[0] = '\0';
+ for (FileStart = 0; gCwd[FileStart] != '\0'; FileStart++) {
+ CwdPlusPathName[FileStart] = gCwd[FileStart];
+ if (gCwd[FileStart] == ':') {
+ FileStart++;
+ CwdPlusPathName[FileStart] = '\0';
+ break;
+ }
+ }
+ } else {
+ AsciiStrCpy (CwdPlusPathName, gCwd);
+ StrLen = AsciiStrLen (gCwd);
+ if ((*PathName != '/') && (*PathName != '\\') && (gCwd[StrLen-1] != '/') && (gCwd[StrLen-1] != '\\')) {
+ AsciiStrCat (CwdPlusPathName, "/");
+ }
+ }
+
AsciiStrCat (CwdPlusPathName, PathName);
+ if (AsciiStrStr (CwdPlusPathName, ":") == NULL) {
+ // Extra error check to make sure we don't recusre and blow stack
+ return NULL;
+ }
+
File = EfiOpen (CwdPlusPathName, OpenMode, SectionType);
FreePool (CwdPlusPathName);
return File;
@@ -690,6 +713,10 @@ EfiOpen (
AsciiStrCpy (File->DeviceName, PathName);
File->DeviceName[FileStart - 1] = '\0';
File->FileName = &File->DeviceName[FileStart];
+ if (File->FileName[0] == '\0') {
+ // if it is just a file name use / as root
+ File->FileName = "/";
+ }
//
// Use best match algorithm on the dev names so we only need to look at the
@@ -1500,6 +1527,82 @@ EfiWrite (
}
+/**
+ Given Cwd expand Path to remove .. and replace them with real
+ directory names.
+
+ @param Cwd Current Working Directory
+ @param Path Path to expand
+
+ @return NULL Cwd or Path are not valid
+ @return 'other' Path with .. expanded
+
+**/
+CHAR8 *
+ExpandPath (
+ IN CHAR8 *Cwd,
+ IN CHAR8 *Path
+ )
+{
+ CHAR8 *NewPath;
+ CHAR8 *Work, *Start, *End;
+ UINTN StrLen;
+ UINTN i;
+
+ if (Cwd == NULL || Path == NULL) {
+ return NULL;
+ }
+
+ StrLen = AsciiStrSize (Cwd);
+ if (StrLen <= 2) {
+ // Smallest valid path is 1 char and a null
+ return NULL;
+ }
+
+ StrLen = AsciiStrSize (Path);
+ NewPath = AllocatePool (AsciiStrSize (Cwd) + StrLen + 1);
+ if (NewPath == NULL) {
+ return NULL;
+ }
+ AsciiStrCpy (NewPath, Cwd);
+
+ End = Path + StrLen;
+ for (Start = Path ;;) {
+ Work = AsciiStrStr (Start, "..") ;
+ if (Work == NULL) {
+ // Remaining part of Path contains no more ..
+ break;
+ }
+
+ // append path prior to ..
+ AsciiStrnCat (NewPath, Start, Work - Start);
+ StrLen = AsciiStrLen (NewPath);
+ for (i = StrLen; i >= 0; i--) {
+ if (NewPath[i] == ':') {
+ // too many ..
+ return NULL;
+ }
+ if (NewPath[i] == '/' || NewPath[i] == '\\') {
+ if ((i > 0) && (NewPath[i-1] == ':')) {
+ // leave the / before a :
+ NewPath[i+1] = '\0';
+ } else {
+ // replace / will Null to remove trailing file/dir reference
+ NewPath[i] = '\0';
+ }
+ break;
+ }
+ }
+
+ Start = Work + 3;
+ }
+
+ // Handle the path that remains after the ..
+ AsciiStrnCat (NewPath, Start, End - Start);
+
+ return NewPath;
+}
+
/**
Set the Curent Working Directory (CWD). If a call is made to EfiOpen () and
@@ -1518,23 +1621,65 @@ EfiSetCwd (
)
{
EFI_OPEN_FILE *File;
+ UINTN Len;
+ CHAR8 *Path;
- File = EfiOpen (Cwd, EFI_FILE_MODE_READ, 0);
- if (File == NULL) {
+ if (Cwd == NULL) {
return EFI_INVALID_PARAMETER;
}
- EfiClose (File);
+ if (AsciiStrCmp (Cwd, ".") == 0) {
+ // cd . is a no-op
+ return EFI_SUCCESS;
+ }
+ Path = Cwd;
+ if (AsciiStrStr (Cwd, "..") != NULL) {
+ if (gCwd == NULL) {
+ // no parent
+ return EFI_SUCCESS;
+ }
+
+ Len = AsciiStrLen (gCwd);
+ if ((gCwd[Len-2] == ':') && ((gCwd[Len-1] == '/') || (gCwd[Len-1] == '\\'))) {
+ // parent is device so nothing to do
+ return EFI_SUCCESS;
+ }
+
+ // Expand .. in Cwd, given we know current working directory
+ Path = ExpandPath (gCwd, Cwd);
+ if (Path == NULL) {
+ return EFI_NOT_FOUND;
+ }
+ }
+
+ File = EfiOpen (Path, EFI_FILE_MODE_READ, 0);
+ if (File == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
if (gCwd != NULL) {
FreePool (gCwd);
}
- gCwd = AllocatePool (AsciiStrSize (Cwd));
+ // Use the info returned from EfiOpen as it can add in CWD if needed. So Cwd could be
+ // relative to the current gCwd or not.
+ gCwd = AllocatePool (AsciiStrSize (File->DeviceName) + AsciiStrSize (File->FileName) + 1);
if (gCwd == NULL) {
return EFI_INVALID_PARAMETER;
}
- AsciiStrCpy (gCwd, Cwd);
+ AsciiStrCpy (gCwd, File->DeviceName);
+ if (File->FileName == NULL) {
+ AsciiStrCat (gCwd, ":\\");
+ } else {
+ AsciiStrCat (gCwd, ":");
+ AsciiStrCat (gCwd, File->FileName);
+ }
+
+ EfiClose (File);
+ if (Path != Cwd) {
+ FreePool (Path);
+ }
return EFI_SUCCESS;
}
@@ -1549,15 +1694,18 @@ EfiSetCwd (
@param Cwd Current Working Directory
- @return NULL No CWD set
+ @return "" No CWD set
@return 'other' Returns buffer that contains CWD.
**/
CHAR8 *
-EfiGettCwd (
+EfiGetCwd (
VOID
)
{
+ if (gCwd == NULL) {
+ return "";
+ }
return gCwd;
}