OcBootManagement: Implement Apple BootPicker support

This commit is contained in:
vit9696 2020-02-09 14:31:32 +03:00
parent 37c26b1a40
commit b0fd7de372
12 changed files with 389 additions and 13 deletions

View File

@ -0,0 +1,99 @@
/** @file
Run Apple boot picker.
Copyright (c) 2020, vit9696. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <PiDxe.h>
#include <Guid/AppleFile.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/OcBootManagementLib.h>
#include <Library/OcConsoleLib.h>
#include <Library/OcMiscLib.h>
#include <Library/OcFileLib.h>
#include <Library/UefiApplicationEntryPoint.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Protocol/DevicePath.h>
#include <Protocol/GraphicsOutput.h>
#include <Protocol/DevicePath.h>
EFI_STATUS
EFIAPI
UefiMain (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
EFI_GRAPHICS_OUTPUT_PROTOCOL *Gop;
EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Pixel;
Status = gBS->HandleProtocol (
gST->ConsoleOutHandle,
&gEfiGraphicsOutputProtocolGuid,
(VOID **) &Gop
);
gBS->SetWatchdogTimer (0, 0, 0, NULL);
OcProvideConsoleGop ();
if (EFI_ERROR (Status)) {
gBS->Stall (SECONDS_TO_MICROSECONDS (10));
return Status;
}
Status = OcRunAppleBootPicker ();
Pixel.Raw = 0x0;
if (Status == EFI_NOT_FOUND) {
//
// Red. No BootPicker in firmware or we cannot get it.
//
Pixel.Pixel.Red = 0xFF;
} else if (Status == EFI_UNSUPPORTED) {
//
// Yellow. BootPicker does not start.
//
Pixel.Pixel.Red = 0xFF;
Pixel.Pixel.Green = 0xFF;
} else if (EFI_ERROR (Status) /* Status == EFI_INVALID_PARAMETER */) {
//
// Fuchsia. BootPicker does not load.
//
Pixel.Pixel.Blue = 0xFF;
Pixel.Pixel.Red = 0xFF;
} else {
//
// Green. BootPicker started but returned.
//
Pixel.Pixel.Green = 0xFF;
}
Gop->Blt (
Gop,
&Pixel.Pixel,
EfiBltVideoFill,
0,
0,
0,
0,
Gop->Mode->Info->HorizontalResolution,
Gop->Mode->Info->VerticalResolution,
0
);
gBS->Stall (SECONDS_TO_MICROSECONDS (10));
return EFI_SUCCESS;
}

View File

@ -0,0 +1,55 @@
## @file
# Clean several important nvram variables to recover from issues.
#
# Copyright (c) 2018, vit9696. All rights reserved.<BR>
#
# This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = BootKicker
FILE_GUID = 3099A880-582F-44BA-8DA3-F4A875F3E34D
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 1.0
ENTRY_POINT = UefiMain
#
# This flag specifies whether HII resource section is generated into PE image.
#
UEFI_HII_RESOURCE_SECTION = TRUE
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
[Sources]
BootKicker.c
[Guids]
gAppleBootPickerFileGuid
[Protocols]
gEfiDevicePathProtocolGuid
gEfiFirmwareVolumeProtocolGuid
[Packages]
EfiPkg/EfiPkg.dec
MdePkg/MdePkg.dec
OcSupportPkg/OcSupportPkg.dec
[LibraryClasses]
OcBootManagementLib
OcConsoleLib
OcFileLib
UefiApplicationEntryPoint
UefiBootServicesTableLib
UefiLib

View File

@ -36,6 +36,15 @@ typedef enum OC_BOOT_ENTRY_TYPE_ {
OcBootSystem
} OC_BOOT_ENTRY_TYPE;
/**
Picker mode.
**/
typedef enum OC_PICKER_MODE_ {
OcPickerModeBuiltin,
OcPickerModeExternal,
OcPickerModeApple,
} OC_PICKER_MODE;
/**
Action to perform as part of executing a system boot entry.
**/
@ -399,6 +408,10 @@ typedef struct {
//
CONST CHAR8 *TitleSuffix;
//
// Used picker mode.
//
OC_PICKER_MODE PickerMode;
//
// Console attributes. 0 is reserved as disabled.
//
UINT32 ConsoleAttributes;
@ -830,4 +843,15 @@ OcDeleteVariables (
VOID
);
/**
Launch Apple BootPicker.
@retval error code, should not return.
**/
EFI_STATUS
OcRunAppleBootPicker (
VOID
);
#endif // OC_BOOT_MANAGEMENT_LIB_H

View File

@ -268,14 +268,14 @@
OC_DECLARE (OC_MISC_BLESS_ARRAY)
#define OC_MISC_BOOT_FIELDS(_, __) \
_(BOOLEAN , HideSelf , , FALSE , ()) \
_(BOOLEAN , PollAppleHotKeys , , FALSE , ()) \
_(BOOLEAN , ShowPicker , , FALSE , ()) \
_(BOOLEAN , UsePicker , , FALSE , ()) \
_(UINT32 , PickerAttributes , , 0 , ()) \
_(UINT32 , TakeoffDelay , , 0 , ()) \
_(UINT32 , Timeout , , 0 , ()) \
_(OC_STRING , HibernateMode , , OC_STRING_CONSTR ("None", _, __), OC_DESTR (OC_STRING))
_(OC_STRING , PickerMode , , OC_STRING_CONSTR ("Builtin", _, __) , OC_DESTR (OC_STRING)) \
_(OC_STRING , HibernateMode , , OC_STRING_CONSTR ("None", _, __) , OC_DESTR (OC_STRING)) \
_(UINT32 , PickerAttributes , , 0 , ()) \
_(UINT32 , TakeoffDelay , , 0 , ()) \
_(UINT32 , Timeout , , 0 , ()) \
_(BOOLEAN , HideSelf , , FALSE , ()) \
_(BOOLEAN , PollAppleHotKeys , , FALSE , ()) \
_(BOOLEAN , ShowPicker , , FALSE , ())
OC_DECLARE (OC_MISC_BOOT)
#define OC_MISC_DEBUG_FIELDS(_, __) \

View File

@ -307,11 +307,24 @@ OcGetGptPartitionEntry (
/**
Unblocks all partition handles without a File System protocol attached from
driver connection, if applicable.
**/
VOID
OcUnblockUnmountedPartitions (
VOID
);
/**
Creates a device path for a firmware file.
@param[in] FileGuid Firmware file GUID.
@retval device path allocated from pool on success.
@retval NULL on failure (e.g. when a file is not present).
**/
EFI_DEVICE_PATH_PROTOCOL *
CreateFvFileDevicePath (
IN EFI_GUID *FileGuid
);
#endif // OC_FILE_LIB_H

View File

@ -14,6 +14,7 @@
#include "BootManagementInternal.h"
#include <Guid/AppleFile.h>
#include <Guid/AppleVariable.h>
#include <Guid/OcVariables.h>
@ -347,6 +348,7 @@ OcRunSimpleBootPicker (
OC_BOOT_ENTRY *Entries;
UINTN EntryCount;
INTN DefaultEntry;
BOOLEAN ForbidApple;
AppleBootPolicy = OcAppleBootPolicyInstallProtocol (FALSE);
if (AppleBootPolicy == NULL) {
@ -360,6 +362,9 @@ OcRunSimpleBootPicker (
return EFI_NOT_FOUND;
}
//
// This one is handled as is for Apple BootPicker for now.
//
if (Context->PickerCommand != OcPickerDefault) {
Status = Context->RequestPrivilege (
Context->PrivilegeContext,
@ -375,6 +380,14 @@ OcRunSimpleBootPicker (
}
}
if (Context->PickerCommand == OcPickerShowPicker && Context->PickerMode == OcPickerModeApple) {
Status = OcRunAppleBootPicker ();
DEBUG ((DEBUG_INFO, "OCB: Apple BootPicker failed - %r, fallback to builtin\n", Status));
ForbidApple = TRUE;
} else {
ForbidApple = FALSE;
}
while (TRUE) {
DEBUG ((DEBUG_INFO, "OCB: Performing OcScanForBootEntries...\n"));
@ -406,6 +419,12 @@ OcRunSimpleBootPicker (
DefaultEntry = OcGetDefaultBootEntry (Context, Entries, EntryCount);
if (Context->PickerCommand == OcPickerShowPicker) {
if (!ForbidApple && Context->PickerMode == OcPickerModeApple) {
Status = OcRunAppleBootPicker ();
DEBUG ((DEBUG_INFO, "OCB: Apple BootPicker failed on error - %r, fallback to builtin\n", Status));
ForbidApple = TRUE;
}
Status = OcShowSimpleBootMenu (
Context,
Entries,
@ -478,3 +497,45 @@ OcRunSimpleBootPicker (
OcFreeBootEntries (Entries, EntryCount);
}
}
EFI_STATUS
OcRunAppleBootPicker (
VOID
)
{
EFI_STATUS Status;
EFI_HANDLE NewHandle;
EFI_DEVICE_PATH_PROTOCOL *Dp;
Dp = CreateFvFileDevicePath (&gAppleBootPickerFileGuid);
if (Dp != NULL) {
NewHandle = NULL;
Status = gBS->LoadImage (
FALSE,
gImageHandle,
Dp,
NULL,
0,
&NewHandle
);
if (EFI_ERROR (Status)) {
Status = EFI_INVALID_PARAMETER;
}
} else {
Status = EFI_NOT_FOUND;
}
if (!EFI_ERROR (Status)) {
Status = gBS->StartImage (
NewHandle,
NULL,
NULL
);
if (EFI_ERROR (Status)) {
Status = EFI_UNSUPPORTED;
}
}
return Status;
}

View File

@ -74,6 +74,7 @@
gOcVendorVariableGuid ## SOMETIMES_CONSUMES
gOcReadOnlyVariableGuid ## SOMETIMES_CONSUMES
gOcWriteOnlyVariableGuid ## SOMETIMES_CONSUMES
gAppleBootPickerFileGuid ## SOMETIMES_CONSUMES
[Protocols]
gAppleBootPolicyProtocolGuid ## PRODUCES

View File

@ -321,11 +321,11 @@ mMiscConfigurationBootSchema[] = {
OC_SCHEMA_STRING_IN ("HibernateMode", OC_GLOBAL_CONFIG, Misc.Boot.HibernateMode),
OC_SCHEMA_BOOLEAN_IN ("HideSelf", OC_GLOBAL_CONFIG, Misc.Boot.HideSelf),
OC_SCHEMA_INTEGER_IN ("PickerAttributes", OC_GLOBAL_CONFIG, Misc.Boot.PickerAttributes),
OC_SCHEMA_STRING_IN ("PickerMode", OC_GLOBAL_CONFIG, Misc.Boot.PickerMode),
OC_SCHEMA_BOOLEAN_IN ("PollAppleHotKeys", OC_GLOBAL_CONFIG, Misc.Boot.PollAppleHotKeys),
OC_SCHEMA_BOOLEAN_IN ("ShowPicker", OC_GLOBAL_CONFIG, Misc.Boot.ShowPicker),
OC_SCHEMA_INTEGER_IN ("TakeoffDelay", OC_GLOBAL_CONFIG, Misc.Boot.TakeoffDelay),
OC_SCHEMA_INTEGER_IN ("Timeout", OC_GLOBAL_CONFIG, Misc.Boot.Timeout),
OC_SCHEMA_BOOLEAN_IN ("UsePicker", OC_GLOBAL_CONFIG, Misc.Boot.UsePicker),
};
STATIC

View File

@ -0,0 +1,113 @@
/** @file
Copyright (C) 2020, vit9696. All rights reserved.
All rights reserved.
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <PiDxe.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/DevicePathLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Protocol/DevicePath.h>
#include <Protocol/GraphicsOutput.h>
#include <Protocol/FirmwareVolume.h>
#include <Protocol/DevicePath.h>
STATIC
EFI_HANDLE
GetFvFileVolume (
IN EFI_GUID *FvNameGuid
)
{
UINTN Index;
EFI_STATUS Status;
UINT32 AuthenticationStatus;
EFI_FIRMWARE_VOLUME_PROTOCOL *FirmwareVolumeInterface;
UINTN NumOfHandles;
EFI_HANDLE *HandleBuffer;
EFI_FV_FILETYPE Type;
UINTN Size;
EFI_FV_FILE_ATTRIBUTES Attributes;
EFI_HANDLE CurrentVolume;
Status = gBS->LocateHandleBuffer (
ByProtocol,
&gEfiFirmwareVolumeProtocolGuid,
NULL,
&NumOfHandles,
&HandleBuffer
);
//
// TODO: Support FirmwareVolume2?
//
if (EFI_ERROR (Status)) {
return NULL;
}
for (Index = 0; Index < NumOfHandles; ++Index) {
CurrentVolume = HandleBuffer[Index];
Status = gBS->HandleProtocol (
CurrentVolume,
&gEfiFirmwareVolumeProtocolGuid,
(VOID **) &FirmwareVolumeInterface
);
if (EFI_ERROR (Status)) {
continue;
}
Status = FirmwareVolumeInterface->ReadFile (
FirmwareVolumeInterface,
FvNameGuid,
NULL,
&Size,
&Type,
&Attributes,
&AuthenticationStatus
);
if (!EFI_ERROR (Status)) {
gBS->FreePool (HandleBuffer);
return CurrentVolume;
}
}
gBS->FreePool (HandleBuffer);
return NULL;
}
EFI_DEVICE_PATH_PROTOCOL *
CreateFvFileDevicePath (
IN EFI_GUID *FileGuid
)
{
EFI_HANDLE VolumeHandle;
EFI_DEVICE_PATH_PROTOCOL *VolumeDevicePath;
MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FvFileNode;
VolumeHandle = GetFvFileVolume (FileGuid);
if (VolumeHandle == NULL) {
return NULL;
}
VolumeDevicePath = DevicePathFromHandle (VolumeHandle);
if (VolumeDevicePath == NULL) {
return NULL;
}
EfiInitializeFwVolDevicepathNode (&FvFileNode, FileGuid);
return AppendDevicePathNode (VolumeDevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &FvFileNode);
}

View File

@ -34,9 +34,11 @@
OpenFile.c
ReadFile.c
GptPartitionEntry.c
FirmwareFile.c
FsConnectQuirk.c
[Packages]
EfiPkg/EfiPkg.dec
OcSupportPkg/OcSupportPkg.dec
MdePkg/MdePkg.dec
@ -54,7 +56,9 @@
gEfiPartTypeSystemPartGuid ## CONSUMES
[Protocols]
gEfiFirmwareVolumeProtocolGuid
gEfiFirmwareVolume2ProtocolGuid
gEfiDevicePathProtocolGuid
gEfiBlockIo2ProtocolGuid
gEfiBlockIoProtocolGuid
gEfiDiskIo2ProtocolGuid

View File

@ -130,9 +130,14 @@ AIKPollKeyboardHandler (
&KeyData
);
if (!EFI_ERROR (Status)) {
(VOID) Counter;
DEBUG ((DEBUG_VERBOSE, "Read key with scan 0x%X and unicode 0x%X at %Lu\n",
KeyData.Key.ScanCode, KeyData.Key.UnicodeChar, Counter
DEBUG ((
DEBUG_VERBOSE,
"AIK: Key scan 0x%X uni 0x%X Shift 0x%X toggle 0x%X at %Lu\n",
KeyData.Key.ScanCode,
KeyData.Key.UnicodeChar,
KeyData.KeyState.KeyShiftState,
KeyData.KeyState.KeyToggleState,
Counter
));
AIKDataWriteEntry (&Keycode->Data, &KeyData);
AIKTargetWriteEntry (&Keycode->Target, &KeyData);

View File

@ -102,6 +102,7 @@
UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf
[Components]
OcSupportPkg/Application/BootKicker/BootKicker.inf
OcSupportPkg/Application/CleanNvram/CleanNvram.inf
OcSupportPkg/Application/PavpProvision/PavpProvision.inf
OcSupportPkg/Application/VerifyMsrE2/VerifyMsrE2.inf