X-Git-Url: https://code.delx.au/refind/blobdiff_plain/3d84a5e2a9686674b50c73749d9e9c52e7fc292a..2f0e524a93415ad4a3128320dfc043841c3a0da8:/refind/main.c diff --git a/refind/main.c b/refind/main.c index 5805685..586fdd9 100644 --- a/refind/main.c +++ b/refind/main.c @@ -87,6 +87,7 @@ #define FALLBACK_FULLNAME L"EFI\\BOOT\\bootx64.efi" #define FALLBACK_BASENAME L"bootx64.efi" #define EFI_STUB_ARCH 0x8664 +EFI_GUID gFreedesktopRootGuid = { 0x4f68bce3, 0xe8cd, 0x4db1, { 0x96, 0xe7, 0xfb, 0xca, 0xf9, 0x84, 0xb7, 0x09 }}; #elif defined (EFI32) #define SHELL_NAMES L"\\EFI\\tools\\shell.efi,\\EFI\\tools\\shellia32.efi,\\shell.efi,\\shellia32.efi" #define GPTSYNC_NAMES L"\\EFI\\tools\\gptsync.efi,\\EFI\\tools\\gptsync_ia32.efi" @@ -97,6 +98,7 @@ #define FALLBACK_FULLNAME L"EFI\\BOOT\\bootia32.efi" #define FALLBACK_BASENAME L"bootia32.efi" #define EFI_STUB_ARCH 0x014c +EFI_GUID gFreedesktopRootGuid = { 0x44479540, 0xf297, 0x41b2, { 0x9a, 0xf7, 0xd1, 0x31, 0xd5, 0xf0, 0x45, 0x8a }}; #else #define SHELL_NAMES L"\\EFI\\tools\\shell.efi,\\shell.efi" #define GPTSYNC_NAMES L"\\EFI\\tools\\gptsync.efi" @@ -106,6 +108,8 @@ #define DRIVER_DIRS L"drivers" #define FALLBACK_FULLNAME L"EFI\\BOOT\\boot.efi" /* Not really correct */ #define FALLBACK_BASENAME L"boot.efi" /* Not really correct */ +// Below is GUID for ARM64 +EFI_GUID gFreedesktopRootGuid = { 0xb921b045, 0x1df0, 0x41c3, { 0xaf, 0x44, 0x4c, 0x6f, 0x28, 0x0d, 0x3f, 0xae }}; #endif #define FAT_ARCH 0x0ef1fab9 /* ID for Apple "fat" binary */ @@ -136,9 +140,9 @@ REFIT_MENU_SCREEN MainMenu = { L"Main Menu", NULL, 0, NULL, 0, NULL, 0, L" L"Insert or F2 for more options; Esc to refresh" }; static REFIT_MENU_SCREEN AboutMenu = { L"About", NULL, 0, NULL, 0, NULL, 0, NULL, L"Press Enter to return to main menu", L"" }; -REFIT_CONFIG GlobalConfig = { FALSE, TRUE, FALSE, FALSE, 0, 0, 0, DONT_CHANGE_TEXT_MODE, 20, 0, 0, GRAPHICS_FOR_OSX, LEGACY_TYPE_MAC, +REFIT_CONFIG GlobalConfig = { FALSE, TRUE, FALSE, FALSE, TRUE, 0, 0, 0, DONT_CHANGE_TEXT_MODE, 20, 0, 0, GRAPHICS_FOR_OSX, LEGACY_TYPE_MAC, 0, 0, { DEFAULT_BIG_ICON_SIZE / 4, DEFAULT_SMALL_ICON_SIZE, DEFAULT_BIG_ICON_SIZE }, BANNER_NOSCALE, - NULL, NULL, CONFIG_FILE_NAME, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, CONFIG_FILE_NAME, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, { TAG_SHELL, TAG_MEMTEST, TAG_GDISK, TAG_APPLE_RECOVERY, TAG_WINDOWS_RECOVERY, TAG_MOK_TOOL, TAG_ABOUT, TAG_SHUTDOWN, TAG_REBOOT, TAG_FIRMWARE, 0, 0, 0, 0, 0, 0, 0, 0 } }; @@ -166,7 +170,7 @@ static VOID AboutrEFInd(VOID) if (AboutMenu.EntryCount == 0) { AboutMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT); - AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.8.5.5"); + AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.8.7.14"); AddMenuInfoLine(&AboutMenu, L""); AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer"); AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012-2015 Roderick W. Smith"); @@ -176,7 +180,8 @@ static VOID AboutrEFInd(VOID) AddMenuInfoLine(&AboutMenu, L"Running on:"); AddMenuInfoLine(&AboutMenu, PoolPrint(L" EFI Revision %d.%02d", ST->Hdr.Revision >> 16, ST->Hdr.Revision & ((1 << 16) - 1))); #if defined(EFI32) - AddMenuInfoLine(&AboutMenu, L" Platform: x86 (32 bit)"); + AddMenuInfoLine(&AboutMenu, PoolPrint(L" Platform: x86 (32 bit); Secure Boot %s", + secure_mode() ? L"active" : L"inactive")); #elif defined(EFIX64) AddMenuInfoLine(&AboutMenu, PoolPrint(L" Platform: x86_64 (64 bit); Secure Boot %s", secure_mode() ? L"active" : L"inactive")); @@ -668,7 +673,7 @@ REFIT_MENU_SCREEN *InitializeSubScreen(IN LOADER_ENTRY *Entry) { return SubScreen; } // REFIT_MENU_SCREEN *InitializeSubScreen() -VOID GenerateSubScreen(LOADER_ENTRY *Entry, IN REFIT_VOLUME *Volume) { +VOID GenerateSubScreen(LOADER_ENTRY *Entry, IN REFIT_VOLUME *Volume, IN BOOLEAN GenerateReturn) { REFIT_MENU_SCREEN *SubScreen; LOADER_ENTRY *SubEntry; CHAR16 *InitrdName; @@ -772,7 +777,7 @@ VOID GenerateSubScreen(LOADER_ENTRY *Entry, IN REFIT_VOLUME *Volume) { // first entry requires special processing, since it was initially set // up with a default title but correct options by InitializeSubScreen(), // earlier.... - if ((SubScreen->Entries != NULL) && (SubScreen->Entries[0] != NULL)) { + if ((TokenCount > 1) && (SubScreen->Entries != NULL) && (SubScreen->Entries[0] != NULL)) { MyFreePool(SubScreen->Entries[0]->Title); SubScreen->Entries[0]->Title = TokenList[0] ? StrDuplicate(TokenList[0]) : StrDuplicate(L"Boot Linux"); } // if @@ -802,7 +807,6 @@ VOID GenerateSubScreen(LOADER_ENTRY *Entry, IN REFIT_VOLUME *Volume) { SubEntry = InitializeLoaderEntry(Entry); if (SubEntry != NULL) { SubEntry->me.Title = L"Boot Linux for a 17\" iMac or a 15\" MacBook Pro (*)"; - SubEntry->UseGraphicsMode = TRUE; SubEntry->LoadOptions = L"-d 0 i17"; SubEntry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_ELILO; AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry); @@ -811,7 +815,6 @@ VOID GenerateSubScreen(LOADER_ENTRY *Entry, IN REFIT_VOLUME *Volume) { SubEntry = InitializeLoaderEntry(Entry); if (SubEntry != NULL) { SubEntry->me.Title = L"Boot Linux for a 20\" iMac (*)"; - SubEntry->UseGraphicsMode = TRUE; SubEntry->LoadOptions = L"-d 0 i20"; SubEntry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_ELILO; AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry); @@ -820,7 +823,6 @@ VOID GenerateSubScreen(LOADER_ENTRY *Entry, IN REFIT_VOLUME *Volume) { SubEntry = InitializeLoaderEntry(Entry); if (SubEntry != NULL) { SubEntry->me.Title = L"Boot Linux for a Mac Mini (*)"; - SubEntry->UseGraphicsMode = TRUE; SubEntry->LoadOptions = L"-d 0 mini"; SubEntry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_ELILO; AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry); @@ -852,13 +854,13 @@ VOID GenerateSubScreen(LOADER_ENTRY *Entry, IN REFIT_VOLUME *Volume) { SubEntry = InitializeLoaderEntry(Entry); if (SubEntry != NULL) { SubEntry->me.Title = L"Run XOM in text mode"; - SubEntry->UseGraphicsMode = FALSE; SubEntry->LoadOptions = L"-v"; SubEntry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_WINDOWS; AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry); } } // entries for xom.efi - AddMenuEntry(SubScreen, &MenuEntryReturn); + if (GenerateReturn) + AddMenuEntry(SubScreen, &MenuEntryReturn); Entry->me.SubScreen = SubScreen; } // VOID GenerateSubScreen() @@ -1001,13 +1003,12 @@ VOID SetLoaderDefaults(LOADER_ENTRY *Entry, CHAR16 *LoaderPath, REFIT_VOLUME *Vo StriCmp(NameClues, L"bootmgr.efi") == 0 || StriCmp(NameClues, L"bootmgfw.efi") == 0 || StriCmp(NameClues, L"bkpbootmgfw.efi") == 0) { - MergeStrings(&OSIconName, L"win", L','); + MergeStrings(&OSIconName, L"win8", L','); Entry->OSType = 'W'; ShortcutLetter = 'W'; Entry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_WINDOWS; } else if (StriCmp(NameClues, L"xom.efi") == 0) { - MergeStrings(&OSIconName, L"xom,win", L','); - Entry->UseGraphicsMode = TRUE; + MergeStrings(&OSIconName, L"xom,win,win8", L','); Entry->OSType = 'X'; ShortcutLetter = 'W'; Entry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_WINDOWS; @@ -1028,7 +1029,7 @@ VOID SetLoaderDefaults(LOADER_ENTRY *Entry, CHAR16 *LoaderPath, REFIT_VOLUME *Vo // Add a specified EFI boot loader to the list, using automatic settings // for icons, options, etc. -LOADER_ENTRY * AddLoaderEntry(IN CHAR16 *LoaderPath, IN CHAR16 *LoaderTitle, IN REFIT_VOLUME *Volume) { +static LOADER_ENTRY * AddLoaderEntry(IN CHAR16 *LoaderPath, IN CHAR16 *LoaderTitle, IN REFIT_VOLUME *Volume, IN BOOLEAN SubScreenReturn) { LOADER_ENTRY *Entry; CleanUpPathNameSlashes(LoaderPath); @@ -1054,13 +1055,50 @@ LOADER_ENTRY * AddLoaderEntry(IN CHAR16 *LoaderPath, IN CHAR16 *LoaderTitle, IN Entry->VolName = Volume->VolName; Entry->DevicePath = FileDevicePath(Volume->DeviceHandle, Entry->LoaderPath); SetLoaderDefaults(Entry, LoaderPath, Volume); - GenerateSubScreen(Entry, Volume); + GenerateSubScreen(Entry, Volume, SubScreenReturn); AddMenuEntry(&MainMenu, (REFIT_MENU_ENTRY *)Entry); } return(Entry); } // LOADER_ENTRY * AddLoaderEntry() +// 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; + REFIT_MENU_SCREEN *SubScreen; + LOADER_ENTRY *SubEntry; + UINTN TokenCount; + + File = ReadLinuxOptionsFile(TargetLoader->LoaderPath, Volume); + if (File != NULL) { + SubScreen = TargetLoader->me.SubScreen; + InitrdName = FindInitrd(FileName, Volume); + while ((TokenCount = ReadTokenLine(File, &TokenList)) > 1) { + SubEntry = InitializeLoaderEntry(TargetLoader); + SplitPathName(FileName, &VolName, &Path, &SubmenuName); + MyFreePool(VolName); + MyFreePool(Path); + MergeStrings(&SubmenuName, L": ", '\0'); + MergeStrings(&SubmenuName, TokenList[0] ? StrDuplicate(TokenList[0]) : StrDuplicate(L"Boot Linux"), '\0'); + Title = StrDuplicate(SubmenuName); + SubEntry->me.Title = Title; + MyFreePool(SubEntry->LoadOptions); + SubEntry->LoadOptions = AddInitrdToOptions(TokenList[1], InitrdName); + MyFreePool(SubEntry->LoaderPath); + SubEntry->LoaderPath = StrDuplicate(FileName); + CleanUpPathNameSlashes(SubEntry->LoaderPath); + SubEntry->DevicePath = FileDevicePath(Volume->DeviceHandle, SubEntry->LoaderPath); + FreeTokenLine(&TokenList, &TokenCount); + SubEntry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_LINUX; + AddMenuEntry(SubScreen, (REFIT_MENU_ENTRY *)SubEntry); + } // while + MyFreePool(SubmenuName); + MyFreePool(InitrdName); + MyFreePool(File); + } // if +} // static VOID AddKernelToSubmenu() + // Returns -1 if (Time1 < Time2), +1 if (Time1 > Time2), or 0 if // (Time1 == Time2). Precision is only to the nearest second; since // this is used for sorting boot loader entries, differences smaller @@ -1296,7 +1334,8 @@ static BOOLEAN ScanLoaderDir(IN REFIT_VOLUME *Volume, IN CHAR16 *Path, IN CHAR16 EFI_FILE_INFO *DirEntry; CHAR16 FileName[256], *Extension; struct LOADER_LIST *LoaderList = NULL, *NewLoader; - BOOLEAN FoundFallbackDuplicate = FALSE; + LOADER_ENTRY *FirstKernel = NULL, *LatestEntry = NULL; + BOOLEAN FoundFallbackDuplicate = FALSE, IsLinux = FALSE; if ((!SelfDirPath || !Path || ((StriCmp(Path, SelfDirPath) == 0) && (Volume->DeviceHandle != SelfVolume->DeviceHandle)) || (StriCmp(Path, SelfDirPath) != 0)) && (ShouldScan(Volume, Path))) { @@ -1336,9 +1375,18 @@ static BOOLEAN ScanLoaderDir(IN REFIT_VOLUME *Volume, IN CHAR16 *Path, IN CHAR16 NewLoader = LoaderList; while (NewLoader != NULL) { - AddLoaderEntry(NewLoader->FileName, NULL, Volume); - NewLoader = NewLoader->NextEntry; + IsLinux = (StriSubCmp(L"bzImage", NewLoader->FileName) || StriSubCmp(L"vmlinuz", NewLoader->FileName)); + if ((FirstKernel != NULL) && IsLinux && GlobalConfig.FoldLinuxKernels) { + AddKernelToSubmenu(FirstKernel, NewLoader->FileName, Volume); + } else { + LatestEntry = AddLoaderEntry(NewLoader->FileName, NULL, Volume, !(IsLinux && GlobalConfig.FoldLinuxKernels)); + if (IsLinux && (FirstKernel == NULL)) + FirstKernel = LatestEntry; + } + NewLoader = NewLoader->NextEntry; } // while + if ((NewLoader != NULL) && (FirstKernel != NULL) && IsLinux && GlobalConfig.FoldLinuxKernels) + AddMenuEntry(FirstKernel->me.SubScreen, &MenuEntryReturn); CleanUpLoaderList(LoaderList); Status = DirIterClose(&DirIter); @@ -1399,7 +1447,7 @@ static VOID ScanNetboot() { NetVolume->DiskKind = DISK_KIND_NET; NetVolume->VolBadgeImage = BuiltinIcon(BUILTIN_ICON_VOL_NET); NetVolume->PartName = NetVolume->VolName = NULL; - AddLoaderEntry(iPXEFileName, Location, NetVolume); + AddLoaderEntry(iPXEFileName, Location, NetVolume, TRUE); MyFreePool(NetVolume); } // if support files exist and are valid } @@ -1414,7 +1462,7 @@ static VOID ScanEfiFiles(REFIT_VOLUME *Volume) { BOOLEAN ScanFallbackLoader = TRUE; BOOLEAN FoundBRBackup = FALSE; - if ((Volume->RootDir != NULL) && (Volume->VolName != NULL) && (Volume->IsReadable)) { + if (Volume && (Volume->RootDir != NULL) && (Volume->VolName != NULL) && (Volume->IsReadable)) { MatchPatterns = StrDuplicate(LOADER_MATCH_PATTERNS); if (GlobalConfig.ScanAllLinux) MergeStrings(&MatchPatterns, LINUX_MATCH_PATTERNS, L','); @@ -1423,7 +1471,7 @@ static VOID ScanEfiFiles(REFIT_VOLUME *Volume) { if (ShouldScan(Volume, MACOSX_LOADER_DIR)) { StrCpy(FileName, MACOSX_LOADER_PATH); if (FileExists(Volume->RootDir, FileName) && !FilenameIn(Volume, MACOSX_LOADER_DIR, L"boot.efi", GlobalConfig.DontScanFiles)) { - AddLoaderEntry(FileName, L"Mac OS X", Volume); + AddLoaderEntry(FileName, L"Mac OS X", Volume, TRUE); if (DuplicatesFallback(Volume, FileName)) ScanFallbackLoader = FALSE; } @@ -1431,7 +1479,7 @@ static VOID ScanEfiFiles(REFIT_VOLUME *Volume) { // check for XOM StrCpy(FileName, L"System\\Library\\CoreServices\\xom.efi"); if (FileExists(Volume->RootDir, FileName) && !FilenameIn(Volume, MACOSX_LOADER_DIR, L"xom.efi", GlobalConfig.DontScanFiles)) { - AddLoaderEntry(FileName, L"Windows XP (XoM)", Volume); + AddLoaderEntry(FileName, L"Windows XP (XoM)", Volume, TRUE); if (DuplicatesFallback(Volume, FileName)) ScanFallbackLoader = FALSE; } @@ -1442,17 +1490,18 @@ static VOID ScanEfiFiles(REFIT_VOLUME *Volume) { StrCpy(FileName, L"EFI\\Microsoft\\Boot\\bkpbootmgfw.efi"); if (FileExists(Volume->RootDir, FileName) && !FilenameIn(Volume, L"EFI\\Microsoft\\Boot", L"bkpbootmgfw.efi", GlobalConfig.DontScanFiles)) { - AddLoaderEntry(FileName, L"Microsoft EFI boot (Boot Repair backup)", Volume); + AddLoaderEntry(FileName, L"Microsoft EFI boot (Boot Repair backup)", Volume, TRUE); FoundBRBackup = TRUE; if (DuplicatesFallback(Volume, FileName)) ScanFallbackLoader = FALSE; } StrCpy(FileName, L"EFI\\Microsoft\\Boot\\bootmgfw.efi"); - if (FileExists(Volume->RootDir, FileName) && !FilenameIn(Volume, L"EFI\\Microsoft\\Boot", L"bootmgfw.efi", GlobalConfig.DontScanFiles)) { + if (FileExists(Volume->RootDir, FileName) && + !FilenameIn(Volume, L"EFI\\Microsoft\\Boot", L"bootmgfw.efi", GlobalConfig.DontScanFiles)) { if (FoundBRBackup) - AddLoaderEntry(FileName, L"Supposed Microsoft EFI boot (probably GRUB)", Volume); + AddLoaderEntry(FileName, L"Supposed Microsoft EFI boot (probably GRUB)", Volume, TRUE); else - AddLoaderEntry(FileName, L"Microsoft EFI boot", Volume); + AddLoaderEntry(FileName, L"Microsoft EFI boot", Volume, TRUE); if (DuplicatesFallback(Volume, FileName)) ScanFallbackLoader = FALSE; } @@ -1472,7 +1521,7 @@ static VOID ScanEfiFiles(REFIT_VOLUME *Volume) { ScanFallbackLoader = FALSE; } // while() Status = DirIterClose(&EfiDirIter); - if (Status != EFI_NOT_FOUND) + if ((Status != EFI_NOT_FOUND) && (Status != EFI_INVALID_PARAMETER)) CheckError(Status, L"while scanning the EFI directory"); // Scan user-specified (or additional default) directories.... @@ -1497,8 +1546,9 @@ static VOID ScanEfiFiles(REFIT_VOLUME *Volume) { // If not a duplicate & if it exists & if it's not us, create an entry // for the fallback boot loader - if (ScanFallbackLoader && FileExists(Volume->RootDir, FALLBACK_FULLNAME) && ShouldScan(Volume, L"EFI\\BOOT")) - AddLoaderEntry(FALLBACK_FULLNAME, L"Fallback boot loader", Volume); + if (ScanFallbackLoader && FileExists(Volume->RootDir, FALLBACK_FULLNAME) && ShouldScan(Volume, L"EFI\\BOOT")) { + AddLoaderEntry(FALLBACK_FULLNAME, L"Fallback boot loader", Volume, TRUE); + } } // if } // static VOID ScanEfiFiles() @@ -1613,7 +1663,7 @@ static UINTN ScanDriverDir(IN CHAR16 *Path) L"", TYPE_EFI, DirEntry->FileName, 0, NULL, FALSE, TRUE); } Status = DirIterClose(&DirIter); - if (Status != EFI_NOT_FOUND) { + if ((Status != EFI_NOT_FOUND) && (Status != EFI_INVALID_PARAMETER)) { SPrint(FileName, 255, L"while scanning the %s directory", Path); CheckError(Status, FileName); } @@ -1726,8 +1776,9 @@ static VOID LoadDrivers(VOID) } // while // connect all devices - if (NumFound > 0) + if (NumFound > 0) { ConnectAllDriversToAllControllers(); + } } /* static VOID LoadDrivers() */ // Locates boot loaders. NOTE: This assumes that GlobalConfig.LegacyType is set correctly.