From a8c98530657b7e6a9b6e9e3ca271a310eebd31b7 Mon Sep 17 00:00:00 2001 From: PoliEcho Date: Tue, 12 Aug 2025 13:56:42 +0200 Subject: [PATCH] add basic drawing functions --- .gitignore | 4 +- README.md | 5 ++ UEFI_fireworks.dsc | 3 + build.sh | 2 +- src/UEFI_fireworks/UEFI_fireworks.inf | 2 + src/UEFI_fireworks/UefiMain.c | 26 ++++++--- src/UEFI_fireworks/const.h | 6 ++ src/UEFI_fireworks/drawing.c | 80 +++++++++++++++++++++++++++ src/UEFI_fireworks/drawing.h | 5 ++ src/UEFI_fireworks/global.h | 4 ++ src/UEFI_fireworks/macros.h | 6 ++ test.sh | 10 ++++ 12 files changed, 142 insertions(+), 11 deletions(-) create mode 100644 README.md create mode 100644 src/UEFI_fireworks/const.h create mode 100644 src/UEFI_fireworks/drawing.c create mode 100644 src/UEFI_fireworks/drawing.h create mode 100644 src/UEFI_fireworks/global.h create mode 100644 src/UEFI_fireworks/macros.h create mode 100755 test.sh diff --git a/.gitignore b/.gitignore index d163863..4c917f3 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ -build/ \ No newline at end of file +build/ +.cache/ +compile_commands.json \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..44ca59a --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +Arch uefi_run fix: sudo ln -s /usr/share/edk2/x64/OVMF_CODE.4m.fd /usr/share/qemu/OVMF.fd + +cd edk2 +source edksetup.sh +make -C BaseTools # if first run \ No newline at end of file diff --git a/UEFI_fireworks.dsc b/UEFI_fireworks.dsc index e0d44ed..0387352 100644 --- a/UEFI_fireworks.dsc +++ b/UEFI_fireworks.dsc @@ -22,6 +22,9 @@ PrintLib|edk2/MdePkg/Library/BasePrintLib/BasePrintLib.inf PcdLib|edk2/MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf RegisterFilterLib|edk2/MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.inf StackCheckLib|edk2/MdePkg/Library/StackCheckLibNull/StackCheckLibNull.inf +TimerLib|edk2/MdePkg/Library/SecPeiDxeTimerLibCpu/SecPeiDxeTimerLibCpu.inf +IoLib|edk2/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf + [Components] diff --git a/build.sh b/build.sh index e9053e8..9c3028f 100755 --- a/build.sh +++ b/build.sh @@ -2,4 +2,4 @@ export PACKAGES_PATH=$PWD:$PWD/edk2 build -a X64 -t GCC5 -p UEFI_fireworks.dsc mkdir -p build -cp edk2/Build/UEFI_fireworks/DEBUG_GCC5/X64/UEFI_fireworks.efi build/ \ No newline at end of file +cp edk2/Build/UEFI_fireworks/DEBUG_GCC5/X64/UEFI_fireworks.efi build/ diff --git a/src/UEFI_fireworks/UEFI_fireworks.inf b/src/UEFI_fireworks/UEFI_fireworks.inf index 23a20bf..547cfd2 100644 --- a/src/UEFI_fireworks/UEFI_fireworks.inf +++ b/src/UEFI_fireworks/UEFI_fireworks.inf @@ -8,6 +8,7 @@ [Sources] UefiMain.c + drawing.c [Packages] edk2/MdePkg/MdePkg.dec @@ -23,6 +24,7 @@ UefiRuntimeServicesTableLib DebugLib PrintLib + TimerLib [Protocols] diff --git a/src/UEFI_fireworks/UefiMain.c b/src/UEFI_fireworks/UefiMain.c index 9fa0a7c..b832ce0 100644 --- a/src/UEFI_fireworks/UefiMain.c +++ b/src/UEFI_fireworks/UefiMain.c @@ -1,7 +1,14 @@ +#include "drawing.h" +#include "global.h" +#include #include #include +#include #include +EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput = NULL; +EFI_GRAPHICS_OUTPUT_BLT_PIXEL *framebuffer = NULL; + EFI_STATUS EFIAPI UefiMain(IN EFI_HANDLE imgHandle, IN EFI_SYSTEM_TABLE *sysTable) { gST = sysTable; @@ -11,18 +18,19 @@ EFI_STATUS EFIAPI UefiMain(IN EFI_HANDLE imgHandle, // UEFI apps automatically exit after 5 minutes. Stop that here gBS->SetWatchdogTimer(0, 0, 0, NULL); - Print(L"Hello, world!\r\n"); + // get screen size + UINTN Columns; + UINTN Rows; - // Allocate a string - CHAR16 *str = NULL; - gBS->AllocatePool(EfiLoaderData, 36, (VOID **)&str); + gST->ConOut->QueryMode(gST->ConOut, gST->ConOut->Mode->Mode, &Columns, &Rows); - // Copy over a string - CHAR16 *str2 = L"Allocated string\r\n"; - gBS->CopyMem((VOID *)str, (VOID *)str2, 36); + gBS->LocateProtocol(&gEfiGraphicsOutputProtocolGuid, NULL, + (VOID **)&GraphicsOutput); - Print(str); - gBS->FreePool(str); + framebuffer = + (EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)GraphicsOutput->Mode->FrameBufferBase; + + clear_screen(GraphicsOutput); return EFI_SUCCESS; } diff --git a/src/UEFI_fireworks/const.h b/src/UEFI_fireworks/const.h new file mode 100644 index 0000000..4d28c3a --- /dev/null +++ b/src/UEFI_fireworks/const.h @@ -0,0 +1,6 @@ +#pragma once +#include "macros.h" +#include + +EFI_GRAPHICS_OUTPUT_BLT_PIXEL night_sky = + COLOR_FROM_HEX(0x11095e); // this cannot be const becose EDK2 said so diff --git a/src/UEFI_fireworks/drawing.c b/src/UEFI_fireworks/drawing.c new file mode 100644 index 0000000..3043a77 --- /dev/null +++ b/src/UEFI_fireworks/drawing.c @@ -0,0 +1,80 @@ +#include "Library/UefiLib.h" +#include "ProcessorBind.h" +#include "const.h" +#include "global.h" +#include "macros.h" +#include +#include + +void draw_pixel(const UINT32 x, const UINT32 y, + const EFI_GRAPHICS_OUTPUT_BLT_PIXEL pixel) { + UINTN framebuffer_offset = + (y * GraphicsOutput->Mode->Info->PixelsPerScanLine) + x; + if (framebuffer_offset >= GraphicsOutput->Mode->FrameBufferSize) { + Print(L"Atepted out of bounds write to framebuffer\r\n"); + Exit(RETURN_WARN_BUFFER_TOO_SMALL); + } + + framebuffer[framebuffer_offset] = pixel; +} + +// uses Mid-Point Circle Drawing Algorithm +// inspired by +// https://www.geeksforgeeks.org/dsa/mid-point-circle-drawing-algorithm/ +void draw_circle(int xc, int yc, int r, + const EFI_GRAPHICS_OUTPUT_BLT_PIXEL color) { + int x = r, y = 0; + draw_pixel(x + xc, y + yc, color); + + if (r > 0) { + draw_pixel(x + xc, -y + yc, color); + draw_pixel(y + xc, x + yc, color); + draw_pixel(-y + xc, x + yc, color); + } + + int P = 1 - r; + while (x > y) { + y++; + + if (P <= 0) + P = P + 2 * y + 1; + + else { + x--; + P = P + 2 * y - 2 * x + 1; + } + + if (x < y) + break; + + draw_pixel(x + xc, y + yc, color); + draw_pixel(-x + xc, y + yc, color); + draw_pixel(x + xc, -y + yc, color); + draw_pixel(-x + xc, -y + yc, color); + + if (x != y) { + draw_pixel(y + xc, x + yc, color); + draw_pixel(-y + xc, x + yc, color); + draw_pixel(y + xc, -x + yc, color); + draw_pixel(-y + xc, -x + yc, color); + } + } +} + +void clear_screen() { + // fill screen + if (GraphicsOutput != NULL) { + GraphicsOutput->Blt( + GraphicsOutput, + &night_sky, // BltBuffer + EfiBltVideoFill, // BltOperation + 0, // SourceX + 0, // SourceY + 0, // DestinationX + 0, // DestinationY + GraphicsOutput->Mode->Info->HorizontalResolution, // Width + GraphicsOutput->Mode->Info->VerticalResolution, // Height + 0 // Delta (not used for fill operations) + ); + } +} diff --git a/src/UEFI_fireworks/drawing.h b/src/UEFI_fireworks/drawing.h new file mode 100644 index 0000000..507ba81 --- /dev/null +++ b/src/UEFI_fireworks/drawing.h @@ -0,0 +1,5 @@ +#pragma once +#include +void draw_circle(int xc, int yc, int r, + const EFI_GRAPHICS_OUTPUT_BLT_PIXEL color); +void clear_screen(EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput); \ No newline at end of file diff --git a/src/UEFI_fireworks/global.h b/src/UEFI_fireworks/global.h new file mode 100644 index 0000000..6e5a18d --- /dev/null +++ b/src/UEFI_fireworks/global.h @@ -0,0 +1,4 @@ +#pragma once +#include +extern EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput; +extern EFI_GRAPHICS_OUTPUT_BLT_PIXEL *framebuffer; \ No newline at end of file diff --git a/src/UEFI_fireworks/macros.h b/src/UEFI_fireworks/macros.h new file mode 100644 index 0000000..b93b142 --- /dev/null +++ b/src/UEFI_fireworks/macros.h @@ -0,0 +1,6 @@ +#pragma once +#define COLOR_FROM_HEX(hex) \ + {.Blue = (hex) & 0xFF, \ + .Green = ((hex) >> 8) & 0xFF, \ + .Red = ((hex) >> 16) & 0xFF, \ + .Reserved = 0} diff --git a/test.sh b/test.sh new file mode 100755 index 0000000..ae6df10 --- /dev/null +++ b/test.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +cp /usr/share/edk2/x64/OVMF_VARS.4m.fd ./my_ovmf_vars.fd + +qemu-system-x86_64 \ + -machine type=q35,accel=kvm \ + -drive if=pflash,format=raw,readonly=on,file=/usr/share/edk2/x64/OVMF_CODE.4m.fd \ + -drive if=pflash,format=raw,file=./my_ovmf_vars.fd \ + -hda fat:rw:$(dirname build/UEFI_fireworks.efi) +rm ./my_ovmf_vars.fd