diff options
author | andrewfish <andrewfish@6f19259b-4bc3-4df7-8a09-765794883524> | 2010-02-10 00:46:41 +0000 |
---|---|---|
committer | andrewfish <andrewfish@6f19259b-4bc3-4df7-8a09-765794883524> | 2010-02-10 00:46:41 +0000 |
commit | 16ccac42cff45475b04dc6a06a24d569baedb427 (patch) | |
tree | e9824e15b6baa535b5227ee1db3c80f292893d1e | |
parent | 99ff63cf03c30a000056d0a51c88965700c1c7f6 (diff) | |
download | edk2-platforms-16ccac42cff45475b04dc6a06a24d569baedb427.tar.xz |
Add CWD and thus a cd command to EBL shell. Fix WatchdogTimout code in EBL, it was inside a PCD feature flag and should have been outside of the PCD so it is in all paths.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@9958 6f19259b-4bc3-4df7-8a09-765794883524
-rw-r--r-- | EmbeddedPkg/Ebl/Dir.c | 45 | ||||
-rw-r--r-- | EmbeddedPkg/Ebl/Main.c | 7 | ||||
-rw-r--r-- | EmbeddedPkg/Include/Library/EfiFileLib.h | 2 | ||||
-rw-r--r-- | EmbeddedPkg/Library/EfiFileLib/EfiFileLib.c | 168 |
4 files changed, 204 insertions, 18 deletions
diff --git a/EmbeddedPkg/Ebl/Dir.c b/EmbeddedPkg/Ebl/Dir.c index 4e9f7b98b2..ff1b557ed1 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 d3dcc58a92..ed2104cfe7 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 4e3c80d7ec..4bbb1b26f1 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 cbe2aeeceb..c58d21e820 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; } |