From 16ccac42cff45475b04dc6a06a24d569baedb427 Mon Sep 17 00:00:00 2001 From: andrewfish Date: Wed, 10 Feb 2010 00:46:41 +0000 Subject: [PATCH] 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 --- EmbeddedPkg/Ebl/Dir.c | 45 +++++- EmbeddedPkg/Ebl/Main.c | 7 +- EmbeddedPkg/Include/Library/EfiFileLib.h | 2 +- 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; } -- 2.39.2