27 Commits

Author SHA1 Message Date
Lauri Kenttä
3396a4799d Update change log and tag v1.5.1 2018-08-11 14:01:48 +03:00
Lauri Kenttä
d35a9abb0a Add debug=0 to the default config.txt 2018-08-11 13:45:04 +03:00
Lauri Kenttä
85811d62a6 Add note about EFI System Partition to config.txt 2018-08-11 13:42:41 +03:00
Lauri Kenttä
449dc6acc6 Create OsIndications if it's missing 2018-07-19 19:10:01 +03:00
Lauri Kenttä
1980e5c05c Clarify default config.txt 2018-07-19 19:10:01 +03:00
Lauri Kenttä
9a59f69a28 Compile C# with csc (not mcs) 2018-07-11 16:59:27 +03:00
Lauri Kenttä
1fffbcff2c Fix member naming 2018-07-11 16:55:26 +03:00
Soheibooo
bd7a5f3eea Correct typo in README 2018-03-02 00:45:10 -05:00
Lauri Kenttä
32643fab96 Update change log and tag v1.5.0 2017-09-30 22:41:00 +03:00
Lauri Kenttä
ecbca09419 Update README: clearer installation instructions 2017-09-30 22:41:00 +03:00
Lauri Kenttä
fa0f846f79 Implement rebooting to UEFI setup 2017-09-30 22:41:00 +03:00
Lauri Kenttä
b469b600ba Reorder the setup process a bit 2017-09-30 22:41:00 +03:00
Lauri Kenttä
f7fa54cfee Move Secure Boot handling to another function 2017-09-30 21:23:12 +03:00
Lauri Kenttä
e092c4768c Add throwable for graceful exiting 2017-09-30 16:41:25 +03:00
Lauri Kenttä
7ad4762a3d Improve ESP detection and move to another file 2017-09-30 16:40:17 +03:00
Lauri Kenttä
cea656631a Reorder some BootLoaderInfo code 2017-09-30 15:40:28 +03:00
Lauri Kenttä
1b6b17ec9a Move some helpers to SetupHelper class 2017-09-30 15:39:52 +03:00
Lauri Kenttä
91aad3b971 Makefile: Add variable for C# file list 2017-09-25 21:18:46 +03:00
Lauri Kenttä
cbcb630697 Update change log and tag v1.4.0 2017-08-29 02:16:22 +03:00
Lauri Kenttä
8531c728e8 Add some recovery instructions 2017-08-29 01:56:58 +03:00
Lauri Kenttä
f255b13027 Hard-code a fallback boot loader path
If the config is invalid, try to load the default boot loader backup.
2017-08-29 01:56:58 +03:00
Lauri Kenttä
054f8cc751 Convert config.txt to UTF-8 2017-08-29 01:56:58 +03:00
Lauri Kenttä
24c4a8aa0c Support UTF-8 in config.txt 2017-08-29 01:56:58 +03:00
Lauri Kenttä
b3cc80b37b Fix possible buffer overflow 2017-08-29 01:56:58 +03:00
Lauri Kenttä
c01cf121a0 Makefile: Add zip target for easier releases 2017-08-29 01:56:58 +03:00
Lauri Kenttä
c12bd7a859 Makefile: Set version to 'unknown' if git fails 2017-01-07 14:03:43 +02:00
Lauri Kenttä
ce44c3dcb3 Makefile: Build both IA-32 and x86_64 by default 2017-01-07 14:02:51 +02:00
11 changed files with 792 additions and 374 deletions

View File

@@ -2,6 +2,26 @@
All notable changes to this project will be documented in this file.
## 1.5.1 - 2018-08-11
### Fixed
- Clarify the default config.txt.
- Fix an exception in some cases when trying to boot to UEFI setup.
## 1.5.0 - 2017-09-30
### Added
- Support for rebooting to UEFI setup.
### Changed
- Minor enhancements to installer.
## 1.4.0 - 2017-08-29
### Added
- Use UTF-8 in the configuration file.
- Use the default boot loader path if the configured one doesn't work.
## 1.3.0 - 2016-12-22
### Added

View File

@@ -9,19 +9,29 @@ GNUEFI_LIB = /usr/$(CC_PREFIX)/lib
FILES_C = src/main.c src/util.c src/types.c src/config.c
FILES_H = $(wildcard src/*.h)
GIT_DESCRIBE = $(shell git describe --tags)
FILES_CS = src/Setup.cs src/SetupHelper.cs src/Esp.cs src/Efi.cs
GIT_DESCRIBE = $(firstword $(shell git describe --tags) unknown)
CFLAGS += '-DGIT_DESCRIBE=L"$(GIT_DESCRIBE)"'
ZIPDIR = HackBGRT-$(GIT_DESCRIBE:v%=%)
ZIP = $(ZIPDIR).zip
.PHONY: all default
efi: bootx64.efi bootia32.efi
setup: setup.exe
all: efi setup
default: bootx64.efi
all: bootx64.efi bootia32.efi setup.exe
zip: $(ZIP)
$(ZIP): bootx64.efi bootia32.efi config.txt splash.bmp setup.exe README.md CHANGELOG.md README.efilib LICENSE
test ! -d "$(ZIPDIR)"
mkdir "$(ZIPDIR)"
cp -a $^ "$(ZIPDIR)" || (rm -rf "$(ZIPDIR)"; exit 1)
7z a -mx=9 "$(ZIP)" "$(ZIPDIR)" || (rm -rf "$(ZIPDIR)"; exit 1)
rm -rf "$(ZIPDIR)"
src/GIT_DESCRIBE.cs: src/Setup.cs $(FILES_C) $(FILES_H)
src/GIT_DESCRIBE.cs: $(FILES_CS) $(FILES_C) $(FILES_H)
echo 'public class GIT_DESCRIBE { public static string data = "$(GIT_DESCRIBE)"; }' > $@
setup.exe: src/Setup.cs src/GIT_DESCRIBE.cs
mcs -define:GIT_DESCRIBE -out:$@ $^
setup.exe: $(FILES_CS) src/GIT_DESCRIBE.cs
csc /define:GIT_DESCRIBE /out:$@ $^
bootx64.efi: CC_PREFIX = x86_64-w64-mingw32
bootx64.efi: GNUEFI_ARCH = x86_64
@@ -32,6 +42,3 @@ 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 bootia32.efi config.txt splash.bmp setup.exe README.md README.efilib LICENSE
tar cJf $@ --transform=s,^,HackBGRT/, $^

View File

@@ -4,33 +4,44 @@ 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.
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 permanently, 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 Secure Boot is disabled, or learn to sign EFI applications.
* Simple Windows installation:
* Get the latest release.
* Start `setup.exe` and select `I` (install).
* Make sure that Secure Boot is disabled, unless you know how to sign EFI applications.
### Windows installation
* Get the latest release from the Releases page.
* Start `setup.exe` and follow the instructions.
* You may need to manually disable Secure Boot and then retry.
* The installer will launch Notepad for modifying the configuration.
* If you need only one custom image, the defaults are fine.
* Otherwise, check out the examples in the configuration file.
* The installer will launch Paint for creating the image(s).
* You can create multiple images by using Save As.
* Be sure to always use the 24-bit BMP/DIB format.
* If Windows later restores the original boot loader, simply reinstall.
* If you wish to change the image or other configuration, simply reinstall.
* Installation for Windows with another boot loader (e.g. GRUB):
* Extract the latest release 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:
* Extract the latest release 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.
* If Windows later restores the original boot loader, just reinstall.
* If you wish to change the image or other configuration, just reinstall.
### Multi-boot configurations
If you only need HackBGRT for Windows:
* Extract the latest release 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`.
If you need it for other systems as well:
* Extract the latest release to `[EFI System Partition]\EFI\HackBGRT\`.
* Set `boot=\EFI\your-actual-boot-loader.efi` in `config.txt`.
* Set `\EFI\HackBGRT\bootx64.efi` as your default boot loader with `efibootmgr` or some other EFI boot manager tool.
On 32-bit machines, use `bootia32.efi` instead of `bootx64.efi`.
## Configuration
@@ -44,6 +55,13 @@ The image must be a 24-bit BMP file with a 54-byte header. That's a TrueColor BM
Multiple images may be specified, in which case one is picked at random.
## Recovery
If something breaks and you can't boot to Windows, you have the following options:
* Windows installation (or recovery) media can fix boot issues.
* You can copy `[EFI System Partition]\EFI\HackBGRT\bootmgfw-original.efi` into `[EFI System Partition]\EFI\Microsoft\Boot\bootmgfw.efi` by some other means such as Linux or Windows command prompt.
## Building
* Compiler: GCC targeting w64-mingw32

BIN
config.txt Executable file → Normal file

Binary file not shown.

180
src/Efi.cs Normal file
View File

@@ -0,0 +1,180 @@
using System;
using System.Linq;
using System.Runtime.InteropServices;
using Microsoft.Win32;
/**
* Methods for handling EFI variables.
*/
public class Efi {
[DllImport("kernel32.dll", SetLastError = true)]
private static extern UInt32 GetFirmwareEnvironmentVariableEx(string lpName, string lpGuid, [MarshalAs(UnmanagedType.LPArray)] byte[] pBuffer, UInt32 nSize, out UInt32 pdwAttributes);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern UInt32 SetFirmwareEnvironmentVariableEx(string lpName, string lpGuid, [MarshalAs(UnmanagedType.LPArray)] byte[] pBuffer, UInt32 nSize, UInt32 pdwAttributes);
[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
private static extern bool AdjustTokenPrivileges(IntPtr htoken, bool disable, ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);
[DllImport("kernel32.dll", ExactSpelling = true)]
private static extern IntPtr GetCurrentProcess();
[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
private static extern bool OpenProcessToken(IntPtr h, int acc, out IntPtr phtok);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool CloseHandle(IntPtr hObject);
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct TokPriv1Luid {
public int Count;
public long Luid;
public int Attr;
}
/**
* Information about an EFI variable.
*/
public class Variable {
public string Name, Guid;
public UInt32 Attributes;
public byte[] Data;
}
public const string EFI_GLOBAL_GUID = "{8be4df61-93ca-11d2-aa0d-00e098032b8c}";
/**
* Enable the privilege to access EFI variables.
*/
public static void EnablePrivilege() {
const int SE_PRIVILEGE_ENABLED = 0x00000002;
const int TOKEN_QUERY = 0x00000008;
const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
const string SE_SYSTEM_ENVIRONMENT_NAME = "SeSystemEnvironmentPrivilege";
IntPtr htoken = IntPtr.Zero;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out htoken)) {
throw new Exception("EnablePrivilege: OpenProcessToken failed: " + Marshal.GetLastWin32Error());
}
try {
TokPriv1Luid tp;
tp.Count = 1;
tp.Luid = 0;
tp.Attr = SE_PRIVILEGE_ENABLED;
if (!LookupPrivilegeValue(null, SE_SYSTEM_ENVIRONMENT_NAME, ref tp.Luid)) {
throw new Exception("EnablePrivilege: LookupPrivilegeValue failed: " + Marshal.GetLastWin32Error());
}
if (!AdjustTokenPrivileges(htoken, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero)) {
throw new Exception("EnablePrivilege: AdjustTokenPrivileges failed: " + Marshal.GetLastWin32Error());
}
} finally {
CloseHandle(htoken);
}
}
/**
* Get an EFI variable.
*
* @param name Name of the EFI variable.
* @param guid GUID of the EFI variable.
* @return Information about the EFI variable.
*/
private static Variable GetVariable(string name, string guid = EFI_GLOBAL_GUID) {
Variable result = new Variable();
result.Name = name;
result.Guid = guid;
result.Data = null;
result.Attributes = 0;
for (UInt32 i = 4096; i <= 1024*1024; i *= 2) {
byte[] buf = new byte[i];
UInt32 len = GetFirmwareEnvironmentVariableEx(name, guid, buf, (UInt32) buf.Length, out result.Attributes);
if (len == buf.Length) {
continue;
}
if (len > 0 || Marshal.GetLastWin32Error() == 0) {
result.Data = new byte[len];
Array.Copy(buf, 0, result.Data, 0, len);
return result;
}
switch (len != 0 ? 0 : Marshal.GetLastWin32Error()) {
case 203:
// Not found.
return result;
case 87:
throw new Exception("GetVariable: Invalid parameter");
case 1314:
throw new Exception("GetVariable: Privilege not held");
default:
throw new Exception("GetVariable: error " + Marshal.GetLastWin32Error());
}
}
throw new Exception("GetFirmwareEnvironmentVariable: too big data");
}
/**
* Set an EFI variable.
*
* @param v Information of the variable.
*/
private static void SetVariable(Variable v) {
UInt32 r = SetFirmwareEnvironmentVariableEx(v.Name, v.Guid, v.Data, (UInt32) v.Data.Length, v.Attributes);
if (r == 0) {
switch (Marshal.GetLastWin32Error()) {
case 87:
throw new Exception("GetVariable: Invalid parameter");
case 1314:
throw new Exception("GetVariable: Privilege not held");
default:
throw new Exception("GetVariable: error " + Marshal.GetLastWin32Error());
}
}
}
/**
* Check if Secure Boot is enabled.
*
* @return 0 for disabled, 1 for enabled, other for unknown.
*/
public static int GetSecureBootStatus() {
// GetVariable("SecureBoot") reports always 1 (on Lenovo E335).
// Windows registry seems to work better, though.
try {
return (int) Registry.GetValue(
"HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\SecureBoot\\State",
"UEFISecureBootEnabled",
-1
);
} catch {
return -1;
}
}
/**
* Check if it's possible to reboot to EFI setup.
*
* @return True, if it's possible to reboot to EFI setup.
*/
public static bool CanBootToFW() {
try {
Variable tmp = GetVariable("OsIndicationsSupported");
return tmp.Data != null && (tmp.Data[0] & 1) != 0;
} catch {
return false;
}
}
/**
* Mark that the next reboot should go to EFI setup.
*/
public static void SetBootToFW() {
Variable tmp = GetVariable("OsIndications");
if (tmp.Data == null) {
tmp.Data = new byte[8];
tmp.Attributes = 7;
}
tmp.Data[0] |= 1;
SetVariable(tmp);
}
}

118
src/Esp.cs Normal file
View File

@@ -0,0 +1,118 @@
using System;
using System.IO;
using System.Text.RegularExpressions;
/**
* EFI System Partition mounter.
*/
public sealed class Esp {
/** The singleton instance of this class, if Path is mounted. */
private static Esp MountInstance;
/** EFI System Partition location, internal variable. */
private static string RealPath;
/** EFI System Partition location, read-only. */
public static string Path {
get {
return RealPath;
}
}
/**
* Constructor: do nothing.
*/
private Esp() {
}
/**
* Destructor: unmount.
*/
~Esp() {
if (this == MountInstance) {
Unmount();
}
}
/**
* Try to find ESP at a path.
*
* @param tryPath The new path to try.
* @param requireMsLoader Look for MS boot loader specifically?
* @return true if the path was given and seems valid, false otherwise.
*/
public static bool TryPath(string tryPath, bool requireMsLoader = true) {
if (MountInstance != null && Path != null) {
Unmount();
}
RealPath = tryPath;
if (Path != null && Path != "") {
if (File.Exists(Path + "\\EFI\\Microsoft\\Boot\\bootmgfw.efi")) {
return true;
}
if (!requireMsLoader && Directory.Exists(Path + "\\EFI")) {
return true;
}
}
RealPath = null;
return false;
}
/**
* Find the EFI System Partition, if it's already mounted.
*
* @return true if the drive vas found.
*/
public static bool Find() {
if (MountInstance != null) {
return true;
}
try {
// Match "The EFI System Partition is mounted at E:\" with some language support.
var re = new Regex(" EFI[^\n]*(?:\n[ \t]*)?([A-Z]:)\\\\");
if (TryPath(re.Match(Setup.Execute("mountvol", "", false)).Groups[1].Captures[0].Value)) {
return true;
}
} catch {
}
for (char c = 'A'; c <= 'Z'; ++c) {
if (TryPath(c + ":")) {
return true;
}
}
return false;
}
/**
* Mount the EFI System Partition.
*
* @return true if the drive was mounted, false otherwise.
*/
public static bool Mount() {
if (MountInstance != null) {
return true;
}
for (char c = 'A'; c <= 'Z'; ++c) {
if (Setup.Execute("mountvol", c + ": /S", true) != null) {
MountInstance = new Esp();
if (TryPath(c + ":", false)) {
return true;
} else {
throw new Exception("Mounted ESP at " + c + ": but it seems to be invalid!");
}
}
}
return false;
}
/**
* Unmount the EFI System Partition, if necessary.
*/
private static void Unmount() {
if (MountInstance != null) {
Setup.Execute("mountvol", Path + " /D", true);
RealPath = null;
MountInstance = null;
}
}
}

View File

@@ -1,16 +1,10 @@
using System;
using System.Reflection;
using System.Diagnostics;
using System.IO;
using System.Text.RegularExpressions;
using System.Linq;
using System.Security.Principal;
using Microsoft.Win32;
/**
* HackBGRT Setup.
*/
public class Setup {
public class Setup: SetupHelper {
/**
* The custom exception class for expected exceptions.
*/
@@ -20,48 +14,34 @@ public class Setup {
}
/**
* EFI System Partition mounter.
* A custom exception class for simply exiting the application.
*/
public class ESP {
/** EFI System Partition mount point. */
public string Path = null;
/** Was the ESP mounted by this instance? */
private bool Mounted = false;
/**
* Mount the EFI System Partition, or determine an existing mount point.
*/
public void Mount() {
try {
// Match "The EFI System Partition is mounted at E:\" with some language support.
var re = new Regex(" EFI[^\n]*(?:\n[ \t]*)?([A-Z]:)\\\\");
Path = re.Match(Execute("mountvol", "", false)).Groups[1].Captures[0].Value;
return;
} catch {
}
// Try to mount somewhere.
for (char c = 'A'; c <= 'Z'; ++c) {
if (Execute("mountvol", c + ": /S", true) != null) {
Console.WriteLine("The EFI System Partition is mounted in " + c + ":\\");
Path = c + ":";
Mounted = true;
return;
}
}
throw new SetupException("The EFI System Partition is not mounted.");
public class ExitSetup: Exception {
public readonly int Code;
public ExitSetup(int code) {
Code = code;
}
}
/**
* Unmount the EFI System Partition, if it was previously mounted by this instance.
*/
public void Unmount() {
if (Mounted) {
Execute("mountvol", Path + " /D", true);
Mounted = false;
Path = null;
/**
* Find or mount or manually choose the EFI System Partition.
*/
public static void InitEspPath() {
if (!Esp.Find() && !Esp.Mount()) {
Console.WriteLine("EFI System Partition was not found.");
Console.WriteLine("Press enter to exit, or give ESP path here: ");
string s = Console.ReadLine();
if (s.Length == 1) {
s = s + ":";
}
if (!Esp.TryPath(s, true)) {
Console.WriteLine("That's not a valid ESP path!");
}
}
if (Esp.Path == null) {
throw new SetupException("EFI System Partition was not found.");
}
Console.WriteLine("EFI System Partition location is " + Esp.Path);
}
/**
@@ -70,259 +50,287 @@ public class Setup {
public enum BootLoaderType {
Unknown,
MS,
HackBGRT
Own
}
/**
* Information about a boot loader: type and architecture.
*/
public struct BootLoaderInfo {
public class BootLoaderInfo {
public string Path;
public bool Exists;
public BootLoaderType Type;
public string Arch;
/**
* Constructor. Also recognizes the boot loader.
*/
public BootLoaderInfo(string path) {
Path = path;
Detect();
}
/**
* Recognize the boot loader type (MS/HackBGRT) and architecture.
*/
public void Detect() {
Exists = false;
Type = BootLoaderType.Unknown;
Arch = null;
try {
byte[] data = File.ReadAllBytes(Path);
Exists = true;
string tmp = System.Text.Encoding.ASCII.GetString(data);
if (tmp.IndexOf("HackBGRT") >= 0) {
Type = BootLoaderType.Own;
} else if (tmp.IndexOf("Microsoft Corporation") >= 0) {
Type = BootLoaderType.MS;
}
switch (BitConverter.ToUInt16(data, BitConverter.ToInt32(data, 0x3c) + 4)) {
case 0x014c: Arch = "ia32"; break;
case 0x0200: Arch = "ia64"; break;
case 0x8664: Arch = "x64"; break;
}
} catch {
}
}
/**
* Replace this boot loader with another.
*
* @param other The new boot loader.
* @return true if the replacement was successful.
*/
public bool ReplaceWith(BootLoaderInfo other) {
if (!other.Exists || !Copy(other.Path, Path)) {
return false;
}
Exists = other.Exists;
Type = other.Type;
Arch = other.Arch;
return true;
}
}
/**
* Recognize the boot loader type (MS/HackBGRT) and architecture.
*
* @param path Path to the boot loader.
* @return Information about the boot loader.
* Install files and replace the MsLoader with our own.
*/
public static BootLoaderInfo RecognizeLoader(string path) {
BootLoaderInfo info;
info.Path = path;
info.Exists = false;
info.Type = BootLoaderType.Unknown;
info.Arch = null;
protected void Install() {
try {
byte[] data = File.ReadAllBytes(path);
info.Exists = true;
string tmp = System.Text.Encoding.ASCII.GetString(data);
if (tmp.IndexOf("HackBGRT") >= 0) {
info.Type = BootLoaderType.HackBGRT;
} else if (tmp.IndexOf("Microsoft Corporation") >= 0) {
info.Type = BootLoaderType.MS;
}
switch (BitConverter.ToUInt16(data, BitConverter.ToInt32(data, 0x3c) + 4)) {
case 0x014c: info.Arch = "ia32"; break;
case 0x0200: info.Arch = "ia64"; break;
case 0x8664: info.Arch = "x64"; break;
if (!Directory.Exists(Destination)) {
Directory.CreateDirectory(Destination);
}
} catch {
throw new SetupException("Failed to copy files to ESP!");
}
return info;
}
/**
* Backup the original boot loader.
*
* @param hackbgrt Path to the HackBGRT directory on the ESP.
* @param msloader Path of the MS boot loader to backup.
* @return Information about the boot loader backup.
*/
public static BootLoaderInfo Backup(string hackbgrt, string msloader) {
try {
if (!Directory.Exists(hackbgrt)) {
Directory.CreateDirectory(hackbgrt);
if (MsLoader.Type == BootLoaderType.MS) {
if (!MsLoaderBackup.ReplaceWith(MsLoader)) {
throw new SetupException("Failed to backup MS boot loader!");
}
BootLoaderInfo info = RecognizeLoader(msloader);
if (info.Type == BootLoaderType.HackBGRT) {
Console.WriteLine(msloader + " already contains a version of HackBGRT, skipping backup.");
} else if (info.Type == BootLoaderType.MS) {
// Overwrite any previous backup, the file might have changed.
Copy(msloader, hackbgrt + "\\bootmgfw-original.efi");
} else {
Console.WriteLine(msloader + " doesn't look right, skipping backup.");
}
} catch {
}
BootLoaderInfo msbackup = RecognizeLoader(hackbgrt + "\\bootmgfw-original.efi");
if (!msbackup.Exists) {
throw new SetupException("Couldn't backup the original bootmgfw.efi.");
if (MsLoaderBackup.Type != BootLoaderType.MS) {
// Duplicate check, but better to be sure...
throw new SetupException("Failed to detect MS boot loader!");
}
if (msbackup.Arch == null || msbackup.Type != BootLoaderType.MS) {
throw new SetupException("The boot loader backup (" + msbackup.Path + ") doesn't look like a supported MS boot loader");
if (!NewLoader.ReplaceWith(NewLoaderSource)) {
throw new SetupException("Couldn't copy new HackBGRT to ESP.");
}
return msbackup;
}
/**
* Install HackBGRT, copy files and replace the msloader with our own.
*
* @param src Path to the installation files.
* @param hackbgrt Path to the HackBGRT directory on the ESP.
* @param msloader Path of the MS boot loader to replace.
* @param msbackup Information of the boot loader backup.
*/
public static void Install(string src, string hackbgrt, string msloader, BootLoaderInfo msbackup) {
string loaderName = "boot" + msbackup.Arch + ".efi";
string loaderSrc = src + "\\" + loaderName;
string loaderInst = hackbgrt + "\\" + loaderName;
if (!File.Exists(loaderSrc)) {
throw new SetupException(loaderName + " doesn't exist.");
if (!File.Exists(Config)) {
Copy(Source + "\\config.txt", Config);
}
Copy(loaderSrc, loaderInst);
if (!File.Exists(hackbgrt + "\\config.txt")) {
Copy(src + "\\config.txt", hackbgrt + "\\config.txt");
if (!File.Exists(Splash)) {
Copy(Source + "\\splash.bmp", Splash);
}
if (!File.Exists(hackbgrt + "\\splash.bmp")) {
Copy(src + "\\splash.bmp", hackbgrt + "\\splash.bmp");
Configure();
if (!MsLoader.ReplaceWith(NewLoader)) {
MsLoader.ReplaceWith(MsLoaderBackup);
throw new SetupException("Couldn't copy new HackBGRT over the MS loader (bootmgfw.efi).");
}
Enable(hackbgrt, msloader, msbackup);
Configure(hackbgrt);
}
/**
* Enable HackBGRT, replace the msloader with our own.
*
* @param hackbgrt Path to the HackBGRT directory on the ESP.
* @param msloader Path of the MS boot loader to replace.
* @param msbackup Information of the boot loader backup.
*/
public static void Enable(string hackbgrt, string msloader, BootLoaderInfo msbackup) {
string loaderName = "boot" + msbackup.Arch + ".efi";
string loaderInst = hackbgrt + "\\" + loaderName;
if (!File.Exists(loaderInst)) {
throw new SetupException(loaderInst + " doesn't exist.");
}
if (!Copy(loaderInst, msloader)) {
Copy(msbackup.Path, msloader);
throw new SetupException("Couldn't install the new bootmgfw.efi.");
}
Console.WriteLine("HackBGRT is now enabled.");
Console.WriteLine("HackBGRT is now installed.");
}
/**
* Configure HackBGRT.
*
* @param hackbgrt Path to the HackBGRT directory on the ESP.
*/
public static void Configure(string hackbgrt) {
protected void Configure() {
// Open config.txt in notepad.
Console.WriteLine("Check the configuration in " + hackbgrt + "\\config.txt.");
Console.WriteLine("Use the supplied config.txt as reference.");
Console.WriteLine("Be sure to check for any format changes if updating!");
Console.WriteLine("Check the configuration in " + Config + ".");
Console.WriteLine(" - Use the supplied config.txt as reference.");
Console.WriteLine(" - Be sure to check for any format changes if updating!");
try {
StartProcess("notepad", hackbgrt + "\\config.txt").WaitForExit();
StartProcess("notepad", Config).WaitForExit();
} catch {
Console.WriteLine("Editing config.txt with notepad failed! Edit it manually.");
Console.WriteLine("Editing config.txt with notepad failed!");
}
Console.WriteLine();
// Open splash.bmp in mspaint.
Console.WriteLine("Draw or copy your preferred image to splash.bmp.");
Console.WriteLine("Draw or copy your preferred image to " + Splash + ".");
try {
StartProcess("mspaint", hackbgrt + "\\splash.bmp").WaitForExit();
StartProcess("mspaint", Splash).WaitForExit();
} catch {
Console.WriteLine("Editing splash.bmp with mspaint failed! Edit it manually.");
Console.WriteLine("Editing splash.bmp with mspaint failed!");
}
Console.WriteLine();
}
/**
* Disable HackBGRT, restore the original boot loader.
*
* @param hackbgrt Where HackBGRT is installed.
* @param msloader Where to restore the MS boot loader.
*/
public static void Disable(string hackbgrt, string msloader) {
BootLoaderInfo info = RecognizeLoader(msloader);
if (info.Type == BootLoaderType.MS) {
Console.WriteLine(msloader + " is already ok.");
} else {
if (!File.Exists(hackbgrt + "\\bootmgfw-original.efi")) {
throw new SetupException("Missing the original bootmgfw.efi.");
protected void Disable() {
if (MsLoader.Type != BootLoaderType.MS) {
if (!MsLoader.ReplaceWith(MsLoaderBackup)) {
throw new SetupException("Couldn't restore the old MS loader.");
}
if (!Copy(hackbgrt + "\\bootmgfw-original.efi", msloader)) {
throw new SetupException("Failed to restore the original bootmgfw.efi.");
}
Console.WriteLine(msloader + " has been restored.");
}
Console.WriteLine(MsLoader.Path + " has been restored.");
}
/**
* Uninstall HackBGRT completely.
*/
protected void Uninstall() {
try {
Directory.Delete(Destination, true);
Console.WriteLine("HackBGRT has been removed.");
} catch {
throw new SetupException("The directory " + Destination + " couldn't be removed.");
}
}
/**
* Uninstall HackBGRT, restore the original boot loader.
*
* @param hackbgrt Where HackBGRT is installed.
* @param msloader Where to restore the MS boot loader.
* Check Secure Boot status and inform the user.
*/
public static void Uninstall(string hackbgrt, string msloader) {
Disable(hackbgrt, msloader);
try {
Directory.Delete(hackbgrt, true);
Console.WriteLine("HackBGRT has been removed.");
} catch {
Console.WriteLine("The directory " + hackbgrt + " couldn't be removed.");
public static void HandleSecureBoot() {
int secureBoot = Efi.GetSecureBootStatus();
if (secureBoot == 0) {
Console.WriteLine("Secure Boot is disabled, good!");
} else {
if (secureBoot == 1) {
Console.WriteLine("Secure Boot is probably enabled.");
} else {
Console.WriteLine("Secure Boot status could not be determined.");
}
Console.WriteLine("It's very important to disable Secure Boot before installing.");
Console.WriteLine("Otherwise your machine may become unbootable.");
Console.WriteLine("Choose action (press a key):");
bool canBootToFW = Efi.CanBootToFW();
if (canBootToFW) {
Console.WriteLine(" S = Enter EFI Setup to disable Secure Boot manually; requires reboot!");
}
Console.WriteLine(" I = Install anyway; THIS MAY BE DANGEROUS!");
Console.WriteLine(" C = Cancel");
var k = Console.ReadKey().Key;
Console.WriteLine();
if (k == ConsoleKey.I) {
Console.WriteLine("Continuing. THIS MAY BE DANGEROUS!");
} else if (canBootToFW && k == ConsoleKey.S) {
Efi.SetBootToFW();
Console.WriteLine();
Console.WriteLine("Reboot your computer. You will then automatically enter the UEFI setup.");
Console.WriteLine("Find and disable Secure Boot, then save and exit, then run this installer.");
Console.WriteLine("Press R to reboot now, other key to exit.");
var k2 = Console.ReadKey().Key;
Console.WriteLine();
if (k2 == ConsoleKey.R) {
StartProcess("shutdown", "-f -r -t 1");
}
Environment.Exit(0);
throw new ExitSetup(0);
} else {
Console.WriteLine("Aborting because of Secure Boot.");
throw new ExitSetup(1);
}
}
}
protected string Source, Destination, Config, Splash;
protected BootLoaderInfo MsLoader, MsLoaderBackup, NewLoader, NewLoaderSource;
protected string EfiArch;
/**
* Initialize information for the Setup.
*/
protected Setup(string source, string esp) {
Source = source;
Destination = esp + "\\EFI\\HackBGRT";
Config = Destination + "\\config.txt";
Splash = Destination + "\\splash.bmp";
MsLoaderBackup = new BootLoaderInfo(Destination + "\\bootmgfw-original.efi");
MsLoader = new BootLoaderInfo(esp + "\\EFI\\Microsoft\\Boot\\bootmgfw.efi");
if (MsLoader.Type == BootLoaderType.MS) {
EfiArch = MsLoader.Arch;
} else if (MsLoaderBackup.Type == BootLoaderType.MS) {
EfiArch = MsLoaderBackup.Arch;
} else {
throw new SetupException("Failed to detect MS boot loader!");
}
string loaderName = "boot" + EfiArch + ".efi";
NewLoaderSource = new BootLoaderInfo(Source + "\\" + loaderName);
NewLoader = new BootLoaderInfo(Destination + "\\" + loaderName);
if (!NewLoaderSource.Exists) {
throw new SetupException("Couldn't find required files! Missing: " + NewLoaderSource.Path);
}
}
/**
* Ask for user's choice and install/uninstall.
*/
protected void HandleUserAction() {
bool isEnabled = MsLoader.Type == BootLoaderType.Own;
bool isInstalled = NewLoader.Type == BootLoaderType.Own;
if (isEnabled) {
Console.WriteLine("HackBGRT is currently enabled.");
} else {
if (isInstalled) {
Console.WriteLine("HackBGRT is currently disabled.");
} else {
Console.WriteLine("HackBGRT is currently not installed.");
}
}
Console.WriteLine();
Console.WriteLine("Choose action (press a key):");
Console.WriteLine(" I = install, upgrade, repair, modify...");
if (isEnabled) {
Console.WriteLine(" D = disable, restore the original boot loader");
}
if (isInstalled) {
Console.WriteLine(" R = remove completely; delete all HackBGRT files and images");
}
Console.WriteLine(" C = cancel");
var k = Console.ReadKey().Key;
Console.WriteLine();
if (k == ConsoleKey.I) {
Install();
} else if ((isEnabled && k == ConsoleKey.D) || (isInstalled && k == ConsoleKey.R)) {
if (isEnabled) {
Disable();
}
if (k == ConsoleKey.R) {
Uninstall(); // NOTICE: It's imperative to Disable() first!
}
} else if (k == ConsoleKey.C) {
throw new ExitSetup(1);
} else {
throw new SetupException("Invalid choice!");
}
}
/**
* Run the setup.
*
* @param src Path to the installation files.
* @param source Path to the installation files.
*/
protected static void RunSetup(string src) {
ESP esp = new ESP();
public static void RunSetup(string source) {
try {
esp.Mount();
int secureBoot = -1;
try {
secureBoot = (int) Registry.GetValue(
"HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\SecureBoot\\State",
"UEFISecureBootEnabled",
-1
);
} catch (Exception) {
}
if (secureBoot != 0) {
if (secureBoot == 1) {
Console.WriteLine("Secure Boot is enabled.");
Console.WriteLine("HackBGRT doesn't work with Secure Boot.");
Console.WriteLine("If you install HackBGRT, your machine may become unbootable,");
Console.WriteLine("unless you manually disable Secure Boot.");
} else {
Console.WriteLine("Could not determine Secure Boot status.");
Console.WriteLine("Your system may be incompatible with HackBGRT.");
Console.WriteLine("If you install HackBGRT, your machine may become unbootable.");
}
Console.WriteLine("Do you still wish to continue? [Y/N]");
var k = Console.ReadKey().Key;
Console.WriteLine();
if (k == ConsoleKey.Y) {
Console.WriteLine("Continuing. THIS IS DANGEROUS!");
} else if (k == ConsoleKey.N) {
Console.WriteLine("Aborting.");
return;
} else {
throw new SetupException("Invalid choice!");
}
}
string hackbgrt = esp.Path + "\\EFI\\HackBGRT";
string msloader = esp.Path + "\\EFI\\Microsoft\\Boot\\bootmgfw.efi";
if (!Directory.Exists(hackbgrt)) {
Install(src, hackbgrt, msloader, Backup(hackbgrt, msloader));
} else {
Console.WriteLine("Choose action (press a key):");
Console.WriteLine(" I = install, upgrade, fix installation");
Console.WriteLine(" C = configure (edit config.txt and splash.bmp)");
Console.WriteLine(" E = enable (after disabling); if in doubt, choose 'I' instead");
Console.WriteLine(" D = disable, restore the original boot loader");
Console.WriteLine(" R = remove completely; fully delete " + hackbgrt);
var k = Console.ReadKey().Key;
Console.WriteLine();
if (k == ConsoleKey.I) {
Install(src, hackbgrt, msloader, Backup(hackbgrt, msloader));
} else if (k == ConsoleKey.C) {
Configure(hackbgrt);
} else if (k == ConsoleKey.E) {
Enable(hackbgrt, msloader, Backup(hackbgrt, msloader));
} else if (k == ConsoleKey.D) {
Disable(hackbgrt, msloader);
} else if (k == ConsoleKey.R) {
Uninstall(hackbgrt, msloader);
} else {
throw new SetupException("Invalid choice!");
}
}
InitEspPath();
HandleSecureBoot();
var s = new Setup(source, Esp.Path);
s.HandleUserAction();
} catch (ExitSetup e) {
Environment.ExitCode = e.Code;
} catch (SetupException e) {
Console.WriteLine("Error: {0}", e.Message);
Environment.ExitCode = 1;
@@ -330,101 +338,7 @@ public class Setup {
Console.WriteLine("Unexpected error!\n{0}", e.ToString());
Console.WriteLine("If this is the most current release, please report this bug.");
Environment.ExitCode = 1;
} finally {
esp.Unmount();
}
}
/**
* Start another process.
*
* @param app Path to the application.
* @param args The argument string.
* @return The started process.
*/
protected static Process StartProcess(string app, string args) {
try {
var info = new ProcessStartInfo(app, args);
info.UseShellExecute = false;
return Process.Start(info);
} catch {
return null;
}
}
/**
* Execute another process, return the output.
*
* @param app Path to the application.
* @param args The argument string.
* @param nullOnFail If set, return null if the program exits with a code other than 0, even if there was some output.
* @return The output, or null if the execution failed.
*/
protected static string Execute(string app, string args, bool nullOnFail) {
try {
var info = new ProcessStartInfo(app, args);
info.UseShellExecute = false;
info.RedirectStandardOutput = true;
var p = Process.Start(info);
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
return (nullOnFail && p.ExitCode != 0) ? null : output;
} catch {
return null;
}
}
/**
* Copy a file, overwrite by default.
*
* @param src The source path.
* @param dest The destination path.
* @return True, if the file was successfully copied.
*/
public static bool Copy(string src, string dest) {
try {
File.Copy(src, dest, true);
return true;
} catch {
return false;
}
}
/**
* The Main program.
*
* @param args The arguments.
*/
public static void Main(string[] args) {
#if GIT_DESCRIBE
Console.WriteLine("HackBGRT installer version: {0}", GIT_DESCRIBE.data);
#else
Console.WriteLine("HackBGRT installer version: unknown; not an official release?");
#endif
var self = Assembly.GetExecutingAssembly().Location;
try {
// Relaunch as admin, if needed.
var id = WindowsIdentity.GetCurrent();
var principal = new WindowsPrincipal(id);
var admin = WindowsBuiltInRole.Administrator;
if (!principal.IsInRole(admin) && !args.Contains("no-elevate")) {
ProcessStartInfo startInfo = new ProcessStartInfo(self);
startInfo.Arguments = "no-elevate";
startInfo.Verb = "runas";
startInfo.UseShellExecute = true;
Process p = Process.Start(startInfo);
p.WaitForExit();
Environment.ExitCode = p.ExitCode;
return;
}
} catch {
Console.WriteLine("This installer needs to be run as administrator!");
Console.WriteLine("Press any key to quit.");
Console.ReadKey();
Environment.ExitCode = 1;
return;
}
RunSetup(Path.GetDirectoryName(self));
Console.WriteLine("Press any key to quit.");
Console.ReadKey();
}

104
src/SetupHelper.cs Normal file
View File

@@ -0,0 +1,104 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Security.Principal;
using System.Linq;
/**
* Helper functions.
*/
public class SetupHelper {
/**
* Start another process.
*
* @param app Path to the application.
* @param args The argument string.
* @return The started process.
*/
public static Process StartProcess(string app, string args) {
try {
var info = new ProcessStartInfo(app, args);
info.UseShellExecute = false;
return Process.Start(info);
} catch {
return null;
}
}
/**
* Execute another process, return the output.
*
* @param app Path to the application.
* @param args The argument string.
* @param nullOnFail If set, return null if the program exits with a code other than 0, even if there was some output.
* @return The output, or null if the execution failed.
*/
public static string Execute(string app, string args, bool nullOnFail) {
try {
var info = new ProcessStartInfo(app, args);
info.UseShellExecute = false;
info.RedirectStandardOutput = true;
var p = Process.Start(info);
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();
return (nullOnFail && p.ExitCode != 0) ? null : output;
} catch {
return null;
}
}
/**
* Copy a file, overwrite by default.
*
* @param src The source path.
* @param dest The destination path.
* @return True, if the file was successfully copied.
*/
public static bool Copy(string src, string dest) {
try {
File.Copy(src, dest, true);
return true;
} catch {
return false;
}
}
/**
* The Main program.
*
* @param args The arguments.
*/
public static void Main(string[] args) {
#if GIT_DESCRIBE
Console.WriteLine("HackBGRT installer version: {0}", GIT_DESCRIBE.data);
#else
Console.WriteLine("HackBGRT installer version: unknown; not an official release?");
#endif
var self = Assembly.GetExecutingAssembly().Location;
try {
// Relaunch as admin, if needed.
var id = WindowsIdentity.GetCurrent();
var principal = new WindowsPrincipal(id);
var admin = WindowsBuiltInRole.Administrator;
if (!principal.IsInRole(admin) && !args.Contains("no-elevate")) {
ProcessStartInfo startInfo = new ProcessStartInfo(self);
startInfo.Arguments = "no-elevate";
startInfo.Verb = "runas";
startInfo.UseShellExecute = true;
Process p = Process.Start(startInfo);
p.WaitForExit();
Environment.ExitCode = p.ExitCode;
return;
}
Efi.EnablePrivilege();
} catch {
Console.WriteLine("This installer needs to be run as administrator!");
Console.WriteLine("Press any key to quit.");
Console.ReadKey();
Environment.ExitCode = 1;
return;
}
Setup.RunSetup(Path.GetDirectoryName(self));
}
}

View File

@@ -4,14 +4,55 @@
#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) {
void* data = 0;
UINTN data_bytes = 0;
data = LoadFileWithPadding(root_dir, path, &data_bytes, 4);
if (!data) {
Print(L"HackBGRT: Failed to load configuration (%s)!\n", path);
return FALSE;
}
UINTN str_len = str_bytes / sizeof(*str);
CHAR16* str;
UINTN str_len;
if (*(CHAR16*)data == 0xfeff) {
// UCS-2
str = data;
str_len = data_bytes / sizeof(*str);
} else {
// UTF-8 -> UCS-2
EFI_STATUS e = BS->AllocatePool(EfiBootServicesData, data_bytes * 2 + 2, (void**)&str);
if (EFI_ERROR(e)) {
FreePool(data);
return FALSE;
}
UINT8* str0 = data;
for (UINTN i = str_len = 0; i < data_bytes;) {
UINTN unicode = 0xfffd;
if (str0[i] < 0x80) {
unicode = str0[i];
i += 1;
} else if (str0[i] < 0xc0) {
i += 1;
} else if (str0[i] < 0xe0) {
unicode = ((str0[i] & 0x1f) << 6) | ((str0[i+1] & 0x3f) << 0);
i += 2;
} else if (str0[i] < 0xf0) {
unicode = ((str0[i] & 0x0f) << 12) | ((str0[i+1] & 0x3f) << 6) | ((str0[i+2] & 0x3f) << 0);
i += 3;
} else if (str0[i] < 0xf8) {
unicode = ((str0[i] & 0x07) << 18) | ((str0[i+1] & 0x3f) << 12) | ((str0[i+2] & 0x3f) << 6) | ((str0[i+3] & 0x3f) << 0);
i += 4;
} else {
i += 1;
}
if (unicode <= 0xffff) {
str[str_len++] = unicode;
} else {
str[str_len++] = 0xfffd;
}
}
str[str_len] = 0;
FreePool(data);
}
for (int i = 0; i < str_len;) {
int j = i;

View File

@@ -355,17 +355,30 @@ EFI_STATUS EFIAPI EfiMain(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *ST_) {
SetResolution(config.resolution_x, config.resolution_y);
HackBgrt(root_dir);
EFI_HANDLE next_image_handle = 0;
if (!config.boot_path) {
Print(L"HackBGRT: Boot path not specified.\n");
goto fail;
} else {
Debug(L"HackBGRT: Loading application %s.\n", config.boot_path);
EFI_DEVICE_PATH* boot_dp = FileDevicePath(image->DeviceHandle, (CHAR16*) config.boot_path);
if (EFI_ERROR(BS->LoadImage(0, image_handle, boot_dp, 0, 0, &next_image_handle))) {
Print(L"HackBGRT: Failed to load application %s.\n", config.boot_path);
}
}
Debug(L"HackBGRT: Loading %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 (!next_image_handle) {
static CHAR16 default_boot_path[] = L"\\EFI\\HackBGRT\\bootmgfw-original.efi";
Debug(L"HackBGRT: Loading application %s.\n", default_boot_path);
EFI_DEVICE_PATH* boot_dp = FileDevicePath(image->DeviceHandle, default_boot_path);
if (EFI_ERROR(BS->LoadImage(0, image_handle, boot_dp, 0, 0, &next_image_handle))) {
Print(L"HackBGRT: Also failed to load application %s.\n", default_boot_path);
goto fail;
}
Print(L"HackBGRT: Reverting to %s.\n", default_boot_path);
Print(L"Press escape to cancel, any other key to boot.\n");
if (ReadKey().ScanCode == SCAN_ESC) {
goto fail;
}
config.boot_path = default_boot_path;
}
if (config.debug) {
Print(L"HackBGRT: Ready to boot.\nPress escape to cancel, any other key to boot.\n");
@@ -374,7 +387,7 @@ EFI_STATUS EFIAPI EfiMain(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *ST_) {
}
}
if (EFI_ERROR(BS->StartImage(next_image_handle, 0, 0))) {
Print(L"HackBGRT: StartImage for %s failed.\n", config.boot_path);
Print(L"HackBGRT: Failed to start %s.\n", config.boot_path);
goto fail;
}
Print(L"HackBGRT: Started %s. Why are we still here?!\n", config.boot_path);
@@ -382,6 +395,7 @@ EFI_STATUS EFIAPI EfiMain(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *ST_) {
fail: {
Print(L"HackBGRT has failed. Use parameter debug=1 for details.\n");
Print(L"Get a Windows install disk or a recovery disk to fix your boot.\n");
#ifdef GIT_DESCRIBE
Print(L"HackBGRT version: " GIT_DESCRIBE L"\n");
#else

View File

@@ -100,7 +100,9 @@ void* LoadFileWithPadding(EFI_FILE_HANDLE dir, const CHAR16* path, UINTN* size_p
return 0;
}
e = handle->Read(handle, &size, data);
*(UINT32*)((char*)data + size) = 0;
for (int i = 0; i < padding; ++i) {
*((char*)data + size + i) = 0;
}
handle->Close(handle);
if (EFI_ERROR(e)) {
FreePool(data);