Home | History | Annotate | Line # | Download | only in apps
      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