lfbgrid.c revision 1.1 1 /* $NetBSD: lfbgrid.c,v 1.1 2018/08/16 18:17:47 jmcneill Exp $ */
2
3 #include <efi.h>
4 #include <efilib.h>
5
6 extern EFI_GUID GraphicsOutputProtocol;
7
8 #define be32_to_cpu(x) __builtin_bswap32(x)
9
10 static void
11 fill_boxes(UINT32 *PixelBuffer, UINT32 Width, UINT32 Height, UINT32 Pitch,
12 EFI_GRAPHICS_PIXEL_FORMAT Format, EFI_PIXEL_BITMASK Info )
13 {
14 UINT32 Red, Green;
15 UINT32 y, x, color;
16
17 switch(Format) {
18 case PixelRedGreenBlueReserved8BitPerColor:
19 Red = be32_to_cpu(0xff000000);
20 Green = be32_to_cpu(0x00ff0000);
21 break;
22 case PixelBlueGreenRedReserved8BitPerColor:
23 Red = be32_to_cpu(0x0000ff00);
24 Green = be32_to_cpu(0x00ff0000);
25 break;
26 case PixelBitMask:
27 Red = Info.RedMask;
28 Green = Info.GreenMask;
29 break;
30 case PixelBltOnly:
31 return;
32 default:
33 Print(L"Invalid pixel format\n");
34 return;
35 }
36
37 for (y = 0; y < Height; y++) {
38 color = ((y / 32) % 2 == 0) ? Red : Green;
39 for (x = 0; x < Width; x++) {
40 if (x % 32 == 0 && x != 0)
41 color = (color == Red) ? Green : Red;
42 PixelBuffer[y * Pitch + x] = color;
43 }
44 }
45 }
46
47 static void
48 draw_boxes(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop)
49 {
50 int i, imax;
51 EFI_STATUS rc;
52 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info;
53 UINTN NumPixels;
54 UINT32 *PixelBuffer;
55 UINT32 CopySize, BufferSize;
56 #if defined(__x86_64__) || defined(__aarch64__)
57 UINT64 FrameBufferAddr;
58 #elif defined(__i386__) || defined(__arm__)
59 UINT32 FrameBufferAddr;
60 #else
61 #error YOUR ARCH HERE
62 #endif
63
64 if (gop->Mode) {
65 imax = gop->Mode->MaxMode;
66 } else {
67 Print(L"gop->Mode is NULL\n");
68 return;
69 }
70
71 for (i = 0; i < imax; i++) {
72 UINTN SizeOfInfo;
73 rc = uefi_call_wrapper(gop->QueryMode, 4, gop, i, &SizeOfInfo,
74 &info);
75 if (EFI_ERROR(rc) && rc == EFI_NOT_STARTED) {
76 Print(L"gop->QueryMode() returned %r\n", rc);
77 Print(L"Trying to start GOP with SetMode().\n");
78 rc = uefi_call_wrapper(gop->SetMode, 2, gop,
79 gop->Mode ? gop->Mode->Mode : 0);
80 rc = uefi_call_wrapper(gop->QueryMode, 4, gop, i,
81 &SizeOfInfo, &info);
82 }
83
84 if (EFI_ERROR(rc)) {
85 Print(L"%d: Bad response from QueryMode: %r (%d)\n",
86 i, rc, rc);
87 continue;
88 }
89
90 if (CompareMem(info, gop->Mode->Info, sizeof (*info)))
91 continue;
92
93 NumPixels = info->VerticalResolution * info->PixelsPerScanLine;
94 BufferSize = NumPixels * sizeof(UINT32);
95 if (BufferSize == gop->Mode->FrameBufferSize) {
96 CopySize = BufferSize;
97 } else {
98 CopySize = BufferSize < gop->Mode->FrameBufferSize ?
99 BufferSize : gop->Mode->FrameBufferSize;
100 Print(L"height * pitch * pixelsize = %lu buf fb size is %lu; using %lu\n",
101 BufferSize, gop->Mode->FrameBufferSize, CopySize);
102 }
103
104 PixelBuffer = AllocatePool(BufferSize);
105 if (!PixelBuffer) {
106 Print(L"Allocation of 0x%08lx bytes failed.\n",
107 sizeof(UINT32) * NumPixels);
108 return;
109 }
110
111 fill_boxes(PixelBuffer, info->HorizontalResolution,
112 info->VerticalResolution, info->PixelsPerScanLine,
113 info->PixelFormat, info->PixelInformation);
114
115 if (info->PixelFormat == PixelBltOnly) {
116 Print(L"No linear framebuffer on this device.\n");
117 return;
118 }
119 #if defined(__x86_64__) || defined(__aarch64__)
120 FrameBufferAddr = (UINT64)gop->Mode->FrameBufferBase;
121 #elif defined(__i386__) || defined(__arm__)
122 FrameBufferAddr = (UINT32)(UINT64)gop->Mode->FrameBufferBase;
123 #else
124 #error YOUR ARCH HERE
125 #endif
126
127 CopyMem((VOID *)FrameBufferAddr, PixelBuffer, CopySize);
128 return;
129 }
130 Print(L"Never found the active video mode?\n");
131 }
132
133 static EFI_STATUS
134 SetWatchdog(UINTN seconds)
135 {
136 EFI_STATUS rc;
137 rc = uefi_call_wrapper(BS->SetWatchdogTimer, 4, seconds, 0x1ffff,
138 0, NULL);
139 if (EFI_ERROR(rc)) {
140 CHAR16 Buffer[64];
141 StatusToString(Buffer, rc);
142 Print(L"Bad response from QueryMode: %s (%d)\n", Buffer, rc);
143 }
144 return rc;
145 }
146
147 EFI_STATUS
148 efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab)
149 {
150 EFI_STATUS rc;
151 EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
152
153 InitializeLib(image_handle, systab);
154
155 SetWatchdog(10);
156
157 rc = LibLocateProtocol(&GraphicsOutputProtocol, (void **)&gop);
158 if (EFI_ERROR(rc)) {
159 Print(L"Could not locate GOP: %r\n", rc);
160 return rc;
161 }
162
163 if (!gop) {
164 Print(L"LocateProtocol(GOP, &gop) returned %r but GOP is NULL\n", rc);
165 return EFI_UNSUPPORTED;
166 }
167
168 draw_boxes(gop);
169
170 SetWatchdog(0);
171 return EFI_SUCCESS;
172 }
173