diff --git a/rEFIt_UEFI/Platform/APFS.cpp b/rEFIt_UEFI/Platform/APFS.cpp index 5a4d4fbeb..c52d916d0 100644 --- a/rEFIt_UEFI/Platform/APFS.cpp +++ b/rEFIt_UEFI/Platform/APFS.cpp @@ -7,6 +7,7 @@ #include "Platform.h" #include "guid.h" +#include "APFS.h" /* S. Mitrofanov 08.06.2016 @@ -28,21 +29,16 @@ * 3: APFS Volume Recovery 521.1 MB disk1s3 * 4: APFS Volume VM 1.1 GB disk1s4 */ -UINTN APFSUUIDBankCounter = 0; -UINT8 *APFSUUIDBank = NULL; -//Vednor APFS device path signature -//BE74FCF7-0B7C-49F3-9147-01F4042E6842 -EFI_GUID APFSSignature = {0xBE74FCF7, 0x0B7C, 0x49F3, { 0x91, 0x47, 0x01, 0xf4, 0x04, 0x2E, 0x68, 0x42 }}; -BOOLEAN APFSSupport = FALSE; - -//Function for obtaining unique part id from APFS partition -//IN DevicePath -//Out: EFI_GUID -//null if it is not APFS part +/* + * Function for obtaining unique part id from APFS partition + * IN: DevicePath + * OUT: EFI_GUID + * returns null if it is not APFS part + */ EFI_GUID *APFSPartitionUUIDExtract( - IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath ) { while (!IsDevicePathEndType(DevicePath) && @@ -51,35 +47,36 @@ EFI_GUID *APFSPartitionUUIDExtract( } if (DevicePathType(DevicePath) == MEDIA_DEVICE_PATH && DevicePathSubType (DevicePath) == MEDIA_VENDOR_DP) { //Check that vendor-assigned GUID defines APFS Container Partition - if ( GuidLEToStr((EFI_GUID *)((UINT8 *)DevicePath+0x04)).equalIC(GuidLEToStr(&APFSSignature)) ) { + if ( GuidLEToXString8((EFI_GUID *)((UINT8 *)DevicePath+0x04)).equalIC(ApfsSignatureUUID) ) { return (EFI_GUID *)((UINT8 *)DevicePath+0x14); } } return NULL; } -UINT8 *APFSContainer_Support(VOID) { - /* - * S. Mtr 2017 - * APFS Container partition support - * Gather System PartitionUniqueGUID - * edit: 17.06.2017 - * Fiil UUIDBank only with APFS container UUIDs - */ - UINTN VolumeIndex; - REFIT_VOLUME *Volume; - EFI_GUID *TmpUUID = NULL; - - //Fill APFSUUIDBank - APFSUUIDBank = (__typeof__(APFSUUIDBank))AllocateZeroPool(0x10*Volumes.size()); - for (VolumeIndex = 0; VolumeIndex < Volumes.size(); VolumeIndex++) { - Volume = &Volumes[VolumeIndex]; - //Check that current volume - apfs partition - if ((TmpUUID = APFSPartitionUUIDExtract(Volume->DevicePath)) != NULL){ - CopyMem(APFSUUIDBank+APFSUUIDBankCounter*0x10,(UINT8 *)TmpUUID,0x10); - APFSUUIDBankCounter++; - } - } - return APFSUUIDBank; +/* + * Function for obtaining unique part id from APFS partition + * IN: DevicePath + * OUT: EFI_GUID + * returns empty string if it is not APFS part + */ +XString8 APFSPartitionUUIDExtractAsXString8( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_GUID* uuid = APFSPartitionUUIDExtract(DevicePath); + if ( uuid ) return GuidLEToXString8(uuid); + return ""_XS8; } + +//XStringW APFSPartitionUUIDExtractAsXStringW( +// IN EFI_DEVICE_PATH_PROTOCOL *DevicePath +// ) +//{ +// EFI_GUID* uuid = APFSPartitionUUIDExtract(DevicePath); +// if ( uuid ) return GuidLEToXStringW(uuid); +// return L""_XSW; +//} + + diff --git a/rEFIt_UEFI/Platform/APFS.h b/rEFIt_UEFI/Platform/APFS.h index 9383f9fac..dbf8f3d41 100644 --- a/rEFIt_UEFI/Platform/APFS.h +++ b/rEFIt_UEFI/Platform/APFS.h @@ -8,23 +8,28 @@ #ifndef PLATFORM_APFS_H_ #define PLATFORM_APFS_H_ -/* Switch for APFS support */ -extern UINTN APFSUUIDBankCounter; -extern UINT8 *APFSUUIDBank; -extern EFI_GUID APFSSignature; -extern BOOLEAN APFSSupport; + +constexpr LString8 ApfsSignatureUUID = "BE74FCF7-0B7C-49F3-9147-01F4042E6842"; -UINT8 *APFSContainer_Support(VOID); - -//Function for obtaining unique part id from APFS partition -//IN DevicePath -//Out: EFI_GUID -//null if it is not APFS part +/* + * Function for obtaining unique part id from APFS partition + * IN: DevicePath + * OUT: EFI_GUID + * returns null if it is not APFS part + */ EFI_GUID *APFSPartitionUUIDExtract( - IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath ); +XString8 APFSPartitionUUIDExtractAsXString8( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + +//XStringW APFSPartitionUUIDExtractAsXStringW( +// IN EFI_DEVICE_PATH_PROTOCOL *DevicePath +// ); + #endif /* PLATFORM_APFS_H_ */ diff --git a/rEFIt_UEFI/Platform/Hibernate.cpp b/rEFIt_UEFI/Platform/Hibernate.cpp index f3d25c777..7019f70da 100644 --- a/rEFIt_UEFI/Platform/Hibernate.cpp +++ b/rEFIt_UEFI/Platform/Hibernate.cpp @@ -926,7 +926,7 @@ IsOsxHibernated (IN LOADER_ENTRY *Entry) DBG(" cant convert Str %ls to GUID\n", Ptr); } else { //TmpStr = PoolPrint(L"%s", strguid(&TmpGuid)); - XStringW TmpStr = GuidLEToStr(&TmpGuid); + XStringW TmpStr = GuidLEToXStringW(&TmpGuid); // DBG("got the guid %ls\n", TmpStr); CopyMem((VOID*)Ptr, TmpStr.wc_str(), TmpStr.sizeInNativeChars()); } diff --git a/rEFIt_UEFI/Platform/Nvram.cpp b/rEFIt_UEFI/Platform/Nvram.cpp index d039bd560..763bca61a 100644 --- a/rEFIt_UEFI/Platform/Nvram.cpp +++ b/rEFIt_UEFI/Platform/Nvram.cpp @@ -1165,7 +1165,7 @@ FindStartupDiskVolume ( EFI_DEVICE_PATH *MediaPath = FindDevicePathNodeWithType(DevicePath, MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP); if (MediaPath) { EFI_GUID *MediaPathGuid = (EFI_GUID *)&((VENDOR_DEVICE_PATH_WITH_DATA*)MediaPath)->VendorDefinedData; - XStringW MediaPathGuidStr = GuidLEToStr(MediaPathGuid); + XStringW MediaPathGuidStr = GuidLEToXStringW(MediaPathGuid); // DBG(" checking '%ls'\n", MediaPathGuidStr.wc_str()); if (StrStr(gEfiBootLoaderPath, MediaPathGuidStr.wc_str())) { DBG(" - found entry %lld. '%ls', Volume '%ls', '%ls'\n", Index, LoaderEntry.Title.s(), Volume->VolName, LoaderPath.wc_str()); diff --git a/rEFIt_UEFI/Platform/Settings.cpp b/rEFIt_UEFI/Platform/Settings.cpp index a434b994e..0900154f2 100644 --- a/rEFIt_UEFI/Platform/Settings.cpp +++ b/rEFIt_UEFI/Platform/Settings.cpp @@ -115,9 +115,6 @@ UINT16 gBacklightLevel; BOOLEAN GetLegacyLanAddress; BOOLEAN ResumeFromCoreStorage; BOOLEAN gRemapSmBiosIsRequire; -CONST CHAR16 **SystemPlists = NULL; -CONST CHAR16 **InstallPlists = NULL; -CONST CHAR16 **RecoveryPlists = NULL; // QPI BOOLEAN SetTable132 = FALSE; @@ -6366,22 +6363,26 @@ CHAR8 *GetOSVersion(IN LOADER_ENTRY *Entry) TagPtr DictPointer = NULL; TagPtr Dict = NULL; TagPtr Prop = NULL; - UINTN i = 0; - UINTN j = 0; if (!Entry || !Entry->Volume) { return OSVersion; } - if (OSTYPE_IS_OSX(Entry->LoaderType)) { - // Detect exact version for Mac OS X Regular/Server - i = 0; - while (SystemPlists[i] != NULL && !FileExists(Entry->Volume->RootDir, SystemPlists[i])) { - i++; + if (OSTYPE_IS_OSX(Entry->LoaderType)) + { + XString8 uuidPrefix; + if ( Entry->APFSTargetUUID.notEmpty() ) uuidPrefix = SPrintf("\\%ls", Entry->APFSTargetUUID.wc_str()); + + XStringW plist = SWPrintf("%s\\System\\Library\\CoreServices\\SystemVersion.plist", uuidPrefix.c_str()); + if ( !FileExists(Entry->Volume->RootDir, plist) ) { + plist = SWPrintf("%s\\System\\Library\\CoreServices\\ServerVersion.plist", uuidPrefix.c_str()); + if ( !FileExists(Entry->Volume->RootDir, plist) ) { + plist.setEmpty(); + } } - if (SystemPlists[i] != NULL) { // found macOS System - Status = egLoadFile(Entry->Volume->RootDir, SystemPlists[i], (UINT8 **)&PlistBuffer, &PlistLen); + if ( plist.notEmpty() ) { // found macOS System + Status = egLoadFile(Entry->Volume->RootDir, plist.wc_str(), (UINT8 **)&PlistBuffer, &PlistLen); if (!EFI_ERROR(Status) && PlistBuffer != NULL && ParseXML(PlistBuffer, &Dict, 0) == EFI_SUCCESS) { Prop = GetProperty(Dict, "ProductVersion"); if (Prop != NULL && Prop->string != NULL && Prop->string[0] != '\0') { @@ -6587,14 +6588,16 @@ CHAR8 *GetOSVersion(IN LOADER_ENTRY *Entry) // 2nd stage - 3 // Check for plist - Preboot of APFS - if (OSVersion == NULL && APFSSupport == TRUE) { - i = 0; - while (InstallPlists[i] != NULL && !FileExists(Entry->Volume->RootDir, InstallPlists[i])) { - i++; - } + if ( OSVersion == NULL ) + { + XStringW plist = L"\\macOS Install Data\\Locked Files\\Boot Files\\SystemVersion.plist"_XSW; + if ( !FileExists(Entry->Volume->RootDir, plist) ) { + plist.setEmpty(); + } - if (InstallPlists[i] != NULL) { - Status = egLoadFile(Entry->Volume->RootDir, InstallPlists[i], (UINT8 **)&PlistBuffer, &PlistLen); + if ( plist.notEmpty() ) { // found macOS System + + Status = egLoadFile(Entry->Volume->RootDir, plist.wc_str(), (UINT8 **)&PlistBuffer, &PlistLen); if (!EFI_ERROR(Status) && PlistBuffer != NULL && ParseXML(PlistBuffer, &Dict, 0) == EFI_SUCCESS) { Prop = GetProperty(Dict, "ProductVersion"); if (Prop != NULL && Prop->string != NULL && Prop->string[0] != '\0') { @@ -6610,14 +6613,27 @@ CHAR8 *GetOSVersion(IN LOADER_ENTRY *Entry) } if (OSTYPE_IS_OSX_RECOVERY (Entry->LoaderType)) { - j = 0; - while (RecoveryPlists[j] != NULL && !FileExists(Entry->Volume->RootDir, RecoveryPlists[j])) { - j++; - } - // Detect exact version for OS X Recovery - if (RecoveryPlists[j] != NULL) { - Status = egLoadFile(Entry->Volume->RootDir, RecoveryPlists[j], (UINT8 **)&PlistBuffer, &PlistLen); + XString8 uuidPrefix; + if ( Entry->APFSTargetUUID.notEmpty() ) uuidPrefix = SPrintf("\\%ls", Entry->APFSTargetUUID.wc_str()); + + XStringW plist = SWPrintf("%s\\SystemVersion.plist", uuidPrefix.c_str()); + if ( !FileExists(Entry->Volume->RootDir, plist) ) { + plist = SWPrintf("%s\\ServerVersion.plist", uuidPrefix.c_str()); + if ( !FileExists(Entry->Volume->RootDir, plist) ) { + plist = L"\\com.apple.recovery.boot\\SystemVersion.plist"_XSW; + if ( !FileExists(Entry->Volume->RootDir, plist) ) { + plist = L"\\com.apple.recovery.boot\\ServerVersion.plist"_XSW; + if ( !FileExists(Entry->Volume->RootDir, plist) ) { + plist.setEmpty(); + } + } + } + } + + // Detect exact version for OS X Recovery + if ( plist.notEmpty() ) { // found macOS System + Status = egLoadFile(Entry->Volume->RootDir, plist.wc_str(), (UINT8 **)&PlistBuffer, &PlistLen); if (!EFI_ERROR(Status) && PlistBuffer != NULL && ParseXML(PlistBuffer, &Dict, 0) == EFI_SUCCESS) { Prop = GetProperty(Dict, "ProductVersion"); if (Prop != NULL && Prop->string != NULL && Prop->string[0] != '\0') { diff --git a/rEFIt_UEFI/Platform/Settings.h b/rEFIt_UEFI/Platform/Settings.h index ec6db5f45..173c9ccd9 100644 --- a/rEFIt_UEFI/Platform/Settings.h +++ b/rEFIt_UEFI/Platform/Settings.h @@ -637,9 +637,6 @@ extern GFX_PROPERTIES gGraphics[]; extern HDA_PROPERTIES gAudios[]; extern UINTN NGFX; extern UINTN NHDA; -extern CONST CHAR16 **SystemPlists; -extern CONST CHAR16 **InstallPlists; -extern CONST CHAR16 **RecoveryPlists; //extern UINT16 gCPUtype; extern SETTINGS_DATA gSettings; extern LANGUAGES gLanguage; diff --git a/rEFIt_UEFI/Platform/guid.cpp b/rEFIt_UEFI/Platform/guid.cpp index c6a001593..4ecc6fa99 100644 --- a/rEFIt_UEFI/Platform/guid.cpp +++ b/rEFIt_UEFI/Platform/guid.cpp @@ -233,7 +233,7 @@ static EFI_STATUS StrHToBuf ( OUT UINT8 *Buf, IN UINTN BufferLength, - IN CHAR16 *Str + IN CONST CHAR16 *Str ) { UINTN Index; @@ -293,12 +293,15 @@ StrHToBuf ( EFI_STATUS StrToGuidLE ( - IN CHAR16 *Str, + IN CONST CHAR16 *Str, OUT EFI_GUID *Guid ) { + EFI_STATUS Status; UINT8 GuidLE[16]; - StrHToBuf (&GuidLE[0], 4, Str); + Status = StrHToBuf (&GuidLE[0], 4, Str); + if ( Status != EFI_SUCCESS ) return Status; + while (!IS_HYPHEN (*Str) && !IS_NULL (*Str)) { Str ++; } @@ -309,7 +312,8 @@ StrToGuidLE ( return EFI_UNSUPPORTED; } - StrHToBuf (&GuidLE[4], 2, Str); + Status = StrHToBuf (&GuidLE[4], 2, Str); + if ( Status != EFI_SUCCESS ) return Status; while (!IS_HYPHEN (*Str) && !IS_NULL (*Str)) { Str ++; } @@ -320,7 +324,8 @@ StrToGuidLE ( return EFI_UNSUPPORTED; } - StrHToBuf (&GuidLE[6], 2, Str); + Status = StrHToBuf (&GuidLE[6], 2, Str); + if ( Status != EFI_SUCCESS ) return Status; while (!IS_HYPHEN (*Str) && !IS_NULL (*Str)) { Str ++; } @@ -331,7 +336,8 @@ StrToGuidLE ( return EFI_UNSUPPORTED; } - StrHToBuf (&GuidLE[8], 2, Str); + Status = StrHToBuf (&GuidLE[8], 2, Str); + if ( Status != EFI_SUCCESS ) return Status; while (!IS_HYPHEN (*Str) && !IS_NULL (*Str)) { Str ++; } @@ -342,7 +348,8 @@ StrToGuidLE ( return EFI_UNSUPPORTED; } - StrHToBuf (&GuidLE[10], 6, Str); + Status = StrHToBuf (&GuidLE[10], 6, Str); + if ( Status != EFI_SUCCESS ) return Status; if (Guid) { CopyMem((UINT8*)Guid, &GuidLE[0], sizeof(EFI_GUID)); @@ -365,10 +372,19 @@ CHAR16 * GuidBeToStr(EFI_GUID *Guid) } -XStringW GuidLEToStr(EFI_GUID *Guid) +XStringW GuidLEToXStringW(EFI_GUID *Guid) { XStringW returnValue; returnValue.SWPrintf("%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", + Guid->Data1, Guid->Data2, Guid->Data3, Guid->Data4[0], Guid->Data4[1], + Guid->Data4[2], Guid->Data4[3], Guid->Data4[4], Guid->Data4[5], Guid->Data4[6], Guid->Data4[7]); + return returnValue; +} + +XString8 GuidLEToXString8(EFI_GUID *Guid) +{ + XString8 returnValue; + returnValue.SPrintf("%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", Guid->Data1, Guid->Data2, Guid->Data3, Guid->Data4[0], Guid->Data4[1], Guid->Data4[2], Guid->Data4[3], Guid->Data4[4], Guid->Data4[5], Guid->Data4[6], Guid->Data4[7]); return returnValue; diff --git a/rEFIt_UEFI/Platform/guid.h b/rEFIt_UEFI/Platform/guid.h index 95f78b94d..17e423999 100644 --- a/rEFIt_UEFI/Platform/guid.h +++ b/rEFIt_UEFI/Platform/guid.h @@ -18,11 +18,12 @@ IsValidGuidAsciiString ( EFI_STATUS StrToGuidLE ( - IN CHAR16 *Str, + IN CONST CHAR16 *Str, OUT EFI_GUID *Guid); CHAR16 * GuidBeToStr(EFI_GUID *Guid); -XStringW GuidLEToStr(EFI_GUID *Guid); +XString8 GuidLEToXString8(EFI_GUID *Guid); +XStringW GuidLEToXStringW(EFI_GUID *Guid); diff --git a/rEFIt_UEFI/entry_scan/common.cpp b/rEFIt_UEFI/entry_scan/common.cpp index bfe26e6ca..46deb4b7d 100644 --- a/rEFIt_UEFI/entry_scan/common.cpp +++ b/rEFIt_UEFI/entry_scan/common.cpp @@ -70,7 +70,7 @@ const XIcon& ScanVolumeDefaultIcon(REFIT_VOLUME *Volume, IN UINT8 OSType, IN EFI DevicePath = NextDevicePathNode(DevicePath); } if (DevicePathType(DevicePath) == MEDIA_DEVICE_PATH && DevicePathSubType (DevicePath) == MEDIA_VENDOR_DP) { - if ( GuidLEToStr((EFI_GUID *)((UINT8 *)DevicePath+0x04)).equalIC(GuidLEToStr(&APFSSignature)) ) { + if ( GuidLEToXString8((EFI_GUID *)((UINT8 *)DevicePath+0x04)).equalIC(ApfsSignatureUUID) ) { IconNum = BUILTIN_ICON_VOL_INTERNAL_APFS; } } else { diff --git a/rEFIt_UEFI/entry_scan/loader.cpp b/rEFIt_UEFI/entry_scan/loader.cpp index 8cdf91552..83f96e786 100644 --- a/rEFIt_UEFI/entry_scan/loader.cpp +++ b/rEFIt_UEFI/entry_scan/loader.cpp @@ -446,6 +446,7 @@ STATIC LOADER_ENTRY *CreateLoaderEntry(IN CONST XStringW& LoaderPath, IN CONST XStringW& FullTitle, IN CONST XStringW& LoaderTitle, IN REFIT_VOLUME *Volume, + IN const XStringW& APFSTargetUUID, IN XIcon *Image, IN XIcon *DriveImage, IN UINT8 OSType, @@ -586,6 +587,7 @@ STATIC LOADER_ENTRY *CreateLoaderEntry(IN CONST XStringW& LoaderPath, Entry = new LOADER_ENTRY(); Entry->Row = 0; Entry->Volume = Volume; + Entry->APFSTargetUUID = APFSTargetUUID; Entry->LoaderPath = LoaderPath; Entry->VolName = Volume->VolName; @@ -810,6 +812,15 @@ void LOADER_ENTRY::AddDefaultMenu() Guid = FindGPTPartitionGuidInDevicePath(Volume->DevicePath); if (Guid) { SubScreen->AddMenuInfoLine_f("UUID: %s", strguid(Guid)); + } + if ( Volume->ApfsFileSystemUUID.notEmpty() || APFSTargetUUID.notEmpty() ) { + SubScreen->AddMenuInfoLine_f("APFS volume name: %ls", VolName); + } + if ( Volume->ApfsFileSystemUUID.notEmpty() ) { + SubScreen->AddMenuInfoLine_f("APFS File System UUID: %s", Volume->ApfsFileSystemUUID.c_str()); + } + if ( APFSTargetUUID.notEmpty() ) { + SubScreen->AddMenuInfoLine_f("APFS Target UUID: %ls", APFSTargetUUID.wc_str()); } SubScreen->AddMenuInfoLine_f("Options: %s", LoadOptions.ConcatAll(" "_XS8).c_str()); // loader-specific submenu entries @@ -987,37 +998,37 @@ void LOADER_ENTRY::AddDefaultMenu() // DBG(" Added '%ls': OSType='%d', OSVersion='%s'\n",Title,LoaderType,OSVersion); } -BOOLEAN AddLoaderEntry(IN CONST XStringW& LoaderPath, IN CONST XStringArray& LoaderOptions, - IN CONST XStringW& LoaderTitle, - IN REFIT_VOLUME *Volume, IN XIcon *Image, +LOADER_ENTRY* AddLoaderEntry(IN CONST XStringW& LoaderPath, IN CONST XStringArray& LoaderOptions, + IN CONST XStringW& FullTitle, IN CONST XStringW& LoaderTitle, + IN REFIT_VOLUME *Volume, IN const XStringW& APFSTargetUUID, IN XIcon *Image, IN UINT8 OSType, IN UINT8 Flags) { LOADER_ENTRY *Entry; INTN HVi; if ((LoaderPath.isEmpty()) || (Volume == NULL) || (Volume->RootDir == NULL) || !FileExists(Volume->RootDir, LoaderPath)) { - return FALSE; + return NULL; } DBG(" AddLoaderEntry for Volume Name=%ls\n", Volume->VolName); if (OSFLAG_ISSET(Flags, OSFLAG_DISABLED)) { DBG(" skipped because entry is disabled\n"); - return FALSE; + return NULL; } if (!gSettings.ShowHiddenEntries && OSFLAG_ISSET(Flags, OSFLAG_HIDDEN)) { DBG(" skipped because entry is hidden\n"); - return FALSE; + return NULL; } //don't add hided entries if (!gSettings.ShowHiddenEntries) { for (HVi = 0; HVi < gSettings.HVCount; HVi++) { if ( LoaderPath.containsIC(gSettings.HVHideStrings[HVi]) ) { DBG(" hiding entry: %ls\n", LoaderPath.s()); - return FALSE; + return NULL; } } } - Entry = CreateLoaderEntry(LoaderPath, LoaderOptions, L""_XSW, LoaderTitle, Volume, Image, NULL, OSType, Flags, 0, MenuBackgroundPixel, CUSTOM_BOOT_DISABLED, NULL, NULL, FALSE); + Entry = CreateLoaderEntry(LoaderPath, LoaderOptions, FullTitle, LoaderTitle, Volume, APFSTargetUUID, Image, NULL, OSType, Flags, 0, MenuBackgroundPixel, CUSTOM_BOOT_DISABLED, NULL, NULL, FALSE); if (Entry != NULL) { if ((Entry->LoaderType == OSTYPE_OSX) || (Entry->LoaderType == OSTYPE_OSX_INSTALLER ) || @@ -1037,9 +1048,9 @@ BOOLEAN AddLoaderEntry(IN CONST XStringW& LoaderPath, IN CONST XStringArray& Loa // InputItems[69].IValue = Entry->Flags; Entry->AddDefaultMenu(); MainMenu.AddMenuEntry(Entry, true); - return TRUE; + return Entry; } - return FALSE; + return NULL; } STATIC VOID LinuxScan(REFIT_VOLUME *Volume, UINT8 KernelScan, UINT8 Type, XStringW *CustomPath, XIcon *CustomImage) @@ -1093,7 +1104,7 @@ STATIC VOID LinuxScan(REFIT_VOLUME *Volume, UINT8 KernelScan, UINT8 Type, XStrin DirIterClose(&DirIter); return; } - AddLoaderEntry(File, NullXStringArray, LoaderTitle, Volume, + AddLoaderEntry(File, NullXStringArray, L""_XSW, LoaderTitle, Volume, L""_XSW, (ImageX.isEmpty() ? NULL : &ImageX), OSTYPE_LIN, OSFLAG_NODEFAULTARGS); } //anyway continue search other entries } @@ -1115,7 +1126,7 @@ STATIC VOID LinuxScan(REFIT_VOLUME *Volume, UINT8 KernelScan, UINT8 Type, XStrin } return; } - AddLoaderEntry(LinuxEntryData[Index].Path, NullXStringArray, XStringW().takeValueFrom(LinuxEntryData[Index].Title), Volume, + AddLoaderEntry(LinuxEntryData[Index].Path, NullXStringArray, L""_XSW, XStringW().takeValueFrom(LinuxEntryData[Index].Title), Volume, L""_XSW, (ImageX.isEmpty() ? NULL : &ImageX), OSTYPE_LIN, OSFLAG_NODEFAULTARGS); } } @@ -1243,7 +1254,7 @@ STATIC VOID LinuxScan(REFIT_VOLUME *Volume, UINT8 KernelScan, UINT8 Type, XStrin } XStringArray Options = LinuxKernelOptions(Iter.DirHandle, Basename(Path.wc_str()) + LINUX_LOADER_PATH.length(), PartUUID, NullXStringArray); // Add the entry - AddLoaderEntry(Path, (Options.isEmpty()) ? LINUX_DEFAULT_OPTIONS : Options, L""_XSW, Volume, NULL, OSTYPE_LINEFI, OSFLAG_NODEFAULTARGS); + AddLoaderEntry(Path, (Options.isEmpty()) ? LINUX_DEFAULT_OPTIONS : Options, L""_XSW, L""_XSW, Volume, L""_XSW, NULL, OSTYPE_LINEFI, OSFLAG_NODEFAULTARGS); Path.setEmpty(); } @@ -1258,7 +1269,7 @@ STATIC VOID LinuxScan(REFIT_VOLUME *Volume, UINT8 KernelScan, UINT8 Type, XStrin Path.SWPrintf("%ls\\%ls", LINUX_BOOT_PATH, FileInfo->FileName); XStringArray Options = LinuxKernelOptions(Iter.DirHandle, Basename(Path.wc_str()) + LINUX_LOADER_PATH.length(), PartUUID, NullXStringArray); // Add the entry - AddLoaderEntry(Path, (Options.isEmpty()) ? LINUX_DEFAULT_OPTIONS : Options, L""_XSW, Volume, NULL, OSTYPE_LINEFI, OSFLAG_NODEFAULTARGS); + AddLoaderEntry(Path, (Options.isEmpty()) ? LINUX_DEFAULT_OPTIONS : Options, L""_XSW, L""_XSW, Volume, L""_XSW, NULL, OSTYPE_LINEFI, OSFLAG_NODEFAULTARGS); Path.setEmpty(); } } @@ -1293,16 +1304,16 @@ VOID AddPRSEntry(REFIT_VOLUME *Volume) switch (WhatBoot) { case Paper: case (Paper | Rock): - AddLoaderEntry(PaperBoot, NullXStringArray, L"macOS InstallP"_XSW, Volume, NULL, OSTYPE_OSX_INSTALLER, 0); + AddLoaderEntry(PaperBoot, NullXStringArray, L""_XSW, L"macOS InstallP"_XSW, Volume, L""_XSW, NULL, OSTYPE_OSX_INSTALLER, 0); break; case Scissor: case (Paper | Scissor): - AddLoaderEntry(ScissorBoot, NullXStringArray, L"macOS InstallS"_XSW, Volume, NULL, OSTYPE_OSX_INSTALLER, 0); + AddLoaderEntry(ScissorBoot, NullXStringArray, L""_XSW, L"macOS InstallS"_XSW, Volume, L""_XSW, NULL, OSTYPE_OSX_INSTALLER, 0); break; case Rock: case (Rock | Scissor): case (Rock | Scissor | Paper): - AddLoaderEntry(RockBoot, NullXStringArray, L"macOS InstallR"_XSW, Volume, NULL, OSTYPE_OSX_INSTALLER, 0); + AddLoaderEntry(RockBoot, NullXStringArray, L""_XSW, L"macOS InstallR"_XSW, Volume, L""_XSW, NULL, OSTYPE_OSX_INSTALLER, 0); break; default: @@ -1315,14 +1326,11 @@ VOID AddPRSEntry(REFIT_VOLUME *Volume) VOID ScanLoader(VOID) { - UINTN VolumeIndex; - REFIT_VOLUME *Volume; - //DBG("Scanning loaders...\n"); DbgHeader("ScanLoader"); - for (VolumeIndex = 0; VolumeIndex < Volumes.size(); VolumeIndex++) { - Volume = &Volumes[VolumeIndex]; + for (UINTN VolumeIndex = 0; VolumeIndex < Volumes.size(); VolumeIndex++) { + REFIT_VOLUME* Volume = &Volumes[VolumeIndex]; if (Volume->RootDir == NULL) { // || Volume->VolName == NULL) //DBG(", no file system\n", VolumeIndex); continue; @@ -1351,41 +1359,41 @@ VOID ScanLoader(VOID) 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")) { - AddLoaderEntry(L"\\.IABootFiles\\boot.efi"_XSW, NullXStringArray, L"OS X Install"_XSW, Volume, NULL, OSTYPE_OSX_INSTALLER, 0); // 10.9 - 10.11 + AddLoaderEntry(L"\\.IABootFiles\\boot.efi"_XSW, NullXStringArray, L""_XSW, L"OS X Install"_XSW, Volume, L""_XSW, NULL, OSTYPE_OSX_INSTALLER, 0); // 10.9 - 10.11 } else { - AddLoaderEntry(L"\\.IABootFiles\\boot.efi"_XSW, NullXStringArray, L"macOS Install"_XSW, Volume, NULL, OSTYPE_OSX_INSTALLER, 0); // 10.12 - 10.13.3 + AddLoaderEntry(L"\\.IABootFiles\\boot.efi"_XSW, NullXStringArray, L""_XSW, L"macOS Install"_XSW, Volume, L""_XSW, NULL, OSTYPE_OSX_INSTALLER, 0); // 10.12 - 10.13.3 } } else if (FileExists(Volume->RootDir, L"\\.IAPhysicalMedia") && FileExists(Volume->RootDir, MACOSX_LOADER_PATH)) { - AddLoaderEntry(MACOSX_LOADER_PATH, NullXStringArray, L"macOS Install"_XSW, Volume, NULL, OSTYPE_OSX_INSTALLER, 0); // 10.13.4+ + AddLoaderEntry(MACOSX_LOADER_PATH, NullXStringArray, L""_XSW, L"macOS Install"_XSW, Volume, L""_XSW, NULL, OSTYPE_OSX_INSTALLER, 0); // 10.13.4+ } // 2nd stage - InstallESD/AppStore/startosinstall/Fusion Drive - AddLoaderEntry(L"\\Mac OS X Install Data\\boot.efi"_XSW, NullXStringArray, L"Mac OS X Install"_XSW, Volume, NULL, OSTYPE_OSX_INSTALLER, 0); // 10.7 - AddLoaderEntry(L"\\OS X Install Data\\boot.efi"_XSW, NullXStringArray, L"OS X Install"_XSW, Volume, NULL, OSTYPE_OSX_INSTALLER, 0); // 10.8 - 10.11 - AddLoaderEntry(L"\\macOS Install Data\\boot.efi"_XSW, NullXStringArray, L"macOS Install"_XSW, Volume, NULL, OSTYPE_OSX_INSTALLER, 0); // 10.12 - 10.12.3 - AddLoaderEntry(L"\\macOS Install Data\\Locked Files\\Boot Files\\boot.efi"_XSW, NullXStringArray, L"macOS Install"_XSW, Volume, NULL, OSTYPE_OSX_INSTALLER, 0); // 10.12.4+ - AddLoaderEntry(L"\\macOS Install Data\\Locked Files\\boot.efi"_XSW, NullXStringArray, L"macOS Install"_XSW, Volume, NULL, OSTYPE_OSX_INSTALLER, 0); // 10.16+ + AddLoaderEntry(L"\\Mac OS X Install Data\\boot.efi"_XSW, NullXStringArray, L""_XSW, L"Mac OS X Install"_XSW, Volume, L""_XSW, NULL, OSTYPE_OSX_INSTALLER, 0); // 10.7 + AddLoaderEntry(L"\\OS X Install Data\\boot.efi"_XSW, NullXStringArray, L""_XSW, L"OS X Install"_XSW, Volume, L""_XSW, NULL, OSTYPE_OSX_INSTALLER, 0); // 10.8 - 10.11 + AddLoaderEntry(L"\\macOS Install Data\\boot.efi"_XSW, NullXStringArray, L""_XSW, L"macOS Install"_XSW, Volume, L""_XSW, NULL, OSTYPE_OSX_INSTALLER, 0); // 10.12 - 10.12.3 + AddLoaderEntry(L"\\macOS Install Data\\Locked Files\\Boot Files\\boot.efi"_XSW, NullXStringArray, L""_XSW, L"macOS Install"_XSW, Volume, L""_XSW, NULL, OSTYPE_OSX_INSTALLER, 0); // 10.12.4+ + AddLoaderEntry(L"\\macOS Install Data\\Locked Files\\boot.efi"_XSW, NullXStringArray, L""_XSW, L"macOS Install"_XSW, Volume, L""_XSW, NULL, OSTYPE_OSX_INSTALLER, 0); // 10.16+ AddPRSEntry(Volume); // 10.12+ // Netinstall - AddLoaderEntry(L"\\NetInstall macOS High Sierra.nbi\\i386\\booter"_XSW, NullXStringArray, L"macOS Install"_XSW, Volume, NULL, OSTYPE_OSX_INSTALLER, 0); + AddLoaderEntry(L"\\NetInstall macOS High Sierra.nbi\\i386\\booter"_XSW, NullXStringArray, L""_XSW, L"macOS Install"_XSW, Volume, L""_XSW, NULL, OSTYPE_OSX_INSTALLER, 0); // 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 if (FileExists(Volume->RootDir, MACOSX_LOADER_PATH)) { if (FileExists(Volume->RootDir, L"\\System\\Installation\\CDIS\\Mac OS X Installer.app")) { // InstallDVD/BaseSystem - AddLoaderEntry(MACOSX_LOADER_PATH, NullXStringArray, L"Mac OS X Install"_XSW, Volume, NULL, OSTYPE_OSX_INSTALLER, 0); // 10.6/10.7 + AddLoaderEntry(MACOSX_LOADER_PATH, NullXStringArray, L""_XSW, L"Mac OS X Install"_XSW, Volume, L""_XSW, NULL, OSTYPE_OSX_INSTALLER, 0); // 10.6/10.7 } else if (FileExists(Volume->RootDir, L"\\System\\Installation\\CDIS\\OS X Installer.app")) { // BaseSystem - AddLoaderEntry(MACOSX_LOADER_PATH, NullXStringArray, L"OS X Install"_XSW, Volume, NULL, OSTYPE_OSX_INSTALLER, 0); // 10.8 - 10.11 + AddLoaderEntry(MACOSX_LOADER_PATH, NullXStringArray, L""_XSW, L"OS X Install"_XSW, Volume, L""_XSW, NULL, OSTYPE_OSX_INSTALLER, 0); // 10.8 - 10.11 } else if (FileExists(Volume->RootDir, L"\\System\\Installation\\CDIS\\macOS Installer.app")) { // BaseSystem - AddLoaderEntry(MACOSX_LOADER_PATH, NullXStringArray, L"macOS Install"_XSW, Volume, NULL, OSTYPE_OSX_INSTALLER, 0); // 10.12+ + AddLoaderEntry(MACOSX_LOADER_PATH, NullXStringArray, L""_XSW, L"macOS Install"_XSW, Volume, L""_XSW, NULL, OSTYPE_OSX_INSTALLER, 0); // 10.12+ } else if (FileExists(Volume->RootDir, L"\\BaseSystem.dmg") && FileExists(Volume->RootDir, L"\\mach_kernel")) { // InstallESD if (FileExists(Volume->RootDir, L"\\MacOSX_Media_Background.png")) { - AddLoaderEntry(MACOSX_LOADER_PATH, NullXStringArray, L"Mac OS X Install"_XSW, Volume, NULL, OSTYPE_OSX_INSTALLER, 0); // 10.7 + AddLoaderEntry(MACOSX_LOADER_PATH, NullXStringArray, L""_XSW, L"Mac OS X Install"_XSW, Volume, L""_XSW, NULL, OSTYPE_OSX_INSTALLER, 0); // 10.7 } else { - AddLoaderEntry(MACOSX_LOADER_PATH, NullXStringArray, L"OS X Install"_XSW, Volume, NULL, OSTYPE_OSX_INSTALLER, 0); // 10.8 + AddLoaderEntry(MACOSX_LOADER_PATH, NullXStringArray, L""_XSW, L"OS X Install"_XSW, Volume, L""_XSW, NULL, OSTYPE_OSX_INSTALLER, 0); // 10.8 } } 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") || @@ -1393,20 +1401,20 @@ VOID ScanLoader(VOID) if (StriStr(Volume->VolName, L"Recovery") != NULL) { // FileVault of HFS+ // TODO: need info for 10.11 and lower - AddLoaderEntry(MACOSX_LOADER_PATH, NullXStringArray, L"macOS FileVault"_XSW, Volume, NULL, OSTYPE_OSX, 0); // 10.12+ + AddLoaderEntry(MACOSX_LOADER_PATH, NullXStringArray, L""_XSW, L"macOS FileVault"_XSW, Volume, L""_XSW, NULL, OSTYPE_OSX, 0); // 10.12+ } else { // Fusion Drive - AddLoaderEntry(MACOSX_LOADER_PATH, NullXStringArray, L"OS X Install"_XSW, Volume, NULL, OSTYPE_OSX_INSTALLER, 0); // 10.11 + AddLoaderEntry(MACOSX_LOADER_PATH, NullXStringArray, L""_XSW, L"OS X Install"_XSW, Volume, L""_XSW, NULL, OSTYPE_OSX_INSTALLER, 0); // 10.11 } } 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")) { - AddLoaderEntry(MACOSX_LOADER_PATH, NullXStringArray, L"Mac OS X"_XSW, Volume, NULL, OSTYPE_OSX, 0); // 10.6 - 10.7 + AddLoaderEntry(MACOSX_LOADER_PATH, NullXStringArray, L""_XSW, L"Mac OS X"_XSW, Volume, L""_XSW, NULL, OSTYPE_OSX, 0); // 10.6 - 10.7 } else if (FileExists(Volume->RootDir, L"\\System\\Library\\CoreServices\\NotificationCenter.app") && !FileExists(Volume->RootDir, L"\\System\\Library\\CoreServices\\Siri.app")) { - AddLoaderEntry(MACOSX_LOADER_PATH, NullXStringArray, L"OS X"_XSW, Volume, NULL, OSTYPE_OSX, 0); // 10.8 - 10.11 + AddLoaderEntry(MACOSX_LOADER_PATH, NullXStringArray, L""_XSW, L"OS X"_XSW, Volume, L""_XSW, NULL, OSTYPE_OSX, 0); // 10.8 - 10.11 } else { - AddLoaderEntry(MACOSX_LOADER_PATH, NullXStringArray, L"macOS"_XSW, Volume, NULL, OSTYPE_OSX, 0); // 10.12+ + AddLoaderEntry(MACOSX_LOADER_PATH, NullXStringArray, L""_XSW, L"macOS"_XSW, Volume, L""_XSW, NULL, OSTYPE_OSX, 0); // 10.12+ } } } @@ -1414,40 +1422,71 @@ VOID ScanLoader(VOID) /* APFS Container support. * s.mtr 2017 */ - if ((StriCmp(Volume->VolName, L"Recovery") == 0 || StriCmp(Volume->VolName, L"Preboot") == 0) && APFSSupport == TRUE) { - for (UINTN i = 0; i < APFSUUIDBankCounter + 1; i++) { - //Store current UUID - XStringW CurrentUUID = GuidLEToStr((EFI_GUID *)((UINT8 *)APFSUUIDBank + i * 0x10)); - //Fill with current UUID -// StrnCpy(APFSFVBootPath + 1, CurrentUUID, 36); -// StrnCpy(APFSRecBootPath + 1, CurrentUUID, 36); -// StrnCpy(APFSInstallBootPath + 1, CurrentUUID, 36); - //Try to add FileVault entry - AddLoaderEntry(SWPrintf("\\%ls\\System\\Library\\CoreServices\\boot.efi", CurrentUUID.c_str()), NullXStringArray, L"FileVault Prebooter"_XSW, Volume, NULL, OSTYPE_OSX, 0); - //Try to add Recovery APFS entry - AddLoaderEntry(SWPrintf("\\%ls\\boot.efi", CurrentUUID.c_str()), NullXStringArray, L"Recovery"_XSW, Volume, NULL, OSTYPE_RECOVERY, 0); - //Try to add macOS install entry - AddLoaderEntry(SWPrintf("\\%ls\\com.apple.installer\\boot.efi", CurrentUUID.c_str()), NullXStringArray, L"macOS Install Prebooter"_XSW, Volume, NULL, OSTYPE_OSX_INSTALLER, 0); - } + if ( StriCmp(Volume->VolName, L"Recovery") == 0 ) { // TODO : use APFS role instead of hard coded partition name + + for (UINTN i = 0; i < Volume->ApfsTargetUUIDArray.size(); i++) + { + const XString8& ApfsTargetUUID = Volume->ApfsTargetUUIDArray[i]; + + const LOADER_ENTRY* targetLoaderEntry = NULL; + for ( size_t entryIdx = 0 ; entryIdx < MainMenu.Entries.size() ; entryIdx ++ ) + { + if ( MainMenu.Entries[entryIdx].getLOADER_ENTRY() ) { + const LOADER_ENTRY* loaderEntry = MainMenu.Entries[entryIdx].getLOADER_ENTRY(); + if ( loaderEntry->Volume->ApfsFileSystemUUID == ApfsTargetUUID ) { + targetLoaderEntry = loaderEntry; + } + } + } + if ( targetLoaderEntry ) { + //Try to add Recovery APFS entry + AddLoaderEntry(SWPrintf("\\%s\\boot.efi", Volume->ApfsTargetUUIDArray[i].c_str()), NullXStringArray, SWPrintf("Boot Mac OS X Recovery for %ls via Recovery", targetLoaderEntry->VolName), L""_XSW, Volume, Volume->ApfsTargetUUIDArray[i], NULL, OSTYPE_RECOVERY, 0); + //Try to add macOS install entry + AddLoaderEntry(SWPrintf("\\%s\\com.apple.installer\\boot.efi", Volume->ApfsTargetUUIDArray[i].c_str()), NullXStringArray, L""_XSW, L"macOS Install Prebooter"_XSW, Volume, Volume->ApfsTargetUUIDArray[i], NULL, OSTYPE_OSX_INSTALLER, 0); + } + else + { + REFIT_VOLUME* targetVolume = NULL; + for (UINTN VolumeIndex2 = 0; VolumeIndex2 < Volumes.size(); VolumeIndex2++) { + REFIT_VOLUME* Volume2 = &Volumes[VolumeIndex2]; + //DBG("name %ls uuid=%ls \n", Volume2->VolName, Volume2->ApfsFileSystemUUID.wc_str()); + if ( Volume2->ApfsFileSystemUUID == ApfsTargetUUID ) { + targetVolume = Volume2; + } + } + if ( targetVolume ) { + //Try to add Recovery APFS entry + AddLoaderEntry(SWPrintf("\\%s\\boot.efi", Volume->ApfsTargetUUIDArray[i].c_str()), NullXStringArray, SWPrintf("Boot Mac OS X Recovery for %ls via Recovery", targetVolume->VolName), L""_XSW, Volume, Volume->ApfsTargetUUIDArray[i], NULL, OSTYPE_RECOVERY, 0); + //Try to add macOS install entry + AddLoaderEntry(SWPrintf("\\%s\\com.apple.installer\\boot.efi", Volume->ApfsTargetUUIDArray[i].c_str()), NullXStringArray, SWPrintf("Boot Mac OS X Install for %ls via Recovery", targetVolume->VolName), L""_XSW, Volume, Volume->ApfsTargetUUIDArray[i], NULL, OSTYPE_OSX_INSTALLER, 0); + } else { + //Try to add Recovery APFS entry + AddLoaderEntry(SWPrintf("\\%s\\boot.efi", Volume->ApfsTargetUUIDArray[i].c_str()), NullXStringArray, SWPrintf("Boot Mac OS X Recovery for %ls via Recovery", targetLoaderEntry->VolName), L""_XSW, Volume, Volume->ApfsTargetUUIDArray[i], NULL, OSTYPE_RECOVERY, 0); + //Try to add macOS install entry + AddLoaderEntry(SWPrintf("\\%s\\com.apple.installer\\boot.efi", Volume->ApfsTargetUUIDArray[i].c_str()), NullXStringArray, L""_XSW, L"macOS Install Prebooter"_XSW, Volume, Volume->ApfsTargetUUIDArray[i], NULL, OSTYPE_OSX_INSTALLER, 0); + } + } + } } + // check for Mac OS X Recovery Boot - AddLoaderEntry(L"\\com.apple.recovery.boot\\boot.efi"_XSW, NullXStringArray, L"Recovery"_XSW, Volume, NULL, OSTYPE_RECOVERY, 0); + AddLoaderEntry(L"\\com.apple.recovery.boot\\boot.efi"_XSW, NullXStringArray, L""_XSW, L"Recovery"_XSW, Volume, L""_XSW, NULL, OSTYPE_RECOVERY, 0); // 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 - AddLoaderEntry(L"\\EFI\\microsoft\\Boot\\bootmgfw-orig.efi"_XSW, NullXStringArray, L"Microsoft EFI"_XSW, Volume, NULL, OSTYPE_WINEFI, 0); + AddLoaderEntry(L"\\EFI\\microsoft\\Boot\\bootmgfw-orig.efi"_XSW, NullXStringArray, L""_XSW, L"Microsoft EFI"_XSW, Volume, L""_XSW, NULL, OSTYPE_WINEFI, 0); // 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 - AddLoaderEntry(L"\\EFI\\microsoft\\Boot\\bootmgfw.efi"_XSW, NullXStringArray, L"Microsoft EFI Boot"_XSW, Volume, NULL, OSTYPE_WINEFI, 0); + AddLoaderEntry(L"\\EFI\\microsoft\\Boot\\bootmgfw.efi"_XSW, NullXStringArray, L""_XSW, L"Microsoft EFI Boot"_XSW, Volume, L""_XSW, NULL, OSTYPE_WINEFI, 0); // 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 - if (!AddLoaderEntry(L"\\EFI\\MICROSOFT\\BOOT\\cdboot.efi"_XSW, NullXStringArray, L"Microsoft EFI cdboot"_XSW, Volume, NULL, OSTYPE_WINEFI, 0)) { - AddLoaderEntry(L"\\EFI\\MICROSOF\\BOOT\\CDBOOT.EFI"_XSW, NullXStringArray, L"Microsoft EFI CDBOOT"_XSW, Volume, NULL, OSTYPE_WINEFI, 0); + if (!AddLoaderEntry(L"\\EFI\\MICROSOFT\\BOOT\\cdboot.efi"_XSW, NullXStringArray, L""_XSW, L"Microsoft EFI cdboot"_XSW, Volume, L""_XSW, NULL, OSTYPE_WINEFI, 0)) { + AddLoaderEntry(L"\\EFI\\MICROSOF\\BOOT\\CDBOOT.EFI"_XSW, NullXStringArray, L""_XSW, L"Microsoft EFI CDBOOT"_XSW, Volume, L""_XSW, NULL, OSTYPE_WINEFI, 0); } #if defined(ANDX86) @@ -1464,7 +1503,7 @@ VOID ScanLoader(VOID) XIcon ImageX; XStringW IconXSW = XStringW().takeValueFrom(AndroidEntryData[Index].Icon); ImageX.LoadXImage(ThemeX.ThemeDir, (L"os_"_XSW + IconXSW.subString(0, IconXSW.indexOf(','))).wc_str()); - AddLoaderEntry(AndroidEntryData[Index].Path, NullXStringArray, XStringW().takeValueFrom(AndroidEntryData[Index].Title), Volume, + AddLoaderEntry(AndroidEntryData[Index].Path, NullXStringArray, L""_XSW, XStringW().takeValueFrom(AndroidEntryData[Index].Title), Volume, L""_XSW, (ImageX.isEmpty() ? NULL : &ImageX), OSTYPE_LIN, OSFLAG_NODEFAULTARGS); } } @@ -1478,18 +1517,85 @@ VOID ScanLoader(VOID) // DBG("search for optical UEFI\n"); if (Volume->DiskKind == DISK_KIND_OPTICAL) { - AddLoaderEntry(BOOT_LOADER_PATH, NullXStringArray, L"UEFI optical"_XSW, Volume, NULL, OSTYPE_OTHER, 0); + AddLoaderEntry(BOOT_LOADER_PATH, NullXStringArray, L""_XSW, L"UEFI optical"_XSW, Volume, L""_XSW, NULL, OSTYPE_OTHER, 0); } // DBG("search for internal UEFI\n"); if (Volume->DiskKind == DISK_KIND_INTERNAL) { - AddLoaderEntry(BOOT_LOADER_PATH, NullXStringArray, L"UEFI internal"_XSW, Volume, NULL, OSTYPE_OTHER, OSFLAG_HIDDEN); + AddLoaderEntry(BOOT_LOADER_PATH, NullXStringArray, L""_XSW, L"UEFI internal"_XSW, Volume, L""_XSW, NULL, OSTYPE_OTHER, OSFLAG_HIDDEN); } // DBG("search for external UEFI\n"); if (Volume->DiskKind == DISK_KIND_EXTERNAL) { - AddLoaderEntry(BOOT_LOADER_PATH, NullXStringArray, L"UEFI external"_XSW, Volume, NULL, OSTYPE_OTHER, OSFLAG_HIDDEN); + AddLoaderEntry(BOOT_LOADER_PATH, NullXStringArray, L""_XSW, L"UEFI external"_XSW, Volume, L""_XSW, NULL, OSTYPE_OTHER, OSFLAG_HIDDEN); } } + + /* Pass to add non redundant Preboot volume AND redundant as hidden */ + + for (UINTN VolumeIndex = 0; VolumeIndex < Volumes.size(); VolumeIndex++) { + REFIT_VOLUME* Volume = &Volumes[VolumeIndex]; + if (Volume->RootDir == NULL) { // || Volume->VolName == NULL) + //DBG(", no file system\n", VolumeIndex); + continue; + } + DBG("- [%02llu]: '%ls'", VolumeIndex, Volume->VolName); + if (Volume->VolName == NULL) { + Volume->VolName = L"Unknown"; + } + + // skip volume if its kind is configured as disabled + if (((1ull<DiskKind) & GlobalConfig.DisableFlags) != 0) + { + DBG(", flagged disable\n"); + continue; + } + + if (Volume->Hidden) { + DBG(", hidden\n"); + continue; + } + DBG("\n"); + + if ( StriCmp(Volume->VolName, L"Preboot") == 0 ) { // TODO, use APFS role instead of partition name + + for (UINTN i = 0; i < Volume->ApfsTargetUUIDArray.size(); i++) + { + const XString8& ApfsTargetUUID = Volume->ApfsTargetUUIDArray[i]; + + int flag = 0; + const LOADER_ENTRY* targetLoaderEntry = NULL; + for ( size_t entryIdx = 0 ; entryIdx < MainMenu.Entries.size() ; entryIdx ++ ) + { + if ( MainMenu.Entries[entryIdx].getLOADER_ENTRY() ) { + const LOADER_ENTRY* loaderEntry = MainMenu.Entries[entryIdx].getLOADER_ENTRY(); + if ( loaderEntry->Volume->ApfsFileSystemUUID == ApfsTargetUUID ) { + targetLoaderEntry = loaderEntry; + flag = OSFLAG_HIDDEN; + } + } + } + if ( targetLoaderEntry ) { + AddLoaderEntry(SWPrintf("\\%s\\System\\Library\\CoreServices\\boot.efi", ApfsTargetUUID.c_str()), NullXStringArray, SWPrintf("Boot Mac OS X from %ls via Preboot", targetLoaderEntry->VolName), L""_XSW, Volume, Volume->ApfsTargetUUIDArray[i], NULL, OSTYPE_OSX, OSFLAG_HIDDEN); + } + else + { + REFIT_VOLUME* targetVolume = NULL; + for (UINTN VolumeIndex2 = 0; VolumeIndex2 < Volumes.size(); VolumeIndex2++) { + REFIT_VOLUME* Volume2 = &Volumes[VolumeIndex2]; + //DBG("name %ls uuid=%ls \n", Volume2->VolName, Volume2->ApfsFileSystemUUID.wc_str()); + if ( Volume2->ApfsFileSystemUUID == ApfsTargetUUID ) { + targetVolume = Volume2; + } + } + if ( targetVolume ) { + AddLoaderEntry(SWPrintf("\\%s\\System\\Library\\CoreServices\\boot.efi", ApfsTargetUUID.c_str()), NullXStringArray, SWPrintf("Boot Mac OS X from %ls via Preboot", targetVolume->VolName), L""_XSW, Volume, Volume->ApfsTargetUUIDArray[i], NULL, OSTYPE_OSX, 0); + } else { + AddLoaderEntry(SWPrintf("\\%s\\System\\Library\\CoreServices\\boot.efi", ApfsTargetUUID.c_str()), NullXStringArray, L""_XSW, L"FileVault Prebooter"_XSW, Volume, Volume->ApfsTargetUUIDArray[i], NULL, OSTYPE_OSX, 0); + } + } + } + } + } } STATIC VOID AddCustomEntry(IN UINTN CustomIndex, @@ -1798,7 +1904,7 @@ STATIC VOID AddCustomEntry(IN UINTN CustomIndex, DBG("match!\n"); // Create an entry for this volume - Entry = CreateLoaderEntry(CustomPath, CustomOptions, Custom->FullTitle, Custom->Title, Volume, + Entry = CreateLoaderEntry(CustomPath, CustomOptions, Custom->FullTitle, Custom->Title, Volume, L""_XSW, (Image.isEmpty() ? NULL : &Image), (DriveImage.isEmpty() ? NULL : &DriveImage), Custom->Type, Custom->Flags, Custom->Hotkey, Custom->BootBgColor, Custom->CustomBoot, &Custom->CustomLogo, /*(KERNEL_AND_KEXT_PATCHES *)(((UINTN)Custom) + OFFSET_OF(CUSTOM_LOADER_ENTRY, KernelAndKextPatches))*/ NULL, TRUE); diff --git a/rEFIt_UEFI/gui/menu_items/menu_items.h b/rEFIt_UEFI/gui/menu_items/menu_items.h index 9afeb9b37..468809f27 100644 --- a/rEFIt_UEFI/gui/menu_items/menu_items.h +++ b/rEFIt_UEFI/gui/menu_items/menu_items.h @@ -346,6 +346,8 @@ class REFIT_ABSTRACT_MENU_ENTRY class LOADER_ENTRY : public REFIT_MENU_ITEM_BOOTNUM { public: + XStringW APFSTargetUUID; + CONST CHAR16 *VolName; EFI_DEVICE_PATH *DevicePath; UINT16 Flags; diff --git a/rEFIt_UEFI/libeg/libeg.h b/rEFIt_UEFI/libeg/libeg.h index 70e6ba93f..3d7b5d72d 100755 --- a/rEFIt_UEFI/libeg/libeg.h +++ b/rEFIt_UEFI/libeg/libeg.h @@ -142,6 +142,7 @@ extern "C" { #endif #include "../cpp_foundation/XString.h" +#include "../cpp_foundation/XStringArray.h" /* types */ typedef enum { @@ -264,6 +265,8 @@ typedef struct { UINT32 DriveCRC32; EFI_GUID RootUUID; //for recovery it is UUID of parent partition UINT64 SleepImageOffset; + XString8 ApfsFileSystemUUID; // apfs file system UUID of that partition. It's not the UUID of subfolder like in Preboot. + XStringArray ApfsTargetUUIDArray; // this is the array of folders that are named as UUID } REFIT_VOLUME; typedef struct KEXT_PATCH KEXT_PATCH; diff --git a/rEFIt_UEFI/refit/lib.cpp b/rEFIt_UEFI/refit/lib.cpp index ff267228a..97ad0d867 100644 --- a/rEFIt_UEFI/refit/lib.cpp +++ b/rEFIt_UEFI/refit/lib.cpp @@ -36,6 +36,8 @@ #include "Platform.h" #include "screen.h" +#include "../Platform/guid.h" +#include "../Platform/APFS.h" #ifndef DEBUG_ALL #define DEBUG_LIB 1 @@ -728,14 +730,17 @@ static EFI_STATUS ScanVolume(IN OUT REFIT_VOLUME *Volume) Volume->DevicePath = (__typeof__(Volume->DevicePath))AllocateAlignedPages(EFI_SIZE_TO_PAGES(DevicePathSize), 64); CopyMem(Volume->DevicePath, DiskDevicePath, DevicePathSize); Volume->DevicePathString = FileDevicePathToStr(Volume->DevicePath); - + // Volume->DevicePath = DuplicateDevicePath(DevicePathFromHandle(Volume->DeviceHandle)); #if REFIT_DEBUG > 0 if (Volume->DevicePath != NULL) { DBG(" %ls\n", FileDevicePathToStr(Volume->DevicePath)); -//#if REFIT_DEBUG >= 2 - // DumpHex(1, 0, GetDevicePathSize(Volume->DevicePath), Volume->DevicePath); -//#endif + //#if REFIT_DEBUG >= 2 + // DumpHex(1, 0, GetDevicePathSize(Volume->DevicePath), Volume->DevicePath); + //#endif + } + if ( Volume->ApfsFileSystemUUID.notEmpty() ) { + DBG(" apfsFileSystemUUID=%s\n", Volume->ApfsFileSystemUUID.c_str()); } #else DBG("\n"); @@ -935,6 +940,26 @@ static EFI_STATUS ScanVolume(IN OUT REFIT_VOLUME *Volume) return EFI_SUCCESS; } + + Volume->ApfsFileSystemUUID = APFSPartitionUUIDExtractAsXString8(Volume->DevicePath); // NullXString if it's not an APFS volume + + // Browse all folders under root that looks like an UUID + if ( Volume->ApfsFileSystemUUID.notEmpty() ) { + REFIT_DIR_ITER DirIter; + EFI_FILE_INFO *DirEntry = NULL; + DirIterOpen(Volume->RootDir, L"\\", &DirIter); + while (DirIterNext(&DirIter, 1, L"*", &DirEntry)) { + if (DirEntry->FileName[0] == '.') { + //DBG("Skip dot entries: %ls\n", DirEntry->FileName); + continue; + } + EFI_GUID guid; + if ( StrToGuidLE(DirEntry->FileName, &guid) == EFI_SUCCESS ) { + Volume->ApfsTargetUUIDArray.Add(DirEntry->FileName); + } + } + DirIterClose(&DirIter); + } if ( FileExists(Volume->RootDir, L"\\.VolumeLabel.txt") ) { EFI_FILE_HANDLE FileHandle; diff --git a/rEFIt_UEFI/refit/main.cpp b/rEFIt_UEFI/refit/main.cpp index cf476f03f..6e682018c 100644 --- a/rEFIt_UEFI/refit/main.cpp +++ b/rEFIt_UEFI/refit/main.cpp @@ -897,7 +897,14 @@ VOID LOADER_ENTRY::StartLoader() } if (gSettings.LastBootedVolume) { - SetStartupDiskVolume(Volume, LoaderType == OSTYPE_OSX ? NullXStringW : LoaderPath); + if ( APFSTargetUUID.notEmpty() ) { + // Jief : we need to LoaderPath. If not, GUI can't know which target was selected. + SetStartupDiskVolume(Volume, LoaderPath); + }else{ + // Jief : I'm not sure why NullXStringW was given if LoaderType == OSTYPE_OSX. + // Let's do it like it was before when not in case of APFSTargetUUID + SetStartupDiskVolume(Volume, LoaderType == OSTYPE_OSX ? NullXStringW : LoaderPath); + } } else if (gSettings.DefaultVolume != NULL) { // DefaultVolume specified in Config.plist or in Boot Option // we'll remove macOS Startup Disk vars which may be present if it is used @@ -1768,120 +1775,6 @@ VOID SetOEMPath(CONST CHAR16 *ConfName) } } -//System / Install / Recovery version filler -const CHAR16 SystemVersionPlist[] = L"\\System\\Library\\CoreServices\\SystemVersion.plist"; -const CHAR16 ServerVersionPlist[] = L"\\System\\Library\\CoreServices\\ServerVersion.plist"; -const CHAR16 InstallVersionPlist[] = L"\\macOS Install Data\\Locked Files\\Boot Files\\SystemVersion.plist"; -const CHAR16 RecoveryVersionPlist[] = L"\\com.apple.recovery.boot\\SystemVersion.plist"; -const CHAR16 APFSSysPlistPath[] = L"\\00000000-0000-0000-0000-000000000000\\System\\Library\\CoreServices\\SystemVersion.plist"; -const CHAR16 APFSServerPlistPath[] = L"\\00000000-0000-0000-0000-000000000000\\System\\Library\\CoreServices\\ServerVersion.plist"; -const CHAR16 APFSInstallPlistPath[] = L"\\00000000-0000-0000-0000-000000000000\\com.apple.installer\\SystemVersion.plist"; -const CHAR16 APFSRecPlistPath[] = L"\\00000000-0000-0000-0000-000000000000\\SystemVersion.plist"; - - -VOID SystemVersionInit(VOID) -{ - //Plists iterators - UINTN SysIter = 2; - UINTN InsIter = 1; - UINTN RecIter = 1; - UINTN k = 0; - UINTN i; - - // If scanloader starts multiple times, then we need to free systemplists, installplists, recoveryplists variables, also - // refresh APFSUUIDBank - if ((SystemPlists != NULL) || (InstallPlists != NULL) || (RecoveryPlists != NULL)) { - if ((APFSUUIDBank != NULL) && (APFSSupport == TRUE)) { - FreePool(APFSUUIDBank); - //Reset APFSUUIDBank counter, we will re-enumerate it - APFSUUIDBankCounter = 0; - APFSUUIDBank = APFSContainer_Support(); - if (APFSUUIDBankCounter == 0) { - APFSSupport = FALSE; - } - } - if (SystemPlists != NULL) { - k = 0; - while (SystemPlists[k] != NULL) { - SystemPlists[k] = NULL; - k++; - } - FreePool(SystemPlists); - SystemPlists = NULL; - } - if (InstallPlists != NULL) { - k = 0; - while (InstallPlists[k] != NULL) { - InstallPlists[k] = NULL; - k++; - } - FreePool(InstallPlists); - InstallPlists = NULL; - } - if (RecoveryPlists != NULL) { - k = 0; - while (RecoveryPlists[k] != NULL) { - RecoveryPlists[k] = NULL; - k++; - } - FreePool(RecoveryPlists); - RecoveryPlists = NULL; - } - } - /************************************************************************/ - /*Allocate Memory for systemplists, installplists and recoveryplists********************/ - //Check apfs support - if (APFSSupport == TRUE) { - SystemPlists = (__typeof__(SystemPlists))AllocateZeroPool((2*APFSUUIDBankCounter+3)*sizeof(CHAR16 *));//array of pointers - InstallPlists = (__typeof__(InstallPlists))AllocateZeroPool((APFSUUIDBankCounter+2)*sizeof(CHAR16 *));//array of pointers - RecoveryPlists = (__typeof__(RecoveryPlists))AllocateZeroPool((APFSUUIDBankCounter+2)*sizeof(CHAR16 *));//array of pointers - } else { - SystemPlists = (__typeof__(SystemPlists))AllocateZeroPool(sizeof(CHAR16 *)*3); - InstallPlists = (__typeof__(InstallPlists))AllocateZeroPool(sizeof(CHAR16 *)*2); - RecoveryPlists = (__typeof__(RecoveryPlists))AllocateZeroPool(sizeof(CHAR16 *)*2); - } - /* Fill it with standard paths*******************************************/ - SystemPlists[0] = SystemVersionPlist; - SystemPlists[1] = ServerVersionPlist; - SystemPlists[2] = NULL; - InstallPlists[0] = InstallVersionPlist; - InstallPlists[1] = NULL; - RecoveryPlists[0] = RecoveryVersionPlist; - RecoveryPlists[1] = NULL; - /************************************************************************/ - //Fill Plists - for (i = 0; i < APFSUUIDBankCounter; i++) { - //Store UUID from bank - XStringW CurrentUUID = GuidLEToStr((EFI_GUID *)((UINT8 *)APFSUUIDBank+i*0x10)); - //Init temp string with system/install/recovery APFS path - CHAR16 *TmpSysPlistPath = (__typeof__(TmpSysPlistPath))AllocateZeroPool(sizeof(APFSSysPlistPath)); - CHAR16 *TmpServerPlistPath = (__typeof__(TmpServerPlistPath))AllocateZeroPool(sizeof(APFSServerPlistPath)); - CHAR16 *TmpInsPlistPath = (__typeof__(TmpInsPlistPath))AllocateZeroPool(sizeof(APFSInstallPlistPath)); - CHAR16 *TmpRecPlistPath = (__typeof__(TmpRecPlistPath))AllocateZeroPool(sizeof(APFSRecPlistPath)); - CopyMem(TmpSysPlistPath, APFSSysPlistPath, sizeof(APFSSysPlistPath)); - CopyMem(TmpServerPlistPath, APFSServerPlistPath, sizeof(APFSServerPlistPath)); - CopyMem(TmpInsPlistPath, APFSInstallPlistPath, sizeof(APFSInstallPlistPath)); - CopyMem(TmpRecPlistPath, APFSRecPlistPath, sizeof(APFSRecPlistPath)); - INTN size = CurrentUUID.length() * sizeof(CHAR16); //not including null termination 36 * 2 = 72 -// DBG("check CurrentUUID bank=%lld size = %lld\n", i, size); -// DBG("check CurrentUUID string = %ls\n", CurrentUUID.wc_str()); //check passed - CopyMem(TmpSysPlistPath+1, CurrentUUID.wc_str(), size); - CopyMem(TmpServerPlistPath+1, CurrentUUID.wc_str(), size); - CopyMem(TmpInsPlistPath+1, CurrentUUID.wc_str(), size); - CopyMem(TmpRecPlistPath+1, CurrentUUID.wc_str(), size); - //Fill SystemPlists/InstallPlists/RecoveryPlists arrays - SystemPlists[SysIter] = TmpSysPlistPath; - SystemPlists[SysIter+1] = TmpServerPlistPath; - SystemPlists[SysIter+2] = NULL; - InstallPlists[InsIter] = TmpInsPlistPath; - InstallPlists[InsIter+1] = NULL; - RecoveryPlists[RecIter] = TmpRecPlistPath; - RecoveryPlists[RecIter+1] = NULL; - SysIter+=2; - InsIter++; - RecIter++; - } -} #ifdef DEBUG_CLOVER XStringW g_str(L"g_str:foobar"); @@ -1981,7 +1874,8 @@ RefitMain (IN EFI_HANDLE ImageHandle, DBG("Clover : Image base = 0x%llX\n", (uintptr_t)SelfLoadedImage->ImageBase); // do not change, it's used by grep to feed the debugger #ifdef JIEF_DEBUG - gBS->Stall(1500000); // to give time to gdb to connect +// gBS->Stall(1500000); // to give time to gdb to connect + gBS->Stall(0500000); // to give time to gdb to connect // PauseForKey(L"press\n"); #endif @@ -2402,25 +2296,6 @@ RefitMain (IN EFI_HANDLE ImageHandle, InitKextList(); ScanVolumes(); - //Check apfs driver loaded state - //Free APFSUUIDBank - if (APFSUUIDBank != NULL) { - //Free mem - FreePool(APFSUUIDBank); - //Reset counter - APFSUUIDBankCounter=0; - } - /* APFS container support */ - //Fill APFSUUIDBank - APFSUUIDBank = APFSContainer_Support(); - if (APFSUUIDBankCounter != 0) { - APFSSupport = TRUE; - } else { - APFSSupport = FALSE; - } - //Fill systemversion plists path - SystemVersionInit(); - // as soon as we have Volumes, find latest nvram.plist and copy it to RT vars if (!AfterTool) { if (gFirmwareClover || gDriversFlags.EmuVariableLoaded) {