/* * refit/main.c * Main code for the boot menu * * Copyright (c) 2006-2010 Christoph Pfisterer * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the * distribution. * * * Neither the name of Christoph Pfisterer nor the names of the * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include // Only use angled for Platform, else, xcode project won't compile #include #include #include "../cpp_foundation/XString.h" #include "../cpp_unit_test/all_tests.h" #include "../entry_scan/entry_scan.h" #include "../libeg/nanosvg.h" #include "../gui/menu_items/menu_globals.h" #include "menu.h" #include "../Platform/Settings.h" #include "../Platform/DataHubCpu.h" #include "../Platform/Events.h" #include "screen.h" #include "../entry_scan/bootscreen.h" #include "../Platform/Nvram.h" #include "../entry_scan/common.h" #include "../gui/shared_with_menu.h" #include "../Platform/platformdata.h" #include "../Platform/guid.h" #include "../Platform/APFS.h" #include "../Platform/cpu.h" #include "../Platform/smbios.h" #include "../Platform/AcpiPatcher.h" #include "../Platform/Hibernate.h" #include "../Platform/LegacyBoot.h" #include "../Platform/PlatformDriverOverride.h" #include "../Platform/Edid.h" #include "../Platform/Console.h" #include "../Platform/spd.h" #include "../Platform/Injectors.h" #include "../Platform/StartupSound.h" #include "../Platform/BootOptions.h" #include "../Platform/boot.h" #include "../Platform/kext_inject.h" #include "../Platform/KextList.h" #include "../gui/REFIT_MENU_SCREEN.h" #include "../gui/REFIT_MAINMENU_SCREEN.h" #include "../Settings/Self.h" #include "../Settings/SelfOem.h" #include "../Platform/BasicIO.h" #include "../include/OSTypes.h" #include "../include/OSFlags.h" #include "../libeg/XTheme.h" #include "../Settings/ConfigManager.h" #include "../Platform/CloverVersion.h" #include "../Platform/SmbiosFillPatchingValues.h" #include "../include/OC.h" #ifndef DEBUG_ALL # ifdef DEBUG_ERALY_CRASH # define DEBUG_MAIN 2 # else # define DEBUG_MAIN 1 # endif #else # define DEBUG_MAIN DEBUG_ALL #endif #if DEBUG_MAIN == 0 #define DBG(...) #else #define DBG(...) DebugLog(DEBUG_MAIN, __VA_ARGS__) #endif #ifndef HIBERNATE #define HIBERNATE 0 #endif #ifndef CHECK_SMC #define CHECK_SMC 0 #endif #define PCAT_RTC_ADDRESS_REGISTER 0x70 #define PCAT_RTC_DATA_REGISTER 0x71 // variables XBool gGuiIsReady = false; XBool gThemeNeedInit = true; XBool DoHibernateWake = false; UINT32 mCurrentColor; extern UINT32 gFakeCPUID; EFI_HANDLE AudioDriverHandle; XStringW OpenRuntimeEfiName; extern void HelpRefit(void); extern void AboutRefit(void); extern EFI_AUDIO_IO_PROTOCOL *AudioIo; extern EFI_DXE_SERVICES *gDS; static EFI_STATUS LoadEFIImageList(IN EFI_DEVICE_PATH **DevicePaths, IN CONST XStringW& ImageTitle, OUT UINTN *ErrorInStep, OUT EFI_HANDLE *NewImageHandle) { EFI_STATUS Status, ReturnStatus; EFI_HANDLE ChildImageHandle = 0; UINTN DevicePathIndex; DBG("Loading %ls", ImageTitle.wc_str()); if (ErrorInStep != NULL) { *ErrorInStep = 0; } if (NewImageHandle != NULL) { *NewImageHandle = NULL; } // load the image into memory ReturnStatus = Status = EFI_NOT_FOUND; // in case the list is empty for (DevicePathIndex = 0; DevicePaths[DevicePathIndex] != NULL; DevicePathIndex++) { ReturnStatus = Status = gBS->LoadImage(false, self.getSelfImageHandle(), DevicePaths[DevicePathIndex], NULL, 0, &ChildImageHandle); DBG(" status=%s", efiStrError(Status)); if (ReturnStatus != EFI_NOT_FOUND) break; } XStringW ErrorInfo = SWPrintf(" while loading %ls", ImageTitle.wc_str()); if (CheckError(Status, ErrorInfo.wc_str())) { if (ErrorInStep != NULL) *ErrorInStep = 1; PauseForKey(NullXString8); goto bailout; }else{ DBG("\n"); #ifdef JIEF_DEBUG DBG("ChildImaheHandle=%llx\n", uintptr_t(ChildImageHandle)); #endif } if (!EFI_ERROR(ReturnStatus)) { //why unload driver?! if (NewImageHandle != NULL) { *NewImageHandle = ChildImageHandle; } #ifdef JIEF_DEBUG EFI_LOADED_IMAGE_PROTOCOL* loadedBootImage = NULL; if (!EFI_ERROR(Status = gBS->HandleProtocol(ChildImageHandle, &gEfiLoadedImageProtocolGuid, (void**)(&loadedBootImage)))) { DBG("%ls : Image base = 0x%llx\n", ImageTitle.wc_str(), (uintptr_t)loadedBootImage->ImageBase); // Jief : Do not change this, it's used by grep to feed the debugger }else{ DBG("Can't get loaded image protocol\n"); } #endif goto bailout; } // unload the image, we don't care if it works or not... Status = gBS->UnloadImage(ChildImageHandle); bailout: return ReturnStatus; } static EFI_STATUS StartEFILoadedImage(IN EFI_HANDLE ChildImageHandle, IN CONST XString8Array& LoadOptions, IN CONST XStringW& LoadOptionsPrefix, IN CONST XStringW& ImageTitle, OUT UINTN *ErrorInStep) { EFI_STATUS Status, ReturnStatus; EFI_LOADED_IMAGE_PROTOCOL *ChildLoadedImage; CHAR16 ErrorInfo[256]; XStringW loadOptionsW; // This has to be declared here, so it's not be freed before calling StartImage // DBG("Starting %ls\n", ImageTitle); if (ErrorInStep != NULL) { *ErrorInStep = 0; } ReturnStatus = Status = EFI_NOT_FOUND; // in case no image handle was specified if (ChildImageHandle == NULL) { if (ErrorInStep != NULL) *ErrorInStep = 1; goto bailout; } // set load options if (!LoadOptions.isEmpty()) { ReturnStatus = Status = gBS->HandleProtocol(ChildImageHandle, &gEfiLoadedImageProtocolGuid, (void **) &ChildLoadedImage); if (CheckError(Status, L"while getting a LoadedImageProtocol handle")) { if (ErrorInStep != NULL) *ErrorInStep = 2; goto bailout_unload; } if ( LoadOptionsPrefix.notEmpty() ) { // NOTE: That last space is also added by the EFI shell and seems to be significant // when passing options to Apple's boot.efi... loadOptionsW = SWPrintf("%ls %s ", LoadOptionsPrefix.wc_str(), LoadOptions.ConcatAll(" "_XS8).c_str()); }else{ loadOptionsW = SWPrintf("%s ", LoadOptions.ConcatAll(" "_XS8).c_str()); // Jief : should we add a space ? Wasn't the case before big refactoring. Yes, a space required. } // NOTE: We also include the terminating null in the length for safety. ChildLoadedImage->LoadOptionsSize = (UINT32)loadOptionsW.sizeInBytes() + sizeof(wchar_t); ChildLoadedImage->LoadOptions = loadOptionsW.wc_str(); //will it be deleted after the procedure exit? Yes, if we don't copy loadOptionsW, so it'll be freed at the end of method DBG("start image '%ls'\n", ImageTitle.s()); DBG("Using load options '%ls'\n", (CHAR16*)ChildLoadedImage->LoadOptions); } // close open file handles UninitRefitLib(); // turn control over to the image // // Before calling the image, enable the Watchdog Timer for // the 5 Minute period - Slice - NO! For slow driver and slow disk we need more // gBS->SetWatchdogTimer (600, 0x0000, 0x00, NULL); ReturnStatus = Status = gBS->StartImage(ChildImageHandle, NULL, NULL); // // Clear the Watchdog Timer after the image returns // gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL); ReinitRefitLib(); // control returns here when the child image calls Exit() if (ImageTitle.notEmpty()) { snwprintf(ErrorInfo, 512, "returned from %ls", ImageTitle.s()); } if (CheckError(Status, ErrorInfo)) { if (ErrorInStep != NULL) *ErrorInStep = 3; } if (!EFI_ERROR(ReturnStatus)) { //why unload driver?! goto bailout; } bailout_unload: // unload the image, we don't care if it works or not... Status = gBS->UnloadImage(ChildImageHandle); bailout: return ReturnStatus; } static EFI_STATUS LoadEFIImage(IN EFI_DEVICE_PATH *DevicePath, IN CONST XStringW& ImageTitle, OUT UINTN *ErrorInStep, OUT EFI_HANDLE *NewImageHandle) { EFI_DEVICE_PATH *DevicePaths[2]; #ifdef ENABLE_SECURE_BOOT // Verify secure boot policy if (GlobalConfig.SecureBoot && GlobalConfig.SecureBootSetupMode) { // Only verify if in forced secure boot mode EFI_STATUS Status = VerifySecureBootImage(DevicePath); if (EFI_ERROR(Status)) { return Status; } } #endif // ENABLE_SECURE_BOOT // Load the image now DevicePaths[0] = DevicePath; DevicePaths[1] = NULL; return LoadEFIImageList(DevicePaths, ImageTitle, ErrorInStep, NewImageHandle); } static EFI_STATUS StartEFIImage(IN EFI_DEVICE_PATH *DevicePath, IN CONST XString8Array& LoadOptions, IN CONST XStringW& LoadOptionsPrefix, IN CONST XStringW& ImageTitle, OUT UINTN *ErrorInStep, OUT EFI_HANDLE *NewImageHandle) { EFI_STATUS Status; EFI_HANDLE ChildImageHandle = NULL; Status = LoadEFIImage(DevicePath, ImageTitle, ErrorInStep, &ChildImageHandle); if (!EFI_ERROR(Status)) { Status = StartEFILoadedImage(ChildImageHandle, LoadOptions, LoadOptionsPrefix, ImageTitle, ErrorInStep); } if (NewImageHandle != NULL) { *NewImageHandle = ChildImageHandle; } return Status; } #ifdef DUMP_KERNEL_KEXT_PATCHES void DumpKernelAndKextPatches(KERNEL_AND_KEXT_PATCHES *Patches) { if (!Patches) { DBG("Kernel and Kext Patches null pointer\n"); return; } DBG("Kernel and Kext Patches at %llx:\n", (uintptr_t)Patches); DBG("\tAllowed: %c\n", GlobalConfig.KextPatchesAllowed ? 'y' : 'n'); DBG("\tDebug: %c\n", Patches->KPDebug ? 'y' : 'n'); // DBG("\tKernelCpu: %c\n", Patches->KPKernelCpu ? 'y' : 'n'); DBG("\tKernelLapic: %c\n", Patches->KPKernelLapic ? 'y' : 'n'); DBG("\tKernelXCPM: %c\n", Patches->KPKernelXCPM ? 'y' : 'n'); DBG("\tKernelPm: %c\n", Patches->KPKernelPm ? 'y' : 'n'); DBG("\tAppleIntelCPUPM: %c\n", Patches->KPAppleIntelCPUPM ? 'y' : 'n'); DBG("\tAppleRTC: %c\n", Patches->KPAppleRTC ? 'y' : 'n'); // Dell smbios truncate fix DBG("\tDellSMBIOSPatch: %c\n", Patches->KPDELLSMBIOS ? 'y' : 'n'); DBG("\tFakeCPUID: 0x%X\n", Patches->FakeCPUID); DBG("\tATIController: %s\n", Patches->KPATIConnectorsController.isEmpty() ? "(null)": Patches->KPATIConnectorsController.c_str()); DBG("\tATIDataLength: %zu\n", Patches->KPATIConnectorsData.size()); DBG("\t%zu Kexts to load\n", Patches->ForceKextsToLoad.size()); if (Patches->ForceKextsToLoad.size()) { size_t i = 0; for (; i < Patches->ForceKextsToLoad.size(); ++i) { DBG("\t KextToLoad[%zu]: %ls\n", i, Patches->ForceKextsToLoad[i].wc_str()); } } DBG("\t%zu Kexts to patch\n", Patches->KextPatches.size()); if (Patches->KextPatches.size()) { size_t i = 0; for (; i < Patches->KextPatches.size(); ++i) { if (Patches->KextPatches[i].IsPlistPatch) { DBG("\t KextPatchPlist[%zu]: %zu bytes, %s\n", i, Patches->KextPatches[i].Data.size(), Patches->KextPatches[i].Name.c_str()); } else { DBG("\t KextPatch[%zu]: %zu bytes, %s\n", i, Patches->KextPatches[i].Data.size(), Patches->KextPatches[i].Name.c_str()); } } } } #endif void LOADER_ENTRY::FilterKextPatches() { if ( GlobalConfig.KextPatchesAllowed && KernelAndKextPatches.KextPatches.size() > 0 ) { DBG("Filtering KextPatches:\n"); for (size_t i = 0; i < KernelAndKextPatches.KextPatches.size(); i++) { DBG(" - [%02zu]: %s :: %s :: [OS: %s | MatchOS: %s | MatchBuild: %s]", i, KernelAndKextPatches.KextPatches[i].Label.c_str(), KernelAndKextPatches.KextPatches[i].IsPlistPatch ? "PlistPatch" : "BinPatch", macOSVersion.asString().c_str(), KernelAndKextPatches.KextPatches[i].MatchOS.notEmpty() ? KernelAndKextPatches.KextPatches[i].MatchOS.c_str() : "All", KernelAndKextPatches.KextPatches[i].MatchBuild.notEmpty() ? KernelAndKextPatches.KextPatches[i].MatchBuild.c_str() : "All" ); if (!gSettings.KernelAndKextPatches.KextPatches[i].MenuItem.BValue) { KernelAndKextPatches.KextPatches[i].MenuItem.BValue = false; DBG(" ==> disabled by user\n"); continue; } KernelAndKextPatches.KextPatches[i].MenuItem.BValue = true; if ((BuildVersion.notEmpty()) && (KernelAndKextPatches.KextPatches[i].MatchBuild.notEmpty())) { KernelAndKextPatches.KextPatches[i].MenuItem.BValue = KernelAndKextPatches.KextPatches[i].IsPatchEnabledByBuildNumber(BuildVersion); DBG(" ==> %s\n", KernelAndKextPatches.KextPatches[i].MenuItem.BValue ? "allowed" : "not allowed"); continue; } KernelAndKextPatches.KextPatches[i].MenuItem.BValue = KernelAndKextPatches.KextPatches[i].IsPatchEnabled(macOSVersion); DBG(" ==> %s\n", KernelAndKextPatches.KextPatches[i].MenuItem.BValue ? "allowed" : "not allowed"); } } } void LOADER_ENTRY::FilterKernelPatches() { if ( GlobalConfig.KernelPatchesAllowed && KernelAndKextPatches.KernelPatches.notEmpty() ) { DBG("Filtering KernelPatches:\n"); for (size_t i = 0; i < KernelAndKextPatches.KernelPatches.size(); ++i) { DBG(" - [%02zu]: %s :: [OS: %s | MatchOS: %s | MatchBuild: %s]", i, KernelAndKextPatches.KernelPatches[i].Label.c_str(), macOSVersion.asString().c_str(), KernelAndKextPatches.KernelPatches[i].MatchOS.notEmpty() ? KernelAndKextPatches.KernelPatches[i].MatchOS.c_str() : "All", KernelAndKextPatches.KernelPatches[i].MatchBuild.notEmpty() ? KernelAndKextPatches.KernelPatches[i].MatchBuild.c_str() : "All" ); if (!gSettings.KernelAndKextPatches.KernelPatches[i].MenuItem.BValue) { KernelAndKextPatches.KernelPatches[i].MenuItem.BValue = false; DBG(" ==> disabled by user\n"); continue; } KernelAndKextPatches.KernelPatches[i].MenuItem.BValue = true; if ((BuildVersion.notEmpty()) && (KernelAndKextPatches.KernelPatches[i].MatchBuild.notEmpty())) { KernelAndKextPatches.KernelPatches[i].MenuItem.BValue = KernelAndKextPatches.KernelPatches[i].IsPatchEnabledByBuildNumber(BuildVersion); DBG(" ==> %s by build\n", KernelAndKextPatches.KernelPatches[i].MenuItem.BValue ? "allowed" : "not allowed"); continue; } KernelAndKextPatches.KernelPatches[i].MenuItem.BValue = KernelAndKextPatches.KernelPatches[i].IsPatchEnabled(macOSVersion); DBG(" ==> %s by OS\n", KernelAndKextPatches.KernelPatches[i].MenuItem.BValue ? "allowed" : "not allowed"); } } } void LOADER_ENTRY::FilterBootPatches() { if ( KernelAndKextPatches.BootPatches.notEmpty() ) { DBG("Filtering BootPatches:\n"); for (size_t i = 0; i < KernelAndKextPatches.BootPatches.size(); ++i) { DBG(" - [%02zu]: %s :: [OS: %s | MatchOS: %s | MatchBuild: %s]", i, KernelAndKextPatches.BootPatches[i].Label.c_str(), macOSVersion.asString().c_str(), KernelAndKextPatches.BootPatches[i].MatchOS.notEmpty() ? KernelAndKextPatches.BootPatches[i].MatchOS.c_str() : "All", KernelAndKextPatches.BootPatches[i].MatchBuild.notEmpty() ? KernelAndKextPatches.BootPatches[i].MatchBuild.c_str() : "All" ); if (!gSettings.KernelAndKextPatches.BootPatches[i].MenuItem.BValue) { DBG(" ==> disabled by user\n"); continue; } KernelAndKextPatches.BootPatches[i].MenuItem.BValue = true; if ((BuildVersion.notEmpty()) && (KernelAndKextPatches.BootPatches[i].MatchBuild.notEmpty())) { KernelAndKextPatches.BootPatches[i].MenuItem.BValue = KernelAndKextPatches.BootPatches[i].IsPatchEnabledByBuildNumber(BuildVersion); DBG(" ==> %s by build\n", KernelAndKextPatches.BootPatches[i].MenuItem.BValue ? "allowed" : "not allowed"); continue; } KernelAndKextPatches.BootPatches[i].MenuItem.BValue = KernelAndKextPatches.BootPatches[i].IsPatchEnabled(macOSVersion); DBG(" ==> %s by OS\n", KernelAndKextPatches.BootPatches[i].MenuItem.BValue ? "allowed" : "not allowed"); } } } // // Null ConOut OutputString() implementation - for blocking // text output from boot.efi when booting in graphics mode // EFI_STATUS EFIAPI NullConOutOutputString(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *, IN CONST CHAR16 *) { return EFI_SUCCESS; } void CheckEmptyFB() { XBool EmptyFB = (GlobalConfig.IgPlatform == 0x00050000) || (GlobalConfig.IgPlatform == 0x01620007) || (GlobalConfig.IgPlatform == 0x04120004) || (GlobalConfig.IgPlatform == 0x19120001) || (GlobalConfig.IgPlatform == 0x59120003) || (GlobalConfig.IgPlatform == 0x9BC80003) || (GlobalConfig.IgPlatform == 0x3E910003); if (EmptyFB) { gSettings.Smbios.gPlatformFeature |= PT_FEATURE_HAS_HEADLESS_GPU; } else { gSettings.Smbios.gPlatformFeature &= ~PT_FEATURE_HAS_HEADLESS_GPU; } } size_t setKextAtPos(XObjArray* kextArrayPtr, const XString8& kextName, size_t pos) { XObjArray& kextArray = *kextArrayPtr; for (size_t kextIdx = 0 ; kextIdx < kextArray.size() ; kextIdx++ ) { if ( kextArray[kextIdx].FileName.contains(kextName) ) { #ifdef JIEF_DEBUG if ( pos >= kextArray.size() ) panic("pos >= kextArray.size()"); #else //it is impossible #endif if ( pos == kextIdx ) return pos+1; if ( pos > kextIdx ) pos -= 1; SIDELOAD_KEXT* kextToMove = &kextArray[kextIdx]; kextArray.RemoveWithoutFreeingAtIndex(kextIdx); kextArray.InsertRef(kextToMove, pos, false); return pos+1; } } return pos; } static XStringW getDriversPath() { #if defined(MDE_CPU_X64) if (gFirmwareClover) { if (FileExists(&self.getCloverDir(), L"drivers\\BIOS")) { return L"drivers\\BIOS"_XSW; } else { return L"drivers64"_XSW; //backward compatibility } } else if (FileExists(&self.getCloverDir(), L"drivers\\5142")) { // can be excluded as obsolete return L"drivers\\5142"_XSW; } else if (FileExists(&self.getCloverDir(), L"drivers\\UEFI")) { return L"drivers\\UEFI"_XSW; } else { return L"drivers64UEFI"_XSW; } #else return L"drivers32"_XSW; #endif } #ifdef JIEF_DEBUG void debugStartImageWithOC() { MsgLog("debugStartImageWithOC\n"); UINT64 CPUFrequencyFromART; InternalCalculateARTFrequencyIntel(&CPUFrequencyFromART, NULL, 1); EFI_LOADED_IMAGE* OcLoadedImage; EFI_STATUS Status = gBS->HandleProtocol(gImageHandle, &gEfiLoadedImageProtocolGuid, (void **) &OcLoadedImage); EFI_SIMPLE_FILE_SYSTEM_PROTOCOL* FileSystem = OcLocateFileSystem(OcLoadedImage->DeviceHandle, OcLoadedImage->FilePath); Status = OcStorageInitFromFs(&mOpenCoreStorage, FileSystem, NULL, NULL, self.getCloverDirFullPath().wc_str(), NULL); Status = ClOcReadConfigurationFile(&mOpenCoreStorage, L"config-oc.plist", &mOpenCoreConfiguration); if ( EFI_ERROR(Status) ) panic("ClOcReadConfigurationFile"); mOpenCoreConfiguration.Misc.Debug.Target = 0; OC_STRING_ASSIGN(mOpenCoreConfiguration.Misc.Boot.PickerMode, "Builtin"); OC_STRING_ASSIGN(mOpenCoreConfiguration.Misc.Security.DmgLoading, "Any"); mOpenCoreConfiguration.Uefi.Quirks.IgnoreInvalidFlexRatio = 0; mOpenCoreConfiguration.Uefi.Quirks.TscSyncTimeout = 0; OcMain(&mOpenCoreStorage, NULL); XStringW devicePathToLookFor; // devicePathToLookFor.takeValueFrom("PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x0,0x0,0x0)/HD(4,GPT,CA224585-830E-4274-5826-1ACB6DA08A4E,0x299F000,0x4AE6310)/VenMedia(BE74FCF7-0B7C-49F3-9147-01F4042E6842,1ABE434C8D0357398516CFDF0A9DD7EF)"); // Jief High Sierra DevicePath devicePathToLookFor.takeValueFrom("PciRoot(0x0)/Pci(0x1F,0x2)/Sata(0x0,0x0,0x0)/HD(2,GPT,D8C7DA82-1E4C-4579-BA7C-6737A5D43464,0x64028,0x1BF08E8)"); // Jief Big Sur Install device path UINTN HandleCount = 0; EFI_HANDLE *Handles = NULL; Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiSimpleFileSystemProtocolGuid, NULL, &HandleCount, &Handles); UINTN HandleIndex = 0; for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) { EFI_DEVICE_PATH_PROTOCOL* DevicePath = DevicePathFromHandle(Handles[HandleIndex]); CHAR16* UnicodeDevicePath = ConvertDevicePathToText(DevicePath, false, false); MsgLog("debugStartImageWithOC : path %ls\n", UnicodeDevicePath); if ( StrCmp(devicePathToLookFor.wc_str(), UnicodeDevicePath) == 0 ) break; } if ( HandleIndex < HandleCount ) { EFI_DEVICE_PATH_PROTOCOL* jfkImagePath = FileDevicePath(Handles[HandleIndex], L"\\System\\Library\\CoreServices\\boot.efi"); CHAR16* UnicodeDevicePath = ConvertDevicePathToText (jfkImagePath, false, false); (void)UnicodeDevicePath; EFI_HANDLE EntryHandle = NULL; // point to InternalEfiLoadImage from OC Status = gBS->LoadImage ( false, gImageHandle, jfkImagePath, NULL, 0, &EntryHandle ); if ( EFI_ERROR(Status) ) return; // TODO message ? EFI_LOADED_IMAGE *LoadedImage = NULL; EFI_STATUS OptionalStatus = gBS->HandleProtocol ( EntryHandle, &gEfiLoadedImageProtocolGuid, (void **) &LoadedImage ); if ( EFI_ERROR(OptionalStatus) ) return; // TODO message ? // XStringW LoadOptionsAsXStringW = SWPrintf("%s ", LoadOptions.ConcatAll(" "_XS8).c_str()); XStringW LoadOptionsAsXStringW = SWPrintf("boot.efi -v -no_compat_check slide=0 kext-dev-mode=1 keepsyms=1 -wegdbg igfxgl=1 bpr_probedelay=200 bpr_initialdelay=400 bpr_postresetdelay=400 "); LoadedImage->LoadOptions = (void*)LoadOptionsAsXStringW.wc_str(); LoadedImage->LoadOptionsSize = (UINT32)LoadOptionsAsXStringW.sizeInBytesIncludingTerminator(); // point to OcStartImage from OC Status = gBS->StartImage (EntryHandle, 0, NULL); if ( EFI_ERROR(Status) ) return; // TODO message ? }else{ MsgLog("debugStartImageWithOC : not found\n"); } } #endif void LOADER_ENTRY::DelegateKernelPatches() { XObjArray selectedPathArray; for (size_t kextPatchIdx = 0 ; kextPatchIdx < KernelAndKextPatches.KextPatches.size() ; kextPatchIdx++ ) { if ( KernelAndKextPatches.KextPatches[kextPatchIdx].MenuItem.BValue ) selectedPathArray.AddReference(&KernelAndKextPatches.KextPatches[kextPatchIdx], false); } for (size_t kernelPatchIdx = 0 ; kernelPatchIdx < KernelAndKextPatches.KernelPatches.size() ; kernelPatchIdx++ ) { if ( KernelAndKextPatches.KernelPatches[kernelPatchIdx].MenuItem.BValue ) selectedPathArray.AddReference(&KernelAndKextPatches.KernelPatches[kernelPatchIdx], false); } mOpenCoreConfiguration.Kernel.Patch.Count = (UINT32)selectedPathArray.size(); mOpenCoreConfiguration.Kernel.Patch.AllocCount = mOpenCoreConfiguration.Kernel.Patch.Count; mOpenCoreConfiguration.Kernel.Patch.ValueSize = sizeof(__typeof_am__(**mOpenCoreConfiguration.Kernel.Patch.Values)); mOpenCoreConfiguration.Kernel.Patch.Values = (__typeof_am__(*mOpenCoreConfiguration.Kernel.Patch.Values)*)malloc(mOpenCoreConfiguration.Kernel.Patch.AllocCount*sizeof(__typeof_am__(*mOpenCoreConfiguration.Kernel.Patch.Values))); memset(mOpenCoreConfiguration.Kernel.Patch.Values, 0, mOpenCoreConfiguration.Kernel.Patch.AllocCount*sizeof(*mOpenCoreConfiguration.Kernel.Patch.Values)); UINT32 FakeCPUID = gSettings.Smbios.SFakeCPU; if (FakeCPUID != 0) gFakeCPUID = FakeCPUID; DBG("Set FakeCPUID: 0x%X\n", gFakeCPUID); memset(mOpenCoreConfiguration.Kernel.Emulate.Cpuid1Data, 0, sizeof(mOpenCoreConfiguration.Kernel.Emulate.Cpuid1Data)); memset(mOpenCoreConfiguration.Kernel.Emulate.Cpuid1Mask, 0, sizeof(mOpenCoreConfiguration.Kernel.Emulate.Cpuid1Mask)); mOpenCoreConfiguration.Kernel.Emulate.Cpuid1Data[0] = gFakeCPUID; mOpenCoreConfiguration.Kernel.Emulate.Cpuid1Mask[0] = 0xFFFFFFFF; for (size_t kextPatchIdx = 0 ; kextPatchIdx < selectedPathArray.size() ; kextPatchIdx++ ) { const ABSTRACT_KEXT_OR_KERNEL_PATCH& kextPatch = selectedPathArray[kextPatchIdx]; //as well as kernel patches DBG("Bridge %s patch to OC : %s\n", kextPatch.getName().c_str(), kextPatch.Label.c_str()); mOpenCoreConfiguration.Kernel.Patch.Values[kextPatchIdx] = (__typeof_am__(*mOpenCoreConfiguration.Kernel.Patch.Values))AllocateZeroPool(mOpenCoreConfiguration.Kernel.Patch.ValueSize); // sizeof(OC_KERNEL_ADD_ENTRY) == 680 OC_STRING_ASSIGN(mOpenCoreConfiguration.Kernel.Patch.Values[kextPatchIdx]->Arch, OC_BLOB_GET(&mOpenCoreConfiguration.Kernel.Scheme.KernelArch)); OC_STRING_ASSIGN(mOpenCoreConfiguration.Kernel.Patch.Values[kextPatchIdx]->Base, kextPatch.ProcedureName.c_str()); OC_STRING_ASSIGN(mOpenCoreConfiguration.Kernel.Patch.Values[kextPatchIdx]->Comment, kextPatch.Label.c_str()); mOpenCoreConfiguration.Kernel.Patch.Values[kextPatchIdx]->Count = (UINT32)kextPatch.Count; mOpenCoreConfiguration.Kernel.Patch.Values[kextPatchIdx]->Enabled = 1; OC_DATA_ASSIGN_N(mOpenCoreConfiguration.Kernel.Patch.Values[kextPatchIdx]->Find, kextPatch.Find.data(), kextPatch.Find.size()); OC_STRING_ASSIGN(mOpenCoreConfiguration.Kernel.Patch.Values[kextPatchIdx]->Identifier, kextPatch.getName().c_str()); mOpenCoreConfiguration.Kernel.Patch.Values[kextPatchIdx]->Limit = (UINT32)kextPatch.SearchLen; OC_DATA_ASSIGN_N(mOpenCoreConfiguration.Kernel.Patch.Values[kextPatchIdx]->Mask, kextPatch.MaskFind.data(), kextPatch.MaskFind.size()); OC_STRING_ASSIGN(mOpenCoreConfiguration.Kernel.Patch.Values[kextPatchIdx]->MaxKernel, ""); // it has been filtered, so we don't need to set Min and MaxKernel OC_STRING_ASSIGN(mOpenCoreConfiguration.Kernel.Patch.Values[kextPatchIdx]->MinKernel, ""); OC_DATA_ASSIGN_N(mOpenCoreConfiguration.Kernel.Patch.Values[kextPatchIdx]->Replace, kextPatch.Replace.data(), kextPatch.Replace.size()); OC_DATA_ASSIGN_N(mOpenCoreConfiguration.Kernel.Patch.Values[kextPatchIdx]->ReplaceMask, kextPatch.MaskReplace.data(), kextPatch.MaskReplace.size()); mOpenCoreConfiguration.Kernel.Patch.Values[kextPatchIdx]->Skip = (UINT32)kextPatch.Skip; #ifdef JIEF_DEBUG if ( kextPatch.Label == "algrey - cpuid_set_info - ryzen cores and logicals count - part 3 - 10.14"_XS8 ) { DEBUG (( DEBUG_INFO, "" )); } #endif } } void LOADER_ENTRY::StartLoader() { EFI_STATUS Status; EFI_TEXT_STRING ConOutOutputString = 0; EFI_HANDLE ImageHandle = NULL; EFI_LOADED_IMAGE *LoadedImage = NULL; CONST CHAR8 *InstallerVersion; DbgHeader("StartLoader"); DBG("Starting %ls\n", FileDevicePathToXStringW(DevicePath).wc_str()); displayFreeMemory("LOADER_ENTRY::StartLoader()"_XS8); // while ( OcCountFreePages(NULL) > 300000 && AllocatePages(100) ) /*DBG("Free memory : %lld\n", OcCountFreePages(NULL))*/; // displayFreeMemory(); if (Settings.notEmpty()) { DBG(" Settings: %ls\n", Settings.wc_str()); Status = gConf.ReLoadConfig(Settings); if (!EFI_ERROR(Status)) { DBG(" - found custom settings for this entry: %ls\n", Settings.wc_str()); } else { DBG(" - [!] LoadUserSettings failed: %s\n", efiStrError(Status)); /* we are not sure of the state of gSettings here... try to boot anyway */ } } DBG("Finally: ExternalClock=%lluMHz BusSpeed=%llukHz CPUFreq=%uMHz", DivU64x32(gCPUStructure.ExternalClock + Kilo - 1, Kilo), DivU64x32(gCPUStructure.FSBFrequency + Kilo - 1, Kilo), gCPUStructure.MaxSpeed); if (gSettings.CPU.QPI) { DBG(" QPI: hw.busfrequency=%lluHz\n", MultU64x32(gSettings.CPU.QPI, Mega)); } else { // to match the value of hw.busfrequency in the terminal DBG(" PIS: hw.busfrequency=%lluHz\n", MultU64x32(LShiftU64(DivU64x32(gCPUStructure.ExternalClock + Kilo - 1, Kilo), 2), Mega)); } //Free memory ConfigsList.setEmpty(); DsdtsList.setEmpty(); OptionMenu.FreeMenu(); //there is a place to free memory // GuiAnime // mainParser // BuiltinIcons // OSIcons delete ThemeX; ThemeX = NULL; #ifdef NANOSVG_MEMORY_ALLOCATION_TRACE if ( nsvg__nbDanglingPtr() > 0 ) { DBG("There is %zu dangling ptr from SVG subsytem\n", nsvg__nbDanglingPtr()); nsvg__outputDanglingPtr(); } #endif #ifdef JIEF_DEBUG displayFreeMemory("LOADER_ENTRY::StartLoader() atfer ThemeX deleted"_XS8); #endif if ( OSTYPE_IS_OSX(LoaderType) || OSTYPE_IS_OSX_RECOVERY(LoaderType) || OSTYPE_IS_OSX_INSTALLER(LoaderType) ) { // if OC is NOT initialized with OcMain, we need the following // OcConfigureLogProtocol ( // 9, // 0, // 2151678018, // 2147483648, // OPEN_CORE_LOG_PREFIX_PATH, // mOpenCoreStorage.FileSystem // ); // DEBUG ((DEBUG_INFO, "OC: Log initialized...\n")); // OcAppleDebugLogInstallProtocol(0); DBG("Beginning OC\n"); EFI_LOADED_IMAGE* OcLoadedImage; Status = gBS->HandleProtocol(gImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &OcLoadedImage); EFI_SIMPLE_FILE_SYSTEM_PROTOCOL* FileSystem = OcLocateFileSystem(OcLoadedImage->DeviceHandle, OcLoadedImage->FilePath); Status = OcStorageInitFromFs(&mOpenCoreStorage, FileSystem, NULL, NULL, self.getCloverDirFullPath().wc_str(), NULL); /* * Define READ_FROM_OC to have mOpenCoreConfiguration initialized from config-oc.plist * The boot should work. * Next, comment out the next lines one by one. Once the boot failed, we got the section that * holds the setting that makes a difference. */ //#define USE_OC_SECTION_Acpi //#define USE_OC_SECTION_Booter //#define USE_OC_SECTION_DeviceProperties //#define USE_OC_SECTION_Kernel //#define USE_OC_SECTION_Misc //#define USE_OC_SECTION_Nvram //#define USE_OC_SECTION_PlatformInfo //#define USE_OC_SECTION_Uefi #if !defined(USE_OC_SECTION_Acpi) && !defined(USE_OC_SECTION_Booter) && !defined(USE_OC_SECTION_DeviceProperties) && !defined(USE_OC_SECTION_Kernel) && !defined(USE_OC_SECTION_Misc) && \ !defined(USE_OC_SECTION_Nvram) && !defined(USE_OC_SECTION_PlatformInfo) && !defined(USE_OC_SECTION_Uefi) memset(&mOpenCoreConfiguration, 0, sizeof(mOpenCoreConfiguration)); // DBG("config-oc.plist isn't used at all\n"); #else Status = ClOcReadConfigurationFile(&mOpenCoreStorage, L"config-oc.plist", &mOpenCoreConfiguration); if ( EFI_ERROR(Status) ) panic("ClOcReadConfigurationFile"); #ifndef USE_OC_SECTION_Acpi memset(&mOpenCoreConfiguration.Acpi, 0, sizeof(mOpenCoreConfiguration.Acpi)); DBG("Erase mOpenCoreConfiguration.Acpi\n"); #else DBG("Keep mOpenCoreConfiguration.Acpi\n"); #endif #ifndef USE_OC_SECTION_Booter memset(&mOpenCoreConfiguration.Booter, 0, sizeof(mOpenCoreConfiguration.Booter)); DBG("Erase mOpenCoreConfiguration.Booter\n"); #else DBG("Keep mOpenCoreConfiguration.Booter\n"); #endif #ifndef USE_OC_SECTION_DeviceProperties memset(&mOpenCoreConfiguration.DeviceProperties, 0, sizeof(mOpenCoreConfiguration.DeviceProperties)); DBG("Erase mOpenCoreConfiguration.DeviceProperties\n"); #else DBG("Keep mOpenCoreConfiguration.DeviceProperties\n"); #endif #ifndef USE_OC_SECTION_Kernel memset(&mOpenCoreConfiguration.Kernel, 0, sizeof(mOpenCoreConfiguration.Kernel)); DBG("Erase mOpenCoreConfiguration.Kernel\n"); #else DBG("Keep mOpenCoreConfiguration.Kernel\n"); for ( size_t i = 0 ; i < mOpenCoreConfiguration.Kernel.Add.Count ; i ++ ) { OC_KERNEL_ADD_ENTRY* entry = mOpenCoreConfiguration.Kernel.Add.Values[i]; OC_STRING_ASSIGN(entry->BundlePath, S8Printf("Kexts\\%s", OC_BLOB_GET(&entry->BundlePath)).c_str()); } // DBG("mOpenCoreConfiguration.Kernel.Add.Count=%d\n", mOpenCoreConfiguration.Kernel.Add.Count); // for ( size_t i = 0 ; i < mOpenCoreConfiguration.Kernel.Add.Count ; i++ ) // { // DBG("mOpenCoreConfiguration.Kernel.Add.Values[%zd]->Identifier=%s\n", i, OC_BLOB_GET(&mOpenCoreConfiguration.Kernel.Add.Values[i]->Identifier)); // DBG("mOpenCoreConfiguration.Kernel.Add.Values[%zd]->BundlePath=%s\n", i, OC_BLOB_GET(&mOpenCoreConfiguration.Kernel.Add.Values[i]->BundlePath)); // DBG("mOpenCoreConfiguration.Kernel.Add.Values[%zd]->PlistPath=%s\n", i, OC_BLOB_GET(&mOpenCoreConfiguration.Kernel.Add.Values[i]->PlistPath)); // } #endif #ifndef USE_OC_SECTION_Misc memset(&mOpenCoreConfiguration.Misc, 0, sizeof(mOpenCoreConfiguration.Misc)); DBG("Erase mOpenCoreConfiguration.Misc\n"); #else DBG("Keep mOpenCoreConfiguration.Misc\n"); #endif #ifndef USE_OC_SECTION_Nvram memset(&mOpenCoreConfiguration.Nvram, 0, sizeof(mOpenCoreConfiguration.Nvram)); DBG("Erase mOpenCoreConfiguration.Nvram\n"); #else DBG("Keep mOpenCoreConfiguration.Nvram\n"); #endif #ifndef USE_OC_SECTION_PlatformInfo memset(&mOpenCoreConfiguration.PlatformInfo, 0, sizeof(mOpenCoreConfiguration.PlatformInfo)); DBG("Erase mOpenCoreConfiguration.PlatformInfo\n"); #else DBG("Keep mOpenCoreConfiguration.PlatformInfo\n"); #endif #ifndef USE_OC_SECTION_Uefi memset(&mOpenCoreConfiguration.Uefi, 0, sizeof(mOpenCoreConfiguration.Uefi)); DBG("Erase mOpenCoreConfiguration.Uefi\n"); #else DBG("Keep mOpenCoreConfiguration.Uefi\n"); // memset(&mOpenCoreConfiguration.Uefi.Apfs, 0, sizeof(mOpenCoreConfiguration.Uefi.Apfs)); // memset(&mOpenCoreConfiguration.Uefi.Audio, 0, sizeof(mOpenCoreConfiguration.Uefi.Audio)); // memset(&mOpenCoreConfiguration.Uefi.ConnectDrivers, 0, sizeof(mOpenCoreConfiguration.Uefi.ConnectDrivers)); // memset(&mOpenCoreConfiguration.Uefi.Drivers, 0, sizeof(mOpenCoreConfiguration.Uefi.Drivers)); // memset(&mOpenCoreConfiguration.Uefi.Input, 0, sizeof(mOpenCoreConfiguration.Uefi.Input)); // memset(&mOpenCoreConfiguration.Uefi.Output, 0, sizeof(mOpenCoreConfiguration.Uefi.Output)); // memset(&mOpenCoreConfiguration.Uefi.ProtocolOverrides, 0, sizeof(mOpenCoreConfiguration.Uefi.ProtocolOverrides)); // memset(&mOpenCoreConfiguration.Uefi.Quirks, 0, sizeof(mOpenCoreConfiguration.Uefi.Quirks)); // memset(&mOpenCoreConfiguration.Uefi.ReservedMemory, 0, sizeof(mOpenCoreConfiguration.Uefi.ReservedMemory)); // doesn't matter #endif #endif if ( gSettings.Boot.DebugLog ) { mOpenCoreConfiguration.Misc.Debug.AppleDebug = true; mOpenCoreConfiguration.Misc.Debug.ApplePanic = true; #ifndef LESS_DEBUG mOpenCoreConfiguration.Misc.Debug.DisplayLevel = 0x80400042; #else mOpenCoreConfiguration.Misc.Debug.DisplayLevel = 0x80000042; #endif mOpenCoreConfiguration.Misc.Debug.Target = 0x41; } else { #ifdef JIEF_DEBUG egSetGraphicsModeEnabled(false); mOpenCoreConfiguration.Misc.Debug.ApplePanic = true; mOpenCoreConfiguration.Misc.Debug.DisplayLevel = 0x80000042; mOpenCoreConfiguration.Misc.Debug.Target = 0x3; #endif } #ifndef USE_OC_SECTION_Misc OC_STRING_ASSIGN(mOpenCoreConfiguration.Misc.Security.SecureBootModel, "Disabled"); OC_STRING_ASSIGN(mOpenCoreConfiguration.Misc.Security.Vault, "Optional"); #endif #ifdef USE_OC_SECTION_Nvram mOpenCoreConfiguration.Nvram.WriteFlash = true; #endif #ifndef USE_OC_SECTION_Uefi mOpenCoreConfiguration.Uefi.Quirks.ForceOcWriteFlash = gSettings.Quirks.OcBooterQuirks.ForceOcWriteFlash; #endif #ifndef USE_OC_SECTION_Booter mOpenCoreConfiguration.Booter.MmioWhitelist.Count = (UINT32)gSettings.Quirks.mmioWhiteListArray.size(); mOpenCoreConfiguration.Booter.MmioWhitelist.AllocCount = mOpenCoreConfiguration.Booter.MmioWhitelist.Count; mOpenCoreConfiguration.Booter.MmioWhitelist.ValueSize = sizeof(__typeof_am__(**mOpenCoreConfiguration.Booter.MmioWhitelist.Values)); // sizeof(OC_KERNEL_ADD_ENTRY) == 680 if ( mOpenCoreConfiguration.Booter.MmioWhitelist.Count > 0 ) { mOpenCoreConfiguration.Booter.MmioWhitelist.Values = (OC_BOOTER_WL_ENTRY**)AllocatePool(mOpenCoreConfiguration.Booter.MmioWhitelist.AllocCount * sizeof(*mOpenCoreConfiguration.Booter.MmioWhitelist.Values)); // sizeof(OC_KERNEL_ADD_ENTRY) == 680 } else { mOpenCoreConfiguration.Booter.MmioWhitelist.Values = NULL; } for ( size_t idx = 0 ; idx < gSettings.Quirks.mmioWhiteListArray.size() ; idx++ ) { const SETTINGS_DATA::QuirksClass::MMIOWhiteList& entry = gSettings.Quirks.mmioWhiteListArray[idx]; DBG("Bridge mmioWhiteList[%zu] to OC : comment=%s\n", idx, entry.comment.c_str()); mOpenCoreConfiguration.Booter.MmioWhitelist.Values[idx] = (__typeof_am__(*mOpenCoreConfiguration.Booter.MmioWhitelist.Values))AllocatePool(mOpenCoreConfiguration.Booter.MmioWhitelist.ValueSize); mOpenCoreConfiguration.Booter.MmioWhitelist.Values[idx]->Address = entry.address; OC_STRING_ASSIGN(mOpenCoreConfiguration.Booter.MmioWhitelist.Values[idx]->Comment, entry.comment.c_str()); mOpenCoreConfiguration.Booter.MmioWhitelist.Values[idx]->Enabled = entry.enabled; } // It's possible to memcpy the whole struct instead of assigning individual member. But that would be relying on internel C++ binary structure, // and worse, if a field is added by OC, everything could be shifted. memset(&mOpenCoreConfiguration.Booter.Quirks, 0, sizeof(mOpenCoreConfiguration.Booter.Quirks)); mOpenCoreConfiguration.Booter.Quirks.AvoidRuntimeDefrag = gSettings.Quirks.OcBooterQuirks.AvoidRuntimeDefrag; mOpenCoreConfiguration.Booter.Quirks.DevirtualiseMmio = gSettings.Quirks.OcBooterQuirks.DevirtualiseMmio; mOpenCoreConfiguration.Booter.Quirks.DisableSingleUser = gSettings.Quirks.OcBooterQuirks.DisableSingleUser; mOpenCoreConfiguration.Booter.Quirks.DisableVariableWrite = gSettings.Quirks.OcBooterQuirks.DisableVariableWrite; mOpenCoreConfiguration.Booter.Quirks.DiscardHibernateMap = gSettings.Quirks.OcBooterQuirks.DiscardHibernateMap; mOpenCoreConfiguration.Booter.Quirks.EnableSafeModeSlide = gSettings.Quirks.OcBooterQuirks.EnableSafeModeSlide; mOpenCoreConfiguration.Booter.Quirks.EnableWriteUnprotector = gSettings.Quirks.OcBooterQuirks.EnableWriteUnprotector; mOpenCoreConfiguration.Booter.Quirks.ForceExitBootServices = gSettings.Quirks.OcBooterQuirks.ForceExitBootServices; mOpenCoreConfiguration.Booter.Quirks.ProtectMemoryRegions = gSettings.Quirks.OcBooterQuirks.ProtectMemoryRegions; mOpenCoreConfiguration.Booter.Quirks.ProtectSecureBoot = gSettings.Quirks.OcBooterQuirks.ProtectSecureBoot; mOpenCoreConfiguration.Booter.Quirks.ProtectUefiServices = gSettings.Quirks.OcBooterQuirks.ProtectUefiServices; mOpenCoreConfiguration.Booter.Quirks.ProvideCustomSlide = gSettings.Quirks.OcBooterQuirks.ProvideCustomSlide; mOpenCoreConfiguration.Booter.Quirks.ProvideMaxSlide = gSettings.Quirks.OcBooterQuirks.ProvideMaxSlide; mOpenCoreConfiguration.Booter.Quirks.RebuildAppleMemoryMap = gSettings.Quirks.OcBooterQuirks.RebuildAppleMemoryMap; mOpenCoreConfiguration.Booter.Quirks.ResizeAppleGpuBars = gSettings.Quirks.OcBooterQuirks.ResizeAppleGpuBars; mOpenCoreConfiguration.Booter.Quirks.SetupVirtualMap = gSettings.Quirks.OcBooterQuirks.SetupVirtualMap; mOpenCoreConfiguration.Booter.Quirks.SignalAppleOS = false; //gSettings.Quirks.OcBooterQuirks.SignalAppleOS; mOpenCoreConfiguration.Booter.Quirks.SyncRuntimePermissions = gSettings.Quirks.OcBooterQuirks.SyncRuntimePermissions; #endif FillOCCpuInfo(&mOpenCoreCpuInfo); mOpenCoreConfiguration.Uefi.Quirks.TscSyncTimeout = gSettings.Quirks.OcBooterQuirks.TscSyncTimeout; #ifndef USE_OC_SECTION_Kernel XObjArray kextArray; if (!DoHibernateWake) { AddKextsInArray(&kextArray); } OC_STRING_ASSIGN(mOpenCoreConfiguration.Kernel.Scheme.KernelArch, "x86_64"); OC_STRING_ASSIGN(mOpenCoreConfiguration.Kernel.Scheme.KernelCache, gSettings.Quirks.OcKernelCache.c_str()); mOpenCoreConfiguration.Kernel.Scheme.FuzzyMatch = gSettings.Quirks.FuzzyMatch; memset(&mOpenCoreConfiguration.Kernel.Quirks, 0, sizeof(mOpenCoreConfiguration.Kernel.Quirks)); mOpenCoreConfiguration.Kernel.Quirks.SetApfsTrimTimeout = -1; // Jief: Slice modified OcConfigurationLib.h to set -1 by default instead of 999. I prefer the modification here to minimize commts in OC submodule. Makes it easier to upgrade submodule. mOpenCoreConfiguration.Kernel.Quirks.AppleCpuPmCfgLock = GlobalConfig.KPAppleIntelCPUPM; mOpenCoreConfiguration.Kernel.Quirks.AppleXcpmCfgLock = GlobalConfig.KPKernelPm; mOpenCoreConfiguration.Kernel.Quirks.AppleXcpmExtraMsrs = gSettings.Quirks.OcKernelQuirks.AppleXcpmExtraMsrs; mOpenCoreConfiguration.Kernel.Quirks.AppleXcpmForceBoost = gSettings.Quirks.OcKernelQuirks.AppleXcpmForceBoost; #ifndef USE_OC_SECTION_PlatformInfo mOpenCoreConfiguration.Kernel.Quirks.CustomSmbiosGuid = gSettings.KernelAndKextPatches.KPDELLSMBIOS; #endif mOpenCoreConfiguration.Kernel.Quirks.DisableIoMapper = gSettings.Quirks.OcKernelQuirks.DisableIoMapper; mOpenCoreConfiguration.Kernel.Quirks.DisableLinkeditJettison = gSettings.Quirks.OcKernelQuirks.DisableLinkeditJettison; mOpenCoreConfiguration.Kernel.Quirks.DisableRtcChecksum = gSettings.KernelAndKextPatches.KPAppleRTC; mOpenCoreConfiguration.Kernel.Emulate.DummyPowerManagement = gSettings.Quirks.OcKernelQuirks.DummyPowerManagement; mOpenCoreConfiguration.Kernel.Quirks.ExtendBTFeatureFlags = gSettings.Quirks.OcKernelQuirks.ExtendBTFeatureFlags; mOpenCoreConfiguration.Kernel.Quirks.ExternalDiskIcons = gSettings.Quirks.OcKernelQuirks.ExternalDiskIcons; mOpenCoreConfiguration.Kernel.Quirks.IncreasePciBarSize = gSettings.Quirks.OcKernelQuirks.IncreasePciBarSize; mOpenCoreConfiguration.Kernel.Quirks.LapicKernelPanic = gSettings.KernelAndKextPatches.KPKernelLapic; mOpenCoreConfiguration.Kernel.Quirks.PanicNoKextDump = gSettings.KernelAndKextPatches.KPPanicNoKextDump; mOpenCoreConfiguration.Kernel.Quirks.PowerTimeoutKernelPanic = gSettings.Quirks.OcKernelQuirks.PowerTimeoutKernelPanic; mOpenCoreConfiguration.Kernel.Quirks.ThirdPartyDrives = gSettings.Quirks.OcKernelQuirks.ThirdPartyDrives; mOpenCoreConfiguration.Kernel.Quirks.XhciPortLimit = gSettings.Quirks.OcKernelQuirks.XhciPortLimit; mOpenCoreConfiguration.Kernel.Quirks.ProvideCurrentCpuInfo = gSettings.Quirks.OcKernelQuirks.ProvideCurrentCpuInfo; mOpenCoreConfiguration.Kernel.Add.Count = (UINT32)kextArray.size(); mOpenCoreConfiguration.Kernel.Add.AllocCount = mOpenCoreConfiguration.Kernel.Add.Count; mOpenCoreConfiguration.Kernel.Add.ValueSize = sizeof(__typeof_am__(**mOpenCoreConfiguration.Kernel.Add.Values)); // sizeof(OC_KERNEL_ADD_ENTRY) == 680 mOpenCoreConfiguration.Kernel.Add.Values = (OC_KERNEL_ADD_ENTRY**)malloc(mOpenCoreConfiguration.Kernel.Add.AllocCount*sizeof(*mOpenCoreConfiguration.Kernel.Add.Values)); // sizeof(OC_KERNEL_ADD_ENTRY*) == sizeof(ptr) memset(mOpenCoreConfiguration.Kernel.Add.Values, 0, mOpenCoreConfiguration.Kernel.Add.AllocCount*sizeof(*mOpenCoreConfiguration.Kernel.Add.Values)); // Seems that Lilu must be first. size_t pos = setKextAtPos(&kextArray, "Lilu.kext"_XS8, 0); pos = setKextAtPos(&kextArray, "VirtualSMC.kext"_XS8, pos); pos = setKextAtPos(&kextArray, "FakeSMC.kext"_XS8, pos); // pos = setKextAtPos(&kextArray, "vecLib.kext"_XS8, pos); // pos = setKextAtPos(&kextArray, "IOAudioFamily.kext"_XS8, pos); pos = setKextAtPos(&kextArray, "IOSkywalkFamily.kext"_XS8, pos); pos = setKextAtPos(&kextArray, "FakePCIID.kext"_XS8, pos); pos = setKextAtPos(&kextArray, "FakePCIID_XHCIMux.kext"_XS8, pos); pos = setKextAtPos(&kextArray, "AMDRyzenCPUPowerManagement.kext"_XS8, pos); pos = setKextAtPos(&kextArray, "SMCAMDProcessor.kext"_XS8, pos); pos = setKextAtPos(&kextArray, "WhateverGreen.kext"_XS8, pos); pos = setKextAtPos(&kextArray, "AppleALC.kext"_XS8, pos); // pos = setKextAtPos(&kextArray, "IntelMausi.kext"_XS8, pos); // not needed special order? pos = setKextAtPos(&kextArray, "SMCProcessor.kext"_XS8, pos); pos = setKextAtPos(&kextArray, "SMCSuperIO.kext"_XS8, pos); pos = setKextAtPos(&kextArray, "USBPorts.kext"_XS8, pos); pos = setKextAtPos(&kextArray, "VoodooGPIO.kext"_XS8, pos); pos = setKextAtPos(&kextArray, "VoodooI2CServices.kext"_XS8, pos); pos = setKextAtPos(&kextArray, "VoodooI2C.kext"_XS8, pos); pos = setKextAtPos(&kextArray, "VoodooI2CHID.kext"_XS8, pos); pos = setKextAtPos(&kextArray, "VoodooSMBus.kext"_XS8, pos); pos = setKextAtPos(&kextArray, "VoodooRMI.kext"_XS8, pos); pos = setKextAtPos(&kextArray, "BrcmFirmwareData.kext"_XS8, pos); pos = setKextAtPos(&kextArray, "BrcmPatchRAM2.kext"_XS8, pos); pos = setKextAtPos(&kextArray, "BrcmPatchRAM3.kext"_XS8, pos); pos = setKextAtPos(&kextArray, "IO80211FamilyLegacy.kext"_XS8, pos); pos = setKextAtPos(&kextArray, "HS80211Family.kext"_XS8, pos); pos = setKextAtPos(&kextArray, "AirPortAtheros40.kext"_XS8, pos); for (size_t kextIdx = 0 ; kextIdx < kextArray.size() ; kextIdx++ ) { const SIDELOAD_KEXT& KextEntry = kextArray[kextIdx]; DBG("Bridge kext to OC : Path=%ls\n", KextEntry.FileName.wc_str()); mOpenCoreConfiguration.Kernel.Add.Values[kextIdx] = (__typeof_am__(*mOpenCoreConfiguration.Kernel.Add.Values))malloc(mOpenCoreConfiguration.Kernel.Add.ValueSize); memset(mOpenCoreConfiguration.Kernel.Add.Values[kextIdx], 0, mOpenCoreConfiguration.Kernel.Add.ValueSize); mOpenCoreConfiguration.Kernel.Add.Values[kextIdx]->Enabled = 1; OC_STRING_ASSIGN(mOpenCoreConfiguration.Kernel.Add.Values[kextIdx]->Arch, OC_BLOB_GET(&mOpenCoreConfiguration.Kernel.Scheme.KernelArch)); OC_STRING_ASSIGN(mOpenCoreConfiguration.Kernel.Add.Values[kextIdx]->Comment, ""); OC_STRING_ASSIGN(mOpenCoreConfiguration.Kernel.Add.Values[kextIdx]->MaxKernel, ""); OC_STRING_ASSIGN(mOpenCoreConfiguration.Kernel.Add.Values[kextIdx]->MinKernel, ""); OC_STRING_ASSIGN(mOpenCoreConfiguration.Kernel.Add.Values[kextIdx]->Identifier, ""); assert( selfOem.isKextsDirFound() ); // be sure before calling getKextsPathRelToSelfDir() XStringW dirPath = SWPrintf("%ls\\%ls", selfOem.getKextsDirPathRelToSelfDir().wc_str(), KextEntry.KextDirNameUnderOEMPath.wc_str()); XString8 bundlePath = S8Printf("%ls\\%ls", dirPath.wc_str(), KextEntry.FileName.wc_str()); if ( FileExists(&self.getCloverDir(), bundlePath) ) { OC_STRING_ASSIGN(mOpenCoreConfiguration.Kernel.Add.Values[kextIdx]->BundlePath, bundlePath.c_str()); } else { DBG("Cannot find kext bundlePath at '%s'\n", bundlePath.c_str()); } #if 1 //CFBundleExecutable XBool NoContents = false; XStringW infoPlistPath = getKextPlist(&self.getCloverDir(), dirPath, KextEntry.FileName, &NoContents); //it will be fullPath, including dir DBG("InfoPlistPath=%ls\n", infoPlistPath.wc_str()); TagDict* dict = getInfoPlist(&self.getCloverDir(), infoPlistPath); // XBool inject = checkOSBundleRequired(dict); XBool inject = true; if (inject) { if ( infoPlistPath.notEmpty()) { if (NoContents) { OC_STRING_ASSIGN(mOpenCoreConfiguration.Kernel.Add.Values[kextIdx]->PlistPath, "Info.plist"); } else { OC_STRING_ASSIGN(mOpenCoreConfiguration.Kernel.Add.Values[kextIdx]->PlistPath, "Contents/Info.plist"); } } else { DBG("Cannot find kext info.plist at '%ls'\n", KextEntry.FileName.wc_str()); } XString8 execpath = getKextExecPath(&self.getCloverDir(), dirPath, KextEntry.FileName, dict, NoContents); if (execpath.notEmpty()) { OC_STRING_ASSIGN(mOpenCoreConfiguration.Kernel.Add.Values[kextIdx]->ExecutablePath, execpath.c_str()); DBG("assign executable as '%s'\n", execpath.c_str()); } } #else XStringW execpath = S8Printf("Contents\\MacOS\\%ls", KextEntry.FileName.subString(0, KextEntry.FileName.rindexOf(".")).wc_str()); XStringW fullPath = SWPrintf("%s\\%ls", OC_BLOB_GET(&mOpenCoreConfiguration.Kernel.Add.Values[kextIdx]->BundlePath), execpath.wc_str()); if ( FileExists(&self.getCloverDir(), fullPath) ) { OC_STRING_ASSIGN(mOpenCoreConfiguration.Kernel.Add.Values[kextIdx]->ExecutablePath, S8Printf("Contents\\MacOS\\%ls", KextEntry.FileName.subString(0, KextEntry.FileName.rindexOf(".")).wc_str()).c_str()); } XStringW infoPlistPath = SWPrintf("%s\\Contents\\Info.plist", OC_BLOB_GET(&mOpenCoreConfiguration.Kernel.Add.Values[kextIdx]->BundlePath)); if (FileExists(&self.getCloverDir(), infoPlistPath)) { OC_STRING_ASSIGN(mOpenCoreConfiguration.Kernel.Add.Values[kextIdx]->PlistPath, "Contents/Info.plist"); // TODO : is always Contents/Info.plist ? } else { DBG("Cannot find kext info.plist at '%ls'\n", infoPlistPath.wc_str()); } #endif mOpenCoreConfiguration.Kernel.Add.Values[kextIdx]->ImageData = NULL; mOpenCoreConfiguration.Kernel.Add.Values[kextIdx]->ImageDataSize = 0; mOpenCoreConfiguration.Kernel.Add.Values[kextIdx]->PlistData = NULL; mOpenCoreConfiguration.Kernel.Add.Values[kextIdx]->PlistDataSize = 0; } // for (size_t kextIdx mOpenCoreConfiguration.Kernel.Force.Count = (UINT32)KernelAndKextPatches.ForceKextsToLoad.size(); mOpenCoreConfiguration.Kernel.Force.AllocCount = mOpenCoreConfiguration.Kernel.Force.Count; mOpenCoreConfiguration.Kernel.Force.ValueSize = sizeof(__typeof_am__(**mOpenCoreConfiguration.Kernel.Force.Values)); // sizeof(OC_KERNEL_FORCE_ENTRY) int valuesSize = mOpenCoreConfiguration.Kernel.Force.AllocCount*sizeof(*mOpenCoreConfiguration.Kernel.Force.Values); mOpenCoreConfiguration.Kernel.Force.Values = (OC_KERNEL_ADD_ENTRY**)malloc(valuesSize); // sizeof(OC_KERNEL_FORCE_ENTRY*) == sizeof(ptr) memset(mOpenCoreConfiguration.Kernel.Force.Values, 0, valuesSize); for (size_t kextIdx = 0; kextIdx < KernelAndKextPatches.ForceKextsToLoad.size(); kextIdx++) { const XStringW& forceKext = KernelAndKextPatches.ForceKextsToLoad[kextIdx]; DBG("Force kext to OC : Path=%ls\n", forceKext.wc_str()); mOpenCoreConfiguration.Kernel.Force.Values[kextIdx] = (__typeof_am__(*mOpenCoreConfiguration.Kernel.Force.Values))malloc(mOpenCoreConfiguration.Kernel.Force.ValueSize); memset(mOpenCoreConfiguration.Kernel.Force.Values[kextIdx], 0, mOpenCoreConfiguration.Kernel.Force.ValueSize); mOpenCoreConfiguration.Kernel.Force.Values[kextIdx]->Enabled = 1; OC_STRING_ASSIGN(mOpenCoreConfiguration.Kernel.Force.Values[kextIdx]->Arch, OC_BLOB_GET(&mOpenCoreConfiguration.Kernel.Scheme.KernelArch)); OC_STRING_ASSIGN(mOpenCoreConfiguration.Kernel.Force.Values[kextIdx]->Comment, ""); OC_STRING_ASSIGN(mOpenCoreConfiguration.Kernel.Force.Values[kextIdx]->MaxKernel, ""); OC_STRING_ASSIGN(mOpenCoreConfiguration.Kernel.Force.Values[kextIdx]->MinKernel, ""); // OC_STRING_ASSIGN(mOpenCoreConfiguration.Kernel.Force.Values[kextIdx]->Identifier, ""); mOpenCoreConfiguration.Kernel.Force.Values[kextIdx]->ImageData = NULL; mOpenCoreConfiguration.Kernel.Force.Values[kextIdx]->ImageDataSize = 0; mOpenCoreConfiguration.Kernel.Force.Values[kextIdx]->PlistData = NULL; mOpenCoreConfiguration.Kernel.Force.Values[kextIdx]->PlistDataSize = 0; REFIT_VOLUME * SystemVolume = Volume; EFI_FILE* SysRoot = Volume->RootDir; if (Volume->ApfsRole == APPLE_APFS_VOLUME_ROLE_PREBOOT) { //search for other partition DBG("boot from Preboot, index=%llu\n", Volume->Index); size_t numbers = Volumes.size(); size_t sysIndex = 0; for (sysIndex=Volume->Index+1; sysIndex < numbers; sysIndex++) { SystemVolume = &Volumes[sysIndex]; SysRoot = SystemVolume->RootDir; DBG("test volume %zd, name %ls:\n", sysIndex, SystemVolume->VolName.wc_str()); if (FileExists(SysRoot, L"\\System\\Library\\CoreServices\\boot.efi")) { DBG("boot.efi found on %zd\n", sysIndex); } REFIT_DIR_ITER DirIter; EFI_FILE_INFO *DirEntry = NULL; DirIterOpen(SysRoot, L"\\System\\Library\\Extensions\\AMDSupport.kext\\Contents\\MacOS\\", &DirIter); while (DirIterNext(&DirIter, 1, L"*", &DirEntry)) { if (DirEntry->FileName[0] == '.') { DBG("Skip dot entries: %ls\n", DirEntry->FileName); continue; } DBG("%ls attr=%llu\n", DirEntry->FileName, DirEntry->Attribute); } DirIterClose(&DirIter); if (FileExists(SysRoot, L"\\System\\Library\\Extensions\\AMDSupport.kext\\Contents\\MacOS\\AMDSupport")) { DBG("AMDSupport found on %zd\n", sysIndex); //never found break; } } } mOpenCoreConfiguration.Kernel.Force.Values[kextIdx]->ImageData = (UINT8*)SysRoot; size_t i1 = forceKext.rindexOf("\\") + 1; size_t i2 = forceKext.rindexOf("."); XStringW identifier = forceKext.subString(i1, i2 - i1); OC_STRING_ASSIGN(mOpenCoreConfiguration.Kernel.Force.Values[kextIdx]->Identifier, S8Printf("%ls", identifier.wc_str()).c_str()); XString8 execpath = S8Printf("Contents\\MacOS\\%ls", identifier.wc_str()); DBG("calculated execpath=%s\n", execpath.c_str()); OC_STRING_ASSIGN(mOpenCoreConfiguration.Kernel.Force.Values[kextIdx]->BundlePath, S8Printf("%ls",forceKext.wc_str()).c_str()); OC_STRING_ASSIGN(mOpenCoreConfiguration.Kernel.Force.Values[kextIdx]->PlistPath, "Contents\\Info.plist"); //then we have to find executablePath and plistPath DBG("bundle path=%s\n", mOpenCoreConfiguration.Kernel.Force.Values[kextIdx]->BundlePath.Value); OC_STRING_ASSIGN(mOpenCoreConfiguration.Kernel.Force.Values[kextIdx]->ExecutablePath, execpath.c_str()); DBG("assign executable as '%s'\n", mOpenCoreConfiguration.Kernel.Force.Values[kextIdx]->ExecutablePath.Value); } if (gSettings.KernelAndKextPatches.BlockSkywalk) { mOpenCoreConfiguration.Kernel.Block.Count = 1; mOpenCoreConfiguration.Kernel.Block.AllocCount = 1; mOpenCoreConfiguration.Kernel.Block.ValueSize = sizeof(__typeof_am__(**mOpenCoreConfiguration.Kernel.Block.Values)); valuesSize = mOpenCoreConfiguration.Kernel.Block.AllocCount*sizeof(*mOpenCoreConfiguration.Kernel.Block.Values); mOpenCoreConfiguration.Kernel.Block.Values = (OC_KERNEL_BLOCK_ENTRY**)malloc(valuesSize); memset(mOpenCoreConfiguration.Kernel.Block.Values, 0, valuesSize); mOpenCoreConfiguration.Kernel.Block.Values[0] = (__typeof_am__(*mOpenCoreConfiguration.Kernel.Block.Values))malloc(mOpenCoreConfiguration.Kernel.Block.ValueSize); memset(mOpenCoreConfiguration.Kernel.Block.Values[0], 0, mOpenCoreConfiguration.Kernel.Block.ValueSize); mOpenCoreConfiguration.Kernel.Block.Values[0]->Enabled = 1; OC_STRING_ASSIGN(mOpenCoreConfiguration.Kernel.Block.Values[0]->Arch, OC_BLOB_GET(&mOpenCoreConfiguration.Kernel.Scheme.KernelArch)); OC_STRING_ASSIGN(mOpenCoreConfiguration.Kernel.Block.Values[0]->Comment, ""); OC_STRING_ASSIGN(mOpenCoreConfiguration.Kernel.Block.Values[0]->MaxKernel, ""); OC_STRING_ASSIGN(mOpenCoreConfiguration.Kernel.Block.Values[0]->MinKernel, "23"); OC_STRING_ASSIGN(mOpenCoreConfiguration.Kernel.Block.Values[0]->Identifier, "com.apple.iokit.IOSkywalkFamily"); OC_STRING_ASSIGN(mOpenCoreConfiguration.Kernel.Block.Values[0]->Strategy, "Exclude"); } #endif mOpenCoreConfiguration.Uefi.Output.ProvideConsoleGop = gSettings.GUI.ProvideConsoleGop; OC_STRING_ASSIGN(mOpenCoreConfiguration.Uefi.Output.Resolution, XString8(gSettings.GUI.ScreenResolution).c_str()); if ( OpenRuntimeEfiName.notEmpty() ) { XStringW FileName = SWPrintf("%ls\\%ls\\%ls", self.getCloverDirFullPath().wc_str(), getDriversPath().wc_str(), OpenRuntimeEfiName.wc_str()); EFI_HANDLE DriverHandle; Status = gBS->LoadImage(false, gImageHandle, FileDevicePath(self.getSelfLoadedImage().DeviceHandle, FileName), NULL, 0, &DriverHandle); if ( !EFI_ERROR(Status) ) { Status = gBS->StartImage(DriverHandle, 0, 0); DBG("Start '%ls' : Status %s\n", OpenRuntimeEfiName.wc_str(), efiStrError(Status)); if ( !EFI_ERROR(Status) ) { OC_FIRMWARE_RUNTIME_PROTOCOL *FwRuntime; Status = gBS->LocateProtocol ( gOcFirmwareRuntimeProtocolGuid, NULL, (VOID **) &FwRuntime ); if (!EFI_ERROR (Status)) { if (FwRuntime->Revision == OC_FIRMWARE_RUNTIME_REVISION) { } else { DEBUG (( DEBUG_ERROR, "OCABC: Incompatible OpenRuntime r%u, require r%u\n", (UINT32) FwRuntime->Revision, (UINT32) OC_FIRMWARE_RUNTIME_REVISION )); DBG("Incompatible OpenRuntime r%llu, require r%u\n", FwRuntime->Revision, OC_FIRMWARE_RUNTIME_REVISION); } } } }else{ DBG("Error when loading '%ls' : Status %s.\n", OpenRuntimeEfiName.wc_str(), efiStrError(Status)); } }else{ DBG("No OpenRuntime driver. This is ok, OpenRuntime is not mandatory.\n"); } OcMain(&mOpenCoreStorage, NULL); XStringW DevicePathAsString = DevicePathToXStringW(DevicePath); if ( DevicePathAsString.rindexOf(".dmg") == MAX_XSIZE ) { // point to InternalEfiLoadImage from OC Status = gBS->LoadImage ( false, gImageHandle, DevicePath, NULL, 0, &ImageHandle ); if ( EFI_ERROR(Status) ) { DBG("LoadImage at '%ls' failed. Status = %s\n", DevicePathAsString.wc_str(), efiStrError(Status)); return; } DBG("ImageHandle = %llx\n", uintptr_t(ImageHandle)); } else { // NOTE : OpenCore ignore the name of the dmg. // InternalLoadDmg calls InternalFindFirstDmgFileName to find the dmg file name. // So be careful that, if an other dmg exists in the dir, that might boot on the wrong one. EFI_DEVICE_PATH_PROTOCOL* DevicePathCopy = DuplicateDevicePath(DevicePath); EFI_DEVICE_PATH_PROTOCOL* PreviousNode = NULL; EFI_DEVICE_PATH_PROTOCOL* Node = DevicePathCopy; while (!IsDevicePathEnd(Node)) { if ( Node->Type == MEDIA_DEVICE_PATH && Node->SubType == MEDIA_FILEPATH_DP ) { PreviousNode = Node; break; } PreviousNode = Node; Node = NextDevicePathNode(Node); } SetDevicePathEndNode(PreviousNode); EFI_DEVICE_PATH_PROTOCOL* LoaderPathBasenameNode = ConvertTextToDeviceNode(LoaderPath.dirname().wc_str()); EFI_DEVICE_PATH_PROTOCOL* DevicePathToDmgDir = AppendDevicePathNode(DevicePathCopy, LoaderPathBasenameNode); DBG("DevicePathToDmgDir = %ls\n", DevicePathToXStringW(DevicePathToDmgDir).wc_str()); INTERNAL_DMG_LOAD_CONTEXT DmgLoadContext = {0,0,0}; DmgLoadContext.DevicePath = DevicePathToDmgDir; EFI_DEVICE_PATH_PROTOCOL* BootEfiFromDmgDevicePath = InternalLoadDmg(&DmgLoadContext, OcDmgLoadingAnyImage); DBG("DevicePath of dmg = %ls\n", DevicePathToXStringW(BootEfiFromDmgDevicePath).wc_str()); // point to InternalEfiLoadImage from OC Status = gBS->LoadImage ( false, gImageHandle, BootEfiFromDmgDevicePath, NULL, 0, &ImageHandle ); if ( EFI_ERROR(Status) ) { DBG("LoadImage at '%ls' failed. Status = %s\n", DevicePathToXStringW(BootEfiFromDmgDevicePath).wc_str(), efiStrError(Status)); return; } } EFI_STATUS OptionalStatus = gBS->HandleProtocol ( ImageHandle, &gEfiLoadedImageProtocolGuid, (void **) &LoadedImage ); if ( EFI_ERROR(OptionalStatus) ) return; // TODO message ? } else { // Load image into memory (will be started later) Status = LoadEFIImage(DevicePath, LoaderPath.basename(), NULL, &ImageHandle); if (EFI_ERROR(Status)) { DBG("Image is not loaded, status=%s\n", efiStrError(Status)); return; // no reason to continue if loading image failed } } egClearScreen(&BootBgColor); //if not set then it is already MenuBackgroundPixel // KillMouse(); // if (LoaderType == OSTYPE_OSX) { if (OSTYPE_IS_OSX(LoaderType) || OSTYPE_IS_OSX_RECOVERY(LoaderType) || OSTYPE_IS_OSX_INSTALLER(LoaderType)) { // To display progress bar properly (especially in FV2 mode) boot.efi needs to be in graphics mode. // Unfortunately many UEFI implementations change the resolution when SetMode happens. // This is not what boot.efi expects, and it freely calls SetMode at its will. // As a result we see progress bar at improper resolution and the background is also missing (10.12.x+). // // libeg already has a workaround for SetMode behaviour, so we extend it for boot.efi support. // The approach tries to be follows: // 1. Ensure we have graphics mode set (since it is a must in the future). // 2. Request text mode for boot.efi, which it expects by default (here a SetMode libeg hack will trigger // on problematic UEFI implementations like AMI). egSetGraphicsModeEnabled(true); egSetGraphicsModeEnabled(false); DBG("GetOSVersion:"); //needed for boot.efi patcher Status = gBS->HandleProtocol(ImageHandle, &gEfiLoadedImageProtocolGuid, (void **) &LoadedImage); // Correct OSVersion if it was not found // This should happen only for 10.7-10.9 OSTYPE_OSX_INSTALLER // For these cases, take OSVersion from loaded boot.efi image in memory if ( macOSVersion.isEmpty()) { if (!EFI_ERROR(Status)) { // version in boot.efi appears as "Mac OS X 10.?" /* Start OSName Mac OS X 10.12 End OSName Start OSVendor Apple Inc. End */ InstallerVersion = AsciiStrStr((CHAR8*)LoadedImage->ImageBase, "Mac OS X "); int location = 9; if (InstallerVersion == NULL) { InstallerVersion = AsciiStrStr((CHAR8*)LoadedImage->ImageBase, "macOS "); location = 7; } if (InstallerVersion != NULL) { // string was found InstallerVersion += location; // advance to version location if (strncmp(InstallerVersion, "10.7", 4) && strncmp(InstallerVersion, "10.8", 4) && strncmp(InstallerVersion, "10.9", 4) && strncmp(InstallerVersion, "10.10", 5) && strncmp(InstallerVersion, "10.11", 5) && strncmp(InstallerVersion, "10.12", 5) && strncmp(InstallerVersion, "10.13", 5) && strncmp(InstallerVersion, "10.14", 5) && strncmp(InstallerVersion, "10.15", 5) && strncmp(InstallerVersion, "10.16", 5) && strncmp(InstallerVersion, "11.", 3) && strncmp(InstallerVersion, "12.", 3) && strncmp(InstallerVersion, "13.", 3) && strncmp(InstallerVersion, "14.", 3) ) { InstallerVersion = NULL; // flag known version was not found } if (InstallerVersion != NULL) { // known version was found in image macOSVersion = InstallerVersion; DBG("Corrected OSVersion: %s\n", macOSVersion.asString().c_str()); } } } BuildVersion.setEmpty(); } if (BuildVersion.notEmpty()) { DBG(" %s (%s)\n", macOSVersion.asString().c_str(), BuildVersion.c_str()); } else { DBG(" %s\n", macOSVersion.asString().c_str()); } if ( macOSVersion >= MacOsVersion("10.11"_XS8) ) { if (OSFLAG_ISSET(Flags, OSFLAG_NOSIP)) { gSettings.RtVariables.CsrActiveConfig = (UINT32)0xBEF; gSettings.RtVariables.BooterConfig = 0x28; } } FilterKextPatches(); FilterKernelPatches(); FilterBootPatches(); if (LoadedImage && !BooterPatch((UINT8*)LoadedImage->ImageBase, LoadedImage->ImageSize)) { DBG("Will not patch boot.efi\n"); } gConf.ReloadSmbios(OSName); DelegateKernelPatches(); // Set boot argument for kernel if no caches, this should force kernel loading if ( OSFLAG_ISSET(Flags, OSFLAG_NOCACHES) && !LoadOptions.containsStartWithIC("Kernel=") ) { XString8 KernelLocation; if ( macOSVersion.notEmpty() && macOSVersion <= MacOsVersion("10.9"_XS8) ) { KernelLocation.S8Printf("\"Kernel=/mach_kernel\""); } else { // used for 10.10, 10.11, and new version. Jief : also for unknown version. KernelLocation.S8Printf("\"Kernel=/System/Library/Kernels/kernel\""); } LoadOptions.AddID(KernelLocation); } // first patchACPI and find PCIROOT and RTC // but before ACPI patch we need smbios patch CheckEmptyFB(); SmbiosFillPatchingValues(GlobalConfig.SetTable132, GlobalConfig.EnabledCores, g_SmbiosDiscoveredSettings.RamSlotCount, gConf.SlotDeviceArray, gSettings, gCPUStructure, &g_SmbiosInjectedSettings); PatchSmbios(g_SmbiosInjectedSettings); #ifdef USE_OC_SECTION_Acpi // If we use the ACPI section form config-oc.plist, let's also delegate the acpi patching to OC #else PatchACPI(Volume, macOSVersion); #endif #ifdef JIEF_DEBUG //SaveOemTables(); #endif // DbgHeader("RestSetup macOS"); SetDevices(this); SetVariablesForOSX(this); // Jief : if we want to use our FixUSBOwnership, we need our OnExitBootServices EventsInitialize(this); FinalizeSmbios(g_SmbiosInjectedSettings); SetCPUProperties(); //very special procedure if (OSFLAG_ISSET(Flags, OSFLAG_HIBERNATED)) { DoHibernateWake = PrepareHibernation(Volume); } SetupDataForOSX(DoHibernateWake); if ( gDriversFlags.AptioFixLoaded && !DoHibernateWake && !LoadOptions.containsStartWithIC("slide=") ) { // Add slide=0 argument for ML+ if not present LoadOptions.AddID("slide=0"_XS8); } /** * syscl - append "-xcpm" argument conditionally if set KernelXCPM on Intel Haswell+ low-end CPUs */ if (KernelAndKextPatches.KPKernelXCPM && gCPUStructure.Vendor == CPU_VENDOR_INTEL && gCPUStructure.Model >= CPU_MODEL_HASWELL && (gCPUStructure.BrandString.contains("Celeron") || gCPUStructure.BrandString.contains("Pentium")) && macOSVersion >= MacOsVersion("10.8.5"_XS8) && macOSVersion < MacOsVersion("10.12"_XS8) && (!LoadOptions.containsIC("-xcpm"))) { // add "-xcpm" argv if not present on Haswell+ Celeron/Pentium LoadOptions.AddID("-xcpm"_XS8); } // add -xcpm on Ivy Bridge if set KernelXCPM and system version is 10.8.5 - 10.11.x if (KernelAndKextPatches.KPKernelXCPM && gCPUStructure.Model == CPU_MODEL_IVY_BRIDGE && macOSVersion >= MacOsVersion("10.8.5"_XS8) && macOSVersion < MacOsVersion("10.12"_XS8) && (!LoadOptions.containsIC("-xcpm"))) { // add "-xcpm" argv if not present on Ivy Bridge LoadOptions.AddID("-xcpm"_XS8); } if (AudioIo) { AudioIo->StopPlayback(AudioIo); // CheckSyncSound(true); EFI_DRIVER_BINDING_PROTOCOL *DriverBinding = NULL; Status = gBS->HandleProtocol(AudioDriverHandle, &gEfiDriverBindingProtocolGuid, (void **)&DriverBinding); if (DriverBinding) { DriverBinding->Stop(DriverBinding, AudioDriverHandle, 0, NULL); } } // blocking boot.efi output if -v is not specified // note: this blocks output even if -v is specified in // /Library/Preferences/SystemConfiguration/com.apple.Boot.plist // which is wrong // apianti - only block console output if using graphics // but don't block custom boot logo if (LoadOptions.containsIC("-v")) { Flags = OSFLAG_UNSET(Flags, OSFLAG_USEGRAPHICS); } } else if (OSTYPE_IS_WINDOWS(LoaderType)) { if (AudioIo) { AudioIo->StopPlayback(AudioIo); } DBG("Closing events for Windows\n"); gBS->CloseEvent (OnReadyToBootEvent); gBS->CloseEvent (ExitBootServiceEvent); gBS->CloseEvent (mSimpleFileSystemChangeEvent); if (gEmuVariableControl != NULL) { gEmuVariableControl->UninstallEmulation(gEmuVariableControl); } PatchACPI_OtherOS(L"Windows", false); } else if (OSTYPE_IS_LINUX(LoaderType) || (LoaderType == OSTYPE_LINEFI)) { DBG("Closing events for Linux\n"); gBS->CloseEvent (OnReadyToBootEvent); gBS->CloseEvent (ExitBootServiceEvent); gBS->CloseEvent (mSimpleFileSystemChangeEvent); if (gEmuVariableControl != NULL) { gEmuVariableControl->UninstallEmulation(gEmuVariableControl); } PatchACPI_OtherOS(L"Linux", false); } if (gSettings.Boot.LastBootedVolume) { if ( APFSTargetUUID.notNull() ) { // 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.Boot.DefaultVolume.notEmpty()) { // DefaultVolume specified in Config.plist or in Boot Option // we'll remove macOS Startup Disk vars which may be present if it is used // to reboot into another volume RemoveStartupDiskVolume(); } /* { // UINT32 machineSignature = 0; EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *FadtPointer = NULL; EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs = NULL; // DBG("---dump hibernations data---\n"); FadtPointer = GetFadt(); if (FadtPointer != NULL) { Facs = (EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE*)(UINTN)(FadtPointer->FirmwareCtrl); DBG(" Firmware wake address=%08lx\n", Facs->FirmwareWakingVector); DBG(" Firmware wake 64 addr=%16llx\n", Facs->XFirmwareWakingVector); DBG(" Hardware signature =%08lx\n", Facs->HardwareSignature); DBG(" GlobalLock =%08lx\n", Facs->GlobalLock); DBG(" Flags =%08lx\n", Facs->Flags); DBG(" HS at offset 0x%08X\n", OFFSET_OF(EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE, HardwareSignature)); // machineSignature = Facs->HardwareSignature; } } */ BeginExternalScreen(OSFLAG_ISSET(Flags, OSFLAG_USEGRAPHICS)/*, L"Booting OS"*/); if (!OSTYPE_IS_WINDOWS(LoaderType) && !OSTYPE_IS_LINUX(LoaderType)) { if (OSFLAG_ISSET(Flags, OSFLAG_USEGRAPHICS)) { // save orig OutputString and replace it with // null implementation ConOutOutputString = gST->ConOut->OutputString; gST->ConOut->OutputString = NullConOutOutputString; } // Initialize the boot screen if (EFI_ERROR(Status = InitBootScreen(this))) { if (Status != EFI_ABORTED) DBG("Failed to initialize custom boot screen: %s!\n", efiStrError(Status)); } else if (EFI_ERROR(Status = LockBootScreen())) { DBG("Failed to lock custom boot screen: %s!\n", efiStrError(Status)); } } // !OSTYPE_IS_WINDOWS if (OSTYPE_IS_OSX(LoaderType) || OSTYPE_IS_OSX_RECOVERY(LoaderType) || OSTYPE_IS_OSX_INSTALLER(LoaderType)) { if (DoHibernateWake) { DBG("Closing events for wake\n"); gBS->CloseEvent (OnReadyToBootEvent); // gBS->CloseEvent (ExitBootServiceEvent); // Jief : we don't need that anymore, if we continue to use OC onExtBootService event gBS->CloseEvent (mSimpleFileSystemChangeEvent); // When doing hibernate wake, save to DataHub only up to initial size of log SavePreBootLog = false; } else { // delete boot-switch-vars if exists Status = gRT->SetVariable(L"boot-switch-vars", gEfiAppleBootGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, 0, NULL); DeleteNvramVariable(L"IOHibernateRTCVariables", gEfiAppleBootGuid); DeleteNvramVariable(L"boot-image", gEfiAppleBootGuid); } SetupBooterLog(!DoHibernateWake); XStringW LoadOptionsAsXStringW = SWPrintf("%ls %s ", Basename(LoaderPath.wc_str()), LoadOptions.ConcatAll(" "_XS8).c_str()); LoadedImage->LoadOptions = (void*)LoadOptionsAsXStringW.wc_str(); LoadedImage->LoadOptionsSize = (UINT32)LoadOptionsAsXStringW.sizeInBytesIncludingTerminator(); DBG("Kernel quirks\n"); DBG("ACPCL %d AXCL %d AXEM %d AXFB %d CSG %d DIM %d DLJ %d DRC %d DPM %d EBTFF %d EDI %d IPBS %d LKP %d PNKD %d PTKP %d TPD %d XPL %d PCC %d\n", mOpenCoreConfiguration.Kernel.Quirks.AppleCpuPmCfgLock, mOpenCoreConfiguration.Kernel.Quirks.AppleXcpmCfgLock, mOpenCoreConfiguration.Kernel.Quirks.AppleXcpmExtraMsrs, mOpenCoreConfiguration.Kernel.Quirks.AppleXcpmForceBoost, mOpenCoreConfiguration.Kernel.Quirks.CustomSmbiosGuid, mOpenCoreConfiguration.Kernel.Quirks.DisableIoMapper, mOpenCoreConfiguration.Kernel.Quirks.DisableLinkeditJettison, mOpenCoreConfiguration.Kernel.Quirks.DisableRtcChecksum, mOpenCoreConfiguration.Kernel.Emulate.DummyPowerManagement, mOpenCoreConfiguration.Kernel.Quirks.ExtendBTFeatureFlags, mOpenCoreConfiguration.Kernel.Quirks.ExternalDiskIcons, mOpenCoreConfiguration.Kernel.Quirks.IncreasePciBarSize, mOpenCoreConfiguration.Kernel.Quirks.LapicKernelPanic, mOpenCoreConfiguration.Kernel.Quirks.PanicNoKextDump, mOpenCoreConfiguration.Kernel.Quirks.PowerTimeoutKernelPanic, mOpenCoreConfiguration.Kernel.Quirks.ThirdPartyDrives, mOpenCoreConfiguration.Kernel.Quirks.XhciPortLimit, mOpenCoreConfiguration.Kernel.Quirks.ProvideCurrentCpuInfo); DBG("Closing log\n"); if (SavePreBootLog) { Status = SaveBooterLog(&self.getCloverDir(), PREBOOT_LOG); } displayFreeMemory("Just before lauching image"_XS8); Status = gBS->StartImage (ImageHandle, 0, NULL); // point to OcStartImage from OC if ( EFI_ERROR(Status) ) { // Ideally, we would return to the menu, displaying an error message // Truth is that we get a black screen before seeing the menu again. // If I remember well, we get a freeze in BdsLibConnectAllEfi() // I'm guessing there is a lot of patching done for booting. // To be able to go back to the menu and boot another thing, // we must undo all the patching... // Here is a quick, not as bad as a black screen solution : a text message and a reboot ! DBG("StartImage failed : %s\n", efiStrError(Status)); SaveBooterLog(&self.getCloverDir(), PREBOOT_LOG); egSetGraphicsModeEnabled(false); printf("StartImage failed : %s\n", efiStrError(Status)); PauseForKey("Reboot needed."_XS8); // Attempt warm reboot gRT->ResetSystem(EfiResetWarm, EFI_SUCCESS, 0, NULL); // Warm reboot may not be supported attempt cold reboot gRT->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL); // Terminate the screen and just exit return; } }else{ StartEFILoadedImage(ImageHandle, LoadOptions, NullXStringW, LoaderPath.basename(), NULL); } // Unlock boot screen if (EFI_ERROR(Status = UnlockBootScreen())) { DBG("Failed to unlock custom boot screen: %s!\n", efiStrError(Status)); } if (OSFLAG_ISSET(Flags, OSFLAG_USEGRAPHICS)) { // return back orig OutputString gST->ConOut->OutputString = ConOutOutputString; } FinishExternalScreen(); } void LEGACY_ENTRY::StartLegacy() { EFI_STATUS Status = EFI_UNSUPPORTED; // Unload EmuVariable before booting legacy. // This is not needed in most cases, but it seems to interfere with legacy OS // booted on some UEFI bioses, such as Phoenix UEFI 2.0 if (gEmuVariableControl != NULL) { gEmuVariableControl->UninstallEmulation(gEmuVariableControl); } if (gSettings.Boot.LastBootedVolume) { SetStartupDiskVolume(Volume, NullXStringW); } else if (gSettings.Boot.DefaultVolume.notEmpty()) { // DefaultVolume specified in Config.plist: // we'll remove macOS Startup Disk vars which may be present if it is used // to reboot into another volume RemoveStartupDiskVolume(); } egClearScreen(&MenuBackgroundPixel); BeginExternalScreen(true/*, L"Booting Legacy OS"*/); XImage BootLogoX; BootLogoX.LoadXImage(&ThemeX->getThemeDir(), Volume->LegacyOS->IconName); BootLogoX.Draw((UGAWidth - BootLogoX.GetWidth()) >> 1, (UGAHeight - BootLogoX.GetHeight()) >> 1); //try my LegacyBoot switch (Volume->BootType) { case BOOTING_BY_CD: Status = bootElTorito(Volume); break; case BOOTING_BY_MBR: Status = bootMBR(Volume); break; case BOOTING_BY_PBR: if (gSettings.Boot.LegacyBoot == "LegacyBiosDefault"_XS8) { Status = bootLegacyBiosDefault(gSettings.Boot.LegacyBiosDefaultEntry); } else if (gSettings.Boot.LegacyBoot == "PBRtest"_XS8) { Status = bootPBRtest(Volume); } else if (gSettings.Boot.LegacyBoot == "PBRsata"_XS8) { Status = bootPBR(Volume, true); } else { // default Status = bootPBR(Volume, false); } break; default: break; } CheckError(Status, L"while LegacyBoot"); FinishExternalScreen(); } // // pre-boot tool functions // void REFIT_MENU_ENTRY_LOADER_TOOL::StartTool() { DBG("Start Tool: %ls\n", LoaderPath.wc_str()); egClearScreen(&MenuBackgroundPixel); // assumes "Start " as assigned below BeginExternalScreen(OSFLAG_ISSET(Flags, OSFLAG_USEGRAPHICS)/*, &Entry->Title[6]*/); // Shouldn't we check that length of Title is at least 6 ? StartEFIImage(DevicePath, LoadOptions, NullXStringW, LoaderPath.basename(), NULL, NULL); FinishExternalScreen(); } // // pre-boot driver functions // static void ScanDriverDir(IN CONST CHAR16 *Path, OUT EFI_HANDLE **DriversToConnect, OUT UINTN *DriversToConnectNum) { EFI_STATUS Status; REFIT_DIR_ITER DirIter; EFI_FILE_INFO *DirEntry; EFI_HANDLE DriverHandle; EFI_DRIVER_BINDING_PROTOCOL *DriverBinding; UINTN DriversArrSize; UINTN DriversArrNum; EFI_HANDLE *DriversArr; XBool Skip; UINT8 AptioBlessed; STATIC CHAR16 CONST * CONST AptioNames[] = { L"AptioMemoryFix", L"AptioFix3Drv", L"AptioFix2Drv", L"AptioFixDrv", L"LowMemFix" }; STATIC UINT8 CONST AptioIndices[] = { OFFSET_OF(DRIVERS_FLAGS, AptioMemFixLoaded), OFFSET_OF(DRIVERS_FLAGS, AptioFix3Loaded), OFFSET_OF(DRIVERS_FLAGS, AptioFix2Loaded), OFFSET_OF(DRIVERS_FLAGS, AptioFixLoaded), OFFSET_OF(DRIVERS_FLAGS, MemFixLoaded) }; DriversArrSize = 0; DriversArrNum = 0; DriversArr = NULL; // OpenRuntimeEfiName.setEmpty(); //only one driver with highest priority will obtain status "Loaded" DirIterOpen(&self.getCloverDir(), Path, &DirIter); #define BOOLEAN_AT_INDEX(k) (*(XBool*)((UINTN)&gDriversFlags + AptioIndices[(k)])) for (size_t i = 0; i != ARRAY_SIZE(AptioIndices); ++i) BOOLEAN_AT_INDEX(i) = false; AptioBlessed = (UINT8) ARRAY_SIZE(AptioNames); while (DirIterNext(&DirIter, 2, L"*.efi", &DirEntry)) { size_t i; for (i = 0; i != ARRAY_SIZE(AptioNames); ++i) if (StrStr(DirEntry->FileName, AptioNames[i]) != NULL) break; if (((UINT8) i) >= AptioBlessed) continue; AptioBlessed = (UINT8) i; if (!i) break; } DirIterClose(&DirIter); // look through contents of the directory DirIterOpen(&self.getCloverDir(), Path, &DirIter); while (DirIterNext(&DirIter, 2, L"*.efi", &DirEntry)) { Skip = (DirEntry->FileName[0] == L'.'); for (size_t i=0; i<gSettings.DisabledDriverArray.size(); i++) { if (StrStr(DirEntry->FileName, gSettings.DisabledDriverArray[i].wc_str()) != NULL) { Skip = true; // skip this break; } } if (Skip) { continue; } if ( LStringW(DirEntry->FileName).startWith("._") ) { continue; } if ( LStringW(DirEntry->FileName).containsIC("OcQuirks") ) { continue; } if ( LStringW(DirEntry->FileName).containsIC("AptioMemoryFix") ) { continue; } if ( LStringW(DirEntry->FileName).containsIC("OpenRuntime") ) { if (!OpenRuntimeEfiName.isEmpty()) { DBG(" - OpenRuntime already detected\n"); continue; } if ( LStringW(DirEntry->FileName).isEqualIC("OpenRuntime-v12.efi") && LString8(OPEN_CORE_VERSION).isEqual("0.7.5") ) { OpenRuntimeEfiName.takeValueFrom(DirEntry->FileName); DBG(" - OpenRuntime-v12 for 075 taken from %ls\n", getDriversPath().wc_str()); }else if ( LStringW(DirEntry->FileName).isEqualIC("OpenRuntime-v12.efi") && LString8(OPEN_CORE_VERSION).isEqual("0.7.3") ) { OpenRuntimeEfiName.takeValueFrom(DirEntry->FileName); DBG(" - OpenRuntime-v12 for 073 taken from %ls\n", getDriversPath().wc_str()); }else if ( LStringW(DirEntry->FileName).isEqualIC("OpenRuntime-v11.efi") && LString8(OPEN_CORE_VERSION).isEqual("0.6.5") ) { OpenRuntimeEfiName.takeValueFrom(DirEntry->FileName); DBG(" - OpenRuntime-v11 for 065 taken from %ls\n", getDriversPath().wc_str()); }else if ( LStringW(DirEntry->FileName).isEqualIC("OpenRuntime-v11.efi") && LString8(OPEN_CORE_VERSION).isEqual("0.6.1") ) { OpenRuntimeEfiName.takeValueFrom(DirEntry->FileName); DBG(" - OpenRuntime-v11 for 061 taken from %ls\n", getDriversPath().wc_str()); }else if ( OpenRuntimeEfiName.isEmpty() ) { OpenRuntimeEfiName.takeValueFrom(DirEntry->FileName); } continue; } { size_t i; // either AptioMem, AptioFix* or LowMemFix exclusively for (i = 0; i != ARRAY_SIZE(AptioNames); ++i) if (StrStr(DirEntry->FileName, AptioNames[i]) != NULL) break; if (i != ARRAY_SIZE(AptioNames)) { if (((UINT8) i) != AptioBlessed) continue; if (AptioBlessed < (UINT8) ARRAY_SIZE(AptioIndices)) BOOLEAN_AT_INDEX(AptioBlessed) = true; AptioBlessed = (UINT8) ARRAY_SIZE(AptioNames); } } #undef BOOLEAN_AT_INDEX XStringW FileName = SWPrintf("%ls\\%ls\\%ls", self.getCloverDirFullPath().wc_str(), Path, DirEntry->FileName); Status = StartEFIImage(FileDevicePath(self.getSelfLoadedImage().DeviceHandle, FileName), NullXString8Array, LStringW(DirEntry->FileName), XStringW().takeValueFrom(DirEntry->FileName), NULL, &DriverHandle); if (EFI_ERROR(Status)) { continue; } if ( FileName.containsIC("AudioDxe") ) { AudioDriverHandle = DriverHandle; } if ( FileName.containsIC("EmuVariable") ) { gDriversFlags.EmuVariableLoaded = true; } else if ( FileName.containsIC("Video") ) { gDriversFlags.VideoLoaded = true; } else if ( FileName.containsIC("Partition") ) { gDriversFlags.PartitionLoaded = true; } else if ( FileName.containsIC("HFS") ) { gDriversFlags.HFSLoaded = true; } else if ( FileName.containsIC("apfs") ) { gDriversFlags.APFSLoaded = true; } if (DriverHandle != NULL && DriversToConnectNum != NULL && DriversToConnect != NULL) { // driver loaded - check for EFI_DRIVER_BINDING_PROTOCOL Status = gBS->HandleProtocol(DriverHandle, &gEfiDriverBindingProtocolGuid, (void **) &DriverBinding); if (!EFI_ERROR(Status) && DriverBinding != NULL) { DBG(" - driver needs connecting\n"); // standard UEFI driver - we would reconnect after loading - add to array if (DriversArrSize == 0) { // new array DriversArrSize = 16; DriversArr = (__typeof__(DriversArr))AllocateZeroPool(sizeof(EFI_HANDLE) * DriversArrSize); } else if (DriversArrNum + 1 == DriversArrSize) { // extend array DriversArr = (__typeof__(DriversArr))ReallocatePool(DriversArrSize, DriversArrSize + 16, DriversArr); DriversArrSize += 16; } DriversArr[DriversArrNum] = DriverHandle; // DBG(" driver %ls included with Binding=%X\n", FileName, DriverBinding); DriversArrNum++; // we'll make array terminated DriversArr[DriversArrNum] = NULL; } } } Status = DirIterClose(&DirIter); if (Status != EFI_NOT_FOUND) { CheckError(Status, SWPrintf( "while scanning the %ls directory", Path).wc_str()); } if (DriversToConnectNum != NULL && DriversToConnect != NULL) { *DriversToConnectNum = DriversArrNum; *DriversToConnect = DriversArr; } } /** * Some UEFI's (like HPQ EFI from HP notebooks) have DiskIo protocols * opened BY_DRIVER (by Partition driver in HP case) even when no file system * is produced from this DiskIo. This then blocks our FS drivers from connecting * and producing file systems. * To fix it: we will disconnect drivers that connected to DiskIo BY_DRIVER * if this is partition volume and if those drivers did not produce file system. */ void DisconnectInvalidDiskIoChildDrivers(void) { EFI_STATUS Status; UINTN HandleCount = 0; UINTN Index; UINTN OpenInfoIndex; EFI_HANDLE *Handles = NULL; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Fs; EFI_BLOCK_IO_PROTOCOL *BlockIo; EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo; UINTN OpenInfoCount; XBool Found; DBG("Searching for invalid DiskIo BY_DRIVER connects:"); // // Get all DiskIo handles // Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiDiskIoProtocolGuid, NULL, &HandleCount, &Handles); if (EFI_ERROR(Status) || HandleCount == 0) { DBG(" no DiskIo handles\n"); return; } // // Check every DiskIo handle // Found = false; for (Index = 0; Index < HandleCount; Index++) { //DBG("\n"); //DBG(" - Handle %p:", Handles[Index]); // // If this is not partition - skip it. // This is then whole disk and DiskIo // should be opened here BY_DRIVER by Partition driver // to produce partition volumes. // Status = gBS->HandleProtocol ( Handles[Index], &gEfiBlockIoProtocolGuid, (void **) &BlockIo ); if (EFI_ERROR(Status)) { //DBG(" BlockIo: %s - skipping\n", efiStrError(Status)); continue; } if (BlockIo->Media == NULL) { //DBG(" BlockIo: no media - skipping\n"); continue; } if (!BlockIo->Media->LogicalPartition) { //DBG(" BlockIo: whole disk - skipping\n"); continue; } //DBG(" BlockIo: partition"); // // If SimpleFileSystem is already produced - skip it, this is ok // Status = gBS->HandleProtocol ( Handles[Index], &gEfiSimpleFileSystemProtocolGuid, (void **) &Fs ); if (Status == EFI_SUCCESS) { //DBG(" FS: ok - skipping\n"); continue; } //DBG(" FS: no"); // // If no SimpleFileSystem on this handle but DiskIo is opened BY_DRIVER // then disconnect this connection // Status = gBS->OpenProtocolInformation ( Handles[Index], &gEfiDiskIoProtocolGuid, &OpenInfo, &OpenInfoCount ); if (EFI_ERROR(Status)) { //DBG(" OpenInfo: no - skipping\n"); continue; } //DBG(" OpenInfo: %d", OpenInfoCount); for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) { if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) == EFI_OPEN_PROTOCOL_BY_DRIVER) { if (!Found) { DBG("\n"); } Found = true; Status = gBS->DisconnectController (Handles[Index], OpenInfo[OpenInfoIndex].AgentHandle, NULL); //DBG(" BY_DRIVER Agent: %p, Disconnect: %s", OpenInfo[OpenInfoIndex].AgentHandle, efiStrError(Status)); DBG(" - Handle %llx with DiskIo, is Partition, no Fs, BY_DRIVER Agent: %llx, Disconnect: %s\n", (uintptr_t)Handles[Index], (uintptr_t)(OpenInfo[OpenInfoIndex].AgentHandle), efiStrError(Status)); } } FreePool(OpenInfo); } FreePool(Handles); if (!Found) { DBG(" not found, all ok\n"); } } void DisconnectSomeDevices(void) { EFI_STATUS Status; UINTN HandleCount; UINTN Index, Index2; EFI_HANDLE *Handles ; EFI_HANDLE *ControllerHandles; UINTN ControllerHandleCount; EFI_BLOCK_IO_PROTOCOL *BlockIo = NULL; // EFI_DISK_IO_PROTOCOL *DiskIo = NULL; EFI_PCI_IO_PROTOCOL *PciIo = NULL; // EFI_FILE_PROTOCOL *RootFP = NULL; // EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *VolumeFS = NULL; PCI_TYPE00 Pci; CHAR16 *DriverName = NULL; EFI_COMPONENT_NAME_PROTOCOL *CompName = NULL; if (gDriversFlags.PartitionLoaded) { DBG("Partition driver loaded: "); // get all BlockIo handles HandleCount = 0; Handles = NULL; Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &HandleCount, &Handles); if (Status == EFI_SUCCESS) { for (Index = 0; Index < HandleCount; Index++) { Status = gBS->HandleProtocol(Handles[Index], &gEfiBlockIoProtocolGuid, (void **) &BlockIo); if (EFI_ERROR(Status)) { continue; } if (BlockIo->Media->BlockSize == 2048) { // disconnect CD controller Status = gBS->DisconnectController(Handles[Index], NULL, NULL); DBG("CD disconnect %s", efiStrError(Status)); } } /* for (Index = 0; Index < HandleCount; Index++) { Status = gBS->DisconnectController(Handles[Index], NULL, NULL); } */ FreePool(Handles); } DBG("\n"); } if ((gDriversFlags.HFSLoaded) || (gDriversFlags.APFSLoaded)) { if (gDriversFlags.HFSLoaded) { DBG("HFS+ driver loaded\n"); } if (gDriversFlags.APFSLoaded) { DBG("APFS driver loaded\n"); } // get all FileSystem handles ControllerHandleCount = 0; ControllerHandles = NULL; Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiSimpleFileSystemProtocolGuid, NULL, &ControllerHandleCount, &ControllerHandles); /* if (!EFI_ERROR(Status)) { for (Index2 = 0; Index2 < ControllerHandleCount; Index2++) { Status = gBS->DisconnectController(ControllerHandles[Index2], NULL, NULL); DBG("Driver [%d] disconnect %s\n", Index2, efiStrError(Status)); } } */ HandleCount = 0; Handles = NULL; Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiComponentNameProtocolGuid, NULL, &HandleCount, &Handles); if (!EFI_ERROR(Status)) { for (Index = 0; Index < HandleCount; Index++) { Status = gBS->OpenProtocol( Handles[Index], gEfiComponentNameProtocolGuid, (void**)&CompName, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); if (EFI_ERROR(Status)) { // DBG("CompName %s\n", efiStrError(Status)); continue; } // 2021-05, Jief : PG7 had a crash. In some cases, CompName->GetDriverName == NULL. if ( CompName->GetDriverName == NULL ) { DBG("DisconnectSomeDevices: GetDriverName CompName=%lld, CompName->GetDriverName=NULL\n", uintptr_t(CompName)); continue; } Status = CompName->GetDriverName(CompName, "eng", &DriverName); if (EFI_ERROR(Status)) { continue; } if ((StriStr(DriverName, L"HFS")) || (StriStr(DriverName, L"apfs"))) { for (Index2 = 0; Index2 < ControllerHandleCount; Index2++) { Status = gBS->DisconnectController(ControllerHandles[Index2], Handles[Index], NULL); //DBG("Disconnect [%ls] from %llX: %s\n", DriverName, uintptr_t(ControllerHandles[Index2]), efiStrError(Status)); } } } FreePool(Handles); } // DBG("\n"); FreePool(ControllerHandles); } if (gDriversFlags.VideoLoaded) { DBG("Video driver loaded: "); // get all PciIo handles HandleCount = 0; Handles = NULL; Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiPciIoProtocolGuid, NULL, &HandleCount, &Handles); if (Status == EFI_SUCCESS) { for (Index = 0; Index < HandleCount; Index++) { Status = gBS->HandleProtocol(Handles[Index], &gEfiPciIoProtocolGuid, (void **) &PciIo); if (EFI_ERROR(Status)) { continue; } Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0, sizeof (Pci) / sizeof (UINT32), &Pci); if (!EFI_ERROR(Status)) { if(IS_PCI_VGA(&Pci) == true) { // disconnect VGA Status = gBS->DisconnectController(Handles[Index], NULL, NULL); DBG("disconnect %s", efiStrError(Status)); } } } FreePool(Handles); } DBG("\n"); } if (!gFirmwareClover) { DisconnectInvalidDiskIoChildDrivers(); } } void PatchVideoBios(UINT8 *Edid) { if ( gSettings.Graphics.PatchVBiosBytes.notEmpty() ) { VideoBiosPatchBytes(gSettings.Graphics.PatchVBiosBytes.getVBIOS_PATCH_BYTES(), gSettings.Graphics.PatchVBiosBytes.getVBIOS_PATCH_BYTES_count()); } if (gSettings.Graphics.PatchVBios) { VideoBiosPatchNativeFromEdid(Edid); } } static void LoadDrivers(void) { EFI_STATUS Status; EFI_HANDLE *DriversToConnect = NULL; UINTN DriversToConnectNum = 0; UINT8 *Edid; UINTN VarSize = 0; XBool VBiosPatchNeeded; DbgHeader("LoadDrivers"); // load drivers from /efi/drivers #if defined(MDE_CPU_X64) if (gFirmwareClover) { if (FileExists(&self.getCloverDir(), L"drivers\\BIOS")) { ScanDriverDir(L"drivers\\BIOS", &DriversToConnect, &DriversToConnectNum); } else { ScanDriverDir(L"drivers64", &DriversToConnect, &DriversToConnectNum); } } else { OpenRuntimeEfiName.setEmpty(); if (FileExists(&self.getCloverDir(), L"drivers\\5142")) { ScanDriverDir(L"drivers\\5142", &DriversToConnect, &DriversToConnectNum); } if (FileExists(&self.getCloverDir(), L"drivers\\UEFI")) { ScanDriverDir(L"drivers\\UEFI", &DriversToConnect, &DriversToConnectNum); } else { ScanDriverDir(L"drivers64UEFI", &DriversToConnect, &DriversToConnectNum); } } #else ScanDriverDir(L"drivers32", &DriversToConnect, &DriversToConnectNum); #endif VBiosPatchNeeded = gSettings.Graphics.PatchVBios || gSettings.Graphics.PatchVBiosBytes.getVBIOS_PATCH_BYTES_count() > 0; if (VBiosPatchNeeded) { // check if it is already done in CloverEFI BiosVideo Status = gRT->GetVariable ( L"CloverVBiosPatchDone", gEfiGlobalVariableGuid, NULL, &VarSize, NULL ); if (Status == EFI_BUFFER_TOO_SMALL) { // var exists - it's done - let's not do it again VBiosPatchNeeded = false; } } if ( (gSettings.Graphics.EDID.CustomEDID.notEmpty() && gFirmwareClover) || (VBiosPatchNeeded && !gDriversFlags.VideoLoaded)) { // we have video bios patch - force video driver reconnect DBG("Video bios patch requested or CustomEDID - forcing video reconnect\n"); gDriversFlags.VideoLoaded = true; DriversToConnectNum++; } UninitRefitLib(); if (DriversToConnectNum > 0) { DBG("%llu drivers needs connecting ...\n", DriversToConnectNum); // note: our platform driver protocol // will use DriversToConnect - do not release it RegisterDriversToHighestPriority(DriversToConnect); if (VBiosPatchNeeded) { if (gSettings.Graphics.EDID.CustomEDID.notEmpty()) { Edid = gSettings.Graphics.EDID.CustomEDID.data(); } else { Edid = getCurrentEdid(); } DisconnectSomeDevices(); PatchVideoBios(Edid); if (gSettings.Graphics.EDID.CustomEDID.isEmpty()) { FreePool(Edid); } } else { DisconnectSomeDevices(); } BdsLibConnectAllDriversToAllControllers(); // Boot speedup: remove temporary "BiosVideoBlockSwitchMode" RT var // to unlock mode switching in CsmVideo gRT->SetVariable(L"BiosVideoBlockSwitchMode", gEfiGlobalVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS, 0, NULL); }else{ BdsLibConnectAllEfi(); // jief : without any driver loaded, i couldn't see my CD, unless I call BdsLibConnectAllEfi } ReinitRefitLib(); } INTN FindDefaultEntry(void) { INTN Index = -1; REFIT_VOLUME *Volume; XBool SearchForLoader; // DBG("FindDefaultEntry ...\n"); //DbgHeader("FindDefaultEntry"); // // try to detect volume set by Startup Disk or previous Clover selection // with broken nvram this requires emulation to be installed. // enable emulation to determin efi-boot-device-data if (gEmuVariableControl != NULL) { gEmuVariableControl->InstallEmulation(gEmuVariableControl); } Index = FindStartupDiskVolume(&MainMenu); if (Index >= 0) { DBG("Boot redirected to Entry %lld. '%ls'\n", Index, MainMenu.Entries[Index].Title.s()); // we got boot-device-data, no need to keep emulating anymore if (gEmuVariableControl != NULL) { gEmuVariableControl->UninstallEmulation(gEmuVariableControl); } return Index; } // // if not found, then try DefaultVolume from config.plist // if not null or empty, search volume that matches gSettings.Boot.DefaultVolume // if (gSettings.Boot.DefaultVolume.notEmpty()) { // if not null or empty, also search for loader that matches gSettings.Boot.DefaultLoader SearchForLoader = gSettings.Boot.DefaultLoader.notEmpty(); /* if (SearchForLoader) { DBG("Searching for DefaultVolume '%ls', DefaultLoader '%ls' ...\n", gSettings.Boot.DefaultVolume, gSettings.Boot.DefaultLoader); } else { DBG("Searching for DefaultVolume '%ls' ...\n", gSettings.Boot.DefaultVolume); } */ for (Index = 0; Index < (INTN)MainMenu.Entries.size() && MainMenu.Entries[Index].getLOADER_ENTRY() && MainMenu.Entries[Index].getLOADER_ENTRY()->Row == 0 ; Index++) { LOADER_ENTRY& Entry = *MainMenu.Entries[Index].getLOADER_ENTRY(); if (!Entry.Volume) { continue; } Volume = Entry.Volume; if ( (Volume->VolName.isEmpty() || Volume->VolName != gSettings.Boot.DefaultVolume) && !Volume->DevicePathString.contains(gSettings.Boot.DefaultVolume) ) { continue; } // we alreday know that Entry.isLoader if (SearchForLoader && (/*Entry.Tag != TAG_LOADER ||*/ !Entry.LoaderPath.containsIC(gSettings.Boot.DefaultLoader))) { continue; } DBG(" - found entry %lld. '%ls', Volume '%ls', DevicePath '%ls'\n", Index, Entry.Title.s(), Volume->VolName.wc_str(), Entry.DevicePathString.wc_str()); // if first method failed and second succeeded - uninstall emulation if (gEmuVariableControl != NULL) { gEmuVariableControl->UninstallEmulation(gEmuVariableControl); } return Index; } } DBG("Default boot entry not found\n"); // if both methods to determine default boot entry have failed - uninstall emulation before GUI if (gEmuVariableControl != NULL) { gEmuVariableControl->UninstallEmulation(gEmuVariableControl); } return -1; } void SetVariablesFromNvram() { CHAR8 *tmpString; UINTN Size = 0; UINTN index = 0, index2, i; CHAR8 *arg = NULL; // DbgHeader("SetVariablesFromNvram"); tmpString = (__typeof__(tmpString))GetNvramVariable(L"boot-args", gEfiAppleBootGuid, NULL, &Size); if (tmpString && (Size <= 0x1000) && (Size > 0)) { DBG("found boot-args in NVRAM:%s, size=%llu\n", tmpString, Size); // use and forget old one // DeleteNvramVariable(L"boot-args", &gEfiAppleBootGuid); Size = AsciiStrLen(tmpString); // some EFI implementations include '\0' in Size, and others don't, so update Size to string length arg = (__typeof__(arg))AllocatePool(Size+1); /* if (AsciiStrStr(tmpString, "nvda_drv=1")) { //found substring gSettings.NvidiaWeb = true; } */ //first we will find new args that is not present in main args index = 0; while ((index < Size) && (tmpString[index] != 0x0)) { ZeroMem(arg, Size+1); index2 = 0; if (tmpString[index] != '\"') { // DBG("search space index=%d\n", index); while ((index < Size) && (tmpString[index] != 0x20) && (tmpString[index] != 0x0)) { arg[index2++] = tmpString[index++]; } DBG("...found arg:%s\n", arg); } else { index++; // DBG("search quote index=%d\n", index); while ((index < Size) && (tmpString[index] != '\"') && (tmpString[index] != 0x0)) { arg[index2++] = tmpString[index++]; } if (tmpString[index] == '\"') { index++; } DBG("...found quoted arg:\n"/*, arg*/); } while (tmpString[index] == 0x20) { index++; } // For the moment only arg -s must be ignored if (AsciiStrCmp(arg, "-s") == 0) { DBG("...ignoring arg:%s\n", arg); continue; } if (!gSettings.Boot.BootArgs.contains(arg)) { //this arg is not present will add DBG("...adding arg:%s\n", arg); gSettings.Boot.BootArgs.trim(); gSettings.Boot.BootArgs += ' '; for (i = 0; i < index2; i++) { gSettings.Boot.BootArgs += arg[i]; } gSettings.Boot.BootArgs += ' '; } } FreePool(arg); } if (tmpString) { FreePool(tmpString); } tmpString = (__typeof__(tmpString))GetNvramVariable(L"nvda_drv", gEfiAppleBootGuid, NULL, NULL); if (tmpString && AsciiStrCmp(tmpString, "1") == 0) { gSettings.SystemParameters.NvidiaWeb = true; } if (tmpString) { FreePool(tmpString); } } void GetListOfConfigs() { REFIT_DIR_ITER DirIter; EFI_FILE_INFO *DirEntry; ConfigsList.setEmpty(); OldChosenConfig = 0; DirIterOpen(&selfOem.getConfigDir(), NULL, &DirIter); DbgHeader("Found config plists"); while (DirIterNext(&DirIter, 2, L"config*.plist", &DirEntry)) { if (DirEntry->FileName[0] == L'.') { continue; } if (StriCmp(DirEntry->FileName, L"config.plist") == 0) { OldChosenConfig = ConfigsList.size(); // DirEntry->FileName is not yet inserted into ConfigsList. So its index will be ConfigsList.size() } size_t NameLen = wcslen(DirEntry->FileName) - 6; //without ".plist" if ( NameLen <= MAX_INTN ) { ConfigsList.AddReference(SWPrintf("%.*ls", (int)NameLen, DirEntry->FileName).forgetDataWithoutFreeing(), true); // this avoid to reallocate and copy memory DBG("- %ls\n", DirEntry->FileName); }else{ DBG("- bug!, NameLen > MAX_INTN"); } } DirIterClose(&DirIter); } void GetListOfDsdts() { REFIT_DIR_ITER DirIter; EFI_FILE_INFO *DirEntry; DsdtsList.setEmpty(); OldChosenDsdt = 0xFFFF; DirIterOpen(&selfOem.getConfigDir(), L"ACPI\\patched", &DirIter); DbgHeader("Found DSDT tables"); while (DirIterNext(&DirIter, 2, L"DSDT*.aml", &DirEntry)) { if (DirEntry->FileName[0] == L'.') { continue; } if ( gSettings.ACPI.DSDT.DsdtName.isEqualIC(DirEntry->FileName) ) { OldChosenDsdt = DsdtsList.size(); // DirEntry->FileName is not yet inserted into DsdtsList. So its index will be DsdtsList.size() } size_t NameLen = wcslen(DirEntry->FileName); //with ".aml" DsdtsList.AddReference(SWPrintf("%.*ls", (int)NameLen, DirEntry->FileName).forgetDataWithoutFreeing(), true); // this avoid to reallocate and copy memory DBG("- %ls\n", DirEntry->FileName); } DirIterClose(&DirIter); } void GetListOfACPI() { REFIT_DIR_ITER DirIter; EFI_FILE_INFO *DirEntry = NULL; // XStringW AcpiPath = SWPrintf("%ls\\ACPI\\patched", OEMPath.wc_str()); // DBG("Get list of ACPI at path %ls\n", AcpiPath.wc_str()); ACPIPatchedAML.setEmpty(); DirIterOpen(&selfOem.getConfigDir(), L"ACPI\\patched", &DirIter); while (DirIterNext(&DirIter, 2, L"*.aml", &DirEntry)) { // DBG("next entry is %ls\n", DirEntry->FileName); if (DirEntry->FileName[0] == L'.') { continue; } if (StriStr(DirEntry->FileName, L"DSDT")) { continue; } // DBG("Found name %ls\n", DirEntry->FileName); XBool ACPIDisabled = false; ACPI_PATCHED_AML* ACPIPatchedAMLTmp = new ACPI_PATCHED_AML; ACPIPatchedAMLTmp->FileName.takeValueFrom(DirEntry->FileName); INTN Count = gSettings.ACPI.DisabledAML.size(); for (INTN i = 0; i < Count; i++) { if ( gSettings.ACPI.DisabledAML[i].isEqualIC(ACPIPatchedAMLTmp->FileName) ) { // if ((gSettings.ACPI.DisabledAML[i] != NULL) && // (StriCmp(ACPIPatchedAMLTmp->FileName, gSettings.ACPI.DisabledAML[i]) == 0) // ) { ACPIDisabled = true; break; } } ACPIPatchedAMLTmp->MenuItem.BValue = ACPIDisabled; ACPIPatchedAML.AddReference(ACPIPatchedAMLTmp, true); } DirIterClose(&DirIter); } void GetListOfThemes () { EFI_STATUS Status = EFI_NOT_FOUND; REFIT_DIR_ITER DirIter; EFI_FILE_INFO *DirEntry; XStringW ThemeTestPath; EFI_FILE *ThemeTestDir = NULL; UINT8 *ThemePtr = NULL; UINTN Size = 0; DbgHeader("GetListOfThemes"); ThemeNameArray.setEmpty(); if ( !self.themesDirExists() ) { DBG("No theme dir was discovered\n"); return; } DirIterOpen(&self.getThemesDir(), NULL, &DirIter); while (DirIterNext(&DirIter, 1, L"*", &DirEntry)) { if (DirEntry->FileName[0] == '.') { //DBG("Skip theme: %ls\n", DirEntry->FileName); continue; } //DBG("Found theme directory: %ls", DirEntry->FileName); DBG("- [%02zu]: %ls", ThemeNameArray.size(), DirEntry->FileName); Status = self.getThemesDir().Open(&self.getThemesDir(), &ThemeTestDir, DirEntry->FileName, EFI_FILE_MODE_READ, 0); if (!EFI_ERROR(Status)) { Status = egLoadFile(ThemeTestDir, CONFIG_THEME_FILENAME, &ThemePtr, &Size); if (EFI_ERROR(Status) || (ThemePtr == NULL) || (Size == 0)) { Status = egLoadFile(ThemeTestDir, CONFIG_THEME_SVG, &ThemePtr, &Size); if (EFI_ERROR(Status)) { Status = EFI_NOT_FOUND; DBG(" - bad theme because %ls nor %ls can't be load", CONFIG_THEME_FILENAME, CONFIG_THEME_SVG); } } if (!EFI_ERROR(Status)) { //we found a theme if ((StriCmp(DirEntry->FileName, L"embedded") == 0) || (StriCmp(DirEntry->FileName, L"random") == 0)) { ThemePtr = NULL; } else { ThemeNameArray.Add(DirEntry->FileName); } } } DBG("\n"); if (ThemePtr) { FreePool(ThemePtr); } } DirIterClose(&DirIter); } // // main entry point // EFI_STATUS EFIAPI RefitMain (IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable) { EFI_STATUS Status; XBool MainLoopRunning = true; XBool ReinitDesktop = true; XBool AfterTool = false; REFIT_ABSTRACT_MENU_ENTRY *ChosenEntry = NULL; REFIT_ABSTRACT_MENU_ENTRY *DefaultEntry = NULL; REFIT_ABSTRACT_MENU_ENTRY *OptionEntry = NULL; INTN DefaultIndex; UINTN MenuExit; UINTN i; EFI_TIME Now; XBool HaveDefaultVolume; REFIT_MENU_SCREEN BootScreen; BootScreen.isBootScreen = true; //other screens will be constructed as false MemLogInit(); // bootstrap gST = SystemTable; gImageHandle = ImageHandle; gBS = SystemTable->BootServices; gRT = SystemTable->RuntimeServices; /*Status = */EfiGetSystemConfigurationTable (&gEfiDxeServicesTableGuid, (void **) &gDS); InitBooterLog(); // ConsoleInHandle = SystemTable->ConsoleInHandle; //#define DEBUG_ERALY_CRASH #ifdef DEBUG_ERALY_CRASH SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Step1"); PauseForKey("press any key\n"_XS8); #endif #ifdef DEBUG_ON_SERIAL_PORT SerialPortInitialize(); #endif { EFI_LOADED_IMAGE* LoadedImage; Status = gBS->HandleProtocol(gImageHandle, &gEfiLoadedImageProtocolGuid, (void **) &LoadedImage); #ifdef DEBUG_ERALY_CRASH SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Step2"); PauseForKey("press any key\n"_XS8); #endif // if ( !EFI_ERROR(Status) ) { // XString8 msg = S8Printf("CloverX64 : Image base = 0x%llX\n", (uintptr_t)LoadedImage->ImageBase); // do not change, it's used by grep to feed the debugger // SerialPortWrite((UINT8*)msg.c_str(), msg.length()); // } if ( !EFI_ERROR(Status) ) { DBG("CloverX64 : Image base = 0x%llX\n", (uintptr_t)LoadedImage->ImageBase); // do not change, it's used by grep to feed the debugger DBG("Clover ImageHandle = %llx\n", (uintptr_t)ImageHandle); #ifdef DEBUG_ERALY_CRASH SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Step3"); PauseForKey("press any key\n"_XS8); #endif } #ifdef JIEF_DEBUG gBS->Stall(2500000); // to give time to gdb to connect // PauseForKey("press\n"_XS8); #endif } #ifdef DEBUG_ERALY_CRASH SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Step4"); PauseForKey("press any key\n"_XS8); #endif #ifdef CLOVER_BUILD // BE CAREFUL. construct_globals_objects will call ctor on every static struct and classes. // For example, if you do "gCPUStructure.TSCCalibr = GetMemLogTscTicksPerSecond();" before this point, it will be erased by construct_globals_objects() construct_globals_objects(gImageHandle); #endif gCPUStructure.TSCCalibr = GetMemLogTscTicksPerSecond(); //ticks for 1second #ifdef DEBUG_ERALY_CRASH SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Step5"); PauseForKey("press any key\n"_XS8); #endif #ifdef JIEF_DEBUG // all_tests(); // PauseForKey(L"press\n"); #endif gRT->GetTime(&Now, NULL); Status = InitRefitLib(gImageHandle); // From here, debug.log starts to be saved because InitRefitLib call self.initialize() if (EFI_ERROR(Status)) return Status; #ifdef DEBUG_ERALY_CRASH SystemTable->ConOut->OutputString(SystemTable->ConOut, L"Step6"); PauseForKey("press any key\n"_XS8); #endif // firmware detection gFirmwareClover = StrCmp(gST->FirmwareVendor, L"CLOVER") == 0; if (!gFirmwareRevision) { // gFirmwareRevision = P__oolPrint(L"%d", gST->FirmwareRevision); } DataHubInstall (ImageHandle, SystemTable); InitializeConsoleSim(); DbgHeader("Starting Clover"); if (Now.TimeZone < -1440 || Now.TimeZone > 1440) { MsgLog("Now is %02d.%02d.%d, %02d:%02d:%02d (GMT)\n", Now.Day, Now.Month, Now.Year, Now.Hour, Now.Minute, Now.Second); } else { MsgLog("Now is %02d.%02d.%d, %02d:%02d:%02d (GMT+%d)\n", Now.Day, Now.Month, Now.Year, Now.Hour, Now.Minute, Now.Second, gSettings.GUI.Timezone); } //MsgLog("Starting Clover rev %ls on %ls EFI\n", gFirmwareRevision, gST->FirmwareVendor); MsgLog("Starting %s on %ls EFI\n", gRevisionStr, gST->FirmwareVendor); MsgLog("Build id: %s\n", gBuildId.c_str()); if ( gBuildInfo ) DBG("Build with: [%s]\n", gBuildInfo); displayFreeMemory(""_XS8); //dumping SETTING structure // if you change something in Platform.h, please uncomment and test that all offsets // are natural aligned i.e. pointers are 8 bytes aligned /* DBG("Settings offsets:\n"); DBG(" OEMProduct: %X\n", OFFSET_OF(SETTINGS_DATA, OEMProduct)); DBG(" DefaultVolume: %X\n", OFFSET_OF(SETTINGS_DATA, DefaultVolume)); DBG(" DefaultLoader: %X\n", OFFSET_OF(SETTINGS_DATA, DefaultLoader)); DBG(" ResetAddr: %X\n", OFFSET_OF(SETTINGS_DATA, ResetAddr)); DBG(" FixDsdt: %X\n", OFFSET_OF(SETTINGS_DATA, FixDsdt)); DBG(" FakeATI: %X\n", OFFSET_OF(SETTINGS_DATA, FakeATI)); DBG(" PatchVBiosBytes:%X\n", OFFSET_OF(SETTINGS_DATA, PatchVBiosBytes)); DBG(" VRAM: %X\n", OFFSET_OF(SETTINGS_DATA, VRAM)); DBG(" SecureBootWhiteListCount: %X\n", OFFSET_OF(SETTINGS_DATA, SecureBootWhiteListCount)); DBG(" LegacyBoot: %X\n", OFFSET_OF(SETTINGS_DATA, LegacyBoot)); DBG(" HVHideStrings: %X\n", OFFSET_OF(SETTINGS_DATA, HVHideStrings)); DBG(" PointerSpeed: %X\n", OFFSET_OF(SETTINGS_DATA, PointerSpeed)); DBG(" RtMLB: %X\n", OFFSET_OF(SETTINGS_DATA, RtMLB)); DBG(" ConfigName: %X\n", OFFSET_OF(SETTINGS_DATA, ConfigName)); DBG(" PointerSpeed: %X\n", OFFSET_OF(SETTINGS_DATA, PointerSpeed)); DBG(" PatchDsdtNum: %X\n", OFFSET_OF(SETTINGS_DATA, PatchDsdtNum)); DBG(" LenToReplace: %X\n", OFFSET_OF(SETTINGS_DATA, LenToReplace)); DBG(" ACPIDropTables: %X\n", OFFSET_OF(SETTINGS_DATA, ACPIDropTables)); DBG(" CustomEntries: %X\n", OFFSET_OF(SETTINGS_DATA, CustomEntries)); DBG(" CustomTool: %X\n", OFFSET_OF(SETTINGS_DATA, CustomTool)); DBG(" AddProperties: %X\n", OFFSET_OF(SETTINGS_DATA, AddProperties)); DBG(" BlockKexts: %X\n", OFFSET_OF(SETTINGS_DATA, BlockKexts)); */ // disable EFI watchdog timer gBS->SetWatchdogTimer(0x0000, 0x0000, 0x0000, NULL); // ZeroMem((void*)&gSettings, sizeof(SETTINGS_DATA)); Status = InitializeUnicodeCollationProtocol(); if (EFI_ERROR(Status)) { DBG("UnicodeCollation Status=%s\n", efiStrError(Status)); } // Status = gBS->HandleProtocol(ConsoleInHandle, &gEfiSimpleTextInputExProtocolGuid, (void **)&SimpleTextEx); // if ( EFI_ERROR(Status) ) { // SimpleTextEx = NULL; // } // DBG("SimpleTextEx Status=%s\n", efiStrError(Status)); gConf.InitialisePlatform(); #ifdef JIEF_DEBUG DumpNvram(); #endif /* * saving debug.log works from here */ { // UINT32 machineSignature = 0; EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *FadtPointer = NULL; EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs = NULL; // DBG("---dump hibernations data---\n"); FadtPointer = GetFadt(); if (FadtPointer != NULL) { Facs = (EFI_ACPI_4_0_FIRMWARE_ACPI_CONTROL_STRUCTURE*)(UINTN)(FadtPointer->FirmwareCtrl); /* DBG(" Firmware wake address=%08lx\n", Facs->FirmwareWakingVector); DBG(" Firmware wake 64 addr=%16llx\n", Facs->XFirmwareWakingVector); DBG(" Hardware signature =%08lx\n", Facs->HardwareSignature); DBG(" GlobalLock =%08lx\n", Facs->GlobalLock); DBG(" Flags =%08lx\n", Facs->Flags); */ machineSignature = Facs->HardwareSignature; } #if HIBERNATE_DUMP_DATA //------------------------------------------------------ DumpVariable(L"Boot0082", gEfiGlobalVariableGuid, 8); DumpVariable(L"boot-switch-vars", gEfiAppleBootGuid, -1); DumpVariable(L"boot-signature", gEfiAppleBootGuid, -1); DumpVariable(L"boot-image-key", gEfiAppleBootGuid, -1); DumpVariable(L"boot-image", gEfiAppleBootGuid, 0); //----------------------------------------------------------- #endif // } #if 0 //testing place { const CHAR16 aaa[] = L"12345 "; const CHAR8 *bbb = "12345 "; DBG(" string %ls, size=%lld, len=%lld sizeof=%ld iStrLen=%lld\n", aaa, StrSize(aaa), StrLen(aaa), sizeof(aaa), iStrLen(bbb, 10)); const CHAR8* ccc = "Выход "; DBG(" string %s, size=%lld, len=%lld sizeof=%ld iStrLen=%lld\n", ccc, AsciiStrSize(ccc), AsciiStrLen(ccc), sizeof(ccc), iStrLen(ccc, 10)); XString8 ddd = "Выход "_XS8; // size_t sizex = ddd.allocatedSize(); DBG(" xstring %s, asize=%ld, sizeinbyte=%ld sizeof=%ld lastcharat=%ld\n", ddd.c_str(), ddd.allocatedSize(), ddd.sizeInBytes(), sizeof(ddd), ddd.indexOf(ddd.lastChar())); CHAR8 compatible[64]; UINT32 FakeLAN = 0x0030168c; UINT32 FakeID = FakeLAN >> 16; UINT32 FakeVendor = FakeLAN & 0xFFFF; snprintf(compatible, 64, "pci%x,%x", FakeVendor, FakeID); DBG(" FakeLAN = 0x%x\n", FakeLAN); DBG(" Compatible=%s strlen=%ld sizeof=%ld iStrLen=%lld\n", compatible, strlen(compatible), sizeof(compatible), iStrLen(compatible, 64)); // LowCase(compatible); // DBG(" Low Compatible=%s strlen=%ld sizeof=%ld iStrLen=%lld\n", compatible, // strlen(compatible), sizeof(compatible), iStrLen(compatible, 64)); DBG("void*=%ld int=%ld long=%ld longlong=%ld enum=%ld\n", sizeof(void*), sizeof(int), sizeof(long int), sizeof(long long), sizeof(EFI_ALLOCATE_TYPE)); /* Results 41:381 0:000 string 12345 , size=16, len=7 sizeof=16 iStrLen=5 41:381 0:000 string Выход , size=13, len=12 sizeof=8 iStrLen=10 41:381 0:000 xstring Выход , asize=0, sizeinbyte=11 sizeof=16 lastcharat=5 41:381 0:000 FakeLAN = 0x30168c 41:381 0:000 Compatible=pci168c,30 strlen=10 sizeof=64 iStrLen=10 */ } #endif if (!GlobalConfig.isFastBoot()) { GetListOfThemes(); GetListOfConfigs(); // SmbiosList.setEmpty(); // SmbiosList.AddReference(new XStringW(L"auto"_XSW), true); } // ThemeX->FillByEmbedded(); //init XTheme before EarlyUserSettings { void *Value = NULL; UINTN Size = 0; //read aptiofixflag from nvram for special boot Status = GetVariable2(L"aptiofixflag", gEfiAppleBootGuid, &Value, &Size); if (!EFI_ERROR(Status)) { GlobalConfig.SpecialBootMode = true; FreePool(Value); DBG("Fast option enabled\n"); } } // for (i=0; i<2; i++) { // if (gConfigDict[i]) { // GetEarlyUserSettings(gConfigDict[i], gSettings); // } // } #ifdef ENABLE_SECURE_BOOT // Install secure boot shim if (EFI_ERROR(Status = InstallSecureBoot())) { PauseForKey("Secure boot failure!\n"_XS8); return Status; } #endif // ENABLE_SECURE_BOOT MainMenu.TimeoutSeconds = gSettings.Boot.Timeout >= 0 ? gSettings.Boot.Timeout : 0; //DBG("LoadDrivers() start\n"); LoadDrivers(); Status = gBS->LocateProtocol(gEmuVariableControlProtocolGuid, NULL, (void**)&gEmuVariableControl); if (EFI_ERROR(Status)) { gEmuVariableControl = NULL; } if (gEmuVariableControl != NULL) { gEmuVariableControl->InstallEmulation(gEmuVariableControl); } DbgHeader("InitScreen"); if (!GlobalConfig.isFastBoot()) { // init screen and dump video modes to log if (gDriversFlags.VideoLoaded) { InitScreen(false); } else { InitScreen(!gFirmwareClover); // ? false : true); } //DBG("DBG: setup screen\n"); SetupScreen(); } else { InitScreen(false); } //DBG("ReinitRefitLib\n"); //Now we have to reinit handles Status = ReinitRefitLib(); if (EFI_ERROR(Status)){ // DebugLog(2, " %s", efiStrError(Status)); PauseForKey("Error reinit refit."_XS8); #ifdef ENABLE_SECURE_BOOT UninstallSecureBoot(); #endif // ENABLE_SECURE_BOOT return Status; } ThemeX = new XTheme(); // DBG("DBG: messages\n"); if (!gSettings.Boot.NoEarlyProgress && !GlobalConfig.isFastBoot() && gSettings.Boot.Timeout>0) { XStringW Message = SWPrintf(" Welcome to Clover %ls ", gFirmwareRevision); BootScreen.DrawTextXY(Message, (UGAWidth >> 1), UGAHeight >> 1, X_IS_CENTER); BootScreen.DrawTextXY(L"... testing hardware ..."_XSW, (UGAWidth >> 1), (UGAHeight >> 1) + 20, X_IS_CENTER); } // DumpBiosMemoryMap(); GuiEventsInitialize(); //DBG("ScanSPD() start\n"); ScanSPD(); //DBG("ScanSPD() end\n"); SetPrivateVarProto(); // GetDefaultSettings(); GetAcpiTablesList(); if (!gSettings.Boot.NoEarlyProgress && !GlobalConfig.isFastBoot() && gSettings.Boot.Timeout>0) { XStringW Message = SWPrintf("... user settings ..."); BootScreen.EraseTextXY(); BootScreen.DrawTextXY(Message, (UGAWidth >> 1), (UGAHeight >> 1) + 20, X_IS_CENTER); } afterGetUserSettings(gSettings); gFakeCPUID = gSettings.KernelAndKextPatches.FakeCPUID; DBG("Set FakeCPUID: 0x%X\n", gFakeCPUID); HaveDefaultVolume = gSettings.Boot.DefaultVolume.notEmpty(); if (!gFirmwareClover && !gDriversFlags.EmuVariableLoaded && !HaveDefaultVolume && gSettings.Boot.Timeout == 0 && !ReadAllKeyStrokes()) { // UEFI boot: get gEfiBootDeviceGuid from NVRAM. // if present, ScanVolumes() will skip scanning other volumes // in the first run. // this speeds up loading of default macOS volume. GetEfiBootDeviceFromNvram(); } if (!gSettings.Boot.NoEarlyProgress && !GlobalConfig.isFastBoot() && gSettings.Boot.Timeout>0) { XStringW Message = SWPrintf("... scan entries ..."); BootScreen.EraseTextXY(); BootScreen.DrawTextXY(Message, (UGAWidth >> 1), (UGAHeight >> 1) + 20, X_IS_CENTER); } AfterTool = false; gGuiIsReady = true; GlobalConfig.gBootChanged = true; GlobalConfig.gThemeChanged = true; do { if (GlobalConfig.gBootChanged && GlobalConfig.gThemeChanged) { // config changed GetListOfDsdts(); //only after GetUserSettings GetListOfACPI(); //ssdt and other tables } GlobalConfig.gBootChanged = false; MainMenu.Entries.setEmpty(); OptionMenu.Entries.setEmpty(); InitKextList(); ScanVolumes(); // as soon as we have Volumes, find latest nvram.plist and copy it to RT vars if (!AfterTool) { if (gFirmwareClover || gDriversFlags.EmuVariableLoaded) { PutNvramPlistToRtVars(); } } // log Audio devices in boot-log. This is for clients like Clover.app GetOutputs(); for (i = 0; i < AudioList.size(); i++) { if (AudioList[i].Name.notEmpty()) { // Never change this log, otherwise clients will stop interpret the output. MsgLog("Found Audio Device %ls (%s) at index %llu\n", AudioList[i].Name.wc_str(), AudioOutputNames[AudioList[i].Device], i); } } if (!GlobalConfig.isFastBoot()) { if (gThemeNeedInit) { UINTN Size = 0; InitTheme((CHAR8*)GetNvramVariable(L"Clover.Theme", gEfiAppleBootGuid, NULL, &Size)); gThemeNeedInit = false; } else if (GlobalConfig.gThemeChanged) { DBG("change theme\n"); InitTheme(NULL); AboutMenu.Entries.setEmpty(); HelpMenu.Entries.setEmpty(); } DBG("theme inited\n"); if (ThemeX->embedded) { DBG("Chosen embedded theme\n"); } else { DBG("Chosen theme %ls\n", ThemeX->Theme.wc_str()); } //now it is a time to set RtVariables SetVariablesFromNvram(); XString8Array TmpArgs = Split<XString8Array>(gSettings.Boot.BootArgs, " "); DBG("after NVRAM boot-args=%s\n", gSettings.Boot.BootArgs.c_str()); GlobalConfig.OptionsBits = EncodeOptions(TmpArgs); // DBG("initial OptionsBits %X\n", GlobalConfig.OptionsBits); FillInputs(true); // scan for loaders and tools, add then to the menu if (gSettings.GUI.Scan.LegacyFirst){ AddCustomLegacy(); if (!gSettings.GUI.Scan.NoLegacy) { ScanLegacy(); } } } GetSmcKeys(true); // Add custom entries AddCustomEntries(); if (gSettings.GUI.Scan.DisableEntryScan) { DBG("Entry scan disabled\n"); } else { ScanLoader(); } if (!GlobalConfig.isFastBoot()) { if (!gSettings.GUI.Scan.LegacyFirst) { AddCustomLegacy(); if (!gSettings.GUI.Scan.NoLegacy) { ScanLegacy(); } } // fixed other menu entries if (!(ThemeX->HideUIFlags & HIDEUI_FLAG_TOOLS)) { AddCustomTool(); if (!gSettings.GUI.Scan.DisableToolScan) { ScanTool(); #ifdef ENABLE_SECURE_BOOT // Check for secure boot setup mode AddSecureBootTool(); #endif // ENABLE_SECURE_BOOT } } MenuEntryOptions.Image = ThemeX->GetIcon(BUILTIN_ICON_FUNC_OPTIONS); // DBG("Options: IconID=%lld name=%s empty=%s\n", MenuEntryOptions.Image.Id, MenuEntryOptions.Image.Name.c_str(), if (gSettings.Boot.DisableCloverHotkeys) MenuEntryOptions.ShortcutLetter = 0x00; MainMenu.AddMenuEntry(&MenuEntryOptions, false); MenuEntryAbout.Image = ThemeX->GetIcon((INTN)BUILTIN_ICON_FUNC_ABOUT); // DBG("About: IconID=%lld name=%s empty=%s\n", MenuEntryAbout.Image.Id, MenuEntryAbout.Image.Name.c_str(), if (gSettings.Boot.DisableCloverHotkeys) MenuEntryAbout.ShortcutLetter = 0x00; MainMenu.AddMenuEntry(&MenuEntryAbout, false); if (!(ThemeX->HideUIFlags & HIDEUI_FLAG_FUNCS) || MainMenu.Entries.size() == 0) { if (gSettings.Boot.DisableCloverHotkeys) MenuEntryReset.ShortcutLetter = 0x00; MenuEntryReset.Image = ThemeX->GetIcon(BUILTIN_ICON_FUNC_RESET); MainMenu.AddMenuEntry(&MenuEntryReset, false); if (gSettings.Boot.DisableCloverHotkeys) MenuEntryShutdown.ShortcutLetter = 0x00; MenuEntryShutdown.Image = ThemeX->GetIcon(BUILTIN_ICON_FUNC_EXIT); MainMenu.AddMenuEntry(&MenuEntryShutdown, false); } } // wait for user ACK when there were errors FinishTextScreen(false); #if CHECK_SMC DumpSmcKeys(); #endif DefaultIndex = FindDefaultEntry(); // DBG("DefaultIndex=%lld and MainMenu.Entries.size()=%llu\n", DefaultIndex, MainMenu.Entries.size()); if ((DefaultIndex >= 0) && (DefaultIndex < (INTN)MainMenu.Entries.size())) { DefaultEntry = &MainMenu.Entries[DefaultIndex]; } else { DefaultEntry = NULL; } MainLoopRunning = true; if (DefaultEntry && (GlobalConfig.isFastBoot() || (gSettings.Boot.SkipHibernateTimeout && DefaultEntry->getLOADER_ENTRY() && OSFLAG_ISSET(DefaultEntry->getLOADER_ENTRY()->Flags, OSFLAG_HIBERNATED)))) { if (DefaultEntry->getLOADER_ENTRY()) { DefaultEntry->StartLoader(); } else if (DefaultEntry->getLEGACY_ENTRY()){ DefaultEntry->StartLegacy(); } gSettings.Boot.FastBoot = false; //Hmm... will never be here } #ifdef JIEF_DEBUG MainMenu.TimeoutSeconds=60; #endif AfterTool = false; gEvent = 0; //clear to cancel loop while (MainLoopRunning) { if (gSettings.Boot.Timeout == 0 && DefaultEntry != NULL && !ReadAllKeyStrokes()) { // go strait to DefaultVolume loading MenuExit = MENU_EXIT_TIMEOUT; } else { MainMenu.GetAnime(); if (GlobalConfig.gThemeChanged) { GlobalConfig.gThemeChanged = false; ThemeX->ClearScreen(); } displayFreeMemory("Before RunMainMenu"_XS8); MenuExit = MainMenu.RunMainMenu(DefaultIndex, &ChosenEntry); } // DBG("exit from MainMenu %llu\n", MenuExit); //MENU_EXIT_ENTER=(1) MENU_EXIT_DETAILS=3 // disable default boot - have sense only in the first run gSettings.Boot.Timeout = -1; if ((DefaultEntry != NULL) && (MenuExit == MENU_EXIT_TIMEOUT)) { if (DefaultEntry->getLOADER_ENTRY()) { DefaultEntry->StartLoader(); } else if (DefaultEntry->getLEGACY_ENTRY()){ DefaultEntry->StartLegacy(); } // if something goes wrong - break main loop to reinit volumes break; } if (MenuExit == MENU_EXIT_OPTIONS){ GlobalConfig.gBootChanged = false; OptionsMenu(&OptionEntry); if (GlobalConfig.gBootChanged) { AfterTool = true; MainLoopRunning = false; break; } continue; } if (MenuExit == MENU_EXIT_HELP){ HelpRefit(); continue; } // EjectVolume if (MenuExit == MENU_EXIT_EJECT){ Status = EFI_SUCCESS; if (ChosenEntry->getLOADER_ENTRY() ) { Status = EjectVolume(ChosenEntry->getLOADER_ENTRY()->Volume); } if ( ChosenEntry->getLEGACY_ENTRY() ) { Status = EjectVolume(ChosenEntry->getLEGACY_ENTRY()->Volume); } if (!EFI_ERROR(Status)) { break; //main loop is broken so Reinit all } continue; } // Hide toggle if (MenuExit == MENU_EXIT_HIDE_TOGGLE) { MainMenu.Entries.includeHidden = !MainMenu.Entries.includeHidden; continue; } // We don't allow exiting the main menu with the Escape key. if (MenuExit == MENU_EXIT_ESCAPE){ break; //refresh main menu // continue; } if ( ChosenEntry->getREFIT_MENU_ITEM_RESET() ) { // Restart if (MenuExit == MENU_EXIT_DETAILS) { //do clear cmos as for AMI BIOS // not sure for more robust method IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, 0x10); IoWrite8 (PCAT_RTC_DATA_REGISTER, 0x0); IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, 0x11); IoWrite8 (PCAT_RTC_DATA_REGISTER, 0x0); // or may be // IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, 0x17); // IoWrite8 (PCAT_RTC_DATA_REGISTER, 0x17); // } } // Attempt warm reboot gRT->ResetSystem(EfiResetWarm, EFI_SUCCESS, 0, NULL); // Warm reboot may not be supported attempt cold reboot gRT->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL); // Terminate the screen and just exit TerminateScreen(); MainLoopRunning = false; ReinitDesktop = false; AfterTool = true; } if ( ChosenEntry->getREFIT_MENU_ITEM_SHUTDOWN() ) { // It is not Shut Down, it is Exit from Clover TerminateScreen(); // gRT->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL); MainLoopRunning = false; // just in case we get this far ReinitDesktop = false; AfterTool = true; } if ( ChosenEntry->getREFIT_MENU_ITEM_OPTIONS() ) { // Options like KernelFlags, DSDTname etc. GlobalConfig.gBootChanged = false; OptionsMenu(&OptionEntry); if (GlobalConfig.gBootChanged) AfterTool = true; if (GlobalConfig.gBootChanged || GlobalConfig.gThemeChanged) // If theme has changed reinit the desktop MainLoopRunning = false; } if ( ChosenEntry->getREFIT_MENU_ITEM_ABOUT() ) { // About rEFIt AboutRefit(); } /* -- not passed here // case TAG_HELP: HelpRefit(); break; */ if ( ChosenEntry->getLOADER_ENTRY() ) { // Boot OS via .EFI loader SetBootCurrent(ChosenEntry->getLOADER_ENTRY()); ChosenEntry->StartLoader(); //if boot.efi failed we should somehow exit from the loop TerminateScreen(); MainLoopRunning = false; ReinitDesktop = false; AfterTool = true; } if ( ChosenEntry->getLEGACY_ENTRY() ) { // Boot legacy OS if (StrCmp(gST->FirmwareVendor, L"Phoenix Technologies Ltd.") == 0 && gST->Hdr.Revision >> 16 == 2 && (gST->Hdr.Revision & ((1 << 16) - 1)) == 0){ // Phoenix SecureCore Tiano 2.0 can't properly initiate LegacyBios protocol when called externally // which results in "Operating System not found" message coming from BIOS // in this case just quit Clover to enter BIOS again TerminateScreen(); MainLoopRunning = false; ReinitDesktop = false; AfterTool = true; } else { SetBootCurrent(ChosenEntry->getLEGACY_ENTRY()); ChosenEntry->StartLegacy(); } } if ( ChosenEntry->getREFIT_MENU_ENTRY_LOADER_TOOL() ) { // Start a EFI tool ChosenEntry->StartTool(); TerminateScreen(); //does not happen // return EFI_SUCCESS; // BdsLibConnectAllDriversToAllControllers(); // PauseForKey(L"Returned from StartTool\n"); MainLoopRunning = false; AfterTool = true; } #ifdef ENABLE_SECURE_BOOT log_technical_bug("not done yet"); // if ( ChosenEntry->getREFIT_MENU_ENTRY_SECURE_BOOT() ) { // Try to enable secure boot // EnableSecureBoot(); // MainLoopRunning = false; // AfterTool = true; // } // // if ( ChosenEntry->getREFIT_MENU_ENTRY_SECURE_BOOT_CONFIG() ) { // Configure secure boot // MainLoopRunning = !ConfigureSecureBoot(); // AfterTool = true; // } #endif // ENABLE_SECURE_BOOT // DBG("come to Clover entry with letter %c\n", ChosenEntry->ShortcutLetter); REFIT_MENU_ENTRY_CLOVER* LoaderEntry = ChosenEntry->getREFIT_MENU_ENTRY_CLOVER(); if ((ChosenEntry->ShortcutLetter == 'C') || LoaderEntry != NULL ) { // Clover options // DBG("enter Clover entry\n"); if (LoaderEntry->LoadOptions.notEmpty()) { // we are uninstalling in case user selected Clover Options and EmuVar is installed // because adding bios boot option requires access to real nvram //Slice: sure? /* if (gEmuVariableControl != NULL) { gEmuVariableControl->UninstallEmulation(gEmuVariableControl); } */ // DBG(" Clover entry not empty\n"); if ( LoaderEntry->LoadOptions.contains(L"BO-ADD") ) { // DBG(" BO-ADD"); XStringW Description; CONST CHAR16 *LoaderName; INTN EntryIndex, NameSize, Name2Size; LOADER_ENTRY *Entry; UINT8 *OptionalData; UINTN OptionalDataSize; UINTN BootNum; // EFI_HANDLE UsedHandle = 0; PrintBootOptions(false); for (EntryIndex = 0; EntryIndex < (INTN)MainMenu.Entries.size(); EntryIndex++) { if (MainMenu.Entries[EntryIndex].Row != 0) { continue; } if (!MainMenu.Entries[EntryIndex].getLOADER_ENTRY()) { continue; } Entry = (LOADER_ENTRY *)MainMenu.Entries[EntryIndex].getLOADER_ENTRY(); XStringW& VolName = Entry->Volume->VolName; DBG("add entry for volume %ls\n", VolName.wc_str()); if (VolName.isEmpty()) { VolName = NullXStringW; } NameSize = VolName.sizeInBytes(); Name2Size = 0; if (Entry->LoaderPath.notEmpty()) { LoaderName = Basename(Entry->LoaderPath.wc_str()); } else { LoaderName = NULL; //legacy boot } if (LoaderName != NULL) { Name2Size = StrSize(LoaderName); } Description = SWPrintf("Clover UEFI"); OptionalDataSize = NameSize + Name2Size + 4 + 2; //signature + VolNameSize OptionalData = (__typeof__(OptionalData))AllocateZeroPool(OptionalDataSize); if (OptionalData == NULL) { break; } CopyMem(OptionalData, "Clvr", 4); //signature = 0x72766c43 CopyMem(OptionalData + 4, &NameSize, 2); CopyMem(OptionalData + 6, VolName.wc_str(), VolName.sizeInBytes()); if (Name2Size != 0) { CopyMem(OptionalData + 6 + NameSize, LoaderName, Name2Size); } // UsedHandle = LoaderEntry->Volume->DeviceHandle; Status = AddBootOptionForFile ( LoaderEntry->Volume->DeviceHandle, LoaderEntry->LoaderPath, true, Description.wc_str(), OptionalData, OptionalDataSize, EntryIndex, (UINT16*)&BootNum ); if (!EFI_ERROR(Status)) { DBG("Entry %lld assigned option %04llX\n", EntryIndex, BootNum); Entry->BootNum = BootNum; } FreePool(OptionalData); break; } //for (EntryIndex PrintBootOptions(false); } else if ( LoaderEntry->LoadOptions.contains(L"BO-REMOVE") ) { PrintBootOptions(false); Status = DeleteBootOptionForFile (LoaderEntry->Volume->DeviceHandle, LoaderEntry->LoaderPath ); PrintBootOptions(false); } else if ( LoaderEntry->LoadOptions.contains(L"BO-PRINT") ) { PrintBootOptions(true); } } MainLoopRunning = false; AfterTool = true; } } //MainLoopRunning UninitRefitLib(); if (!AfterTool) { // PauseForKey(L"After uninit"); //reconnectAll if (!gFirmwareClover) { BdsLibConnectAllEfi(); } else { DBG("ConnectAll after refresh menu\n"); BdsLibConnectAllDriversToAllControllers(); } // ReinitRefitLib(); // PauseForKey(L"After ReinitRefitLib"); } if (ReinitDesktop) { DBG("ReinitRefitLib after theme change\n"); ReinitRefitLib(); } // PauseForKey(L"After ReinitRefitLib"); } while (ReinitDesktop); // If we end up here, things have gone wrong. Try to reboot, and if that // fails, go into an endless loop. //Slice - NO!!! Return to EFI GUI // gRT->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL); // EndlessIdleLoop(); #ifdef ENABLE_SECURE_BOOT UninstallSecureBoot(); #endif // ENABLE_SECURE_BOOT // Unload EmuVariable before returning to EFI GUI, as it should not be present when booting other Operating Systems. // This seems critical in some UEFI implementations, such as Phoenix UEFI 2.0 if (gEmuVariableControl != NULL) { gEmuVariableControl->UninstallEmulation(gEmuVariableControl); } UninitializeConsoleSim (); #ifdef CLOVER_BUILD destruct_globals_objects(NULL); #endif return EFI_SUCCESS; }