1 /* $NetBSD: lfbgrid.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 #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 (defined (__riscv) && __riscv_xlen == 64) 58 UINT64 FrameBufferAddr; 59 #elif defined(__i386__) || defined(__arm__) 60 UINT32 FrameBufferAddr; 61 #else 62 #error YOUR ARCH HERE 63 #endif 64 65 if (gop->Mode) { 66 imax = gop->Mode->MaxMode; 67 } else { 68 Print(L"gop->Mode is NULL\n"); 69 return; 70 } 71 72 for (i = 0; i < imax; i++) { 73 UINTN SizeOfInfo; 74 rc = uefi_call_wrapper(gop->QueryMode, 4, gop, i, &SizeOfInfo, 75 &info); 76 if (rc == EFI_NOT_STARTED) { 77 Print(L"gop->QueryMode() returned %r\n", rc); 78 Print(L"Trying to start GOP with SetMode().\n"); 79 rc = uefi_call_wrapper(gop->SetMode, 2, gop, 80 gop->Mode ? gop->Mode->Mode : 0); 81 rc = uefi_call_wrapper(gop->QueryMode, 4, gop, i, 82 &SizeOfInfo, &info); 83 } 84 85 if (EFI_ERROR(rc)) { 86 Print(L"%d: Bad response from QueryMode: %r (%d)\n", 87 i, rc, rc); 88 continue; 89 } 90 91 if (CompareMem(info, gop->Mode->Info, sizeof (*info))) 92 continue; 93 94 NumPixels = info->VerticalResolution * info->PixelsPerScanLine; 95 BufferSize = NumPixels * sizeof(UINT32); 96 if (BufferSize == gop->Mode->FrameBufferSize) { 97 CopySize = BufferSize; 98 } else { 99 CopySize = BufferSize < gop->Mode->FrameBufferSize ? 100 BufferSize : gop->Mode->FrameBufferSize; 101 Print(L"height * pitch * pixelsize = %lu buf fb size is %lu; using %lu\n", 102 BufferSize, gop->Mode->FrameBufferSize, CopySize); 103 } 104 105 PixelBuffer = AllocatePool(BufferSize); 106 if (!PixelBuffer) { 107 Print(L"Allocation of 0x%08lx bytes failed.\n", 108 sizeof(UINT32) * NumPixels); 109 return; 110 } 111 112 fill_boxes(PixelBuffer, info->HorizontalResolution, 113 info->VerticalResolution, info->PixelsPerScanLine, 114 info->PixelFormat, info->PixelInformation); 115 116 if (info->PixelFormat == PixelBltOnly) { 117 Print(L"No linear framebuffer on this device.\n"); 118 return; 119 } 120 #if defined(__x86_64__) || defined(__aarch64__) || \ 121 (defined (__riscv) && __riscv_xlen == 64) 122 FrameBufferAddr = (UINT64)gop->Mode->FrameBufferBase; 123 #elif defined(__i386__) || defined(__arm__) 124 FrameBufferAddr = (UINT32)(UINT64)gop->Mode->FrameBufferBase; 125 #else 126 #error YOUR ARCH HERE 127 #endif 128 129 CopyMem((VOID *)FrameBufferAddr, PixelBuffer, CopySize); 130 return; 131 } 132 Print(L"Never found the active video mode?\n"); 133 } 134 135 static EFI_STATUS 136 SetWatchdog(UINTN seconds) 137 { 138 EFI_STATUS rc; 139 rc = uefi_call_wrapper(BS->SetWatchdogTimer, 4, seconds, 0x1ffff, 140 0, NULL); 141 if (EFI_ERROR(rc)) { 142 CHAR16 Buffer[64]; 143 StatusToString(Buffer, rc); 144 Print(L"Bad response from QueryMode: %s (%d)\n", Buffer, rc); 145 } 146 return rc; 147 } 148 149 EFI_STATUS 150 efi_main (EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab) 151 { 152 EFI_STATUS rc; 153 EFI_GRAPHICS_OUTPUT_PROTOCOL *gop; 154 155 InitializeLib(image_handle, systab); 156 157 SetWatchdog(10); 158 159 rc = LibLocateProtocol(&GraphicsOutputProtocol, (void **)&gop); 160 if (EFI_ERROR(rc)) { 161 Print(L"Could not locate GOP: %r\n", rc); 162 return rc; 163 } 164 165 if (!gop) { 166 Print(L"LocateProtocol(GOP, &gop) returned %r but GOP is NULL\n", rc); 167 return EFI_UNSUPPORTED; 168 } 169 170 draw_boxes(gop); 171 172 SetWatchdog(0); 173 return EFI_SUCCESS; 174 } 175