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