mirror of
https://github.com/Metabolix/HackBGRT.git
synced 2025-12-06 17:15:42 -08:00
Initial release to GitHub
This commit is contained in:
12
Doxyfile
Normal file
12
Doxyfile
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
INPUT = src
|
||||||
|
FILE_PATTERNS = *.c *.h
|
||||||
|
JAVADOC_AUTOBRIEF = YES
|
||||||
|
EXTRACT_ALL = YES
|
||||||
|
EXTRACT_STATIC = YES
|
||||||
|
STRIP_CODE_COMMENTS = NO
|
||||||
|
INLINE_SOURCES = NO
|
||||||
|
GENERATE_HTML = YES
|
||||||
|
HTML_OUTPUT = html
|
||||||
|
HTML_FILE_EXTENSION = .html
|
||||||
|
HTML_DYNAMIC_SECTIONS = YES
|
||||||
|
GENERATE_LATEX = NO
|
||||||
27
Makefile
Normal file
27
Makefile
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
CC = $(CC_PREFIX)-gcc
|
||||||
|
CFLAGS = -std=c11 -O2 -ffreestanding -mno-red-zone -fno-stack-protector -Wshadow -Wall -Wunused -Werror-implicit-function-declaration -Werror
|
||||||
|
CFLAGS += -I$(GNUEFI_INC) -I$(GNUEFI_INC)/$(GNUEFI_ARCH) -I$(GNUEFI_INC)/protocol
|
||||||
|
LDFLAGS = -nostdlib -shared -Wl,-dll -Wl,--subsystem,10 -e _EfiMain
|
||||||
|
LIBS = -L$(GNUEFI_LIB) -lefi -lgcc
|
||||||
|
|
||||||
|
GNUEFI_INC = /usr/$(CC_PREFIX)/include/efi
|
||||||
|
GNUEFI_LIB = /usr/$(CC_PREFIX)/lib
|
||||||
|
|
||||||
|
FILES_C = src/main.c src/util.c src/config.c
|
||||||
|
FILES_H = $(wildcard src/*.h)
|
||||||
|
|
||||||
|
.PHONY: all
|
||||||
|
all: bootx64.efi
|
||||||
|
|
||||||
|
bootx64.efi: CC_PREFIX = x86_64-w64-mingw32
|
||||||
|
bootx64.efi: GNUEFI_ARCH = x86_64
|
||||||
|
bootx64.efi: $(FILES_C)
|
||||||
|
$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ $(LIBS) -s
|
||||||
|
|
||||||
|
bootia32.efi: CC_PREFIX = i686-w64-mingw32
|
||||||
|
bootia32.efi: GNUEFI_ARCH = ia32
|
||||||
|
bootia32.efi: $(FILES_C)
|
||||||
|
$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ $(LIBS) -s
|
||||||
|
|
||||||
|
HackBGRT.tar.xz: bootx64.efi config.txt splash.bmp install.bat uninstall.bat README.md README.efilib LICENSE
|
||||||
|
tar cJf $@ --transform=s,^,HackBGRT/, $^
|
||||||
31
README.efilib
Normal file
31
README.efilib
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# vim: set fileencoding=utf-8
|
||||||
|
|
||||||
|
HackBGRT uses the gnu-efi library, which in turn is using the EFI Application
|
||||||
|
Toolkit distributed by Intel at http://developer.intel.com/technology/efi
|
||||||
|
|
||||||
|
This code is covered by the following agreement:
|
||||||
|
|
||||||
|
Copyright (c) 1998-2000 Intel Corporation
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||||
|
provided that the following conditions are met:
|
||||||
|
|
||||||
|
Redistributions of source code must retain the above copyright notice, this list of conditions and
|
||||||
|
the following disclaimer.
|
||||||
|
|
||||||
|
Redistributions in binary form must reproduce the above copyright notice, this list of conditions
|
||||||
|
and the following disclaimer in the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||||
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE. THE EFI SPECIFICATION AND ALL OTHER INFORMATION
|
||||||
|
ON THIS WEB SITE ARE PROVIDED "AS IS" WITH NO WARRANTIES, AND ARE SUBJECT
|
||||||
|
TO CHANGE WITHOUT NOTICE.
|
||||||
48
README.md
Normal file
48
README.md
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
# HackBGRT
|
||||||
|
|
||||||
|
HackBGRT is intended as a boot logo changer for UEFI-based Windows systems.
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
When booting on a UEFI-based computer, Windows may show a vendor-defined logo which is stored on the UEFI firmware in a section called Boot Graphics Resource Table (BGRT). It's usually very difficult to change the image permamently, but a custom UEFI application may be used to overwrite it during the boot. HackBGRT does exactly that.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
**Important:** If you mess up the installation, your system may become unbootable! Create a rescue disk before use. This software comes with no warranty. Use at your own risk.
|
||||||
|
|
||||||
|
* Make sure that your computer is booting with UEFI.
|
||||||
|
* Make sure that you have a 64-bit x86-64 processor.
|
||||||
|
* Make sure that Secure Boot is disabled, or learn to sign EFI applications.
|
||||||
|
* Simple Windows installation:
|
||||||
|
* Get at least these files: `bootx64.efi`, `config.txt`, `install.bat`, `splash.bmp`.
|
||||||
|
* Run Command Prompt as Administrator.
|
||||||
|
* Run `install.bat` from the Command Prompt.
|
||||||
|
* The installer will launch Paint for creating the image(s).
|
||||||
|
* The installer will launch Notepad for modifying the configuration.
|
||||||
|
* If Windows later reinstalls the original boot loader, run `install.bat` again.
|
||||||
|
* Installation for Windows with another boot loader (e.g. GRUB):
|
||||||
|
* Copy the mentioned files to `[EFI System Partition]\EFI\HackBGRT\`.
|
||||||
|
* Set `boot=\EFI\Microsoft\Boot\bootmgfw.efi` in `config.txt`.
|
||||||
|
* Point your boot loader to `\EFI\HackBGRT\bootx64.efi`.
|
||||||
|
* Installation for all operating systems:
|
||||||
|
* Copy the mentioned files to `[EFI System Partition]\EFI\HackBGRT\`.
|
||||||
|
* Set `boot=` to your preferred boot loader in `config.txt`.
|
||||||
|
* Set `\EFI\HackBGRT\bootx64.efi` as your default boot loader with `efibootmgr` or some other EFI boot manager tool.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
The configuration options are described in `config.txt`, which should be stored in `[EFI System Partition]\EFI\HackBGRT\config.txt`.
|
||||||
|
|
||||||
|
## Images
|
||||||
|
|
||||||
|
The image path can be changed in the configuration file. The default path is `[EFI System Partition]\EFI\HackBGRT\splash.bmp`.
|
||||||
|
|
||||||
|
The image must be a 24-bit BMP file with a 54-byte header. That's a TrueColor BMP3 in Imagemagick, or 24-bit BMP/DIB in Microsoft Paint.
|
||||||
|
|
||||||
|
Multiple images may be specified, in which case one is picked at random.
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
* Compiler: GCC targeting w64-mingw32
|
||||||
|
* Compiler flags: see Makefile
|
||||||
|
* Libraries: gnu-efi
|
||||||
BIN
config.txt
Executable file
BIN
config.txt
Executable file
Binary file not shown.
120
install.bat
Executable file
120
install.bat
Executable file
@@ -0,0 +1,120 @@
|
|||||||
|
@ECHO OFF
|
||||||
|
CD %~dp0
|
||||||
|
|
||||||
|
IF NOT "%1" == "uninstall" (
|
||||||
|
IF NOT EXIST bootx64.efi (
|
||||||
|
ECHO Missing bootx64.efi, you're doing something wrong.
|
||||||
|
GOTO fail_before_esp
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
SET ESP_UNMOUNT=1
|
||||||
|
SET ESP=-
|
||||||
|
FOR /F "delims=" %%I IN ('CMD /C "MOUNTVOL | FINDSTR /C:EFI | FINDSTR /C::"') DO (
|
||||||
|
ECHO %%I
|
||||||
|
SET ESP_STR=%%I
|
||||||
|
SET ESP=%ESP_STR:~-3,2%
|
||||||
|
SET ESP_UNMOUNT=0
|
||||||
|
)
|
||||||
|
IF %ESP% == - MOUNTVOL S: /S >NUL && SET ESP=S:
|
||||||
|
IF %ESP% == - MOUNTVOL B: /S >NUL && SET ESP=B:
|
||||||
|
IF %ESP% == - MOUNTVOL A: /S >NUL && SET ESP=A:
|
||||||
|
IF %ESP% == - MOUNTVOL X: /S >NUL && SET ESP=X:
|
||||||
|
|
||||||
|
IF %ESP% == - (
|
||||||
|
ECHO The EFI System Partition is not mounted.
|
||||||
|
GOTO fail_before_esp
|
||||||
|
)
|
||||||
|
|
||||||
|
SET HackBGRT=%ESP%\EFI\HackBGRT
|
||||||
|
SET MSBOOT=%ESP%\EFI\Microsoft\Boot
|
||||||
|
|
||||||
|
IF NOT EXIST %MSBOOT% (
|
||||||
|
ECHO %MSBOOT% does not exist.
|
||||||
|
ECHO If the path seems incorrect, report a bug.
|
||||||
|
GOTO fail
|
||||||
|
)
|
||||||
|
|
||||||
|
IF "%1" == "uninstall" (
|
||||||
|
IF NOT EXIST %HackBGRT%\bootmgfw-original.efi (
|
||||||
|
ECHO Missing %HackBGRT%\bootmgfw-original.efi!
|
||||||
|
GOTO fail
|
||||||
|
)
|
||||||
|
COPY %HackBGRT%\bootmgfw-original.efi %MSBOOT%\bootmgfw.efi >NUL || (
|
||||||
|
ECHO Failed to restore the original bootmgfw.efi.
|
||||||
|
GOTO fail
|
||||||
|
)
|
||||||
|
ECHO The original bootmgfw.efi has been restored.
|
||||||
|
IF EXIST %HackBGRT% (
|
||||||
|
DEL /P %HackBGRT%
|
||||||
|
)
|
||||||
|
EXIT /B
|
||||||
|
)
|
||||||
|
|
||||||
|
IF NOT EXIST %HackBGRT% (
|
||||||
|
MKDIR %HackBGRT%
|
||||||
|
)
|
||||||
|
IF NOT EXIST %HackBGRT%\bootmgfw-original.efi (
|
||||||
|
COPY %MSBOOT%\bootmgfw.efi %HackBGRT%\bootmgfw-original.efi >NUL || (
|
||||||
|
ECHO Couldn't copy the original bootmgfw.efi.
|
||||||
|
GOTO fail
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
ECHO Copying files...
|
||||||
|
COPY /Y LICENSE %HackBGRT%\ >NUL
|
||||||
|
COPY /Y README.md %HackBGRT%\ >NUL
|
||||||
|
COPY /Y README.efilib %HackBGRT%\ >NUL
|
||||||
|
COPY /Y install.bat %HackBGRT%\ >NUL
|
||||||
|
COPY /Y uninstall.bat %HackBGRT%\ >NUL
|
||||||
|
COPY /Y bootx64.efi %HackBGRT%\ >NUL || GOTO fail
|
||||||
|
IF NOT EXIST %HackBGRT%\splash.bmp (
|
||||||
|
COPY splash.bmp %HackBGRT%\ >NUL || GOTO fail
|
||||||
|
)
|
||||||
|
IF EXIST %HackBGRT%\config.txt (
|
||||||
|
ECHO Copying configuration as config-new.txt.
|
||||||
|
ECHO Be sure to check for any format changes!
|
||||||
|
COPY /Y config.txt %HackBGRT%\config-new.txt >NUL || GOTO fail
|
||||||
|
) ELSE (
|
||||||
|
COPY /Y config.txt %HackBGRT%\config.txt >NUL || GOTO fail
|
||||||
|
)
|
||||||
|
|
||||||
|
ECHO Draw or copy your preferred image to splash.bmp.
|
||||||
|
START /WAIT mspaint %HackBGRT%\splash.bmp
|
||||||
|
|
||||||
|
ECHO Check the configuration in config.txt.
|
||||||
|
IF EXIST %HackBGRT%\config-new.txt (
|
||||||
|
ECHO See config-new.txt for reference.
|
||||||
|
START notepad %HackBGRT%\config-new.txt
|
||||||
|
)
|
||||||
|
START /WAIT notepad %HackBGRT%\config.txt
|
||||||
|
|
||||||
|
ECHO Replacing bootmgfw.efi.
|
||||||
|
COPY /Y bootx64.efi %MSBOOT%\bootmgfw.efi >NUL || (
|
||||||
|
ECHO Failed to copy the boot loader!
|
||||||
|
ECHO Restoring the original bootmgfw.efi...
|
||||||
|
COPY %HackBGRT%\bootmgfw-original.efi %MSBOOT%\bootmgfw.efi >NUL || (
|
||||||
|
ECHO Restoration failed You will need to fix this!
|
||||||
|
)
|
||||||
|
GOTO fail
|
||||||
|
)
|
||||||
|
|
||||||
|
IF %ESP_UNMOUNT% == 1 (
|
||||||
|
MOUNTVOL %ESP% /D
|
||||||
|
)
|
||||||
|
|
||||||
|
ECHO Installation is ready.
|
||||||
|
ECHO If your CPU is not x86-64, you should definitely uninstall now.
|
||||||
|
ECHO Remember to disable Secure Boot, or HackBGRT will not boot.
|
||||||
|
PAUSE
|
||||||
|
EXIT /B
|
||||||
|
|
||||||
|
:fail
|
||||||
|
IF %ESP_UNMOUNT% == 1 (
|
||||||
|
MOUNTVOL %ESP% /D
|
||||||
|
)
|
||||||
|
|
||||||
|
:fail_before_esp
|
||||||
|
ECHO Exiting due to errors.
|
||||||
|
PAUSE
|
||||||
|
EXIT /B 1
|
||||||
BIN
splash.bmp
Normal file
BIN
splash.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 96 KiB |
102
src/config.c
Normal file
102
src/config.c
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
#include "config.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#include <efilib.h>
|
||||||
|
|
||||||
|
BOOLEAN ReadConfigFile(struct HackBGRT_config* config, EFI_FILE_HANDLE root_dir, const CHAR16* path) {
|
||||||
|
CHAR16* str = 0;
|
||||||
|
UINTN str_bytes = 0;
|
||||||
|
str = LoadFileWithPadding(root_dir, path, &str_bytes, sizeof(*str));
|
||||||
|
if (!str) {
|
||||||
|
Print(L"HackBGRT: Failed to load configuration (%s)!\n", path);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
UINTN str_len = str_bytes / sizeof(*str);
|
||||||
|
|
||||||
|
for (int i = 0; i < str_len;) {
|
||||||
|
int j = i;
|
||||||
|
while (j < str_len && str[j] != '\r' && str[j] != '\n') {
|
||||||
|
++j;
|
||||||
|
}
|
||||||
|
while (j < str_len && (str[j] == '\r' || str[j] == '\n')) {
|
||||||
|
str[j] = 0;
|
||||||
|
++j;
|
||||||
|
}
|
||||||
|
ReadConfigLine(config, root_dir, &str[i]);
|
||||||
|
i = j;
|
||||||
|
}
|
||||||
|
// NOTICE: string is not freed, because paths are not copied.
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetBMPWithRandom(struct HackBGRT_config* config, int weight, enum HackBGRT_action action, int x, int y, const CHAR16* path) {
|
||||||
|
config->image_weight_sum += weight;
|
||||||
|
UINT32 random = Random();
|
||||||
|
UINT32 limit = 0xfffffffful / config->image_weight_sum * weight;
|
||||||
|
if (config->debug) {
|
||||||
|
Print(L"HackBGRT: weight %d, action %d, x %d, y %d, path %s, random = %08x, limit = %08x\n", weight, action, x, y, path, random, limit);
|
||||||
|
}
|
||||||
|
if (!config->image_weight_sum || random <= limit) {
|
||||||
|
config->action = action;
|
||||||
|
config->image_path = path;
|
||||||
|
config->image_x = x;
|
||||||
|
config->image_y = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ParseCoordinate(const CHAR16* str, enum HackBGRT_action action) {
|
||||||
|
if (str && L'0' <= str[0] && str[0] <= L'9') {
|
||||||
|
return Atoi(str);
|
||||||
|
}
|
||||||
|
if ((str && StrnCmp(str, L"native", 6) == 0) || action == HackBGRT_KEEP) {
|
||||||
|
return HackBGRT_coord_native;
|
||||||
|
}
|
||||||
|
return HackBGRT_coord_auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ReadConfigImage(struct HackBGRT_config* config, const CHAR16* line) {
|
||||||
|
const CHAR16* n = StrStrAfter(line, L"n=");
|
||||||
|
const CHAR16* x = StrStrAfter(line, L"x=");
|
||||||
|
const CHAR16* y = StrStrAfter(line, L"y=");
|
||||||
|
const CHAR16* f = StrStrAfter(line, L"path=");
|
||||||
|
enum HackBGRT_action action = HackBGRT_KEEP;
|
||||||
|
if (f) {
|
||||||
|
action = HackBGRT_REPLACE;
|
||||||
|
} else if (StrStr(line, L"remove")) {
|
||||||
|
action = HackBGRT_REMOVE;
|
||||||
|
} else if (StrStr(line, L"black")) {
|
||||||
|
action = HackBGRT_BLACK;
|
||||||
|
} else if (StrStr(line, L"keep")) {
|
||||||
|
action = HackBGRT_KEEP;
|
||||||
|
} else {
|
||||||
|
Print(L"HackBGRT: Invalid image line: %s\n", line);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int weight = n && (!f || n < f) ? Atoi(n) : 1;
|
||||||
|
SetBMPWithRandom(config, weight, action, ParseCoordinate(x, action), ParseCoordinate(y, action), f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReadConfigLine(struct HackBGRT_config* config, EFI_FILE_HANDLE root_dir, const CHAR16* line) {
|
||||||
|
line = TrimLeft(line);
|
||||||
|
if (line[0] == L'#' || line[0] == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrnCmp(line, L"debug=", 6) == 0) {
|
||||||
|
config->debug = (StrCmp(line, L"debug=1") == 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (StrnCmp(line, L"image=", 6) == 0) {
|
||||||
|
ReadConfigImage(config, line + 6);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (StrnCmp(line, L"boot=", 5) == 0) {
|
||||||
|
config->boot_path = line + 5;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (StrnCmp(line, L"config=", 7) == 0) {
|
||||||
|
ReadConfigFile(config, root_dir, line + 7);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Print(L"Unknown configuration directive: %s\n", line);
|
||||||
|
}
|
||||||
51
src/config.h
Normal file
51
src/config.h
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <efi.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Possible actions to perform on the BGRT.
|
||||||
|
*/
|
||||||
|
enum HackBGRT_action {
|
||||||
|
HackBGRT_KEEP = 0, HackBGRT_REPLACE, HackBGRT_REMOVE, HackBGRT_BLACK
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Special values for the image coordinates.
|
||||||
|
* @see struct HackBGRT_config
|
||||||
|
*/
|
||||||
|
enum HackBGRT_coordinate {
|
||||||
|
HackBGRT_coord_auto = 0x10000001,
|
||||||
|
HackBGRT_coord_native = 0x10000002
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The configuration.
|
||||||
|
*/
|
||||||
|
struct HackBGRT_config {
|
||||||
|
int debug;
|
||||||
|
enum HackBGRT_action action;
|
||||||
|
const CHAR16* image_path;
|
||||||
|
int image_x;
|
||||||
|
int image_y;
|
||||||
|
int image_weight_sum;
|
||||||
|
const CHAR16* boot_path;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a configuration parameter. (May recursively read config files.)
|
||||||
|
*
|
||||||
|
* @param config The configuration to modify.
|
||||||
|
* @param root_dir The root directory, in case the parameter contains an include.
|
||||||
|
* @param line The configuration line to parse.
|
||||||
|
*/
|
||||||
|
extern void ReadConfigLine(struct HackBGRT_config* config, EFI_FILE_HANDLE root_dir, const CHAR16* line);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a configuration file. (May recursively read more files.)
|
||||||
|
*
|
||||||
|
* @param config The configuration to modify.
|
||||||
|
* @param root_dir The root directory.
|
||||||
|
* @param path The path to the file.
|
||||||
|
* @return FALSE, if the file couldn't be read, TRUE otherwise.
|
||||||
|
*/
|
||||||
|
extern BOOLEAN ReadConfigFile(struct HackBGRT_config* config, EFI_FILE_HANDLE root_dir, const CHAR16* path);
|
||||||
311
src/main.c
Normal file
311
src/main.c
Normal file
@@ -0,0 +1,311 @@
|
|||||||
|
#include <efi.h>
|
||||||
|
#include <efilib.h>
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Print function signature.
|
||||||
|
*/
|
||||||
|
typedef UINTN print_t(IN CHAR16 *fmt, ...);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The function for debug printing; either Print or NullPrint.
|
||||||
|
*/
|
||||||
|
print_t* Debug = NullPrint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The configuration.
|
||||||
|
*/
|
||||||
|
static struct HackBGRT_config config = {
|
||||||
|
.action = HackBGRT_KEEP
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the GOP (Graphics Output Protocol) pointer.
|
||||||
|
*/
|
||||||
|
static EFI_GRAPHICS_OUTPUT_PROTOCOL* GOP(void) {
|
||||||
|
static EFI_GRAPHICS_OUTPUT_PROTOCOL* gop;
|
||||||
|
if (!gop) {
|
||||||
|
EFI_GUID GraphicsOutputProtocolGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
|
||||||
|
LibLocateProtocol(&GraphicsOutputProtocolGuid, (VOID **)&gop);
|
||||||
|
}
|
||||||
|
return gop;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select the correct coordinate (manual, automatic, native)
|
||||||
|
*
|
||||||
|
* @param value The configured coordinate value; has special values for automatic and native.
|
||||||
|
* @param automatic The automatically calculated alternative.
|
||||||
|
* @param native The original coordinate.
|
||||||
|
* @see enum HackBGRT_coordinate
|
||||||
|
*/
|
||||||
|
static int SelectCoordinate(int value, int automatic, int native) {
|
||||||
|
if (value == HackBGRT_coord_auto) {
|
||||||
|
return automatic;
|
||||||
|
}
|
||||||
|
if (value == HackBGRT_coord_native) {
|
||||||
|
return native;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize (clear) a BGRT.
|
||||||
|
*
|
||||||
|
* @param bgrt The BGRT to initialize.
|
||||||
|
*/
|
||||||
|
static void InitBGRT(ACPI_BGRT* bgrt) {
|
||||||
|
const char data[0x38] = "BGRT" "\x38\x00\x00\x00" "\x00" "\xd6" "Mtblx*" "HackBGRT" "\x20\x17\x00\x00" "PTL " "\x02\x00\x00\x00" "\x01\x00" "\x00" "\x00";
|
||||||
|
CopyMem(bgrt, data, sizeof(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill a BGRT as specified by the parameters.
|
||||||
|
*
|
||||||
|
* @param bgrt The BGRT to fill.
|
||||||
|
* @param new_bmp The BMP to use.
|
||||||
|
* @param new_x The x coordinate to use.
|
||||||
|
* @param new_y The y coordinate to use.
|
||||||
|
*/
|
||||||
|
static void FillBGRT(ACPI_BGRT* bgrt, BMP* new_bmp, int new_x, int new_y) {
|
||||||
|
BMP* old_bmp = (BMP*) (UINTN) bgrt->image_address;
|
||||||
|
ACPI_BGRT bgrt0 = *bgrt;
|
||||||
|
InitBGRT(bgrt);
|
||||||
|
|
||||||
|
if (new_bmp) {
|
||||||
|
bgrt->image_address = (UINTN) new_bmp;
|
||||||
|
}
|
||||||
|
BMP* bmp = (BMP*) (UINTN) bgrt->image_address;
|
||||||
|
|
||||||
|
// Calculate the automatically centered position for the image.
|
||||||
|
int x_auto, y_auto;
|
||||||
|
if (GOP()) {
|
||||||
|
x_auto = max(0, ((int)GOP()->Mode->Info->HorizontalResolution - (int)bmp->width) / 2);
|
||||||
|
y_auto = max(0, ((int)GOP()->Mode->Info->VerticalResolution * 2/3 - (int)bmp->height) / 2);
|
||||||
|
} else {
|
||||||
|
x_auto = max(0, (int)bgrt0.image_offset_x + ((int)old_bmp->width - (int)bmp->width) / 2);
|
||||||
|
y_auto = max(0, (int)bgrt0.image_offset_y + ((int)old_bmp->height - (int)bmp->height) / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the position (manual, automatic, original).
|
||||||
|
bgrt->image_offset_x = SelectCoordinate(new_x, x_auto, bgrt0.image_offset_x);
|
||||||
|
bgrt->image_offset_y = SelectCoordinate(new_y, y_auto, bgrt0.image_offset_y);
|
||||||
|
Debug(L"HackBGRT: BMP at (%d, %d).\n", (int) bgrt->image_offset_x, (int) bgrt->image_offset_y);
|
||||||
|
|
||||||
|
bgrt->header.checksum = 0;
|
||||||
|
bgrt->header.checksum = CalculateAcpiChecksum(bgrt, sizeof(*bgrt));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the BGRT and optionally destroy it or create if missing.
|
||||||
|
*
|
||||||
|
* @param action The intended action.
|
||||||
|
* @return Pointer to the BGRT, or 0 if not found (or destroyed).
|
||||||
|
*/
|
||||||
|
static ACPI_BGRT* FindBGRT(enum HackBGRT_action action) {
|
||||||
|
ACPI_20_RSDP* good_rsdp = 0;
|
||||||
|
ACPI_BGRT* bgrt = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < ST->NumberOfTableEntries; i++) {
|
||||||
|
EFI_GUID Acpi20TableGuid = ACPI_20_TABLE_GUID;
|
||||||
|
EFI_GUID* vendor_guid = &ST->ConfigurationTable[i].VendorGuid;
|
||||||
|
if (!CompareGuid(vendor_guid, &AcpiTableGuid) && !CompareGuid(vendor_guid, &Acpi20TableGuid)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
EFI_CONFIGURATION_TABLE *ect = &ST->ConfigurationTable[i];
|
||||||
|
if (CompareMem(ect->VendorTable, "RSD PTR ", 8) != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ACPI_20_RSDP* rsdp = (ACPI_20_RSDP *)ect->VendorTable;
|
||||||
|
Debug(L"RSDP: revision = %d, OEM ID = %s\n", rsdp->revision, TmpStr(rsdp->oem_id, 6));
|
||||||
|
|
||||||
|
if (rsdp->revision < 2) {
|
||||||
|
Debug(L"* XSDT: N/A (revision < 2)\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ACPI_SDT_HEADER* xsdt = (ACPI_SDT_HEADER *) (UINTN) rsdp->xsdt_address;
|
||||||
|
if (!xsdt) {
|
||||||
|
Debug(L"* XSDT: N/A (null)\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (CompareMem(xsdt->signature, "XSDT", 4) != 0) {
|
||||||
|
Debug(L"* XSDT: N/A (invalid signature)\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
good_rsdp = rsdp;
|
||||||
|
UINT64* entry_arr = (UINT64*)&xsdt[1];
|
||||||
|
UINT32 entry_arr_length = (xsdt->length - sizeof(*xsdt)) / sizeof(UINT64);
|
||||||
|
|
||||||
|
Debug(L"* XSDT: OEM ID = %s, entry count = %d\n", TmpStr(xsdt->oem_id, 6), entry_arr_length);
|
||||||
|
|
||||||
|
for (int j = 0; j < entry_arr_length; j++) {
|
||||||
|
ACPI_SDT_HEADER *entry = (ACPI_SDT_HEADER *)((UINTN)entry_arr[j]);
|
||||||
|
Debug(L" - ACPI table: %s, revision = %d, OEM ID = %s\n", TmpStr(entry->signature, 4), entry->revision, TmpStr(entry->oem_id, 6));
|
||||||
|
if (CompareMem(entry->signature, "BGRT", 4) == 0) {
|
||||||
|
if (!bgrt && action != HackBGRT_REMOVE) {
|
||||||
|
bgrt = (void*) entry;
|
||||||
|
} else {
|
||||||
|
if (bgrt) {
|
||||||
|
Debug(L" -> Deleting; BGRT was already found!\n");
|
||||||
|
} else {
|
||||||
|
Debug(L" -> Deleting.\n");
|
||||||
|
}
|
||||||
|
for (int k = j+1; k < entry_arr_length; ++k) {
|
||||||
|
entry_arr[k-1] = entry_arr[k];
|
||||||
|
}
|
||||||
|
--entry_arr_length;
|
||||||
|
entry_arr[entry_arr_length] = 0;
|
||||||
|
xsdt->length -= sizeof(entry_arr[0]);
|
||||||
|
--j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (action == HackBGRT_REMOVE) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!good_rsdp) {
|
||||||
|
Print(L"HackBGRT: RSDP or XSDT not found.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!bgrt) {
|
||||||
|
if (action == HackBGRT_KEEP) {
|
||||||
|
Print(L"HackBGRT: BGRT not found.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
Debug(L"HackBGRT: BGRT not found, creating.\n");
|
||||||
|
ACPI_20_RSDP* rsdp = good_rsdp;
|
||||||
|
ACPI_SDT_HEADER* xsdt0 = (ACPI_SDT_HEADER *) (UINTN) rsdp->xsdt_address;
|
||||||
|
ACPI_SDT_HEADER* xsdt = 0;
|
||||||
|
UINT32 xsdt_len = xsdt0->length + sizeof(UINT64);
|
||||||
|
BS->AllocatePool(EfiACPIReclaimMemory, xsdt_len, (void**)&xsdt);
|
||||||
|
BS->AllocatePool(EfiACPIReclaimMemory, sizeof(*bgrt), (void**)&bgrt);
|
||||||
|
if (!xsdt || !bgrt) {
|
||||||
|
Print(L"HackBGRT: Failed to allocate memory for XSDT and BGRT.\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
rsdp->xsdt_address = (UINTN) xsdt;
|
||||||
|
CopyMem(xsdt, xsdt0, xsdt0->length);
|
||||||
|
*(UINT64*)((char*)xsdt + xsdt->length) = (UINTN) bgrt;
|
||||||
|
xsdt->length = xsdt_len;
|
||||||
|
InitBGRT(bgrt);
|
||||||
|
}
|
||||||
|
return bgrt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a bitmap or generate one, or return 0 if not applicable.
|
||||||
|
*
|
||||||
|
* @param action Tells what to do.
|
||||||
|
* @param root_dir The root directory for loading a BMP.
|
||||||
|
* @param path The BMP path within the root directory.
|
||||||
|
* @return The loaded BMP, or 0 if not needed or not available.
|
||||||
|
*/
|
||||||
|
static BMP* LoadBMP(enum HackBGRT_action action, EFI_FILE_HANDLE root_dir, const CHAR16* path) {
|
||||||
|
BMP* bmp = 0;
|
||||||
|
if (action == HackBGRT_KEEP || action == HackBGRT_REMOVE) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (action == HackBGRT_BLACK) {
|
||||||
|
BS->AllocatePool(EfiBootServicesData, 58, (void**) &bmp);
|
||||||
|
if (!bmp) {
|
||||||
|
Print(L"HackBGRT: Failed to allocate a blank BMP!\n");
|
||||||
|
BS->Stall(1000000);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
CopyMem(
|
||||||
|
bmp,
|
||||||
|
"\x42\x4d\x3a\x00\x00\x00\x00\x00\x00\x00\x36\x00\x00\x00\x28\x00"
|
||||||
|
"\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x18\x00\x00\x00"
|
||||||
|
"\x00\x00\x04\x00\x00\x00\x13\x0b\x00\x00\x13\x0b\x00\x00\x00\x00"
|
||||||
|
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
|
||||||
|
58
|
||||||
|
);
|
||||||
|
return bmp;
|
||||||
|
}
|
||||||
|
if (!path) {
|
||||||
|
Print(L"HackBGRT: Missing BMP path. REPORT THIS BUG!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
Debug(L"HackBGRT: Loading %s.\n", path);
|
||||||
|
bmp = LoadFile(root_dir, path, 0);
|
||||||
|
if (!bmp) {
|
||||||
|
Print(L"HackBGRT: Failed to load BMP (%s)!\n", path);
|
||||||
|
BS->Stall(1000000);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return bmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The main program.
|
||||||
|
*/
|
||||||
|
EFI_STATUS EFIAPI EfiMain(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *ST_) {
|
||||||
|
InitializeLib(image_handle, ST_);
|
||||||
|
|
||||||
|
EFI_LOADED_IMAGE* image;
|
||||||
|
if (EFI_ERROR(BS->HandleProtocol(image_handle, &LoadedImageProtocol, (void**) &image))) {
|
||||||
|
Debug(L"HackBGRT: LOADED_IMAGE_PROTOCOL failed.\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_FILE_HANDLE root_dir = LibOpenRoot(image->DeviceHandle);
|
||||||
|
|
||||||
|
CHAR16 **argv;
|
||||||
|
int argc = GetShellArgcArgv(image_handle, &argv);
|
||||||
|
|
||||||
|
if (argc <= 1) {
|
||||||
|
const CHAR16* config_path = L"\\EFI\\HackBGRT\\config.txt";
|
||||||
|
if (!ReadConfigFile(&config, root_dir, config_path)) {
|
||||||
|
Print(L"HackBGRT: No config, no command line!\n", config_path);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 1; i < argc; ++i) {
|
||||||
|
ReadConfigLine(&config, root_dir, argv[i]);
|
||||||
|
}
|
||||||
|
Debug = config.debug ? Print : NullPrint;
|
||||||
|
|
||||||
|
BMP* new_bmp = LoadBMP(config.action, root_dir, config.image_path);
|
||||||
|
ACPI_BGRT* bgrt = FindBGRT(config.action);
|
||||||
|
if (bgrt) {
|
||||||
|
FillBGRT(bgrt, new_bmp, config.image_x, config.image_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!config.boot_path) {
|
||||||
|
Print(L"HackBGRT: Boot path not specified.\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug(L"HackBGRT: Loading and booting %s.\n", config.boot_path);
|
||||||
|
EFI_DEVICE_PATH* boot_dp = FileDevicePath(image->DeviceHandle, (CHAR16*) config.boot_path);
|
||||||
|
EFI_HANDLE next_image_handle;
|
||||||
|
if (EFI_ERROR(BS->LoadImage(0, image_handle, boot_dp, 0, 0, &next_image_handle))) {
|
||||||
|
Print(L"HackBGRT: LoadImage for new image (%s) failed.\n", config.boot_path);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (EFI_ERROR(BS->StartImage(next_image_handle, 0, 0))) {
|
||||||
|
Print(L"HackBGRT: StartImage for %s failed.\n", config.boot_path);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
Print(L"HackBGRT: Started %s. Why are we still here?!\n", config.boot_path);
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
fail: {
|
||||||
|
Print(L"HackBGRT has failed. Use parameter debug=1 for details.\nPress any key to exit.\n");
|
||||||
|
WaitKey();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forward to EfiMain.
|
||||||
|
*
|
||||||
|
* Some compilers and architectures differ in underscore handling. This helps.
|
||||||
|
*/
|
||||||
|
EFI_STATUS EFIAPI _EfiMain(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *ST_) {
|
||||||
|
return EfiMain(image_handle, ST_);
|
||||||
|
}
|
||||||
54
src/types.h
Normal file
54
src/types.h
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
|
||||||
|
/** RSDP (Root System Description Pointer) */
|
||||||
|
typedef struct {
|
||||||
|
CHAR8 signature[8];
|
||||||
|
UINT8 checksum;
|
||||||
|
CHAR8 oem_id[6];
|
||||||
|
UINT8 revision;
|
||||||
|
UINT32 rsdt_address;
|
||||||
|
UINT32 length;
|
||||||
|
UINT64 xsdt_address;
|
||||||
|
UINT8 extended_checksum;
|
||||||
|
UINT8 reserved[3];
|
||||||
|
} ACPI_20_RSDP;
|
||||||
|
|
||||||
|
/** SDT (System Description Table) entry header */
|
||||||
|
typedef struct {
|
||||||
|
CHAR8 signature[4];
|
||||||
|
UINT32 length;
|
||||||
|
UINT8 revision;
|
||||||
|
UINT8 checksum;
|
||||||
|
CHAR8 oem_id[6];
|
||||||
|
CHAR8 oem_table_id[8];
|
||||||
|
UINT32 oem_revision;
|
||||||
|
UINT32 asl_compiler_id;
|
||||||
|
UINT32 asl_compiler_revision;
|
||||||
|
} ACPI_SDT_HEADER;
|
||||||
|
|
||||||
|
/** BGRT structure */
|
||||||
|
typedef struct {
|
||||||
|
ACPI_SDT_HEADER header;
|
||||||
|
UINT16 version;
|
||||||
|
UINT8 status;
|
||||||
|
UINT8 image_type;
|
||||||
|
UINT64 image_address;
|
||||||
|
UINT32 image_offset_x;
|
||||||
|
UINT32 image_offset_y;
|
||||||
|
} ACPI_BGRT;
|
||||||
|
|
||||||
|
/** Bitmap file header */
|
||||||
|
typedef struct {
|
||||||
|
UINT8 magic_BM[2];
|
||||||
|
UINT32 file_size;
|
||||||
|
UINT8 unused_0x06[4];
|
||||||
|
UINT32 pixel_data_offset;
|
||||||
|
UINT32 dib_header_size;
|
||||||
|
UINT32 width;
|
||||||
|
UINT32 height;
|
||||||
|
UINT16 planes;
|
||||||
|
UINT16 bpp;
|
||||||
|
} BMP;
|
||||||
|
#pragma pack(pop)
|
||||||
115
src/util.c
Normal file
115
src/util.c
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#include <efilib.h>
|
||||||
|
|
||||||
|
const CHAR16* TmpStr(CHAR8 *src, int length) {
|
||||||
|
static CHAR16 arr[4][16];
|
||||||
|
static int j;
|
||||||
|
CHAR16* dest = arr[j = (j+1) % 4];
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < length && i < 16-1 && src[i]; ++i) {
|
||||||
|
dest[i] = src[i];
|
||||||
|
}
|
||||||
|
dest[i] = 0;
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINTN NullPrint(IN CHAR16 *fmt, ...) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT8 CalculateAcpiChecksum(void* data, UINTN size) {
|
||||||
|
UINT8 sum = 0;
|
||||||
|
UINT8* arr = data;
|
||||||
|
for (UINTN i = 0; i < size; ++i) {
|
||||||
|
sum += arr[i];
|
||||||
|
}
|
||||||
|
return 256 - sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CHAR16* TrimLeft(const CHAR16* s) {
|
||||||
|
// Skip white-space and BOM.
|
||||||
|
while (s[0] == L'\xfeff' || s[0] == ' ' || s[0] == '\t') {
|
||||||
|
++s;
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CHAR16* StrStr(const CHAR16* haystack, const CHAR16* needle) {
|
||||||
|
int len = StrLen(needle);
|
||||||
|
while (haystack && haystack[0]) {
|
||||||
|
if (StrnCmp(haystack, needle, len) == 0) {
|
||||||
|
return haystack;
|
||||||
|
}
|
||||||
|
++haystack;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CHAR16* StrStrAfter(const CHAR16* haystack, const CHAR16* needle) {
|
||||||
|
return (haystack = StrStr(haystack, needle)) ? haystack + StrLen(needle) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT64 Random_a, Random_b;
|
||||||
|
|
||||||
|
UINT64 Random(void) {
|
||||||
|
// Implemented after xoroshiro128plus.c
|
||||||
|
if (!Random_a && !Random_b) {
|
||||||
|
RandomSeedAuto();
|
||||||
|
}
|
||||||
|
UINT64 a = Random_a, b = Random_b, r = a + b;
|
||||||
|
b ^= a;
|
||||||
|
Random_a = rotl(a, 55) ^ b ^ (b << 14);
|
||||||
|
Random_b = rotl(b, 36);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RandomSeed(UINT64 a, UINT64 b) {
|
||||||
|
Random_a = a;
|
||||||
|
Random_b = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RandomSeedAuto(void) {
|
||||||
|
EFI_TIME t;
|
||||||
|
RT->GetTime(&t, 0);
|
||||||
|
UINT64 a, b = ((((((UINT64) t.Second * 100 + t.Minute) * 100 + t.Hour) * 100 + t.Day) * 100 + t.Month) * 10000 + t.Year) * 300000 + t.Nanosecond;
|
||||||
|
BS->GetNextMonotonicCount(&a);
|
||||||
|
RandomSeed(a, b), Random(), Random();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaitKey(void) {
|
||||||
|
ST->ConIn->Reset(ST->ConIn, FALSE);
|
||||||
|
WaitForSingleEvent(ST->ConIn->WaitForKey, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* LoadFileWithPadding(EFI_FILE_HANDLE dir, const CHAR16* path, UINTN* size_ptr, UINTN padding) {
|
||||||
|
EFI_STATUS e;
|
||||||
|
EFI_FILE_HANDLE handle;
|
||||||
|
|
||||||
|
e = dir->Open(dir, &handle, (CHAR16*) path, EFI_FILE_MODE_READ, 0);
|
||||||
|
if (EFI_ERROR(e)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
EFI_FILE_INFO *info = LibFileInfo(handle);
|
||||||
|
UINTN size = info->FileSize;
|
||||||
|
FreePool(info);
|
||||||
|
|
||||||
|
void* data = 0;
|
||||||
|
e = BS->AllocatePool(EfiBootServicesData, size + padding, &data);
|
||||||
|
if (EFI_ERROR(e)) {
|
||||||
|
handle->Close(handle);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
e = handle->Read(handle, &size, data);
|
||||||
|
*(UINT32*)((char*)data + size) = 0;
|
||||||
|
handle->Close(handle);
|
||||||
|
if (EFI_ERROR(e)) {
|
||||||
|
FreePool(data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (size_ptr) {
|
||||||
|
*size_ptr = size;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
101
src/util.h
Normal file
101
src/util.h
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <efi.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a short ASCII string to UCS2, store in a static array.
|
||||||
|
*
|
||||||
|
* @param src The ASCII string. Will be truncated to 15 characters + null.
|
||||||
|
* @param length The maximum length, if the string is not null-terminated.
|
||||||
|
* @return The UCS2 string, statically allocated, null-terminated.
|
||||||
|
*/
|
||||||
|
extern const CHAR16* TmpStr(CHAR8 *src, int length);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Empty function that has the same signature as Print.
|
||||||
|
*/
|
||||||
|
extern UINTN NullPrint(IN CHAR16 *fmt, ...);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the checksum for an ACPI table.
|
||||||
|
*
|
||||||
|
* @param data Pointer to the table.
|
||||||
|
* @param size Table length in bytes.
|
||||||
|
* @return Checksum.
|
||||||
|
*/
|
||||||
|
extern UINT8 CalculateAcpiChecksum(void* data, UINTN size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the greater of two numbers.
|
||||||
|
*/
|
||||||
|
static inline int max(int a, int b) {
|
||||||
|
return a > b ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trim BOM, spaces and tabs from the beginning of a string.
|
||||||
|
*
|
||||||
|
* @param s The string.
|
||||||
|
* @return Pointer to the first acceptable character.
|
||||||
|
*/
|
||||||
|
extern const CHAR16* TrimLeft(const CHAR16* s);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the position of another string within a string.
|
||||||
|
*
|
||||||
|
* @param haystack The full text.
|
||||||
|
* @param needle The string to look for.
|
||||||
|
* @return Pointer to the first occurence of needle in the haystack, or 0.
|
||||||
|
*/
|
||||||
|
extern const CHAR16* StrStr(const CHAR16* haystack, const CHAR16* needle);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the position after another string within a string.
|
||||||
|
*
|
||||||
|
* @param haystack The full text.
|
||||||
|
* @param needle The string to look for.
|
||||||
|
* @return Pointer after the first occurence of needle in the haystack, or 0.
|
||||||
|
*/
|
||||||
|
extern const CHAR16* StrStrAfter(const CHAR16* haystack, const CHAR16* needle);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rotate left a 64-bit value.
|
||||||
|
*/
|
||||||
|
static inline UINT64 rotl(const UINT64 x, int k) {
|
||||||
|
return (x << k) | (x >> (64 - k));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a random 64-bit number.
|
||||||
|
*/
|
||||||
|
extern UINT64 Random(void);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Seed the random number generator. Pass 0 and 0 to seed from the clock.
|
||||||
|
*/
|
||||||
|
extern void RandomSeed(UINT64 a, UINT64 b);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Seed the random number generator automatically.
|
||||||
|
*/
|
||||||
|
extern void RandomSeedAuto(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for a key press.
|
||||||
|
*/
|
||||||
|
extern void WaitKey(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a file, allocate some extra bytes as well.
|
||||||
|
*/
|
||||||
|
extern void* LoadFileWithPadding(EFI_FILE_HANDLE dir, const CHAR16* path, UINTN* size_ptr, UINTN padding);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a file.
|
||||||
|
*/
|
||||||
|
static inline void* LoadFile(EFI_FILE_HANDLE dir, const CHAR16* path, UINTN* size_ptr) {
|
||||||
|
return LoadFileWithPadding(dir, path, size_ptr, 0);
|
||||||
|
}
|
||||||
|
|
||||||
9
uninstall.bat
Executable file
9
uninstall.bat
Executable file
@@ -0,0 +1,9 @@
|
|||||||
|
@ECHO OFF
|
||||||
|
CD %~dp0
|
||||||
|
|
||||||
|
IF NOT EXIST install.bat (
|
||||||
|
ECHO The uninstaller needs install.bat!
|
||||||
|
EXIT /B 1
|
||||||
|
)
|
||||||
|
|
||||||
|
CALL install.bat uninstall
|
||||||
Reference in New Issue
Block a user