20#include <Library/BaseLib.h>
21#include <Library/BaseOverflowLib.h>
22#include <Library/DebugLib.h>
23#include <Library/MemoryAllocationLib.h>
32#define KERNEL_HEADER_SIZE (EFI_PAGE_SIZE * 2)
49 OUT UINT32 *AllocatedSize,
50 IN UINT32 ReservedSize
55 if (BaseOverflowAddU32 (TargetSize, ReservedSize, &TargetSize)) {
56 return EFI_INVALID_PARAMETER;
59 if (*AllocatedSize >= TargetSize) {
63 TmpBuffer = AllocatePool (TargetSize);
64 if (TmpBuffer == NULL) {
65 return EFI_OUT_OF_RESOURCES;
70 *AllocatedSize = TargetSize;
78 IN EFI_FILE_PROTOCOL *File,
94 while (RemainingSize > 0) {
95 ChunkSize =
MIN (RemainingSize,
Size);
102 if (EFI_ERROR (Status)) {
108 RemainingSize -= ChunkSize;
119 if (EFI_ERROR (Status)) {
142 IN EFI_FILE_PROTOCOL *File,
143 IN BOOLEAN Prefer32Bit,
145 IN UINT32 BufferSize,
146 OUT BOOLEAN *Is32Bit,
147 OUT UINT32 *FatOffset,
155 if (EFI_ERROR (Status)) {
159 if (BufferSize >= FileSize) {
160 return EFI_INVALID_PARAMETER;
171 *Is32Bit = Prefer32Bit;
176 if (Status == EFI_NOT_FOUND) {
185 *Is32Bit = !Prefer32Bit;
194 IN EFI_FILE_PROTOCOL *File,
197 OUT UINT32 *AllocatedSize,
198 IN UINT32 ReservedSize
205 UINT8 *CompressedBuffer;
206 UINT32 CompressionType;
207 UINT32 CompressedSize;
208 UINT32 DecompressedSize;
209 UINT32 DecompressedHash;
213 CompressedSize = SwapBytes32 (CompHeader->
Compressed);
214 DecompressedSize = SwapBytes32 (CompHeader->
Decompressed);
215 DecompressedHash = SwapBytes32 (CompHeader->
Hash);
220 || (CompressedSize == 0)
224 DEBUG ((DEBUG_INFO,
"OCAK: Comp kernel invalid comp %u or decomp %u at %08X\n", CompressedSize, DecompressedSize, Offset));
229 if (EFI_ERROR (Status)) {
230 DEBUG ((DEBUG_INFO,
"OCAK: Decomp kernel (%u bytes) cannot be allocated at %08X\n", DecompressedSize, Offset));
234 CompressedBuffer = AllocatePool (CompressedSize);
235 if (CompressedBuffer == NULL) {
236 DEBUG ((DEBUG_INFO,
"OCAK: Comp kernel (%u bytes) cannot be allocated at %08X\n", CompressedSize, Offset));
241 if (EFI_ERROR (Status)) {
242 DEBUG ((DEBUG_INFO,
"OCAK: Comp kernel (%u bytes) cannot be read at %08X\n", CompressedSize, Offset));
243 FreePool (CompressedBuffer);
248 KernelSize = (UINT32)
DecompressLZVN (*
Buffer, DecompressedSize, CompressedBuffer, CompressedSize);
250 KernelSize = (UINT32)
DecompressLZSS (*
Buffer, DecompressedSize, CompressedBuffer, CompressedSize);
253 if (KernelSize != DecompressedSize) {
260 (VOID)DecompressedHash;
262 FreePool (CompressedBuffer);
270 IN EFI_FILE_PROTOCOL *File,
271 IN BOOLEAN Prefer32Bit,
274 OUT UINT32 *KernelSize,
275 OUT UINT32 *AllocatedSize,
276 IN UINT32 ReservedSize,
287 if (EFI_ERROR (Status)) {
294 ForbidFat = Offset > 0;
298 if (!BASE_TYPE_ALIGNED (UINT32, *
Buffer)) {
299 DEBUG ((DEBUG_INFO,
"OCAK: Misaligned kernel header %p at %08X\n", *
Buffer, Offset));
300 return EFI_INVALID_PARAMETER;
303 MagicPtr = (UINT32 *)*
Buffer;
324 return EFI_INVALID_PARAMETER;
329 "OCAK: Found %a Mach-O compressed %d offset %u size %u\n",
330 Is32Bit ?
"32-bit" :
"64-bit",
351 if (EFI_ERROR (Status)) {
352 DEBUG ((DEBUG_INFO,
"OCAK: Kernel size cannot be determined - %r\n", Status));
353 return EFI_OUT_OF_RESOURCES;
356 DEBUG ((DEBUG_VERBOSE,
"OCAK: Determined kernel size is %u bytes\n", *KernelSize));
360 if (EFI_ERROR (Status)) {
361 DEBUG ((DEBUG_INFO,
"OCAK: Kernel (%u bytes) cannot be allocated at %08X\n", *KernelSize, Offset));
366 if (EFI_ERROR (Status)) {
367 DEBUG ((DEBUG_INFO,
"OCAK: Kernel (%u bytes) cannot be read at %08X\n", *KernelSize, Offset));
375 DEBUG ((DEBUG_INFO,
"Fat kernel recursion %p at %08X\n", MagicPtr, Offset));
376 return EFI_INVALID_PARAMETER;
380 if (EFI_ERROR (Status)) {
390 DEBUG ((DEBUG_INFO,
"Compression recursion %p at %08X\n", MagicPtr, Offset));
391 return EFI_INVALID_PARAMETER;
397 ForbidFat = Compressed = TRUE;
403 if (*KernelSize != 0) {
404 DEBUG ((DEBUG_VERBOSE,
"OCAK: Compressed result has %08X magic\n", *(UINT32 *)
Buffer));
408 return EFI_INVALID_PARAMETER;
411 DEBUG ((Offset > 0 ? DEBUG_INFO : DEBUG_VERBOSE,
"OCAK: Invalid kernel magic %08X at %08X\n", *MagicPtr, Offset));
412 return EFI_INVALID_PARAMETER;
419 IN EFI_FILE_PROTOCOL *File,
420 IN BOOLEAN Prefer32Bit,
421 OUT BOOLEAN *Is32Bit,
423 OUT UINT32 *KernelSize,
424 OUT UINT32 *AllocatedSize,
425 IN UINT32 ReservedSize,
426 OUT UINT8 *Digest OPTIONAL
437 ASSERT (KernelSize != NULL);
438 ASSERT (AllocatedSize != NULL);
443 *Kernel = AllocatePool (*AllocatedSize);
446 if (*Kernel == NULL) {
447 return EFI_OUT_OF_RESOURCES;
467 if (EFI_ERROR (Status)) {
477 if (EFI_ERROR (Status)) {
485 if (Remainder == NULL) {
488 return EFI_OUT_OF_RESOURCES;
498 FreePool (Remainder);
499 if (EFI_ERROR (Status)) {
515 IN EFI_FILE_PROTOCOL *File,
516 IN BOOLEAN Prefer32Bit,
518 OUT UINT32 *MkextSize,
519 OUT UINT32 *AllocatedSize,
520 IN UINT32 ReservedSize,
521 IN UINT32 NumReservedKexts
532 ASSERT (MkextSize != NULL);
533 ASSERT (AllocatedSize != NULL);
539 TmpMkext = AllocatePool (TmpMkextSize);
540 if (TmpMkext == NULL) {
541 return EFI_OUT_OF_RESOURCES;
545 if (EFI_ERROR (Status)) {
550 Status =
ParseFatArchitecture (File, Prefer32Bit, TmpMkext, TmpMkextSize, &Is32Bit, &Offset, &TmpMkextSize);
552 if (EFI_ERROR (Status)) {
556 if (Prefer32Bit != Is32Bit) {
557 return EFI_NOT_FOUND;
563 TmpMkext = AllocatePool (TmpMkextSize);
564 if (TmpMkext == NULL) {
565 return EFI_OUT_OF_RESOURCES;
568 Status =
OcGetFileData (File, Offset, TmpMkextSize, TmpMkext);
569 if (EFI_ERROR (Status)) {
579 return EFI_UNSUPPORTED;
582 DEBUG ((DEBUG_VERBOSE,
"OCAK: Found %a mkext offset %u size %u\n", Prefer32Bit ?
"32-bit" :
"64-bit", Offset, TmpMkextSize));
588 Status =
MkextDecompress (TmpMkext, TmpMkextSize, NumReservedKexts, NULL, 0, AllocatedSize);
589 if (EFI_ERROR (Status)) {
594 if (BaseOverflowAddU32 (*AllocatedSize, ReservedSize, AllocatedSize)) {
596 return EFI_INVALID_PARAMETER;
599 *Mkext = AllocatePool (*AllocatedSize);
600 if (*Mkext == NULL) {
602 return EFI_OUT_OF_RESOURCES;
608 Status =
MkextDecompress (TmpMkext, TmpMkextSize, NumReservedKexts, *Mkext, *AllocatedSize, MkextSize);
611 if (EFI_ERROR (Status)) {
#define MACH_COMPRESSED_BINARY_INVERT_LZVN
#define MACH_COMPRESSED_BINARY_INVERT_LZSS
#define MACH_COMPRESSED_BINARY_INVERT_SIGNATURE
#define MACH_FAT_BINARY_SIGNATURE
#define MACH_FAT_BINARY_INVERT_SIGNATURE
#define MACH_HEADER_SIGNATURE
the mach magic number
#define MACH_HEADER_64_SIGNATURE
the 64-bit mach magic number
STATIC EFI_STATUS ReadAppleKernelImage(IN EFI_FILE_PROTOCOL *File, IN BOOLEAN Prefer32Bit, IN OUT KERNEL_ARCH *Arch, IN OUT UINT8 **Buffer, OUT UINT32 *KernelSize, OUT UINT32 *AllocatedSize, IN UINT32 ReservedSize, IN UINT32 Offset)
EFI_STATUS ReadAppleKernel(IN EFI_FILE_PROTOCOL *File, IN BOOLEAN Prefer32Bit, OUT BOOLEAN *Is32Bit, OUT UINT8 **Kernel, OUT UINT32 *KernelSize, OUT UINT32 *AllocatedSize, IN UINT32 ReservedSize, OUT UINT8 *Digest OPTIONAL)
STATIC EFI_STATUS KernelGetFileData(IN EFI_FILE_PROTOCOL *File, IN UINT32 Position, IN UINT32 Size, OUT UINT8 *Buffer)
STATIC BOOLEAN mNeedKernelDigest
EFI_STATUS ReadAppleMkext(IN EFI_FILE_PROTOCOL *File, IN BOOLEAN Prefer32Bit, OUT UINT8 **Mkext, OUT UINT32 *MkextSize, OUT UINT32 *AllocatedSize, IN UINT32 ReservedSize, IN UINT32 NumReservedKexts)
STATIC UINT32 ParseCompressedHeader(IN EFI_FILE_PROTOCOL *File, IN OUT UINT8 **Buffer, IN UINT32 Offset, OUT UINT32 *AllocatedSize, IN UINT32 ReservedSize)
STATIC EFI_STATUS ReplaceBuffer(IN UINT32 TargetSize, IN OUT UINT8 **Buffer, OUT UINT32 *AllocatedSize, IN UINT32 ReservedSize)
#define KERNEL_HEADER_SIZE
STATIC UINT32 mKernelDigestPosition
STATIC SHA384_CONTEXT mKernelDigestContext
STATIC EFI_STATUS ParseFatArchitecture(IN EFI_FILE_PROTOCOL *File, IN BOOLEAN Prefer32Bit, IN UINT8 *Buffer, IN UINT32 BufferSize, OUT BOOLEAN *Is32Bit, OUT UINT32 *FatOffset, OUT UINT32 *FatSize)
DMG_SIZE_DEVICE_PATH Size
BOOLEAN MkextCheckCpuType(IN UINT8 *Mkext, IN UINT32 MkextSize, IN MACH_CPU_TYPE CpuType)
EFI_STATUS MkextDecompress(IN CONST UINT8 *Buffer, IN UINT32 BufferSize, IN UINT32 NumReservedKexts, IN OUT UINT8 *OutBuffer OPTIONAL, IN UINT32 OutBufferSize OPTIONAL, IN OUT UINT32 *OutMkextSize)
#define OC_COMPRESSION_MAX_LENGTH
UINTN DecompressLZVN(OUT UINT8 *Dst, IN UINTN DstLen, IN CONST UINT8 *Src, IN UINTN SrcLen)
UINT32 DecompressLZSS(OUT UINT8 *Dst, IN UINT32 DstLen, IN UINT8 *Src, IN UINT32 SrcLen)
VOID Sha384Init(SHA384_CONTEXT *Context)
VOID Sha384Final(SHA384_CONTEXT *Context, UINT8 *HashDigest)
VOID Sha384Update(SHA384_CONTEXT *Context, CONST UINT8 *Data, UINTN Len)
EFI_STATUS OcGetFileSize(IN EFI_FILE_PROTOCOL *File, OUT UINT32 *Size)
EFI_STATUS OcGetFileData(IN EFI_FILE_PROTOCOL *File, IN UINT32 Position, IN UINT32 Size, OUT UINT8 *Buffer)
EFI_STATUS FatGetArchitectureOffset(IN CONST UINT8 *Buffer, IN UINT32 BufferSize, IN UINT32 FullSize, IN MACH_CPU_TYPE CpuType, OUT UINT32 *FatOffset, OUT UINT32 *FatSize)
OC_TYPING_BUFFER_ENTRY Buffer[OC_TYPING_BUFFER_SIZE]