From c8545a25643d514cb81722bdf513c738c2e42e27 Mon Sep 17 00:00:00 2001 From: vit9696 Date: Tue, 18 Jun 2019 11:20:27 +0300 Subject: [PATCH] OcBootManagementLib: Rework filesystem scan policy --- Include/Library/OcBootManagementLib.h | 37 +++++- Include/Library/OcFileLib.h | 6 +- .../BootManagementInternal.h | 3 +- .../OcBootManagementLib/OcBootManagementLib.c | 6 +- .../OcBootManagementLib.inf | 4 + .../OcBootManagementLib/PolicyManagement.c | 113 ++++++++---------- 6 files changed, 98 insertions(+), 71 deletions(-) diff --git a/Include/Library/OcBootManagementLib.h b/Include/Library/OcBootManagementLib.h index 8c0afb9e..bce3fb2a 100755 --- a/Include/Library/OcBootManagementLib.h +++ b/Include/Library/OcBootManagementLib.h @@ -91,6 +91,11 @@ typedef struct OC_BOOT_ENTRY_ { **/ #define OC_SCAN_ALLOW_FS_HFS BIT9 +/** + Allow scanning ESP filesystems. +**/ +#define OC_SCAN_ALLOW_FS_ESP BIT10 + /** Allow scanning SATA devices. **/ @@ -144,7 +149,7 @@ typedef struct OC_BOOT_ENTRY_ { All device bits used by OC_SCAN_DEVICE_LOCK. **/ #define OC_SCAN_FILE_SYSTEM_BITS ( \ - OC_SCAN_ALLOW_FS_APFS | OC_SCAN_ALLOW_FS_HFS) + OC_SCAN_ALLOW_FS_APFS | OC_SCAN_ALLOW_FS_HFS | OC_SCAN_ALLOW_FS_ESP) /** By default allow booting from APFS from internal drives. @@ -356,7 +361,6 @@ OcFreeBootEntries ( @param[in] BootPolicy Apple Boot Policy Protocol. @param[in] Policy Scan policy. @param[in] Handle Device handle (with EfiSimpleFileSystem protocol). - @param[in] SimpleFs Simple file system protocol of the device handle. @param[out] BootEntry Resulting boot entry. @param[out] AlternateBootEntry Resulting alternate boot entry (e.g. recovery). @param[in] IsLoadHandle OpenCore load handle, try skipping OC entry. @@ -370,7 +374,6 @@ OcFillBootEntry ( IN APPLE_BOOT_POLICY_PROTOCOL *BootPolicy, IN UINT32 Policy, IN EFI_HANDLE Handle, - IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFs, OUT OC_BOOT_ENTRY *BootEntry, OUT OC_BOOT_ENTRY *AlternateBootEntry OPTIONAL, IN BOOLEAN IsLoadHandle @@ -446,7 +449,7 @@ OcLoadBootEntry ( @retval EFI_SUCCESS Hibernation mode was found and activated. **/ EFI_STATUS -ActivateHibernateWake ( +OcActivateHibernateWake ( IN UINT32 HibernateMask ); @@ -462,4 +465,30 @@ OcRunSimpleBootPicker ( IN OC_PICKER_CONTEXT *Context ); +/** + Get device scan policy type. + + @param[in] Handle Device/partition handle. + @param[out] External Check whether device is external. + + @retval required policy or 0 on mismatch. +**/ +UINT32 +OcGetDevicePolicyType ( + IN EFI_HANDLE Handle, + OUT BOOLEAN *External OPTIONAL + ); + +/** + Get file system scan policy type. + + @param[in] Handle Partition handle. + + @retval required policy or 0 on mismatch. +**/ +UINT32 +OcGetFileSystemPolicyType ( + IN EFI_HANDLE Handle + ); + #endif // OC_BOOT_MANAGEMENT_LIB_H diff --git a/Include/Library/OcFileLib.h b/Include/Library/OcFileLib.h index 6f71403f..e55b23f4 100755 --- a/Include/Library/OcFileLib.h +++ b/Include/Library/OcFileLib.h @@ -238,6 +238,7 @@ OcOpenFileByDevicePath ( @param[in] HdDevicePath The Device Path of the partition. + @retval device handle or NULL **/ EFI_HANDLE OcPartitionGetDiskHandle ( @@ -249,6 +250,7 @@ OcPartitionGetDiskHandle ( @param[in] DiskDevicePath The Device Path of the disk to scan. + @retval device path or NULL **/ EFI_DEVICE_PATH_PROTOCOL * OcDiskFindSystemPartitionPath ( @@ -256,10 +258,12 @@ OcDiskFindSystemPartitionPath ( ); /** - Retrieve the partition's GPT information, if applicable + Retrieve the partition's GPT information, if applicable. + Calls to this function undergo internal lazy caching. @param[in] FsHandle The device handle of the partition to retrieve info of. + @retval partition entry or NULL **/ CONST EFI_PARTITION_ENTRY * OcGetGptPartitionEntry ( diff --git a/Library/OcBootManagementLib/BootManagementInternal.h b/Library/OcBootManagementLib/BootManagementInternal.h index fff9d088..28ccdd1d 100644 --- a/Library/OcBootManagementLib/BootManagementInternal.h +++ b/Library/OcBootManagementLib/BootManagementInternal.h @@ -30,10 +30,9 @@ typedef struct { EFI_HANDLE BlockIoHandle; } INTERNAL_DMG_LOAD_CONTEXT; -EFI_STATUS +RETURN_STATUS InternalCheckScanPolicy ( IN EFI_HANDLE Handle, - IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFs, IN UINT32 Policy, OUT BOOLEAN *External OPTIONAL ); diff --git a/Library/OcBootManagementLib/OcBootManagementLib.c b/Library/OcBootManagementLib/OcBootManagementLib.c index 11ff9812..12b2845b 100644 --- a/Library/OcBootManagementLib/OcBootManagementLib.c +++ b/Library/OcBootManagementLib/OcBootManagementLib.c @@ -297,7 +297,6 @@ OcFillBootEntry ( IN APPLE_BOOT_POLICY_PROTOCOL *BootPolicy, IN UINT32 Policy, IN EFI_HANDLE Handle, - IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFs, OUT OC_BOOT_ENTRY *BootEntry, OUT OC_BOOT_ENTRY *AlternateBootEntry OPTIONAL, IN BOOLEAN IsLoadHandle @@ -313,7 +312,7 @@ OcFillBootEntry ( Count = 0; - Status = InternalCheckScanPolicy (Handle, SimpleFs, Policy, &BootEntry->IsExternal); + Status = InternalCheckScanPolicy (Handle, Policy, &BootEntry->IsExternal); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_INFO, "OCB: Skipping handle %p due to scan policy %x\n", Handle, Policy)); return 0; @@ -448,7 +447,6 @@ OcScanForBootEntries ( BootPolicy, Context->ScanPolicy, Handles[Index], - SimpleFs, &Entries[EntryIndex], &Entries[EntryIndex+1], Context->ExcludeHandle == Handles[Index] @@ -536,7 +534,7 @@ OcScanForBootEntries ( } EFI_STATUS -ActivateHibernateWake ( +OcActivateHibernateWake ( IN UINT32 HibernateMask ) { diff --git a/Library/OcBootManagementLib/OcBootManagementLib.inf b/Library/OcBootManagementLib/OcBootManagementLib.inf index 94ba17cf..4fa42494 100644 --- a/Library/OcBootManagementLib/OcBootManagementLib.inf +++ b/Library/OcBootManagementLib/OcBootManagementLib.inf @@ -51,7 +51,11 @@ gAppleBlessedOsxFolderInfoGuid ## SOMETIMES_CONSUMES gEfiFileInfoGuid ## SOMETIMES_CONSUMES gEfiGlobalVariableGuid ## SOMETIMES_CONSUMES + gEfiPartTypeSystemPartGuid ## SOMETIMES_CONSUMES + gAppleApfsPartitionTypeGuid ## SOMETIMES_CONSUMES gAppleBootVariableGuid ## SOMETIMES_CONSUMES + gAppleHfsPartitionTypeGuid ## SOMETIMES_CONSUMES + gAppleHfsBootPartitionTypeGuid ## SOMETIMES_CONSUMES gAppleLegacyLoadAppFileGuid ## SOMETIMES_CONSUMES [Protocols] diff --git a/Library/OcBootManagementLib/PolicyManagement.c b/Library/OcBootManagementLib/PolicyManagement.c index adefed4b..c50a0413 100644 --- a/Library/OcBootManagementLib/PolicyManagement.c +++ b/Library/OcBootManagementLib/PolicyManagement.c @@ -16,7 +16,9 @@ #include #include +#include #include +#include #include #include #include @@ -26,15 +28,17 @@ #include #include +#include +#include #include #include +#include #include #include #include -STATIC UINT32 -InternalGetRequestedPolicyType ( +OcGetDevicePolicyType ( IN EFI_HANDLE Handle, OUT BOOLEAN *External OPTIONAL ) @@ -106,77 +110,66 @@ InternalGetRequestedPolicyType ( return 0; } -EFI_STATUS +UINT32 +OcGetFileSystemPolicyType ( + IN EFI_HANDLE Handle + ) +{ + CONST EFI_PARTITION_ENTRY *PartitionEntry; + + PartitionEntry = OcGetGptPartitionEntry (Handle); + + if (PartitionEntry == NULL) { + DEBUG ((DEBUG_INFO, "OCB: missing partition info for %p\n", Handle)); + return 0; + } + + if (CompareGuid (&PartitionEntry->PartitionTypeGUID, &gAppleApfsPartitionTypeGuid)) { + return OC_SCAN_ALLOW_FS_APFS; + } + + if (CompareGuid (&PartitionEntry->PartitionTypeGUID, &gEfiPartTypeSystemPartGuid)) { + return OC_SCAN_ALLOW_FS_ESP; + } + + // + // Unsure whether these two should be separate, likely not. + // + if (CompareGuid (&PartitionEntry->PartitionTypeGUID, &gAppleHfsPartitionTypeGuid) + || CompareGuid (&PartitionEntry->PartitionTypeGUID, &gAppleHfsBootPartitionTypeGuid)) { + return OC_SCAN_ALLOW_FS_HFS; + } + + return 0; +} + +RETURN_STATUS InternalCheckScanPolicy ( IN EFI_HANDLE Handle, - IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFs, IN UINT32 Policy, OUT BOOLEAN *External OPTIONAL ) { - EFI_STATUS Status; - EFI_FILE_PROTOCOL *Root; - UINTN BufferSize; - UINT32 RequestedPolicy; + UINT32 DevicePolicy; + UINT32 FileSystemPolicy; - RequestedPolicy = InternalGetRequestedPolicyType (Handle, External); - if ((Policy & OC_SCAN_DEVICE_LOCK) != 0 && (Policy & RequestedPolicy) == 0) { + // + // Always request policy type due to external checks. + // + DevicePolicy = OcGetDevicePolicyType (Handle, External); + if ((Policy & OC_SCAN_DEVICE_LOCK) != 0 && (Policy & DevicePolicy) == 0) { + DEBUG ((DEBUG_INFO, "OCB: invalid device policy (%u/%u) for %p\n", DevicePolicy, Policy, Handle)); return EFI_SECURITY_VIOLATION; } - Status = EFI_SUCCESS; - if ((Policy & OC_SCAN_FILE_SYSTEM_LOCK) != 0) { - Status = SimpleFs->OpenVolume (SimpleFs, &Root); + FileSystemPolicy = OcGetFileSystemPolicyType (Handle); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = EFI_SECURITY_VIOLATION; - - // - // FIXME: We cannot use EfiPartitionInfo protocol, as it is not - // widely available, and when it is, it is not guaranteed to be spec compliant. - // For this reason we would really like to implement ApplePartitionInfo protocol, - // but currently it is not a priority. - // - if ((Policy & OC_SCAN_ALLOW_FS_APFS) != 0 && EFI_ERROR (Status)) { - BufferSize = 0; - Status = Root->GetInfo (Root, &gAppleApfsVolumeInfoGuid, &BufferSize, NULL); - if (Status == EFI_BUFFER_TOO_SMALL) { - Status = EFI_SUCCESS; - } - } - - // - // FIXME: This is even worse but works for testing the concept purposes. - // Current logic is blessed but not APFS. - // - if ((Policy & OC_SCAN_ALLOW_FS_HFS) != 0 && EFI_ERROR (Status)) { - BufferSize = 0; - Status = Root->GetInfo (Root, &gAppleApfsVolumeInfoGuid, &BufferSize, NULL); - if (Status != EFI_BUFFER_TOO_SMALL) { - BufferSize = 0; - Status = Root->GetInfo (Root, &gAppleBlessedSystemFileInfoGuid, &BufferSize, NULL); - if (Status == EFI_BUFFER_TOO_SMALL) { - Status = EFI_SUCCESS; - } else { - BufferSize = 0; - Status = Root->GetInfo (Root, &gAppleBlessedSystemFolderInfoGuid, &BufferSize, NULL); - if (Status == EFI_BUFFER_TOO_SMALL) { - Status = EFI_SUCCESS; - } - } - } - } - - Root->Close (Root); - - if (EFI_ERROR (Status)) { - return Status; + if ((Policy & FileSystemPolicy) == 0) { + DEBUG ((DEBUG_INFO, "OCB: invalid file system policy (%u/%u) for %p\n", FileSystemPolicy, Policy, Handle)); + return EFI_SECURITY_VIOLATION; } } - return EFI_SUCCESS; + return RETURN_SUCCESS; }