diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..be77eab --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "gnu-efi"] + path = gnu-efi + url = https://github.com/rhboot/gnu-efi.git diff --git a/Makefile b/Makefile index c7cf855..e5d6dd5 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,11 @@ 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 +LDFLAGS = -nostdlib -shared -Wl,-dll -Wl,--subsystem,10 -e efi_main -s GNUEFI_INC = /usr/$(CC_PREFIX)/include/efi -GNUEFI_LIB = /usr/$(CC_PREFIX)/lib -FILES_C = src/main.c src/util.c src/types.c src/config.c src/sbat.c +FILES_C = src/main.c src/util.c src/types.c src/config.c src/sbat.c src/efi.c FILES_H = $(wildcard src/*.h) FILES_CS = src/Setup.cs src/Esp.cs src/Efi.cs GIT_DESCRIBE := $(firstword $(GIT_DESCRIBE) $(shell git describe --tags) unknown) @@ -59,13 +57,13 @@ efi/bootx64.efi: CC_PREFIX = x86_64-w64-mingw32 efi/bootx64.efi: GNUEFI_ARCH = x86_64 efi/bootx64.efi: $(FILES_C) @mkdir -p efi - $(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ $(LIBS) -s + $(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ efi/bootia32.efi: CC_PREFIX = i686-w64-mingw32 efi/bootia32.efi: GNUEFI_ARCH = ia32 efi/bootia32.efi: $(FILES_C) @mkdir -p efi - $(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ $(LIBS) -s + $(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ clean: rm -rf setup.exe efi efi-signed diff --git a/gnu-efi b/gnu-efi new file mode 160000 index 0000000..965f557 --- /dev/null +++ b/gnu-efi @@ -0,0 +1 @@ +Subproject commit 965f557ab7d9cb87993ea43bbbc6514c3d28f6bb diff --git a/src/config.c b/src/config.c index c038f0b..fd9b663 100644 --- a/src/config.c +++ b/src/config.c @@ -1,8 +1,6 @@ #include "config.h" #include "util.h" -#include - BOOLEAN ReadConfigFile(struct HackBGRT_config* config, EFI_FILE_HANDLE root_dir, const CHAR16* path) { void* data = 0; UINTN data_bytes = 0; diff --git a/src/config.h b/src/config.h index c9e0c1d..b6261fc 100644 --- a/src/config.h +++ b/src/config.h @@ -1,6 +1,6 @@ #pragma once -#include +#include "efi.h" /** * Possible actions to perform on the BGRT. diff --git a/src/efi.c b/src/efi.c new file mode 100644 index 0000000..fbf713f --- /dev/null +++ b/src/efi.c @@ -0,0 +1,159 @@ +#include "efi.h" +#include "util.h" + +// New implementations of some functions in gnu-efi. +// These functions are designed to avoid other gnu-efi calls. + +EFI_STATUS LibLocateProtocol(IN EFI_GUID *ProtocolGuid, OUT VOID **Interface) { + EFI_HANDLE buffer[256]; + UINTN size = sizeof(buffer); + if (!EFI_ERROR(BS->LocateHandle(ByProtocol, ProtocolGuid, NULL, &size, buffer))) { + for (int i = 0; i < size / sizeof(EFI_HANDLE); ++i) { + if (!EFI_ERROR(BS->HandleProtocol(buffer[i], ProtocolGuid, Interface))) { + return EFI_SUCCESS; + } + } + } + return EFI_NOT_FOUND; +} + +EFI_DEVICE_PATH *FileDevicePath(IN EFI_HANDLE Device OPTIONAL, IN CHAR16 *FileName) { + EFI_DEVICE_PATH *old_path = 0; + if (!Device || EFI_ERROR(BS->HandleProtocol(Device, TmpGuidPtr((EFI_GUID) EFI_DEVICE_PATH_PROTOCOL_GUID), (void**)&old_path))) { + static EFI_DEVICE_PATH end_path = {END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, {sizeof(end_path), 0}}; + old_path = &end_path; + } + UINTN old_path_size = 0, instances = 0; + for (EFI_DEVICE_PATH *p0 = old_path;; p0 = NextDevicePathNode(p0)) { + old_path_size += DevicePathNodeLength(p0); + if (IsDevicePathEndType(p0)) { + instances += 1; + } + if (IsDevicePathEnd(p0)) { + break; + } + } + + UINTN size_str = (StrLen(FileName) + 1) * sizeof(*FileName); + UINTN size_fdp = SIZE_OF_FILEPATH_DEVICE_PATH + size_str; + + EFI_DEVICE_PATH *new_path; + if (EFI_ERROR(BS->AllocatePool(EfiBootServicesData, old_path_size + instances * size_fdp, (void**)&new_path))) { + return 0; + } + + EFI_DEVICE_PATH *p1 = new_path; + for (EFI_DEVICE_PATH *p0 = old_path;; p0 = NextDevicePathNode(p0)) { + if (IsDevicePathEndType(p0)) { + *p1 = (EFI_DEVICE_PATH) { + .Type = MEDIA_DEVICE_PATH, + .SubType = MEDIA_FILEPATH_DP, + .Length = {size_fdp, size_fdp >> 8}, + }; + FILEPATH_DEVICE_PATH *f = (FILEPATH_DEVICE_PATH *) p1; + BS->CopyMem(f->PathName, FileName, size_str); + p1 = NextDevicePathNode(p1); + } + BS->CopyMem(p1, p0, DevicePathNodeLength(p0)); + if (IsDevicePathEnd(p0)) { + break; + } + p1 = NextDevicePathNode(p1); + } + + return new_path; +} + +INTN CompareMem(IN CONST VOID *Dest, IN CONST VOID *Src, IN UINTN len) { + CONST UINT8 *d = Dest, *s = Src; + for (UINTN i = 0; i < len; ++i) { + if (d[i] != s[i]) { + return d[i] - s[i]; + } + } + return 0; +} + +void StrnCat(IN CHAR16* dest, IN CONST CHAR16* src, UINTN len) { + CHAR16* d = dest; + while (*d) { + ++d; + } + while (len-- && *src) { + *d++ = *src++; + } + *d = 0; +} + +UINTN StrLen(IN CONST CHAR16* s) { + UINTN i = 0; + while (*s++) { + ++i; + } + return i; +} + +INTN StriCmp(IN CONST CHAR16* s1, IN CONST CHAR16* s2) { + while (*s1 && *s2) { + CHAR16 c1 = *s1++, c2 = *s2++; + if (c1 >= 'A' && c1 <= 'Z') { + c1 += 'a' - 'A'; + } + if (c2 >= 'A' && c2 <= 'Z') { + c2 += 'a' - 'A'; + } + if (c1 != c2) { + return c1 - c2; + } + } + return *s1 - *s2; +} + +INTN StrnCmp(IN CONST CHAR16* s1, IN CONST CHAR16* s2, UINTN len) { + while (*s1 && *s2 && len--) { + CHAR16 c1 = *s1++, c2 = *s2++; + if (c1 >= 'A' && c1 <= 'Z') { + c1 += 'a' - 'A'; + } + if (c2 >= 'A' && c2 <= 'Z') { + c2 += 'a' - 'A'; + } + if (c1 != c2) { + return c1 - c2; + } + } + return len ? *s1 - *s2 : 0; +} + +INTN StrCmp(IN CONST CHAR16* s1, IN CONST CHAR16* s2) { + while (*s1 && *s2) { + if (*s1 != *s2) { + return *s1 - *s2; + } + ++s1, ++s2; + } + return *s1 - *s2; +} + +UINTN Atoi(IN CONST CHAR16* s) { + UINTN n = 0; + while (*s >= '0' && *s <= '9') { + n = n * 10 + *s++ - '0'; + } + return n; +} + +void *memset(void *s, int c, __SIZE_TYPE__ n) { + unsigned char *p = s; + while (n--) + *p++ = c; + return s; +} + +void *memcpy(void *dest, const void *src, __SIZE_TYPE__ n) { + const unsigned char *q = src; + unsigned char *p = dest; + while (n--) + *p++ = *q++; + return dest; +} diff --git a/src/efi.h b/src/efi.h new file mode 100644 index 0000000..d440649 --- /dev/null +++ b/src/efi.h @@ -0,0 +1,5 @@ +#pragma once + +#include +#include +#include diff --git a/src/main.c b/src/main.c index 251633c..e28199a 100644 --- a/src/main.c +++ b/src/main.c @@ -1,6 +1,4 @@ -#include -#include - +#include "efi.h" #include "types.h" #include "config.h" #include "util.h" @@ -14,6 +12,10 @@ const CHAR16 version[] = L"unknown; not an official release?"; #endif +EFI_SYSTEM_TABLE *ST; +EFI_BOOT_SERVICES *BS; +EFI_RUNTIME_SERVICES *RT; + /** * The configuration. */ @@ -404,8 +406,11 @@ static EFI_HANDLE LoadApp(int print_failure, EFI_HANDLE image_handle, EFI_LOADED /** * The main program. */ -EFI_STATUS EFIAPI EfiMain(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *ST_) { - InitializeLib(image_handle, ST_); +EFI_STATUS EFIAPI efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *ST_) { + ST = ST_; + BS = ST_->BootServices; + RT = ST_->RuntimeServices; + Log(0, L"HackBGRT version: %s\n", version); EFI_LOADED_IMAGE* image; @@ -504,12 +509,3 @@ EFI_STATUS EFIAPI EfiMain(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *ST_) { 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_); -} diff --git a/src/types.h b/src/types.h index 3bb42a3..34e0c8e 100644 --- a/src/types.h +++ b/src/types.h @@ -1,6 +1,6 @@ #pragma once -#include +#include "efi.h" #pragma pack(push, 1) diff --git a/src/util.c b/src/util.c index 1bd8129..d7a34c0 100644 --- a/src/util.c +++ b/src/util.c @@ -1,7 +1,5 @@ #include "util.h" -#include - const CHAR16* TmpStr(CHAR8 *src, int length) { static CHAR16 arr[4][16]; static int j; diff --git a/src/util.h b/src/util.h index 3785fd4..a83cd6d 100644 --- a/src/util.h +++ b/src/util.h @@ -1,6 +1,6 @@ #pragma once -#include +#include "efi.h" /** * Convert a short ASCII string to UCS2, store in a static array.