Compare commits

...

13 Commits

Author SHA1 Message Date
PoliEcho 36a7c9066a misc changes 2025-08-19 16:38:32 +02:00
PoliEcho 9b768a4e9e README and build.sh changes 2025-08-19 16:35:16 +02:00
PoliEcho 868d27cecb update edk2 2025-08-18 23:16:58 +02:00
PoliEcho c72a80832b forgot to commit README 2025-08-18 21:05:24 +02:00
PoliEcho 54a54de423 enhance build script 2025-08-18 21:05:04 +02:00
PoliEcho 8af36091ba add input 2025-08-18 20:47:56 +02:00
PoliEcho fa35f79e34 addtions to test script 2025-08-17 15:14:07 +02:00
PoliEcho 83ef67ad28 fix rockets a bit 2025-08-17 14:37:30 +02:00
PoliEcho 91001e09ba add rockets 2025-08-16 16:29:37 +02:00
PoliEcho 8c53885621 update gitignore 2025-08-16 16:28:59 +02:00
PoliEcho 887e393d92 polishing a bit 2025-08-16 13:20:03 +02:00
PoliEcho f2ad30047a fix on real hardware 2025-08-15 19:26:00 +02:00
PoliEcho 24edc2599b addded simulation and fixed serial 2025-08-15 17:09:27 +02:00
22 changed files with 507 additions and 80 deletions
+1
View File
@@ -1,3 +1,4 @@
build/
.cache/
compile_commands.json
src/UEFI_fireworks/rocket.c
+56 -2
View File
@@ -1,5 +1,59 @@
Arch uefi_run fix: sudo ln -s /usr/share/edk2/x64/OVMF_CODE.4m.fd /usr/share/qemu/OVMF.fd
# UEFI Fireworks
## How to build
```bash
git submodule update --init --recursive
cd edk2
source edksetup.sh
make -C BaseTools # if first run
make -C BaseTools
cd ..
./build.sh
```
## How to use
### Download release
#### On Real hardware
if your have amd64(x86_64) UEFI computer
Download release and copy the UEFI_fireworks.efi to <USB_DRIVE>/EFI/BOOT/bootx64.efi case independent
#### On VM
run:
you will need OVMF firmware you can get it [here](https://qemu.weilnetz.de/test/ovmf/usr/share/OVMF/OVMF_CODE_4M.fd)
```bash
qemu-system-x86_64 -machine type=q35,accel=kvm -drive if=pflash,format=raw,readonly=on,file="$OVMF_CODE_PATH" -hda fat:rw:build -boot order=c -smp 4 -s -serial mon:stdio
```
### Build
#### On VM
you will need OVMF firmware you can get it [here](https://qemu.weilnetz.de/test/ovmf/usr/share/OVMF/OVMF_CODE_4M.fd)
run ```./test.sh $OVMF_CODE_PATH# only works on AMD64``` to run in VM using QEMU
#### On Real hardware
copy ```edk2/Build/UEFI_fireworks/DEBUG_GCC5/<YOUR ARCH>/UEFI_fireworks.efi``` to FAT32 or FAT16 USB at location:
| Architecture | Default Boot Path |
| ------------------- | ------------------------ |
| **x86_64 (AMD64)** | `/EFI/BOOT/BOOTX64.EFI` |
| **x86 (IA32)** | `/EFI/BOOT/BOOTIA32.EFI` |
| **ARM64 (AArch64)** | `/EFI/BOOT/BOOTAA64.EFI` |
| **ARM (32-bit)** | `/EFI/BOOT/BOOTARM.EFI` |
## Controling
| Key | Action | Note |
| ---------- | ------------ | ----------------------------------- |
| ARROW_UP | speed up | delays under 1ms may be unrelayable |
| ARROW_DOWN | slow down | max delay is about UINT32_MAXμs |
| PAGE_UP | speed up | 10x step |
| PAGE_DOWN | speed down | 10x step |
| Home key | reset speed | reset frame delay to 10ms |
| Delete key | clear screen | |
+8 -3
View File
@@ -17,16 +17,21 @@ MemoryAllocationLib|edk2/MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAlloca
DevicePathLib|edk2/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
UefiBootServicesTableLib|edk2/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
UefiRuntimeServicesTableLib|edk2/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
DebugLib|edk2/MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
DebugLib|edk2/MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
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
RngLib|edk2/MdePkg/Library/BaseRngLib/BaseRngLib.inf
SerialPortLib|edk2/MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf
DebugPrintErrorLevelLib|edk2/MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
LocalApicLib|edk2/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf
CpuLib|edk2/MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
UefiRuntimeServicesTableLib|edk2/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
TimerLib|edk2/MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
BmpSupportLib|edk2/MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf
SafeIntLib|edk2/MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
[Components]
src/UEFI_fireworks/UEFI_fireworks.inf
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
View File
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

+11 -3
View File
@@ -1,9 +1,17 @@
#!/bin/bash
export PACKAGES_PATH=$PWD:$PWD/edk2
magick assets/rocket_orig.bmp -type TrueColor -define bmp:format=bmp3 -compress None assets/rocket.bmp
xxd -i assets/rocket.bmp > src/UEFI_fireworks/rocket.c
if [ "$1" == "debug" ]; then
build -a X64 -t GCC5 -p UEFI_fireworks.dsc -b DEBUG
else
build -a X64 -t GCC5 -p UEFI_fireworks.dsc
build -a X64 -t GCC5 -p UEFI_fireworks.dsc -b RELEASE
fi
mkdir -p build/EFI/BOOT/
if [ "$1" == "debug" ]; then
cp -v $(find edk2/Build/UEFI_fireworks/DEBUG_GCC5/ -name "UEFI_fireworks.efi" -type f | head -1) build/
cp -v $(find edk2/Build/UEFI_fireworks/DEBUG_GCC5/ -name "UEFI_fireworks.efi" -type f | head -1) build/EFI/BOOT/BOOTX64.EFI
else
cp -v $(find edk2/Build/UEFI_fireworks/RELEASE_GCC5/ -name "UEFI_fireworks.efi" -type f | head -1) build/
cp -v $(find edk2/Build/UEFI_fireworks/RELEASE_GCC5/ -name "UEFI_fireworks.efi" -type f | head -1) build/EFI/BOOT/BOOTX64.EFI
fi
mkdir -p build
cp edk2/Build/UEFI_fireworks/DEBUG_GCC5/X64/UEFI_fireworks.efi build/
+1 -1
Submodule edk2 updated: 808f1f1f87...d46aa46c83
+5
View File
@@ -9,6 +9,9 @@
[Sources]
UefiMain.c
drawing.c
rng.c
time.c
rocket.c
[Packages]
edk2/MdePkg/MdePkg.dec
@@ -27,6 +30,8 @@
TimerLib
RngLib
SerialPortLib
UefiRuntimeServicesTableLib
BmpSupportLib
[Protocols]
gEfiRngProtocolGuid
+164 -47
View File
@@ -1,8 +1,12 @@
#include "Library/UefiApplicationEntryPoint.h"
#include "ProcessorBind.h"
#include "Protocol/SimpleTextIn.h"
#include "Uefi/UefiBaseType.h"
#include "const.h"
#include "drawing.h"
#include "global.h"
#include "macros.h"
#include "rng.h"
#include "time.h"
#include "types.h"
#include <Base.h>
#include <Library/BaseLib.h>
@@ -10,20 +14,26 @@
#include <Library/MemoryAllocationLib.h>
#include <Library/RngLib.h>
#include <Library/SerialPortLib.h>
#include <Library/TimerLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Protocol/GraphicsOutput.h>
#include <Uefi.h>
#include <stdint.h>
EFI_GRAPHICS_OUTPUT_BLT_PIXEL night_sky =
COLOR_FROM_HEX(0x090531); // this cannot be const becose EDK2 said so
#define DEFAULT_SLEEP_TIME 10000
firework_instance create_firework();
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) {
Print(L"Starting program\n");
gST = sysTable;
gBS = sysTable->BootServices;
gImageHandle = imgHandle;
gRT = sysTable->RuntimeServices;
// UEFI apps automatically exit after 5 minutes. Stop that here
gBS->SetWatchdogTimer(0, 0, 0, NULL);
@@ -37,63 +47,170 @@ EFI_STATUS EFIAPI UefiMain(IN EFI_HANDLE imgHandle,
gBS->LocateProtocol(&gEfiGraphicsOutputProtocolGuid, NULL,
(VOID **)&GraphicsOutput);
if (GraphicsOutput == NULL) {
Print(L"GraphicsOutput protocol not found!\n");
return EFI_NOT_FOUND;
}
framebuffer =
(EFI_GRAPHICS_OUTPUT_BLT_PIXEL *)GraphicsOutput->Mode->FrameBufferBase;
clear_screen(GraphicsOutput);
LIST_ENTRY firework_list;
InitializeListHead(&firework_list);
init_rng();
init_rocket_blt();
if (SerialPortInitialize() == RETURN_SUCCESS) {
SERIAL_PRINT("Serial initialized");
SERIAL_PRINT("Serial initialized\n");
} else {
Print(L"Failed to initialize Serial");
Exit(RETURN_DEVICE_ERROR);
Print(L"Failed to initialize Serial!\n");
}
SerialPortSetControl(EFI_SERIAL_CLEAR_TO_SEND |
EFI_SERIAL_DATA_TERMINAL_READY |
EFI_SERIAL_REQUEST_TO_SEND);
firework_instance *firework_array[UINT8_MAX];
gBS->SetMem(firework_array, sizeof(firework_array),
0); // make all pointers null
SERIAL_PRINT("DOES it work?\n");
Print(L"If you see this message for long time, timer does not work\n");
microsleep(1);
clear_screen();
UINTN sleep_time = DEFAULT_SLEEP_TIME;
while (TRUE) {
UINT32 random;
GetRandomNumber32(&random);
if (random % 6 == 0) {
UINT8 random;
fill_random_bytes(&random, sizeof(random));
if (random % 30 == 0) {
// spawn new firework
firework_node *new_firework_node =
AllocateZeroPool(sizeof(firework_node));
if (new_firework_node == NULL) {
firework_instance *new_firework_instence =
AllocateZeroPool(sizeof(firework_instance));
if (new_firework_instence == NULL) {
return EFI_OUT_OF_RESOURCES;
}
new_firework_node->Signature = FIREWORK_NODE_SIGNATURE;
GetRandomNumber32(&random);
new_firework_node->Firework.max_r =
random % 501; // so max number can be 500
for (UINT8 i = 0; i < ARRAY_SIZE(new_firework_node->Firework.color);
i++) {
GetRandomNumber32(
(UINT32 *)&new_firework_node->Firework.color[i]); // belive
new_firework_node->Firework.r[i] = 0;
}
new_firework_node->Firework.cleanup_r = 0;
GetRandomNumber32(&random);
new_firework_node->Firework.x =
random % GraphicsOutput->Mode->Info->HorizontalResolution + 1;
GetRandomNumber32(&random);
new_firework_node->Firework.y =
random % GraphicsOutput->Mode->Info->VerticalResolution + 1;
InsertTailList(&firework_list, &new_firework_node->Link);
*new_firework_instence = create_firework();
for (UINT8 i = 0; i < ARRAY_SIZE(firework_array); i++) {
if (firework_array[i] == NULL ||
firework_array[i]->status == INACTIVE) {
if (firework_array[i] != NULL) {
FreePool(firework_array[i]); // free firework
firework_array[i] = NULL;
}
firework_array[i] = new_firework_instence;
goto assgned;
} // firework will not be created if if all slots are full
}
SERIAL_PRINT("NO free slots\n");
}
assgned:
for (UINT8 i = 0; i < ARRAY_SIZE(firework_array); i++) {
if (firework_array[i] != NULL) {
if (firework_array[i]->status == ACTIVE) {
if (!step_firework(firework_array[i])) {
firework_array[i]->status = INACTIVE;
}
} else if (firework_array[i]->status == LAUNCHING) {
if (!step_rocket(&firework_array[i]->rocket, firework_array[i]->y)) {
firework_array[i]->status = ACTIVE;
}
} else {
FreePool(firework_array[i]); // free firework
firework_array[i] = NULL;
}
}
}
EFI_INPUT_KEY key;
EFI_STATUS status = gST->ConIn->ReadKeyStroke(gST->ConIn, &key);
gST->ConIn->Reset(gST->ConIn, FALSE);
if (status == EFI_SUCCESS) {
switch (key.ScanCode) {
case SCAN_UP: // increase simulation speed
if (sleep_time > 100) {
sleep_time = sleep_time - 100;
} else if (sleep_time > 10) {
sleep_time = sleep_time - 10;
} else if (sleep_time > 1) {
sleep_time = sleep_time - 1;
}
break;
case SCAN_DOWN:
if (sleep_time < UINT32_MAX - 100) {
sleep_time = sleep_time + 100;
} else if (sleep_time < UINT32_MAX - 10) {
sleep_time = sleep_time + 10;
} else if (sleep_time < UINT32_MAX - 1) {
sleep_time = sleep_time + 1;
}
break;
case SCAN_PAGE_UP:
if (sleep_time > 1000) {
sleep_time = sleep_time - 1000;
} else if (sleep_time > 100) {
sleep_time = sleep_time - 100;
} else if (sleep_time > 10) {
sleep_time = sleep_time - 10;
} else if (sleep_time > 1) {
sleep_time = sleep_time - 1;
}
break;
case SCAN_PAGE_DOWN:
if (sleep_time < UINT32_MAX - 1000) {
sleep_time = sleep_time + 1000;
} else if (sleep_time < UINT32_MAX - 100) {
sleep_time = sleep_time + 100;
} else if (sleep_time < UINT32_MAX - 10) {
sleep_time = sleep_time + 10;
} else if (sleep_time < UINT32_MAX - 1) {
sleep_time = sleep_time + 1;
}
break;
case SCAN_HOME:
sleep_time = DEFAULT_SLEEP_TIME;
break;
case SCAN_DELETE:
for (UINT8 i = 0; i < ARRAY_SIZE(firework_array); i++) {
if (firework_array[i] != NULL) {
FreePool(firework_array[i]);
firework_array[i] = NULL;
}
}
// clear_screen(); does not work on real hardware here for some unknown
// reason
for (UINTN i = 0; i < GraphicsOutput->Mode->FrameBufferSize; i++) {
framebuffer[i] = night_sky;
}
break;
}
}
microsleep(sleep_time);
}
firework_node *current_node = NULL;
for (LIST_ENTRY *node = GetFirstNode(&firework_list);
!IsNodeAtEnd(&firework_list, node);
node = GetNextNode(&firework_list, node)) {
// Print(L"Processing firework\r\n");
current_node = CR(node, firework_node, Link, FIREWORK_NODE_SIGNATURE);
if (!step_firework(&current_node->Firework)) {
RemoveEntryList(node); // remove if firework ended
}
}
MicroSecondDelay(500000);
}
return EFI_SUCCESS;
}
firework_instance create_firework() {
firework_instance firework;
UINT32 random;
fill_random_bytes(&random, sizeof(random));
firework.max_r = (random % 190) + 10; // 10 to 200,
for (UINT8 i = 0; i < ARRAY_SIZE(firework.color); i++) {
fill_random_bytes(&firework.color[i],
sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL) - 1);
firework.r[i] = 0;
}
firework.cleanup_r = 0;
fill_random_bytes(&random, sizeof(random));
firework.x = random % GraphicsOutput->Mode->Info->HorizontalResolution;
fill_random_bytes(&random, sizeof(random));
firework.y = random % GraphicsOutput->Mode->Info->VerticalResolution /
2; // spawn only on upper half of the screen
firework.rocket.x = firework.x + rocket_asset.width / 2;
firework.rocket.y = GraphicsOutput->Mode->Info->VerticalResolution;
firework.status = LAUNCHING;
return firework;
}
+3
View File
@@ -0,0 +1,3 @@
#pragma once
extern unsigned char assets_rocket_bmp[];
extern unsigned int assets_rocket_bmp_len;
+3 -2
View File
@@ -2,5 +2,6 @@
#include "macros.h"
#include <Protocol/GraphicsOutput.h>
EFI_GRAPHICS_OUTPUT_BLT_PIXEL night_sky =
COLOR_FROM_HEX(0x11095e); // this cannot be const becose EDK2 said so
extern EFI_GRAPHICS_OUTPUT_BLT_PIXEL night_sky;
enum firework_status { INACTIVE, ACTIVE, LAUNCHING };
+74 -4
View File
@@ -1,21 +1,30 @@
#include "Base.h"
#include "Library/BaseMemoryLib.h"
#include "Library/MemoryAllocationLib.h"
#include "Library/UefiLib.h"
#include "ProcessorBind.h"
#include "bmp.h"
#include "const.h"
#include "global.h"
#include "time.h"
#include "types.h"
#include <../MdeModulePkg/Include/Library/BmpSupportLib.h>
#include <Library/UefiApplicationEntryPoint.h>
#include <Protocol/GraphicsOutput.h>
#include <alloca.h>
void draw_pixel(const UINT32 x, const UINT32 y,
const EFI_GRAPHICS_OUTPUT_BLT_PIXEL pixel) {
if (x >= GraphicsOutput->Mode->Info->HorizontalResolution ||
y >= GraphicsOutput->Mode->Info
->VerticalResolution) { // ignore when out of bounds
return;
}
UINTN framebuffer_offset =
(y * GraphicsOutput->Mode->Info->PixelsPerScanLine) + x;
if (framebuffer_offset <
GraphicsOutput->Mode->FrameBufferSize) { // ignre when out of bounds
framebuffer[framebuffer_offset] = pixel;
}
}
// uses Mid-Point Circle Drawing Algorithm
// inspired by
@@ -82,7 +91,7 @@ void clear_screen() {
}
}
BOOLEAN step_firework(struct firework_instance *firework) {
BOOLEAN step_firework(firework_instance *firework) {
for (UINT8 i = 0; i < ARRAY_SIZE(firework->r); i++) {
if (firework->r[i] < firework->max_r) {
if (i == 0 || (firework->max_r / 3.5) * i <= firework->r[i - 1]) {
@@ -102,3 +111,64 @@ BOOLEAN step_firework(struct firework_instance *firework) {
}
return TRUE;
}
rocket_blt rocket_asset;
BOOLEAN **rocket_alfa_mask;
UINT32 *rocket_clean_up_mask;
void init_rocket_blt() {
EFI_STATUS Status = TranslateBmpToGopBlt(
assets_rocket_bmp, assets_rocket_bmp_len, &rocket_asset.blt,
&rocket_asset.blt_size, &rocket_asset.height, &rocket_asset.width);
if (EFI_ERROR(Status)) {
Print(L"Failed to load rocket asset: %r\n", Status);
Exit(Status);
}
rocket_clean_up_mask = AllocatePool(rocket_asset.width * sizeof(location));
rocket_alfa_mask = AllocateZeroPool(rocket_asset.height * sizeof(BOOLEAN *));
for (UINT32 i = 0; i < rocket_asset.height; i++) {
rocket_alfa_mask[i] = AllocatePool(rocket_asset.width * sizeof(BOOLEAN));
for (UINT32 j = 0; j < rocket_asset.width; j++) {
if (rocket_asset.blt[i * rocket_asset.width + j].Blue == 0 &&
rocket_asset.blt[i * rocket_asset.width + j].Green == 0 &&
rocket_asset.blt[i * rocket_asset.width + j].Red == 0) {
rocket_alfa_mask[i][j] = FALSE;
} else {
rocket_alfa_mask[i][j] = TRUE;
rocket_clean_up_mask[j] = i + 1; // build the cleanup mask
}
}
}
}
void draw_rocket(location *rocket) {
for (UINT32 i = 0; i < rocket_asset.width; i++) {
for (UINT32 j = 0; j < rocket_asset.height; j++) {
if (rocket_alfa_mask[j][i]) {
draw_pixel(i + rocket->x, j + rocket->y,
rocket_asset.blt[j * rocket_asset.width + i]);
}
}
}
}
BOOLEAN step_rocket(location *rocket, UINT32 max_y) {
draw_rocket(rocket);
for (UINT8 i = 0; i < rocket_asset.width; i++) {
draw_pixel(rocket->x + i, rocket->y + rocket_clean_up_mask[i], night_sky);
}
if (rocket->y <= max_y) {
// remove rocket
for (UINT32 i = 0; i < rocket_asset.width; i++) {
for (UINT32 j = 0; j < rocket_asset.height; j++) {
if (rocket_alfa_mask[j][i]) {
draw_pixel(i + rocket->x, j + rocket->y, night_sky);
}
}
}
return FALSE;
} else {
rocket->y--;
return TRUE;
}
}
+4 -2
View File
@@ -3,5 +3,7 @@
#include <Protocol/GraphicsOutput.h>
void draw_circle(int xc, int yc, int r,
const EFI_GRAPHICS_OUTPUT_BLT_PIXEL color);
void clear_screen(EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput);
BOOLEAN step_firework(struct firework_instance *firework);
void clear_screen();
BOOLEAN step_firework(firework_instance *firework);
void init_rocket_blt();
BOOLEAN step_rocket(location *rocket, UINT32 max_y);
+2
View File
@@ -1,4 +1,6 @@
#pragma once
#include "types.h"
#include <Protocol/GraphicsOutput.h>
extern EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
extern EFI_GRAPHICS_OUTPUT_BLT_PIXEL *framebuffer;
extern rocket_blt rocket_asset;
+119
View File
@@ -0,0 +1,119 @@
#include "rng.h"
#include "Library/UefiBootServicesTableLib.h"
#include "Library/UefiLib.h"
#include "ProcessorBind.h"
#include "Uefi/UefiBaseType.h"
#include "time.h"
#include <Library/BaseLib.h>
#include <Library/RngLib.h>
#include <Library/TimerLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Uefi.h>
#include <stdint.h>
void (*fill_random_bytes)(void *dst, UINTN n);
UINT16 shift_LFSR(UINT16 LFSR) {
UINT16 lsb = LFSR & 1;
LFSR >>= 1;
if (lsb) {
LFSR ^= 0xB400;
}
return LFSR;
}
void fill_random_bytes_TRUE(void *dst, UINTN n) {
UINT16 rand;
if (n % 2 != 0) {
GetRandomNumber16(&rand);
*(UINT8 *)dst = (UINT8)rand;
dst++;
n--;
}
while (n != 0) {
GetRandomNumber16(&rand);
*(UINT16 *)dst = rand;
dst += 2;
n -= 2;
}
}
UINT16 LFSR;
void fill_random_bytes_LFSR(void *dst, UINTN n) {
if (n % 2 != 0) {
LFSR = shift_LFSR(LFSR);
*(UINT8 *)dst = (UINT8)LFSR;
dst++;
n--;
}
while (n != 0) {
LFSR = shift_LFSR(LFSR);
*(UINT16 *)dst = LFSR;
dst += 2;
n -= 2;
}
}
void init_rng() {
UINT16 test_var;
if (GetRandomNumber16(&test_var)) {
fill_random_bytes = fill_random_bytes_TRUE;
} else {
gST->ConOut->SetAttribute(gST->ConOut, EFI_YELLOW);
Print(L"[WARNING]");
gST->ConOut->SetAttribute(gST->ConOut, EFI_WHITE);
Print(L" RNG device not available falling back to LFSR!\r\n");
EFI_TIME Time;
EFI_STATUS Status;
UINT32 starting;
Status = gRT->GetTime(&Time, NULL);
if (EFI_ERROR(Status)) {
Print(L"failed to get time\r\n");
microsleep(2000000);
starting = 1;
} else {
starting = Time.Second;
}
Print(L"Press any key to seed the LFSR\r\n");
EFI_INPUT_KEY Key;
UINTN Index;
Status = gBS->WaitForEvent(1, &(gST->ConIn->WaitForKey), &Index);
if (EFI_ERROR(Status)) {
Print(L"failed to wait key\r\n");
Key.ScanCode = 1;
Key.UnicodeChar = 1;
} else {
Status = gST->ConIn->ReadKeyStroke(gST->ConIn, &Key);
if (EFI_ERROR(Status)) {
Print(L"failed to read key\r\n");
Key.ScanCode = 1;
Key.UnicodeChar = 1;
}
}
if (Key.ScanCode == 0) {
Key.ScanCode = 1;
}
Status = gRT->GetTime(&Time, NULL);
if (EFI_ERROR(Status)) {
Print(L"failed to get time\r\n");
Time.Second = 1;
}
UINT8 time_diff = (Time.Second - starting);
if (time_diff == 0) {
time_diff = 1;
}
LFSR = (typeof(LFSR))(((UINTN)Key.ScanCode * (UINTN)Key.UnicodeChar *
(UINTN)(time_diff)) %
UINT16_MAX);
if (LFSR <= 1) {
LFSR = 0xf5d7;
}
fill_random_bytes = fill_random_bytes_LFSR;
}
}
+3
View File
@@ -0,0 +1,3 @@
#pragma once
extern void (*fill_random_bytes)(void *dst, UINTN n);
void init_rng();
+24
View File
@@ -0,0 +1,24 @@
#include "Library/UefiLib.h"
#include <Library/UefiBootServicesTableLib.h>
EFI_STATUS
microsleep(UINTN n) {
EFI_STATUS Status;
EFI_EVENT TimerEvent;
Status =
gBS->CreateEvent(EVT_TIMER, TPL_APPLICATION, NULL, NULL, &TimerEvent);
if (EFI_ERROR(Status)) {
return Status;
}
Status = gBS->SetTimer(TimerEvent, TimerRelative,
EFI_TIMER_PERIOD_MICROSECONDS(n));
if (!EFI_ERROR(Status)) {
gBS->WaitForEvent(1, &TimerEvent, NULL);
}
gBS->CloseEvent(TimerEvent);
return Status;
}
+2
View File
@@ -0,0 +1,2 @@
#pragma once
void microsleep(UINTN n);
+16 -7
View File
@@ -1,19 +1,28 @@
#pragma once
#include "ProcessorBind.h"
#include "Protocol/GraphicsOutput.h"
#include "const.h"
#include <Library/BaseLib.h>
struct firework_instance {
typedef struct {
UINT32 x;
UINT32 y;
} location;
typedef struct {
enum firework_status status; // IF INACTIVE can be overwriten
UINT32 x;
UINT32 y;
UINT16 max_r;
UINT16 r[3];
EFI_GRAPHICS_OUTPUT_BLT_PIXEL color[3];
UINT16 cleanup_r;
};
location rocket;
} firework_instance;
typedef struct {
UINTN Signature;
struct firework_instance Firework;
LIST_ENTRY Link;
} firework_node;
#define FIREWORK_NODE_SIGNATURE SIGNATURE_32('f', 'w', 'r', 'k')
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *blt;
UINTN blt_size;
UINTN height;
UINTN width;
} rocket_blt;
+8 -6
View File
@@ -1,14 +1,16 @@
#!/bin/bash
cp /usr/share/edk2/x64/OVMF_VARS.4m.fd ./my_ovmf_vars.fd
if [ $# -ge 1 ]; then
OVMF_CODE_PATH=$1
else
OVMF_CODE_PATH=/usr/share/edk2/x64/OVMF_CODE.4m.fd
fi
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) \
-drive if=pflash,format=raw,readonly=on,file="$OVMF_CODE_PATH" \
-hda fat:rw:build \
-boot order=c \
-smp 4 \
-s \
-serial mon:stdio
rm ./my_ovmf_vars.fd