Rework APFS Preboot and Recovery volumes

This commit is contained in:
jief666 2020-08-07 11:23:46 +03:00
parent 76c0e3fe55
commit feba2f1399
14 changed files with 338 additions and 295 deletions

View File

@ -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;
//}

View File

@ -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_ */

View File

@ -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());
}

View File

@ -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());

View File

@ -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') {

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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 {

View File

@ -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<<Volume->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);

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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) {