Added support for "%v" as a variable for the kernel version number in
authorsrs5694 <srs5694@users.sourceforge.net>
Fri, 3 Mar 2017 01:38:30 +0000 (20:38 -0500)
committersrs5694 <srs5694@users.sourceforge.net>
Fri, 3 Mar 2017 01:38:30 +0000 (20:38 -0500)
refind_linux.conf.

NEWS.txt
refind/global.h
refind/main.c
refind/mystrings.c
refind/mystrings.h

index 7e218c1..13f18d5 100644 (file)
--- a/NEWS.txt
+++ b/NEWS.txt
@@ -1,6 +1,18 @@
 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
index efb16d0..0da3ff3 100644 (file)
 #define NULL_GUID_VALUE { 0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} };
 #define REFIND_GUID_VALUE { 0x36D08FA7, 0xCF0B, 0x42F5, {0x8F, 0x14, 0x68, 0xDF, 0x73, 0xED, 0x37, 0x40} };
 
+// Configuration file variables
+#define KERNEL_VERSION L"%v"
+
 //
 // global definitions
 //
index bdfa6ac..eeb7719 100644 (file)
@@ -757,7 +757,7 @@ REFIT_MENU_SCREEN *InitializeSubScreen(IN LOADER_ENTRY *Entry) {
 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;
@@ -855,6 +855,8 @@ VOID GenerateSubScreen(LOADER_ENTRY *Entry, IN REFIT_VOLUME *Volume, IN BOOLEAN
         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....
@@ -864,6 +866,7 @@ VOID GenerateSubScreen(LOADER_ENTRY *Entry, IN REFIT_VOLUME *Volume, IN BOOLEAN
             } // 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);
@@ -943,20 +946,24 @@ VOID GenerateSubScreen(LOADER_ENTRY *Entry, IN REFIT_VOLUME *Volume, IN BOOLEAN
     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()
 
@@ -1143,16 +1150,19 @@ static LOADER_ENTRY * AddLoaderEntry(IN CHAR16 *LoaderPath, IN CHAR16 *LoaderTit
 // 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');
@@ -1176,6 +1186,7 @@ static VOID AddKernelToSubmenu(LOADER_ENTRY * TargetLoader, CHAR16 *FileName, RE
         MyFreePool(InitrdName);
         MyFreePool(File);
     } // if
+    MyFreePool(KernelVersion);
 } // static VOID AddKernelToSubmenu()
 
 // Returns -1 if (Time1 < Time2), +1 if (Time1 > Time2), or 0 if
index 75e2d89..ca7a6a1 100644 (file)
@@ -348,6 +348,29 @@ BOOLEAN IsInSubstring(IN CHAR16 *BigString, IN CHAR16 *List) {
    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) {
index b79a4b7..d2ff7d7 100644 (file)
@@ -51,6 +51,7 @@ UINTN NumCharsInCommon(IN CHAR16* String1, IN CHAR16* String2);
 CHAR16 *FindCommaDelimited(IN CHAR16 *InString, IN UINTN Index);
 BOOLEAN IsIn(IN CHAR16 *SmallString, IN CHAR16 *List);
 BOOLEAN IsInSubstring(IN CHAR16 *BigString, IN CHAR16 *List);
+BOOLEAN ReplaceSubstring(IN OUT CHAR16 **MainString, IN CHAR16 *SearchString, IN CHAR16 *ReplString);
 
 BOOLEAN IsValidHex(CHAR16 *Input);
 UINT64 StrToHex(CHAR16 *Input, UINTN Position, UINTN NumChars);