// constants
-#define CONFIG_FILE_NAME L"refind.conf"
-#define LINUX_OPTIONS_FILENAME L"linux.conf"
-#define MAXCONFIGFILESIZE (128*1024)
+#define CONFIG_FILE_NAME L"refind.conf"
+#define LINUX_OPTIONS_FILENAMES L"refind_linux.conf,linux.conf"
+#define MAXCONFIGFILESIZE (128*1024)
#define ENCODING_ISO8859_1 (0)
#define ENCODING_UTF8 (1)
// Read a Linux kernel options file for a Linux boot loader into memory. The LoaderPath
// and Volume variables identify the location of the options file, but not its name --
// you pass this function the filename of the Linux kernel, initial RAM disk, or other
-// file in the target directory, and this function finds the file with the name
-// LINUX_OPTIONS_FILENAME within that directory and loads it.
+// file in the target directory, and this function finds the file with a name in the
+// comma-delimited list of names specified by LINUX_OPTIONS_FILENAMES within that
+// directory and loads it. This function tries multiple files because I originally
+// used the filename linux.conf, but close on the heels of that decision, the Linux
+// kernel developers decided to use that name for a similar purpose, but with a
+// different file format. Thus, I'm migrating rEFInd to use the name refind_linux.conf,
+// but I want a migration period in which both names are used.
+//
// The return value is a pointer to the REFIT_FILE handle for the file, or NULL if
// it wasn't found.
REFIT_FILE * ReadLinuxOptionsFile(IN CHAR16 *LoaderPath, IN REFIT_VOLUME *Volume) {
- CHAR16 *OptionsFilename = NULL;
+ CHAR16 *OptionsFilename, *FullFilename;
+ BOOLEAN GoOn = TRUE;
+ UINTN i = 0;
REFIT_FILE *File = NULL;
EFI_STATUS Status;
-
- OptionsFilename = FindPath(LoaderPath);
- MergeStrings(&OptionsFilename, LINUX_OPTIONS_FILENAME, L'\\');
- if (FileExists(Volume->RootDir, OptionsFilename)) {
- File = AllocateZeroPool(sizeof(REFIT_FILE));
- Status = ReadFile(Volume->RootDir, OptionsFilename, File);
- if (CheckError(Status, L"while loading the Linux options file"))
- File = NULL;
- }
- if (OptionsFilename != NULL)
- FreePool(OptionsFilename);
+
+ do {
+ OptionsFilename = FindCommaDelimited(LINUX_OPTIONS_FILENAMES, i++);
+ FullFilename = FindPath(LoaderPath);
+ if ((OptionsFilename != NULL) && (FullFilename != NULL)) {
+ MergeStrings(&FullFilename, OptionsFilename, '\\');
+ if (FileExists(Volume->RootDir, FullFilename)) {
+ File = AllocateZeroPool(sizeof(REFIT_FILE));
+ Status = ReadFile(Volume->RootDir, FullFilename, File);
+ GoOn = FALSE;
+ if (CheckError(Status, L"while loading the Linux options file"))
+ File = NULL;
+ } // if
+ } else {
+ GoOn = FALSE;
+ } // if/else
+ if (OptionsFilename != NULL)
+ FreePool(OptionsFilename);
+ if (FullFilename != NULL)
+ FreePool(FullFilename);
+ OptionsFilename = FullFilename = NULL;
+ } while (GoOn);
return (File);
} // static REFIT_FILE * FindLinuxOptionsFile()
// Load an icon for an operating system
//
+// Load an OS icon from among the comma-delimited list provided in OSIconName.
EG_IMAGE * LoadOSIcon(IN CHAR16 *OSIconName OPTIONAL, IN CHAR16 *FallbackIconName, BOOLEAN BootLogo)
{
EG_IMAGE *Image;
- CHAR16 CutoutName[16];
+ CHAR16 *CutoutName;
CHAR16 FileName[256];
- UINTN StartIndex, Index, NextIndex;
+ UINTN Index = 0;
if (GlobalConfig.TextOnly) // skip loading if it's not used anyway
return NULL;
- Image = NULL;
// try the names from OSIconName
- for (StartIndex = 0; OSIconName != NULL && OSIconName[StartIndex]; StartIndex = NextIndex) {
- // find the next name in the list
- NextIndex = 0;
- for (Index = StartIndex; OSIconName[Index]; Index++) {
- if (OSIconName[Index] == ',') {
- NextIndex = Index + 1;
- break;
- }
- }
- if (OSIconName[Index] == 0)
- NextIndex = Index;
-
- // construct full path
- if (Index > StartIndex + 15) // prevent buffer overflow
- continue;
- CopyMem(CutoutName, OSIconName + StartIndex, (Index - StartIndex) * sizeof(CHAR16));
- CutoutName[Index - StartIndex] = 0;
- SPrint(FileName, 255, L"icons\\%s_%s.icns",
- BootLogo ? L"boot" : L"os", CutoutName);
-
+ while ((CutoutName = FindCommaDelimited(OSIconName, Index++)) != NULL) {
+ SPrint(FileName, 255, L"icons\\%s_%s.icns", BootLogo ? L"boot" : L"os", CutoutName);
+
// try to load it
Image = egLoadIcon(SelfDir, FileName, 128);
if (Image != NULL)
return Image;
- }
+ FreePool(CutoutName);
+ } // while
// try the fallback name
- SPrint(FileName, 255, L"icons\\%s_%s.icns",
- BootLogo ? L"boot" : L"os", FallbackIconName);
+ SPrint(FileName, 255, L"icons\\%s_%s.icns", BootLogo ? L"boot" : L"os", FallbackIconName);
Image = egLoadIcon(SelfDir, FileName, 128);
if (Image != NULL)
return Image;
return LoadOSIcon(NULL, FallbackIconName, FALSE);
return DummyImage(128);
-}
+} /* EG_IMAGE * LoadOSIcon() */
//
// Load an image from a .icns file
} // if (EndOfElement > 0)
return (Found);
} // CHAR16 *FindNumbers()
+
+// 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
+// is NULL.
+CHAR16 *FindCommaDelimited(IN CHAR16 *InString, IN UINTN Index) {
+ UINTN StartPos = 0, CurPos = 0;
+ BOOLEAN Found = FALSE;
+ CHAR16 *FoundString = NULL;
+
+ if (InString != NULL) {
+ // After while() loop, StartPos marks start of item #Index
+ while ((Index > 0) && (CurPos < StrLen(InString))) {
+ if (InString[CurPos] == L',') {
+ Index--;
+ StartPos = CurPos + 1;
+ } // if
+ CurPos++;
+ } // while
+ // After while() loop, CurPos is one past the end of the element
+ while ((CurPos < StrLen(InString)) && (!Found)) {
+ if (InString[CurPos] == L',')
+ Found = TRUE;
+ else
+ CurPos++;
+ } // while
+ } // if
+ if (Index == 0)
+ FoundString = StrDuplicate(&InString[StartPos]);
+ if (FoundString != NULL)
+ FoundString[CurPos - StartPos] = 0;
+ return (FoundString);
+} // CHAR16 *FindCommaDelimited()
CHAR16 *FindLastDirName(IN CHAR16 *Path);
CHAR16 *FindPath(IN CHAR16* FullPath);
CHAR16 *FindNumbers(IN CHAR16 *InString);
+CHAR16 *FindCommaDelimited(IN CHAR16 *InString, IN UINTN Index);
#endif
\ No newline at end of file
{
if (AboutMenu.EntryCount == 0) {
AboutMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT);
- AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.2.2");
+ AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.2.2.1");
AddMenuInfoLine(&AboutMenu, L"");
AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer");
AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012 Roderick W. Smith");
while ((DirIterNext(&DirIter, 2, L"init*", &DirEntry)) && (InitrdName == NULL)) {
InitrdVersion = FindNumbers(DirEntry->FileName);
if (KernelVersion != NULL) {
-// if (StriSubCmp(KernelVersion, DirEntry->FileName)) {
if (StriCmp(InitrdVersion, KernelVersion) == 0)
InitrdName = PoolPrint(L"%s\\%s", Path, DirEntry->FileName);
-// } // if match found
} else {
if (InitrdVersion == NULL)
InitrdName = PoolPrint(L"%s\\%s", Path, DirEntry->FileName);
SubEntry = InitializeLoaderEntry(Entry);
if (SubEntry != NULL) {
SubEntry->me.Title = L"Boot using default options";
-// SubEntry->me.Title = (Entry->OSType == 'M') ? L"Boot Mac OS X" : PoolPrint(L"Run %s", FileName);
if ((SubEntry->InitrdPath != NULL) && (StrLen(SubEntry->InitrdPath) > 0) && (!StriSubCmp(L"initrd", SubEntry->LoadOptions))) {
Temp = PoolPrint(L"initrd=%s", SubEntry->InitrdPath);
MergeStrings(&SubEntry->LoadOptions, Temp, L' ');