#include <efilib.h>
#include <efiprot.h>
+int find_best_video_mode(void);
+int find_video_mode(int xres, int yres, int bpp);
+int set_video_mode(int mode);
+int cur_video_mode(void);
+void draw_box(int x, int y, int w, int h, int r, int g, int b);
+int mask_to_shift(unsigned int mask);
+int mask_to_bpp(unsigned int mask);
+int mode_bpp(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *minf);
+
+uint32_t *fb;
+int fb_width, fb_height;
+int scanwidth;
+int rshift, bshift, gshift;
+unsigned int rmask, bmask, gmask;
+EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
+
EFI_STATUS EFIAPI efi_main(EFI_HANDLE img, EFI_SYSTEM_TABLE *systab)
{
+ int mode;
+ EFI_HANDLE *handles;
+ unsigned long nhandles = 0;
+ unsigned long misize;
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mi;
+ SIMPLE_TEXT_OUTPUT_INTERFACE *sout;
+
InitializeLib(img, systab);
+
+ sout = systab->ConOut;
+ uefi_call_wrapper(sout->ClearScreen, 1, sout);
Print(L"hello world\n");
+ LibLocateHandle(ByProtocol, &GraphicsOutputProtocol, 0, &nhandles, 0);
+ if(nhandles <= 0) {
+ Print(L"Failed to locate any graphics output devices\n");
+ goto end;
+ }
+ if(!(handles = AllocatePool(nhandles))) {
+ Print(L"Failed to allocate memory for %lu handles\n", nhandles);
+ goto end;
+ }
+ Print(L"Found %lu graphics output devices\n", nhandles);
+ if(LibLocateHandle(ByProtocol, &GraphicsOutputProtocol, 0, &nhandles, &handles) != 0) {
+ Print(L"Failed to retreive graphics output device handles\n");
+ goto end;
+ }
+ if(uefi_call_wrapper(BS->HandleProtocol, 3, handles[0], &GraphicsOutputProtocol, &gop) != 0) {
+ Print(L"Failed to retreive graphics output protocol structure\n");
+ goto end;
+ }
+
+
+ if((mode = find_best_video_mode()) == -1) {
+ Print(L"Failed to find best video mode, leaving as is\n");
+ } else {
+ if(set_video_mode(mode) == -1) {
+ Print(L"Failed to change video mode, leaving as is\n");
+ }
+ }
+ uefi_call_wrapper(gop->QueryMode, 4, gop, gop->Mode->Mode, &misize, &mi);
+
+ fb_width = mi->HorizontalResolution;
+ fb_height = mi->VerticalResolution;
+ scanwidth = mi->PixelsPerScanLine;
+
+ switch(mi->PixelFormat) {
+ case PixelRedGreenBlueReserved8BitPerColor:
+ rshift = 0;
+ gshift = 8;
+ bshift = 16;
+ rmask = 0xff;
+ gmask = 0xff00;
+ bmask = 0xff0000;
+ break;
+
+ case PixelBlueGreenRedReserved8BitPerColor:
+ rshift = 16;
+ gshift = 8;
+ bshift = 0;
+ rmask = 0xff0000;
+ gmask = 0xff00;
+ bmask = 0xff;
+ break;
+
+ case PixelBitMask:
+ rmask = mi->PixelInformation.RedMask;
+ gmask = mi->PixelInformation.GreenMask;
+ bmask = mi->PixelInformation.BlueMask;
+ rshift = mask_to_shift(rmask);
+ gshift = mask_to_shift(gmask);
+ bshift = mask_to_shift(bmask);
+ break;
+
+ default:
+ Print(L"Unsupported pixel format\n");
+ goto end;
+ }
+ fb = (uint32_t*)gop->Mode->FrameBufferBase;
+
+ Print(L"Video mode %ux%u %dbpp (fmt id: %u)\n", mi->HorizontalResolution,
+ mi->VerticalResolution, mask_to_bpp(rmask | gmask | bmask), (unsigned int)mi->PixelFormat);
+
+ draw_box(100, 100, 200, 200, 255, 128, 64);
+
+end:
asm volatile("cli");
for(;;) {
asm volatile("hlt");
return EFI_SUCCESS;
}
+
+static uint32_t calc_score(int x, int y, int bpp)
+{
+ uint32_t a = y >> 5;
+ uint32_t b = x >> 5;
+
+ if(a > 0xfff) a = 0xfff;
+ if(b > 0xfff) b = 0xfff;
+
+ return (a << 20) | (b << 8) | (bpp & 0xff);
+}
+
+int find_best_video_mode(void)
+{
+ int i, nmodes, w, h;
+ int score, best_score = 0, best_mode = -1;
+ unsigned long misize;
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mi;
+
+ nmodes = gop->Mode->MaxMode;
+ for(i=0; i<nmodes; i++) {
+ uefi_call_wrapper(gop->QueryMode, 4, gop, i, &misize, &mi);
+ w = mi->HorizontalResolution;
+ h = mi->VerticalResolution;
+
+ score = calc_score(w, h, mode_bpp(mi));
+ if(score > best_score) {
+ best_score = score;
+ best_mode = i;
+ }
+ }
+ return best_mode;
+}
+
+int find_video_mode(int xres, int yres, int bpp)
+{
+ int i, nmodes, w, h;
+ unsigned long misize;
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *mi;
+
+ nmodes = gop->Mode->MaxMode;
+ for(i=0; i<nmodes; i++) {
+ uefi_call_wrapper(gop->QueryMode, 4, gop, i, &misize, &mi);
+ w = mi->HorizontalResolution;
+ h = mi->VerticalResolution;
+ if(w == xres && h == yres && mode_bpp(mi) >= bpp) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+int set_video_mode(int mode)
+{
+ if(uefi_call_wrapper(gop->SetMode, 2, gop, mode) != 0) {
+ return -1;
+ }
+ return 0;
+}
+
+int cur_video_mode(void)
+{
+ return gop->Mode->Mode;
+}
+
+void draw_box(int x, int y, int w, int h, int r, int g, int b)
+{
+ int i, j;
+ uint32_t pixcol;
+ uint32_t *pptr = fb + y * scanwidth + x;
+
+ pixcol = (((uint32_t)r << rshift) & rmask) |
+ (((uint32_t)g << gshift) & gmask) |
+ (((uint32_t)b << bshift) & bmask);
+
+ for(i=0; i<h; i++) {
+ for(j=0; j<w; j++) {
+ *pptr++ = pixcol;
+ }
+ pptr += scanwidth - w;
+ }
+}
+
+int mask_to_shift(unsigned int mask)
+{
+ int res = 0;
+ while((mask & 1) == 0) {
+ mask >>= 1;
+ res++;
+ }
+ return res;
+}
+
+int mask_to_bpp(unsigned int mask)
+{
+ int res = 0;
+
+ while(mask) {
+ mask >>= 1;
+ res++;
+ }
+ return res;
+}
+
+int mode_bpp(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *minf)
+{
+ switch(minf->PixelFormat) {
+ case PixelRedGreenBlueReserved8BitPerColor:
+ case PixelBlueGreenRedReserved8BitPerColor:
+ return 24;
+
+ case PixelBitMask:
+ return mask_to_bpp(minf->PixelInformation.RedMask | minf->PixelInformation.GreenMask |
+ minf->PixelInformation.BlueMask);
+
+ default:
+ break;
+ }
+ return 0;
+}