mirror of
https://github.com/Metabolix/HackBGRT.git
synced 2025-12-07 09:36:10 -08:00
Create an own entry, don't replace MS boot loader
This commit is contained in:
10
README.md
10
README.md
@@ -28,6 +28,8 @@ When booting on a UEFI-based computer, Windows may show a vendor-defined logo wh
|
|||||||
* Edit the `config.txt` and `splash.bmp` (or any other images) to your needs.
|
* Edit the `config.txt` and `splash.bmp` (or any other images) to your needs.
|
||||||
* Run `setup.exe batch COMMANDS` as administrator, with some of the following commands:
|
* Run `setup.exe batch COMMANDS` as administrator, with some of the following commands:
|
||||||
* `install` – copy the files but don't enable.
|
* `install` – copy the files but don't enable.
|
||||||
|
* `enable-entry` – create a new EFI boot entry.
|
||||||
|
* `disable-entry` – disable the EFI boot entry.
|
||||||
* `enable-overwrite` – overwrite the MS boot loader.
|
* `enable-overwrite` – overwrite the MS boot loader.
|
||||||
* `disable-overwrite` – restore the MS boot loader.
|
* `disable-overwrite` – restore the MS boot loader.
|
||||||
* `allow-secure-boot` – ignore Secure Boot in subsequent commands.
|
* `allow-secure-boot` – ignore Secure Boot in subsequent commands.
|
||||||
@@ -45,8 +47,7 @@ If you only need HackBGRT for Windows:
|
|||||||
If you need it for other systems as well:
|
If you need it for other systems as well:
|
||||||
|
|
||||||
* Configure HackBGRT to start your boot loader (such as systemd-boot): `boot=\EFI\systemd\systemd-bootx64.efi`.
|
* Configure HackBGRT to start your boot loader (such as systemd-boot): `boot=\EFI\systemd\systemd-bootx64.efi`.
|
||||||
* Run `setup.exe`, install files.
|
* Run `setup.exe`, install as a new EFI boot entry.
|
||||||
* Set `\EFI\HackBGRT\loader.efi` as your default boot loader with `efibootmgr` or some other EFI boot manager tool.
|
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
@@ -64,10 +65,7 @@ Advanced users may edit the `config.txt` to define multiple images, in which cas
|
|||||||
|
|
||||||
## Recovery
|
## Recovery
|
||||||
|
|
||||||
If something breaks and you can't boot to Windows, you have the following options:
|
If something breaks and you can't boot to Windows, you need to use the Windows installation disk (or recovery disk) to fix boot issues.
|
||||||
|
|
||||||
* 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
|
## Building
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
# vim: set fileencoding=utf-8
|
# vim: set fileencoding=utf-8
|
||||||
# The same options may be given also as command line parameters in the EFI Shell, which is useful for debugging.
|
# The same options may be given also as command line parameters in the EFI Shell, which is useful for debugging.
|
||||||
|
|
||||||
# Boot loader path. Default: backup of the Windows boot loader.
|
# Boot loader path. MS = either backup or original Windows boot loader.
|
||||||
boot=\EFI\HackBGRT\bootmgfw-original.efi
|
boot=MS
|
||||||
|
|
||||||
# The image is specified with an image line.
|
# The image is specified with an image line.
|
||||||
# Multiple image lines may be present, in which case one will be picked by random.
|
# Multiple image lines may be present, in which case one will be picked by random.
|
||||||
|
|||||||
235
src/Efi.cs
235
src/Efi.cs
@@ -1,4 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
@@ -42,6 +45,92 @@ public class Efi {
|
|||||||
public string Name, Guid;
|
public string Name, Guid;
|
||||||
public UInt32 Attributes;
|
public UInt32 Attributes;
|
||||||
public byte[] Data;
|
public byte[] Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert to string.
|
||||||
|
*
|
||||||
|
* @return String representation of this object.
|
||||||
|
*/
|
||||||
|
public override string ToString() {
|
||||||
|
var hex = BitConverter.ToString(Data).Replace("-", " ");
|
||||||
|
var text = new string(Data.Select(c => 0x20 <= c && c <= 0x7f ? (char) c : ' ').ToArray());
|
||||||
|
return $"{Name} Guid={Guid} Attributes={Attributes} Text='{text}' Bytes='{hex}'";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Information about an EFI boot entry.
|
||||||
|
*/
|
||||||
|
public class BootEntryData {
|
||||||
|
public UInt32 Attributes;
|
||||||
|
public string Label;
|
||||||
|
public class DevicePathNode {
|
||||||
|
public byte Type, SubType;
|
||||||
|
public byte[] Data;
|
||||||
|
public DevicePathNode(byte[] data) {
|
||||||
|
Type = data[0];
|
||||||
|
SubType = data[1];
|
||||||
|
Data = data.Skip(4).ToArray();
|
||||||
|
}
|
||||||
|
public byte[] ToBytes() {
|
||||||
|
var len = Data.Length + 4;
|
||||||
|
return new byte[] { Type, SubType, (byte)(len & 0xff), (byte)(len >> 8) }.Concat(Data).ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public List<DevicePathNode> DevicePathNodes;
|
||||||
|
public byte[] Arguments;
|
||||||
|
|
||||||
|
public BootEntryData(byte[] data) {
|
||||||
|
Attributes = BitConverter.ToUInt32(data, 0);
|
||||||
|
var pathNodesLength = BitConverter.ToUInt16(data, 4);
|
||||||
|
Label = new string(BytesToUInt16s(data).Skip(3).TakeWhile(i => i != 0).Select(i => (char)i).ToArray());
|
||||||
|
var pos = 6 + 2 * (Label.Length + 1);
|
||||||
|
var pathNodesEnd = pos + pathNodesLength;
|
||||||
|
DevicePathNodes = new List<DevicePathNode>();
|
||||||
|
while (pos + 4 <= pathNodesEnd) {
|
||||||
|
var len = BitConverter.ToUInt16(data, pos + 2);
|
||||||
|
if (len < 4 || pos + len > pathNodesEnd) {
|
||||||
|
return; // throw new Exception("Bad entry.");
|
||||||
|
}
|
||||||
|
DevicePathNodes.Add(new DevicePathNode(data.Skip(pos).Take(len).ToArray()));
|
||||||
|
pos += len;
|
||||||
|
}
|
||||||
|
Arguments = data.Skip(pathNodesEnd).ToArray();
|
||||||
|
}
|
||||||
|
public byte[] ToBytes() {
|
||||||
|
return new byte[0]
|
||||||
|
.Concat(BitConverter.GetBytes((UInt32) Attributes))
|
||||||
|
.Concat(BitConverter.GetBytes((UInt16) DevicePathNodes.Sum(n => n.Data.Length + 4)))
|
||||||
|
.Concat(Encoding.Unicode.GetBytes(Label + "\0"))
|
||||||
|
.Concat(DevicePathNodes.SelectMany(n => n.ToBytes()))
|
||||||
|
.Concat(Arguments)
|
||||||
|
.ToArray();
|
||||||
|
}
|
||||||
|
public DevicePathNode FileNameNode {
|
||||||
|
get {
|
||||||
|
var d = DevicePathNodes;
|
||||||
|
return d.Count > 1 && d[d.Count - 1].Type == 0x7F && d[d.Count - 2].Type == 0x04 ? d[d.Count - 2] : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public bool HasFileName {
|
||||||
|
get {
|
||||||
|
return FileNameNode != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public string FileName {
|
||||||
|
get {
|
||||||
|
if (!HasFileName) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return new string(Encoding.Unicode.GetChars(FileNameNode.Data).TakeWhile(c => c != '\0').ToArray());
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
if (!HasFileName) {
|
||||||
|
throw new Exception("Logic error: Setting FileName on a bad boot entry.");
|
||||||
|
}
|
||||||
|
FileNameNode.Data = Encoding.Unicode.GetBytes(value + "\0");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public const string EFI_GLOBAL_GUID = "{8be4df61-93ca-11d2-aa0d-00e098032b8c}";
|
public const string EFI_GLOBAL_GUID = "{8be4df61-93ca-11d2-aa0d-00e098032b8c}";
|
||||||
@@ -117,17 +206,23 @@ public class Efi {
|
|||||||
* Set an EFI variable.
|
* Set an EFI variable.
|
||||||
*
|
*
|
||||||
* @param v Information of the variable.
|
* @param v Information of the variable.
|
||||||
|
* @param dryRun Don't actually set the variable.
|
||||||
*/
|
*/
|
||||||
private static void SetVariable(Variable v) {
|
private static void SetVariable(Variable v, bool dryRun = false) {
|
||||||
|
Console.WriteLine($"Writing EFI variable {v}");
|
||||||
|
if (dryRun) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
UInt32 r = SetFirmwareEnvironmentVariableEx(v.Name, v.Guid, v.Data, (UInt32) v.Data.Length, v.Attributes);
|
UInt32 r = SetFirmwareEnvironmentVariableEx(v.Name, v.Guid, v.Data, (UInt32) v.Data.Length, v.Attributes);
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
switch (Marshal.GetLastWin32Error()) {
|
switch (Marshal.GetLastWin32Error()) {
|
||||||
case 87:
|
case 87:
|
||||||
throw new Exception("GetVariable: Invalid parameter");
|
throw new Exception("SetVariable: Invalid parameter");
|
||||||
case 1314:
|
case 1314:
|
||||||
throw new Exception("GetVariable: Privilege not held");
|
throw new Exception("SetVariable: Privilege not held");
|
||||||
default:
|
default:
|
||||||
throw new Exception("GetVariable: error " + Marshal.GetLastWin32Error());
|
throw new Exception("SetVariable: error " + Marshal.GetLastWin32Error());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -177,4 +272,136 @@ public class Efi {
|
|||||||
tmp.Data[0] |= 1;
|
tmp.Data[0] |= 1;
|
||||||
SetVariable(tmp);
|
SetVariable(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert bytes into UInt16 values.
|
||||||
|
*
|
||||||
|
* @param bytes The byte array.
|
||||||
|
* @return An enumeration of UInt16 values.
|
||||||
|
*/
|
||||||
|
public static IEnumerable<UInt16> BytesToUInt16s(byte[] bytes) {
|
||||||
|
// TODO: return bytes.Chunk(2).Select(b => (UInt16) (b[0] + 0x100 * b[1])).ToArray();
|
||||||
|
return Enumerable.Range(0, bytes.Length / 2).Select(i => (UInt16) (bytes[2 * i] + 0x100 * bytes[2 * i + 1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable the said boot entry from BootOrder.
|
||||||
|
*
|
||||||
|
* @param label Label of the boot entry.
|
||||||
|
* @param fileName File name of the boot entry.
|
||||||
|
* @param dryRun Don't actually disable the entry.
|
||||||
|
* @return True, if the entry was found in BootOrder.
|
||||||
|
*/
|
||||||
|
public static bool DisableBootEntry(string label, string fileName, bool dryRun = false) {
|
||||||
|
Variable bootOrder;
|
||||||
|
try {
|
||||||
|
bootOrder = GetVariable("BootOrder");
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (bootOrder.Data == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var found = false;
|
||||||
|
var bootOrderInts = new List<UInt16>();
|
||||||
|
foreach (var num in BytesToUInt16s(bootOrder.Data)) {
|
||||||
|
var entry = GetVariable(String.Format("Boot{0:X04}", num));
|
||||||
|
if (entry.Data != null) {
|
||||||
|
var entryData = new BootEntryData(entry.Data);
|
||||||
|
if (entryData.Label == label && entryData.FileName == fileName) {
|
||||||
|
found = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bootOrderInts.Add(num);
|
||||||
|
}
|
||||||
|
if (found) {
|
||||||
|
bootOrder.Data = bootOrderInts.SelectMany(num => new byte[] { (byte)(num & 0xff), (byte)(num >> 8) }).ToArray();
|
||||||
|
SetVariable(bootOrder, dryRun);
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create and enable the said boot entry from BootOrder.
|
||||||
|
*
|
||||||
|
* @param label Label of the boot entry.
|
||||||
|
* @param fileName File name of the boot entry.
|
||||||
|
* @param dryRun Don't actually create the entry.
|
||||||
|
*/
|
||||||
|
public static void MakeAndEnableBootEntry(string label, string fileName, bool dryRun = false) {
|
||||||
|
Variable msEntry = null, ownEntry = null;
|
||||||
|
UInt16 msNum = 0, ownNum = 0;
|
||||||
|
|
||||||
|
// Find a free entry and the MS bootloader entry.
|
||||||
|
Variable bootOrder = null;
|
||||||
|
try {
|
||||||
|
bootOrder = GetVariable("BootOrder");
|
||||||
|
} catch {
|
||||||
|
if (dryRun) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bootOrder == null || bootOrder.Data == null) {
|
||||||
|
throw new Exception("MakeBootEntry: Could not read BootOrder. Maybe your computer is defective.");
|
||||||
|
}
|
||||||
|
var bootCurrent = GetVariable("BootCurrent");
|
||||||
|
if (bootCurrent.Data == null) {
|
||||||
|
throw new Exception("MakeBootEntry: Could not read BootCurrent. Maybe your computer is defective.");
|
||||||
|
}
|
||||||
|
var bootOrderInts = new List<UInt16>(BytesToUInt16s(bootOrder.Data));
|
||||||
|
foreach (var num in BytesToUInt16s(bootCurrent.Data).Concat(bootOrderInts).Concat(Enumerable.Range(0, 0xffff).Select(i => (UInt16) i))) {
|
||||||
|
var entry = GetVariable(String.Format("Boot{0:X04}", num));
|
||||||
|
if (entry.Data == null) {
|
||||||
|
if (ownEntry == null) {
|
||||||
|
ownNum = num;
|
||||||
|
ownEntry = entry;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var entryData = new BootEntryData(entry.Data);
|
||||||
|
if (!entryData.HasFileName) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (entryData.Label == label && entryData.FileName == fileName) {
|
||||||
|
ownNum = num;
|
||||||
|
ownEntry = entry;
|
||||||
|
}
|
||||||
|
if (msEntry == null && entryData.FileName.StartsWith("\\EFI\\Microsoft\\Boot\\bootmgfw.efi", StringComparison.OrdinalIgnoreCase)) {
|
||||||
|
msNum = num;
|
||||||
|
msEntry = entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ownEntry != null && msEntry != null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ownEntry == null) {
|
||||||
|
throw new Exception("MakeBootEntry: Boot entry list is full.");
|
||||||
|
} else if (msEntry == null) {
|
||||||
|
throw new Exception("MakeBootEntry: Windows Boot Manager not found.");
|
||||||
|
} else {
|
||||||
|
// Make a new boot entry using the MS entry as a starting point.
|
||||||
|
var entryData = new BootEntryData(msEntry.Data);
|
||||||
|
entryData.Arguments = Encoding.UTF8.GetBytes(label + "\0");
|
||||||
|
entryData.Attributes = 1; // LOAD_OPTION_ACTIVE
|
||||||
|
entryData.Label = label;
|
||||||
|
entryData.FileName = fileName;
|
||||||
|
ownEntry.Attributes = 7; // EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS
|
||||||
|
ownEntry.Data = entryData.ToBytes();
|
||||||
|
SetVariable(ownEntry, dryRun);
|
||||||
|
}
|
||||||
|
|
||||||
|
var msPos = bootOrderInts.IndexOf(msNum);
|
||||||
|
var ownPos = bootOrderInts.IndexOf(ownNum);
|
||||||
|
var mustAdd = ownPos == -1;
|
||||||
|
var mustMove = 0 <= msPos && msPos <= ownPos;
|
||||||
|
if (mustAdd || mustMove) {
|
||||||
|
if (mustMove) {
|
||||||
|
bootOrderInts.RemoveAt(ownPos);
|
||||||
|
}
|
||||||
|
bootOrderInts.Insert(msPos < 0 ? 0 : msPos, ownNum);
|
||||||
|
bootOrder.Data = bootOrderInts.SelectMany(num => new byte[] { (byte)(num & 0xff), (byte)(num >> 8) }).ToArray();
|
||||||
|
SetVariable(bootOrder, dryRun);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
47
src/Setup.cs
47
src/Setup.cs
@@ -41,6 +41,7 @@ public class Setup: SetupHelper {
|
|||||||
protected static readonly string[] privilegedActions = new string[] {
|
protected static readonly string[] privilegedActions = new string[] {
|
||||||
"install",
|
"install",
|
||||||
"allow-secure-boot",
|
"allow-secure-boot",
|
||||||
|
"enable-entry", "disable-entry",
|
||||||
"enable-overwrite", "disable-overwrite",
|
"enable-overwrite", "disable-overwrite",
|
||||||
"disable",
|
"disable",
|
||||||
"uninstall",
|
"uninstall",
|
||||||
@@ -219,6 +220,22 @@ public class Setup: SetupHelper {
|
|||||||
Console.WriteLine($"HackBGRT has been copied to {InstallPath}.");
|
Console.WriteLine($"HackBGRT has been copied to {InstallPath}.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable HackBGRT boot entry.
|
||||||
|
*/
|
||||||
|
protected void EnableEntry() {
|
||||||
|
Efi.MakeAndEnableBootEntry("HackBGRT", "\\EFI\\HackBGRT\\loader.efi", DryRun);
|
||||||
|
Console.WriteLine("Enabled NVRAM entry for HackBGRT.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable HackBGRT boot entry.
|
||||||
|
*/
|
||||||
|
protected void DisableEntry() {
|
||||||
|
Efi.DisableBootEntry("HackBGRT", "\\EFI\\HackBGRT\\loader.efi", DryRun);
|
||||||
|
Console.WriteLine("Disabled NVRAM entry for HackBGRT.");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable HackBGRT by overwriting the MS boot loader.
|
* Enable HackBGRT by overwriting the MS boot loader.
|
||||||
*/
|
*/
|
||||||
@@ -248,6 +265,7 @@ public class Setup: SetupHelper {
|
|||||||
protected void RestoreMsLoader() {
|
protected void RestoreMsLoader() {
|
||||||
var MsLoader = new BootLoaderInfo(Esp.MsLoaderPath);
|
var MsLoader = new BootLoaderInfo(Esp.MsLoaderPath);
|
||||||
if (MsLoader.Type == BootLoaderType.Own) {
|
if (MsLoader.Type == BootLoaderType.Own) {
|
||||||
|
Console.WriteLine("Disabling an old version of HackBGRT.");
|
||||||
var MsLoaderBackup = new BootLoaderInfo(BackupLoaderPath);
|
var MsLoaderBackup = new BootLoaderInfo(BackupLoaderPath);
|
||||||
if (!MsLoader.ReplaceWith(MsLoaderBackup)) {
|
if (!MsLoader.ReplaceWith(MsLoaderBackup)) {
|
||||||
throw new SetupException("Couldn't restore the old MS loader.");
|
throw new SetupException("Couldn't restore the old MS loader.");
|
||||||
@@ -281,6 +299,7 @@ public class Setup: SetupHelper {
|
|||||||
*/
|
*/
|
||||||
protected void Uninstall() {
|
protected void Uninstall() {
|
||||||
RestoreMsLoader();
|
RestoreMsLoader();
|
||||||
|
DisableEntry();
|
||||||
try {
|
try {
|
||||||
Directory.Delete(InstallPath, true);
|
Directory.Delete(InstallPath, true);
|
||||||
Console.WriteLine($"HackBGRT has been removed from {InstallPath}.");
|
Console.WriteLine($"HackBGRT has been removed from {InstallPath}.");
|
||||||
@@ -359,18 +378,30 @@ public class Setup: SetupHelper {
|
|||||||
protected void ShowMenu() {
|
protected void ShowMenu() {
|
||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
Console.WriteLine("Choose action (press a key):");
|
Console.WriteLine("Choose action (press a key):");
|
||||||
Console.WriteLine(" I = install, enable, upgrade, repair, modify");
|
Console.WriteLine(" I = install");
|
||||||
Console.WriteLine(" F = install files only, don't enable");
|
Console.WriteLine(" - creates a new EFI boot entry for HackBGRT");
|
||||||
Console.WriteLine(" D = disable, restore the original boot loader");
|
Console.WriteLine(" - sometimes needs to be enabled in firmware settings");
|
||||||
Console.WriteLine(" R = remove completely; delete all HackBGRT files and images");
|
Console.WriteLine(" - should fall back to MS boot loader if HackBGRT fails");
|
||||||
|
Console.WriteLine(" O = install (legacy)");
|
||||||
|
Console.WriteLine(" - overwrites the MS boot loader");
|
||||||
|
Console.WriteLine(" - may require re-install after Windows updates");
|
||||||
|
Console.WriteLine(" - could brick your system if configured incorrectly");
|
||||||
|
Console.WriteLine(" F = install files only");
|
||||||
|
Console.WriteLine(" - needs to be enabled somehow");
|
||||||
|
Console.WriteLine(" D = disable");
|
||||||
|
Console.WriteLine(" - removes created entries, restores MS boot loader");
|
||||||
|
Console.WriteLine(" R = remove completely");
|
||||||
|
Console.WriteLine(" - disables, then deletes all files and images");
|
||||||
Console.WriteLine(" C = cancel");
|
Console.WriteLine(" C = cancel");
|
||||||
|
|
||||||
var k = Console.ReadKey().Key;
|
var k = Console.ReadKey().Key;
|
||||||
Console.WriteLine();
|
Console.WriteLine();
|
||||||
if (k == ConsoleKey.I || k == ConsoleKey.F) {
|
if (k == ConsoleKey.I || k == ConsoleKey.O || k == ConsoleKey.F) {
|
||||||
Configure();
|
Configure();
|
||||||
}
|
}
|
||||||
if (k == ConsoleKey.I) {
|
if (k == ConsoleKey.I) {
|
||||||
|
RunPrivilegedActions(new string[] { "install", "enable-entry" });
|
||||||
|
} else if (k == ConsoleKey.O) {
|
||||||
RunPrivilegedActions(new string[] { "install", "enable-overwrite" });
|
RunPrivilegedActions(new string[] { "install", "enable-overwrite" });
|
||||||
} else if (k == ConsoleKey.F) {
|
} else if (k == ConsoleKey.F) {
|
||||||
RunPrivilegedActions(new string[] { "install" });
|
RunPrivilegedActions(new string[] { "install" });
|
||||||
@@ -417,6 +448,11 @@ public class Setup: SetupHelper {
|
|||||||
InstallFiles();
|
InstallFiles();
|
||||||
} else if (arg == "allow-secure-boot") {
|
} else if (arg == "allow-secure-boot") {
|
||||||
allowSecureBoot = true;
|
allowSecureBoot = true;
|
||||||
|
} else if (arg == "enable-entry") {
|
||||||
|
HandleSecureBoot(allowSecureBoot);
|
||||||
|
EnableEntry();
|
||||||
|
} else if (arg == "disable-entry") {
|
||||||
|
DisableEntry();
|
||||||
} else if (arg == "enable-overwrite") {
|
} else if (arg == "enable-overwrite") {
|
||||||
HandleSecureBoot(allowSecureBoot);
|
HandleSecureBoot(allowSecureBoot);
|
||||||
OverwriteMsLoader();
|
OverwriteMsLoader();
|
||||||
@@ -424,6 +460,7 @@ public class Setup: SetupHelper {
|
|||||||
RestoreMsLoader();
|
RestoreMsLoader();
|
||||||
} else if (arg == "disable") {
|
} else if (arg == "disable") {
|
||||||
RestoreMsLoader();
|
RestoreMsLoader();
|
||||||
|
DisableEntry();
|
||||||
} else if (arg == "uninstall") {
|
} else if (arg == "uninstall") {
|
||||||
Uninstall();
|
Uninstall();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
46
src/main.c
46
src/main.c
@@ -323,6 +323,19 @@ void HackBgrt(EFI_FILE_HANDLE root_dir) {
|
|||||||
HandleAcpiTables(HackBGRT_REPLACE, bgrt);
|
HandleAcpiTables(HackBGRT_REPLACE, bgrt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load an application.
|
||||||
|
*/
|
||||||
|
static EFI_HANDLE LoadApp(print_t* print_failure, EFI_HANDLE image_handle, EFI_LOADED_IMAGE* image, const CHAR16* path) {
|
||||||
|
EFI_DEVICE_PATH* boot_dp = FileDevicePath(image->DeviceHandle, (CHAR16*) path);
|
||||||
|
EFI_HANDLE result = 0;
|
||||||
|
Debug(L"HackBGRT: Loading application %s.\n", path);
|
||||||
|
if (EFI_ERROR(BS->LoadImage(0, image_handle, boot_dp, 0, 0, &result))) {
|
||||||
|
print_failure(L"HackBGRT: Failed to load application %s.\n", path);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The main program.
|
* The main program.
|
||||||
*/
|
*/
|
||||||
@@ -356,29 +369,34 @@ EFI_STATUS EFIAPI EfiMain(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *ST_) {
|
|||||||
HackBgrt(root_dir);
|
HackBgrt(root_dir);
|
||||||
|
|
||||||
EFI_HANDLE next_image_handle = 0;
|
EFI_HANDLE next_image_handle = 0;
|
||||||
if (!config.boot_path) {
|
static CHAR16 backup_boot_path[] = L"\\EFI\\HackBGRT\\bootmgfw-original.efi";
|
||||||
Print(L"HackBGRT: Boot path not specified.\n");
|
static CHAR16 ms_boot_path[] = L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi";
|
||||||
|
|
||||||
|
if (config.boot_path && StriCmp(config.boot_path, L"MS") != 0) {
|
||||||
|
next_image_handle = LoadApp(Print, image_handle, image, config.boot_path);
|
||||||
} else {
|
} else {
|
||||||
Debug(L"HackBGRT: Loading application %s.\n", config.boot_path);
|
config.boot_path = backup_boot_path;
|
||||||
EFI_DEVICE_PATH* boot_dp = FileDevicePath(image->DeviceHandle, (CHAR16*) config.boot_path);
|
next_image_handle = LoadApp(Debug, image_handle, image, config.boot_path);
|
||||||
if (EFI_ERROR(BS->LoadImage(0, image_handle, boot_dp, 0, 0, &next_image_handle))) {
|
if (!next_image_handle) {
|
||||||
Print(L"HackBGRT: Failed to load application %s.\n", config.boot_path);
|
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) {
|
||||||
static CHAR16 default_boot_path[] = L"\\EFI\\HackBGRT\\bootmgfw-original.efi";
|
config.boot_path = backup_boot_path;
|
||||||
Debug(L"HackBGRT: Loading application %s.\n", default_boot_path);
|
next_image_handle = LoadApp(Print, image_handle, image, config.boot_path);
|
||||||
EFI_DEVICE_PATH* boot_dp = FileDevicePath(image->DeviceHandle, default_boot_path);
|
if (!next_image_handle) {
|
||||||
if (EFI_ERROR(BS->LoadImage(0, image_handle, boot_dp, 0, 0, &next_image_handle))) {
|
config.boot_path = ms_boot_path;
|
||||||
Print(L"HackBGRT: Also failed to load application %s.\n", default_boot_path);
|
next_image_handle = LoadApp(Print, image_handle, image, config.boot_path);
|
||||||
goto fail;
|
if (!next_image_handle) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Print(L"HackBGRT: Reverting to %s.\n", default_boot_path);
|
Print(L"HackBGRT: Reverting to %s.\n", config.boot_path);
|
||||||
Print(L"Press escape to cancel, any other key to boot.\n");
|
Print(L"Press escape to cancel, any other key to boot.\n");
|
||||||
if (ReadKey().ScanCode == SCAN_ESC) {
|
if (ReadKey().ScanCode == SCAN_ESC) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
config.boot_path = default_boot_path;
|
|
||||||
}
|
}
|
||||||
if (config.debug) {
|
if (config.debug) {
|
||||||
Print(L"HackBGRT: Ready to boot.\nPress escape to cancel, any other key to boot.\n");
|
Print(L"HackBGRT: Ready to boot.\nPress escape to cancel, any other key to boot.\n");
|
||||||
|
|||||||
Reference in New Issue
Block a user