X-Git-Url: https://code.delx.au/refind/blobdiff_plain/deb53fbf9687d73d13ff1547f95fcee240224fdc..96e4448844c6f535679f9def29d700b94918d293:/refind/main.c diff --git a/refind/main.c b/refind/main.c index a7da984..d96c6e5 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 */ @@ -124,6 +128,9 @@ // a ".efi" extension to be found when scanning for boot loaders. #define LINUX_MATCH_PATTERNS L"vmlinuz*,bzImage*" +// Maximum length of a text string in certain menus +#define MAX_LINE_LENGTH 65 + static REFIT_MENU_ENTRY MenuEntryAbout = { L"About rEFInd", TAG_ABOUT, 1, 0, 'A', NULL, NULL, NULL }; static REFIT_MENU_ENTRY MenuEntryReset = { L"Reboot Computer", TAG_REBOOT, 1, 0, 'R', NULL, NULL, NULL }; static REFIT_MENU_ENTRY MenuEntryShutdown = { L"Shut Down Computer", TAG_SHUTDOWN, 1, 0, 'U', NULL, NULL, NULL }; @@ -136,9 +143,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 +173,7 @@ static VOID AboutrEFInd(VOID) if (AboutMenu.EntryCount == 0) { AboutMenu.TitleImage = BuiltinIcon(BUILTIN_ICON_FUNC_ABOUT); - AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.8.6.2"); + AddMenuInfoLine(&AboutMenu, L"rEFInd Version 0.8.7.15"); AddMenuInfoLine(&AboutMenu, L""); AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2006-2010 Christoph Pfisterer"); AddMenuInfoLine(&AboutMenu, L"Copyright (c) 2012-2015 Roderick W. Smith"); @@ -176,7 +183,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")); @@ -184,7 +192,7 @@ static VOID AboutrEFInd(VOID) AddMenuInfoLine(&AboutMenu, L" Platform: unknown"); #endif FirmwareVendor = StrDuplicate(ST->FirmwareVendor); - LimitStringLength(FirmwareVendor, 65); // More than ~65 causes empty info page on 800x600 display + LimitStringLength(FirmwareVendor, MAX_LINE_LENGTH); // More than ~65 causes empty info page on 800x600 display AddMenuInfoLine(&AboutMenu, PoolPrint(L" Firmware: %s %d.%02d", FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & ((1 << 16) - 1))); AddMenuInfoLine(&AboutMenu, PoolPrint(L" Screen Output: %s", egScreenDescription())); @@ -668,7 +676,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 +780,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 +810,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 +818,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 +826,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 +857,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() @@ -1007,7 +1012,6 @@ VOID SetLoaderDefaults(LOADER_ENTRY *Entry, CHAR16 *LoaderPath, REFIT_VOLUME *Vo Entry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_WINDOWS; } else if (StriCmp(NameClues, L"xom.efi") == 0) { MergeStrings(&OSIconName, L"xom,win,win8", L','); - Entry->UseGraphicsMode = TRUE; Entry->OSType = 'X'; ShortcutLetter = 'W'; Entry->UseGraphicsMode = GlobalConfig.GraphicsFor & GRAPHICS_FOR_WINDOWS; @@ -1028,7 +1032,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 +1058,51 @@ 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); + MergeStrings(&SubmenuName, L": ", '\0'); + MergeStrings(&SubmenuName, TokenList[0] ? StrDuplicate(TokenList[0]) : StrDuplicate(L"Boot Linux"), '\0'); + Title = StrDuplicate(SubmenuName); + LimitStringLength(Title, MAX_LINE_LENGTH); + 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(VolName); + MyFreePool(Path); + 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 +1338,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 +1379,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 +1451,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 +1466,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 +1475,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 +1483,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 +1494,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; } @@ -1497,8 +1550,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()