X-Git-Url: https://code.delx.au/refind/blobdiff_plain/2569172b598d42a95c1aeb3bde752358f0b43689..8cd838bfacced99d1045a36d1618ebd9cc86ab7b:/refind/config.c diff --git a/refind/config.c b/refind/config.c index 871b0e6..c310e30 100644 --- a/refind/config.c +++ b/refind/config.c @@ -1,5 +1,5 @@ /* - * refit/config.c + * refind/config.c * Configuration file functions * * Copyright (c) 2006 Christoph Pfisterer @@ -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 @@ -305,8 +305,12 @@ VOID FreeTokenLine(IN OUT CHAR16 ***TokenList, IN OUT UINTN *TokenCount) // handle a parameter with a single integer argument static VOID HandleInt(IN CHAR16 **TokenList, IN UINTN TokenCount, OUT UINTN *Value) { - if (TokenCount == 2) - *Value = Atoi(TokenList[1]); + if (TokenCount == 2) { + if (StriCmp(TokenList[1], L"-1") == 0) + *Value = -1; + else + *Value = Atoi(TokenList[1]); + } } // handle a parameter with a single string argument @@ -340,7 +344,7 @@ VOID ReadConfig(CHAR16 *FileName) REFIT_FILE File; CHAR16 **TokenList; CHAR16 *FlagName; - CHAR16 *SelfPath = NULL; + CHAR16 *TempStr = NULL; UINTN TokenCount, i; // Set a few defaults only if we're loading the default file. @@ -350,15 +354,16 @@ VOID ReadConfig(CHAR16 *FileName) MyFreePool(GlobalConfig.DontScanDirs); if (SelfVolume) { if (SelfVolume->VolName) { - SelfPath = SelfVolume->VolName ? StrDuplicate(SelfVolume->VolName) : NULL; + TempStr = SelfVolume->VolName ? StrDuplicate(SelfVolume->VolName) : NULL; } else { - SelfPath = AllocateZeroPool(256 * sizeof(CHAR16)); - if (SelfPath != NULL) - SPrint(SelfPath, 255, L"fs%d", SelfVolume->VolNumber); + TempStr = AllocateZeroPool(256 * sizeof(CHAR16)); + if (TempStr != NULL) + SPrint(TempStr, 255, L"fs%d", SelfVolume->VolNumber); } // if/else } - MergeStrings(&SelfPath, SelfDirPath, L':'); - GlobalConfig.DontScanDirs = SelfPath; + MergeStrings(&TempStr, SelfDirPath, L':'); + MergeStrings(&TempStr, MEMTEST_LOCATIONS, L','); + GlobalConfig.DontScanDirs = TempStr; MyFreePool(GlobalConfig.DontScanFiles); GlobalConfig.DontScanFiles = StrDuplicate(DONT_SCAN_FILES); MergeStrings(&(GlobalConfig.DontScanFiles), MOK_NAMES, L','); @@ -463,6 +468,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); } @@ -779,6 +788,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, 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; + 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] = '/'; + Line = PoolPrint(L"\"Boot with normal options\" \"ro root=%s\"\n", Root); + MergeStrings((CHAR16 **) &(Options->Buffer), Line, 0); + MyFreePool(Line); + Line = PoolPrint(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 @@ -789,12 +857,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; @@ -807,17 +878,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;