2019-09-03 11:58:42 +02:00
/*
* refit / scan / loader . c
*
* Copyright ( c ) 2006 - 2010 Christoph Pfisterer
* All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions are
* met :
*
* * Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
*
* * Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the
* distribution .
*
* * Neither the name of Christoph Pfisterer nor the names of the
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* " AS IS " AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT
* LIMITED TO , THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL ,
* SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT
* LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
* DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*/
2020-04-16 11:09:22 +02:00
# include "loader.h"
2020-04-23 15:20:48 +02:00
# include "../cpp_foundation/XString.h"
2019-09-03 11:58:42 +02:00
# include "entry_scan.h"
2020-02-29 08:30:21 +01:00
# include "../Platform/Settings.h"
# include "../Platform/Hibernate.h"
# include "../refit/screen.h"
# include "../refit/menu.h"
2020-04-05 14:25:39 +02:00
# include "common.h"
2020-04-16 09:15:26 +02:00
# include "../Platform/Nvram.h"
# include "../Platform/APFS.h"
# include "../Platform/guid.h"
2020-04-26 15:07:30 +02:00
# include "../refit/lib.h"
# include "../gui/REFIT_MENU_SCREEN.h"
2019-09-03 11:58:42 +02:00
# ifndef DEBUG_ALL
# define DEBUG_SCAN_LOADER 1
# else
# define DEBUG_SCAN_LOADER DEBUG_ALL
# endif
# if DEBUG_SCAN_LOADER == 0
# define DBG(...)
# else
# define DBG(...) DebugLog(DEBUG_SCAN_LOADER, __VA_ARGS__)
# endif
2020-04-29 22:32:44 +02:00
const XStringW MACOSX_LOADER_PATH = L " \\ System \\ Library \\ CoreServices \\ boot.efi " _XSW ;
2019-09-03 11:58:42 +02:00
2020-04-29 22:32:44 +02:00
const XStringW LINUX_ISSUE_PATH = L " \\ etc \\ issue " _XSW ;
2019-09-03 11:58:42 +02:00
# define LINUX_BOOT_PATH L"\\boot"
# define LINUX_BOOT_ALT_PATH L"\\boot"
2020-04-30 08:22:26 +02:00
const XString8 LINUX_LOADER_PATH = " vmlinuz " _XS8 ;
2020-04-05 14:25:39 +02:00
const XStringW LINUX_FULL_LOADER_PATH = SWPrintf ( " %ls \\ %s " , LINUX_BOOT_PATH , LINUX_LOADER_PATH . c_str ( ) ) ;
2019-09-03 11:58:42 +02:00
# define LINUX_LOADER_SEARCH_PATH L"vmlinuz*"
2020-04-26 15:07:30 +02:00
const XStringArray LINUX_DEFAULT_OPTIONS = Split < XStringArray > ( " ro add_efi_memmap quiet splash vt.handoff=7 " , " " ) ;
2019-09-03 11:58:42 +02:00
# if defined(MDE_CPU_X64)
2020-04-27 11:50:49 +02:00
# define BOOT_LOADER_PATH L"\\EFI\\BOOT\\BOOTX64.efi"_XSW
2019-09-03 11:58:42 +02:00
# else
2020-04-27 11:50:49 +02:00
# define BOOT_LOADER_PATH L"\\EFI\\BOOT\\BOOTIA32.efi"_XSW
2019-09-03 11:58:42 +02:00
# endif
2020-04-16 11:09:22 +02:00
2020-05-17 20:56:10 +02:00
//extern LOADER_ENTRY *SubMenuKextInjectMgmt(LOADER_ENTRY *Entry);
2019-09-03 11:58:42 +02:00
// Linux loader path data
typedef struct LINUX_PATH_DATA
{
2020-04-27 11:50:49 +02:00
CONST XStringW Path ;
CONST XStringW Title ;
CONST XStringW Icon ;
2020-04-30 08:03:56 +02:00
CONST XString8 Issue ;
2019-09-03 11:58:42 +02:00
} LINUX_PATH_DATA ;
2020-04-26 01:54:13 +02:00
typedef struct LINUX_ICON_DATA
{
CONST CHAR16 * DirectoryName ;
CONST CHAR16 * IconName ;
} LINUX_ICON_MAPPING ;
STATIC LINUX_ICON_DATA LinuxIconMapping [ ] = {
{ L " LinuxMint " , L " mint " } ,
{ L " arch_grub " , L " arch " } ,
{ L " opensuse " , L " suse " } ,
{ L " ORACLE " , L " solaris " } ,
{ L " elementary " , L " eos " } ,
{ L " pclinuxos " , L " pclinux " } ,
{ L " mx18 " , L " mx " } ,
{ L " mx19 " , L " mx " }
} ;
2020-04-27 11:50:49 +02:00
STATIC CONST UINTN LinuxIconMappingCount = ( sizeof ( LinuxIconMapping ) / sizeof ( LinuxIconMapping [ 0 ] ) ) ;
2020-04-26 01:54:13 +02:00
2019-09-03 11:58:42 +02:00
STATIC LINUX_PATH_DATA LinuxEntryData [ ] = {
# if defined(MDE_CPU_X64)
2020-04-23 11:08:10 +02:00
//comment out all common names
// { L"\\EFI\\grub\\grubx64.efi", L"Grub EFI boot menu", L"grub,linux" },
// { L"\\EFI\\Gentoo\\grubx64.efi", L"Gentoo EFI boot menu", L"gentoo,linux", "Gentoo" },
2020-04-27 11:50:49 +02:00
{ L " \\ EFI \\ Gentoo \\ kernelx64.efi " _XSW , L " Gentoo EFI kernel " _XSW , L " gentoo,linux " _XSW } ,
2020-04-23 11:08:10 +02:00
// { L"\\EFI\\RedHat\\grubx64.efi", L"RedHat EFI boot menu", L"redhat,linux", "Redhat" },
// { L"\\EFI\\debian\\grubx64.efi", L"Debian EFI boot menu", L"debian,linux", "Debian" },
// { L"\\EFI\\kali\\grubx64.efi", L"Kali EFI boot menu", L"kali,linux", "Kali" },
// { L"\\EFI\\ubuntu\\grubx64.efi", L"Ubuntu EFI boot menu", L"ubuntu,linux", "Ubuntu" },
// { L"\\EFI\\kubuntu\\grubx64.efi", L"kubuntu EFI boot menu", L"kubuntu,linux", "kubuntu" },
// { L"\\EFI\\LinuxMint\\grubx64.efi", L"Linux Mint EFI boot menu", L"mint,linux", "Linux Mint" },
// { L"\\EFI\\Fedora\\grubx64.efi", L"Fedora EFI boot menu", L"fedora,linux", "Fedora" },
// { L"\\EFI\\opensuse\\grubx64.efi", L"OpenSuse EFI boot menu", L"suse,linux", "openSUSE" },
// { L"\\EFI\\arch\\grubx64.efi", L"ArchLinux EFI boot menu", L"arch,linux" },
// { L"\\EFI\\arch_grub\\grubx64.efi", L"ArchLinux EFI boot menu", L"arch,linux" },
// { L"\\EFI\\ORACLE\\grubx64.efi", L"Oracle Solaris EFI boot menu", L"solaris,linux", "Solaris" },
// { L"\\EFI\\Endless\\grubx64.efi", L"EndlessOS EFI boot menu", L"endless,linux", "EndlessOS" },
// { L"\\EFI\\antergos_grub\\grubx64.efi", L"Antergos EFI boot menu", L"antergos,linux", "Antergos" },
// { L"\\EFI\\Deepin\\grubx64.efi", L"Deepin EFI boot menu", L"deepin,linux", "Deepin" },
// { L"\\EFI\\elementary\\grubx64.efi", L"Elementary EFI boot menu", L"eos,linux", "Elementary" },
// { L"\\EFI\\Manjaro\\grubx64.efi", L"Manjaro EFI boot menu", L"manjaro,linux", "Manjaro" },
// { L"\\EFI\\xubuntu\\grubx64.efi", L"Xubuntu EFI boot menu", L"xubuntu,linux", "Xubuntu" },
// { L"\\EFI\\zorin\\grubx64.efi", L"Zorin EFI boot menu", L"zorin,linux", "Zorin" },
2020-04-30 08:22:26 +02:00
{ L " \\ EFI \\ goofiboot \\ goofibootx64.efi " _XSW , L " Solus EFI boot menu " _XSW , L " solus,linux " _XSW , " Solus " _XS8 } ,
2020-04-23 11:08:10 +02:00
// { L"\\EFI\\centos\\grubx64.efi", L"CentOS EFI boot menu", L"centos,linux", "CentOS" },
// { L"\\EFI\\pclinuxos\\grubx64.efi", L"PCLinuxOS EFI boot menu", L"pclinux,linux", "PCLinux" },
// { L"\\EFI\\neon\\grubx64.efi", L"KDE Neon EFI boot menu", L"neon,linux", "KDE Neon" },
// { L"\\EFI\\MX19\\grubx64.efi", L"MX Linux EFI boot menu", L"mx,linux", "MX Linux" },
// { L"\\EFI\\parrot\\grubx64.efi", L"Parrot OS EFI boot menu", L"parrot,linux", "Parrot OS" },
2019-09-03 11:58:42 +02:00
# else
2020-04-23 11:08:10 +02:00
//dont bother about 32bit compilation
2019-09-03 11:58:42 +02:00
{ L " \\ EFI \\ grub \\ grub.efi " , L " Grub EFI boot menu " , L " grub,linux " } ,
{ L " \\ EFI \\ Gentoo \\ grub.efi " , L " Gentoo EFI boot menu " , L " gentoo,linux " , " Gentoo " } ,
{ L " \\ EFI \\ Gentoo \\ kernel.efi " , L " Gentoo EFI kernel " , L " gentoo,linux " } ,
{ L " \\ EFI \\ RedHat \\ grub.efi " , L " RedHat EFI boot menu " , L " redhat,linux " , " Redhat " } ,
{ L " \\ EFI \\ debian \\ grub.efi " , L " Debian EFI boot menu " , L " debian,linux " , " Debian " } ,
{ L " \\ EFI \\ kali \\ grub.efi " , L " Kali EFI boot menu " , L " kali,linux " , " Kali " } ,
{ L " \\ EFI \\ ubuntu \\ grub.efi " , L " Ubuntu EFI boot menu " , L " ubuntu,linux " , " Ubuntu " } ,
{ L " \\ EFI \\ kubuntu \\ grub.efi " , L " kubuntu EFI boot menu " , L " kubuntu,linux " , " kubuntu " } ,
{ L " \\ EFI \\ LinuxMint \\ grub.efi " , L " Linux Mint EFI boot menu " , L " mint,linux " , " Linux Mint " } ,
{ L " \\ EFI \\ Fedora \\ grub.efi " , L " Fedora EFI boot menu " , L " fedora,linux " , " Fedora " } ,
{ L " \\ EFI \\ opensuse \\ grub.efi " , L " OpenSuse EFI boot menu " , L " suse,linux " , " openSUSE " } ,
{ L " \\ EFI \\ arch \\ grub.efi " , L " ArchLinux EFI boot menu " , L " arch,linux " } ,
{ L " \\ EFI \\ arch_grub \\ grub.efi " , L " ArchLinux EFI boot menu " , L " arch,linux " } ,
{ L " \\ EFI \\ ORACLE \\ grub.efi " , L " Oracle Solaris EFI boot menu " , L " solaris,linux " , " Solaris " } ,
{ L " \\ EFI \\ Endless \\ grub.efi " , L " EndlessOS EFI boot menu " , L " endless,linux " , " EndlessOS " } ,
{ L " \\ EFI \\ antergos_grub \\ grub.efi " , L " Antergos EFI boot menu " , L " antergos,linux " , " Antergos " } ,
{ L " \\ EFI \\ Deepin \\ grub.efi " , L " Deepin EFI boot menu " , L " deepin,linux " , " Deepin " } ,
{ L " \\ EFI \\ elementary \\ grub.efi " , L " Elementary EFI boot menu " , L " eos,linux " , " Elementary " } ,
{ L " \\ EFI \\ Manjaro \\ grub.efi " , L " Manjaro EFI boot menu " , L " manjaro,linux " , " Manjaro " } ,
{ L " \\ EFI \\ xubuntu \\ grub.efi " , L " Xubuntu EFI boot menu " , L " xubuntu,linux " , " Xubuntu " } ,
{ L " \\ EFI \\ zorin \\ grub.efi " , L " Zorin EFI boot menu " , L " zorin,linux " , " Zorin " } ,
{ L " \\ EFI \\ goofiboot \\ goofiboot.efi " , L " Solus EFI boot menu " , L " solus,linux " , " Solus " } ,
{ L " \\ EFI \\ centos \\ grub.efi " , L " CentOS EFI boot menu " , L " centos,linux " , " CentOS " } ,
{ L " \\ EFI \\ pclinuxos \\ grub.efi " , L " PCLinuxOS EFI boot menu " , L " pclinux,linux " , " PCLinux " } ,
{ L " \\ EFI \\ neon \\ grub.efi " , L " KDE Neon EFI boot menu " , L " neon,linux " , " KDE Neon " } ,
2020-04-06 19:06:48 +02:00
{ L " \\ EFI \\ MX19 \\ grub.efi " , L " MX Linux EFI boot menu " , L " mx,linux " , " MX Linux " } ,
2019-09-03 11:58:42 +02:00
{ L " \\ EFI \\ parrot \\ grub.efi " , L " Parrot OS EFI boot menu " , L " parrot,linux " , " Parrot OS " } ,
# endif
2020-04-27 11:50:49 +02:00
{ L " \\ EFI \\ SuSe \\ elilo.efi " _XSW , L " OpenSuse EFI boot menu " _XSW , L " suse,linux " _XSW } ,
2019-09-03 11:58:42 +02:00
} ;
2020-04-27 11:50:49 +02:00
STATIC CONST UINTN LinuxEntryDataCount = ( sizeof ( LinuxEntryData ) / sizeof ( LinuxEntryData [ 0 ] ) ) ;
2019-09-03 11:58:42 +02:00
# if defined(ANDX86)
# if !defined(MDE_CPU_X64)
# undef ANDX86
# else
// ANDX86 loader path data
# define ANDX86_FINDLEN 3
typedef struct ANDX86_PATH_DATA
{
2020-04-27 11:50:49 +02:00
CONST XStringW Path ;
CONST XStringW Title ;
CONST XStringW Icon ;
CONST XStringW Find [ ANDX86_FINDLEN ] ;
2019-09-03 11:58:42 +02:00
} ANDX86_PATH_DATA ;
STATIC ANDX86_PATH_DATA AndroidEntryData [ ] = {
//{ L"\\EFI\\boot\\grubx64.efi", L"Grub", L"grub,linux" },
//{ L"\\EFI\\boot\\bootx64.efi", L"Grub", L"grub,linux" },
2020-04-27 11:50:49 +02:00
{ L " \\ EFI \\ remixos \\ grubx64.efi " _XSW , L " Remix " _XSW , L " remix,grub,linux " _XSW , { L " \\ isolinux \\ isolinux.bin " _XSW , L " \\ initrd.img " _XSW , L " \\ kernel " _XSW } } ,
{ L " \\ EFI \\ PhoenixOS \\ boot \\ grubx64.efi " _XSW , L " PhoenixOS " _XSW , L " phoenix,grub,linux " _XSW , { L " \\ EFI \\ PhoenixOS \\ boot \\ efi.img " _XSW , L " \\ EFI \\ PhoenixOS \\ initrd.img " _XSW , L " \\ EFI \\ PhoenixOS \\ kernel " _XSW } } ,
{ L " \\ EFI \\ boot \\ grubx64.efi " _XSW , L " Phoenix " _XSW , L " phoenix,grub,linux " _XSW , { L " \\ phoenix \\ kernel " _XSW , L " \\ phoenix \\ initrd.img " _XSW , L " \\ phoenix \\ ramdisk.img " _XSW } } ,
{ L " \\ EFI \\ boot \\ bootx64.efi " _XSW , L " Chrome " _XSW , L " chrome,grub,linux " _XSW , { L " \\ syslinux \\ vmlinuz.A " _XSW , L " \\ syslinux \\ vmlinuz.B " _XSW , L " \\ syslinux \\ ldlinux.sys " _XSW } } ,
2020-04-23 11:08:10 +02:00
2019-09-03 11:58:42 +02:00
} ;
STATIC CONST UINTN AndroidEntryDataCount = ( sizeof ( AndroidEntryData ) / sizeof ( ANDX86_PATH_DATA ) ) ;
# endif
# endif
2020-04-29 22:32:44 +02:00
CONST XStringW PaperBoot = L " \\ com.apple.boot.P \\ boot.efi " _XSW ;
CONST XStringW RockBoot = L " \\ com.apple.boot.R \\ boot.efi " _XSW ;
CONST XStringW ScissorBoot = L " \\ com.apple.boot.S \\ boot.efi " _XSW ;
2019-09-03 11:58:42 +02:00
// OS X installer paths
2020-04-27 11:50:49 +02:00
CONST XStringW OSXInstallerPaths [ ] = {
L " \\ .IABootFiles \\ boot.efi " _XSW , // 10.9 - 10.13.3
L " \\ Mac OS X Install Data \\ boot.efi " _XSW , // 10.7
L " \\ OS X Install Data \\ boot.efi " _XSW , // 10.8 - 10.11
L " \\ macOS Install Data \\ boot.efi " _XSW , // 10.12 - 10.12.3
L " \\ macOS Install Data \\ Locked Files \\ Boot Files \\ boot.efi " _XSW // 10.12.4+
2019-09-03 11:58:42 +02:00
} ;
2020-04-27 11:50:49 +02:00
STATIC CONST UINTN OSXInstallerPathsCount = ( sizeof ( OSXInstallerPaths ) / sizeof ( OSXInstallerPaths [ 0 ] ) ) ;
2019-09-03 11:58:42 +02:00
STATIC INTN TimeCmp ( IN EFI_TIME * Time1 ,
IN EFI_TIME * Time2 )
{
INTN Comparison ;
if ( Time1 = = NULL ) {
if ( Time2 = = NULL ) {
return 0 ;
} else {
return - 1 ;
}
} else if ( Time2 = = NULL ) {
return 1 ;
}
Comparison = Time1 - > Year - Time2 - > Year ;
if ( Comparison = = 0 ) {
Comparison = Time1 - > Month - Time2 - > Month ;
if ( Comparison = = 0 ) {
Comparison = Time1 - > Day - Time2 - > Day ;
if ( Comparison = = 0 ) {
Comparison = Time1 - > Hour - Time2 - > Hour ;
if ( Comparison = = 0 ) {
Comparison = Time1 - > Minute - Time2 - > Minute ;
if ( Comparison = = 0 ) {
Comparison = Time1 - > Second - Time2 - > Second ;
if ( Comparison = = 0 ) {
Comparison = Time1 - > Nanosecond - Time2 - > Nanosecond ;
}
}
}
}
}
}
return Comparison ;
}
2020-04-27 11:50:49 +02:00
UINT8 GetOSTypeFromPath ( IN CONST XStringW & Path )
2019-09-03 11:58:42 +02:00
{
2020-04-27 11:50:49 +02:00
if ( Path . isEmpty ( ) ) {
2019-09-03 11:58:42 +02:00
return OSTYPE_OTHER ;
}
2020-04-27 11:50:49 +02:00
if ( Path . equalIC ( MACOSX_LOADER_PATH ) ) {
2019-09-03 11:58:42 +02:00
return OSTYPE_OSX ;
2020-04-27 11:50:49 +02:00
} else if ( Path . equalIC ( OSXInstallerPaths [ 0 ] ) | |
( Path . equalIC ( OSXInstallerPaths [ 1 ] ) ) | |
( Path . equalIC ( OSXInstallerPaths [ 2 ] ) ) | |
( Path . equalIC ( OSXInstallerPaths [ 3 ] ) ) | |
( Path . equalIC ( OSXInstallerPaths [ 4 ] ) ) | |
( Path . equalIC ( RockBoot ) ) | | ( Path . equalIC ( PaperBoot ) ) | | ( Path . equalIC ( ScissorBoot ) ) | |
( ! Path . equalIC ( L " \\ .IABootFiles \\ boot.efi " ) & & Path . equalIC ( L " \\ .IAPhysicalMedia " ) & & Path . equalIC ( MACOSX_LOADER_PATH ) )
2019-09-03 11:58:42 +02:00
) {
return OSTYPE_OSX_INSTALLER ;
2020-04-27 11:50:49 +02:00
} else if ( Path . equalIC ( L " \\ com.apple.recovery.boot \\ boot.efi " ) ) {
2019-09-03 11:58:42 +02:00
return OSTYPE_RECOVERY ;
2020-04-27 11:50:49 +02:00
} else if ( ( Path . equalIC ( L " \\ EFI \\ Microsoft \\ Boot \\ bootmgfw-orig.efi " ) ) | | //test first as orig
( Path . equalIC ( L " \\ EFI \\ Microsoft \\ Boot \\ bootmgfw.efi " ) ) | | //it can be Clover
// ( Path.equalIC(L"\\bootmgr.efi")) || //never worked, just extra icon in menu
( Path . equalIC ( L " \\ EFI \\ MICROSOFT \\ BOOT \\ cdboot.efi " ) ) ) {
2019-09-03 11:58:42 +02:00
return OSTYPE_WINEFI ;
2020-04-23 22:43:35 +02:00
} else if ( LINUX_FULL_LOADER_PATH . equalIC ( Path ) ) {
2019-09-03 11:58:42 +02:00
return OSTYPE_LINEFI ;
2020-04-27 11:50:49 +02:00
} else if ( Path . containsIC ( " grubx64.efi " ) ) {
2020-04-23 11:08:10 +02:00
return OSTYPE_LINEFI ;
2019-09-03 11:58:42 +02:00
} else {
UINTN Index ;
# if defined(ANDX86)
Index = 0 ;
while ( Index < AndroidEntryDataCount ) {
2020-04-27 11:50:49 +02:00
if ( Path . equalIC ( AndroidEntryData [ Index ] . Path ) ) {
2019-09-03 11:58:42 +02:00
return OSTYPE_LIN ;
}
+ + Index ;
}
# endif
Index = 0 ;
while ( Index < LinuxEntryDataCount ) {
2020-04-27 11:50:49 +02:00
if ( Path . equalIC ( LinuxEntryData [ Index ] . Path ) ) {
2019-09-03 11:58:42 +02:00
return OSTYPE_LIN ;
}
+ + Index ;
}
}
return OSTYPE_OTHER ;
}
2020-04-27 11:50:49 +02:00
static const XStringW linux = L " linux " _XSW ;
STATIC CONST XStringW & LinuxIconNameFromPath ( IN CONST XStringW & Path ,
IN EFI_FILE_PROTOCOL * RootDir )
2019-09-03 11:58:42 +02:00
{
UINTN Index ;
# if defined(ANDX86)
Index = 0 ;
while ( Index < AndroidEntryDataCount ) {
2020-04-27 11:50:49 +02:00
if ( Path . equalIC ( AndroidEntryData [ Index ] . Path ) ) {
2019-09-03 11:58:42 +02:00
return AndroidEntryData [ Index ] . Icon ;
}
+ + Index ;
}
# endif
2020-04-23 11:08:10 +02:00
//check not common names
2019-09-03 11:58:42 +02:00
Index = 0 ;
while ( Index < LinuxEntryDataCount ) {
2020-04-27 11:50:49 +02:00
if ( Path . equalIC ( LinuxEntryData [ Index ] . Path ) ) {
2019-09-03 11:58:42 +02:00
return LinuxEntryData [ Index ] . Icon ;
}
+ + Index ;
}
2020-04-23 11:08:10 +02:00
2019-09-03 11:58:42 +02:00
// Try to open the linux issue
2020-04-23 22:43:35 +02:00
if ( ( RootDir ! = NULL ) & & LINUX_FULL_LOADER_PATH . equalIC ( Path ) ) {
2019-09-03 11:58:42 +02:00
CHAR8 * Issue = NULL ;
UINTN IssueLen = 0 ;
2020-04-09 18:32:46 +02:00
if ( ! EFI_ERROR ( egLoadFile ( RootDir , LINUX_ISSUE_PATH . wc_str ( ) , ( UINT8 * * ) & Issue , & IssueLen ) ) & & ( Issue ! = NULL ) ) {
2019-09-03 11:58:42 +02:00
if ( IssueLen > 0 ) {
for ( Index = 0 ; Index < LinuxEntryDataCount ; + + Index ) {
2020-04-27 11:50:49 +02:00
if ( LinuxEntryData [ Index ] . Issue . notEmpty ( ) & & AsciiStrStr ( Issue , LinuxEntryData [ Index ] . Issue . c_str ( ) ) ! = NULL ) {
2019-09-03 11:58:42 +02:00
FreePool ( Issue ) ;
return LinuxEntryData [ Index ] . Icon ;
}
}
}
FreePool ( Issue ) ;
}
}
2020-04-27 11:50:49 +02:00
return linux ;
2019-09-03 11:58:42 +02:00
}
2020-04-30 08:03:56 +02:00
STATIC CONST XString8 LinuxInitImagePath [ ] = {
2020-04-30 08:22:26 +02:00
" initrd%s " _XS8 ,
" initrd.img%s " _XS8 ,
" initrd%s.img " _XS8 ,
" initramfs%s " _XS8 ,
" initramfs.img%s " _XS8 ,
" initramfs%s.img " _XS8 ,
2019-09-03 11:58:42 +02:00
} ;
2020-04-27 11:50:49 +02:00
STATIC CONST UINTN LinuxInitImagePathCount = ( sizeof ( LinuxInitImagePath ) / sizeof ( LinuxInitImagePath [ 0 ] ) ) ;
2019-09-03 11:58:42 +02:00
2020-04-26 15:07:30 +02:00
STATIC XStringArray LinuxKernelOptions ( IN EFI_FILE_PROTOCOL * Dir ,
2020-02-17 21:41:09 +01:00
IN CONST CHAR16 * Version ,
IN CONST CHAR16 * PartUUID ,
2020-04-26 15:07:30 +02:00
IN CONST XStringArray & Options OPTIONAL )
2019-09-03 11:58:42 +02:00
{
UINTN Index = 0 ;
if ( ( Dir = = NULL ) | | ( PartUUID = = NULL ) ) {
2020-04-05 14:25:39 +02:00
return Options ;
2019-09-03 11:58:42 +02:00
}
while ( Index < LinuxInitImagePathCount ) {
2020-04-05 14:25:39 +02:00
XStringW InitRd = SWPrintf ( LinuxInitImagePath [ Index + + ] . c_str ( ) , ( Version = = NULL ) ? L " " : Version ) ;
2020-04-10 05:11:00 +02:00
if ( InitRd . notEmpty ( ) ) {
2020-04-27 14:13:09 +02:00
if ( FileExists ( Dir , InitRd ) ) {
2020-05-12 08:01:46 +02:00
XStringArray CustomOptions ;
CustomOptions . Add ( SPrintf ( " root=/dev/disk/by-partuuid/%ls " , PartUUID ) ) ;
CustomOptions . Add ( SPrintf ( " initrd=%ls \\ %ls " , LINUX_BOOT_ALT_PATH , InitRd . wc_str ( ) ) ) ;
CustomOptions . import ( LINUX_DEFAULT_OPTIONS ) ;
CustomOptions . import ( Options ) ;
2019-09-03 11:58:42 +02:00
return CustomOptions ;
}
}
}
2020-04-26 15:07:30 +02:00
XStringArray CustomOptions ;
CustomOptions . Add ( SPrintf ( " root=/dev/disk/by-partuuid/%ls " , PartUUID ) ) ;
CustomOptions . import ( LINUX_DEFAULT_OPTIONS ) ;
CustomOptions . import ( Options ) ;
return CustomOptions ;
2019-09-03 11:58:42 +02:00
}
STATIC BOOLEAN isFirstRootUUID ( REFIT_VOLUME * Volume )
{
UINTN VolumeIndex ;
REFIT_VOLUME * scanedVolume ;
2020-02-27 15:34:29 +01:00
for ( VolumeIndex = 0 ; VolumeIndex < Volumes . size ( ) ; VolumeIndex + + ) {
scanedVolume = & Volumes [ VolumeIndex ] ;
2019-09-03 11:58:42 +02:00
if ( scanedVolume = = Volume )
return TRUE ;
if ( CompareGuid ( & scanedVolume - > RootUUID , & Volume - > RootUUID ) )
return FALSE ;
}
return TRUE ;
}
//Set Entry->VolName to .disk_label.contentDetails if it exists
STATIC EFI_STATUS GetOSXVolumeName ( LOADER_ENTRY * Entry )
{
EFI_STATUS Status = EFI_NOT_FOUND ;
2020-02-17 21:41:09 +01:00
CONST CHAR16 * targetNameFile = L " \\ System \\ Library \\ CoreServices \\ .disk_label.contentDetails " ;
2019-09-03 11:58:42 +02:00
CHAR8 * fileBuffer ;
CHAR8 * targetString ;
UINTN fileLen = 0 ;
if ( FileExists ( Entry - > Volume - > RootDir , targetNameFile ) ) {
Status = egLoadFile ( Entry - > Volume - > RootDir , targetNameFile , ( UINT8 * * ) & fileBuffer , & fileLen ) ;
if ( ! EFI_ERROR ( Status ) ) {
CHAR16 * tmpName ;
//Create null terminated string
targetString = ( CHAR8 * ) AllocateZeroPool ( fileLen + 1 ) ;
CopyMem ( ( VOID * ) targetString , ( VOID * ) fileBuffer , fileLen ) ;
2020-03-25 19:32:44 +01:00
DBG ( " found disk_label with contents:%s \n " , targetString ) ;
2019-09-03 11:58:42 +02:00
// NOTE: Sothor - This was never run. If we need this correct it and uncomment it.
// if (Entry->LoaderType == OSTYPE_OSX) {
// INTN i;
// //remove occurence number. eg: "vol_name 2" --> "vol_name"
// i=fileLen-1;
// while ((i>0) && (targetString[i]>='0') && (targetString[i]<='9')) {
// i--;
// }
// if (targetString[i] == ' ') {
// targetString[i] = 0;
// }
// }
//Convert to Unicode
tmpName = ( CHAR16 * ) AllocateZeroPool ( ( fileLen + 1 ) * 2 ) ;
AsciiStrToUnicodeStrS ( targetString , tmpName , fileLen ) ;
Entry - > VolName = EfiStrDuplicate ( tmpName ) ;
2020-03-25 19:32:44 +01:00
DBG ( " Created name:%ls \n " , Entry - > VolName ) ;
2019-09-03 11:58:42 +02:00
FreePool ( tmpName ) ;
FreePool ( fileBuffer ) ;
FreePool ( targetString ) ;
}
}
return Status ;
}
2020-04-27 11:50:49 +02:00
STATIC LOADER_ENTRY * CreateLoaderEntry ( IN CONST XStringW & LoaderPath ,
2020-04-26 15:07:30 +02:00
IN CONST XStringArray & LoaderOptions ,
2020-04-03 22:00:42 +02:00
IN CONST XStringW & FullTitle ,
IN CONST XStringW & LoaderTitle ,
2020-04-01 14:57:32 +02:00
IN REFIT_VOLUME * Volume ,
2020-05-16 21:30:29 +02:00
IN XIcon * Image ,
IN XIcon * DriveImage ,
2020-04-01 14:57:32 +02:00
IN UINT8 OSType ,
IN UINT8 Flags ,
IN CHAR16 Hotkey ,
EFI_GRAPHICS_OUTPUT_BLT_PIXEL BootBgColor ,
IN UINT8 CustomBoot ,
2020-04-11 14:34:59 +02:00
IN XImage * CustomLogo ,
2020-04-01 14:57:32 +02:00
IN KERNEL_AND_KEXT_PATCHES * Patches ,
IN BOOLEAN CustomEntry )
2019-09-03 11:58:42 +02:00
{
2020-04-28 22:42:53 +02:00
EFI_DEVICE_PATH * LoaderDevicePath ;
2020-02-17 21:41:09 +01:00
CONST CHAR16 * LoaderDevicePathString ;
CONST CHAR16 * FilePathAsString ;
2020-04-27 11:50:49 +02:00
// CONST CHAR16 *OSIconName = NULL;
2020-04-03 22:00:42 +02:00
CHAR16 ShortcutLetter ;
LOADER_ENTRY * Entry ;
2020-02-17 21:41:09 +01:00
CONST CHAR8 * indent = " " ;
2019-09-03 11:58:42 +02:00
// Check parameters are valid
2020-04-27 11:50:49 +02:00
if ( ( LoaderPath . isEmpty ( ) ) | | ( Volume = = NULL ) ) {
2019-09-03 11:58:42 +02:00
return NULL ;
}
// Get the loader device path
2020-04-27 14:13:09 +02:00
LoaderDevicePath = FileDevicePath ( Volume - > DeviceHandle , LoaderPath ) ;
2019-09-03 11:58:42 +02:00
if ( LoaderDevicePath = = NULL ) {
return NULL ;
}
LoaderDevicePathString = FileDevicePathToStr ( LoaderDevicePath ) ;
if ( LoaderDevicePathString = = NULL ) {
return NULL ;
}
// Ignore this loader if it's self path
FilePathAsString = FileDevicePathToStr ( SelfFullDevicePath ) ;
if ( FilePathAsString ) {
INTN Comparison = StriCmp ( FilePathAsString , LoaderDevicePathString ) ;
FreePool ( FilePathAsString ) ;
if ( Comparison = = 0 ) {
2020-03-25 19:32:44 +01:00
DBG ( " %s skipped because path `%ls` is self path! \n " , indent , LoaderDevicePathString ) ;
2019-09-03 11:58:42 +02:00
FreePool ( LoaderDevicePathString ) ;
return NULL ;
}
}
2020-04-10 16:35:24 +02:00
// DBG("OSType =%d\n", OSType);
2019-09-03 11:58:42 +02:00
if ( ! CustomEntry ) {
CUSTOM_LOADER_ENTRY * Custom ;
UINTN CustomIndex = 0 ;
// Ignore this loader if it's device path is already present in another loader
2020-02-28 21:28:33 +01:00
for ( UINTN i = 0 ; i < MainMenu . Entries . size ( ) ; + + i ) {
REFIT_ABSTRACT_MENU_ENTRY & MainEntry = MainMenu . Entries [ i ] ;
2019-09-03 11:58:42 +02:00
// Only want loaders
2020-02-28 21:28:33 +01:00
if ( MainEntry . getLOADER_ENTRY ( ) ) {
if ( StriCmp ( MainEntry . getLOADER_ENTRY ( ) - > DevicePathString , LoaderDevicePathString ) = = 0 ) {
2020-03-25 19:32:44 +01:00
DBG ( " %s skipped because path `%ls` already exists for another entry! \n " , indent , LoaderDevicePathString ) ;
2019-09-03 11:58:42 +02:00
FreePool ( LoaderDevicePathString ) ;
return NULL ;
}
}
}
// If this isn't a custom entry make sure it's not hidden by a custom entry
Custom = gSettings . CustomEntries ;
while ( Custom ) {
// Check if the custom entry is hidden or disabled
if ( ( OSFLAG_ISSET ( Custom - > Flags , OSFLAG_DISABLED ) | |
( OSFLAG_ISSET ( Custom - > Flags , OSFLAG_HIDDEN ) & & ! gSettings . ShowHiddenEntries ) ) ) {
INTN volume_match = 0 ;
INTN volume_type_match = 0 ;
INTN path_match = 0 ;
INTN type_match = 0 ;
// Check if volume match
if ( Custom - > Volume ! = NULL ) {
// Check if the string matches the volume
volume_match =
( ( StrStr ( Volume - > DevicePathString , Custom - > Volume ) ! = NULL ) | |
( ( Volume - > VolName ! = NULL ) & & ( StrStr ( Volume - > VolName , Custom - > Volume ) ! = NULL ) ) ) ? 1 : - 1 ;
}
// Check if the volume_type match
if ( Custom - > VolumeType ! = 0 ) {
2020-04-23 11:08:10 +02:00
volume_type_match = ( ( ( 1ull < < Volume - > DiskKind ) & Custom - > VolumeType ) ! = 0 ) ? 1 : - 1 ;
2019-09-03 11:58:42 +02:00
}
// Check if the path match
2020-04-27 11:50:49 +02:00
if ( Custom - > Path . notEmpty ( ) ) {
2019-09-03 11:58:42 +02:00
// Check if the loader path match
2020-04-27 11:50:49 +02:00
path_match = ( Custom - > Path . equalIC ( LoaderPath ) ) ? 1 : - 1 ;
2019-09-03 11:58:42 +02:00
}
// Check if the type match
if ( Custom - > Type ! = 0 ) {
type_match = OSTYPE_COMPARE ( Custom - > Type , OSType ) ? 1 : - 1 ;
}
if ( volume_match = = - 1 | | volume_type_match = = - 1 | | path_match = = - 1 | | type_match = = - 1 ) {
UINTN add_comma = 0 ;
2020-04-23 18:05:21 +02:00
DBG ( " %sNot match custom entry %llu: " , indent , CustomIndex ) ;
2019-09-03 11:58:42 +02:00
if ( volume_match ! = 0 ) {
2020-03-25 19:32:44 +01:00
DBG ( " Volume: %ls " , volume_match = = 1 ? L " match " : L " not match " ) ;
2019-09-03 11:58:42 +02:00
add_comma + + ;
}
if ( path_match ! = 0 ) {
2020-03-25 19:32:44 +01:00
DBG ( " %lsPath: %ls " ,
2019-09-03 11:58:42 +02:00
( add_comma ? L " , " : L " " ) ,
path_match = = 1 ? L " match " : L " not match " ) ;
add_comma + + ;
}
if ( volume_type_match ! = 0 ) {
2020-03-25 19:32:44 +01:00
DBG ( " %lsVolumeType: %ls " ,
2019-09-03 11:58:42 +02:00
( add_comma ? L " , " : L " " ) ,
volume_type_match = = 1 ? L " match " : L " not match " ) ;
add_comma + + ;
}
if ( type_match ! = 0 ) {
2020-03-25 19:32:44 +01:00
DBG ( " %lsType: %ls " ,
2019-09-03 11:58:42 +02:00
( add_comma ? L " , " : L " " ) ,
type_match = = 1 ? L " match " : L " not match " ) ;
}
DBG ( " \n " ) ;
} else {
// Custom entry match
2020-04-03 22:00:42 +02:00
DBG ( " %sSkipped because matching custom entry %llu! \n " , indent , CustomIndex ) ;
2019-09-03 11:58:42 +02:00
FreePool ( LoaderDevicePathString ) ;
return NULL ;
}
}
Custom = Custom - > Next ;
+ + CustomIndex ;
}
}
2020-04-10 16:35:24 +02:00
// DBG("prepare the menu entry\n");
2019-09-03 11:58:42 +02:00
// prepare the menu entry
2020-03-04 16:27:41 +01:00
Entry = new LOADER_ENTRY ( ) ;
2020-02-28 21:28:33 +01:00
Entry - > Row = 0 ;
2019-09-03 11:58:42 +02:00
Entry - > Volume = Volume ;
2020-04-27 11:50:49 +02:00
Entry - > LoaderPath = LoaderPath ;
2019-09-03 11:58:42 +02:00
Entry - > VolName = Volume - > VolName ;
Entry - > DevicePath = LoaderDevicePath ;
Entry - > DevicePathString = LoaderDevicePathString ;
Entry - > Flags = OSFLAG_SET ( Flags , OSFLAG_USEGRAPHICS ) ;
2020-05-16 21:30:29 +02:00
2020-04-26 15:07:30 +02:00
if ( OSFLAG_ISSET ( Flags , OSFLAG_NODEFAULTARGS ) ) {
Entry - > LoadOptions = LoaderOptions ;
} else {
Entry - > LoadOptions = Split < XStringArray > ( gSettings . BootArgs , " " ) ;
Entry - > LoadOptions . import ( LoaderOptions ) ;
2019-09-03 11:58:42 +02:00
}
//actions
2020-02-28 21:28:33 +01:00
Entry - > AtClick = ActionSelect ;
Entry - > AtDoubleClick = ActionEnter ;
Entry - > AtRightClick = ActionDetails ;
2019-09-03 11:58:42 +02:00
Entry - > CustomBoot = CustomBoot ;
2020-04-11 14:34:59 +02:00
if ( CustomLogo ! = nullptr ) {
Entry - > CustomLogo = * CustomLogo ; //else empty ximage already constructed
}
2019-09-03 11:58:42 +02:00
Entry - > LoaderType = OSType ;
Entry - > BuildVersion = NULL ;
Entry - > OSVersion = GetOSVersion ( Entry ) ;
2020-04-10 16:35:24 +02:00
//DBG("OSVersion=%s \n", Entry->OSVersion);
2019-09-03 11:58:42 +02:00
// detect specific loaders
2020-04-27 11:50:49 +02:00
XStringW OSIconName ;
2019-09-03 11:58:42 +02:00
ShortcutLetter = 0 ;
switch ( OSType ) {
case OSTYPE_OSX :
case OSTYPE_RECOVERY :
case OSTYPE_OSX_INSTALLER :
OSIconName = GetOSIconName ( Entry - > OSVersion ) ; // Sothor - Get OSIcon name using OSVersion
// apianti - force custom logo even when verbose
2020-05-30 20:03:19 +02:00
/* this is not needed, as this flag is also being unset when booting if -v is present (LoadOptions may change until then)
2020-04-23 22:43:35 +02:00
if ( Entry - > LoadOptions . containsIC ( " -v " ) ) {
2019-09-03 11:58:42 +02:00
// OSX is not booting verbose, so we can set console to graphics mode
Entry - > Flags = OSFLAG_UNSET ( Entry - > Flags , OSFLAG_USEGRAPHICS ) ;
}
2020-05-30 20:03:19 +02:00
*/
2019-09-03 11:58:42 +02:00
if ( OSType = = OSTYPE_OSX & & IsOsxHibernated ( Entry ) ) {
Entry - > Flags = OSFLAG_SET ( Entry - > Flags , OSFLAG_HIBERNATED ) ;
DBG ( " =>set entry as hibernated \n " ) ;
}
//always unset checkFakeSmc for installer
if ( OSType = = OSTYPE_OSX_INSTALLER ) {
Entry - > Flags = OSFLAG_UNSET ( Entry - > Flags , OSFLAG_CHECKFAKESMC ) ;
Entry - > Flags = OSFLAG_SET ( Entry - > Flags , OSFLAG_WITHKEXTS ) ;
}
ShortcutLetter = ' M ' ;
if ( ( Entry - > VolName = = NULL ) | | ( StrLen ( Entry - > VolName ) = = 0 ) ) {
// else no sense to override it with dubious name
GetOSXVolumeName ( Entry ) ;
}
break ;
case OSTYPE_WIN :
2020-04-27 11:50:49 +02:00
OSIconName = L " win " _XSW ;
2019-09-03 11:58:42 +02:00
ShortcutLetter = ' W ' ;
break ;
case OSTYPE_WINEFI :
2020-04-27 11:50:49 +02:00
OSIconName = L " vista,win " _XSW ;
2019-09-03 11:58:42 +02:00
//ShortcutLetter = 'V';
ShortcutLetter = ' W ' ;
break ;
case OSTYPE_LIN :
case OSTYPE_LINEFI :
2020-04-23 11:08:10 +02:00
// we already detected linux and have Path and Image
Entry - > LoaderType = OSType ;
2020-04-27 11:50:49 +02:00
OSIconName = L " linux " _XSW ;
2020-04-23 11:08:10 +02:00
if ( Image = = nullptr ) {
2020-05-16 21:30:29 +02:00
DBG ( " linux image not found \n " ) ;
2020-04-23 11:08:10 +02:00
OSIconName = LinuxIconNameFromPath ( LoaderPath , Volume - > RootDir ) ; //something named "issue"
}
2019-09-03 11:58:42 +02:00
ShortcutLetter = ' L ' ;
break ;
2020-04-25 22:14:53 +02:00
//case OSTYPE_OTHER:
2019-09-03 11:58:42 +02:00
case OSTYPE_EFI :
2020-04-27 11:50:49 +02:00
OSIconName = L " clover " _XSW ;
2020-04-05 23:14:27 +02:00
ShortcutLetter = ' E ' ;
2019-09-03 11:58:42 +02:00
Entry - > LoaderType = OSTYPE_OTHER ;
break ;
default :
2020-04-27 11:50:49 +02:00
OSIconName = L " unknown " _XSW ;
2019-09-03 11:58:42 +02:00
Entry - > LoaderType = OSTYPE_OTHER ;
break ;
}
2020-04-10 16:35:24 +02:00
//DBG("OSIconName=%ls \n", OSIconName);
2020-04-03 22:00:42 +02:00
Entry - > Title = FullTitle ;
if ( Entry - > Title . isEmpty ( ) & & Volume - > VolLabel ! = NULL ) {
if ( Volume - > VolLabel [ 0 ] = = L ' # ' ) {
2020-04-27 11:50:49 +02:00
Entry - > Title . SWPrintf ( " Boot %ls from %ls " , ( ! LoaderTitle . isEmpty ( ) ) ? LoaderTitle . wc_str ( ) : LoaderPath . basename ( ) . wc_str ( ) , Volume - > VolLabel + 1 ) ;
2020-04-03 22:00:42 +02:00
} else {
2020-04-27 11:50:49 +02:00
Entry - > Title . SWPrintf ( " Boot %ls from %ls " , ( ! LoaderTitle . isEmpty ( ) ) ? LoaderTitle . wc_str ( ) : LoaderPath . basename ( ) . wc_str ( ) , Volume - > VolLabel ) ;
2020-04-03 22:00:42 +02:00
}
}
2020-03-10 12:51:04 +01:00
2020-04-03 22:00:42 +02:00
BOOLEAN BootCampStyle = ThemeX . BootCampStyle ;
if ( Entry - > Title . isEmpty ( ) & & ( ( Entry - > VolName = = NULL ) | | ( StrLen ( Entry - > VolName ) = = 0 ) ) ) {
2020-05-10 09:59:33 +02:00
XStringW BasenameXW = XStringW ( Basename ( Volume - > DevicePathString ) ) ;
2020-04-10 16:35:24 +02:00
// DBG("encounter Entry->VolName ==%ls and StrLen(Entry->VolName) ==%llu\n",Entry->VolName, StrLen(Entry->VolName));
2020-04-03 22:00:42 +02:00
if ( BootCampStyle ) {
if ( ! LoaderTitle . isEmpty ( ) ) {
Entry - > Title = LoaderTitle ;
} else {
2020-05-10 09:59:33 +02:00
Entry - > Title = ( BasenameXW . contains ( L " - " ) ) ? BasenameXW . subString ( 0 , BasenameXW . indexOf ( L " - " ) + 1 ) + L " ..) " : BasenameXW ;
2020-04-03 22:00:42 +02:00
}
} else {
2020-04-27 11:50:49 +02:00
Entry - > Title . SWPrintf ( " Boot %ls from %ls " , ( ! LoaderTitle . isEmpty ( ) ) ? LoaderTitle . wc_str ( ) : LoaderPath . basename ( ) . wc_str ( ) ,
2020-05-10 09:59:33 +02:00
( BasenameXW . contains ( L " - " ) ) ? ( BasenameXW . subString ( 0 , BasenameXW . indexOf ( L " - " ) + 1 ) + L " ..) " ) . wc_str ( ) : BasenameXW . wc_str ( ) ) ;
2020-04-03 22:00:42 +02:00
}
}
2020-04-10 16:35:24 +02:00
// DBG("check Entry->Title \n");
2020-04-03 22:00:42 +02:00
if ( Entry - > Title . isEmpty ( ) ) {
2020-04-10 16:35:24 +02:00
// DBG("encounter LoaderTitle ==%ls and Entry->VolName ==%ls\n", LoaderTitle.wc_str(), Entry->VolName);
2020-04-03 22:00:42 +02:00
if ( BootCampStyle ) {
if ( ( StriCmp ( LoaderTitle . wc_str ( ) , L " macOS " ) = = 0 ) | | ( StriCmp ( LoaderTitle . wc_str ( ) , L " Recovery " ) = = 0 ) ) {
Entry - > Title . takeValueFrom ( Entry - > VolName ) ;
} else {
if ( ! LoaderTitle . isEmpty ( ) ) {
Entry - > Title = LoaderTitle ;
} else {
2020-04-27 11:50:49 +02:00
Entry - > Title = LoaderPath . basename ( ) ;
2020-04-03 22:00:42 +02:00
}
}
} else {
2020-04-27 11:50:49 +02:00
Entry - > Title . SWPrintf ( " Boot %ls from %ls " , ( ! LoaderTitle . isEmpty ( ) ) ? LoaderTitle . wc_str ( ) : LoaderPath . basename ( ) . wc_str ( ) ,
2020-04-03 22:00:42 +02:00
Entry - > VolName ) ;
}
}
2020-04-10 16:35:24 +02:00
// DBG("Entry->Title =%ls\n", Entry->Title.wc_str());
2019-09-03 11:58:42 +02:00
// just an example that UI can show hibernated volume to the user
// should be better to show it on entry image
if ( OSFLAG_ISSET ( Entry - > Flags , OSFLAG_HIBERNATED ) ) {
2020-03-31 18:10:30 +02:00
Entry - > Title . SWPrintf ( " %ls (hibernated) " , Entry - > Title . s ( ) ) ;
2019-09-03 11:58:42 +02:00
}
2020-02-28 21:28:33 +01:00
Entry - > ShortcutLetter = ( Hotkey = = 0 ) ? ShortcutLetter : Hotkey ;
2019-09-03 11:58:42 +02:00
// get custom volume icon if present
2020-03-27 17:50:17 +01:00
if ( GlobalConfig . CustomIcons & & FileExists ( Volume - > RootDir , L " \\ .VolumeIcon.icns " ) ) {
2020-05-16 21:30:29 +02:00
Entry - > Image . Image . LoadIcns ( Volume - > RootDir , L " \\ .VolumeIcon.icns " , 128 ) ;
if ( ! Entry - > Image . Image . isEmpty ( ) ) {
Entry - > Image . setFilled ( ) ;
DBG ( " using VolumeIcon.icns image from Volume \n " ) ;
}
2020-03-24 16:17:12 +01:00
} else if ( Image ) {
2020-04-23 11:08:10 +02:00
Entry - > Image = * Image ; //copy image from temporary storage
2020-03-24 16:17:12 +01:00
} else {
2020-04-05 17:54:10 +02:00
Entry - > Image = ThemeX . LoadOSIcon ( OSIconName ) ;
2020-03-24 16:17:12 +01:00
}
2020-04-10 16:35:24 +02:00
// DBG("Load DriveImage\n");
2020-04-03 22:00:42 +02:00
// Load DriveImage
if ( DriveImage ) {
2020-04-10 16:35:24 +02:00
// DBG("DriveImage presents\n");
2020-04-03 22:00:42 +02:00
Entry - > DriveImage = * DriveImage ;
} else {
2020-04-05 20:56:36 +02:00
Entry - > DriveImage = ScanVolumeDefaultIcon ( Volume , Entry - > LoaderType , Volume - > DevicePath ) ;
2020-04-03 22:00:42 +02:00
}
2020-04-10 16:35:24 +02:00
// DBG("HideBadges=%llu Volume=%ls ", ThemeX.HideBadges, Volume->VolName);
2020-03-24 16:17:12 +01:00
if ( ThemeX . HideBadges & HDBADGES_SHOW ) {
if ( ThemeX . HideBadges & HDBADGES_SWAP ) {
2020-05-16 21:30:29 +02:00
Entry - > BadgeImage . Image = XImage ( Entry - > DriveImage . Image , 0 ) ;
2020-04-10 16:35:24 +02:00
DBG ( " Show badge as Drive. " ) ;
2020-03-24 16:17:12 +01:00
} else {
2020-05-16 21:30:29 +02:00
Entry - > BadgeImage . Image = XImage ( Entry - > Image . Image , 0 ) ;
2020-04-10 16:35:24 +02:00
DBG ( " Show badge as OSImage. " ) ;
2020-03-24 16:17:12 +01:00
}
2020-05-16 21:30:29 +02:00
if ( ! Entry - > BadgeImage . Image . isEmpty ( ) ) {
Entry - > BadgeImage . setFilled ( ) ;
}
2020-03-24 16:17:12 +01:00
}
2020-04-01 14:57:32 +02:00
Entry - > BootBgColor = BootBgColor ;
2019-09-03 11:58:42 +02:00
Entry - > KernelAndKextPatches = ( ( Patches = = NULL ) ? ( KERNEL_AND_KEXT_PATCHES * ) ( ( ( UINTN ) & gSettings ) + OFFSET_OF ( SETTINGS_DATA , KernelAndKextPatches ) ) : Patches ) ;
# ifdef DUMP_KERNEL_KEXT_PATCHES
DumpKernelAndKextPatches ( Entry - > KernelAndKextPatches ) ;
# endif
2020-04-10 16:35:24 +02:00
DBG ( " %sLoader entry created for '%ls' \n " , indent , Entry - > DevicePathString ) ;
2019-09-03 11:58:42 +02:00
return Entry ;
}
2020-05-16 22:07:27 +02:00
void LOADER_ENTRY : : AddDefaultMenu ( )
2019-09-03 11:58:42 +02:00
{
2020-04-27 11:50:49 +02:00
XStringW FileName ;
2020-04-05 14:25:39 +02:00
// CHAR16* TempOptions;
2019-09-03 11:58:42 +02:00
// CHAR16 DiagsFileName[256];
LOADER_ENTRY * SubEntry ;
2020-05-16 22:07:27 +02:00
// REFIT_MENU_SCREEN *SubScreen;
// REFIT_VOLUME *Volume;
2019-09-03 11:58:42 +02:00
UINT64 VolumeSize ;
EFI_GUID * Guid = NULL ;
BOOLEAN KernelIs64BitOnly ;
2020-05-17 20:56:10 +02:00
UINT64 os_version = AsciiOSVersionToUint64 ( OSVersion ) ;
2020-05-10 11:41:34 +02:00
constexpr LString8 quietLitteral = " quiet " ;
constexpr LString8 splashLitteral = " splash " ;
2019-09-03 11:58:42 +02:00
// Only kernels up to 10.7 have 32-bit mode
2020-05-16 22:07:27 +02:00
KernelIs64BitOnly = ( OSVersion = = NULL | |
2020-05-17 20:56:10 +02:00
os_version > = AsciiOSVersionToUint64 ( " 10.8 " ) ) ;
const char * macOS = ( os_version < AsciiOSVersionToUint64 ( " 10.8 " ) ) ? " Mac OS X " :
( os_version < AsciiOSVersionToUint64 ( " 10.12 " ) ) ? " OS X " : " macOS " ;
2019-09-03 11:58:42 +02:00
2020-05-16 22:07:27 +02:00
FileName = LoaderPath . basename ( ) ;
2019-09-03 11:58:42 +02:00
// create the submenu
2020-03-04 07:21:43 +01:00
// SubScreen = (__typeof__(SubScreen))AllocateZeroPool(sizeof(REFIT_MENU_SCREEN));
SubScreen = new REFIT_MENU_SCREEN ;
2020-05-16 22:07:27 +02:00
SubScreen - > Title . SWPrintf ( " Options for %ls on %ls " , Title . wc_str ( ) , VolName ) ;
2020-03-22 11:48:13 +01:00
2020-05-16 22:07:27 +02:00
SubScreen - > TitleImage = Image ;
SubScreen - > ID = LoaderType + 20 ; //wow
2020-04-27 17:18:36 +02:00
// DBG("get anime for os=%lld\n", SubScreen->ID);
2020-04-15 18:30:39 +02:00
SubScreen - > GetAnime ( ) ;
2019-09-03 11:58:42 +02:00
VolumeSize = RShiftU64 ( MultU64x32 ( Volume - > BlockIO - > Media - > LastBlock , Volume - > BlockIO - > Media - > BlockSize ) , 20 ) ;
2020-04-04 18:22:07 +02:00
SubScreen - > AddMenuInfoLine_f ( " Volume size: %lluMb " , VolumeSize ) ;
2020-05-16 22:07:27 +02:00
SubScreen - > AddMenuInfoLine_f ( " %ls " , FileDevicePathToStr ( DevicePath ) ) ;
2019-09-03 11:58:42 +02:00
Guid = FindGPTPartitionGuidInDevicePath ( Volume - > DevicePath ) ;
if ( Guid ) {
2020-04-27 17:18:36 +02:00
SubScreen - > AddMenuInfoLine_f ( " UUID: %s " , strguid ( Guid ) ) ;
2019-09-03 11:58:42 +02:00
}
2020-05-16 22:07:27 +02:00
SubScreen - > AddMenuInfoLine_f ( " Options: %s " , LoadOptions . ConcatAll ( " " _XS8 ) . c_str ( ) ) ;
2019-09-03 11:58:42 +02:00
// loader-specific submenu entries
2020-05-16 22:07:27 +02:00
if ( LoaderType = = OSTYPE_OSX | |
LoaderType = = OSTYPE_OSX_INSTALLER | |
LoaderType = = OSTYPE_RECOVERY ) { // entries for Mac OS X
2020-05-17 20:56:10 +02:00
SubScreen - > AddMenuInfoLine_f ( " %s: %s " , macOS , OSVersion ) ;
2019-09-03 11:58:42 +02:00
2020-05-16 22:07:27 +02:00
if ( OSFLAG_ISSET ( Flags , OSFLAG_HIBERNATED ) ) {
SubEntry = getPartiallyDuplicatedEntry ( ) ;
2019-09-03 11:58:42 +02:00
if ( SubEntry ) {
2020-03-10 17:50:55 +01:00
SubEntry - > Title . takeValueFrom ( " Cancel hibernate wake " ) ;
2019-09-03 11:58:42 +02:00
SubEntry - > Flags = OSFLAG_UNSET ( SubEntry - > Flags , OSFLAG_HIBERNATED ) ;
2020-03-03 21:44:07 +01:00
SubScreen - > AddMenuEntry ( SubEntry , true ) ;
2019-09-03 11:58:42 +02:00
}
}
2020-05-16 22:07:27 +02:00
SubEntry = getPartiallyDuplicatedEntry ( ) ;
2019-09-03 11:58:42 +02:00
if ( SubEntry ) {
2020-05-17 20:56:10 +02:00
SubEntry - > Title . SWPrintf ( " Boot %s with selected options " , macOS ) ;
2020-03-03 21:44:07 +01:00
SubScreen - > AddMenuEntry ( SubEntry , true ) ;
2019-09-03 11:58:42 +02:00
}
2020-05-16 22:07:27 +02:00
SubEntry = getPartiallyDuplicatedEntry ( ) ;
2019-09-03 11:58:42 +02:00
if ( SubEntry ) {
2020-05-17 20:56:10 +02:00
SubEntry - > Title . SWPrintf ( " Boot %s with injected kexts " , macOS ) ;
2019-09-03 11:58:42 +02:00
SubEntry - > Flags = OSFLAG_UNSET ( SubEntry - > Flags , OSFLAG_CHECKFAKESMC ) ;
SubEntry - > Flags = OSFLAG_SET ( SubEntry - > Flags , OSFLAG_WITHKEXTS ) ;
2020-03-03 21:44:07 +01:00
SubScreen - > AddMenuEntry ( SubEntry , true ) ;
2019-09-03 11:58:42 +02:00
}
2020-05-10 17:50:24 +02:00
2020-05-16 22:07:27 +02:00
SubEntry = getPartiallyDuplicatedEntry ( ) ;
2019-09-03 11:58:42 +02:00
if ( SubEntry ) {
2020-05-17 20:56:10 +02:00
SubEntry - > Title . SWPrintf ( " Boot %s without injected kexts " , macOS ) ;
2019-09-03 11:58:42 +02:00
SubEntry - > Flags = OSFLAG_UNSET ( SubEntry - > Flags , OSFLAG_CHECKFAKESMC ) ;
SubEntry - > Flags = OSFLAG_UNSET ( SubEntry - > Flags , OSFLAG_WITHKEXTS ) ;
2020-03-10 10:45:17 +01:00
SubScreen - > AddMenuEntry ( SubEntry , true ) ;
2019-09-03 11:58:42 +02:00
}
2020-05-17 20:56:10 +02:00
SubScreen - > AddMenuEntry ( SubMenuKextInjectMgmt ( ) , true ) ;
2020-04-04 18:22:07 +02:00
SubScreen - > AddMenuInfo_f ( " === boot-args === " ) ;
2019-09-03 11:58:42 +02:00
if ( ! KernelIs64BitOnly ) {
if ( os_version < AsciiOSVersionToUint64 ( " 10.8 " ) ) {
2020-03-03 21:44:07 +01:00
SubScreen - > AddMenuCheck ( " Mac OS X 32bit " , OPT_I386 , 68 ) ;
2019-09-03 11:58:42 +02:00
}
2020-05-17 20:56:10 +02:00
// SubScreen->AddMenuCheck(XString8().SPrintf("%s 64bit", macOS).c_str(), OPT_X64, 68);
SubScreen - > AddMenuCheck ( ( macOS + " 64bit " _XS8 ) . c_str ( ) , OPT_X64 , 68 ) ;
2019-09-03 11:58:42 +02:00
}
2020-03-03 21:44:07 +01:00
SubScreen - > AddMenuCheck ( " Verbose (-v) " , OPT_VERBOSE , 68 ) ;
2019-09-03 11:58:42 +02:00
// No Caches option works on 10.6 - 10.9
if ( os_version < AsciiOSVersionToUint64 ( " 10.10 " ) ) {
2020-03-03 21:44:07 +01:00
SubScreen - > AddMenuCheck ( " Without caches (-f) " , OPT_NOCACHES , 68 ) ;
2019-09-03 11:58:42 +02:00
}
2020-03-03 21:44:07 +01:00
SubScreen - > AddMenuCheck ( " Single User (-s) " , OPT_SINGLE_USER , 68 ) ;
SubScreen - > AddMenuCheck ( " Safe Mode (-x) " , OPT_SAFE , 68 ) ;
SubScreen - > AddMenuCheck ( " Disable KASLR (slide=0) " , OPT_SLIDE , 68 ) ;
SubScreen - > AddMenuCheck ( " Set Nvidia to VESA (nv_disable=1) " , OPT_NVDISABLE , 68 ) ;
SubScreen - > AddMenuCheck ( " Use Nvidia WEB drivers (nvda_drv=1) " , OPT_NVWEBON , 68 ) ;
SubScreen - > AddMenuCheck ( " Disable PowerNap (darkwake=0) " , OPT_POWERNAPOFF , 68 ) ;
SubScreen - > AddMenuCheck ( " Use XNU CPUPM (-xcpm) " , OPT_XCPM , 68 ) ;
// SubScreen->AddMenuCheck("Disable Intel Idle Mode (-gux_no_idle)", OPT_GNOIDLE, 68);
// SubScreen->AddMenuCheck("Sleep Uses Shutdown (-gux_nosleep)", OPT_GNOSLEEP, 68);
// SubScreen->AddMenuCheck("Force No Msi Int (-gux_nomsi)", OPT_GNOMSI, 68);
// SubScreen->AddMenuCheck("EHC manage USB2 ports (-gux_defer_usb2)", OPT_EHCUSB, 68);
SubScreen - > AddMenuCheck ( " Keep symbols on panic (keepsyms=1) " , OPT_KEEPSYMS , 68 ) ;
SubScreen - > AddMenuCheck ( " Don't reboot on panic (debug=0x100) " , OPT_DEBUG , 68 ) ;
SubScreen - > AddMenuCheck ( " Debug kexts (kextlog=0xffff) " , OPT_KEXTLOG , 68 ) ;
// SubScreen->AddMenuCheck("Disable AppleALC (-alcoff)", OPT_APPLEALC, 68);
// SubScreen->AddMenuCheck("Disable Shiki (-shikioff)", OPT_SHIKI, 68);
2019-09-03 11:58:42 +02:00
if ( gSettings . CsrActiveConfig = = 0 ) {
2020-03-03 21:44:07 +01:00
SubScreen - > AddMenuCheck ( " No SIP " , OSFLAG_NOSIP , 69 ) ;
2019-09-03 11:58:42 +02:00
}
2020-05-16 22:07:27 +02:00
} else if ( LoaderType = = OSTYPE_LINEFI ) {
BOOLEAN Quiet = LoadOptions . contains ( quietLitteral ) ;
BOOLEAN WithSplash = LoadOptions . contains ( splashLitteral ) ;
2019-09-03 11:58:42 +02:00
// default entry
2020-05-16 22:07:27 +02:00
SubEntry = getPartiallyDuplicatedEntry ( ) ;
2019-09-03 11:58:42 +02:00
if ( SubEntry ) {
2020-04-27 11:50:49 +02:00
SubEntry - > Title . SWPrintf ( " Run %ls " , FileName . wc_str ( ) ) ;
2020-03-03 21:44:07 +01:00
SubScreen - > AddMenuEntry ( SubEntry , true ) ;
2019-09-03 11:58:42 +02:00
}
2020-05-16 22:07:27 +02:00
SubEntry = getPartiallyDuplicatedEntry ( ) ;
2019-09-03 11:58:42 +02:00
if ( SubEntry ) {
if ( Quiet ) {
2020-05-16 22:07:27 +02:00
SubEntry - > Title . SWPrintf ( " %ls verbose " , Title . s ( ) ) ;
2020-05-10 11:41:34 +02:00
SubEntry - > LoadOptions . removeIC ( quietLitteral ) ;
2019-09-03 11:58:42 +02:00
} else {
2020-05-16 22:07:27 +02:00
SubEntry - > Title . SWPrintf ( " %ls quiet " , Title . s ( ) ) ;
2020-05-10 11:41:34 +02:00
SubEntry - > LoadOptions . AddID ( quietLitteral ) ;
2019-09-03 11:58:42 +02:00
}
2020-05-10 17:50:24 +02:00
SubScreen - > AddMenuEntry ( SubEntry , true ) ;
2019-09-03 11:58:42 +02:00
}
2020-05-10 17:50:24 +02:00
2020-05-16 22:07:27 +02:00
SubEntry = getPartiallyDuplicatedEntry ( ) ;
2019-09-03 11:58:42 +02:00
if ( SubEntry ) {
if ( WithSplash ) {
2020-05-16 22:07:27 +02:00
SubEntry - > Title . SWPrintf ( " %ls without splash " , Title . s ( ) ) ;
2020-05-10 11:41:34 +02:00
SubEntry - > LoadOptions . removeIC ( splashLitteral ) ;
2019-09-03 11:58:42 +02:00
} else {
2020-05-16 22:07:27 +02:00
SubEntry - > Title . SWPrintf ( " %ls with splash " , Title . s ( ) ) ;
2020-05-10 11:41:34 +02:00
SubEntry - > LoadOptions . AddID ( splashLitteral ) ;
2019-09-03 11:58:42 +02:00
}
2020-05-10 17:50:24 +02:00
SubScreen - > AddMenuEntry ( SubEntry , true ) ;
2019-09-03 11:58:42 +02:00
}
2020-05-10 17:50:24 +02:00
2020-05-16 22:07:27 +02:00
SubEntry = getPartiallyDuplicatedEntry ( ) ;
2019-09-03 11:58:42 +02:00
if ( SubEntry ) {
if ( WithSplash ) {
if ( Quiet ) {
2020-05-16 22:07:27 +02:00
SubEntry - > Title . SWPrintf ( " %ls verbose without splash " , Title . s ( ) ) ;
2020-05-10 11:41:34 +02:00
SubEntry - > LoadOptions . removeIC ( splashLitteral ) ;
SubEntry - > LoadOptions . removeIC ( quietLitteral ) ;
2019-09-03 11:58:42 +02:00
} else {
2020-05-16 22:07:27 +02:00
SubEntry - > Title . SWPrintf ( " %ls quiet without splash " , Title . s ( ) ) ;
2020-05-10 11:41:34 +02:00
SubEntry - > LoadOptions . removeIC ( splashLitteral ) ;
SubEntry - > LoadOptions . Add ( quietLitteral ) ;
2019-09-03 11:58:42 +02:00
}
} else if ( Quiet ) {
2020-05-16 22:07:27 +02:00
SubEntry - > Title . SWPrintf ( " %ls verbose with splash " , Title . s ( ) ) ;
2020-05-10 17:50:24 +02:00
SubEntry - > LoadOptions . removeIC ( quietLitteral ) ; //
2020-05-10 11:41:34 +02:00
SubEntry - > LoadOptions . AddID ( splashLitteral ) ;
2019-09-03 11:58:42 +02:00
} else {
2020-05-16 22:07:27 +02:00
SubEntry - > Title . SWPrintf ( " %ls quiet with splash " , Title . s ( ) ) ;
2020-05-10 11:41:34 +02:00
SubEntry - > LoadOptions . AddID ( quietLitteral ) ;
SubEntry - > LoadOptions . AddID ( splashLitteral ) ;
2019-09-03 11:58:42 +02:00
}
2020-05-10 17:50:24 +02:00
SubScreen - > AddMenuEntry ( SubEntry , true ) ;
2019-09-03 11:58:42 +02:00
}
2020-05-10 17:50:24 +02:00
2020-05-17 20:56:10 +02:00
} else if ( ( LoaderType = = OSTYPE_WIN ) | | ( LoaderType = = OSTYPE_WINEFI ) ) {
2019-09-03 11:58:42 +02:00
// by default, skip the built-in selection and boot from hard disk only
2020-05-17 20:56:10 +02:00
LoadOptions . setEmpty ( ) ;
LoadOptions . Add ( " -s " _XS8 ) ;
LoadOptions . Add ( " -h " _XS8 ) ;
2019-09-03 11:58:42 +02:00
// default entry
2020-05-17 20:56:10 +02:00
SubEntry = getPartiallyDuplicatedEntry ( ) ;
2019-09-03 11:58:42 +02:00
if ( SubEntry ) {
2020-04-27 11:50:49 +02:00
SubEntry - > Title . SWPrintf ( " Run %ls " , FileName . wc_str ( ) ) ;
2020-03-10 10:45:17 +01:00
SubScreen - > AddMenuEntry ( SubEntry , true ) ;
2019-09-03 11:58:42 +02:00
}
2020-05-17 20:56:10 +02:00
SubEntry = getPartiallyDuplicatedEntry ( ) ;
2019-09-03 11:58:42 +02:00
if ( SubEntry ) {
2020-03-10 17:50:55 +01:00
SubEntry - > Title . takeValueFrom ( " Boot Windows from Hard Disk " ) ;
2020-03-10 10:45:17 +01:00
SubScreen - > AddMenuEntry ( SubEntry , true ) ;
2019-09-03 11:58:42 +02:00
}
2020-05-17 20:56:10 +02:00
SubEntry = getPartiallyDuplicatedEntry ( ) ;
2019-09-03 11:58:42 +02:00
if ( SubEntry ) {
2020-03-10 17:50:55 +01:00
SubEntry - > Title . takeValueFrom ( " Boot Windows from CD-ROM " ) ;
2020-05-17 20:56:10 +02:00
LoadOptions . setEmpty ( ) ;
LoadOptions . Add ( " -s " _XS8 ) ;
LoadOptions . Add ( " -c " _XS8 ) ;
2020-03-10 10:45:17 +01:00
SubScreen - > AddMenuEntry ( SubEntry , true ) ;
2019-09-03 11:58:42 +02:00
}
2020-05-17 20:56:10 +02:00
SubEntry = getPartiallyDuplicatedEntry ( ) ;
2019-09-03 11:58:42 +02:00
if ( SubEntry ) {
2020-04-27 11:50:49 +02:00
SubEntry - > Title . SWPrintf ( " Run %ls in text mode " , FileName . wc_str ( ) ) ;
2019-09-03 11:58:42 +02:00
SubEntry - > Flags = OSFLAG_UNSET ( SubEntry - > Flags , OSFLAG_USEGRAPHICS ) ;
2020-05-17 20:56:10 +02:00
LoadOptions . setEmpty ( ) ;
LoadOptions . Add ( " -v " _XS8 ) ;
2019-09-03 11:58:42 +02:00
SubEntry - > LoaderType = OSTYPE_OTHER ; // Sothor - Why are we using OSTYPE_OTHER here?
2020-03-10 10:45:17 +01:00
SubScreen - > AddMenuEntry ( SubEntry , true ) ;
2019-09-03 11:58:42 +02:00
}
}
2020-03-03 21:44:07 +01:00
SubScreen - > AddMenuEntry ( & MenuEntryReturn , false ) ;
2020-05-16 22:07:27 +02:00
// DBG(" Added '%ls': OSType='%d', OSVersion='%s'\n",Title,LoaderType,OSVersion);
2019-09-03 11:58:42 +02:00
}
2020-05-06 00:23:59 +02:00
2020-04-27 11:50:49 +02:00
BOOLEAN AddLoaderEntry ( IN CONST XStringW & LoaderPath , IN CONST XStringArray & LoaderOptions ,
2020-04-03 22:00:42 +02:00
IN CONST XStringW & LoaderTitle ,
2020-05-16 21:30:29 +02:00
IN REFIT_VOLUME * Volume , IN XIcon * Image ,
2020-04-03 22:00:42 +02:00
IN UINT8 OSType , IN UINT8 Flags )
2019-09-03 11:58:42 +02:00
{
LOADER_ENTRY * Entry ;
INTN HVi ;
2020-04-27 14:13:09 +02:00
if ( ( LoaderPath . isEmpty ( ) ) | | ( Volume = = NULL ) | | ( Volume - > RootDir = = NULL ) | | ! FileExists ( Volume - > RootDir , LoaderPath ) ) {
2019-09-03 11:58:42 +02:00
return FALSE ;
}
2020-03-25 19:32:44 +01:00
DBG ( " AddLoaderEntry for Volume Name=%ls \n " , Volume - > VolName ) ;
2019-09-03 11:58:42 +02:00
if ( OSFLAG_ISSET ( Flags , OSFLAG_DISABLED ) ) {
DBG ( " skipped because entry is disabled \n " ) ;
return FALSE ;
}
if ( ! gSettings . ShowHiddenEntries & & OSFLAG_ISSET ( Flags , OSFLAG_HIDDEN ) ) {
DBG ( " skipped because entry is hidden \n " ) ;
return FALSE ;
}
//don't add hided entries
if ( ! gSettings . ShowHiddenEntries ) {
for ( HVi = 0 ; HVi < gSettings . HVCount ; HVi + + ) {
2020-04-27 11:50:49 +02:00
if ( LoaderPath . containsIC ( gSettings . HVHideStrings [ HVi ] ) ) {
DBG ( " hiding entry: %ls \n " , LoaderPath . s ( ) ) ;
2019-09-03 11:58:42 +02:00
return FALSE ;
}
}
}
2020-04-23 11:08:10 +02:00
Entry = CreateLoaderEntry ( LoaderPath , LoaderOptions , L " " _XSW , LoaderTitle , Volume , Image , NULL , OSType , Flags , 0 , MenuBackgroundPixel , CUSTOM_BOOT_DISABLED , NULL , NULL , FALSE ) ;
2019-09-03 11:58:42 +02:00
if ( Entry ! = NULL ) {
if ( ( Entry - > LoaderType = = OSTYPE_OSX ) | |
( Entry - > LoaderType = = OSTYPE_OSX_INSTALLER ) | |
( Entry - > LoaderType = = OSTYPE_RECOVERY ) ) {
if ( gSettings . WithKexts ) {
Entry - > Flags = OSFLAG_SET ( Entry - > Flags , OSFLAG_WITHKEXTS ) ;
}
if ( gSettings . WithKextsIfNoFakeSMC ) {
Entry - > Flags = OSFLAG_SET ( Entry - > Flags , OSFLAG_CHECKFAKESMC ) ;
Entry - > Flags = OSFLAG_SET ( Entry - > Flags , OSFLAG_WITHKEXTS ) ;
}
if ( gSettings . NoCaches ) {
Entry - > Flags = OSFLAG_SET ( Entry - > Flags , OSFLAG_NOCACHES ) ;
}
}
//TODO there is a problem that Entry->Flags is unique while InputItems are global ;(
// InputItems[69].IValue = Entry->Flags;
2020-05-16 22:07:27 +02:00
Entry - > AddDefaultMenu ( ) ;
2020-03-03 21:44:07 +01:00
MainMenu . AddMenuEntry ( Entry , true ) ;
2019-09-03 11:58:42 +02:00
return TRUE ;
}
return FALSE ;
}
2020-05-06 00:23:59 +02:00
2020-05-16 21:30:29 +02:00
STATIC VOID LinuxScan ( REFIT_VOLUME * Volume , UINT8 KernelScan , UINT8 Type , XStringW * CustomPath , XIcon * CustomImage )
2020-05-06 00:23:59 +02:00
{
// When used for Regular Entries, all found entries will be added by AddLoaderEntry()
// When used for Custom Entries (detected by CustomPath!=NULL), CustomPath+CustomImage will be set to the first entry found and execution will stop
// Scanning is adjusted according to Type: OSTYPE_LIN will scan for linux loaders, OSTYPE_LINEFI will scan for linux kernels, unspecified will scan for both
UINTN Index ;
EFI_GUID * PartGUID ;
// check for linux loaders
if ( Type ! = OSTYPE_LINEFI ) { // OSTYPE_LIN or unspecified
//
//----- Test common linux name and path like /EFI/ubuntu/grubx64.efi
REFIT_DIR_ITER DirIter ;
EFI_FILE_INFO * DirEntry = NULL ;
DirIterOpen ( Volume - > RootDir , L " \\ EFI " , & DirIter ) ;
while ( DirIterNext ( & DirIter , 1 , L " * " , & DirEntry ) ) {
if ( DirEntry - > FileName [ 0 ] = = ' . ' ) {
//DBG("Skip dot entries: %ls\n", DirEntry->FileName);
continue ;
}
XStringW File = SWPrintf ( " EFI \\ %ls \\ grubx64.efi " , DirEntry - > FileName ) ;
XStringW OSName = XStringW ( ) . takeValueFrom ( DirEntry - > FileName ) ; // this is folder name, for example "ubuntu"
OSName . lowerAscii ( ) ; // lowercase for icon name and title (first letter in title will be capitalized later)
if ( FileExists ( Volume - > RootDir , File ) ) {
// check if nonstandard icon mapping is needed
for ( Index = 0 ; Index < LinuxIconMappingCount ; + + Index ) {
if ( StrCmp ( OSName . wc_str ( ) , LinuxIconMapping [ Index ] . DirectoryName ) = = 0 ) {
OSName = XStringW ( ) . takeValueFrom ( LinuxIconMapping [ Index ] . IconName ) ;
break ;
}
}
if ( ! CustomPath ) {
DBG ( " found entry %ls,linux \n " , OSName . wc_str ( ) ) ;
}
XStringW LoaderTitle = OSName . subString ( 0 , 1 ) ; // capitalize first letter for title
LoaderTitle . upperAscii ( ) ;
LoaderTitle + = OSName . subString ( 1 , OSName . length ( ) ) + L " Linux " _XSW ;
// Very few linux icons exist in IconNames, but these few may be preloaded, so check that first
2020-05-16 21:30:29 +02:00
XIcon ImageX = ThemeX . GetIcon ( L " os_ " _XSW + OSName ) ; //will the image be destroyed or rewritten by next image after the cycle end?
2020-05-06 00:23:59 +02:00
if ( ImageX . isEmpty ( ) ) {
// no preloaded icon, try to load from dir
ImageX . LoadXImage ( ThemeX . ThemeDir , L " os_ " _XSW + OSName ) ;
}
if ( CustomPath ) {
* CustomPath = File ;
if ( CustomImage ) {
* CustomImage = ImageX ;
}
DirIterClose ( & DirIter ) ;
return ;
}
AddLoaderEntry ( File , NullXStringArray , LoaderTitle , Volume ,
( ImageX . isEmpty ( ) ? NULL : & ImageX ) , OSTYPE_LIN , OSFLAG_NODEFAULTARGS ) ;
} //anyway continue search other entries
}
DirIterClose ( & DirIter ) ;
// check for non-standard grub path
for ( Index = 0 ; Index < LinuxEntryDataCount ; + + Index ) {
if ( FileExists ( Volume - > RootDir , LinuxEntryData [ Index ] . Path ) ) {
XStringW OSIconName = XStringW ( ) . takeValueFrom ( LinuxEntryData [ Index ] . Icon ) ;
OSIconName = OSIconName . subString ( 0 , OSIconName . indexOf ( ' , ' ) ) ;
2020-05-16 21:30:29 +02:00
XIcon ImageX = ThemeX . GetIcon ( L " os_ " _XSW + OSIconName ) ;
2020-05-06 00:23:59 +02:00
if ( ImageX . isEmpty ( ) ) {
ImageX . LoadXImage ( ThemeX . ThemeDir , L " os_ " _XSW + OSIconName ) ;
}
if ( CustomPath ) {
* CustomPath = LinuxEntryData [ Index ] . Path ;
if ( CustomImage ) {
* CustomImage = ImageX ;
}
return ;
}
AddLoaderEntry ( LinuxEntryData [ Index ] . Path , NullXStringArray , XStringW ( ) . takeValueFrom ( LinuxEntryData [ Index ] . Title ) , Volume ,
( ImageX . isEmpty ( ) ? NULL : & ImageX ) , OSTYPE_LIN , OSFLAG_NODEFAULTARGS ) ;
}
}
2020-05-10 01:40:55 +02:00
}
if ( Type ! = OSTYPE_LIN ) { //OSTYPE_LINEFI or unspecified
2020-05-06 00:23:59 +02:00
// check for linux kernels
PartGUID = FindGPTPartitionGuidInDevicePath ( Volume - > DevicePath ) ;
if ( ( PartGUID ! = NULL ) & & ( Volume - > RootDir ! = NULL ) ) {
REFIT_DIR_ITER Iter ;
EFI_FILE_INFO * FileInfo = NULL ;
EFI_TIME PreviousTime ;
XStringW Path ;
// CHAR16 *Options;
// Get the partition UUID and make sure it's lower case
CHAR16 PartUUID [ 40 ] ;
ZeroMem ( & PreviousTime , sizeof ( EFI_TIME ) ) ;
snwprintf ( PartUUID , sizeof ( PartUUID ) , " %s " , strguid ( PartGUID ) ) ;
StrToLower ( PartUUID ) ;
// open the /boot directory (or whatever directory path)
DirIterOpen ( Volume - > RootDir , LINUX_BOOT_PATH , & Iter ) ;
// Check which kernel scan to use
// the following options can produce only a single option
switch ( KernelScan ) {
case KERNEL_SCAN_FIRST :
// First kernel found only
while ( DirIterNext ( & Iter , 2 , LINUX_LOADER_SEARCH_PATH , & FileInfo ) ) {
if ( FileInfo ! = NULL ) {
if ( FileInfo - > FileSize = = 0 ) {
continue ;
}
// get the kernel file path
Path . SWPrintf ( " %ls \\ %ls " , LINUX_BOOT_PATH , FileInfo - > FileName ) ;
// free the file info
break ;
}
}
break ;
case KERNEL_SCAN_LAST :
// Last kernel found only
while ( DirIterNext ( & Iter , 2 , LINUX_LOADER_SEARCH_PATH , & FileInfo ) ) {
if ( FileInfo ! = NULL ) {
if ( FileInfo - > FileSize > 0 ) {
// get the kernel file path
Path . SWPrintf ( " %ls \\ %ls " , LINUX_BOOT_PATH , FileInfo - > FileName ) ;
}
}
}
break ;
case KERNEL_SCAN_NEWEST :
// Newest dated kernel only
while ( DirIterNext ( & Iter , 2 , LINUX_LOADER_SEARCH_PATH , & FileInfo ) ) {
if ( FileInfo ! = NULL ) {
if ( FileInfo - > FileSize > 0 ) {
// get the kernel file path
if ( ( PreviousTime . Year = = 0 ) | | ( TimeCmp ( & PreviousTime , & ( FileInfo - > ModificationTime ) ) < 0 ) ) {
Path . SWPrintf ( " %ls \\ %ls " , LINUX_BOOT_PATH , FileInfo - > FileName ) ;
PreviousTime = FileInfo - > ModificationTime ;
}
}
}
}
break ;
case KERNEL_SCAN_OLDEST :
// Oldest dated kernel only
while ( DirIterNext ( & Iter , 2 , LINUX_LOADER_SEARCH_PATH , & FileInfo ) ) {
if ( FileInfo ! = NULL ) {
if ( FileInfo - > FileSize > 0 ) {
// get the kernel file path
if ( ( PreviousTime . Year = = 0 ) | | ( TimeCmp ( & PreviousTime , & ( FileInfo - > ModificationTime ) ) > 0 ) ) {
Path . SWPrintf ( " %ls \\ %ls " , LINUX_BOOT_PATH , FileInfo - > FileName ) ;
PreviousTime = FileInfo - > ModificationTime ;
}
}
}
}
break ;
case KERNEL_SCAN_MOSTRECENT :
// most recent kernel version only
while ( DirIterNext ( & Iter , 2 , LINUX_LOADER_SEARCH_PATH , & FileInfo ) ) {
if ( FileInfo ! = NULL ) {
if ( FileInfo - > FileSize > 0 ) {
// get the kernel file path
XStringW NewPath = SWPrintf ( " %ls \\ %ls " , LINUX_BOOT_PATH , FileInfo - > FileName ) ;
if ( Path < NewPath ) {
Path = NewPath ;
} else {
Path . setEmpty ( ) ;
}
}
}
}
break ;
case KERNEL_SCAN_EARLIEST :
// earliest kernel version only
while ( DirIterNext ( & Iter , 2 , LINUX_LOADER_SEARCH_PATH , & FileInfo ) ) {
if ( FileInfo ! = NULL ) {
if ( FileInfo - > FileSize > 0 ) {
// get the kernel file path
XStringW NewPath = SWPrintf ( " %ls \\ %ls " , LINUX_BOOT_PATH , FileInfo - > FileName ) ;
if ( Path > NewPath ) {
Path = NewPath ;
} else {
Path . setEmpty ( ) ;
}
}
}
}
break ;
case KERNEL_SCAN_NONE :
default :
// No kernel scan
break ;
}
// add the produced entry
if ( Path . notEmpty ( ) ) {
if ( CustomPath ) {
* CustomPath = Path ;
DirIterClose ( & Iter ) ;
return ;
}
XStringArray Options = LinuxKernelOptions ( Iter . DirHandle , Basename ( Path . wc_str ( ) ) + LINUX_LOADER_PATH . length ( ) , PartUUID , NullXStringArray ) ;
// Add the entry
AddLoaderEntry ( Path , ( Options . isEmpty ( ) ) ? LINUX_DEFAULT_OPTIONS : Options , L " " _XSW , Volume , NULL , OSTYPE_LINEFI , OSFLAG_NODEFAULTARGS ) ;
Path . setEmpty ( ) ;
}
// the following produces multiple entries
// custom entries has a different implementation, and does not use this code
if ( ! CustomPath & & KernelScan = = KERNEL_SCAN_ALL ) {
// get all the filename matches
while ( DirIterNext ( & Iter , 2 , LINUX_LOADER_SEARCH_PATH , & FileInfo ) ) {
if ( FileInfo ! = NULL ) {
if ( FileInfo - > FileSize > 0 ) {
// get the kernel file path
Path . SWPrintf ( " %ls \\ %ls " , LINUX_BOOT_PATH , FileInfo - > FileName ) ;
2020-05-10 01:40:55 +02:00
XStringArray Options = LinuxKernelOptions ( Iter . DirHandle , Basename ( Path . wc_str ( ) ) + LINUX_LOADER_PATH . length ( ) , PartUUID , NullXStringArray ) ;
2020-05-06 00:23:59 +02:00
// Add the entry
AddLoaderEntry ( Path , ( Options . isEmpty ( ) ) ? LINUX_DEFAULT_OPTIONS : Options , L " " _XSW , Volume , NULL , OSTYPE_LINEFI , OSFLAG_NODEFAULTARGS ) ;
Path . setEmpty ( ) ;
}
}
}
}
//close the directory
DirIterClose ( & Iter ) ;
}
}
}
2019-09-03 11:58:42 +02:00
//constants
2020-04-27 11:50:49 +02:00
//const XStringW APFSFVBootPath = L"\\00000000-0000-0000-0000-000000000000\\System\\Library\\CoreServices\\boot.efi"_XSW;
//const XStringW APFSRecBootPath = L"\\00000000-0000-0000-0000-000000000000\\boot.efi"_XSW;
//const XStringW APFSInstallBootPath = L"\\00000000-0000-0000-0000-000000000000\\com.apple.installer\\boot.efi"_XSW;
2019-09-03 11:58:42 +02:00
# define Paper 1
# define Rock 2
# define Scissor 4
VOID AddPRSEntry ( REFIT_VOLUME * Volume )
{
INTN WhatBoot = 0 ;
2020-04-03 22:00:42 +02:00
//CONST INTN Paper = 1;
//CONST INTN Rock = 2;
//CONST INTN Scissor = 4;
2019-09-03 11:58:42 +02:00
2020-04-27 14:13:09 +02:00
WhatBoot | = FileExists ( Volume - > RootDir , RockBoot ) ? Rock : 0 ;
WhatBoot | = FileExists ( Volume - > RootDir , PaperBoot ) ? Paper : 0 ;
WhatBoot | = FileExists ( Volume - > RootDir , ScissorBoot ) ? Scissor : 0 ;
2019-09-03 11:58:42 +02:00
switch ( WhatBoot ) {
case Paper :
case ( Paper | Rock ) :
2020-04-26 15:07:30 +02:00
AddLoaderEntry ( PaperBoot , NullXStringArray , L " macOS InstallP " _XSW , Volume , NULL , OSTYPE_OSX_INSTALLER , 0 ) ;
2019-09-03 11:58:42 +02:00
break ;
case Scissor :
case ( Paper | Scissor ) :
2020-04-26 15:07:30 +02:00
AddLoaderEntry ( ScissorBoot , NullXStringArray , L " macOS InstallS " _XSW , Volume , NULL , OSTYPE_OSX_INSTALLER , 0 ) ;
2019-09-03 11:58:42 +02:00
break ;
case Rock :
case ( Rock | Scissor ) :
case ( Rock | Scissor | Paper ) :
2020-04-26 15:07:30 +02:00
AddLoaderEntry ( RockBoot , NullXStringArray , L " macOS InstallR " _XSW , Volume , NULL , OSTYPE_OSX_INSTALLER , 0 ) ;
2019-09-03 11:58:42 +02:00
break ;
default :
break ;
}
}
# undef Paper
# undef Rock
# undef Scissor
VOID ScanLoader ( VOID )
{
2020-05-06 00:23:59 +02:00
UINTN VolumeIndex ;
2019-09-03 11:58:42 +02:00
REFIT_VOLUME * Volume ;
//DBG("Scanning loaders...\n");
DbgHeader ( " ScanLoader " ) ;
2020-02-27 15:34:29 +01:00
for ( VolumeIndex = 0 ; VolumeIndex < Volumes . size ( ) ; VolumeIndex + + ) {
Volume = & Volumes [ VolumeIndex ] ;
2019-09-03 11:58:42 +02:00
if ( Volume - > RootDir = = NULL ) { // || Volume->VolName == NULL)
//DBG(", no file system\n", VolumeIndex);
continue ;
}
2020-03-25 19:32:44 +01:00
DBG ( " - [%02llu]: '%ls' " , VolumeIndex , Volume - > VolName ) ;
2019-09-03 11:58:42 +02:00
if ( Volume - > VolName = = NULL ) {
Volume - > VolName = L " Unknown " ;
}
// skip volume if its kind is configured as disabled
2020-04-23 11:08:10 +02:00
if ( ( ( 1ull < < Volume - > DiskKind ) & GlobalConfig . DisableFlags ) ! = 0 )
2019-09-03 11:58:42 +02:00
{
2020-04-23 11:08:10 +02:00
DBG ( " , flagged disable \n " ) ;
2019-09-03 11:58:42 +02:00
continue ;
}
if ( Volume - > Hidden ) {
DBG ( " , hidden \n " ) ;
continue ;
}
DBG ( " \n " ) ;
// check for Mac OS X Install Data
// 1st stage - createinstallmedia
if ( FileExists ( Volume - > RootDir , L " \\ .IABootFiles \\ boot.efi " ) ) {
if ( FileExists ( Volume - > RootDir , L " \\ Install OS X Mavericks.app " ) | |
FileExists ( Volume - > RootDir , L " \\ Install OS X Yosemite.app " ) | |
FileExists ( Volume - > RootDir , L " \\ Install OS X El Capitan.app " ) ) {
2020-04-29 22:32:44 +02:00
AddLoaderEntry ( L " \\ .IABootFiles \\ boot.efi " _XSW , NullXStringArray , L " OS X Install " _XSW , Volume , NULL , OSTYPE_OSX_INSTALLER , 0 ) ; // 10.9 - 10.11
2019-09-03 11:58:42 +02:00
} else {
2020-04-27 11:50:49 +02:00
AddLoaderEntry ( L " \\ .IABootFiles \\ boot.efi " _XSW , NullXStringArray , L " macOS Install " _XSW , Volume , NULL , OSTYPE_OSX_INSTALLER , 0 ) ; // 10.12 - 10.13.3
2019-09-03 11:58:42 +02:00
}
2020-04-27 14:13:09 +02:00
} else if ( FileExists ( Volume - > RootDir , L " \\ .IAPhysicalMedia " ) & & FileExists ( Volume - > RootDir , MACOSX_LOADER_PATH ) ) {
2020-04-26 15:07:30 +02:00
AddLoaderEntry ( MACOSX_LOADER_PATH , NullXStringArray , L " macOS Install " _XSW , Volume , NULL , OSTYPE_OSX_INSTALLER , 0 ) ; // 10.13.4+
2019-09-03 11:58:42 +02:00
}
// 2nd stage - InstallESD/AppStore/startosinstall/Fusion Drive
2020-04-29 22:32:44 +02:00
AddLoaderEntry ( L " \\ Mac OS X Install Data \\ boot.efi " _XSW , NullXStringArray , L " Mac OS X Install " _XSW , Volume , NULL , OSTYPE_OSX_INSTALLER , 0 ) ; // 10.7
2020-04-27 11:50:49 +02:00
AddLoaderEntry ( L " \\ OS X Install Data \\ boot.efi " _XSW , NullXStringArray , L " OS X Install " _XSW , Volume , NULL , OSTYPE_OSX_INSTALLER , 0 ) ; // 10.8 - 10.11
AddLoaderEntry ( L " \\ macOS Install Data \\ boot.efi " _XSW , NullXStringArray , L " macOS Install " _XSW , Volume , NULL , OSTYPE_OSX_INSTALLER , 0 ) ; // 10.12 - 10.12.3
AddLoaderEntry ( L " \\ macOS Install Data \\ Locked Files \\ Boot Files \\ boot.efi " _XSW , NullXStringArray , L " macOS Install " _XSW , Volume , NULL , OSTYPE_OSX_INSTALLER , 0 ) ; // 10.12.4+
2019-09-03 11:58:42 +02:00
AddPRSEntry ( Volume ) ; // 10.12+
// Netinstall
2020-04-27 11:50:49 +02:00
AddLoaderEntry ( L " \\ NetInstall macOS High Sierra.nbi \\ i386 \\ booter " _XSW , NullXStringArray , L " macOS Install " _XSW , Volume , NULL , OSTYPE_OSX_INSTALLER , 0 ) ;
2019-09-03 11:58:42 +02:00
// Use standard location for boot.efi, according to the install files is present
// That file indentifies a DVD/ESD/BaseSystem/Fusion Drive Install Media, so when present, check standard path to avoid entry duplication
2020-04-27 14:13:09 +02:00
if ( FileExists ( Volume - > RootDir , MACOSX_LOADER_PATH ) ) {
2020-04-03 22:00:42 +02:00
if ( FileExists ( Volume - > RootDir , L " \\ System \\ Installation \\ CDIS \\ Mac OS X Installer.app " ) ) {
// InstallDVD/BaseSystem
2020-04-26 15:07:30 +02:00
AddLoaderEntry ( MACOSX_LOADER_PATH , NullXStringArray , L " Mac OS X Install " _XSW , Volume , NULL , OSTYPE_OSX_INSTALLER , 0 ) ; // 10.6/10.7
2020-04-03 22:00:42 +02:00
} else if ( FileExists ( Volume - > RootDir , L " \\ System \\ Installation \\ CDIS \\ OS X Installer.app " ) ) {
// BaseSystem
2020-04-26 15:07:30 +02:00
AddLoaderEntry ( MACOSX_LOADER_PATH , NullXStringArray , L " OS X Install " _XSW , Volume , NULL , OSTYPE_OSX_INSTALLER , 0 ) ; // 10.8 - 10.11
2020-04-03 22:00:42 +02:00
} else if ( FileExists ( Volume - > RootDir , L " \\ System \\ Installation \\ CDIS \\ macOS Installer.app " ) ) {
// BaseSystem
2020-04-26 15:07:30 +02:00
AddLoaderEntry ( MACOSX_LOADER_PATH , NullXStringArray , L " macOS Install " _XSW , Volume , NULL , OSTYPE_OSX_INSTALLER , 0 ) ; // 10.12+
2020-04-03 22:00:42 +02:00
} else if ( FileExists ( Volume - > RootDir , L " \\ BaseSystem.dmg " ) & & FileExists ( Volume - > RootDir , L " \\ mach_kernel " ) ) {
// InstallESD
if ( FileExists ( Volume - > RootDir , L " \\ MacOSX_Media_Background.png " ) ) {
2020-04-26 15:07:30 +02:00
AddLoaderEntry ( MACOSX_LOADER_PATH , NullXStringArray , L " Mac OS X Install " _XSW , Volume , NULL , OSTYPE_OSX_INSTALLER , 0 ) ; // 10.7
2020-04-03 22:00:42 +02:00
} else {
2020-04-26 15:07:30 +02:00
AddLoaderEntry ( MACOSX_LOADER_PATH , NullXStringArray , L " OS X Install " _XSW , Volume , NULL , OSTYPE_OSX_INSTALLER , 0 ) ; // 10.8
2020-04-03 22:00:42 +02:00
}
} else if ( FileExists ( Volume - > RootDir , L " \\ com.apple.boot.R \\ System \\ Library \\ PrelinkedKernels \\ prelinkedkernel " ) | |
FileExists ( Volume - > RootDir , L " \\ com.apple.boot.P \\ System \\ Library \\ PrelinkedKernels \\ prelinkedkernel " ) | |
FileExists ( Volume - > RootDir , L " \\ com.apple.boot.S \\ System \\ Library \\ PrelinkedKernels \\ prelinkedkernel " ) ) {
if ( StriStr ( Volume - > VolName , L " Recovery " ) ! = NULL ) {
// FileVault of HFS+
// TODO: need info for 10.11 and lower
2020-04-26 15:07:30 +02:00
AddLoaderEntry ( MACOSX_LOADER_PATH , NullXStringArray , L " macOS FileVault " _XSW , Volume , NULL , OSTYPE_OSX , 0 ) ; // 10.12+
2020-04-03 22:00:42 +02:00
} else {
// Fusion Drive
2020-04-26 15:07:30 +02:00
AddLoaderEntry ( MACOSX_LOADER_PATH , NullXStringArray , L " OS X Install " _XSW , Volume , NULL , OSTYPE_OSX_INSTALLER , 0 ) ; // 10.11
2020-04-03 22:00:42 +02:00
}
} else if ( ! FileExists ( Volume - > RootDir , L " \\ .IAPhysicalMedia " ) ) {
// Installed
if ( EFI_ERROR ( GetRootUUID ( Volume ) ) | | isFirstRootUUID ( Volume ) ) {
if ( ! FileExists ( Volume - > RootDir , L " \\ System \\ Library \\ CoreServices \\ NotificationCenter.app " ) & & ! FileExists ( Volume - > RootDir , L " \\ System \\ Library \\ CoreServices \\ Siri.app " ) ) {
2020-04-26 15:07:30 +02:00
AddLoaderEntry ( MACOSX_LOADER_PATH , NullXStringArray , L " Mac OS X " _XSW , Volume , NULL , OSTYPE_OSX , 0 ) ; // 10.6 - 10.7
2020-04-03 22:00:42 +02:00
} else if ( FileExists ( Volume - > RootDir , L " \\ System \\ Library \\ CoreServices \\ NotificationCenter.app " ) & & ! FileExists ( Volume - > RootDir , L " \\ System \\ Library \\ CoreServices \\ Siri.app " ) ) {
2020-04-26 15:07:30 +02:00
AddLoaderEntry ( MACOSX_LOADER_PATH , NullXStringArray , L " OS X " _XSW , Volume , NULL , OSTYPE_OSX , 0 ) ; // 10.8 - 10.11
2020-04-03 22:00:42 +02:00
} else {
2020-04-26 15:07:30 +02:00
AddLoaderEntry ( MACOSX_LOADER_PATH , NullXStringArray , L " macOS " _XSW , Volume , NULL , OSTYPE_OSX , 0 ) ; // 10.12+
2020-04-03 22:00:42 +02:00
}
}
}
}
2020-04-05 14:25:39 +02:00
/* APFS Container support.
2019-09-03 11:58:42 +02:00
* s . mtr 2017
*/
if ( ( StriCmp ( Volume - > VolName , L " Recovery " ) = = 0 | | StriCmp ( Volume - > VolName , L " Preboot " ) = = 0 ) & & APFSSupport = = TRUE ) {
for ( UINTN i = 0 ; i < APFSUUIDBankCounter + 1 ; i + + ) {
//Store current UUID
2020-04-27 11:50:49 +02:00
XStringW CurrentUUID = GuidLEToStr ( ( EFI_GUID * ) ( ( UINT8 * ) APFSUUIDBank + i * 0x10 ) ) ;
2019-09-03 11:58:42 +02:00
//Fill with current UUID
2020-04-27 11:50:49 +02:00
// StrnCpy(APFSFVBootPath + 1, CurrentUUID, 36);
// StrnCpy(APFSRecBootPath + 1, CurrentUUID, 36);
// StrnCpy(APFSInstallBootPath + 1, CurrentUUID, 36);
2020-04-03 22:00:42 +02:00
//Try to add FileVault entry
2020-04-27 11:50:49 +02:00
AddLoaderEntry ( SWPrintf ( " \\ %ls \\ System \\ Library \\ CoreServices \\ boot.efi " , CurrentUUID . c_str ( ) ) , NullXStringArray , L " FileVault Prebooter " _XSW , Volume , NULL , OSTYPE_OSX , 0 ) ;
2020-04-03 22:00:42 +02:00
//Try to add Recovery APFS entry
2020-04-27 11:50:49 +02:00
AddLoaderEntry ( SWPrintf ( " \\ %ls \\ boot.efi " , CurrentUUID . c_str ( ) ) , NullXStringArray , L " Recovery " _XSW , Volume , NULL , OSTYPE_RECOVERY , 0 ) ;
2020-04-03 22:00:42 +02:00
//Try to add macOS install entry
2020-04-27 11:50:49 +02:00
AddLoaderEntry ( SWPrintf ( " \\ %ls \\ com.apple.installer \\ boot.efi " , CurrentUUID . c_str ( ) ) , NullXStringArray , L " macOS Install Prebooter " _XSW , Volume , NULL , OSTYPE_OSX_INSTALLER , 0 ) ;
2019-09-03 11:58:42 +02:00
}
}
2020-04-03 22:00:42 +02:00
// check for Mac OS X Recovery Boot
2020-04-27 11:50:49 +02:00
AddLoaderEntry ( L " \\ com.apple.recovery.boot \\ boot.efi " _XSW , NullXStringArray , L " Recovery " _XSW , Volume , NULL , OSTYPE_RECOVERY , 0 ) ;
2019-09-03 11:58:42 +02:00
2020-04-03 22:00:42 +02:00
// Sometimes, on some systems (HP UEFI, if Win is installed first)
// it is needed to get rid of bootmgfw.efi to allow starting of
// Clover as /efi/boot/bootx64.efi from HD. We can do that by renaming
// bootmgfw.efi to bootmgfw-orig.efi
2020-04-27 11:50:49 +02:00
AddLoaderEntry ( L " \\ EFI \\ microsoft \\ Boot \\ bootmgfw-orig.efi " _XSW , NullXStringArray , L " Microsoft EFI " _XSW , Volume , NULL , OSTYPE_WINEFI , 0 ) ;
2020-04-03 22:00:42 +02:00
// check for Microsoft boot loader/menu
// If there is bootmgfw-orig.efi, then do not check for bootmgfw.efi
// since on some systems this will actually be CloverX64.efi
// renamed to bootmgfw.efi
2020-04-27 11:50:49 +02:00
AddLoaderEntry ( L " \\ EFI \\ microsoft \\ Boot \\ bootmgfw.efi " _XSW , NullXStringArray , L " Microsoft EFI Boot " _XSW , Volume , NULL , OSTYPE_WINEFI , 0 ) ;
2020-04-03 22:00:42 +02:00
// check for Microsoft boot loader/menu. This entry is redundant so excluded
// AddLoaderEntry(L"\\bootmgr.efi", L"", L"Microsoft EFI mgrboot", Volume, NULL, OSTYPE_WINEFI, 0);
// check for Microsoft boot loader/menu on CDROM
2020-04-27 11:50:49 +02:00
if ( ! AddLoaderEntry ( L " \\ EFI \\ MICROSOFT \\ BOOT \\ cdboot.efi " _XSW , NullXStringArray , L " Microsoft EFI cdboot " _XSW , Volume , NULL , OSTYPE_WINEFI , 0 ) ) {
AddLoaderEntry ( L " \\ EFI \\ MICROSOF \\ BOOT \\ CDBOOT.EFI " _XSW , NullXStringArray , L " Microsoft EFI CDBOOT " _XSW , Volume , NULL , OSTYPE_WINEFI , 0 ) ;
2020-04-03 22:00:42 +02:00
}
2020-05-06 00:23:59 +02:00
2019-09-03 11:58:42 +02:00
# if defined(ANDX86)
if ( TRUE ) { //gSettings.AndroidScan
// check for Android loaders
2020-05-06 00:23:59 +02:00
for ( UINTN Index = 0 ; Index < AndroidEntryDataCount ; + + Index ) {
2019-09-03 11:58:42 +02:00
UINTN aIndex , aFound ;
2020-04-27 14:13:09 +02:00
if ( FileExists ( Volume - > RootDir , AndroidEntryData [ Index ] . Path ) ) {
2019-09-03 11:58:42 +02:00
aFound = 0 ;
for ( aIndex = 0 ; aIndex < ANDX86_FINDLEN ; + + aIndex ) {
2020-04-27 11:50:49 +02:00
if ( ( AndroidEntryData [ Index ] . Find [ aIndex ] . isEmpty ( ) ) | | FileExists ( Volume - > RootDir , AndroidEntryData [ Index ] . Find [ aIndex ] ) ) + + aFound ;
2019-09-03 11:58:42 +02:00
}
if ( aFound & & ( aFound = = aIndex ) ) {
2020-05-16 21:30:29 +02:00
XIcon ImageX ;
2020-04-13 17:43:32 +02:00
XStringW IconXSW = XStringW ( ) . takeValueFrom ( AndroidEntryData [ Index ] . Icon ) ;
2020-04-23 22:43:35 +02:00
ImageX . LoadXImage ( ThemeX . ThemeDir , ( L " os_ " _XSW + IconXSW . subString ( 0 , IconXSW . indexOf ( ' , ' ) ) ) . wc_str ( ) ) ;
2020-04-26 15:07:30 +02:00
AddLoaderEntry ( AndroidEntryData [ Index ] . Path , NullXStringArray , XStringW ( ) . takeValueFrom ( AndroidEntryData [ Index ] . Title ) , Volume ,
2020-04-10 21:02:30 +02:00
( ImageX . isEmpty ( ) ? NULL : & ImageX ) , OSTYPE_LIN , OSFLAG_NODEFAULTARGS ) ;
2019-09-03 11:58:42 +02:00
}
}
}
}
# endif
if ( gSettings . LinuxScan ) {
2020-05-06 00:23:59 +02:00
LinuxScan ( Volume , gSettings . KernelScan , 0 , NULL , NULL ) ;
}
2019-09-03 11:58:42 +02:00
// DBG("search for optical UEFI\n");
if ( Volume - > DiskKind = = DISK_KIND_OPTICAL ) {
2020-04-26 15:07:30 +02:00
AddLoaderEntry ( BOOT_LOADER_PATH , NullXStringArray , L " UEFI optical " _XSW , Volume , NULL , OSTYPE_OTHER , 0 ) ;
2019-09-03 11:58:42 +02:00
}
// DBG("search for internal UEFI\n");
if ( Volume - > DiskKind = = DISK_KIND_INTERNAL ) {
2020-04-26 15:07:30 +02:00
AddLoaderEntry ( BOOT_LOADER_PATH , NullXStringArray , L " UEFI internal " _XSW , Volume , NULL , OSTYPE_OTHER , OSFLAG_HIDDEN ) ;
2019-09-03 11:58:42 +02:00
}
// DBG("search for external UEFI\n");
if ( Volume - > DiskKind = = DISK_KIND_EXTERNAL ) {
2020-04-26 15:07:30 +02:00
AddLoaderEntry ( BOOT_LOADER_PATH , NullXStringArray , L " UEFI external " _XSW , Volume , NULL , OSTYPE_OTHER , OSFLAG_HIDDEN ) ;
2019-09-03 11:58:42 +02:00
}
}
}
STATIC VOID AddCustomEntry ( IN UINTN CustomIndex ,
2020-04-27 11:50:49 +02:00
IN XStringW CustomPath ,
2019-09-03 11:58:42 +02:00
IN CUSTOM_LOADER_ENTRY * Custom ,
IN REFIT_MENU_SCREEN * SubMenu )
{
UINTN VolumeIndex ;
REFIT_VOLUME * Volume ;
REFIT_DIR_ITER SIter ;
REFIT_DIR_ITER * Iter = & SIter ;
CHAR16 PartUUID [ 40 ] ;
BOOLEAN IsSubEntry = ( SubMenu ! = NULL ) ;
2020-04-27 11:50:49 +02:00
BOOLEAN FindCustomPath = ( CustomPath . isEmpty ( ) ) ;
2019-09-03 11:58:42 +02:00
if ( Custom = = NULL ) {
return ;
}
2020-05-06 00:23:59 +02:00
if ( FindCustomPath & & ( Custom - > Type ! = OSTYPE_LINEFI ) & & ( Custom - > Type ! = OSTYPE_LIN ) ) {
// DBG("Custom %lsentry %llu skipped because it didn't have a ", IsSubEntry ? L"sub " : L"", CustomIndex);
2020-04-03 22:00:42 +02:00
// if (Custom->Type == 0) {
// DBG("Type.\n");
// } else {
// DBG("Path.\n");
// }
2019-09-03 11:58:42 +02:00
return ;
}
if ( OSFLAG_ISSET ( Custom - > Flags , OSFLAG_DISABLED ) ) {
2020-05-06 00:23:59 +02:00
// DBG("Custom %lsentry %llu skipped because it is disabled.\n", IsSubEntry ? L"sub " : L"", CustomIndex);
2019-09-03 11:58:42 +02:00
return ;
}
2020-05-06 00:23:59 +02:00
2019-09-03 11:58:42 +02:00
if ( ! gSettings . ShowHiddenEntries & & OSFLAG_ISSET ( Custom - > Flags , OSFLAG_HIDDEN ) ) {
2020-05-06 00:23:59 +02:00
// DBG("Custom %lsentry %llu skipped because it is hidden.\n", IsSubEntry ? L"sub " : L"", CustomIndex);
2019-09-03 11:58:42 +02:00
return ;
}
2020-05-06 00:23:59 +02:00
2020-04-03 22:00:42 +02:00
#if 0 //if someone want to debug this
DBG ( " Custom %lsentry %llu " , IsSubEntry ? L " sub " : L " " , CustomIndex ) ;
// if (Custom->Title) {
DBG ( " Title: \" %ls \" " , Custom - > Title . wc_str ( ) ) ;
// }
// if (Custom->FullTitle) {
DBG ( " FullTitle: \" %ls \" " , Custom - > FullTitle . wc_str ( ) ) ;
// }
2019-09-03 11:58:42 +02:00
if ( CustomPath ) {
2020-03-25 19:32:44 +01:00
DBG ( " Path: \" %ls \" " , CustomPath ) ;
2019-09-03 11:58:42 +02:00
}
if ( Custom - > Options ! = NULL ) {
2020-03-25 19:32:44 +01:00
DBG ( " Options: \" %ls \" " , Custom - > Options ) ;
2019-09-03 11:58:42 +02:00
}
2020-04-17 15:14:24 +02:00
DBG ( " Type:%d Flags:0x%hhX matching " , Custom - > Type , Custom - > Flags ) ;
2019-09-03 11:58:42 +02:00
if ( Custom - > Volume ) {
2020-03-25 19:32:44 +01:00
DBG ( " Volume: \" %ls \" \n " , Custom - > Volume ) ;
2019-09-03 11:58:42 +02:00
} else {
DBG ( " all volumes \n " ) ;
}
2020-04-03 22:00:42 +02:00
# endif
2019-09-03 11:58:42 +02:00
2020-02-27 15:34:29 +01:00
for ( VolumeIndex = 0 ; VolumeIndex < Volumes . size ( ) ; + + VolumeIndex ) {
2019-09-03 11:58:42 +02:00
CUSTOM_LOADER_ENTRY * CustomSubEntry ;
LOADER_ENTRY * Entry = NULL ;
2020-05-16 21:30:29 +02:00
XIcon Image = Custom - > Image ;
XIcon DriveImage = Custom - > DriveImage ;
2020-04-03 22:00:42 +02:00
2019-09-03 11:58:42 +02:00
EFI_GUID * Guid = NULL ;
UINT64 VolumeSize ;
2020-02-27 15:34:29 +01:00
Volume = & Volumes [ VolumeIndex ] ;
2019-09-03 11:58:42 +02:00
if ( ( Volume = = NULL ) | | ( Volume - > RootDir = = NULL ) ) {
continue ;
}
if ( Volume - > VolName = = NULL ) {
Volume - > VolName = L " Unknown " ;
}
2020-03-25 19:32:44 +01:00
DBG ( " Checking volume \" %ls \" (%ls) ... " , Volume - > VolName , Volume - > DevicePathString ) ;
2019-09-03 11:58:42 +02:00
// skip volume if its kind is configured as disabled
2020-04-20 14:45:25 +02:00
if ( ( ( 1ull < < Volume - > DiskKind ) & GlobalConfig . DisableFlags ) ! = 0 ) {
2020-04-11 14:34:59 +02:00
DBG ( " skipped because media is disabled \n " ) ;
continue ;
}
2019-09-03 11:58:42 +02:00
2020-04-12 17:36:40 +02:00
if ( Custom - > VolumeType ! = 0 & & ( ( 1 < < Volume - > DiskKind ) & Custom - > VolumeType ) = = 0 ) {
2020-04-11 14:34:59 +02:00
DBG ( " skipped because media is ignored \n " ) ;
continue ;
}
2019-09-03 11:58:42 +02:00
if ( Volume - > Hidden ) {
DBG ( " skipped because volume is hidden \n " ) ;
continue ;
}
2020-05-06 00:23:59 +02:00
// Check for exact volume matches (devicepath / volumelabel)
2019-09-03 11:58:42 +02:00
if ( Custom - > Volume ) {
if ( ( StrStr ( Volume - > DevicePathString , Custom - > Volume ) = = NULL ) & &
( ( Volume - > VolName = = NULL ) | | ( StrStr ( Volume - > VolName , Custom - > Volume ) = = NULL ) ) ) {
2020-05-06 00:23:59 +02:00
DBG ( " skipped because volume does not match \n " ) ;
2019-09-03 11:58:42 +02:00
continue ;
}
// NOTE: Sothor - We dont care about legacy OS type // Check if the volume should be of certain os type
//if ((Custom->Type != 0) && (Volume->OSType != 0) && !OSTYPE_COMPARE(OSType, Volume->OSType)) {
// DBG("skipped because wrong type (%d != %d)\n", OSType, Volume->OSType);
// continue;
//}
//} else if ((Custom->Type != 0) && (Volume->OSType != 0) && !OSTYPE_COMPARE(OSType, Volume->OSType)) {
//DBG("skipped because wrong type (%d != %d)\n", OSType, Volume->OSType);
//continue;
}
2020-05-06 00:23:59 +02:00
2019-09-03 11:58:42 +02:00
// Check the volume is readable and the entry exists on the volume
if ( Volume - > RootDir = = NULL ) {
DBG ( " skipped because filesystem is not readable \n " ) ;
continue ;
}
2020-05-06 00:23:59 +02:00
/*
2019-09-03 11:58:42 +02:00
if ( StriCmp ( CustomPath , MACOSX_LOADER_PATH ) = = 0 & & FileExists ( Volume - > RootDir , L " \\ .IAPhysicalMedia " ) ) {
DBG ( " skipped standard macOS path because volume is 2nd stage Install Media \n " ) ;
continue ;
2020-05-06 00:23:59 +02:00
}
*/
2019-09-03 11:58:42 +02:00
Guid = FindGPTPartitionGuidInDevicePath ( Volume - > DevicePath ) ;
if ( FindCustomPath ) {
// Get the partition UUID and make sure it's lower case
if ( Guid = = NULL ) {
DBG ( " skipped because volume does not have partition uuid \n " ) ;
continue ;
}
2020-04-04 15:50:13 +02:00
snwprintf ( PartUUID , sizeof ( PartUUID ) , " %s " , strguid ( Guid ) ) ;
2019-09-03 11:58:42 +02:00
StrToLower ( PartUUID ) ;
2020-05-06 00:23:59 +02:00
// search for standard/nonstandard linux uefi paths, and all kernel scan options that != KERNEL_SCAN_ALL
if ( Custom - > Type = = OSTYPE_LIN | | Custom - > KernelScan ! = KERNEL_SCAN_ALL ) {
LinuxScan ( Volume , Custom - > KernelScan , Custom - > Type , & CustomPath , & Image ) ;
}
if ( Custom - > Type = = OSTYPE_LINEFI ) {
// Open the boot directory to determine linux loadoptions when found item, or kernels when KERNEL_SCAN_ALL
DirIterOpen ( Volume - > RootDir , LINUX_BOOT_PATH , Iter ) ;
2019-09-03 11:58:42 +02:00
}
2020-04-27 14:13:09 +02:00
} else if ( ! FileExists ( Volume - > RootDir , CustomPath ) ) {
2019-09-03 11:58:42 +02:00
DBG ( " skipped because path does not exist \n " ) ;
continue ;
}
// Change to custom image if needed
2020-04-03 22:00:42 +02:00
if ( Image . isEmpty ( ) & & Custom - > ImagePath ) {
Image . LoadXImage ( ThemeX . ThemeDir , Custom - > ImagePath ) ;
2020-04-13 00:28:01 +02:00
if ( Image . isEmpty ( ) ) {
2020-04-13 17:43:32 +02:00
Image . LoadXImage ( ThemeX . ThemeDir , L " os_ " _XSW + Custom - > ImagePath ) ;
2020-04-13 13:13:37 +02:00
if ( Image . isEmpty ( ) ) {
Image . LoadXImage ( SelfDir , Custom - > ImagePath ) ;
if ( Image . isEmpty ( ) ) {
Image . LoadXImage ( SelfRootDir , Custom - > ImagePath ) ;
if ( Image . isEmpty ( ) ) {
Image . LoadXImage ( Volume - > RootDir , Custom - > ImagePath ) ;
}
}
}
2020-04-13 00:28:01 +02:00
}
2020-04-03 22:00:42 +02:00
}
2019-09-03 11:58:42 +02:00
// Change to custom drive image if needed
2020-04-03 22:00:42 +02:00
if ( DriveImage . isEmpty ( ) & & Custom - > DriveImagePath ) {
2020-04-12 19:20:47 +02:00
DriveImage . LoadXImage ( ThemeX . ThemeDir , Custom - > DriveImagePath ) ;
2020-04-13 13:13:37 +02:00
if ( DriveImage . isEmpty ( ) ) {
DriveImage . LoadXImage ( SelfDir , Custom - > ImagePath ) ;
if ( DriveImage . isEmpty ( ) ) {
DriveImage . LoadXImage ( SelfRootDir , Custom - > ImagePath ) ;
if ( DriveImage . isEmpty ( ) ) {
DriveImage . LoadXImage ( Volume - > RootDir , Custom - > ImagePath ) ;
}
}
}
2020-04-03 22:00:42 +02:00
}
2020-05-06 00:23:59 +02:00
do { // when not scanning for kernels, this loop will execute only once
2020-04-26 15:07:30 +02:00
XStringArray CustomOptions = Custom - > LoadOptions ;
2020-05-06 00:23:59 +02:00
// for LINEFI with option KERNEL_SCAN_ALL, use this loop to search for kernels
if ( FindCustomPath & & Custom - > Type = = OSTYPE_LINEFI & & Custom - > KernelScan = = KERNEL_SCAN_ALL ) {
2019-09-03 11:58:42 +02:00
EFI_FILE_INFO * FileInfo = NULL ;
// Get the next kernel path or stop looking
if ( ! DirIterNext ( Iter , 2 , LINUX_LOADER_SEARCH_PATH , & FileInfo ) | | ( FileInfo = = NULL ) ) {
DBG ( " \n " ) ;
break ;
}
// who knows....
if ( FileInfo - > FileSize = = 0 ) {
continue ;
}
// get the kernel file path
2020-04-27 11:50:49 +02:00
CustomPath . SWPrintf ( " %ls \\ %ls " , LINUX_BOOT_PATH , FileInfo - > FileName ) ;
2019-09-03 11:58:42 +02:00
}
2020-04-27 11:50:49 +02:00
if ( CustomPath . isEmpty ( ) ) {
2019-09-03 11:58:42 +02:00
DBG ( " skipped \n " ) ;
break ;
}
2020-05-06 00:23:59 +02:00
// Check to make sure if we should update linux custom options or not
if ( FindCustomPath & & Custom - > Type = = OSTYPE_LINEFI & & OSFLAG_ISUNSET ( Custom - > Flags , OSFLAG_NODEFAULTARGS ) ) {
2019-09-03 11:58:42 +02:00
// Find the init ram image and select root
2020-04-27 11:50:49 +02:00
CustomOptions = LinuxKernelOptions ( Iter - > DirHandle , Basename ( CustomPath . wc_str ( ) ) + LINUX_LOADER_PATH . length ( ) , PartUUID , Custom - > LoadOptions ) ;
2020-05-10 22:31:35 +02:00
Custom - > Flags = OSFLAG_SET ( Custom - > Flags , OSFLAG_NODEFAULTARGS ) ;
2019-09-03 11:58:42 +02:00
}
2020-05-06 00:23:59 +02:00
2019-09-03 11:58:42 +02:00
// Check to make sure that this entry is not hidden or disabled by another custom entry
if ( ! IsSubEntry ) {
CUSTOM_LOADER_ENTRY * Ptr ;
UINTN i = 0 ;
BOOLEAN BetterMatch = FALSE ;
for ( Ptr = gSettings . CustomEntries ; Ptr ! = NULL ; + + i , Ptr = Ptr - > Next ) {
// Don't match against this custom
if ( Ptr = = Custom ) {
continue ;
}
// Can only match the same types
if ( Custom - > Type ! = Ptr - > Type ) {
continue ;
}
// Check if the volume string matches
if ( Custom - > Volume ! = Ptr - > Volume ) {
if ( Ptr - > Volume = = NULL ) {
// Less precise volume match
if ( Custom - > Path ! = Ptr - > Path ) {
// Better path match
2020-04-27 11:50:49 +02:00
BetterMatch = ( ( Ptr - > Path . notEmpty ( ) ) & & CustomPath . equal ( Ptr - > Path ) & &
2019-09-03 11:58:42 +02:00
( ( Custom - > VolumeType = = Ptr - > VolumeType ) | |
2020-04-23 11:08:10 +02:00
( ( 1ull < < Volume - > DiskKind ) & Custom - > VolumeType ) ! = 0 ) ) ;
2019-09-03 11:58:42 +02:00
}
} else if ( ( StrStr ( Volume - > DevicePathString , Custom - > Volume ) = = NULL ) & &
( ( Volume - > VolName = = NULL ) | | ( StrStr ( Volume - > VolName , Custom - > Volume ) = = NULL ) ) ) {
if ( Custom - > Volume = = NULL ) {
// More precise volume match
if ( Custom - > Path ! = Ptr - > Path ) {
// Better path match
2020-04-27 11:50:49 +02:00
BetterMatch = ( ( Ptr - > Path . notEmpty ( ) ) & & CustomPath . equal ( Ptr - > Path ) & &
2019-09-03 11:58:42 +02:00
( ( Custom - > VolumeType = = Ptr - > VolumeType ) | |
2020-04-23 11:08:10 +02:00
( ( 1ull < < Volume - > DiskKind ) & Custom - > VolumeType ) ! = 0 ) ) ;
2019-09-03 11:58:42 +02:00
} else if ( Custom - > VolumeType ! = Ptr - > VolumeType ) {
// More precise volume type match
BetterMatch = ( ( Custom - > VolumeType = = 0 ) & &
2020-04-23 11:08:10 +02:00
( ( 1ull < < Volume - > DiskKind ) & Custom - > VolumeType ) ! = 0 ) ;
2019-09-03 11:58:42 +02:00
} else {
// Better match
BetterMatch = TRUE ;
}
// Duplicate volume match
} else if ( Custom - > Path ! = Ptr - > Path ) {
// Better path match
2020-04-27 11:50:49 +02:00
BetterMatch = ( ( Ptr - > Path . notEmpty ( ) ) & & CustomPath . equal ( Ptr - > Path ) & &
2019-09-03 11:58:42 +02:00
( ( Custom - > VolumeType = = Ptr - > VolumeType ) | |
2020-04-23 11:08:10 +02:00
( ( 1ull < < Volume - > DiskKind ) & Custom - > VolumeType ) ! = 0 ) ) ;
2019-09-03 11:58:42 +02:00
// Duplicate path match
} else if ( Custom - > VolumeType ! = Ptr - > VolumeType ) {
// More precise volume type match
BetterMatch = ( ( Custom - > VolumeType = = 0 ) & &
2020-04-23 11:08:10 +02:00
( ( 1ull < < Volume - > DiskKind ) & Custom - > VolumeType ) ! = 0 ) ;
2019-09-03 11:58:42 +02:00
} else {
// Duplicate entry
BetterMatch = ( i < = CustomIndex ) ;
}
}
// Duplicate volume match
} else if ( Custom - > Path ! = Ptr - > Path ) {
2020-04-27 11:50:49 +02:00
if ( Ptr - > Path . isEmpty ( ) ) {
2019-09-03 11:58:42 +02:00
// Less precise path match
BetterMatch = ( ( Custom - > VolumeType ! = Ptr - > VolumeType ) & &
2020-04-23 11:08:10 +02:00
( ( 1ull < < Volume - > DiskKind ) & Custom - > VolumeType ) ! = 0 ) ;
2020-04-27 11:50:49 +02:00
} else if ( CustomPath . equal ( Ptr - > Path ) ) {
if ( Custom - > Path . isEmpty ( ) ) {
2019-09-03 11:58:42 +02:00
// More precise path and volume type match
BetterMatch = ( ( Custom - > VolumeType = = Ptr - > VolumeType ) | |
2020-04-23 11:08:10 +02:00
( ( 1ull < < Volume - > DiskKind ) & Custom - > VolumeType ) ! = 0 ) ;
2019-09-03 11:58:42 +02:00
} else if ( Custom - > VolumeType ! = Ptr - > VolumeType ) {
// More precise volume type match
BetterMatch = ( ( Custom - > VolumeType = = 0 ) & &
2020-04-23 11:08:10 +02:00
( ( 1ull < < Volume - > DiskKind ) & Custom - > VolumeType ) ! = 0 ) ;
2019-09-03 11:58:42 +02:00
} else {
// Duplicate entry
BetterMatch = ( i < = CustomIndex ) ;
}
}
// Duplicate path match
} else if ( Custom - > VolumeType ! = Ptr - > VolumeType ) {
// More precise volume type match
BetterMatch = ( ( Custom - > VolumeType = = 0 ) & &
2020-04-23 11:08:10 +02:00
( ( 1ull < < Volume - > DiskKind ) & Custom - > VolumeType ) ! = 0 ) ;
2019-09-03 11:58:42 +02:00
} else {
// Duplicate entry
BetterMatch = ( i < = CustomIndex ) ;
}
if ( BetterMatch ) {
break ;
}
}
if ( BetterMatch ) {
2020-05-06 00:23:59 +02:00
DBG ( " skipped because custom entry %llu is a better match and will produce a duplicate entry \n " , i ) ;
2019-09-03 11:58:42 +02:00
continue ;
}
}
2020-05-06 00:23:59 +02:00
2019-09-03 11:58:42 +02:00
DBG ( " match! \n " ) ;
// Create an entry for this volume
2020-04-12 17:36:40 +02:00
Entry = CreateLoaderEntry ( CustomPath , CustomOptions , Custom - > FullTitle , Custom - > Title , Volume ,
( Image . isEmpty ( ) ? NULL : & Image ) , ( DriveImage . isEmpty ( ) ? NULL : & DriveImage ) ,
Custom - > Type , Custom - > Flags , Custom - > Hotkey , Custom - > BootBgColor , Custom - > CustomBoot , & Custom - > CustomLogo ,
/*(KERNEL_AND_KEXT_PATCHES *)(((UINTN)Custom) + OFFSET_OF(CUSTOM_LOADER_ENTRY, KernelAndKextPatches))*/ NULL , TRUE ) ;
2019-09-03 11:58:42 +02:00
if ( Entry ! = NULL ) {
2020-05-06 00:23:59 +02:00
DBG ( " Custom settings: %ls.plist will %s be applied \n " , Custom - > Settings , Custom - > CommonSettings ? " not " : " " ) ;
2019-09-03 11:58:42 +02:00
if ( ! Custom - > CommonSettings ) {
Entry - > Settings = Custom - > Settings ;
}
if ( OSFLAG_ISUNSET ( Custom - > Flags , OSFLAG_NODEFAULTMENU ) ) {
2020-05-16 22:07:27 +02:00
Entry - > AddDefaultMenu ( ) ;
2019-09-03 11:58:42 +02:00
} else if ( Custom - > SubEntries ! = NULL ) {
UINTN CustomSubIndex = 0 ;
// Add subscreen
2020-03-04 07:21:43 +01:00
// REFIT_MENU_SCREEN *SubScreen = (__typeof__(SubScreen))AllocateZeroPool(sizeof(REFIT_MENU_SCREEN));
REFIT_MENU_SCREEN * SubScreen = new REFIT_MENU_SCREEN ;
2019-09-03 11:58:42 +02:00
if ( SubScreen ) {
2020-04-27 11:50:49 +02:00
SubScreen - > Title . SWPrintf ( " Boot Options for %ls on %ls " , ( Custom - > Title . notEmpty ( ) ) ? Custom - > Title . wc_str ( ) : CustomPath . wc_str ( ) , Entry - > VolName ) ;
2020-05-16 21:30:29 +02:00
SubScreen - > TitleImage = Entry - > Image ;
2019-09-03 11:58:42 +02:00
SubScreen - > ID = Custom - > Type + 20 ;
2020-04-15 18:30:39 +02:00
SubScreen - > GetAnime ( ) ;
2019-09-03 11:58:42 +02:00
VolumeSize = RShiftU64 ( MultU64x32 ( Volume - > BlockIO - > Media - > LastBlock , Volume - > BlockIO - > Media - > BlockSize ) , 20 ) ;
2020-04-04 18:22:07 +02:00
SubScreen - > AddMenuInfoLine_f ( " Volume size: %lldMb " , VolumeSize ) ;
SubScreen - > AddMenuInfoLine_f ( " %ls " , FileDevicePathToStr ( Entry - > DevicePath ) ) ;
2019-09-03 11:58:42 +02:00
if ( Guid ) {
2020-04-04 18:22:07 +02:00
SubScreen - > AddMenuInfoLine_f ( " UUID: %s " , strguid ( Guid ) ) ;
2019-09-03 11:58:42 +02:00
}
2020-04-30 08:22:26 +02:00
SubScreen - > AddMenuInfoLine_f ( " Options: %s " , Entry - > LoadOptions . ConcatAll ( " " _XS8 ) . c_str ( ) ) ;
2019-09-03 11:58:42 +02:00
DBG ( " Create sub entries \n " ) ;
for ( CustomSubEntry = Custom - > SubEntries ; CustomSubEntry ; CustomSubEntry = CustomSubEntry - > Next ) {
if ( ! CustomSubEntry - > Settings ) {
CustomSubEntry - > Settings = Custom - > Settings ;
}
2020-04-27 11:50:49 +02:00
AddCustomEntry ( CustomSubIndex + + , ( CustomSubEntry - > Path . notEmpty ( ) ) ? CustomSubEntry - > Path : CustomPath , CustomSubEntry , SubScreen ) ;
2019-09-03 11:58:42 +02:00
}
2020-03-03 21:44:07 +01:00
SubScreen - > AddMenuEntry ( & MenuEntryReturn , true ) ;
2020-02-28 21:28:33 +01:00
Entry - > SubScreen = SubScreen ;
2019-09-03 11:58:42 +02:00
}
}
2020-03-03 21:44:07 +01:00
if ( IsSubEntry )
SubMenu - > AddMenuEntry ( Entry , true ) ;
else
MainMenu . AddMenuEntry ( Entry , true ) ;
2019-09-03 11:58:42 +02:00
}
2020-05-06 00:23:59 +02:00
} while ( FindCustomPath & & Custom - > Type = = OSTYPE_LINEFI & & Custom - > KernelScan = = KERNEL_SCAN_ALL ) ; // repeat loop only for kernel scanning
2019-09-03 11:58:42 +02:00
// Close the kernel boot directory
2020-05-06 00:23:59 +02:00
if ( FindCustomPath & & Custom - > Type = = OSTYPE_LINEFI ) {
2019-09-03 11:58:42 +02:00
DirIterClose ( Iter ) ;
}
}
2020-05-06 00:23:59 +02:00
2019-09-03 11:58:42 +02:00
}
// Add custom entries
VOID AddCustomEntries ( VOID )
{
CUSTOM_LOADER_ENTRY * Custom ;
UINTN i = 0 ;
if ( ! gSettings . CustomEntries ) {
return ;
}
//DBG("Custom entries start\n");
DbgHeader ( " AddCustomEntries " ) ;
// Traverse the custom entries
for ( Custom = gSettings . CustomEntries ; Custom ; + + i , Custom = Custom - > Next ) {
2020-04-27 11:50:49 +02:00
if ( ( Custom - > Path . isEmpty ( ) ) & & ( Custom - > Type ! = 0 ) ) {
2019-09-03 11:58:42 +02:00
if ( OSTYPE_IS_OSX ( Custom - > Type ) ) {
AddCustomEntry ( i , MACOSX_LOADER_PATH , Custom , NULL ) ;
} else if ( OSTYPE_IS_OSX_RECOVERY ( Custom - > Type ) ) {
2020-04-27 11:50:49 +02:00
AddCustomEntry ( i , L " \\ com.apple.recovery.boot \\ boot.efi " _XSW , Custom , NULL ) ;
2019-09-03 11:58:42 +02:00
} else if ( OSTYPE_IS_OSX_INSTALLER ( Custom - > Type ) ) {
UINTN Index = 0 ;
while ( Index < OSXInstallerPathsCount ) {
AddCustomEntry ( i , OSXInstallerPaths [ Index + + ] , Custom , NULL ) ;
}
} else if ( OSTYPE_IS_WINDOWS ( Custom - > Type ) ) {
2020-04-27 11:50:49 +02:00
AddCustomEntry ( i , L " \\ EFI \\ Microsoft \\ Boot \\ bootmgfw.efi " _XSW , Custom , NULL ) ;
2019-09-03 11:58:42 +02:00
} else if ( OSTYPE_IS_LINUX ( Custom - > Type ) ) {
# if defined(ANDX86)
2020-05-06 00:37:43 +02:00
for ( UINTN Index = 0 ; Index < AndroidEntryDataCount ; + + Index ) {
AddCustomEntry ( i , AndroidEntryData [ Index ] . Path , Custom , NULL ) ;
2019-09-03 11:58:42 +02:00
}
# endif
2020-05-06 00:23:59 +02:00
AddCustomEntry ( i , NullXStringW , Custom , NULL ) ;
2019-09-03 11:58:42 +02:00
} else if ( Custom - > Type = = OSTYPE_LINEFI ) {
2020-04-27 11:50:49 +02:00
AddCustomEntry ( i , NullXStringW , Custom , NULL ) ;
2019-09-03 11:58:42 +02:00
} else {
AddCustomEntry ( i , BOOT_LOADER_PATH , Custom , NULL ) ;
}
} else {
AddCustomEntry ( i , Custom - > Path , Custom , NULL ) ;
}
}
//DBG("Custom entries finish\n");
}