From 324b5143ab017c02a050b15192d8080a4f5aa850 Mon Sep 17 00:00:00 2001 From: John Davis Date: Sun, 30 Jul 2023 21:03:41 -0500 Subject: [PATCH 01/55] OcFileLib: Add OcDiskGetDevicePath function --- Include/Acidanthera/Library/OcFileLib.h | 12 ++++ .../{GptPartitionEntry.c => DiskMisc.c} | 71 ++++++++++++------- Library/OcFileLib/OcFileLib.inf | 2 +- 3 files changed, 58 insertions(+), 27 deletions(-) rename Library/OcFileLib/{GptPartitionEntry.c => DiskMisc.c} (96%) diff --git a/Include/Acidanthera/Library/OcFileLib.h b/Include/Acidanthera/Library/OcFileLib.h index 8846d6eada6..8eb973dac2e 100644 --- a/Include/Acidanthera/Library/OcFileLib.h +++ b/Include/Acidanthera/Library/OcFileLib.h @@ -482,6 +482,18 @@ OcOpenFileByDevicePath ( IN UINT64 Attributes ); +/** + Retrieve the disk's Device Path from a partition's Device Path. + + @param[in] HdDevicePath The Device Path of the partition. + + @retval Device Path or NULL +**/ +EFI_DEVICE_PATH_PROTOCOL* +OcDiskGetDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *HdDevicePath + ); + /** Retrieve the disk's device handle from a partition's Device Path. diff --git a/Library/OcFileLib/GptPartitionEntry.c b/Library/OcFileLib/DiskMisc.c similarity index 96% rename from Library/OcFileLib/GptPartitionEntry.c rename to Library/OcFileLib/DiskMisc.c index b0f4b8a02a0..28bfcef35ef 100644 --- a/Library/OcFileLib/GptPartitionEntry.c +++ b/Library/OcFileLib/DiskMisc.c @@ -173,7 +173,6 @@ STATIC EFI_HANDLE InternalPartitionGetDiskHandle ( IN EFI_DEVICE_PATH_PROTOCOL *HdDevicePath, - IN UINTN HdNodeOffset, OUT BOOLEAN *HasBlockIo2 ) { @@ -181,27 +180,14 @@ InternalPartitionGetDiskHandle ( EFI_STATUS Status; - EFI_DEVICE_PATH_PROTOCOL *PrefixPath; + EFI_DEVICE_PATH_PROTOCOL *DiskPath; EFI_DEVICE_PATH_PROTOCOL *TempPath; ASSERT (HdDevicePath != NULL); - ASSERT (HdNodeOffset < GetDevicePathSize (HdDevicePath)); ASSERT (HasBlockIo2 != NULL); - PrefixPath = DuplicateDevicePath (HdDevicePath); - if (PrefixPath == NULL) { - DEBUG ((DEBUG_INFO, "OCPI: DP allocation error\n")); - return NULL; - } - - // - // Strip the HD node in order to retrieve the last node supporting Block I/O - // before it, which is going to be its disk. - // - TempPath = (EFI_DEVICE_PATH_PROTOCOL *)((UINTN)PrefixPath + HdNodeOffset); - SetDevicePathEndNode (TempPath); - - TempPath = PrefixPath; + DiskPath = OcDiskGetDevicePath (HdDevicePath); + TempPath = DiskPath; Status = gBS->LocateDevicePath ( &gEfiBlockIo2ProtocolGuid, &TempPath, @@ -210,7 +196,7 @@ InternalPartitionGetDiskHandle ( *HasBlockIo2 = !EFI_ERROR (Status); if (EFI_ERROR (Status)) { - TempPath = PrefixPath; + TempPath = DiskPath; Status = gBS->LocateDevicePath ( &gEfiBlockIoProtocolGuid, &TempPath, @@ -222,30 +208,32 @@ InternalPartitionGetDiskHandle ( DebugPrintDevicePath ( DEBUG_INFO, "OCPI: Failed to locate disk", - PrefixPath + TempPath ); DiskHandle = NULL; } - FreePool (PrefixPath); + FreePool (DiskPath); return DiskHandle; } /** - Retrieve the disk's device handle from a partition's Device Path. + Retrieve the disk's Device Path from a partition's Device Path. @param[in] HdDevicePath The Device Path of the partition. + @retval Device Path or NULL **/ -EFI_HANDLE -OcPartitionGetDiskHandle ( +EFI_DEVICE_PATH_PROTOCOL* +OcDiskGetDevicePath ( IN EFI_DEVICE_PATH_PROTOCOL *HdDevicePath ) { + EFI_DEVICE_PATH_PROTOCOL *PrefixPath; + EFI_DEVICE_PATH_PROTOCOL *TempPath; CONST HARDDRIVE_DEVICE_PATH *HdNode; - BOOLEAN Dummy; ASSERT (HdDevicePath != NULL); @@ -260,9 +248,41 @@ OcPartitionGetDiskHandle ( return NULL; } + PrefixPath = DuplicateDevicePath (HdDevicePath); + if (PrefixPath == NULL) { + DEBUG ((DEBUG_INFO, "OCPI: DP allocation error\n")); + return NULL; + } + + // + // Strip the HD node in order to retrieve the last node supporting Block I/O + // before it, which is going to be its disk. + // + TempPath = (EFI_DEVICE_PATH_PROTOCOL *)((UINTN)PrefixPath + ((UINTN)HdNode - (UINTN)HdDevicePath)); + SetDevicePathEndNode (TempPath); + + TempPath = PrefixPath; + + return TempPath; +} + +/** + Retrieve the disk's device handle from a partition's Device Path. + + @param[in] HdDevicePath The Device Path of the partition. + +**/ +EFI_HANDLE +OcPartitionGetDiskHandle ( + IN EFI_DEVICE_PATH_PROTOCOL *HdDevicePath + ) +{ + BOOLEAN Dummy; + + ASSERT (HdDevicePath != NULL); + return InternalPartitionGetDiskHandle ( HdDevicePath, - (UINTN)HdNode - (UINTN)HdDevicePath, &Dummy ); } @@ -591,7 +611,6 @@ OcGetGptPartitionEntry ( DiskHandle = InternalPartitionGetDiskHandle ( FsDevicePath, - (UINTN)HdNode - (UINTN)FsDevicePath, &HasBlockIo2 ); if (DiskHandle == NULL) { diff --git a/Library/OcFileLib/OcFileLib.inf b/Library/OcFileLib/OcFileLib.inf index e81d5a24c5f..d801c25b94f 100755 --- a/Library/OcFileLib/OcFileLib.inf +++ b/Library/OcFileLib/OcFileLib.inf @@ -33,7 +33,7 @@ LocateFileSystem.c OpenFile.c ReadFile.c - GptPartitionEntry.c + DiskMisc.c FirmwareFile.c FileMisc.c From 6a4a475446fdfb2aa7773184dc4d359d1ce299f6 Mon Sep 17 00:00:00 2001 From: John Davis Date: Sun, 30 Jul 2023 21:05:48 -0500 Subject: [PATCH 02/55] OcFileLib: Fix uncrustify on previous commit --- Include/Acidanthera/Library/OcFileLib.h | 2 +- Library/OcFileLib/DiskMisc.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Include/Acidanthera/Library/OcFileLib.h b/Include/Acidanthera/Library/OcFileLib.h index 8eb973dac2e..116a587eee3 100644 --- a/Include/Acidanthera/Library/OcFileLib.h +++ b/Include/Acidanthera/Library/OcFileLib.h @@ -489,7 +489,7 @@ OcOpenFileByDevicePath ( @retval Device Path or NULL **/ -EFI_DEVICE_PATH_PROTOCOL* +EFI_DEVICE_PATH_PROTOCOL * OcDiskGetDevicePath ( IN EFI_DEVICE_PATH_PROTOCOL *HdDevicePath ); diff --git a/Library/OcFileLib/DiskMisc.c b/Library/OcFileLib/DiskMisc.c index 28bfcef35ef..a2acd037499 100644 --- a/Library/OcFileLib/DiskMisc.c +++ b/Library/OcFileLib/DiskMisc.c @@ -226,7 +226,7 @@ InternalPartitionGetDiskHandle ( @retval Device Path or NULL **/ -EFI_DEVICE_PATH_PROTOCOL* +EFI_DEVICE_PATH_PROTOCOL * OcDiskGetDevicePath ( IN EFI_DEVICE_PATH_PROTOCOL *HdDevicePath ) @@ -277,7 +277,7 @@ OcPartitionGetDiskHandle ( IN EFI_DEVICE_PATH_PROTOCOL *HdDevicePath ) { - BOOLEAN Dummy; + BOOLEAN Dummy; ASSERT (HdDevicePath != NULL); From 50b0e45e6fa7b33bf5db07928a37f50f257d895d Mon Sep 17 00:00:00 2001 From: John Davis Date: Sun, 30 Jul 2023 21:25:19 -0500 Subject: [PATCH 03/55] OcBootManagementLib: Add initial functions for Mac legacy booting --- .../BootManagementInternal.h | 13 + .../OcBootManagementLib/LegacyBootSupport.c | 297 ++++++++++++++++++ .../OcBootManagementLib.inf | 1 + 3 files changed, 311 insertions(+) create mode 100644 Library/OcBootManagementLib/LegacyBootSupport.c diff --git a/Library/OcBootManagementLib/BootManagementInternal.h b/Library/OcBootManagementLib/BootManagementInternal.h index 1a3ac19387a..6b16061accb 100644 --- a/Library/OcBootManagementLib/BootManagementInternal.h +++ b/Library/OcBootManagementLib/BootManagementInternal.h @@ -124,6 +124,19 @@ typedef enum { BootEntryDisabled, } INTERNAL_ENTRY_VISIBILITY; +EFI_STATUS +InternalLoadAppleLegacyInterface ( + IN EFI_HANDLE ParentImageHandle, + IN EFI_DEVICE_PATH_PROTOCOL *HdDevicePath, + OUT EFI_HANDLE *ImageHandle + ); + +BOOLEAN +InternalDiskContainsBootcode ( + IN EFI_HANDLE DiskHandle, + IN BOOLEAN UseBlockIo2 + ); + EFI_STATUS InternalCheckScanPolicy ( IN EFI_HANDLE Handle, diff --git a/Library/OcBootManagementLib/LegacyBootSupport.c b/Library/OcBootManagementLib/LegacyBootSupport.c new file mode 100644 index 00000000000..45cf0ce3284 --- /dev/null +++ b/Library/OcBootManagementLib/LegacyBootSupport.c @@ -0,0 +1,297 @@ +/** @file + Copyright (C) 2023, Goldfish64. 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 "BootManagementInternal.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MBR_SECTOR_SIZE 512 + +// +// PIWG firmware media device path for Apple legacy interface. +// FwFile(2B0585EB-D8B8-49A9-8B8CE21B01AEF2B7) +// +static CONST UINT8 AppleLegacyInterfaceMediaDevicePathData[] = { + 0x04, 0x06, 0x14, 0x00, 0xEB, 0x85, 0x05, 0x2B, + 0xB8, 0xD8, 0xA9, 0x49, 0x8B, 0x8C, 0xE2, 0x1B, + 0x01, 0xAE, 0xF2, 0xB7, 0x7F, 0xFF, 0x04, 0x00, +}; +static CONST EFI_DEVICE_PATH_PROTOCOL *AppleLegacyInterfaceMediaDevicePathPath = (EFI_DEVICE_PATH_PROTOCOL *)AppleLegacyInterfaceMediaDevicePathData; + +#define MAX_APPLE_LEGACY_DEVICE_PATHS 16 + +STATIC +BOOLEAN +CheckLegacySignature ( + IN CONST CHAR8 *SignatureStr, + IN UINT8 *Buffer, + IN UINTN BufferSize + ) +{ + UINT32 Offset; + + Offset = 0; + + return FindPattern ((CONST UINT8 *)SignatureStr, NULL, AsciiStrLen (SignatureStr), Buffer, BufferSize, &Offset); +} + +STATIC +EFI_STATUS +ScanAppleLegacyInterfacePaths ( + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePaths, + IN UINTN MaxDevicePaths + ) +{ + EFI_STATUS Status; + UINTN NoHandles; + EFI_HANDLE *Handles; + UINTN HandleIndex; + UINTN PathCount; + UINTN PathIndex; + BOOLEAN DevicePathExists; + + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + MaxDevicePaths--; + PathCount = 0; + + // + // Get all LoadedImage protocol handles. + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiLoadedImageProtocolGuid, + NULL, + &NoHandles, + &Handles + ); + if (EFI_ERROR (Status)) { + return Status; + } + + for (HandleIndex = 0; HandleIndex < NoHandles && PathCount < MaxDevicePaths; HandleIndex++) { + Status = gBS->HandleProtocol ( + Handles[HandleIndex], + &gEfiLoadedImageProtocolGuid, + (VOID **)&LoadedImage + ); + if (EFI_ERROR (Status)) { + continue; + } + + Status = gBS->HandleProtocol ( + LoadedImage->DeviceHandle, + &gEfiDevicePathProtocolGuid, + (VOID **)&DevicePath + ); + if (EFI_ERROR (Status)) { + continue; + } + + // + // Legacy boot interface will be behind a memory range node. + // + if ( (DevicePathType (DevicePath) != HARDWARE_DEVICE_PATH) + || (DevicePathSubType (DevicePath) != HW_MEMMAP_DP)) + { + continue; + } + + // + // Ensure we don't add a duplicate path. + // + DevicePathExists = FALSE; + for (PathIndex = 0; PathIndex < PathCount; PathIndex++) { + if (DevicePathNodeLength (DevicePath) != DevicePathNodeLength (DevicePaths[PathIndex])) { + continue; + } + + if (CompareMem (DevicePath, DevicePaths[PathIndex], DevicePathNodeLength (DevicePath))) { + DevicePathExists = TRUE; + break; + } + } + + if (DevicePathExists) { + continue; + } + + DevicePaths[PathCount++] = AppendDevicePath (DevicePath, AppleLegacyInterfaceMediaDevicePathPath); + } + + FreePool (Handles); + + DevicePaths[PathCount] = NULL; + return EFI_SUCCESS; +} + +EFI_STATUS +InternalLoadAppleLegacyInterface ( + IN EFI_HANDLE ParentImageHandle, + IN EFI_DEVICE_PATH_PROTOCOL *HdDevicePath, + OUT EFI_HANDLE *ImageHandle + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *WholeDiskPath; + EFI_DEVICE_PATH_PROTOCOL **LegacyDevicePaths; + CHAR16 *UnicodeDevicePath; + UINTN Index; + + // + // Get device path to disk to be booted. + // TODO: Handle CD booting, device path is not required in that case. + // + WholeDiskPath = OcDiskGetDevicePath (HdDevicePath); + if (WholeDiskPath == NULL) { + return EFI_INVALID_PARAMETER; + } + + DebugPrintDevicePath (DEBUG_INFO, "OCB: Legacy disk device path", WholeDiskPath); + + // TODO: Mark target partition as active on pure MBR and hybrid GPT disks. + // Macs only boot the active partition. + + // + // Set BootCampHD variable pointing to target disk. + // + Status = gRT->SetVariable ( + APPLE_BOOT_CAMP_HD_VARIABLE_NAME, + &gAppleBootVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + GetDevicePathSize (WholeDiskPath), + WholeDiskPath + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Get list of possible locations for Apple legacy interface and attempt to load. + // + LegacyDevicePaths = AllocateZeroPool (sizeof (*LegacyDevicePaths) * MAX_APPLE_LEGACY_DEVICE_PATHS); + if (LegacyDevicePaths == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = ScanAppleLegacyInterfacePaths (LegacyDevicePaths, MAX_APPLE_LEGACY_DEVICE_PATHS); + if (!EFI_ERROR (Status)) { + for (Index = 0; LegacyDevicePaths[Index] != NULL; Index++) { + Status = gBS->LoadImage ( + FALSE, + ParentImageHandle, + LegacyDevicePaths[Index], + NULL, + 0, + ImageHandle + ); + if (Status != EFI_NOT_FOUND) { + DEBUG_CODE_BEGIN (); + + UnicodeDevicePath = ConvertDevicePathToText (LegacyDevicePaths[Index], FALSE, FALSE); + DEBUG (( + DEBUG_INFO, + "OCB: Loaded Apple legacy interface at dp %s - %r\n", + UnicodeDevicePath != NULL ? UnicodeDevicePath : L"", + Status + )); + if (UnicodeDevicePath != NULL) { + FreePool (UnicodeDevicePath); + } + + DEBUG_CODE_END (); + + break; + } + } + } + + FreePool (LegacyDevicePaths); + + return Status; +} + +BOOLEAN +InternalDiskContainsBootcode ( + IN EFI_HANDLE DiskHandle, + IN BOOLEAN UseBlockIo2 + ) +{ + EFI_STATUS Status; + UINT8 *Buffer; + UINTN BufferSize; + BOOLEAN BootcodeResult; + + OC_DISK_CONTEXT DiskContext; + + ASSERT (DiskHandle != NULL); + + Status = OcDiskInitializeContext (&DiskContext, DiskHandle, UseBlockIo2); + if (EFI_ERROR (Status)) { + return FALSE; + } + + // + // Retrieve the first sector of the disk. + // + BufferSize = ALIGN_VALUE (MBR_SECTOR_SIZE, DiskContext.BlockSize); + Buffer = AllocatePool (BufferSize); + if (Buffer == NULL) { + DEBUG ((DEBUG_INFO, "OCBP: Buffer allocation error\n")); + return FALSE; + } + + Status = OcDiskRead ( + &DiskContext, + 0, + BufferSize, + Buffer + ); + + if (EFI_ERROR (Status)) { + FreePool (Buffer); + return FALSE; + } + + // + // Validate sector contents and check for known signatures + // indicating the partition is bootable. + // + BootcodeResult = FALSE; + if (CheckLegacySignature ("BOOTMGR", Buffer, BufferSize)) { + DEBUG ((DEBUG_INFO, "OCB: Found Windows BOOTMGR\n")); + BootcodeResult = TRUE; + } else if (CheckLegacySignature ("NTLDR", Buffer, BufferSize)) { + DEBUG ((DEBUG_INFO, "OCB: Found Windows NTLDR\n")); + BootcodeResult = TRUE; + } + + FreePool (Buffer); + + return BootcodeResult; +} diff --git a/Library/OcBootManagementLib/OcBootManagementLib.inf b/Library/OcBootManagementLib/OcBootManagementLib.inf index efb5743b9a3..02b44687c72 100644 --- a/Library/OcBootManagementLib/OcBootManagementLib.inf +++ b/Library/OcBootManagementLib/OcBootManagementLib.inf @@ -45,6 +45,7 @@ DmgBootSupport.c HotKeySupport.c ImageLoader.c + LegacyBootSupport.c PolicyManagement.c OcBootManagementLib.c From 86717d44c8c716dddd4e9722a9f78f4140062d5b Mon Sep 17 00:00:00 2001 From: John Davis Date: Sun, 30 Jul 2023 21:44:08 -0500 Subject: [PATCH 04/55] OcBootManagementLib: Fix Windows build error --- Library/OcBootManagementLib/LegacyBootSupport.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Library/OcBootManagementLib/LegacyBootSupport.c b/Library/OcBootManagementLib/LegacyBootSupport.c index 45cf0ce3284..3e9f9cdddac 100644 --- a/Library/OcBootManagementLib/LegacyBootSupport.c +++ b/Library/OcBootManagementLib/LegacyBootSupport.c @@ -49,7 +49,7 @@ BOOLEAN CheckLegacySignature ( IN CONST CHAR8 *SignatureStr, IN UINT8 *Buffer, - IN UINTN BufferSize + IN UINT32 BufferSize ) { UINT32 Offset; @@ -244,7 +244,7 @@ InternalDiskContainsBootcode ( { EFI_STATUS Status; UINT8 *Buffer; - UINTN BufferSize; + UINT32 BufferSize; BOOLEAN BootcodeResult; OC_DISK_CONTEXT DiskContext; From 5a5112059c092254924fd2c2a7f4c00644b15d4a Mon Sep 17 00:00:00 2001 From: John Davis Date: Sun, 30 Jul 2023 22:06:33 -0500 Subject: [PATCH 05/55] OcBootManagementLib: Fix Windows build error --- Library/OcBootManagementLib/LegacyBootSupport.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Library/OcBootManagementLib/LegacyBootSupport.c b/Library/OcBootManagementLib/LegacyBootSupport.c index 3e9f9cdddac..79360e37a38 100644 --- a/Library/OcBootManagementLib/LegacyBootSupport.c +++ b/Library/OcBootManagementLib/LegacyBootSupport.c @@ -56,7 +56,7 @@ CheckLegacySignature ( Offset = 0; - return FindPattern ((CONST UINT8 *)SignatureStr, NULL, AsciiStrLen (SignatureStr), Buffer, BufferSize, &Offset); + return FindPattern ((CONST UINT8 *)SignatureStr, NULL, (CONST UINT32) AsciiStrLen (SignatureStr), Buffer, BufferSize, &Offset); } STATIC From 9893ce7ad0f392bbe821a11138ec2032c8ca83d9 Mon Sep 17 00:00:00 2001 From: John Davis Date: Mon, 31 Jul 2023 18:33:39 -0500 Subject: [PATCH 06/55] OcBootManagementLib: Add legacy boot entry detection --- .../Acidanthera/Library/OcBootManagementLib.h | 30 +++ Library/OcBootManagementLib/BootEntryInfo.c | 26 +++ .../OcBootManagementLib/BootEntryManagement.c | 200 +++++++++++++++--- .../BootManagementInternal.h | 25 ++- .../OcBootManagementLib/DefaultEntryChoice.c | 24 ++- .../OcBootManagementLib/LegacyBootSupport.c | 34 ++- .../OcBootManagementLib/PolicyManagement.c | 3 +- Library/OcMainLib/OpenCoreMisc.c | 8 + 8 files changed, 288 insertions(+), 62 deletions(-) diff --git a/Include/Acidanthera/Library/OcBootManagementLib.h b/Include/Acidanthera/Library/OcBootManagementLib.h index 6c91c350102..934dd6095fe 100644 --- a/Include/Acidanthera/Library/OcBootManagementLib.h +++ b/Include/Acidanthera/Library/OcBootManagementLib.h @@ -153,6 +153,23 @@ typedef UINT32 OC_BOOT_ENTRY_TYPE; #define OC_BOOT_EXTERNAL_TOOL BIT7 #define OC_BOOT_SYSTEM BIT8 +/** + Legacy system boot type. +**/ +typedef enum OC_LEGACY_BOOT_TYPE_ { + OcLegacyBootTypeNone, + OcLegacyBootTypeApple +} OC_LEGACY_BOOT_TYPE; + +/** + Legacy operating system type. +**/ +typedef enum OC_LEGACY_OS_TYPE_ { + OcLegacyOsTypeNone, + OcLegacyOsTypeWindowsNtldr, + OcLegacyOsTypeWindowsBootmgr +} OC_LEGACY_OS_TYPE; + /** Picker mode. **/ @@ -262,6 +279,11 @@ typedef struct OC_BOOT_ENTRY_ { // BOOLEAN IsAppleInstaller; // + // Describes type of legacy OS to be booted. + // Set when entry is to be booted through legacy interface. + // + OC_LEGACY_OS_TYPE LegacyOsType; + // // Should make this option default boot option. // BOOLEAN SetDefault; @@ -348,6 +370,10 @@ struct OC_BOOT_FILESYSTEM_ { // BOOLEAN LoaderFs; // + // Legacy bootsector type. + // + OC_LEGACY_OS_TYPE LegacyOsType; + // // Contains recovery on the filesystem. // BOOLEAN HasSelfRecovery; @@ -949,6 +975,10 @@ struct OC_PICKER_CONTEXT_ { // CONST CHAR8 *InstanceIdentifier; // + // Legacy boot method type. + // + OC_LEGACY_BOOT_TYPE LegacyBootType; + // // Enable polling boot arguments. // BOOLEAN PollAppleHotKeys; diff --git a/Library/OcBootManagementLib/BootEntryInfo.c b/Library/OcBootManagementLib/BootEntryInfo.c index b150ea334bb..4171e8d94a5 100644 --- a/Library/OcBootManagementLib/BootEntryInfo.c +++ b/Library/OcBootManagementLib/BootEntryInfo.c @@ -890,3 +890,29 @@ InternalDescribeBootEntry ( return EFI_SUCCESS; } + +EFI_STATUS +InternalDescribeLegacyBootEntry ( + IN OC_BOOT_CONTEXT *BootContext, + IN OC_LEGACY_OS_TYPE LegacyOsType, + IN OUT OC_BOOT_ENTRY *BootEntry + ) +{ + ASSERT (LegacyOsType != OcLegacyOsTypeNone); + + // + // Name is based on previously detected boot sector type. + // + switch (LegacyOsType) { + case OcLegacyOsTypeWindowsBootmgr: + case OcLegacyOsTypeWindowsNtldr: + BootEntry->Type = OC_BOOT_WINDOWS; + BootEntry->Name = AllocateCopyPool (sizeof (L"Windows (legacy)"), L"Windows (legacy)"); + break; + + default: + break; + } + + return EFI_SUCCESS; +} diff --git a/Library/OcBootManagementLib/BootEntryManagement.c b/Library/OcBootManagementLib/BootEntryManagement.c index 5ccdb05dc0a..24eddbeb0a5 100644 --- a/Library/OcBootManagementLib/BootEntryManagement.c +++ b/Library/OcBootManagementLib/BootEntryManagement.c @@ -1595,6 +1595,92 @@ AddBootEntryFromBootOption ( return Status; } +/** + Create bootable entries from legacy boot partitons. + + @param[in,out] BootContext Context of filesystems. + @param[in,out] FileSystem Filesystem to scan for recovery. + + @retval EFI_SUCCESS on success. +**/ +STATIC +EFI_STATUS +AddBootEntryFromLegacyPartition ( + IN OUT OC_BOOT_CONTEXT *BootContext, + IN OUT OC_BOOT_FILESYSTEM *FileSystem + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + OC_BOOT_ENTRY *BootEntry; + + // + // Only support legacy filesystems. + // + if (FileSystem->LegacyOsType == OcLegacyOsTypeNone) { + return EFI_UNSUPPORTED; + } + + Status = gBS->HandleProtocol ( + FileSystem->Handle, + &gEfiDevicePathProtocolGuid, + (VOID **)&DevicePath + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + DebugPrintDevicePath (DEBUG_INFO, "OCB: Adding legacy entry for disk", DevicePath); + + // + // Allocate, initialise, and describe boot entry. + // + BootEntry = AllocateZeroPool (sizeof (*BootEntry)); + if (BootEntry == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + BootEntry->IsExternal = FileSystem->External; + BootEntry->DevicePath = DevicePath; + BootEntry->LegacyOsType = FileSystem->LegacyOsType; + BootEntry->LaunchInText = TRUE; + + // + // Load options are set based on type of disk. + // Internal disk = "HD" + // External disk = "USB" + // Optical disk = "CD" + // + // TODO: Support optical media. + // + if (BootEntry->IsExternal) { + BootEntry->LoadOptionsSize = L_STR_SIZE ("USB"); + BootEntry->LoadOptions = AllocateCopyPool (L_STR_SIZE ("USB"), "USB"); + } else { + BootEntry->LoadOptionsSize = L_STR_SIZE ("HD"); + BootEntry->LoadOptions = AllocateCopyPool (L_STR_SIZE ("HD"), "HD"); + } + + if (BootEntry->LoadOptions == NULL) { + FreePool (BootEntry); + return EFI_OUT_OF_RESOURCES; + } + + Status = InternalDescribeLegacyBootEntry (BootContext, FileSystem->LegacyOsType, BootEntry); + if (EFI_ERROR (Status)) { + FreePool (BootEntry); + return Status; + } + + RegisterBootOption ( + BootContext, + FileSystem, + BootEntry + ); + + return EFI_SUCCESS; +} + /** Allocate a new filesystem entry in boot entries in case it can be used according to current ScanPolicy. @@ -1608,9 +1694,10 @@ AddBootEntryFromBootOption ( STATIC EFI_STATUS AddFileSystemEntry ( - IN OUT OC_BOOT_CONTEXT *BootContext, - IN EFI_HANDLE FileSystemHandle, - OUT OC_BOOT_FILESYSTEM **FileSystemEntry OPTIONAL + IN OUT OC_BOOT_CONTEXT *BootContext, + IN EFI_HANDLE FileSystemHandle, + IN OC_LEGACY_OS_TYPE LegacyOsType, + OUT OC_BOOT_FILESYSTEM **FileSystemEntry OPTIONAL ) { EFI_STATUS Status; @@ -1624,6 +1711,7 @@ AddFileSystemEntry ( Status = InternalCheckScanPolicy ( FileSystemHandle, BootContext->PickerContext->ScanPolicy, + LegacyOsType != OcLegacyOsTypeNone, &IsExternal ); @@ -1644,10 +1732,11 @@ AddFileSystemEntry ( DEBUG (( DEBUG_INFO, - "OCB: Adding fs %p (E:%d|L:%d|P:%r) - %s\n", + "OCB: Adding fs %p (E:%d|L:%d|B:%d|P:%r) - %s\n", FileSystemHandle, IsExternal, LoaderFs, + LegacyOsType, Status, OC_HUMAN_STRING (TextDevicePath) )); @@ -1672,6 +1761,7 @@ AddFileSystemEntry ( Entry->RecoveryFs = NULL; Entry->External = IsExternal; Entry->LoaderFs = LoaderFs; + Entry->LegacyOsType = LegacyOsType; Entry->HasSelfRecovery = FALSE; InsertTailList (&BootContext->FileSystems, &Entry->Link); ++BootContext->FileSystemCount; @@ -1815,7 +1905,7 @@ InternalFileSystemForHandle ( return NULL; } - Status = AddFileSystemEntry (BootContext, FileSystemHandle, &FileSystem); + Status = AddFileSystemEntry (BootContext, FileSystemHandle, FALSE, &FileSystem); if (!EFI_ERROR (Status)) { return FileSystem; } @@ -1830,11 +1920,12 @@ BuildFileSystemList ( IN BOOLEAN Empty ) { - OC_BOOT_CONTEXT *BootContext; - EFI_STATUS Status; - UINTN NoHandles; - EFI_HANDLE *Handles; - UINTN Index; + OC_BOOT_CONTEXT *BootContext; + EFI_STATUS Status; + OC_LEGACY_OS_TYPE LegacyOsType; + UINTN NoHandles; + EFI_HANDLE *Handles; + UINTN Index; BootContext = AllocatePool (sizeof (*BootContext)); if (BootContext == NULL) { @@ -1857,6 +1948,9 @@ BuildFileSystemList ( return BootContext; } + // + // Add readable filesystems. + // Status = gBS->LocateHandleBuffer ( ByProtocol, &gEfiSimpleFileSystemProtocolGuid, @@ -1872,11 +1966,43 @@ BuildFileSystemList ( AddFileSystemEntry ( BootContext, Handles[Index], + FALSE, NULL ); } FreePool (Handles); + + // + // Add legacy partitions with valid boot sectors if on a supported legacy platform. + // + if (Context->LegacyBootType != OcLegacyBootTypeNone) { + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiBlockIoProtocolGuid, + NULL, + &NoHandles, + &Handles + ); + if (EFI_ERROR (Status)) { + return BootContext; + } + + for (Index = 0; Index < NoHandles; ++Index) { + LegacyOsType = InternalGetDiskLegacyOsType (Handles[Index], FALSE); + if (LegacyOsType == OcLegacyOsTypeNone) { + continue; + } + + AddFileSystemEntry ( + BootContext, + Handles[Index], + LegacyOsType, + NULL + ); + } + } + return BootContext; } @@ -2079,28 +2205,40 @@ OcScanForBootEntries ( { FileSystem = BASE_CR (Link, OC_BOOT_FILESYSTEM, Link); - PartitionEntry = OcGetGptPartitionEntry (FileSystem->Handle); - IsDefaultEntryProtocolPartition = ( - (DefaultEntryId != NULL) - && CompareGuid ( - &DefaultEntryPartuuid, - (PartitionEntry == NULL) ? &gEfiPartTypeUnusedGuid : &PartitionEntry->UniquePartitionGUID - ) - ); + if (FileSystem->LegacyOsType != OcLegacyOsTypeNone) { + // + // Process legacy boot partition. + // + if (IsListEmpty (&FileSystem->BootEntries)) { + AddBootEntryFromLegacyPartition ( + BootContext, + FileSystem + ); + } + } else { + PartitionEntry = OcGetGptPartitionEntry (FileSystem->Handle); + IsDefaultEntryProtocolPartition = ( + (DefaultEntryId != NULL) + && CompareGuid ( + &DefaultEntryPartuuid, + (PartitionEntry == NULL) ? &gEfiPartTypeUnusedGuid : &PartitionEntry->UniquePartitionGUID + ) + ); - // - // No entries, or only entry pre-created from boot entry protocol, - // so process this directory with Apple Bless. - // - if (IsDefaultEntryProtocolPartition || IsListEmpty (&FileSystem->BootEntries)) { - AddBootEntryFromBless ( - BootContext, - FileSystem, - gAppleBootPolicyPredefinedPaths, - gAppleBootPolicyNumPredefinedPaths, - FALSE, - FALSE - ); + // + // No entries, or only entry pre-created from boot entry protocol, + // so process this directory with Apple Bless. + // + if (IsDefaultEntryProtocolPartition || IsListEmpty (&FileSystem->BootEntries)) { + AddBootEntryFromBless ( + BootContext, + FileSystem, + gAppleBootPolicyPredefinedPaths, + gAppleBootPolicyNumPredefinedPaths, + FALSE, + FALSE + ); + } } // diff --git a/Library/OcBootManagementLib/BootManagementInternal.h b/Library/OcBootManagementLib/BootManagementInternal.h index 6b16061accb..e40f34b39d2 100644 --- a/Library/OcBootManagementLib/BootManagementInternal.h +++ b/Library/OcBootManagementLib/BootManagementInternal.h @@ -131,16 +131,17 @@ InternalLoadAppleLegacyInterface ( OUT EFI_HANDLE *ImageHandle ); -BOOLEAN -InternalDiskContainsBootcode ( - IN EFI_HANDLE DiskHandle, - IN BOOLEAN UseBlockIo2 +OC_LEGACY_OS_TYPE +InternalGetDiskLegacyOsType ( + IN EFI_HANDLE DiskHandle, + IN BOOLEAN UseBlockIo2 ); EFI_STATUS InternalCheckScanPolicy ( IN EFI_HANDLE Handle, IN UINT32 Policy, + IN BOOLEAN Legacy, OUT BOOLEAN *External OPTIONAL ); @@ -246,6 +247,22 @@ InternalDescribeBootEntry ( IN OUT OC_BOOT_ENTRY *BootEntry ); +/** + Describe legacy boot entry contents by setting fields other than DevicePath. + + @param[in] BootContext Boot context. + @param[in] LegacyOsType Legacy OS type. + @param[in,out] BootEntry Located boot entry. + + @retval EFI_SUCCESS The entry point is described successfully. +**/ +EFI_STATUS +InternalDescribeLegacyBootEntry ( + IN OC_BOOT_CONTEXT *BootContext, + IN OC_LEGACY_OS_TYPE LegacyOsType, + IN OUT OC_BOOT_ENTRY *BootEntry + ); + BOOLEAN InternalIsAppleLegacyLoadApp ( IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath diff --git a/Library/OcBootManagementLib/DefaultEntryChoice.c b/Library/OcBootManagementLib/DefaultEntryChoice.c index 5c118fc072f..cfcb851cc72 100644 --- a/Library/OcBootManagementLib/DefaultEntryChoice.c +++ b/Library/OcBootManagementLib/DefaultEntryChoice.c @@ -1577,14 +1577,22 @@ InternalLoadBootEntry ( DEBUG_CODE_END (); - Status = gBS->LoadImage ( - FALSE, - ParentHandle, - DevicePath, - EntryData, - EntryDataSize, - EntryHandle - ); + if (BootEntry->LegacyOsType != OcLegacyOsTypeNone) { + Status = InternalLoadAppleLegacyInterface ( + ParentHandle, + DevicePath, + EntryHandle + ); + } else { + Status = gBS->LoadImage ( + FALSE, + ParentHandle, + DevicePath, + EntryData, + EntryDataSize, + EntryHandle + ); + } if (EntryData != NULL) { FreePool (EntryData); diff --git a/Library/OcBootManagementLib/LegacyBootSupport.c b/Library/OcBootManagementLib/LegacyBootSupport.c index 79360e37a38..9a81fe3096f 100644 --- a/Library/OcBootManagementLib/LegacyBootSupport.c +++ b/Library/OcBootManagementLib/LegacyBootSupport.c @@ -56,7 +56,7 @@ CheckLegacySignature ( Offset = 0; - return FindPattern ((CONST UINT8 *)SignatureStr, NULL, (CONST UINT32) AsciiStrLen (SignatureStr), Buffer, BufferSize, &Offset); + return FindPattern ((CONST UINT8 *)SignatureStr, NULL, (CONST UINT32)AsciiStrLen (SignatureStr), Buffer, BufferSize, &Offset); } STATIC @@ -236,16 +236,16 @@ InternalLoadAppleLegacyInterface ( return Status; } -BOOLEAN -InternalDiskContainsBootcode ( - IN EFI_HANDLE DiskHandle, - IN BOOLEAN UseBlockIo2 +OC_LEGACY_OS_TYPE +InternalGetDiskLegacyOsType ( + IN EFI_HANDLE DiskHandle, + IN BOOLEAN UseBlockIo2 ) { - EFI_STATUS Status; - UINT8 *Buffer; - UINT32 BufferSize; - BOOLEAN BootcodeResult; + EFI_STATUS Status; + UINT8 *Buffer; + UINT32 BufferSize; + OC_LEGACY_OS_TYPE LegacyOsType; OC_DISK_CONTEXT DiskContext; @@ -253,7 +253,7 @@ InternalDiskContainsBootcode ( Status = OcDiskInitializeContext (&DiskContext, DiskHandle, UseBlockIo2); if (EFI_ERROR (Status)) { - return FALSE; + return OcLegacyOsTypeNone; } // @@ -263,7 +263,7 @@ InternalDiskContainsBootcode ( Buffer = AllocatePool (BufferSize); if (Buffer == NULL) { DEBUG ((DEBUG_INFO, "OCBP: Buffer allocation error\n")); - return FALSE; + return OcLegacyOsTypeNone; } Status = OcDiskRead ( @@ -275,23 +275,21 @@ InternalDiskContainsBootcode ( if (EFI_ERROR (Status)) { FreePool (Buffer); - return FALSE; + return OcLegacyOsTypeNone; } // // Validate sector contents and check for known signatures // indicating the partition is bootable. // - BootcodeResult = FALSE; + LegacyOsType = OcLegacyOsTypeNone; if (CheckLegacySignature ("BOOTMGR", Buffer, BufferSize)) { - DEBUG ((DEBUG_INFO, "OCB: Found Windows BOOTMGR\n")); - BootcodeResult = TRUE; + LegacyOsType = OcLegacyOsTypeWindowsBootmgr; } else if (CheckLegacySignature ("NTLDR", Buffer, BufferSize)) { - DEBUG ((DEBUG_INFO, "OCB: Found Windows NTLDR\n")); - BootcodeResult = TRUE; + LegacyOsType = OcLegacyOsTypeWindowsNtldr; } FreePool (Buffer); - return BootcodeResult; + return LegacyOsType; } diff --git a/Library/OcBootManagementLib/PolicyManagement.c b/Library/OcBootManagementLib/PolicyManagement.c index f1b52a05910..5fe66fea4ca 100644 --- a/Library/OcBootManagementLib/PolicyManagement.c +++ b/Library/OcBootManagementLib/PolicyManagement.c @@ -286,6 +286,7 @@ EFI_STATUS InternalCheckScanPolicy ( IN EFI_HANDLE Handle, IN UINT32 Policy, + IN BOOLEAN Legacy, OUT BOOLEAN *External OPTIONAL ) { @@ -301,7 +302,7 @@ InternalCheckScanPolicy ( return EFI_SECURITY_VIOLATION; } - if ((Policy & OC_SCAN_FILE_SYSTEM_LOCK) != 0) { + if (!Legacy && ((Policy & OC_SCAN_FILE_SYSTEM_LOCK) != 0)) { FileSystemPolicy = OcGetFileSystemPolicyType (Handle); if ((Policy & FileSystemPolicy) == 0) { diff --git a/Library/OcMainLib/OpenCoreMisc.c b/Library/OcMainLib/OpenCoreMisc.c index 29fb6229e67..b2277b58385 100644 --- a/Library/OcMainLib/OpenCoreMisc.c +++ b/Library/OcMainLib/OpenCoreMisc.c @@ -939,6 +939,14 @@ OcMiscBoot ( Context->InstanceIdentifier = AsciiInstanceIdentifier; Context->BlacklistAppleUpdate = Config->Misc.Security.BlacklistAppleUpdate; + // + // Apple legacy boot interface is only available on Apple platforms. + // + Context->LegacyBootType = OcLegacyBootTypeNone; + if (OcStriCmp (L"Apple", gST->FirmwareVendor) == 0) { + Context->LegacyBootType = OcLegacyBootTypeApple; + } + if ((Config->Misc.Security.ExposeSensitiveData & OCS_EXPOSE_VERSION_UI) != 0) { Context->TitleSuffix = OcMiscGetVersionString (); } From 8cd00866253b90b4d6260d34e4d618f4986bf45d Mon Sep 17 00:00:00 2001 From: John Davis Date: Tue, 1 Aug 2023 20:39:34 -0500 Subject: [PATCH 07/55] OcBootManagementLib: Fix incorrect device path allocation --- Library/OcBootManagementLib/BootEntryManagement.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Library/OcBootManagementLib/BootEntryManagement.c b/Library/OcBootManagementLib/BootEntryManagement.c index 24eddbeb0a5..999cc037d1c 100644 --- a/Library/OcBootManagementLib/BootEntryManagement.c +++ b/Library/OcBootManagementLib/BootEntryManagement.c @@ -1640,8 +1640,13 @@ AddBootEntryFromLegacyPartition ( return EFI_OUT_OF_RESOURCES; } + BootEntry->DevicePath = DuplicateDevicePath (DevicePath); + if (BootEntry->DevicePath == NULL) { + FreePool (BootEntry); + return EFI_OUT_OF_RESOURCES; + } + BootEntry->IsExternal = FileSystem->External; - BootEntry->DevicePath = DevicePath; BootEntry->LegacyOsType = FileSystem->LegacyOsType; BootEntry->LaunchInText = TRUE; @@ -2001,6 +2006,8 @@ BuildFileSystemList ( NULL ); } + + FreePool (Handles); } return BootContext; From 44fb3acb3d8b8967ab28eb133e66726ab17fae24 Mon Sep 17 00:00:00 2001 From: John Davis Date: Sat, 5 Aug 2023 12:16:06 -0500 Subject: [PATCH 08/55] OcBootManagementLib: Improve MBR detection --- Include/Acidanthera/Library/OcFileLib.h | 16 ++++ .../OcBootManagementLib/BootEntryManagement.c | 2 +- .../BootManagementInternal.h | 5 +- .../OcBootManagementLib/LegacyBootSupport.c | 84 +++++++++++++------ Library/OcFileLib/DiskMisc.c | 67 +++++++++++++++ 5 files changed, 145 insertions(+), 29 deletions(-) diff --git a/Include/Acidanthera/Library/OcFileLib.h b/Include/Acidanthera/Library/OcFileLib.h index 116a587eee3..2b923781be1 100644 --- a/Include/Acidanthera/Library/OcFileLib.h +++ b/Include/Acidanthera/Library/OcFileLib.h @@ -19,6 +19,8 @@ #include +#include + #include #include #include @@ -602,6 +604,20 @@ OcGetGptPartitionEntry ( IN EFI_HANDLE FsHandle ); +/** + Retrieve the disk MBR table, if applicable. + + @param[in] DiskHandle Disk device handle to retrive MBR partition table from. + @param[in] UseBlockIo2 Use 2nd revision of Block I/O if available. + + @retval partition entry list or NULL. +**/ +MASTER_BOOT_RECORD * +OcGetDiskMbrTable ( + IN EFI_HANDLE DiskHandle, + IN BOOLEAN UseBlockIo2 + ); + /** Creates a device path for a firmware file. diff --git a/Library/OcBootManagementLib/BootEntryManagement.c b/Library/OcBootManagementLib/BootEntryManagement.c index 999cc037d1c..0a2463b7447 100644 --- a/Library/OcBootManagementLib/BootEntryManagement.c +++ b/Library/OcBootManagementLib/BootEntryManagement.c @@ -1994,7 +1994,7 @@ BuildFileSystemList ( } for (Index = 0; Index < NoHandles; ++Index) { - LegacyOsType = InternalGetDiskLegacyOsType (Handles[Index], FALSE); + LegacyOsType = InternalGetPartitionLegacyOsType (Handles[Index]); if (LegacyOsType == OcLegacyOsTypeNone) { continue; } diff --git a/Library/OcBootManagementLib/BootManagementInternal.h b/Library/OcBootManagementLib/BootManagementInternal.h index e40f34b39d2..038e96bcecc 100644 --- a/Library/OcBootManagementLib/BootManagementInternal.h +++ b/Library/OcBootManagementLib/BootManagementInternal.h @@ -132,9 +132,8 @@ InternalLoadAppleLegacyInterface ( ); OC_LEGACY_OS_TYPE -InternalGetDiskLegacyOsType ( - IN EFI_HANDLE DiskHandle, - IN BOOLEAN UseBlockIo2 +InternalGetPartitionLegacyOsType ( + IN EFI_HANDLE PartitionHandle ); EFI_STATUS diff --git a/Library/OcBootManagementLib/LegacyBootSupport.c b/Library/OcBootManagementLib/LegacyBootSupport.c index 9a81fe3096f..2e4aa5b8395 100644 --- a/Library/OcBootManagementLib/LegacyBootSupport.c +++ b/Library/OcBootManagementLib/LegacyBootSupport.c @@ -14,6 +14,8 @@ #include "BootManagementInternal.h" +#include + #include #include @@ -29,8 +31,6 @@ #include #include -#define MBR_SECTOR_SIZE 512 - // // PIWG firmware media device path for Apple legacy interface. // FwFile(2B0585EB-D8B8-49A9-8B8CE21B01AEF2B7) @@ -237,44 +237,78 @@ InternalLoadAppleLegacyInterface ( } OC_LEGACY_OS_TYPE -InternalGetDiskLegacyOsType ( - IN EFI_HANDLE DiskHandle, - IN BOOLEAN UseBlockIo2 +InternalGetPartitionLegacyOsType ( + IN EFI_HANDLE PartitionHandle ) { - EFI_STATUS Status; - UINT8 *Buffer; - UINT32 BufferSize; - OC_LEGACY_OS_TYPE LegacyOsType; + EFI_STATUS Status; + MASTER_BOOT_RECORD *Mbr; + MASTER_BOOT_RECORD *Pbr; + OC_LEGACY_OS_TYPE LegacyOsType; - OC_DISK_CONTEXT DiskContext; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + OC_DISK_CONTEXT DiskContext; + EFI_HANDLE DiskHandle; - ASSERT (DiskHandle != NULL); + ASSERT (PartitionHandle != NULL); - Status = OcDiskInitializeContext (&DiskContext, DiskHandle, UseBlockIo2); - if (EFI_ERROR (Status)) { + // + // Read MBR of whole disk. + // + DevicePath = DevicePathFromHandle (PartitionHandle); + if (DevicePath == NULL) { return OcLegacyOsTypeNone; } + DebugPrintDevicePath (DEBUG_INFO, "OCB: Reading MBR of disk", DevicePath); + + DiskHandle = OcPartitionGetDiskHandle (DevicePath); + if (DiskHandle == NULL) { + return OcLegacyOsTypeNone; + } + + Mbr = OcGetDiskMbrTable (DiskHandle, TRUE); + if (Mbr == NULL) { + DEBUG ((DEBUG_INFO, "OCB: Disk does not contain a valid MBR partition table\n")); + return OcLegacyOsTypeNone; + } + + FreePool (Mbr); + // - // Retrieve the first sector of the disk. + // Retrieve the first sector of the partition. // - BufferSize = ALIGN_VALUE (MBR_SECTOR_SIZE, DiskContext.BlockSize); - Buffer = AllocatePool (BufferSize); - if (Buffer == NULL) { - DEBUG ((DEBUG_INFO, "OCBP: Buffer allocation error\n")); + Status = OcDiskInitializeContext ( + &DiskContext, + PartitionHandle, + TRUE + ); + if (EFI_ERROR (Status)) { + return OcLegacyOsTypeNone; + } + + Pbr = (MASTER_BOOT_RECORD *)AllocatePool (MBR_SIZE); + if (Pbr == NULL) { + DEBUG ((DEBUG_INFO, "OCB: Buffer allocation error\n")); return OcLegacyOsTypeNone; } Status = OcDiskRead ( &DiskContext, 0, - BufferSize, - Buffer + MBR_SIZE, + Pbr ); - if (EFI_ERROR (Status)) { - FreePool (Buffer); + FreePool (Pbr); + return OcLegacyOsTypeNone; + } + + // + // Validate signature in PBR. + // + if (Pbr->Signature != MBR_SIGNATURE) { + FreePool (Pbr); return OcLegacyOsTypeNone; } @@ -283,13 +317,13 @@ InternalGetDiskLegacyOsType ( // indicating the partition is bootable. // LegacyOsType = OcLegacyOsTypeNone; - if (CheckLegacySignature ("BOOTMGR", Buffer, BufferSize)) { + if (CheckLegacySignature ("BOOTMGR", Pbr, MBR_SIZE)) { LegacyOsType = OcLegacyOsTypeWindowsBootmgr; - } else if (CheckLegacySignature ("NTLDR", Buffer, BufferSize)) { + } else if (CheckLegacySignature ("NTLDR", Pbr, MBR_SIZE)) { LegacyOsType = OcLegacyOsTypeWindowsNtldr; } - FreePool (Buffer); + FreePool (Pbr); return LegacyOsType; } diff --git a/Library/OcFileLib/DiskMisc.c b/Library/OcFileLib/DiskMisc.c index a2acd037499..4779d5940bc 100644 --- a/Library/OcFileLib/DiskMisc.c +++ b/Library/OcFileLib/DiskMisc.c @@ -14,6 +14,8 @@ #include +#include + #include #include #include @@ -655,3 +657,68 @@ OcGetGptPartitionEntry ( return PartEntry; } + +MASTER_BOOT_RECORD * +OcGetDiskMbrTable ( + IN EFI_HANDLE DiskHandle, + IN BOOLEAN UseBlockIo2 + ) +{ + EFI_STATUS Status; + MASTER_BOOT_RECORD *Mbr; + OC_DISK_CONTEXT DiskContext; + UINTN Index; + BOOLEAN IsProtectiveMbr; + + ASSERT (DiskHandle != NULL); + + // + // Read first sector containing MBR table. + // + Status = OcDiskInitializeContext (&DiskContext, DiskHandle, UseBlockIo2); + if (EFI_ERROR (Status)) { + return NULL; + } + + Mbr = (MASTER_BOOT_RECORD *)AllocatePool (sizeof (*Mbr)); + if (Mbr == NULL) { + return NULL; + } + + Status = OcDiskRead (&DiskContext, 0, sizeof (*Mbr), Mbr); + if (EFI_ERROR (Status)) { + FreePool (Mbr); + return NULL; + } + + // + // Validate MBR signatures. + // + // If MBR is a protective one (as part of a GPT disk), ignore. + // Protective MBR is defined as a single partition of type 0xEE, other three partitions are to be zero. + // + if (Mbr->Signature != MBR_SIGNATURE) { + FreePool (Mbr); + return NULL; + } + + if ( (Mbr->Partition[0].OSIndicator == PMBR_GPT_PARTITION) + && (*((UINT32 *)Mbr->Partition[0].StartingLBA) == 0x01) + && (*((UINT32 *)Mbr->Partition[0].SizeInLBA) != 0)) + { + IsProtectiveMbr = TRUE; + for (Index = 1; Index < MAX_MBR_PARTITIONS; Index++) { + if ((*((UINT32 *)Mbr->Partition[Index].StartingLBA) != 0) || (*((UINT32 *)Mbr->Partition[Index].SizeInLBA) != 0)) { + IsProtectiveMbr = FALSE; + break; + } + } + + if (IsProtectiveMbr) { + FreePool (Mbr); + return NULL; + } + } + + return Mbr; +} From 3756798c7d70325a84c5521af6ca2958ede063bc Mon Sep 17 00:00:00 2001 From: John Davis Date: Sat, 5 Aug 2023 12:25:02 -0500 Subject: [PATCH 09/55] OcBootManagementLib: Fix previous commit --- Library/OcBootManagementLib/LegacyBootSupport.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Library/OcBootManagementLib/LegacyBootSupport.c b/Library/OcBootManagementLib/LegacyBootSupport.c index 2e4aa5b8395..79d1b21bf5b 100644 --- a/Library/OcBootManagementLib/LegacyBootSupport.c +++ b/Library/OcBootManagementLib/LegacyBootSupport.c @@ -47,16 +47,15 @@ static CONST EFI_DEVICE_PATH_PROTOCOL *AppleLegacyInterfaceMediaDevicePathPath STATIC BOOLEAN CheckLegacySignature ( - IN CONST CHAR8 *SignatureStr, - IN UINT8 *Buffer, - IN UINT32 BufferSize + IN CONST CHAR8 *SignatureStr, + IN MASTER_BOOT_RECORD *Pbr ) { UINT32 Offset; Offset = 0; - return FindPattern ((CONST UINT8 *)SignatureStr, NULL, (CONST UINT32)AsciiStrLen (SignatureStr), Buffer, BufferSize, &Offset); + return FindPattern ((CONST UINT8 *)SignatureStr, NULL, (CONST UINT32)AsciiStrLen (SignatureStr), (CONST UINT8 *)Pbr, sizeof (*Pbr), &Offset); } STATIC @@ -317,9 +316,9 @@ InternalGetPartitionLegacyOsType ( // indicating the partition is bootable. // LegacyOsType = OcLegacyOsTypeNone; - if (CheckLegacySignature ("BOOTMGR", Pbr, MBR_SIZE)) { + if (CheckLegacySignature ("BOOTMGR", Pbr)) { LegacyOsType = OcLegacyOsTypeWindowsBootmgr; - } else if (CheckLegacySignature ("NTLDR", Pbr, MBR_SIZE)) { + } else if (CheckLegacySignature ("NTLDR", Pbr)) { LegacyOsType = OcLegacyOsTypeWindowsNtldr; } From 323a42003ac279e924584423823db7086bcc4dbc Mon Sep 17 00:00:00 2001 From: John Davis Date: Sat, 5 Aug 2023 16:05:07 -0500 Subject: [PATCH 10/55] OcBootManagementLib: Handle legacy default boot entry --- Include/Acidanthera/Library/OcFileLib.h | 6 + .../OcBootManagementLib/BootEntryManagement.c | 293 ++++++++++-------- Library/OcFileLib/DiskMisc.c | 120 ++++++- 3 files changed, 289 insertions(+), 130 deletions(-) diff --git a/Include/Acidanthera/Library/OcFileLib.h b/Include/Acidanthera/Library/OcFileLib.h index 2b923781be1..e5ee7bf1094 100644 --- a/Include/Acidanthera/Library/OcFileLib.h +++ b/Include/Acidanthera/Library/OcFileLib.h @@ -618,6 +618,12 @@ OcGetDiskMbrTable ( IN BOOLEAN UseBlockIo2 ); +EFI_DEVICE_PATH_PROTOCOL * +OcDiskFindActiveMbrPartitionPath ( + IN EFI_DEVICE_PATH_PROTOCOL *DiskDevicePath, + OUT UINTN *PartitionDevicePathSize + ); + /** Creates a device path for a firmware file. diff --git a/Library/OcBootManagementLib/BootEntryManagement.c b/Library/OcBootManagementLib/BootEntryManagement.c index 0a2463b7447..89a1deaea3f 100644 --- a/Library/OcBootManagementLib/BootEntryManagement.c +++ b/Library/OcBootManagementLib/BootEntryManagement.c @@ -1173,6 +1173,97 @@ AddBootEntryFromSelfRecovery ( return Status; } +/** + Create bootable entries from legacy boot partitons. + + @param[in,out] BootContext Context of filesystems. + @param[in,out] FileSystem Filesystem to scan for recovery. + + @retval EFI_SUCCESS on success. +**/ +STATIC +EFI_STATUS +AddBootEntryFromLegacyPartition ( + IN OUT OC_BOOT_CONTEXT *BootContext, + IN OUT OC_BOOT_FILESYSTEM *FileSystem + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + OC_BOOT_ENTRY *BootEntry; + + // + // Only support legacy filesystems. + // + if (FileSystem->LegacyOsType == OcLegacyOsTypeNone) { + return EFI_UNSUPPORTED; + } + + Status = gBS->HandleProtocol ( + FileSystem->Handle, + &gEfiDevicePathProtocolGuid, + (VOID **)&DevicePath + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + DebugPrintDevicePath (DEBUG_INFO, "OCB: Adding legacy entry for disk", DevicePath); + + // + // Allocate, initialise, and describe boot entry. + // + BootEntry = AllocateZeroPool (sizeof (*BootEntry)); + if (BootEntry == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + BootEntry->DevicePath = DuplicateDevicePath (DevicePath); + if (BootEntry->DevicePath == NULL) { + FreePool (BootEntry); + return EFI_OUT_OF_RESOURCES; + } + + BootEntry->IsExternal = FileSystem->External; + BootEntry->LegacyOsType = FileSystem->LegacyOsType; + BootEntry->LaunchInText = TRUE; + + // + // Load options are set based on type of disk. + // Internal disk = "HD" + // External disk = "USB" + // Optical disk = "CD" + // + // TODO: Support optical media. + // + if (BootEntry->IsExternal) { + BootEntry->LoadOptionsSize = L_STR_SIZE ("USB"); + BootEntry->LoadOptions = AllocateCopyPool (L_STR_SIZE ("USB"), "USB"); + } else { + BootEntry->LoadOptionsSize = L_STR_SIZE ("HD"); + BootEntry->LoadOptions = AllocateCopyPool (L_STR_SIZE ("HD"), "HD"); + } + + if (BootEntry->LoadOptions == NULL) { + FreePool (BootEntry); + return EFI_OUT_OF_RESOURCES; + } + + Status = InternalDescribeLegacyBootEntry (BootContext, FileSystem->LegacyOsType, BootEntry); + if (EFI_ERROR (Status)) { + FreePool (BootEntry); + return Status; + } + + RegisterBootOption ( + BootContext, + FileSystem, + BootEntry + ); + + return EFI_SUCCESS; +} + /** Create bootable entries from boot options. @@ -1209,11 +1300,13 @@ AddBootEntryFromBootOption ( EFI_DEVICE_PATH_PROTOCOL *DevicePath; EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath; EFI_DEVICE_PATH_PROTOCOL *ExpandedDevicePath; + EFI_DEVICE_PATH_PROTOCOL *ActivePartitionDevicePath; EFI_HANDLE FileSystemHandle; OC_BOOT_FILESYSTEM *FileSystem; UINTN DevicePathSize; INTN NumPatchedNodes; BOOLEAN IsAppleLegacy; + BOOLEAN IsLegacyEntry; BOOLEAN IsRoot; EFI_LOAD_OPTION *LoadOption; UINTN LoadOptionSize; @@ -1262,6 +1355,7 @@ AddBootEntryFromBootOption ( // BootCamp device path will point to disk instead of partition. // IsAppleLegacy = InternalIsAppleLegacyLoadApp (DevicePath); + IsLegacyEntry = FALSE; if (IsAppleLegacy) { FreePool (DevicePath); Status = GetVariable2 ( @@ -1303,7 +1397,15 @@ AddBootEntryFromBootOption ( } // - // Expand BootCamp device path to EFI partition device path. + // Handle Apple BootCamp device path. + // + // If we have a legacy installation of Windows in place, Device Path + // will point to disk containing the active partition to boot. This will + // need to be expanded to the full Device Path of the active partition. + // + // If not, locate the EFI partition Device Path to boot Windows in UEFI mode. + // Installing Windows on Macs that normally use legacy mode for Boot Camp + // will exhibit this behavior if Windows is selected as a startup disk from within macOS. // if (IsAppleLegacy) { // @@ -1316,12 +1418,36 @@ AddBootEntryFromBootOption ( return EFI_NOT_FOUND; } - RemainingDevicePath = DevicePath; - DevicePath = OcDiskFindSystemPartitionPath ( - DevicePath, - &DevicePathSize, - &FileSystemHandle - ); + // + // Attempt to locate active MBR partition Device Path. + // + RemainingDevicePath = DevicePath; + ActivePartitionDevicePath = OcDiskFindActiveMbrPartitionPath ( + DevicePath, + &DevicePathSize + ); + if (ActivePartitionDevicePath != NULL) { + DevicePath = ActivePartitionDevicePath; + Status = gBS->LocateDevicePath ( + &gEfiBlockIoProtocolGuid, + &ActivePartitionDevicePath, + &FileSystemHandle + ); + + if (!EFI_ERROR (Status)) { + IsLegacyEntry = TRUE; + } + + // + // Expand BootCamp device path to EFI partition device path. + // + } else { + DevicePath = OcDiskFindSystemPartitionPath ( + DevicePath, + &DevicePathSize, + &FileSystemHandle + ); + } FreePool (RemainingDevicePath); @@ -1341,8 +1467,9 @@ AddBootEntryFromBootOption ( } // - // The Device Path returned by OcDiskFindSystemPartitionPath() is a pointer - // to an installed protocol. Duplicate it so we own the memory. + // The Device Path returned by OcDiskFindActiveMbrPartitionPath() and + // OcDiskFindSystemPartitionPath() is a pointer to an installed protocol. + // Duplicate it so we own the memory. // if (DevicePath != NULL) { DevicePath = AllocateCopyPool (DevicePathSize, DevicePath); @@ -1565,125 +1692,41 @@ AddBootEntryFromBootOption ( FreePool (DevicePath); } - // - // We may have a Boot#### entry pointing to macOS with full DP (up to boot.efi), - // so IsRoot will be true. However, if this is APFS, we may still have: - // - Recovery for this macOS. - // - Another macOS installation. - // We can only detect them with bless, so we invoke bless in deduplication mode. - // We also detect only the Core Apple Boot Policy predefined booter paths to - // avoid detection of e.g. generic booters (such as BOOTx64) to avoid - // duplicates. - // - // The amount of paths depends on the kind of the entry. - // - If this is a root entry (i.e. it points to the partition) - // we invoke full bless, as it may be Windows entry created by legacy NVRAM script. - // - If this is a full entry (i.e. it points to the bootloader) - // we invoke partial bless, which ignores BOOTx64.efi. - // Ignoring BOOTx64.efi is important as we may already have bootmgfw.efi as our entry, - // and we do not want to see Windows added twice. - // - Status = AddBootEntryFromBless ( - BootContext, - FileSystem, - gAppleBootPolicyPredefinedPaths, - IsRoot ? gAppleBootPolicyNumPredefinedPaths : gAppleBootPolicyCoreNumPredefinedPaths, - LazyScan, - TRUE - ); - - return Status; -} - -/** - Create bootable entries from legacy boot partitons. - - @param[in,out] BootContext Context of filesystems. - @param[in,out] FileSystem Filesystem to scan for recovery. - - @retval EFI_SUCCESS on success. -**/ -STATIC -EFI_STATUS -AddBootEntryFromLegacyPartition ( - IN OUT OC_BOOT_CONTEXT *BootContext, - IN OUT OC_BOOT_FILESYSTEM *FileSystem - ) -{ - EFI_STATUS Status; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - OC_BOOT_ENTRY *BootEntry; - - // - // Only support legacy filesystems. - // - if (FileSystem->LegacyOsType == OcLegacyOsTypeNone) { - return EFI_UNSUPPORTED; - } - - Status = gBS->HandleProtocol ( - FileSystem->Handle, - &gEfiDevicePathProtocolGuid, - (VOID **)&DevicePath - ); - if (EFI_ERROR (Status)) { - return EFI_UNSUPPORTED; - } - - DebugPrintDevicePath (DEBUG_INFO, "OCB: Adding legacy entry for disk", DevicePath); - - // - // Allocate, initialise, and describe boot entry. - // - BootEntry = AllocateZeroPool (sizeof (*BootEntry)); - if (BootEntry == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - BootEntry->DevicePath = DuplicateDevicePath (DevicePath); - if (BootEntry->DevicePath == NULL) { - FreePool (BootEntry); - return EFI_OUT_OF_RESOURCES; - } - - BootEntry->IsExternal = FileSystem->External; - BootEntry->LegacyOsType = FileSystem->LegacyOsType; - BootEntry->LaunchInText = TRUE; - - // - // Load options are set based on type of disk. - // Internal disk = "HD" - // External disk = "USB" - // Optical disk = "CD" - // - // TODO: Support optical media. - // - if (BootEntry->IsExternal) { - BootEntry->LoadOptionsSize = L_STR_SIZE ("USB"); - BootEntry->LoadOptions = AllocateCopyPool (L_STR_SIZE ("USB"), "USB"); + if (IsLegacyEntry) { + Status = AddBootEntryFromLegacyPartition ( + BootContext, + FileSystem + ); } else { - BootEntry->LoadOptionsSize = L_STR_SIZE ("HD"); - BootEntry->LoadOptions = AllocateCopyPool (L_STR_SIZE ("HD"), "HD"); - } - - if (BootEntry->LoadOptions == NULL) { - FreePool (BootEntry); - return EFI_OUT_OF_RESOURCES; - } - - Status = InternalDescribeLegacyBootEntry (BootContext, FileSystem->LegacyOsType, BootEntry); - if (EFI_ERROR (Status)) { - FreePool (BootEntry); - return Status; + // + // We may have a Boot#### entry pointing to macOS with full DP (up to boot.efi), + // so IsRoot will be true. However, if this is APFS, we may still have: + // - Recovery for this macOS. + // - Another macOS installation. + // We can only detect them with bless, so we invoke bless in deduplication mode. + // We also detect only the Core Apple Boot Policy predefined booter paths to + // avoid detection of e.g. generic booters (such as BOOTx64) to avoid + // duplicates. + // + // The amount of paths depends on the kind of the entry. + // - If this is a root entry (i.e. it points to the partition) + // we invoke full bless, as it may be Windows entry created by legacy NVRAM script. + // - If this is a full entry (i.e. it points to the bootloader) + // we invoke partial bless, which ignores BOOTx64.efi. + // Ignoring BOOTx64.efi is important as we may already have bootmgfw.efi as our entry, + // and we do not want to see Windows added twice. + // + Status = AddBootEntryFromBless ( + BootContext, + FileSystem, + gAppleBootPolicyPredefinedPaths, + IsRoot ? gAppleBootPolicyNumPredefinedPaths : gAppleBootPolicyCoreNumPredefinedPaths, + LazyScan, + TRUE + ); } - RegisterBootOption ( - BootContext, - FileSystem, - BootEntry - ); - - return EFI_SUCCESS; + return Status; } /** diff --git a/Library/OcFileLib/DiskMisc.c b/Library/OcFileLib/DiskMisc.c index 4779d5940bc..1467cc1800e 100644 --- a/Library/OcFileLib/DiskMisc.c +++ b/Library/OcFileLib/DiskMisc.c @@ -173,8 +173,9 @@ InternalDebugPrintPartitionEntry ( STATIC EFI_HANDLE -InternalPartitionGetDiskHandle ( +InternalGetDiskHandle ( IN EFI_DEVICE_PATH_PROTOCOL *HdDevicePath, + IN BOOLEAN IsPartitionPath, OUT BOOLEAN *HasBlockIo2 ) { @@ -188,7 +189,12 @@ InternalPartitionGetDiskHandle ( ASSERT (HdDevicePath != NULL); ASSERT (HasBlockIo2 != NULL); - DiskPath = OcDiskGetDevicePath (HdDevicePath); + if (IsPartitionPath) { + DiskPath = OcDiskGetDevicePath (HdDevicePath); + } else { + DiskPath = HdDevicePath; + } + TempPath = DiskPath; Status = gBS->LocateDevicePath ( &gEfiBlockIo2ProtocolGuid, @@ -216,7 +222,9 @@ InternalPartitionGetDiskHandle ( DiskHandle = NULL; } - FreePool (DiskPath); + if (IsPartitionPath && (DiskPath != NULL)) { + FreePool (DiskPath); + } return DiskHandle; } @@ -283,8 +291,9 @@ OcPartitionGetDiskHandle ( ASSERT (HdDevicePath != NULL); - return InternalPartitionGetDiskHandle ( + return InternalGetDiskHandle ( HdDevicePath, + TRUE, &Dummy ); } @@ -611,8 +620,9 @@ OcGetGptPartitionEntry ( return NULL; } - DiskHandle = InternalPartitionGetDiskHandle ( + DiskHandle = InternalGetDiskHandle ( FsDevicePath, + TRUE, &HasBlockIo2 ); if (DiskHandle == NULL) { @@ -722,3 +732,103 @@ OcGetDiskMbrTable ( return Mbr; } + +EFI_DEVICE_PATH_PROTOCOL * +OcDiskFindActiveMbrPartitionPath ( + IN EFI_DEVICE_PATH_PROTOCOL *DiskDevicePath, + OUT UINTN *PartitionDevicePathSize + ) +{ + EFI_STATUS Status; + EFI_HANDLE DiskHandle; + BOOLEAN HasBlockIo2; + UINTN Index; + INT32 ActivePartition; + + UINTN NoHandles; + EFI_HANDLE *Handles; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + HARDDRIVE_DEVICE_PATH *HdNode; + MASTER_BOOT_RECORD *Mbr; + + ASSERT (DiskDevicePath != NULL); + ASSERT (PartitionDevicePathSize != NULL); + + // + // Get MBR partition table from disk. + // + DiskHandle = InternalGetDiskHandle ( + DiskDevicePath, + FALSE, + &HasBlockIo2 + ); + if (DiskHandle == NULL) { + return NULL; + } + + Mbr = OcGetDiskMbrTable ( + DiskHandle, + HasBlockIo2 + ); + if (Mbr == NULL) { + return NULL; + } + + // + // Determine active partition based on first one with active partition set. + // Multiple active partitions should not occur but possible. + // + ActivePartition = -1; + for (Index = 0; Index < MAX_MBR_PARTITIONS; Index++) { + if (Mbr->Partition[Index].BootIndicator == 0x80) { + ActivePartition = (INT32)Index; + } + } + + // + // No active partitions present. + // + if (ActivePartition == -1) { + DEBUG ((DEBUG_INFO, "OCPI: No active partitions found in MBR\n")); + FreePool (Mbr); + return NULL; + } + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiBlockIoProtocolGuid, + NULL, + &NoHandles, + &Handles + ); + if (EFI_ERROR (Status)) { + FreePool (Mbr); + return NULL; + } + + for (Index = 0; Index < NoHandles; Index++) { + DevicePath = DevicePathFromHandle (Handles[Index]); + if (DevicePath == NULL) { + continue; + } + + if (CompareMem (DevicePath, DiskDevicePath, GetDevicePathSize (DiskDevicePath) - END_DEVICE_PATH_LENGTH) == 0) { + HdNode = (HARDDRIVE_DEVICE_PATH *)FindDevicePathNodeWithType ( + DevicePath, + MEDIA_DEVICE_PATH, + MEDIA_HARDDRIVE_DP + ); + if (HdNode != NULL) { + if (HdNode->PartitionStart == *((UINT32 *)Mbr->Partition[ActivePartition].StartingLBA)) { + DebugPrintDevicePath (DEBUG_INFO, "OCPI: Got active MBR partition device path", DevicePath); + FreePool (Mbr); + *PartitionDevicePathSize = GetDevicePathSize (DevicePath); + return DevicePath; + } + } + } + } + + FreePool (Mbr); + return NULL; +} From 9fd5aae44fb2013f559acfb9178f43d51410c311 Mon Sep 17 00:00:00 2001 From: John Davis Date: Sat, 5 Aug 2023 19:24:01 -0500 Subject: [PATCH 11/55] OcBootManagementLib: Fix hang on certain Mac models during legacy start --- Library/OcBootManagementLib/PolicyManagement.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Library/OcBootManagementLib/PolicyManagement.c b/Library/OcBootManagementLib/PolicyManagement.c index 5fe66fea4ca..d1aa1119d53 100644 --- a/Library/OcBootManagementLib/PolicyManagement.c +++ b/Library/OcBootManagementLib/PolicyManagement.c @@ -336,6 +336,16 @@ OcGetBootDevicePathType ( *IsFolder = FALSE; } + // + // Detect firmware images such as the Apple legacy loader interface. + // + // Certain Mac models lock up if any additional probing of the device path + // is performed when the Apple legacy loader interface is being started. + // + if (DevicePath->Type == MEDIA_DEVICE_PATH && DevicePath->SubType == MEDIA_PIWG_FW_FILE_DP) { + return OC_BOOT_UNKNOWN; + } + Path = OcCopyDevicePathFullName (DevicePath, NULL); if (Path == NULL) { return OC_BOOT_UNKNOWN; From f93f52b20c7e9b8a4c33abab23bddf184cc0a031 Mon Sep 17 00:00:00 2001 From: John Davis Date: Sat, 5 Aug 2023 19:29:08 -0500 Subject: [PATCH 12/55] OcBootManagementLib: Cleanup MBR detecting logging --- Library/OcBootManagementLib/LegacyBootSupport.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Library/OcBootManagementLib/LegacyBootSupport.c b/Library/OcBootManagementLib/LegacyBootSupport.c index 79d1b21bf5b..f7df960d6df 100644 --- a/Library/OcBootManagementLib/LegacyBootSupport.c +++ b/Library/OcBootManagementLib/LegacyBootSupport.c @@ -259,8 +259,6 @@ InternalGetPartitionLegacyOsType ( return OcLegacyOsTypeNone; } - DebugPrintDevicePath (DEBUG_INFO, "OCB: Reading MBR of disk", DevicePath); - DiskHandle = OcPartitionGetDiskHandle (DevicePath); if (DiskHandle == NULL) { return OcLegacyOsTypeNone; @@ -268,7 +266,7 @@ InternalGetPartitionLegacyOsType ( Mbr = OcGetDiskMbrTable (DiskHandle, TRUE); if (Mbr == NULL) { - DEBUG ((DEBUG_INFO, "OCB: Disk does not contain a valid MBR partition table\n")); + DEBUG ((DEBUG_VERBOSE, "OCB: Disk does not contain a valid MBR partition table\n")); return OcLegacyOsTypeNone; } @@ -277,6 +275,7 @@ InternalGetPartitionLegacyOsType ( // // Retrieve the first sector of the partition. // + DebugPrintDevicePath (DEBUG_INFO, "OCB: Reading MBR of disk", DevicePath); Status = OcDiskInitializeContext ( &DiskContext, PartitionHandle, From b26ce6e7f8db94a22007b7b792dfa71a819b3e5a Mon Sep 17 00:00:00 2001 From: John Davis Date: Sat, 5 Aug 2023 19:41:42 -0500 Subject: [PATCH 13/55] OcBootManagementLib: Fix logging --- Library/OcBootManagementLib/LegacyBootSupport.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Library/OcBootManagementLib/LegacyBootSupport.c b/Library/OcBootManagementLib/LegacyBootSupport.c index f7df960d6df..cbdbdd559e1 100644 --- a/Library/OcBootManagementLib/LegacyBootSupport.c +++ b/Library/OcBootManagementLib/LegacyBootSupport.c @@ -258,6 +258,7 @@ InternalGetPartitionLegacyOsType ( if (DevicePath == NULL) { return OcLegacyOsTypeNone; } + DebugPrintDevicePath (DEBUG_VERBOSE, "OCB: Reading MBR for disk", DevicePath); DiskHandle = OcPartitionGetDiskHandle (DevicePath); if (DiskHandle == NULL) { @@ -275,7 +276,7 @@ InternalGetPartitionLegacyOsType ( // // Retrieve the first sector of the partition. // - DebugPrintDevicePath (DEBUG_INFO, "OCB: Reading MBR of disk", DevicePath); + DebugPrintDevicePath (DEBUG_INFO, "OCB: Reading PBR for partition", DevicePath); Status = OcDiskInitializeContext ( &DiskContext, PartitionHandle, From 52b6eb72ce6682b834346cc379bd25d12f83a3cd Mon Sep 17 00:00:00 2001 From: John Davis Date: Sat, 5 Aug 2023 22:24:17 -0500 Subject: [PATCH 14/55] OcBootManagementLib: Fix assertion for unknown legacy OS name --- Library/OcBootManagementLib/BootEntryInfo.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Library/OcBootManagementLib/BootEntryInfo.c b/Library/OcBootManagementLib/BootEntryInfo.c index 4171e8d94a5..984944e7b8b 100644 --- a/Library/OcBootManagementLib/BootEntryInfo.c +++ b/Library/OcBootManagementLib/BootEntryInfo.c @@ -911,6 +911,8 @@ InternalDescribeLegacyBootEntry ( break; default: + BootEntry->Type = OC_BOOT_UNKNOWN; + BootEntry->Name = AllocateCopyPool (sizeof (L"Unknown OS (legacy)"), L"Unknown OS (legacy)"); break; } From a4cb596b7c796d02394e7bac3da06e9f85f91516 Mon Sep 17 00:00:00 2001 From: John Davis Date: Sat, 5 Aug 2023 22:27:38 -0500 Subject: [PATCH 15/55] OcBootManagementLib: Add legacy CD boot support --- .../Acidanthera/Library/OcBootManagementLib.h | 3 +- Include/Acidanthera/Library/OcFileLib.h | 12 ++ .../OcBootManagementLib/BootEntryManagement.c | 11 +- .../OcBootManagementLib/LegacyBootSupport.c | 132 +++++++++++------- .../OcBootManagementLib/PolicyManagement.c | 15 +- Library/OcFileLib/DiskMisc.c | 69 +++++++-- 6 files changed, 168 insertions(+), 74 deletions(-) diff --git a/Include/Acidanthera/Library/OcBootManagementLib.h b/Include/Acidanthera/Library/OcBootManagementLib.h index 934dd6095fe..4966683133b 100644 --- a/Include/Acidanthera/Library/OcBootManagementLib.h +++ b/Include/Acidanthera/Library/OcBootManagementLib.h @@ -167,7 +167,8 @@ typedef enum OC_LEGACY_BOOT_TYPE_ { typedef enum OC_LEGACY_OS_TYPE_ { OcLegacyOsTypeNone, OcLegacyOsTypeWindowsNtldr, - OcLegacyOsTypeWindowsBootmgr + OcLegacyOsTypeWindowsBootmgr, + OcLegacyOsTypeIsoLinux } OC_LEGACY_OS_TYPE; /** diff --git a/Include/Acidanthera/Library/OcFileLib.h b/Include/Acidanthera/Library/OcFileLib.h index e5ee7bf1094..c7c3c178467 100644 --- a/Include/Acidanthera/Library/OcFileLib.h +++ b/Include/Acidanthera/Library/OcFileLib.h @@ -508,6 +508,18 @@ OcPartitionGetDiskHandle ( IN EFI_DEVICE_PATH_PROTOCOL *HdDevicePath ); +/** + Check if disk is a CD-ROM device. + + @param[in] HdDevicePath The Device Path of the disk. + + @retval Device Path or NULL +**/ +BOOLEAN +OcIsDiskCdRom ( + IN EFI_DEVICE_PATH_PROTOCOL *DiskDevicePath + ); + /** Locate the disk's EFI System Partition. diff --git a/Library/OcBootManagementLib/BootEntryManagement.c b/Library/OcBootManagementLib/BootEntryManagement.c index 89a1deaea3f..af98f546de9 100644 --- a/Library/OcBootManagementLib/BootEntryManagement.c +++ b/Library/OcBootManagementLib/BootEntryManagement.c @@ -1234,11 +1234,14 @@ AddBootEntryFromLegacyPartition ( // External disk = "USB" // Optical disk = "CD" // - // TODO: Support optical media. - // if (BootEntry->IsExternal) { - BootEntry->LoadOptionsSize = L_STR_SIZE ("USB"); - BootEntry->LoadOptions = AllocateCopyPool (L_STR_SIZE ("USB"), "USB"); + if (OcIsDiskCdRom (BootEntry->DevicePath)) { + BootEntry->LoadOptionsSize = L_STR_SIZE ("CD"); + BootEntry->LoadOptions = AllocateCopyPool (L_STR_SIZE ("CD"), "CD"); + } else { + BootEntry->LoadOptionsSize = L_STR_SIZE ("USB"); + BootEntry->LoadOptions = AllocateCopyPool (L_STR_SIZE ("USB"), "USB"); + } } else { BootEntry->LoadOptionsSize = L_STR_SIZE ("HD"); BootEntry->LoadOptions = AllocateCopyPool (L_STR_SIZE ("HD"), "HD"); diff --git a/Library/OcBootManagementLib/LegacyBootSupport.c b/Library/OcBootManagementLib/LegacyBootSupport.c index cbdbdd559e1..fc4ffeeb6e4 100644 --- a/Library/OcBootManagementLib/LegacyBootSupport.c +++ b/Library/OcBootManagementLib/LegacyBootSupport.c @@ -55,7 +55,14 @@ CheckLegacySignature ( Offset = 0; - return FindPattern ((CONST UINT8 *)SignatureStr, NULL, (CONST UINT32)AsciiStrLen (SignatureStr), (CONST UINT8 *)Pbr, sizeof (*Pbr), &Offset); + return FindPattern ( + (CONST UINT8 *)SignatureStr, + NULL, + (CONST UINT32)AsciiStrLen (SignatureStr), + Pbr->BootStrapCode, + sizeof (Pbr->BootStrapCode), + &Offset + ); } STATIC @@ -166,28 +173,30 @@ InternalLoadAppleLegacyInterface ( // Get device path to disk to be booted. // TODO: Handle CD booting, device path is not required in that case. // - WholeDiskPath = OcDiskGetDevicePath (HdDevicePath); - if (WholeDiskPath == NULL) { - return EFI_INVALID_PARAMETER; - } + if (!OcIsDiskCdRom (HdDevicePath)) { + WholeDiskPath = OcDiskGetDevicePath (HdDevicePath); + if (WholeDiskPath == NULL) { + return EFI_INVALID_PARAMETER; + } - DebugPrintDevicePath (DEBUG_INFO, "OCB: Legacy disk device path", WholeDiskPath); + DebugPrintDevicePath (DEBUG_INFO, "OCB: Legacy disk device path", WholeDiskPath); - // TODO: Mark target partition as active on pure MBR and hybrid GPT disks. - // Macs only boot the active partition. + // TODO: Mark target partition as active on pure MBR and hybrid GPT disks. + // Macs only boot the active partition. - // - // Set BootCampHD variable pointing to target disk. - // - Status = gRT->SetVariable ( - APPLE_BOOT_CAMP_HD_VARIABLE_NAME, - &gAppleBootVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, - GetDevicePathSize (WholeDiskPath), - WholeDiskPath - ); - if (EFI_ERROR (Status)) { - return Status; + // + // Set BootCampHD variable pointing to target disk. + // + Status = gRT->SetVariable ( + APPLE_BOOT_CAMP_HD_VARIABLE_NAME, + &gAppleBootVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + GetDevicePathSize (WholeDiskPath), + WholeDiskPath + ); + if (EFI_ERROR (Status)) { + return Status; + } } // @@ -242,7 +251,7 @@ InternalGetPartitionLegacyOsType ( { EFI_STATUS Status; MASTER_BOOT_RECORD *Mbr; - MASTER_BOOT_RECORD *Pbr; + UINTN MbrSize; OC_LEGACY_OS_TYPE LegacyOsType; EFI_DEVICE_PATH_PROTOCOL *DevicePath; @@ -258,6 +267,7 @@ InternalGetPartitionLegacyOsType ( if (DevicePath == NULL) { return OcLegacyOsTypeNone; } + DebugPrintDevicePath (DEBUG_VERBOSE, "OCB: Reading MBR for disk", DevicePath); DiskHandle = OcPartitionGetDiskHandle (DevicePath); @@ -271,43 +281,51 @@ InternalGetPartitionLegacyOsType ( return OcLegacyOsTypeNone; } - FreePool (Mbr); - // - // Retrieve the first sector of the partition. + // For hard disk devices, get PBR sector instead. // - DebugPrintDevicePath (DEBUG_INFO, "OCB: Reading PBR for partition", DevicePath); - Status = OcDiskInitializeContext ( - &DiskContext, - PartitionHandle, - TRUE - ); - if (EFI_ERROR (Status)) { - return OcLegacyOsTypeNone; - } + if (!OcIsDiskCdRom (DevicePath)) { + FreePool (Mbr); - Pbr = (MASTER_BOOT_RECORD *)AllocatePool (MBR_SIZE); - if (Pbr == NULL) { - DEBUG ((DEBUG_INFO, "OCB: Buffer allocation error\n")); - return OcLegacyOsTypeNone; - } + // + // Retrieve the first sector of the partition. + // + DebugPrintDevicePath (DEBUG_VERBOSE, "OCB: Reading PBR for partition", DevicePath); + Status = OcDiskInitializeContext ( + &DiskContext, + PartitionHandle, + TRUE + ); + if (EFI_ERROR (Status)) { + return OcLegacyOsTypeNone; + } - Status = OcDiskRead ( - &DiskContext, - 0, - MBR_SIZE, - Pbr - ); - if (EFI_ERROR (Status)) { - FreePool (Pbr); - return OcLegacyOsTypeNone; + MbrSize = ALIGN_VALUE (sizeof (*Mbr), DiskContext.BlockSize); + Mbr = (MASTER_BOOT_RECORD *)AllocatePool (MbrSize); + if (Mbr == NULL) { + DEBUG ((DEBUG_INFO, "OCB: Buffer allocation error\n")); + return OcLegacyOsTypeNone; + } + + Status = OcDiskRead ( + &DiskContext, + 0, + MbrSize, + Mbr + ); + if (EFI_ERROR (Status)) { + FreePool (Mbr); + return OcLegacyOsTypeNone; + } } + DebugPrintHexDump (DEBUG_INFO, "OCB: MbrHEX", Mbr->BootStrapCode, sizeof (Mbr->BootStrapCode)); + // - // Validate signature in PBR. + // Validate signature in MBR. // - if (Pbr->Signature != MBR_SIGNATURE) { - FreePool (Pbr); + if (Mbr->Signature != MBR_SIGNATURE) { + FreePool (Mbr); return OcLegacyOsTypeNone; } @@ -315,14 +333,20 @@ InternalGetPartitionLegacyOsType ( // Validate sector contents and check for known signatures // indicating the partition is bootable. // - LegacyOsType = OcLegacyOsTypeNone; - if (CheckLegacySignature ("BOOTMGR", Pbr)) { + if (CheckLegacySignature ("BOOTMGR", Mbr)) { LegacyOsType = OcLegacyOsTypeWindowsBootmgr; - } else if (CheckLegacySignature ("NTLDR", Pbr)) { + } else if (CheckLegacySignature ("NTLDR", Mbr)) { LegacyOsType = OcLegacyOsTypeWindowsNtldr; + } else if ( CheckLegacySignature ("ISOLINUX", Mbr) + || CheckLegacySignature ("isolinux", Mbr)) + { + LegacyOsType = OcLegacyOsTypeIsoLinux; + } else { + LegacyOsType = OcLegacyOsTypeNone; + DEBUG ((DEBUG_INFO, "OCB: Unknown legacy bootsector signature\n")); } - FreePool (Pbr); + FreePool (Mbr); return LegacyOsType; } diff --git a/Library/OcBootManagementLib/PolicyManagement.c b/Library/OcBootManagementLib/PolicyManagement.c index d1aa1119d53..61d5e9c69b8 100644 --- a/Library/OcBootManagementLib/PolicyManagement.c +++ b/Library/OcBootManagementLib/PolicyManagement.c @@ -75,6 +75,19 @@ OcGetDevicePolicyType ( SubType = DevicePathSubType (DevicePathWalker); switch (SubType) { case MSG_SATA_DP: + // + // Check if this SATA Bus has a CD connected. + // + DevicePathWalker = NextDevicePathNode (DevicePathWalker); + if ( !IsDevicePathEnd (DevicePathWalker) + && (DevicePathType (DevicePathWalker) == MEDIA_DEVICE_PATH) + && (DevicePathSubType (DevicePathWalker) == MEDIA_CDROM_DP)) + { + if (External != NULL) { + *External = TRUE; + } + } + return OC_SCAN_ALLOW_DEVICE_SATA; case MSG_SASEX_DP: return OC_SCAN_ALLOW_DEVICE_SASEX; @@ -342,7 +355,7 @@ OcGetBootDevicePathType ( // Certain Mac models lock up if any additional probing of the device path // is performed when the Apple legacy loader interface is being started. // - if (DevicePath->Type == MEDIA_DEVICE_PATH && DevicePath->SubType == MEDIA_PIWG_FW_FILE_DP) { + if ((DevicePath->Type == MEDIA_DEVICE_PATH) && (DevicePath->SubType == MEDIA_PIWG_FW_FILE_DP)) { return OC_BOOT_UNKNOWN; } diff --git a/Library/OcFileLib/DiskMisc.c b/Library/OcFileLib/DiskMisc.c index 1467cc1800e..e6f228197bf 100644 --- a/Library/OcFileLib/DiskMisc.c +++ b/Library/OcFileLib/DiskMisc.c @@ -241,21 +241,28 @@ OcDiskGetDevicePath ( IN EFI_DEVICE_PATH_PROTOCOL *HdDevicePath ) { - EFI_DEVICE_PATH_PROTOCOL *PrefixPath; - EFI_DEVICE_PATH_PROTOCOL *TempPath; - CONST HARDDRIVE_DEVICE_PATH *HdNode; + EFI_DEVICE_PATH_PROTOCOL *PrefixPath; + EFI_DEVICE_PATH_PROTOCOL *TempPath; + CONST EFI_DEVICE_PATH_PROTOCOL *HdNode; ASSERT (HdDevicePath != NULL); - HdNode = (HARDDRIVE_DEVICE_PATH *)( - FindDevicePathNodeWithType ( - HdDevicePath, - MEDIA_DEVICE_PATH, - MEDIA_HARDDRIVE_DP - ) - ); + HdNode = FindDevicePathNodeWithType ( + HdDevicePath, + MEDIA_DEVICE_PATH, + MEDIA_HARDDRIVE_DP + ); if (HdNode == NULL) { - return NULL; + HdNode = FindDevicePathNodeWithType ( + HdDevicePath, + MEDIA_DEVICE_PATH, + MEDIA_CDROM_DP + ); + if (HdNode == NULL) { + return NULL; + } + + DEBUG ((DEBUG_INFO, "got cdrom\n")); } PrefixPath = DuplicateDevicePath (HdDevicePath); @@ -298,6 +305,29 @@ OcPartitionGetDiskHandle ( ); } +BOOLEAN +OcIsDiskCdRom ( + IN EFI_DEVICE_PATH_PROTOCOL *DiskDevicePath + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePathWalker; + + ASSERT (DiskDevicePath != NULL); + + DevicePathWalker = DiskDevicePath; + while (!IsDevicePathEnd (DevicePathWalker)) { + if ( (DevicePathType (DevicePathWalker) == MEDIA_DEVICE_PATH) + && (DevicePathSubType (DevicePathWalker) == MEDIA_CDROM_DP)) + { + return TRUE; + } + + DevicePathWalker = NextDevicePathNode (DevicePathWalker); + } + + return FALSE; +} + EFI_DEVICE_PATH_PROTOCOL * OcDiskFindSystemPartitionPath ( IN CONST EFI_DEVICE_PATH_PROTOCOL *DiskDevicePath, @@ -676,6 +706,7 @@ OcGetDiskMbrTable ( { EFI_STATUS Status; MASTER_BOOT_RECORD *Mbr; + UINTN MbrSize; OC_DISK_CONTEXT DiskContext; UINTN Index; BOOLEAN IsProtectiveMbr; @@ -685,17 +716,27 @@ OcGetDiskMbrTable ( // // Read first sector containing MBR table. // - Status = OcDiskInitializeContext (&DiskContext, DiskHandle, UseBlockIo2); + Status = OcDiskInitializeContext ( + &DiskContext, + DiskHandle, + UseBlockIo2 + ); if (EFI_ERROR (Status)) { return NULL; } - Mbr = (MASTER_BOOT_RECORD *)AllocatePool (sizeof (*Mbr)); + MbrSize = ALIGN_VALUE (sizeof (*Mbr), DiskContext.BlockSize); + Mbr = (MASTER_BOOT_RECORD *)AllocatePool (MbrSize); if (Mbr == NULL) { return NULL; } - Status = OcDiskRead (&DiskContext, 0, sizeof (*Mbr), Mbr); + Status = OcDiskRead ( + &DiskContext, + 0, + MbrSize, + Mbr + ); if (EFI_ERROR (Status)) { FreePool (Mbr); return NULL; From 0a92019b1217e099f751193026f726c8b87ed266 Mon Sep 17 00:00:00 2001 From: John Davis Date: Mon, 7 Aug 2023 18:14:57 -0500 Subject: [PATCH 16/55] OcBootManagementLib: Only attempt Apple legacy boot when available --- Library/OcBootManagementLib/DefaultEntryChoice.c | 15 ++++++++++----- Library/OcBootManagementLib/LegacyBootSupport.c | 1 - 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Library/OcBootManagementLib/DefaultEntryChoice.c b/Library/OcBootManagementLib/DefaultEntryChoice.c index cfcb851cc72..52937a7217f 100644 --- a/Library/OcBootManagementLib/DefaultEntryChoice.c +++ b/Library/OcBootManagementLib/DefaultEntryChoice.c @@ -1578,11 +1578,16 @@ InternalLoadBootEntry ( DEBUG_CODE_END (); if (BootEntry->LegacyOsType != OcLegacyOsTypeNone) { - Status = InternalLoadAppleLegacyInterface ( - ParentHandle, - DevicePath, - EntryHandle - ); + if (Context->LegacyBootType == OcLegacyBootTypeApple) { + Status = InternalLoadAppleLegacyInterface ( + ParentHandle, + DevicePath, + EntryHandle + ); + } else { + DEBUG ((DEBUG_INFO, "OCB: Unsupported legacy interface type: %u\n", Context->LegacyBootType)); + Status = EFI_UNSUPPORTED; + } } else { Status = gBS->LoadImage ( FALSE, diff --git a/Library/OcBootManagementLib/LegacyBootSupport.c b/Library/OcBootManagementLib/LegacyBootSupport.c index fc4ffeeb6e4..2c053403ffb 100644 --- a/Library/OcBootManagementLib/LegacyBootSupport.c +++ b/Library/OcBootManagementLib/LegacyBootSupport.c @@ -171,7 +171,6 @@ InternalLoadAppleLegacyInterface ( // // Get device path to disk to be booted. - // TODO: Handle CD booting, device path is not required in that case. // if (!OcIsDiskCdRom (HdDevicePath)) { WholeDiskPath = OcDiskGetDevicePath (HdDevicePath); From 3b6d8b8c98635ee5eecf7300ae227c29f340cc81 Mon Sep 17 00:00:00 2001 From: John Davis Date: Mon, 7 Aug 2023 18:15:47 -0500 Subject: [PATCH 17/55] OcBootManagementLib: Move legacy type detection into library --- .../Acidanthera/Library/OcBootManagementLib.h | 3 +- .../BootManagementInternal.h | 5 +++ .../OcBootManagementLib/LegacyBootSupport.c | 31 +++++++++++++++++-- .../OcBootManagementLib/OcBootManagementLib.c | 5 +++ .../OcBootManagementLib.inf | 2 ++ Library/OcMainLib/OpenCoreMisc.c | 8 ----- 6 files changed, 43 insertions(+), 11 deletions(-) diff --git a/Include/Acidanthera/Library/OcBootManagementLib.h b/Include/Acidanthera/Library/OcBootManagementLib.h index 4966683133b..10fcc44e92e 100644 --- a/Include/Acidanthera/Library/OcBootManagementLib.h +++ b/Include/Acidanthera/Library/OcBootManagementLib.h @@ -158,7 +158,8 @@ typedef UINT32 OC_BOOT_ENTRY_TYPE; **/ typedef enum OC_LEGACY_BOOT_TYPE_ { OcLegacyBootTypeNone, - OcLegacyBootTypeApple + OcLegacyBootTypeApple, + OcLegacyBootTypeLegacyBios } OC_LEGACY_BOOT_TYPE; /** diff --git a/Library/OcBootManagementLib/BootManagementInternal.h b/Library/OcBootManagementLib/BootManagementInternal.h index 038e96bcecc..2d3e0ba6f6d 100644 --- a/Library/OcBootManagementLib/BootManagementInternal.h +++ b/Library/OcBootManagementLib/BootManagementInternal.h @@ -136,6 +136,11 @@ InternalGetPartitionLegacyOsType ( IN EFI_HANDLE PartitionHandle ); +OC_LEGACY_BOOT_TYPE +InternalGetLegacyBootType ( + VOID + ); + EFI_STATUS InternalCheckScanPolicy ( IN EFI_HANDLE Handle, diff --git a/Library/OcBootManagementLib/LegacyBootSupport.c b/Library/OcBootManagementLib/LegacyBootSupport.c index 2c053403ffb..985fc620a74 100644 --- a/Library/OcBootManagementLib/LegacyBootSupport.c +++ b/Library/OcBootManagementLib/LegacyBootSupport.c @@ -16,8 +16,6 @@ #include -#include - #include #include #include @@ -31,6 +29,9 @@ #include #include +#include +#include + // // PIWG firmware media device path for Apple legacy interface. // FwFile(2B0585EB-D8B8-49A9-8B8CE21B01AEF2B7) @@ -349,3 +350,29 @@ InternalGetPartitionLegacyOsType ( return LegacyOsType; } + +OC_LEGACY_BOOT_TYPE +InternalGetLegacyBootType ( + VOID + ) +{ + EFI_STATUS Status; + EFI_LEGACY_8259_PROTOCOL *Legacy8259; + OC_LEGACY_BOOT_TYPE BootType; + + // + // Apple legacy boot interface is only available on Apple platforms. + // Use legacy 16-bit thunks on legacy PC platforms. + // + BootType = OcLegacyBootTypeNone; + if (OcStriCmp (L"Apple", gST->FirmwareVendor) == 0) { + BootType = OcLegacyBootTypeApple; + } else { + Status = gBS->LocateProtocol (&gEfiLegacy8259ProtocolGuid, NULL, (VOID **)&Legacy8259); + if (!EFI_ERROR (Status) && (Legacy8259 != NULL)) { + BootType = OcLegacyBootTypeLegacyBios; + } + } + + return BootType; +} diff --git a/Library/OcBootManagementLib/OcBootManagementLib.c b/Library/OcBootManagementLib/OcBootManagementLib.c index b1d778226fa..85963549bb2 100644 --- a/Library/OcBootManagementLib/OcBootManagementLib.c +++ b/Library/OcBootManagementLib/OcBootManagementLib.c @@ -324,6 +324,11 @@ OcRunBootPicker ( Context->HideAuxiliary = FALSE; } + // + // Get legacy boot mode. + // + Context->LegacyBootType = InternalGetLegacyBootType (); + while (TRUE) { // // Never show Apple Picker twice, re-scan for entries if we previously successfully showed it. diff --git a/Library/OcBootManagementLib/OcBootManagementLib.inf b/Library/OcBootManagementLib/OcBootManagementLib.inf index 02b44687c72..42efff2e8e2 100644 --- a/Library/OcBootManagementLib/OcBootManagementLib.inf +++ b/Library/OcBootManagementLib/OcBootManagementLib.inf @@ -53,6 +53,7 @@ OpenCorePkg/OpenCorePkg.dec MdePkg/MdePkg.dec MdeModulePkg/MdeModulePkg.dec + OvmfPkg/OvmfPkg.dec UefiCpuPkg/UefiCpuPkg.dec [Guids] @@ -85,6 +86,7 @@ gAppleBeepGenProtocolGuid ## SOMETIMES_CONSUMES gOcBootEntryProtocolGuid ## CONSUMES gAppleFirmwareUserInterfaceProtocolGuid ## SOMETIMES_CONSUMES + gEfiLegacy8259ProtocolGuid ## SOMETIMES_CONSUMES [LibraryClasses] BaseLib diff --git a/Library/OcMainLib/OpenCoreMisc.c b/Library/OcMainLib/OpenCoreMisc.c index b2277b58385..29fb6229e67 100644 --- a/Library/OcMainLib/OpenCoreMisc.c +++ b/Library/OcMainLib/OpenCoreMisc.c @@ -939,14 +939,6 @@ OcMiscBoot ( Context->InstanceIdentifier = AsciiInstanceIdentifier; Context->BlacklistAppleUpdate = Config->Misc.Security.BlacklistAppleUpdate; - // - // Apple legacy boot interface is only available on Apple platforms. - // - Context->LegacyBootType = OcLegacyBootTypeNone; - if (OcStriCmp (L"Apple", gST->FirmwareVendor) == 0) { - Context->LegacyBootType = OcLegacyBootTypeApple; - } - if ((Config->Misc.Security.ExposeSensitiveData & OCS_EXPOSE_VERSION_UI) != 0) { Context->TitleSuffix = OcMiscGetVersionString (); } From c9abfdaefe5bbe9d804df7e3bf7e74a1faf899b5 Mon Sep 17 00:00:00 2001 From: John Davis Date: Mon, 7 Aug 2023 19:42:41 -0500 Subject: [PATCH 18/55] OcLegacyThunkLib: Consolidate 16-bit thunking interface into library --- .../Acidanthera/Library/OcLegacyThunkLib.h | 70 ++++++ Legacy/BootPlatform/BiosVideo/BiosVideo.c | 26 +-- Legacy/BootPlatform/BiosVideo/BiosVideo.h | 57 +---- Legacy/BootPlatform/BiosVideo/BiosVideo.inf | 2 +- Legacy/BootPlatform/BlockIoDxe/BiosBlkIo.c | 4 +- Legacy/BootPlatform/BlockIoDxe/BiosBlkIo.h | 49 +--- Legacy/BootPlatform/BlockIoDxe/BiosInt13.c | 24 +- Legacy/BootPlatform/BlockIoDxe/BlockIoDxe.inf | 2 +- .../BootPlatform/BlockIoDxe/LegacyBiosThunk.c | 216 ------------------ Legacy/BootPlatform/CpuDxe/CpuDxe.c | 138 +---------- Legacy/BootPlatform/CpuDxe/CpuDxe.h | 8 +- Legacy/BootPlatform/CpuDxe/CpuDxe.inf | 2 + .../OcLegacyThunkLib/OcLegacyThunkLib.c | 47 ++-- Library/OcLegacyThunkLib/OcLegacyThunkLib.inf | 49 ++++ OpenCorePkg.dec | 3 + OpenCorePkg.dsc | 1 + OpenDuetPkg.dsc | 1 + 17 files changed, 189 insertions(+), 510 deletions(-) create mode 100644 Include/Acidanthera/Library/OcLegacyThunkLib.h delete mode 100644 Legacy/BootPlatform/BlockIoDxe/LegacyBiosThunk.c rename Legacy/BootPlatform/BiosVideo/LegacyBiosThunk.c => Library/OcLegacyThunkLib/OcLegacyThunkLib.c (83%) create mode 100644 Library/OcLegacyThunkLib/OcLegacyThunkLib.inf diff --git a/Include/Acidanthera/Library/OcLegacyThunkLib.h b/Include/Acidanthera/Library/OcLegacyThunkLib.h new file mode 100644 index 00000000000..4c2a97c3056 --- /dev/null +++ b/Include/Acidanthera/Library/OcLegacyThunkLib.h @@ -0,0 +1,70 @@ +/** @file + This library implements thunking to legacy 16-bit environment. + + Copyright (c) 2023, Goldfish64. All rights reserved.
+ Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause +**/ + +#ifndef OC_LEGACY_THUNK_LIB_H +#define OC_LEGACY_THUNK_LIB_H + +#include + +// +// Legacy region base is 0x0C0000. +// +#define LEGACY_REGION_BASE 0x0C0000 +#define LEGACY_REGION_SIZE 0x10000 + +#define EFI_SEGMENT(_Adr) (UINT16) ((UINT16) (((UINTN) (_Adr)) >> 4) & 0xf000) +#define EFI_OFFSET(_Adr) (UINT16) (((UINT16) ((UINTN) (_Adr))) & 0xffff) + +/** + Initialize legacy environment for BIOS INI caller. + + @param ThunkContext the instance pointer of THUNK_CONTEXT +**/ +VOID +OcLegacyThunkInitializeBiosIntCaller ( + IN OUT THUNK_CONTEXT *ThunkContext + ); + +/** + Initialize interrupt redirection code and entries, because + IDT Vectors 0x68-0x6f must be redirected to IDT Vectors 0x08-0x0f. + Or the interrupt will lost when we do thunk. + NOTE: We do not reset 8259 vector base, because it will cause pending + interrupt lost. + + @param Legacy8259 Instance pointer for EFI_LEGACY_8259_PROTOCOL. + +**/ +VOID +OcLegacyThunkInitializeInterruptRedirection ( + IN EFI_LEGACY_8259_PROTOCOL *Legacy8259 + ); + +/** + Thunk to 16-bit real mode and execute a software interrupt with a vector + of BiosInt. Regs will contain the 16-bit register context on entry and + exit. + + @param This Protocol instance pointer. + @param BiosInt Processor interrupt vector to invoke + @param Reg Register contexted passed into (and returned) from thunk to 16-bit mode + + @retval TRUE Thunk completed, and there were no BIOS errors in the target code. + See Regs for status. + @retval FALSE There was a BIOS erro in the target code. +**/ +BOOLEAN +EFIAPI +OcLegacyThunkBiosInt86 ( + IN THUNK_CONTEXT *ThunkContext, + IN EFI_LEGACY_8259_PROTOCOL *Legacy8259, + IN UINT8 BiosInt, + IN IA32_REGISTER_SET *Regs + ); + +#endif // OC_LEGACY_THUNK_LIB_H diff --git a/Legacy/BootPlatform/BiosVideo/BiosVideo.c b/Legacy/BootPlatform/BiosVideo/BiosVideo.c index f977eee14a7..010c5f625b1 100644 --- a/Legacy/BootPlatform/BiosVideo/BiosVideo.c +++ b/Legacy/BootPlatform/BiosVideo/BiosVideo.c @@ -209,8 +209,8 @@ BiosVideoDriverBindingStart ( goto Done; } - InitializeBiosIntCaller (&mThunkContext); - InitializeInterruptRedirection (mLegacy8259); + OcLegacyThunkInitializeBiosIntCaller (&mThunkContext); + OcLegacyThunkInitializeInterruptRedirection (mLegacy8259); } // @@ -622,12 +622,12 @@ BiosVideoChildHandleUninstall ( // Regs.H.AH = 0x00; Regs.H.AL = 0x03; - LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs); + OcLegacyThunkBiosInt86 (BiosVideoPrivate->ThunkContext, BiosVideoPrivate->Legacy8259, 0x10, &Regs); Regs.H.AH = 0x11; Regs.H.AL = 0x14; Regs.H.BL = 0; - LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs); + OcLegacyThunkBiosInt86 (BiosVideoPrivate->ThunkContext, BiosVideoPrivate->Legacy8259, 0x10, &Regs); // // Do not disable IO/memory decode since that would prevent legacy ROM from working @@ -712,7 +712,7 @@ BiosVideoGetVbeData ( Regs.E.ES = EFI_SEGMENT ((UINTN)BiosVideoPrivate->VbeInformationBlock); Regs.X.DI = EFI_OFFSET ((UINTN)BiosVideoPrivate->VbeInformationBlock); - LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs); + OcLegacyThunkBiosInt86 (BiosVideoPrivate->ThunkContext, BiosVideoPrivate->Legacy8259, 0x10, &Regs); Status = EFI_DEVICE_ERROR; @@ -772,7 +772,7 @@ BiosVideoGetVbeData ( Regs.E.ES = EFI_SEGMENT ((UINTN)BiosVideoPrivate->VbeModeInformationBlock); Regs.X.DI = EFI_OFFSET ((UINTN)BiosVideoPrivate->VbeModeInformationBlock); - LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs); + OcLegacyThunkBiosInt86 (BiosVideoPrivate->ThunkContext, BiosVideoPrivate->Legacy8259, 0x10, &Regs); // // See if the call succeeded. If it didn't, then try the next mode. @@ -984,7 +984,7 @@ BiosVideoGetVbeData ( Regs.E.ES = EFI_SEGMENT ((UINTN)BiosVideoPrivate->VbeEdidDataBlock); Regs.X.DI = EFI_OFFSET ((UINTN)BiosVideoPrivate->VbeEdidDataBlock); - LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs); + OcLegacyThunkBiosInt86 (BiosVideoPrivate->ThunkContext, BiosVideoPrivate->Legacy8259, 0x10, &Regs); // // If the call succeed, populate EDID Discovered protocol. @@ -1533,7 +1533,7 @@ BiosVideoSetModeWorker ( // Set VGA Mode // Regs.X.AX = ModeData->VbeModeNumber; - LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs); + OcLegacyThunkBiosInt86 (BiosVideoPrivate->ThunkContext, BiosVideoPrivate->Legacy8259, 0x10, &Regs); } else { // // Allocate a working buffer for BLT operations to the VBE frame buffer @@ -1554,7 +1554,7 @@ BiosVideoSetModeWorker ( Regs.E.ES = EFI_SEGMENT ((UINTN)BiosVideoPrivate->VbeCrtcInformationBlock); Regs.X.DI = EFI_OFFSET ((UINTN)BiosVideoPrivate->VbeCrtcInformationBlock); - LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs); + OcLegacyThunkBiosInt86 (BiosVideoPrivate->ThunkContext, BiosVideoPrivate->Legacy8259, 0x10, &Regs); // // Check to see if the call succeeded @@ -2652,12 +2652,12 @@ BiosVideoVgaMiniPortSetMode ( // Regs.H.AH = 0x00; Regs.H.AL = 0x83; - LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs); + OcLegacyThunkBiosInt86 (BiosVideoPrivate->ThunkContext, BiosVideoPrivate->Legacy8259, 0x10, &Regs); Regs.H.AH = 0x11; Regs.H.AL = 0x14; Regs.H.BL = 0; - LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs); + OcLegacyThunkBiosInt86 (BiosVideoPrivate->ThunkContext, BiosVideoPrivate->Legacy8259, 0x10, &Regs); break; @@ -2667,12 +2667,12 @@ BiosVideoVgaMiniPortSetMode ( // Regs.H.AH = 0x00; Regs.H.AL = 0x83; - LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs); + OcLegacyThunkBiosInt86 (BiosVideoPrivate->ThunkContext, BiosVideoPrivate->Legacy8259, 0x10, &Regs); Regs.H.AH = 0x11; Regs.H.AL = 0x12; Regs.H.BL = 0; - LegacyBiosInt86 (BiosVideoPrivate, 0x10, &Regs); + OcLegacyThunkBiosInt86 (BiosVideoPrivate->ThunkContext, BiosVideoPrivate->Legacy8259, 0x10, &Regs); break; default: diff --git a/Legacy/BootPlatform/BiosVideo/BiosVideo.h b/Legacy/BootPlatform/BiosVideo/BiosVideo.h index c6a886635d4..aec22985c30 100644 --- a/Legacy/BootPlatform/BiosVideo/BiosVideo.h +++ b/Legacy/BootPlatform/BiosVideo/BiosVideo.h @@ -47,6 +47,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include +#include #include #include @@ -55,13 +56,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include "VesaBiosExtensions.h" -// -// ** CHANGE ** -// Legacy region base is now 0x0C0000 instead of 0x100000. -// -#define LEGACY_REGION_BASE 0x0C0000 -#define LEGACY_REGION_SIZE 0x10000 - // // Vendor IDs. // @@ -171,9 +165,6 @@ typedef struct { #define GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER 0xffff -#define EFI_SEGMENT(_Adr) (UINT16) ((UINT16) (((UINTN) (_Adr)) >> 4) & 0xf000) -#define EFI_OFFSET(_Adr) (UINT16) (((UINT16) ((UINTN) (_Adr))) & 0xffff) - // // Global Variables // @@ -553,52 +544,6 @@ BiosVideoIsVga ( #define VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER 0x08 -/** - Initialize legacy environment for BIOS INI caller. - - @param ThunkContext the instance pointer of THUNK_CONTEXT -**/ -VOID -InitializeBiosIntCaller ( - THUNK_CONTEXT *ThunkContext - ); - -/** - Initialize interrupt redirection code and entries, because - IDT Vectors 0x68-0x6f must be redirected to IDT Vectors 0x08-0x0f. - Or the interrupt will lost when we do thunk. - NOTE: We do not reset 8259 vector base, because it will cause pending - interrupt lost. - - @param Legacy8259 Instance pointer for EFI_LEGACY_8259_PROTOCOL. - -**/ -VOID -InitializeInterruptRedirection ( - IN EFI_LEGACY_8259_PROTOCOL *Legacy8259 - ); - -/** - Thunk to 16-bit real mode and execute a software interrupt with a vector - of BiosInt. Regs will contain the 16-bit register context on entry and - exit. - - @param This Protocol instance pointer. - @param BiosInt Processor interrupt vector to invoke - @param Reg Register contexted passed into (and returned) from thunk to 16-bit mode - - @retval TRUE Thunk completed, and there were no BIOS errors in the target code. - See Regs for status. - @retval FALSE There was a BIOS erro in the target code. -**/ -BOOLEAN -EFIAPI -LegacyBiosInt86 ( - IN BIOS_VIDEO_DEV *BiosDev, - IN UINT8 BiosInt, - IN IA32_REGISTER_SET *Regs - ); - /** Force the specified resolution and reconnect the controller. Specifying zero for Width and Height will pull the maximum diff --git a/Legacy/BootPlatform/BiosVideo/BiosVideo.inf b/Legacy/BootPlatform/BiosVideo/BiosVideo.inf index 23a88534cb0..52ce22c6b74 100644 --- a/Legacy/BootPlatform/BiosVideo/BiosVideo.inf +++ b/Legacy/BootPlatform/BiosVideo/BiosVideo.inf @@ -37,6 +37,7 @@ MemoryAllocationLib UefiDriverEntryPoint DevicePathLib + OcLegacyThunkLib OcMemoryLib OcMiscLib @@ -45,7 +46,6 @@ BiosVideo.c ComponentName.c VesaBiosExtensions.h - LegacyBiosThunk.c VideoBiosPatch.c [Protocols] diff --git a/Legacy/BootPlatform/BlockIoDxe/BiosBlkIo.c b/Legacy/BootPlatform/BlockIoDxe/BiosBlkIo.c index 5daecf12895..a6598f951ae 100644 --- a/Legacy/BootPlatform/BlockIoDxe/BiosBlkIo.c +++ b/Legacy/BootPlatform/BlockIoDxe/BiosBlkIo.c @@ -255,8 +255,8 @@ BiosBlockIoDriverBindingStart ( goto Error; } - InitializeBiosIntCaller (&mThunkContext); - InitializeInterruptRedirection (Legacy8259); + OcLegacyThunkInitializeBiosIntCaller (&mThunkContext); + OcLegacyThunkInitializeInterruptRedirection (Legacy8259); // // Open the IO Abstraction(s) needed diff --git a/Legacy/BootPlatform/BlockIoDxe/BiosBlkIo.h b/Legacy/BootPlatform/BlockIoDxe/BiosBlkIo.h index b8bb04ea669..c971e597668 100644 --- a/Legacy/BootPlatform/BlockIoDxe/BiosBlkIo.h +++ b/Legacy/BootPlatform/BlockIoDxe/BiosBlkIo.h @@ -26,13 +26,12 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include +#include #include #include "Edd.h" -#define LEGACY_REGION_BASE 0x0C0000 - // // Global Variables // @@ -423,50 +422,4 @@ SetBiosInitBlockIoDevicePath ( OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath ); -/** - Initialize legacy environment for BIOS INI caller. - - @param ThunkContext the instance pointer of THUNK_CONTEXT -**/ -VOID -InitializeBiosIntCaller ( - THUNK_CONTEXT *ThunkContext - ); - -/** - Initialize interrupt redirection code and entries, because - IDT Vectors 0x68-0x6f must be redirected to IDT Vectors 0x08-0x0f. - Or the interrupt will lost when we do thunk. - NOTE: We do not reset 8259 vector base, because it will cause pending - interrupt lost. - - @param Legacy8259 Instance pointer for EFI_LEGACY_8259_PROTOCOL. - -**/ -VOID -InitializeInterruptRedirection ( - IN EFI_LEGACY_8259_PROTOCOL *Legacy8259 - ); - -/** - Thunk to 16-bit real mode and execute a software interrupt with a vector - of BiosInt. Regs will contain the 16-bit register context on entry and - exit. - - @param This Protocol instance pointer. - @param BiosInt Processor interrupt vector to invoke - @param Reg Register contexted passed into (and returned) from thunk to 16-bit mode - - @retval TRUE Thunk completed, and there were no BIOS errors in the target code. - See Regs for status. - @retval FALSE There was a BIOS erro in the target code. -**/ -BOOLEAN -EFIAPI -LegacyBiosInt86 ( - IN BIOS_BLOCK_IO_DEV *BiosDev, - IN UINT8 BiosInt, - IN IA32_REGISTER_SET *Regs - ); - #endif diff --git a/Legacy/BootPlatform/BlockIoDxe/BiosInt13.c b/Legacy/BootPlatform/BlockIoDxe/BiosInt13.c index 7b8c8765a74..d6c0c686909 100644 --- a/Legacy/BootPlatform/BlockIoDxe/BiosInt13.c +++ b/Legacy/BootPlatform/BlockIoDxe/BiosInt13.c @@ -137,7 +137,7 @@ Int13GetDeviceParameters ( Regs.H.AH = 0x08; Regs.H.DL = Drive->Number; - CarryFlag = LegacyBiosInt86 (BiosBlockIoDev, 0x13, &Regs); + CarryFlag = OcLegacyThunkBiosInt86 (BiosBlockIoDev->ThunkContext, BiosBlockIoDev->Legacy8259, 0x13, &Regs); DEBUG ((DEBUG_INIT, "Int13GetDeviceParameters: INT 13 08 DL=%02x : CF=%d AH=%02x\n", Drive->Number, CarryFlag, Regs.H.AH)); if ((CarryFlag != 0) || (Regs.H.AH != 0x00)) { Drive->ErrorCode = Regs.H.AH; @@ -192,7 +192,7 @@ Int13Extensions ( Regs.H.AH = 0x41; Regs.X.BX = 0x55aa; Regs.H.DL = Drive->Number; - CarryFlag = LegacyBiosInt86 (BiosBlockIoDev, 0x13, &Regs); + CarryFlag = OcLegacyThunkBiosInt86 (BiosBlockIoDev->ThunkContext, BiosBlockIoDev->Legacy8259, 0x13, &Regs); DEBUG ((DEBUG_INIT, "Int13Extensions: INT 13 41 DL=%02x : CF=%d BX=%04x\n", Drive->Number, CarryFlag, Regs.X.BX)); if ((CarryFlag != 0) || (Regs.X.BX != 0xaa55)) { @@ -242,7 +242,7 @@ GetDriveParameters ( mLegacyDriverUnder1Mb->Parameters.StructureSize = (UINT16)sizeof (EDD_DRIVE_PARAMETERS); Regs.E.DS = EFI_SEGMENT ((UINTN)(&mLegacyDriverUnder1Mb->Parameters)); Regs.X.SI = EFI_OFFSET ((UINTN)(&mLegacyDriverUnder1Mb->Parameters)); - CarryFlag = LegacyBiosInt86 (BiosBlockIoDev, 0x13, &Regs); + CarryFlag = OcLegacyThunkBiosInt86 (BiosBlockIoDev->ThunkContext, BiosBlockIoDev->Legacy8259, 0x13, &Regs); DEBUG ((DEBUG_INIT, "GetDriveParameters: INT 13 48 DL=%02x : CF=%d AH=%02x\n", Drive->Number, CarryFlag, Regs.H.AH)); if ((CarryFlag != 0) || (Regs.H.AH != 0x00)) { Drive->ErrorCode = Regs.H.AH; @@ -265,7 +265,7 @@ GetDriveParameters ( // Regs.H.AH = 0x20; Regs.H.DL = Drive->Number; - CarryFlag = LegacyBiosInt86 (BiosBlockIoDev, 0x13, &Regs); + CarryFlag = OcLegacyThunkBiosInt86 (BiosBlockIoDev->ThunkContext, BiosBlockIoDev->Legacy8259, 0x13, &Regs); DEBUG ((DEBUG_INIT, "GetDriveParameters: INT 13 20 DL=%02x : CF=%d AL=%02x\n", Drive->Number, CarryFlag, Regs.H.AL)); if (CarryFlag != 0) { // @@ -482,7 +482,7 @@ Edd30BiosReadBlocks ( Regs.X.SI = EFI_OFFSET (AddressPacket); Regs.E.DS = EFI_SEGMENT (AddressPacket); - CarryFlag = LegacyBiosInt86 (BiosBlockIoDev, 0x13, &Regs); + CarryFlag = OcLegacyThunkBiosInt86 (BiosBlockIoDev->ThunkContext, BiosBlockIoDev->Legacy8259, 0x13, &Regs); DEBUG ( ( DEBUG_BLKIO, "Edd30BiosReadBlocks: INT 13 42 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number, @@ -631,7 +631,7 @@ Edd30BiosWriteBlocks ( Regs.X.SI = EFI_OFFSET (AddressPacket); Regs.E.DS = EFI_SEGMENT (AddressPacket); - CarryFlag = LegacyBiosInt86 (BiosBlockIoDev, 0x13, &Regs); + CarryFlag = OcLegacyThunkBiosInt86 (BiosBlockIoDev->ThunkContext, BiosBlockIoDev->Legacy8259, 0x13, &Regs); DEBUG ( ( DEBUG_BLKIO, "Edd30BiosWriteBlocks: INT 13 43 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number, @@ -730,7 +730,7 @@ BiosBlockIoReset ( Regs.H.AH = 0x00; Regs.H.DL = BiosBlockIoDev->Bios.Number; - CarryFlag = LegacyBiosInt86 (BiosBlockIoDev, 0x13, &Regs); + CarryFlag = OcLegacyThunkBiosInt86 (BiosBlockIoDev->ThunkContext, BiosBlockIoDev->Legacy8259, 0x13, &Regs); DEBUG ( ( DEBUG_INIT, "BiosBlockIoReset: INT 13 00 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number, CarryFlag, @@ -742,7 +742,7 @@ BiosBlockIoReset ( if (Regs.H.AL == BIOS_RESET_FAILED) { Regs.H.AH = 0x00; Regs.H.DL = BiosBlockIoDev->Bios.Number; - CarryFlag = LegacyBiosInt86 (BiosBlockIoDev, 0x13, &Regs); + CarryFlag = OcLegacyThunkBiosInt86 (BiosBlockIoDev->ThunkContext, BiosBlockIoDev->Legacy8259, 0x13, &Regs); DEBUG ( ( DEBUG_INIT, "BiosBlockIoReset: INT 13 00 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number, CarryFlag, @@ -867,7 +867,7 @@ Edd11BiosReadBlocks ( Regs.X.SI = EFI_OFFSET (AddressPacket); Regs.E.DS = EFI_SEGMENT (AddressPacket); - CarryFlag = LegacyBiosInt86 (BiosBlockIoDev, 0x13, &Regs); + CarryFlag = OcLegacyThunkBiosInt86 (BiosBlockIoDev->ThunkContext, BiosBlockIoDev->Legacy8259, 0x13, &Regs); DEBUG ( ( DEBUG_BLKIO, "Edd11BiosReadBlocks: INT 13 42 DL=%02x : CF=%d AH=%02x : LBA 0x%lx Block(s) %0d \n", @@ -1025,7 +1025,7 @@ Edd11BiosWriteBlocks ( TransferByteSize = NumberOfBlocks * BlockSize; CopyMem ((VOID *)(UINTN)TransferBuffer, Buffer, TransferByteSize); - CarryFlag = LegacyBiosInt86 (BiosBlockIoDev, 0x13, &Regs); + CarryFlag = OcLegacyThunkBiosInt86 (BiosBlockIoDev->ThunkContext, BiosBlockIoDev->Legacy8259, 0x13, &Regs); DEBUG ( ( DEBUG_BLKIO, "Edd11BiosWriteBlocks: INT 13 43 DL=%02x : CF=%d AH=%02x\n: LBA 0x%lx Block(s) %0d \n", @@ -1217,7 +1217,7 @@ BiosReadLegacyDrive ( EFI_SEGMENT (mEdd11Buffer)) ); - CarryFlag = LegacyBiosInt86 (BiosBlockIoDev, 0x13, &Regs); + CarryFlag = OcLegacyThunkBiosInt86 (BiosBlockIoDev->ThunkContext, BiosBlockIoDev->Legacy8259, 0x13, &Regs); DEBUG ( ( DEBUG_BLKIO, "BiosReadLegacyDrive: INT 13 02 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number, @@ -1422,7 +1422,7 @@ BiosWriteLegacyDrive ( EFI_SEGMENT (mEdd11Buffer)) ); - CarryFlag = LegacyBiosInt86 (BiosBlockIoDev, 0x13, &Regs); + CarryFlag = OcLegacyThunkBiosInt86 (BiosBlockIoDev->ThunkContext, BiosBlockIoDev->Legacy8259, 0x13, &Regs); DEBUG ( ( DEBUG_BLKIO, "BiosWriteLegacyDrive: INT 13 03 DL=%02x : CF=%d AH=%02x\n", BiosBlockIoDev->Bios.Number, diff --git a/Legacy/BootPlatform/BlockIoDxe/BlockIoDxe.inf b/Legacy/BootPlatform/BlockIoDxe/BlockIoDxe.inf index f02cd734db1..7a732a93ee2 100644 --- a/Legacy/BootPlatform/BlockIoDxe/BlockIoDxe.inf +++ b/Legacy/BootPlatform/BlockIoDxe/BlockIoDxe.inf @@ -26,7 +26,6 @@ BiosBlkIo.c BiosInt13.c ComponentName.c - LegacyBiosThunk.c [LibraryClasses] UefiDriverEntryPoint @@ -36,6 +35,7 @@ UefiLib DevicePathLib MemoryAllocationLib + OcLegacyThunkLib [Protocols] gEfiBlockIoProtocolGuid ## BY_START diff --git a/Legacy/BootPlatform/BlockIoDxe/LegacyBiosThunk.c b/Legacy/BootPlatform/BlockIoDxe/LegacyBiosThunk.c deleted file mode 100644 index e0e426a739e..00000000000 --- a/Legacy/BootPlatform/BlockIoDxe/LegacyBiosThunk.c +++ /dev/null @@ -1,216 +0,0 @@ -/** @file - Provide legacy thunk interface for accessing Bios Block I/O. - -Copyright (c) 2006 - 2007, Intel Corporation. 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 "BiosBlkIo.h" - -/** - Initialize legacy environment for BIOS INI caller. - - @param ThunkContext the instance pointer of THUNK_CONTEXT -**/ -VOID -InitializeBiosIntCaller ( - THUNK_CONTEXT *ThunkContext - ) -{ - EFI_STATUS Status; - UINT32 RealModeBufferSize; - UINT32 ExtraStackSize; - EFI_PHYSICAL_ADDRESS LegacyRegionBase; - UINT32 LegacyRegionSize; - - // - // Get LegacyRegion - // - AsmGetThunk16Properties (&RealModeBufferSize, &ExtraStackSize); - LegacyRegionSize = (((RealModeBufferSize + ExtraStackSize) / EFI_PAGE_SIZE) + 1) * EFI_PAGE_SIZE; - LegacyRegionBase = LEGACY_REGION_BASE; - Status = gBS->AllocatePages ( - AllocateMaxAddress, - EfiACPIMemoryNVS, - EFI_SIZE_TO_PAGES (LegacyRegionSize), - &LegacyRegionBase - ); - ASSERT_EFI_ERROR (Status); - - ThunkContext->RealModeBuffer = (VOID *)(UINTN)LegacyRegionBase; - ThunkContext->RealModeBufferSize = LegacyRegionSize; - ThunkContext->ThunkAttributes = THUNK_ATTRIBUTE_BIG_REAL_MODE|THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15; - AsmPrepareThunk16 (ThunkContext); -} - -/** - Initialize interrupt redirection code and entries, because - IDT Vectors 0x68-0x6f must be redirected to IDT Vectors 0x08-0x0f. - Or the interrupt will lost when we do thunk. - NOTE: We do not reset 8259 vector base, because it will cause pending - interrupt lost. - - @param Legacy8259 Instance pointer for EFI_LEGACY_8259_PROTOCOL. - -**/ -VOID -InitializeInterruptRedirection ( - IN EFI_LEGACY_8259_PROTOCOL *Legacy8259 - ) -{ - EFI_STATUS Status; - EFI_PHYSICAL_ADDRESS LegacyRegionBase; - UINTN LegacyRegionLength; - volatile UINT32 *IdtArray; - UINTN Index; - UINT8 ProtectedModeBaseVector; - - STATIC CONST UINT32 InterruptRedirectionCode[] = { - 0x90CF08CD, // INT8; IRET; NOP - 0x90CF09CD, // INT9; IRET; NOP - 0x90CF0ACD, // INTA; IRET; NOP - 0x90CF0BCD, // INTB; IRET; NOP - 0x90CF0CCD, // INTC; IRET; NOP - 0x90CF0DCD, // INTD; IRET; NOP - 0x90CF0ECD, // INTE; IRET; NOP - 0x90CF0FCD // INTF; IRET; NOP - }; - - // - // Get LegacyRegion - // - LegacyRegionLength = sizeof (InterruptRedirectionCode); - LegacyRegionBase = LEGACY_REGION_BASE; - Status = gBS->AllocatePages ( - AllocateMaxAddress, - EfiACPIMemoryNVS, - EFI_SIZE_TO_PAGES (LegacyRegionLength), - &LegacyRegionBase - ); - ASSERT_EFI_ERROR (Status); - - // - // Copy code to legacy region - // - CopyMem ((VOID *)(UINTN)LegacyRegionBase, InterruptRedirectionCode, sizeof (InterruptRedirectionCode)); - - // - // Get VectorBase, it should be 0x68 - // - Status = Legacy8259->GetVector (Legacy8259, Efi8259Irq0, &ProtectedModeBaseVector); - ASSERT_EFI_ERROR (Status); - - // - // Patch IVT 0x68 ~ 0x6f - // - IdtArray = (UINT32 *)0; - for (Index = 0; Index < 8; Index++) { - IdtArray[ProtectedModeBaseVector + Index] = ((EFI_SEGMENT (LegacyRegionBase + Index * 4)) << 16) | (EFI_OFFSET (LegacyRegionBase + Index * 4)); - } -} - -/** - Thunk to 16-bit real mode and execute a software interrupt with a vector - of BiosInt. Regs will contain the 16-bit register context on entry and - exit. - - @param This Protocol instance pointer. - @param BiosInt Processor interrupt vector to invoke - @param Reg Register contexted passed into (and returned) from thunk to 16-bit mode - - @retval TRUE Thunk completed, and there were no BIOS errors in the target code. - See Regs for status. - @retval FALSE There was a BIOS erro in the target code. -**/ -BOOLEAN -EFIAPI -LegacyBiosInt86 ( - IN BIOS_BLOCK_IO_DEV *BiosDev, - IN UINT8 BiosInt, - IN IA32_REGISTER_SET *Regs - ) -{ - UINTN Status; - IA32_REGISTER_SET ThunkRegSet; - BOOLEAN Ret; - UINT16 *Stack16; - BOOLEAN Enabled; - - ZeroMem (&ThunkRegSet, sizeof (ThunkRegSet)); - ThunkRegSet.E.EFLAGS.Bits.Reserved_0 = 1; - ThunkRegSet.E.EFLAGS.Bits.Reserved_1 = 0; - ThunkRegSet.E.EFLAGS.Bits.Reserved_2 = 0; - ThunkRegSet.E.EFLAGS.Bits.Reserved_3 = 0; - ThunkRegSet.E.EFLAGS.Bits.IOPL = 3; - ThunkRegSet.E.EFLAGS.Bits.NT = 0; - ThunkRegSet.E.EFLAGS.Bits.IF = 1; - ThunkRegSet.E.EFLAGS.Bits.TF = 0; - ThunkRegSet.E.EFLAGS.Bits.CF = 0; - - ThunkRegSet.E.EDI = Regs->E.EDI; - ThunkRegSet.E.ESI = Regs->E.ESI; - ThunkRegSet.E.EBP = Regs->E.EBP; - ThunkRegSet.E.EBX = Regs->E.EBX; - ThunkRegSet.E.EDX = Regs->E.EDX; - ThunkRegSet.E.ECX = Regs->E.ECX; - ThunkRegSet.E.EAX = Regs->E.EAX; - ThunkRegSet.E.DS = Regs->E.DS; - ThunkRegSet.E.ES = Regs->E.ES; - - // - // The call to Legacy16 is a critical section to EFI - // - Enabled = SaveAndDisableInterrupts (); - - // - // Set Legacy16 state. 0x08, 0x70 is legacy 8259 vector bases. - // - Status = BiosDev->Legacy8259->SetMode (BiosDev->Legacy8259, Efi8259LegacyMode, NULL, NULL); - ASSERT_EFI_ERROR (Status); - - Stack16 = (UINT16 *)((UINT8 *)BiosDev->ThunkContext->RealModeBuffer + BiosDev->ThunkContext->RealModeBufferSize - sizeof (UINT16)); - - ThunkRegSet.E.SS = (UINT16)(((UINTN)Stack16 >> 16) << 12); - ThunkRegSet.E.ESP = (UINT16)(UINTN)Stack16; - - ThunkRegSet.E.Eip = (UINT16)((volatile UINT32 *)NULL)[BiosInt]; - ThunkRegSet.E.CS = (UINT16)(((volatile UINT32 *)NULL)[BiosInt] >> 16); - BiosDev->ThunkContext->RealModeState = &ThunkRegSet; - AsmThunk16 (BiosDev->ThunkContext); - - // - // Restore protected mode interrupt state - // - Status = BiosDev->Legacy8259->SetMode (BiosDev->Legacy8259, Efi8259ProtectedMode, NULL, NULL); - ASSERT_EFI_ERROR (Status); - - // - // End critical section - // - SetInterruptState (Enabled); - - Regs->E.EDI = ThunkRegSet.E.EDI; - Regs->E.ESI = ThunkRegSet.E.ESI; - Regs->E.EBP = ThunkRegSet.E.EBP; - Regs->E.EBX = ThunkRegSet.E.EBX; - Regs->E.EDX = ThunkRegSet.E.EDX; - Regs->E.ECX = ThunkRegSet.E.ECX; - Regs->E.EAX = ThunkRegSet.E.EAX; - Regs->E.SS = ThunkRegSet.E.SS; - Regs->E.CS = ThunkRegSet.E.CS; - Regs->E.DS = ThunkRegSet.E.DS; - Regs->E.ES = ThunkRegSet.E.ES; - - CopyMem (&(Regs->E.EFLAGS), &(ThunkRegSet.E.EFLAGS), sizeof (UINT32)); - - Ret = (BOOLEAN)(Regs->E.EFLAGS.Bits.CF == 1); - - return Ret; -} diff --git a/Legacy/BootPlatform/CpuDxe/CpuDxe.c b/Legacy/BootPlatform/CpuDxe/CpuDxe.c index 6b20f14330c..f9acf9db1a0 100644 --- a/Legacy/BootPlatform/CpuDxe/CpuDxe.c +++ b/Legacy/BootPlatform/CpuDxe/CpuDxe.c @@ -948,8 +948,8 @@ Return --*/ { - EFI_IA32_REGISTER_SET Regs; - UINT16 OriginalVideoMode = (UINT16)-1; + IA32_REGISTER_SET Regs; + UINT16 OriginalVideoMode = (UINT16)-1; // // Set new video mode @@ -970,7 +970,7 @@ Return gBS->SetMem (&Regs, sizeof (Regs), 0); Regs.H.AH = 0x00; Regs.H.AL = (UINT8)NewVideoMode; - LegacyBiosInt86 (0x10, &Regs); + OcLegacyThunkBiosInt86 (&mThunkContext, gLegacy8259, 0x10, &Regs); // // VIDEO - TEXT-MODE CHARGEN - LOAD ROM 8x16 CHARACTER SET (VGA) @@ -982,7 +982,7 @@ Return Regs.H.AH = 0x11; Regs.H.AL = 0x14; Regs.H.BL = 0; - LegacyBiosInt86 (0x10, &Regs); + OcLegacyThunkBiosInt86 (&mThunkContext, gLegacy8259, 0x10, &Regs); } else { // // VESA SuperVGA BIOS - SET SuperVGA VIDEO MODE @@ -998,7 +998,7 @@ Return gBS->SetMem (&Regs, sizeof (Regs), 0); Regs.X.AX = 0x4F02; Regs.X.BX = NewVideoMode; - LegacyBiosInt86 (0x10, &Regs); + OcLegacyThunkBiosInt86 (&mThunkContext, gLegacy8259, 0x10, &Regs); if (Regs.X.AX != 0x004F) { // // SORRY: Cannot set to video mode! @@ -1138,7 +1138,7 @@ Routine Description: InstallInterruptHandler (InterruptVector, SystemTimerHandler); } - InitializeBiosIntCaller (); + OcLegacyThunkInitializeBiosIntCaller (&mThunkContext); // // Install CPU Architectural Protocol and the thunk protocol @@ -1153,129 +1153,3 @@ Routine Description: ASSERT_EFI_ERROR (Status); return Status; } - -VOID -InitializeBiosIntCaller ( - VOID - ) -{ - EFI_STATUS Status; - UINT32 RealModeBufferSize; - UINT32 ExtraStackSize; - EFI_PHYSICAL_ADDRESS LegacyRegionBase; - UINT32 LegacyRegionSize; - - // - // Get LegacyRegion - // - AsmGetThunk16Properties (&RealModeBufferSize, &ExtraStackSize); - LegacyRegionSize = (((RealModeBufferSize + ExtraStackSize) / EFI_PAGE_SIZE) + 1) * EFI_PAGE_SIZE; - LegacyRegionBase = 0x0C0000; - Status = gBS->AllocatePages ( - AllocateMaxAddress, - EfiACPIMemoryNVS, - EFI_SIZE_TO_PAGES (LegacyRegionSize), - &LegacyRegionBase - ); - ASSERT_EFI_ERROR (Status); - - ZeroMem ((VOID *)(UINTN)LegacyRegionBase, LegacyRegionSize); - - mThunkContext.RealModeBuffer = (VOID *)(UINTN)LegacyRegionBase; - mThunkContext.RealModeBufferSize = LegacyRegionSize; - mThunkContext.ThunkAttributes = 3; - AsmPrepareThunk16 (&mThunkContext); -} - -BOOLEAN -EFIAPI -LegacyBiosInt86 ( - IN UINT8 BiosInt, - IN EFI_IA32_REGISTER_SET *Regs - ) -{ - UINTN Status; - BOOLEAN InterruptsEnabled; - IA32_REGISTER_SET ThunkRegSet; - BOOLEAN Ret; - UINT16 *Stack16; - - if (!gLegacy8259 || !mThunkContext.RealModeBuffer) { - return FALSE; - } - - Regs->X.Flags.Reserved1 = 1; - Regs->X.Flags.Reserved2 = 0; - Regs->X.Flags.Reserved3 = 0; - Regs->X.Flags.Reserved4 = 0; - Regs->X.Flags.IOPL = 3; - Regs->X.Flags.NT = 0; - Regs->X.Flags.IF = 1; - Regs->X.Flags.TF = 0; - Regs->X.Flags.CF = 0; - - ZeroMem (&ThunkRegSet, sizeof (ThunkRegSet)); - ThunkRegSet.E.EDI = Regs->E.EDI; - ThunkRegSet.E.ESI = Regs->E.ESI; - ThunkRegSet.E.EBP = Regs->E.EBP; - ThunkRegSet.E.EBX = Regs->E.EBX; - ThunkRegSet.E.EDX = Regs->E.EDX; - ThunkRegSet.E.ECX = Regs->E.ECX; - ThunkRegSet.E.EAX = Regs->E.EAX; - ThunkRegSet.E.DS = Regs->E.DS; - ThunkRegSet.E.ES = Regs->E.ES; - - CopyMem (&(ThunkRegSet.E.EFLAGS), &(Regs->E.EFlags), sizeof (UINT32)); - - // - // The call to Legacy16 is a critical section to EFI - // - InterruptsEnabled = SaveAndDisableInterrupts (); - - // - // Set Legacy16 state. 0x08, 0x70 is legacy 8259 vector bases. - // - Status = gLegacy8259->SetMode (gLegacy8259, Efi8259LegacyMode, NULL, NULL); - ASSERT_EFI_ERROR (Status); - - Stack16 = (UINT16 *)((UINT8 *)mThunkContext.RealModeBuffer + mThunkContext.RealModeBufferSize - sizeof (UINT16)); - Stack16 -= sizeof (ThunkRegSet.E.EFLAGS) / sizeof (UINT16); - CopyMem (Stack16, &ThunkRegSet.E.EFLAGS, sizeof (ThunkRegSet.E.EFLAGS)); - - ThunkRegSet.E.SS = (UINT16)(((UINTN)Stack16 >> 16) << 12); - ThunkRegSet.E.ESP = (UINT16)(UINTN)Stack16; - ThunkRegSet.E.Eip = (UINT16)((volatile UINT32 *)NULL)[BiosInt]; - ThunkRegSet.E.CS = (UINT16)(((volatile UINT32 *)NULL)[BiosInt] >> 16); - - mThunkContext.RealModeState = &ThunkRegSet; - AsmThunk16 (&mThunkContext); - - // - // Restore protected mode interrupt state - // - Status = gLegacy8259->SetMode (gLegacy8259, Efi8259ProtectedMode, NULL, NULL); - ASSERT_EFI_ERROR (Status); - - // - // End critical section - // - SetInterruptState (InterruptsEnabled); - - Regs->E.EDI = ThunkRegSet.E.EDI; - Regs->E.ESI = ThunkRegSet.E.ESI; - Regs->E.EBP = ThunkRegSet.E.EBP; - Regs->E.EBX = ThunkRegSet.E.EBX; - Regs->E.EDX = ThunkRegSet.E.EDX; - Regs->E.ECX = ThunkRegSet.E.ECX; - Regs->E.EAX = ThunkRegSet.E.EAX; - Regs->E.SS = ThunkRegSet.E.SS; - Regs->E.CS = ThunkRegSet.E.CS; - Regs->E.DS = ThunkRegSet.E.DS; - Regs->E.ES = ThunkRegSet.E.ES; - - CopyMem (&(Regs->E.EFlags), &(ThunkRegSet.E.EFLAGS), sizeof (UINT32)); - - Ret = (BOOLEAN)(Regs->E.EFlags.CF == 1); - - return Ret; -} diff --git a/Legacy/BootPlatform/CpuDxe/CpuDxe.h b/Legacy/BootPlatform/CpuDxe/CpuDxe.h index a28bd5cf330..10010d3ff60 100644 --- a/Legacy/BootPlatform/CpuDxe/CpuDxe.h +++ b/Legacy/BootPlatform/CpuDxe/CpuDxe.h @@ -26,6 +26,7 @@ Module Name: #include #include #include +#include #include #include @@ -130,11 +131,4 @@ InitDescriptor ( VOID ); -BOOLEAN -EFIAPI -LegacyBiosInt86 ( - IN UINT8 BiosInt, - IN EFI_IA32_REGISTER_SET *Regs - ); - #endif diff --git a/Legacy/BootPlatform/CpuDxe/CpuDxe.inf b/Legacy/BootPlatform/CpuDxe/CpuDxe.inf index d105af515c1..214e665532b 100644 --- a/Legacy/BootPlatform/CpuDxe/CpuDxe.inf +++ b/Legacy/BootPlatform/CpuDxe/CpuDxe.inf @@ -26,6 +26,7 @@ ENTRY_POINT = InitializeCpu [Packages] + OpenCorePkg/OpenCorePkg.dec OpenCorePkg/OpenDuetPkg.dec MdePkg/MdePkg.dec OvmfPkg/OvmfPkg.dec @@ -35,6 +36,7 @@ PrintLib UefiBootServicesTableLib BaseMemoryLib + OcLegacyThunkLib [Sources.Ia32] Ia32/CpuInterrupt.nasm diff --git a/Legacy/BootPlatform/BiosVideo/LegacyBiosThunk.c b/Library/OcLegacyThunkLib/OcLegacyThunkLib.c similarity index 83% rename from Legacy/BootPlatform/BiosVideo/LegacyBiosThunk.c rename to Library/OcLegacyThunkLib/OcLegacyThunkLib.c index 67ae8836260..421da8a3f79 100644 --- a/Legacy/BootPlatform/BiosVideo/LegacyBiosThunk.c +++ b/Library/OcLegacyThunkLib/OcLegacyThunkLib.c @@ -1,18 +1,20 @@ /** @file - Provide legacy thunk interface for accessing Bios Video Rom. - -Copyright (c) 2006 - 2007, Intel Corporation. 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. + This file implements thunking to legacy 16-bit environment. + Copyright (c) 2023, Goldfish64. All rights reserved.
+ Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause **/ -#include "BiosVideo.h" +#include + +#include +#include +#include +#include +#include +#include +#include /** Initialize legacy environment for BIOS INI caller. @@ -20,7 +22,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. @param ThunkContext the instance pointer of THUNK_CONTEXT **/ VOID -InitializeBiosIntCaller ( +OcLegacyThunkInitializeBiosIntCaller ( THUNK_CONTEXT *ThunkContext ) { @@ -63,7 +65,7 @@ InitializeBiosIntCaller ( **/ VOID -InitializeInterruptRedirection ( +OcLegacyThunkInitializeInterruptRedirection ( IN EFI_LEGACY_8259_PROTOCOL *Legacy8259 ) { @@ -133,10 +135,11 @@ InitializeInterruptRedirection ( **/ BOOLEAN EFIAPI -LegacyBiosInt86 ( - IN BIOS_VIDEO_DEV *BiosDev, - IN UINT8 BiosInt, - IN IA32_REGISTER_SET *Regs +OcLegacyThunkBiosInt86 ( + IN THUNK_CONTEXT *ThunkContext, + IN EFI_LEGACY_8259_PROTOCOL *Legacy8259, + IN UINT8 BiosInt, + IN IA32_REGISTER_SET *Regs ) { UINTN Status; @@ -174,23 +177,23 @@ LegacyBiosInt86 ( // // Set Legacy16 state. 0x08, 0x70 is legacy 8259 vector bases. // - Status = BiosDev->Legacy8259->SetMode (BiosDev->Legacy8259, Efi8259LegacyMode, NULL, NULL); + Status = Legacy8259->SetMode (Legacy8259, Efi8259LegacyMode, NULL, NULL); ASSERT_EFI_ERROR (Status); - Stack16 = (UINT16 *)((UINT8 *)BiosDev->ThunkContext->RealModeBuffer + BiosDev->ThunkContext->RealModeBufferSize - sizeof (UINT16)); + Stack16 = (UINT16 *)((UINT8 *)ThunkContext->RealModeBuffer + ThunkContext->RealModeBufferSize - sizeof (UINT16)); ThunkRegSet.E.SS = (UINT16)(((UINTN)Stack16 >> 16) << 12); ThunkRegSet.E.ESP = (UINT16)(UINTN)Stack16; ThunkRegSet.E.Eip = (UINT16)((volatile UINT32 *)NULL)[BiosInt]; ThunkRegSet.E.CS = (UINT16)(((volatile UINT32 *)NULL)[BiosInt] >> 16); - BiosDev->ThunkContext->RealModeState = &ThunkRegSet; - AsmThunk16 (BiosDev->ThunkContext); + ThunkContext->RealModeState = &ThunkRegSet; + AsmThunk16 (ThunkContext); // // Restore protected mode interrupt state // - Status = BiosDev->Legacy8259->SetMode (BiosDev->Legacy8259, Efi8259ProtectedMode, NULL, NULL); + Status = Legacy8259->SetMode (Legacy8259, Efi8259ProtectedMode, NULL, NULL); ASSERT_EFI_ERROR (Status); // diff --git a/Library/OcLegacyThunkLib/OcLegacyThunkLib.inf b/Library/OcLegacyThunkLib/OcLegacyThunkLib.inf new file mode 100644 index 00000000000..7627d27a196 --- /dev/null +++ b/Library/OcLegacyThunkLib/OcLegacyThunkLib.inf @@ -0,0 +1,49 @@ +## @file +# +# Component description file for the library handling thunking to legacy 16-bit environment. +# +# Copyright (C) 2023, Goldfish64. 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. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = OcLegacyThunkLib + FILE_GUID = 133D1AF1-8BB5-4F12-AC93-2DF858D9935F + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = OcLegacyThunkLib|PEIM DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_DRIVER UEFI_APPLICATION DXE_SMM_DRIVER + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + OcLegacyThunkLib.c + +[Packages] + MdePkg/MdePkg.dec + OpenCorePkg/OpenCorePkg.dec + OvmfPkg/OvmfPkg.dec + +[Protocols] + gEfiLegacy8259ProtocolGuid + +[LibraryClasses] + BaseMemoryLib + DebugLib + MemoryAllocationLib + UefiBootServicesTableLib + UefiLib diff --git a/OpenCorePkg.dec b/OpenCorePkg.dec index 49ac93973c5..ee0e77bdabe 100755 --- a/OpenCorePkg.dec +++ b/OpenCorePkg.dec @@ -900,6 +900,9 @@ ## @libraryclass OcInputLib|Include/Acidanthera/Library/OcInputLib.h + ## @libraryclass + OcLegacyThunkLib|Include/Acidanthera/Library/OcLegacyThunkLib.h + ## @libraryclass OcLogAggregatorLib|Include/Acidanthera/Library/OcLogAggregatorLib.h diff --git a/OpenCorePkg.dsc b/OpenCorePkg.dsc index 212bab3be88..01552ceeeae 100755 --- a/OpenCorePkg.dsc +++ b/OpenCorePkg.dsc @@ -114,6 +114,7 @@ OcHeciLib|OpenCorePkg/Library/OcHeciLib/OcHeciLib.inf OcHiiDatabaseLocalLib|OpenCorePkg/Library/OcHiiDatabaseLib/OcHiiDatabaseLocalLib.inf OcInputLib|OpenCorePkg/Library/OcInputLib/OcInputLib.inf + OcLegacyThunkLib|OpenCorePkg/Library/OcLegacyThunkLib/OcLegacyThunkLib.inf OcLogAggregatorLib|OpenCorePkg/Library/OcLogAggregatorLib/OcLogAggregatorLib.inf OcMachoLib|OpenCorePkg/Library/OcMachoLib/OcMachoLib.inf OcMacInfoLib|OpenCorePkg/Library/OcMacInfoLib/OcMacInfoLib.inf diff --git a/OpenDuetPkg.dsc b/OpenDuetPkg.dsc index 97a30d07475..b7af0e37624 100644 --- a/OpenDuetPkg.dsc +++ b/OpenDuetPkg.dsc @@ -106,6 +106,7 @@ OcDevicePathLib|OpenCorePkg/Library/OcDevicePathLib/OcDevicePathLib.inf OcFileLib|OpenCorePkg/Library/OcFileLib/OcFileLib.inf OcGuardLib|OpenCorePkg/Library/OcGuardLib/OcGuardLib.inf + OcLegacyThunkLib|OpenCorePkg/Library/OcLegacyThunkLib/OcLegacyThunkLib.inf OcMemoryLib|OpenCorePkg/Library/OcMemoryLib/OcMemoryLib.inf OcMiscLib|OpenCorePkg/Library/OcMiscLib/OcMiscLib.inf OcStringLib|OpenCorePkg/Library/OcStringLib/OcStringLib.inf From 83af80a2cf535497fe752912e4821ac8cab8cd29 Mon Sep 17 00:00:00 2001 From: John Davis Date: Mon, 7 Aug 2023 19:52:14 -0500 Subject: [PATCH 19/55] OcLegacyThunkLib: Fix codestyle --- Library/OcLegacyThunkLib/OcLegacyThunkLib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Library/OcLegacyThunkLib/OcLegacyThunkLib.c b/Library/OcLegacyThunkLib/OcLegacyThunkLib.c index 421da8a3f79..aec83a87c7a 100644 --- a/Library/OcLegacyThunkLib/OcLegacyThunkLib.c +++ b/Library/OcLegacyThunkLib/OcLegacyThunkLib.c @@ -185,8 +185,8 @@ OcLegacyThunkBiosInt86 ( ThunkRegSet.E.SS = (UINT16)(((UINTN)Stack16 >> 16) << 12); ThunkRegSet.E.ESP = (UINT16)(UINTN)Stack16; - ThunkRegSet.E.Eip = (UINT16)((volatile UINT32 *)NULL)[BiosInt]; - ThunkRegSet.E.CS = (UINT16)(((volatile UINT32 *)NULL)[BiosInt] >> 16); + ThunkRegSet.E.Eip = (UINT16)((volatile UINT32 *)NULL)[BiosInt]; + ThunkRegSet.E.CS = (UINT16)(((volatile UINT32 *)NULL)[BiosInt] >> 16); ThunkContext->RealModeState = &ThunkRegSet; AsmThunk16 (ThunkContext); From af725143d75209b802da589f733c8b6c1ddaadf1 Mon Sep 17 00:00:00 2001 From: John Davis Date: Mon, 7 Aug 2023 20:06:10 -0500 Subject: [PATCH 20/55] OcLegacyThunkLib: Fix comments --- Include/Acidanthera/Library/OcLegacyThunkLib.h | 11 ++++++----- Library/OcLegacyThunkLib/OcLegacyThunkLib.c | 11 ++++++----- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Include/Acidanthera/Library/OcLegacyThunkLib.h b/Include/Acidanthera/Library/OcLegacyThunkLib.h index 4c2a97c3056..991fa07a210 100644 --- a/Include/Acidanthera/Library/OcLegacyThunkLib.h +++ b/Include/Acidanthera/Library/OcLegacyThunkLib.h @@ -23,7 +23,7 @@ /** Initialize legacy environment for BIOS INI caller. - @param ThunkContext the instance pointer of THUNK_CONTEXT + @param ThunkContext The instance pointer of THUNK_CONTEXT. **/ VOID OcLegacyThunkInitializeBiosIntCaller ( @@ -50,13 +50,14 @@ OcLegacyThunkInitializeInterruptRedirection ( of BiosInt. Regs will contain the 16-bit register context on entry and exit. - @param This Protocol instance pointer. - @param BiosInt Processor interrupt vector to invoke - @param Reg Register contexted passed into (and returned) from thunk to 16-bit mode + @param ThunkContext The instance pointer of THUNK_CONTEXT. + @param Legacy8259 Instance pointer for EFI_LEGACY_8259_PROTOCOL. + @param BiosInt Processor interrupt vector to invoke + @param Reg Register contexted passed into (and returned) from thunk to 16-bit mode @retval TRUE Thunk completed, and there were no BIOS errors in the target code. See Regs for status. - @retval FALSE There was a BIOS erro in the target code. + @retval FALSE There was a BIOS error in the target code. **/ BOOLEAN EFIAPI diff --git a/Library/OcLegacyThunkLib/OcLegacyThunkLib.c b/Library/OcLegacyThunkLib/OcLegacyThunkLib.c index aec83a87c7a..24e10724f11 100644 --- a/Library/OcLegacyThunkLib/OcLegacyThunkLib.c +++ b/Library/OcLegacyThunkLib/OcLegacyThunkLib.c @@ -19,7 +19,7 @@ /** Initialize legacy environment for BIOS INI caller. - @param ThunkContext the instance pointer of THUNK_CONTEXT + @param ThunkContext The instance pointer of THUNK_CONTEXT. **/ VOID OcLegacyThunkInitializeBiosIntCaller ( @@ -125,13 +125,14 @@ OcLegacyThunkInitializeInterruptRedirection ( of BiosInt. Regs will contain the 16-bit register context on entry and exit. - @param This Protocol instance pointer. - @param BiosInt Processor interrupt vector to invoke - @param Reg Register contexted passed into (and returned) from thunk to 16-bit mode + @param ThunkContext The instance pointer of THUNK_CONTEXT. + @param Legacy8259 Instance pointer for EFI_LEGACY_8259_PROTOCOL. + @param BiosInt Processor interrupt vector to invoke + @param Reg Register contexted passed into (and returned) from thunk to 16-bit mode @retval TRUE Thunk completed, and there were no BIOS errors in the target code. See Regs for status. - @retval FALSE There was a BIOS erro in the target code. + @retval FALSE There was a BIOS error in the target code. **/ BOOLEAN EFIAPI From 4776b9873d45090f6c330f791dcf6235a7690699 Mon Sep 17 00:00:00 2001 From: John Davis Date: Tue, 8 Aug 2023 17:11:01 -0500 Subject: [PATCH 21/55] OcLegacyThunkLib: Return status from init functions --- Include/Acidanthera/Library/OcLegacyThunkLib.h | 4 ++-- Legacy/BootPlatform/BiosVideo/BiosVideo.c | 11 +++++++++-- Legacy/BootPlatform/BlockIoDxe/BiosBlkIo.c | 11 +++++++++-- Legacy/BootPlatform/CpuDxe/CpuDxe.c | 3 ++- Library/OcLegacyThunkLib/OcLegacyThunkLib.c | 16 ++++++++++++---- 5 files changed, 34 insertions(+), 11 deletions(-) diff --git a/Include/Acidanthera/Library/OcLegacyThunkLib.h b/Include/Acidanthera/Library/OcLegacyThunkLib.h index 991fa07a210..cb651446aa5 100644 --- a/Include/Acidanthera/Library/OcLegacyThunkLib.h +++ b/Include/Acidanthera/Library/OcLegacyThunkLib.h @@ -25,7 +25,7 @@ @param ThunkContext The instance pointer of THUNK_CONTEXT. **/ -VOID +EFI_STATUS OcLegacyThunkInitializeBiosIntCaller ( IN OUT THUNK_CONTEXT *ThunkContext ); @@ -40,7 +40,7 @@ OcLegacyThunkInitializeBiosIntCaller ( @param Legacy8259 Instance pointer for EFI_LEGACY_8259_PROTOCOL. **/ -VOID +EFI_STATUS OcLegacyThunkInitializeInterruptRedirection ( IN EFI_LEGACY_8259_PROTOCOL *Legacy8259 ); diff --git a/Legacy/BootPlatform/BiosVideo/BiosVideo.c b/Legacy/BootPlatform/BiosVideo/BiosVideo.c index 010c5f625b1..1188832ddf8 100644 --- a/Legacy/BootPlatform/BiosVideo/BiosVideo.c +++ b/Legacy/BootPlatform/BiosVideo/BiosVideo.c @@ -209,8 +209,15 @@ BiosVideoDriverBindingStart ( goto Done; } - OcLegacyThunkInitializeBiosIntCaller (&mThunkContext); - OcLegacyThunkInitializeInterruptRedirection (mLegacy8259); + Status = OcLegacyThunkInitializeBiosIntCaller (&mThunkContext); + if (EFI_ERROR (Status)) { + goto Done; + } + + Status = OcLegacyThunkInitializeInterruptRedirection (mLegacy8259); + if (EFI_ERROR (Status)) { + goto Done; + } } // diff --git a/Legacy/BootPlatform/BlockIoDxe/BiosBlkIo.c b/Legacy/BootPlatform/BlockIoDxe/BiosBlkIo.c index a6598f951ae..10ca63a2fab 100644 --- a/Legacy/BootPlatform/BlockIoDxe/BiosBlkIo.c +++ b/Legacy/BootPlatform/BlockIoDxe/BiosBlkIo.c @@ -255,8 +255,15 @@ BiosBlockIoDriverBindingStart ( goto Error; } - OcLegacyThunkInitializeBiosIntCaller (&mThunkContext); - OcLegacyThunkInitializeInterruptRedirection (Legacy8259); + Status = OcLegacyThunkInitializeBiosIntCaller (&mThunkContext); + if (EFI_ERROR (Status)) { + goto Error; + } + + Status = OcLegacyThunkInitializeInterruptRedirection (Legacy8259); + if (EFI_ERROR (Status)) { + goto Error; + } // // Open the IO Abstraction(s) needed diff --git a/Legacy/BootPlatform/CpuDxe/CpuDxe.c b/Legacy/BootPlatform/CpuDxe/CpuDxe.c index f9acf9db1a0..8d900be4e39 100644 --- a/Legacy/BootPlatform/CpuDxe/CpuDxe.c +++ b/Legacy/BootPlatform/CpuDxe/CpuDxe.c @@ -1138,7 +1138,8 @@ Routine Description: InstallInterruptHandler (InterruptVector, SystemTimerHandler); } - OcLegacyThunkInitializeBiosIntCaller (&mThunkContext); + Status = OcLegacyThunkInitializeBiosIntCaller (&mThunkContext); + ASSERT_EFI_ERROR (Status); // // Install CPU Architectural Protocol and the thunk protocol diff --git a/Library/OcLegacyThunkLib/OcLegacyThunkLib.c b/Library/OcLegacyThunkLib/OcLegacyThunkLib.c index 24e10724f11..f33c788470d 100644 --- a/Library/OcLegacyThunkLib/OcLegacyThunkLib.c +++ b/Library/OcLegacyThunkLib/OcLegacyThunkLib.c @@ -21,7 +21,7 @@ @param ThunkContext The instance pointer of THUNK_CONTEXT. **/ -VOID +EFI_STATUS OcLegacyThunkInitializeBiosIntCaller ( THUNK_CONTEXT *ThunkContext ) @@ -44,7 +44,9 @@ OcLegacyThunkInitializeBiosIntCaller ( EFI_SIZE_TO_PAGES (LegacyRegionSize), &LegacyRegionBase ); - ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } ZeroMem ((VOID *)(UINTN)LegacyRegionBase, LegacyRegionSize); @@ -52,6 +54,7 @@ OcLegacyThunkInitializeBiosIntCaller ( ThunkContext->RealModeBufferSize = LegacyRegionSize; ThunkContext->ThunkAttributes = THUNK_ATTRIBUTE_BIG_REAL_MODE|THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15; AsmPrepareThunk16 (ThunkContext); + return Status; } /** @@ -64,7 +67,7 @@ OcLegacyThunkInitializeBiosIntCaller ( @param Legacy8259 Instance pointer for EFI_LEGACY_8259_PROTOCOL. **/ -VOID +EFI_STATUS OcLegacyThunkInitializeInterruptRedirection ( IN EFI_LEGACY_8259_PROTOCOL *Legacy8259 ) @@ -98,7 +101,9 @@ OcLegacyThunkInitializeInterruptRedirection ( EFI_SIZE_TO_PAGES (LegacyRegionLength), &LegacyRegionBase ); - ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } // // Copy code to legacy region @@ -118,6 +123,9 @@ OcLegacyThunkInitializeInterruptRedirection ( for (Index = 0; Index < 8; Index++) { IdtArray[ProtectedModeBaseVector + Index] = ((EFI_SEGMENT (LegacyRegionBase + Index * 4)) << 16) | (EFI_OFFSET (LegacyRegionBase + Index * 4)); } + + return Status; +} } /** From 7f83d12384b905ac62503e47c0f8f7dae5c553cb Mon Sep 17 00:00:00 2001 From: John Davis Date: Tue, 8 Aug 2023 19:31:19 -0500 Subject: [PATCH 22/55] OcLegacyThunkLib: Fix previous commit --- .../Acidanthera/Library/OcLegacyThunkLib.h | 8 +++ Library/OcLegacyThunkLib/OcLegacyThunkLib.c | 60 +++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/Include/Acidanthera/Library/OcLegacyThunkLib.h b/Include/Acidanthera/Library/OcLegacyThunkLib.h index cb651446aa5..c5e091247f4 100644 --- a/Include/Acidanthera/Library/OcLegacyThunkLib.h +++ b/Include/Acidanthera/Library/OcLegacyThunkLib.h @@ -45,6 +45,14 @@ OcLegacyThunkInitializeInterruptRedirection ( IN EFI_LEGACY_8259_PROTOCOL *Legacy8259 ); +/** + Disconnect all EFI graphics device handles in preparation for calling to legacy mode. +**/ +VOID +OcLegacyThunkDisconnectEfiGraphics ( + VOID + ); + /** Thunk to 16-bit real mode and execute a software interrupt with a vector of BiosInt. Regs will contain the 16-bit register context on entry and diff --git a/Library/OcLegacyThunkLib/OcLegacyThunkLib.c b/Library/OcLegacyThunkLib/OcLegacyThunkLib.c index f33c788470d..35c3099e7bd 100644 --- a/Library/OcLegacyThunkLib/OcLegacyThunkLib.c +++ b/Library/OcLegacyThunkLib/OcLegacyThunkLib.c @@ -126,6 +126,66 @@ OcLegacyThunkInitializeInterruptRedirection ( return Status; } + +/** + Disconnect all EFI graphics device handles in preparation for calling to legacy mode. +**/ +VOID +OcLegacyThunkDisconnectEfiGraphics ( + VOID + ) +{ + EFI_STATUS Status; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN Index; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_CLASSCODE ClassCode; + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiPciIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return; + } + + for (Index = 0; Index < HandleCount; ++Index) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiPciIoProtocolGuid, + (VOID **)&PciIo + ); + + if (EFI_ERROR (Status)) { + continue; + } + + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint8, + PCI_CLASSCODE_OFFSET, + sizeof (PCI_CLASSCODE) / sizeof (UINT8), + &ClassCode + ); + if (EFI_ERROR (Status)) { + continue; + } + + if ((ClassCode.BaseCode == PCI_CLASS_DISPLAY) && (ClassCode.SubClassCode == PCI_CLASS_DISPLAY_VGA)) { + Status = gBS->DisconnectController ( + HandleBuffer[Index], + NULL, + NULL + ); + DEBUG ((DEBUG_INFO, "OCLT: Disconnected graphics controller - %r\n", Status)); + } + } + + FreePool (HandleBuffer); } /** From b4bb4b55df36824e3516d0481736537e20ffcf52 Mon Sep 17 00:00:00 2001 From: John Davis Date: Tue, 8 Aug 2023 19:56:49 -0500 Subject: [PATCH 23/55] OcLegacyThunkLib: Fix previous commit --- Library/OcLegacyThunkLib/OcLegacyThunkLib.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Library/OcLegacyThunkLib/OcLegacyThunkLib.c b/Library/OcLegacyThunkLib/OcLegacyThunkLib.c index 35c3099e7bd..f37eecb9adf 100644 --- a/Library/OcLegacyThunkLib/OcLegacyThunkLib.c +++ b/Library/OcLegacyThunkLib/OcLegacyThunkLib.c @@ -8,13 +8,20 @@ #include -#include -#include +#include + #include -#include #include +#include +#include #include +#include #include +#include +#include + +#include +#include /** Initialize legacy environment for BIOS INI caller. From 7601bc5ad409c80a2aa0b7c0dcc87ee0ed6b1868 Mon Sep 17 00:00:00 2001 From: John Davis Date: Wed, 9 Aug 2023 19:25:24 -0500 Subject: [PATCH 24/55] OcLegacyThunkLib: Add missing package --- Library/OcLegacyThunkLib/OcLegacyThunkLib.c | 8 ++++---- Library/OcLegacyThunkLib/OcLegacyThunkLib.inf | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Library/OcLegacyThunkLib/OcLegacyThunkLib.c b/Library/OcLegacyThunkLib/OcLegacyThunkLib.c index f37eecb9adf..bc3422ae844 100644 --- a/Library/OcLegacyThunkLib/OcLegacyThunkLib.c +++ b/Library/OcLegacyThunkLib/OcLegacyThunkLib.c @@ -184,10 +184,10 @@ OcLegacyThunkDisconnectEfiGraphics ( if ((ClassCode.BaseCode == PCI_CLASS_DISPLAY) && (ClassCode.SubClassCode == PCI_CLASS_DISPLAY_VGA)) { Status = gBS->DisconnectController ( - HandleBuffer[Index], - NULL, - NULL - ); + HandleBuffer[Index], + NULL, + NULL + ); DEBUG ((DEBUG_INFO, "OCLT: Disconnected graphics controller - %r\n", Status)); } } diff --git a/Library/OcLegacyThunkLib/OcLegacyThunkLib.inf b/Library/OcLegacyThunkLib/OcLegacyThunkLib.inf index 7627d27a196..432491c9219 100644 --- a/Library/OcLegacyThunkLib/OcLegacyThunkLib.inf +++ b/Library/OcLegacyThunkLib/OcLegacyThunkLib.inf @@ -37,6 +37,7 @@ MdePkg/MdePkg.dec OpenCorePkg/OpenCorePkg.dec OvmfPkg/OvmfPkg.dec + UefiCpuPkg/UefiCpuPkg.dec [Protocols] gEfiLegacy8259ProtocolGuid From 9a29c0126428254570dce398205504e9284f06d2 Mon Sep 17 00:00:00 2001 From: John Davis Date: Wed, 9 Aug 2023 19:35:32 -0500 Subject: [PATCH 25/55] OpenLegacyBoot: Move legacy functionality into standalone driver --- .../Acidanthera/Library/OcBootManagementLib.h | 43 +-- .../Acidanthera/Library/OcLegacyThunkLib.h | 12 + Library/OcBootManagementLib/BootEntryInfo.c | 28 -- .../OcBootManagementLib/BootEntryManagement.c | 334 ++++-------------- .../BootManagementInternal.h | 34 -- .../OcBootManagementLib/DefaultEntryChoice.c | 29 +- .../OcBootManagementLib/OcBootManagementLib.c | 5 - .../OcBootManagementLib.inf | 3 - .../OcBootManagementLib/PolicyManagement.c | 3 +- Library/OcLegacyThunkLib/OcLegacyThunkLib.c | 174 +++++++++ OpenCorePkg.dsc | 1 + Platform/OpenLegacyBoot/LegacyBootInternal.h | 44 +++ .../OpenLegacyBoot}/LegacyBootSupport.c | 139 ++++++-- Platform/OpenLegacyBoot/OpenLegacyBoot.c | 277 +++++++++++++++ Platform/OpenLegacyBoot/OpenLegacyBoot.inf | 44 +++ Platform/ResetNvramEntry/ResetNvramEntry.c | 3 +- Platform/ToggleSipEntry/ToggleSipEntry.c | 3 +- build_oc.tool | 1 + 18 files changed, 754 insertions(+), 423 deletions(-) create mode 100644 Platform/OpenLegacyBoot/LegacyBootInternal.h rename {Library/OcBootManagementLib => Platform/OpenLegacyBoot}/LegacyBootSupport.c (78%) create mode 100644 Platform/OpenLegacyBoot/OpenLegacyBoot.c create mode 100644 Platform/OpenLegacyBoot/OpenLegacyBoot.inf diff --git a/Include/Acidanthera/Library/OcBootManagementLib.h b/Include/Acidanthera/Library/OcBootManagementLib.h index 10fcc44e92e..7ce19037501 100644 --- a/Include/Acidanthera/Library/OcBootManagementLib.h +++ b/Include/Acidanthera/Library/OcBootManagementLib.h @@ -153,25 +153,6 @@ typedef UINT32 OC_BOOT_ENTRY_TYPE; #define OC_BOOT_EXTERNAL_TOOL BIT7 #define OC_BOOT_SYSTEM BIT8 -/** - Legacy system boot type. -**/ -typedef enum OC_LEGACY_BOOT_TYPE_ { - OcLegacyBootTypeNone, - OcLegacyBootTypeApple, - OcLegacyBootTypeLegacyBios -} OC_LEGACY_BOOT_TYPE; - -/** - Legacy operating system type. -**/ -typedef enum OC_LEGACY_OS_TYPE_ { - OcLegacyOsTypeNone, - OcLegacyOsTypeWindowsNtldr, - OcLegacyOsTypeWindowsBootmgr, - OcLegacyOsTypeIsoLinux -} OC_LEGACY_OS_TYPE; - /** Picker mode. **/ @@ -209,7 +190,8 @@ typedef enum OC_PICKER_MODE_ { typedef EFI_STATUS (*OC_BOOT_SYSTEM_ACTION) ( - IN OUT OC_PICKER_CONTEXT *PickerContext + IN OUT OC_PICKER_CONTEXT *PickerContext, + IN VOID *ActionContext ); /** @@ -231,6 +213,10 @@ typedef struct OC_BOOT_ENTRY_ { // OC_BOOT_SYSTEM_ACTION SystemAction; // + // Context for action to perform on execution for system entries. + // + VOID *SystemActionContext; + // // Id under which to save entry as default. // CHAR16 *Id; @@ -281,11 +267,6 @@ typedef struct OC_BOOT_ENTRY_ { // BOOLEAN IsAppleInstaller; // - // Describes type of legacy OS to be booted. - // Set when entry is to be booted through legacy interface. - // - OC_LEGACY_OS_TYPE LegacyOsType; - // // Should make this option default boot option. // BOOLEAN SetDefault; @@ -372,10 +353,6 @@ struct OC_BOOT_FILESYSTEM_ { // BOOLEAN LoaderFs; // - // Legacy bootsector type. - // - OC_LEGACY_OS_TYPE LegacyOsType; - // // Contains recovery on the filesystem. // BOOLEAN HasSelfRecovery; @@ -628,6 +605,10 @@ typedef struct { // OC_BOOT_SYSTEM_ACTION SystemAction; // + // System action context. Boot Entry Protocol only. Optional. + // + VOID *SystemActionContext; + // // Audio base path for system action. Boot Entry Protocol only. Optional. // CHAR8 *AudioBasePath; @@ -977,10 +958,6 @@ struct OC_PICKER_CONTEXT_ { // CONST CHAR8 *InstanceIdentifier; // - // Legacy boot method type. - // - OC_LEGACY_BOOT_TYPE LegacyBootType; - // // Enable polling boot arguments. // BOOLEAN PollAppleHotKeys; diff --git a/Include/Acidanthera/Library/OcLegacyThunkLib.h b/Include/Acidanthera/Library/OcLegacyThunkLib.h index c5e091247f4..0808cadb1bd 100644 --- a/Include/Acidanthera/Library/OcLegacyThunkLib.h +++ b/Include/Acidanthera/Library/OcLegacyThunkLib.h @@ -76,4 +76,16 @@ OcLegacyThunkBiosInt86 ( IN IA32_REGISTER_SET *Regs ); +BOOLEAN +EFIAPI +OcLegacyThunkFarCall86 ( + IN THUNK_CONTEXT *ThunkContext, + IN EFI_LEGACY_8259_PROTOCOL *Legacy8259, + IN UINT16 Segment, + IN UINT16 Offset, + IN IA32_REGISTER_SET *Regs, + IN VOID *Stack, + IN UINTN StackSize + ); + #endif // OC_LEGACY_THUNK_LIB_H diff --git a/Library/OcBootManagementLib/BootEntryInfo.c b/Library/OcBootManagementLib/BootEntryInfo.c index 984944e7b8b..b150ea334bb 100644 --- a/Library/OcBootManagementLib/BootEntryInfo.c +++ b/Library/OcBootManagementLib/BootEntryInfo.c @@ -890,31 +890,3 @@ InternalDescribeBootEntry ( return EFI_SUCCESS; } - -EFI_STATUS -InternalDescribeLegacyBootEntry ( - IN OC_BOOT_CONTEXT *BootContext, - IN OC_LEGACY_OS_TYPE LegacyOsType, - IN OUT OC_BOOT_ENTRY *BootEntry - ) -{ - ASSERT (LegacyOsType != OcLegacyOsTypeNone); - - // - // Name is based on previously detected boot sector type. - // - switch (LegacyOsType) { - case OcLegacyOsTypeWindowsBootmgr: - case OcLegacyOsTypeWindowsNtldr: - BootEntry->Type = OC_BOOT_WINDOWS; - BootEntry->Name = AllocateCopyPool (sizeof (L"Windows (legacy)"), L"Windows (legacy)"); - break; - - default: - BootEntry->Type = OC_BOOT_UNKNOWN; - BootEntry->Name = AllocateCopyPool (sizeof (L"Unknown OS (legacy)"), L"Unknown OS (legacy)"); - break; - } - - return EFI_SUCCESS; -} diff --git a/Library/OcBootManagementLib/BootEntryManagement.c b/Library/OcBootManagementLib/BootEntryManagement.c index af98f546de9..c27932c6292 100644 --- a/Library/OcBootManagementLib/BootEntryManagement.c +++ b/Library/OcBootManagementLib/BootEntryManagement.c @@ -720,10 +720,11 @@ InternalAddBootEntryFromCustomEntry ( )); if (CustomEntry->SystemAction) { - BootEntry->Type = OC_BOOT_SYSTEM; - BootEntry->SystemAction = CustomEntry->SystemAction; - BootEntry->AudioBasePath = CustomEntry->AudioBasePath; - BootEntry->AudioBaseType = CustomEntry->AudioBaseType; + BootEntry->Type = OC_BOOT_SYSTEM; + BootEntry->SystemAction = CustomEntry->SystemAction; + BootEntry->SystemActionContext = CustomEntry->SystemActionContext; + BootEntry->AudioBasePath = CustomEntry->AudioBasePath; + BootEntry->AudioBaseType = CustomEntry->AudioBaseType; } else if (CustomEntry->Tool) { BootEntry->Type = OC_BOOT_EXTERNAL_TOOL; UnicodeUefiSlashes (PathName); @@ -1173,100 +1174,6 @@ AddBootEntryFromSelfRecovery ( return Status; } -/** - Create bootable entries from legacy boot partitons. - - @param[in,out] BootContext Context of filesystems. - @param[in,out] FileSystem Filesystem to scan for recovery. - - @retval EFI_SUCCESS on success. -**/ -STATIC -EFI_STATUS -AddBootEntryFromLegacyPartition ( - IN OUT OC_BOOT_CONTEXT *BootContext, - IN OUT OC_BOOT_FILESYSTEM *FileSystem - ) -{ - EFI_STATUS Status; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - OC_BOOT_ENTRY *BootEntry; - - // - // Only support legacy filesystems. - // - if (FileSystem->LegacyOsType == OcLegacyOsTypeNone) { - return EFI_UNSUPPORTED; - } - - Status = gBS->HandleProtocol ( - FileSystem->Handle, - &gEfiDevicePathProtocolGuid, - (VOID **)&DevicePath - ); - if (EFI_ERROR (Status)) { - return EFI_UNSUPPORTED; - } - - DebugPrintDevicePath (DEBUG_INFO, "OCB: Adding legacy entry for disk", DevicePath); - - // - // Allocate, initialise, and describe boot entry. - // - BootEntry = AllocateZeroPool (sizeof (*BootEntry)); - if (BootEntry == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - BootEntry->DevicePath = DuplicateDevicePath (DevicePath); - if (BootEntry->DevicePath == NULL) { - FreePool (BootEntry); - return EFI_OUT_OF_RESOURCES; - } - - BootEntry->IsExternal = FileSystem->External; - BootEntry->LegacyOsType = FileSystem->LegacyOsType; - BootEntry->LaunchInText = TRUE; - - // - // Load options are set based on type of disk. - // Internal disk = "HD" - // External disk = "USB" - // Optical disk = "CD" - // - if (BootEntry->IsExternal) { - if (OcIsDiskCdRom (BootEntry->DevicePath)) { - BootEntry->LoadOptionsSize = L_STR_SIZE ("CD"); - BootEntry->LoadOptions = AllocateCopyPool (L_STR_SIZE ("CD"), "CD"); - } else { - BootEntry->LoadOptionsSize = L_STR_SIZE ("USB"); - BootEntry->LoadOptions = AllocateCopyPool (L_STR_SIZE ("USB"), "USB"); - } - } else { - BootEntry->LoadOptionsSize = L_STR_SIZE ("HD"); - BootEntry->LoadOptions = AllocateCopyPool (L_STR_SIZE ("HD"), "HD"); - } - - if (BootEntry->LoadOptions == NULL) { - FreePool (BootEntry); - return EFI_OUT_OF_RESOURCES; - } - - Status = InternalDescribeLegacyBootEntry (BootContext, FileSystem->LegacyOsType, BootEntry); - if (EFI_ERROR (Status)) { - FreePool (BootEntry); - return Status; - } - - RegisterBootOption ( - BootContext, - FileSystem, - BootEntry - ); - - return EFI_SUCCESS; -} - /** Create bootable entries from boot options. @@ -1303,13 +1210,11 @@ AddBootEntryFromBootOption ( EFI_DEVICE_PATH_PROTOCOL *DevicePath; EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath; EFI_DEVICE_PATH_PROTOCOL *ExpandedDevicePath; - EFI_DEVICE_PATH_PROTOCOL *ActivePartitionDevicePath; EFI_HANDLE FileSystemHandle; OC_BOOT_FILESYSTEM *FileSystem; UINTN DevicePathSize; INTN NumPatchedNodes; BOOLEAN IsAppleLegacy; - BOOLEAN IsLegacyEntry; BOOLEAN IsRoot; EFI_LOAD_OPTION *LoadOption; UINTN LoadOptionSize; @@ -1358,7 +1263,6 @@ AddBootEntryFromBootOption ( // BootCamp device path will point to disk instead of partition. // IsAppleLegacy = InternalIsAppleLegacyLoadApp (DevicePath); - IsLegacyEntry = FALSE; if (IsAppleLegacy) { FreePool (DevicePath); Status = GetVariable2 ( @@ -1400,15 +1304,7 @@ AddBootEntryFromBootOption ( } // - // Handle Apple BootCamp device path. - // - // If we have a legacy installation of Windows in place, Device Path - // will point to disk containing the active partition to boot. This will - // need to be expanded to the full Device Path of the active partition. - // - // If not, locate the EFI partition Device Path to boot Windows in UEFI mode. - // Installing Windows on Macs that normally use legacy mode for Boot Camp - // will exhibit this behavior if Windows is selected as a startup disk from within macOS. + // Expand BootCamp device path to EFI partition device path. // if (IsAppleLegacy) { // @@ -1421,36 +1317,12 @@ AddBootEntryFromBootOption ( return EFI_NOT_FOUND; } - // - // Attempt to locate active MBR partition Device Path. - // - RemainingDevicePath = DevicePath; - ActivePartitionDevicePath = OcDiskFindActiveMbrPartitionPath ( - DevicePath, - &DevicePathSize - ); - if (ActivePartitionDevicePath != NULL) { - DevicePath = ActivePartitionDevicePath; - Status = gBS->LocateDevicePath ( - &gEfiBlockIoProtocolGuid, - &ActivePartitionDevicePath, - &FileSystemHandle - ); - - if (!EFI_ERROR (Status)) { - IsLegacyEntry = TRUE; - } - - // - // Expand BootCamp device path to EFI partition device path. - // - } else { - DevicePath = OcDiskFindSystemPartitionPath ( - DevicePath, - &DevicePathSize, - &FileSystemHandle - ); - } + RemainingDevicePath = DevicePath; + DevicePath = OcDiskFindSystemPartitionPath ( + DevicePath, + &DevicePathSize, + &FileSystemHandle + ); FreePool (RemainingDevicePath); @@ -1470,9 +1342,8 @@ AddBootEntryFromBootOption ( } // - // The Device Path returned by OcDiskFindActiveMbrPartitionPath() and - // OcDiskFindSystemPartitionPath() is a pointer to an installed protocol. - // Duplicate it so we own the memory. + // The Device Path returned by OcDiskFindSystemPartitionPath() is a pointer + // to an installed protocol. Duplicate it so we own the memory. // if (DevicePath != NULL) { DevicePath = AllocateCopyPool (DevicePathSize, DevicePath); @@ -1695,39 +1566,32 @@ AddBootEntryFromBootOption ( FreePool (DevicePath); } - if (IsLegacyEntry) { - Status = AddBootEntryFromLegacyPartition ( - BootContext, - FileSystem - ); - } else { - // - // We may have a Boot#### entry pointing to macOS with full DP (up to boot.efi), - // so IsRoot will be true. However, if this is APFS, we may still have: - // - Recovery for this macOS. - // - Another macOS installation. - // We can only detect them with bless, so we invoke bless in deduplication mode. - // We also detect only the Core Apple Boot Policy predefined booter paths to - // avoid detection of e.g. generic booters (such as BOOTx64) to avoid - // duplicates. - // - // The amount of paths depends on the kind of the entry. - // - If this is a root entry (i.e. it points to the partition) - // we invoke full bless, as it may be Windows entry created by legacy NVRAM script. - // - If this is a full entry (i.e. it points to the bootloader) - // we invoke partial bless, which ignores BOOTx64.efi. - // Ignoring BOOTx64.efi is important as we may already have bootmgfw.efi as our entry, - // and we do not want to see Windows added twice. - // - Status = AddBootEntryFromBless ( - BootContext, - FileSystem, - gAppleBootPolicyPredefinedPaths, - IsRoot ? gAppleBootPolicyNumPredefinedPaths : gAppleBootPolicyCoreNumPredefinedPaths, - LazyScan, - TRUE - ); - } + // + // We may have a Boot#### entry pointing to macOS with full DP (up to boot.efi), + // so IsRoot will be true. However, if this is APFS, we may still have: + // - Recovery for this macOS. + // - Another macOS installation. + // We can only detect them with bless, so we invoke bless in deduplication mode. + // We also detect only the Core Apple Boot Policy predefined booter paths to + // avoid detection of e.g. generic booters (such as BOOTx64) to avoid + // duplicates. + // + // The amount of paths depends on the kind of the entry. + // - If this is a root entry (i.e. it points to the partition) + // we invoke full bless, as it may be Windows entry created by legacy NVRAM script. + // - If this is a full entry (i.e. it points to the bootloader) + // we invoke partial bless, which ignores BOOTx64.efi. + // Ignoring BOOTx64.efi is important as we may already have bootmgfw.efi as our entry, + // and we do not want to see Windows added twice. + // + Status = AddBootEntryFromBless ( + BootContext, + FileSystem, + gAppleBootPolicyPredefinedPaths, + IsRoot ? gAppleBootPolicyNumPredefinedPaths : gAppleBootPolicyCoreNumPredefinedPaths, + LazyScan, + TRUE + ); return Status; } @@ -1745,10 +1609,9 @@ AddBootEntryFromBootOption ( STATIC EFI_STATUS AddFileSystemEntry ( - IN OUT OC_BOOT_CONTEXT *BootContext, - IN EFI_HANDLE FileSystemHandle, - IN OC_LEGACY_OS_TYPE LegacyOsType, - OUT OC_BOOT_FILESYSTEM **FileSystemEntry OPTIONAL + IN OUT OC_BOOT_CONTEXT *BootContext, + IN EFI_HANDLE FileSystemHandle, + OUT OC_BOOT_FILESYSTEM **FileSystemEntry OPTIONAL ) { EFI_STATUS Status; @@ -1762,7 +1625,6 @@ AddFileSystemEntry ( Status = InternalCheckScanPolicy ( FileSystemHandle, BootContext->PickerContext->ScanPolicy, - LegacyOsType != OcLegacyOsTypeNone, &IsExternal ); @@ -1783,11 +1645,10 @@ AddFileSystemEntry ( DEBUG (( DEBUG_INFO, - "OCB: Adding fs %p (E:%d|L:%d|B:%d|P:%r) - %s\n", + "OCB: Adding fs %p (E:%d|L:%d|P:%r) - %s\n", FileSystemHandle, IsExternal, LoaderFs, - LegacyOsType, Status, OC_HUMAN_STRING (TextDevicePath) )); @@ -1812,7 +1673,6 @@ AddFileSystemEntry ( Entry->RecoveryFs = NULL; Entry->External = IsExternal; Entry->LoaderFs = LoaderFs; - Entry->LegacyOsType = LegacyOsType; Entry->HasSelfRecovery = FALSE; InsertTailList (&BootContext->FileSystems, &Entry->Link); ++BootContext->FileSystemCount; @@ -1956,7 +1816,7 @@ InternalFileSystemForHandle ( return NULL; } - Status = AddFileSystemEntry (BootContext, FileSystemHandle, FALSE, &FileSystem); + Status = AddFileSystemEntry (BootContext, FileSystemHandle, &FileSystem); if (!EFI_ERROR (Status)) { return FileSystem; } @@ -1971,12 +1831,11 @@ BuildFileSystemList ( IN BOOLEAN Empty ) { - OC_BOOT_CONTEXT *BootContext; - EFI_STATUS Status; - OC_LEGACY_OS_TYPE LegacyOsType; - UINTN NoHandles; - EFI_HANDLE *Handles; - UINTN Index; + OC_BOOT_CONTEXT *BootContext; + EFI_STATUS Status; + UINTN NoHandles; + EFI_HANDLE *Handles; + UINTN Index; BootContext = AllocatePool (sizeof (*BootContext)); if (BootContext == NULL) { @@ -1999,9 +1858,6 @@ BuildFileSystemList ( return BootContext; } - // - // Add readable filesystems. - // Status = gBS->LocateHandleBuffer ( ByProtocol, &gEfiSimpleFileSystemProtocolGuid, @@ -2017,45 +1873,11 @@ BuildFileSystemList ( AddFileSystemEntry ( BootContext, Handles[Index], - FALSE, NULL ); } FreePool (Handles); - - // - // Add legacy partitions with valid boot sectors if on a supported legacy platform. - // - if (Context->LegacyBootType != OcLegacyBootTypeNone) { - Status = gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiBlockIoProtocolGuid, - NULL, - &NoHandles, - &Handles - ); - if (EFI_ERROR (Status)) { - return BootContext; - } - - for (Index = 0; Index < NoHandles; ++Index) { - LegacyOsType = InternalGetPartitionLegacyOsType (Handles[Index]); - if (LegacyOsType == OcLegacyOsTypeNone) { - continue; - } - - AddFileSystemEntry ( - BootContext, - Handles[Index], - LegacyOsType, - NULL - ); - } - - FreePool (Handles); - } - return BootContext; } @@ -2258,40 +2080,28 @@ OcScanForBootEntries ( { FileSystem = BASE_CR (Link, OC_BOOT_FILESYSTEM, Link); - if (FileSystem->LegacyOsType != OcLegacyOsTypeNone) { - // - // Process legacy boot partition. - // - if (IsListEmpty (&FileSystem->BootEntries)) { - AddBootEntryFromLegacyPartition ( - BootContext, - FileSystem - ); - } - } else { - PartitionEntry = OcGetGptPartitionEntry (FileSystem->Handle); - IsDefaultEntryProtocolPartition = ( - (DefaultEntryId != NULL) - && CompareGuid ( - &DefaultEntryPartuuid, - (PartitionEntry == NULL) ? &gEfiPartTypeUnusedGuid : &PartitionEntry->UniquePartitionGUID - ) - ); + PartitionEntry = OcGetGptPartitionEntry (FileSystem->Handle); + IsDefaultEntryProtocolPartition = ( + (DefaultEntryId != NULL) + && CompareGuid ( + &DefaultEntryPartuuid, + (PartitionEntry == NULL) ? &gEfiPartTypeUnusedGuid : &PartitionEntry->UniquePartitionGUID + ) + ); - // - // No entries, or only entry pre-created from boot entry protocol, - // so process this directory with Apple Bless. - // - if (IsDefaultEntryProtocolPartition || IsListEmpty (&FileSystem->BootEntries)) { - AddBootEntryFromBless ( - BootContext, - FileSystem, - gAppleBootPolicyPredefinedPaths, - gAppleBootPolicyNumPredefinedPaths, - FALSE, - FALSE - ); - } + // + // No entries, or only entry pre-created from boot entry protocol, + // so process this directory with Apple Bless. + // + if (IsDefaultEntryProtocolPartition || IsListEmpty (&FileSystem->BootEntries)) { + AddBootEntryFromBless ( + BootContext, + FileSystem, + gAppleBootPolicyPredefinedPaths, + gAppleBootPolicyNumPredefinedPaths, + FALSE, + FALSE + ); } // @@ -2633,7 +2443,7 @@ OcLoadBootEntry ( if ((BootEntry->Type & OC_BOOT_SYSTEM) != 0) { ASSERT (BootEntry->SystemAction != NULL); - return BootEntry->SystemAction (Context); + return BootEntry->SystemAction (Context, BootEntry->SystemActionContext); } Status = InternalLoadBootEntry ( diff --git a/Library/OcBootManagementLib/BootManagementInternal.h b/Library/OcBootManagementLib/BootManagementInternal.h index 2d3e0ba6f6d..1a3ac19387a 100644 --- a/Library/OcBootManagementLib/BootManagementInternal.h +++ b/Library/OcBootManagementLib/BootManagementInternal.h @@ -124,28 +124,10 @@ typedef enum { BootEntryDisabled, } INTERNAL_ENTRY_VISIBILITY; -EFI_STATUS -InternalLoadAppleLegacyInterface ( - IN EFI_HANDLE ParentImageHandle, - IN EFI_DEVICE_PATH_PROTOCOL *HdDevicePath, - OUT EFI_HANDLE *ImageHandle - ); - -OC_LEGACY_OS_TYPE -InternalGetPartitionLegacyOsType ( - IN EFI_HANDLE PartitionHandle - ); - -OC_LEGACY_BOOT_TYPE -InternalGetLegacyBootType ( - VOID - ); - EFI_STATUS InternalCheckScanPolicy ( IN EFI_HANDLE Handle, IN UINT32 Policy, - IN BOOLEAN Legacy, OUT BOOLEAN *External OPTIONAL ); @@ -251,22 +233,6 @@ InternalDescribeBootEntry ( IN OUT OC_BOOT_ENTRY *BootEntry ); -/** - Describe legacy boot entry contents by setting fields other than DevicePath. - - @param[in] BootContext Boot context. - @param[in] LegacyOsType Legacy OS type. - @param[in,out] BootEntry Located boot entry. - - @retval EFI_SUCCESS The entry point is described successfully. -**/ -EFI_STATUS -InternalDescribeLegacyBootEntry ( - IN OC_BOOT_CONTEXT *BootContext, - IN OC_LEGACY_OS_TYPE LegacyOsType, - IN OUT OC_BOOT_ENTRY *BootEntry - ); - BOOLEAN InternalIsAppleLegacyLoadApp ( IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath diff --git a/Library/OcBootManagementLib/DefaultEntryChoice.c b/Library/OcBootManagementLib/DefaultEntryChoice.c index 52937a7217f..5c118fc072f 100644 --- a/Library/OcBootManagementLib/DefaultEntryChoice.c +++ b/Library/OcBootManagementLib/DefaultEntryChoice.c @@ -1577,27 +1577,14 @@ InternalLoadBootEntry ( DEBUG_CODE_END (); - if (BootEntry->LegacyOsType != OcLegacyOsTypeNone) { - if (Context->LegacyBootType == OcLegacyBootTypeApple) { - Status = InternalLoadAppleLegacyInterface ( - ParentHandle, - DevicePath, - EntryHandle - ); - } else { - DEBUG ((DEBUG_INFO, "OCB: Unsupported legacy interface type: %u\n", Context->LegacyBootType)); - Status = EFI_UNSUPPORTED; - } - } else { - Status = gBS->LoadImage ( - FALSE, - ParentHandle, - DevicePath, - EntryData, - EntryDataSize, - EntryHandle - ); - } + Status = gBS->LoadImage ( + FALSE, + ParentHandle, + DevicePath, + EntryData, + EntryDataSize, + EntryHandle + ); if (EntryData != NULL) { FreePool (EntryData); diff --git a/Library/OcBootManagementLib/OcBootManagementLib.c b/Library/OcBootManagementLib/OcBootManagementLib.c index 85963549bb2..b1d778226fa 100644 --- a/Library/OcBootManagementLib/OcBootManagementLib.c +++ b/Library/OcBootManagementLib/OcBootManagementLib.c @@ -324,11 +324,6 @@ OcRunBootPicker ( Context->HideAuxiliary = FALSE; } - // - // Get legacy boot mode. - // - Context->LegacyBootType = InternalGetLegacyBootType (); - while (TRUE) { // // Never show Apple Picker twice, re-scan for entries if we previously successfully showed it. diff --git a/Library/OcBootManagementLib/OcBootManagementLib.inf b/Library/OcBootManagementLib/OcBootManagementLib.inf index 42efff2e8e2..efb5743b9a3 100644 --- a/Library/OcBootManagementLib/OcBootManagementLib.inf +++ b/Library/OcBootManagementLib/OcBootManagementLib.inf @@ -45,7 +45,6 @@ DmgBootSupport.c HotKeySupport.c ImageLoader.c - LegacyBootSupport.c PolicyManagement.c OcBootManagementLib.c @@ -53,7 +52,6 @@ OpenCorePkg/OpenCorePkg.dec MdePkg/MdePkg.dec MdeModulePkg/MdeModulePkg.dec - OvmfPkg/OvmfPkg.dec UefiCpuPkg/UefiCpuPkg.dec [Guids] @@ -86,7 +84,6 @@ gAppleBeepGenProtocolGuid ## SOMETIMES_CONSUMES gOcBootEntryProtocolGuid ## CONSUMES gAppleFirmwareUserInterfaceProtocolGuid ## SOMETIMES_CONSUMES - gEfiLegacy8259ProtocolGuid ## SOMETIMES_CONSUMES [LibraryClasses] BaseLib diff --git a/Library/OcBootManagementLib/PolicyManagement.c b/Library/OcBootManagementLib/PolicyManagement.c index 61d5e9c69b8..a19faaab915 100644 --- a/Library/OcBootManagementLib/PolicyManagement.c +++ b/Library/OcBootManagementLib/PolicyManagement.c @@ -299,7 +299,6 @@ EFI_STATUS InternalCheckScanPolicy ( IN EFI_HANDLE Handle, IN UINT32 Policy, - IN BOOLEAN Legacy, OUT BOOLEAN *External OPTIONAL ) { @@ -315,7 +314,7 @@ InternalCheckScanPolicy ( return EFI_SECURITY_VIOLATION; } - if (!Legacy && ((Policy & OC_SCAN_FILE_SYSTEM_LOCK) != 0)) { + if ((Policy & OC_SCAN_FILE_SYSTEM_LOCK) != 0) { FileSystemPolicy = OcGetFileSystemPolicyType (Handle); if ((Policy & FileSystemPolicy) == 0) { diff --git a/Library/OcLegacyThunkLib/OcLegacyThunkLib.c b/Library/OcLegacyThunkLib/OcLegacyThunkLib.c index bc3422ae844..bdacfa3e1dc 100644 --- a/Library/OcLegacyThunkLib/OcLegacyThunkLib.c +++ b/Library/OcLegacyThunkLib/OcLegacyThunkLib.c @@ -23,6 +23,33 @@ #include #include +// +// 8254 Timer registers +// +#define TIMER0_COUNT_PORT 0x40 +#define TIMER1_COUNT_PORT 0x41 +#define TIMER2_COUNT_PORT 0x42 +#define TIMER_CONTROL_PORT 0x43 +#define TIMER0_CONTROL_WORD 0x36 + +// +// Vector base definitions +// +// +// 8259 Hardware definitions +// +#define LEGACY_MODE_BASE_VECTOR_MASTER 0x08 +#define LEGACY_MODE_BASE_VECTOR_SLAVE 0x70 + +// +// The original PC used INT8-F for master PIC. Since these mapped over +// processor exceptions TIANO moved the master PIC to INT68-6F. +// +// The vector base for slave PIC is set as 0x70 for PC-AT compatibility. +// +#define PROTECTED_MODE_BASE_VECTOR_MASTER 0x68 +#define PROTECTED_MODE_BASE_VECTOR_SLAVE 0x70 + /** Initialize legacy environment for BIOS INI caller. @@ -295,3 +322,150 @@ OcLegacyThunkBiosInt86 ( return Ret; } + +BOOLEAN +EFIAPI +OcLegacyThunkFarCall86 ( + IN THUNK_CONTEXT *ThunkContext, + IN EFI_LEGACY_8259_PROTOCOL *Legacy8259, + IN UINT16 Segment, + IN UINT16 Offset, + IN IA32_REGISTER_SET *Regs, + IN VOID *Stack, + IN UINTN StackSize + ) +{ + UINTN Status; + UINT16 *Stack16; + IA32_REGISTER_SET ThunkRegSet; + BOOLEAN Ret; + // BOOLEAN InterruptState; + UINT64 TimerPeriod; + BOOLEAN Enabled; + + EFI_TIMER_ARCH_PROTOCOL *TimerProtocol; + + ZeroMem (&ThunkRegSet, sizeof (ThunkRegSet)); + ThunkRegSet.E.EFLAGS.Bits.Reserved_0 = 1; + ThunkRegSet.E.EFLAGS.Bits.Reserved_1 = 0; + ThunkRegSet.E.EFLAGS.Bits.Reserved_2 = 0; + ThunkRegSet.E.EFLAGS.Bits.Reserved_3 = 0; + ThunkRegSet.E.EFLAGS.Bits.IOPL = 3; + ThunkRegSet.E.EFLAGS.Bits.NT = 0; + ThunkRegSet.E.EFLAGS.Bits.IF = 1; + ThunkRegSet.E.EFLAGS.Bits.TF = 0; + ThunkRegSet.E.EFLAGS.Bits.CF = 0; + + ThunkRegSet.E.EDI = Regs->E.EDI; + ThunkRegSet.E.ESI = Regs->E.ESI; + ThunkRegSet.E.EBP = Regs->E.EBP; + ThunkRegSet.E.EBX = Regs->E.EBX; + ThunkRegSet.E.EDX = Regs->E.EDX; + ThunkRegSet.E.ECX = Regs->E.ECX; + ThunkRegSet.E.EAX = Regs->E.EAX; + ThunkRegSet.E.DS = Regs->E.DS; + ThunkRegSet.E.ES = Regs->E.ES; + + // + // The call to Legacy16 is a critical section to EFI + // + Enabled = SaveAndDisableInterrupts (); + + // + // Save current rate of DXE timer and disable it + // while executing in real mode. + // + Status = gBS->LocateProtocol ( + &gEfiTimerArchProtocolGuid, + NULL, + (VOID **)&TimerProtocol + ); + if (EFI_ERROR (Status)) { + TimerProtocol->GetTimerPeriod (TimerProtocol, &TimerPeriod); + TimerProtocol->SetTimerPeriod (TimerProtocol, 0); + } + + // + // Reset timer to default legacy rate of 54.9254. + // + IoWrite8 (TIMER_CONTROL_PORT, TIMER0_CONTROL_WORD); + IoWrite8 (TIMER0_COUNT_PORT, 0x00); + IoWrite8 (TIMER0_COUNT_PORT, 0x00); + + // + // Put the 8259 into its legacy mode by reprogramming the vector bases + // + Status = Legacy8259->SetVectorBase (Legacy8259, LEGACY_MODE_BASE_VECTOR_MASTER, LEGACY_MODE_BASE_VECTOR_SLAVE); + ASSERT_EFI_ERROR (Status); + + // + // Set Legacy16 state. 0x08, 0x70 is legacy 8259 vector bases. + // + Status = Legacy8259->SetMode (Legacy8259, Efi8259LegacyMode, NULL, NULL); + ASSERT_EFI_ERROR (Status); + + // + // Clear the error flag; thunk code may set it. Stack16 should be the high address + // Make Statk16 address the low 16 bit must be not zero. + // + Stack16 = (UINT16 *)((UINT8 *)ThunkContext->RealModeBuffer + ThunkContext->RealModeBufferSize - sizeof (UINT16)); + + if ((Stack != NULL) && (StackSize != 0)) { + // + // Copy Stack to low memory stack + // + Stack16 -= StackSize / sizeof (UINT16); + CopyMem (Stack16, Stack, StackSize); + } + + ThunkRegSet.E.SS = (UINT16)(((UINTN)Stack16 >> 16) << 12); + ThunkRegSet.E.ESP = (UINT16)(UINTN)Stack16; + ThunkRegSet.E.CS = Segment; + ThunkRegSet.E.Eip = Offset; + + ThunkContext->RealModeState = &ThunkRegSet; + AsmThunk16 (ThunkContext); + + if ((Stack != NULL) && (StackSize != 0)) { + // + // Copy low memory stack to Stack + // + CopyMem (Stack, Stack16, StackSize); + } + + // + // Restore protected mode interrupt state + // + Status = Legacy8259->SetMode (Legacy8259, Efi8259ProtectedMode, NULL, NULL); + ASSERT_EFI_ERROR (Status); + + ThunkContext->RealModeState = NULL; + + // + // Enable and restore rate of DXE Timer + // + // Private->Timer->SetTimerPeriod (Private->Timer, TimerPeriod); + + // + // End critical section + // + SetInterruptState (Enabled); + + Regs->E.EDI = ThunkRegSet.E.EDI; + Regs->E.ESI = ThunkRegSet.E.ESI; + Regs->E.EBP = ThunkRegSet.E.EBP; + Regs->E.EBX = ThunkRegSet.E.EBX; + Regs->E.EDX = ThunkRegSet.E.EDX; + Regs->E.ECX = ThunkRegSet.E.ECX; + Regs->E.EAX = ThunkRegSet.E.EAX; + Regs->E.SS = ThunkRegSet.E.SS; + Regs->E.CS = ThunkRegSet.E.CS; + Regs->E.DS = ThunkRegSet.E.DS; + Regs->E.ES = ThunkRegSet.E.ES; + + CopyMem (&(Regs->E.EFLAGS), &(ThunkRegSet.E.EFLAGS), sizeof (UINT32)); + + Ret = (BOOLEAN)(Regs->E.EFLAGS.Bits.CF == 1); + + return Ret; +} diff --git a/OpenCorePkg.dsc b/OpenCorePkg.dsc index 01552ceeeae..4aba7840a8d 100755 --- a/OpenCorePkg.dsc +++ b/OpenCorePkg.dsc @@ -299,6 +299,7 @@ OpenCorePkg/Legacy/BootPlatform/BiosVideo/BiosVideo.inf OpenCorePkg/Platform/CrScreenshotDxe/CrScreenshotDxe.inf OpenCorePkg/Platform/OpenCanopy/OpenCanopy.inf + OpenCorePkg/Platform/OpenLegacyBoot/OpenLegacyBoot.inf OpenCorePkg/Platform/OpenLinuxBoot/OpenLinuxBoot.inf OpenCorePkg/Platform/OpenNtfsDxe/OpenNtfsDxe.inf OpenCorePkg/Platform/OpenPartitionDxe/PartitionDxe.inf diff --git a/Platform/OpenLegacyBoot/LegacyBootInternal.h b/Platform/OpenLegacyBoot/LegacyBootInternal.h new file mode 100644 index 00000000000..4bb6d1dceb2 --- /dev/null +++ b/Platform/OpenLegacyBoot/LegacyBootInternal.h @@ -0,0 +1,44 @@ +/** @file + Copyright (C) 2023, Goldfish64. All rights reserved.
+ SPDX-License-Identifier: BSD-3-Clause +**/ + +#ifndef LEGACY_BOOT_INTERNAL_H +#define LEGACY_BOOT_INTERNAL_H + +extern EFI_HANDLE gImageHandle; +extern BOOLEAN gIsAppleInterfaceSupported; + +/** + Legacy operating system type. +**/ +typedef enum OC_LEGACY_OS_TYPE_ { + OcLegacyOsTypeNone, + OcLegacyOsTypeWindowsNtldr, + OcLegacyOsTypeWindowsBootmgr, + OcLegacyOsTypeIsoLinux +} OC_LEGACY_OS_TYPE; + +EFI_STATUS +InternalIsLegacyInterfaceSupported ( + OUT BOOLEAN *IsAppleInterfaceSupported + ); + +EFI_STATUS +InternalLoadAppleLegacyInterface ( + IN EFI_HANDLE ParentImageHandle, + IN EFI_DEVICE_PATH_PROTOCOL *HdDevicePath, + OUT EFI_HANDLE *ImageHandle + ); + +OC_LEGACY_OS_TYPE +InternalGetPartitionLegacyOsType ( + IN EFI_HANDLE PartitionHandle + ); + +EFI_STATUS +InternalLoadLegacyMbr ( + IN EFI_DEVICE_PATH_PROTOCOL *HdDevicePath + ); + +#endif // LEGACY_BOOT_INTERNAL_H diff --git a/Library/OcBootManagementLib/LegacyBootSupport.c b/Platform/OpenLegacyBoot/LegacyBootSupport.c similarity index 78% rename from Library/OcBootManagementLib/LegacyBootSupport.c rename to Platform/OpenLegacyBoot/LegacyBootSupport.c index 985fc620a74..1de67a5edc2 100644 --- a/Library/OcBootManagementLib/LegacyBootSupport.c +++ b/Platform/OpenLegacyBoot/LegacyBootSupport.c @@ -1,18 +1,9 @@ /** @file - Copyright (C) 2023, Goldfish64. 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. + Copyright (C) 2023, Goldfish64. All rights reserved.
+ SPDX-License-Identifier: BSD-3-Clause **/ -#include "BootManagementInternal.h" +#include "LegacyBootInternal.h" #include @@ -20,11 +11,12 @@ #include #include #include +#include #include #include #include +#include #include -#include #include #include #include @@ -32,6 +24,8 @@ #include #include +THUNK_CONTEXT mThunkContext; + // // PIWG firmware media device path for Apple legacy interface. // FwFile(2B0585EB-D8B8-49A9-8B8CE21B01AEF2B7) @@ -45,7 +39,7 @@ static CONST EFI_DEVICE_PATH_PROTOCOL *AppleLegacyInterfaceMediaDevicePathPath #define MAX_APPLE_LEGACY_DEVICE_PATHS 16 -STATIC +// STATIC BOOLEAN CheckLegacySignature ( IN CONST CHAR8 *SignatureStr, @@ -157,6 +151,34 @@ ScanAppleLegacyInterfacePaths ( return EFI_SUCCESS; } +EFI_STATUS +InternalIsLegacyInterfaceSupported ( + OUT BOOLEAN *IsAppleInterfaceSupported + ) +{ + EFI_STATUS Status; + EFI_LEGACY_8259_PROTOCOL *Legacy8259; + + ASSERT (IsAppleInterfaceSupported != NULL); + + // + // Apple legacy boot interface is only available on Apple platforms. + // Use legacy 16-bit thunks on legacy PC platforms. + // + if (OcStriCmp (L"Apple", gST->FirmwareVendor) == 0) { + *IsAppleInterfaceSupported = TRUE; + return EFI_SUCCESS; + } else { + Status = gBS->LocateProtocol (&gEfiLegacy8259ProtocolGuid, NULL, (VOID **)&Legacy8259); + if (!EFI_ERROR (Status) && (Legacy8259 != NULL)) { + *IsAppleInterfaceSupported = FALSE; + return EFI_SUCCESS; + } + } + + return EFI_UNSUPPORTED; +} + EFI_STATUS InternalLoadAppleLegacyInterface ( IN EFI_HANDLE ParentImageHandle, @@ -268,7 +290,7 @@ InternalGetPartitionLegacyOsType ( return OcLegacyOsTypeNone; } - DebugPrintDevicePath (DEBUG_VERBOSE, "OCB: Reading MBR for disk", DevicePath); + DebugPrintDevicePath (DEBUG_INFO, "OCB: Reading MBR for disk", DevicePath); DiskHandle = OcPartitionGetDiskHandle (DevicePath); if (DiskHandle == NULL) { @@ -277,7 +299,7 @@ InternalGetPartitionLegacyOsType ( Mbr = OcGetDiskMbrTable (DiskHandle, TRUE); if (Mbr == NULL) { - DEBUG ((DEBUG_VERBOSE, "OCB: Disk does not contain a valid MBR partition table\n")); + DEBUG ((DEBUG_INFO, "OCB: Disk does not contain a valid MBR partition table\n")); return OcLegacyOsTypeNone; } @@ -290,7 +312,7 @@ InternalGetPartitionLegacyOsType ( // // Retrieve the first sector of the partition. // - DebugPrintDevicePath (DEBUG_VERBOSE, "OCB: Reading PBR for partition", DevicePath); + DebugPrintDevicePath (DEBUG_INFO, "OCB: Reading PBR for partition", DevicePath); Status = OcDiskInitializeContext ( &DiskContext, PartitionHandle, @@ -351,28 +373,79 @@ InternalGetPartitionLegacyOsType ( return LegacyOsType; } -OC_LEGACY_BOOT_TYPE -InternalGetLegacyBootType ( - VOID +EFI_STATUS +InternalLoadLegacyMbr ( + IN EFI_DEVICE_PATH_PROTOCOL *HdDevicePath ) { - EFI_STATUS Status; + EFI_STATUS Status; + EFI_HANDLE DiskHandle; + MASTER_BOOT_RECORD *Mbr; + IA32_REGISTER_SET Regs; + UINT8 *MbrPtr = (UINT8 *)0x7C00; + EFI_LEGACY_8259_PROTOCOL *Legacy8259; - OC_LEGACY_BOOT_TYPE BootType; // - // Apple legacy boot interface is only available on Apple platforms. - // Use legacy 16-bit thunks on legacy PC platforms. + // Locate required protocols. // - BootType = OcLegacyBootTypeNone; - if (OcStriCmp (L"Apple", gST->FirmwareVendor) == 0) { - BootType = OcLegacyBootTypeApple; - } else { - Status = gBS->LocateProtocol (&gEfiLegacy8259ProtocolGuid, NULL, (VOID **)&Legacy8259); - if (!EFI_ERROR (Status) && (Legacy8259 != NULL)) { - BootType = OcLegacyBootTypeLegacyBios; - } + Status = gBS->LocateProtocol ( + &gEfiLegacy8259ProtocolGuid, + NULL, + (VOID **)&Legacy8259 + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "OCB: Could not locate Legacy8259 protocol\n")); + return Status; } - return BootType; + DebugPrintDevicePath (DEBUG_INFO, "OCB: Reading MBR for disk", HdDevicePath); + + DiskHandle = OcPartitionGetDiskHandle (HdDevicePath); + if (DiskHandle == NULL) { + return EFI_INVALID_PARAMETER; + } + + Mbr = OcGetDiskMbrTable (DiskHandle, TRUE); + if (Mbr == NULL) { + DEBUG ((DEBUG_INFO, "OCB: Disk does not contain a valid MBR partition table\n")); + return EFI_INVALID_PARAMETER; + } + + // + // Create and initialize thunk structures. + // + Status = OcLegacyThunkInitializeBiosIntCaller (&mThunkContext); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = OcLegacyThunkInitializeInterruptRedirection (Legacy8259); + if (EFI_ERROR (Status)) { + return Status; + } + + DEBUG ((DEBUG_INFO, "OCB: Preparing to boot legacy system\n")); + + OcLegacyThunkDisconnectEfiGraphics (); + + CopyMem (MbrPtr, Mbr, sizeof (*Mbr)); + + ZeroMem (&Regs, sizeof (Regs)); + Regs.X.DX = 0x82; + OcLegacyThunkFarCall86 ( + &mThunkContext, + Legacy8259, + 0, + 0x7c00, + &Regs, + NULL, + 0 + ); + + DEBUG ((DEBUG_INFO, "here\n")); + while (TRUE) { + } + + return EFI_SUCCESS; } diff --git a/Platform/OpenLegacyBoot/OpenLegacyBoot.c b/Platform/OpenLegacyBoot/OpenLegacyBoot.c new file mode 100644 index 00000000000..e0fc59daa51 --- /dev/null +++ b/Platform/OpenLegacyBoot/OpenLegacyBoot.c @@ -0,0 +1,277 @@ +/** @file + Legacy boot driver. + + Copyright (c) 2023, Goldfish64. All rights reserved.
+ SPDX-License-Identifier: BSD-3-Clause +**/ + +#include "LegacyBootInternal.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +EFI_HANDLE gImageHandle; +BOOLEAN gIsAppleInterfaceSupported; + +VOID +InternalFreePickerEntry ( + IN OC_PICKER_ENTRY *Entry + ) +{ + ASSERT (Entry != NULL); + + if (Entry == NULL) { + return; + } + + // + // TODO: Is this un-CONST casting okay? + // (Are they CONST because they are not supposed to be freed when used as before?) + // + if (Entry->Id != NULL) { + FreePool ((CHAR8 *)Entry->Id); + } + + if (Entry->Name != NULL) { + FreePool ((CHAR8 *)Entry->Name); + } + + if (Entry->Path != NULL) { + FreePool ((CHAR8 *)Entry->Path); + } + + if (Entry->Arguments != NULL) { + FreePool ((CHAR8 *)Entry->Arguments); + } + + if (Entry->Flavour != NULL) { + FreePool ((CHAR8 *)Entry->Flavour); + } +} + +STATIC +EFI_STATUS +SystemActionDoLegacyBoot ( + IN OUT OC_PICKER_CONTEXT *PickerContext, + IN VOID *ActionContext + ) +{ + EFI_STATUS Status; + EFI_HANDLE LoadedImageHandle; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)ActionContext; + + if (gIsAppleInterfaceSupported) { + DebugPrintDevicePath (DEBUG_INFO, "LEG: Device path", DevicePath); + + Status = InternalLoadAppleLegacyInterface ( + gImageHandle, + DevicePath, + &LoadedImageHandle + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "LEG: Failure while loading Apple legacy interface - %r\n", Status)); + return Status; + } + + Status = gBS->HandleProtocol ( + LoadedImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **)&LoadedImage + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "LEG: Failure while loading Apple legacy interface - %r\n", Status)); + return Status; + } + + LoadedImage->LoadOptionsSize = 0; + LoadedImage->LoadOptions = NULL; + + CONST CHAR8 *Args; + + Args = AllocateCopyPool (L_STR_SIZE ("HD"), "HD"); + + OcAppendArgumentsToLoadedImage (LoadedImage, &Args, 1, TRUE); + DEBUG (( + DEBUG_INFO, + "OCB: Args <%s>\n", + LoadedImage->LoadOptions + )); + Status = gBS->StartImage (LoadedImageHandle, NULL, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "LEG: Failure while starting Apple legacy interface - %r\n", Status)); + return Status; + } + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +OcGetLegacyBootEntries ( + IN OUT OC_PICKER_CONTEXT *PickerContext, + IN CONST EFI_HANDLE Device OPTIONAL, + OUT OC_PICKER_ENTRY **Entries, + OUT UINTN *NumEntries + ) +{ + // EFI_STATUS Status; + // EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem; + // EFI_FILE_PROTOCOL *RootDirectory; + // UINT32 FileSystemPolicy; + + OC_LEGACY_OS_TYPE LegacyType; + OC_PICKER_ENTRY *PickerEntry; + + // + // No custom entries. + // + if (Device == NULL) { + return EFI_NOT_FOUND; + } + + // + // Open partition file system. + // + + /* Status = gBS->HandleProtocol ( + Device, + &gEfiSimpleFileSystemProtocolGuid, + (VOID **)&FileSystem + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "LEG: Missing filesystem - %r\n", Status)); + return Status; + } + + // + // Get handle to partiton root directory. + // + Status = FileSystem->OpenVolume ( + FileSystem, + &RootDirectory + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "LEG: Invalid root volume - %r\n", Status)); + return Status; + } + + FileSystemPolicy = OcGetFileSystemPolicyType (Device);*/ + + // + // Disallow all but NTFS filesystems. + // + // if ((FileSystemPolicy & OC_SCAN_ALLOW_FS_NTFS) != 0) { + // DEBUG ((DEBUG_INFO, "LEG: Not scanning non-NTFS filesystem\n")); + // Status = EFI_NOT_FOUND; + // } + + // + // Scan for boot entry (only one entry per filesystem). + // + LegacyType = InternalGetPartitionLegacyOsType (Device); + // RootDirectory->Close (RootDirectory); + if (LegacyType == OcLegacyOsTypeNone) { + return EFI_NOT_FOUND; + } + + PickerEntry = AllocateZeroPool (sizeof (*PickerEntry)); + PickerEntry->Id = "legacy_boot"; + PickerEntry->Name = "Windows (legacy)"; + PickerEntry->Path = NULL; + PickerEntry->Arguments = NULL; + PickerEntry->Flavour = OC_FLAVOUR_WINDOWS; + PickerEntry->Tool = FALSE; + PickerEntry->TextMode = TRUE; + PickerEntry->RealPath = FALSE; + PickerEntry->SystemAction = SystemActionDoLegacyBoot; + PickerEntry->SystemActionContext = DevicePathFromHandle (Device); + + *Entries = PickerEntry; + *NumEntries = 1; + + return EFI_SUCCESS; +} + +STATIC +VOID +EFIAPI +OcFreeLegacyBootEntries ( + IN OC_PICKER_ENTRY **Entries, + IN UINTN NumEntries + ) +{ + return; + UINTN Index; + + ASSERT (Entries != NULL); + ASSERT (*Entries != NULL); + if ((Entries == NULL) || (*Entries == NULL)) { + return; + } + + for (Index = 0; Index < NumEntries; Index++) { + InternalFreePickerEntry (&(*Entries)[Index]); + } + + FreePool (*Entries); + *Entries = NULL; +} + +STATIC +OC_BOOT_ENTRY_PROTOCOL + mLegacyBootEntryProtocol = { + OC_BOOT_ENTRY_PROTOCOL_REVISION, + OcGetLegacyBootEntries, + OcFreeLegacyBootEntries, + NULL +}; + +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + gImageHandle = ImageHandle; + + Status = InternalIsLegacyInterfaceSupported (&gIsAppleInterfaceSupported); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "LEG: Legacy boot interface is supported on this system\n")); + return Status; + } + + DEBUG ((DEBUG_INFO, "LEG: Apple legacy interface: %d\n", gIsAppleInterfaceSupported)); + + Status = gBS->InstallMultipleProtocolInterfaces ( + &ImageHandle, + &gOcBootEntryProtocolGuid, + &mLegacyBootEntryProtocol, + NULL + ); + + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} diff --git a/Platform/OpenLegacyBoot/OpenLegacyBoot.inf b/Platform/OpenLegacyBoot/OpenLegacyBoot.inf new file mode 100644 index 00000000000..80da3de5fdd --- /dev/null +++ b/Platform/OpenLegacyBoot/OpenLegacyBoot.inf @@ -0,0 +1,44 @@ +## @file +# Legacy boot entry protocol implementation. +# +# Copyright (C) 2023, Goldfish64. All rights reserved.
+# SPDX-License-Identifier: BSD-3-Clause +## + + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = OpenLegacyBoot + ENTRY_POINT = UefiMain + FILE_GUID = 4BE5FC32-9434-4799-9F8F-ECD579025074 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + +[Packages] + OpenCorePkg/OpenCorePkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + OvmfPkg/OvmfPkg.dec + +[Guids] + gAppleLegacyLoadAppFileGuid ## SOMETIMES_CONSUMES + +[LibraryClasses] + DebugLib + OcBootManagementLib + OcFileLib + OcFlexArrayLib + OcLegacyThunkLib + SortLib + UefiBootServicesTableLib + UefiDriverEntryPoint + UefiLib + +[Protocols] + gOcBootEntryProtocolGuid ## PRODUCES + gEfiLegacy8259ProtocolGuid ## SOMETIMES_CONSUMES + +[Sources] + LegacyBootInternal.h + LegacyBootSupport.c + OpenLegacyBoot.c diff --git a/Platform/ResetNvramEntry/ResetNvramEntry.c b/Platform/ResetNvramEntry/ResetNvramEntry.c index 025f53f4325..dae08cf6f1d 100644 --- a/Platform/ResetNvramEntry/ResetNvramEntry.c +++ b/Platform/ResetNvramEntry/ResetNvramEntry.c @@ -39,7 +39,8 @@ WaitForChime ( STATIC EFI_STATUS SystemActionResetNvram ( - IN OUT OC_PICKER_CONTEXT *PickerContext + IN OUT OC_PICKER_CONTEXT *PickerContext, + IN VOID *ActionContext ) { UINT8 ResetNVRam = 1; diff --git a/Platform/ToggleSipEntry/ToggleSipEntry.c b/Platform/ToggleSipEntry/ToggleSipEntry.c index 96255582045..b4092d562de 100644 --- a/Platform/ToggleSipEntry/ToggleSipEntry.c +++ b/Platform/ToggleSipEntry/ToggleSipEntry.c @@ -32,7 +32,8 @@ STATIC BOOLEAN mShowCsr; STATIC EFI_STATUS SystemActionSetSip ( - IN OUT OC_PICKER_CONTEXT *Context + IN OUT OC_PICKER_CONTEXT *Context, + IN VOID *ActionContext ) { EFI_STATUS Status; diff --git a/build_oc.tool b/build_oc.tool index 22a7efa0bd0..94d54adb820 100755 --- a/build_oc.tool +++ b/build_oc.tool @@ -198,6 +198,7 @@ package() { "NvmExpressDxe.efi" "OpenCanopy.efi" "OpenHfsPlus.efi" + "OpenLegacyBoot.efi" "OpenLinuxBoot.efi" "OpenNtfsDxe.efi" "OpenPartitionDxe.efi" From 3a31eca836b8cba107a01f2b5fde6728212f47ea Mon Sep 17 00:00:00 2001 From: John Davis Date: Sat, 12 Aug 2023 14:39:39 -0500 Subject: [PATCH 26/55] OpenLegacyBoot: Cleanup state variables --- Library/OcLegacyThunkLib/OcLegacyThunkLib.inf | 1 + Platform/OpenLegacyBoot/LegacyBootInternal.h | 27 ++++++- Platform/OpenLegacyBoot/LegacyBootSupport.c | 18 ----- Platform/OpenLegacyBoot/OpenLegacyBoot.c | 72 +++++++++---------- 4 files changed, 61 insertions(+), 57 deletions(-) diff --git a/Library/OcLegacyThunkLib/OcLegacyThunkLib.inf b/Library/OcLegacyThunkLib/OcLegacyThunkLib.inf index 432491c9219..ff863551a03 100644 --- a/Library/OcLegacyThunkLib/OcLegacyThunkLib.inf +++ b/Library/OcLegacyThunkLib/OcLegacyThunkLib.inf @@ -41,6 +41,7 @@ [Protocols] gEfiLegacy8259ProtocolGuid + gEfiTimerArchProtocolGuid [LibraryClasses] BaseMemoryLib diff --git a/Platform/OpenLegacyBoot/LegacyBootInternal.h b/Platform/OpenLegacyBoot/LegacyBootInternal.h index 4bb6d1dceb2..68b2e76ff98 100644 --- a/Platform/OpenLegacyBoot/LegacyBootInternal.h +++ b/Platform/OpenLegacyBoot/LegacyBootInternal.h @@ -6,8 +6,26 @@ #ifndef LEGACY_BOOT_INTERNAL_H #define LEGACY_BOOT_INTERNAL_H -extern EFI_HANDLE gImageHandle; -extern BOOLEAN gIsAppleInterfaceSupported; +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include /** Legacy operating system type. @@ -19,6 +37,11 @@ typedef enum OC_LEGACY_OS_TYPE_ { OcLegacyOsTypeIsoLinux } OC_LEGACY_OS_TYPE; +typedef struct { + EFI_HANDLE FsHandle; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; +} OPEN_LEGACY_BOOT_CONTEXT; + EFI_STATUS InternalIsLegacyInterfaceSupported ( OUT BOOLEAN *IsAppleInterfaceSupported diff --git a/Platform/OpenLegacyBoot/LegacyBootSupport.c b/Platform/OpenLegacyBoot/LegacyBootSupport.c index 1de67a5edc2..5830c8ce8d5 100644 --- a/Platform/OpenLegacyBoot/LegacyBootSupport.c +++ b/Platform/OpenLegacyBoot/LegacyBootSupport.c @@ -5,24 +5,6 @@ #include "LegacyBootInternal.h" -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include THUNK_CONTEXT mThunkContext; diff --git a/Platform/OpenLegacyBoot/OpenLegacyBoot.c b/Platform/OpenLegacyBoot/OpenLegacyBoot.c index e0fc59daa51..e8d2ac7ed11 100644 --- a/Platform/OpenLegacyBoot/OpenLegacyBoot.c +++ b/Platform/OpenLegacyBoot/OpenLegacyBoot.c @@ -7,22 +7,10 @@ #include "LegacyBootInternal.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - #include -EFI_HANDLE gImageHandle; -BOOLEAN gIsAppleInterfaceSupported; +STATIC EFI_HANDLE mImageHandle; +STATIC BOOLEAN mIsAppleInterfaceSupported; VOID InternalFreePickerEntry ( @@ -63,23 +51,28 @@ InternalFreePickerEntry ( STATIC EFI_STATUS SystemActionDoLegacyBoot ( - IN OUT OC_PICKER_CONTEXT *PickerContext, - IN VOID *ActionContext + IN OUT OC_PICKER_CONTEXT *PickerContext, + IN VOID *ActionContext ) { EFI_STATUS Status; EFI_HANDLE LoadedImageHandle; EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - - DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)ActionContext; + OPEN_LEGACY_BOOT_CONTEXT *LegacyContext; - if (gIsAppleInterfaceSupported) { - DebugPrintDevicePath (DEBUG_INFO, "LEG: Device path", DevicePath); + LegacyContext = (OPEN_LEGACY_BOOT_CONTEXT *)ActionContext; + // + // Load and start legacy OS. + // + // On Macs, use the Apple legacy interface. + // On other systems, use the Legacy8259 protocol. + // + DebugPrintDevicePath (DEBUG_INFO, "LEG: Legacy device path", LegacyContext->DevicePath); + if (mIsAppleInterfaceSupported) { Status = InternalLoadAppleLegacyInterface ( - gImageHandle, - DevicePath, + mImageHandle, + LegacyContext->DevicePath, &LoadedImageHandle ); if (EFI_ERROR (Status)) { @@ -190,17 +183,22 @@ OcGetLegacyBootEntries ( return EFI_NOT_FOUND; } - PickerEntry = AllocateZeroPool (sizeof (*PickerEntry)); - PickerEntry->Id = "legacy_boot"; - PickerEntry->Name = "Windows (legacy)"; - PickerEntry->Path = NULL; - PickerEntry->Arguments = NULL; - PickerEntry->Flavour = OC_FLAVOUR_WINDOWS; - PickerEntry->Tool = FALSE; - PickerEntry->TextMode = TRUE; - PickerEntry->RealPath = FALSE; - PickerEntry->SystemAction = SystemActionDoLegacyBoot; - PickerEntry->SystemActionContext = DevicePathFromHandle (Device); + PickerEntry = AllocateZeroPool (sizeof (*PickerEntry)); + PickerEntry->Id = "legacy_boot"; + PickerEntry->Name = "Windows (legacy)"; + PickerEntry->Path = NULL; + PickerEntry->Arguments = NULL; + PickerEntry->Flavour = OC_FLAVOUR_WINDOWS; + PickerEntry->Tool = FALSE; + PickerEntry->TextMode = TRUE; + PickerEntry->RealPath = FALSE; + PickerEntry->SystemAction = SystemActionDoLegacyBoot; + + OPEN_LEGACY_BOOT_CONTEXT *contex = (OPEN_LEGACY_BOOT_CONTEXT *)AllocateZeroPool (sizeof (OPEN_LEGACY_BOOT_CONTEXT)); + + contex->DevicePath = DevicePathFromHandle (Device); + contex->FsHandle = Device; + PickerEntry->SystemActionContext = contex; *Entries = PickerEntry; *NumEntries = 1; @@ -251,15 +249,15 @@ UefiMain ( { EFI_STATUS Status; - gImageHandle = ImageHandle; + mImageHandle = ImageHandle; - Status = InternalIsLegacyInterfaceSupported (&gIsAppleInterfaceSupported); + Status = InternalIsLegacyInterfaceSupported (&mIsAppleInterfaceSupported); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_WARN, "LEG: Legacy boot interface is supported on this system\n")); return Status; } - DEBUG ((DEBUG_INFO, "LEG: Apple legacy interface: %d\n", gIsAppleInterfaceSupported)); + DEBUG ((DEBUG_INFO, "LEG: Apple legacy interface: %d\n", mIsAppleInterfaceSupported)); Status = gBS->InstallMultipleProtocolInterfaces ( &ImageHandle, From 61eeb93171795be1b242e54b93285f87534e2914 Mon Sep 17 00:00:00 2001 From: John Davis Date: Sat, 12 Aug 2023 18:52:22 -0500 Subject: [PATCH 27/55] OpenLegacyBoot: Add initial support for PC legacy boot interface --- Platform/OpenLegacyBoot/BiosDisk.c | 205 +++++++++++++++++++ Platform/OpenLegacyBoot/LegacyBootInternal.h | 12 +- Platform/OpenLegacyBoot/LegacyBootSupport.c | 84 ++++++-- Platform/OpenLegacyBoot/OpenLegacyBoot.c | 2 + Platform/OpenLegacyBoot/OpenLegacyBoot.inf | 1 + 5 files changed, 290 insertions(+), 14 deletions(-) create mode 100644 Platform/OpenLegacyBoot/BiosDisk.c diff --git a/Platform/OpenLegacyBoot/BiosDisk.c b/Platform/OpenLegacyBoot/BiosDisk.c new file mode 100644 index 00000000000..cbe7097ff62 --- /dev/null +++ b/Platform/OpenLegacyBoot/BiosDisk.c @@ -0,0 +1,205 @@ +/** @file + Copyright (C) 2023, Goldfish64. All rights reserved.
+ SPDX-License-Identifier: BSD-3-Clause +**/ + +#include "LegacyBootInternal.h" + +// +// Int 13 BIOS Errors +// +#define BIOS_PASS 0x00 +#define BIOS_WRITE_PROTECTED 0x03 +#define BIOS_SECTOR_NOT_FOUND 0x04 +#define BIOS_RESET_FAILED 0x05 +#define BIOS_DISK_CHANGED 0x06 +#define BIOS_DRIVE_DOES_NOT_EXIST 0x07 +#define BIOS_DMA_ERROR 0x08 +#define BIOS_DATA_BOUNDRY_ERROR 0x09 +#define BIOS_BAD_SECTOR 0x0a +#define BIOS_BAD_TRACK 0x0b +#define BIOS_MEADIA_TYPE_NOT_FOUND 0x0c +#define BIOS_INVALED_FORMAT 0x0d +#define BIOS_ECC_ERROR 0x10 +#define BIOS_ECC_CORRECTED_ERROR 0x11 +#define BIOS_HARD_DRIVE_FAILURE 0x20 +#define BIOS_SEEK_FAILED 0x40 +#define BIOS_DRIVE_TIMEOUT 0x80 +#define BIOS_DRIVE_NOT_READY 0xaa +#define BIOS_UNDEFINED_ERROR 0xbb +#define BIOS_WRITE_FAULT 0xcc +#define BIOS_SENSE_FAILED 0xff + +typedef struct { + UINT8 PacketSizeInBytes; // 0x10 + UINT8 Zero; + UINT8 NumberOfBlocks; // Max 0x7f + UINT8 Zero2; + UINT32 SegOffset; + UINT64 Lba; +} DEVICE_ADDRESS_PACKET; + +STATIC +EFI_STATUS +BiosDiskReset ( + IN THUNK_CONTEXT *ThunkContext, + IN EFI_LEGACY_8259_PROTOCOL *Legacy8259, + IN UINT8 DriveNumber + ) +{ + IA32_REGISTER_SET Regs; + UINTN CarryFlag; + + ZeroMem (&Regs, sizeof (IA32_REGISTER_SET)); + + Regs.H.AH = 0x00; + Regs.H.DL = DriveNumber; + CarryFlag = OcLegacyThunkBiosInt86 (ThunkContext, Legacy8259, 0x13, &Regs); + + if (CarryFlag != 0) { + DEBUG ((DEBUG_WARN, "LEG: Failed to reset BIOS disk %u, error 0x%X\n", DriveNumber, Regs.H.AL)); + if (Regs.H.AL == BIOS_RESET_FAILED) { + Regs.H.AH = 0x00; + Regs.H.DL = DriveNumber; + CarryFlag = OcLegacyThunkBiosInt86 (ThunkContext, Legacy8259, 0x13, &Regs); + if (CarryFlag != 0) { + DEBUG ((DEBUG_WARN, "LEG: Failed to reset BIOS disk %u, error 0x%X\n", DriveNumber, Regs.H.AH)); + return EFI_DEVICE_ERROR; + } + } + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +BiosDiskExtensionsSupported ( + IN THUNK_CONTEXT *ThunkContext, + IN EFI_LEGACY_8259_PROTOCOL *Legacy8259, + IN UINT8 DriveNumber + ) +{ + INTN CarryFlag; + IA32_REGISTER_SET Regs; + + ZeroMem (&Regs, sizeof (IA32_REGISTER_SET)); + + Regs.H.AH = 0x41; + Regs.X.BX = 0x55aa; + Regs.H.DL = DriveNumber; + CarryFlag = OcLegacyThunkBiosInt86 (ThunkContext, Legacy8259, 0x13, &Regs); + + if ((CarryFlag != 0) || (Regs.X.BX != 0xaa55)) { + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +BiosDiskReadExtSectors ( + IN THUNK_CONTEXT *ThunkContext, + IN EFI_LEGACY_8259_PROTOCOL *Legacy8259, + IN DEVICE_ADDRESS_PACKET *DeviceAddressPacket, + IN UINT8 DriveNumber, + IN UINT64 Lba, + IN UINT8 NumSectors, + IN OUT UINT8 *Buffer + ) +{ + INTN CarryFlag; + IA32_REGISTER_SET Regs; + + ZeroMem (&Regs, sizeof (IA32_REGISTER_SET)); + + DeviceAddressPacket->PacketSizeInBytes = sizeof (*DeviceAddressPacket); + DeviceAddressPacket->Zero = 0; + DeviceAddressPacket->NumberOfBlocks = NumSectors; + DeviceAddressPacket->Zero2 = 0; + DeviceAddressPacket->SegOffset = (UINT32)LShiftU64 (RShiftU64 ((UINTN)Buffer, 4), 16); + DeviceAddressPacket->Lba = Lba; + + Regs.H.AH = 0x42; + Regs.H.DL = DriveNumber; + Regs.X.SI = EFI_OFFSET (DeviceAddressPacket); + Regs.E.DS = EFI_SEGMENT (DeviceAddressPacket); + CarryFlag = OcLegacyThunkBiosInt86 (ThunkContext, Legacy8259, 0x13, &Regs); + + DEBUG ((DEBUG_INFO, "carry %u\n", CarryFlag)); + + return EFI_SUCCESS; +} + +EFI_STATUS +InternalGetBiosDiskNumber ( + IN THUNK_CONTEXT *ThunkContext, + IN EFI_LEGACY_8259_PROTOCOL *Legacy8259, + OUT UINT8 *DriveNumber + ) +{ + EFI_STATUS Status; + UINT8 DriveAddr; + EFI_PHYSICAL_ADDRESS DeviceAddressPacketAddress; + DEVICE_ADDRESS_PACKET *DeviceAddressPacket; + UINT8 *Buffer; + + // + // Allocate low memory buffer for disk reads. + // + DeviceAddressPacketAddress = (SIZE_1MB - 1); + Status = gBS->AllocatePages ( + AllocateMaxAddress, + EfiBootServicesData, + EFI_SIZE_TO_PAGES (sizeof (*DeviceAddressPacket) + (MBR_SIZE * 4)) + 1, + &DeviceAddressPacketAddress + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "LEG: Failure allocating low memory packet for BIOS disk read - %r\n", Status)); + return Status; + } + + DeviceAddressPacket = (DEVICE_ADDRESS_PACKET *)DeviceAddressPacketAddress; + Buffer = (UINT8 *)DeviceAddressPacketAddress + 0x200; + + // + // Locate disk with matching checksum of first few sectors. + // + for (DriveAddr = 0x80; DriveAddr < 0x88; DriveAddr++) { + DEBUG ((DEBUG_INFO, "drive %X\n", DriveAddr)); + + // + // Reset disk and verify INT13H extensions are supported. + // + Status = BiosDiskReset (ThunkContext, Legacy8259, DriveAddr); + if (EFI_ERROR (Status)) { + continue; + } + + Status = BiosDiskExtensionsSupported (ThunkContext, Legacy8259, DriveAddr); + if (EFI_ERROR (Status)) { + continue; + } + + // + // Read sectors from disk. + // + Status = BiosDiskReadExtSectors ( + ThunkContext, + Legacy8259, + DeviceAddressPacket, + DriveAddr, + 0, + 4, + Buffer + ); + if (EFI_ERROR (Status)) { + continue; + } + + DebugPrintHexDump (DEBUG_INFO, "raw bios bytes", Buffer, 512); + } + + return EFI_SUCCESS; +} diff --git a/Platform/OpenLegacyBoot/LegacyBootInternal.h b/Platform/OpenLegacyBoot/LegacyBootInternal.h index 68b2e76ff98..c6b4699575c 100644 --- a/Platform/OpenLegacyBoot/LegacyBootInternal.h +++ b/Platform/OpenLegacyBoot/LegacyBootInternal.h @@ -42,6 +42,13 @@ typedef struct { EFI_DEVICE_PATH_PROTOCOL *DevicePath; } OPEN_LEGACY_BOOT_CONTEXT; +EFI_STATUS +InternalGetBiosDiskNumber ( + IN THUNK_CONTEXT *ThunkContext, + IN EFI_LEGACY_8259_PROTOCOL *Legacy8259, + OUT UINT8 *DriveNumber + ); + EFI_STATUS InternalIsLegacyInterfaceSupported ( OUT BOOLEAN *IsAppleInterfaceSupported @@ -60,8 +67,9 @@ InternalGetPartitionLegacyOsType ( ); EFI_STATUS -InternalLoadLegacyMbr ( - IN EFI_DEVICE_PATH_PROTOCOL *HdDevicePath +InternalLoadLegacyPbr ( + IN EFI_DEVICE_PATH_PROTOCOL *PartitionPath, + IN EFI_HANDLE PartitionHandle ); #endif // LEGACY_BOOT_INTERNAL_H diff --git a/Platform/OpenLegacyBoot/LegacyBootSupport.c b/Platform/OpenLegacyBoot/LegacyBootSupport.c index 5830c8ce8d5..9196ba94379 100644 --- a/Platform/OpenLegacyBoot/LegacyBootSupport.c +++ b/Platform/OpenLegacyBoot/LegacyBootSupport.c @@ -356,20 +356,25 @@ InternalGetPartitionLegacyOsType ( } EFI_STATUS -InternalLoadLegacyMbr ( - IN EFI_DEVICE_PATH_PROTOCOL *HdDevicePath +InternalLoadLegacyPbr ( + IN EFI_DEVICE_PATH_PROTOCOL *PartitionPath, + IN EFI_HANDLE PartitionHandle ) { EFI_STATUS Status; EFI_HANDLE DiskHandle; MASTER_BOOT_RECORD *Mbr; - IA32_REGISTER_SET Regs; - UINT8 *MbrPtr = (UINT8 *)0x7C00; + MASTER_BOOT_RECORD *Pbr; + UINTN PbrSize; + OC_DISK_CONTEXT DiskContext; + IA32_REGISTER_SET Regs; + MASTER_BOOT_RECORD *MbrPtr = (MASTER_BOOT_RECORD *)0x0600; + MASTER_BOOT_RECORD *PbrPtr = (MASTER_BOOT_RECORD *)0x7C00; EFI_LEGACY_8259_PROTOCOL *Legacy8259; // - // Locate required protocols. + // Locate Legacy8259 protocol. // Status = gBS->LocateProtocol ( &gEfiLegacy8259ProtocolGuid, @@ -377,20 +382,55 @@ InternalLoadLegacyMbr ( (VOID **)&Legacy8259 ); if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_INFO, "OCB: Could not locate Legacy8259 protocol\n")); + DEBUG ((DEBUG_INFO, "LEG: Could not locate Legacy8259 protocol\n")); return Status; } - DebugPrintDevicePath (DEBUG_INFO, "OCB: Reading MBR for disk", HdDevicePath); + // + // Retrieve the PBR from partition. + // + Status = OcDiskInitializeContext ( + &DiskContext, + PartitionHandle, + TRUE + ); + if (EFI_ERROR (Status)) { + return Status; + } + + PbrSize = ALIGN_VALUE (sizeof (*Pbr), DiskContext.BlockSize); + Pbr = (MASTER_BOOT_RECORD *)AllocatePool (PbrSize); + if (Pbr == NULL) { + DEBUG ((DEBUG_INFO, "LEG: Buffer allocation error\n")); + return EFI_OUT_OF_RESOURCES; + } - DiskHandle = OcPartitionGetDiskHandle (HdDevicePath); + Status = OcDiskRead ( + &DiskContext, + 0, + PbrSize, + Pbr + ); + if (EFI_ERROR (Status)) { + FreePool (Pbr); + return Status; + } + + DebugPrintHexDump (DEBUG_INFO, "LEG: PbrHEX", (UINT8 *)Pbr, sizeof (*Pbr)); + + // + // Retrieve MBR from disk. + // + DiskHandle = OcPartitionGetDiskHandle (PartitionPath); if (DiskHandle == NULL) { + FreePool (Pbr); return EFI_INVALID_PARAMETER; } Mbr = OcGetDiskMbrTable (DiskHandle, TRUE); if (Mbr == NULL) { - DEBUG ((DEBUG_INFO, "OCB: Disk does not contain a valid MBR partition table\n")); + DEBUG ((DEBUG_INFO, "LEG: Disk does not contain a valid MBR partition table\n")); + FreePool (Pbr); return EFI_INVALID_PARAMETER; } @@ -399,22 +439,42 @@ InternalLoadLegacyMbr ( // Status = OcLegacyThunkInitializeBiosIntCaller (&mThunkContext); if (EFI_ERROR (Status)) { + FreePool (Pbr); + FreePool (Mbr); return Status; } Status = OcLegacyThunkInitializeInterruptRedirection (Legacy8259); if (EFI_ERROR (Status)) { + FreePool (Pbr); + FreePool (Mbr); return Status; } - DEBUG ((DEBUG_INFO, "OCB: Preparing to boot legacy system\n")); + // + // Determine BIOS disk number. + // + InternalGetBiosDiskNumber (&mThunkContext, Legacy8259, NULL); + + // + // Copy MBR and PBR to low memory locations for booting. + // + CopyMem (PbrPtr, Pbr, sizeof (*Pbr)); + CopyMem (MbrPtr, Mbr, sizeof (*Mbr)); + + DebugPrintHexDump (DEBUG_INFO, "LEG: PbrPtr", (UINT8 *)PbrPtr, sizeof (*PbrPtr)); OcLegacyThunkDisconnectEfiGraphics (); - CopyMem (MbrPtr, Mbr, sizeof (*Mbr)); + // + // Thunk to real mode and invoke legacy boot sector. + // If successful, this function will not return. + // ZeroMem (&Regs, sizeof (Regs)); - Regs.X.DX = 0x82; + + Regs.H.DL = 0x80; + Regs.X.SI = (UINT16)(UINTN)&MbrPtr->Partition[2]; OcLegacyThunkFarCall86 ( &mThunkContext, Legacy8259, diff --git a/Platform/OpenLegacyBoot/OpenLegacyBoot.c b/Platform/OpenLegacyBoot/OpenLegacyBoot.c index e8d2ac7ed11..c622c0a09c5 100644 --- a/Platform/OpenLegacyBoot/OpenLegacyBoot.c +++ b/Platform/OpenLegacyBoot/OpenLegacyBoot.c @@ -108,6 +108,8 @@ SystemActionDoLegacyBoot ( DEBUG ((DEBUG_WARN, "LEG: Failure while starting Apple legacy interface - %r\n", Status)); return Status; } + } else { + InternalLoadLegacyPbr (LegacyContext->DevicePath, LegacyContext->FsHandle); } return EFI_SUCCESS; diff --git a/Platform/OpenLegacyBoot/OpenLegacyBoot.inf b/Platform/OpenLegacyBoot/OpenLegacyBoot.inf index 80da3de5fdd..c553c39c255 100644 --- a/Platform/OpenLegacyBoot/OpenLegacyBoot.inf +++ b/Platform/OpenLegacyBoot/OpenLegacyBoot.inf @@ -39,6 +39,7 @@ gEfiLegacy8259ProtocolGuid ## SOMETIMES_CONSUMES [Sources] + BiosDisk.c LegacyBootInternal.h LegacyBootSupport.c OpenLegacyBoot.c From 5b8063f1d13238d810c7a4c68283a428ae6788fb Mon Sep 17 00:00:00 2001 From: John Davis Date: Sun, 13 Aug 2023 20:44:15 -0500 Subject: [PATCH 28/55] OpenLegacyBoot: Switch to separate action type for legacy entries --- .../Acidanthera/Library/OcBootManagementLib.h | 100 +++++++------- Include/Acidanthera/Library/OcFileLib.h | 14 +- Include/Acidanthera/Protocol/OcBootEntry.h | 2 +- Library/OcBootManagementLib/BootEntryInfo.c | 2 +- .../OcBootManagementLib/BootEntryManagement.c | 122 ++++++++++++++---- .../OcBootManagementLib/DefaultEntryChoice.c | 1 + Library/OcFileLib/DiskMisc.c | 114 +++++++++++++--- Platform/OpenLegacyBoot/LegacyBootInternal.h | 5 - Platform/OpenLegacyBoot/LegacyBootSupport.c | 2 - Platform/OpenLegacyBoot/OpenLegacyBoot.c | 46 +++---- Platform/ResetNvramEntry/ResetNvramEntry.c | 3 +- Platform/ToggleSipEntry/ToggleSipEntry.c | 3 +- 12 files changed, 289 insertions(+), 125 deletions(-) diff --git a/Include/Acidanthera/Library/OcBootManagementLib.h b/Include/Acidanthera/Library/OcBootManagementLib.h index 7ce19037501..0f7ea2518fe 100644 --- a/Include/Acidanthera/Library/OcBootManagementLib.h +++ b/Include/Acidanthera/Library/OcBootManagementLib.h @@ -152,6 +152,7 @@ typedef UINT32 OC_BOOT_ENTRY_TYPE; #define OC_BOOT_EXTERNAL_OS BIT6 #define OC_BOOT_EXTERNAL_TOOL BIT7 #define OC_BOOT_SYSTEM BIT8 +#define OC_BOOT_EXTERNAL_SYSTEM BIT9 /** Picker mode. @@ -190,8 +191,17 @@ typedef enum OC_PICKER_MODE_ { typedef EFI_STATUS (*OC_BOOT_SYSTEM_ACTION) ( - IN OUT OC_PICKER_CONTEXT *PickerContext, - IN VOID *ActionContext + IN OUT OC_PICKER_CONTEXT *PickerContext + ); + +/** + Action to perform as part of executing an external boot system boot entry. +**/ +typedef +EFI_STATUS +(*OC_BOOT_EXTERNAL_SYSTEM_ACTION) ( + IN OUT OC_PICKER_CONTEXT *PickerContext, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath ); /** @@ -202,107 +212,107 @@ typedef struct OC_BOOT_ENTRY_ { // // Link in entry list in OC_BOOT_FILESYSTEM. // - LIST_ENTRY Link; + LIST_ENTRY Link; // // Device path to booter or its directory. // Can be NULL, for example, for custom or system entries. // - EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; // // Action to perform on execution. Only valid for system entries. // - OC_BOOT_SYSTEM_ACTION SystemAction; + OC_BOOT_SYSTEM_ACTION SystemAction; // - // Context for action to perform on execution for system entries. + // Action to perform on execution. Only valid for external boot system entries. // - VOID *SystemActionContext; + OC_BOOT_EXTERNAL_SYSTEM_ACTION ExternalSystemAction; // // Id under which to save entry as default. // - CHAR16 *Id; + CHAR16 *Id; // // Obtained human visible name. // - CHAR16 *Name; + CHAR16 *Name; // // Obtained boot path directory. // For custom entries this contains tool path. // - CHAR16 *PathName; + CHAR16 *PathName; // // Content flavour. // - CHAR8 *Flavour; + CHAR8 *Flavour; // // Heuristical value signaling inferred type of booted os. // WARNING: Non-definitive, do not rely on for any security purposes. // - OC_BOOT_ENTRY_TYPE Type; + OC_BOOT_ENTRY_TYPE Type; // // Entry index number, assigned by picker. // - UINT32 EntryIndex; + UINT32 EntryIndex; // // Set when this entry is an externally available entry (e.g. USB). // - BOOLEAN IsExternal; + BOOLEAN IsExternal; // // Should try booting from first dmg found in DevicePath. // - BOOLEAN IsFolder; + BOOLEAN IsFolder; // // Set when this entry refers to a generic booter (e.g. BOOTx64.EFI). // - BOOLEAN IsGeneric; + BOOLEAN IsGeneric; // // Set when this entry refers to a custom boot entry. // - BOOLEAN IsCustom; + BOOLEAN IsCustom; // // Set when entry was created by OC_BOOT_ENTRY_PROTOCOL. // - BOOLEAN IsBootEntryProtocol; + BOOLEAN IsBootEntryProtocol; // // Set when entry is identified as macOS installer. // - BOOLEAN IsAppleInstaller; + BOOLEAN IsAppleInstaller; // // Should make this option default boot option. // - BOOLEAN SetDefault; + BOOLEAN SetDefault; // // Should launch this entry in text mode. // - BOOLEAN LaunchInText; + BOOLEAN LaunchInText; // // Should expose real device path when dealing with custom entries. // - BOOLEAN ExposeDevicePath; + BOOLEAN ExposeDevicePath; // // Should disable OpenRuntime NVRAM protection around invocation of tool. // - BOOLEAN FullNvramAccess; + BOOLEAN FullNvramAccess; // // Partition UUID of entry device. // Set for non-system action boot entry protocol boot entries only. // - EFI_GUID UniquePartitionGUID; + EFI_GUID UniquePartitionGUID; // // Load option data (usually "boot args") size. // - UINT32 LoadOptionsSize; + UINT32 LoadOptionsSize; // // Load option data (usually "boot args"). // - VOID *LoadOptions; + VOID *LoadOptions; // // Audio base path for system action. Boot Entry Protocol only. // - CHAR8 *AudioBasePath; + CHAR8 *AudioBasePath; // // Audio base type for system action. Boot Entry Protocol only. // - CHAR8 *AudioBaseType; + CHAR8 *AudioBaseType; } OC_BOOT_ENTRY; /** @@ -562,60 +572,60 @@ typedef struct { // Multiple entries may share an id - allows e.g. newest version // of Linux install to automatically become selected default. // - CONST CHAR8 *Id; + CONST CHAR8 *Id; // // Entry name. // - CONST CHAR8 *Name; + CONST CHAR8 *Name; // // Absolute device path to file for user custom entries, // file path relative to device root for boot entry protocol. // - CONST CHAR8 *Path; + CONST CHAR8 *Path; // // Entry boot arguments. // - CONST CHAR8 *Arguments; + CONST CHAR8 *Arguments; // // Content flavour. // - CONST CHAR8 *Flavour; + CONST CHAR8 *Flavour; // // Whether this entry is auxiliary. // - BOOLEAN Auxiliary; + BOOLEAN Auxiliary; // // Whether this entry is a tool. // - BOOLEAN Tool; + BOOLEAN Tool; // // Whether it should be started in text mode. // - BOOLEAN TextMode; + BOOLEAN TextMode; // // Whether we should pass the actual device path (if possible). // - BOOLEAN RealPath; + BOOLEAN RealPath; // // Should disable OpenRuntime NVRAM protection around invocation of tool. // - BOOLEAN FullNvramAccess; + BOOLEAN FullNvramAccess; // // System action. Boot Entry Protocol only. Optional. // - OC_BOOT_SYSTEM_ACTION SystemAction; - // - // System action context. Boot Entry Protocol only. Optional. - // - VOID *SystemActionContext; + OC_BOOT_SYSTEM_ACTION SystemAction; // // Audio base path for system action. Boot Entry Protocol only. Optional. // - CHAR8 *AudioBasePath; + CHAR8 *AudioBasePath; // // Audio base type for system action. Boot Entry Protocol only. Optional. // - CHAR8 *AudioBaseType; + CHAR8 *AudioBaseType; + // + // External boot system action. Boot Entry Protocol only. Optional. + // + OC_BOOT_EXTERNAL_SYSTEM_ACTION ExternalSystemAction; } OC_PICKER_ENTRY; /** diff --git a/Include/Acidanthera/Library/OcFileLib.h b/Include/Acidanthera/Library/OcFileLib.h index c7c3c178467..a86fbd5d9b8 100644 --- a/Include/Acidanthera/Library/OcFileLib.h +++ b/Include/Acidanthera/Library/OcFileLib.h @@ -508,6 +508,17 @@ OcPartitionGetDiskHandle ( IN EFI_DEVICE_PATH_PROTOCOL *HdDevicePath ); +/** + Retrieve the partition's device handle from a partition's Device Path. + + @param[in] HdDevicePath The Device Path of the partition. + +**/ +EFI_HANDLE +OcPartitionGetPartitionHandle ( + IN EFI_DEVICE_PATH_PROTOCOL *HdDevicePath + ); + /** Check if disk is a CD-ROM device. @@ -633,7 +644,8 @@ OcGetDiskMbrTable ( EFI_DEVICE_PATH_PROTOCOL * OcDiskFindActiveMbrPartitionPath ( IN EFI_DEVICE_PATH_PROTOCOL *DiskDevicePath, - OUT UINTN *PartitionDevicePathSize + OUT UINTN *PartitionDevicePathSize, + OUT EFI_HANDLE *PartitionDeviceHandle ); /** diff --git a/Include/Acidanthera/Protocol/OcBootEntry.h b/Include/Acidanthera/Protocol/OcBootEntry.h index 85c5bba6835..9ac8326c89a 100644 --- a/Include/Acidanthera/Protocol/OcBootEntry.h +++ b/Include/Acidanthera/Protocol/OcBootEntry.h @@ -28,7 +28,7 @@ WARNING: This protocol is currently undergoing active design. **/ -#define OC_BOOT_ENTRY_PROTOCOL_REVISION 4 +#define OC_BOOT_ENTRY_PROTOCOL_REVISION 5 /** Forward declaration of OC_BOOT_ENTRY_PROTOCOL structure. diff --git a/Library/OcBootManagementLib/BootEntryInfo.c b/Library/OcBootManagementLib/BootEntryInfo.c index b150ea334bb..0f2b937fd55 100644 --- a/Library/OcBootManagementLib/BootEntryInfo.c +++ b/Library/OcBootManagementLib/BootEntryInfo.c @@ -597,7 +597,7 @@ OcGetBootEntryFile ( IN BOOLEAN SearchAtRoot ) { - if ((BootEntry->Type & (OC_BOOT_EXTERNAL_TOOL | OC_BOOT_SYSTEM)) != 0) { + if ((BootEntry->Type & (OC_BOOT_EXTERNAL_TOOL | OC_BOOT_SYSTEM | OC_BOOT_EXTERNAL_SYSTEM)) != 0) { return EFI_NOT_FOUND; } diff --git a/Library/OcBootManagementLib/BootEntryManagement.c b/Library/OcBootManagementLib/BootEntryManagement.c index c27932c6292..9fbe2a2ccb6 100644 --- a/Library/OcBootManagementLib/BootEntryManagement.c +++ b/Library/OcBootManagementLib/BootEntryManagement.c @@ -691,7 +691,7 @@ InternalAddBootEntryFromCustomEntry ( return EFI_OUT_OF_RESOURCES; } - if (!CustomEntry->SystemAction) { + if (!CustomEntry->ExternalSystemAction && !CustomEntry->SystemAction) { ASSERT (CustomEntry->Path != NULL); PathName = AsciiStrCopyToUnicode (CustomEntry->Path, 0); if (PathName == NULL) { @@ -714,17 +714,27 @@ InternalAddBootEntryFromCustomEntry ( DEBUG_INFO, "OCB: Adding custom entry %s (%a|B:%d) -> %a\n", BootEntry->Name, - CustomEntry->SystemAction != NULL ? "action" : (CustomEntry->Tool ? "tool" : "os"), + CustomEntry->ExternalSystemAction != NULL ? "ext-action" : (CustomEntry->SystemAction != NULL ? "action" : (CustomEntry->Tool ? "tool" : "os")), IsBootEntryProtocol, CustomEntry->Path )); - if (CustomEntry->SystemAction) { - BootEntry->Type = OC_BOOT_SYSTEM; - BootEntry->SystemAction = CustomEntry->SystemAction; - BootEntry->SystemActionContext = CustomEntry->SystemActionContext; - BootEntry->AudioBasePath = CustomEntry->AudioBasePath; - BootEntry->AudioBaseType = CustomEntry->AudioBaseType; + if (CustomEntry->ExternalSystemAction) { + BootEntry->Type = OC_BOOT_EXTERNAL_SYSTEM; + BootEntry->ExternalSystemAction = CustomEntry->ExternalSystemAction; + BootEntry->AudioBasePath = CustomEntry->AudioBasePath; + BootEntry->AudioBaseType = CustomEntry->AudioBaseType; + BootEntry->DevicePath = DevicePathFromHandle (FileSystem->Handle); + + if (BootEntry->DevicePath == NULL) { + FreeBootEntry (BootEntry); + return EFI_OUT_OF_RESOURCES; + } + } else if (CustomEntry->SystemAction) { + BootEntry->Type = OC_BOOT_SYSTEM; + BootEntry->SystemAction = CustomEntry->SystemAction; + BootEntry->AudioBasePath = CustomEntry->AudioBasePath; + BootEntry->AudioBaseType = CustomEntry->AudioBaseType; } else if (CustomEntry->Tool) { BootEntry->Type = OC_BOOT_EXTERNAL_TOOL; UnicodeUefiSlashes (PathName); @@ -830,7 +840,7 @@ InternalAddBootEntryFromCustomEntry ( BootEntry->ExposeDevicePath = CustomEntry->RealPath; BootEntry->FullNvramAccess = CustomEntry->FullNvramAccess; - if (BootEntry->SystemAction != NULL) { + if ((BootEntry->ExternalSystemAction != NULL) || (BootEntry->SystemAction != NULL)) { ASSERT (CustomEntry->Arguments == NULL); } else { ASSERT (CustomEntry->Arguments != NULL); @@ -848,7 +858,7 @@ InternalAddBootEntryFromCustomEntry ( BootEntry->IsCustom = TRUE; BootEntry->IsBootEntryProtocol = IsBootEntryProtocol; - if (IsBootEntryProtocol && (BootEntry->SystemAction == NULL)) { + if (IsBootEntryProtocol && (BootEntry->ExternalSystemAction == NULL) && (BootEntry->SystemAction == NULL)) { PartitionEntry = OcGetGptPartitionEntry (FileSystem->Handle); if (PartitionEntry == NULL) { CopyGuid (&BootEntry->UniquePartitionGUID, &gEfiPartTypeUnusedGuid); @@ -1213,8 +1223,10 @@ AddBootEntryFromBootOption ( EFI_HANDLE FileSystemHandle; OC_BOOT_FILESYSTEM *FileSystem; UINTN DevicePathSize; + CHAR16 *TextDevicePath; INTN NumPatchedNodes; BOOLEAN IsAppleLegacy; + BOOLEAN IsAppleLegacyHandled; BOOLEAN IsRoot; EFI_LOAD_OPTION *LoadOption; UINTN LoadOptionSize; @@ -1306,6 +1318,7 @@ AddBootEntryFromBootOption ( // // Expand BootCamp device path to EFI partition device path. // + IsAppleLegacyHandled = FALSE; if (IsAppleLegacy) { // // BootCampHD always refers to a full Device Path. Failure to patch @@ -1317,13 +1330,77 @@ AddBootEntryFromBootOption ( return EFI_NOT_FOUND; } + // + // Attempt to handle detected legacy OS. + // RemainingDevicePath = DevicePath; - DevicePath = OcDiskFindSystemPartitionPath ( + DevicePath = OcDiskFindActiveMbrPartitionPath ( DevicePath, &DevicePathSize, &FileSystemHandle ); + // + // Disk with MBR or hybrid MBR was detected. + // + if (DevicePath != NULL) { + // + // Ensure that we are allowed to boot from this filesystem. + // + FileSystem = InternalFileSystemForHandle (BootContext, FileSystemHandle, TRUE, NULL); + if (FileSystem != NULL) { + TextDevicePath = ConvertDevicePathToText (DevicePath, FALSE, FALSE); + if (TextDevicePath != NULL) { + // + // Add entry from externally provided legacy interface. + // + Status = OcAddEntriesFromBootEntryProtocol ( + BootContext, + FileSystem, + EntryProtocolHandles, + EntryProtocolHandleCount, + TextDevicePath, + TRUE, + FALSE + ); + if (!EFI_ERROR (Status)) { + if (EntryProtocolId != NULL) { + *EntryProtocolId = TextDevicePath; + } + + IsAppleLegacyHandled = TRUE; + } else { + FreePool (TextDevicePath); + } + } + } + } + + if (!IsAppleLegacyHandled) { + // + // Boot option was set to Apple legacy interface incorrectly by macOS. + // This will occur on Macs that normally boot Windows in legacy mode, + // but have Windows installed in UEFI mode. + // + // Locate the ESP from the BootCampHD Device Path instead. + // + DevicePath = OcDiskFindSystemPartitionPath ( + RemainingDevicePath, + &DevicePathSize, + &FileSystemHandle + ); + + // + // Ensure that we are allowed to boot from this filesystem. + // + if (DevicePath != NULL) { + FileSystem = InternalFileSystemForHandle (BootContext, FileSystemHandle, LazyScan, NULL); + if (FileSystem == NULL) { + DevicePath = NULL; + } + } + } + FreePool (RemainingDevicePath); // @@ -1331,16 +1408,6 @@ AddBootEntryFromBootOption ( // IsRoot = TRUE; - // - // Ensure that we are allowed to boot from this filesystem. - // - if (DevicePath != NULL) { - FileSystem = InternalFileSystemForHandle (BootContext, FileSystemHandle, LazyScan, NULL); - if (FileSystem == NULL) { - DevicePath = NULL; - } - } - // // The Device Path returned by OcDiskFindSystemPartitionPath() is a pointer // to an installed protocol. Duplicate it so we own the memory. @@ -1566,6 +1633,10 @@ AddBootEntryFromBootOption ( FreePool (DevicePath); } + if (IsAppleLegacyHandled) { + return EFI_SUCCESS; + } + // // We may have a Boot#### entry pointing to macOS with full DP (up to boot.efi), // so IsRoot will be true. However, if this is APFS, we may still have: @@ -2089,6 +2160,8 @@ OcScanForBootEntries ( ) ); + IsDefaultEntryProtocolPartition = (DefaultEntryId != NULL); + // // No entries, or only entry pre-created from boot entry protocol, // so process this directory with Apple Bless. @@ -2441,9 +2514,14 @@ OcLoadBootEntry ( EFI_HANDLE EntryHandle; INTERNAL_DMG_LOAD_CONTEXT DmgLoadContext; + if ((BootEntry->Type & OC_BOOT_EXTERNAL_SYSTEM) != 0) { + ASSERT (BootEntry->ExternalSystemAction != NULL); + return BootEntry->ExternalSystemAction (Context, BootEntry->DevicePath); + } + if ((BootEntry->Type & OC_BOOT_SYSTEM) != 0) { ASSERT (BootEntry->SystemAction != NULL); - return BootEntry->SystemAction (Context, BootEntry->SystemActionContext); + return BootEntry->SystemAction (Context); } Status = InternalLoadBootEntry ( diff --git a/Library/OcBootManagementLib/DefaultEntryChoice.c b/Library/OcBootManagementLib/DefaultEntryChoice.c index 5c118fc072f..a51d8472e7a 100644 --- a/Library/OcBootManagementLib/DefaultEntryChoice.c +++ b/Library/OcBootManagementLib/DefaultEntryChoice.c @@ -1515,6 +1515,7 @@ InternalLoadBootEntry ( // // System entries are not loaded but called directly. // + ASSERT ((BootEntry->Type & OC_BOOT_EXTERNAL_SYSTEM) == 0); ASSERT ((BootEntry->Type & OC_BOOT_SYSTEM) == 0); ASSERT (Context != NULL); ASSERT (DmgLoadContext != NULL); diff --git a/Library/OcFileLib/DiskMisc.c b/Library/OcFileLib/DiskMisc.c index e6f228197bf..cf590d05db3 100644 --- a/Library/OcFileLib/DiskMisc.c +++ b/Library/OcFileLib/DiskMisc.c @@ -305,6 +305,28 @@ OcPartitionGetDiskHandle ( ); } +/** + Retrieve the partition's device handle from a partition's Device Path. + + @param[in] HdDevicePath The Device Path of the partition. + +**/ +EFI_HANDLE +OcPartitionGetPartitionHandle ( + IN EFI_DEVICE_PATH_PROTOCOL *HdDevicePath + ) +{ + BOOLEAN Dummy; + + ASSERT (HdDevicePath != NULL); + + return InternalGetDiskHandle ( + HdDevicePath, + FALSE, + &Dummy + ); +} + BOOLEAN OcIsDiskCdRom ( IN EFI_DEVICE_PATH_PROTOCOL *DiskDevicePath @@ -777,7 +799,8 @@ OcGetDiskMbrTable ( EFI_DEVICE_PATH_PROTOCOL * OcDiskFindActiveMbrPartitionPath ( IN EFI_DEVICE_PATH_PROTOCOL *DiskDevicePath, - OUT UINTN *PartitionDevicePathSize + OUT UINTN *PartitionDevicePathSize, + OUT EFI_HANDLE *PartitionDeviceHandle ) { EFI_STATUS Status; @@ -785,15 +808,41 @@ OcDiskFindActiveMbrPartitionPath ( BOOLEAN HasBlockIo2; UINTN Index; INT32 ActivePartition; + BOOLEAN Result; + INTN CmpResult; UINTN NoHandles; EFI_HANDLE *Handles; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *PartitionDevicePath; HARDDRIVE_DEVICE_PATH *HdNode; MASTER_BOOT_RECORD *Mbr; + UINTN DiskDpSize; + UINTN DiskDpCmpSize; + EFI_DEVICE_PATH_PROTOCOL *HdDevicePath; + UINTN HdDpSize; + ASSERT (DiskDevicePath != NULL); ASSERT (PartitionDevicePathSize != NULL); + ASSERT (PartitionDeviceHandle != NULL); + + DebugPrintDevicePath ( + DEBUG_INFO, + "OCPI: Locating MBR disk's active partition", + (EFI_DEVICE_PATH_PROTOCOL *)DiskDevicePath + ); + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiSimpleFileSystemProtocolGuid, + NULL, + &NoHandles, + &Handles + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "OCPI: Failed to locate FS handles\n")); + return NULL; + } // // Get MBR partition table from disk. @@ -835,41 +884,68 @@ OcDiskFindActiveMbrPartitionPath ( return NULL; } - Status = gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiBlockIoProtocolGuid, - NULL, - &NoHandles, - &Handles - ); - if (EFI_ERROR (Status)) { + // + // The partition's Device Path must be at least as big as the disk's (prefix) + // plus an additional HardDrive node. + // + DiskDpSize = GetDevicePathSize (DiskDevicePath); + Result = BaseOverflowAddUN ( + DiskDpSize, + sizeof (HARDDRIVE_DEVICE_PATH), + &DiskDpCmpSize + ); + if (Result) { + DEBUG ((DEBUG_INFO, "OCPI: HD node would overflow DP\n")); FreePool (Mbr); return NULL; } + PartitionDevicePath = NULL; + for (Index = 0; Index < NoHandles; Index++) { - DevicePath = DevicePathFromHandle (Handles[Index]); - if (DevicePath == NULL) { + HdDevicePath = DevicePathFromHandle (Handles[Index]); + if (HdDevicePath == NULL) { continue; } - if (CompareMem (DevicePath, DiskDevicePath, GetDevicePathSize (DiskDevicePath) - END_DEVICE_PATH_LENGTH) == 0) { + HdDpSize = GetDevicePathSize (HdDevicePath); + if (HdDpSize < DiskDpCmpSize) { + continue; + } + + // + // Verify the partition's Device Path has the disk's prefixed. + // + CmpResult = CompareMem ( + HdDevicePath, + DiskDevicePath, + DiskDpSize - END_DEVICE_PATH_LENGTH + ); + if (CmpResult != 0) { + continue; + } + + if (CompareMem (HdDevicePath, DiskDevicePath, GetDevicePathSize (DiskDevicePath) - END_DEVICE_PATH_LENGTH) == 0) { HdNode = (HARDDRIVE_DEVICE_PATH *)FindDevicePathNodeWithType ( - DevicePath, + HdDevicePath, MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP ); if (HdNode != NULL) { if (HdNode->PartitionStart == *((UINT32 *)Mbr->Partition[ActivePartition].StartingLBA)) { - DebugPrintDevicePath (DEBUG_INFO, "OCPI: Got active MBR partition device path", DevicePath); - FreePool (Mbr); - *PartitionDevicePathSize = GetDevicePathSize (DevicePath); - return DevicePath; + DebugPrintDevicePath (DEBUG_INFO, "OCPI: Got active MBR partition device path", HdDevicePath); + + PartitionDevicePath = HdDevicePath; + *PartitionDevicePathSize = HdDpSize; + *PartitionDeviceHandle = Handles[Index]; + break; } } } } + FreePool (Handles); FreePool (Mbr); - return NULL; + + return PartitionDevicePath; } diff --git a/Platform/OpenLegacyBoot/LegacyBootInternal.h b/Platform/OpenLegacyBoot/LegacyBootInternal.h index c6b4699575c..34b515cb72a 100644 --- a/Platform/OpenLegacyBoot/LegacyBootInternal.h +++ b/Platform/OpenLegacyBoot/LegacyBootInternal.h @@ -37,11 +37,6 @@ typedef enum OC_LEGACY_OS_TYPE_ { OcLegacyOsTypeIsoLinux } OC_LEGACY_OS_TYPE; -typedef struct { - EFI_HANDLE FsHandle; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; -} OPEN_LEGACY_BOOT_CONTEXT; - EFI_STATUS InternalGetBiosDiskNumber ( IN THUNK_CONTEXT *ThunkContext, diff --git a/Platform/OpenLegacyBoot/LegacyBootSupport.c b/Platform/OpenLegacyBoot/LegacyBootSupport.c index 9196ba94379..e8bbc3ae88e 100644 --- a/Platform/OpenLegacyBoot/LegacyBootSupport.c +++ b/Platform/OpenLegacyBoot/LegacyBootSupport.c @@ -5,7 +5,6 @@ #include "LegacyBootInternal.h" - THUNK_CONTEXT mThunkContext; // @@ -466,7 +465,6 @@ InternalLoadLegacyPbr ( OcLegacyThunkDisconnectEfiGraphics (); - // // Thunk to real mode and invoke legacy boot sector. // If successful, this function will not return. diff --git a/Platform/OpenLegacyBoot/OpenLegacyBoot.c b/Platform/OpenLegacyBoot/OpenLegacyBoot.c index c622c0a09c5..3c20f154003 100644 --- a/Platform/OpenLegacyBoot/OpenLegacyBoot.c +++ b/Platform/OpenLegacyBoot/OpenLegacyBoot.c @@ -50,17 +50,14 @@ InternalFreePickerEntry ( STATIC EFI_STATUS -SystemActionDoLegacyBoot ( - IN OUT OC_PICKER_CONTEXT *PickerContext, - IN VOID *ActionContext +ExternalSystemActionDoLegacyBoot ( + IN OUT OC_PICKER_CONTEXT *PickerContext, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath ) { EFI_STATUS Status; EFI_HANDLE LoadedImageHandle; EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; - OPEN_LEGACY_BOOT_CONTEXT *LegacyContext; - - LegacyContext = (OPEN_LEGACY_BOOT_CONTEXT *)ActionContext; // // Load and start legacy OS. @@ -68,11 +65,11 @@ SystemActionDoLegacyBoot ( // On Macs, use the Apple legacy interface. // On other systems, use the Legacy8259 protocol. // - DebugPrintDevicePath (DEBUG_INFO, "LEG: Legacy device path", LegacyContext->DevicePath); + DebugPrintDevicePath (DEBUG_INFO, "LEG: Legacy device path", DevicePath); if (mIsAppleInterfaceSupported) { Status = InternalLoadAppleLegacyInterface ( mImageHandle, - LegacyContext->DevicePath, + DevicePath, &LoadedImageHandle ); if (EFI_ERROR (Status)) { @@ -109,7 +106,7 @@ SystemActionDoLegacyBoot ( return Status; } } else { - InternalLoadLegacyPbr (LegacyContext->DevicePath, LegacyContext->FsHandle); + InternalLoadLegacyPbr (DevicePath, OcPartitionGetPartitionHandle (DevicePath)); } return EFI_SUCCESS; @@ -185,22 +182,21 @@ OcGetLegacyBootEntries ( return EFI_NOT_FOUND; } - PickerEntry = AllocateZeroPool (sizeof (*PickerEntry)); - PickerEntry->Id = "legacy_boot"; - PickerEntry->Name = "Windows (legacy)"; - PickerEntry->Path = NULL; - PickerEntry->Arguments = NULL; - PickerEntry->Flavour = OC_FLAVOUR_WINDOWS; - PickerEntry->Tool = FALSE; - PickerEntry->TextMode = TRUE; - PickerEntry->RealPath = FALSE; - PickerEntry->SystemAction = SystemActionDoLegacyBoot; - - OPEN_LEGACY_BOOT_CONTEXT *contex = (OPEN_LEGACY_BOOT_CONTEXT *)AllocateZeroPool (sizeof (OPEN_LEGACY_BOOT_CONTEXT)); - - contex->DevicePath = DevicePathFromHandle (Device); - contex->FsHandle = Device; - PickerEntry->SystemActionContext = contex; + CHAR16 *str2 = ConvertDevicePathToText (DevicePathFromHandle (Device), FALSE, FALSE); + CHAR8 *str = AllocateZeroPool (StrLen (str2) + 1); + + UnicodeStrToAsciiStrS (str2, str, StrLen (str2) + 1); + + PickerEntry = AllocateZeroPool (sizeof (*PickerEntry)); + PickerEntry->Id = str; + PickerEntry->Name = "Windows (legacy)"; + PickerEntry->Path = NULL; + PickerEntry->Arguments = NULL; + PickerEntry->Flavour = OC_FLAVOUR_WINDOWS; + PickerEntry->Tool = FALSE; + PickerEntry->TextMode = TRUE; + PickerEntry->RealPath = FALSE; + PickerEntry->ExternalSystemAction = ExternalSystemActionDoLegacyBoot; *Entries = PickerEntry; *NumEntries = 1; diff --git a/Platform/ResetNvramEntry/ResetNvramEntry.c b/Platform/ResetNvramEntry/ResetNvramEntry.c index dae08cf6f1d..025f53f4325 100644 --- a/Platform/ResetNvramEntry/ResetNvramEntry.c +++ b/Platform/ResetNvramEntry/ResetNvramEntry.c @@ -39,8 +39,7 @@ WaitForChime ( STATIC EFI_STATUS SystemActionResetNvram ( - IN OUT OC_PICKER_CONTEXT *PickerContext, - IN VOID *ActionContext + IN OUT OC_PICKER_CONTEXT *PickerContext ) { UINT8 ResetNVRam = 1; diff --git a/Platform/ToggleSipEntry/ToggleSipEntry.c b/Platform/ToggleSipEntry/ToggleSipEntry.c index b4092d562de..96255582045 100644 --- a/Platform/ToggleSipEntry/ToggleSipEntry.c +++ b/Platform/ToggleSipEntry/ToggleSipEntry.c @@ -32,8 +32,7 @@ STATIC BOOLEAN mShowCsr; STATIC EFI_STATUS SystemActionSetSip ( - IN OUT OC_PICKER_CONTEXT *Context, - IN VOID *ActionContext + IN OUT OC_PICKER_CONTEXT *Context ) { EFI_STATUS Status; From a0628f0faac22d415561565523784d75d2bd2177 Mon Sep 17 00:00:00 2001 From: John Davis Date: Sun, 13 Aug 2023 20:49:30 -0500 Subject: [PATCH 29/55] OcLegacyThunkLib: Add missing library reference to IoLib --- Library/OcLegacyThunkLib/OcLegacyThunkLib.inf | 1 + 1 file changed, 1 insertion(+) diff --git a/Library/OcLegacyThunkLib/OcLegacyThunkLib.inf b/Library/OcLegacyThunkLib/OcLegacyThunkLib.inf index ff863551a03..224f8888fb2 100644 --- a/Library/OcLegacyThunkLib/OcLegacyThunkLib.inf +++ b/Library/OcLegacyThunkLib/OcLegacyThunkLib.inf @@ -46,6 +46,7 @@ [LibraryClasses] BaseMemoryLib DebugLib + IoLib MemoryAllocationLib UefiBootServicesTableLib UefiLib From 2e8456e33d514476bb2761d1b9f0e5c2c7a919a6 Mon Sep 17 00:00:00 2001 From: John Davis Date: Sun, 13 Aug 2023 20:55:54 -0500 Subject: [PATCH 30/55] OcLegacyThunkLib: Add missing protocol reference --- Library/OcLegacyThunkLib/OcLegacyThunkLib.inf | 1 + 1 file changed, 1 insertion(+) diff --git a/Library/OcLegacyThunkLib/OcLegacyThunkLib.inf b/Library/OcLegacyThunkLib/OcLegacyThunkLib.inf index 224f8888fb2..7f9e9bc8dd6 100644 --- a/Library/OcLegacyThunkLib/OcLegacyThunkLib.inf +++ b/Library/OcLegacyThunkLib/OcLegacyThunkLib.inf @@ -41,6 +41,7 @@ [Protocols] gEfiLegacy8259ProtocolGuid + gEfiPciIoProtocolGuid gEfiTimerArchProtocolGuid [LibraryClasses] From 667d9c338335b31a1fbeedbc2e148312a4b8f52b Mon Sep 17 00:00:00 2001 From: John Davis Date: Sun, 13 Aug 2023 21:27:14 -0500 Subject: [PATCH 31/55] OpenLegacyBoot: Fix CI build issues --- Platform/OpenLegacyBoot/BiosDisk.c | 4 ++-- Platform/OpenLegacyBoot/OpenLegacyBoot.c | 13 ++----------- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/Platform/OpenLegacyBoot/BiosDisk.c b/Platform/OpenLegacyBoot/BiosDisk.c index cbe7097ff62..8bfccc83d5a 100644 --- a/Platform/OpenLegacyBoot/BiosDisk.c +++ b/Platform/OpenLegacyBoot/BiosDisk.c @@ -160,8 +160,8 @@ InternalGetBiosDiskNumber ( return Status; } - DeviceAddressPacket = (DEVICE_ADDRESS_PACKET *)DeviceAddressPacketAddress; - Buffer = (UINT8 *)DeviceAddressPacketAddress + 0x200; + DeviceAddressPacket = (DEVICE_ADDRESS_PACKET *)(UINTN)DeviceAddressPacketAddress; + Buffer = (UINT8 *)(UINTN)DeviceAddressPacketAddress + 0x200; // // Locate disk with matching checksum of first few sectors. diff --git a/Platform/OpenLegacyBoot/OpenLegacyBoot.c b/Platform/OpenLegacyBoot/OpenLegacyBoot.c index 3c20f154003..b5401993df0 100644 --- a/Platform/OpenLegacyBoot/OpenLegacyBoot.c +++ b/Platform/OpenLegacyBoot/OpenLegacyBoot.c @@ -31,17 +31,9 @@ InternalFreePickerEntry ( FreePool ((CHAR8 *)Entry->Id); } - if (Entry->Name != NULL) { + /*if (Entry->Name != NULL) { FreePool ((CHAR8 *)Entry->Name); - } - - if (Entry->Path != NULL) { - FreePool ((CHAR8 *)Entry->Path); - } - - if (Entry->Arguments != NULL) { - FreePool ((CHAR8 *)Entry->Arguments); - } + }*/ if (Entry->Flavour != NULL) { FreePool ((CHAR8 *)Entry->Flavour); @@ -212,7 +204,6 @@ OcFreeLegacyBootEntries ( IN UINTN NumEntries ) { - return; UINTN Index; ASSERT (Entries != NULL); From d5de54598c082d5865e3e9b40e73220bf2f29301 Mon Sep 17 00:00:00 2001 From: John Davis Date: Mon, 14 Aug 2023 18:03:35 -0500 Subject: [PATCH 32/55] OpenLegacyBoot: Fix prefix on debug prints --- Platform/OpenLegacyBoot/BiosDisk.c | 6 ++--- Platform/OpenLegacyBoot/LegacyBootSupport.c | 27 +++++++++++---------- Platform/OpenLegacyBoot/OpenLegacyBoot.c | 18 +++++++------- 3 files changed, 26 insertions(+), 25 deletions(-) diff --git a/Platform/OpenLegacyBoot/BiosDisk.c b/Platform/OpenLegacyBoot/BiosDisk.c index 8bfccc83d5a..4fa45a5045e 100644 --- a/Platform/OpenLegacyBoot/BiosDisk.c +++ b/Platform/OpenLegacyBoot/BiosDisk.c @@ -57,13 +57,13 @@ BiosDiskReset ( CarryFlag = OcLegacyThunkBiosInt86 (ThunkContext, Legacy8259, 0x13, &Regs); if (CarryFlag != 0) { - DEBUG ((DEBUG_WARN, "LEG: Failed to reset BIOS disk %u, error 0x%X\n", DriveNumber, Regs.H.AL)); + DEBUG ((DEBUG_WARN, "OLB: Failed to reset BIOS disk %u, error 0x%X\n", DriveNumber, Regs.H.AL)); if (Regs.H.AL == BIOS_RESET_FAILED) { Regs.H.AH = 0x00; Regs.H.DL = DriveNumber; CarryFlag = OcLegacyThunkBiosInt86 (ThunkContext, Legacy8259, 0x13, &Regs); if (CarryFlag != 0) { - DEBUG ((DEBUG_WARN, "LEG: Failed to reset BIOS disk %u, error 0x%X\n", DriveNumber, Regs.H.AH)); + DEBUG ((DEBUG_WARN, "OLB: Failed to reset BIOS disk %u, error 0x%X\n", DriveNumber, Regs.H.AH)); return EFI_DEVICE_ERROR; } } @@ -156,7 +156,7 @@ InternalGetBiosDiskNumber ( &DeviceAddressPacketAddress ); if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_WARN, "LEG: Failure allocating low memory packet for BIOS disk read - %r\n", Status)); + DEBUG ((DEBUG_WARN, "OLB: Failure allocating low memory packet for BIOS disk read - %r\n", Status)); return Status; } diff --git a/Platform/OpenLegacyBoot/LegacyBootSupport.c b/Platform/OpenLegacyBoot/LegacyBootSupport.c index e8bbc3ae88e..e46b1cf096a 100644 --- a/Platform/OpenLegacyBoot/LegacyBootSupport.c +++ b/Platform/OpenLegacyBoot/LegacyBootSupport.c @@ -182,7 +182,7 @@ InternalLoadAppleLegacyInterface ( return EFI_INVALID_PARAMETER; } - DebugPrintDevicePath (DEBUG_INFO, "OCB: Legacy disk device path", WholeDiskPath); + DebugPrintDevicePath (DEBUG_INFO, "OLB: Legacy disk device path", WholeDiskPath); // TODO: Mark target partition as active on pure MBR and hybrid GPT disks. // Macs only boot the active partition. @@ -227,7 +227,7 @@ InternalLoadAppleLegacyInterface ( UnicodeDevicePath = ConvertDevicePathToText (LegacyDevicePaths[Index], FALSE, FALSE); DEBUG (( DEBUG_INFO, - "OCB: Loaded Apple legacy interface at dp %s - %r\n", + "OLB: Loaded Apple legacy interface at dp %s - %r\n", UnicodeDevicePath != NULL ? UnicodeDevicePath : L"", Status )); @@ -271,7 +271,7 @@ InternalGetPartitionLegacyOsType ( return OcLegacyOsTypeNone; } - DebugPrintDevicePath (DEBUG_INFO, "OCB: Reading MBR for disk", DevicePath); + DebugPrintDevicePath (DEBUG_INFO, "OLB: Reading MBR for disk", DevicePath); DiskHandle = OcPartitionGetDiskHandle (DevicePath); if (DiskHandle == NULL) { @@ -280,7 +280,7 @@ InternalGetPartitionLegacyOsType ( Mbr = OcGetDiskMbrTable (DiskHandle, TRUE); if (Mbr == NULL) { - DEBUG ((DEBUG_INFO, "OCB: Disk does not contain a valid MBR partition table\n")); + DEBUG ((DEBUG_INFO, "OLB: Disk does not contain a valid MBR partition table\n")); return OcLegacyOsTypeNone; } @@ -293,7 +293,7 @@ InternalGetPartitionLegacyOsType ( // // Retrieve the first sector of the partition. // - DebugPrintDevicePath (DEBUG_INFO, "OCB: Reading PBR for partition", DevicePath); + DebugPrintDevicePath (DEBUG_INFO, "OLB: Reading PBR for partition", DevicePath); Status = OcDiskInitializeContext ( &DiskContext, PartitionHandle, @@ -306,7 +306,7 @@ InternalGetPartitionLegacyOsType ( MbrSize = ALIGN_VALUE (sizeof (*Mbr), DiskContext.BlockSize); Mbr = (MASTER_BOOT_RECORD *)AllocatePool (MbrSize); if (Mbr == NULL) { - DEBUG ((DEBUG_INFO, "OCB: Buffer allocation error\n")); + DEBUG ((DEBUG_INFO, "OLB: Buffer allocation error\n")); return OcLegacyOsTypeNone; } @@ -322,7 +322,7 @@ InternalGetPartitionLegacyOsType ( } } - DebugPrintHexDump (DEBUG_INFO, "OCB: MbrHEX", Mbr->BootStrapCode, sizeof (Mbr->BootStrapCode)); + DebugPrintHexDump (DEBUG_INFO, "OLB: MbrHEX", Mbr->BootStrapCode, sizeof (Mbr->BootStrapCode)); // // Validate signature in MBR. @@ -346,7 +346,7 @@ InternalGetPartitionLegacyOsType ( LegacyOsType = OcLegacyOsTypeIsoLinux; } else { LegacyOsType = OcLegacyOsTypeNone; - DEBUG ((DEBUG_INFO, "OCB: Unknown legacy bootsector signature\n")); + DEBUG ((DEBUG_INFO, "OLB: Unknown legacy bootsector signature\n")); } FreePool (Mbr); @@ -381,7 +381,7 @@ InternalLoadLegacyPbr ( (VOID **)&Legacy8259 ); if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_INFO, "LEG: Could not locate Legacy8259 protocol\n")); + DEBUG ((DEBUG_INFO, "OLB: Could not locate Legacy8259 protocol\n")); return Status; } @@ -400,7 +400,7 @@ InternalLoadLegacyPbr ( PbrSize = ALIGN_VALUE (sizeof (*Pbr), DiskContext.BlockSize); Pbr = (MASTER_BOOT_RECORD *)AllocatePool (PbrSize); if (Pbr == NULL) { - DEBUG ((DEBUG_INFO, "LEG: Buffer allocation error\n")); + DEBUG ((DEBUG_INFO, "OLB: Buffer allocation error\n")); return EFI_OUT_OF_RESOURCES; } @@ -415,7 +415,7 @@ InternalLoadLegacyPbr ( return Status; } - DebugPrintHexDump (DEBUG_INFO, "LEG: PbrHEX", (UINT8 *)Pbr, sizeof (*Pbr)); + DebugPrintHexDump (DEBUG_INFO, "OLB: PbrHEX", (UINT8 *)Pbr, sizeof (*Pbr)); // // Retrieve MBR from disk. @@ -428,7 +428,7 @@ InternalLoadLegacyPbr ( Mbr = OcGetDiskMbrTable (DiskHandle, TRUE); if (Mbr == NULL) { - DEBUG ((DEBUG_INFO, "LEG: Disk does not contain a valid MBR partition table\n")); + DEBUG ((DEBUG_INFO, "OLB: Disk does not contain a valid MBR partition table\n")); FreePool (Pbr); return EFI_INVALID_PARAMETER; } @@ -461,9 +461,10 @@ InternalLoadLegacyPbr ( CopyMem (PbrPtr, Pbr, sizeof (*Pbr)); CopyMem (MbrPtr, Mbr, sizeof (*Mbr)); - DebugPrintHexDump (DEBUG_INFO, "LEG: PbrPtr", (UINT8 *)PbrPtr, sizeof (*PbrPtr)); + DebugPrintHexDump (DEBUG_INFO, "OLB: PbrPtr", (UINT8 *)PbrPtr, sizeof (*PbrPtr)); OcLegacyThunkDisconnectEfiGraphics (); + ReleaseUsbOwnership (); // // Thunk to real mode and invoke legacy boot sector. diff --git a/Platform/OpenLegacyBoot/OpenLegacyBoot.c b/Platform/OpenLegacyBoot/OpenLegacyBoot.c index b5401993df0..1ba0e207617 100644 --- a/Platform/OpenLegacyBoot/OpenLegacyBoot.c +++ b/Platform/OpenLegacyBoot/OpenLegacyBoot.c @@ -57,7 +57,7 @@ ExternalSystemActionDoLegacyBoot ( // On Macs, use the Apple legacy interface. // On other systems, use the Legacy8259 protocol. // - DebugPrintDevicePath (DEBUG_INFO, "LEG: Legacy device path", DevicePath); + DebugPrintDevicePath (DEBUG_INFO, "OLB: Legacy device path", DevicePath); if (mIsAppleInterfaceSupported) { Status = InternalLoadAppleLegacyInterface ( mImageHandle, @@ -65,7 +65,7 @@ ExternalSystemActionDoLegacyBoot ( &LoadedImageHandle ); if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_WARN, "LEG: Failure while loading Apple legacy interface - %r\n", Status)); + DEBUG ((DEBUG_WARN, "OLB: Failure while loading Apple legacy interface - %r\n", Status)); return Status; } @@ -75,7 +75,7 @@ ExternalSystemActionDoLegacyBoot ( (VOID **)&LoadedImage ); if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_WARN, "LEG: Failure while loading Apple legacy interface - %r\n", Status)); + DEBUG ((DEBUG_WARN, "OLB: Failure while loading Apple legacy interface - %r\n", Status)); return Status; } @@ -94,7 +94,7 @@ ExternalSystemActionDoLegacyBoot ( )); Status = gBS->StartImage (LoadedImageHandle, NULL, NULL); if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_WARN, "LEG: Failure while starting Apple legacy interface - %r\n", Status)); + DEBUG ((DEBUG_WARN, "OLB: Failure while starting Apple legacy interface - %r\n", Status)); return Status; } } else { @@ -139,7 +139,7 @@ OcGetLegacyBootEntries ( (VOID **)&FileSystem ); if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_WARN, "LEG: Missing filesystem - %r\n", Status)); + DEBUG ((DEBUG_WARN, "OLB: Missing filesystem - %r\n", Status)); return Status; } @@ -151,7 +151,7 @@ OcGetLegacyBootEntries ( &RootDirectory ); if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_WARN, "LEG: Invalid root volume - %r\n", Status)); + DEBUG ((DEBUG_WARN, "OLB: Invalid root volume - %r\n", Status)); return Status; } @@ -161,7 +161,7 @@ OcGetLegacyBootEntries ( // Disallow all but NTFS filesystems. // // if ((FileSystemPolicy & OC_SCAN_ALLOW_FS_NTFS) != 0) { - // DEBUG ((DEBUG_INFO, "LEG: Not scanning non-NTFS filesystem\n")); + // DEBUG ((DEBUG_INFO, "OLB: Not scanning non-NTFS filesystem\n")); // Status = EFI_NOT_FOUND; // } @@ -242,11 +242,11 @@ UefiMain ( Status = InternalIsLegacyInterfaceSupported (&mIsAppleInterfaceSupported); if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_WARN, "LEG: Legacy boot interface is supported on this system\n")); + DEBUG ((DEBUG_WARN, "OLB: Legacy boot interface is supported on this system\n")); return Status; } - DEBUG ((DEBUG_INFO, "LEG: Apple legacy interface: %d\n", mIsAppleInterfaceSupported)); + DEBUG ((DEBUG_INFO, "OLB: Apple legacy interface: %d\n", mIsAppleInterfaceSupported)); Status = gBS->InstallMultipleProtocolInterfaces ( &ImageHandle, From 387adeb564cc482dc81d47b80a16d351fb724369 Mon Sep 17 00:00:00 2001 From: John Davis Date: Mon, 14 Aug 2023 19:34:52 -0500 Subject: [PATCH 33/55] OpenLegacyBoot: Fix previous commit --- Platform/OpenLegacyBoot/LegacyBootSupport.c | 1 - 1 file changed, 1 deletion(-) diff --git a/Platform/OpenLegacyBoot/LegacyBootSupport.c b/Platform/OpenLegacyBoot/LegacyBootSupport.c index e46b1cf096a..7d32ad5f422 100644 --- a/Platform/OpenLegacyBoot/LegacyBootSupport.c +++ b/Platform/OpenLegacyBoot/LegacyBootSupport.c @@ -464,7 +464,6 @@ InternalLoadLegacyPbr ( DebugPrintHexDump (DEBUG_INFO, "OLB: PbrPtr", (UINT8 *)PbrPtr, sizeof (*PbrPtr)); OcLegacyThunkDisconnectEfiGraphics (); - ReleaseUsbOwnership (); // // Thunk to real mode and invoke legacy boot sector. From e03a5773aec04a1608841775bcf719ed20fe23d0 Mon Sep 17 00:00:00 2001 From: John Davis Date: Thu, 17 Aug 2023 17:31:50 -0500 Subject: [PATCH 34/55] OpenLegacyBoot: Implement active partition switching --- Include/Acidanthera/Library/OcFileLib.h | 63 +++++- Library/OcFileLib/DiskMisc.c | 226 +++++++++++++++++-- Platform/OpenLegacyBoot/LegacyBootInternal.h | 3 +- Platform/OpenLegacyBoot/LegacyBootSupport.c | 65 ++++-- Platform/OpenLegacyBoot/OpenLegacyBoot.c | 2 +- 5 files changed, 310 insertions(+), 49 deletions(-) diff --git a/Include/Acidanthera/Library/OcFileLib.h b/Include/Acidanthera/Library/OcFileLib.h index a86fbd5d9b8..5295fc80e9e 100644 --- a/Include/Acidanthera/Library/OcFileLib.h +++ b/Include/Acidanthera/Library/OcFileLib.h @@ -591,6 +591,24 @@ OcDiskRead ( OUT VOID *Buffer ); +/** + Write information to disk. + + @param[in] Context Disk I/O context. + @param[in] Lba LBA number to write to. + @param[in] BufferSize Buffer size allocated in Buffer. + @param[out] Buffer Buffer containing data to write. + + @retval EFI_SUCCESS on success. +**/ +EFI_STATUS +OcDiskWrite ( + IN OC_DISK_CONTEXT *Context, + IN UINT64 Lba, + IN UINTN BufferSize, + IN VOID *Buffer + ); + /** OC partition list. **/ @@ -630,17 +648,54 @@ OcGetGptPartitionEntry ( /** Retrieve the disk MBR table, if applicable. - @param[in] DiskHandle Disk device handle to retrive MBR partition table from. - @param[in] UseBlockIo2 Use 2nd revision of Block I/O if available. + @param[in] DiskHandle Disk device handle to retrive MBR partition table from. + @param[in] CheckPartitions Check partition layout. This should be FALSE for a PBR. - @retval partition entry list or NULL. + @retval MBR partition table or NULL. **/ MASTER_BOOT_RECORD * OcGetDiskMbrTable ( IN EFI_HANDLE DiskHandle, - IN BOOLEAN UseBlockIo2 + IN BOOLEAN CheckPartitions + ); + +/** + Retrieve the MBR partition index for the specified partition. + + @param[in] PartitionHandle Partition device handle to retrieve MBR partition index for. + @param[out] PartitionIndex Pointer to store partition index in. + + @retval EFI_SUCCESS on success. +**/ +EFI_STATUS +OcDiskGetMbrPartitionIndex ( + IN EFI_HANDLE PartitionHandle, + OUT UINT8 *PartitionIndex ); +/** + Mark specified MBR partition as active. + + @param[in] DiskHandle Disk device handle containing MBR partition table + @param[in] PartitionIndex MBR partition index. + + @retval EFI_SUCCESS on success. +**/ +EFI_STATUS +OcDiskMarkMbrPartitionActive ( + IN EFI_HANDLE DiskHandle, + IN UINT8 PartitionIndex + ); + +/** + Locate the disk's active MBR partition. + + @param[in] DiskDevicePath The Device Path of the disk to scan. + @param[out] PartitionDevicePathSize The size of the returned Device Path. + @param[out] PartitionDeviceHandle Device handle of the returned partition. + + @return The device path protocol from the discovered handle or NULL. +**/ EFI_DEVICE_PATH_PROTOCOL * OcDiskFindActiveMbrPartitionPath ( IN EFI_DEVICE_PATH_PROTOCOL *DiskDevicePath, diff --git a/Library/OcFileLib/DiskMisc.c b/Library/OcFileLib/DiskMisc.c index cf590d05db3..c5eeed47b46 100644 --- a/Library/OcFileLib/DiskMisc.c +++ b/Library/OcFileLib/DiskMisc.c @@ -40,6 +40,8 @@ STATIC EFI_GUID mInternalPartitionEntryProtocolGuid = { 0x9FC6B19, 0xB8A1, 0x4A01, { 0x8D, 0xB1, 0x87, 0x94, 0xE7, 0x63, 0x4C, 0xA5 } }; +#define MBR_PARTITION_ACTIVE 0x80 + EFI_STATUS OcDiskInitializeContext ( OUT OC_DISK_CONTEXT *Context, @@ -49,6 +51,9 @@ OcDiskInitializeContext ( { EFI_STATUS Status; + ASSERT (Context != NULL); + ASSERT (DiskHandle != NULL); + // // Retrieve the Block I/O protocol. // @@ -142,6 +147,41 @@ OcDiskRead ( return Status; } +EFI_STATUS +OcDiskWrite ( + IN OC_DISK_CONTEXT *Context, + IN UINT64 Lba, + IN UINTN BufferSize, + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + + ASSERT (Context->BlockIo != NULL || Context->BlockIo2 != NULL); + ASSERT ((BufferSize & (Context->BlockSize - 1)) == 0); + + if (Context->BlockIo2 != NULL) { + Status = Context->BlockIo2->WriteBlocksEx ( + Context->BlockIo2, + Context->MediaId, + Lba, + NULL, + BufferSize, + Buffer + ); + } else { + Status = Context->BlockIo->WriteBlocks ( + Context->BlockIo, + Context->MediaId, + Lba, + BufferSize, + Buffer + ); + } + + return Status; +} + STATIC VOID InternalDebugPrintPartitionEntry ( @@ -723,7 +763,7 @@ OcGetGptPartitionEntry ( MASTER_BOOT_RECORD * OcGetDiskMbrTable ( IN EFI_HANDLE DiskHandle, - IN BOOLEAN UseBlockIo2 + IN BOOLEAN CheckPartitions ) { EFI_STATUS Status; @@ -741,7 +781,7 @@ OcGetDiskMbrTable ( Status = OcDiskInitializeContext ( &DiskContext, DiskHandle, - UseBlockIo2 + TRUE ); if (EFI_ERROR (Status)) { return NULL; @@ -775,27 +815,178 @@ OcGetDiskMbrTable ( return NULL; } - if ( (Mbr->Partition[0].OSIndicator == PMBR_GPT_PARTITION) - && (*((UINT32 *)Mbr->Partition[0].StartingLBA) == 0x01) - && (*((UINT32 *)Mbr->Partition[0].SizeInLBA) != 0)) - { - IsProtectiveMbr = TRUE; - for (Index = 1; Index < MAX_MBR_PARTITIONS; Index++) { - if ((*((UINT32 *)Mbr->Partition[Index].StartingLBA) != 0) || (*((UINT32 *)Mbr->Partition[Index].SizeInLBA) != 0)) { - IsProtectiveMbr = FALSE; - break; + if (CheckPartitions) { + if ( (Mbr->Partition[0].OSIndicator == PMBR_GPT_PARTITION) + && (*((UINT32 *)Mbr->Partition[0].StartingLBA) == 0x01) + && (*((UINT32 *)Mbr->Partition[0].SizeInLBA) != 0)) + { + IsProtectiveMbr = TRUE; + for (Index = 1; Index < MAX_MBR_PARTITIONS; Index++) { + if ((*((UINT32 *)Mbr->Partition[Index].StartingLBA) != 0) || (*((UINT32 *)Mbr->Partition[Index].SizeInLBA) != 0)) { + IsProtectiveMbr = FALSE; + break; + } } - } - if (IsProtectiveMbr) { - FreePool (Mbr); - return NULL; + if (IsProtectiveMbr) { + FreePool (Mbr); + return NULL; + } } } return Mbr; } +EFI_STATUS +OcDiskGetMbrPartitionIndex ( + IN EFI_HANDLE PartitionHandle, + OUT UINT8 *PartitionIndex + ) +{ + EFI_STATUS Status; + MASTER_BOOT_RECORD *Mbr; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_HANDLE DiskHandle; + CONST HARDDRIVE_DEVICE_PATH *HdNode; + UINT8 Index; + + ASSERT (PartitionHandle != NULL); + ASSERT (PartitionIndex != NULL); + + // + // Retrieve the partition Device Path information. + // + DevicePath = DevicePathFromHandle (PartitionHandle); + if (DevicePath == NULL) { + DEBUG ((DEBUG_INFO, "OCPI: Failed to retrieve Device Path\n")); + return EFI_UNSUPPORTED; + } + + HdNode = (HARDDRIVE_DEVICE_PATH *)( + FindDevicePathNodeWithType ( + DevicePath, + MEDIA_DEVICE_PATH, + MEDIA_HARDDRIVE_DP + ) + ); + if (HdNode == NULL) { + DEBUG ((DEBUG_INFO, "OCPI: Device Path does not describe a partition\n")); + return EFI_UNSUPPORTED; + } + + DiskHandle = OcPartitionGetDiskHandle (DevicePath); + if (DiskHandle == NULL) { + return EFI_UNSUPPORTED; + } + + // + // Get MBR from partition's disk. + // + Mbr = OcGetDiskMbrTable ( + DiskHandle, + TRUE + ); + if (Mbr == NULL) { + DEBUG ((DEBUG_INFO, "OCPI: Disk does not have an MBR partition table\n")); + return EFI_UNSUPPORTED; + } + + Status = EFI_NOT_FOUND; + for (Index = 0; Index < MAX_MBR_PARTITIONS; Index++) { + if ( (*((UINT32 *)Mbr->Partition[Index].StartingLBA) == HdNode->PartitionStart) + && (*((UINT32 *)Mbr->Partition[Index].SizeInLBA) == HdNode->PartitionSize)) + { + *PartitionIndex = Index; + Status = EFI_SUCCESS; + break; + } + } + + FreePool (Mbr); + + return Status; +} + +EFI_STATUS +OcDiskMarkMbrPartitionActive ( + IN EFI_HANDLE DiskHandle, + IN UINT8 PartitionIndex + ) +{ + EFI_STATUS Status; + MASTER_BOOT_RECORD *Mbr; + UINTN MbrSize; + UINTN Index; + OC_DISK_CONTEXT DiskContext; + + ASSERT (DiskHandle != NULL); + ASSERT (PartitionIndex < MAX_MBR_PARTITIONS); + + // + // Read first sector containing MBR table. + // + Status = OcDiskInitializeContext ( + &DiskContext, + DiskHandle, + TRUE + ); + if (EFI_ERROR (Status)) { + return Status; + } + + MbrSize = ALIGN_VALUE (sizeof (*Mbr), DiskContext.BlockSize); + Mbr = (MASTER_BOOT_RECORD *)AllocatePool (MbrSize); + if (Mbr == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = OcDiskRead ( + &DiskContext, + 0, + MbrSize, + Mbr + ); + if (EFI_ERROR (Status)) { + FreePool (Mbr); + return Status; + } + + // + // Validate MBR signatures. + // + // If MBR is a protective one (as part of a GPT disk), ignore. + // Protective MBR is defined as a single partition of type 0xEE, other three partitions are to be zero. + // + if (Mbr->Signature != MBR_SIGNATURE) { + FreePool (Mbr); + return EFI_UNSUPPORTED; + } + + // + // Mark desired partition as active. + // + for (Index = 0; Index < MAX_MBR_PARTITIONS; Index++) { + Mbr->Partition[Index].BootIndicator = 0x00; + } + + Mbr->Partition[PartitionIndex].BootIndicator = MBR_PARTITION_ACTIVE; + + // + // Write MBR to disk. + // + Status = OcDiskWrite ( + &DiskContext, + 0, + MbrSize, + Mbr + ); + + FreePool (Mbr); + + return Status; +} + EFI_DEVICE_PATH_PROTOCOL * OcDiskFindActiveMbrPartitionPath ( IN EFI_DEVICE_PATH_PROTOCOL *DiskDevicePath, @@ -858,7 +1049,7 @@ OcDiskFindActiveMbrPartitionPath ( Mbr = OcGetDiskMbrTable ( DiskHandle, - HasBlockIo2 + TRUE ); if (Mbr == NULL) { return NULL; @@ -870,8 +1061,9 @@ OcDiskFindActiveMbrPartitionPath ( // ActivePartition = -1; for (Index = 0; Index < MAX_MBR_PARTITIONS; Index++) { - if (Mbr->Partition[Index].BootIndicator == 0x80) { + if (Mbr->Partition[Index].BootIndicator == MBR_PARTITION_ACTIVE) { ActivePartition = (INT32)Index; + break; } } diff --git a/Platform/OpenLegacyBoot/LegacyBootInternal.h b/Platform/OpenLegacyBoot/LegacyBootInternal.h index 34b515cb72a..735a5976672 100644 --- a/Platform/OpenLegacyBoot/LegacyBootInternal.h +++ b/Platform/OpenLegacyBoot/LegacyBootInternal.h @@ -63,8 +63,7 @@ InternalGetPartitionLegacyOsType ( EFI_STATUS InternalLoadLegacyPbr ( - IN EFI_DEVICE_PATH_PROTOCOL *PartitionPath, - IN EFI_HANDLE PartitionHandle + IN EFI_DEVICE_PATH_PROTOCOL *PartitionPath ); #endif // LEGACY_BOOT_INTERNAL_H diff --git a/Platform/OpenLegacyBoot/LegacyBootSupport.c b/Platform/OpenLegacyBoot/LegacyBootSupport.c index 7d32ad5f422..ad9638ec12e 100644 --- a/Platform/OpenLegacyBoot/LegacyBootSupport.c +++ b/Platform/OpenLegacyBoot/LegacyBootSupport.c @@ -168,6 +168,9 @@ InternalLoadAppleLegacyInterface ( ) { EFI_STATUS Status; + EFI_HANDLE DiskHandle; + EFI_HANDLE PartitionHandle; + UINT8 PartitionIndex; EFI_DEVICE_PATH_PROTOCOL *WholeDiskPath; EFI_DEVICE_PATH_PROTOCOL **LegacyDevicePaths; CHAR16 *UnicodeDevicePath; @@ -184,8 +187,28 @@ InternalLoadAppleLegacyInterface ( DebugPrintDevicePath (DEBUG_INFO, "OLB: Legacy disk device path", WholeDiskPath); - // TODO: Mark target partition as active on pure MBR and hybrid GPT disks. - // Macs only boot the active partition. + // + // Mark target partition as active. + // + DiskHandle = OcPartitionGetDiskHandle (HdDevicePath); + if (DiskHandle == NULL) { + return EFI_INVALID_PARAMETER; + } + + PartitionHandle = OcPartitionGetPartitionHandle (HdDevicePath); + if (PartitionHandle == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = OcDiskGetMbrPartitionIndex (PartitionHandle, &PartitionIndex); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = OcDiskMarkMbrPartitionActive (DiskHandle, PartitionIndex); + if (EFI_ERROR (Status)) { + return Status; + } // // Set BootCampHD variable pointing to target disk. @@ -356,16 +379,15 @@ InternalGetPartitionLegacyOsType ( EFI_STATUS InternalLoadLegacyPbr ( - IN EFI_DEVICE_PATH_PROTOCOL *PartitionPath, - IN EFI_HANDLE PartitionHandle + IN EFI_DEVICE_PATH_PROTOCOL *PartitionPath ) { EFI_STATUS Status; EFI_HANDLE DiskHandle; + EFI_HANDLE PartitionHandle; MASTER_BOOT_RECORD *Mbr; MASTER_BOOT_RECORD *Pbr; - UINTN PbrSize; - OC_DISK_CONTEXT DiskContext; + UINT8 PartitionIndex; IA32_REGISTER_SET Regs; MASTER_BOOT_RECORD *MbrPtr = (MASTER_BOOT_RECORD *)0x0600; @@ -386,30 +408,21 @@ InternalLoadLegacyPbr ( } // - // Retrieve the PBR from partition. + // Retrieve the PBR from partition and partition index. // - Status = OcDiskInitializeContext ( - &DiskContext, - PartitionHandle, - TRUE - ); - if (EFI_ERROR (Status)) { - return Status; + PartitionHandle = OcPartitionGetPartitionHandle (PartitionPath); + if (PartitionHandle == NULL) { + DEBUG ((DEBUG_INFO, "OLB: Could not locate partition handle\n")); + return EFI_INVALID_PARAMETER; } - PbrSize = ALIGN_VALUE (sizeof (*Pbr), DiskContext.BlockSize); - Pbr = (MASTER_BOOT_RECORD *)AllocatePool (PbrSize); + Pbr = OcGetDiskMbrTable (PartitionHandle, FALSE); if (Pbr == NULL) { - DEBUG ((DEBUG_INFO, "OLB: Buffer allocation error\n")); - return EFI_OUT_OF_RESOURCES; + DEBUG ((DEBUG_INFO, "OLB: Partition does not contain a valid PBR\n")); + return EFI_INVALID_PARAMETER; } - Status = OcDiskRead ( - &DiskContext, - 0, - PbrSize, - Pbr - ); + Status = OcDiskGetMbrPartitionIndex (PartitionHandle, &PartitionIndex); if (EFI_ERROR (Status)) { FreePool (Pbr); return Status; @@ -433,6 +446,8 @@ InternalLoadLegacyPbr ( return EFI_INVALID_PARAMETER; } + DebugPrintHexDump (DEBUG_INFO, "OLB: MbrHEX", (UINT8 *)Mbr, sizeof (*Mbr)); + // // Create and initialize thunk structures. // @@ -472,7 +487,7 @@ InternalLoadLegacyPbr ( ZeroMem (&Regs, sizeof (Regs)); Regs.H.DL = 0x80; - Regs.X.SI = (UINT16)(UINTN)&MbrPtr->Partition[2]; + Regs.X.SI = (UINT16)(UINTN)&MbrPtr->Partition[PartitionIndex]; OcLegacyThunkFarCall86 ( &mThunkContext, Legacy8259, diff --git a/Platform/OpenLegacyBoot/OpenLegacyBoot.c b/Platform/OpenLegacyBoot/OpenLegacyBoot.c index 1ba0e207617..8b07e685267 100644 --- a/Platform/OpenLegacyBoot/OpenLegacyBoot.c +++ b/Platform/OpenLegacyBoot/OpenLegacyBoot.c @@ -98,7 +98,7 @@ ExternalSystemActionDoLegacyBoot ( return Status; } } else { - InternalLoadLegacyPbr (DevicePath, OcPartitionGetPartitionHandle (DevicePath)); + InternalLoadLegacyPbr (DevicePath); } return EFI_SUCCESS; From ed62e4ed04ccf338c8100bbda37a5f4ed4f13793 Mon Sep 17 00:00:00 2001 From: John Davis Date: Sat, 19 Aug 2023 15:07:33 -0500 Subject: [PATCH 35/55] OcFileLib: Add El-Torito read function --- Include/Acidanthera/Library/OcFileLib.h | 18 ++++++- Library/OcFileLib/DiskMisc.c | 68 ++++++++++++++++++++++++- 2 files changed, 83 insertions(+), 3 deletions(-) diff --git a/Include/Acidanthera/Library/OcFileLib.h b/Include/Acidanthera/Library/OcFileLib.h index 5295fc80e9e..4c45c643a70 100644 --- a/Include/Acidanthera/Library/OcFileLib.h +++ b/Include/Acidanthera/Library/OcFileLib.h @@ -522,7 +522,7 @@ OcPartitionGetPartitionHandle ( /** Check if disk is a CD-ROM device. - @param[in] HdDevicePath The Device Path of the disk. + @param[in] DiskDevicePath The Device Path of the disk. @retval Device Path or NULL **/ @@ -531,6 +531,22 @@ OcIsDiskCdRom ( IN EFI_DEVICE_PATH_PROTOCOL *DiskDevicePath ); +/** + Read El-Torito boot sector from CD-ROM device. + + @param[in] DiskDevicePath The Device Path of the disk. + @param[out] Buffer Pointer to pool-allocated buffer containing the boot sector data. + @param[out] BufferSize Size of Buffer. + + @retval EFI_SUCCESS on success. +**/ +EFI_STATUS +OcDiskReadElTorito ( + IN EFI_DEVICE_PATH_PROTOCOL *DiskDevicePath, + OUT UINT8 **Buffer, + OUT UINTN *BufferSize + ); + /** Locate the disk's EFI System Partition. diff --git a/Library/OcFileLib/DiskMisc.c b/Library/OcFileLib/DiskMisc.c index c5eeed47b46..9008d8124b7 100644 --- a/Library/OcFileLib/DiskMisc.c +++ b/Library/OcFileLib/DiskMisc.c @@ -301,8 +301,6 @@ OcDiskGetDevicePath ( if (HdNode == NULL) { return NULL; } - - DEBUG ((DEBUG_INFO, "got cdrom\n")); } PrefixPath = DuplicateDevicePath (HdDevicePath); @@ -390,6 +388,72 @@ OcIsDiskCdRom ( return FALSE; } +EFI_STATUS +OcDiskReadElTorito ( + IN EFI_DEVICE_PATH_PROTOCOL *DiskDevicePath, + OUT UINT8 **Buffer, + OUT UINTN *BufferSize + ) +{ + EFI_STATUS Status; + UINT8 *BootBuffer; + UINTN BootBufferSize; + + CDROM_DEVICE_PATH *CdNode; + EFI_HANDLE DiskHandle; + OC_DISK_CONTEXT DiskContext; + + ASSERT (DiskDevicePath != NULL); + ASSERT (Buffer != NULL); + ASSERT (BufferSize != NULL); + + // + // Retrieve the CD-ROM Device Path information. + // + CdNode = (CDROM_DEVICE_PATH *)( + FindDevicePathNodeWithType ( + DiskDevicePath, + MEDIA_DEVICE_PATH, + MEDIA_CDROM_DP + ) + ); + if (CdNode == NULL) { + DEBUG ((DEBUG_INFO, "OCPI: Device Path does not describe a CD-ROM\n")); + return EFI_UNSUPPORTED; + } + + DiskHandle = OcPartitionGetDiskHandle (DiskDevicePath); + + Status = OcDiskInitializeContext (&DiskContext, DiskHandle, TRUE); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // TODO: Unclear whether the sector size here is the native CD size 2048 or 512. + // + BootBufferSize = CdNode->PartitionSize * DiskContext.BlockSize; + BootBuffer = AllocatePool (BootBufferSize); + if (BootBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = OcDiskRead ( + &DiskContext, + CdNode->PartitionStart, + BootBufferSize, + BootBuffer + ); + if (EFI_ERROR (Status)) { + FreePool (BootBuffer); + return Status; + } + + *Buffer = BootBuffer; + *BufferSize = BootBufferSize; + return EFI_SUCCESS; +} + EFI_DEVICE_PATH_PROTOCOL * OcDiskFindSystemPartitionPath ( IN CONST EFI_DEVICE_PATH_PROTOCOL *DiskDevicePath, From c70ad782c3a75a59ee2943e273335aea6197a8ce Mon Sep 17 00:00:00 2001 From: John Davis Date: Sat, 19 Aug 2023 15:09:01 -0500 Subject: [PATCH 36/55] OpenLegacyBoot: Switch to Block I/O for legacy detection --- .../Acidanthera/Library/OcBootManagementLib.h | 12 +- .../OcBootManagementLib/BootEntryManagement.c | 17 +- Platform/OpenLegacyBoot/LegacyBootInternal.h | 7 +- Platform/OpenLegacyBoot/LegacyBootSupport.c | 108 +++++------ Platform/OpenLegacyBoot/OpenLegacyBoot.c | 167 ++++++++++-------- 5 files changed, 160 insertions(+), 151 deletions(-) diff --git a/Include/Acidanthera/Library/OcBootManagementLib.h b/Include/Acidanthera/Library/OcBootManagementLib.h index 0f7ea2518fe..33fb388be85 100644 --- a/Include/Acidanthera/Library/OcBootManagementLib.h +++ b/Include/Acidanthera/Library/OcBootManagementLib.h @@ -200,8 +200,8 @@ EFI_STATUS typedef EFI_STATUS (*OC_BOOT_EXTERNAL_SYSTEM_ACTION) ( - IN OUT OC_PICKER_CONTEXT *PickerContext, - IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + IN OUT OC_PICKER_CONTEXT *PickerContext, + IN VOID *ActionContext ); /** @@ -227,6 +227,10 @@ typedef struct OC_BOOT_ENTRY_ { // OC_BOOT_EXTERNAL_SYSTEM_ACTION ExternalSystemAction; // + // Action to perform on execution. Only valid for external boot system entries. + // + VOID *ExternalSystemActionContext; + // // Id under which to save entry as default. // CHAR16 *Id; @@ -626,6 +630,10 @@ typedef struct { // External boot system action. Boot Entry Protocol only. Optional. // OC_BOOT_EXTERNAL_SYSTEM_ACTION ExternalSystemAction; + // + // External boot system action context. Boot Entry Protocol only. Optional. + // + VOID *ExternalSystemActionContext; } OC_PICKER_ENTRY; /** diff --git a/Library/OcBootManagementLib/BootEntryManagement.c b/Library/OcBootManagementLib/BootEntryManagement.c index 9fbe2a2ccb6..f9b7bda3d73 100644 --- a/Library/OcBootManagementLib/BootEntryManagement.c +++ b/Library/OcBootManagementLib/BootEntryManagement.c @@ -720,16 +720,11 @@ InternalAddBootEntryFromCustomEntry ( )); if (CustomEntry->ExternalSystemAction) { - BootEntry->Type = OC_BOOT_EXTERNAL_SYSTEM; - BootEntry->ExternalSystemAction = CustomEntry->ExternalSystemAction; - BootEntry->AudioBasePath = CustomEntry->AudioBasePath; - BootEntry->AudioBaseType = CustomEntry->AudioBaseType; - BootEntry->DevicePath = DevicePathFromHandle (FileSystem->Handle); - - if (BootEntry->DevicePath == NULL) { - FreeBootEntry (BootEntry); - return EFI_OUT_OF_RESOURCES; - } + BootEntry->Type = OC_BOOT_EXTERNAL_SYSTEM; + BootEntry->ExternalSystemAction = CustomEntry->ExternalSystemAction; + BootEntry->ExternalSystemActionContext = CustomEntry->ExternalSystemActionContext; + BootEntry->AudioBasePath = CustomEntry->AudioBasePath; + BootEntry->AudioBaseType = CustomEntry->AudioBaseType; } else if (CustomEntry->SystemAction) { BootEntry->Type = OC_BOOT_SYSTEM; BootEntry->SystemAction = CustomEntry->SystemAction; @@ -2516,7 +2511,7 @@ OcLoadBootEntry ( if ((BootEntry->Type & OC_BOOT_EXTERNAL_SYSTEM) != 0) { ASSERT (BootEntry->ExternalSystemAction != NULL); - return BootEntry->ExternalSystemAction (Context, BootEntry->DevicePath); + return BootEntry->ExternalSystemAction (Context, BootEntry->ExternalSystemActionContext); } if ((BootEntry->Type & OC_BOOT_SYSTEM) != 0) { diff --git a/Platform/OpenLegacyBoot/LegacyBootInternal.h b/Platform/OpenLegacyBoot/LegacyBootInternal.h index 735a5976672..2f8decf14f1 100644 --- a/Platform/OpenLegacyBoot/LegacyBootInternal.h +++ b/Platform/OpenLegacyBoot/LegacyBootInternal.h @@ -37,6 +37,10 @@ typedef enum OC_LEGACY_OS_TYPE_ { OcLegacyOsTypeIsoLinux } OC_LEGACY_OS_TYPE; +typedef struct { + EFI_DEVICE_PATH_PROTOCOL *DevicePath; +} LEGACY_ENTRY_CONTEXT; + EFI_STATUS InternalGetBiosDiskNumber ( IN THUNK_CONTEXT *ThunkContext, @@ -58,7 +62,8 @@ InternalLoadAppleLegacyInterface ( OC_LEGACY_OS_TYPE InternalGetPartitionLegacyOsType ( - IN EFI_HANDLE PartitionHandle + IN EFI_HANDLE PartitionHandle, + IN BOOLEAN IsCdRomSupported ); EFI_STATUS diff --git a/Platform/OpenLegacyBoot/LegacyBootSupport.c b/Platform/OpenLegacyBoot/LegacyBootSupport.c index ad9638ec12e..5f49852c4ab 100644 --- a/Platform/OpenLegacyBoot/LegacyBootSupport.c +++ b/Platform/OpenLegacyBoot/LegacyBootSupport.c @@ -20,11 +20,12 @@ static CONST EFI_DEVICE_PATH_PROTOCOL *AppleLegacyInterfaceMediaDevicePathPath #define MAX_APPLE_LEGACY_DEVICE_PATHS 16 -// STATIC +STATIC BOOLEAN CheckLegacySignature ( - IN CONST CHAR8 *SignatureStr, - IN MASTER_BOOT_RECORD *Pbr + IN CONST CHAR8 *SignatureStr, + IN CONST UINT8 *Buffer, + IN CONST UINTN BufferSize ) { UINT32 Offset; @@ -35,8 +36,8 @@ CheckLegacySignature ( (CONST UINT8 *)SignatureStr, NULL, (CONST UINT32)AsciiStrLen (SignatureStr), - Pbr->BootStrapCode, - sizeof (Pbr->BootStrapCode), + Buffer, + BufferSize, &Offset ); } @@ -272,99 +273,82 @@ InternalLoadAppleLegacyInterface ( OC_LEGACY_OS_TYPE InternalGetPartitionLegacyOsType ( - IN EFI_HANDLE PartitionHandle + IN EFI_HANDLE PartitionHandle, + IN BOOLEAN IsCdRomSupported ) { - EFI_STATUS Status; - MASTER_BOOT_RECORD *Mbr; - UINTN MbrSize; - OC_LEGACY_OS_TYPE LegacyOsType; - + EFI_STATUS Status; + UINT8 *Buffer; + UINTN BufferSize; + MASTER_BOOT_RECORD *Mbr; EFI_DEVICE_PATH_PROTOCOL *DevicePath; - OC_DISK_CONTEXT DiskContext; EFI_HANDLE DiskHandle; + OC_LEGACY_OS_TYPE LegacyOsType; ASSERT (PartitionHandle != NULL); - // - // Read MBR of whole disk. - // DevicePath = DevicePathFromHandle (PartitionHandle); if (DevicePath == NULL) { return OcLegacyOsTypeNone; } - DebugPrintDevicePath (DEBUG_INFO, "OLB: Reading MBR for disk", DevicePath); - DiskHandle = OcPartitionGetDiskHandle (DevicePath); if (DiskHandle == NULL) { return OcLegacyOsTypeNone; } - Mbr = OcGetDiskMbrTable (DiskHandle, TRUE); - if (Mbr == NULL) { - DEBUG ((DEBUG_INFO, "OLB: Disk does not contain a valid MBR partition table\n")); - return OcLegacyOsTypeNone; - } - // - // For hard disk devices, get PBR sector instead. + // For CD devices, validate El-Torito structures. + // For hard disk and USB devices, validate MBR and PBR of target partition. // - if (!OcIsDiskCdRom (DevicePath)) { - FreePool (Mbr); + if (OcIsDiskCdRom (DevicePath)) { + if (!IsCdRomSupported) { + DEBUG ((DEBUG_INFO, "OLB: CD-ROM boot not supported on this platform\n")); + return OcLegacyOsTypeNone; + } - // - // Retrieve the first sector of the partition. - // - DebugPrintDevicePath (DEBUG_INFO, "OLB: Reading PBR for partition", DevicePath); - Status = OcDiskInitializeContext ( - &DiskContext, - PartitionHandle, - TRUE - ); + DebugPrintDevicePath (DEBUG_INFO, "OLB: Reading El-Torito for CDROM", DevicePath); + Status = OcDiskReadElTorito (DevicePath, &Buffer, &BufferSize); if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "OLB: Failed reading El-Torito - %r\n", Status)); return OcLegacyOsTypeNone; } - - MbrSize = ALIGN_VALUE (sizeof (*Mbr), DiskContext.BlockSize); - Mbr = (MASTER_BOOT_RECORD *)AllocatePool (MbrSize); + } else { + DebugPrintDevicePath (DEBUG_INFO, "OLB: Reading MBR for parent disk", DevicePath); + Mbr = OcGetDiskMbrTable (DiskHandle, TRUE); if (Mbr == NULL) { - DEBUG ((DEBUG_INFO, "OLB: Buffer allocation error\n")); + DEBUG ((DEBUG_INFO, "OLB: Disk does not contain a valid MBR\n")); return OcLegacyOsTypeNone; } - Status = OcDiskRead ( - &DiskContext, - 0, - MbrSize, - Mbr - ); - if (EFI_ERROR (Status)) { - FreePool (Mbr); + FreePool (Mbr); + + // + // Retrieve PBR for partition. + // + DebugPrintDevicePath (DEBUG_INFO, "OLB: Reading PBR for partition", DevicePath); + Mbr = OcGetDiskMbrTable (PartitionHandle, FALSE); + if (Mbr == NULL) { + DEBUG ((DEBUG_INFO, "OLB: Partition does not contain a valid PBR\n")); return OcLegacyOsTypeNone; } - } - DebugPrintHexDump (DEBUG_INFO, "OLB: MbrHEX", Mbr->BootStrapCode, sizeof (Mbr->BootStrapCode)); - - // - // Validate signature in MBR. - // - if (Mbr->Signature != MBR_SIGNATURE) { - FreePool (Mbr); - return OcLegacyOsTypeNone; + Buffer = (UINT8 *)Mbr; + BufferSize = sizeof (*Mbr); } + DebugPrintHexDump (DEBUG_INFO, "OLB: PbrHEX", Buffer, BufferSize); + // // Validate sector contents and check for known signatures // indicating the partition is bootable. // - if (CheckLegacySignature ("BOOTMGR", Mbr)) { + if (CheckLegacySignature ("BOOTMGR", Buffer, BufferSize)) { LegacyOsType = OcLegacyOsTypeWindowsBootmgr; - } else if (CheckLegacySignature ("NTLDR", Mbr)) { + } else if (CheckLegacySignature ("NTLDR", Buffer, BufferSize)) { LegacyOsType = OcLegacyOsTypeWindowsNtldr; - } else if ( CheckLegacySignature ("ISOLINUX", Mbr) - || CheckLegacySignature ("isolinux", Mbr)) + } else if ( CheckLegacySignature ("ISOLINUX", Buffer, BufferSize) + || CheckLegacySignature ("isolinux", Buffer, BufferSize)) { LegacyOsType = OcLegacyOsTypeIsoLinux; } else { @@ -372,7 +356,7 @@ InternalGetPartitionLegacyOsType ( DEBUG ((DEBUG_INFO, "OLB: Unknown legacy bootsector signature\n")); } - FreePool (Mbr); + FreePool (Buffer); return LegacyOsType; } @@ -441,7 +425,7 @@ InternalLoadLegacyPbr ( Mbr = OcGetDiskMbrTable (DiskHandle, TRUE); if (Mbr == NULL) { - DEBUG ((DEBUG_INFO, "OLB: Disk does not contain a valid MBR partition table\n")); + DEBUG ((DEBUG_INFO, "OLB: Disk does not contain a valid MBR\n")); FreePool (Pbr); return EFI_INVALID_PARAMETER; } diff --git a/Platform/OpenLegacyBoot/OpenLegacyBoot.c b/Platform/OpenLegacyBoot/OpenLegacyBoot.c index 8b07e685267..e5a7a838cc2 100644 --- a/Platform/OpenLegacyBoot/OpenLegacyBoot.c +++ b/Platform/OpenLegacyBoot/OpenLegacyBoot.c @@ -43,13 +43,17 @@ InternalFreePickerEntry ( STATIC EFI_STATUS ExternalSystemActionDoLegacyBoot ( - IN OUT OC_PICKER_CONTEXT *PickerContext, - IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + IN OUT OC_PICKER_CONTEXT *PickerContext, + IN VOID *ActionContext ) { EFI_STATUS Status; EFI_HANDLE LoadedImageHandle; EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + LEGACY_ENTRY_CONTEXT *LegacyContext; + CONST CHAR8 *Args; + + LegacyContext = ActionContext; // // Load and start legacy OS. @@ -57,11 +61,11 @@ ExternalSystemActionDoLegacyBoot ( // On Macs, use the Apple legacy interface. // On other systems, use the Legacy8259 protocol. // - DebugPrintDevicePath (DEBUG_INFO, "OLB: Legacy device path", DevicePath); + DebugPrintDevicePath (DEBUG_INFO, "OLB: Legacy device path", LegacyContext->DevicePath); if (mIsAppleInterfaceSupported) { Status = InternalLoadAppleLegacyInterface ( mImageHandle, - DevicePath, + LegacyContext->DevicePath, &LoadedImageHandle ); if (EFI_ERROR (Status)) { @@ -69,6 +73,9 @@ ExternalSystemActionDoLegacyBoot ( return Status; } + // + // Specify boot device type on loaded image. + // Status = gBS->HandleProtocol ( LoadedImageHandle, &gEfiLoadedImageProtocolGuid, @@ -82,23 +89,21 @@ ExternalSystemActionDoLegacyBoot ( LoadedImage->LoadOptionsSize = 0; LoadedImage->LoadOptions = NULL; - CONST CHAR8 *Args; - - Args = AllocateCopyPool (L_STR_SIZE ("HD"), "HD"); + if (OcIsDiskCdRom (LegacyContext->DevicePath)) { + Args = AllocateCopyPool (L_STR_SIZE ("CD"), "CD"); + } else { + Args = AllocateCopyPool (L_STR_SIZE ("HD"), "HD"); + } OcAppendArgumentsToLoadedImage (LoadedImage, &Args, 1, TRUE); - DEBUG (( - DEBUG_INFO, - "OCB: Args <%s>\n", - LoadedImage->LoadOptions - )); + Status = gBS->StartImage (LoadedImageHandle, NULL, NULL); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_WARN, "OLB: Failure while starting Apple legacy interface - %r\n", Status)); return Status; } } else { - InternalLoadLegacyPbr (DevicePath); + InternalLoadLegacyPbr (LegacyContext->DevicePath); } return EFI_SUCCESS; @@ -114,84 +119,96 @@ OcGetLegacyBootEntries ( OUT UINTN *NumEntries ) { - // EFI_STATUS Status; - // EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem; - // EFI_FILE_PROTOCOL *RootDirectory; - // UINT32 FileSystemPolicy; + EFI_STATUS Status; + UINTN NoHandles; + EFI_HANDLE *Handles; + UINTN HandleIndex; + + EFI_HANDLE BlockDeviceHandle; + EFI_DEVICE_PATH_PROTOCOL *BlockDevicePath; + OC_LEGACY_OS_TYPE LegacyOsType; + OC_FLEX_ARRAY *FlexPickerEntries; + OC_PICKER_ENTRY *PickerEntry; - OC_LEGACY_OS_TYPE LegacyType; - OC_PICKER_ENTRY *PickerEntry; + ASSERT (PickerContext != NULL); + ASSERT (Entries != NULL); + ASSERT (NumEntries != NULL); // - // No custom entries. + // Custom entries only. // - if (Device == NULL) { + if (Device != NULL) { return EFI_NOT_FOUND; } + FlexPickerEntries = OcFlexArrayInit (sizeof (OC_PICKER_ENTRY), (OC_FLEX_ARRAY_FREE_ITEM)InternalFreePickerEntry); + if (FlexPickerEntries == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // - // Open partition file system. + // Get all Block I/O handles. // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiBlockIoProtocolGuid, + NULL, + &NoHandles, + &Handles + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "OLB: Failed to get Block I/O handles - %r\n", Status)); + OcFlexArrayFree (&FlexPickerEntries); + return Status; + } - /* Status = gBS->HandleProtocol ( - Device, - &gEfiSimpleFileSystemProtocolGuid, - (VOID **)&FileSystem - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_WARN, "OLB: Missing filesystem - %r\n", Status)); - return Status; - } - - // - // Get handle to partiton root directory. - // - Status = FileSystem->OpenVolume ( - FileSystem, - &RootDirectory - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_WARN, "OLB: Invalid root volume - %r\n", Status)); - return Status; - } - - FileSystemPolicy = OcGetFileSystemPolicyType (Device);*/ + for (HandleIndex = 0; HandleIndex < NoHandles; HandleIndex++) { + BlockDeviceHandle = Handles[HandleIndex]; - // - // Disallow all but NTFS filesystems. - // - // if ((FileSystemPolicy & OC_SCAN_ALLOW_FS_NTFS) != 0) { - // DEBUG ((DEBUG_INFO, "OLB: Not scanning non-NTFS filesystem\n")); - // Status = EFI_NOT_FOUND; - // } + // + // Detect legacy OS type. + // + LegacyOsType = InternalGetPartitionLegacyOsType (BlockDeviceHandle, mIsAppleInterfaceSupported); + if (LegacyOsType == OcLegacyOsTypeNone) { + continue; + } - // - // Scan for boot entry (only one entry per filesystem). - // - LegacyType = InternalGetPartitionLegacyOsType (Device); - // RootDirectory->Close (RootDirectory); - if (LegacyType == OcLegacyOsTypeNone) { - return EFI_NOT_FOUND; - } + BlockDevicePath = DevicePathFromHandle (BlockDeviceHandle); + if (BlockDevicePath == NULL) { + DEBUG ((DEBUG_INFO, "OLB: Could not find Device Path for block device\n")); + continue; + } + + // + // Create picker entry. + // + PickerEntry = OcFlexArrayAddItem (FlexPickerEntries); + if (PickerEntry == NULL) { + OcFlexArrayFree (&FlexPickerEntries); + return EFI_OUT_OF_RESOURCES; + } + + CHAR16 *str2 = ConvertDevicePathToText (BlockDevicePath, FALSE, FALSE); + CHAR8 *str = AllocateZeroPool (StrLen (str2) + 1); - CHAR16 *str2 = ConvertDevicePathToText (DevicePathFromHandle (Device), FALSE, FALSE); - CHAR8 *str = AllocateZeroPool (StrLen (str2) + 1); + UnicodeStrToAsciiStrS (str2, str, StrLen (str2) + 1); - UnicodeStrToAsciiStrS (str2, str, StrLen (str2) + 1); + PickerEntry->Id = str; + PickerEntry->Name = "Windows (legacy)"; + PickerEntry->Path = NULL; + PickerEntry->Arguments = NULL; + PickerEntry->Flavour = OC_FLAVOUR_WINDOWS; + PickerEntry->Tool = FALSE; + PickerEntry->TextMode = TRUE; + PickerEntry->RealPath = FALSE; + PickerEntry->ExternalSystemAction = ExternalSystemActionDoLegacyBoot; - PickerEntry = AllocateZeroPool (sizeof (*PickerEntry)); - PickerEntry->Id = str; - PickerEntry->Name = "Windows (legacy)"; - PickerEntry->Path = NULL; - PickerEntry->Arguments = NULL; - PickerEntry->Flavour = OC_FLAVOUR_WINDOWS; - PickerEntry->Tool = FALSE; - PickerEntry->TextMode = TRUE; - PickerEntry->RealPath = FALSE; - PickerEntry->ExternalSystemAction = ExternalSystemActionDoLegacyBoot; + LEGACY_ENTRY_CONTEXT *LegacyContext = AllocateZeroPool (sizeof (LEGACY_ENTRY_CONTEXT)); + LegacyContext->DevicePath = BlockDevicePath; + PickerEntry->ExternalSystemActionContext = LegacyContext; + } - *Entries = PickerEntry; - *NumEntries = 1; + OcFlexArrayFreeContainer (&FlexPickerEntries, (VOID **)Entries, NumEntries); return EFI_SUCCESS; } From d3f5845bad964f9a05a560ecca8a19c1c3bbc43b Mon Sep 17 00:00:00 2001 From: John Davis Date: Sat, 19 Aug 2023 16:44:51 -0500 Subject: [PATCH 37/55] OcFileLib: Fix Windows builds --- Library/OcFileLib/DiskMisc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Library/OcFileLib/DiskMisc.c b/Library/OcFileLib/DiskMisc.c index 9008d8124b7..123abb76180 100644 --- a/Library/OcFileLib/DiskMisc.c +++ b/Library/OcFileLib/DiskMisc.c @@ -432,7 +432,7 @@ OcDiskReadElTorito ( // // TODO: Unclear whether the sector size here is the native CD size 2048 or 512. // - BootBufferSize = CdNode->PartitionSize * DiskContext.BlockSize; + BootBufferSize = (UINTN)(CdNode->PartitionSize * DiskContext.BlockSize); BootBuffer = AllocatePool (BootBufferSize); if (BootBuffer == NULL) { return EFI_OUT_OF_RESOURCES; From 6335b3391413019c3f69e483444142cd190c3b39 Mon Sep 17 00:00:00 2001 From: John Davis Date: Sat, 19 Aug 2023 17:24:09 -0500 Subject: [PATCH 38/55] OpenLegacyBoot: Cleanup picker entry creation --- .../Acidanthera/Library/OcBootManagementLib.h | 4 + .../OcBootManagementLib/BootEntryManagement.c | 1 + Platform/OpenLegacyBoot/OpenLegacyBoot.c | 120 ++++++++++++++---- 3 files changed, 101 insertions(+), 24 deletions(-) diff --git a/Include/Acidanthera/Library/OcBootManagementLib.h b/Include/Acidanthera/Library/OcBootManagementLib.h index 33fb388be85..44df0a4c041 100644 --- a/Include/Acidanthera/Library/OcBootManagementLib.h +++ b/Include/Acidanthera/Library/OcBootManagementLib.h @@ -634,6 +634,10 @@ typedef struct { // External boot system action context. Boot Entry Protocol only. Optional. // VOID *ExternalSystemActionContext; + // + // Whether this entry should be labeled as external to the system. Boot Entry Protocol only. Optional. + // + BOOLEAN External; } OC_PICKER_ENTRY; /** diff --git a/Library/OcBootManagementLib/BootEntryManagement.c b/Library/OcBootManagementLib/BootEntryManagement.c index f9b7bda3d73..f23b6db0320 100644 --- a/Library/OcBootManagementLib/BootEntryManagement.c +++ b/Library/OcBootManagementLib/BootEntryManagement.c @@ -725,6 +725,7 @@ InternalAddBootEntryFromCustomEntry ( BootEntry->ExternalSystemActionContext = CustomEntry->ExternalSystemActionContext; BootEntry->AudioBasePath = CustomEntry->AudioBasePath; BootEntry->AudioBaseType = CustomEntry->AudioBaseType; + BootEntry->IsExternal = CustomEntry->External; } else if (CustomEntry->SystemAction) { BootEntry->Type = OC_BOOT_SYSTEM; BootEntry->SystemAction = CustomEntry->SystemAction; diff --git a/Platform/OpenLegacyBoot/OpenLegacyBoot.c b/Platform/OpenLegacyBoot/OpenLegacyBoot.c index e5a7a838cc2..81c7ee39c29 100644 --- a/Platform/OpenLegacyBoot/OpenLegacyBoot.c +++ b/Platform/OpenLegacyBoot/OpenLegacyBoot.c @@ -12,8 +12,27 @@ STATIC EFI_HANDLE mImageHandle; STATIC BOOLEAN mIsAppleInterfaceSupported; +STATIC +CHAR8 * +GetLegacyEntryName ( + OC_LEGACY_OS_TYPE LegacyOsType + ) +{ + return AllocateCopyPool (L_STR_SIZE ("Windows (legacy)"), "Windows (legacy)"); +} + +STATIC +CHAR8 * +GetLegacyEntryFlavour ( + OC_LEGACY_OS_TYPE LegacyOsType + ) +{ + return AllocateCopyPool (L_STR_SIZE (OC_FLAVOUR_WINDOWS), OC_FLAVOUR_WINDOWS); +} + +STATIC VOID -InternalFreePickerEntry ( +FreePickerEntry ( IN OC_PICKER_ENTRY *Entry ) { @@ -23,21 +42,21 @@ InternalFreePickerEntry ( return; } - // - // TODO: Is this un-CONST casting okay? - // (Are they CONST because they are not supposed to be freed when used as before?) - // if (Entry->Id != NULL) { FreePool ((CHAR8 *)Entry->Id); } - /*if (Entry->Name != NULL) { + if (Entry->Name != NULL) { FreePool ((CHAR8 *)Entry->Name); - }*/ + } if (Entry->Flavour != NULL) { FreePool ((CHAR8 *)Entry->Flavour); } + + if (Entry->ExternalSystemActionContext != NULL) { + FreePool (Entry->ExternalSystemActionContext); + } } STATIC @@ -123,12 +142,19 @@ OcGetLegacyBootEntries ( UINTN NoHandles; EFI_HANDLE *Handles; UINTN HandleIndex; + UINT32 ScanPolicy; + BOOLEAN IsExternal; + + CHAR16 *UnicodeDevicePath; + CHAR8 *AsciiDevicePath; + UINTN AsciiDevicePathSize; EFI_HANDLE BlockDeviceHandle; EFI_DEVICE_PATH_PROTOCOL *BlockDevicePath; OC_LEGACY_OS_TYPE LegacyOsType; OC_FLEX_ARRAY *FlexPickerEntries; OC_PICKER_ENTRY *PickerEntry; + LEGACY_ENTRY_CONTEXT *LegacyContext; ASSERT (PickerContext != NULL); ASSERT (Entries != NULL); @@ -141,7 +167,7 @@ OcGetLegacyBootEntries ( return EFI_NOT_FOUND; } - FlexPickerEntries = OcFlexArrayInit (sizeof (OC_PICKER_ENTRY), (OC_FLEX_ARRAY_FREE_ITEM)InternalFreePickerEntry); + FlexPickerEntries = OcFlexArrayInit (sizeof (OC_PICKER_ENTRY), (OC_FLEX_ARRAY_FREE_ITEM)FreePickerEntry); if (FlexPickerEntries == NULL) { return EFI_OUT_OF_RESOURCES; } @@ -165,6 +191,17 @@ OcGetLegacyBootEntries ( for (HandleIndex = 0; HandleIndex < NoHandles; HandleIndex++) { BlockDeviceHandle = Handles[HandleIndex]; + // + // If device type locking is set and this device is not allowed, + // skip device. + // + if ((PickerContext->ScanPolicy & OC_SCAN_DEVICE_LOCK) != 0) { + ScanPolicy = OcGetDevicePolicyType (BlockDeviceHandle, &IsExternal); + if ((ScanPolicy & PickerContext->ScanPolicy) == 0) { + continue; + } + } + // // Detect legacy OS type. // @@ -180,7 +217,7 @@ OcGetLegacyBootEntries ( } // - // Create picker entry. + // Create and add picker entry to entries. // PickerEntry = OcFlexArrayAddItem (FlexPickerEntries); if (PickerEntry == NULL) { @@ -188,24 +225,59 @@ OcGetLegacyBootEntries ( return EFI_OUT_OF_RESOURCES; } - CHAR16 *str2 = ConvertDevicePathToText (BlockDevicePath, FALSE, FALSE); - CHAR8 *str = AllocateZeroPool (StrLen (str2) + 1); + // + // Device Path will be used as ID and is required for default entry matching. + // + UnicodeDevicePath = ConvertDevicePathToText (BlockDevicePath, FALSE, FALSE); + if (UnicodeDevicePath == NULL) { + OcFlexArrayFree (&FlexPickerEntries); + return EFI_OUT_OF_RESOURCES; + } + + AsciiDevicePathSize = (StrLen (UnicodeDevicePath) + 1) * sizeof (CHAR8); + AsciiDevicePath = AllocatePool (AsciiDevicePathSize); + if (AsciiDevicePath == NULL) { + FreePool (UnicodeDevicePath); + OcFlexArrayFree (&FlexPickerEntries); + return EFI_OUT_OF_RESOURCES; + } + + Status = UnicodeStrToAsciiStrS (UnicodeDevicePath, AsciiDevicePath, AsciiDevicePathSize); + FreePool (UnicodeDevicePath); + if (EFI_ERROR (Status)) { + FreePool (AsciiDevicePath); + OcFlexArrayFree (&FlexPickerEntries); + return Status; + } - UnicodeStrToAsciiStrS (str2, str, StrLen (str2) + 1); + // + // Context referencing booted entry later on. + // + LegacyContext = AllocateZeroPool (sizeof (*LegacyContext)); + if (LegacyContext == NULL) { + FreePool (AsciiDevicePath); + OcFlexArrayFree (&FlexPickerEntries); + return EFI_OUT_OF_RESOURCES; + } - PickerEntry->Id = str; - PickerEntry->Name = "Windows (legacy)"; - PickerEntry->Path = NULL; - PickerEntry->Arguments = NULL; - PickerEntry->Flavour = OC_FLAVOUR_WINDOWS; - PickerEntry->Tool = FALSE; - PickerEntry->TextMode = TRUE; - PickerEntry->RealPath = FALSE; - PickerEntry->ExternalSystemAction = ExternalSystemActionDoLegacyBoot; + LegacyContext->DevicePath = BlockDevicePath; - LEGACY_ENTRY_CONTEXT *LegacyContext = AllocateZeroPool (sizeof (LEGACY_ENTRY_CONTEXT)); - LegacyContext->DevicePath = BlockDevicePath; + PickerEntry->Id = AsciiDevicePath; + PickerEntry->Name = GetLegacyEntryName (LegacyOsType); + PickerEntry->Path = NULL; + PickerEntry->Arguments = NULL; + PickerEntry->Flavour = GetLegacyEntryFlavour (LegacyOsType); + PickerEntry->Tool = FALSE; + PickerEntry->TextMode = FALSE; + PickerEntry->RealPath = FALSE; + + PickerEntry->ExternalSystemAction = ExternalSystemActionDoLegacyBoot; PickerEntry->ExternalSystemActionContext = LegacyContext; + + if ((PickerEntry->Name == NULL) || (PickerEntry->Flavour == NULL)) { + OcFlexArrayFree (&FlexPickerEntries); + return EFI_OUT_OF_RESOURCES; + } } OcFlexArrayFreeContainer (&FlexPickerEntries, (VOID **)Entries, NumEntries); @@ -230,7 +302,7 @@ OcFreeLegacyBootEntries ( } for (Index = 0; Index < NumEntries; Index++) { - InternalFreePickerEntry (&(*Entries)[Index]); + FreePickerEntry (&(*Entries)[Index]); } FreePool (*Entries); From 52d1fe943c22fa8455bc2906d02bd96dcef6868e Mon Sep 17 00:00:00 2001 From: John Davis Date: Sat, 19 Aug 2023 17:30:49 -0500 Subject: [PATCH 39/55] OpenLegacyBoot: Fix Windows builds --- Platform/OpenLegacyBoot/LegacyBootSupport.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Platform/OpenLegacyBoot/LegacyBootSupport.c b/Platform/OpenLegacyBoot/LegacyBootSupport.c index 5f49852c4ab..6195fd70687 100644 --- a/Platform/OpenLegacyBoot/LegacyBootSupport.c +++ b/Platform/OpenLegacyBoot/LegacyBootSupport.c @@ -24,8 +24,8 @@ STATIC BOOLEAN CheckLegacySignature ( IN CONST CHAR8 *SignatureStr, - IN CONST UINT8 *Buffer, - IN CONST UINTN BufferSize + IN UINT8 *Buffer, + IN UINTN BufferSize ) { UINT32 Offset; @@ -37,7 +37,7 @@ CheckLegacySignature ( NULL, (CONST UINT32)AsciiStrLen (SignatureStr), Buffer, - BufferSize, + (UINT32)BufferSize, &Offset ); } From 86b0f06467a11bdffadf453e6b7556245fbc28bb Mon Sep 17 00:00:00 2001 From: John Davis Date: Sat, 19 Aug 2023 18:53:52 -0500 Subject: [PATCH 40/55] OpenLegacyBoot: Fix external device handling --- Platform/OpenLegacyBoot/BiosDisk.c | 6 +-- Platform/OpenLegacyBoot/LegacyBootInternal.h | 1 + Platform/OpenLegacyBoot/OpenLegacyBoot.c | 41 +++++++++++++------- 3 files changed, 30 insertions(+), 18 deletions(-) diff --git a/Platform/OpenLegacyBoot/BiosDisk.c b/Platform/OpenLegacyBoot/BiosDisk.c index 4fa45a5045e..e9ee71dd8a2 100644 --- a/Platform/OpenLegacyBoot/BiosDisk.c +++ b/Platform/OpenLegacyBoot/BiosDisk.c @@ -57,13 +57,13 @@ BiosDiskReset ( CarryFlag = OcLegacyThunkBiosInt86 (ThunkContext, Legacy8259, 0x13, &Regs); if (CarryFlag != 0) { - DEBUG ((DEBUG_WARN, "OLB: Failed to reset BIOS disk %u, error 0x%X\n", DriveNumber, Regs.H.AL)); + DEBUG ((DEBUG_INFO, "OLB: Failed to reset BIOS disk %u, error 0x%X\n", DriveNumber, Regs.H.AL)); if (Regs.H.AL == BIOS_RESET_FAILED) { Regs.H.AH = 0x00; Regs.H.DL = DriveNumber; CarryFlag = OcLegacyThunkBiosInt86 (ThunkContext, Legacy8259, 0x13, &Regs); if (CarryFlag != 0) { - DEBUG ((DEBUG_WARN, "OLB: Failed to reset BIOS disk %u, error 0x%X\n", DriveNumber, Regs.H.AH)); + DEBUG ((DEBUG_INFO, "OLB: Failed to reset BIOS disk %u, error 0x%X\n", DriveNumber, Regs.H.AH)); return EFI_DEVICE_ERROR; } } @@ -156,7 +156,7 @@ InternalGetBiosDiskNumber ( &DeviceAddressPacketAddress ); if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_WARN, "OLB: Failure allocating low memory packet for BIOS disk read - %r\n", Status)); + DEBUG ((DEBUG_INFO, "OLB: Failure allocating low memory packet for BIOS disk read - %r\n", Status)); return Status; } diff --git a/Platform/OpenLegacyBoot/LegacyBootInternal.h b/Platform/OpenLegacyBoot/LegacyBootInternal.h index 2f8decf14f1..d6d276101d5 100644 --- a/Platform/OpenLegacyBoot/LegacyBootInternal.h +++ b/Platform/OpenLegacyBoot/LegacyBootInternal.h @@ -39,6 +39,7 @@ typedef enum OC_LEGACY_OS_TYPE_ { typedef struct { EFI_DEVICE_PATH_PROTOCOL *DevicePath; + BOOLEAN IsExternal; } LEGACY_ENTRY_CONTEXT; EFI_STATUS diff --git a/Platform/OpenLegacyBoot/OpenLegacyBoot.c b/Platform/OpenLegacyBoot/OpenLegacyBoot.c index 81c7ee39c29..da4542e509c 100644 --- a/Platform/OpenLegacyBoot/OpenLegacyBoot.c +++ b/Platform/OpenLegacyBoot/OpenLegacyBoot.c @@ -70,7 +70,7 @@ ExternalSystemActionDoLegacyBoot ( EFI_HANDLE LoadedImageHandle; EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; LEGACY_ENTRY_CONTEXT *LegacyContext; - CONST CHAR8 *Args; + CONST CHAR8 *AppleBootArg; LegacyContext = ActionContext; @@ -88,12 +88,12 @@ ExternalSystemActionDoLegacyBoot ( &LoadedImageHandle ); if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_WARN, "OLB: Failure while loading Apple legacy interface - %r\n", Status)); + DEBUG ((DEBUG_INFO, "OLB: Failure while loading Apple legacy interface - %r\n", Status)); return Status; } // - // Specify boot device type on loaded image. + // Specify boot device type argument on loaded image. // Status = gBS->HandleProtocol ( LoadedImageHandle, @@ -101,7 +101,8 @@ ExternalSystemActionDoLegacyBoot ( (VOID **)&LoadedImage ); if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_WARN, "OLB: Failure while loading Apple legacy interface - %r\n", Status)); + DEBUG ((DEBUG_INFO, "OLB: Failure while loading Apple legacy interface - %r\n", Status)); + gBS->UnloadImage (LoadedImageHandle); return Status; } @@ -109,20 +110,30 @@ ExternalSystemActionDoLegacyBoot ( LoadedImage->LoadOptions = NULL; if (OcIsDiskCdRom (LegacyContext->DevicePath)) { - Args = AllocateCopyPool (L_STR_SIZE ("CD"), "CD"); + AppleBootArg = "CD"; + } else if (LegacyContext->IsExternal) { + AppleBootArg = "USB"; } else { - Args = AllocateCopyPool (L_STR_SIZE ("HD"), "HD"); + AppleBootArg = "HD"; } - OcAppendArgumentsToLoadedImage (LoadedImage, &Args, 1, TRUE); + if (!OcAppendArgumentsToLoadedImage (LoadedImage, &AppleBootArg, 1, TRUE)) { + gBS->UnloadImage (LoadedImageHandle); + return EFI_INVALID_PARAMETER; + } Status = gBS->StartImage (LoadedImageHandle, NULL, NULL); if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_WARN, "OLB: Failure while starting Apple legacy interface - %r\n", Status)); + DEBUG ((DEBUG_INFO, "OLB: Failure while starting Apple legacy interface - %r\n", Status)); + gBS->UnloadImage (LoadedImageHandle); return Status; } } else { - InternalLoadLegacyPbr (LegacyContext->DevicePath); + Status = InternalLoadLegacyPbr (LegacyContext->DevicePath); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "OLB: Failure while starting legacy PBR interface - %r\n", Status)); + return Status; + } } return EFI_SUCCESS; @@ -183,7 +194,7 @@ OcGetLegacyBootEntries ( &Handles ); if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_WARN, "OLB: Failed to get Block I/O handles - %r\n", Status)); + DEBUG ((DEBUG_INFO, "OLB: Failed to get Block I/O handles - %r\n", Status)); OcFlexArrayFree (&FlexPickerEntries); return Status; } @@ -195,11 +206,9 @@ OcGetLegacyBootEntries ( // If device type locking is set and this device is not allowed, // skip device. // - if ((PickerContext->ScanPolicy & OC_SCAN_DEVICE_LOCK) != 0) { - ScanPolicy = OcGetDevicePolicyType (BlockDeviceHandle, &IsExternal); - if ((ScanPolicy & PickerContext->ScanPolicy) == 0) { - continue; - } + ScanPolicy = OcGetDevicePolicyType (BlockDeviceHandle, &IsExternal); + if (((PickerContext->ScanPolicy & OC_SCAN_DEVICE_LOCK) != 0) && ((ScanPolicy & PickerContext->ScanPolicy) == 0)) { + continue; } // @@ -261,6 +270,7 @@ OcGetLegacyBootEntries ( } LegacyContext->DevicePath = BlockDevicePath; + LegacyContext->IsExternal = IsExternal; PickerEntry->Id = AsciiDevicePath; PickerEntry->Name = GetLegacyEntryName (LegacyOsType); @@ -270,6 +280,7 @@ OcGetLegacyBootEntries ( PickerEntry->Tool = FALSE; PickerEntry->TextMode = FALSE; PickerEntry->RealPath = FALSE; + PickerEntry->External = IsExternal; PickerEntry->ExternalSystemAction = ExternalSystemActionDoLegacyBoot; PickerEntry->ExternalSystemActionContext = LegacyContext; From 12085032fcc8316dff2bc49cf96c1c05fd0dcf7b Mon Sep 17 00:00:00 2001 From: John Davis Date: Sat, 19 Aug 2023 19:40:16 -0500 Subject: [PATCH 41/55] OpenLegacyBoot: Fix device path storage on legacy entries --- .../Acidanthera/Library/OcBootManagementLib.h | 12 +-- .../OcBootManagementLib/BootEntryManagement.c | 14 ++-- Platform/OpenLegacyBoot/LegacyBootInternal.h | 5 -- Platform/OpenLegacyBoot/OpenLegacyBoot.c | 78 ++++++++----------- 4 files changed, 45 insertions(+), 64 deletions(-) diff --git a/Include/Acidanthera/Library/OcBootManagementLib.h b/Include/Acidanthera/Library/OcBootManagementLib.h index 44df0a4c041..bd15da754f7 100644 --- a/Include/Acidanthera/Library/OcBootManagementLib.h +++ b/Include/Acidanthera/Library/OcBootManagementLib.h @@ -200,8 +200,8 @@ EFI_STATUS typedef EFI_STATUS (*OC_BOOT_EXTERNAL_SYSTEM_ACTION) ( - IN OUT OC_PICKER_CONTEXT *PickerContext, - IN VOID *ActionContext + IN OUT OC_PICKER_CONTEXT *PickerContext, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath ); /** @@ -227,10 +227,6 @@ typedef struct OC_BOOT_ENTRY_ { // OC_BOOT_EXTERNAL_SYSTEM_ACTION ExternalSystemAction; // - // Action to perform on execution. Only valid for external boot system entries. - // - VOID *ExternalSystemActionContext; - // // Id under which to save entry as default. // CHAR16 *Id; @@ -631,9 +627,9 @@ typedef struct { // OC_BOOT_EXTERNAL_SYSTEM_ACTION ExternalSystemAction; // - // External boot system action context. Boot Entry Protocol only. Optional. + // External boot system Device Path. Boot Entry Protocol only. Optional. // - VOID *ExternalSystemActionContext; + EFI_DEVICE_PATH_PROTOCOL *ExternalSystemDevicePath; // // Whether this entry should be labeled as external to the system. Boot Entry Protocol only. Optional. // diff --git a/Library/OcBootManagementLib/BootEntryManagement.c b/Library/OcBootManagementLib/BootEntryManagement.c index f23b6db0320..6486f4c6e0a 100644 --- a/Library/OcBootManagementLib/BootEntryManagement.c +++ b/Library/OcBootManagementLib/BootEntryManagement.c @@ -720,12 +720,12 @@ InternalAddBootEntryFromCustomEntry ( )); if (CustomEntry->ExternalSystemAction) { - BootEntry->Type = OC_BOOT_EXTERNAL_SYSTEM; - BootEntry->ExternalSystemAction = CustomEntry->ExternalSystemAction; - BootEntry->ExternalSystemActionContext = CustomEntry->ExternalSystemActionContext; - BootEntry->AudioBasePath = CustomEntry->AudioBasePath; - BootEntry->AudioBaseType = CustomEntry->AudioBaseType; - BootEntry->IsExternal = CustomEntry->External; + BootEntry->Type = OC_BOOT_EXTERNAL_SYSTEM; + BootEntry->ExternalSystemAction = CustomEntry->ExternalSystemAction; + BootEntry->AudioBasePath = CustomEntry->AudioBasePath; + BootEntry->AudioBaseType = CustomEntry->AudioBaseType; + BootEntry->DevicePath = CustomEntry->ExternalSystemDevicePath; + BootEntry->IsExternal = CustomEntry->External; } else if (CustomEntry->SystemAction) { BootEntry->Type = OC_BOOT_SYSTEM; BootEntry->SystemAction = CustomEntry->SystemAction; @@ -2512,7 +2512,7 @@ OcLoadBootEntry ( if ((BootEntry->Type & OC_BOOT_EXTERNAL_SYSTEM) != 0) { ASSERT (BootEntry->ExternalSystemAction != NULL); - return BootEntry->ExternalSystemAction (Context, BootEntry->ExternalSystemActionContext); + return BootEntry->ExternalSystemAction (Context, BootEntry->DevicePath); } if ((BootEntry->Type & OC_BOOT_SYSTEM) != 0) { diff --git a/Platform/OpenLegacyBoot/LegacyBootInternal.h b/Platform/OpenLegacyBoot/LegacyBootInternal.h index d6d276101d5..ead42d71326 100644 --- a/Platform/OpenLegacyBoot/LegacyBootInternal.h +++ b/Platform/OpenLegacyBoot/LegacyBootInternal.h @@ -37,11 +37,6 @@ typedef enum OC_LEGACY_OS_TYPE_ { OcLegacyOsTypeIsoLinux } OC_LEGACY_OS_TYPE; -typedef struct { - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - BOOLEAN IsExternal; -} LEGACY_ENTRY_CONTEXT; - EFI_STATUS InternalGetBiosDiskNumber ( IN THUNK_CONTEXT *ThunkContext, diff --git a/Platform/OpenLegacyBoot/OpenLegacyBoot.c b/Platform/OpenLegacyBoot/OpenLegacyBoot.c index da4542e509c..49bbef4c99c 100644 --- a/Platform/OpenLegacyBoot/OpenLegacyBoot.c +++ b/Platform/OpenLegacyBoot/OpenLegacyBoot.c @@ -53,38 +53,38 @@ FreePickerEntry ( if (Entry->Flavour != NULL) { FreePool ((CHAR8 *)Entry->Flavour); } - - if (Entry->ExternalSystemActionContext != NULL) { - FreePool (Entry->ExternalSystemActionContext); - } } STATIC EFI_STATUS ExternalSystemActionDoLegacyBoot ( - IN OUT OC_PICKER_CONTEXT *PickerContext, - IN VOID *ActionContext + IN OUT OC_PICKER_CONTEXT *PickerContext, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath ) { EFI_STATUS Status; + EFI_HANDLE DiskHandle; EFI_HANDLE LoadedImageHandle; EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; - LEGACY_ENTRY_CONTEXT *LegacyContext; + BOOLEAN IsExternal; CONST CHAR8 *AppleBootArg; - LegacyContext = ActionContext; - // // Load and start legacy OS. // // On Macs, use the Apple legacy interface. // On other systems, use the Legacy8259 protocol. // - DebugPrintDevicePath (DEBUG_INFO, "OLB: Legacy device path", LegacyContext->DevicePath); + DebugPrintDevicePath (DEBUG_INFO, "OLB: Legacy device path", DevicePath); if (mIsAppleInterfaceSupported) { + DiskHandle = OcPartitionGetPartitionHandle (DevicePath); + if (DiskHandle == NULL) { + return EFI_INVALID_PARAMETER; + } + Status = InternalLoadAppleLegacyInterface ( mImageHandle, - LegacyContext->DevicePath, + DevicePath, &LoadedImageHandle ); if (EFI_ERROR (Status)) { @@ -109,18 +109,23 @@ ExternalSystemActionDoLegacyBoot ( LoadedImage->LoadOptionsSize = 0; LoadedImage->LoadOptions = NULL; - if (OcIsDiskCdRom (LegacyContext->DevicePath)) { + OcGetDevicePolicyType (DiskHandle, &IsExternal); + + if (OcIsDiskCdRom (DevicePath)) { AppleBootArg = "CD"; - } else if (LegacyContext->IsExternal) { + } else if (IsExternal) { AppleBootArg = "USB"; } else { AppleBootArg = "HD"; } - if (!OcAppendArgumentsToLoadedImage (LoadedImage, &AppleBootArg, 1, TRUE)) { - gBS->UnloadImage (LoadedImageHandle); - return EFI_INVALID_PARAMETER; - } + OcAppendArgumentsToLoadedImage ( + LoadedImage, + &AppleBootArg, + 1, + TRUE + ); + DEBUG ((DEBUG_INFO, "OLB: Apple legacy interface args <%s>\n", LoadedImage->LoadOptions)); Status = gBS->StartImage (LoadedImageHandle, NULL, NULL); if (EFI_ERROR (Status)) { @@ -129,7 +134,7 @@ ExternalSystemActionDoLegacyBoot ( return Status; } } else { - Status = InternalLoadLegacyPbr (LegacyContext->DevicePath); + Status = InternalLoadLegacyPbr (DevicePath); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_INFO, "OLB: Failure while starting legacy PBR interface - %r\n", Status)); return Status; @@ -165,7 +170,6 @@ OcGetLegacyBootEntries ( OC_LEGACY_OS_TYPE LegacyOsType; OC_FLEX_ARRAY *FlexPickerEntries; OC_PICKER_ENTRY *PickerEntry; - LEGACY_ENTRY_CONTEXT *LegacyContext; ASSERT (PickerContext != NULL); ASSERT (Entries != NULL); @@ -259,31 +263,17 @@ OcGetLegacyBootEntries ( return Status; } - // - // Context referencing booted entry later on. - // - LegacyContext = AllocateZeroPool (sizeof (*LegacyContext)); - if (LegacyContext == NULL) { - FreePool (AsciiDevicePath); - OcFlexArrayFree (&FlexPickerEntries); - return EFI_OUT_OF_RESOURCES; - } - - LegacyContext->DevicePath = BlockDevicePath; - LegacyContext->IsExternal = IsExternal; - - PickerEntry->Id = AsciiDevicePath; - PickerEntry->Name = GetLegacyEntryName (LegacyOsType); - PickerEntry->Path = NULL; - PickerEntry->Arguments = NULL; - PickerEntry->Flavour = GetLegacyEntryFlavour (LegacyOsType); - PickerEntry->Tool = FALSE; - PickerEntry->TextMode = FALSE; - PickerEntry->RealPath = FALSE; - PickerEntry->External = IsExternal; - - PickerEntry->ExternalSystemAction = ExternalSystemActionDoLegacyBoot; - PickerEntry->ExternalSystemActionContext = LegacyContext; + PickerEntry->Id = AsciiDevicePath; + PickerEntry->Name = GetLegacyEntryName (LegacyOsType); + PickerEntry->Path = NULL; + PickerEntry->Arguments = NULL; + PickerEntry->Flavour = GetLegacyEntryFlavour (LegacyOsType); + PickerEntry->Tool = FALSE; + PickerEntry->TextMode = FALSE; + PickerEntry->RealPath = FALSE; + PickerEntry->External = IsExternal; + PickerEntry->ExternalSystemAction = ExternalSystemActionDoLegacyBoot; + PickerEntry->ExternalSystemDevicePath = BlockDevicePath; if ((PickerEntry->Name == NULL) || (PickerEntry->Flavour == NULL)) { OcFlexArrayFree (&FlexPickerEntries); From dabc04a64c29ef2f48edd9e5c1718bbbb9e08627 Mon Sep 17 00:00:00 2001 From: John Davis Date: Sat, 19 Aug 2023 21:23:20 -0500 Subject: [PATCH 42/55] OcBootManagementLib: Fix Apple legacy interface default entry handling --- .../OcBootManagementLib/BootEntryManagement.c | 66 +++++++++---------- .../OcBootManagementLib/BootEntryProtocol.c | 8 --- Library/OcFileLib/DiskMisc.c | 4 +- 3 files changed, 32 insertions(+), 46 deletions(-) diff --git a/Library/OcBootManagementLib/BootEntryManagement.c b/Library/OcBootManagementLib/BootEntryManagement.c index 6486f4c6e0a..5bbf9103848 100644 --- a/Library/OcBootManagementLib/BootEntryManagement.c +++ b/Library/OcBootManagementLib/BootEntryManagement.c @@ -1327,7 +1327,7 @@ AddBootEntryFromBootOption ( } // - // Attempt to handle detected legacy OS. + // Attempt to handle detected legacy OS via Apple legacy interface. // RemainingDevicePath = DevicePath; DevicePath = OcDiskFindActiveMbrPartitionPath ( @@ -1340,34 +1340,30 @@ AddBootEntryFromBootOption ( // Disk with MBR or hybrid MBR was detected. // if (DevicePath != NULL) { - // - // Ensure that we are allowed to boot from this filesystem. - // - FileSystem = InternalFileSystemForHandle (BootContext, FileSystemHandle, TRUE, NULL); - if (FileSystem != NULL) { - TextDevicePath = ConvertDevicePathToText (DevicePath, FALSE, FALSE); - if (TextDevicePath != NULL) { - // - // Add entry from externally provided legacy interface. - // - Status = OcAddEntriesFromBootEntryProtocol ( - BootContext, - FileSystem, - EntryProtocolHandles, - EntryProtocolHandleCount, - TextDevicePath, - TRUE, - FALSE - ); - if (!EFI_ERROR (Status)) { - if (EntryProtocolId != NULL) { - *EntryProtocolId = TextDevicePath; - } - - IsAppleLegacyHandled = TRUE; - } else { - FreePool (TextDevicePath); + TextDevicePath = ConvertDevicePathToText (DevicePath, FALSE, FALSE); + if (TextDevicePath != NULL) { + // + // Add entry from externally provided legacy interface. + // Boot entry ID must be active partition Device Path. + // + Status = OcAddEntriesFromBootEntryProtocol ( + BootContext, + CustomFileSystem, + EntryProtocolHandles, + EntryProtocolHandleCount, + TextDevicePath, + TRUE, + FALSE + ); + if (!EFI_ERROR (Status)) { + if (EntryProtocolId != NULL) { + *EntryProtocolId = TextDevicePath; } + + FileSystem = CustomFileSystem; + IsAppleLegacyHandled = TRUE; + } else { + FreePool (TextDevicePath); } } } @@ -2156,8 +2152,6 @@ OcScanForBootEntries ( ) ); - IsDefaultEntryProtocolPartition = (DefaultEntryId != NULL); - // // No entries, or only entry pre-created from boot entry protocol, // so process this directory with Apple Bless. @@ -2195,11 +2189,6 @@ OcScanForBootEntries ( AddBootEntryFromSelfRecovery (BootContext, FileSystem); } - if (DefaultEntryId != NULL) { - FreePool (DefaultEntryId); - DefaultEntryId = NULL; - } - if (CustomFileSystem != NULL) { // // Insert the custom file system last for entry order. @@ -2220,12 +2209,17 @@ OcScanForBootEntries ( CustomFileSystem, EntryProtocolHandles, EntryProtocolHandleCount, - NULL, + DefaultEntryId, FALSE, FALSE ); } + if (DefaultEntryId != NULL) { + FreePool (DefaultEntryId); + DefaultEntryId = NULL; + } + OcFreeBootEntryProtocolHandles (&EntryProtocolHandles); if (BootContext->BootEntryCount == 0) { diff --git a/Library/OcBootManagementLib/BootEntryProtocol.c b/Library/OcBootManagementLib/BootEntryProtocol.c index 724fd8ccdfc..6bcde243c36 100644 --- a/Library/OcBootManagementLib/BootEntryProtocol.c +++ b/Library/OcBootManagementLib/BootEntryProtocol.c @@ -250,14 +250,6 @@ OcAddEntriesFromBootEntryProtocol ( ASSERT (!CreateDefault || (DefaultEntryId != NULL)); - // - // Non-filesystem entries cannot be saved as normal default boot option, - // but can be triggered as default boot item by boot entry protocol hotkey. - // - if (!CreateForHotKey && CreateDefault && (FileSystem->Handle == OC_CUSTOM_FS_HANDLE)) { - return EFI_NOT_FOUND; - } - AddEntriesContext.ReturnStatus = EFI_NOT_FOUND; AddEntriesContext.BootContext = BootContext; AddEntriesContext.FileSystem = FileSystem; diff --git a/Library/OcFileLib/DiskMisc.c b/Library/OcFileLib/DiskMisc.c index 123abb76180..0c4eb67c75d 100644 --- a/Library/OcFileLib/DiskMisc.c +++ b/Library/OcFileLib/DiskMisc.c @@ -1089,13 +1089,13 @@ OcDiskFindActiveMbrPartitionPath ( Status = gBS->LocateHandleBuffer ( ByProtocol, - &gEfiSimpleFileSystemProtocolGuid, + &gEfiBlockIoProtocolGuid, NULL, &NoHandles, &Handles ); if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_INFO, "OCPI: Failed to locate FS handles\n")); + DEBUG ((DEBUG_INFO, "OCPI: Failed to locate Block I/O handles\n")); return NULL; } From 9a710567407ec531ce653f250664a8cea24c709f Mon Sep 17 00:00:00 2001 From: John Davis Date: Sat, 19 Aug 2023 22:18:27 -0500 Subject: [PATCH 43/55] OcBootManagementLib: Fix device path use after free --- Library/OcBootManagementLib/BootEntryManagement.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Library/OcBootManagementLib/BootEntryManagement.c b/Library/OcBootManagementLib/BootEntryManagement.c index 5bbf9103848..6b2c8a085ba 100644 --- a/Library/OcBootManagementLib/BootEntryManagement.c +++ b/Library/OcBootManagementLib/BootEntryManagement.c @@ -724,8 +724,13 @@ InternalAddBootEntryFromCustomEntry ( BootEntry->ExternalSystemAction = CustomEntry->ExternalSystemAction; BootEntry->AudioBasePath = CustomEntry->AudioBasePath; BootEntry->AudioBaseType = CustomEntry->AudioBaseType; - BootEntry->DevicePath = CustomEntry->ExternalSystemDevicePath; BootEntry->IsExternal = CustomEntry->External; + BootEntry->DevicePath = DuplicateDevicePath (CustomEntry->ExternalSystemDevicePath); + + if (BootEntry->DevicePath == NULL) { + FreeBootEntry (BootEntry); + return EFI_OUT_OF_RESOURCES; + } } else if (CustomEntry->SystemAction) { BootEntry->Type = OC_BOOT_SYSTEM; BootEntry->SystemAction = CustomEntry->SystemAction; From 5b9861b3a8efd4e7ae7dadc45ee08a347867fb33 Mon Sep 17 00:00:00 2001 From: John Davis Date: Sat, 19 Aug 2023 22:19:20 -0500 Subject: [PATCH 44/55] OpenLegacyBoot: Detect BIOS disk address for PC boot --- Library/OcLegacyThunkLib/OcLegacyThunkLib.c | 12 ++- Platform/OpenLegacyBoot/BiosDisk.c | 100 ++++++++++++++++--- Platform/OpenLegacyBoot/LegacyBootInternal.h | 9 +- Platform/OpenLegacyBoot/LegacyBootSupport.c | 22 ++-- 4 files changed, 113 insertions(+), 30 deletions(-) diff --git a/Library/OcLegacyThunkLib/OcLegacyThunkLib.c b/Library/OcLegacyThunkLib/OcLegacyThunkLib.c index bdacfa3e1dc..d69d19fd3b4 100644 --- a/Library/OcLegacyThunkLib/OcLegacyThunkLib.c +++ b/Library/OcLegacyThunkLib/OcLegacyThunkLib.c @@ -339,9 +339,8 @@ OcLegacyThunkFarCall86 ( UINT16 *Stack16; IA32_REGISTER_SET ThunkRegSet; BOOLEAN Ret; - // BOOLEAN InterruptState; - UINT64 TimerPeriod; - BOOLEAN Enabled; + UINT64 TimerPeriod; + BOOLEAN Enabled; EFI_TIMER_ARCH_PROTOCOL *TimerProtocol; @@ -405,8 +404,8 @@ OcLegacyThunkFarCall86 ( ASSERT_EFI_ERROR (Status); // - // Clear the error flag; thunk code may set it. Stack16 should be the high address - // Make Statk16 address the low 16 bit must be not zero. + // Clear the error flag; thunk code may set it. Stack16 should be the high address. + // Make Stack16 address the low 16 bit must be not zero. // Stack16 = (UINT16 *)((UINT8 *)ThunkContext->RealModeBuffer + ThunkContext->RealModeBufferSize - sizeof (UINT16)); @@ -426,6 +425,9 @@ OcLegacyThunkFarCall86 ( ThunkContext->RealModeState = &ThunkRegSet; AsmThunk16 (ThunkContext); + // + // EFI is likely trashed if we get here, but attempt to restore state. + // if ((Stack != NULL) && (StackSize != 0)) { // // Copy low memory stack to Stack diff --git a/Platform/OpenLegacyBoot/BiosDisk.c b/Platform/OpenLegacyBoot/BiosDisk.c index e9ee71dd8a2..c802de7200f 100644 --- a/Platform/OpenLegacyBoot/BiosDisk.c +++ b/Platform/OpenLegacyBoot/BiosDisk.c @@ -39,6 +39,8 @@ typedef struct { UINT64 Lba; } DEVICE_ADDRESS_PACKET; +#define BIOS_DISK_CHECK_BUFFER_SECTOR_COUNT 4 + STATIC EFI_STATUS BiosDiskReset ( @@ -127,47 +129,93 @@ BiosDiskReadExtSectors ( Regs.E.DS = EFI_SEGMENT (DeviceAddressPacket); CarryFlag = OcLegacyThunkBiosInt86 (ThunkContext, Legacy8259, 0x13, &Regs); - DEBUG ((DEBUG_INFO, "carry %u\n", CarryFlag)); + if (CarryFlag != 0) { + return EFI_DEVICE_ERROR; + } return EFI_SUCCESS; } EFI_STATUS -InternalGetBiosDiskNumber ( - IN THUNK_CONTEXT *ThunkContext, - IN EFI_LEGACY_8259_PROTOCOL *Legacy8259, - OUT UINT8 *DriveNumber +InternalGetBiosDiskAddress ( + IN THUNK_CONTEXT *ThunkContext, + IN EFI_LEGACY_8259_PROTOCOL *Legacy8259, + IN EFI_HANDLE DiskHandle, + OUT UINT8 *DriveAddress ) { EFI_STATUS Status; + OC_DISK_CONTEXT DiskContext; UINT8 DriveAddr; EFI_PHYSICAL_ADDRESS DeviceAddressPacketAddress; DEVICE_ADDRESS_PACKET *DeviceAddressPacket; - UINT8 *Buffer; + UINT8 *BiosBuffer; + UINTN BiosBufferPages; + UINT32 BiosCrc32; + UINT8 *DiskBuffer; + UINTN DiskBufferSize; + UINT32 DiskCrc32; + BOOLEAN MatchedDisk; + + // + // Read sectors from EFI disk device. + // + Status = OcDiskInitializeContext (&DiskContext, DiskHandle, TRUE); + if (EFI_ERROR (Status)) { + return Status; + } + + DiskBufferSize = ALIGN_VALUE (BIOS_DISK_CHECK_BUFFER_SECTOR_COUNT * MBR_SIZE, DiskContext.BlockSize); + DiskBuffer = AllocatePool (DiskBufferSize); + if (DiskBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = OcDiskRead ( + &DiskContext, + 0, + DiskBufferSize, + DiskBuffer + ); + if (EFI_ERROR (Status)) { + FreePool (DiskBuffer); + return Status; + } + + gBS->CalculateCrc32 ( + DiskBuffer, + BIOS_DISK_CHECK_BUFFER_SECTOR_COUNT * MBR_SIZE, + &DiskCrc32 + ); + DEBUG ((DEBUG_INFO, "OLB: EFI disk CRC32: 0x%X\n", DiskCrc32)); // // Allocate low memory buffer for disk reads. // DeviceAddressPacketAddress = (SIZE_1MB - 1); + BiosBufferPages = EFI_SIZE_TO_PAGES (sizeof (*DeviceAddressPacket) + (BIOS_DISK_CHECK_BUFFER_SECTOR_COUNT * MBR_SIZE)) + 1; Status = gBS->AllocatePages ( AllocateMaxAddress, EfiBootServicesData, - EFI_SIZE_TO_PAGES (sizeof (*DeviceAddressPacket) + (MBR_SIZE * 4)) + 1, + BiosBufferPages, &DeviceAddressPacketAddress ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_INFO, "OLB: Failure allocating low memory packet for BIOS disk read - %r\n", Status)); + FreePool (DiskBuffer); return Status; } DeviceAddressPacket = (DEVICE_ADDRESS_PACKET *)(UINTN)DeviceAddressPacketAddress; - Buffer = (UINT8 *)(UINTN)DeviceAddressPacketAddress + 0x200; + BiosBuffer = (UINT8 *)(UINTN)DeviceAddressPacketAddress + 0x200; // - // Locate disk with matching checksum of first few sectors. + // Read sectors from each BIOS disk. + // Compare against sectors from EFI disk to determine BIOS disk address. // + MatchedDisk = FALSE; for (DriveAddr = 0x80; DriveAddr < 0x88; DriveAddr++) { - DEBUG ((DEBUG_INFO, "drive %X\n", DriveAddr)); + DEBUG ((DEBUG_INFO, "OLB: Reading BIOS drive 0x%X\n", DriveAddr)); // // Reset disk and verify INT13H extensions are supported. @@ -183,7 +231,7 @@ InternalGetBiosDiskNumber ( } // - // Read sectors from disk. + // Read first 4 sectors from disk. // Status = BiosDiskReadExtSectors ( ThunkContext, @@ -191,15 +239,37 @@ InternalGetBiosDiskNumber ( DeviceAddressPacket, DriveAddr, 0, - 4, - Buffer + BIOS_DISK_CHECK_BUFFER_SECTOR_COUNT, + BiosBuffer ); if (EFI_ERROR (Status)) { continue; } - DebugPrintHexDump (DEBUG_INFO, "raw bios bytes", Buffer, 512); + // + // Calculate CRC32 of BIOS disk sectors. + // + gBS->CalculateCrc32 ( + BiosBuffer, + BIOS_DISK_CHECK_BUFFER_SECTOR_COUNT * MBR_SIZE, + &BiosCrc32 + ); + DEBUG ((DEBUG_INFO, "OLB: BIOS disk CRC32: 0x%X\n", BiosCrc32)); + + if (BiosCrc32 == DiskCrc32) { + DEBUG ((DEBUG_INFO, "OLB: Matched BIOS disk address 0x%X\n", DriveAddr)); + + MatchedDisk = TRUE; + *DriveAddress = DriveAddr; + break; + } } - return EFI_SUCCESS; + FreePool (DiskBuffer); + gBS->FreePages ( + DeviceAddressPacketAddress, + BiosBufferPages + ); + + return MatchedDisk ? EFI_SUCCESS : EFI_NOT_FOUND; } diff --git a/Platform/OpenLegacyBoot/LegacyBootInternal.h b/Platform/OpenLegacyBoot/LegacyBootInternal.h index ead42d71326..8464da91d48 100644 --- a/Platform/OpenLegacyBoot/LegacyBootInternal.h +++ b/Platform/OpenLegacyBoot/LegacyBootInternal.h @@ -38,10 +38,11 @@ typedef enum OC_LEGACY_OS_TYPE_ { } OC_LEGACY_OS_TYPE; EFI_STATUS -InternalGetBiosDiskNumber ( - IN THUNK_CONTEXT *ThunkContext, - IN EFI_LEGACY_8259_PROTOCOL *Legacy8259, - OUT UINT8 *DriveNumber +InternalGetBiosDiskAddress ( + IN THUNK_CONTEXT *ThunkContext, + IN EFI_LEGACY_8259_PROTOCOL *Legacy8259, + IN EFI_HANDLE DiskHandle, + OUT UINT8 *DriveNumber ); EFI_STATUS diff --git a/Platform/OpenLegacyBoot/LegacyBootSupport.c b/Platform/OpenLegacyBoot/LegacyBootSupport.c index 6195fd70687..a7d97d17abd 100644 --- a/Platform/OpenLegacyBoot/LegacyBootSupport.c +++ b/Platform/OpenLegacyBoot/LegacyBootSupport.c @@ -372,6 +372,7 @@ InternalLoadLegacyPbr ( MASTER_BOOT_RECORD *Mbr; MASTER_BOOT_RECORD *Pbr; UINT8 PartitionIndex; + UINT8 BiosDiskAddress; IA32_REGISTER_SET Regs; MASTER_BOOT_RECORD *MbrPtr = (MASTER_BOOT_RECORD *)0x0600; @@ -452,7 +453,18 @@ InternalLoadLegacyPbr ( // // Determine BIOS disk number. // - InternalGetBiosDiskNumber (&mThunkContext, Legacy8259, NULL); + Status = InternalGetBiosDiskAddress ( + &mThunkContext, + Legacy8259, + DiskHandle, + &BiosDiskAddress + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "OLB: Disk address could not be determined\n")); + FreePool (Pbr); + FreePool (Mbr); + return Status; + } // // Copy MBR and PBR to low memory locations for booting. @@ -470,7 +482,7 @@ InternalLoadLegacyPbr ( // ZeroMem (&Regs, sizeof (Regs)); - Regs.H.DL = 0x80; + Regs.H.DL = BiosDiskAddress; Regs.X.SI = (UINT16)(UINTN)&MbrPtr->Partition[PartitionIndex]; OcLegacyThunkFarCall86 ( &mThunkContext, @@ -482,9 +494,7 @@ InternalLoadLegacyPbr ( 0 ); - DEBUG ((DEBUG_INFO, "here\n")); - while (TRUE) { - } + DEBUG ((DEBUG_WARN, "OLB: Failure calling legacy boot sector\n")); - return EFI_SUCCESS; + return EFI_INVALID_PARAMETER; } From 8c96647760338ec945856a6c30cc4baf150552f1 Mon Sep 17 00:00:00 2001 From: John Davis Date: Sun, 20 Aug 2023 13:52:32 -0500 Subject: [PATCH 45/55] Docs: Add BootCampHD to LegacySchema in sample configs --- Docs/Sample.plist | 1 + Docs/SampleCustom.plist | 1 + 2 files changed, 2 insertions(+) diff --git a/Docs/Sample.plist b/Docs/Sample.plist index e2d67b1d279..74eae16b3fc 100644 --- a/Docs/Sample.plist +++ b/Docs/Sample.plist @@ -1322,6 +1322,7 @@ nvda_drv prev-lang:kbd backlight-level + BootCampHD 8BE4DF61-93CA-11D2-AA0D-00E098032B8C diff --git a/Docs/SampleCustom.plist b/Docs/SampleCustom.plist index 1674d07a852..eda903ea1a6 100644 --- a/Docs/SampleCustom.plist +++ b/Docs/SampleCustom.plist @@ -1349,6 +1349,7 @@ nvda_drv prev-lang:kbd backlight-level + BootCampHD 8BE4DF61-93CA-11D2-AA0D-00E098032B8C From bbb7dee447477b304ba3eaaf75d4f73f0aa7d70b Mon Sep 17 00:00:00 2001 From: John Davis Date: Sun, 20 Aug 2023 14:15:51 -0500 Subject: [PATCH 46/55] BootLoader: Start only boot sector in protective MBR in boot0 --- Legacy/BootLoader/boot0.nasm | 31 +++++-------------------------- 1 file changed, 5 insertions(+), 26 deletions(-) diff --git a/Legacy/BootLoader/boot0.nasm b/Legacy/BootLoader/boot0.nasm index e9ca16e83a5..df88ec4c107 100644 --- a/Legacy/BootLoader/boot0.nasm +++ b/Legacy/BootLoader/boot0.nasm @@ -90,8 +90,6 @@ kPartTypePMBR EQU 0xee ; On all GUID Partition Table disks a Pr ; reserving the entire space used on the disk by the GPT partitions, ; including all headers. -kPartActive EQU 0x80 ; active flag enabled -kPartInactive EQU 0x00 ; active flag disabled kEFISystemGUID EQU 0x3BC93EC9 ; last 4 bytes of EFI System Partition Type GUID: ; C12A7328-F81F-11D2-BA4B-00A0C93EC93B kBasicDataGUID EQU 0xC79926B7 ; last 4 bytes of Basic Data System Partition Type GUID: @@ -253,8 +251,7 @@ find_boot: .loop: ; - ; First scan through the partition table looking for the active - ; partition. + ; First scan through the partition table looking for the protective MBR. ; %if DEBUG mov al, [si + part.type] ; print partition type @@ -266,36 +263,18 @@ find_boot: cmp BYTE [si + part.type], 0 ; unused partition? je .continue ; skip to next entry cmp BYTE [si + part.type], kPartTypePMBR ; check for Protective MBR - jne .tryToBootIfActive - - mov BYTE [si + part.bootid], kPartInactive ; found Protective MBR - ; clear active flag to make sure this protective - ; partition won't be used as a bootable partition. - mov bl, 1 ; Assume we can deal with GPT but try to scan - ; later if not found any other bootable partitions. - -.tryToBootIfActive: - ; We're going to try to boot a partition if it is active - cmp BYTE [si + part.bootid], kPartActive jne .continue - ; - ; Found boot partition, read boot sector to memory. - ; - - xor dh, dh ; Argument for loadBootSector to skip file system signature check. - call loadBootSector - jne .continue - jmp SHORT initBootLoader + mov bl, 1 ; found Protective MBR + ; GPT header should be at LBA 1 .continue: add si, BYTE part_size ; advance SI to next partition entry loop .loop ; loop through all partition entries ; - ; Scanned all partitions but not found any with active flag enabled - ; Anyway if we found a protective MBR before we still have a chance - ; for a possible GPT Header at LBA 1 + ; Partition scan completed + ; If a protective MBR was found there should be a GPT header at LBA 1 ; dec bl jnz .exit ; didn't find Protective MBR before From cf88226eed0cc1d13716936af02ca4db4ceb5ec0 Mon Sep 17 00:00:00 2001 From: John Davis Date: Sun, 20 Aug 2023 22:09:05 -0500 Subject: [PATCH 47/55] OcLegacyThunkLib: Fix incorrect timer handling --- Library/OcLegacyThunkLib/OcLegacyThunkLib.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Library/OcLegacyThunkLib/OcLegacyThunkLib.c b/Library/OcLegacyThunkLib/OcLegacyThunkLib.c index d69d19fd3b4..0cfa3c46973 100644 --- a/Library/OcLegacyThunkLib/OcLegacyThunkLib.c +++ b/Library/OcLegacyThunkLib/OcLegacyThunkLib.c @@ -379,9 +379,11 @@ OcLegacyThunkFarCall86 ( NULL, (VOID **)&TimerProtocol ); - if (EFI_ERROR (Status)) { + if (!EFI_ERROR (Status)) { TimerProtocol->GetTimerPeriod (TimerProtocol, &TimerPeriod); TimerProtocol->SetTimerPeriod (TimerProtocol, 0); + } else { + TimerProtocol = NULL; } // @@ -446,7 +448,9 @@ OcLegacyThunkFarCall86 ( // // Enable and restore rate of DXE Timer // - // Private->Timer->SetTimerPeriod (Private->Timer, TimerPeriod); + if (TimerProtocol != NULL) { + TimerProtocol->SetTimerPeriod (TimerProtocol, TimerPeriod); + } // // End critical section From 4821ae92fbe4961c68f36bf80e6964c28f48454a Mon Sep 17 00:00:00 2001 From: John Davis Date: Sat, 26 Aug 2023 16:44:49 -0500 Subject: [PATCH 48/55] OpenLegacyBoot: Add support for setting legacy entry as default --- .../Acidanthera/Library/OcBootManagementLib.h | 18 +++ .../OcBootManagementLib/BootEntryManagement.c | 13 ++- .../OcBootManagementLib/DefaultEntryChoice.c | 83 ++++++++++---- Platform/OpenLegacyBoot/LegacyBootInternal.h | 7 +- Platform/OpenLegacyBoot/LegacyBootSupport.c | 106 ++++++++--------- Platform/OpenLegacyBoot/OpenLegacyBoot.c | 107 ++++++++++++++++-- 6 files changed, 238 insertions(+), 96 deletions(-) diff --git a/Include/Acidanthera/Library/OcBootManagementLib.h b/Include/Acidanthera/Library/OcBootManagementLib.h index bd15da754f7..8632ad67b0f 100644 --- a/Include/Acidanthera/Library/OcBootManagementLib.h +++ b/Include/Acidanthera/Library/OcBootManagementLib.h @@ -204,6 +204,16 @@ EFI_STATUS IN EFI_DEVICE_PATH_PROTOCOL *DevicePath ); +/** + Gets Device Path for external boot system boot entry. +**/ +typedef +EFI_STATUS +(*OC_BOOT_EXTERNAL_SYSTEM_GET_DP) ( + IN OUT OC_PICKER_CONTEXT *PickerContext, + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath + ); + /** Discovered boot entry. Note, inner resources must be freed with FreeBootEntry. @@ -227,6 +237,10 @@ typedef struct OC_BOOT_ENTRY_ { // OC_BOOT_EXTERNAL_SYSTEM_ACTION ExternalSystemAction; // + // Gets Device Path for external boot system boot entry. Only valid for external boot system entries. + // + OC_BOOT_EXTERNAL_SYSTEM_GET_DP ExternalSystemGetDevicePath; + // // Id under which to save entry as default. // CHAR16 *Id; @@ -627,6 +641,10 @@ typedef struct { // OC_BOOT_EXTERNAL_SYSTEM_ACTION ExternalSystemAction; // + // Gets Device Path for external boot system boot entry. Boot Entry Protocol only. Optional. + // + OC_BOOT_EXTERNAL_SYSTEM_GET_DP ExternalSystemGetDevicePath; + // // External boot system Device Path. Boot Entry Protocol only. Optional. // EFI_DEVICE_PATH_PROTOCOL *ExternalSystemDevicePath; diff --git a/Library/OcBootManagementLib/BootEntryManagement.c b/Library/OcBootManagementLib/BootEntryManagement.c index 6b2c8a085ba..f0a903ce1c9 100644 --- a/Library/OcBootManagementLib/BootEntryManagement.c +++ b/Library/OcBootManagementLib/BootEntryManagement.c @@ -720,12 +720,13 @@ InternalAddBootEntryFromCustomEntry ( )); if (CustomEntry->ExternalSystemAction) { - BootEntry->Type = OC_BOOT_EXTERNAL_SYSTEM; - BootEntry->ExternalSystemAction = CustomEntry->ExternalSystemAction; - BootEntry->AudioBasePath = CustomEntry->AudioBasePath; - BootEntry->AudioBaseType = CustomEntry->AudioBaseType; - BootEntry->IsExternal = CustomEntry->External; - BootEntry->DevicePath = DuplicateDevicePath (CustomEntry->ExternalSystemDevicePath); + BootEntry->Type = OC_BOOT_EXTERNAL_SYSTEM; + BootEntry->ExternalSystemAction = CustomEntry->ExternalSystemAction; + BootEntry->ExternalSystemGetDevicePath = CustomEntry->ExternalSystemGetDevicePath; + BootEntry->AudioBasePath = CustomEntry->AudioBasePath; + BootEntry->AudioBaseType = CustomEntry->AudioBaseType; + BootEntry->IsExternal = CustomEntry->External; + BootEntry->DevicePath = DuplicateDevicePath (CustomEntry->ExternalSystemDevicePath); if (BootEntry->DevicePath == NULL) { FreeBootEntry (BootEntry); diff --git a/Library/OcBootManagementLib/DefaultEntryChoice.c b/Library/OcBootManagementLib/DefaultEntryChoice.c index a51d8472e7a..95e5ec0862f 100644 --- a/Library/OcBootManagementLib/DefaultEntryChoice.c +++ b/Library/OcBootManagementLib/DefaultEntryChoice.c @@ -795,6 +795,7 @@ OcSetDefaultBootEntry ( UINTN BootChosenIndex; UINTN Index; UINTN DevicePathSize; + UINTN ExtSystemDevPathSize; UINTN LoadOptionSize; UINTN LoadOptionIdSize; UINTN LoadOptionNameSize; @@ -804,6 +805,7 @@ OcSetDefaultBootEntry ( CONST OC_CUSTOM_BOOT_DEVICE_PATH *CustomDevPath; CONST OC_ENTRY_PROTOCOL_DEVICE_PATH *EntryProtocolDevPath; + EFI_DEVICE_PATH_PROTOCOL *ExtSystemDevPath; VENDOR_DEVICE_PATH *DestCustomDevPath; FILEPATH_DEVICE_PATH *DestCustomEntryName; EFI_DEVICE_PATH_PROTOCOL *DestCustomEndNode; @@ -822,6 +824,20 @@ OcSetDefaultBootEntry ( return EFI_INVALID_PARAMETER; } + // + // Get final device path for external boot system entries. + // + ExtSystemDevPath = NULL; + if ((Entry->Type == OC_BOOT_EXTERNAL_SYSTEM) && (Entry->ExternalSystemGetDevicePath != NULL)) { + ExtSystemDevPath = Entry->DevicePath; + Status = Entry->ExternalSystemGetDevicePath (Context, &ExtSystemDevPath); + if (EFI_ERROR (Status)) { + ExtSystemDevPath = NULL; + } else { + ExtSystemDevPathSize = GetDevicePathSize (ExtSystemDevPath); + } + } + if (Context->CustomBootGuid) { BootVariableGuid = &gOcVendorVariableGuid; BootOrderName = OC_VENDOR_BOOT_ORDER_VARIABLE_NAME; @@ -874,35 +890,42 @@ OcSetDefaultBootEntry ( continue; } - BootOptionRemainingDevicePath = BootOptionDevicePath; - Status = gBS->LocateDevicePath ( - &gEfiSimpleFileSystemProtocolGuid, - &BootOptionRemainingDevicePath, - &DeviceHandle - ); - - if (!EFI_ERROR (Status)) { - MatchedEntry = InternalMatchBootEntryByDevicePath ( - Entry, - BootOptionDevicePath, - BootOptionRemainingDevicePath, - LoadOption->FilePathListLength, - FALSE - ); + if (ExtSystemDevPath != NULL) { + DevicePathSize = GetDevicePathSize (BootOptionDevicePath); + if (DevicePathSize >= ExtSystemDevPathSize) { + MatchedEntry = CompareMem (BootOptionDevicePath, ExtSystemDevPath, ExtSystemDevPathSize) == 0; + } } else { - CustomDevPath = InternalGetOcCustomDevPath (BootOptionDevicePath); - if (CustomDevPath != NULL) { - MatchedEntry = InternalMatchCustomBootEntryByDevicePath ( + BootOptionRemainingDevicePath = BootOptionDevicePath; + Status = gBS->LocateDevicePath ( + &gEfiSimpleFileSystemProtocolGuid, + &BootOptionRemainingDevicePath, + &DeviceHandle + ); + + if (!EFI_ERROR (Status)) { + MatchedEntry = InternalMatchBootEntryByDevicePath ( Entry, - CustomDevPath + BootOptionDevicePath, + BootOptionRemainingDevicePath, + LoadOption->FilePathListLength, + FALSE ); } else { - EntryProtocolDevPath = InternalGetOcEntryProtocolDevPath (BootOptionDevicePath); - if (EntryProtocolDevPath != NULL) { - MatchedEntry = InternalMatchEntryProtocolEntryByDevicePath ( + CustomDevPath = InternalGetOcCustomDevPath (BootOptionDevicePath); + if (CustomDevPath != NULL) { + MatchedEntry = InternalMatchCustomBootEntryByDevicePath ( Entry, - EntryProtocolDevPath + CustomDevPath ); + } else { + EntryProtocolDevPath = InternalGetOcEntryProtocolDevPath (BootOptionDevicePath); + if (EntryProtocolDevPath != NULL) { + MatchedEntry = InternalMatchEntryProtocolEntryByDevicePath ( + Entry, + EntryProtocolDevPath + ); + } } } } @@ -950,7 +973,9 @@ OcSetDefaultBootEntry ( } } - if (!Entry->IsCustom) { + if (ExtSystemDevPath != NULL) { + DevicePathSize = ExtSystemDevPathSize; + } else if (!Entry->IsCustom) { DevicePathSize = GetDevicePathSize (Entry->DevicePath); } else { DevicePathSize = SIZE_OF_OC_CUSTOM_BOOT_DEVICE_PATH @@ -996,7 +1021,10 @@ OcSetDefaultBootEntry ( CopyMem (LoadOption + 1, LoadOptionName, LoadOptionNameSize); } - if (!Entry->IsCustom) { + if (ExtSystemDevPath != NULL) { + DebugPrintHexDump (DEBUG_INFO, "hex", (UINT8 *)ExtSystemDevPath, DevicePathSize); + CopyMem ((UINT8 *)(LoadOption + 1) + LoadOptionNameSize, ExtSystemDevPath, DevicePathSize); + } else if (!Entry->IsCustom) { CopyMem ((UINT8 *)(LoadOption + 1) + LoadOptionNameSize, Entry->DevicePath, DevicePathSize); } else { DestCustomDevPath = (VENDOR_DEVICE_PATH *)( @@ -1057,6 +1085,11 @@ OcSetDefaultBootEntry ( FreePool (LoadOption); + if (ExtSystemDevPath != NULL) { + FreePool (ExtSystemDevPath); + ExtSystemDevPath = NULL; + } + if (EFI_ERROR (Status)) { DEBUG (( DEBUG_INFO, diff --git a/Platform/OpenLegacyBoot/LegacyBootInternal.h b/Platform/OpenLegacyBoot/LegacyBootInternal.h index 8464da91d48..df90c24bf39 100644 --- a/Platform/OpenLegacyBoot/LegacyBootInternal.h +++ b/Platform/OpenLegacyBoot/LegacyBootInternal.h @@ -50,10 +50,15 @@ InternalIsLegacyInterfaceSupported ( OUT BOOLEAN *IsAppleInterfaceSupported ); +EFI_STATUS +InternalSetBootCampHDPath ( + IN EFI_DEVICE_PATH_PROTOCOL *HdDevicePath + ); + EFI_STATUS InternalLoadAppleLegacyInterface ( IN EFI_HANDLE ParentImageHandle, - IN EFI_DEVICE_PATH_PROTOCOL *HdDevicePath, + OUT EFI_DEVICE_PATH_PROTOCOL **ImageDevicePath, OUT EFI_HANDLE *ImageHandle ); diff --git a/Platform/OpenLegacyBoot/LegacyBootSupport.c b/Platform/OpenLegacyBoot/LegacyBootSupport.c index a7d97d17abd..412908cbfb3 100644 --- a/Platform/OpenLegacyBoot/LegacyBootSupport.c +++ b/Platform/OpenLegacyBoot/LegacyBootSupport.c @@ -11,12 +11,12 @@ THUNK_CONTEXT mThunkContext; // PIWG firmware media device path for Apple legacy interface. // FwFile(2B0585EB-D8B8-49A9-8B8CE21B01AEF2B7) // -static CONST UINT8 AppleLegacyInterfaceMediaDevicePathData[] = { +STATIC CONST UINT8 AppleLegacyInterfaceMediaDevicePathData[] = { 0x04, 0x06, 0x14, 0x00, 0xEB, 0x85, 0x05, 0x2B, 0xB8, 0xD8, 0xA9, 0x49, 0x8B, 0x8C, 0xE2, 0x1B, - 0x01, 0xAE, 0xF2, 0xB7, 0x7F, 0xFF, 0x04, 0x00, + 0x01, 0xAE, 0xF2, 0xB7, 0x7F, 0xFF, 0x04, 0x00 }; -static CONST EFI_DEVICE_PATH_PROTOCOL *AppleLegacyInterfaceMediaDevicePathPath = (EFI_DEVICE_PATH_PROTOCOL *)AppleLegacyInterfaceMediaDevicePathData; +STATIC CONST EFI_DEVICE_PATH_PROTOCOL *AppleLegacyInterfaceMediaDevicePathPath = (EFI_DEVICE_PATH_PROTOCOL *)AppleLegacyInterfaceMediaDevicePathData; #define MAX_APPLE_LEGACY_DEVICE_PATHS 16 @@ -162,10 +162,8 @@ InternalIsLegacyInterfaceSupported ( } EFI_STATUS -InternalLoadAppleLegacyInterface ( - IN EFI_HANDLE ParentImageHandle, - IN EFI_DEVICE_PATH_PROTOCOL *HdDevicePath, - OUT EFI_HANDLE *ImageHandle +InternalSetBootCampHDPath ( + IN EFI_DEVICE_PATH_PROTOCOL *HdDevicePath ) { EFI_STATUS Status; @@ -173,58 +171,60 @@ InternalLoadAppleLegacyInterface ( EFI_HANDLE PartitionHandle; UINT8 PartitionIndex; EFI_DEVICE_PATH_PROTOCOL *WholeDiskPath; - EFI_DEVICE_PATH_PROTOCOL **LegacyDevicePaths; - CHAR16 *UnicodeDevicePath; - UINTN Index; + + WholeDiskPath = OcDiskGetDevicePath (HdDevicePath); + if (WholeDiskPath == NULL) { + return EFI_INVALID_PARAMETER; + } + + DebugPrintDevicePath (DEBUG_INFO, "OLB: Legacy disk device path", WholeDiskPath); // - // Get device path to disk to be booted. + // Mark target partition as active. // - if (!OcIsDiskCdRom (HdDevicePath)) { - WholeDiskPath = OcDiskGetDevicePath (HdDevicePath); - if (WholeDiskPath == NULL) { - return EFI_INVALID_PARAMETER; - } - - DebugPrintDevicePath (DEBUG_INFO, "OLB: Legacy disk device path", WholeDiskPath); + DiskHandle = OcPartitionGetDiskHandle (HdDevicePath); + if (DiskHandle == NULL) { + return EFI_INVALID_PARAMETER; + } - // - // Mark target partition as active. - // - DiskHandle = OcPartitionGetDiskHandle (HdDevicePath); - if (DiskHandle == NULL) { - return EFI_INVALID_PARAMETER; - } + PartitionHandle = OcPartitionGetPartitionHandle (HdDevicePath); + if (PartitionHandle == NULL) { + return EFI_INVALID_PARAMETER; + } - PartitionHandle = OcPartitionGetPartitionHandle (HdDevicePath); - if (PartitionHandle == NULL) { - return EFI_INVALID_PARAMETER; - } + Status = OcDiskGetMbrPartitionIndex (PartitionHandle, &PartitionIndex); + if (EFI_ERROR (Status)) { + return Status; + } - Status = OcDiskGetMbrPartitionIndex (PartitionHandle, &PartitionIndex); - if (EFI_ERROR (Status)) { - return Status; - } + Status = OcDiskMarkMbrPartitionActive (DiskHandle, PartitionIndex); + if (EFI_ERROR (Status)) { + return Status; + } - Status = OcDiskMarkMbrPartitionActive (DiskHandle, PartitionIndex); - if (EFI_ERROR (Status)) { - return Status; - } + // + // Set BootCampHD variable pointing to target disk. + // + return gRT->SetVariable ( + APPLE_BOOT_CAMP_HD_VARIABLE_NAME, + &gAppleBootVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + GetDevicePathSize (WholeDiskPath), + WholeDiskPath + ); +} - // - // Set BootCampHD variable pointing to target disk. - // - Status = gRT->SetVariable ( - APPLE_BOOT_CAMP_HD_VARIABLE_NAME, - &gAppleBootVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, - GetDevicePathSize (WholeDiskPath), - WholeDiskPath - ); - if (EFI_ERROR (Status)) { - return Status; - } - } +EFI_STATUS +InternalLoadAppleLegacyInterface ( + IN EFI_HANDLE ParentImageHandle, + OUT EFI_DEVICE_PATH_PROTOCOL **ImageDevicePath, + OUT EFI_HANDLE *ImageHandle + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL **LegacyDevicePaths; + CHAR16 *UnicodeDevicePath; + UINTN Index; // // Get list of possible locations for Apple legacy interface and attempt to load. @@ -246,9 +246,11 @@ InternalLoadAppleLegacyInterface ( ImageHandle ); if (Status != EFI_NOT_FOUND) { + *ImageDevicePath = LegacyDevicePaths[Index]; + DEBUG_CODE_BEGIN (); - UnicodeDevicePath = ConvertDevicePathToText (LegacyDevicePaths[Index], FALSE, FALSE); + UnicodeDevicePath = ConvertDevicePathToText (*ImageDevicePath, FALSE, FALSE); DEBUG (( DEBUG_INFO, "OLB: Loaded Apple legacy interface at dp %s - %r\n", diff --git a/Platform/OpenLegacyBoot/OpenLegacyBoot.c b/Platform/OpenLegacyBoot/OpenLegacyBoot.c index 49bbef4c99c..405ffff80cd 100644 --- a/Platform/OpenLegacyBoot/OpenLegacyBoot.c +++ b/Platform/OpenLegacyBoot/OpenLegacyBoot.c @@ -12,6 +12,20 @@ STATIC EFI_HANDLE mImageHandle; STATIC BOOLEAN mIsAppleInterfaceSupported; +// +// Fallback PIWG firmware media device path for Apple legacy interface. +// MemoryMapped(0xB,0xFFE00000,0xFFF9FFFF)/FvFile(2B0585EB-D8B8-49A9-8B8C-E21B01AEF2B7) +// +STATIC CONST UINT8 AppleLegacyInterfaceFallbackDevicePathData[] = { + 0x01, 0x03, 0x18, 0x00, 0x0B, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xE0, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xF9, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x06, 0x14, 0x00, 0xEB, 0x85, 0x05, 0x2B, + 0xB8, 0xD8, 0xA9, 0x49, 0x8B, 0x8C, 0xE2, 0x1B, + 0x01, 0xAE, 0xF2, 0xB7, 0x7F, 0xFF, 0x04, 0x00 +}; +STATIC CONST EFI_DEVICE_PATH_PROTOCOL *AppleLegacyInterfaceFallbackDevicePathPath = (EFI_DEVICE_PATH_PROTOCOL *)AppleLegacyInterfaceFallbackDevicePathData; + STATIC CHAR8 * GetLegacyEntryName ( @@ -65,10 +79,22 @@ ExternalSystemActionDoLegacyBoot ( EFI_STATUS Status; EFI_HANDLE DiskHandle; EFI_HANDLE LoadedImageHandle; + EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath; EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; BOOLEAN IsExternal; CONST CHAR8 *AppleBootArg; + // + // Set BootCampHD to desired disk Device Path for non-CD devices. + // + if (!OcIsDiskCdRom (DevicePath)) { + Status = InternalSetBootCampHDPath (DevicePath); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "OLB: Failure while setting BootCampHD variable - %r\n", Status)); + return Status; + } + } + // // Load and start legacy OS. // @@ -84,7 +110,7 @@ ExternalSystemActionDoLegacyBoot ( Status = InternalLoadAppleLegacyInterface ( mImageHandle, - DevicePath, + &LoadedImageDevicePath, &LoadedImageHandle ); if (EFI_ERROR (Status)) { @@ -144,6 +170,62 @@ ExternalSystemActionDoLegacyBoot ( return EFI_SUCCESS; } +STATIC +EFI_STATUS +ExternalSystemGetDevicePath ( + IN OUT OC_PICKER_CONTEXT *PickerContext, + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath + ) +{ + EFI_STATUS Status; + EFI_HANDLE LoadedImageHandle; + EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath; + EFI_DEVICE_PATH_PROTOCOL *AppleLoaderDevicePath; + + // + // Set BootCampHD to desired disk Device Path for non-CD devices. + // + if (!OcIsDiskCdRom (*DevicePath)) { + Status = InternalSetBootCampHDPath (*DevicePath); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "OLB: Failure while setting BootCampHD variable - %r\n", Status)); + return Status; + } + } + + // + // Locate Apple legacy interface loader. + // + // On Macs, use the Apple legacy interface and set BootCampHD. + // On other systems, use a default placeholder path. + // + DebugPrintDevicePath (DEBUG_INFO, "OLB: Legacy device path", *DevicePath); + if (mIsAppleInterfaceSupported) { + Status = InternalLoadAppleLegacyInterface ( + mImageHandle, + &LoadedImageDevicePath, + &LoadedImageHandle + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "OLB: Failure while loading Apple legacy interface - %r\n", Status)); + return Status; + } + + gBS->UnloadImage (LoadedImageHandle); + + AppleLoaderDevicePath = DuplicateDevicePath (LoadedImageDevicePath); + } else { + AppleLoaderDevicePath = DuplicateDevicePath (AppleLegacyInterfaceFallbackDevicePathPath); + } + + if (AppleLoaderDevicePath == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + *DevicePath = AppleLoaderDevicePath; + return EFI_SUCCESS; +} + STATIC EFI_STATUS EFIAPI @@ -263,17 +345,18 @@ OcGetLegacyBootEntries ( return Status; } - PickerEntry->Id = AsciiDevicePath; - PickerEntry->Name = GetLegacyEntryName (LegacyOsType); - PickerEntry->Path = NULL; - PickerEntry->Arguments = NULL; - PickerEntry->Flavour = GetLegacyEntryFlavour (LegacyOsType); - PickerEntry->Tool = FALSE; - PickerEntry->TextMode = FALSE; - PickerEntry->RealPath = FALSE; - PickerEntry->External = IsExternal; - PickerEntry->ExternalSystemAction = ExternalSystemActionDoLegacyBoot; - PickerEntry->ExternalSystemDevicePath = BlockDevicePath; + PickerEntry->Id = AsciiDevicePath; + PickerEntry->Name = GetLegacyEntryName (LegacyOsType); + PickerEntry->Path = NULL; + PickerEntry->Arguments = NULL; + PickerEntry->Flavour = GetLegacyEntryFlavour (LegacyOsType); + PickerEntry->Tool = FALSE; + PickerEntry->TextMode = FALSE; + PickerEntry->RealPath = FALSE; + PickerEntry->External = IsExternal; + PickerEntry->ExternalSystemAction = ExternalSystemActionDoLegacyBoot; + PickerEntry->ExternalSystemGetDevicePath = ExternalSystemGetDevicePath; + PickerEntry->ExternalSystemDevicePath = BlockDevicePath; if ((PickerEntry->Name == NULL) || (PickerEntry->Flavour == NULL)) { OcFlexArrayFree (&FlexPickerEntries); From ec656dbb8fad5f6d2d01053ea3713f62bcc720a1 Mon Sep 17 00:00:00 2001 From: John Davis Date: Sat, 26 Aug 2023 16:56:27 -0500 Subject: [PATCH 49/55] OcBootManagementLib: Fix previous commit --- Library/OcBootManagementLib/DefaultEntryChoice.c | 1 - 1 file changed, 1 deletion(-) diff --git a/Library/OcBootManagementLib/DefaultEntryChoice.c b/Library/OcBootManagementLib/DefaultEntryChoice.c index 95e5ec0862f..94b36c93759 100644 --- a/Library/OcBootManagementLib/DefaultEntryChoice.c +++ b/Library/OcBootManagementLib/DefaultEntryChoice.c @@ -1022,7 +1022,6 @@ OcSetDefaultBootEntry ( } if (ExtSystemDevPath != NULL) { - DebugPrintHexDump (DEBUG_INFO, "hex", (UINT8 *)ExtSystemDevPath, DevicePathSize); CopyMem ((UINT8 *)(LoadOption + 1) + LoadOptionNameSize, ExtSystemDevPath, DevicePathSize); } else if (!Entry->IsCustom) { CopyMem ((UINT8 *)(LoadOption + 1) + LoadOptionNameSize, Entry->DevicePath, DevicePathSize); From 48b3beb0c8c057743e9983f685b5b1c97d7d9140 Mon Sep 17 00:00:00 2001 From: John Davis Date: Sat, 26 Aug 2023 17:00:34 -0500 Subject: [PATCH 50/55] OpenDuet: Use PcdTurnOffUsbLegacySupport PCD instead USB emulation mode should only be disabled for regular OpenDuet build, and not BlockIoDxe one. --- Library/DuetBdsLib/BdsPlatform.c | 125 ------------------------------- OpenDuetPkg.dsc | 1 + 2 files changed, 1 insertion(+), 125 deletions(-) diff --git a/Library/DuetBdsLib/BdsPlatform.c b/Library/DuetBdsLib/BdsPlatform.c index 8a14fcffce0..8d6f5a61ed1 100644 --- a/Library/DuetBdsLib/BdsPlatform.c +++ b/Library/DuetBdsLib/BdsPlatform.c @@ -519,123 +519,6 @@ UpdateMemoryMap ( } } -STATIC -EFI_STATUS -DisableUsbLegacySupport ( - VOID - ) - -/*++ - -Routine Description: - Disable the USB legacy Support in all Ehci and Uhci. - This function assume all PciIo handles have been created in system. - -Arguments: - None - -Returns: - EFI_SUCCESS - EFI_NOT_FOUND ---*/ -{ - EFI_STATUS Status; - EFI_HANDLE *HandleArray; - UINTN HandleArrayCount; - UINTN Index; - EFI_PCI_IO_PROTOCOL *PciIo; - UINT8 Class[3]; - UINT16 Command; - UINT32 HcCapParams; - UINT32 ExtendCap; - UINT32 Value; - UINT32 TimeOut; - - // - // Find the usb host controller - // - Status = gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiPciIoProtocolGuid, - NULL, - &HandleArrayCount, - &HandleArray - ); - if (!EFI_ERROR (Status)) { - for (Index = 0; Index < HandleArrayCount; Index++) { - Status = gBS->HandleProtocol ( - HandleArray[Index], - &gEfiPciIoProtocolGuid, - (VOID **)&PciIo - ); - if (!EFI_ERROR (Status)) { - // - // Find the USB host controller controller - // - Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Class); - if (!EFI_ERROR (Status)) { - if ((PCI_CLASS_SERIAL == Class[2]) && - (PCI_CLASS_SERIAL_USB == Class[1])) - { - if (PCI_IF_UHCI == Class[0]) { - // - // Found the UHCI, then disable the legacy support - // - Command = 0; - Status = PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0xC0, 1, &Command); - } else if (PCI_IF_EHCI == Class[0]) { - // - // Found the EHCI, then disable the legacy support - // - Status = PciIo->Mem.Read ( - PciIo, - EfiPciIoWidthUint32, - 0, ///< EHC_BAR_INDEX - (UINT64)0x08, ///< EHC_HCCPARAMS_OFFSET - 1, - &HcCapParams - ); - - ExtendCap = (HcCapParams >> 8) & 0xFF; - // - // Disable the SMI in USBLEGCTLSTS firstly - // Not doing this may result in a hardlock soon after - // - PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap + 0x4, 1, &Value); - Value &= 0xFFFF0000; - PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, ExtendCap + 0x4, 1, &Value); - - // - // Get EHCI Ownership from legacy bios - // - PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value); - Value |= (0x1 << 24); - PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value); - - TimeOut = 40; - while (TimeOut--) { - gBS->Stall (500); - - PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value); - - if ((Value & 0x01010000) == 0x01000000) { - break; - } - } - } - } - } - } - } - - gBS->FreePool (HandleArray); - } else { - return Status; - } - - return EFI_SUCCESS; -} - STATIC EFI_STATUS ConnectRootBridge ( @@ -1091,14 +974,6 @@ Routine Description: DetectAndPreparePlatformPciDevicePath (TRUE); } - // - // The ConIn devices connection will start the USB bus, should disable all - // Usb legacy support firstly. - // Caution: Must ensure the PCI bus driver has been started. Since the - // ConnectRootBridge() will create all the PciIo protocol, it's safe here now - // - DisableUsbLegacySupport (); - // // Connect the all the default console with current console variable // diff --git a/OpenDuetPkg.dsc b/OpenDuetPkg.dsc index b7af0e37624..2d749013fca 100644 --- a/OpenDuetPkg.dsc +++ b/OpenDuetPkg.dsc @@ -245,6 +245,7 @@ gEfiMdeModulePkgTokenSpaceGuid.PcdConOutUgaSupport|FALSE gEfiMdeModulePkgTokenSpaceGuid.PcdDevicePathSupportDevicePathFromText|FALSE gEfiMdeModulePkgTokenSpaceGuid.PcdDevicePathSupportDevicePathToText|FALSE + gEfiMdeModulePkgTokenSpaceGuid.PcdTurnOffUsbLegacySupport|TRUE gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport|FALSE [PcdsFixedAtBuild] From aca03849fe146b0bbb056e38f7337a41d1c319af Mon Sep 17 00:00:00 2001 From: John Davis Date: Sat, 26 Aug 2023 19:46:53 -0500 Subject: [PATCH 51/55] OcBootManagementLib: Allow external boot system entries to use custom icons --- Library/OcBootManagementLib/BootEntryInfo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Library/OcBootManagementLib/BootEntryInfo.c b/Library/OcBootManagementLib/BootEntryInfo.c index 0f2b937fd55..b150ea334bb 100644 --- a/Library/OcBootManagementLib/BootEntryInfo.c +++ b/Library/OcBootManagementLib/BootEntryInfo.c @@ -597,7 +597,7 @@ OcGetBootEntryFile ( IN BOOLEAN SearchAtRoot ) { - if ((BootEntry->Type & (OC_BOOT_EXTERNAL_TOOL | OC_BOOT_SYSTEM | OC_BOOT_EXTERNAL_SYSTEM)) != 0) { + if ((BootEntry->Type & (OC_BOOT_EXTERNAL_TOOL | OC_BOOT_SYSTEM)) != 0) { return EFI_NOT_FOUND; } From e8c9724f3a85a26f707c55f44d7baa4b4adf9402 Mon Sep 17 00:00:00 2001 From: John Davis Date: Sat, 26 Aug 2023 19:47:22 -0500 Subject: [PATCH 52/55] OpenCanopy: Fix labels for external boot system entries --- Platform/OpenCanopy/Views/BootPicker.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Platform/OpenCanopy/Views/BootPicker.c b/Platform/OpenCanopy/Views/BootPicker.c index 88b507dae8a..48a8cefe412 100644 --- a/Platform/OpenCanopy/Views/BootPicker.c +++ b/Platform/OpenCanopy/Views/BootPicker.c @@ -1453,6 +1453,14 @@ BootPickerEntriesSet ( Status = EFI_UNSUPPORTED; } + break; + case OC_BOOT_EXTERNAL_SYSTEM: + if (OcAsciiStriStr (Entry->Flavour, OC_FLAVOUR_WINDOWS) != NULL) { + Status = CopyLabel (&VolumeEntry->Label, &GuiContext->Labels[LABEL_WINDOWS]); + } else { + Status = CopyLabel (&VolumeEntry->Label, &GuiContext->Labels[LABEL_OTHER]); + } + break; case OC_BOOT_UNKNOWN: Status = CopyLabel (&VolumeEntry->Label, &GuiContext->Labels[LABEL_GENERIC_HDD]); From 608a01ee55e349d886d12ab11b5b28721cce2c68 Mon Sep 17 00:00:00 2001 From: John Davis Date: Sat, 26 Aug 2023 19:47:52 -0500 Subject: [PATCH 53/55] OpenLegacyBoot: Implement custom entry names from .contentDetails --- Platform/OpenLegacyBoot/OpenLegacyBoot.c | 43 +++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/Platform/OpenLegacyBoot/OpenLegacyBoot.c b/Platform/OpenLegacyBoot/OpenLegacyBoot.c index 405ffff80cd..e45554a9cd9 100644 --- a/Platform/OpenLegacyBoot/OpenLegacyBoot.c +++ b/Platform/OpenLegacyBoot/OpenLegacyBoot.c @@ -44,6 +44,43 @@ GetLegacyEntryFlavour ( return AllocateCopyPool (L_STR_SIZE (OC_FLAVOUR_WINDOWS), OC_FLAVOUR_WINDOWS); } +STATIC +CHAR8 * +LoadAppleDiskLabel ( + IN OUT OC_PICKER_CONTEXT *PickerContext, + IN EFI_HANDLE DiskHandle + ) +{ + EFI_STATUS Status; + CHAR8 *DiskLabel; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem; + + DiskLabel = NULL; + if ((PickerContext->PickerAttributes & OC_ATTR_USE_DISK_LABEL_FILE) != 0) { + Status = gBS->HandleProtocol ( + DiskHandle, + &gEfiSimpleFileSystemProtocolGuid, + (VOID **)&FileSystem + ); + if (EFI_ERROR (Status)) { + return NULL; + } + + DiskLabel = OcReadFile (FileSystem, L".contentDetails", NULL, 0); + if (DiskLabel == NULL) { + DiskLabel = OcReadFile (FileSystem, L".disk_label.contentDetails", NULL, 0); + } + + if (DiskLabel == NULL) { + DEBUG ((DEBUG_INFO, "OLB: %s %s not present\n", L".contentDetails", L".disk_label.contentDetails")); + } else { + DEBUG ((DEBUG_INFO, "OLB: Found disk label '%a'\n", DiskLabel)); + } + } + + return DiskLabel; +} + STATIC VOID FreePickerEntry ( @@ -345,8 +382,12 @@ OcGetLegacyBootEntries ( return Status; } + PickerEntry->Name = LoadAppleDiskLabel (PickerContext, BlockDeviceHandle); + if (PickerEntry->Name == NULL) { + PickerEntry->Name = GetLegacyEntryName (LegacyOsType); + } + PickerEntry->Id = AsciiDevicePath; - PickerEntry->Name = GetLegacyEntryName (LegacyOsType); PickerEntry->Path = NULL; PickerEntry->Arguments = NULL; PickerEntry->Flavour = GetLegacyEntryFlavour (LegacyOsType); From 7e8555acdb9f23b4cac4929bc43ee91cd54d38c8 Mon Sep 17 00:00:00 2001 From: John Davis Date: Sat, 26 Aug 2023 22:36:27 -0500 Subject: [PATCH 54/55] OpenLegacyBoot: Add --hide-devices option --- Platform/OpenLegacyBoot/OpenLegacyBoot.c | 89 +++++++++++++++++++----- 1 file changed, 73 insertions(+), 16 deletions(-) diff --git a/Platform/OpenLegacyBoot/OpenLegacyBoot.c b/Platform/OpenLegacyBoot/OpenLegacyBoot.c index e45554a9cd9..1a157a2f2e2 100644 --- a/Platform/OpenLegacyBoot/OpenLegacyBoot.c +++ b/Platform/OpenLegacyBoot/OpenLegacyBoot.c @@ -12,6 +12,8 @@ STATIC EFI_HANDLE mImageHandle; STATIC BOOLEAN mIsAppleInterfaceSupported; +STATIC OC_FLEX_ARRAY *mHiddenDevicePaths; + // // Fallback PIWG firmware media device path for Apple legacy interface. // MemoryMapped(0xB,0xFFE00000,0xFFF9FFFF)/FvFile(2B0585EB-D8B8-49A9-8B8C-E21B01AEF2B7) @@ -277,12 +279,15 @@ OcGetLegacyBootEntries ( UINTN NoHandles; EFI_HANDLE *Handles; UINTN HandleIndex; + UINTN DevicePathIndex; + BOOLEAN SkipHiddenDevice; UINT32 ScanPolicy; BOOLEAN IsExternal; CHAR16 *UnicodeDevicePath; CHAR8 *AsciiDevicePath; UINTN AsciiDevicePathSize; + CHAR16 **HiddenUnicodeDevicePath; EFI_HANDLE BlockDeviceHandle; EFI_DEVICE_PATH_PROTOCOL *BlockDevicePath; @@ -334,14 +339,6 @@ OcGetLegacyBootEntries ( continue; } - // - // Detect legacy OS type. - // - LegacyOsType = InternalGetPartitionLegacyOsType (BlockDeviceHandle, mIsAppleInterfaceSupported); - if (LegacyOsType == OcLegacyOsTypeNone) { - continue; - } - BlockDevicePath = DevicePathFromHandle (BlockDeviceHandle); if (BlockDevicePath == NULL) { DEBUG ((DEBUG_INFO, "OLB: Could not find Device Path for block device\n")); @@ -349,19 +346,51 @@ OcGetLegacyBootEntries ( } // - // Create and add picker entry to entries. + // Device Path will be used as ID and is required for default entry matching. // - PickerEntry = OcFlexArrayAddItem (FlexPickerEntries); - if (PickerEntry == NULL) { + UnicodeDevicePath = ConvertDevicePathToText (BlockDevicePath, FALSE, FALSE); + if (UnicodeDevicePath == NULL) { OcFlexArrayFree (&FlexPickerEntries); return EFI_OUT_OF_RESOURCES; } // - // Device Path will be used as ID and is required for default entry matching. + // Skip device if on hidden list. // - UnicodeDevicePath = ConvertDevicePathToText (BlockDevicePath, FALSE, FALSE); - if (UnicodeDevicePath == NULL) { + if (mHiddenDevicePaths != NULL) { + SkipHiddenDevice = FALSE; + for (DevicePathIndex = 0; DevicePathIndex < mHiddenDevicePaths->Count; DevicePathIndex++) { + HiddenUnicodeDevicePath = (CHAR16 **)OcFlexArrayItemAt (mHiddenDevicePaths, DevicePathIndex); + ASSERT (HiddenUnicodeDevicePath != NULL); + + if (StrCmp (UnicodeDevicePath, *HiddenUnicodeDevicePath) == 0) { + DEBUG ((DEBUG_INFO, "OLB: Skipping hidden device %s\n", *HiddenUnicodeDevicePath)); + SkipHiddenDevice = TRUE; + break; + } + } + + if (SkipHiddenDevice) { + FreePool (UnicodeDevicePath); + continue; + } + } + + // + // Detect legacy OS type. + // + LegacyOsType = InternalGetPartitionLegacyOsType (BlockDeviceHandle, mIsAppleInterfaceSupported); + if (LegacyOsType == OcLegacyOsTypeNone) { + FreePool (UnicodeDevicePath); + continue; + } + + // + // Create and add picker entry to entries. + // + PickerEntry = OcFlexArrayAddItem (FlexPickerEntries); + if (PickerEntry == NULL) { + FreePool (UnicodeDevicePath); OcFlexArrayFree (&FlexPickerEntries); return EFI_OUT_OF_RESOURCES; } @@ -450,9 +479,37 @@ UefiMain ( IN EFI_SYSTEM_TABLE *SystemTable ) { - EFI_STATUS Status; + EFI_STATUS Status; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + CHAR16 *DevicePathNames; + OC_FLEX_ARRAY *ParsedLoadOptions; + + Status = gBS->HandleProtocol ( + ImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **)&LoadedImage + ); + if (EFI_ERROR (Status)) { + return Status; + } - mImageHandle = ImageHandle; + mImageHandle = ImageHandle; + mHiddenDevicePaths = NULL; + + Status = OcParseLoadOptions (LoadedImage, &ParsedLoadOptions); + if (!EFI_ERROR (Status)) { + OcParsedVarsGetUnicodeStr (ParsedLoadOptions, L"--hide-devices", &DevicePathNames); + if (DevicePathNames != NULL) { + mHiddenDevicePaths = OcStringSplit (DevicePathNames, L';', OcStringFormatUnicode); + if (mHiddenDevicePaths == NULL) { + return EFI_OUT_OF_RESOURCES; + } + } + } else { + if (Status != EFI_NOT_FOUND) { + return Status; + } + } Status = InternalIsLegacyInterfaceSupported (&mIsAppleInterfaceSupported); if (EFI_ERROR (Status)) { From f9a6965f4e88662bc419532b1cb4fad335162a0a Mon Sep 17 00:00:00 2001 From: John Davis Date: Mon, 4 Sep 2023 18:47:39 -0500 Subject: [PATCH 55/55] OcFileLib: Use ReadUnaligned32 for MBR table checks --- Library/OcFileLib/DiskMisc.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Library/OcFileLib/DiskMisc.c b/Library/OcFileLib/DiskMisc.c index 0c4eb67c75d..ca4407a5133 100644 --- a/Library/OcFileLib/DiskMisc.c +++ b/Library/OcFileLib/DiskMisc.c @@ -881,12 +881,14 @@ OcGetDiskMbrTable ( if (CheckPartitions) { if ( (Mbr->Partition[0].OSIndicator == PMBR_GPT_PARTITION) - && (*((UINT32 *)Mbr->Partition[0].StartingLBA) == 0x01) - && (*((UINT32 *)Mbr->Partition[0].SizeInLBA) != 0)) + && (ReadUnaligned32 ((UINT32 *)Mbr->Partition[0].StartingLBA) == 0x01) + && (ReadUnaligned32 ((UINT32 *)Mbr->Partition[0].SizeInLBA) != 0)) { IsProtectiveMbr = TRUE; for (Index = 1; Index < MAX_MBR_PARTITIONS; Index++) { - if ((*((UINT32 *)Mbr->Partition[Index].StartingLBA) != 0) || (*((UINT32 *)Mbr->Partition[Index].SizeInLBA) != 0)) { + if ( (ReadUnaligned32 ((UINT32 *)Mbr->Partition[Index].StartingLBA) != 0) + || (ReadUnaligned32 ((UINT32 *)Mbr->Partition[Index].SizeInLBA) != 0)) + { IsProtectiveMbr = FALSE; break; } @@ -958,8 +960,8 @@ OcDiskGetMbrPartitionIndex ( Status = EFI_NOT_FOUND; for (Index = 0; Index < MAX_MBR_PARTITIONS; Index++) { - if ( (*((UINT32 *)Mbr->Partition[Index].StartingLBA) == HdNode->PartitionStart) - && (*((UINT32 *)Mbr->Partition[Index].SizeInLBA) == HdNode->PartitionSize)) + if ( (ReadUnaligned32 ((UINT32 *)Mbr->Partition[Index].StartingLBA) == HdNode->PartitionStart) + && (ReadUnaligned32 ((UINT32 *)Mbr->Partition[Index].SizeInLBA) == HdNode->PartitionSize)) { *PartitionIndex = Index; Status = EFI_SUCCESS;