OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
GopStop.c
Go to the documentation of this file.
1
15#include <Uefi.h>
16#include <Guid/AppleFile.h>
17#include <Library/BaseMemoryLib.h>
18#include <Library/DebugLib.h>
19#include <Library/PrintLib.h>
20#include <Library/MemoryAllocationLib.h>
23#include <Library/OcMiscLib.h>
24#include <Library/OcFileLib.h>
25#include <Library/UefiApplicationEntryPoint.h>
26#include <Library/UefiBootServicesTableLib.h>
27#include <Library/UefiRuntimeServicesTableLib.h>
28#include <Library/UefiLib.h>
29#include <Protocol/DevicePath.h>
30#include <Protocol/GraphicsOutput.h>
31
32STATIC
33VOID
35 IN EFI_HANDLE Handle,
36 IN UINTN GopIndex,
37 IN UINTN HandleCount,
38 OUT CHAR8 *Report
39 )
40{
41 EFI_STATUS Status;
42 EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop;
43 UINT32 Index;
44 CHAR8 Tmp[256];
45 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
46 UINTN InfoSize;
47 UINTN Width;
48 UINTN Height;
49 INTN NewMode;
50
51 Status = gBS->HandleProtocol (
52 Handle,
54 (VOID **)&Gop
55 );
56
57 //
58 // GOP report:
59 //
60 AsciiSPrint (
61 Tmp,
62 sizeof (Tmp),
63 "GOP #%u of total %u, %a - %r\n",
64 (UINT32)(GopIndex + 1),
65 (UINT32)HandleCount,
66 gST->ConsoleOutHandle == Handle ? "console" : "auxiliary",
67 Status
68 );
69 DEBUG ((DEBUG_WARN, "GSTT: %a", Tmp));
70 AsciiStrCatS (Report, EFI_PAGE_SIZE, Tmp);
71
72 if (EFI_ERROR (Status)) {
73 return;
74 }
75
76 AsciiSPrint (
77 Tmp,
78 sizeof (Tmp),
79 "Current mode %u, max mode %u, FB: %p, FBS: %LX\n",
80 Gop->Mode->Mode,
81 Gop->Mode->MaxMode,
82 (UINT64)Gop->Mode->FrameBufferBase,
83 (UINT32)Gop->Mode->FrameBufferSize
84 );
85 DEBUG ((DEBUG_WARN, "GSTT: %a", Tmp));
86 AsciiStrCatS (Report, EFI_PAGE_SIZE, Tmp);
87
88 Info = Gop->Mode->Info;
89 AsciiSPrint (
90 Tmp,
91 sizeof (Tmp),
92 "Current: %u x %u, pixel %d (%X %X %X %X), scan: %u\n",
93 Info->HorizontalResolution,
94 Info->VerticalResolution,
95 Info->PixelFormat,
96 Info->PixelInformation.RedMask,
97 Info->PixelInformation.GreenMask,
98 Info->PixelInformation.BlueMask,
99 Info->PixelInformation.ReservedMask,
100 Info->PixelsPerScanLine
101 );
102 DEBUG ((DEBUG_WARN, "GSTT: %a", Tmp));
103 AsciiStrCatS (Report, EFI_PAGE_SIZE, Tmp);
104
105 Width = 0;
106 Height = 0;
107 NewMode = -1;
108
109 for (Index = 0; Index < Gop->Mode->MaxMode; ++Index) {
110 Status = Gop->QueryMode (
111 Gop,
112 Index,
113 &InfoSize,
114 &Info
115 );
116
117 if (EFI_ERROR (Status)) {
118 AsciiSPrint (
119 Tmp,
120 sizeof (Tmp),
121 "%u: %r\n",
122 Index,
123 Status
124 );
125 DEBUG ((DEBUG_WARN, "GSTT: %a", Tmp));
126 AsciiStrCatS (Report, EFI_PAGE_SIZE, Tmp);
127 continue;
128 }
129
130 AsciiSPrint (
131 Tmp,
132 sizeof (Tmp),
133 "%u: %u x %u, pixel %d (%X %X %X %X), scan: %u\n",
134 Index,
135 Info->HorizontalResolution,
136 Info->VerticalResolution,
137 Info->PixelFormat,
138 Info->PixelInformation.RedMask,
139 Info->PixelInformation.GreenMask,
140 Info->PixelInformation.BlueMask,
141 Info->PixelInformation.ReservedMask,
142 Info->PixelsPerScanLine
143 );
144 DEBUG ((DEBUG_WARN, "GSTT: %a", Tmp));
145 AsciiStrCatS (Report, EFI_PAGE_SIZE, Tmp);
146
147 if ( (Info->HorizontalResolution > Width)
148 || ((Info->HorizontalResolution == Width) && (Info->VerticalResolution > Height)))
149 {
150 Width = Info->HorizontalResolution;
151 Height = Info->VerticalResolution;
152 NewMode = (INTN)Index;
153 }
154
155 FreePool (Info);
156 }
157
158 if (NewMode >= 0) {
159 Status = Gop->SetMode (
160 Gop,
161 (UINT32)NewMode
162 );
163
164 Info = Gop->Mode->Info;
165 AsciiSPrint (
166 Tmp,
167 sizeof (Tmp),
168 "New %u <-> %u: max mode %u, FB: %p, FBS: %LX - %r\n",
169 (UINT32)NewMode,
170 Gop->Mode->Mode,
171 Gop->Mode->MaxMode,
172 (UINT64)Gop->Mode->FrameBufferBase,
173 (UINT32)Gop->Mode->FrameBufferSize,
174 Status
175 );
176 DEBUG ((DEBUG_WARN, "GSTT: %a", Tmp));
177 AsciiStrCatS (Report, EFI_PAGE_SIZE, Tmp);
178 AsciiSPrint (
179 Tmp,
180 sizeof (Tmp),
181 "New %u <-> %u: %u x %u, pixel %d (%X %X %X %X), scan: %u\n",
182 (UINT32)NewMode,
183 Gop->Mode->Mode,
184 Info->HorizontalResolution,
185 Info->VerticalResolution,
186 Info->PixelFormat,
187 Info->PixelInformation.RedMask,
188 Info->PixelInformation.GreenMask,
189 Info->PixelInformation.BlueMask,
190 Info->PixelInformation.ReservedMask,
191 Info->PixelsPerScanLine
192 );
193 DEBUG ((DEBUG_WARN, "GSTT: %a", Tmp));
194 AsciiStrCatS (Report, EFI_PAGE_SIZE, Tmp);
195 }
196}
197
198STATIC
199VOID
201 IN EFI_HANDLE Handle
202 )
203{
204 EFI_STATUS Status;
205 EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop;
206 UINTN Index;
207 UINT32 ChunkX;
208 UINT32 ChunkY;
209 UINT32 ChunkW;
210 UINT32 ChunkH;
211 UINT32 ColorIndex;
212
213 Status = gBS->HandleProtocol (
214 Handle,
216 (VOID **)&Gop
217 );
218
219 if ( EFI_ERROR (Status)
220 || (Gop->Mode->Info->HorizontalResolution == 0)
221 || (Gop->Mode->Info->VerticalResolution == 0))
222 {
223 return;
224 }
225
226 STATIC EFI_GRAPHICS_OUTPUT_BLT_PIXEL mGraphicsEfiColors[16] = {
227 //
228 // B G R reserved
229 //
230 { 0x00, 0x00, 0x00, 0x00 }, // 0 - BLACK
231 { 0x98, 0x00, 0x00, 0x00 }, // 1 - LIGHTBLUE
232 { 0x00, 0x98, 0x00, 0x00 }, // 2 - LIGHGREEN
233 { 0x98, 0x98, 0x00, 0x00 }, // 3 - LIGHCYAN
234 { 0x00, 0x00, 0x98, 0x00 }, // 4 - LIGHRED
235 { 0x98, 0x00, 0x98, 0x00 }, // 5 - MAGENTA
236 { 0x00, 0x98, 0x98, 0x00 }, // 6 - BROWN
237 { 0x98, 0x98, 0x98, 0x00 }, // 7 - LIGHTGRAY
238 { 0x30, 0x30, 0x30, 0x00 }, // 8 - DARKGRAY - BRIGHT BLACK
239 { 0xff, 0x00, 0x00, 0x00 }, // 9 - BLUE
240 { 0x00, 0xff, 0x00, 0x00 }, // 10 - LIME
241 { 0xff, 0xff, 0x00, 0x00 }, // 11 - CYAN
242 { 0x00, 0x00, 0xff, 0x00 }, // 12 - RED
243 { 0xff, 0x00, 0xff, 0x00 }, // 13 - FUCHSIA
244 { 0x00, 0xff, 0xff, 0x00 }, // 14 - YELLOW
245 { 0xff, 0xff, 0xff, 0x00 } // 15 - WHITE
246 };
247
248 STATIC UINT32 mColorsTest[9] = { 12, 10, 9, 15, 7, 0, 11, 5, 14 };
249
250 if (Gop->Mode->FrameBufferBase != 0) {
251 //
252 // 1. Fill screen with Red (#FF0000) in direct mode.
253 //
254 SetMem32 (
255 (VOID *)(UINTN)Gop->Mode->FrameBufferBase,
256 Gop->Mode->Info->VerticalResolution * Gop->Mode->Info->PixelsPerScanLine * sizeof (UINT32),
257 *(UINT32 *)&mGraphicsEfiColors[mColorsTest[0]]
258 );
259
260 //
261 // 2. Wait 5 seconds.
262 // Note: Ensure that stall value is within UINT32 in nanoseconds.
263 //
264 for (Index = 0; Index < 5; ++Index) {
265 gBS->Stall (SECONDS_TO_MICROSECONDS (1));
266 }
267 }
268
269 //
270 // 3. Fill screen with 4 Red (#FF0000) / Green (#00FF00) / Blue (#0000FF) / White (#FFFFFF) rectangles.
271 // The user should visually ensure that the colours match and that rectangles equally split the screen in 4 parts.
272 //
273 ChunkW = Gop->Mode->Info->HorizontalResolution / 2;
274 ChunkH = Gop->Mode->Info->VerticalResolution / 2;
275 ColorIndex = 0;
276 for (ChunkY = 0; ChunkY + ChunkH <= Gop->Mode->Info->VerticalResolution; ChunkY += ChunkH) {
277 for (ChunkX = 0; ChunkX + ChunkW <= Gop->Mode->Info->HorizontalResolution; ChunkX += ChunkW) {
278 Gop->Blt (
279 Gop,
280 &mGraphicsEfiColors[mColorsTest[ColorIndex]],
281 EfiBltVideoFill,
282 0,
283 0,
284 ChunkX,
285 ChunkY,
286 ChunkW,
287 ChunkH,
288 0
289 );
290 ++ColorIndex;
291 }
292 }
293
294 //
295 // 4. Wait 5 seconds.
296 // Note: Ensure that stall value is within UINT32 in nanoseconds.
297 //
298 for (Index = 0; Index < 5; ++Index) {
299 gBS->Stall (SECONDS_TO_MICROSECONDS (1));
300 }
301
302 //
303 // TODO:
304 // 5. Fill screen with white text on black screen in normal mode.
305 // The screen should effectively be filled with 9 equal rectangles.
306 // From left to right top to bottom they should contain the following symbols: A B C D # F G H I.
307 // Instead of # there should be current GOP number. The user should visually ensure text and
308 // background colour, rectangle sizes, rectangle data.
309 // 6. Wait 5 seconds.
310 // 7. Fill screen with white text on black screen in HiDPI mode. This should repeat the previous test
311 // but the text should be twice bigger. The user should ensure all previous requirements and the
312 // fact that the text got bigger.
313 // 8. Wait 5 seconds.
314 // 9. Print all GOP reports one by one (on separate screens) with white text in black screen in
315 // normal mode. Wait 5 seconds after each. The user should screenshot these and later compare
316 // to the file if available.
317 //
318
319 //
320 // 10. Fill screen with 9 rectangles of different colours. From left to right top to bottom they
321 // should contain the following colours: Red (#FF0000), Green (#00FF00), Blue (#0000FF), White (#FFFFFF),
322 // Light Grey (#989898), Black (#000000), Cyan (#00FFFF), Magenta (#FF00FF), Yellow (#FFFF00). The user should
323 // visually ensure that the colours match and that rectangles equally split the screen in 9 parts.
324 //
325 ChunkW = Gop->Mode->Info->HorizontalResolution / 3;
326 ChunkH = Gop->Mode->Info->VerticalResolution / 3;
327 ColorIndex = 0;
328 for (ChunkY = 0; ChunkY + ChunkH <= Gop->Mode->Info->VerticalResolution; ChunkY += ChunkH) {
329 for (ChunkX = 0; ChunkX + ChunkW <= Gop->Mode->Info->HorizontalResolution; ChunkX += ChunkW) {
330 Gop->Blt (
331 Gop,
332 &mGraphicsEfiColors[mColorsTest[ColorIndex]],
333 EfiBltVideoFill,
334 0,
335 0,
336 ChunkX,
337 ChunkY,
338 ChunkW,
339 ChunkH,
340 0
341 );
342 ++ColorIndex;
343 }
344 }
345
346 //
347 // 11. Wait 5 seconds.
348 // Note: Ensure that stall value is within UINT32 in nanoseconds.
349 //
350 for (Index = 0; Index < 5; ++Index) {
351 gBS->Stall (SECONDS_TO_MICROSECONDS (1));
352 }
353}
354
355EFI_STATUS
356EFIAPI
358 IN EFI_HANDLE ImageHandle,
359 IN EFI_SYSTEM_TABLE *SystemTable
360 )
361{
362 EFI_STATUS Status;
363 UINTN HandleCount;
364 EFI_HANDLE *HandleBuffer;
365 UINTN Index;
366
367 CHAR8 (*Reports)[EFI_PAGE_SIZE];
368 CHAR8 *FinalReport;
369 CHAR16 Filename[64];
370 EFI_TIME Date;
371
372 //
373 // 1. Disable watchdog timer.
374 //
375 gBS->SetWatchdogTimer (0, 0, 0, NULL);
376
377 //
378 // 2. Gather all N available GOP protocols.
379 //
380 HandleCount = 0;
381 Status = gBS->LocateHandleBuffer (
382 ByProtocol,
384 NULL,
385 &HandleCount,
386 &HandleBuffer
387 );
388
389 DEBUG ((
390 DEBUG_WARN,
391 "GSTT: Found %u handles with GOP protocol - %r\n",
392 (UINT32)HandleCount,
393 Status
394 ));
395
396 if (EFI_ERROR (Status)) {
397 return Status;
398 }
399
400 //
401 // 3. Allocate N buffer for GOP reports (PAGE_SIZE).
402 //
403 Reports = AllocateZeroPool (EFI_PAGE_SIZE * HandleCount);
404 if (Reports == NULL) {
405 DEBUG ((DEBUG_WARN, "GSTT: Cannot allocate memory for GOP reports\n"));
406 FreePool (HandleBuffer);
407 return EFI_OUT_OF_RESOURCES;
408 }
409
410 //
411 // 4. Get GOP reports for every GOP and set maximum resolution.
412 //
413 for (Index = 0; Index < HandleCount; ++Index) {
414 AnalyzeGopHandle (HandleBuffer[Index], Index, HandleCount, Reports[Index]);
415 }
416
417 //
418 // 5. Save GOP reports to file to any writable fs (gop-date.txt).
419 //
420 FinalReport = AllocateZeroPool (EFI_PAGE_SIZE * HandleCount);
421 if (FinalReport != NULL) {
422 for (Index = 0; Index < HandleCount; ++Index) {
423 AsciiStrCatS (FinalReport, EFI_PAGE_SIZE * HandleCount, Reports[Index]);
424 AsciiStrCatS (FinalReport, EFI_PAGE_SIZE * HandleCount, "\n\n");
425 }
426
427 Status = gRT->GetTime (&Date, NULL);
428 if (EFI_ERROR (Status)) {
429 ZeroMem (&Date, sizeof (Date));
430 }
431
432 UnicodeSPrint (
433 Filename,
434 sizeof (Filename),
435 L"gop-%04u-%02u-%02u-%02u%02u%02u.txt",
436 (UINT32)Date.Year,
437 (UINT32)Date.Month,
438 (UINT32)Date.Day,
439 (UINT32)Date.Hour,
440 (UINT32)Date.Minute,
441 (UINT32)Date.Second
442 );
443
444 OcSetFileData (NULL, Filename, FinalReport, (UINT32)AsciiStrLen (FinalReport));
445
446 FreePool (FinalReport);
447 } else {
448 DEBUG ((DEBUG_WARN, "GSTT: Cannot allocate memory for final report\n"));
449 }
450
451 //
452 // 6. Run tests in every GOP with non-zero resolution.
453 //
454 for (Index = 0; Index < HandleCount; ++Index) {
455 RunGopTest (HandleBuffer[Index]);
456 }
457
458 FreePool (Reports);
459 FreePool (HandleBuffer);
460
461 return EFI_SUCCESS;
462}
STATIC VOID RunGopTest(IN EFI_HANDLE Handle)
Definition GopStop.c:200
EFI_STATUS EFIAPI UefiMain(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
Definition GopStop.c:357
STATIC VOID AnalyzeGopHandle(IN EFI_HANDLE Handle, IN UINTN GopIndex, IN UINTN HandleCount, OUT CHAR8 *Report)
Definition GopStop.c:34
EFI_SYSTEM_TABLE * gST
EFI_BOOT_SERVICES * gBS
EFI_STATUS OcSetFileData(IN EFI_FILE_PROTOCOL *WritableFs OPTIONAL, IN CONST CHAR16 *FileName, IN CONST VOID *Buffer, IN UINT32 Size)
#define SECONDS_TO_MICROSECONDS(x)
Definition OcMiscLib.h:30
APPLE_EVENT_HANDLE Handle
Definition OcTypingLib.h:45
STATIC UINT32 mGraphicsEfiColors[16]
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
EFI_RUNTIME_SERVICES * gRT
EFI_GUID gEfiGraphicsOutputProtocolGuid