From eb6b186feec433c54fcc4efcf1e4b2b2ade4b6d8 Mon Sep 17 00:00:00 2001 From: vit9696 Date: Thu, 14 Mar 2019 00:30:00 +0300 Subject: [PATCH] Implement kernel interception code --- Include/Library/OcAppleKernelLib.h | 41 +++ Include/Library/OcFileLib.h | 35 +- Library/OcAppleKernelLib/OcAppleKernelLib.inf | 45 +++ Library/OcAppleKernelLib/ReadAppleKernel.c | 337 ++++++++++++++++++ Library/OcCompressionLib/OcCompressionLib.inf | 2 + Library/OcFileLib/FileProtocol.c | 72 ++++ Library/OcFileLib/OcFileLib.inf | 1 + Library/OcVirtualFsLib/VirtualFile.c | 2 +- OcSupportPkg.dec | 3 + OcSupportPkg.dsc | 2 + STATUS.md | 6 + Tests/KernelTest/KernelTest.c | 63 +++- Tests/KernelTest/KernelTest.inf | 1 + Tests/KernelTest/KernelTestApp.inf | 2 + 14 files changed, 608 insertions(+), 4 deletions(-) create mode 100644 Include/Library/OcAppleKernelLib.h create mode 100644 Library/OcAppleKernelLib/OcAppleKernelLib.inf create mode 100644 Library/OcAppleKernelLib/ReadAppleKernel.c create mode 100644 Library/OcFileLib/FileProtocol.c diff --git a/Include/Library/OcAppleKernelLib.h b/Include/Library/OcAppleKernelLib.h new file mode 100644 index 00000000..c69df864 --- /dev/null +++ b/Include/Library/OcAppleKernelLib.h @@ -0,0 +1,41 @@ +/** @file + Copyright (C) 2019, vit9696. All rights reserved. + + All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#ifndef OC_APPLE_KERNEL_LIB_H +#define OC_APPLE_KERNEL_LIB_H + +#include +#include + +/** + Read Apple kernel for target architecture (possibly decompressing) + into pool allocated buffer. + + @param[in] File File handle instance. + @param[in, out] Kernel Resulting non-fat kernel buffer from pool. + @param[out] KernelSize Actual kernel size. + @param[out] AllocatedSize Allocated kernel size (AllocatedSize >= KernelSize). + + @return EFI_SUCCESS on success. +**/ +EFI_STATUS +ReadAppleKernel ( + IN EFI_FILE_PROTOCOL *File, + IN OUT UINT8 **Kernel, + OUT UINT32 *KernelSize, + OUT UINT32 *AllocatedSize + ); + +#endif // OC_APPLE_KERNEL_LIB_H + diff --git a/Include/Library/OcFileLib.h b/Include/Library/OcFileLib.h index 767e979a..66a1c266 100755 --- a/Include/Library/OcFileLib.h +++ b/Include/Library/OcFileLib.h @@ -50,7 +50,8 @@ GetVolumeLabel ( IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileSystem ); -/** Read file from device path with implicit double (2 byte) null termination. +/** + Read file from device path with implicit double (2 byte) null termination. Null termination does not affect the returned file size. Depending on the implementation 0 byte files may return null. @@ -67,4 +68,36 @@ ReadFile ( OUT UINTN *FileSize OPTIONAL ); +/** + Read exact amount of bytes from EFI_FILE_PROTOCOL at specified position. + + @param[in] File A pointer to the file protocol. + @param[in] Position Position to read data from. + @param[in] Size The size of the data read. + @param[out] Buffer A pointer to previously allocated buffer to read data to. + + @retval EFI_SUCCESS on success. +**/ +EFI_STATUS +ReadFileData ( + IN EFI_FILE_PROTOCOL *File, + IN UINT32 Position, + IN UINT32 Size, + OUT UINT8 *Buffer + ); + +/** + Determine file size if it is less than 4 GB. + + @param[in] File A pointer to the file protocol. + @param[out] Size 32-bit file size. + + @retval EFI_SUCCESS on success. +**/ +EFI_STATUS +ReadFileSize ( + IN EFI_FILE_PROTOCOL *File, + OUT UINT32 *Size + ); + #endif // OC_FILE_LIB_H_ diff --git a/Library/OcAppleKernelLib/OcAppleKernelLib.inf b/Library/OcAppleKernelLib/OcAppleKernelLib.inf new file mode 100644 index 00000000..a5ac45b5 --- /dev/null +++ b/Library/OcAppleKernelLib/OcAppleKernelLib.inf @@ -0,0 +1,45 @@ +## @file +# OcAppleKernelLib +# +# Copyright (c) 2019, vit9696 +# +# 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 = OcAppleKernelLib + FILE_GUID = 9CFA01EA-9A9B-450C-B672-E108CA30DC3F + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = OcAppleKernelLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER SMM_CORE UEFI_APPLICATION UEFI_DRIVER + + +# +# VALID_ARCHITECTURES = X64 +# + +[Sources] + ReadAppleKernel.c + +[Packages] + EfiPkg/EfiPkg.dec + MdePkg/MdePkg.dec + OcSupportPkg/OcSupportPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + MemoryAllocationLib + OcCompressionLib + OcFileLib + OcMachoLib diff --git a/Library/OcAppleKernelLib/ReadAppleKernel.c b/Library/OcAppleKernelLib/ReadAppleKernel.c new file mode 100644 index 00000000..fa228675 --- /dev/null +++ b/Library/OcAppleKernelLib/ReadAppleKernel.c @@ -0,0 +1,337 @@ +/** @file + Copyright (C) 2019, vit9696. All rights reserved. + + All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +// +// Pick a reasonable maximum to fit. +// +#define KERNEL_HEADER_SIZE (EFI_PAGE_SIZE*2) + +STATIC +EFI_STATUS +ReplaceBuffer ( + IN UINT32 TargetSize, + IN OUT UINT8 **Buffer, + OUT UINT32 *AllocatedSize + ) +{ + UINT8 *TmpBuffer; + + if (*AllocatedSize >= TargetSize) { + return EFI_SUCCESS; + } + + TmpBuffer = AllocatePool (TargetSize); + if (TmpBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + FreePool (*Buffer); + *Buffer = TmpBuffer; + *AllocatedSize = TargetSize; + + return EFI_SUCCESS; +} + +STATIC +UINT32 +ParseFatArchitecture ( + IN EFI_FILE_PROTOCOL *File, + IN OUT UINT8 **Buffer, + IN OUT UINT32 *Offset + ) +{ + BOOLEAN SwapBytes; + MACH_FAT_HEADER *FatHeader; + UINT32 NumberOfFatArch; + MACH_CPU_TYPE CpuType; + UINT32 TmpSize; + UINT32 Index; + UINT32 Size; + + FatHeader = (MACH_FAT_HEADER *) *Buffer; + SwapBytes = FatHeader->Signature == MACH_FAT_BINARY_INVERT_SIGNATURE; + NumberOfFatArch = FatHeader->NumberOfFatArch; + if (SwapBytes) { + NumberOfFatArch = SwapBytes32 (NumberOfFatArch); + } + + if (OcOverflowMulAddU32 (NumberOfFatArch, sizeof (MACH_FAT_ARCH), sizeof (MACH_FAT_HEADER), &TmpSize) + || TmpSize > KERNEL_HEADER_SIZE) { + DEBUG ((DEBUG_INFO, "Fat kernel invalid arch count %u\n", NumberOfFatArch)); + return 0; + } + + // + // TODO: Currently there are no kernels with MachCpuSubtypeX8664H, but we should support them. + // + for (Index = 0; Index < NumberOfFatArch; Index++) { + CpuType = FatHeader->FatArch[Index].CpuType; + if (SwapBytes) { + CpuType = SwapBytes32 (CpuType); + } + if (CpuType == MachCpuTypeX8664) { + *Offset = FatHeader->FatArch[Index].Offset; + Size = FatHeader->FatArch[Index].Size; + if (SwapBytes) { + *Offset = SwapBytes32 (*Offset); + Size = SwapBytes32 (Size); + } + + if (*Offset == 0) { + DEBUG ((DEBUG_INFO, "Fat kernel has 0 offset\n")); + return 0; + } + + if (OcOverflowAddU32 (*Offset, Size, &TmpSize)) { + DEBUG ((DEBUG_INFO, "Fat kernel invalid size %u\n", Size)); + return 0; + } + + return Size; + } + } + + DEBUG ((DEBUG_INFO, "Fat kernel has no x86_64 arch\n")); + return 0; +} + +STATIC +UINT32 +ParseCompressedHeader ( + IN EFI_FILE_PROTOCOL *File, + IN OUT UINT8 **Buffer, + IN UINT32 *Offset, + OUT UINT32 *AllocatedSize + ) +{ + EFI_STATUS Status; + + UINT32 KernelSize; + MACH_COMP_HEADER *CompHeader; + UINT8 *CompressedBuffer; + UINT32 CompressionType; + UINT32 CompressedSize; + UINT32 DecompressedSize; + UINT32 DecompressedHash; + + CompHeader = (MACH_COMP_HEADER *) *Buffer; + CompressionType = CompHeader->Compression; + CompressedSize = SwapBytes32 (CompHeader->Compressed); + DecompressedSize = SwapBytes32 (CompHeader->Decompressed); + DecompressedHash = SwapBytes32 (CompHeader->Hash); + + KernelSize = 0; + + if (CompressedSize > OC_COMPRESSION_MAX_LENGTH + || CompressedSize == 0 + || DecompressedSize > OC_COMPRESSION_MAX_LENGTH + || DecompressedSize < KERNEL_HEADER_SIZE) { + DEBUG ((DEBUG_INFO, "Comp kernel invalid comp %u or decomp %u at %08X\n", CompressedSize, DecompressedSize, *Offset)); + return KernelSize; + } + + Status = ReplaceBuffer (DecompressedSize, Buffer, AllocatedSize); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "Decomp kernel (%u bytes) cannot be allocated at %08X\n", DecompressedSize, *Offset)); + return KernelSize; + } + + CompressedBuffer = AllocatePool (CompressedSize); + if (CompressedBuffer == NULL) { + DEBUG ((DEBUG_INFO, "Comp kernel (%u bytes) cannot be allocated at %08X\n", CompressedSize, *Offset)); + return KernelSize; + } + + Status = ReadFileData (File, *Offset + sizeof (MACH_COMP_HEADER), CompressedSize, CompressedBuffer); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "Comp kernel (%u bytes) cannot be read at %08X\n", CompressedSize, *Offset)); + FreePool (CompressedBuffer); + return KernelSize; + } + + if (CompressionType == MACH_COMPRESSED_BINARY_INVERT_LZVN) { + KernelSize = (UINT32) DecompressLZVN (*Buffer, DecompressedSize, CompressedBuffer, CompressedSize); + } else if (CompressionType == MACH_COMPRESSED_BINARY_INVERT_LZSS) { + KernelSize = (UINT32) DecompressLZSS (*Buffer, DecompressedSize, CompressedBuffer, CompressedSize); + } + + if (KernelSize != DecompressedSize) { + KernelSize = 0; + } + + // + // TODO: implement adler32 hash verification. + // + + FreePool (CompressedBuffer); + + return KernelSize; +} + +STATIC +EFI_STATUS +ReadAppleKernelImage ( + IN EFI_FILE_PROTOCOL *File, + IN OUT UINT8 **Buffer, + OUT UINT32 *KernelSize, + OUT UINT32 *AllocatedSize, + IN UINT32 Offset + ) +{ + EFI_STATUS Status; + UINT32 *MagicPtr; + BOOLEAN ForbidFat; + BOOLEAN Compressed; + + Status = ReadFileData (File, Offset, KERNEL_HEADER_SIZE, *Buffer); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Do not allow FAT architectures with Offset > 0 (recursion). + // + ForbidFat = Offset > 0; + Compressed = FALSE; + + while (TRUE) { + MagicPtr = (UINT32 *) *Buffer; + if (!OC_ALIGNED (MagicPtr)) { + DEBUG ((DEBUG_INFO, "Misaligned kernel header %p at %08X\n", MagicPtr, Offset)); + return EFI_INVALID_PARAMETER; + } + + switch (*MagicPtr) { + case MACH_HEADER_64_SIGNATURE: + DEBUG ((DEBUG_VERBOSE, "Found Mach-O compressed %d offset %u size %u\n", Compressed, Offset, *KernelSize)); + + // + // This is just a valid (formerly) compressed image. + // + if (Compressed) { + return EFI_SUCCESS; + } + + // + // This is an uncompressed image, just fully read it. + // + + if (Offset == 0) { + // + // Figure out size for a non fat image. + // + Status = ReadFileSize (File, KernelSize); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "Kernel size cannot be determined - %r\n", Status)); + return EFI_OUT_OF_RESOURCES; + } + } + + Status = ReplaceBuffer (*KernelSize, Buffer, AllocatedSize); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "Kernel (%u bytes) cannot be allocated at %08X\n", *KernelSize, Offset)); + return Status; + } + + Status = ReadFileData (File, Offset, *KernelSize, *Buffer); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "Kernel (%u bytes) cannot be read at %08X\n", *KernelSize, Offset)); + } + + return Status; + case MACH_FAT_BINARY_SIGNATURE: + case MACH_FAT_BINARY_INVERT_SIGNATURE: { + if (ForbidFat) { + DEBUG ((DEBUG_INFO, "Fat kernel recursion %p at %08X\n", MagicPtr, Offset)); + return EFI_INVALID_PARAMETER; + } + + *KernelSize = ParseFatArchitecture (File, Buffer, &Offset); + if (*KernelSize != 0) { + return ReadAppleKernelImage (File, Buffer, KernelSize, AllocatedSize, Offset); + } + return EFI_INVALID_PARAMETER; + } + case MACH_COMPRESSED_BINARY_INVERT_SIGNATURE: { + if (Compressed) { + DEBUG ((DEBUG_INFO, "Compression recursion %p at %08X\n", MagicPtr, Offset)); + return EFI_INVALID_PARAMETER; + } + + // + // No FAT or Comp is allowed after compressed. + // + ForbidFat = Compressed = TRUE; + + // + // Loop into updated image in Buffer. + // + *KernelSize = ParseCompressedHeader (File, Buffer, &Offset, AllocatedSize); + if (*KernelSize != 0) { + DEBUG ((DEBUG_VERBOSE, "Compressed result has %08X magic\n", *(UINT32 *) Buffer)); + continue; + } + return EFI_INVALID_PARAMETER; + } + default: + DEBUG ((Offset > 0 ? DEBUG_INFO : DEBUG_VERBOSE, "Invalid kernel magic %08X at %08X\n", *MagicPtr, Offset)); + return EFI_INVALID_PARAMETER; + } + } +} + +EFI_STATUS +ReadAppleKernel ( + IN EFI_FILE_PROTOCOL *File, + IN OUT UINT8 **Kernel, + OUT UINT32 *KernelSize, + OUT UINT32 *AllocatedSize + ) +{ + EFI_STATUS Status; + + *KernelSize = 0; + *AllocatedSize = KERNEL_HEADER_SIZE; + *Kernel = AllocatePool (KERNEL_HEADER_SIZE); + + if (*Kernel == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = ReadAppleKernelImage ( + File, + Kernel, + KernelSize, + AllocatedSize, + 0 + ); + + if (EFI_ERROR (Status)) { + FreePool (*Kernel); + } + + return Status; +} diff --git a/Library/OcCompressionLib/OcCompressionLib.inf b/Library/OcCompressionLib/OcCompressionLib.inf index 310ba322..05ba93b0 100644 --- a/Library/OcCompressionLib/OcCompressionLib.inf +++ b/Library/OcCompressionLib/OcCompressionLib.inf @@ -40,3 +40,5 @@ [LibraryClasses] BaseLib + BaseMemoryLib + MemoryAllocationLib diff --git a/Library/OcFileLib/FileProtocol.c b/Library/OcFileLib/FileProtocol.c new file mode 100644 index 00000000..8e7827c5 --- /dev/null +++ b/Library/OcFileLib/FileProtocol.c @@ -0,0 +1,72 @@ +/** @file + Copyright (C) 2019, vit9696. All rights reserved. + + All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +**/ + +#include +#include +#include + +EFI_STATUS +ReadFileData ( + IN EFI_FILE_PROTOCOL *File, + IN UINT32 Position, + IN UINT32 Size, + OUT UINT8 *Buffer + ) +{ + EFI_STATUS Status; + UINTN ReadSize; + + Status = File->SetPosition (File, Position); + if (EFI_ERROR (Status)) { + return Status; + } + + ReadSize = Size; + Status = File->Read (File, &ReadSize, Buffer); + if (EFI_ERROR (Status)) { + return Status; + } + + if (ReadSize != Size) { + return EFI_BAD_BUFFER_SIZE; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +ReadFileSize ( + IN EFI_FILE_PROTOCOL *File, + OUT UINT32 *Size + ) +{ + EFI_STATUS Status; + UINT64 Position; + + Status = File->SetPosition (File, 0xFFFFFFFFFFFFFFFFULL); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = File->GetPosition (File, &Position); + if (EFI_ERROR (Status)) { + return Status; + } + + if ((UINT32) Position != Position) { + return EFI_OUT_OF_RESOURCES; + } + + return EFI_SUCCESS; +} diff --git a/Library/OcFileLib/OcFileLib.inf b/Library/OcFileLib/OcFileLib.inf index c3697999..ad4146e1 100755 --- a/Library/OcFileLib/OcFileLib.inf +++ b/Library/OcFileLib/OcFileLib.inf @@ -27,6 +27,7 @@ # VALID_ARCHITECTURES = IA32 X64 [Sources] + FileProtocol.c GetFileInfo.c GetVolumeLabel.c ReadFile.c diff --git a/Library/OcVirtualFsLib/VirtualFile.c b/Library/OcVirtualFsLib/VirtualFile.c index f82e0d28..5ce93aee 100644 --- a/Library/OcVirtualFsLib/VirtualFile.c +++ b/Library/OcVirtualFsLib/VirtualFile.c @@ -100,7 +100,7 @@ EFIAPI VirtualFileRead ( IN EFI_FILE_PROTOCOL *This, IN OUT UINTN *BufferSize, - OUT VOID *Buffer + OUT VOID *Buffer ) { VIRTUAL_FILE_DATA *Data; diff --git a/OcSupportPkg.dec b/OcSupportPkg.dec index 6111a7c2..7c08f86f 100644 --- a/OcSupportPkg.dec +++ b/OcSupportPkg.dec @@ -59,6 +59,9 @@ ## @libraryclass OcAppleImageVerificationLib|Include/Library/OcAppleImageVerificationLib.h + ## @libraryclass + OcAppleKernelLib|Include/Library/OcAppleKernelLib.h + ## @libraryclass OcCompressionLib|Include/Library/OcCompressionLib.h diff --git a/OcSupportPkg.dsc b/OcSupportPkg.dsc index 76e2390e..ce597671 100644 --- a/OcSupportPkg.dsc +++ b/OcSupportPkg.dsc @@ -51,6 +51,7 @@ OcAppleBootPolicyLib|OcSupportPkg/Library/OcAppleBootPolicyLib/OcAppleBootPolicyLib.inf OcAppleChunklistLib|OcSupportPkg/Library/OcAppleChunklistLib/OcAppleChunklistLib.inf OcAppleImageVerificationLib|OcSupportPkg/Library/OcAppleImageVerificationLib/OcAppleImageVerificationLib.inf + OcAppleKernelLib|OcSupportPkg/Library/OcAppleKernelLib/OcAppleKernelLib.inf OcCpuLib|OcSupportPkg/Library/OcCpuLib/OcCpuLib.inf OcCryptoLib|OcSupportPkg/Library/OcCryptoLib/OcCryptoLib.inf OcCompressionLib|OcSupportPkg/Library/OcCompressionLib/OcCompressionLib.inf @@ -78,6 +79,7 @@ OcSupportPkg/Library/OcAppleBootPolicyLib/OcAppleBootPolicyLib.inf OcSupportPkg/Library/OcAppleChunklistLib/OcAppleChunklistLib.inf OcSupportPkg/Library/OcAppleImageVerificationLib/OcAppleImageVerificationLib.inf + OcSupportPkg/Library/OcAppleKernelLib/OcAppleKernelLib.inf OcSupportPkg/Library/OcCpuLib/OcCpuLib.inf OcSupportPkg/Library/OcCryptoLib/OcCryptoLib.inf OcSupportPkg/Library/OcCompressionLib/OcCompressionLib.inf diff --git a/STATUS.md b/STATUS.md index e97a3a21..7ebdfc21 100644 --- a/STATUS.md +++ b/STATUS.md @@ -17,6 +17,12 @@ listed here. **Issues**: 1. No proper interface for OS detection. 1. No dmg boot detection. +* OcAppleKernelLib + **Status**: functional + **Issues**: none +* OcCompressionLib + **Status**: functional + **Issues**: none * OcAppleChunklistLib **Status**: in progress **Issues**: diff --git a/Tests/KernelTest/KernelTest.c b/Tests/KernelTest/KernelTest.c index 39a17ae0..bc2c65f6 100644 --- a/Tests/KernelTest/KernelTest.c +++ b/Tests/KernelTest/KernelTest.c @@ -28,7 +28,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include #include +#include #include +#include #include #include @@ -55,11 +57,68 @@ TestFileOpen ( IN UINT64 Attributes ) { - EFI_STATUS Status; + EFI_STATUS Status; + UINT8 *Kernel; + UINT32 KernelSize; + UINT32 AllocatedSize; + CHAR16 *FileNameCopy; + EFI_FILE_PROTOCOL *VirtualFileHandle; Status = This->Open (This, NewHandle, FileName, OpenMode, Attributes); - Print (L"[FS %p] %s in %X/%X - %r\n", This, FileName, OpenMode, Attributes, Status); + if (!EFI_ERROR (Status) + && OpenMode == EFI_FILE_MODE_READ + && StrStr (FileName, L"kernel") != NULL) { + Print (L"Trying XNU hook on %s\n", FileName); + Status = ReadAppleKernel (*NewHandle, &Kernel, &KernelSize, &AllocatedSize); + Print (L"Result of XNU hook on %s is %r\n", FileName, Status); + + // + // This is not Apple kernel, just return the original file. + // + if (EFI_ERROR (Status)) { + return EFI_SUCCESS; + } + + // + // TODO: patches, dropping, and injection here. + // + + ApplyPatch ( + (UINT8 *) "Darwin Kernel Version", + NULL, + L_STR_LEN ("Darwin Kernel Version"), + (UINT8 *) "OpenCore Boot Version", + Kernel, + KernelSize, + 1, + 0 + ); + + // + // This was our file, yet firmware is dying. + // + FileNameCopy = AllocateCopyPool (StrSize (FileName), FileName); + if (FileNameCopy == NULL) { + DEBUG ((DEBUG_WARN, "Failed to allocate kernel name (%a) copy\n", FileName)); + FreePool (Kernel); + return EFI_SUCCESS; + } + + Status = CreateVirtualFile (FileNameCopy, Kernel, KernelSize, &VirtualFileHandle); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "Failed to virtualise kernel file (%a)\n", FileName)); + FreePool (Kernel); + FreePool (FileNameCopy); + return EFI_SUCCESS; + } + + // + // Return our handle. + // + (*NewHandle)->Close(*NewHandle); + *NewHandle = VirtualFileHandle; + } return Status; } diff --git a/Tests/KernelTest/KernelTest.inf b/Tests/KernelTest/KernelTest.inf index ea8da250..eb92180b 100644 --- a/Tests/KernelTest/KernelTest.inf +++ b/Tests/KernelTest/KernelTest.inf @@ -62,6 +62,7 @@ OcMiscLib OcProtocolLib OcAppleBootPolicyLib + OcAppleKernelLib OcSmbiosLib OcDataHubLib OcVirtualFsLib diff --git a/Tests/KernelTest/KernelTestApp.inf b/Tests/KernelTest/KernelTestApp.inf index 20ddba35..96ef0d0f 100644 --- a/Tests/KernelTest/KernelTestApp.inf +++ b/Tests/KernelTest/KernelTestApp.inf @@ -61,4 +61,6 @@ OcAppleBootPolicyLib OcSmbiosLib OcDataHubLib + OcAppleKernelLib + OcCompressionLib OcVirtualFsLib