mirror of
https://github.com/acidanthera/OpenCorePkg.git
synced 2025-12-08 19:25:01 +00:00
OcBootManagement: Support OPT and CMD+R with picker
This commit is contained in:
parent
a1fbe0757b
commit
8fe7bef825
@ -20,6 +20,18 @@
|
||||
#include <Library/OcAppleBootPolicyLib.h>
|
||||
#include <Protocol/LoadedImage.h>
|
||||
|
||||
/**
|
||||
Operating system boot type.
|
||||
WARNING: This is only for debug purposes.
|
||||
**/
|
||||
typedef enum OC_BOOT_ENTRY_TYPE_ {
|
||||
OcBootUnknown,
|
||||
OcBootApple,
|
||||
OcBootAppleRecovery,
|
||||
OcBootWindows,
|
||||
OcBootCustom
|
||||
} OC_BOOT_ENTRY_TYPE;
|
||||
|
||||
/**
|
||||
Discovered boot entry.
|
||||
Note, inner resources must be freed with OcResetBootEntry.
|
||||
@ -40,9 +52,10 @@ typedef struct OC_BOOT_ENTRY_ {
|
||||
//
|
||||
CHAR16 *PathName;
|
||||
//
|
||||
// Set when this entry is a custom externally loadable tool entry.
|
||||
// Heuristical value signalising about booted os.
|
||||
// WARNING: This is only for debug purposes.
|
||||
//
|
||||
BOOLEAN IsCustom;
|
||||
OC_BOOT_ENTRY_TYPE Type;
|
||||
//
|
||||
// Set when this entry is an externally available entry (e.g. USB).
|
||||
//
|
||||
@ -52,15 +65,6 @@ typedef struct OC_BOOT_ENTRY_ {
|
||||
//
|
||||
BOOLEAN IsFolder;
|
||||
//
|
||||
// Heuristical value signalising about recovery os.
|
||||
//
|
||||
BOOLEAN IsRecovery;
|
||||
//
|
||||
// Heuristical value signalising about Windows os (otherwise macOS).
|
||||
// WARNING: This is only for debug purposes.
|
||||
//
|
||||
BOOLEAN IsWindows;
|
||||
//
|
||||
// Load option data (usually "boot args") size.
|
||||
//
|
||||
UINT32 LoadOptionsSize;
|
||||
@ -270,7 +274,7 @@ EFI_STATUS
|
||||
);
|
||||
|
||||
/**
|
||||
Custom picker entry
|
||||
Custom picker entry.
|
||||
**/
|
||||
typedef struct {
|
||||
//
|
||||
@ -283,6 +287,17 @@ typedef struct {
|
||||
CONST CHAR8 *Path;
|
||||
} OC_PICKER_ENTRY;
|
||||
|
||||
/**
|
||||
Picker behaviour action.
|
||||
**/
|
||||
typedef enum {
|
||||
OcPickerDefault = 0,
|
||||
OcPickerShowPicker = 1,
|
||||
OcPickerResetNvram = 2,
|
||||
OcPickerBootApple = 3,
|
||||
OcPickerBootAppleRecovery = 4,
|
||||
} OC_PICKER_CMD;
|
||||
|
||||
/**
|
||||
Boot picker context describing picker behaviour.
|
||||
**/
|
||||
@ -300,9 +315,10 @@ typedef struct {
|
||||
//
|
||||
UINT32 TimeoutSeconds;
|
||||
//
|
||||
// Show boot menu or just boot the default option.
|
||||
// Define picker behaviour.
|
||||
// For example, show boot menu or just boot the default option.
|
||||
//
|
||||
BOOLEAN ShowPicker;
|
||||
OC_PICKER_CMD PickerCommand;
|
||||
//
|
||||
// Use custom (gOcVendorVariableGuid) for Boot#### variables.
|
||||
//
|
||||
@ -412,21 +428,19 @@ OcScanForBootEntries (
|
||||
);
|
||||
|
||||
/**
|
||||
Obtain default entry from the list.
|
||||
Obtain default entry from picker context.
|
||||
|
||||
@param[in] Context Picker context.
|
||||
@param[in,out] BootEntries Described list of entries, may get updated.
|
||||
@param[in] NumBootEntries Positive number of boot entries.
|
||||
@param[in] CustomBootGuid Use custom GUID for Boot#### lookup.
|
||||
@param[in] LoadHandle Handle to skip (potential OpenCore handle).
|
||||
|
||||
@retval boot entry or NULL.
|
||||
@retval boot entry or 0.
|
||||
**/
|
||||
OC_BOOT_ENTRY *
|
||||
UINT32
|
||||
OcGetDefaultBootEntry (
|
||||
IN OUT OC_BOOT_ENTRY *BootEntries,
|
||||
IN UINTN NumBootEntries,
|
||||
IN BOOLEAN CustomBootGuid,
|
||||
IN EFI_HANDLE LoadHandle OPTIONAL
|
||||
IN OC_PICKER_CONTEXT *Context,
|
||||
IN OUT OC_BOOT_ENTRY *BootEntries,
|
||||
IN UINTN NumBootEntries
|
||||
);
|
||||
|
||||
/**
|
||||
@ -490,6 +504,16 @@ OcIsAppleHibernateWake (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Check pressed hotkeys and update booter context based on this.
|
||||
|
||||
@param[in,out] Context Picker context.
|
||||
**/
|
||||
VOID
|
||||
OcLoadPickerHotkeys (
|
||||
IN OUT OC_PICKER_CONTEXT *Context
|
||||
);
|
||||
|
||||
/**
|
||||
Install missing boot policy, scan, and show simple boot menu.
|
||||
|
||||
@ -528,6 +552,18 @@ OcGetFileSystemPolicyType (
|
||||
IN EFI_HANDLE Handle
|
||||
);
|
||||
|
||||
/**
|
||||
Check if supplied device path contains Apple bootloader.
|
||||
|
||||
@param[in] DevicePath Device path.
|
||||
|
||||
@retval TRUE for potentially Apple images.
|
||||
**/
|
||||
BOOLEAN
|
||||
OcIsAppleBootDevicePath (
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
|
||||
);
|
||||
|
||||
/**
|
||||
Get loaded image protocol for Apple bootloader.
|
||||
|
||||
|
||||
@ -297,9 +297,8 @@ InternalSetBootEntryFlags (
|
||||
BOOLEAN Result;
|
||||
INTN CmpResult;
|
||||
|
||||
BootEntry->Type = OcBootUnknown;
|
||||
BootEntry->IsFolder = FALSE;
|
||||
BootEntry->IsRecovery = FALSE;
|
||||
BootEntry->IsWindows = FALSE;
|
||||
|
||||
DevicePathWalker = BootEntry->DevicePath;
|
||||
|
||||
@ -307,6 +306,9 @@ InternalSetBootEntryFlags (
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// TODO: Move this to a new OcIsAppleRecoveryBootDevicePath function.
|
||||
//
|
||||
while (!IsDevicePathEnd (DevicePathWalker)) {
|
||||
if ((DevicePathType (DevicePathWalker) == MEDIA_DEVICE_PATH)
|
||||
&& (DevicePathSubType (DevicePathWalker) == MEDIA_FILEPATH_DP)) {
|
||||
@ -318,7 +320,7 @@ InternalSetBootEntryFlags (
|
||||
//
|
||||
BootEntry->IsFolder = (FilePath->PathName[Len - 1] == L'\\');
|
||||
|
||||
if (!BootEntry->IsRecovery) {
|
||||
if (BootEntry->Type == OcBootUnknown) {
|
||||
Result = OcOverflowSubUN (
|
||||
Len,
|
||||
L_STR_LEN (L"com.apple.recovery.boot"),
|
||||
@ -332,7 +334,7 @@ InternalSetBootEntryFlags (
|
||||
L_STR_SIZE_NT (L"com.apple.recovery.boot")
|
||||
);
|
||||
if (CmpResult == 0) {
|
||||
BootEntry->IsRecovery = TRUE;
|
||||
BootEntry->Type = OcBootAppleRecovery;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -345,6 +347,10 @@ InternalSetBootEntryFlags (
|
||||
|
||||
DevicePathWalker = NextDevicePathNode (DevicePathWalker);
|
||||
}
|
||||
|
||||
if (BootEntry->Type == OcBootUnknown && OcIsAppleBootDevicePath (BootEntry->DevicePath)) {
|
||||
BootEntry->Type = OcBootApple;
|
||||
}
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
@ -544,7 +550,7 @@ InternalFillValidBootEntries (
|
||||
DEBUG_BULK_INFO,
|
||||
"OCB: Adding entry %u, external - %d, skip recovery - %d\n",
|
||||
(UINT32) EntryIndex,
|
||||
Entries[EntryIndex].IsExternal,
|
||||
DevPathScanInfo->IsExternal,
|
||||
DevPathScanInfo->SkipRecovery
|
||||
));
|
||||
DebugPrintDevicePath (DEBUG_BULK_INFO, "DevicePath", DevicePath);
|
||||
@ -571,7 +577,7 @@ InternalFillValidBootEntries (
|
||||
DEBUG ((
|
||||
DEBUG_BULK_INFO,
|
||||
"OCB: Adding entry %u recovery (%s) - %r\n",
|
||||
Entries[EntryIndex].IsExternal,
|
||||
DevPathScanInfo->IsExternal,
|
||||
RecoveryPath != NULL ? RecoveryPath : L"<null>",
|
||||
Status
|
||||
));
|
||||
|
||||
@ -272,7 +272,7 @@ InternalGetBootEntryByDevicePath (
|
||||
|
||||
for (Index = 0; Index < NumBootEntries; ++Index) {
|
||||
BootEntry = &BootEntries[Index];
|
||||
if (BootEntry->IsCustom) {
|
||||
if (BootEntry->Type == OcBootCustom) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -352,8 +352,19 @@ InternalIsAppleLegacyLoadApp (
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
Obtain default entry from the list.
|
||||
|
||||
@param[in,out] BootEntries Described list of entries, may get updated.
|
||||
@param[in] NumBootEntries Positive number of boot entries.
|
||||
@param[in] CustomBootGuid Use custom GUID for Boot#### lookup.
|
||||
@param[in] LoadHandle Handle to skip (potential OpenCore handle).
|
||||
|
||||
@retval boot entry or NULL.
|
||||
**/
|
||||
STATIC
|
||||
OC_BOOT_ENTRY *
|
||||
OcGetDefaultBootEntry (
|
||||
InternalGetDefaultBootEntry (
|
||||
IN OUT OC_BOOT_ENTRY *BootEntries,
|
||||
IN UINTN NumBootEntries,
|
||||
IN BOOLEAN CustomBootGuid,
|
||||
@ -695,6 +706,63 @@ OcGetDefaultBootEntry (
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UINT32
|
||||
OcGetDefaultBootEntry (
|
||||
IN OC_PICKER_CONTEXT *Context,
|
||||
IN OUT OC_BOOT_ENTRY *BootEntries,
|
||||
IN UINTN NumBootEntries
|
||||
)
|
||||
{
|
||||
UINT32 BootEntryIndex;
|
||||
OC_BOOT_ENTRY *BootEntry;
|
||||
UINTN Index;
|
||||
|
||||
BootEntry = InternalGetDefaultBootEntry (
|
||||
BootEntries,
|
||||
NumBootEntries,
|
||||
Context->CustomBootGuid,
|
||||
Context->ExcludeHandle
|
||||
);
|
||||
|
||||
if (BootEntry != NULL) {
|
||||
BootEntryIndex = (UINT32) (BootEntry - BootEntries);
|
||||
DEBUG ((DEBUG_INFO, "OCB: Initial default is %u\n", BootEntryIndex));
|
||||
} else {
|
||||
BootEntryIndex = 0;
|
||||
DEBUG ((DEBUG_INFO, "OCB: Initial default is 0, fallback\n"));
|
||||
}
|
||||
|
||||
if (Context->PickerCommand == OcPickerBootApple) {
|
||||
if (BootEntries[BootEntryIndex].Type != OcBootApple) {
|
||||
for (Index = 0; Index < NumBootEntries; ++Index) {
|
||||
if (BootEntries[Index].Type == OcBootApple) {
|
||||
BootEntryIndex = (UINT32) Index;
|
||||
DEBUG ((DEBUG_INFO, "OCB: Override default to Apple %u\n", BootEntryIndex));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (Context->PickerCommand == OcPickerBootAppleRecovery) {
|
||||
if (BootEntries[BootEntryIndex].Type != OcBootAppleRecovery) {
|
||||
if (BootEntryIndex + 1 < NumBootEntries
|
||||
&& BootEntries[BootEntryIndex + 1].Type == OcBootAppleRecovery) {
|
||||
BootEntryIndex = BootEntryIndex + 1;
|
||||
DEBUG ((DEBUG_INFO, "OCB: Override default to Apple Recovery %u, next\n", BootEntryIndex));
|
||||
} else {
|
||||
for (Index = 0; Index < NumBootEntries; ++Index) {
|
||||
if (BootEntries[Index].Type == OcBootAppleRecovery) {
|
||||
BootEntryIndex = (UINT32) Index;
|
||||
DEBUG ((DEBUG_INFO, "OCB: Override default option to Apple Recovery %u\n", BootEntryIndex));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return BootEntryIndex;
|
||||
}
|
||||
|
||||
#if 0
|
||||
STATIC
|
||||
VOID
|
||||
@ -830,7 +898,7 @@ InternalLoadBootEntry (
|
||||
if (DevicePath == NULL) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
} else if (BootEntry->IsCustom && BootEntry->DevicePath == NULL) {
|
||||
} else if (BootEntry->Type == OcBootCustom && BootEntry->DevicePath == NULL) {
|
||||
ASSERT (Context->CustomRead != NULL);
|
||||
|
||||
Status = Context->CustomRead (
|
||||
@ -894,7 +962,7 @@ InternalLoadBootEntry (
|
||||
LoadedImage->LoadOptionsSize = BootEntry->LoadOptionsSize;
|
||||
LoadedImage->LoadOptions = BootEntry->LoadOptions;
|
||||
|
||||
if (BootEntry->IsCustom) {
|
||||
if (BootEntry->Type == OcBootCustom) {
|
||||
DEBUG ((
|
||||
DEBUG_INFO,
|
||||
"OCB: Custom DeviceHandle %p FilePath %p\n",
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
#include <IndustryStandard/AppleHibernate.h>
|
||||
|
||||
#include <Protocol/AppleBootPolicy.h>
|
||||
#include <Protocol/AppleKeyMapAggregator.h>
|
||||
#include <Protocol/LoadedImage.h>
|
||||
#include <Protocol/SimpleTextOut.h>
|
||||
|
||||
@ -56,7 +57,7 @@ OcDescribeBootEntry (
|
||||
//
|
||||
// Custom entries need no special description.
|
||||
//
|
||||
if (BootEntry->IsCustom) {
|
||||
if (BootEntry->Type == OcBootCustom) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
@ -106,14 +107,16 @@ OcDescribeBootEntry (
|
||||
//
|
||||
|
||||
//
|
||||
// Windows boot entry may have a custom name, so ensure IsWindows is set correctly.
|
||||
// Windows boot entry may have a custom name, so ensure OcBootWindows is set correctly.
|
||||
//
|
||||
DEBUG ((DEBUG_INFO, "Trying to detect Microsoft BCD\n"));
|
||||
Status = ReadFileSize (FileSystem, L"\\EFI\\Microsoft\\Boot\\BCD", &BcdSize);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
BootEntry->IsWindows = TRUE;
|
||||
if (BootEntry->Name == NULL) {
|
||||
BootEntry->Name = AllocateCopyPool (sizeof (L"BOOTCAMP Windows"), L"BOOTCAMP Windows");
|
||||
if (BootEntry->Type == OcBootUnknown) {
|
||||
DEBUG ((DEBUG_INFO, "Trying to detect Microsoft BCD\n"));
|
||||
Status = ReadFileSize (FileSystem, L"\\EFI\\Microsoft\\Boot\\BCD", &BcdSize);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
BootEntry->Type = OcBootWindows;
|
||||
if (BootEntry->Name == NULL) {
|
||||
BootEntry->Name = AllocateCopyPool (sizeof (L"BOOTCAMP Windows"), L"BOOTCAMP Windows");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -122,7 +125,9 @@ OcDescribeBootEntry (
|
||||
if (BootEntry->Name != NULL
|
||||
&& (!StrCmp (BootEntry->Name, L"Recovery HD")
|
||||
|| !StrCmp (BootEntry->Name, L"Recovery"))) {
|
||||
BootEntry->IsRecovery = TRUE;
|
||||
if (BootEntry->Type == OcBootUnknown || BootEntry->Type == OcBootApple) {
|
||||
BootEntry->Type = OcBootAppleRecovery;
|
||||
}
|
||||
RecoveryBootName = InternalGetAppleRecoveryName (FileSystem, BootDirectoryName);
|
||||
if (RecoveryBootName != NULL) {
|
||||
FreePool (BootEntry->Name);
|
||||
@ -323,12 +328,11 @@ OcScanForBootEntries (
|
||||
DEBUG_CODE_BEGIN ();
|
||||
DEBUG ((
|
||||
DEBUG_INFO,
|
||||
"Entry %u is %s at %s (W:%d|R:%d|F:%d)\n",
|
||||
"Entry %u is %s at %s (T:%d|F:%d)\n",
|
||||
(UINT32) Index,
|
||||
Entries[Index].Name,
|
||||
Entries[Index].PathName,
|
||||
Entries[Index].IsWindows,
|
||||
Entries[Index].IsRecovery,
|
||||
Entries[Index].Type,
|
||||
Entries[Index].IsFolder
|
||||
));
|
||||
|
||||
@ -360,7 +364,7 @@ OcScanForBootEntries (
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Entries[EntryIndex].IsCustom = TRUE;
|
||||
Entries[EntryIndex].Type = OcBootCustom;
|
||||
|
||||
if (Index < Context->AbsoluteEntryCount) {
|
||||
Entries[EntryIndex].DevicePath = ConvertTextToDevicePath (PathName);
|
||||
@ -758,6 +762,131 @@ OcLoadBootEntry (
|
||||
return Status;
|
||||
}
|
||||
|
||||
STATIC
|
||||
BOOLEAN
|
||||
OcKeyMapHasModifier (
|
||||
IN APPLE_KEY_MAP_AGGREGATOR_PROTOCOL *KeyMapAggregator,
|
||||
IN APPLE_MODIFIER_MAP ModifierLeft,
|
||||
IN APPLE_MODIFIER_MAP ModifierRight OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
Status = KeyMapAggregator->ContainsKeyStrokes (
|
||||
KeyMapAggregator,
|
||||
ModifierLeft,
|
||||
0,
|
||||
NULL,
|
||||
FALSE
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status) && ModifierRight != 0) {
|
||||
Status = KeyMapAggregator->ContainsKeyStrokes (
|
||||
KeyMapAggregator,
|
||||
ModifierRight,
|
||||
0,
|
||||
NULL,
|
||||
FALSE
|
||||
);
|
||||
}
|
||||
|
||||
return !EFI_ERROR (Status);
|
||||
}
|
||||
|
||||
STATIC
|
||||
BOOLEAN
|
||||
OcKeyMapHasKey (
|
||||
IN APPLE_KEY_MAP_AGGREGATOR_PROTOCOL *KeyMapAggregator,
|
||||
IN APPLE_KEY_CODE KeyCode
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
Status = KeyMapAggregator->ContainsKeyStrokes (
|
||||
KeyMapAggregator,
|
||||
0,
|
||||
1,
|
||||
&KeyCode,
|
||||
FALSE
|
||||
);
|
||||
|
||||
return !EFI_ERROR (Status);
|
||||
}
|
||||
|
||||
VOID
|
||||
OcLoadPickerHotkeys (
|
||||
IN OUT OC_PICKER_CONTEXT *Context
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
APPLE_KEY_MAP_AGGREGATOR_PROTOCOL *KeyMap;
|
||||
BOOLEAN HasCommand;
|
||||
BOOLEAN HasOption;
|
||||
BOOLEAN HasShift;
|
||||
BOOLEAN HasKeyP;
|
||||
BOOLEAN HasKeyR;
|
||||
BOOLEAN HasKeyX;
|
||||
|
||||
Status = gBS->LocateProtocol (
|
||||
&gAppleKeyMapAggregatorProtocolGuid,
|
||||
NULL,
|
||||
(VOID **) &KeyMap
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "OCB: Missing AppleKeyMapAggregator - %r\n", Status));
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// I do not like this code a little, as it is prone to race conditions during key presses.
|
||||
// For the good false positives are not too critical here, and in reality users are not that fast.
|
||||
//
|
||||
// Reference key list:
|
||||
// https://support.apple.com/HT201255
|
||||
// https://support.apple.com/HT204904
|
||||
//
|
||||
// We are slightly more permissive than AppleBds, as we permit combining keys.
|
||||
//
|
||||
|
||||
HasCommand = OcKeyMapHasModifier (KeyMap, APPLE_MODIFIER_LEFT_COMMAND, APPLE_MODIFIER_RIGHT_COMMAND);
|
||||
HasOption = OcKeyMapHasModifier (KeyMap, APPLE_MODIFIER_LEFT_OPTION, APPLE_MODIFIER_RIGHT_OPTION);
|
||||
HasShift = OcKeyMapHasModifier (KeyMap, APPLE_MODIFIER_LEFT_SHIFT, APPLE_MODIFIER_RIGHT_SHIFT);
|
||||
HasKeyP = OcKeyMapHasKey (KeyMap, AppleHidUsbKbUsageKeyP);
|
||||
HasKeyR = OcKeyMapHasKey (KeyMap, AppleHidUsbKbUsageKeyP);
|
||||
HasKeyX = OcKeyMapHasKey (KeyMap, AppleHidUsbKbUsageKeyX);
|
||||
|
||||
if (HasOption && HasCommand && HasKeyP && HasKeyR) {
|
||||
//
|
||||
// TODO: Protect this with some policy?
|
||||
//
|
||||
DEBUG ((DEBUG_INFO, "OCB: CMD+OPT+P+R causes NVRAM reset\n"));
|
||||
Context->PickerCommand = OcPickerResetNvram;
|
||||
} else if (HasCommand && HasKeyR) {
|
||||
DEBUG ((DEBUG_INFO, "OCB: CMD+R causes recovery to boot\n"));
|
||||
Context->PickerCommand = OcPickerBootAppleRecovery;
|
||||
} else if (HasKeyX) {
|
||||
DEBUG ((DEBUG_INFO, "OCB: X causes macOS to boot\n"));
|
||||
Context->PickerCommand = OcPickerBootApple;
|
||||
} else if (HasOption) {
|
||||
DEBUG ((DEBUG_INFO, "OCB: OPT causes picker to show\n"));
|
||||
Context->PickerCommand = OcPickerShowPicker;
|
||||
} else {
|
||||
//
|
||||
// In addition to these overrides we always have ShowPicker = YES in config.
|
||||
// The following keys are not implemented:
|
||||
// C - CD/DVD boot, legacy that is gone now.
|
||||
// D - Diagnostics, could implement dumping stuff here in some future,
|
||||
// but we will need to store the data before handling the key.
|
||||
// Should also be DEBUG only for security reasons.
|
||||
// N - Network boot, simply not supported (and bad for security).
|
||||
// T - Target disk mode, simply not supported (and bad for security).
|
||||
//
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
OcRunSimpleBootPicker (
|
||||
IN OC_PICKER_CONTEXT *Context
|
||||
@ -767,9 +896,8 @@ OcRunSimpleBootPicker (
|
||||
APPLE_BOOT_POLICY_PROTOCOL *AppleBootPolicy;
|
||||
OC_BOOT_ENTRY *Chosen;
|
||||
OC_BOOT_ENTRY *Entries;
|
||||
OC_BOOT_ENTRY *Entry;
|
||||
UINTN EntryCount;
|
||||
UINT32 DefaultEntry;
|
||||
INTN DefaultEntry;
|
||||
|
||||
AppleBootPolicy = OcAppleBootPolicyInstallProtocol (FALSE);
|
||||
if (AppleBootPolicy == NULL) {
|
||||
@ -801,13 +929,9 @@ OcRunSimpleBootPicker (
|
||||
|
||||
DEBUG ((DEBUG_INFO, "Performing OcShowSimpleBootMenu...\n"));
|
||||
|
||||
DefaultEntry = 0;
|
||||
Entry = OcGetDefaultBootEntry (Entries, EntryCount, Context->CustomBootGuid, Context->ExcludeHandle);
|
||||
if (Entry != NULL) {
|
||||
DefaultEntry = (UINT32)(Entry - Entries);
|
||||
}
|
||||
DefaultEntry = OcGetDefaultBootEntry (Context, Entries, EntryCount);
|
||||
|
||||
if (Context->ShowPicker) {
|
||||
if (Context->PickerCommand == OcPickerShowPicker) {
|
||||
Status = OcShowSimpleBootMenu (
|
||||
Entries,
|
||||
EntryCount,
|
||||
@ -831,10 +955,9 @@ OcRunSimpleBootPicker (
|
||||
if (!EFI_ERROR (Status)) {
|
||||
DEBUG ((
|
||||
DEBUG_INFO,
|
||||
"Should boot from %s (W:%d|R:%d|F:%d)\n",
|
||||
"Should boot from %s (T:%d|F:%d)\n",
|
||||
Chosen->Name,
|
||||
Chosen->IsWindows,
|
||||
Chosen->IsRecovery,
|
||||
Chosen->Type,
|
||||
Chosen->IsFolder
|
||||
));
|
||||
}
|
||||
|
||||
@ -61,6 +61,7 @@
|
||||
|
||||
[Protocols]
|
||||
gAppleBootPolicyProtocolGuid ## PRODUCES
|
||||
gAppleKeyMapAggregatorProtocolGuid ## SOMETIMES_CONSUMES
|
||||
gEfiSimpleFileSystemProtocolGuid ## SOMETIMES_CONSUMES
|
||||
gEfiLoadedImageProtocolGuid ## SOMETIMES_CONSUMES
|
||||
gEfiUsbIoProtocolGuid ## SOMETIMES_CONSUMES
|
||||
|
||||
@ -220,6 +220,39 @@ InternalCheckScanPolicy (
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
OcIsAppleBootDevicePath (
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
|
||||
)
|
||||
{
|
||||
EFI_DEVICE_PATH_PROTOCOL *CurrNode;
|
||||
FILEPATH_DEVICE_PATH *LastNode;
|
||||
UINTN PathLen;
|
||||
UINTN Index;
|
||||
|
||||
LastNode = NULL;
|
||||
|
||||
for (CurrNode = DevicePath; !IsDevicePathEnd (CurrNode); CurrNode = NextDevicePathNode (CurrNode)) {
|
||||
if (DevicePathType (CurrNode) == MEDIA_DEVICE_PATH && DevicePathSubType (CurrNode) == MEDIA_FILEPATH_DP) {
|
||||
LastNode = (FILEPATH_DEVICE_PATH *) CurrNode;
|
||||
}
|
||||
}
|
||||
|
||||
if (LastNode != NULL) {
|
||||
//
|
||||
// Detect macOS by boot.efi in the bootloader name.
|
||||
//
|
||||
PathLen = OcFileDevicePathNameLen (LastNode);
|
||||
if (PathLen >= L_STR_LEN ("boot.efi")) {
|
||||
Index = PathLen - L_STR_LEN ("boot.efi");
|
||||
return (Index == 0 || LastNode->PathName[Index - 1] == L'\\')
|
||||
&& CompareMem (&LastNode->PathName[Index], L"boot.efi", L_STR_SIZE (L"boot.efi")) == 0;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
EFI_LOADED_IMAGE_PROTOCOL *
|
||||
OcGetAppleBootLoadedImage (
|
||||
IN EFI_HANDLE ImageHandle
|
||||
@ -227,37 +260,18 @@ OcGetAppleBootLoadedImage (
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
|
||||
EFI_DEVICE_PATH_PROTOCOL *CurrNode;
|
||||
FILEPATH_DEVICE_PATH *LastNode;
|
||||
BOOLEAN IsMacOS;
|
||||
UINTN PathLen;
|
||||
UINTN Index;
|
||||
|
||||
IsMacOS = FALSE;
|
||||
Status = gBS->HandleProtocol (
|
||||
ImageHandle,
|
||||
&gEfiLoadedImageProtocolGuid,
|
||||
(VOID **)&LoadedImage
|
||||
);
|
||||
|
||||
Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **)&LoadedImage);
|
||||
|
||||
if (!EFI_ERROR (Status) && LoadedImage->FilePath) {
|
||||
LastNode = NULL;
|
||||
|
||||
for (CurrNode = LoadedImage->FilePath; !IsDevicePathEnd (CurrNode); CurrNode = NextDevicePathNode (CurrNode)) {
|
||||
if (DevicePathType (CurrNode) == MEDIA_DEVICE_PATH && DevicePathSubType (CurrNode) == MEDIA_FILEPATH_DP) {
|
||||
LastNode = (FILEPATH_DEVICE_PATH *) CurrNode;
|
||||
}
|
||||
}
|
||||
|
||||
if (LastNode != NULL) {
|
||||
//
|
||||
// Detect macOS by boot.efi in the bootloader name.
|
||||
//
|
||||
PathLen = OcFileDevicePathNameLen (LastNode);
|
||||
if (PathLen >= L_STR_LEN ("boot.efi")) {
|
||||
Index = PathLen - L_STR_LEN ("boot.efi");
|
||||
IsMacOS = (Index == 0 || LastNode->PathName[Index - 1] == L'\\')
|
||||
&& CompareMem (&LastNode->PathName[Index], L"boot.efi", L_STR_SIZE (L"boot.efi")) == 0;
|
||||
}
|
||||
}
|
||||
if (!EFI_ERROR (Status)
|
||||
&& LoadedImage->FilePath != NULL
|
||||
&& OcIsAppleBootDevicePath (LoadedImage->FilePath)) {
|
||||
return LoadedImage;
|
||||
}
|
||||
|
||||
return IsMacOS ? LoadedImage : NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user