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