From 8e261d06ab599ac8eb4d0108a88c30a0a1b8f814 Mon Sep 17 00:00:00 2001 From: srs5694 Date: Mon, 16 Apr 2012 12:43:20 -0400 Subject: [PATCH] New config file option: "also_scan_dirs". --- NEWS.txt | 12 +++++++ docs/refind/configfile.html | 5 +++ icons/{os_mint.icns => os_linuxmint.icns} | Bin refind.conf-sample | 16 ++++++++- refind/config.c | 11 +++++- refind/global.h | 1 + refind/lib.c | 19 +++++----- refind/lib.h | 1 + refind/main.c | 42 +++++++++++++++------- 9 files changed, 84 insertions(+), 23 deletions(-) rename icons/{os_mint.icns => os_linuxmint.icns} (100%) diff --git a/NEWS.txt b/NEWS.txt index 8723aa5..6ae3946 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -1,3 +1,15 @@ +0.2.7 (?/??/2012): +------------------ + +- Fixed bug that caused rEFInd to show up in its own menu sometimes. + +- Added new refind.conf token: also_scan_dirs. When scanning volumes for + EFI boot loaders, rEFInd always scans the root directory and every + subdirectory of the /EFI directory, but it doesn't recurse into these + directories. The also_scan_dirs token adds more directories to the scan + list. It defaults to "elilo,boot", but you can set it to any directory or + directories you like. + 0.2.6 (4/14/2012): ------------------ diff --git a/docs/refind/configfile.html b/docs/refind/configfile.html index ce7cebe..20e1246 100644 --- a/docs/refind/configfile.html +++ b/docs/refind/configfile.html @@ -177,6 +177,11 @@ timeout 20 internal, external, optical, hdbios, biosexternal, cd, and manual Tells rEFInd what methods to use to locate boot loaders. The internal, external, and optical parameters tell rEFInd to scan for EFI boot loaders on internal, external, and optical (CD, DVD, and Blu-ray) devices, respectively. The hdbios, biosexternal, and cd parameters are similar, but scan for BIOS boot loaders. (Note that the BIOS options are likely to be useless on UEFI PCs.) The manual parameter tells rEFInd to scan the configuration file for manual settings. You can specify multiple parameters to have the program scan for multiple boot loader types. When you do so, the order determines the order in which the boot loaders appear in the menu. The default is internal, external, optical. + + also_scan_dirs + directory path(s) + Adds the specified directory or directories to the directory list that rEFInd scans for EFI boot loaders when scanfor includes the internal, external, or optical options. Directories are specified relative to the filesystem's root directory. If this option is used, it's applied to all the filesystems that rEFInd scans. If a specified directory doesn't exist, rEFInd ignores it (no error results). + default_selection A substring of a boot loader's title diff --git a/icons/os_mint.icns b/icons/os_linuxmint.icns similarity index 100% rename from icons/os_mint.icns rename to icons/os_linuxmint.icns diff --git a/refind.conf-sample b/refind.conf-sample index 7e3cb2c..97a01df 100644 --- a/refind.conf-sample +++ b/refind.conf-sample @@ -55,6 +55,7 @@ timeout 20 # systems) # reboot - a tag to reboot the computer # Default is shell,about,shutdown,reboot +# #showtools shell, about, reboot # Which types of boot loaders to search, and in what order to display them: @@ -66,7 +67,20 @@ timeout 20 # cd - BIOS optical-disc boot loaders # manual - use stanzas later in this configuration file # Default is internal,external,optical -scanfor internal,external,optical +# +#scanfor internal,external,optical + +# When scanning volumes for EFI boot loaders, rEFInd always looks for +# Mac OS X's and Microsoft Windows' boot loaders in their normal locations, +# and scans the root directory and every subdirectory of the /EFI directory +# for additional boot loaders, but it doesn't recurse into these directories. +# The also_scan_dirs token adds more directories to the scan list. +# Directories are specified relative to the volume's root directory. This +# option applies to ALL the volumes that rEFInd scans. If a specified +# directory doesn't exist, it's ignored (no error condition results). +# The default is to scan no additional directories. +# +#also_scan_dirs boot,EFI/linux/kernels # Set the maximum number of tags that can be displayed on the screen at # any time. If more loaders are discovered than this value, rEFInd shows diff --git a/refind/config.c b/refind/config.c index 8016931..7ad8f91 100644 --- a/refind/config.c +++ b/refind/config.c @@ -357,7 +357,16 @@ VOID ReadConfig(VOID) else GlobalConfig.ScanFor[i] = ' '; } - } else if (StriCmp(TokenList[0], L"showtools") == 0) { + + } else if (StriCmp(TokenList[0], L"also_scan_dirs") == 0) { + if (GlobalConfig.AlsoScan != NULL) { + FreePool(GlobalConfig.AlsoScan); + GlobalConfig.AlsoScan = NULL; + } // if + for (i = 1; i < TokenCount; i++) + MergeStrings(&GlobalConfig.AlsoScan, TokenList[i], L','); + + } else if (StriCmp(TokenList[0], L"showtools") == 0) { SetMem(GlobalConfig.ShowTools, NUM_TOOLS * sizeof(UINTN), 0); for (i = 1; (i < TokenCount) && (i < NUM_TOOLS); i++) { FlagName = TokenList[i]; diff --git a/refind/global.h b/refind/global.h index 9489bee..d61676b 100644 --- a/refind/global.h +++ b/refind/global.h @@ -159,6 +159,7 @@ typedef struct { CHAR16 *SelectionSmallFileName; CHAR16 *SelectionBigFileName; CHAR16 *DefaultSelection; + CHAR16 *AlsoScan; UINTN ShowTools[NUM_TOOLS]; CHAR8 ScanFor[NUM_SCAN_OPTIONS]; // codes of types of loaders for which to scan } REFIT_CONFIG; diff --git a/refind/lib.c b/refind/lib.c index e78ae6a..f5037c5 100644 --- a/refind/lib.c +++ b/refind/lib.c @@ -79,8 +79,9 @@ static VOID UninitVolumes(VOID); // Converts forward slashes to backslashes and removes duplicate slashes. // Necessary because some (buggy?) EFI implementations produce "\/" strings -// in pathnames. -static VOID CleanUpPathNameSlashes(IN OUT CHAR16 *PathName) { +// in pathnames and because some user inputs can produce duplicate directory +// separators +VOID CleanUpPathNameSlashes(IN OUT CHAR16 *PathName) { CHAR16 *NewName; UINTN i, j = 0; BOOLEAN LastWasSlash = FALSE; @@ -1076,8 +1077,8 @@ VOID MergeStrings(IN OUT CHAR16 **First, IN CHAR16 *Second, CHAR16 AddChar) { if (Second != NULL) Length2 = StrLen(Second); NewString = AllocatePool(sizeof(CHAR16) * (Length1 + Length2 + 2)); - NewString[0] = L'\0'; if (NewString != NULL) { + NewString[0] = L'\0'; if (*First != NULL) { StrCat(NewString, *First); if (AddChar) { @@ -1085,7 +1086,7 @@ VOID MergeStrings(IN OUT CHAR16 **First, IN CHAR16 *Second, CHAR16 AddChar) { NewString[Length1 + 1] = 0; } // if (AddChar) } // if (*First != NULL) - if (First != NULL) + if (Second != NULL) StrCat(NewString, Second); FreePool(*First); *First = NewString; @@ -1174,7 +1175,7 @@ CHAR16 *FindNumbers(IN CHAR16 *InString) { // Find the #Index element (numbered from 0) in a comma-delimited string // of elements. -// Returns the found element, or NULL if Index is out of range of InString +// Returns the found element, or NULL if Index is out of range or InString // is NULL. CHAR16 *FindCommaDelimited(IN CHAR16 *InString, IN UINTN Index) { UINTN StartPos = 0, CurPos = 0; @@ -1197,10 +1198,10 @@ CHAR16 *FindCommaDelimited(IN CHAR16 *InString, IN UINTN Index) { else CurPos++; } // while + if (Index == 0) + FoundString = StrDuplicate(&InString[StartPos]); + if (FoundString != NULL) + FoundString[CurPos - StartPos] = 0; } // if - if (Index == 0) - FoundString = StrDuplicate(&InString[StartPos]); - if (FoundString != NULL) - FoundString[CurPos - StartPos] = 0; return (FoundString); } // CHAR16 *FindCommaDelimited() diff --git a/refind/lib.h b/refind/lib.h index 374fecb..d888b98 100644 --- a/refind/lib.h +++ b/refind/lib.h @@ -73,6 +73,7 @@ EFI_STATUS InitRefitLib(IN EFI_HANDLE ImageHandle); VOID UninitRefitLib(VOID); EFI_STATUS ReinitRefitLib(VOID); +VOID CleanUpPathNameSlashes(IN OUT CHAR16 *PathName); VOID CreateList(OUT VOID ***ListPtr, OUT UINTN *ElementCount, IN UINTN InitialElementCount); VOID AddListElement(IN OUT VOID ***ListPtr, IN OUT UINTN *ElementCount, IN VOID *NewElement); VOID FreeList(IN OUT VOID ***ListPtr, IN OUT UINTN *ElementCount /*, IN Callback*/); diff --git a/refind/main.c b/refind/main.c index 5e8496e..058728c 100644 --- a/refind/main.c +++ b/refind/main.c @@ -72,7 +72,7 @@ static REFIT_MENU_ENTRY MenuEntryExit = { L"Exit rEFInd", TAG_EXIT, 1, 0, 0, static REFIT_MENU_SCREEN MainMenu = { L"Main Menu", NULL, 0, NULL, 0, NULL, 0, L"Automatic boot" }; static REFIT_MENU_SCREEN AboutMenu = { L"About", NULL, 0, NULL, 0, NULL, 0, NULL }; -REFIT_CONFIG GlobalConfig = { FALSE, 20, 0, 0, NULL, NULL, NULL, NULL, +REFIT_CONFIG GlobalConfig = { FALSE, 20, 0, 0, NULL, NULL, NULL, NULL, NULL, {TAG_SHELL, TAG_ABOUT, TAG_SHUTDOWN, TAG_REBOOT, 0, 0, 0, 0, 0 }}; // @@ -83,7 +83,7 @@ static VOID AboutrEFInd(VOID) { if (AboutMenu.EntryCount == 0) { AboutMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT); - AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.2.6"); + AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.2.6.1"); AddMenuInfoLine(&AboutMenu, L""); AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer"); AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012 Roderick W. Smith"); @@ -606,6 +606,7 @@ VOID SetLoaderDefaults(LOADER_ENTRY *Entry, CHAR16 *LoaderPath, IN REFIT_VOLUME LOADER_ENTRY * AddLoaderEntry(IN CHAR16 *LoaderPath, IN CHAR16 *LoaderTitle, IN REFIT_VOLUME *Volume) { LOADER_ENTRY *Entry; + CleanUpPathNameSlashes(LoaderPath); Entry = InitializeLoaderEntry(NULL); if (Entry != NULL) { Entry->Title = StrDuplicate(LoaderTitle); @@ -630,12 +631,18 @@ static VOID ScanLoaderDir(IN REFIT_VOLUME *Volume, IN CHAR16 *Path) EFI_STATUS Status; REFIT_DIR_ITER DirIter; EFI_FILE_INFO *DirEntry; - CHAR16 FileName[256]; + CHAR16 FileName[256], *SelfPath; + UINTN i = 0; + + // Skip past leading slashes, which are sometimes (but not always) included + // in SelfDirPath, to get a path that's known to never include this feature. + while ((SelfDirPath != NULL) && (SelfDirPath[i] == L'\\')) { + i++; + } + SelfPath = &SelfDirPath[i]; // NOTE: *DO NOT* call FreePool() on SelfPath!!! - // Note: SelfDirPath includes a leading backslash ('\'), but Path - // doesn't, so we rejigger the string to compensate.... - if (!SelfDirPath || !Path || ((StriCmp(Path, &SelfDirPath[1]) == 0) && Volume != SelfVolume) || - (StriCmp(Path, &SelfDirPath[1]) != 0)) { + if (!SelfPath || !Path || ((StriCmp(Path, SelfPath) == 0) && Volume != SelfVolume) || + (StriCmp(Path, SelfPath) != 0)) { // look through contents of the directory DirIterOpen(Volume->RootDir, Path, &DirIter); while (DirIterNext(&DirIter, 2, L"*.efi", &DirEntry)) { @@ -667,7 +674,8 @@ static VOID ScanEfiFiles(REFIT_VOLUME *Volume) { EFI_STATUS Status; REFIT_DIR_ITER EfiDirIter; EFI_FILE_INFO *EfiDirEntry; - CHAR16 FileName[256]; + CHAR16 FileName[256], *Directory; + UINTN i, Length; if ((Volume->RootDir != NULL) && (Volume->VolName != NULL)) { // check for Mac OS X boot loader @@ -690,10 +698,6 @@ static VOID ScanEfiFiles(REFIT_VOLUME *Volume) { // scan the root directory for EFI executables ScanLoaderDir(Volume, NULL); - // scan the elilo directory (as used on gimli's first Live CD) - ScanLoaderDir(Volume, L"elilo"); - // scan the boot directory - ScanLoaderDir(Volume, L"boot"); // scan subdirectories of the EFI directory (as per the standard) DirIterOpen(Volume->RootDir, L"EFI", &EfiDirIter); @@ -706,6 +710,20 @@ static VOID ScanEfiFiles(REFIT_VOLUME *Volume) { Status = DirIterClose(&EfiDirIter); if (Status != EFI_NOT_FOUND) CheckError(Status, L"while scanning the EFI directory"); + + // Scan user-specified (or additional default) directories.... + i = 0; + while ((Directory = FindCommaDelimited(GlobalConfig.AlsoScan, i++)) != NULL) { + Length = StrLen(Directory); + // Some EFI implementations won't read a directory if the path ends in + // a backslash, so eliminate this character, if it's present.... + while ((Length > 0) && (Directory[Length - 1] == L'\\')) { + Directory[--Length] = 0; + } // while + if (Length > 0) + ScanLoaderDir(Volume, Directory); + FreePool(Directory); + } // while } // if } // static VOID ScanEfiFiles() -- 2.39.2