xref: /netbsd-src/sys/external/bsd/gnu-efi/dist/apps/bltgrid.c (revision d16b7486a53dcb8072b60ec6fcb4373a2d0c27b7)
1 /*	$NetBSD: bltgrid.c,v 1.1.1.2 2021/09/30 18:50:09 jmcneill Exp $	*/
2 
3 #include <efi.h>
4 #include <efilib.h>
5 
6 extern EFI_GUID GraphicsOutputProtocol;
7 
8 static void
9 fill_boxes(UINT32 *PixelBuffer, UINT32 Width, UINT32 Height)
10 {
11 	UINT32 y, x = 0;
12 	/*
13 	 * This assums BGRR, but it doesn't really matter; we pick red and
14 	 * green so it'll just be blue/green if the pixel format is backwards.
15 	 */
16 	EFI_GRAPHICS_OUTPUT_BLT_PIXEL Red = {0, 0, 0xff, 0},
17 				      Green = {0, 0xff, 0, 0},
18 				      *Color;
19 
20 	for (y = 0; y < Height; y++) {
21 		Color = ((y / 32) % 2 == 0) ? &Red : &Green;
22 		for (x = 0; x < Width; x++) {
23 			if (x % 32 == 0 && x != 0)
24 				Color = (Color == &Red) ? &Green : &Red;
25 			PixelBuffer[y * Width + x] = *(UINT32 *)Color;
26 		}
27 	}
28 }
29 
30 static void
31 draw_boxes(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop)
32 {
33 	int i, imax;
34 	EFI_STATUS rc;
35 	EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info;
36 	UINTN NumPixels;
37 	UINT32 *PixelBuffer;
38 	UINT32 BufferSize;
39 
40 	if (gop->Mode) {
41 		imax = gop->Mode->MaxMode;
42 	} else {
43 		Print(L"gop->Mode is NULL\n");
44 		return;
45 	}
46 
47 	for (i = 0; i < imax; i++) {
48 		UINTN SizeOfInfo;
49 		rc = uefi_call_wrapper(gop->QueryMode, 4, gop, i, &SizeOfInfo,
50 					&info);
51 		if (rc == EFI_NOT_STARTED) {
52 			Print(L"gop->QueryMode() returned %r\n", rc);
53 			Print(L"Trying to start GOP with SetMode().\n");
54 			rc = uefi_call_wrapper(gop->SetMode, 2, gop,
55 				gop->Mode ? gop->Mode->Mode : 0);
56 			rc = uefi_call_wrapper(gop->QueryMode, 4, gop, i,
57 				&SizeOfInfo, &info);
58 		}
59 
60 		if (EFI_ERROR(rc)) {
61 			Print(L"%d: Bad response from QueryMode: %r (%d)\n",
62 			      i, rc, rc);
63 			continue;
64 		}
65 
66 		if (CompareMem(info, gop->Mode->Info, sizeof (*info)))
67 			continue;
68 
69 		NumPixels = info->VerticalResolution * info->HorizontalResolution;
70 		BufferSize = NumPixels * sizeof(UINT32);
71 
72 		PixelBuffer = AllocatePool(BufferSize);
73 		if (!PixelBuffer) {
74 			Print(L"Allocation of 0x%08lx bytes failed.\n",
75 			      sizeof(UINT32) * NumPixels);
76 			return;
77 		}
78 
79 		fill_boxes(PixelBuffer,
80 			   info->HorizontalResolution, info->VerticalResolution);
81 
82 		uefi_call_wrapper(gop->Blt, 10, gop,
83 				  (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)PixelBuffer,
84 				  EfiBltBufferToVideo,
85 				  0, 0, 0, 0,
86 				  info->HorizontalResolution,
87 				  info->VerticalResolution,
88 				  0);
89 		FreePool(PixelBuffer);
90 		return;
91 	}
92 	Print(L"Never found the active video mode?\n");
93 }
94 
95 static EFI_STATUS
96 SetWatchdog(UINTN seconds)
97 {
98 	EFI_STATUS rc;
99 	rc = uefi_call_wrapper(BS->SetWatchdogTimer, 4, seconds, 0x1ffff,
100 				0, NULL);
101 	if (EFI_ERROR(rc)) {
102 		CHAR16 Buffer[64];
103 		StatusToString(Buffer, rc);
104 		Print(L"Bad response from QueryMode: %s (%d)\n", Buffer, rc);
105 	}
106 	return rc;
107 }
108 
109 EFI_STATUS
110 efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab)
111 {
112 	EFI_STATUS rc;
113 	EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
114 
115 	InitializeLib(image_handle, systab);
116 
117 	SetWatchdog(10);
118 
119 	rc = LibLocateProtocol(&GraphicsOutputProtocol, (void **)&gop);
120 	if (EFI_ERROR(rc)) {
121 		Print(L"Could not locate GOP: %r\n", rc);
122 		return rc;
123 	}
124 
125 	if (!gop) {
126 		Print(L"LocateProtocol(GOP, &gop) returned %r but GOP is NULL\n", rc);
127 		return EFI_UNSUPPORTED;
128 	}
129 
130 	draw_boxes(gop);
131 
132 	SetWatchdog(0);
133 	return EFI_SUCCESS;
134 }
135