From 96599b1838a8c9ea85efd91de0efe6495d4bfdc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauri=20Kentt=C3=A4?= Date: Sat, 5 Apr 2025 16:29:29 +0300 Subject: [PATCH] Try to load config.txt from the current dir To allow multiple configurations for HackBGRT, or to allow a custom installation path, try to load config.txt from the same directory as the executable. --- README.md | 2 ++ src/efi.c | 27 +++++++++++++++++++++++++++ src/main.c | 31 +++++++++++++++++++++++++++---- 3 files changed, 56 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index eaea816..07aa7c0 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,8 @@ If you need it for other systems as well: To install purely on Linux, you can install with `setup.exe dry-run` and then manually copy files from `dry-run/EFI` to your `[EFI System Partition]/EFI`. For further instructions, consult the documentation of your own Linux system. +HackBGRT tries to read its configuration from the same directory where it's installed, so you can even make (manually) multiple installations in different directories. + ## Configuration The configuration options are described in `config.txt`, which the installer copies into `[EFI System Partition]\EFI\HackBGRT\config.txt`. diff --git a/src/efi.c b/src/efi.c index fbf713f..5fa2292 100644 --- a/src/efi.c +++ b/src/efi.c @@ -64,6 +64,33 @@ EFI_DEVICE_PATH *FileDevicePath(IN EFI_HANDLE Device OPTIONAL, IN CHAR16 *FileNa return new_path; } +CHAR16 *DevicePathToStr(EFI_DEVICE_PATH *DevPath) { + UINTN path_length = 0; + for (EFI_DEVICE_PATH *p0 = DevPath;; p0 = NextDevicePathNode(p0)) { + if (DevicePathType(p0) != MEDIA_DEVICE_PATH || DevicePathSubType(p0) != MEDIA_FILEPATH_DP) { + break; + } + path_length += DevicePathNodeLength(p0) + 1; + } + + CHAR16* str; + UINTN size_str = (path_length + 1) * sizeof(*str); + + if (!path_length || EFI_ERROR(BS->AllocatePool(EfiBootServicesData, size_str, (void**)&str))) { + return 0; + } + + UINTN pos = 0; + for (EFI_DEVICE_PATH *p0 = DevPath; pos < path_length; p0 = NextDevicePathNode(p0)) { + FILEPATH_DEVICE_PATH *f = (FILEPATH_DEVICE_PATH *) p0; + BS->CopyMem(str + pos, f->PathName, StrLen(f->PathName) * sizeof(*str)); + pos += DevicePathNodeLength(p0) + 1; + str[pos - 1] = L'\\'; + } + str[pos - 1] = 0; + return str; +} + 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) { diff --git a/src/main.c b/src/main.c index 7175702..c508d6d 100644 --- a/src/main.c +++ b/src/main.c @@ -439,16 +439,39 @@ EFI_STATUS EFIAPI efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *ST_) { goto fail; } - EFI_FILE_HANDLE base_dir; - if (EFI_ERROR(root_dir->Open(root_dir, &base_dir, L"\\EFI\\HackBGRT", EFI_FILE_MODE_READ, 0))) { - Log(config.debug, L"Failed to HackBGRT directory.\n"); - base_dir = root_dir; + CHAR16* default_dir_path = L"\\EFI\\HackBGRT"; + Log(config.debug, L"Default directory: %s\n", default_dir_path); + EFI_FILE_HANDLE default_dir; + if (EFI_ERROR(root_dir->Open(root_dir, &default_dir, default_dir_path, EFI_FILE_MODE_READ, 0))) { + Log(config.debug, L"Failed to open HackBGRT default directory.\n"); + default_dir = root_dir; } + CHAR16* working_dir_path = DevicePathToStr(image->FilePath); + for (int i = StrLen(working_dir_path), skipped_last_component = 0; i--;) { + if (working_dir_path[i] == L'/' || working_dir_path[i] == L'\\') { + working_dir_path[i] = skipped_last_component++ ? L'\\' : L'\0'; + } + } + Log(config.debug, L"Working directory: %s\n", working_dir_path); + EFI_FILE_HANDLE working_dir; + if (EFI_ERROR(root_dir->Open(root_dir, &working_dir, working_dir_path, EFI_FILE_MODE_READ, 0))) { + Log(config.debug, L"Failed to open HackBGRT working directory.\n"); + working_dir = default_dir; + } + + EFI_FILE_HANDLE base_dir = working_dir; + EFI_SHELL_PARAMETERS_PROTOCOL *shell_param_proto = NULL; if (EFI_ERROR(BS->OpenProtocol(image_handle, TmpGuidPtr((EFI_GUID) EFI_SHELL_PARAMETERS_PROTOCOL_GUID), (void**) &shell_param_proto, 0, 0, EFI_OPEN_PROTOCOL_GET_PROTOCOL)) || shell_param_proto->Argc <= 1) { const CHAR16* config_path = L"config.txt"; + retry_read_config: if (!ReadConfigFile(&config, base_dir, config_path)) { + if (base_dir != default_dir && StrCmp(default_dir_path, working_dir_path) != 0) { + base_dir = default_dir; + Log(config.debug, L"Trying the default directory.\n"); + goto retry_read_config; + } Log(1, L"No config, no command line!\n", config_path); goto fail; }