提交 1c445a99 编写于 作者: V vit9696

OpenCore: Switch to application type for better FW compatibility

This resolves booting issues with Microsoft Surface firmwares
references acidanthera/bugtracker#1446
上级 dc1a0d8a
......@@ -17,7 +17,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Protocol/DevicePath.h>
#include <Protocol/LoadedImage.h>
#include <Protocol/OcBootstrap.h>
#include <Library/UefiLib.h>
#include <Library/BaseMemoryLib.h>
......@@ -35,9 +34,8 @@ STATIC
EFI_STATUS
LoadOpenCore (
IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem,
IN EFI_DEVICE_PATH_PROTOCOL *LoaderDevicePath,
OUT EFI_HANDLE *ImageHandle,
OUT EFI_DEVICE_PATH_PROTOCOL **ImagePath
IN EFI_HANDLE DeviceHandle,
IN EFI_DEVICE_PATH_PROTOCOL *LoaderDevicePath
)
{
EFI_STATUS Status;
......@@ -47,17 +45,16 @@ LoadOpenCore (
UINTN RootPathLength;
CHAR16 *LoaderPath;
UINT32 BufferSize;
EFI_DEVICE_PATH_PROTOCOL *ImagePath;
ASSERT (FileSystem != NULL);
ASSERT (ImageHandle != NULL);
ASSERT (ImagePath != NULL);
Buffer = NULL;
BufferSize = 0;
LoaderPath = OcCopyDevicePathFullName (LoaderDevicePath, NULL);
*ImagePath = NULL;
ImagePath = NULL;
//
// Try relative path: EFI\\XXX\\Bootstrap\\Bootstrap.efi -> EFI\\XXX\\OpenCore.efi
......@@ -76,8 +73,8 @@ LoadOpenCore (
DEBUG ((DEBUG_INFO, "BS: Startup path - %s (%p)\n", LoaderPath, Buffer));
if (Buffer != NULL) {
*ImagePath = FileDevicePath (NULL, LoaderPath);
if (*ImagePath == NULL) {
ImagePath = FileDevicePath (DeviceHandle, LoaderPath);
if (ImagePath == NULL) {
DEBUG ((DEBUG_INFO, "BS: File DP allocation failure, aborting\n"));
FreePool (Buffer);
Buffer = NULL;
......@@ -110,12 +107,12 @@ LoadOpenCore (
// Failure to allocate this one is not too critical, as we will still be able
// to choose it as a default path.
//
*ImagePath = FileDevicePath (NULL, OPEN_CORE_ROOT_PATH L"\\" OPEN_CORE_DRIVER_PATH);
ImagePath = FileDevicePath (DeviceHandle, OPEN_CORE_ROOT_PATH L"\\" OPEN_CORE_DRIVER_PATH);
}
}
if (Buffer == NULL) {
ASSERT (*ImagePath == NULL);
ASSERT (ImagePath == NULL);
DEBUG ((DEBUG_ERROR, "BS: Failed to locate valid OpenCore image - %p!\n", Buffer));
return EFI_NOT_FOUND;
}
......@@ -125,68 +122,16 @@ LoadOpenCore (
//
// Run OpenCore image
//
*ImageHandle = NULL;
Status = OcLoadAndRunImage (
NULL,
ImagePath,
Buffer,
BufferSize,
ImageHandle
NULL
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "BS: Failed to start OpenCore image - %r\n", Status));
FreePool (Buffer);
if (*ImagePath != NULL) {
FreePool (*ImagePath);
}
}
return Status;
}
STATIC
EFI_STATUS
StartOpenCore (
IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem,
IN EFI_HANDLE LoadHandle,
IN EFI_DEVICE_PATH_PROTOCOL *LoadPath OPTIONAL
)
{
EFI_STATUS Status;
OC_BOOTSTRAP_PROTOCOL *Bootstrap;
EFI_DEVICE_PATH_PROTOCOL *AbsPath;
Bootstrap = NULL;
Status = gBS->LocateProtocol (
&gOcBootstrapProtocolGuid,
NULL,
(VOID **) &Bootstrap
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "BS: Failed to locate bootstrap protocol - %r\n", Status));
return EFI_NOT_FOUND;
}
if (Bootstrap->Revision != OC_BOOTSTRAP_PROTOCOL_REVISION) {
DEBUG ((
DEBUG_WARN,
"BS: Unsupported bootstrap protocol %u vs %u\n",
Bootstrap->Revision,
OC_BOOTSTRAP_PROTOCOL_REVISION
));
return EFI_UNSUPPORTED;
}
//
// For NULL path it will provide the path for the partition itself.
//
AbsPath = AbsoluteDevicePath (LoadHandle, LoadPath);
Status = Bootstrap->ReRun (Bootstrap, FileSystem, AbsPath);
if (AbsPath != NULL) {
FreePool (AbsPath);
}
DEBUG ((DEBUG_ERROR, "BS: Failed to start OpenCore image - %r\n", Status));
FreePool (Buffer);
FreePool (ImagePath);
return Status;
}
......@@ -201,8 +146,6 @@ UefiMain (
EFI_STATUS Status;
EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem;
EFI_HANDLE OcImageHandle;
EFI_DEVICE_PATH_PROTOCOL *OcImagePath;
DEBUG ((DEBUG_INFO, "BS: Starting OpenCore...\n"));
......@@ -239,29 +182,8 @@ UefiMain (
return EFI_NOT_FOUND;
}
//
// Try to start previously loaded OpenCore
//
DEBUG ((DEBUG_INFO, "BS: Trying to start loaded OpenCore image...\n"));
Status = StartOpenCore (FileSystem, LoadedImage->DeviceHandle, NULL);
if (EFI_ERROR (Status) && Status != EFI_NOT_FOUND) {
return Status;
}
DEBUG ((DEBUG_INFO, "BS: Trying to load OpenCore image...\n"));
Status = LoadOpenCore (FileSystem, LoadedImage->FilePath, &OcImageHandle, &OcImagePath);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "BS: Failed to load OpenCore from disk - %r\n", Status));
return EFI_NOT_FOUND;
}
Status = StartOpenCore (FileSystem, LoadedImage->DeviceHandle, OcImagePath);
DEBUG ((DEBUG_WARN, "BS: Failed to start OpenCore image - %r\n", Status));
if (OcImagePath != NULL) {
FreePool (OcImagePath);
}
Status = LoadOpenCore (FileSystem, LoadedImage->DeviceHandle, LoadedImage->FilePath);
DEBUG ((DEBUG_WARN, "BS: Failed to load OpenCore from disk - %r\n", Status));
return Status;
}
......@@ -44,7 +44,6 @@
gEfiDevicePathProtocolGuid ## CONSUMES
gEfiLoadedImageProtocolGuid ## CONSUMES
gEfiSimpleFileSystemProtocolGuid ## CONSUMES
gOcBootstrapProtocolGuid ## CONSUMES
[LibraryClasses]
UefiApplicationEntryPoint
......
......@@ -174,101 +174,71 @@ OcMain (
STATIC
EFI_STATUS
EFIAPI
OcBootstrapRerun (
IN OC_BOOTSTRAP_PROTOCOL *This,
OcBootstrap (
IN EFI_HANDLE DeviceHandle,
IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem,
IN EFI_DEVICE_PATH_PROTOCOL *LoadPath OPTIONAL
IN EFI_DEVICE_PATH_PROTOCOL *LoadPath
)
{
EFI_STATUS Status;
EFI_DEVICE_PATH_PROTOCOL *RemainingPath;
UINTN StoragePathSize;
DEBUG ((DEBUG_INFO, "OC: ReRun executed!\n"));
++This->NestedCount;
if (This->NestedCount == 1) {
mOpenCoreVaultKey = OcGetVaultKey (This);
//
// Calculate root path (never freed).
//
RemainingPath = NULL;
if (LoadPath != NULL) {
ASSERT (mStorageRoot == NULL);
mStorageRoot = OcCopyDevicePathFullName (LoadPath, &RemainingPath);
//
// Skipping this or later failing to call UnicodeGetParentDirectory means
// we got valid path to the root of the partition. This happens when
// OpenCore.efi was loaded from e.g. firmware and then bootstrapped
// on a different partition.
//
if (mStorageRoot != NULL) {
if (UnicodeGetParentDirectory (mStorageRoot)) {
//
// This means we got valid path to ourselves.
//
DEBUG ((DEBUG_INFO, "OC: Got launch root path %s\n", mStorageRoot));
} else {
FreePool (mStorageRoot);
mStorageRoot = NULL;
}
}
}
mOpenCoreVaultKey = OcGetVaultKey ();
mStorageHandle = DeviceHandle;
if (mStorageRoot == NULL) {
mStorageRoot = OPEN_CORE_ROOT_PATH;
RemainingPath = NULL;
DEBUG ((DEBUG_INFO, "OC: Got default root path %s\n", mStorageRoot));
}
//
// Calculate root path (never freed).
//
RemainingPath = NULL;
mStorageRoot = OcCopyDevicePathFullName (LoadPath, &RemainingPath);
//
// Skipping this or later failing to call UnicodeGetParentDirectory means
// we got valid path to the root of the partition. This happens when
// OpenCore.efi was loaded from e.g. firmware and then bootstrapped
// on a different partition.
//
if (mStorageRoot == NULL) {
DEBUG ((DEBUG_ERROR, "OC: Failed to get launcher path\n"));
return EFI_UNSUPPORTED;
}
//
// Calculate storage path.
//
if (RemainingPath != NULL) {
StoragePathSize = (UINTN) RemainingPath - (UINTN) LoadPath;
mStoragePath = AllocatePool (StoragePathSize + END_DEVICE_PATH_LENGTH);
if (mStoragePath != NULL) {
CopyMem (mStoragePath, LoadPath, StoragePathSize);
SetDevicePathEndNode ((UINT8 *) mStoragePath + StoragePathSize);
}
} else {
mStoragePath = NULL;
}
ASSERT (RemainingPath != NULL);
RemainingPath = LoadPath;
gBS->LocateDevicePath (
&gEfiSimpleFileSystemProtocolGuid,
&RemainingPath,
&mStorageHandle
);
Status = OcStorageInitFromFs (
&mOpenCoreStorage,
FileSystem,
mStorageHandle,
mStoragePath,
mStorageRoot,
mOpenCoreVaultKey
);
if (!EFI_ERROR (Status)) {
OcMain (&mOpenCoreStorage, LoadPath);
OcStorageFree (&mOpenCoreStorage);
} else {
DEBUG ((DEBUG_ERROR, "OC: Failed to open root FS - %r!\n", Status));
if (Status == EFI_SECURITY_VIOLATION) {
CpuDeadLoop (); ///< Should not return.
}
}
} else {
DEBUG ((DEBUG_WARN, "OC: Nested ReRun is not supported\n"));
Status = EFI_ALREADY_STARTED;
if (!UnicodeGetParentDirectory (mStorageRoot)) {
DEBUG ((DEBUG_ERROR, "OC: Failed to get launcher root path\n"));
FreePool (mStorageRoot);
return EFI_UNSUPPORTED;
}
--This->NestedCount;
StoragePathSize = (UINTN) RemainingPath - (UINTN) LoadPath;
mStoragePath = AllocatePool (StoragePathSize + END_DEVICE_PATH_LENGTH);
if (mStoragePath == NULL) {
FreePool (mStorageRoot);
return EFI_OUT_OF_RESOURCES;
}
CopyMem (mStoragePath, LoadPath, StoragePathSize);
SetDevicePathEndNode ((UINT8 *) mStoragePath + StoragePathSize);
Status = OcStorageInitFromFs (
&mOpenCoreStorage,
FileSystem,
mStorageHandle,
mStoragePath,
mStorageRoot,
mOpenCoreVaultKey
);
if (!EFI_ERROR (Status)) {
OcMain (&mOpenCoreStorage, LoadPath);
OcStorageFree (&mOpenCoreStorage);
} else {
DEBUG ((DEBUG_ERROR, "OC: Failed to open root FS - %r!\n", Status));
if (Status == EFI_SECURITY_VIOLATION) {
CpuDeadLoop (); ///< Should not return.
}
}
return Status;
}
......@@ -287,9 +257,6 @@ STATIC
OC_BOOTSTRAP_PROTOCOL
mOpenCoreBootStrap = {
.Revision = OC_BOOTSTRAP_PROTOCOL_REVISION,
.NestedCount = 0,
.VaultKey = NULL,
.ReRun = OcBootstrapRerun,
.GetLoadHandle = OcGetLoadHandle,
};
......@@ -339,25 +306,13 @@ UefiMain (
return EFI_NOT_FOUND;
}
BootstrapHandle = NULL;
Status = gBS->InstallMultipleProtocolInterfaces (
&BootstrapHandle,
&gOcBootstrapProtocolGuid,
&mOpenCoreBootStrap,
NULL
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "OC: Failed to install bootstrap protocol - %r\n", Status));
return Status;
if (LoadedImage->FilePath == NULL) {
DEBUG ((DEBUG_ERROR, "OC: Missing boot path\n"));
return EFI_INVALID_PARAMETER;
}
DebugPrintDevicePath (DEBUG_INFO, "OC: Booter path", LoadedImage->FilePath);
if (LoadedImage->FilePath == NULL) {
DEBUG ((DEBUG_INFO, "OC: Booted from bootstrap\n"));
return EFI_SUCCESS;
}
//
// Obtain the file system device path
//
......@@ -365,22 +320,35 @@ UefiMain (
LoadedImage->DeviceHandle,
LoadedImage->FilePath
);
if (FileSystem == NULL) {
DEBUG ((DEBUG_ERROR, "OC: Failed to locate file system\n"));
return EFI_INVALID_PARAMETER;
}
AbsPath = AbsoluteDevicePath (LoadedImage->DeviceHandle, LoadedImage->FilePath);
if (AbsPath == NULL) {
DEBUG ((DEBUG_ERROR, "OC: Failed to allocate absolute path\n"));
return EFI_OUT_OF_RESOURCES;
}
//
// Return success in either case to let rerun work afterwards.
//
if (FileSystem != NULL) {
mOpenCoreBootStrap.ReRun (&mOpenCoreBootStrap, FileSystem, AbsPath);
DEBUG ((DEBUG_ERROR, "OC: Failed to boot\n"));
} else {
DEBUG ((DEBUG_ERROR, "OC: Failed to locate file system\n"));
}
DebugPrintDevicePath (DEBUG_INFO, "OC: Absolute booter path", LoadedImage->FilePath);
if (AbsPath != NULL) {
BootstrapHandle = NULL;
Status = gBS->InstallMultipleProtocolInterfaces (
&BootstrapHandle,
&gOcBootstrapProtocolGuid,
&mOpenCoreBootStrap,
NULL
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "OC: Failed to install bootstrap protocol - %r\n", Status));
FreePool (AbsPath);
return Status;
}
OcBootstrap (LoadedImage->DeviceHandle, FileSystem, AbsPath);
DEBUG ((DEBUG_ERROR, "OC: Failed to boot\n"));
CpuDeadLoop ();
return EFI_SUCCESS;
}
## @file
# General purpose test application.
# OpenCore primary application.
#
# Copyright (c) 2019, vit9696. All rights reserved.<BR>
#
......@@ -16,7 +16,7 @@
INF_VERSION = 0x00010005
BASE_NAME = OpenCore
FILE_GUID = 9E1F2D62-016E-4CE7-BF5B-6A47286AE984
MODULE_TYPE = UEFI_DRIVER
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 1.0
INF_VERSION = 0x00010005
EDK_RELEASE_VERSION = 0x00020000
......@@ -57,3 +57,4 @@
[LibraryClasses]
OcMainLib
UefiApplicationEntryPoint
......@@ -13,6 +13,7 @@ OpenCore Changelog
- Fixed crashes in OpenUsbKbDxe when handling unsupported devices
- Removed `HdaCodecDump` application in favor of `SysReport`
- Added `SetApfsTrimTimeout` to tune APFS trim command
- Changed `OpenCore.efi` to application to improve FW compatibility
#### v0.6.5
- Fixed installing OpenDuet on protected volumes
......
......@@ -81,7 +81,7 @@
**/
OC_RSA_PUBLIC_KEY *
OcGetVaultKey (
IN OC_BOOTSTRAP_PROTOCOL *Bootstrap
VOID
);
/**
......
......@@ -30,38 +30,13 @@
///
/// OC_BOOTSTRAP_PROTOCOL revision
///
#define OC_BOOTSTRAP_PROTOCOL_REVISION 6
#define OC_BOOTSTRAP_PROTOCOL_REVISION 7
///
/// Forward declaration of OC_BOOTSTRAP_PROTOCOL structure.
///
typedef struct OC_BOOTSTRAP_PROTOCOL_ OC_BOOTSTRAP_PROTOCOL;
/**
Restart OpenCore at specified file system.
@param[in] This This protocol.
@param[in] FileSystem File system to bootstrap in.
@param[in] LoadPath EFI device path to loaded image, optional.
* LoadPath may point to OpenCore.efi driver itself when the image was loaded
normally. In this case parent directory is used as a root directory.
* LoadPath may point to file system when the image was loaded before rerun.
In this case the LoadPath means the path we should bootstrap ourselves in.
* LoadPath may be NULL when the image was loaded from unknown location.
In this case some features like registering Bootstrap.efi cannot be used.
@retval EFI_ALREADY_STARTED if already started.
@retval Does not return on success.
**/
typedef
EFI_STATUS
(EFIAPI *OC_BOOTSTRAP_RERUN) (
IN OC_BOOTSTRAP_PROTOCOL *This,
IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem,
IN EFI_DEVICE_PATH_PROTOCOL *LoadPath OPTIONAL
);
/**
Obtain OpenCore load handle.
......@@ -81,9 +56,6 @@ EFI_HANDLE
///
struct OC_BOOTSTRAP_PROTOCOL_ {
UINTN Revision;
UINTN NestedCount;
OC_RSA_PUBLIC_KEY *VaultKey;
OC_BOOTSTRAP_RERUN ReRun;
OC_GET_LOAD_HANDLE GetLoadHandle;
};
......
......@@ -48,7 +48,6 @@
gEfiDevicePathProtocolGuid ## CONSUMES
gEfiLoadedImageProtocolGuid ## CONSUMES
gEfiSimpleFileSystemProtocolGuid ## CONSUMES
gOcBootstrapProtocolGuid ## CONSUMES
gOcInterfaceProtocolGuid ## SOMETIMES_CONSUMES
[LibraryClasses]
......@@ -90,6 +89,5 @@
PrintLib
SerialPortLib
UefiBootServicesTableLib
UefiDriverEntryPoint
UefiLib
UefiRuntimeServicesTableLib
......@@ -38,33 +38,27 @@ mOpenCoreVaultKey = {
OC_RSA_PUBLIC_KEY *
OcGetVaultKey (
IN OC_BOOTSTRAP_PROTOCOL *Bootstrap
VOID
)
{
UINT32 Index;
BOOLEAN AllZero;
//
// Return previously discovered key.
// TODO: Perhaps try to get the key from firmware too?
//
if (Bootstrap->VaultKey == NULL) {
//
// TODO: Perhaps try to get the key from firmware too?
//
AllZero = TRUE;
for (Index = 0; Index < sizeof (OC_RSA_PUBLIC_KEY); ++Index) {
if (((UINT8 *) &mOpenCoreVaultKey.VaultKey)[Index] != 0) {
AllZero = FALSE;
break;
}
AllZero = TRUE;
for (Index = 0; Index < sizeof (OC_RSA_PUBLIC_KEY); ++Index) {
if (((UINT8 *) &mOpenCoreVaultKey.VaultKey)[Index] != 0) {
AllZero = FALSE;
break;
}
}
if (!AllZero) {
Bootstrap->VaultKey = (OC_RSA_PUBLIC_KEY *) &mOpenCoreVaultKey.VaultKey;
}
if (!AllZero) {
return (OC_RSA_PUBLIC_KEY *) &mOpenCoreVaultKey.VaultKey;
}
return (OC_RSA_PUBLIC_KEY *) Bootstrap->VaultKey;
return NULL;
}
......@@ -161,6 +161,7 @@
OpenCorePkg/Application/KeyTester/KeyTester.inf
OpenCorePkg/Application/MmapDump/MmapDump.inf
OpenCorePkg/Application/OpenControl/OpenControl.inf
OpenCorePkg/Application/OpenCore/OpenCore.inf
OpenCorePkg/Application/PavpProvision/PavpProvision.inf
OpenCorePkg/Application/ResetSystem/ResetSystem.inf
OpenCorePkg/Application/RtcRw/RtcRw.inf
......@@ -234,7 +235,6 @@
OpenCorePkg/Library/OcPeCoffLib/OcPeCoffLib.inf
OpenCorePkg/Platform/CrScreenshotDxe/CrScreenshotDxe.inf
OpenCorePkg/Platform/OpenCanopy/OpenCanopy.inf
OpenCorePkg/Platform/OpenCore/OpenCore.inf
OpenCorePkg/Platform/OpenRuntime/OpenRuntime.inf
OpenCorePkg/Platform/OpenUsbKbDxe/UsbKbDxe.inf
OpenCorePkg/Staging/AudioDxe/AudioDxe.inf
......
......@@ -59,8 +59,6 @@
gEfiAbsolutePointerProtocolGuid
gEfiUserInterfaceThemeProtocolGuid
gAppleEventProtocolGuid
gOcBootstrapProtocolGuid
gOcInterfaceProtocolGuid
gEfiLoadedImageProtocolGuid
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册