OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
GopPassThrough.c
Go to the documentation of this file.
1
17
18#include <Library/DebugLib.h>
19#include <Library/MemoryAllocationLib.h>
20#include <Library/UefiBootServicesTableLib.h>
21
22#include <Library/OcMiscLib.h>
23
24STATIC
25EFI_STATUS
26EFIAPI
28 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
29 IN UINT32 ModeNumber,
30 OUT UINTN *SizeOfInfo,
31 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
32 )
33{
34 if (ModeNumber != 0) {
35 DEBUG ((DEBUG_VERBOSE, "OCC: OcGopDrawQueryMode invalid ModeNumber - %u\n", ModeNumber));
36 return EFI_INVALID_PARAMETER;
37 }
38
39 if ((SizeOfInfo == NULL) || (Info == NULL)) {
40 DEBUG ((DEBUG_VERBOSE, "OCC: OcGopDrawQueryMode got invalid parameter SizeOfInfo or Info!\n"));
41 return EFI_INVALID_PARAMETER;
42 }
43
44 *SizeOfInfo = This->Mode->SizeOfInfo;
45 *Info = AllocateCopyPool (This->Mode->SizeOfInfo, This->Mode->Info);
46 if (*Info == NULL) {
47 DEBUG ((DEBUG_VERBOSE, "OCC: OcGopDrawQueryMode failed to allocate memory for GOP Info!\n"));
48 return EFI_DEVICE_ERROR;
49 }
50
51 return EFI_SUCCESS;
52}
53
54STATIC
55EFI_STATUS
56EFIAPI
58 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
59 IN UINT32 ModeNumber
60 )
61{
62 if (ModeNumber != 0) {
63 DEBUG ((DEBUG_VERBOSE, "OCC: OcGopDrawSetMode unsupported ModeNumber - %u\n", ModeNumber));
64 return EFI_UNSUPPORTED;
65 }
66
67 //
68 // Assuming 0 is the only mode that is accepted, which is already set.
69 //
70 return EFI_SUCCESS;
71}
72
73STATIC
74EFI_STATUS
75EFIAPI
77 IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
78 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer OPTIONAL,
79 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
80 IN UINTN SourceX,
81 IN UINTN SourceY,
82 IN UINTN DestinationX,
83 IN UINTN DestinationY,
84 IN UINTN Width,
85 IN UINTN Height,
86 IN UINTN Delta OPTIONAL
87 )
88{
89 OC_GOP_PROTOCOL *OcGopDraw;
90
91 OcGopDraw = BASE_CR (This, OC_GOP_PROTOCOL, GraphicsOutput);
92
93 return OcGopDraw->Uga->Blt (
94 OcGopDraw->Uga,
95 (EFI_UGA_PIXEL *)BltBuffer,
96 (EFI_UGA_BLT_OPERATION)BltOperation,
97 SourceX,
98 SourceY,
99 DestinationX,
100 DestinationY,
101 Width,
102 Height,
103 Delta
104 );
105}
106
107EFI_STATUS
109 IN BOOLEAN ForAll
110 )
111{
112 EFI_STATUS Status;
113 UINTN HandleCount;
114 EFI_HANDLE *HandleBuffer;
115 UINTN Index;
116 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
117 EFI_UGA_DRAW_PROTOCOL *UgaDraw;
118 OC_GOP_PROTOCOL *OcGopDraw;
119 APPLE_FRAMEBUFFER_INFO_PROTOCOL *FramebufferInfo;
120 EFI_PHYSICAL_ADDRESS FramebufferBase;
121 UINT32 FramebufferSize;
122 UINT32 ScreenRowBytes;
123 UINT32 ScreenWidth;
124 UINT32 ScreenHeight;
125 UINT32 ScreenDepth;
126 UINT32 HorizontalResolution;
127 UINT32 VerticalResolution;
128 EFI_GRAPHICS_PIXEL_FORMAT PixelFormat;
129 UINT32 ColorDepth;
130 UINT32 RefreshRate;
131 BOOLEAN HasAppleFramebuffer;
132
133 //
134 // We should not proxy UGA when there is no AppleFramebuffer,
135 // but on systems where there is nothing, it is the only option.
136 // REF: https://github.com/acidanthera/bugtracker/issues/1498
137 //
138 Status = gBS->LocateProtocol (
140 NULL,
141 (VOID *)&FramebufferInfo
142 );
143 HasAppleFramebuffer = !EFI_ERROR (Status);
144
145 DEBUG_CODE_BEGIN ();
147 DEBUG ((DEBUG_INFO, "OCC: Found %u handles with GOP draw\n", HandleCount));
148
150 DEBUG ((DEBUG_INFO, "OCC: Found %u handles with Apple Framebuffer info\n", HandleCount));
151
152 if (EFI_ERROR (Status)) {
153 DEBUG ((DEBUG_INFO, "OCC: Failed to locate AppleFramebufferInfo protocol - %r\n", Status));
154 } else {
155 Status = FramebufferInfo->GetInfo (
156 FramebufferInfo,
157 &FramebufferBase,
158 &FramebufferSize,
159 &ScreenRowBytes,
160 &ScreenWidth,
161 &ScreenHeight,
162 &ScreenDepth
163 );
164 if (!EFI_ERROR (Status)) {
165 DEBUG ((
166 DEBUG_INFO,
167 "OCC: AppleFramebufferInfo - Got Base %Lx, Size %u, RowBytes %u, Width %u, Height %u, Depth %u\n",
168 FramebufferBase,
169 FramebufferSize,
170 ScreenRowBytes,
171 ScreenWidth,
172 ScreenHeight,
173 ScreenDepth
174 ));
175 } else {
176 DEBUG ((DEBUG_INFO, "OCC: AppleFramebufferInfo failed to retrieve info - %r\n", Status));
177 }
178 }
179
180 DEBUG_CODE_END ();
181
182 Status = gBS->LocateHandleBuffer (
183 ByProtocol,
185 NULL,
186 &HandleCount,
187 &HandleBuffer
188 );
189 if (EFI_ERROR (Status)) {
190 DEBUG ((DEBUG_INFO, "OCC: Failed to find handles with UGA - %r\n", Status));
191 return Status;
192 }
193
194 DEBUG ((DEBUG_INFO, "OCC: Found %u handles with UGA for GOP check\n", (UINT32)HandleCount));
195 for (Index = 0; Index < HandleCount; ++Index) {
196 DEBUG ((DEBUG_INFO, "OCC: Trying handle %u - %p\n", (UINT32)Index, HandleBuffer[Index]));
197
198 Status = gBS->HandleProtocol (
199 HandleBuffer[Index],
201 (VOID **)&UgaDraw
202 );
203 if (EFI_ERROR (Status)) {
204 DEBUG ((DEBUG_INFO, "OCC: No UGA protocol - %r\n", Status));
205 continue;
206 }
207
208 Status = gBS->HandleProtocol (
209 HandleBuffer[Index],
211 (VOID **)&GraphicsOutput
212 );
213 if (!EFI_ERROR (Status)) {
214 DEBUG ((DEBUG_INFO, "OCC: Skipping GOP proxying as it is already present on handle %u - %p\n", (UINT32)Index, HandleBuffer[Index]));
215 continue;
216 }
217
218 FramebufferBase = 0;
219 FramebufferSize = 0;
220 ScreenRowBytes = 0;
221 PixelFormat = PixelBltOnly;
222
223 Status = gBS->HandleProtocol (
224 HandleBuffer[Index],
226 (VOID **)&FramebufferInfo
227 );
228 if (EFI_ERROR (Status)) {
229 DEBUG ((
230 DEBUG_INFO,
231 "OCC: Failed to retrieve AppleFramebufferInfo protocol on handle %u - %p (%r)\n",
232 (UINT32)Index,
233 HandleBuffer[Index],
234 Status
235 ));
236 if (HasAppleFramebuffer || !ForAll) {
237 continue;
238 }
239 } else {
240 DEBUG ((
241 DEBUG_INFO,
242 "OCC: Got AppleFramebufferInfo protocol on handle %u - %p\n",
243 (UINT32)Index,
244 HandleBuffer[Index]
245 ));
246
247 Status = FramebufferInfo->GetInfo (
248 FramebufferInfo,
249 &FramebufferBase,
250 &FramebufferSize,
251 &ScreenRowBytes,
252 &ScreenWidth,
253 &ScreenHeight,
254 &ScreenDepth
255 );
256 if (!EFI_ERROR (Status)) {
257 PixelFormat = PixelRedGreenBlueReserved8BitPerColor;
258
259 DEBUG ((
260 DEBUG_INFO,
261 "OCC: AppleFramebufferInfo - Got Base %Lx, Size %u, RowBytes %u, Width %u, Height %u, Depth %u on handle %u - %p\n",
262 FramebufferBase,
263 FramebufferSize,
264 ScreenRowBytes,
265 ScreenWidth,
266 ScreenHeight,
267 ScreenDepth,
268 (UINT32)Index,
269 HandleBuffer[Index]
270 ));
271 } else {
272 DEBUG ((
273 DEBUG_INFO,
274 "OCC: Failed to get info from AppleFramebufferInfo protocol on handle %u - %p (%r)\n",
275 (UINT32)Index,
276 HandleBuffer[Index],
277 Status
278 ));
279 if (HasAppleFramebuffer) {
280 continue;
281 }
282 }
283 }
284
285 Status = UgaDraw->GetMode (
286 UgaDraw,
287 &HorizontalResolution,
288 &VerticalResolution,
289 &ColorDepth,
290 &RefreshRate
291 );
292 if (EFI_ERROR (Status)) {
293 DEBUG ((DEBUG_INFO, "OCC: UGA->GetMode returns error - %r\n", Status));
294 continue;
295 }
296
297 OcGopDraw = AllocateZeroPool (sizeof (*OcGopDraw));
298 if (OcGopDraw == NULL) {
299 DEBUG ((DEBUG_INFO, "OCC: Failed to allocate GOP protocol\n"));
300 continue;
301 }
302
303 OcGopDraw->Uga = UgaDraw;
304 OcGopDraw->GraphicsOutput.QueryMode = OcGopDrawQueryMode;
305 OcGopDraw->GraphicsOutput.SetMode = OcGopDrawSetMode;
306 OcGopDraw->GraphicsOutput.Blt = OcGopDrawBlt;
307 OcGopDraw->GraphicsOutput.Mode = AllocateZeroPool (sizeof (*OcGopDraw->GraphicsOutput.Mode));
308 if (OcGopDraw->GraphicsOutput.Mode == NULL) {
309 FreePool (OcGopDraw);
310 continue;
311 }
312
313 //
314 // Only Mode 0 is supported, so there is only one mode supported in total.
315 //
316 OcGopDraw->GraphicsOutput.Mode->MaxMode = 1;
317 //
318 // Again, only Mode 0 is supported.
319 //
320 OcGopDraw->GraphicsOutput.Mode->Mode = 0;
321 OcGopDraw->GraphicsOutput.Mode->Info = AllocateZeroPool (sizeof (*OcGopDraw->GraphicsOutput.Mode->Info));
322 if (OcGopDraw->GraphicsOutput.Mode->Info == NULL) {
323 FreePool (OcGopDraw->GraphicsOutput.Mode);
324 FreePool (OcGopDraw);
325 continue;
326 }
327
328 OcGopDraw->GraphicsOutput.Mode->Info->Version = 0;
329 OcGopDraw->GraphicsOutput.Mode->Info->HorizontalResolution = HorizontalResolution;
330 OcGopDraw->GraphicsOutput.Mode->Info->VerticalResolution = VerticalResolution;
331 OcGopDraw->GraphicsOutput.Mode->Info->PixelFormat = PixelFormat;
332 //
333 // No pixel mask is needed (i.e. all zero) in PixelInformation,
334 // plus AllocateZeroPool already assigns zero for it.
335 // Skip.
336 // ------------------------------------------------------------------------------
337 // ScreenRowBytes is PixelsPerScanLine * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL),
338 // so here to divide it back.
339 //
340 OcGopDraw->GraphicsOutput.Mode->Info->PixelsPerScanLine = ScreenRowBytes / sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
341 OcGopDraw->GraphicsOutput.Mode->SizeOfInfo = sizeof (*OcGopDraw->GraphicsOutput.Mode->Info);
342 OcGopDraw->GraphicsOutput.Mode->FrameBufferBase = FramebufferBase;
343 OcGopDraw->GraphicsOutput.Mode->FrameBufferSize = FramebufferSize;
344
345 Status = gBS->InstallMultipleProtocolInterfaces (
346 &HandleBuffer[Index],
348 &OcGopDraw->GraphicsOutput,
349 NULL
350 );
351 if (EFI_ERROR (Status)) {
352 FreePool (OcGopDraw->GraphicsOutput.Mode->Info);
353 FreePool (OcGopDraw->GraphicsOutput.Mode);
354 FreePool (OcGopDraw);
355 }
356
357 DEBUG ((
358 DEBUG_INFO,
359 "OCC: Installed GOP protocol - %r (Handle %u - %p, Resolution %ux%u, FramebufferBase %Lx, PixelFormat %d)\n",
360 Status,
361 (UINT32)Index,
362 HandleBuffer[Index],
363 HorizontalResolution,
364 VerticalResolution,
365 FramebufferBase,
366 PixelFormat
367 ));
368 }
369
370 FreePool (HandleBuffer);
371
372 return Status;
373}
EFI_GUID gAppleFramebufferInfoProtocolGuid
STATIC EFI_STATUS EFIAPI OcGopDrawSetMode(IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, IN UINT32 ModeNumber)
STATIC EFI_STATUS EFIAPI OcGopDrawBlt(IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer OPTIONAL, IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, IN UINTN SourceX, IN UINTN SourceY, IN UINTN DestinationX, IN UINTN DestinationY, IN UINTN Width, IN UINTN Height, IN UINTN Delta OPTIONAL)
STATIC EFI_STATUS EFIAPI OcGopDrawQueryMode(IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, IN UINT32 ModeNumber, OUT UINTN *SizeOfInfo, OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info)
EFI_STATUS OcProvideGopPassThrough(IN BOOLEAN ForAll)
EFI_BOOT_SERVICES * gBS
UINTN OcCountProtocolInstances(IN EFI_GUID *Protocol)
EFI_GUID gEfiUgaDrawProtocolGuid
EFI_GUID gEfiGraphicsOutputProtocolGuid
APPLE_FRAMEBUFFER_INFO_GET_INFO GetInfo
EFI_UGA_DRAW_PROTOCOL * Uga
EFI_GRAPHICS_OUTPUT_PROTOCOL GraphicsOutput