]> code.delx.au - refind/blobdiff - refind/config.c
Support for memtest86 as a second-row item.
[refind] / refind / config.c
index c18e979d4c7dd331501ca8151a937255c5adf768..5dfea7de2a93236168c642d8ebd84088b6a4e2af 100644 (file)
@@ -35,7 +35,7 @@
  */
 
 /*
- * Modifications copyright (c) 2012 Roderick W. Smith
+ * Modifications copyright (c) 2012-2013 Roderick W. Smith
  * 
  * Modifications distributed under the terms of the GNU General Public
  * License (GPL) version 3 (GPLv3), a copy of which must be distributed
@@ -463,6 +463,10 @@ VOID ReadConfig(CHAR16 *FileName)
                    GlobalConfig.ShowTools[i - 1] = TAG_APPLE_RECOVERY;
                 } else if (StriCmp(FlagName, L"mok_tool") == 0) {
                    GlobalConfig.ShowTools[i - 1] = TAG_MOK_TOOL;
+                } else if (StriCmp(FlagName, L"firmware") == 0) {
+                   GlobalConfig.ShowTools[i - 1] = TAG_FIRMWARE;
+                } else if ((StriCmp(FlagName, L"memtest86") == 0) || (StriCmp(FlagName, L"memtest") == 0)) {
+                   GlobalConfig.ShowTools[i - 1] = TAG_MEMTEST;
                 } else {
                    Print(L" unknown showtools flag: '%s'\n", FlagName);
                 }
@@ -497,6 +501,9 @@ VOID ReadConfig(CHAR16 *FileName)
            else
               GlobalConfig.RequestedScreenHeight = 0;
 
+        } else if (StriCmp(TokenList[0], L"screensaver") == 0) {
+           HandleInt(TokenList, TokenCount, &(GlobalConfig.ScreensaverTime));
+
         } else if (StriCmp(TokenList[0], L"use_graphics_for") == 0) {
            GlobalConfig.GraphicsFor = 0;
            for (i = 1; i < TokenCount; i++) {
@@ -776,6 +783,65 @@ VOID ScanUserConfigured(CHAR16 *FileName)
    } // if()
 } // VOID ScanUserConfigured()
 
+// Create an options file based on /etc/fstab. The resulting file has two options
+// lines, one of which boots the system with "ro root={rootfs}" and the other of
+// which boots the system with "ro root={rootfs} single", where "{rootfs}" is the
+// filesystem identifier associated with the "/" line in /etc/fstab.
+static REFIT_FILE * GenerateOptionsFromEtcFstab(REFIT_VOLUME *Volume) {
+   UINTN        TokenCount, i;
+   REFIT_FILE   *Options = NULL, *Fstab = NULL;
+   EFI_STATUS   Status;
+   CHAR16       **TokenList, Line[513], Root[100];
+
+   if (FileExists(Volume->RootDir, L"\\etc\\fstab")) {
+      Options = AllocateZeroPool(sizeof(REFIT_FILE));
+      Fstab = AllocateZeroPool(sizeof(REFIT_FILE));
+      Status = ReadFile(Volume->RootDir, L"\\etc\\fstab", Fstab, &i);
+      if (CheckError(Status, L"while reading /etc/fstab")) {
+         if (Options != NULL)
+            FreePool(Options);
+         if (Fstab != NULL)
+            FreePool(Fstab);
+         Options = NULL;
+         Fstab = NULL;
+      } else { // File read; locate root fs and create entries
+         Options->Encoding = ENCODING_UTF16_LE;
+         Line[0] = '\0';
+         while ((TokenCount = ReadTokenLine(Fstab, &TokenList)) > 0) {
+            if (TokenCount > 2) {
+               Root[0] = '\0';
+               if (StriCmp(TokenList[1], L"\\") == 0) {
+                  SPrint(Root, 99, L"%s", TokenList[0]);
+               } else if (StriCmp(TokenList[2], L"\\") == 0) {
+                  SPrint(Root, 99, L"%s=%s", TokenList[0], TokenList[1]);
+               } // if/elseif/elseif
+               if (Root[0] != L'\0') {
+                  for (i = 0; i < StrLen(Root); i++)
+                     if (Root[i] == '\\')
+                        Root[i] = '/';
+                  SPrint(Line, 512, L"\"Boot with normal options\"    \"ro root=%s\"\n", Root);
+                  MergeStrings((CHAR16 **) &(Options->Buffer), Line, 0);
+                  SPrint(Line, 512, L"\"Boot into single-user mode\"  \"ro root=%s single\"\n", Root);
+                  MergeStrings((CHAR16**) &(Options->Buffer), Line, 0);
+                  Options->BufferSize = StrLen((CHAR16*) Options->Buffer) * sizeof(CHAR16);
+               } // if
+            } // if
+            FreeTokenLine(&TokenList, &TokenCount);
+         } // while
+
+         Options->Current8Ptr  = (CHAR8 *)Options->Buffer;
+         Options->End8Ptr      = Options->Current8Ptr + Options->BufferSize;
+         Options->Current16Ptr = (CHAR16 *)Options->Buffer;
+         Options->End16Ptr     = Options->Current16Ptr + (Options->BufferSize >> 1);
+
+         MyFreePool(Fstab->Buffer);
+         MyFreePool(Fstab);
+      } // if/else file read error
+   } // if /etc/fstab exists
+   return Options;
+} // GenerateOptionsFromEtcFstab()
+
+
 // 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
@@ -786,12 +852,15 @@ VOID ScanUserConfigured(CHAR16 *FileName)
 // 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.
+// If a rEFInd options file can't be found, try to generate minimal options from
+// /etc/fstab on the same volume as the kernel. This typically works only if the
+// kernel is being read from the Linux root filesystem.
 //
 // 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, *FullFilename;
-   BOOLEAN      GoOn = TRUE;
+   BOOLEAN      GoOn = TRUE, FileFound = FALSE;
    UINTN        i = 0, size;
    REFIT_FILE   *File = NULL;
    EFI_STATUS   Status;
@@ -804,17 +873,20 @@ REFIT_FILE * ReadLinuxOptionsFile(IN CHAR16 *LoaderPath, IN REFIT_VOLUME *Volume
          if (FileExists(Volume->RootDir, FullFilename)) {
             File = AllocateZeroPool(sizeof(REFIT_FILE));
             Status = ReadFile(Volume->RootDir, FullFilename, File, &size);
-            GoOn = FALSE;
             if (CheckError(Status, L"while loading the Linux options file")) {
                if (File != NULL)
                   FreePool(File);
                File = NULL;
-               GoOn = TRUE;
-            } // if error
+            } else {
+               GoOn = FALSE;
+               FileFound = TRUE;
+            } // if/else error
          } // if file exists
       } else { // a filename string is NULL
          GoOn = FALSE;
       } // if/else
+      if (!FileFound)
+         File = GenerateOptionsFromEtcFstab(Volume);
       MyFreePool(OptionsFilename);
       MyFreePool(FullFilename);
       OptionsFilename = FullFilename = NULL;