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 .
*/
2021-02-06 18:16:46 +01:00
# include <Platform.h>
# include "../refit/lib.h"
# include "../libeg/libeg.h"
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-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"
2021-03-22 13:40:01 +01:00
# include "../gui/REFIT_MAINMENU_SCREEN.h"
2021-04-28 20:30:34 +02:00
# include "../Settings/Self.h"
2021-02-06 18:16:46 +01:00
# include "../include/OSTypes.h"
2020-12-01 20:09:30 +01:00
# include "../Platform/BootOptions.h"
2021-02-04 15:04:31 +01:00
# include "../Platform/Volumes.h"
2021-02-06 18:16:46 +01:00
# include "../include/OSFlags.h"
# include "../libeg/XTheme.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-08-11 08:00:19 +02:00
const XString8Array LINUX_DEFAULT_OPTIONS = Split < XString8Array > ( " 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 ;
2021-02-06 18:16:46 +01: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" },
2021-02-06 18:16:46 +01:00
{ L " \\ EFI \\ Gentoo \\ kernelx64.efi " _XSW , L " Gentoo EFI kernel " _XSW , L " gentoo,linux " _XSW , " " _XS8 } ,
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
2021-02-06 18:16:46 +01:00
{ L " \\ EFI \\ SuSe \\ elilo.efi " _XSW , L " OpenSuse EFI boot menu " _XSW , L " suse,linux " _XSW , " " _XS8 } ,
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
2020-06-24 06:20:45 +02:00
L " \\ macOS Install Data \\ Locked Files \\ Boot Files \\ boot.efi " _XSW , // 10.12.4-10.15
L " \\ macOS Install Data \\ Locked Files \\ boot.efi " _XSW // 10.16+
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 ;
}
2021-04-11 07:18:52 +02:00
if ( Path . isEqualIC ( MACOSX_LOADER_PATH ) ) {
2019-09-03 11:58:42 +02:00
return OSTYPE_OSX ;
2021-04-11 07:18:52 +02:00
} else if ( Path . isEqualIC ( OSXInstallerPaths [ 0 ] ) | |
( Path . isEqualIC ( OSXInstallerPaths [ 1 ] ) ) | |
( Path . isEqualIC ( OSXInstallerPaths [ 2 ] ) ) | |
( Path . isEqualIC ( OSXInstallerPaths [ 3 ] ) ) | |
( Path . isEqualIC ( OSXInstallerPaths [ 4 ] ) ) | |
2022-01-25 18:07:33 +01:00
( Path . isEqualIC ( RockBoot ) ) | | ( Path . isEqualIC ( PaperBoot ) ) | | ( Path . isEqualIC ( ScissorBoot ) ) /* ||
( ! Path . isEqualIC ( L " \\ .IABootFiles \\ boot.efi " ) & &
Path . isEqualIC ( L " \\ .IAPhysicalMedia " ) ) */ //what is it???
2019-09-03 11:58:42 +02:00
) {
return OSTYPE_OSX_INSTALLER ;
2021-04-11 07:18:52 +02:00
} else if ( Path . isEqualIC ( L " \\ com.apple.recovery.boot \\ boot.efi " ) ) {
2019-09-03 11:58:42 +02:00
return OSTYPE_RECOVERY ;
2021-04-11 07:18:52 +02:00
} else if ( ( Path . isEqualIC ( L " \\ EFI \\ Microsoft \\ Boot \\ bootmgfw-orig.efi " ) ) | | //test first as orig
( Path . isEqualIC ( L " \\ EFI \\ Microsoft \\ Boot \\ bootmgfw.efi " ) ) | | //it can be Clover
// ( Path.isEqualIC(L"\\bootmgr.efi")) || //never worked, just extra icon in menu
( Path . isEqualIC ( L " \\ EFI \\ MICROSOFT \\ BOOT \\ cdboot.efi " ) ) ) {
2019-09-03 11:58:42 +02:00
return OSTYPE_WINEFI ;
2021-04-11 07:18:52 +02:00
} else if ( LINUX_FULL_LOADER_PATH . isEqualIC ( 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 ) {
2021-04-11 07:18:52 +02:00
if ( Path . isEqualIC ( AndroidEntryData [ Index ] . Path ) ) {
2019-09-03 11:58:42 +02:00
return OSTYPE_LIN ;
}
+ + Index ;
}
# endif
Index = 0 ;
while ( Index < LinuxEntryDataCount ) {
2021-04-11 07:18:52 +02:00
if ( Path . isEqualIC ( 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 ,
2020-10-03 19:02:31 +02:00
const EFI_FILE_PROTOCOL * RootDir )
2019-09-03 11:58:42 +02:00
{
UINTN Index ;
# if defined(ANDX86)
Index = 0 ;
while ( Index < AndroidEntryDataCount ) {
2021-04-11 07:18:52 +02:00
if ( Path . isEqualIC ( 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 ) {
2021-04-11 07:18:52 +02:00
if ( Path . isEqualIC ( 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
2021-04-11 07:18:52 +02:00
if ( ( RootDir ! = NULL ) & & LINUX_FULL_LOADER_PATH . isEqualIC ( 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-10-03 19:02:31 +02:00
STATIC XString8Array LinuxKernelOptions ( const EFI_FILE_PROTOCOL * Dir ,
2020-02-17 21:41:09 +01:00
IN CONST CHAR16 * Version ,
IN CONST CHAR16 * PartUUID ,
2020-08-11 08:00:19 +02:00
IN CONST XString8Array & 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-08-11 08:00:19 +02:00
XString8Array CustomOptions ;
CustomOptions . Add ( S8Printf ( " root=/dev/disk/by-partuuid/%ls " , PartUUID ) ) ;
CustomOptions . Add ( S8Printf ( " initrd=%ls \\ %ls " , LINUX_BOOT_ALT_PATH , InitRd . wc_str ( ) ) ) ;
2020-05-12 08:01:46 +02:00
CustomOptions . import ( LINUX_DEFAULT_OPTIONS ) ;
CustomOptions . import ( Options ) ;
2019-09-03 11:58:42 +02:00
return CustomOptions ;
}
}
}
2020-08-11 08:00:19 +02:00
XString8Array CustomOptions ;
CustomOptions . Add ( S8Printf ( " root=/dev/disk/by-partuuid/%ls " , PartUUID ) ) ;
2020-04-26 15:07:30 +02:00
CustomOptions . import ( LINUX_DEFAULT_OPTIONS ) ;
CustomOptions . import ( Options ) ;
return CustomOptions ;
2019-09-03 11:58:42 +02:00
}
2021-09-28 10:28:45 +02:00
STATIC XBool isFirstRootUUID ( REFIT_VOLUME * Volume )
2019-09-03 11:58:42 +02:00
{
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 )
2021-09-28 10:28:45 +02:00
return true ;
2019-09-03 11:58:42 +02:00
2022-04-26 00:55:56 +02:00
if ( scanedVolume - > RootUUID = = Volume - > RootUUID )
2021-09-28 10:28:45 +02:00
return false ;
2019-09-03 11:58:42 +02:00
}
2021-09-28 10:28:45 +02:00
return true ;
2019-09-03 11:58:42 +02:00
}
//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 ;
UINTN fileLen = 0 ;
if ( FileExists ( Entry - > Volume - > RootDir , targetNameFile ) ) {
Status = egLoadFile ( Entry - > Volume - > RootDir , targetNameFile , ( UINT8 * * ) & fileBuffer , & fileLen ) ;
if ( ! EFI_ERROR ( Status ) ) {
2020-08-09 17:55:30 +02:00
// CHAR16 *tmpName;
2019-09-03 11:58:42 +02:00
//Create null terminated string
2020-08-09 17:55:30 +02:00
// targetString = (CHAR8*) A_llocateZeroPool(fileLen+1);
2020-10-03 19:02:31 +02:00
// CopyMem( (void*)targetString, (void*)fileBuffer, fileLen);
2020-08-09 17:55:30 +02: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;
// }
// }
2020-08-09 17:55:30 +02:00
// //Convert to Unicode
// tmpName = (CHAR16*)A_llocateZeroPool((fileLen+1)*2);
// AsciiStrToUnicodeStrS(targetString, tmpName, fileLen);
2019-09-03 11:58:42 +02:00
2020-08-27 20:47:56 +02:00
Entry - > DisplayedVolName . strncpy ( fileBuffer , fileLen ) ;
DBG ( " Created name:%ls \n " , Entry - > DisplayedVolName . wc_str ( ) ) ;
2019-09-03 11:58:42 +02:00
FreePool ( fileBuffer ) ;
}
}
return Status ;
}
2020-10-22 15:55:30 +02:00
2021-04-28 20:30:34 +02:00
2022-04-26 00:55:56 +02:00
MacOsVersion GetOSVersion ( int LoaderType , const EFI_GUID & APFSTargetUUID , const REFIT_VOLUME * Volume , XString8 * BuildVersionPtr )
2021-04-28 20:30:34 +02:00
{
XString8 OSVersion ;
XString8 BuildVersion ;
EFI_STATUS Status = EFI_NOT_FOUND ;
2023-11-07 11:02:22 +01:00
UINT8 * PlistBuffer = NULL ;
2021-04-28 20:30:34 +02:00
UINTN PlistLen ;
TagDict * Dict = NULL ;
const TagDict * DictPointer = NULL ;
const TagStruct * Prop = NULL ;
if ( ! Volume ) {
return NullXString8 ;
}
if ( OSTYPE_IS_OSX ( LoaderType ) )
{
XString8 uuidPrefix ;
2022-04-26 00:55:56 +02:00
if ( APFSTargetUUID . notNull ( ) ) uuidPrefix = S8Printf ( " \\ %s " , APFSTargetUUID . toXString8 ( ) . c_str ( ) ) ;
2021-04-28 20:30:34 +02:00
XStringW plist = SWPrintf ( " %s \\ System \\ Library \\ CoreServices \\ SystemVersion.plist " , uuidPrefix . c_str ( ) ) ;
if ( ! FileExists ( Volume - > RootDir , plist ) ) {
plist = SWPrintf ( " %s \\ System \\ Library \\ CoreServices \\ ServerVersion.plist " , uuidPrefix . c_str ( ) ) ;
if ( ! FileExists ( Volume - > RootDir , plist ) ) {
plist . setEmpty ( ) ;
}
}
if ( plist . notEmpty ( ) ) { // found macOS System
2023-11-07 11:02:22 +01:00
Status = egLoadFile ( Volume - > RootDir , plist . wc_str ( ) , & PlistBuffer , & PlistLen ) ;
2021-04-28 20:30:34 +02:00
if ( ! EFI_ERROR ( Status ) & & PlistBuffer ! = NULL & & ParseXML ( PlistBuffer , & Dict , 0 ) = = EFI_SUCCESS ) {
Prop = Dict - > propertyForKey ( " ProductVersion " ) ;
if ( Prop ! = NULL ) {
if ( ! Prop - > isString ( ) ) {
MsgLog ( " ATTENTION : property not string in ProductVersion \n " ) ;
} else {
if ( Prop - > getString ( ) - > stringValue ( ) . notEmpty ( ) ) {
OSVersion = Prop - > getString ( ) - > stringValue ( ) ;
}
}
}
Prop = Dict - > propertyForKey ( " ProductBuildVersion " ) ;
if ( Prop ! = NULL ) {
if ( ! Prop - > isString ( ) ) {
MsgLog ( " ATTENTION : property not string in ProductBuildVersion \n " ) ;
} else {
if ( Prop - > getString ( ) - > stringValue ( ) . notEmpty ( ) ) {
BuildVersion = Prop - > getString ( ) - > stringValue ( ) ;
}
}
}
2023-11-18 11:04:54 +01:00
Dict - > ReleaseTag ( ) ;
2021-04-28 20:30:34 +02:00
}
}
}
if ( OSTYPE_IS_OSX_INSTALLER ( LoaderType ) ) {
// Detect exact version for 2nd stage Installer (thanks to dmazar for this idea)
// This should work for most installer cases. Rest cases will be read from boot.efi before booting.
// Reworked by Sherlocks. 2018.04.12
// 1st stage - 1
// Check for plist - createinstallmedia/BaseSystem/InstallDVD/InstallESD
XStringW InstallerPlist ;
2022-04-26 00:55:56 +02:00
if ( APFSTargetUUID . notNull ( ) ) {
InstallerPlist = SWPrintf ( " %s \\ System \\ Library \\ CoreServices \\ SystemVersion.plist " , APFSTargetUUID . toXString8 ( ) . c_str ( ) ) ;
2021-04-28 20:30:34 +02:00
if ( ! FileExists ( Volume - > RootDir , InstallerPlist ) ) InstallerPlist . setEmpty ( ) ;
}
if ( InstallerPlist . isEmpty ( ) ) {
InstallerPlist = SWPrintf ( " \\ .IABootFilesSystemVersion.plist " ) ; // 10.9 - 10.13.3
if ( ! FileExists ( Volume - > RootDir , InstallerPlist ) & & FileExists ( Volume - > RootDir , L " \\ System \\ Library \\ CoreServices \\ boot.efi " ) & &
( ( FileExists ( Volume - > RootDir , L " \\ BaseSystem.dmg " ) & & FileExists ( Volume - > RootDir , L " \\ mach_kernel " ) ) | | // 10.7/10.8
FileExists ( Volume - > RootDir , L " \\ System \\ Installation \\ CDIS \\ Mac OS X Installer.app " ) | | // 10.6/10.7
FileExists ( Volume - > RootDir , L " \\ System \\ Installation \\ CDIS \\ OS X Installer.app " ) | | // 10.8 - 10.11
FileExists ( Volume - > RootDir , L " \\ System \\ Installation \\ CDIS \\ macOS Installer.app " ) | | // 10.12+
FileExists ( Volume - > RootDir , L " \\ .IAPhysicalMedia " ) ) ) { // 10.13.4+
InstallerPlist = SWPrintf ( " \\ System \\ Library \\ CoreServices \\ SystemVersion.plist " ) ;
}
}
if ( FileExists ( Volume - > RootDir , InstallerPlist ) ) {
2023-11-07 11:02:22 +01:00
Status = egLoadFile ( Volume - > RootDir , InstallerPlist . wc_str ( ) , & PlistBuffer , & PlistLen ) ;
2021-04-28 20:30:34 +02:00
if ( ! EFI_ERROR ( Status ) & & PlistBuffer ! = NULL & & ParseXML ( PlistBuffer , & Dict , 0 ) = = EFI_SUCCESS ) {
Prop = Dict - > propertyForKey ( " ProductVersion " ) ;
if ( Prop ! = NULL ) {
if ( ! Prop - > isString ( ) ) {
MsgLog ( " ATTENTION : property not string in ProductVersion \n " ) ;
} else {
if ( Prop - > getString ( ) - > stringValue ( ) . notEmpty ( ) ) {
OSVersion = Prop - > getString ( ) - > stringValue ( ) ;
}
}
}
Prop = Dict - > propertyForKey ( " ProductBuildVersion " ) ;
if ( Prop ! = NULL ) {
if ( ! Prop - > isString ( ) ) {
MsgLog ( " ATTENTION : property not string in ProductBuildVersion \n " ) ;
} else {
if ( Prop - > getString ( ) - > stringValue ( ) . notEmpty ( ) ) {
BuildVersion = Prop - > getString ( ) - > stringValue ( ) ;
}
}
}
2023-11-18 11:04:54 +01:00
Dict - > ReleaseTag ( ) ;
2021-04-28 20:30:34 +02:00
}
}
// if ( OSVersion.isEmpty() )
// {
// if ( FileExists(Volume->RootDir, SWPrintf("\\%ls\\com.apple.installer\\BridgeVersion.plist", APFSTargetUUID.wc_str()).wc_str()) ) {
// OSVersion = "11.0"_XS8;
// // TODO so far, is there is a BridgeVersion.plist, it's version 11.0. Has to be improved with next releases.
// }
// }
// 1st stage - 2
// Check for plist - createinstallmedia/NetInstall
if ( OSVersion . isEmpty ( ) ) {
InstallerPlist = SWPrintf ( " \\ .IABootFiles \\ com.apple.Boot.plist " ) ; // 10.9 - ...
if ( FileExists ( Volume - > RootDir , InstallerPlist ) ) {
2023-11-07 11:02:22 +01:00
Status = egLoadFile ( Volume - > RootDir , InstallerPlist . wc_str ( ) , & PlistBuffer , & PlistLen ) ;
2021-04-28 20:30:34 +02:00
if ( ! EFI_ERROR ( Status ) & & PlistBuffer ! = NULL & & ParseXML ( PlistBuffer , & Dict , 0 ) = = EFI_SUCCESS ) {
Prop = Dict - > propertyForKey ( " Kernel Flags " ) ;
if ( Prop ! = NULL ) {
if ( ! Prop - > isString ( ) ) {
MsgLog ( " ATTENTION : property not string in Kernel Flags \n " ) ;
} else {
2021-06-11 16:33:07 +02:00
if ( Prop - > getString ( ) - > stringValue ( ) . contains ( " Install%20macOS%20BigSur " ) | | Prop - > getString ( ) - > stringValue ( ) . contains ( " Install%20macOS%2011 " ) ) {
2021-04-28 20:30:34 +02:00
OSVersion = " 11 " _XS8 ;
2021-06-11 16:33:07 +02:00
} else if ( Prop - > getString ( ) - > stringValue ( ) . contains ( " Install%20macOS%20Monterey " ) | | Prop - > getString ( ) - > stringValue ( ) . contains ( " Install%20macOS%2012 " ) ) {
2021-06-09 19:49:30 +02:00
OSVersion = " 12 " _XS8 ;
2022-06-24 18:03:14 +02:00
} else if ( Prop - > getString ( ) - > stringValue ( ) . contains ( " Install%20macOS%20Ventura " ) | | Prop - > getString ( ) - > stringValue ( ) . contains ( " Install%20macOS%2013 " ) ) {
OSVersion = " 13 " _XS8 ;
2023-06-05 21:23:36 +02:00
} else if ( Prop - > getString ( ) - > stringValue ( ) . contains ( " Install%20macOS%20Sonoma " ) | | Prop - > getString ( ) - > stringValue ( ) . contains ( " Install%20macOS%2014 " ) ) {
OSVersion = " 14 " _XS8 ;
2021-04-28 20:30:34 +02:00
} else if ( Prop - > getString ( ) - > stringValue ( ) . contains ( " Install%20macOS%2010.16 " ) ) {
OSVersion = " 10.16 " _XS8 ;
} else if ( Prop - > getString ( ) - > stringValue ( ) . contains ( " Install%20macOS%20Catalina " ) | | Prop - > getString ( ) - > stringValue ( ) . contains ( " Install%20macOS%2010.15 " ) ) {
OSVersion = " 10.15 " _XS8 ;
} else if ( Prop - > getString ( ) - > stringValue ( ) . contains ( " Install%20macOS%20Mojave " ) | | Prop - > getString ( ) - > stringValue ( ) . contains ( " Install%20macOS%2010.14 " ) ) {
OSVersion = " 10.14 " _XS8 ;
} else if ( Prop - > getString ( ) - > stringValue ( ) . contains ( " Install%20macOS%20High%20Sierra " ) | | Prop - > getString ( ) - > stringValue ( ) . contains ( " Install%20macOS%2010.13 " ) ) {
OSVersion = " 10.13 " _XS8 ;
} else if ( Prop - > getString ( ) - > stringValue ( ) . contains ( " Install%20macOS%20Sierra " ) | | Prop - > getString ( ) - > stringValue ( ) . contains ( " Install%20OS%20hhX%2010.12 " ) ) {
OSVersion = " 10.12 " _XS8 ;
} else if ( Prop - > getString ( ) - > stringValue ( ) . contains ( " Install%20OS%20hhX%20El%20Capitan " ) | | Prop - > getString ( ) - > stringValue ( ) . contains ( " Install%20OS%20hhX%2010.11 " ) ) {
OSVersion = " 10.11 " _XS8 ;
} else if ( Prop - > getString ( ) - > stringValue ( ) . contains ( " Install%20OS%20hhX%20Yosemite " ) | | Prop - > getString ( ) - > stringValue ( ) . contains ( " Install%20OS%20hhX%2010.10 " ) ) {
OSVersion = " 10.10 " _XS8 ;
} else if ( Prop - > getString ( ) - > stringValue ( ) . contains ( " Install%20OS%20hhX%20Mavericks.app " ) ) {
OSVersion = " 10.9 " _XS8 ;
} else if ( Prop - > getString ( ) - > stringValue ( ) . contains ( " Install%20OS%20hhX%20Mountain%20Lion " ) ) {
OSVersion = " 10.8 " _XS8 ;
} else if ( Prop - > getString ( ) - > stringValue ( ) . contains ( " Install%20Mac%20OS%20hhX%20Lion " ) ) {
OSVersion = " 10.7 " _XS8 ;
}
}
}
}
}
}
// 2nd stage - 1
// Check for plist - AppStore/createinstallmedia/startosinstall/Fusion Drive
if ( OSVersion . isEmpty ( ) ) {
InstallerPlist = SWPrintf ( " \\ macOS Install Data \\ Locked Files \\ Boot Files \\ SystemVersion.plist " ) ; // 10.12.4+
if ( ! FileExists ( Volume - > RootDir , InstallerPlist ) ) {
InstallerPlist = SWPrintf ( " \\ macOS Install Data \\ InstallInfo.plist " ) ; // 10.12+
if ( ! FileExists ( Volume - > RootDir , InstallerPlist ) ) {
InstallerPlist = SWPrintf ( " \\ com.apple.boot.R \\ SystemVersion.plist) " ) ; // 10.12+
if ( ! FileExists ( Volume - > RootDir , InstallerPlist ) ) {
InstallerPlist = SWPrintf ( " \\ com.apple.boot.P \\ SystemVersion.plist " ) ; // 10.12+
if ( ! FileExists ( Volume - > RootDir , InstallerPlist ) ) {
InstallerPlist = SWPrintf ( " \\ com.apple.boot.S \\ SystemVersion.plist " ) ; // 10.12+
if ( ! FileExists ( Volume - > RootDir , InstallerPlist ) & &
( 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 " ) ) ) {
InstallerPlist = SWPrintf ( " \\ System \\ Library \\ CoreServices \\ SystemVersion.plist " ) ; // 10.11
}
}
}
}
}
if ( FileExists ( Volume - > RootDir , InstallerPlist ) ) {
2023-11-07 11:02:22 +01:00
Status = egLoadFile ( Volume - > RootDir , InstallerPlist . wc_str ( ) , & PlistBuffer , & PlistLen ) ;
2021-04-28 20:30:34 +02:00
if ( ! EFI_ERROR ( Status ) & & PlistBuffer ! = NULL & & ParseXML ( PlistBuffer , & Dict , 0 ) = = EFI_SUCCESS ) {
Prop = Dict - > propertyForKey ( " ProductVersion " ) ;
if ( Prop ! = NULL ) {
if ( ! Prop - > isString ( ) ) {
MsgLog ( " ATTENTION : property not string in ProductVersion \n " ) ;
} else {
if ( Prop - > getString ( ) - > stringValue ( ) . notEmpty ( ) ) {
OSVersion = Prop - > getString ( ) - > stringValue ( ) ;
}
}
}
Prop = Dict - > propertyForKey ( " ProductBuildVersion " ) ;
if ( Prop ! = NULL ) {
if ( ! Prop - > isString ( ) ) {
MsgLog ( " ATTENTION : property not string in ProductBuildVersion \n " ) ;
} else {
if ( Prop - > getString ( ) - > stringValue ( ) . notEmpty ( ) ) {
BuildVersion = Prop - > getString ( ) - > stringValue ( ) ;
}
}
}
// In InstallInfo.plist, there is no a version key only when updating from AppStore in 10.13+
// If use the startosinstall in 10.13+, this version key exists in InstallInfo.plist
DictPointer = Dict - > dictPropertyForKey ( " System Image Info " ) ; // 10.12+
if ( DictPointer ! = NULL ) {
Prop = DictPointer - > propertyForKey ( " version " ) ;
if ( Prop ! = NULL ) {
if ( ! Prop - > isString ( ) ) {
MsgLog ( " ATTENTION : property not string in version \n " ) ;
} else {
OSVersion = Prop - > getString ( ) - > stringValue ( ) ;
}
}
}
2023-11-18 11:04:54 +01:00
Dict - > ReleaseTag ( ) ;
2021-04-28 20:30:34 +02:00
}
}
}
// 2nd stage - 2
// Check for ia.log - InstallESD/createinstallmedia/startosinstall
// Implemented by Sherlocks
if ( OSVersion . isEmpty ( ) ) {
2023-11-11 15:57:02 +01:00
CONST CHAR8 * s ;
UINT8 * fileBuffer ;
2021-04-28 20:30:34 +02:00
// CHAR8 *Res5 = (__typeof__(Res5))AllocateZeroPool(5);
// CHAR8 *Res6 = (__typeof__(Res6))AllocateZeroPool(6);
// CHAR8 *Res7 = (__typeof__(Res7))AllocateZeroPool(7);
// CHAR8 *Res8 = (__typeof__(Res8))AllocateZeroPool(8);
UINTN fileLen = 0 ;
XStringW InstallerLog ;
InstallerLog = L " \\ Mac OS X Install Data \\ ia.log " _XSW ; // 10.7
if ( ! FileExists ( Volume - > RootDir , InstallerLog ) ) {
InstallerLog = L " \\ OS X Install Data \\ ia.log " _XSW ; // 10.8 - 10.11
if ( ! FileExists ( Volume - > RootDir , InstallerLog ) ) {
InstallerLog = L " \\ macOS Install Data \\ ia.log " _XSW ; // 10.12+
}
}
if ( FileExists ( Volume - > RootDir , InstallerLog ) ) {
2023-11-11 15:57:02 +01:00
Status = egLoadFile ( Volume - > RootDir , InstallerLog . wc_str ( ) , & fileBuffer , & fileLen ) ;
2021-04-28 20:30:34 +02:00
if ( ! EFI_ERROR ( Status ) ) {
XString8 targetString ;
2023-11-11 15:57:02 +01:00
targetString . strncpy ( ( CHAR8 * ) fileBuffer , fileLen ) ;
2021-04-28 20:30:34 +02:00
// s = SearchString(targetString, fileLen, "Running OS Build: Mac OS X ", 27);
s = AsciiStrStr ( targetString . c_str ( ) , " Running OS Build: Mac OS X " ) ;
if ( s [ 31 ] = = ' ' ) {
OSVersion . S8Printf ( " %c%c.%c \n " , s [ 27 ] , s [ 28 ] , s [ 30 ] ) ;
if ( s [ 38 ] = = ' ) ' ) {
BuildVersion . S8Printf ( " %c%c%c%c%c \n " , s [ 33 ] , s [ 34 ] , s [ 35 ] , s [ 36 ] , s [ 37 ] ) ;
} else if ( s [ 39 ] = = ' ) ' ) {
BuildVersion . S8Printf ( " %c%c%c%c%c%c \n " , s [ 33 ] , s [ 34 ] , s [ 35 ] , s [ 36 ] , s [ 37 ] , s [ 38 ] ) ;
}
} else if ( s [ 31 ] = = ' . ' ) {
OSVersion . S8Printf ( " %c%c.%c.%c \n " , s [ 27 ] , s [ 28 ] , s [ 30 ] , s [ 32 ] ) ;
if ( s [ 40 ] = = ' ) ' ) {
BuildVersion . S8Printf ( " %c%c%c%c%c \n " , s [ 35 ] , s [ 36 ] , s [ 37 ] , s [ 38 ] , s [ 39 ] ) ;
} else if ( s [ 41 ] = = ' ) ' ) {
BuildVersion . S8Printf ( " %c%c%c%c%c%c \n " , s [ 35 ] , s [ 36 ] , s [ 37 ] , s [ 38 ] , s [ 39 ] , s [ 40 ] ) ;
}
} else if ( s [ 32 ] = = ' ' ) {
OSVersion . S8Printf ( " %c%c.%c%c \n " , s [ 27 ] , s [ 28 ] , s [ 30 ] , s [ 31 ] ) ;
if ( s [ 39 ] = = ' ) ' ) {
BuildVersion . S8Printf ( " %c%c%c%c%c \n " , s [ 34 ] , s [ 35 ] , s [ 36 ] , s [ 37 ] , s [ 38 ] ) ;
} else if ( s [ 40 ] = = ' ) ' ) {
BuildVersion . S8Printf ( " %c%c%c%c%c%c \n " , s [ 34 ] , s [ 35 ] , s [ 36 ] , s [ 37 ] , s [ 38 ] , s [ 39 ] ) ;
} else if ( s [ 41 ] = = ' ) ' ) {
BuildVersion . S8Printf ( " %c%c%c%c%c%c%c \n " , s [ 34 ] , s [ 35 ] , s [ 36 ] , s [ 37 ] , s [ 38 ] , s [ 39 ] , s [ 40 ] ) ;
}
} else if ( s [ 32 ] = = ' . ' ) {
OSVersion . S8Printf ( " %c%c.%c%c.%c \n " , s [ 27 ] , s [ 28 ] , s [ 30 ] , s [ 31 ] , s [ 33 ] ) ;
if ( s [ 41 ] = = ' ) ' ) {
BuildVersion . S8Printf ( " %c%c%c%c%c \n " , s [ 36 ] , s [ 37 ] , s [ 38 ] , s [ 39 ] , s [ 40 ] ) ;
} else if ( s [ 42 ] = = ' ) ' ) {
BuildVersion . S8Printf ( " %c%c%c%c%c%c \n " , s [ 36 ] , s [ 37 ] , s [ 38 ] , s [ 39 ] , s [ 40 ] , s [ 41 ] ) ;
} else if ( s [ 43 ] = = ' ) ' ) {
BuildVersion . S8Printf ( " %c%c%c%c%c%c%c \n " , s [ 36 ] , s [ 37 ] , s [ 38 ] , s [ 39 ] , s [ 40 ] , s [ 41 ] , s [ 42 ] ) ;
}
}
FreePool ( fileBuffer ) ;
}
}
}
// 2nd stage - 3
// Check for plist - Preboot of APFS
if ( OSVersion . isEmpty ( ) )
{
XStringW plist = L " \\ macOS Install Data \\ Locked Files \\ Boot Files \\ SystemVersion.plist " _XSW ;
if ( ! FileExists ( Volume - > RootDir , plist ) ) {
plist . setEmpty ( ) ;
}
if ( plist . notEmpty ( ) ) { // found macOS System
2023-11-07 11:02:22 +01:00
Status = egLoadFile ( Volume - > RootDir , plist . wc_str ( ) , & PlistBuffer , & PlistLen ) ;
2021-04-28 20:30:34 +02:00
if ( ! EFI_ERROR ( Status ) & & PlistBuffer ! = NULL & & ParseXML ( PlistBuffer , & Dict , 0 ) = = EFI_SUCCESS ) {
Prop = Dict - > propertyForKey ( " ProductVersion " ) ;
if ( Prop ! = NULL ) {
if ( ! Prop - > isString ( ) ) {
MsgLog ( " ATTENTION : property not string in ProductVersion \n " ) ;
} else {
OSVersion = Prop - > getString ( ) - > stringValue ( ) ;
}
}
Prop = Dict - > propertyForKey ( " ProductBuildVersion " ) ;
if ( Prop ! = NULL ) {
if ( ! Prop - > isString ( ) ) {
MsgLog ( " ATTENTION : property not string in ProductBuildVersion \n " ) ;
} else {
BuildVersion = Prop - > getString ( ) - > stringValue ( ) ;
}
}
}
2023-11-18 11:04:54 +01:00
Dict - > ReleaseTag ( ) ;
2021-04-28 20:30:34 +02:00
}
}
}
if ( OSTYPE_IS_OSX_RECOVERY ( LoaderType ) ) {
XString8 uuidPrefix ;
2022-04-26 00:55:56 +02:00
if ( APFSTargetUUID . notNull ( ) ) uuidPrefix = S8Printf ( " \\ %s " , APFSTargetUUID . toXString8 ( ) . c_str ( ) ) ;
2021-04-28 20:30:34 +02:00
XStringW plist = SWPrintf ( " %s \\ SystemVersion.plist " , uuidPrefix . c_str ( ) ) ;
if ( ! FileExists ( Volume - > RootDir , plist ) ) {
plist = SWPrintf ( " %s \\ ServerVersion.plist " , uuidPrefix . c_str ( ) ) ;
if ( ! FileExists ( Volume - > RootDir , plist ) ) {
plist = L " \\ com.apple.recovery.boot \\ SystemVersion.plist " _XSW ;
if ( ! FileExists ( Volume - > RootDir , plist ) ) {
plist = L " \\ com.apple.recovery.boot \\ ServerVersion.plist " _XSW ;
if ( ! FileExists ( Volume - > RootDir , plist ) ) {
plist . setEmpty ( ) ;
}
}
}
}
// Detect exact version for OS X Recovery
if ( plist . notEmpty ( ) ) { // found macOS System
2023-11-07 11:02:22 +01:00
Status = egLoadFile ( Volume - > RootDir , plist . wc_str ( ) , & PlistBuffer , & PlistLen ) ;
2021-04-28 20:30:34 +02:00
if ( ! EFI_ERROR ( Status ) & & PlistBuffer ! = NULL & & ParseXML ( PlistBuffer , & Dict , 0 ) = = EFI_SUCCESS ) {
Prop = Dict - > propertyForKey ( " ProductVersion " ) ;
if ( Prop ! = NULL ) {
if ( ! Prop - > isString ( ) ) {
MsgLog ( " ATTENTION : property not string in ProductVersion \n " ) ;
} else {
OSVersion = Prop - > getString ( ) - > stringValue ( ) ;
}
}
Prop = Dict - > propertyForKey ( " ProductBuildVersion " ) ;
if ( Prop ! = NULL ) {
if ( ! Prop - > isString ( ) ) {
MsgLog ( " ATTENTION : property not string in ProductBuildVersion \n " ) ;
} else {
BuildVersion = Prop - > getString ( ) - > stringValue ( ) ;
}
}
}
2023-11-18 11:04:54 +01:00
Dict - > ReleaseTag ( ) ;
2021-04-28 20:30:34 +02:00
} else if ( FileExists ( Volume - > RootDir , L " \\ com.apple.recovery.boot \\ boot.efi " ) ) {
// Special case - com.apple.recovery.boot/boot.efi exists but SystemVersion.plist doesn't --> 10.9 recovery
OSVersion = " 10.9 " _XS8 ;
}
}
if ( PlistBuffer ! = NULL ) {
FreePool ( PlistBuffer ) ;
}
( * BuildVersionPtr ) . stealValueFrom ( & BuildVersion ) ;
return OSVersion ;
}
inline MacOsVersion GetOSVersion ( IN LOADER_ENTRY * Entry ) { return GetOSVersion ( Entry - > LoaderType , Entry - > APFSTargetUUID , Entry - > Volume , & Entry - > BuildVersion ) ; } ;
//constexpr XStringW iconMac = L"mac"_XSW;
CONST XStringW
GetOSIconName ( const MacOsVersion & OSVersion )
{
XStringW OSIconName ;
if ( OSVersion . isEmpty ( ) ) {
OSIconName = L " mac " _XSW ;
2023-06-10 08:30:00 +02:00
} else if ( OSVersion . elementAt ( 0 ) = = 14 ) {
2023-06-16 23:44:39 +02:00
// Sonoma
2023-06-10 08:30:00 +02:00
OSIconName = L " sonoma,mac " _XSW ;
2022-06-24 18:03:14 +02:00
} else if ( OSVersion . elementAt ( 0 ) = = 13 ) {
// Ventura
OSIconName = L " ventura,mac " _XSW ;
2021-06-09 19:49:30 +02:00
} else if ( OSVersion . elementAt ( 0 ) = = 12 ) {
// Monterey
OSIconName = L " monterey,mac " _XSW ;
2021-04-28 20:30:34 +02:00
} else if ( ( OSVersion . elementAt ( 0 ) = = 10 & & OSVersion . elementAt ( 1 ) = = 16 ) | |
( OSVersion . elementAt ( 0 ) = = 11 /*&& OSVersion.elementAt(1) == 0*/ )
) {
// Big Sur
OSIconName = L " bigsur,mac " _XSW ;
2021-06-09 19:49:30 +02:00
} else if ( OSVersion . elementAt ( 0 ) = = 10 ) {
2021-04-28 20:30:34 +02:00
if ( OSVersion . elementAt ( 1 ) = = 15 ) {
// Catalina
OSIconName = L " cata,mac " _XSW ;
} else if ( OSVersion . elementAt ( 1 ) = = 14 ) {
// Mojave
OSIconName = L " moja,mac " _XSW ;
} else if ( OSVersion . elementAt ( 1 ) = = 13 ) {
// High Sierra
OSIconName = L " hsierra,mac " _XSW ;
} else if ( OSVersion . elementAt ( 1 ) = = 12 ) {
// Sierra
OSIconName = L " sierra,mac " _XSW ;
} else if ( OSVersion . elementAt ( 1 ) = = 11 ) {
// El Capitan
OSIconName = L " cap,mac " _XSW ;
} else if ( OSVersion . elementAt ( 1 ) = = 10 ) {
// Yosemite
OSIconName = L " yos,mac " _XSW ;
} else if ( OSVersion . elementAt ( 1 ) = = 9 ) {
// Mavericks
OSIconName = L " mav,mac " _XSW ;
} else if ( OSVersion . elementAt ( 1 ) = = 8 ) {
// Mountain Lion
OSIconName = L " cougar,mac " _XSW ;
} else if ( OSVersion . elementAt ( 1 ) = = 7 ) {
// Lion
OSIconName = L " lion,mac " _XSW ;
} else if ( OSVersion . elementAt ( 1 ) = = 6 ) {
// Snow Leopard
OSIconName = L " snow,mac " _XSW ;
} else if ( OSVersion . elementAt ( 1 ) = = 5 ) {
// Leopard
OSIconName = L " leo,mac " _XSW ;
} else if ( OSVersion . elementAt ( 1 ) = = 4 ) {
// Tiger
OSIconName = L " tiger,mac " _XSW ;
} else {
OSIconName = L " mac " _XSW ;
}
} else {
OSIconName = L " mac " _XSW ;
}
return OSIconName ;
}
2020-04-27 11:50:49 +02:00
STATIC LOADER_ENTRY * CreateLoaderEntry ( IN CONST XStringW & LoaderPath ,
2020-08-11 08:00:19 +02:00
IN CONST XString8Array & LoaderOptions ,
2021-03-22 13:40:01 +01:00
IN CONST XString8 & FullTitle ,
IN CONST XString8 & 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 ,
2023-11-26 15:10:53 +01:00
IN wchar_t Hotkey ,
2020-04-01 14:57:32 +02:00
EFI_GRAPHICS_OUTPUT_BLT_PIXEL BootBgColor ,
IN UINT8 CustomBoot ,
2021-03-19 21:32:42 +01:00
IN const XImage & CustomLogo ,
2020-08-12 17:15:47 +02:00
IN const KERNEL_AND_KEXT_PATCHES * Patches ,
2021-09-28 10:28:45 +02:00
IN XBool CustomEntry )
2019-09-03 11:58:42 +02:00
{
2020-04-28 22:42:53 +02:00
EFI_DEVICE_PATH * LoaderDevicePath ;
2020-08-09 17:55:30 +02:00
XStringW LoaderDevicePathString ;
XStringW FilePathAsString ;
2023-11-26 15:10:53 +01:00
wchar_t ShortcutLetter ;
2020-04-03 22:00:42 +02:00
LOADER_ENTRY * Entry ;
2021-02-04 15:04:31 +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 ;
}
2020-08-09 17:55:30 +02:00
LoaderDevicePathString = FileDevicePathToXStringW ( LoaderDevicePath ) ;
if ( LoaderDevicePathString . isEmpty ( ) ) {
2019-09-03 11:58:42 +02:00
return NULL ;
}
// Ignore this loader if it's self path
2020-10-03 19:02:31 +02:00
XStringW selfDevicePathAsXStringW = FileDevicePathToXStringW ( & self . getSelfDevicePath ( ) ) ;
if ( selfDevicePathAsXStringW = = LoaderDevicePathString ) {
2021-02-04 15:04:31 +01:00
DBG ( " %sskipped because path `%ls` is self path! \n " , indent , LoaderDevicePathString . wc_str ( ) ) ;
2020-10-03 19:02:31 +02:00
return NULL ;
2019-09-03 11:58:42 +02:00
}
2023-06-16 23:44:39 +02:00
2020-08-15 22:39:25 +02:00
// prepare the menu entry
2021-05-05 19:10:10 +02:00
Entry = new LOADER_ENTRY ;
2020-08-15 22:39:25 +02:00
2019-09-03 11:58:42 +02:00
if ( ! CustomEntry ) {
// 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 ( ) ) {
2020-08-09 17:55:30 +02:00
if ( StriCmp ( MainEntry . getLOADER_ENTRY ( ) - > DevicePathString . wc_str ( ) , LoaderDevicePathString . wc_str ( ) ) = = 0 ) {
2021-02-04 15:04:31 +01:00
DBG ( " %sskipped because path `%ls` already exists for another entry! \n " , indent , LoaderDevicePathString . wc_str ( ) ) ;
2019-09-03 11:58:42 +02:00
return NULL ;
}
}
}
// If this isn't a custom entry make sure it's not hidden by a custom entry
2021-03-22 13:40:01 +01:00
for ( size_t CustomIndex = 0 ; CustomIndex < GlobalConfig . CustomEntries . size ( ) ; + + CustomIndex ) {
CUSTOM_LOADER_ENTRY & Custom = GlobalConfig . CustomEntries [ CustomIndex ] ;
if ( Custom . settings . Disabled ) continue ; // before, disabled entries settings weren't loaded.
2019-09-03 11:58:42 +02:00
// Check if the custom entry is hidden or disabled
2021-03-25 15:32:56 +01:00
if ( OSFLAG_ISSET ( Custom . getFlags ( gSettings . SystemParameters . NoCaches ) , OSFLAG_DISABLED ) | | Custom . settings . Hidden ) {
2019-09-03 11:58:42 +02:00
INTN volume_match = 0 ;
INTN volume_type_match = 0 ;
INTN path_match = 0 ;
INTN type_match = 0 ;
// Check if volume match
2021-03-22 13:40:01 +01:00
if ( Custom . settings . Volume . notEmpty ( ) ) {
2019-09-03 11:58:42 +02:00
// Check if the string matches the volume
volume_match =
2021-03-22 13:40:01 +01:00
( ( StrStr ( Volume - > DevicePathString . wc_str ( ) , Custom . settings . Volume . wc_str ( ) ) ! = NULL ) | |
( ( Volume - > VolName . notEmpty ( ) ) & & ( StrStr ( Volume - > VolName . wc_str ( ) , Custom . settings . Volume . wc_str ( ) ) ! = NULL ) ) ) ? 1 : - 1 ;
2019-09-03 11:58:42 +02:00
}
// Check if the volume_type match
2021-03-22 13:40:01 +01:00
if ( Custom . settings . VolumeType ! = 0 ) {
volume_type_match = ( ( ( 1ull < < Volume - > DiskKind ) & Custom . settings . VolumeType ) ! = 0 ) ? 1 : - 1 ;
2019-09-03 11:58:42 +02:00
}
// Check if the path match
2021-03-22 13:40:01 +01:00
if ( Custom . settings . Path . notEmpty ( ) ) {
2019-09-03 11:58:42 +02:00
// Check if the loader path match
2021-04-11 07:18:52 +02:00
path_match = ( Custom . settings . Path . isEqualIC ( LoaderPath ) ) ? 1 : - 1 ;
2019-09-03 11:58:42 +02:00
}
// Check if the type match
2021-03-22 13:40:01 +01:00
if ( Custom . settings . Type ! = 0 ) {
type_match = OSTYPE_COMPARE ( Custom . settings . Type , OSType ) ? 1 : - 1 ;
2019-09-03 11:58:42 +02:00
}
if ( volume_match = = - 1 | | volume_type_match = = - 1 | | path_match = = - 1 | | type_match = = - 1 ) {
UINTN add_comma = 0 ;
2021-03-19 21:32:42 +01:00
DBG ( " %sNot match custom entry %zu: " , 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
2021-03-19 21:32:42 +01:00
DBG ( " %sHidden because matching custom entry %zu! \n " , indent , CustomIndex ) ;
2020-08-15 22:39:25 +02:00
Entry - > Hidden = true ;
2019-09-03 11:58:42 +02:00
}
}
}
}
2020-02-28 21:28:33 +01:00
Entry - > Row = 0 ;
2019-09-03 11:58:42 +02:00
Entry - > Volume = Volume ;
2021-01-31 10:50:23 +01:00
if ( LoaderPath . length ( ) > = 38 ) {
if ( isPathSeparator ( LoaderPath [ 0 ] ) & & isPathSeparator ( LoaderPath [ 37 ] ) ) {
2022-04-26 00:55:56 +02:00
Entry - > APFSTargetUUID . takeValueFrom ( LoaderPath . subString ( 1 , 36 ) ) ; // if guid is not valid, APFSTargetUUID will be set to null
2021-01-31 10:50:23 +01:00
}
}
// Entry->APFSTargetUUID = APFSTargetUUID;
2019-09-03 11:58:42 +02:00
2020-04-27 11:50:49 +02:00
Entry - > LoaderPath = LoaderPath ;
2020-10-26 21:37:32 +01:00
Entry - > DisplayedVolName = Volume - > VolName ;
2019-09-03 11:58:42 +02:00
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 ) ) {
2020-08-07 15:17:30 +02:00
Entry - > LoadOptions = LoaderOptions ;
2020-04-26 15:07:30 +02:00
} else {
2021-02-02 10:02:21 +01:00
Entry - > LoadOptions = Split < XString8Array > ( gSettings . Boot . BootArgs , " " ) ;
2020-08-07 15:17:30 +02:00
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 ;
2021-03-19 21:32:42 +01:00
Entry - > CustomLogo = CustomLogo ; //could be an empty image
2020-04-11 14:34:59 +02:00
2019-09-03 11:58:42 +02:00
Entry - > LoaderType = OSType ;
2020-08-12 17:15:47 +02:00
Entry - > BuildVersion . setEmpty ( ) ;
2020-11-12 22:25:56 +01:00
# ifdef JIEF_DEBUG
if ( Entry - > LoaderPath . contains ( " com.apple.installer " ) ) {
DBG ( " %s " , " " ) ;
}
2022-04-26 00:55:56 +02:00
if ( Entry - > APFSTargetUUID . Data1 = = 0x99999999 ) {
2020-11-12 22:25:56 +01:00
DBG ( " %s " , " " ) ;
}
# endif
2021-01-31 10:50:23 +01:00
Entry - > macOSVersion = GetOSVersion ( Entry ) ;
2021-02-04 15:04:31 +01:00
DBG ( " %sOSVersion=%s \n " , indent , Entry - > macOSVersion . asString ( ) . c_str ( ) ) ;
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 :
2023-06-16 23:44:39 +02:00
OSIconName = GetOSIconName ( Entry - > macOSVersion ) ;
2019-09-03 11:58:42 +02:00
if ( OSType = = OSTYPE_OSX & & IsOsxHibernated ( Entry ) ) {
Entry - > Flags = OSFLAG_SET ( Entry - > Flags , OSFLAG_HIBERNATED ) ;
2021-02-04 15:04:31 +01:00
DBG ( " %s =>set entry as hibernated \n " , indent ) ;
2019-09-03 11:58:42 +02:00
}
2023-11-26 15:10:53 +01:00
ShortcutLetter = L ' M ' ;
2020-08-27 20:47:56 +02:00
if ( Entry - > DisplayedVolName . isEmpty ( ) ) {
2019-09-03 11:58:42 +02:00
// 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 ;
2023-11-26 15:10:53 +01:00
ShortcutLetter = L ' W ' ;
2019-09-03 11:58:42 +02:00
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';
2023-11-26 15:10:53 +01:00
ShortcutLetter = L ' W ' ;
2019-09-03 11:58:42 +02:00
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 ) {
2021-02-04 15:04:31 +01:00
DBG ( " %slinux image not found \n " , indent ) ;
2020-04-23 11:08:10 +02:00
OSIconName = LinuxIconNameFromPath ( LoaderPath , Volume - > RootDir ) ; //something named "issue"
}
2023-11-26 15:10:53 +01:00
ShortcutLetter = L ' L ' ;
2019-09-03 11:58:42 +02:00
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 ;
2023-11-26 15:10:53 +01:00
ShortcutLetter = L ' 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);
2023-06-16 23:44:39 +02:00
Entry - > OSName = OSIconName . subString ( 0 , OSIconName . indexOf ( ' , ' ) ) ; //TODO
// SmbiosList.AddReference(OSName.forgetDataWithoutFreeing(), true);
2020-04-03 22:00:42 +02:00
Entry - > Title = FullTitle ;
2020-08-09 17:55:30 +02:00
if ( Entry - > Title . isEmpty ( ) & & Volume - > VolLabel . notEmpty ( ) ) {
2020-04-03 22:00:42 +02:00
if ( Volume - > VolLabel [ 0 ] = = L ' # ' ) {
2021-03-22 13:40:01 +01:00
Entry - > Title . SWPrintf ( " Boot %ls from %ls " , ( ! LoaderTitle . isEmpty ( ) ) ? XStringW ( LoaderTitle ) . wc_str ( ) : LoaderPath . basename ( ) . wc_str ( ) , Volume - > VolLabel . data ( 1 ) ) ;
2020-04-03 22:00:42 +02:00
} else {
2021-03-22 13:40:01 +01:00
Entry - > Title . SWPrintf ( " Boot %ls from %ls " , ( ! LoaderTitle . isEmpty ( ) ) ? XStringW ( LoaderTitle ) . wc_str ( ) : LoaderPath . basename ( ) . wc_str ( ) , Volume - > VolLabel . wc_str ( ) ) ;
2020-04-03 22:00:42 +02:00
}
}
2020-03-10 12:51:04 +01:00
2023-11-06 21:53:57 +01:00
XBool BootCampStyle = ThemeX - > BootCampStyle ;
2020-04-03 22:00:42 +02:00
2020-08-27 20:47:56 +02:00
if ( Entry - > Title . isEmpty ( ) & & Entry - > DisplayedVolName . isEmpty ( ) ) {
2020-08-09 17:55:30 +02:00
XStringW BasenameXW = XStringW ( Basename ( Volume - > DevicePathString . wc_str ( ) ) ) ;
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 {
2021-03-22 13:40:01 +01:00
Entry - > Title . SWPrintf ( " Boot %ls from %ls " , ( ! LoaderTitle . isEmpty ( ) ) ? XStringW ( 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 ) {
2021-03-22 13:40:01 +01:00
if ( ( StriCmp ( XStringW ( LoaderTitle ) . wc_str ( ) , L " macOS " ) = = 0 ) | | ( StriCmp ( XStringW ( LoaderTitle ) . wc_str ( ) , L " Recovery " ) = = 0 ) ) {
2020-08-27 20:47:56 +02:00
Entry - > Title . takeValueFrom ( Entry - > DisplayedVolName ) ;
2020-04-03 22:00:42 +02:00
} 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 {
2021-03-22 13:40:01 +01:00
Entry - > Title . SWPrintf ( " Boot %ls from %ls " , ( ! LoaderTitle . isEmpty ( ) ) ? XStringW ( LoaderTitle ) . wc_str ( ) : LoaderPath . basename ( ) . wc_str ( ) ,
2020-08-27 20:47:56 +02:00
Entry - > DisplayedVolName . wc_str ( ) ) ;
2020-04-03 22:00:42 +02:00
}
}
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
2021-02-02 10:02:21 +01:00
if ( gSettings . GUI . 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 ( ) ) {
2021-02-04 15:04:31 +01:00
DBG ( " %susing VolumeIcon.icns image from Volume \n " , indent ) ;
2020-05-16 21:30:29 +02:00
}
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 {
2023-11-06 21:53:57 +01: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
}
2023-11-06 21:53:57 +01:00
// DBG("HideBadges=%llu Volume=%ls ", ThemeX->HideBadges, Volume->VolName);
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 ) ;
2021-02-04 15:04:31 +01:00
DBG ( " %sShow badge as Drive. \n " , indent ) ;
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 ) ;
2021-02-04 15:04:31 +01:00
DBG ( " %sShow badge as OSImage. \n " , indent ) ;
2020-03-24 16:17:12 +01:00
}
}
2020-04-01 14:57:32 +02:00
Entry - > BootBgColor = BootBgColor ;
2020-08-12 17:15:47 +02:00
Entry - > KernelAndKextPatches = Patches = = NULL ? gSettings . KernelAndKextPatches : * Patches ;
2019-09-03 11:58:42 +02:00
# ifdef DUMP_KERNEL_KEXT_PATCHES
DumpKernelAndKextPatches ( Entry - > KernelAndKextPatches ) ;
# endif
2020-08-09 17:55:30 +02:00
DBG ( " %sLoader entry created for '%ls' \n " , indent , Entry - > DevicePathString . wc_str ( ) ) ;
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
{
2023-06-16 23:44:39 +02:00
XStringW FileName ;
LOADER_ENTRY * SubEntry ;
UINT64 VolumeSize ;
2022-04-26 00:55:56 +02:00
EFI_GUID Guid ;
2023-06-16 23:44:39 +02:00
XBool KernelIs64BitOnly ;
2020-08-07 15:17:30 +02:00
2021-04-08 17:07:05 +02:00
constexpr LString8 quietLitteral = " quiet " _XS8 ;
constexpr LString8 splashLitteral = " splash " _XS8 ;
2019-09-03 11:58:42 +02:00
// Only kernels up to 10.7 have 32-bit mode
2021-01-31 10:50:23 +01:00
KernelIs64BitOnly = ( macOSVersion . isEmpty ( ) | |
macOSVersion > = MacOsVersion ( " 10.8 " _XS8 ) ) ;
2020-05-17 20:56:10 +02:00
2021-01-31 10:50:23 +01:00
const char * macOS = ( macOSVersion . notEmpty ( ) & & macOSVersion < MacOsVersion ( " 10.8 " _XS8 ) ) ? " Mac OS X " :
( macOSVersion . notEmpty ( ) & & macOSVersion < MacOsVersion ( " 10.12 " _XS8 ) ) ? " 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 = new REFIT_MENU_SCREEN ;
2020-08-27 20:47:56 +02:00
SubScreen - > Title . SWPrintf ( " Options for %ls on %ls " , Title . wc_str ( ) , DisplayedVolName . wc_str ( ) ) ;
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-08-07 15:17:30 +02:00
SubScreen - > AddMenuInfoLine_f ( " Volume size: %lluMb " , VolumeSize ) ;
2020-08-09 17:55:30 +02:00
SubScreen - > AddMenuInfoLine_f ( " %ls " , FileDevicePathToXStringW ( DevicePath ) . wc_str ( ) ) ;
2019-09-03 11:58:42 +02:00
Guid = FindGPTPartitionGuidInDevicePath ( Volume - > DevicePath ) ;
2022-04-26 00:55:56 +02:00
if ( Guid . notNull ( ) ) {
SubScreen - > AddMenuInfoLine_f ( " UUID: %s " , Guid . toXString8 ( ) . c_str ( ) ) ;
2020-08-07 10:23:46 +02:00
}
2022-04-26 00:55:56 +02:00
if ( Volume - > ApfsFileSystemUUID . notNull ( ) | | APFSTargetUUID . notNull ( ) ) {
2020-08-27 20:47:56 +02:00
SubScreen - > AddMenuInfoLine_f ( " APFS volume name: %ls " , DisplayedVolName . wc_str ( ) ) ;
2020-08-07 10:23:46 +02:00
}
2022-04-26 00:55:56 +02:00
if ( Volume - > ApfsFileSystemUUID . notNull ( ) ) {
SubScreen - > AddMenuInfoLine_f ( " APFS file system UUID: %s " , Volume - > ApfsFileSystemUUID . toXString8 ( ) . c_str ( ) ) ;
2020-10-22 15:55:30 +02:00
}
2022-04-26 00:55:56 +02:00
if ( Volume - > ApfsContainerUUID . notNull ( ) ) {
SubScreen - > AddMenuInfoLine_f ( " APFS container UUID: %s " , Volume - > ApfsContainerUUID . toXString8 ( ) . c_str ( ) ) ;
2020-08-07 10:23:46 +02:00
}
2022-04-26 00:55:56 +02:00
if ( APFSTargetUUID . notNull ( ) ) {
SubScreen - > AddMenuInfoLine_f ( " APFS target UUID: %s " , APFSTargetUUID . toXString8 ( ) . c_str ( ) ) ;
2019-09-03 11:58:42 +02:00
}
2020-08-07 15:17:30 +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
2021-01-31 10:50:23 +01:00
SubScreen - > AddMenuInfoLine_f ( " %s: %s " , macOS , macOSVersion . asString ( ) . c_str ( ) ) ;
2019-09-03 11:58:42 +02:00
2020-05-16 22:07:27 +02:00
if ( OSFLAG_ISSET ( Flags , OSFLAG_HIBERNATED ) ) {
SubEntry = getPartiallyDuplicatedEntry ( ) ;
2021-03-25 22:15:15 +01:00
SubEntry - > Title . takeValueFrom ( " Cancel hibernate wake " ) ;
SubEntry - > Flags = OSFLAG_UNSET ( SubEntry - > Flags , OSFLAG_HIBERNATED ) ;
SubScreen - > AddMenuEntry ( SubEntry , true ) ;
2019-09-03 11:58:42 +02:00
}
2020-05-16 22:07:27 +02:00
SubEntry = getPartiallyDuplicatedEntry ( ) ;
2021-03-25 22:15:15 +01:00
SubEntry - > Title . SWPrintf ( " Boot %s with selected options " , macOS ) ;
SubScreen - > AddMenuEntry ( SubEntry , true ) ;
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 ) {
2021-01-31 10:50:23 +01:00
if ( macOSVersion . notEmpty ( ) & & macOSVersion < MacOsVersion ( " 10.8 " _XS8 ) ) {
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
2021-01-31 10:50:23 +01:00
if ( macOSVersion . notEmpty ( ) & & macOSVersion < MacOsVersion ( " 10.10 " _XS8 ) ) {
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 ( " 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 ) ;
2019-09-03 11:58:42 +02:00
2021-03-26 10:43:15 +01:00
if ( gSettings . RtVariables . 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 ) {
2021-09-28 10:28:45 +02:00
XBool Quiet = LoadOptions . contains ( quietLitteral ) ;
XBool WithSplash = LoadOptions . contains ( splashLitteral ) ;
2019-09-03 11:58:42 +02:00
// default entry
2020-05-16 22:07:27 +02:00
SubEntry = getPartiallyDuplicatedEntry ( ) ;
2021-03-25 22:15:15 +01:00
SubEntry - > Title . SWPrintf ( " Run %ls " , FileName . wc_str ( ) ) ;
SubScreen - > AddMenuEntry ( SubEntry , true ) ;
2019-09-03 11:58:42 +02:00
2020-05-16 22:07:27 +02:00
SubEntry = getPartiallyDuplicatedEntry ( ) ;
2021-03-25 22:15:15 +01:00
if ( Quiet ) {
SubEntry - > Title . SWPrintf ( " %ls verbose " , Title . s ( ) ) ;
SubEntry - > LoadOptions . removeIC ( quietLitteral ) ;
} else {
SubEntry - > Title . SWPrintf ( " %ls quiet " , Title . s ( ) ) ;
SubEntry - > LoadOptions . AddID ( quietLitteral ) ;
2019-09-03 11:58:42 +02:00
}
2021-03-25 22:15:15 +01:00
SubScreen - > AddMenuEntry ( SubEntry , true ) ;
2020-05-10 17:50:24 +02:00
2020-05-16 22:07:27 +02:00
SubEntry = getPartiallyDuplicatedEntry ( ) ;
2021-03-25 22:15:15 +01:00
if ( WithSplash ) {
SubEntry - > Title . SWPrintf ( " %ls without splash " , Title . s ( ) ) ;
SubEntry - > LoadOptions . removeIC ( splashLitteral ) ;
} else {
SubEntry - > Title . SWPrintf ( " %ls with splash " , Title . s ( ) ) ;
SubEntry - > LoadOptions . AddID ( splashLitteral ) ;
2019-09-03 11:58:42 +02:00
}
2021-03-25 22:15:15 +01:00
SubScreen - > AddMenuEntry ( SubEntry , true ) ;
2020-05-10 17:50:24 +02:00
2020-05-16 22:07:27 +02:00
SubEntry = getPartiallyDuplicatedEntry ( ) ;
2021-03-25 22:15:15 +01:00
if ( WithSplash ) {
if ( Quiet ) {
SubEntry - > Title . SWPrintf ( " %ls verbose without splash " , Title . s ( ) ) ;
SubEntry - > LoadOptions . removeIC ( splashLitteral ) ;
SubEntry - > LoadOptions . removeIC ( quietLitteral ) ;
2019-09-03 11:58:42 +02:00
} else {
2021-03-25 22:15:15 +01:00
SubEntry - > Title . SWPrintf ( " %ls quiet without splash " , Title . s ( ) ) ;
SubEntry - > LoadOptions . removeIC ( splashLitteral ) ;
SubEntry - > LoadOptions . Add ( quietLitteral ) ;
2019-09-03 11:58:42 +02:00
}
2021-03-25 22:15:15 +01:00
} else if ( Quiet ) {
SubEntry - > Title . SWPrintf ( " %ls verbose with splash " , Title . s ( ) ) ;
SubEntry - > LoadOptions . removeIC ( quietLitteral ) ; //
SubEntry - > LoadOptions . AddID ( splashLitteral ) ;
} else {
SubEntry - > Title . SWPrintf ( " %ls quiet with splash " , Title . s ( ) ) ;
SubEntry - > LoadOptions . AddID ( quietLitteral ) ;
SubEntry - > LoadOptions . AddID ( splashLitteral ) ;
2019-09-03 11:58:42 +02:00
}
2021-03-25 22:15:15 +01:00
SubScreen - > AddMenuEntry ( SubEntry , true ) ;
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 ( ) ;
2021-03-25 22:15:15 +01:00
SubEntry - > Title . SWPrintf ( " Run %ls " , FileName . wc_str ( ) ) ;
SubScreen - > AddMenuEntry ( SubEntry , true ) ;
2019-09-03 11:58:42 +02:00
2020-05-17 20:56:10 +02:00
SubEntry = getPartiallyDuplicatedEntry ( ) ;
2021-03-25 22:15:15 +01:00
SubEntry - > Title . takeValueFrom ( " Boot Windows from Hard Disk " ) ;
SubScreen - > AddMenuEntry ( SubEntry , true ) ;
2019-09-03 11:58:42 +02:00
2020-05-17 20:56:10 +02:00
SubEntry = getPartiallyDuplicatedEntry ( ) ;
2021-03-25 22:15:15 +01:00
SubEntry - > Title . takeValueFrom ( " Boot Windows from CD-ROM " ) ;
LoadOptions . setEmpty ( ) ;
LoadOptions . Add ( " -s " _XS8 ) ;
LoadOptions . Add ( " -c " _XS8 ) ;
SubScreen - > AddMenuEntry ( SubEntry , true ) ;
2019-09-03 11:58:42 +02:00
2020-05-17 20:56:10 +02:00
SubEntry = getPartiallyDuplicatedEntry ( ) ;
2021-03-25 22:15:15 +01:00
SubEntry - > Title . SWPrintf ( " Run %ls in text mode " , FileName . wc_str ( ) ) ;
SubEntry - > Flags = OSFLAG_UNSET ( SubEntry - > Flags , OSFLAG_USEGRAPHICS ) ;
LoadOptions . setEmpty ( ) ;
LoadOptions . Add ( " -v " _XS8 ) ;
SubEntry - > LoaderType = OSTYPE_OTHER ; // Sothor - Why are we using OSTYPE_OTHER here?
SubScreen - > AddMenuEntry ( SubEntry , true ) ;
2019-09-03 11:58:42 +02:00
2021-03-25 22:15:15 +01:00
} else {
// default entry
SubEntry = getPartiallyDuplicatedEntry ( ) ;
SubEntry - > Title . SWPrintf ( " Run %ls " , FileName . wc_str ( ) ) ;
SubScreen - > AddMenuEntry ( SubEntry , true ) ;
2019-09-03 11:58:42 +02:00
}
}
2020-05-06 00:23:59 +02:00
2020-08-11 08:00:19 +02:00
LOADER_ENTRY * AddLoaderEntry ( IN CONST XStringW & LoaderPath , IN CONST XString8Array & LoaderOptions ,
2020-08-07 10:23:46 +02:00
IN CONST XStringW & FullTitle , IN CONST XStringW & LoaderTitle ,
2021-01-31 10:50:23 +01: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 ;
2020-04-27 14:13:09 +02:00
if ( ( LoaderPath . isEmpty ( ) ) | | ( Volume = = NULL ) | | ( Volume - > RootDir = = NULL ) | | ! FileExists ( Volume - > RootDir , LoaderPath ) ) {
2020-08-07 10:23:46 +02:00
return NULL ;
2019-09-03 11:58:42 +02:00
}
2021-02-04 15:04:31 +01:00
DBG ( " AddLoaderEntry for Volume Name=%ls, idx=%zu \n " , Volume - > VolName . wc_str ( ) , MainMenu . Entries . sizeIncludingHidden ( ) ) ;
2019-09-03 11:58:42 +02:00
if ( OSFLAG_ISSET ( Flags , OSFLAG_DISABLED ) ) {
2020-10-04 19:12:10 +02:00
DBG ( " skipped because entry is disabled \n " ) ;
2020-08-07 10:23:46 +02:00
return NULL ;
2019-09-03 11:58:42 +02:00
}
2020-10-22 15:55:30 +02:00
2021-09-28 10:28:45 +02:00
Entry = CreateLoaderEntry ( LoaderPath , LoaderOptions , FullTitle , LoaderTitle , Volume , Image , NULL , OSType , Flags , 0 , MenuBackgroundPixel , CUSTOM_BOOT_DISABLED , NullXImage , 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 ) ) {
2023-06-16 23:44:39 +02:00
2021-03-25 15:32:56 +01:00
if ( gSettings . SystemParameters . NoCaches ) {
2019-09-03 11:58:42 +02:00
Entry - > Flags = OSFLAG_SET ( Entry - > Flags , OSFLAG_NOCACHES ) ;
}
}
2020-08-15 22:39:25 +02:00
if ( Volume - > Hidden ) {
2021-02-04 15:04:31 +01:00
DBG ( " hiding entry because volume is hidden: %ls \n " , LoaderPath . s ( ) ) ;
2020-08-15 22:39:25 +02:00
Entry - > Hidden = true ;
} else {
2021-03-19 21:32:42 +01:00
for ( size_t HVi = 0 ; HVi < gSettings . GUI . HVHideStrings . size ( ) ; HVi + + ) {
if ( LoaderPath . containsIC ( gSettings . GUI . HVHideStrings [ HVi ] ) ) {
2020-10-04 19:12:10 +02:00
DBG ( " hiding entry: %ls \n " , LoaderPath . s ( ) ) ;
2020-08-15 22:39:25 +02:00
Entry - > Hidden = true ;
}
}
}
2019-09-03 11:58:42 +02:00
//TODO there is a problem that Entry->Flags is unique while InputItems are global ;(
2020-05-16 22:07:27 +02:00
Entry - > AddDefaultMenu ( ) ;
2021-02-04 15:04:31 +01:00
DBG ( " Menu entry added at index %zd \n " , MainMenu . Entries . sizeIncludingHidden ( ) ) ;
2020-03-03 21:44:07 +01:00
MainMenu . AddMenuEntry ( Entry , true ) ;
2020-08-07 10:23:46 +02:00
return Entry ;
2019-09-03 11:58:42 +02:00
}
2020-08-07 10:23:46 +02:00
return NULL ;
2019-09-03 11:58:42 +02:00
}
2020-05-06 00:23:59 +02:00
2020-10-03 19:02:31 +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 ;
// 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
2023-11-06 21:53:57 +01: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
2023-11-06 21:53:57 +01:00
ImageX . LoadXImage ( & ThemeX - > getThemeDir ( ) , L " os_ " _XSW + OSName ) ;
2020-05-06 00:23:59 +02:00
}
if ( CustomPath ) {
* CustomPath = File ;
if ( CustomImage ) {
* CustomImage = ImageX ;
}
DirIterClose ( & DirIter ) ;
return ;
}
2021-01-31 10:50:23 +01:00
AddLoaderEntry ( File , NullXString8Array , L " " _XSW , LoaderTitle , Volume ,
2020-05-06 00:23:59 +02:00
( 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 ( ' , ' ) ) ;
2023-11-06 21:53:57 +01:00
XIcon ImageX = ThemeX - > GetIcon ( L " os_ " _XSW + OSIconName ) ;
2020-05-06 00:23:59 +02:00
if ( ImageX . isEmpty ( ) ) {
2023-11-06 21:53:57 +01:00
ImageX . LoadXImage ( & ThemeX - > getThemeDir ( ) , L " os_ " _XSW + OSIconName ) ;
2020-05-06 00:23:59 +02:00
}
if ( CustomPath ) {
* CustomPath = LinuxEntryData [ Index ] . Path ;
if ( CustomImage ) {
* CustomImage = ImageX ;
}
return ;
}
2021-01-31 10:50:23 +01:00
AddLoaderEntry ( LinuxEntryData [ Index ] . Path , NullXString8Array , L " " _XSW , XStringW ( ) . takeValueFrom ( LinuxEntryData [ Index ] . Title ) , Volume ,
2020-05-06 00:23:59 +02:00
( 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
2022-04-26 00:55:56 +02:00
EFI_GUID PartGUID = FindGPTPartitionGuidInDevicePath ( Volume - > DevicePath ) ;
if ( PartGUID . notNull ( ) & & Volume - > RootDir ! = NULL ) {
2020-05-06 00:23:59 +02:00
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 ) ) ;
2022-04-26 00:55:56 +02:00
snwprintf ( PartUUID , sizeof ( PartUUID ) , " %s " , PartGUID . toXString8 ( ) . c_str ( ) ) ;
2020-05-06 00:23:59 +02:00
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 ;
}
2020-08-11 08:00:19 +02:00
XString8Array Options = LinuxKernelOptions ( Iter . DirHandle , Basename ( Path . wc_str ( ) ) + LINUX_LOADER_PATH . length ( ) , PartUUID , NullXString8Array ) ;
2020-05-06 00:23:59 +02:00
// Add the entry
2021-01-31 10:50:23 +01:00
AddLoaderEntry ( Path , ( Options . isEmpty ( ) ) ? LINUX_DEFAULT_OPTIONS : Options , L " " _XSW , L " " _XSW , Volume , NULL , OSTYPE_LINEFI , OSFLAG_NODEFAULTARGS ) ;
2020-05-06 00:23:59 +02:00
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-08-11 08:00:19 +02:00
XString8Array Options = LinuxKernelOptions ( Iter . DirHandle , Basename ( Path . wc_str ( ) ) + LINUX_LOADER_PATH . length ( ) , PartUUID , NullXString8Array ) ;
2020-05-06 00:23:59 +02:00
// Add the entry
2021-01-31 10:50:23 +01:00
AddLoaderEntry ( Path , ( Options . isEmpty ( ) ) ? LINUX_DEFAULT_OPTIONS : Options , L " " _XSW , L " " _XSW , Volume , NULL , OSTYPE_LINEFI , OSFLAG_NODEFAULTARGS ) ;
2020-05-06 00:23:59 +02:00
Path . setEmpty ( ) ;
}
}
}
}
//close the directory
DirIterClose ( & Iter ) ;
}
}
}
2019-09-03 11:58:42 +02:00
# define Paper 1
# define Rock 2
# define Scissor 4
2020-10-03 19:02:31 +02:00
void AddPRSEntry ( REFIT_VOLUME * Volume )
2019-09-03 11:58:42 +02:00
{
INTN WhatBoot = 0 ;
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 ) :
2021-01-31 10:50:23 +01:00
AddLoaderEntry ( PaperBoot , NullXString8Array , L " " _XSW , L " macOS InstallP " _XSW , Volume , NULL , OSTYPE_OSX_INSTALLER , 0 ) ;
2019-09-03 11:58:42 +02:00
break ;
case Scissor :
case ( Paper | Scissor ) :
2021-01-31 10:50:23 +01:00
AddLoaderEntry ( ScissorBoot , NullXString8Array , L " " _XSW , 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 ) :
2021-01-31 10:50:23 +01:00
AddLoaderEntry ( RockBoot , NullXString8Array , L " " _XSW , 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
2021-04-28 20:30:34 +02:00
XString8 GetAuthRootDmg ( const EFI_FILE & dir , const XStringW & path )
{
XString8 returnValue ;
XStringW plist = SWPrintf ( " %ls \\ com.apple.Boot.plist " , path . wc_str ( ) ) ;
if ( ! FileExists ( dir , plist ) ) return NullXString8 ;
2023-11-07 11:02:22 +01:00
UINT8 * PlistBuffer = NULL ;
2023-06-16 23:44:39 +02:00
UINTN PlistLen ;
TagDict * Dict = NULL ;
const TagStruct * Prop = NULL ;
2021-04-28 20:30:34 +02:00
2023-11-07 11:02:22 +01:00
EFI_STATUS Status = egLoadFile ( & dir , plist . wc_str ( ) , & PlistBuffer , & PlistLen ) ;
2021-04-28 20:30:34 +02:00
if ( ! EFI_ERROR ( Status ) & & PlistBuffer ! = NULL & & ParseXML ( PlistBuffer , & Dict , 0 ) = = EFI_SUCCESS )
{
Prop = Dict - > propertyForKey ( " Kernel Flags " ) ;
if ( Prop ! = NULL ) {
if ( ! Prop - > isString ( ) ) {
MsgLog ( " ATTENTION : Kernel Flags not string in ProductVersion \n " ) ;
} else {
if ( Prop - > getString ( ) - > stringValue ( ) . notEmpty ( ) ) {
const XString8 & kernelFlags = Prop - > getString ( ) - > stringValue ( ) ;
size_t idx = kernelFlags . indexOf ( " auth-root-dmg " ) ;
if ( idx = = MAX_XSIZE ) return NullXString8 ;
idx + = strlen ( " auth-root-dmg " ) ;
while ( idx < kernelFlags . length ( ) & & IS_BLANK ( kernelFlags [ idx ] ) ) + + idx ;
if ( kernelFlags [ idx ] = = ' = ' ) + + idx ;
else return NullXString8 ;
while ( idx < kernelFlags . length ( ) & & IS_BLANK ( kernelFlags [ idx ] ) ) + + idx ;
if ( kernelFlags . isEqualAtIC ( idx , " file:// " _XS8 ) ) idx + = strlen ( " file:// " ) ;
size_t idxEnd = idx ;
while ( idxEnd < kernelFlags . length ( ) & & ! IS_BLANK ( kernelFlags [ idxEnd ] ) ) + + idxEnd ;
returnValue = kernelFlags . subString ( idx , idxEnd - idx ) ;
}
}
}
}
if ( PlistBuffer ) FreePool ( PlistBuffer ) ;
2023-11-18 11:04:54 +01:00
if ( Dict ) Dict - > ReleaseTag ( ) ;
2021-04-28 20:30:34 +02:00
return returnValue ;
}
MacOsVersion GetMacOSVersionFromFolder ( const EFI_FILE & dir , const XStringW & path )
{
MacOsVersion macOSVersion ;
XStringW plist = SWPrintf ( " %ls \\ SystemVersion.plist " , path . wc_str ( ) ) ;
if ( ! FileExists ( dir , plist ) ) {
plist = SWPrintf ( " %ls \\ ServerVersion.plist " , path . wc_str ( ) ) ;
if ( ! FileExists ( dir , plist ) ) {
plist . setEmpty ( ) ;
}
}
if ( plist . notEmpty ( ) ) { // found macOS System
2023-11-07 11:02:22 +01:00
UINT8 * PlistBuffer = NULL ;
2021-04-28 20:30:34 +02:00
UINTN PlistLen ;
TagDict * Dict = NULL ;
const TagStruct * Prop = NULL ;
2023-11-07 11:02:22 +01:00
EFI_STATUS Status = egLoadFile ( & dir , plist . wc_str ( ) , & PlistBuffer , & PlistLen ) ;
2021-04-28 20:30:34 +02:00
if ( ! EFI_ERROR ( Status ) & & PlistBuffer ! = NULL & & ParseXML ( PlistBuffer , & Dict , 0 ) = = EFI_SUCCESS ) {
Prop = Dict - > propertyForKey ( " ProductVersion " ) ;
if ( Prop ! = NULL ) {
if ( ! Prop - > isString ( ) ) {
MsgLog ( " ATTENTION : property not string in ProductVersion \n " ) ;
} else {
if ( Prop - > getString ( ) - > stringValue ( ) . notEmpty ( ) ) {
macOSVersion = Prop - > getString ( ) - > stringValue ( ) ;
}
}
}
}
if ( PlistBuffer ) FreePool ( PlistBuffer ) ;
}
return macOSVersion ;
}
2020-10-03 19:02:31 +02:00
void ScanLoader ( void )
2019-09-03 11:58:42 +02:00
{
//DBG("Scanning loaders...\n");
DbgHeader ( " ScanLoader " ) ;
2021-01-31 10:50:23 +01:00
for ( UINTN VolumeIndex = 0 ; VolumeIndex < Volumes . size ( ) ; VolumeIndex + + )
{
2020-08-07 10:23:46 +02:00
REFIT_VOLUME * 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-08-09 17:55:30 +02:00
DBG ( " - [%02llu]: '%ls' " , VolumeIndex , Volume - > VolName . wc_str ( ) ) ;
if ( Volume - > VolName . isEmpty ( ) ) {
Volume - > VolName = L " Unknown " _XSW ;
2019-09-03 11:58:42 +02:00
}
// 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 ;
}
DBG ( " \n " ) ;
2023-06-16 23:44:39 +02:00
if ( Volume - > ApfsContainerUUID . notNull ( ) ) { DBG ( " ApfsContainerUUID=%s \n " , Volume - > ApfsContainerUUID . toXString8 ( ) . c_str ( ) ) ; }
if ( Volume - > ApfsFileSystemUUID . notNull ( ) ) { DBG ( " ApfsFileSystemUUID=%s \n " , Volume - > ApfsFileSystemUUID . toXString8 ( ) . c_str ( ) ) ; }
2021-02-04 15:04:31 +01:00
2019-09-03 11:58:42 +02:00
// 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 " ) ) {
2021-01-31 10:50:23 +01:00
AddLoaderEntry ( L " \\ .IABootFiles \\ boot.efi " _XSW , NullXString8Array , L " " _XSW , L " OS X Install " _XSW , Volume , NULL , OSTYPE_OSX_INSTALLER , 0 ) ; // 10.9 - 10.11
2019-09-03 11:58:42 +02:00
} else {
2021-01-31 10:50:23 +01:00
AddLoaderEntry ( L " \\ .IABootFiles \\ boot.efi " _XSW , NullXString8Array , L " " _XSW , 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 ) ) {
2021-01-31 10:50:23 +01:00
AddLoaderEntry ( MACOSX_LOADER_PATH , NullXString8Array , L " " _XSW , 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
2021-01-31 10:50:23 +01:00
// 10.7
AddLoaderEntry ( L " \\ Mac OS X Install Data \\ boot.efi " _XSW , NullXString8Array , L " " _XSW , L " Mac OS X Install " _XSW , Volume , NULL , OSTYPE_OSX_INSTALLER , 0 ) ; // 10.7
// 10.8 - 10.11
AddLoaderEntry ( L " \\ OS X Install Data \\ boot.efi " _XSW , NullXString8Array , L " " _XSW , L " OS X Install " _XSW , Volume , NULL , OSTYPE_OSX_INSTALLER , 0 ) ; // 10.8 - 10.11
// 10.12 - 10.12.3
AddLoaderEntry ( L " \\ macOS Install Data \\ boot.efi " _XSW , NullXString8Array , L " " _XSW , L " macOS Install " _XSW , Volume , NULL , OSTYPE_OSX_INSTALLER , 0 ) ; // 10.12 - 10.12.3
// 10.12.4-10.15
AddLoaderEntry ( L " \\ macOS Install Data \\ Locked Files \\ Boot Files \\ boot.efi " _XSW , NullXString8Array , L " " _XSW , L " macOS Install " _XSW , Volume , NULL , OSTYPE_OSX_INSTALLER , 0 ) ;
// Big Sur install must be via Preboot. Next line must stay commented.
// AddLoaderEntry(L"\\macOS Install Data\\Locked Files\\boot.efi"_XSW, NullXString8Array, L""_XSW, L"macOS Install"_XSW, Volume, NULL, OSTYPE_OSX_INSTALLER, 0); // 11+
2019-09-03 11:58:42 +02:00
AddPRSEntry ( Volume ) ; // 10.12+
// Netinstall
2021-01-31 10:50:23 +01:00
AddLoaderEntry ( L " \\ NetInstall macOS High Sierra.nbi \\ i386 \\ booter " _XSW , NullXString8Array , L " " _XSW , 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
2021-01-31 10:50:23 +01:00
AddLoaderEntry ( MACOSX_LOADER_PATH , NullXString8Array , L " " _XSW , 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
2021-01-31 10:50:23 +01:00
AddLoaderEntry ( MACOSX_LOADER_PATH , NullXString8Array , L " " _XSW , 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
2021-01-31 10:50:23 +01:00
AddLoaderEntry ( MACOSX_LOADER_PATH , NullXString8Array , L " " _XSW , 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 " ) ) {
2021-01-31 10:50:23 +01:00
AddLoaderEntry ( MACOSX_LOADER_PATH , NullXString8Array , L " " _XSW , L " Mac OS X Install " _XSW , Volume , NULL , OSTYPE_OSX_INSTALLER , 0 ) ; // 10.7
2020-04-03 22:00:42 +02:00
} else {
2021-01-31 10:50:23 +01:00
AddLoaderEntry ( MACOSX_LOADER_PATH , NullXString8Array , L " " _XSW , 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 " ) ) {
2020-08-09 17:55:30 +02:00
if ( StriStr ( Volume - > VolName . wc_str ( ) , L " Recovery " ) ! = NULL ) {
2020-04-03 22:00:42 +02:00
// FileVault of HFS+
// TODO: need info for 10.11 and lower
2021-01-31 10:50:23 +01:00
AddLoaderEntry ( MACOSX_LOADER_PATH , NullXString8Array , L " " _XSW , L " macOS FileVault " _XSW , Volume , NULL , OSTYPE_OSX , 0 ) ; // 10.12+
2020-04-03 22:00:42 +02:00
} else {
// Fusion Drive
2021-01-31 10:50:23 +01:00
AddLoaderEntry ( MACOSX_LOADER_PATH , NullXString8Array , L " " _XSW , 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 " ) ) {
2021-01-31 10:50:23 +01:00
AddLoaderEntry ( MACOSX_LOADER_PATH , NullXString8Array , L " " _XSW , 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 " ) ) {
2021-01-31 10:50:23 +01:00
AddLoaderEntry ( MACOSX_LOADER_PATH , NullXString8Array , L " " _XSW , L " OS X " _XSW , Volume , NULL , OSTYPE_OSX , 0 ) ; // 10.8 - 10.11
2020-04-03 22:00:42 +02:00
} else {
2021-02-04 15:04:31 +01:00
MacOsVersion macOSVersion ;
2022-04-26 00:55:56 +02:00
if ( Volume - > ApfsFileSystemUUID . notNull ( ) & & ( Volume - > ApfsRole & APPLE_APFS_VOLUME_ROLE_SYSTEM ) ! = 0 )
2020-10-20 23:33:02 +02:00
{
2021-02-04 15:04:31 +01:00
macOSVersion = GetMacOSVersionFromFolder ( * Volume - > RootDir , L " \\ System \\ Library \\ CoreServices " _XSW ) ;
2020-10-20 23:33:02 +02:00
}
2021-02-04 15:04:31 +01:00
if ( macOSVersion < MacOsVersion ( " 11 " _XS8 ) ) {
2021-01-31 10:50:23 +01:00
AddLoaderEntry ( MACOSX_LOADER_PATH , NullXString8Array , L " " _XSW , L " macOS " _XSW , Volume , NULL , OSTYPE_OSX , 0 ) ; // 10.12+
2020-10-20 23:33:02 +02:00
}
2020-04-03 22:00:42 +02:00
}
}
}
}
2020-08-07 10:23:46 +02:00
2020-04-03 22:00:42 +02:00
// check for Mac OS X Recovery Boot
2021-01-31 10:50:23 +01:00
AddLoaderEntry ( L " \\ com.apple.recovery.boot \\ boot.efi " _XSW , NullXString8Array , L " " _XSW , 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
2021-01-31 10:50:23 +01:00
AddLoaderEntry ( L " \\ EFI \\ microsoft \\ Boot \\ bootmgfw-orig.efi " _XSW , NullXString8Array , L " " _XSW , 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
2021-01-31 10:50:23 +01:00
AddLoaderEntry ( L " \\ EFI \\ microsoft \\ Boot \\ bootmgfw.efi " _XSW , NullXString8Array , L " " _XSW , 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
2021-01-31 10:50:23 +01:00
if ( ! AddLoaderEntry ( L " \\ EFI \\ MICROSOFT \\ BOOT \\ cdboot.efi " _XSW , NullXString8Array , L " " _XSW , L " Microsoft EFI cdboot " _XSW , Volume , NULL , OSTYPE_WINEFI , 0 ) ) {
AddLoaderEntry ( L " \\ EFI \\ MICROSOFT \\ BOOT \\ CDBOOT.EFI " _XSW , NullXString8Array , L " " _XSW , 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
2020-08-15 22:39:25 +02:00
2019-09-03 11:58:42 +02:00
# if defined(ANDX86)
2021-09-28 10:28:45 +02:00
if ( true ) { //gSettings.AndroidScan
2019-09-03 11:58:42 +02:00
// 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-08-07 15:17:30 +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 ) ;
2023-11-06 21:53:57 +01:00
ImageX . LoadXImage ( & ThemeX - > getThemeDir ( ) , ( L " os_ " _XSW + IconXSW . subString ( 0 , IconXSW . indexOf ( ' , ' ) ) ) . wc_str ( ) ) ;
2021-01-31 10:50:23 +01:00
AddLoaderEntry ( AndroidEntryData [ Index ] . Path , NullXString8Array , L " " _XSW , 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
2021-03-19 21:32:42 +01:00
if ( gSettings . GUI . Scan . LinuxScan ) {
LinuxScan ( Volume , gSettings . GUI . Scan . KernelScan , 0 , NULL , NULL ) ;
2020-05-06 00:23:59 +02:00
}
2019-09-03 11:58:42 +02:00
// DBG("search for optical UEFI\n");
if ( Volume - > DiskKind = = DISK_KIND_OPTICAL ) {
2021-01-31 10:50:23 +01:00
AddLoaderEntry ( BOOT_LOADER_PATH , NullXString8Array , L " " _XSW , 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 ) {
2021-01-31 10:50:23 +01:00
LOADER_ENTRY * le = AddLoaderEntry ( BOOT_LOADER_PATH , NullXString8Array , L " " _XSW , L " UEFI internal " _XSW , Volume , NULL , OSTYPE_OTHER , 0 ) ;
2021-02-04 15:04:31 +01:00
if ( le ) {
DBG ( " hiding entry because DiskKind is DISK_KIND_INTERNAL: %ls \n " , le - > LoaderPath . s ( ) ) ;
le - > Hidden = true ;
}
2019-09-03 11:58:42 +02:00
}
// DBG("search for external UEFI\n");
if ( Volume - > DiskKind = = DISK_KIND_EXTERNAL ) {
2021-01-31 10:50:23 +01:00
LOADER_ENTRY * le = AddLoaderEntry ( BOOT_LOADER_PATH , NullXString8Array , L " " _XSW , L " UEFI external " _XSW , Volume , NULL , OSTYPE_OTHER , 0 ) ;
2021-02-04 15:04:31 +01:00
if ( le ) {
DBG ( " hiding entry because DiskKind is DISK_KIND_EXTERNAL: %ls \n " , le - > LoaderPath . s ( ) ) ;
le - > Hidden = true ;
}
2019-09-03 11:58:42 +02:00
}
2020-08-07 10:23:46 +02:00
2020-10-26 21:37:32 +01:00
//DBG("Volume->ApfsTargetUUIDArray.size()=%zd\n", Volume->ApfsTargetUUIDArray.size());
2020-08-07 15:17:30 +02:00
if ( Volume - > ApfsTargetUUIDArray . size ( ) > 0 ) {
2020-08-07 10:23:46 +02:00
for ( UINTN i = 0 ; i < Volume - > ApfsTargetUUIDArray . size ( ) ; i + + )
{
2022-04-26 00:55:56 +02:00
const EFI_GUID & ApfsTargetUUID = Volume - > ApfsTargetUUIDArray [ i ] ;
DBG ( " APFSTargetUUID=%s \n " , ApfsTargetUUID . toXString8 ( ) . c_str ( ) ) ;
2020-10-22 15:55:30 +02:00
XStringW FullTitle ;
XStringW FullTitleRecovery ;
XStringW FullTitleInstaller ;
XStringW LoaderTitle ;
XStringW LoaderTitleInstaller ;
2020-11-13 16:15:46 +01:00
// Find the "target" volume.
2021-02-04 15:04:31 +01:00
REFIT_VOLUME * targetVolume = Volumes . getVolumeWithApfsContainerUUIDAndFileSystemUUID ( Volume - > ApfsContainerUUID , ApfsTargetUUID ) ;
2020-11-13 16:15:46 +01:00
// If targetVolume is found, and it's a data partition, try to find the system partition that goes with it.
2020-10-26 21:37:32 +01:00
//DBG("targetVolume=%d\n", targetVolume ? 1 : 0);
2020-10-22 15:55:30 +02:00
if ( targetVolume ) {
if ( ( targetVolume - > ApfsRole & APPLE_APFS_VOLUME_ROLE_DATA ) ! = 0 ) {
2020-10-26 21:37:32 +01:00
for ( size_t VolumeIndex2 = 0 ; VolumeIndex2 < Volumes . size ( ) ; VolumeIndex2 + + ) {
2020-10-22 15:55:30 +02:00
REFIT_VOLUME * Volume2 = & Volumes [ VolumeIndex2 ] ;
2020-10-26 21:37:32 +01:00
//DBG("idx=%zu name %ls uuid=%s \n", VolumeIndex2, Volume2->VolName.wc_str(), Volume2->ApfsFileSystemUUID.c_str());
2020-10-22 15:55:30 +02:00
if ( Volume2 - > ApfsContainerUUID = = targetVolume - > ApfsContainerUUID ) {
if ( ( Volume2 - > ApfsRole & APPLE_APFS_VOLUME_ROLE_SYSTEM ) ! = 0 ) {
2020-10-26 21:37:32 +01:00
if ( ! targetVolume ) {
targetVolume = Volume2 ;
} else {
// More than one system partition in container. I don't know how to select which one is supposed to pair with this
targetVolume = NULL ; // we'll try .disk_label.contentDetails
break ; // we need to escape the loop after bootVolume = NULL;
}
}
}
}
}
}
2020-11-13 16:15:46 +01:00
// If targetVolume is not found, and it's not a recovery, find the preboot volume from the same container
2020-10-26 21:37:32 +01:00
//DBG("2) targetVolume=%d\n", targetVolume ? 1 : 0);
if ( ! targetVolume ) {
REFIT_VOLUME * bootVolume = Volume ;
if ( ( Volume - > ApfsRole & APPLE_APFS_VOLUME_ROLE_RECOVERY ) ! = 0 ) {
for ( size_t VolumeIndex2 = 0 ; VolumeIndex2 < Volumes . size ( ) ; VolumeIndex2 + + ) {
REFIT_VOLUME * Volume2 = & Volumes [ VolumeIndex2 ] ;
//DBG("idx=%zu name %ls uuid=%s \n", VolumeIndex2, Volume2->VolName.wc_str(), Volume2->ApfsFileSystemUUID.c_str());
if ( ( Volume2 - > ApfsRole & APPLE_APFS_VOLUME_ROLE_PREBOOT ) ! = 0 ) {
if ( Volume2 - > ApfsContainerUUID = = Volume - > ApfsContainerUUID ) {
bootVolume = Volume2 ;
break ;
2020-10-22 15:55:30 +02:00
}
}
2020-08-07 15:17:30 +02:00
}
2020-10-26 21:37:32 +01:00
}
if ( bootVolume ) {
XStringW targetNameFile ;
CHAR8 * fileBuffer ;
UINTN fileLen = 0 ;
2022-04-26 00:55:56 +02:00
targetNameFile . SWPrintf ( " %s \\ System \\ Library \\ CoreServices \\ .disk_label.contentDetails " , ApfsTargetUUID . toXString8 ( ) . c_str ( ) ) ;
2020-10-26 21:37:32 +01:00
if ( FileExists ( bootVolume - > RootDir , targetNameFile ) ) {
EFI_STATUS Status = egLoadFile ( bootVolume - > RootDir , targetNameFile . wc_str ( ) , ( UINT8 * * ) & fileBuffer , & fileLen ) ;
if ( ! EFI_ERROR ( Status ) ) {
2021-02-27 07:31:06 +01:00
FullTitle . SWPrintf ( " Boot Mac OS from %.*s " , ( int ) fileLen , fileBuffer ) ;
FullTitleRecovery . SWPrintf ( " Boot Mac OS Recovery for %.*s " , ( int ) fileLen , fileBuffer ) ;
FullTitleInstaller . SWPrintf ( " Boot Mac OS Install for %.*s " , ( int ) fileLen , fileBuffer ) ;
2021-01-31 10:50:23 +01:00
if ( fileLen < MAX_INT32 ) {
2021-02-04 15:04:31 +01:00
DBG ( " contentDetails name:%.*s \n " , ( int ) fileLen , fileBuffer ) ;
2021-01-31 10:50:23 +01:00
}
2020-10-26 21:37:32 +01:00
FreePool ( fileBuffer ) ;
}
}
2020-08-07 15:17:30 +02:00
}
2020-10-22 15:55:30 +02:00
}
if ( FullTitle . isEmpty ( ) ) {
2020-08-07 15:17:30 +02:00
if ( targetVolume ) {
2021-02-27 07:31:06 +01:00
FullTitle . SWPrintf ( " Boot Mac OS from %ls " , targetVolume - > getVolLabelOrOSXVolumeNameOrVolName ( ) . wc_str ( ) ) ;
FullTitleRecovery . SWPrintf ( " Boot Mac OS Recovery for %ls " , targetVolume - > getVolLabelOrOSXVolumeNameOrVolName ( ) . wc_str ( ) ) ;
FullTitleInstaller . SWPrintf ( " Boot Mac OS Install for %ls " , targetVolume - > getVolLabelOrOSXVolumeNameOrVolName ( ) . wc_str ( ) ) ;
2020-10-22 15:55:30 +02:00
} else {
2021-02-27 07:31:06 +01:00
FullTitle . SWPrintf ( " Boot Mac OS " ) ;
FullTitleRecovery . SWPrintf ( " Boot Mac OS Recovery " ) ;
FullTitleInstaller . SWPrintf ( " Mac OS Install " ) ;
2020-08-07 15:17:30 +02:00
}
}
2021-02-04 15:04:31 +01:00
/*MacOsVersion macOSVersion = GetMacOSVersionFromFolder(*Volume->RootDir, SWPrintf("\\%s\\System\\Library\\CoreServices", ApfsTargetUUID.c_str()));
if ( macOSVersion . notEmpty ( ) & & macOSVersion < MacOsVersion ( " 11 " _XS8 ) ) */ FullTitle . SWCatf ( " via %ls " , Volume - > getVolLabelOrOSXVolumeNameOrVolName ( ) . wc_str ( ) ) ;
2022-04-26 00:55:56 +02:00
AddLoaderEntry ( SWPrintf ( " \\ %s \\ System \\ Library \\ CoreServices \\ boot.efi " , ApfsTargetUUID . toXString8 ( ) . c_str ( ) ) , NullXString8Array , FullTitle , LoaderTitle , Volume , NULL , OSTYPE_OSX , 0 ) ;
2021-02-04 15:04:31 +01:00
2020-10-22 15:55:30 +02:00
//Try to add Recovery APFS entry
2021-02-04 15:04:31 +01:00
/*macOSVersion = GetMacOSVersionFromFolder(*Volume->RootDir, SWPrintf("\\%s", ApfsTargetUUID.c_str()));
if ( macOSVersion . notEmpty ( ) & & macOSVersion < MacOsVersion ( " 11 " _XS8 ) ) */ FullTitleRecovery . SWCatf ( " via %ls " , Volume - > getVolLabelOrOSXVolumeNameOrVolName ( ) . wc_str ( ) ) ;
2022-04-26 00:55:56 +02:00
if ( ! AddLoaderEntry ( SWPrintf ( " \\ %s \\ boot.efi " , Volume - > ApfsTargetUUIDArray [ i ] . toXString8 ( ) . c_str ( ) ) , NullXString8Array , FullTitleRecovery , L " " _XSW , Volume , NULL , OSTYPE_RECOVERY , 0 ) ) {
2020-11-28 16:08:18 +01:00
//Try to add Recovery APFS entry as dmg
2022-04-26 00:55:56 +02:00
AddLoaderEntry ( SWPrintf ( " \\ %s \\ BaseSystem.dmg " , Volume - > ApfsTargetUUIDArray [ i ] . toXString8 ( ) . c_str ( ) ) , NullXString8Array , FullTitleRecovery , L " " _XSW , Volume , NULL , OSTYPE_RECOVERY , 0 ) ;
2020-11-28 16:08:18 +01:00
}
2020-11-28 14:48:31 +01:00
//Try to add macOS install entry
2021-02-04 15:04:31 +01:00
/*macOSVersion = GetMacOSVersionFromFolder(*Volume->RootDir, SWPrintf("\\%s\\com.apple.installer", ApfsTargetUUID.c_str()));
if ( macOSVersion . notEmpty ( ) & & macOSVersion < MacOsVersion ( " 11 " _XS8 ) ) */ FullTitleInstaller . SWCatf ( " via %ls " , Volume - > getVolLabelOrOSXVolumeNameOrVolName ( ) . wc_str ( ) ) ;
2022-04-26 00:55:56 +02:00
XString8 installerPath = SWPrintf ( " \\ %s \\ com.apple.installer " , Volume - > ApfsTargetUUIDArray [ i ] . toXString8 ( ) . c_str ( ) ) ;
2021-02-04 15:04:31 +01:00
if ( FileExists ( Volume - > RootDir , installerPath ) ) {
XString8 rootDmg = GetAuthRootDmg ( * Volume - > RootDir , installerPath ) ;
rootDmg . replaceAll ( " %20 " _XS8 , " " _XS8 ) ;
// while ( rootDmg.notEmpty() && rootDmg.startWith('/') ) rootDmg.deleteCharsAtPos(0, 1);
rootDmg . replaceAll ( ' / ' , ' \\ ' ) ;
2021-02-06 18:16:46 +01:00
REFIT_VOLUME * targetInstallVolume = Volumes . getVolumeWithApfsContainerUUIDAndFileSystemUUID ( Volume - > ApfsContainerUUID , Volume - > ApfsTargetUUIDArray [ i ] ) ;
if ( targetInstallVolume ) {
2021-03-27 19:53:30 +01:00
EFI_FILE_PROTOCOL * TestFile ;
EFI_STATUS Status = targetInstallVolume - > RootDir - > Open ( targetInstallVolume - > RootDir , & TestFile , L " \\ " , EFI_FILE_MODE_READ , 0 ) ;
if ( EFI_ERROR ( Status ) ) TestFile = NULL ; // if the root of the volume can't be opened (most likely encrypted), add the installer anyway.
if ( rootDmg . isEmpty ( ) | | EFI_ERROR ( Status ) | | FileExists ( * targetInstallVolume - > RootDir , rootDmg ) ) { // rootDmg empty is accepted, to be compatible with previous code
2022-04-26 00:55:56 +02:00
AddLoaderEntry ( SWPrintf ( " \\ %s \\ com.apple.installer \\ boot.efi " , Volume - > ApfsTargetUUIDArray [ i ] . toXString8 ( ) . c_str ( ) ) , NullXString8Array , FullTitleInstaller , LoaderTitleInstaller , Volume , NULL , OSTYPE_OSX_INSTALLER , 0 ) ;
2021-02-04 15:04:31 +01:00
} else {
DBG ( " Dead installer entry found (installer dmg boot file not found : '%s') \n " , rootDmg . c_str ( ) ) ;
}
2021-03-27 19:53:30 +01:00
if ( TestFile ! = NULL ) TestFile - > Close ( TestFile ) ;
2021-02-04 15:04:31 +01:00
} else {
2022-04-26 00:55:56 +02:00
DBG ( " Dead installer entry found (target volume not found : '%s') \n " , Volume - > ApfsTargetUUIDArray [ i ] . toXString8 ( ) . c_str ( ) ) ;
2021-02-04 15:04:31 +01:00
}
}
2020-08-07 10:23:46 +02:00
}
}
}
2020-08-15 22:39:25 +02:00
2021-02-04 15:04:31 +01:00
DBG ( " Entries list before ordering \n " ) ;
for ( size_t idx = 0 ; idx < MainMenu . Entries . sizeIncludingHidden ( ) ; idx + + ) {
if ( MainMenu . Entries . ElementAt ( idx ) . getLOADER_ENTRY ( ) ) {
DBG ( " Entry %zd : %ls%s \n " , idx , MainMenu . Entries . ElementAt ( idx ) . Title . wc_str ( ) , MainMenu . Entries . ElementAt ( idx ) . Hidden ? " (hidden) " : " " ) ;
} else {
DBG ( " Entry %zd : %ls%s \n " , idx , MainMenu . Entries . ElementAt ( idx ) . Title . wc_str ( ) , MainMenu . Entries . ElementAt ( idx ) . Hidden ? " (hidden) " : " " ) ;
}
}
2020-10-22 15:55:30 +02:00
// Hide redundant preboot partition
2020-08-15 22:39:25 +02:00
for ( size_t entryIdx1 = 0 ; entryIdx1 < MainMenu . Entries . sizeIncludingHidden ( ) ; entryIdx1 + + )
{
2020-10-22 15:55:30 +02:00
LOADER_ENTRY * loaderEntry1Ptr = MainMenu . Entries . ElementAt ( entryIdx1 ) . getLOADER_ENTRY ( ) ;
if ( ! loaderEntry1Ptr ) continue ;
LOADER_ENTRY & loaderEntry1 = * loaderEntry1Ptr ;
2020-08-15 22:39:25 +02:00
2022-04-26 00:55:56 +02:00
if ( ( loaderEntry1 . LoaderType = = OSTYPE_OSX | | loaderEntry1 . LoaderType = = OSTYPE_OSX_INSTALLER ) & & loaderEntry1 . APFSTargetUUID . notNull ( ) )
2020-10-22 15:55:30 +02:00
{
2021-02-04 15:04:31 +01:00
size_t entryIdx2 = MainMenu . Entries . getApfsLoaderIdx ( loaderEntry1 . Volume - > ApfsContainerUUID , loaderEntry1 . APFSTargetUUID , loaderEntry1 . LoaderType ) ;
if ( entryIdx2 ! = SIZE_T_MAX ) {
DBG ( " Hiding entry %zd because of entry %zd \n " , entryIdx1 , entryIdx2 ) ;
loaderEntry1 . Hidden = true ;
2020-08-15 22:39:25 +02:00
}
2020-10-22 15:55:30 +02:00
}
2020-08-15 22:39:25 +02:00
}
2020-10-23 08:04:01 +02:00
typedef struct EntryIdx {
size_t idx ;
REFIT_ABSTRACT_MENU_ENTRY * entry ;
EntryIdx ( size_t _idx , REFIT_ABSTRACT_MENU_ENTRY * _entry ) : idx ( _idx ) , entry ( _entry ) { } ;
} EntryIdx ;
2021-01-31 10:50:23 +01:00
2020-10-23 08:04:01 +02:00
XObjArray < EntryIdx > EntriesArrayTmp ;
2021-01-31 10:50:23 +01:00
2020-10-23 08:04:01 +02:00
for ( size_t idx = 0 ; idx < MainMenu . Entries . sizeIncludingHidden ( ) ; idx + + ) {
if ( MainMenu . Entries . ElementAt ( idx ) . getLOADER_ENTRY ( ) ) {
2022-04-26 00:55:56 +02:00
if ( MainMenu . Entries . ElementAt ( idx ) . getLOADER_ENTRY ( ) - > APFSTargetUUID . notNull ( ) ) {
2021-01-31 10:50:23 +01:00
// DBG("Add in EntriesArrayTmp at index %zd Entry %zd : %ls\n", EntriesArrayTmp.size(), idx, MainMenu.Entries.ElementAt(idx).Title.wc_str());
2020-10-23 08:04:01 +02:00
EntriesArrayTmp . AddReference ( new EntryIdx ( idx , & MainMenu . Entries . ElementAt ( idx ) ) , true ) ;
}
}
}
2021-09-28 15:54:31 +02:00
XBool hasMovedSomething ;
2020-10-23 08:04:01 +02:00
2020-10-22 15:55:30 +02:00
// Re-order preboot partition
do {
hasMovedSomething = false ;
2020-10-23 08:04:01 +02:00
for ( size_t idx = 0 ; ! hasMovedSomething & & idx < EntriesArrayTmp . size ( ) ; )
2020-10-22 15:55:30 +02:00
{
2020-10-23 08:04:01 +02:00
LOADER_ENTRY * loaderEntry1Ptr = EntriesArrayTmp . ElementAt ( idx ) . entry - > getLOADER_ENTRY ( ) ;
if ( ! loaderEntry1Ptr ) {
EntriesArrayTmp . RemoveAtIndex ( idx ) ;
// do not increment idx
continue ;
}
2020-10-22 15:55:30 +02:00
LOADER_ENTRY & loaderEntry1 = * loaderEntry1Ptr ;
2020-10-23 08:04:01 +02:00
if ( loaderEntry1 . LoaderType = = OSTYPE_OSX & & ( loaderEntry1 . Volume - > ApfsRole & APPLE_APFS_VOLUME_ROLE_PREBOOT ) ! = 0 )
2020-10-22 15:55:30 +02:00
{
2020-10-23 08:04:01 +02:00
size_t prebootIdx = MainMenu . Entries . getIdx ( loaderEntry1Ptr ) ;
2021-04-12 14:11:01 +02:00
if ( prebootIdx = = SIZE_T_MAX ) {
2021-05-08 11:34:17 +02:00
log_technical_bug ( " %s : prebootIdx == SIZE_T_MAX " , __PRETTY_FUNCTION__ ) ;
2021-04-12 14:11:01 +02:00
} else {
size_t idxMain = MainMenu . Entries . getApfsLoaderIdx ( loaderEntry1 . Volume - > ApfsContainerUUID , loaderEntry1 . APFSTargetUUID , OSTYPE_OSX ) ;
if ( idxMain ! = SIZE_T_MAX & & idxMain ! = prebootIdx + 1 ) {
DBG ( " Move preboot entry %zu before system %zu \n " , prebootIdx , idxMain ) ;
MainMenu . Entries . moveBefore ( prebootIdx , idxMain ) ; // this will move preboot entry just before main
EntriesArrayTmp . RemoveAtIndex ( idx ) ;
hasMovedSomething = true ;
}
2020-10-22 15:55:30 +02:00
}
}
2020-10-23 08:04:01 +02:00
+ + idx ;
}
} while ( hasMovedSomething ) ;
// Re-order installer partition
do {
hasMovedSomething = false ;
for ( size_t idx = 0 ; ! hasMovedSomething & & idx < EntriesArrayTmp . size ( ) ; )
{
LOADER_ENTRY * loaderEntry1Ptr = EntriesArrayTmp . ElementAt ( idx ) . entry - > getLOADER_ENTRY ( ) ;
if ( ! loaderEntry1Ptr ) {
EntriesArrayTmp . RemoveAtIndex ( idx ) ;
// do not increment idx
continue ;
}
LOADER_ENTRY & loaderEntry1 = * loaderEntry1Ptr ;
if ( loaderEntry1 . LoaderType = = OSTYPE_OSX_INSTALLER )
{
size_t installerIdx = MainMenu . Entries . getIdx ( loaderEntry1Ptr ) ;
2021-04-12 14:11:01 +02:00
if ( installerIdx = = SIZE_T_MAX ) {
2021-05-08 11:34:17 +02:00
log_technical_bug ( " %s : installerIdx == SIZE_T_MAX " , __PRETTY_FUNCTION__ ) ;
2020-10-23 08:04:01 +02:00
} else {
2021-04-12 14:11:01 +02:00
size_t idxPreboot = MainMenu . Entries . getApfsPrebootLoaderIdx ( loaderEntry1 . Volume - > ApfsContainerUUID , loaderEntry1 . APFSTargetUUID , OSTYPE_OSX ) ;
if ( idxPreboot ! = SIZE_T_MAX ) {
if ( idxPreboot ! = installerIdx + 1 ) {
DBG ( " Move installer entry %zu before preboot %zu \n " , EntriesArrayTmp . ElementAt ( idx ) . idx , idxPreboot ) ;
MainMenu . Entries . moveBefore ( installerIdx , idxPreboot ) ; // this will move preboot entry just before main
2020-10-23 08:04:01 +02:00
EntriesArrayTmp . RemoveAtIndex ( idx ) ;
hasMovedSomething = true ;
}
2021-04-12 14:11:01 +02:00
} else {
size_t idxMain = MainMenu . Entries . getApfsLoaderIdx ( loaderEntry1 . Volume - > ApfsContainerUUID , loaderEntry1 . APFSTargetUUID , OSTYPE_OSX ) ;
if ( idxMain ! = SIZE_T_MAX ) {
if ( idxMain ! = installerIdx + 1 ) {
DBG ( " Move installer entry %zu before system %zu \n " , EntriesArrayTmp . ElementAt ( idx ) . idx , idxMain ) ;
MainMenu . Entries . moveBefore ( installerIdx , idxMain ) ; // this will move preboot entry just before main
EntriesArrayTmp . RemoveAtIndex ( idx ) ;
hasMovedSomething = true ;
}
}
2020-10-23 08:04:01 +02:00
}
}
}
+ + idx ;
2020-10-22 15:55:30 +02:00
}
} while ( hasMovedSomething ) ;
// Re-order recovery partition
do {
hasMovedSomething = false ;
2020-10-23 08:04:01 +02:00
for ( size_t idx = 0 ; ! hasMovedSomething & & idx < EntriesArrayTmp . size ( ) ; )
2020-10-22 15:55:30 +02:00
{
2020-10-23 08:04:01 +02:00
LOADER_ENTRY * loaderEntry1Ptr = EntriesArrayTmp . ElementAt ( idx ) . entry - > getLOADER_ENTRY ( ) ;
if ( ! loaderEntry1Ptr ) {
EntriesArrayTmp . RemoveAtIndex ( idx ) ;
// do not increment idx
continue ;
}
2020-10-22 15:55:30 +02:00
LOADER_ENTRY & loaderEntry1 = * loaderEntry1Ptr ;
2020-10-23 08:04:01 +02:00
if ( loaderEntry1 . LoaderType = = OSTYPE_RECOVERY & & ( loaderEntry1 . Volume - > ApfsRole & APPLE_APFS_VOLUME_ROLE_RECOVERY ) ! = 0 )
2020-10-22 15:55:30 +02:00
{
2020-10-23 08:04:01 +02:00
size_t recoveryIdx = MainMenu . Entries . getIdx ( loaderEntry1Ptr ) ;
2021-04-12 14:11:01 +02:00
if ( recoveryIdx = = SIZE_T_MAX ) {
2021-05-08 11:34:17 +02:00
log_technical_bug ( " %s : recoveryIdx == SIZE_T_MAX " , __PRETTY_FUNCTION__ ) ;
2020-10-22 15:55:30 +02:00
} else {
2021-04-12 14:11:01 +02:00
size_t idxMain = MainMenu . Entries . getApfsLoaderIdx ( loaderEntry1 . Volume - > ApfsContainerUUID , loaderEntry1 . APFSTargetUUID , OSTYPE_OSX ) ;
if ( idxMain ! = SIZE_T_MAX ) {
if ( idxMain + 1 ! = recoveryIdx ) {
DBG ( " Move recovery entry %zu after system %zu \n " , EntriesArrayTmp . ElementAt ( idx ) . idx , idxMain ) ;
MainMenu . Entries . moveAfter ( recoveryIdx , idxMain ) ; // this will move preboot entry just before main
2020-10-23 08:04:01 +02:00
EntriesArrayTmp . RemoveAtIndex ( idx ) ;
hasMovedSomething = true ;
}
2021-04-12 14:11:01 +02:00
} else {
size_t idxPreboot = MainMenu . Entries . getApfsPrebootLoaderIdx ( loaderEntry1 . Volume - > ApfsContainerUUID , loaderEntry1 . APFSTargetUUID , OSTYPE_OSX ) ;
if ( idxPreboot ! = SIZE_T_MAX ) {
if ( idxPreboot + 1 ! = recoveryIdx ) {
DBG ( " Move recovery entry %zu after preboot %zu \n " , EntriesArrayTmp . ElementAt ( idx ) . idx , idxPreboot ) ;
MainMenu . Entries . moveAfter ( recoveryIdx , idxPreboot ) ; // this will move preboot entry just before main
EntriesArrayTmp . RemoveAtIndex ( idx ) ;
hasMovedSomething = true ;
}
}
2020-10-22 15:55:30 +02:00
}
}
}
2020-10-23 08:04:01 +02:00
+ + idx ;
2020-10-22 15:55:30 +02:00
}
} while ( hasMovedSomething ) ;
2021-02-04 15:04:31 +01:00
2022-08-01 21:34:35 +02:00
DBG ( " Entries list after ordering \n " ) ;
2021-02-04 15:04:31 +01:00
for ( size_t idx = 0 ; idx < MainMenu . Entries . sizeIncludingHidden ( ) ; idx + + ) {
2022-08-01 21:34:35 +02:00
// if ( MainMenu.Entries.ElementAt(idx).getLOADER_ENTRY() ) {
// DBG(" Entry %zd : %ls%s\n", idx, MainMenu.Entries.ElementAt(idx).Title.wc_str(), MainMenu.Entries.ElementAt(idx).Hidden ? " (hidden)" : "");
// }else{
2021-02-04 15:04:31 +01:00
DBG ( " Entry %zd : %ls%s \n " , idx , MainMenu . Entries . ElementAt ( idx ) . Title . wc_str ( ) , MainMenu . Entries . ElementAt ( idx ) . Hidden ? " (hidden) " : " " ) ;
2022-08-01 21:34:35 +02:00
// }
2021-02-04 15:04:31 +01:00
}
2019-09-03 11:58:42 +02:00
}
2021-03-22 13:40:01 +01:00
STATIC void AddCustomSubEntry ( REFIT_VOLUME * Volume ,
IN UINTN CustomIndex ,
IN const XStringW & CustomPath ,
UINT8 parentType ,
IN const CUSTOM_LOADER_SUBENTRY & Custom ,
IN const XStringW & DefaultEntrySettings ,
IN REFIT_MENU_SCREEN * SubMenu )
{
2023-09-05 18:54:23 +02:00
if ( CustomPath . isEmpty ( ) ) return ;
if ( SubMenu = = NULL ) return ;
2021-03-22 13:40:01 +01:00
if ( Custom . settings . Disabled ) {
// DBG("Custom %lsentry %llu skipped because it is disabled.\n", IsSubEntry ? L"sub " : L"", CustomIndex);
return ;
}
#if 0 //if someone want to debug this
DBG ( " Custom %lsentry %llu " , IsSubEntry ? L " sub " : L " " , CustomIndex ) ;
// if (Custom.settings.Title) {
DBG ( " Title: \" %ls \" " , Custom . settings . Title . wc_str ( ) ) ;
// }
// if (Custom.settings.FullTitle) {
DBG ( " FullTitle: \" %ls \" " , Custom . settings . FullTitle . wc_str ( ) ) ;
// }
if ( CustomPath ) {
DBG ( " Path: \" %ls \" " , CustomPath ) ;
}
if ( Custom . settings . Options ! = NULL ) {
DBG ( " Options: \" %ls \" " , Custom . settings . Options ) ;
}
DBG ( " Type:%d Flags:0x%hhX matching " , Custom . settings . Type , Custom . settings . Flags ) ;
if ( Custom . settings . Volume ) {
DBG ( " Volume: \" %ls \" \n " , Custom . settings . Volume ) ;
} else {
DBG ( " all volumes \n " ) ;
}
# endif
LOADER_ENTRY * Entry = NULL ;
if ( ( Volume = = NULL ) | | ( Volume - > RootDir = = NULL ) ) {
return ;
}
if ( Volume - > VolName . isEmpty ( ) ) {
Volume - > VolName = L " Unknown " _XSW ;
}
// do { // when not scanning for kernels, this loop will execute only once
XString8Array CustomOptions = Custom . getLoadOptions ( ) ;
2021-03-25 15:32:56 +01:00
UINT8 newCustomFlags = Custom . getFlags ( gSettings . SystemParameters . NoCaches ) ;
2021-03-22 13:40:01 +01:00
// Create an entry for this volume
Entry = CreateLoaderEntry ( CustomPath , CustomOptions , Custom . getFullTitle ( ) , Custom . getTitle ( ) , Volume ,
NULL , NULL ,
parentType , newCustomFlags , 0 , { 0 , 0 , 0 , 0 } , 0 , NullXImage ,
2021-09-28 10:28:45 +02:00
/*(KERNEL_AND_KEXT_PATCHES *)(((UINTN)Custom) + OFFSET_OF(CUSTOM_LOADER_ENTRY, KernelAndKextPatches))*/ NULL , true ) ;
2021-03-22 13:40:01 +01:00
if ( Entry ! = NULL ) {
if ( OSFLAG_ISUNSET ( newCustomFlags , OSFLAG_NODEFAULTMENU ) ) {
Entry - > AddDefaultMenu ( ) ;
}
SubMenu - > AddMenuEntry ( Entry , true ) ;
}
}
2021-03-19 21:32:42 +01:00
STATIC void AddCustomEntry ( IN UINTN CustomIndex ,
IN const XStringW & _CustomPath ,
IN const CUSTOM_LOADER_ENTRY & Custom ,
IN const XStringW & DefaultEntrySettings ,
IN REFIT_MENU_SCREEN * SubMenu )
2019-09-03 11:58:42 +02:00
{
UINTN VolumeIndex ;
REFIT_VOLUME * Volume ;
REFIT_DIR_ITER SIter ;
REFIT_DIR_ITER * Iter = & SIter ;
CHAR16 PartUUID [ 40 ] ;
2021-03-19 21:32:42 +01:00
XStringW CustomPath = _CustomPath ;
2021-09-28 15:54:31 +02:00
XBool FindCustomPath = ( CustomPath . isEmpty ( ) ) ;
2019-09-03 11:58:42 +02:00
2021-03-22 13:40:01 +01:00
if ( SubMenu ! = NULL ) panic ( " Call AddCustomSubEntry instead " ) ;
if ( FindCustomPath & & ( Custom . settings . Type ! = OSTYPE_LINEFI ) & & ( Custom . settings . Type ! = OSTYPE_LIN ) ) {
2020-05-06 00:23:59 +02:00
// DBG("Custom %lsentry %llu skipped because it didn't have a ", IsSubEntry ? L"sub " : L"", CustomIndex);
2021-03-19 21:32:42 +01:00
// if (Custom.Type == 0) {
2020-04-03 22:00:42 +02:00
// DBG("Type.\n");
// } else {
// DBG("Path.\n");
// }
2019-09-03 11:58:42 +02:00
return ;
}
2021-03-25 15:32:56 +01:00
if ( OSFLAG_ISSET ( Custom . getFlags ( gSettings . SystemParameters . NoCaches ) , 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
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 ) ;
2021-03-22 13:40:01 +01:00
// if (Custom.settings.Title) {
DBG ( " Title: \" %ls \" " , Custom . settings . Title . wc_str ( ) ) ;
2020-04-03 22:00:42 +02:00
// }
2021-03-22 13:40:01 +01:00
// if (Custom.settings.FullTitle) {
DBG ( " FullTitle: \" %ls \" " , Custom . settings . FullTitle . wc_str ( ) ) ;
2020-04-03 22:00:42 +02:00
// }
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
}
2021-03-22 13:40:01 +01:00
if ( Custom . settings . Options ! = NULL ) {
DBG ( " Options: \" %ls \" " , Custom . settings . Options ) ;
2019-09-03 11:58:42 +02:00
}
2021-03-22 13:40:01 +01:00
DBG ( " Type:%d Flags:0x%hhX matching " , Custom . settings . Type , Custom . settings . Flags ) ;
if ( Custom . settings . Volume ) {
DBG ( " Volume: \" %ls \" \n " , Custom . settings . 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
LOADER_ENTRY * Entry = NULL ;
2021-03-23 09:32:57 +01:00
XIcon Image = Custom . Image ;
XIcon DriveImage = Custom . DriveImage ;
2020-04-03 22:00:42 +02:00
2022-04-26 00:55:56 +02:00
EFI_GUID Guid ;
2019-09-03 11:58:42 +02:00
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 ;
}
2020-08-09 17:55:30 +02:00
if ( Volume - > VolName . isEmpty ( ) ) {
Volume - > VolName = L " Unknown " _XSW ;
2019-09-03 11:58:42 +02:00
}
2020-08-09 17:55:30 +02:00
DBG ( " Checking volume \" %ls \" (%ls) ... " , Volume - > VolName . wc_str ( ) , Volume - > DevicePathString . wc_str ( ) ) ;
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
2021-03-22 13:40:01 +01:00
if ( Custom . settings . VolumeType ! = 0 & & ( ( 1 < < Volume - > DiskKind ) & Custom . settings . VolumeType ) = = 0 ) {
2020-04-11 14:34:59 +02:00
DBG ( " skipped because media is ignored \n " ) ;
continue ;
}
2020-12-01 20:09:30 +01: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-04-11 14:34:59 +02:00
2019-09-03 11:58:42 +02:00
if ( Volume - > Hidden ) {
DBG ( " skipped because volume is hidden \n " ) ;
continue ;
}
2020-12-01 20:09:30 +01:00
2020-05-06 00:23:59 +02:00
// Check for exact volume matches (devicepath / volumelabel)
2021-03-22 13:40:01 +01:00
if ( Custom . settings . Volume . notEmpty ( ) ) {
if ( ( StrStr ( Volume - > DevicePathString . wc_str ( ) , Custom . settings . Volume . wc_str ( ) ) = = NULL ) & &
( ( Volume - > VolName . isEmpty ( ) ) | | ( StrStr ( Volume - > VolName . wc_str ( ) , Custom . settings . Volume . wc_str ( ) ) = = NULL ) ) ) {
2021-09-28 15:54:31 +02:00
XBool CustomEntryFound = false ;
2020-12-01 20:09:30 +01:00
//..\VenMedia(BE74FCF7-0B7C-49F3-9147-01F4042E6842,E97E25EA28F4DF46AAD44CC3F12E28D3)
EFI_DEVICE_PATH * MediaPath = Clover_FindDevicePathNodeWithType ( Volume - > DevicePath , MEDIA_DEVICE_PATH , MEDIA_VENDOR_DP ) ;
if ( MediaPath ) {
2022-04-26 00:55:56 +02:00
EFI_GUID MediaPathGuid = * ( EFI_GUID * ) & ( ( VENDOR_DEVICE_PATH_WITH_DATA * ) MediaPath ) - > VendorDefinedData ;
XStringW MediaPathGuidStr = MediaPathGuid . toXStringW ( ) ;
2020-12-01 20:09:30 +01:00
// DBG(" checking '%ls'\n", MediaPathGuidStr.wc_str());
2021-03-22 13:40:01 +01:00
if ( StrStr ( Custom . settings . Volume . wc_str ( ) , MediaPathGuidStr . wc_str ( ) ) ) {
DBG ( " - found entry for volume '%ls', '%ls' \n " , Custom . settings . Volume . wc_str ( ) , MediaPathGuidStr . wc_str ( ) ) ;
2020-12-01 20:09:30 +01:00
CustomEntryFound = true ;
} else {
2021-03-22 13:40:01 +01:00
DBG ( " - search volume '%ls', but MediaPath '%ls' \n " , Custom . settings . Volume . wc_str ( ) , MediaPathGuidStr . wc_str ( ) ) ;
2020-12-01 20:09:30 +01:00
}
}
if ( ! CustomEntryFound ) {
DBG ( " skipped because volume does not match \n " ) ;
continue ;
}
2019-09-03 11:58:42 +02:00
}
}
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
2022-04-26 00:55:56 +02:00
if ( Guid . isNull ( ) ) {
2019-09-03 11:58:42 +02:00
DBG ( " skipped because volume does not have partition uuid \n " ) ;
continue ;
}
2022-04-26 00:55:56 +02:00
snwprintf ( PartUUID , sizeof ( PartUUID ) , " %s " , Guid . toXString8 ( ) . c_str ( ) ) ;
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
2021-03-22 13:40:01 +01:00
if ( Custom . settings . Type = = OSTYPE_LIN | | Custom . settings . KernelScan ! = KERNEL_SCAN_ALL ) {
LinuxScan ( Volume , Custom . settings . KernelScan , Custom . settings . Type , & CustomPath , & Image ) ;
2020-05-06 00:23:59 +02:00
}
2021-03-22 13:40:01 +01:00
if ( Custom . settings . Type = = OSTYPE_LINEFI ) {
2020-05-06 00:23:59 +02:00
// 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 ) ) {
2021-03-22 13:40:01 +01:00
DBG ( " skipped because path '%ls' does not exist \n " , CustomPath . wc_str ( ) ) ;
2019-09-03 11:58:42 +02:00
continue ;
}
// Change to custom image if needed
2021-03-23 09:32:57 +01:00
if ( Image . isEmpty ( ) & & Custom . settings . dgetImagePath ( ) . notEmpty ( ) ) {
2023-11-06 21:53:57 +01:00
Image . LoadXImage ( & ThemeX - > getThemeDir ( ) , Custom . settings . dgetImagePath ( ) ) ;
2020-04-13 00:28:01 +02:00
if ( Image . isEmpty ( ) ) {
2023-11-06 21:53:57 +01:00
Image . LoadXImage ( & ThemeX - > getThemeDir ( ) , L " os_ " _XSW + Custom . settings . dgetImagePath ( ) ) ;
2020-04-13 13:13:37 +02:00
if ( Image . isEmpty ( ) ) {
2021-03-23 09:32:57 +01:00
Image . LoadXImage ( & self . getCloverDir ( ) , Custom . settings . dgetImagePath ( ) ) ;
2020-04-13 13:13:37 +02:00
if ( Image . isEmpty ( ) ) {
2021-03-23 09:32:57 +01:00
Image . LoadXImage ( & self . getSelfVolumeRootDir ( ) , Custom . settings . dgetImagePath ( ) ) ;
2020-04-13 13:13:37 +02:00
if ( Image . isEmpty ( ) ) {
2021-03-23 09:32:57 +01:00
Image . LoadXImage ( Volume - > RootDir , Custom . settings . dgetImagePath ( ) ) ;
2020-04-13 13:13:37 +02:00
}
}
}
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
2021-03-23 09:32:57 +01:00
if ( DriveImage . isEmpty ( ) & & Custom . settings . dgetDriveImagePath ( ) . notEmpty ( ) ) {
2023-11-06 21:53:57 +01:00
DriveImage . LoadXImage ( & ThemeX - > getThemeDir ( ) , Custom . settings . dgetDriveImagePath ( ) ) ;
2020-04-13 13:13:37 +02:00
if ( DriveImage . isEmpty ( ) ) {
2021-03-23 09:32:57 +01:00
DriveImage . LoadXImage ( & self . getCloverDir ( ) , Custom . settings . dgetImagePath ( ) ) ;
2020-04-13 13:13:37 +02:00
if ( DriveImage . isEmpty ( ) ) {
2021-03-23 09:32:57 +01:00
DriveImage . LoadXImage ( & self . getSelfVolumeRootDir ( ) , Custom . settings . dgetImagePath ( ) ) ;
2020-04-13 13:13:37 +02:00
if ( DriveImage . isEmpty ( ) ) {
2021-03-23 09:32:57 +01:00
DriveImage . LoadXImage ( Volume - > RootDir , Custom . settings . dgetImagePath ( ) ) ;
2020-04-13 13:13:37 +02:00
}
}
}
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
2021-03-22 13:40:01 +01:00
XString8Array CustomOptions = Custom . getLoadOptions ( ) ;
2020-05-06 00:23:59 +02:00
// for LINEFI with option KERNEL_SCAN_ALL, use this loop to search for kernels
2021-03-22 13:40:01 +01:00
if ( FindCustomPath & & Custom . settings . Type = = OSTYPE_LINEFI & & Custom . settings . 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
2021-03-25 15:32:56 +01:00
UINT8 newCustomFlags = Custom . getFlags ( gSettings . SystemParameters . NoCaches ) ;
2021-03-19 21:32:42 +01:00
2020-05-06 00:23:59 +02:00
// Check to make sure if we should update linux custom options or not
2021-03-25 15:32:56 +01:00
if ( FindCustomPath & & Custom . settings . Type = = OSTYPE_LINEFI & & OSFLAG_ISUNSET ( Custom . getFlags ( gSettings . SystemParameters . NoCaches ) , OSFLAG_NODEFAULTARGS ) ) {
2019-09-03 11:58:42 +02:00
// Find the init ram image and select root
2021-03-22 13:40:01 +01:00
CustomOptions = LinuxKernelOptions ( Iter - > DirHandle , Basename ( CustomPath . wc_str ( ) ) + LINUX_LOADER_PATH . length ( ) , PartUUID , Custom . getLoadOptions ( ) ) ;
2021-03-25 15:32:56 +01:00
newCustomFlags = OSFLAG_SET ( Custom . getFlags ( gSettings . SystemParameters . NoCaches ) , 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
2021-03-22 13:40:01 +01:00
if ( true ) {
2021-09-28 15:54:31 +02:00
XBool BetterMatch = false ;
2021-03-22 13:40:01 +01:00
for ( size_t i = 0 ; i < GlobalConfig . CustomEntries . size ( ) ; + + i ) {
CUSTOM_LOADER_ENTRY & CustomEntry = GlobalConfig . CustomEntries [ i ] ;
if ( CustomEntry . settings . Disabled ) continue ; // before, disabled entries settings weren't loaded.
2019-09-03 11:58:42 +02:00
// Don't match against this custom
2021-03-20 15:29:34 +01:00
if ( & CustomEntry = = & Custom ) {
2019-09-03 11:58:42 +02:00
continue ;
}
// Can only match the same types
2021-03-22 13:40:01 +01:00
if ( Custom . settings . Type ! = CustomEntry . settings . Type ) {
2019-09-03 11:58:42 +02:00
continue ;
}
// Check if the volume string matches
2021-03-22 13:40:01 +01:00
if ( Custom . settings . Volume ! = CustomEntry . settings . Volume ) {
if ( CustomEntry . settings . Volume . isEmpty ( ) ) {
2019-09-03 11:58:42 +02:00
// Less precise volume match
2021-03-22 13:40:01 +01:00
if ( Custom . settings . Path ! = CustomEntry . settings . Path ) {
2019-09-03 11:58:42 +02:00
// Better path match
2021-04-11 07:18:52 +02:00
BetterMatch = ( ( CustomEntry . settings . Path . notEmpty ( ) ) & & CustomPath . isEqual ( CustomEntry . settings . Path ) & &
2021-03-22 13:40:01 +01:00
( ( Custom . settings . VolumeType = = CustomEntry . settings . VolumeType ) | |
( ( 1ull < < Volume - > DiskKind ) & Custom . settings . VolumeType ) ! = 0 ) ) ;
2019-09-03 11:58:42 +02:00
}
2021-03-22 13:40:01 +01:00
} else if ( ( StrStr ( Volume - > DevicePathString . wc_str ( ) , Custom . settings . Volume . wc_str ( ) ) = = NULL ) & &
( ( Volume - > VolName . isEmpty ( ) ) | | ( StrStr ( Volume - > VolName . wc_str ( ) , Custom . settings . Volume . wc_str ( ) ) = = NULL ) ) ) {
if ( Custom . settings . Volume . isEmpty ( ) ) {
2019-09-03 11:58:42 +02:00
// More precise volume match
2021-03-22 13:40:01 +01:00
if ( Custom . settings . Path ! = CustomEntry . settings . Path ) {
2019-09-03 11:58:42 +02:00
// Better path match
2021-04-11 07:18:52 +02:00
BetterMatch = ( ( CustomEntry . settings . Path . notEmpty ( ) ) & & CustomPath . isEqual ( CustomEntry . settings . Path ) & &
2021-03-22 13:40:01 +01:00
( ( Custom . settings . VolumeType = = CustomEntry . settings . VolumeType ) | |
( ( 1ull < < Volume - > DiskKind ) & Custom . settings . VolumeType ) ! = 0 ) ) ;
} else if ( Custom . settings . VolumeType ! = CustomEntry . settings . VolumeType ) {
2019-09-03 11:58:42 +02:00
// More precise volume type match
2021-03-22 13:40:01 +01:00
BetterMatch = ( ( Custom . settings . VolumeType = = 0 ) & &
( ( 1ull < < Volume - > DiskKind ) & Custom . settings . VolumeType ) ! = 0 ) ;
2019-09-03 11:58:42 +02:00
} else {
// Better match
2021-09-28 10:28:45 +02:00
BetterMatch = true ;
2019-09-03 11:58:42 +02:00
}
// Duplicate volume match
2021-03-22 13:40:01 +01:00
} else if ( Custom . settings . Path ! = CustomEntry . settings . Path ) {
2019-09-03 11:58:42 +02:00
// Better path match
2021-04-11 07:18:52 +02:00
BetterMatch = ( ( CustomEntry . settings . Path . notEmpty ( ) ) & & CustomPath . isEqual ( CustomEntry . settings . Path ) & &
2021-03-22 13:40:01 +01:00
( ( Custom . settings . VolumeType = = CustomEntry . settings . VolumeType ) | |
( ( 1ull < < Volume - > DiskKind ) & Custom . settings . VolumeType ) ! = 0 ) ) ;
2019-09-03 11:58:42 +02:00
// Duplicate path match
2021-03-22 13:40:01 +01:00
} else if ( Custom . settings . VolumeType ! = CustomEntry . settings . VolumeType ) {
2019-09-03 11:58:42 +02:00
// More precise volume type match
2021-03-22 13:40:01 +01:00
BetterMatch = ( ( Custom . settings . VolumeType = = 0 ) & &
( ( 1ull < < Volume - > DiskKind ) & Custom . settings . VolumeType ) ! = 0 ) ;
2019-09-03 11:58:42 +02:00
} else {
// Duplicate entry
BetterMatch = ( i < = CustomIndex ) ;
}
}
// Duplicate volume match
2021-03-22 13:40:01 +01:00
} else if ( Custom . settings . Path ! = CustomEntry . settings . Path ) {
if ( CustomEntry . settings . Path . isEmpty ( ) ) {
2019-09-03 11:58:42 +02:00
// Less precise path match
2021-03-22 13:40:01 +01:00
BetterMatch = ( ( Custom . settings . VolumeType ! = CustomEntry . settings . VolumeType ) & &
( ( 1ull < < Volume - > DiskKind ) & Custom . settings . VolumeType ) ! = 0 ) ;
2021-04-11 07:18:52 +02:00
} else if ( CustomPath . isEqual ( CustomEntry . settings . Path ) ) {
2021-03-22 13:40:01 +01:00
if ( Custom . settings . Path . isEmpty ( ) ) {
2019-09-03 11:58:42 +02:00
// More precise path and volume type match
2021-03-22 13:40:01 +01:00
BetterMatch = ( ( Custom . settings . VolumeType = = CustomEntry . settings . VolumeType ) | |
( ( 1ull < < Volume - > DiskKind ) & Custom . settings . VolumeType ) ! = 0 ) ;
} else if ( Custom . settings . VolumeType ! = CustomEntry . settings . VolumeType ) {
2019-09-03 11:58:42 +02:00
// More precise volume type match
2021-03-22 13:40:01 +01:00
BetterMatch = ( ( Custom . settings . VolumeType = = 0 ) & &
( ( 1ull < < Volume - > DiskKind ) & Custom . settings . VolumeType ) ! = 0 ) ;
2019-09-03 11:58:42 +02:00
} else {
// Duplicate entry
BetterMatch = ( i < = CustomIndex ) ;
}
}
// Duplicate path match
2021-03-22 13:40:01 +01:00
} else if ( Custom . settings . VolumeType ! = CustomEntry . settings . VolumeType ) {
2019-09-03 11:58:42 +02:00
// More precise volume type match
2021-03-22 13:40:01 +01:00
BetterMatch = ( ( Custom . settings . VolumeType = = 0 ) & &
( ( 1ull < < Volume - > DiskKind ) & Custom . settings . VolumeType ) ! = 0 ) ;
2019-09-03 11:58:42 +02:00
} else {
// Duplicate entry
BetterMatch = ( i < = CustomIndex ) ;
}
if ( BetterMatch ) {
2021-03-19 21:32:42 +01:00
DBG ( " skipped because custom entry %zu is a better match and will produce a duplicate entry \n " , i ) ;
2019-09-03 11:58:42 +02:00
break ;
}
}
if ( BetterMatch ) {
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
2021-03-23 09:32:57 +01:00
Entry = CreateLoaderEntry ( CustomPath , CustomOptions , Custom . settings . FullTitle , Custom . settings . dgetTitle ( ) , Volume ,
2020-04-12 17:36:40 +02:00
( Image . isEmpty ( ) ? NULL : & Image ) , ( DriveImage . isEmpty ( ) ? NULL : & DriveImage ) ,
2021-03-23 09:32:57 +01:00
Custom . settings . Type , newCustomFlags , Custom . settings . Hotkey , Custom . settings . BootBgColor , Custom . CustomLogoType , Custom . CustomLogoImage ,
2021-09-28 10:28:45 +02:00
/*(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 ) {
2021-04-28 20:30:34 +02:00
if ( Custom . settings . Settings . notEmpty ( ) ) {
DBG ( " Custom settings: %ls.plist will %s be applied \n " , Custom . settings . Settings . wc_str ( ) , Custom . settings . CommonSettings ? " not " : " " ) ;
}
2021-03-22 13:40:01 +01:00
if ( ! Custom . settings . CommonSettings ) {
2021-03-19 21:32:42 +01:00
Entry - > Settings = DefaultEntrySettings ;
2019-09-03 11:58:42 +02:00
}
2021-04-28 20:30:34 +02:00
if ( Custom . settings . ForceTextMode ) {
Entry - > Flags = OSFLAG_UNSET ( Entry - > Flags , OSFLAG_USEGRAPHICS ) ;
}
2021-03-19 21:32:42 +01:00
if ( OSFLAG_ISUNSET ( newCustomFlags , OSFLAG_NODEFAULTMENU ) ) {
2020-05-16 22:07:27 +02:00
Entry - > AddDefaultMenu ( ) ;
2021-03-19 21:32:42 +01:00
} else if ( Custom . SubEntries . notEmpty ( ) ) {
2019-09-03 11:58:42 +02:00
UINTN CustomSubIndex = 0 ;
// Add subscreen
2020-03-04 07:21:43 +01:00
REFIT_MENU_SCREEN * SubScreen = new REFIT_MENU_SCREEN ;
2021-03-23 09:32:57 +01:00
SubScreen - > Title . SWPrintf ( " Boot Options for %ls on %ls " , ( Custom . settings . dgetTitle ( ) . notEmpty ( ) ) ? XStringW ( Custom . settings . dgetTitle ( ) ) . wc_str ( ) : CustomPath . wc_str ( ) , Entry - > DisplayedVolName . wc_str ( ) ) ;
2021-03-22 13:40:01 +01:00
SubScreen - > TitleImage = Entry - > Image ;
SubScreen - > ID = Custom . settings . Type + 20 ;
SubScreen - > GetAnime ( ) ;
VolumeSize = RShiftU64 ( MultU64x32 ( Volume - > BlockIO - > Media - > LastBlock , Volume - > BlockIO - > Media - > BlockSize ) , 20 ) ;
SubScreen - > AddMenuInfoLine_f ( " Volume size: %lldMb " , VolumeSize ) ;
SubScreen - > AddMenuInfoLine_f ( " %ls " , FileDevicePathToXStringW ( Entry - > DevicePath ) . wc_str ( ) ) ;
2022-04-26 00:55:56 +02:00
if ( Guid . notNull ( ) ) {
SubScreen - > AddMenuInfoLine_f ( " UUID: %s " , Guid . toXString8 ( ) . c_str ( ) ) ;
2021-03-22 13:40:01 +01:00
}
SubScreen - > AddMenuInfoLine_f ( " Options: %s " , Entry - > LoadOptions . ConcatAll ( " " _XS8 ) . c_str ( ) ) ;
DBG ( " Create sub entries \n " ) ;
for ( size_t CustomSubEntryIndex = 0 ; CustomSubEntryIndex < Custom . SubEntries . size ( ) ; + + CustomSubEntryIndex ) {
const CUSTOM_LOADER_SUBENTRY & CustomSubEntry = Custom . SubEntries [ CustomSubEntryIndex ] ;
2023-09-05 18:54:23 +02:00
AddCustomSubEntry ( Volume , CustomSubIndex + + , Custom . settings . Path . notEmpty ( ) ? Custom . settings . Path : CustomPath , Custom . settings . Type , CustomSubEntry , Custom . settings . Settings , SubScreen ) ;
2019-09-03 11:58:42 +02:00
}
2021-03-22 13:40:01 +01:00
SubScreen - > AddMenuEntry ( & MenuEntryReturn , true ) ;
Entry - > SubScreen = SubScreen ;
2019-09-03 11:58:42 +02:00
}
2023-09-05 18:54:23 +02:00
MainMenu . AddMenuEntry ( Entry , true ) ;
2021-03-22 13:40:01 +01:00
Entry - > Hidden = Custom . settings . Hidden ;
if ( Custom . settings . Hidden ) DBG ( " hiding entry because Custom.settings.Hidden \n " ) ;
2019-09-03 11:58:42 +02:00
}
2021-03-22 13:40:01 +01:00
} while ( FindCustomPath & & Custom . settings . Type = = OSTYPE_LINEFI & & Custom . settings . KernelScan = = KERNEL_SCAN_ALL ) ; // repeat loop only for kernel scanning
2020-05-06 00:23:59 +02:00
2019-09-03 11:58:42 +02:00
// Close the kernel boot directory
2021-03-22 13:40:01 +01:00
if ( FindCustomPath & & Custom . settings . 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
2020-10-03 19:02:31 +02:00
void AddCustomEntries ( void )
2019-09-03 11:58:42 +02:00
{
2021-03-22 13:40:01 +01:00
if ( GlobalConfig . CustomEntries . isEmpty ( ) ) return ;
2019-09-03 11:58:42 +02:00
//DBG("Custom entries start\n");
DbgHeader ( " AddCustomEntries " ) ;
// Traverse the custom entries
2021-03-22 13:40:01 +01:00
for ( size_t i = 0 ; i < GlobalConfig . CustomEntries . size ( ) ; + + i ) {
CUSTOM_LOADER_ENTRY & Custom = GlobalConfig . CustomEntries [ i ] ;
2021-03-23 09:32:57 +01:00
DBG ( " - [00]: '%s' \n " , Custom . settings . FullTitle . isEmpty ( ) ? Custom . settings . dgetTitle ( ) . c_str ( ) : Custom . settings . FullTitle . c_str ( ) ) ;
2021-03-22 13:40:01 +01:00
if ( Custom . settings . Disabled ) {
DBG ( " Disabled \n " ) ;
continue ; // before, disabled entries settings weren't loaded.
}
if ( ( Custom . settings . Path . isEmpty ( ) ) & & ( Custom . settings . Type ! = 0 ) ) {
if ( OSTYPE_IS_OSX ( Custom . settings . Type ) ) {
AddCustomEntry ( i , MACOSX_LOADER_PATH , Custom , Custom . settings . Settings , NULL ) ;
} else if ( OSTYPE_IS_OSX_RECOVERY ( Custom . settings . Type ) ) {
AddCustomEntry ( i , L " \\ com.apple.recovery.boot \\ boot.efi " _XSW , Custom , Custom . settings . Settings , NULL ) ;
} else if ( OSTYPE_IS_OSX_INSTALLER ( Custom . settings . Type ) ) {
2019-09-03 11:58:42 +02:00
UINTN Index = 0 ;
while ( Index < OSXInstallerPathsCount ) {
2021-03-22 13:40:01 +01:00
AddCustomEntry ( i , OSXInstallerPaths [ Index + + ] , Custom , Custom . settings . Settings , NULL ) ;
2019-09-03 11:58:42 +02:00
}
2021-03-22 13:40:01 +01:00
} else if ( OSTYPE_IS_WINDOWS ( Custom . settings . Type ) ) {
AddCustomEntry ( i , L " \\ EFI \\ Microsoft \\ Boot \\ bootmgfw.efi " _XSW , Custom , Custom . settings . Settings , NULL ) ;
} else if ( OSTYPE_IS_LINUX ( Custom . settings . Type ) ) {
2019-09-03 11:58:42 +02:00
# if defined(ANDX86)
2020-05-06 00:37:43 +02:00
for ( UINTN Index = 0 ; Index < AndroidEntryDataCount ; + + Index ) {
2021-03-22 13:40:01 +01:00
AddCustomEntry ( i , AndroidEntryData [ Index ] . Path , Custom , Custom . settings . Settings , NULL ) ;
2019-09-03 11:58:42 +02:00
}
# endif
2021-03-22 13:40:01 +01:00
AddCustomEntry ( i , NullXStringW , Custom , Custom . settings . Settings , NULL ) ;
} else if ( Custom . settings . Type = = OSTYPE_LINEFI ) {
AddCustomEntry ( i , NullXStringW , Custom , Custom . settings . Settings , NULL ) ;
2019-09-03 11:58:42 +02:00
} else {
2021-03-22 13:40:01 +01:00
AddCustomEntry ( i , BOOT_LOADER_PATH , Custom , Custom . settings . Settings , NULL ) ;
2019-09-03 11:58:42 +02:00
}
} else {
2021-03-22 13:40:01 +01:00
AddCustomEntry ( i , Custom . settings . Path , Custom , Custom . settings . Settings , NULL ) ;
2019-09-03 11:58:42 +02:00
}
}
//DBG("Custom entries finish\n");
}