diff --git a/Changelog.md b/Changelog.md
index 3e85e2a6..22aa5341 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -10,6 +10,7 @@ OpenCore Changelog
- Added XCPM CPU power management ACPI table for Intel Alder Lake
- Updated draw order to avoid graphics tearing in OpenCanopy
- Fixed handling PCI device paths with logical units in ScanPolicy
+- Added `ReconnectGraphicsOnConnect` option for enabling alternative UEFI graphics drivers
#### v0.7.5
- Revised OpenLinuxBoot documentation
diff --git a/Docs/Configuration.tex b/Docs/Configuration.tex
index 5b084e70..14510201 100755
--- a/Docs/Configuration.tex
+++ b/Docs/Configuration.tex
@@ -7338,6 +7338,19 @@ with the boot menu.
\emph{Note}: This option will also replace incompatible implementations of GOP on the
console handle, as may be the case on the \texttt{MacPro5,1} when using modern GPUs.
+\item
+ \texttt{ReconnectGraphicsOnConnect}\\
+ \textbf{Type}: \texttt{plist\ boolean}\\
+ \textbf{Failsafe}: \texttt{false}\\
+ \textbf{Description}: Reconnect all graphics drivers during driver connection.
+
+ On certain firmware, it may be desireable to use an alternative graphics driver
+ providing better screen resolution options on legacy machines, or a driver supporting
+ \texttt{ForceResolution}. This option attempts to disconnect all currently connected
+ graphics drivers before connecting newly loaded drivers.
+
+ \emph{Note}: This option requires \texttt{ConnectDrivers} to be enabled.
+
\item
\texttt{ReconnectOnResChange}\\
\textbf{Type}: \texttt{plist\ boolean}\\
diff --git a/Docs/Sample.plist b/Docs/Sample.plist
index 2430b30f..a43ace5f 100644
--- a/Docs/Sample.plist
+++ b/Docs/Sample.plist
@@ -1500,6 +1500,8 @@
ProvideConsoleGop
+ ReconnectGraphicsOnConnect
+
ReconnectOnResChange
ReplaceTabWithSpace
diff --git a/Docs/SampleCustom.plist b/Docs/SampleCustom.plist
index 839dfc3c..e4992f04 100644
--- a/Docs/SampleCustom.plist
+++ b/Docs/SampleCustom.plist
@@ -1838,6 +1838,8 @@
ProvideConsoleGop
+ ReconnectGraphicsOnConnect
+
ReconnectOnResChange
ReplaceTabWithSpace
diff --git a/Include/Acidanthera/Library/OcConfigurationLib.h b/Include/Acidanthera/Library/OcConfigurationLib.h
index bfcf8345..b36facb9 100644
--- a/Include/Acidanthera/Library/OcConfigurationLib.h
+++ b/Include/Acidanthera/Library/OcConfigurationLib.h
@@ -654,7 +654,8 @@ typedef enum {
_(INT8 , UIScale , , -1 , ()) \
_(BOOLEAN , UgaPassThrough , , FALSE , ()) \
_(BOOLEAN , DirectGopRendering , , FALSE , ()) \
- _(BOOLEAN , ForceResolution , , FALSE , ())
+ _(BOOLEAN , ForceResolution , , FALSE , ()) \
+ _(BOOLEAN , ReconnectGraphicsOnConnect , , FALSE , ())
OC_DECLARE (OC_UEFI_OUTPUT)
///
diff --git a/Include/Acidanthera/Library/OcDriverConnectionLib.h b/Include/Acidanthera/Library/OcDriverConnectionLib.h
index 812b4231..fb8241d6 100644
--- a/Include/Acidanthera/Library/OcDriverConnectionLib.h
+++ b/Include/Acidanthera/Library/OcDriverConnectionLib.h
@@ -38,6 +38,14 @@ OcUnblockUnmountedPartitions (
VOID
);
+/**
+ Disconnects all graphics drivers attached to PCI I/O protcols.
+**/
+VOID
+OcDisconnectGraphicsDrivers (
+ VOID
+ );
+
/**
Disconnect effectively all drivers attached at handle.
diff --git a/Library/OcConfigurationLib/OcConfigurationLib.c b/Library/OcConfigurationLib/OcConfigurationLib.c
index 766f9dd8..6a08a441 100644
--- a/Library/OcConfigurationLib/OcConfigurationLib.c
+++ b/Library/OcConfigurationLib/OcConfigurationLib.c
@@ -774,20 +774,21 @@ mUefiInputSchema[] = {
STATIC
OC_SCHEMA
mUefiOutputSchema[] = {
- OC_SCHEMA_BOOLEAN_IN ("ClearScreenOnModeSwitch",OC_GLOBAL_CONFIG, Uefi.Output.ClearScreenOnModeSwitch),
- OC_SCHEMA_STRING_IN ("ConsoleMode", OC_GLOBAL_CONFIG, Uefi.Output.ConsoleMode),
- OC_SCHEMA_BOOLEAN_IN ("DirectGopRendering", OC_GLOBAL_CONFIG, Uefi.Output.DirectGopRendering),
- OC_SCHEMA_BOOLEAN_IN ("ForceResolution", OC_GLOBAL_CONFIG, Uefi.Output.ForceResolution),
- OC_SCHEMA_STRING_IN ("GopPassThrough", OC_GLOBAL_CONFIG, Uefi.Output.GopPassThrough),
- OC_SCHEMA_BOOLEAN_IN ("IgnoreTextInGraphics", OC_GLOBAL_CONFIG, Uefi.Output.IgnoreTextInGraphics),
- OC_SCHEMA_BOOLEAN_IN ("ProvideConsoleGop", OC_GLOBAL_CONFIG, Uefi.Output.ProvideConsoleGop),
- OC_SCHEMA_BOOLEAN_IN ("ReconnectOnResChange", OC_GLOBAL_CONFIG, Uefi.Output.ReconnectOnResChange),
- OC_SCHEMA_BOOLEAN_IN ("ReplaceTabWithSpace", OC_GLOBAL_CONFIG, Uefi.Output.ReplaceTabWithSpace),
- OC_SCHEMA_STRING_IN ("Resolution", OC_GLOBAL_CONFIG, Uefi.Output.Resolution),
- OC_SCHEMA_BOOLEAN_IN ("SanitiseClearScreen", OC_GLOBAL_CONFIG, Uefi.Output.SanitiseClearScreen),
- OC_SCHEMA_STRING_IN ("TextRenderer", OC_GLOBAL_CONFIG, Uefi.Output.TextRenderer),
- OC_SCHEMA_INTEGER_IN ("UIScale", OC_GLOBAL_CONFIG, Uefi.Output.UIScale),
- OC_SCHEMA_BOOLEAN_IN ("UgaPassThrough", OC_GLOBAL_CONFIG, Uefi.Output.UgaPassThrough),
+ OC_SCHEMA_BOOLEAN_IN ("ClearScreenOnModeSwitch", OC_GLOBAL_CONFIG, Uefi.Output.ClearScreenOnModeSwitch),
+ OC_SCHEMA_STRING_IN ("ConsoleMode", OC_GLOBAL_CONFIG, Uefi.Output.ConsoleMode),
+ OC_SCHEMA_BOOLEAN_IN ("DirectGopRendering", OC_GLOBAL_CONFIG, Uefi.Output.DirectGopRendering),
+ OC_SCHEMA_BOOLEAN_IN ("ForceResolution", OC_GLOBAL_CONFIG, Uefi.Output.ForceResolution),
+ OC_SCHEMA_STRING_IN ("GopPassThrough", OC_GLOBAL_CONFIG, Uefi.Output.GopPassThrough),
+ OC_SCHEMA_BOOLEAN_IN ("IgnoreTextInGraphics", OC_GLOBAL_CONFIG, Uefi.Output.IgnoreTextInGraphics),
+ OC_SCHEMA_BOOLEAN_IN ("ProvideConsoleGop", OC_GLOBAL_CONFIG, Uefi.Output.ProvideConsoleGop),
+ OC_SCHEMA_BOOLEAN_IN ("ReconnectGraphicsOnConnect",OC_GLOBAL_CONFIG, Uefi.Output.ReconnectGraphicsOnConnect),
+ OC_SCHEMA_BOOLEAN_IN ("ReconnectOnResChange", OC_GLOBAL_CONFIG, Uefi.Output.ReconnectOnResChange),
+ OC_SCHEMA_BOOLEAN_IN ("ReplaceTabWithSpace", OC_GLOBAL_CONFIG, Uefi.Output.ReplaceTabWithSpace),
+ OC_SCHEMA_STRING_IN ("Resolution", OC_GLOBAL_CONFIG, Uefi.Output.Resolution),
+ OC_SCHEMA_BOOLEAN_IN ("SanitiseClearScreen", OC_GLOBAL_CONFIG, Uefi.Output.SanitiseClearScreen),
+ OC_SCHEMA_STRING_IN ("TextRenderer", OC_GLOBAL_CONFIG, Uefi.Output.TextRenderer),
+ OC_SCHEMA_INTEGER_IN ("UIScale", OC_GLOBAL_CONFIG, Uefi.Output.UIScale),
+ OC_SCHEMA_BOOLEAN_IN ("UgaPassThrough", OC_GLOBAL_CONFIG, Uefi.Output.UgaPassThrough),
};
STATIC
diff --git a/Library/OcDriverConnectionLib/DriverDisconnection.c b/Library/OcDriverConnectionLib/DriverDisconnection.c
index 6289f434..3a19722c 100644
--- a/Library/OcDriverConnectionLib/DriverDisconnection.c
+++ b/Library/OcDriverConnectionLib/DriverDisconnection.c
@@ -12,7 +12,10 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include
+#include
+
#include
+#include
#include
#include
@@ -126,3 +129,57 @@ OcUnblockUnmountedPartitions (
FreePool (Handles);
}
+
+VOID
+OcDisconnectGraphicsDrivers (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_TYPE00 Pci;
+
+ //
+ // Locate all currently connected PCI I/O protocols and disconnect graphics drivers.
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiPciIoProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (!EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO, "OCDC: Found %u handles with PCI I/O\n", (UINT32) HandleCount));
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[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) {
+ Status = gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);
+ DEBUG ((DEBUG_INFO, "OCDC: Disconnected graphics driver handle %u - %p result - %r\n", Index, HandleBuffer[Index], Status));
+ }
+ }
+ }
+
+ FreePool (HandleBuffer);
+ }
+}
diff --git a/Library/OcMainLib/OpenCoreUefi.c b/Library/OcMainLib/OpenCoreUefi.c
index a848e502..c1058e36 100644
--- a/Library/OcMainLib/OpenCoreUefi.c
+++ b/Library/OcMainLib/OpenCoreUefi.c
@@ -905,6 +905,13 @@ OcLoadUefiSupport (
// DriversToConnect is not freed as it is owned by OcRegisterDriversToHighestPriority.
//
}
+
+ if (Config->Uefi.Output.ReconnectGraphicsOnConnect) {
+ DEBUG ((DEBUG_INFO, "OC: Disconnecting graphics drivers...\n"));
+ OcDisconnectGraphicsDrivers ();
+ DEBUG ((DEBUG_INFO, "OC: Disconnecting graphics drivers done...\n"));
+ }
+
OcConnectDrivers ();
DEBUG ((DEBUG_INFO, "OC: Connecting drivers done...\n"));
} else {