mirror of
https://github.com/acidanthera/OpenCorePkg.git
synced 2025-12-08 19:25:01 +00:00
EnableGop: Provide standalone GOP driver for EFI-era Macs
This commit is contained in:
parent
b07843fe1d
commit
f6bf1f2d86
@ -6,6 +6,8 @@ OpenCore Changelog
|
||||
- Added Linux support to legacy boot BootInstall script
|
||||
- Updated builtin firmware versions for SMBIOS and the rest
|
||||
- Fixed incomplete console mode initialisation when started in graphics mode
|
||||
- Provided additional UEFI forge mode, for use in firmware drivers
|
||||
- Implemented firmware driver enabling pre-OpenCore graphics on non-natively supported GPUs on EFI-era Macs
|
||||
|
||||
#### v0.8.8
|
||||
- Updated underlying EDK II package to edk2-stable202211
|
||||
|
||||
@ -3723,10 +3723,15 @@ the default boot entry choice will remain changed until the next manual reconfig
|
||||
|
||||
\emph{Note 3}: On Macs with problematic GOP, it may be difficult to re-bless OpenCore if its bless status
|
||||
is lost. The \texttt{BootKicker} utility can be used to work around this problem, if set up as a Tool
|
||||
in OpenCore (e.g. on a CDROM) with \texttt{FullNvramAccess} enabled. It will launch the Apple picker,
|
||||
which allows selection of an item to boot next (with \texttt{Enter}), or next and subsequently, i.e.
|
||||
as the blessed entry (with \texttt{CTRL+Enter}), as normal. After the selection is made, the system
|
||||
will reboot and the chosen entry will be booted.
|
||||
in OpenCore with \texttt{FullNvramAccess} enabled. It will launch the Apple picker,
|
||||
which allows selection of an item to boot next (with \texttt{Enter}), or next and from then on until
|
||||
the next change (with \texttt{CTRL+Enter}). Note that after the selection is made, the system
|
||||
\emph{will reboot} before the chosen entry is booted. While this behaviour might seem surprising,
|
||||
it can be used both to switch which OpenCore installation is blessed, with \texttt{CTRL+Enter},
|
||||
e.g. from a recovery OpenCore installation on CD (selected with the \texttt{C} key on boot) back
|
||||
to the main installion of OpenCore on the hard drive, if this is lost after an NVRAM reset. It can
|
||||
also be used, even when the native picker cannot be shown normally (unsupported GPU), to do a one-shot
|
||||
boot without OpenCore, e.g. to another OS or tool, or to an earlier version of macOS.
|
||||
|
||||
\item
|
||||
\texttt{PickerVariant}\\
|
||||
@ -6355,6 +6360,11 @@ even cause permanent firmware damage. Some of the known drivers are listed below
|
||||
any available writeable filesystem upon pressing \texttt{F10}.
|
||||
This is a modified version of \href{https://github.com/LongSoft/CrScreenshotDxe}{\texttt{CrScreenshotDxe}}
|
||||
driver by \href{https://github.com/NikolajSchlej}{Nikolaj Schlej}. \\
|
||||
\href{https://github.com/acidanthera/OpenCorePkg}{\texttt{EnableGop\{Direct\}}}\textbf{*}
|
||||
& Early beta release firmware-embeddable driver providing pre-OpenCore non-native GPU support
|
||||
on MacPro5,1. Installation instructions can be found in the
|
||||
\href{https://github.com/acidanthera/OpenCorePkg/blob/master/Staging/EnableGop/README.md}{\texttt{Utilities/EnableGop}}
|
||||
directory of the OpenCore release zip file - proceed with caution. \\
|
||||
\href{https://github.com/acidanthera/OcBinaryData}{\texttt{ExFatDxe}}
|
||||
& Proprietary ExFAT file system driver for Bootcamp support commonly found in Apple
|
||||
firmware. For Sandy Bridge and earlier CPUs, the \texttt{ExFatDxeLegacy} driver should be
|
||||
|
||||
@ -6,7 +6,8 @@
|
||||
#ifndef OC_BOOT_MANAGEMENT_LIB_H
|
||||
#define OC_BOOT_MANAGEMENT_LIB_H
|
||||
|
||||
#include <Uefi.h>
|
||||
#include <PiDxe.h>
|
||||
#include <Guid/AppleVariable.h>
|
||||
#include <IndustryStandard/AppleBootArgs.h>
|
||||
#include <IndustryStandard/AppleHid.h>
|
||||
#include <Library/OcAppleBootPolicyLib.h>
|
||||
@ -19,6 +20,8 @@
|
||||
#include <Protocol/LoadedImage.h>
|
||||
#include <Protocol/AppleBeepGen.h>
|
||||
#include <Protocol/OcAudio.h>
|
||||
#include <Protocol/GraphicsOutput.h>
|
||||
#include <Protocol/AppleUserInterface.h>
|
||||
|
||||
#if defined (OC_TARGET_DEBUG) || defined (OC_TARGET_NOOPT)
|
||||
// #define BUILTIN_DEMONSTRATE_TYPING
|
||||
@ -2075,6 +2078,17 @@ OcAddEntriesFromBootEntryProtocol (
|
||||
IN BOOLEAN CreateForHotKey
|
||||
);
|
||||
|
||||
/**
|
||||
Force Apple Firmware UI to always reconnect to current console GOP.
|
||||
|
||||
@retval EFI_SUCCESS Firmware UI ConnectGop method was successfully reset.
|
||||
@retval other Compatible firmware UI protocol for reset could not be found.
|
||||
**/
|
||||
EFI_STATUS
|
||||
OcUnlockAppleFirmwareUI (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Launch Apple boot picker firmware application.
|
||||
|
||||
|
||||
@ -73,11 +73,17 @@ OcPciInfoDump (
|
||||
/**
|
||||
Upgrade UEFI version to 2.x.
|
||||
|
||||
@param[in] Forge If TRUE forge, else just report status.
|
||||
@param[in] Trash If TRUE trash gBS->CreateEventEx directly, else reallocate gBS.
|
||||
Reallocate strategy will only affect current image and any images
|
||||
it loads. Trash strategy should affect all images.
|
||||
|
||||
@retval EFI_SUCCESS on success.
|
||||
**/
|
||||
EFI_STATUS
|
||||
OcForgeUefiSupport (
|
||||
VOID
|
||||
IN BOOLEAN Forge,
|
||||
IN BOOLEAN Trash
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
@ -459,16 +459,30 @@ OcRunBootPicker (
|
||||
}
|
||||
}
|
||||
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
SetPickerEntryReason (
|
||||
IN APPLE_PICKER_ENTRY_REASON PickerEntryReason
|
||||
)
|
||||
{
|
||||
return gRT->SetVariable (
|
||||
APPLE_PICKER_ENTRY_REASON_VARIABLE_NAME,
|
||||
&gAppleVendorVariableGuid,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS,
|
||||
sizeof (PickerEntryReason),
|
||||
&PickerEntryReason
|
||||
);
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
OcRunFirmwareApplication (
|
||||
IN EFI_GUID *ApplicationGuid,
|
||||
IN BOOLEAN SetReason
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_HANDLE NewHandle;
|
||||
EFI_DEVICE_PATH_PROTOCOL *Dp;
|
||||
APPLE_PICKER_ENTRY_REASON PickerEntryReason;
|
||||
EFI_STATUS Status;
|
||||
EFI_HANDLE NewHandle;
|
||||
EFI_DEVICE_PATH_PROTOCOL *Dp;
|
||||
|
||||
DEBUG ((DEBUG_INFO, "OCB: run fw app attempting to find %g...\n", ApplicationGuid));
|
||||
|
||||
@ -493,14 +507,7 @@ OcRunFirmwareApplication (
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
if (SetReason) {
|
||||
PickerEntryReason = ApplePickerEntryReasonUnknown;
|
||||
Status = gRT->SetVariable (
|
||||
APPLE_PICKER_ENTRY_REASON_VARIABLE_NAME,
|
||||
&gAppleVendorVariableGuid,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS,
|
||||
sizeof (PickerEntryReason),
|
||||
&PickerEntryReason
|
||||
);
|
||||
Status = SetPickerEntryReason (ApplePickerEntryReasonUnknown);
|
||||
}
|
||||
|
||||
DEBUG ((
|
||||
@ -524,14 +531,86 @@ OcRunFirmwareApplication (
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Patching prolog of this function works on more similar era firmware
|
||||
// than assuming that mGopAlreadyConnected is located immediately after
|
||||
// protocol interface (which applies on MacPro5,1 v144.0.0.0.0 but not others).
|
||||
//
|
||||
// MacPro5,1 + some iMacs:
|
||||
//
|
||||
// sub rsp, 28h
|
||||
// cmp cs:mGopAlreadyConnected, 0 ///< Ignore offset of this var
|
||||
// jz short loc_10004431
|
||||
// xor eax, eax
|
||||
// jmp short loc_1000446F ///< Change this to no jump
|
||||
//
|
||||
STATIC CONST UINT8 ConnectGopPrologue[] = {
|
||||
0x48, 0x83, 0xEC, 0x28, 0x80, 0x3D, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x74, 0x04, 0x33, 0xC0, 0xEB,
|
||||
0x3E
|
||||
};
|
||||
|
||||
STATIC CONST UINT8 ConnectGopPrologueMask[] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
|
||||
0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF
|
||||
};
|
||||
|
||||
STATIC CONST UINT8 ConnectGopReplace[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00
|
||||
};
|
||||
|
||||
STATIC CONST UINT8 ConnectGopReplaceMask[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF
|
||||
};
|
||||
|
||||
//
|
||||
// iMac11,1:
|
||||
//
|
||||
// push rbx
|
||||
// sub rsp, 30h
|
||||
// cmp cs:byte_100065C8, 0
|
||||
// jz short loc_10004077
|
||||
// xor ebx, ebx
|
||||
// jmp short loc_100040D1
|
||||
//
|
||||
|
||||
STATIC CONST UINT8 AltConnectGopPrologue[] = {
|
||||
0x48, 0x53, 0x48, 0x83, 0xEC, 0x30,
|
||||
0x80, 0x3D, 0x00, 0x00, 0x00, 0x00,0x00,
|
||||
0x74, 0x04, 0x33, 0xDB, 0xEB, 0x5A
|
||||
};
|
||||
|
||||
STATIC CONST UINT8 AltConnectGopPrologueMask[] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
|
||||
};
|
||||
|
||||
STATIC CONST UINT8 AltConnectGopReplace[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
STATIC CONST UINT8 AltConnectGopReplaceMask[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xFF
|
||||
};
|
||||
|
||||
EFI_STATUS
|
||||
OcLaunchAppleBootPicker (
|
||||
OcUnlockAppleFirmwareUI (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
APPLE_FIRMWARE_USER_INTERFACE_PROTOCOL *FirmwareUI;
|
||||
UINT8 *aGopAlreadyConnected;
|
||||
UINT32 ReplaceCount;
|
||||
|
||||
Status = gBS->LocateProtocol (
|
||||
&gAppleFirmwareUserInterfaceProtocolGuid,
|
||||
@ -540,11 +619,11 @@ OcLaunchAppleBootPicker (
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_INFO, "OC: Cannot locate FirmwareUI protocol - %r\n", Status));
|
||||
DEBUG ((DEBUG_INFO, "OCB: Cannot locate FirmwareUI protocol - %r\n", Status));
|
||||
} else if (FirmwareUI->Revision != APPLE_FIRMWARE_USER_INTERFACE_PROTOCOL_REVISION) {
|
||||
DEBUG ((
|
||||
DEBUG_INFO,
|
||||
"OC: Launch Apple picker incompatible FirmwareUI protocol revision %u != %u\n",
|
||||
"OCB: Unlock FirmwareUI incompatible protocol revision %u != %u\n",
|
||||
FirmwareUI->Revision,
|
||||
APPLE_FIRMWARE_USER_INTERFACE_PROTOCOL_REVISION
|
||||
));
|
||||
@ -552,19 +631,63 @@ OcLaunchAppleBootPicker (
|
||||
}
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
//
|
||||
// Location of relevant byte variable within loaded driver.
|
||||
//
|
||||
aGopAlreadyConnected = (VOID *)((UINT8 *)FirmwareUI + sizeof (APPLE_FIRMWARE_USER_INTERFACE_PROTOCOL));
|
||||
ReplaceCount = ApplyPatch (
|
||||
ConnectGopPrologue,
|
||||
ConnectGopPrologueMask,
|
||||
sizeof (ConnectGopPrologue),
|
||||
ConnectGopReplace,
|
||||
ConnectGopReplaceMask,
|
||||
(VOID *)FirmwareUI->ConnectGop,
|
||||
sizeof (ConnectGopPrologue),
|
||||
1,
|
||||
0
|
||||
);
|
||||
|
||||
if (*aGopAlreadyConnected != 1) {
|
||||
DEBUG ((DEBUG_WARN, "OC: Cannot force reconnect Apple GOP %u\n", *aGopAlreadyConnected));
|
||||
} else {
|
||||
*aGopAlreadyConnected = 0;
|
||||
DEBUG ((DEBUG_INFO, "OC: Force reconnect Apple GOP\n"));
|
||||
if (ReplaceCount == 0) {
|
||||
ReplaceCount = ApplyPatch (
|
||||
AltConnectGopPrologue,
|
||||
AltConnectGopPrologueMask,
|
||||
sizeof (AltConnectGopPrologue),
|
||||
AltConnectGopReplace,
|
||||
AltConnectGopReplaceMask,
|
||||
(VOID *)FirmwareUI->ConnectGop,
|
||||
sizeof (AltConnectGopPrologue),
|
||||
1,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
if (ReplaceCount == 0) {
|
||||
Status = EFI_NOT_FOUND;
|
||||
DEBUG ((
|
||||
DEBUG_INFO,
|
||||
"OCB: 0x%016LX 0x%016LX 0x%016LX\n",
|
||||
*((UINT64 *)((UINT8 *)FirmwareUI->ConnectGop)),
|
||||
*((UINT64 *)(((UINT8 *)FirmwareUI->ConnectGop) + 8)),
|
||||
*((UINT64 *)(((UINT8 *)FirmwareUI->ConnectGop) + 16))
|
||||
));
|
||||
}
|
||||
|
||||
DEBUG ((
|
||||
EFI_ERROR (Status) ? DEBUG_WARN : DEBUG_INFO,
|
||||
"OCB: FirmwareUI ConnectGop patch - %r\n",
|
||||
Status
|
||||
));
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
OcLaunchAppleBootPicker (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
OcUnlockAppleFirmwareUI ();
|
||||
|
||||
Status = OcRunFirmwareApplication (&gAppleBootPickerFileGuid, TRUE);
|
||||
|
||||
return Status;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
/** @file
|
||||
Copyright (c) 2020, joevt. All rights reserved.
|
||||
Copyright (C) 2021, vit9696. All rights reserved.
|
||||
Copyright (C) 2021-2023, vit9696, mikebeaton. All rights reserved.
|
||||
|
||||
All rights reserved.
|
||||
|
||||
@ -13,13 +13,14 @@
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
**/
|
||||
|
||||
#include <Uefi.h>
|
||||
#include <PiDxe.h>
|
||||
|
||||
#include <Guid/EventGroup.h>
|
||||
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/DxeServicesTableLib.h>
|
||||
#include <Library/IoLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/OcDeviceMiscLib.h>
|
||||
@ -67,23 +68,46 @@ OcCreateEventEx (
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// The Trash strategy relies on old Apple firmware allocating gBS and gDS consecutively.
|
||||
// This layout is directly inherited from standard edk EFI code.
|
||||
// The strategy trashes the DXE_SERVICES_SIGNATURE value in gDS->Hdr.Signature, which
|
||||
// happily is only used when the memory is being loaded (when we check for references
|
||||
// to DXE_SERVICES_SIGNATURE throughout the edk code).
|
||||
// For the Trash strategy to work, we are required to trash exactly that QWORD of memory,
|
||||
// but in the targeted firmware we can confirm that it is harmless to do so before proceeding.
|
||||
//
|
||||
EFI_STATUS
|
||||
OcForgeUefiSupport (
|
||||
VOID
|
||||
IN BOOLEAN Forge,
|
||||
IN BOOLEAN Trash
|
||||
)
|
||||
{
|
||||
EFI_BOOT_SERVICES *NewBS;
|
||||
|
||||
DEBUG ((
|
||||
DEBUG_INFO,
|
||||
"OCDM: Found 0x%X UEFI version (%u bytes, rebuilding to %u)\n",
|
||||
"OCDM: Found 0x%X/0x%X UEFI version (%u bytes, %u %a to %u) gST %p gBS %p gBS->CreateEventEx %p &gBS %p\n",
|
||||
gST->Hdr.Revision,
|
||||
gBS->Hdr.Revision,
|
||||
gBS->Hdr.HeaderSize,
|
||||
(UINT32)sizeof (EFI_BOOT_SERVICES)
|
||||
Forge,
|
||||
Trash ? "trashing" : "rebuilding",
|
||||
(UINT32)sizeof (EFI_BOOT_SERVICES),
|
||||
gST,
|
||||
gBS,
|
||||
gBS->CreateEventEx,
|
||||
&gBS
|
||||
));
|
||||
|
||||
if (!Forge) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Already too new.
|
||||
// This check will replace any earlier forge to 2.0 <= UEFI < 2.3.
|
||||
// This is desirable in some cases and harmless in others.
|
||||
//
|
||||
if (gST->Hdr.Revision >= EFI_2_30_SYSTEM_TABLE_REVISION) {
|
||||
return EFI_ALREADY_STARTED;
|
||||
@ -93,13 +117,29 @@ OcForgeUefiSupport (
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
NewBS = AllocateZeroPool (sizeof (EFI_BOOT_SERVICES));
|
||||
if (NewBS == NULL) {
|
||||
DEBUG ((DEBUG_INFO, "OCDM: Failed to allocate BS copy\n"));
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
if (Trash) {
|
||||
if ((VOID *)&gBS->CreateEventEx != (VOID *)gDS) {
|
||||
DEBUG ((
|
||||
DEBUG_WARN,
|
||||
"OCDM: Aborting trash strategy, gDS does not follow gBS\n"
|
||||
));
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
CopyMem (NewBS, gBS, gBS->Hdr.HeaderSize);
|
||||
DEBUG ((
|
||||
DEBUG_INFO,
|
||||
"OCDM: Trashing gDS->Hdr.Signature with gBS->CreateEventEx\n"
|
||||
));
|
||||
NewBS = gBS;
|
||||
} else {
|
||||
NewBS = AllocateZeroPool (sizeof (EFI_BOOT_SERVICES));
|
||||
if (NewBS == NULL) {
|
||||
DEBUG ((DEBUG_INFO, "OCDM: Failed to allocate BS copy\n"));
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
CopyMem (NewBS, gBS, gBS->Hdr.HeaderSize);
|
||||
}
|
||||
|
||||
NewBS->CreateEventEx = OcCreateEventEx;
|
||||
NewBS->Hdr.HeaderSize = sizeof (EFI_BOOT_SERVICES);
|
||||
@ -113,5 +153,10 @@ OcForgeUefiSupport (
|
||||
gST->Hdr.CRC32 = 0;
|
||||
gST->Hdr.CRC32 = CalculateCrc32 (gST, gST->Hdr.HeaderSize);
|
||||
|
||||
if (Trash) {
|
||||
gDS->Hdr.CRC32 = 0;
|
||||
gDS->Hdr.CRC32 = CalculateCrc32 (gDS, gDS->Hdr.HeaderSize);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
@ -62,6 +62,7 @@
|
||||
PrintLib
|
||||
UefiLib
|
||||
UefiBootServicesTableLib
|
||||
DxeServicesTableLib
|
||||
|
||||
[Sources]
|
||||
ActivateHpetSupport.c
|
||||
|
||||
@ -939,9 +939,7 @@ OcLoadUefiSupport (
|
||||
OcInstallPermissiveSecurityPolicy ();
|
||||
}
|
||||
|
||||
if (Config->Uefi.Quirks.ForgeUefiSupport) {
|
||||
OcForgeUefiSupport ();
|
||||
}
|
||||
OcForgeUefiSupport (Config->Uefi.Quirks.ForgeUefiSupport, FALSE);
|
||||
|
||||
if (Config->Uefi.Quirks.ReloadOptionRoms) {
|
||||
OcReloadOptionRoms ();
|
||||
|
||||
@ -744,6 +744,12 @@
|
||||
## @Prompt Use Pin Capabilities to identify audio outputs.
|
||||
gOpenCorePkgTokenSpaceGuid.PcdAudioControllerUsePinCapsForOutputs|TRUE|BOOLEAN|0x00000008
|
||||
|
||||
## Indicates whether to build EnableGop driver with DirectGopRendering.<BR><BR>
|
||||
## TRUE - DirectGopRendering will be used.<BR>
|
||||
## FALSE - DirectGopRendering will not be used.<BR>
|
||||
## @Prompt Use DirectGopRendering.
|
||||
gOpenCorePkgTokenSpaceGuid.PcdEnableGopDirect|FALSE|BOOLEAN|0x00000009
|
||||
|
||||
[PcdsFixedAtBuild]
|
||||
## Defines the Console Control initialization mode set on entry.<BR><BR>
|
||||
## 0 - EfiConsoleControlScreenText<BR>
|
||||
|
||||
@ -22,6 +22,7 @@
|
||||
BUILD_TARGETS = RELEASE|DEBUG|NOOPT
|
||||
SKUID_IDENTIFIER = DEFAULT
|
||||
DSC_SPECIFICATION = 0x00010006
|
||||
FLASH_DEFINITION = OpenCorePkg/OpenCorePkg.fdf
|
||||
|
||||
#
|
||||
# Network definition
|
||||
@ -319,6 +320,14 @@
|
||||
OpenCorePkg/Platform/ResetNvramEntry/ResetNvramEntry.inf
|
||||
OpenCorePkg/Platform/ToggleSipEntry/ToggleSipEntry.inf
|
||||
OpenCorePkg/Staging/AudioDxe/AudioDxe.inf
|
||||
OpenCorePkg/Staging/EnableGop/EnableGop.inf {
|
||||
<LibraryClasses>
|
||||
DebugLib|OpenCorePkg/Library/OcDebugLibNull/OcDebugLibNull.inf
|
||||
}
|
||||
OpenCorePkg/Staging/EnableGop/EnableGopDirect.inf {
|
||||
<LibraryClasses>
|
||||
DebugLib|OpenCorePkg/Library/OcDebugLibNull/OcDebugLibNull.inf
|
||||
}
|
||||
OpenCorePkg/Staging/OpenHfsPlus/OpenHfsPlus.inf
|
||||
OpenCorePkg/Tests/AcpiTest/AcpiTest.inf
|
||||
OpenCorePkg/Tests/AcpiTest/AcpiTestApp.inf
|
||||
|
||||
105
OpenCorePkg.fdf
Normal file
105
OpenCorePkg.fdf
Normal file
@ -0,0 +1,105 @@
|
||||
## @file
|
||||
# Compile standalone firmware filesystem files.
|
||||
#
|
||||
# Copyright (C) 2022-2023, Mike Beaton. All rights reserved.<BR>
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
##
|
||||
|
||||
#
|
||||
# For now disable non-64-bit build; Mac Pro cannot use it, and EDK-II
|
||||
# build system does not separate 64 bit and 32 bit .ffs files, which
|
||||
# we want to distribute.
|
||||
#
|
||||
# If we needed all archs in future we could distribute the complete
|
||||
# .fv files, from which the .ffs can be re-extracted.
|
||||
#
|
||||
!if ($(ARCH) == X64)
|
||||
|
||||
!if ($(ARCH) == X64)
|
||||
[FV.FfsFilesX64]
|
||||
!else
|
||||
[FV.FfsFilesIA32]
|
||||
!endif
|
||||
|
||||
BlockSize = 0x10000
|
||||
NumBlocks = 8
|
||||
FvAlignment = 16 #FV alignment and FV attributes setting.
|
||||
ERASE_POLARITY = 1
|
||||
MEMORY_MAPPED = TRUE
|
||||
STICKY_WRITE = TRUE
|
||||
LOCK_CAP = TRUE
|
||||
LOCK_STATUS = TRUE
|
||||
WRITE_DISABLED_CAP = TRUE
|
||||
WRITE_ENABLED_CAP = TRUE
|
||||
WRITE_STATUS = TRUE
|
||||
WRITE_LOCK_CAP = TRUE
|
||||
WRITE_LOCK_STATUS = TRUE
|
||||
READ_DISABLED_CAP = TRUE
|
||||
READ_ENABLED_CAP = TRUE
|
||||
READ_STATUS = TRUE
|
||||
READ_LOCK_CAP = TRUE
|
||||
READ_LOCK_STATUS = TRUE
|
||||
|
||||
#
|
||||
# DXE Drivers (other .inf files for conversion to .ffs may be added here)
|
||||
#
|
||||
INF OpenCorePkg/Staging/EnableGop/EnableGop.inf
|
||||
|
||||
!if ($(ARCH) == X64)
|
||||
[FV.EnableGopDirectX64]
|
||||
!else
|
||||
[FV.EnableGopDirectIA32]
|
||||
!endif
|
||||
|
||||
BlockSize = 0x10000
|
||||
NumBlocks = 8
|
||||
FvAlignment = 16 #FV alignment and FV attributes setting.
|
||||
ERASE_POLARITY = 1
|
||||
MEMORY_MAPPED = TRUE
|
||||
STICKY_WRITE = TRUE
|
||||
LOCK_CAP = TRUE
|
||||
LOCK_STATUS = TRUE
|
||||
WRITE_DISABLED_CAP = TRUE
|
||||
WRITE_ENABLED_CAP = TRUE
|
||||
WRITE_STATUS = TRUE
|
||||
WRITE_LOCK_CAP = TRUE
|
||||
WRITE_LOCK_STATUS = TRUE
|
||||
READ_DISABLED_CAP = TRUE
|
||||
READ_ENABLED_CAP = TRUE
|
||||
READ_STATUS = TRUE
|
||||
READ_LOCK_CAP = TRUE
|
||||
READ_LOCK_STATUS = TRUE
|
||||
|
||||
#
|
||||
# DXE Drivers
|
||||
#
|
||||
|
||||
#
|
||||
# EnableGopDirect intentionally has the same GUID as EnableGop, so it must go in a separate FV.
|
||||
# (We don't care about the FV, rather the intermediate FFS files which are generated during build.)
|
||||
#
|
||||
INF OpenCorePkg/Staging/EnableGop/EnableGopDirect.inf
|
||||
|
||||
!endif
|
||||
|
||||
#
|
||||
# Ideally we would match the compressed layout of DXE drivers in Mac Pro 144.0.0.0.0 firmware,
|
||||
# as per the commented out lines, but Mac Pro will not load this with standard compression.
|
||||
# With lines commented out we make a different, non-compressed layout which the Mac Pro will load.
|
||||
#
|
||||
# TODO: Is there a way to make a Tiano-compressed COMPRESS section, as in Mac Pro firmware, using
|
||||
# EDK-II build tools? If we manually reconstuct one with UEFITool 0.25.1, Mac Pro will load it.
|
||||
#
|
||||
# Note: `GUIDED A31280AD-481E-41B6-95E8-127F4C984779` will make a Tiano compressed GUIDED
|
||||
# section, but this is different and 144.0.0.0.0 will not load it.
|
||||
#
|
||||
[Rule.Common.DXE_DRIVER]
|
||||
FILE DRIVER = $(NAMED_GUID) Checksum {
|
||||
# COMPRESS {
|
||||
# GUIDED {
|
||||
DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
|
||||
PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi
|
||||
UI STRING="$(MODULE_NAME)" Optional
|
||||
# }
|
||||
# }
|
||||
}
|
||||
132
Staging/EnableGop/EnableGop.c
Normal file
132
Staging/EnableGop/EnableGop.c
Normal file
@ -0,0 +1,132 @@
|
||||
/** @file
|
||||
Provide GOP on unsupported graphics cards on EFI-era MacPro and iMac.
|
||||
|
||||
Copyright (c) 2022-2023, Mike Beaton. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
**/
|
||||
|
||||
#include <Uefi.h>
|
||||
|
||||
#include <Library/DxeServicesTableLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||
|
||||
#include <Library/OcBootManagementLib.h>
|
||||
#include <Library/OcConsoleLib.h>
|
||||
#include <Library/OcDeviceMiscLib.h>
|
||||
|
||||
STATIC EFI_GET_MEMORY_SPACE_MAP mOriginalGetMemorySpaceMap;
|
||||
|
||||
//
|
||||
// Equivalent to a very cut down OcLoadUefiOutputSupport.
|
||||
//
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
LoadUefiOutputSupport (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
Status = OcProvideConsoleGop (FALSE);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
OcSetConsoleResolution (
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
FALSE
|
||||
);
|
||||
|
||||
if (FeaturePcdGet (PcdEnableGopDirect)) {
|
||||
OcUseDirectGop (-1);
|
||||
}
|
||||
|
||||
OcSetupConsole (
|
||||
OcConsoleRendererBuiltinGraphics,
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE,
|
||||
FALSE
|
||||
);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
ProvideGop (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
OcUnlockAppleFirmwareUI ();
|
||||
|
||||
return LoadUefiOutputSupport ();
|
||||
}
|
||||
|
||||
//
|
||||
// This memory map access happens twice during PlatformBdsPolicyBehavior, once
|
||||
// in the equivalent of efi InitializeMemoryTest at the start of the function,
|
||||
// and once during PlatformBdsDiagnostics, slightly later. The second call(s)
|
||||
// (there is more than one code path, depending on the boot type) are after
|
||||
// the default console has been connected, and therefore ideal for us.
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
WrappedGetMemorySpaceMap (
|
||||
OUT UINTN *NumberOfDescriptors,
|
||||
OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR **MemorySpaceMap
|
||||
)
|
||||
{
|
||||
STATIC UINTN mGetMemorySpaceMapAccessCount = 0;
|
||||
|
||||
mGetMemorySpaceMapAccessCount++;
|
||||
|
||||
if (mGetMemorySpaceMapAccessCount == 2) {
|
||||
ProvideGop ();
|
||||
}
|
||||
|
||||
return mOriginalGetMemorySpaceMap (
|
||||
NumberOfDescriptors,
|
||||
MemorySpaceMap
|
||||
);
|
||||
}
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
WrapGetMemorySpaceMap (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
mOriginalGetMemorySpaceMap = gDS->GetMemorySpaceMap;
|
||||
gDS->GetMemorySpaceMap = WrappedGetMemorySpaceMap;
|
||||
|
||||
gDS->Hdr.CRC32 = 0;
|
||||
gBS->CalculateCrc32 (gDS, gDS->Hdr.HeaderSize, &gDS->Hdr.CRC32);
|
||||
}
|
||||
|
||||
//
|
||||
// If we execute the entire console setup at Driver#### time then we have to forge UEFI, reload option ROMs
|
||||
// and connect them, all at that point.
|
||||
// This works on some systems but causes crashes others, or causes an empty picker with question mark folder.
|
||||
// Current strategy is:
|
||||
// - Forge UEFI early; relatively easy: just do it immediately, as below, and insert this driver either
|
||||
// a) anywhere in main firmware volume, or b) in VBIOS anywhere before GOP driver which needs it
|
||||
// - Execute rest of payload after option roms have been loaded, _and_ after firmware has already connected
|
||||
// them (see WrapGetMemorySpaceMap strategy above).
|
||||
// With this strategy we do not need to reload or reconnect any option ROMs, which is much more stable.
|
||||
//
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UefiMain (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
OcForgeUefiSupport (TRUE, TRUE);
|
||||
WrapGetMemorySpaceMap ();
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
46
Staging/EnableGop/EnableGop.inf
Normal file
46
Staging/EnableGop/EnableGop.inf
Normal file
@ -0,0 +1,46 @@
|
||||
## @file
|
||||
#
|
||||
# Provide GOP on unsupported graphics cards on EFI-era MacPro and iMac.
|
||||
#
|
||||
# Copyright (c) 2022-2023, Mike Beaton. All rights reserved.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = EnableGop
|
||||
FILE_GUID = 3FBA58B1-F8C0-41BC-ACD8-253043A3A17F
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
ENTRY_POINT = UefiMain
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64
|
||||
#
|
||||
|
||||
[Sources]
|
||||
EnableGop.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
OpenCorePkg/OpenCorePkg.dec
|
||||
UefiCpuPkg/UefiCpuPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
DxeServicesTableLib
|
||||
OcBootManagementLib
|
||||
OcConsoleLib
|
||||
OcDeviceMiscLib
|
||||
UefiBootServicesTableLib
|
||||
UefiDriverEntryPoint
|
||||
UefiRuntimeServicesTableLib
|
||||
|
||||
[FeaturePcd]
|
||||
gOpenCorePkgTokenSpaceGuid.PcdEnableGopDirect|FALSE
|
||||
|
||||
[Depex]
|
||||
TRUE
|
||||
46
Staging/EnableGop/EnableGopDirect.inf
Normal file
46
Staging/EnableGop/EnableGopDirect.inf
Normal file
@ -0,0 +1,46 @@
|
||||
## @file
|
||||
#
|
||||
# Provide GOP on unsupported graphics cards on EFI-era MacPro and iMac using DirectGopRendering.
|
||||
#
|
||||
# Copyright (c) 2023, Mike Beaton. All rights reserved.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = EnableGopDirect
|
||||
FILE_GUID = 3FBA58B1-F8C0-41BC-ACD8-253043A3A17F
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
ENTRY_POINT = UefiMain
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64
|
||||
#
|
||||
|
||||
[Sources]
|
||||
EnableGop.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
OpenCorePkg/OpenCorePkg.dec
|
||||
UefiCpuPkg/UefiCpuPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
DxeServicesTableLib
|
||||
OcBootManagementLib
|
||||
OcConsoleLib
|
||||
OcDeviceMiscLib
|
||||
UefiBootServicesTableLib
|
||||
UefiDriverEntryPoint
|
||||
UefiRuntimeServicesTableLib
|
||||
|
||||
[FeaturePcd]
|
||||
gOpenCorePkgTokenSpaceGuid.PcdEnableGopDirect|TRUE
|
||||
|
||||
[Depex]
|
||||
TRUE
|
||||
117
Staging/EnableGop/NvInsertEfi.sh
Executable file
117
Staging/EnableGop/NvInsertEfi.sh
Executable file
@ -0,0 +1,117 @@
|
||||
#!/bin/bash
|
||||
|
||||
#
|
||||
# Copyright © 2023 Mike Beaton. All rights reserved.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
# Insert EFI into Nvidia VBIOS.
|
||||
#
|
||||
# TODO: Check that original GOP is present, and locate it in the original file automatically.
|
||||
#
|
||||
|
||||
usage() {
|
||||
echo "Usage: ./${SELFNAME} {rom-file} {efi-file} {GOP offset} {out-file}"
|
||||
echo "E.g.:"
|
||||
echo " ./${SELFNAME} nv.rom GOP.efi 0xFC00 mod.rom"
|
||||
echo " ./${SELFNAME} nv.rom GOP.efi 64512 mod.rom"
|
||||
echo ""
|
||||
}
|
||||
|
||||
SELFNAME="$(/usr/bin/basename "${0}")"
|
||||
|
||||
if [ "$#" -ne 4 ] ; then
|
||||
usage
|
||||
exit 0
|
||||
fi
|
||||
|
||||
commands=(
|
||||
"EfiRom"
|
||||
"UEFIRomExtract"
|
||||
)
|
||||
FOUND=1
|
||||
for command in "${commands[@]}"; do
|
||||
if ! command -v "$command" 1>/dev/null ; then
|
||||
echo "${command} not available!"
|
||||
FOUND=0
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$FOUND" -eq 0 ] ; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ROM_FILE="$1"
|
||||
EFI_FILE="$2"
|
||||
GOP_OFFSET="$3"
|
||||
OUT_FILE="$4"
|
||||
|
||||
# https://unix.stackexchange.com/a/84980/340732
|
||||
tmpdir=$(mktemp -d 2>/dev/null || mktemp -d -t 'vbios') || exit 1
|
||||
|
||||
echo "Splitting original ROM..."
|
||||
|
||||
dd bs=1 if="$ROM_FILE" of="$tmpdir/original_first_part.rom" count=$(($GOP_OFFSET)) status=none || exit 1
|
||||
dd bs=1 if="$ROM_FILE" of="$tmpdir/original_last_part.rom" skip=$(($GOP_OFFSET)) status=none || exit 1
|
||||
|
||||
echo "Compressing ${EFI_FILE} using EfiRom..."
|
||||
EfiRom -o "$tmpdir/insert.rom" -ec "$EFI_FILE" -f 0xAAAA -i 0xBBBB -l 0x30000 || exit 1
|
||||
|
||||
echo "Adding Nvidia header..."
|
||||
dd bs=1 if="$tmpdir/insert.rom" of="$tmpdir/insert_first_part" count=$((0x38)) status=none || exit 1
|
||||
dd bs=1 if="$tmpdir/insert.rom" of="$tmpdir/insert_last_part" skip=$((0x38)) status=none || exit 1
|
||||
|
||||
INSERT_SIZE=$(stat -f%z "$tmpdir/insert.rom") || exit 1
|
||||
|
||||
# add NPDE from original GOP
|
||||
dd bs=1 if="$tmpdir/original_last_part.rom" of="$tmpdir/insert_first_part" skip=$((0x38)) seek=$((0x38)) count=$((0x18)) status=none || exit 1
|
||||
cat "$tmpdir/insert_first_part" "$tmpdir/insert_last_part" > "$tmpdir/insert_oversize.rom" || exit 1
|
||||
# `truncate` not present by default on macOS
|
||||
dd bs=1 if="$tmpdir/insert_oversize.rom" of="$tmpdir/insert_fixed.rom" count="$INSERT_SIZE" status=none || exit 1
|
||||
|
||||
# patch size in NPDE
|
||||
dd bs=1 if="$tmpdir/insert.rom" of="$tmpdir/insert_fixed.rom" skip=$((0x2)) seek=$((0x48)) count=1 conv=notrunc status=none || exit 1
|
||||
|
||||
# patch with vendor and device id from original GOP
|
||||
dd bs=1 if="$tmpdir/original_last_part.rom" of="$tmpdir/insert_fixed.rom" skip=$((0x20)) seek=$((0x20)) count=4 conv=notrunc status=none || exit 1
|
||||
|
||||
# patch size in PCIR
|
||||
dd bs=1 if="$tmpdir/original_last_part.rom" of="$tmpdir/insert_fixed.rom" skip=$((0x16)) seek=$((0x16)) count=1 conv=notrunc status=none || exit 1
|
||||
|
||||
# patch end marker in NPDE in fixed ROM (leave PCIR correct and EFI extractable from fixed ROM)
|
||||
echo -n -e '\x00' | dd bs=1 of="$tmpdir/insert_fixed.rom" seek=$((0x4A)) conv=notrunc status=none || exit 1
|
||||
|
||||
echo "Writing ${OUT_FILE}..."
|
||||
cat "$tmpdir/original_first_part.rom" "$tmpdir/insert_fixed.rom" "$tmpdir/original_last_part.rom" > "$OUT_FILE" || exit 1
|
||||
|
||||
# patch end marker in PCIR in out file
|
||||
echo -n -e '\x00' | dd bs=1 of="$OUT_FILE" seek=$(($GOP_OFFSET + 0x31)) conv=notrunc status=none || exit 1
|
||||
|
||||
echo "Verifying ${OUT_FILE}..."
|
||||
dd bs=1 if="$OUT_FILE" of="$tmpdir/out_efi_part.rom" skip=$(($GOP_OFFSET)) status=none || exit 1
|
||||
UEFIRomExtract "$tmpdir/out_efi_part.rom" "$tmpdir/extracted.efi" 1>/dev/null || exit 1
|
||||
ERROR=0
|
||||
diff "$tmpdir/extracted.efi" "$EFI_FILE" 1>/dev/null || ERROR=1
|
||||
|
||||
if [ "$ERROR" -ne 0 ] ; then
|
||||
echo " - Failure comparing extracted EFI to original!"
|
||||
fi
|
||||
|
||||
OLD_EFI_COUNT=$(EfiRom -d "$tmpdir/original_last_part.rom" | grep "0x0EF1" | wc -l) || exit 1
|
||||
OLD_EFI_COUNT=$(($OLD_EFI_COUNT)) || exit 1
|
||||
|
||||
NEW_EFI_COUNT=$(EfiRom -d "$tmpdir/out_efi_part.rom" | grep "0x0EF1" | wc -l) || exit 1
|
||||
NEW_EFI_COUNT=$(($NEW_EFI_COUNT)) || exit 1
|
||||
|
||||
if [ "$NEW_EFI_COUNT" -ne $(($OLD_EFI_COUNT + 1)) ] ; then
|
||||
echo " - Found ${NEW_EFI_COUNT} EFI parts, expected $(($OLD_EFI_COUNT + 1))!"
|
||||
fi
|
||||
|
||||
if [ "$ERROR" -eq 0 ] ; then
|
||||
echo "SUCCESS."
|
||||
else
|
||||
echo "*** WARNING - FAIL ***"
|
||||
fi
|
||||
|
||||
rm -rf "$tmpdir" || exit 1
|
||||
|
||||
echo "Done."
|
||||
154
Staging/EnableGop/README.md
Normal file
154
Staging/EnableGop/README.md
Normal file
@ -0,0 +1,154 @@
|
||||
# Provides standalone GOP driver for EFI era Mac Pro and iMac
|
||||
|
||||
## Status
|
||||
**Current status: Early beta release.**
|
||||
|
||||
This driver has been tested and is working on several iMac models
|
||||
with several different GPUs, and on several MacPro4,1/5,1 machines with several different GPUs. However, in the worst
|
||||
case (and still quite possible) scenario, an incompatible or incorrectly installed driver
|
||||
in firmware may brick your hardware.
|
||||
|
||||
*In all cases take a backup of the main firmware or VBIOS firmware which you are modifying, and confirm that
|
||||
you can successfully restore from this, before starting.*
|
||||
|
||||
## Recovery from bricked hardware
|
||||
- If attempting firmware insertion on a MacPro4,1/5,1, for recovery from a bricked device you will either
|
||||
need a Matt card (which may breach intellectual property laws in some jurisdictions) or the ability to
|
||||
desolder and reprogram your own NVRAM chip.
|
||||
- If testing via firmware insertion on an iMac, you will need the ability to disassemble your iMac and
|
||||
reprogram its NVRAM chip using a SOIC clip attached to a CH341A controller running on another computer.
|
||||
- If testing via VBIOS insertion (iMac or Mac Pro), you will need the ability to disassemble your system,
|
||||
likely remove the heat sink from the graphics card, and then reprogram its NVRAM chip using a SOIC
|
||||
clip attached to a CH341A controller running on another computer.
|
||||
- If testing via VBIOS insertion, in some cases it may also be possible
|
||||
to use physical electrical connection to your GPU NVRAM chip in order to boot with no graphics, then connect
|
||||
to your machine with `ssh` (which must have been enabled beforehand) and reprogram the GPU NVRAM. Advice on
|
||||
this is not provided here, but may be found for instance on the iMac GPU related forum threads listed below.
|
||||
|
||||
*If you are not familiar with the above procedures, you are strongly recommended to wait for further testing by
|
||||
users who are. No further help can be provided here, and you proceed entirely at your own risk.*
|
||||
|
||||
## Summary
|
||||
Targetting EFI-era (~2009-2012) MacPro4,1/5,1 and iMac firmware, this driver gathers and injects the parts of
|
||||
OpenCore needed for pre-boot graphics support with non-natively supported GPUs.
|
||||
|
||||
The requirements for using this driver are:
|
||||
|
||||
- EFI-era (~2009-2012) MacPro4,1/5,1 or iMac with most recent firmware.
|
||||
- A GPU which does not produce native pre-boot graphics (such as native picker when pressing ALT key during boot)
|
||||
before OpenCore starts (otherwise, you do not need it).
|
||||
- A GPU which produces graphics when using OpenCore (this must include successfully showing the native Apple boot
|
||||
picker when started via the latest version of OpenCore tool `BootKicker.efi`) (otherwise, the driver will not work).
|
||||
- *Note*: If your OpenCore installation includes a required GOP driver for your graphics card (this is added
|
||||
automatically on some systems by recent versions of OpenCore Legacy Patcher, as a way to enable OpenCore menu
|
||||
in cards such as ex-mining GPUs), then you would also need to burn that driver to the VBIOS of your graphics
|
||||
card in order to obtain pre-OpenCore graphics; instructions for this are outside the scope of this tutorial,
|
||||
although the procedures required for modifying VBIOS are similar to what is covered here.
|
||||
|
||||
When installed, the driver should enable:
|
||||
|
||||
- Native boot picker via ALT key
|
||||
- Firmware password UI
|
||||
- Target disk mode UI
|
||||
- macOS boot progress screen
|
||||
- etc.
|
||||
|
||||
Compiled versions of the driver files and these instructions may be found in the `Utilities/EnableGop`
|
||||
directory of the OpenCore release package.
|
||||
|
||||
For GPUs needing `DirectGopRendering` in OpenCore configuration, use `EnableGopDirect.efi`, otherwise use `EnableGop.efi`
|
||||
as it renders faster on most other systems.
|
||||
|
||||
The driver may be installed to VBIOS or to main firmware. It is expected that most Mac Pro users will use firmware insertion
|
||||
and most iMac users will chose VBIOS insertion, however both techniques work on both systems (but it is harder to modify the
|
||||
iMac firmware).
|
||||
|
||||
## Usage
|
||||
|
||||
## Install to firmware
|
||||
|
||||
For reading and writing to firmware on the Mac Pro, @Macschrauber's [Rom Dump](https://www.youtube.com/watch?v=q4NW00oyUKE) works
|
||||
well. Alternatively the kexts and executables which this uses can be sourced individually (or extracted from the Rom Dump app) and
|
||||
run from the command line.
|
||||
|
||||
The firmware on the iMac cannot be updated without an initial hardware flash (SOIC clip plus CH341A controller), therefore
|
||||
the recommended approach on iMac systems is [VBIOS injection](#install-to-vbios). However, the below instructions for firmware
|
||||
injection do work, if you are willing to do a hardware flash of the resulting firmware file, or if you have already
|
||||
[unprotected your iMac firmware](https://forums.macrumors.com/threads/imac-2011-see-more-uefi-firmware-mod.2257435/page-3?post=31087001#post-31087001) -
|
||||
which reduces security, and is only recommended for those actively developing firmware modifications.
|
||||
|
||||
The `.ffs` file provided in this directory can be manually added to the extracted firmware file using [`UEFITool`](https://github.com/LongSoft/UEFITool),
|
||||
or automatically added using @dosdude1's [`DXEInject`](https://dosdude1.com/apps/). Once more, if you are not familiar with these procedures,
|
||||
you are recommended to proceed with extreme caution.
|
||||
|
||||
### Using DXEInject
|
||||
|
||||
To install the driver via `DXEInject`, the command is:
|
||||
|
||||
- `DXEInject {original}.rom {modified}.rom EnableGop.ffs`
|
||||
|
||||
The file `{modifed}.rom` is ready for burning, although the result can be checked using UEFITool, if required.
|
||||
|
||||
> *Note*: If only reading a file with UEFITool, the latest version is recommended, as it provides the most information.
|
||||
For writing, the older version 0.25.1 must be used, as described below.
|
||||
|
||||
### Using UEFITool
|
||||
|
||||
The `.ffs` file may be inserted anywhere within the same firmware volume which contains `DuetBds`
|
||||
(file GUID `A6F691AC-31C8-4444-854C-E2C1A6950F92`). However, for simplicity, these instructions
|
||||
will insert it in the same place that `DXEInject` does:
|
||||
|
||||
- Use UEFITool 0.25.1 (it must be that old version, not the newer NE or new engine versions, which
|
||||
cannot yet edit)
|
||||
- Perform a header-only GUID search for `BAE7599F-3C6B-43B7-BDF0-9CE07AA91AA6`
|
||||
- Double-click on the search result
|
||||
- Right-click on the DXE driver with that GUID which should then appear
|
||||
- Choose "Insert after..." and select `EnableGop.ffs`
|
||||
- Save the modified firmware
|
||||
|
||||
The end result, after saving and re-loading, should look like this:
|
||||
|
||||
<img src="UEFITool_Inserted_Screenshot.png">
|
||||
|
||||
## Install to VBIOS
|
||||
|
||||
Instructions and a script for inserting the driver into NVidia VBIOS are provided.
|
||||
Similar techniques are appropriate for AMD GPUs.
|
||||
|
||||
For further information on VBIOS modification, see:
|
||||
|
||||
- https://forums.macrumors.com/threads/2011-imac-graphics-card-upgrade.1596614/
|
||||
- https://forums.macrumors.com/threads/imac-2011-maxwell-and-pascal-gpu-upgrade.2300989/
|
||||
- https://github.com/Ausdauersportler/IMAC-EFI-BOOT-SCREEN/wiki
|
||||
- https://winraid.level1techs.com/t/amd-and-nvidia-gop-update-no-requests-diy/30917
|
||||
|
||||
### Nvidia
|
||||
|
||||
To use the provided `NvInsertEfi.sh` script:
|
||||
|
||||
- Locate an appropriate version of the `nvflash` tool (avilable for Linux and Windows), which can be used to read
|
||||
from and write to your Nvidia GPU VBIOS.
|
||||
- Use `nvflash` to read a copy of your VBIOS.
|
||||
- Using a hex editor, search in the VBIOS for the byte sequence `F1 0E 00 00` with the byte sequence `55 AA` coming
|
||||
close before it; the start address of the `55 AA` is the value needed for the insertion offset in the next step.
|
||||
- Run `./NvInsertEfi.Sh {original}.rom EnableGop.ffs {offset} {modified}/.rom`.
|
||||
- Only if you modified a rom file obtained via `flashrom` rather than `nvflash`, you should manually truncate
|
||||
the modified file's size to the original file's size at this point. (`nvflash` files only contain the used section
|
||||
of the VBIOS, and therefore must not be truncated.)
|
||||
- The new file `{modified}.rom` may be burnt to the VBIOS firmware.
|
||||
|
||||
Please note all the cautions already given above about the difficulty of recovering, unless you are familiar with
|
||||
the procedures necessary, if this process fails.
|
||||
|
||||
### AMD
|
||||
|
||||
Similar procedures as for Nvidia apply.
|
||||
|
||||
- Further assistance and information may be available in the forums and pages listed above.
|
||||
|
||||
## No longer supported: Install as Driver#### entry
|
||||
|
||||
Early test versions of this driver included code to allow it to work when installed as a `Driver####` entry
|
||||
(`Driver####` entries do work when installed via `bcfg` and using MacPro4,1/5,1 firmware; they do not work on
|
||||
that firmware if using `efibootmgr`, and they are not supported by iMac firmware). This code has been removed
|
||||
in order to minimise the driver size for VBIOS insertion.
|
||||
BIN
Staging/EnableGop/UEFITool_Inserted_Screenshot.png
Normal file
BIN
Staging/EnableGop/UEFITool_Inserted_Screenshot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 692 KiB |
@ -1,8 +1,11 @@
|
||||
Staging drivers considered experimental and not production ready.
|
||||
|
||||
## OpenHfsPlus
|
||||
This driver implements HFS+ support with bless extensions.
|
||||
|
||||
## AudioDxe
|
||||
Improved audio driver (currently only Intel HD audio).
|
||||
HDMI or other digital outputs don't work.
|
||||
|
||||
## EnableGop
|
||||
Standalone firmware-embeddable driver for non-native GPU support on EFI-era Mac Pro and iMac.
|
||||
|
||||
## OpenHfsPlus
|
||||
This driver implements HFS+ support with bless extensions.
|
||||
|
||||
@ -249,6 +249,32 @@ package() {
|
||||
fi
|
||||
done
|
||||
|
||||
# Copy Mac Pro GOP firmware driver.
|
||||
mkdir -p "${dstdir}/Utilities/EnableGop" || exit 1
|
||||
ENABLE_GOP_GUID="3FBA58B1-F8C0-41BC-ACD8-253043A3A17F"
|
||||
ffsNames=(
|
||||
"EnableGop"
|
||||
"EnableGopDirect"
|
||||
)
|
||||
for ffsName in "${ffsNames[@]}"; do
|
||||
cp "FV/Ffs/${ENABLE_GOP_GUID}${ffsName}/${ENABLE_GOP_GUID}.ffs" "${dstdir}/Utilities/EnableGop/${ffsName}.ffs" || exit 1
|
||||
done
|
||||
gopDrivers=(
|
||||
"EnableGop.efi"
|
||||
"EnableGopDirect.efi"
|
||||
)
|
||||
for file in "${gopDrivers[@]}"; do
|
||||
cp "X64/${file}" "${dstdir}/Utilities/EnableGop"/ || exit 1
|
||||
done
|
||||
helpFiles=(
|
||||
"README.md"
|
||||
"UEFITool_Inserted_Screenshot.png"
|
||||
"NvInsertEfi.sh"
|
||||
)
|
||||
for file in "${helpFiles[@]}"; do
|
||||
cp "${selfdir}/Staging/EnableGop/${file}" "${dstdir}/Utilities/EnableGop"/ || exit 1
|
||||
done
|
||||
|
||||
utils=(
|
||||
"ACPIe"
|
||||
"acdtinfo"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user