0.10.5 (??/??/2017):
--------------------
+- Two improvements to initrd detection for Linux kernels:
+ - If multiple initrd files match the kernel's version number, the file
+ with more matching characters after the version number is used, rather
+ than the first initrd file found.
+ - The "%v" string, if present in the refind_linux.conf file's second
+ field, will be replaced by the kernel version number. Thus, you can
+ specify options like:
+ "Boot with standard initrd" "ro root=/dev/sda2 initrd=initrd-%v-std"
+ "Boot with debug initrd" "ro root=/dev/sda2 initrd=initrd-%v-debug"
+ This enables using multiple initrd files per kernel, to be used for
+ different purposes.
+
- Minor code optimization.
- Add new key mappings: Backspace (Delete on Mac keyboards) works the same
VOID GenerateSubScreen(LOADER_ENTRY *Entry, IN REFIT_VOLUME *Volume, IN BOOLEAN GenerateReturn) {
REFIT_MENU_SCREEN *SubScreen;
LOADER_ENTRY *SubEntry;
- CHAR16 *InitrdName;
+ CHAR16 *InitrdName, *KernelVersion = NULL;
CHAR16 DiagsFileName[256];
REFIT_FILE *File;
UINTN TokenCount;
if (File != NULL) {
InitrdName = FindInitrd(Entry->LoaderPath, Volume);
TokenCount = ReadTokenLine(File, &TokenList);
+ KernelVersion = FindNumbers(Entry->LoaderPath);
+ ReplaceSubstring(&(TokenList[1]), KERNEL_VERSION, KernelVersion);
// first entry requires special processing, since it was initially set
// up with a default title but correct options by InitializeSubScreen(),
// earlier....
} // if
FreeTokenLine(&TokenList, &TokenCount);
while ((TokenCount = ReadTokenLine(File, &TokenList)) > 1) {
+ ReplaceSubstring(&(TokenList[1]), KERNEL_VERSION, KernelVersion);
SubEntry = InitializeLoaderEntry(Entry);
SubEntry->me.Title = TokenList[0] ? StrDuplicate(TokenList[0]) : StrDuplicate(L"Boot Linux");
MyFreePool(SubEntry->LoadOptions);
if (GenerateReturn)
AddMenuEntry(SubScreen, &MenuEntryReturn);
Entry->me.SubScreen = SubScreen;
+ MyFreePool(KernelVersion);
} // VOID GenerateSubScreen()
// Returns options for a Linux kernel. Reads them from an options file in the
// kernel's directory; and if present, adds an initrd= option for an initial
// RAM disk file with the same version number as the kernel file.
static CHAR16 * GetMainLinuxOptions(IN CHAR16 * LoaderPath, IN REFIT_VOLUME *Volume) {
- CHAR16 *Options = NULL, *InitrdName, *FullOptions = NULL;
+ CHAR16 *Options = NULL, *InitrdName, *FullOptions = NULL, *KernelVersion;
Options = GetFirstOptionsFromFile(LoaderPath, Volume);
InitrdName = FindInitrd(LoaderPath, Volume);
+ KernelVersion = FindNumbers(InitrdName);
+ ReplaceSubstring(&Options, KERNEL_VERSION, KernelVersion);
FullOptions = AddInitrdToOptions(Options, InitrdName);
MyFreePool(Options);
MyFreePool(InitrdName);
+ MyFreePool(KernelVersion);
return (FullOptions);
} // static CHAR16 * GetMainLinuxOptions()
// Add a Linux kernel as a submenu entry for another (pre-existing) Linux kernel entry.
static VOID AddKernelToSubmenu(LOADER_ENTRY * TargetLoader, CHAR16 *FileName, REFIT_VOLUME *Volume) {
REFIT_FILE *File;
- CHAR16 **TokenList = NULL, *InitrdName, *SubmenuName = NULL, *VolName = NULL, *Path = NULL, *Title;
+ CHAR16 **TokenList = NULL, *InitrdName, *SubmenuName = NULL, *VolName = NULL;
+ CHAR16 *Path = NULL, *Title, *KernelVersion;
REFIT_MENU_SCREEN *SubScreen;
LOADER_ENTRY *SubEntry;
UINTN TokenCount;
+ KernelVersion = FindNumbers(FileName);
File = ReadLinuxOptionsFile(TargetLoader->LoaderPath, Volume);
if (File != NULL) {
SubScreen = TargetLoader->me.SubScreen;
InitrdName = FindInitrd(FileName, Volume);
while ((TokenCount = ReadTokenLine(File, &TokenList)) > 1) {
+ ReplaceSubstring(&(TokenList[1]), KERNEL_VERSION, KernelVersion);
SubEntry = InitializeLoaderEntry(TargetLoader);
SplitPathName(FileName, &VolName, &Path, &SubmenuName);
MergeStrings(&SubmenuName, L": ", '\0');
MyFreePool(InitrdName);
MyFreePool(File);
} // if
+ MyFreePool(KernelVersion);
} // static VOID AddKernelToSubmenu()
// Returns -1 if (Time1 < Time2), +1 if (Time1 > Time2), or 0 if
return Found;
} // BOOLEAN IsSubstringIn()
+// Replace *SearchString in **MainString with *ReplString.
+// Returns TRUE if replacement was done, FALSE otherwise.
+BOOLEAN ReplaceSubstring(IN OUT CHAR16 **MainString, IN CHAR16 *SearchString, IN CHAR16 *ReplString) {
+ BOOLEAN WasReplaced = FALSE;
+ CHAR16 *FoundSearchString, *NewString, *EndString;
+
+ FoundSearchString = MyStrStr(*MainString, SearchString);
+ if (FoundSearchString) {
+ NewString = AllocateZeroPool(sizeof(CHAR16) * StrLen(*MainString));
+ if (NewString) {
+ EndString = &(FoundSearchString[StrLen(SearchString)]);
+ FoundSearchString[0] = L'\0';
+ StrCpy(NewString, *MainString);
+ MergeStrings(&NewString, ReplString, L'\0');
+ MergeStrings(&NewString, EndString, L'\0');
+ MyFreePool(MainString);
+ *MainString = NewString;
+ WasReplaced = TRUE;
+ } // if
+ } // if
+ return WasReplaced;
+} // BOOLEAN ReplaceSubstring()
+
// Returns TRUE if *Input contains nothing but valid hexadecimal characters,
// FALSE otherwise. Note that a leading "0x" is NOT acceptable in the input!
BOOLEAN IsValidHex(CHAR16 *Input) {