Gather log during boot

This commit is contained in:
Lauri Kenttä
2023-11-17 23:13:12 +02:00
parent e93ed54cb2
commit db934099df
9 changed files with 141 additions and 67 deletions
+1
View File
@@ -48,6 +48,7 @@ Instructions for enrolling the certificate (if it's possible at all) depend on y
* `allow-bad-loader` – ignore bad boot loader configuration in subsequent commands. * `allow-bad-loader` – ignore bad boot loader configuration in subsequent commands.
* `disable` – run all relevant `disable-*` commands. * `disable` – run all relevant `disable-*` commands.
* `uninstall` – disable and remove completely. * `uninstall` – disable and remove completely.
* `show-boot-log` – show the debug log collected during boot (if `log=1` is set in `config.txt`).
* For example, run `setup.exe batch install allow-secure-boot enable-overwrite` to copy files and overwrite the MS boot loader regardless of Secure Boot status. * For example, run `setup.exe batch install allow-secure-boot enable-overwrite` to copy files and overwrite the MS boot loader regardless of Secure Boot status.
### Multi-boot configurations ### Multi-boot configurations
+5
View File
@@ -38,6 +38,11 @@ image= y=-200 path=\EFI\HackBGRT\splash.bmp
# Preferred resolution. Use 0x0 for maximum and -1x-1 for original. # Preferred resolution. Use 0x0 for maximum and -1x-1 for original.
resolution=0x0 resolution=0x0
# Logging (0 for disabled, 1 for enabled).
# When logging is enabled, setup.exe can show debug information about the current boot.
# The log might occupy a few kilobytes of RAM.
log=1
# Debug mode (0 for disabled, 1 for enabled). # Debug mode (0 for disabled, 1 for enabled).
# Shows debug information and prompts for keypress before booting. # Shows debug information and prompts for keypress before booting.
debug=0 debug=0
+23
View File
@@ -139,8 +139,19 @@ public class Efi {
} }
} }
/**
* GUID of the global EFI variables.
*/
public const string EFI_GLOBAL_GUID = "{8be4df61-93ca-11d2-aa0d-00e098032b8c}"; public const string EFI_GLOBAL_GUID = "{8be4df61-93ca-11d2-aa0d-00e098032b8c}";
/**
* GUID for HackBGRT EFI variables.
*/
public const string EFI_HACKBGRT_GUID = "{03c64761-075f-4dba-abfb-2ed89e18b236}";
/**
* Directory containing EFI variables in Linux.
*/
public const string LinuxEfiDir = "/sys/firmware/efi/efivars"; public const string LinuxEfiDir = "/sys/firmware/efi/efivars";
/** /**
@@ -471,6 +482,18 @@ public class Efi {
} }
} }
/**
* Retrieve HackBGRT log collected during boot.
*/
public static string GetHackBGRTLog() {
try {
var log = GetVariable("HackBGRTLog", EFI_HACKBGRT_GUID);
return new string(BytesToUInt16s(log.Data).Select(i => (char)i).ToArray());
} catch (Exception e) {
return $"Log not found: {e.ToString()}";
}
}
/** /**
* Log the BGRT table (for debugging). * Log the BGRT table (for debugging).
*/ */
+9 -1
View File
@@ -69,6 +69,7 @@ public class Setup {
"disable", "disable",
"uninstall", "uninstall",
"boot-to-fw", "boot-to-fw",
"show-boot-log",
}; };
/** @var The target directory. */ /** @var The target directory. */
@@ -751,6 +752,7 @@ public class Setup {
WriteLine(" B = boot to UEFI setup"); WriteLine(" B = boot to UEFI setup");
WriteLine(" - lets you disable Secure Boot"); WriteLine(" - lets you disable Secure Boot");
WriteLine(" - lets you move HackBGRT before Windows in boot order"); WriteLine(" - lets you move HackBGRT before Windows in boot order");
WriteLine(" L = show boot log (what HackBGRT did during boot)");
WriteLine(" C = cancel"); WriteLine(" C = cancel");
var k = Console.ReadKey().Key; var k = Console.ReadKey().Key;
@@ -773,6 +775,8 @@ public class Setup {
RunPrivilegedActions(new string[] { "uninstall" }); RunPrivilegedActions(new string[] { "uninstall" });
} else if (k == ConsoleKey.B) { } else if (k == ConsoleKey.B) {
RunPrivilegedActions(new string[] { "boot-to-fw" }); RunPrivilegedActions(new string[] { "boot-to-fw" });
} else if (k == ConsoleKey.L) {
RunPrivilegedActions(new string[] { "show-boot-log" });
} else if (k == ConsoleKey.C) { } else if (k == ConsoleKey.C) {
throw new ExitSetup(1); throw new ExitSetup(1);
} else { } else {
@@ -806,6 +810,8 @@ public class Setup {
InitEspPath(); InitEspPath();
InitEspInfo(); InitEspInfo();
var bootLog = $"\n--- BOOT LOG START ---\n{Efi.GetHackBGRTLog()}\n--- BOOT LOG END ---";
Setup.Log(bootLog);
Efi.LogBGRT(); Efi.LogBGRT();
Efi.LogBootEntries(); Efi.LogBootEntries();
if (GetBootTime() is DateTime bootTime) { if (GetBootTime() is DateTime bootTime) {
@@ -869,6 +875,8 @@ public class Setup {
Uninstall(); Uninstall();
} else if (arg == "boot-to-fw") { } else if (arg == "boot-to-fw") {
BootToFW(); BootToFW();
} else if (arg == "show-boot-log") {
WriteLine(bootLog);
} else { } else {
throw new SetupException($"Invalid action: '{arg}'!"); throw new SetupException($"Invalid action: '{arg}'!");
} }
@@ -934,7 +942,7 @@ public class Setup {
WriteLine("This was a dry run, your system was not actually modified."); WriteLine("This was a dry run, your system was not actually modified.");
} }
if (!Batch) { if (!Batch) {
WriteLine("If you need to report a bug, please include the setup.log file."); WriteLine("If you need to report a bug,\n - run this setup again with menu option L (show-boot-log)\n - then include the setup.log file with your report.");
WriteLine("Press any key to quit."); WriteLine("Press any key to quit.");
Console.ReadKey(); Console.ReadKey();
} }
+9 -7
View File
@@ -8,7 +8,7 @@ BOOLEAN ReadConfigFile(struct HackBGRT_config* config, EFI_FILE_HANDLE root_dir,
UINTN data_bytes = 0; UINTN data_bytes = 0;
data = LoadFileWithPadding(root_dir, path, &data_bytes, 4); data = LoadFileWithPadding(root_dir, path, &data_bytes, 4);
if (!data) { if (!data) {
Print(L"HackBGRT: Failed to load configuration (%s)!\n", path); Log(1, L"HackBGRT: Failed to load configuration (%s)!\n", path);
return FALSE; return FALSE;
} }
CHAR16* str; CHAR16* str;
@@ -74,9 +74,7 @@ static void SetBMPWithRandom(struct HackBGRT_config* config, int weight, enum Ha
config->image_weight_sum += weight; config->image_weight_sum += weight;
UINT32 random = Random(); UINT32 random = Random();
UINT32 limit = 0xfffffffful / config->image_weight_sum * weight; UINT32 limit = 0xfffffffful / config->image_weight_sum * weight;
if (config->debug) { Log(config->debug, L"HackBGRT: n=%d, action=%d, x=%d, y=%d, o=%d, path=%s, random = %08x, limit = %08x\n", weight, action, x, y, o, path, random, limit);
Print(L"HackBGRT: weight %d, action %d, x %d, y %d, o %d, path %s, random = %08x, limit = %08x\n", weight, action, x, y, o, path, random, limit);
}
if (!config->image_weight_sum || random <= limit) { if (!config->image_weight_sum || random <= limit) {
config->action = action; config->action = action;
config->image_path = path; config->image_path = path;
@@ -112,7 +110,7 @@ static void ReadConfigImage(struct HackBGRT_config* config, const CHAR16* line)
} else if (StrStr(line, L"keep")) { } else if (StrStr(line, L"keep")) {
action = HackBGRT_KEEP; action = HackBGRT_KEEP;
} else { } else {
Print(L"HackBGRT: Invalid image line: %s\n", line); Log(1, L"HackBGRT: Invalid image line: %s\n", line);
return; return;
} }
int weight = n && (!f || n < f) ? Atoi(n) : 1; int weight = n && (!f || n < f) ? Atoi(n) : 1;
@@ -129,7 +127,7 @@ static void ReadConfigResolution(struct HackBGRT_config* config, const CHAR16* l
config->resolution_x = *x == '-' ? -(int)Atoi(x+1) : (int)Atoi(x); config->resolution_x = *x == '-' ? -(int)Atoi(x+1) : (int)Atoi(x);
config->resolution_y = *y == '-' ? -(int)Atoi(y+1) : (int)Atoi(y); config->resolution_y = *y == '-' ? -(int)Atoi(y+1) : (int)Atoi(y);
} else { } else {
Print(L"HackBGRT: Invalid resolution line: %s\n", line); Log(1, L"HackBGRT: Invalid resolution line: %s\n", line);
} }
} }
@@ -143,6 +141,10 @@ void ReadConfigLine(struct HackBGRT_config* config, EFI_FILE_HANDLE root_dir, co
config->debug = (StrCmp(line, L"debug=1") == 0); config->debug = (StrCmp(line, L"debug=1") == 0);
return; return;
} }
if (StrnCmp(line, L"log=", 4) == 0) {
config->log = (StrCmp(line, L"log=1") == 0);
return;
}
if (StrnCmp(line, L"image=", 6) == 0) { if (StrnCmp(line, L"image=", 6) == 0) {
ReadConfigImage(config, line + 6); ReadConfigImage(config, line + 6);
return; return;
@@ -159,5 +161,5 @@ void ReadConfigLine(struct HackBGRT_config* config, EFI_FILE_HANDLE root_dir, co
ReadConfigResolution(config, line + 11); ReadConfigResolution(config, line + 11);
return; return;
} }
Print(L"Unknown configuration directive: %s\n", line); Log(1, L"Unknown configuration directive: %s\n", line);
} }
+1 -1
View File
@@ -21,7 +21,7 @@ enum HackBGRT_coordinate {
* The configuration. * The configuration.
*/ */
struct HackBGRT_config { struct HackBGRT_config {
int debug; int debug, log;
enum HackBGRT_action action; enum HackBGRT_action action;
const CHAR16* image_path; const CHAR16* image_path;
int image_x; int image_x;
+57 -55
View File
@@ -6,20 +6,20 @@
#include "util.h" #include "util.h"
/** /**
* The Print function signature. * The version.
*/ */
typedef UINTN print_t(IN CONST CHAR16 *fmt, ...); #ifdef GIT_DESCRIBE_W
const CHAR16 version[] = GIT_DESCRIBE_W;
/** #else
* The function for debug printing; either Print or NullPrint. const CHAR16 version[] = L"unknown; not an official release?";
*/ #endif
print_t* Debug = NullPrint;
/** /**
* The configuration. * The configuration.
*/ */
static struct HackBGRT_config config = { static struct HackBGRT_config config = {
.action = HackBGRT_KEEP .log = 1,
.action = HackBGRT_KEEP,
}; };
/** /**
@@ -45,7 +45,7 @@ static void SetResolution(int w, int h) {
if (!gop) { if (!gop) {
config.old_resolution_x = config.resolution_x = 0; config.old_resolution_x = config.resolution_x = 0;
config.old_resolution_y = config.resolution_y = 0; config.old_resolution_y = config.resolution_y = 0;
Debug(L"GOP not found!\n"); Log(config.debug, L"GOP not found!\n");
return; return;
} }
UINTN best_i = gop->Mode->Mode; UINTN best_i = gop->Mode->Mode;
@@ -54,7 +54,7 @@ static void SetResolution(int w, int h) {
w = (w <= 0 ? w < 0 ? best_w : 999999 : w); w = (w <= 0 ? w < 0 ? best_w : 999999 : w);
h = (h <= 0 ? h < 0 ? best_h : 999999 : h); h = (h <= 0 ? h < 0 ? best_h : 999999 : h);
Debug(L"Looking for resolution %dx%d...\n", w, h); Log(config.debug, L"Looking for resolution %dx%d...\n", w, h);
for (UINT32 i = gop->Mode->MaxMode; i--;) { for (UINT32 i = gop->Mode->MaxMode; i--;) {
int new_w = 0, new_h = 0; int new_w = 0, new_h = 0;
@@ -87,7 +87,7 @@ static void SetResolution(int w, int h) {
best_h = new_h; best_h = new_h;
best_i = i; best_i = i;
} }
Debug(L"Found resolution %dx%d.\n", best_w, best_h); Log(config.debug, L"Found resolution %dx%d.\n", best_w, best_h);
config.resolution_x = best_w; config.resolution_x = best_w;
config.resolution_y = best_h; config.resolution_y = best_h;
if (best_i != gop->Mode->Mode) { if (best_i != gop->Mode->Mode) {
@@ -107,7 +107,7 @@ ACPI_SDT_HEADER* CreateXsdt(ACPI_SDT_HEADER* xsdt0, UINTN entries) {
UINT32 xsdt_len = sizeof(ACPI_SDT_HEADER) + entries * sizeof(UINT64); UINT32 xsdt_len = sizeof(ACPI_SDT_HEADER) + entries * sizeof(UINT64);
BS->AllocatePool(EfiACPIReclaimMemory, xsdt_len, (void**)&xsdt); BS->AllocatePool(EfiACPIReclaimMemory, xsdt_len, (void**)&xsdt);
if (!xsdt) { if (!xsdt) {
Print(L"HackBGRT: Failed to allocate memory for XSDT.\n"); Log(1, L"HackBGRT: Failed to allocate memory for XSDT.\n");
return 0; return 0;
} }
ZeroMem(xsdt, xsdt_len); ZeroMem(xsdt, xsdt_len);
@@ -139,17 +139,17 @@ static ACPI_BGRT* HandleAcpiTables(enum HackBGRT_action action, ACPI_BGRT* bgrt)
if (CompareMem(rsdp->signature, "RSD PTR ", 8) != 0 || rsdp->revision < 2 || !VerifyAcpiRsdp2Checksums(rsdp)) { if (CompareMem(rsdp->signature, "RSD PTR ", 8) != 0 || rsdp->revision < 2 || !VerifyAcpiRsdp2Checksums(rsdp)) {
continue; continue;
} }
Debug(L"RSDP @%x: revision = %d, OEM ID = %s\n", (UINTN)rsdp, rsdp->revision, TmpStr(rsdp->oem_id, 6)); Log(config.debug, L"RSDP @%x: revision = %d, OEM ID = %s\n", (UINTN)rsdp, rsdp->revision, TmpStr(rsdp->oem_id, 6));
ACPI_SDT_HEADER* xsdt = (ACPI_SDT_HEADER *) (UINTN) rsdp->xsdt_address; ACPI_SDT_HEADER* xsdt = (ACPI_SDT_HEADER *) (UINTN) rsdp->xsdt_address;
if (!xsdt || CompareMem(xsdt->signature, "XSDT", 4) != 0 || !VerifyAcpiSdtChecksum(xsdt)) { if (!xsdt || CompareMem(xsdt->signature, "XSDT", 4) != 0 || !VerifyAcpiSdtChecksum(xsdt)) {
Debug(L"* XSDT: missing or invalid\n"); Log(config.debug, L"* XSDT: missing or invalid\n");
continue; continue;
} }
UINT64* entry_arr = (UINT64*)&xsdt[1]; UINT64* entry_arr = (UINT64*)&xsdt[1];
UINT32 entry_arr_length = (xsdt->length - sizeof(*xsdt)) / sizeof(UINT64); UINT32 entry_arr_length = (xsdt->length - sizeof(*xsdt)) / sizeof(UINT64);
Debug(L"* XSDT @%x: OEM ID = %s, entry count = %d\n", (UINTN)xsdt, TmpStr(xsdt->oem_id, 6), entry_arr_length); Log(config.debug, L"* XSDT @%x: OEM ID = %s, entry count = %d\n", (UINTN)xsdt, TmpStr(xsdt->oem_id, 6), entry_arr_length);
int bgrt_count = 0; int bgrt_count = 0;
for (int j = 0; j < entry_arr_length; j++) { for (int j = 0; j < entry_arr_length; j++) {
@@ -157,16 +157,16 @@ static ACPI_BGRT* HandleAcpiTables(enum HackBGRT_action action, ACPI_BGRT* bgrt)
if (CompareMem(entry->signature, "BGRT", 4) != 0) { if (CompareMem(entry->signature, "BGRT", 4) != 0) {
continue; continue;
} }
Debug(L" - ACPI table @%x: %s, revision = %d, OEM ID = %s\n", (UINTN)entry, TmpStr(entry->signature, 4), entry->revision, TmpStr(entry->oem_id, 6)); Log(config.debug, L" - ACPI table @%x: %s, revision = %d, OEM ID = %s\n", (UINTN)entry, TmpStr(entry->signature, 4), entry->revision, TmpStr(entry->oem_id, 6));
switch (action) { switch (action) {
case HackBGRT_KEEP: case HackBGRT_KEEP:
if (!bgrt) { if (!bgrt) {
Debug(L" -> Returning this one for later use.\n"); Log(config.debug, L" -> Returning this one for later use.\n");
bgrt = (ACPI_BGRT*) entry; bgrt = (ACPI_BGRT*) entry;
} }
break; break;
case HackBGRT_REMOVE: case HackBGRT_REMOVE:
Debug(L" -> Deleting.\n"); Log(config.debug, L" -> Deleting.\n");
for (int k = j+1; k < entry_arr_length; ++k) { for (int k = j+1; k < entry_arr_length; ++k) {
entry_arr[k-1] = entry_arr[k]; entry_arr[k-1] = entry_arr[k];
} }
@@ -176,13 +176,13 @@ static ACPI_BGRT* HandleAcpiTables(enum HackBGRT_action action, ACPI_BGRT* bgrt)
--j; --j;
break; break;
case HackBGRT_REPLACE: case HackBGRT_REPLACE:
Debug(L" -> Replacing.\n"); Log(config.debug, L" -> Replacing.\n");
entry_arr[j] = (UINTN) bgrt; entry_arr[j] = (UINTN) bgrt;
} }
bgrt_count += 1; bgrt_count += 1;
} }
if (!bgrt_count && action == HackBGRT_REPLACE && bgrt) { if (!bgrt_count && action == HackBGRT_REPLACE && bgrt) {
Debug(L" - Adding missing BGRT.\n"); Log(config.debug, L" - Adding missing BGRT.\n");
xsdt = CreateXsdt(xsdt, entry_arr_length + 1); xsdt = CreateXsdt(xsdt, entry_arr_length + 1);
entry_arr = (UINT64*)&xsdt[1]; entry_arr = (UINT64*)&xsdt[1];
entry_arr[entry_arr_length++] = (UINTN) bgrt; entry_arr[entry_arr_length++] = (UINTN) bgrt;
@@ -208,7 +208,7 @@ static BMP* MakeBMP(int w, int h, UINT8 r, UINT8 g, UINT8 b) {
BMP* bmp = 0; BMP* bmp = 0;
BS->AllocatePool(EfiBootServicesData, 54 + w * h * 4, (void**) &bmp); BS->AllocatePool(EfiBootServicesData, 54 + w * h * 4, (void**) &bmp);
if (!bmp) { if (!bmp) {
Print(L"HackBGRT: Failed to allocate a blank BMP!\n"); Log(1, L"HackBGRT: Failed to allocate a blank BMP!\n");
BS->Stall(1000000); BS->Stall(1000000);
return 0; return 0;
} }
@@ -243,7 +243,7 @@ static BMP* LoadBMP(EFI_FILE_HANDLE root_dir, const CHAR16* path) {
if (!path) { if (!path) {
return MakeBMP(1, 1, 0, 0, 0); // empty path = black image return MakeBMP(1, 1, 0, 0, 0); // empty path = black image
} }
Debug(L"HackBGRT: Loading %s.\n", path); Log(config.debug, L"HackBGRT: Loading %s.\n", path);
UINTN size = 0; UINTN size = 0;
BMP* bmp = LoadFile(root_dir, path, &size); BMP* bmp = LoadFile(root_dir, path, &size);
if (bmp) { if (bmp) {
@@ -251,9 +251,9 @@ static BMP* LoadBMP(EFI_FILE_HANDLE root_dir, const CHAR16* path) {
return bmp; return bmp;
} }
FreePool(bmp); FreePool(bmp);
Print(L"HackBGRT: Invalid BMP (%s)!\n", path); Log(1, L"HackBGRT: Invalid BMP (%s)!\n", path);
} else { } else {
Print(L"HackBGRT: Failed to load BMP (%s)!\n", path); Log(1, L"HackBGRT: Failed to load BMP (%s)!\n", path);
} }
BS->Stall(1000000); BS->Stall(1000000);
return MakeBMP(16, 16, 255, 0, 0); // error = red image return MakeBMP(16, 16, 255, 0, 0); // error = red image
@@ -321,7 +321,7 @@ void HackBgrt(EFI_FILE_HANDLE root_dir) {
// Replace missing = allocate new. // Replace missing = allocate new.
BS->AllocatePool(EfiACPIReclaimMemory, sizeof(*bgrt), (void**)&bgrt); BS->AllocatePool(EfiACPIReclaimMemory, sizeof(*bgrt), (void**)&bgrt);
if (!bgrt) { if (!bgrt) {
Print(L"HackBGRT: Failed to allocate memory for BGRT.\n"); Log(1, L"HackBGRT: Failed to allocate memory for BGRT.\n");
return; return;
} }
} }
@@ -373,8 +373,8 @@ void HackBgrt(EFI_FILE_HANDLE root_dir) {
bgrt->image_offset_x = max(0, min(max_x, new_x + (new_reso_x - new_bmp->width) / 2)); bgrt->image_offset_x = max(0, min(max_x, new_x + (new_reso_x - new_bmp->width) / 2));
bgrt->image_offset_y = max(0, min(max_y, new_y + (new_reso_y - new_bmp->height) / 2)); bgrt->image_offset_y = max(0, min(max_y, new_y + (new_reso_y - new_bmp->height) / 2));
Debug( Log(config.debug,
L"HackBGRT: BMP at (%d, %d), center (%d, %d), resolution (%d, %d) with orientation %d applied.\n", L"HackBGRT: BMP at (%d, %d), center (%d, %d), resolution (%d, %d), orientation %d.\n",
(int) bgrt->image_offset_x, (int) bgrt->image_offset_y, (int) bgrt->image_offset_x, (int) bgrt->image_offset_y,
new_x, new_y, new_reso_x, new_reso_y, new_x, new_y, new_reso_x, new_reso_y,
new_orientation * 90 new_orientation * 90
@@ -388,12 +388,12 @@ void HackBgrt(EFI_FILE_HANDLE root_dir) {
/** /**
* Load an application. * Load an application.
*/ */
static EFI_HANDLE LoadApp(print_t* print_failure, EFI_HANDLE image_handle, EFI_LOADED_IMAGE* image, const CHAR16* path) { static EFI_HANDLE LoadApp(int print_failure, EFI_HANDLE image_handle, EFI_LOADED_IMAGE* image, const CHAR16* path) {
EFI_DEVICE_PATH* boot_dp = FileDevicePath(image->DeviceHandle, (CHAR16*) path); EFI_DEVICE_PATH* boot_dp = FileDevicePath(image->DeviceHandle, (CHAR16*) path);
EFI_HANDLE result = 0; EFI_HANDLE result = 0;
Debug(L"HackBGRT: Loading application %s.\n", path); Log(config.debug, L"HackBGRT: Loading application %s.\n", path);
if (EFI_ERROR(BS->LoadImage(0, image_handle, boot_dp, 0, 0, &result))) { if (EFI_ERROR(BS->LoadImage(0, image_handle, boot_dp, 0, 0, &result))) {
print_failure(L"HackBGRT: Failed to load application %s.\n", path); Log(config.debug || print_failure, L"HackBGRT: Failed to load application %s.\n", path);
} }
return result; return result;
} }
@@ -403,10 +403,11 @@ static EFI_HANDLE LoadApp(print_t* print_failure, EFI_HANDLE image_handle, EFI_L
*/ */
EFI_STATUS EFIAPI EfiMain(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *ST_) { EFI_STATUS EFIAPI EfiMain(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *ST_) {
InitializeLib(image_handle, ST_); InitializeLib(image_handle, ST_);
Log(0, L"HackBGRT version: %s\n", version);
EFI_LOADED_IMAGE* image; EFI_LOADED_IMAGE* image;
if (EFI_ERROR(BS->HandleProtocol(image_handle, &LoadedImageProtocol, (void**) &image))) { if (EFI_ERROR(BS->HandleProtocol(image_handle, &LoadedImageProtocol, (void**) &image))) {
Debug(L"HackBGRT: LOADED_IMAGE_PROTOCOL failed.\n"); Log(config.debug, L"HackBGRT: LOADED_IMAGE_PROTOCOL failed.\n");
goto fail; goto fail;
} }
@@ -418,14 +419,16 @@ EFI_STATUS EFIAPI EfiMain(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *ST_) {
if (argc <= 1) { if (argc <= 1) {
const CHAR16* config_path = L"\\EFI\\HackBGRT\\config.txt"; const CHAR16* config_path = L"\\EFI\\HackBGRT\\config.txt";
if (!ReadConfigFile(&config, root_dir, config_path)) { if (!ReadConfigFile(&config, root_dir, config_path)) {
Print(L"HackBGRT: No config, no command line!\n", config_path); Log(1, L"HackBGRT: No config, no command line!\n", config_path);
goto fail; goto fail;
} }
} }
for (int i = 1; i < argc; ++i) { for (int i = 1; i < argc; ++i) {
ReadConfigLine(&config, root_dir, argv[i]); ReadConfigLine(&config, root_dir, argv[i]);
} }
Debug = config.debug ? Print : NullPrint; if (config.debug) {
Print(L"HackBGRT version: %s\n", version);
}
SetResolution(config.resolution_x, config.resolution_y); SetResolution(config.resolution_x, config.resolution_y);
HackBgrt(root_dir); HackBgrt(root_dir);
@@ -433,55 +436,54 @@ EFI_STATUS EFIAPI EfiMain(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *ST_) {
EFI_HANDLE next_image_handle = 0; EFI_HANDLE next_image_handle = 0;
static CHAR16 backup_boot_path[] = L"\\EFI\\HackBGRT\\bootmgfw-original.efi"; static CHAR16 backup_boot_path[] = L"\\EFI\\HackBGRT\\bootmgfw-original.efi";
static CHAR16 ms_boot_path[] = L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi"; static CHAR16 ms_boot_path[] = L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi";
int try_ms_quietly = 1;
if (config.boot_path && StriCmp(config.boot_path, L"MS") != 0) { if (config.boot_path && StriCmp(config.boot_path, L"MS") != 0) {
next_image_handle = LoadApp(Print, image_handle, image, config.boot_path); next_image_handle = LoadApp(1, image_handle, image, config.boot_path);
} else { try_ms_quietly = 0;
config.boot_path = backup_boot_path;
next_image_handle = LoadApp(Debug, image_handle, image, config.boot_path);
if (!next_image_handle) {
config.boot_path = ms_boot_path;
next_image_handle = LoadApp(Debug, image_handle, image, config.boot_path);
}
} }
if (!next_image_handle) { if (!next_image_handle) {
config.boot_path = backup_boot_path; config.boot_path = backup_boot_path;
next_image_handle = LoadApp(Print, image_handle, image, config.boot_path); next_image_handle = LoadApp(!try_ms_quietly, image_handle, image, config.boot_path);
if (!next_image_handle) { if (!next_image_handle) {
config.boot_path = ms_boot_path; config.boot_path = ms_boot_path;
next_image_handle = LoadApp(Print, image_handle, image, config.boot_path); next_image_handle = LoadApp(!try_ms_quietly, image_handle, image, config.boot_path);
if (!next_image_handle) { if (!next_image_handle) {
goto fail; goto fail;
} }
} }
Print(L"HackBGRT: Reverting to %s.\n", config.boot_path); if (try_ms_quietly) {
goto ready_to_boot;
}
Log(1, L"HackBGRT: Reverting to %s.\n", config.boot_path);
Print(L"Press escape to cancel or any other key (or wait 15 seconds) to boot.\n"); Print(L"Press escape to cancel or any other key (or wait 15 seconds) to boot.\n");
if (ReadKey(15000).ScanCode == SCAN_ESC) { if (ReadKey(15000).ScanCode == SCAN_ESC) {
goto fail; goto fail;
} }
} else if (config.debug) { } else ready_to_boot: if (config.debug) {
Print(L"HackBGRT: Ready to boot. Disable debug mode to skip this screen.\n"); Print(L"HackBGRT: Ready to boot.\n");
Print(L"If all goes well, you can set debug=0 and log=0 in config.txt.\n");
Print(L"Press escape to cancel or any other key (or wait 15 seconds) to boot.\n"); Print(L"Press escape to cancel or any other key (or wait 15 seconds) to boot.\n");
if (ReadKey(15000).ScanCode == SCAN_ESC) { if (ReadKey(15000).ScanCode == SCAN_ESC) {
return 0; return 0;
} }
} }
if (!config.log) {
ClearLogVariable();
}
if (EFI_ERROR(BS->StartImage(next_image_handle, 0, 0))) { if (EFI_ERROR(BS->StartImage(next_image_handle, 0, 0))) {
Print(L"HackBGRT: Failed to start %s.\n", config.boot_path); Log(1, L"HackBGRT: Failed to start %s.\n", config.boot_path);
goto fail; goto fail;
} }
Print(L"HackBGRT: Started %s. Why are we still here?!\n", config.boot_path); Log(1, L"HackBGRT: Started %s. Why are we still here?!\n", config.boot_path);
Print(L"Please check that %s is not actually HackBGRT!\n", config.boot_path); Print(L"Please check that %s is not actually HackBGRT!\n", config.boot_path);
goto fail; goto fail;
fail: { fail: {
Print(L"HackBGRT has failed. Use parameter debug=1 for details.\n"); Log(1, L"HackBGRT has failed.\n");
Print(L"Get a Windows install disk or a recovery disk to fix your boot.\n"); Print(L"Dumping log:\n\n");
#ifdef GIT_DESCRIBE_W DumpLog();
Print(L"HackBGRT version: " GIT_DESCRIBE_W L"\n"); Print(L"If you can't boot into Windows, get install/recovery disk to fix your boot.\n");
#else
Print(L"HackBGRT version: unknown; not an official release?\n");
#endif
Print(L"Press any key (or wait 15 seconds) to exit.\n"); Print(L"Press any key (or wait 15 seconds) to exit.\n");
ReadKey(15000); ReadKey(15000);
return 1; return 1;
+25 -2
View File
@@ -14,8 +14,31 @@ const CHAR16* TmpStr(CHAR8 *src, int length) {
return dest; return dest;
} }
UINTN NullPrint(IN CONST CHAR16 *fmt, ...) { #define log_buffer_size (65536)
return 0; CHAR16 log_buffer[log_buffer_size] = {0};
CHAR16 LogVarName[] = L"HackBGRTLog";
EFI_GUID LogVarGuid = {0x03c64761, 0x075f, 0x4dba, {0xab, 0xfb, 0x2e, 0xd8, 0x9e, 0x18, 0xb2, 0x36}}; // self-made: 03c64761-075f-4dba-abfb-2ed89e18b236
void Log(int print, IN CONST CHAR16 *fmt, ...) {
va_list args;
CHAR16 buf[256];
va_start(args, fmt);
VSPrint(buf, sizeof(buf), fmt, args); // size is in bytes, not CHAR16s
va_end(args);
if (print) {
Print(L"%s", buf);
}
StrnCat(log_buffer, buf, log_buffer_size - StrLen(log_buffer) - 1);
LibSetVariable(LogVarName, &LogVarGuid, StrLen(log_buffer) * 2, log_buffer);
}
void DumpLog(void) {
Print(L"%s", log_buffer);
}
void ClearLogVariable(void) {
LibDeleteVariable(LogVarName, &LogVarGuid);
} }
const CHAR16* TrimLeft(const CHAR16* s) { const CHAR16* TrimLeft(const CHAR16* s) {
+11 -1
View File
@@ -14,7 +14,17 @@ extern const CHAR16* TmpStr(CHAR8 *src, int length);
/** /**
* Empty function that has the same signature as Print. * Empty function that has the same signature as Print.
*/ */
extern UINTN NullPrint(IN CONST CHAR16 *fmt, ...); extern void Log(int print, IN CONST CHAR16 *fmt, ...);
/**
* Dump the log buffer to the screen.
*/
extern void DumpLog(void);
/**
* Clear the log EFI variable, for minor RAM savings.
*/
extern void ClearLogVariable(void);
/** /**
* Return the greater of two numbers. * Return the greater of two numbers.