1#include <efi.h>
2#include <efilib.h>
3
4extern EFI_GUID GraphicsOutputProtocol;
5
6static int memcmp(const void *s1, const void *s2, UINTN n)
7{
8	const unsigned char *c1 = s1, *c2 = s2;
9	int d = 0;
10
11	if (!s1 && !s2)
12		return 0;
13	if (s1 && !s2)
14		return 1;
15	if (!s1 && s2)
16		return -1;
17
18	while (n--) {
19		d = (int)*c1++ - (int)*c2++;
20		if (d)
21			break;
22	}
23	return d;
24}
25
26static void
27print_modes(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop)
28{
29	int i, imax;
30	EFI_STATUS rc;
31
32	imax = gop->Mode->MaxMode;
33
34	Print(L"GOP reports MaxMode %d\n", imax);
35	for (i = 0; i < imax; i++) {
36		EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info;
37		UINTN SizeOfInfo;
38		rc = uefi_call_wrapper(gop->QueryMode, 4, gop, i, &SizeOfInfo,
39					&info);
40		if (EFI_ERROR(rc) && rc == EFI_NOT_STARTED) {
41			rc = uefi_call_wrapper(gop->SetMode, 2, gop,
42				gop->Mode->Mode);
43			rc = uefi_call_wrapper(gop->QueryMode, 4, gop, i,
44				&SizeOfInfo, &info);
45		}
46
47		if (EFI_ERROR(rc)) {
48			CHAR16 Buffer[64];
49			StatusToString(Buffer, rc);
50			Print(L"%d: Bad response from QueryMode: %s (%d)\n",
51				i, Buffer, rc);
52			continue;
53		}
54		Print(L"%c%d: %dx%d ", memcmp(info,gop->Mode->Info,sizeof(*info)) == 0 ? '*' : ' ', i,
55			info->HorizontalResolution,
56			info->VerticalResolution);
57		switch(info->PixelFormat) {
58			case PixelRedGreenBlueReserved8BitPerColor:
59				Print(L"RGBR");
60				break;
61			case PixelBlueGreenRedReserved8BitPerColor:
62				Print(L"BGRR");
63				break;
64			case PixelBitMask:
65				Print(L"R:%08x G:%08x B:%08x X:%08x",
66					info->PixelInformation.RedMask,
67					info->PixelInformation.GreenMask,
68					info->PixelInformation.BlueMask,
69					info->PixelInformation.ReservedMask);
70				break;
71			case PixelBltOnly:
72				Print(L"(blt only)");
73				break;
74			default:
75				Print(L"(Invalid pixel format)");
76				break;
77		}
78		Print(L" pitch %d\n", info->PixelsPerScanLine);
79	}
80}
81
82static EFI_STATUS
83SetWatchdog(UINTN seconds)
84{
85	EFI_STATUS rc;
86	rc = uefi_call_wrapper(BS->SetWatchdogTimer, 4, seconds, 0x1ffff,
87				0, NULL);
88	if (EFI_ERROR(rc)) {
89		CHAR16 Buffer[64];
90		StatusToString(Buffer, rc);
91		Print(L"Bad response from QueryMode: %s (%d)\n", Buffer, rc);
92	}
93	return rc;
94}
95
96EFI_STATUS
97efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab)
98{
99	EFI_STATUS rc;
100	EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
101
102	InitializeLib(image_handle, systab);
103
104	SetWatchdog(10);
105
106	rc = LibLocateProtocol(&GraphicsOutputProtocol, (void **)&gop);
107	if (EFI_ERROR(rc))
108		return rc;
109
110	print_modes(gop);
111
112	SetWatchdog(0);
113	return EFI_SUCCESS;
114}
115