OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
DriverDisconnection.c
Go to the documentation of this file.
1
13#include <Uefi.h>
14
15#include <IndustryStandard/Pci.h>
16
18#include <Protocol/BlockIo.h>
20#include <Protocol/PciIo.h>
21#include <Protocol/SimpleFileSystem.h>
22
23#include <Library/DebugLib.h>
24#include <Library/MemoryAllocationLib.h>
29#include <Library/UefiBootServicesTableLib.h>
30
31EFI_STATUS
33 IN EFI_HANDLE Controller
34 )
35{
36 EFI_STATUS Status;
37 UINTN NumBlockIoInfo;
38 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *BlockIoInfos;
39 UINTN BlockIoInfoIndex;
40
41 //
42 // Disconnect any blocking drivers if applicable.
43 //
44 Status = gBS->OpenProtocolInformation (
45 Controller,
47 &BlockIoInfos,
48 &NumBlockIoInfo
49 );
50 if (EFI_ERROR (Status)) {
51 DEBUG ((DEBUG_INFO, "OCDC: Attached drivers could not been retrieved\n"));
52 return Status;
53 }
54
55 for (BlockIoInfoIndex = 0; BlockIoInfoIndex < NumBlockIoInfo; ++BlockIoInfoIndex) {
56 if ((BlockIoInfos[BlockIoInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
57 Status = gBS->DisconnectController (
58 Controller,
59 BlockIoInfos[BlockIoInfoIndex].AgentHandle,
60 NULL
61 );
62 if (EFI_ERROR (Status)) {
63 DEBUG ((
64 DEBUG_INFO,
65 "OCDC: Failed to unblock handle %p - %r\n",
66 Controller,
67 Status
68 ));
69 }
70 }
71 }
72
73 FreePool (BlockIoInfos);
74 return EFI_SUCCESS;
75}
76
77VOID
79 VOID
80 )
81{
82 EFI_STATUS Status;
83
84 UINTN NumHandles;
85 EFI_HANDLE *Handles;
86 UINTN HandleIndex;
87
88 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem;
89 EFI_BLOCK_IO_PROTOCOL *BlockIo;
90
91 //
92 // For all Block I/O handles, check whether it is a partition. If it is and
93 // does not have a File System protocol attached, ensure it does not have a
94 // blocking driver attached which prevents the connection of a FS driver.
95 //
96 Status = gBS->LocateHandleBuffer (
97 ByProtocol,
99 NULL,
100 &NumHandles,
101 &Handles
102 );
103 if (EFI_ERROR (Status)) {
104 DEBUG ((DEBUG_INFO, "OCDC: Could not locate DiskIo handles\n"));
105 return;
106 }
107
108 for (HandleIndex = 0; HandleIndex < NumHandles; ++HandleIndex) {
109 //
110 // Skip the current handle if a File System driver is already attached.
111 //
112 Status = gBS->HandleProtocol (
113 Handles[HandleIndex],
115 (VOID **)&FileSystem
116 );
117 if (!EFI_ERROR (Status)) {
118 continue;
119 }
120
121 //
122 // Ensure the current handle describes a partition.
123 //
124 Status = gBS->HandleProtocol (
125 Handles[HandleIndex],
127 (VOID **)&BlockIo
128 );
129 if (EFI_ERROR (Status) || !BlockIo->Media->LogicalPartition) {
130 continue;
131 }
132
133 OcDisconnectDriversOnHandle (Handles[HandleIndex]);
134 }
135
136 FreePool (Handles);
137}
138
139VOID
141 VOID
142 )
143{
144 EFI_STATUS Status;
145 UINT32 Index;
146
147 UINTN HandleCount;
148 EFI_HANDLE *HandleBuffer;
149 EFI_PCI_IO_PROTOCOL *PciIo;
150 PCI_TYPE00 Pci;
151
152 //
153 // Locate all currently connected PCI I/O protocols and disconnect graphics drivers.
154 //
155 Status = gBS->LocateHandleBuffer (
156 ByProtocol,
157 &gEfiPciIoProtocolGuid,
158 NULL,
159 &HandleCount,
160 &HandleBuffer
161 );
162 if (!EFI_ERROR (Status)) {
163 DEBUG ((DEBUG_INFO, "OCDC: Found %u handles with PCI I/O\n", (UINT32)HandleCount));
164 for (Index = 0; Index < HandleCount; Index++) {
165 Status = gBS->HandleProtocol (
166 HandleBuffer[Index],
167 &gEfiPciIoProtocolGuid,
168 (VOID **)&PciIo
169 );
170 if (EFI_ERROR (Status)) {
171 continue;
172 }
173
174 Status = PciIo->Pci.Read (
175 PciIo,
176 EfiPciIoWidthUint32,
177 0,
178 sizeof (Pci) / sizeof (UINT32),
179 &Pci
180 );
181 if (!EFI_ERROR (Status)) {
182 if (IS_PCI_VGA (&Pci) == TRUE) {
183 Status = gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);
184 DEBUG ((DEBUG_INFO, "OCDC: Disconnected graphics driver handle %u - %p result - %r\n", Index, HandleBuffer[Index], Status));
185 }
186 }
187 }
188
189 FreePool (HandleBuffer);
190 }
191}
192
193VOID
195 VOID
196 )
197{
198 EFI_STATUS Status;
199 UINT32 Index;
200
201 UINTN HandleCount;
202 EFI_HANDLE *HandleBuffer;
203 EFI_PCI_IO_PROTOCOL *PciIo;
204 PCI_CLASSCODE HdaClassReg;
205
206 //
207 // Locate all currently connected PCI I/O protocols and disconnect HDA controllers.
208 //
209 Status = gBS->LocateHandleBuffer (
210 ByProtocol,
211 &gEfiPciIoProtocolGuid,
212 NULL,
213 &HandleCount,
214 &HandleBuffer
215 );
216 if (!EFI_ERROR (Status)) {
217 DEBUG ((DEBUG_INFO, "OCDC: Found %u handles with PCI I/O\n", (UINT32)HandleCount));
218 for (Index = 0; Index < HandleCount; Index++) {
219 Status = gBS->HandleProtocol (
220 HandleBuffer[Index],
221 &gEfiPciIoProtocolGuid,
222 (VOID **)&PciIo
223 );
224 if (EFI_ERROR (Status)) {
225 continue;
226 }
227
228 //
229 // Read class code from PCI.
230 //
231 Status = PciIo->Pci.Read (
232 PciIo,
233 EfiPciIoWidthUint8,
234 PCI_CLASSCODE_OFFSET,
235 sizeof (PCI_CLASSCODE),
236 &HdaClassReg
237 );
238
239 //
240 // Check class code, ignore everything but HDA controllers.
241 //
242 if ( EFI_ERROR (Status)
243 || (HdaClassReg.BaseCode != PCI_CLASS_MEDIA)
244 || (HdaClassReg.SubClassCode != PCI_CLASS_MEDIA_MIXED_MODE))
245 {
246 continue;
247 }
248
249 DebugPrintDevicePathForHandle (DEBUG_INFO, "OCDC: Disconnecting audio controller", HandleBuffer[Index]);
250 Status = gBS->DisconnectController (HandleBuffer[Index], NULL, NULL);
251 DEBUG ((DEBUG_INFO, "OCDC: Disconnected - %r\n", Status));
252 }
253
254 FreePool (HandleBuffer);
255 }
256}
VOID OcUnblockUnmountedPartitions(VOID)
VOID OcDisconnectGraphicsDrivers(VOID)
EFI_STATUS OcDisconnectDriversOnHandle(IN EFI_HANDLE Controller)
VOID OcDisconnectHdaControllers(VOID)
EFI_BOOT_SERVICES * gBS
VOID DebugPrintDevicePathForHandle(IN UINTN ErrorLevel, IN CONST CHAR8 *Message, IN EFI_HANDLE Handle OPTIONAL)
EFI_GUID gEfiSimpleFileSystemProtocolGuid
EFI_GUID gEfiBlockIoProtocolGuid