diff --git a/Include/Library/OcAppleRamDiskLib.h b/Include/Library/OcAppleRamDiskLib.h
new file mode 100644
index 00000000..879b4ec5
--- /dev/null
+++ b/Include/Library/OcAppleRamDiskLib.h
@@ -0,0 +1,54 @@
+/** @file
+ Apple RAM Disk library.
+
+Copyright (C) 2019, Download-Fritz. 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_RAM_DISK_LIB_H
+#define OC_APPLE_RAM_DISK_LIB_H
+
+#include
+
+APPLE_RAM_DISK_EXTENT_TABLE *
+OcAppleRamDiskAllocate (
+ IN UINTN Size,
+ IN EFI_MEMORY_TYPE MemoryType
+ );
+
+BOOLEAN
+OcAppleRamDiskRead (
+ IN APPLE_RAM_DISK_EXTENT_TABLE *ExtentTable,
+ IN UINT64 Offset,
+ IN UINTN Size,
+ OUT VOID *Buffer
+ );
+
+BOOLEAN
+OcAppleRamDiskWrite (
+ IN APPLE_RAM_DISK_EXTENT_TABLE *ExtentTable,
+ IN UINT64 Offset,
+ IN UINTN Size,
+ IN CONST VOID *Buffer
+ );
+
+BOOLEAN
+OcAppleRamDiskLoadFile (
+ IN OUT APPLE_RAM_DISK_EXTENT_TABLE *ExtentTable,
+ IN EFI_FILE_PROTOCOL *File,
+ IN UINTN FileSize
+ );
+
+VOID
+OcAppleRamDiskFree (
+ IN APPLE_RAM_DISK_EXTENT_TABLE *ExtentTable
+ );
+
+#endif // OC_APPLE_RAM_DISK_LIB_H
diff --git a/Library/OcAppleRamDiskLib/OcAppleRamDiskLib.c b/Library/OcAppleRamDiskLib/OcAppleRamDiskLib.c
new file mode 100644
index 00000000..07423171
--- /dev/null
+++ b/Library/OcAppleRamDiskLib/OcAppleRamDiskLib.c
@@ -0,0 +1,525 @@
+/** @file
+ Apple RAM Disk library.
+
+Copyright (C) 2019, Download-Fritz. 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
+
+#define INTERNAL_ASSERT_EXTENT_TABLE_VALID(ExtentTable) \
+ ASSERT ((ExtentTable)->Signature == APPLE_RAM_DISK_EXTENT_SIGNATURE); \
+ ASSERT ((ExtentTable)->Version == APPLE_RAM_DISK_EXTENT_VERSION); \
+ ASSERT ((ExtentTable)->Reserved == 0); \
+ ASSERT ((ExtentTable)->Signature2 == APPLE_RAM_DISK_EXTENT_SIGNATURE); \
+ ASSERT ((ExtentTable)->ExtentCount > 0); \
+ ASSERT ((ExtentTable)->ExtentCount <= ARRAY_SIZE ((ExtentTable)->Extents))
+
+STATIC
+BOOLEAN
+InternalAllocateRemaining (
+ OUT APPLE_RAM_DISK_EXTENT *Extents,
+ OUT UINT32 *NumExtents,
+ IN UINT32 MaxExtents,
+ IN EFI_MEMORY_DESCRIPTOR *MemoryMap,
+ IN UINTN MemoryMapSize,
+ IN UINTN DescriptorSize,
+ IN UINTN RemainingPages,
+ IN EFI_MEMORY_TYPE MemoryType
+ );
+
+STATIC
+BOOLEAN
+InternalAllocateRemainingWorker (
+ OUT APPLE_RAM_DISK_EXTENT *Extents,
+ OUT UINT32 *NumExtents,
+ IN UINT32 MaxExtents,
+ IN EFI_MEMORY_DESCRIPTOR *MemoryMap,
+ IN UINTN MemoryMapSize,
+ IN UINTN DescriptorSize,
+ IN UINTN RemainingPages,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN BOOLEAN Above4G
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN Result;
+
+ EFI_PHYSICAL_ADDRESS ExtentMemory;
+
+ EFI_MEMORY_DESCRIPTOR *EntryWalker;
+ EFI_MEMORY_DESCRIPTOR *BiggestEntry;
+
+ UINT32 Index;
+
+ ASSERT (Extents != NULL);
+ ASSERT (MaxExtents > 0);
+ ASSERT (NumExtents != NULL);
+ ASSERT (MemoryMap != NULL);
+ ASSERT (MemoryMapSize > 0);
+ ASSERT (DescriptorSize > 0);
+ ASSERT ((MemoryMapSize % DescriptorSize) == 0);
+ ASSERT (RemainingPages > 0);
+
+ BiggestEntry = NULL;
+
+ for (
+ EntryWalker = MemoryMap;
+ (UINT8 *)EntryWalker < ((UINT8 *)MemoryMap + MemoryMapSize);
+ EntryWalker = NEXT_MEMORY_DESCRIPTOR (EntryWalker, DescriptorSize)) {
+ if ((EntryWalker->Type != EfiConventionalMemory)
+ || (((Above4G ? 1 : 0) ^ ((EntryWalker->PhysicalStart < BASE_4GB) ? 1 : 0)) == 0)) {
+ continue;
+ }
+
+ if ((BiggestEntry == NULL)
+ || (EntryWalker->NumberOfPages > BiggestEntry->NumberOfPages)) {
+ BiggestEntry = EntryWalker;
+ }
+ }
+
+ if (BiggestEntry == NULL) {
+ return FALSE;
+ }
+
+ if (BiggestEntry->NumberOfPages >= RemainingPages) {
+ //
+ // Backtracking - potential finish
+ //
+ ExtentMemory = BiggestEntry->PhysicalStart;
+ ExtentMemory += EFI_PAGES_TO_SIZE (BiggestEntry->NumberOfPages - RemainingPages);
+ Status = gBS->AllocatePages (
+ AllocateAddress,
+ MemoryType,
+ RemainingPages,
+ &ExtentMemory
+ );
+ if (!EFI_ERROR (Status)) {
+ Extents[0].Start = ExtentMemory;
+ Extents[0].Length = EFI_PAGES_TO_SIZE (RemainingPages);
+ *NumExtents = 1;
+
+ return TRUE;
+ }
+ }
+
+ if (MaxExtents == 1) {
+ return FALSE;
+ }
+ //
+ // Backtracking - iteration
+ //
+ BiggestEntry->Type = MemoryType;
+ Result = InternalAllocateRemaining (
+ &Extents[1],
+ NumExtents,
+ (MaxExtents - 1),
+ MemoryMap,
+ MemoryMapSize,
+ DescriptorSize,
+ (RemainingPages - BiggestEntry->NumberOfPages),
+ MemoryType
+ );
+ BiggestEntry->Type = EfiConventionalMemory;
+
+ if (!Result) {
+ return FALSE;
+ }
+
+ ExtentMemory = BiggestEntry->PhysicalStart;
+ Status = gBS->AllocatePages (
+ AllocateAddress,
+ MemoryType,
+ BiggestEntry->NumberOfPages,
+ &ExtentMemory
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // Clean up all successfully backtracked allocations.
+ //
+ for (Index = 0; Index < *NumExtents; ++Index) {
+ gBS->FreePages (
+ Extents[Index + 1].Start,
+ EFI_SIZE_TO_PAGES (Extents[Index + 1].Length)
+ );
+ }
+
+ *NumExtents = 0;
+ return FALSE;
+ }
+
+ Extents[0].Start = ExtentMemory;
+ Extents[0].Length = EFI_PAGES_TO_SIZE (BiggestEntry->NumberOfPages);
+ ++(*NumExtents);
+
+ return TRUE;
+}
+
+STATIC
+BOOLEAN
+InternalAllocateRemaining (
+ OUT APPLE_RAM_DISK_EXTENT *Extents,
+ OUT UINT32 *NumExtents,
+ IN UINT32 MaxExtents,
+ IN EFI_MEMORY_DESCRIPTOR *MemoryMap,
+ IN UINTN MemoryMapSize,
+ IN UINTN DescriptorSize,
+ IN UINTN RemainingPages,
+ IN EFI_MEMORY_TYPE MemoryType
+ )
+{
+ BOOLEAN Result;
+ //
+ // Prefer fitting all contents above 4 GB.
+ //
+ Result = InternalAllocateRemainingWorker (
+ Extents,
+ NumExtents,
+ MaxExtents,
+ MemoryMap,
+ MemoryMapSize,
+ DescriptorSize,
+ RemainingPages,
+ MemoryType,
+ TRUE
+ );
+ if (!Result) {
+ Result = InternalAllocateRemainingWorker (
+ Extents,
+ NumExtents,
+ MaxExtents,
+ MemoryMap,
+ MemoryMapSize,
+ DescriptorSize,
+ RemainingPages,
+ MemoryType,
+ FALSE
+ );
+ }
+
+ return Result;
+}
+
+APPLE_RAM_DISK_EXTENT_TABLE *
+OcAppleRamDiskAllocate (
+ IN UINTN Size,
+ IN EFI_MEMORY_TYPE MemoryType
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN Result;
+
+ UINTN MemoryMapSize;
+ EFI_MEMORY_DESCRIPTOR *MemoryMap;
+ UINTN MapKey;
+ UINTN DescriptorSize;
+ UINT32 DescriptorVersion;
+
+ APPLE_RAM_DISK_EXTENT_TABLE *ExtentTable;
+ UINT64 ExtentTableMemory;
+
+ Status = gBS->AllocatePages (
+ AllocateAnyPages,
+ MemoryType,
+ EFI_SIZE_TO_PAGES (sizeof (*ExtentTable)),
+ &ExtentTableMemory
+ );
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ MemoryMapSize = 0;
+ Status = gBS->GetMemoryMap (
+ &MemoryMapSize,
+ NULL,
+ &MapKey,
+ &DescriptorSize,
+ &DescriptorVersion
+ );
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ gBS->FreePages (
+ ExtentTableMemory,
+ EFI_SIZE_TO_PAGES (sizeof (*ExtentTable))
+ );
+ return NULL;
+ }
+ //
+ // Apple uses 1024 as constant, however it will grow by at least
+ // DescriptorSize.
+ //
+ Result = OcOverflowAddUN (
+ MemoryMapSize,
+ MAX (DescriptorSize, 1024),
+ &MemoryMapSize
+ );
+ if (Result) {
+ gBS->FreePages (
+ ExtentTableMemory,
+ EFI_SIZE_TO_PAGES (sizeof (*ExtentTable))
+ );
+ return NULL;
+ }
+
+ MemoryMap = AllocatePool (MemoryMapSize);
+ if (MemoryMap == NULL) {
+ gBS->FreePages (
+ ExtentTableMemory,
+ EFI_SIZE_TO_PAGES (sizeof (*ExtentTable))
+ );
+ return NULL;
+ }
+
+ Status = gBS->GetMemoryMap (
+ &MemoryMapSize,
+ MemoryMap,
+ &MapKey,
+ &DescriptorSize,
+ &DescriptorVersion
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePages (
+ ExtentTableMemory,
+ EFI_SIZE_TO_PAGES (sizeof (*ExtentTable))
+ );
+ FreePool (MemoryMap);
+ return NULL;
+ }
+
+ ExtentTable = (VOID *)(UINTN)ExtentTableMemory;
+ ExtentTable->Signature = APPLE_RAM_DISK_EXTENT_SIGNATURE;
+ ExtentTable->Version = APPLE_RAM_DISK_EXTENT_VERSION;
+ ExtentTable->Reserved = 0;
+ ExtentTable->Signature2 = APPLE_RAM_DISK_EXTENT_SIGNATURE;
+ ExtentTable->ExtentCount = 0;
+ Result = InternalAllocateRemaining (
+ ExtentTable->Extents,
+ &ExtentTable->ExtentCount,
+ ARRAY_SIZE (ExtentTable->Extents),
+ MemoryMap,
+ MemoryMapSize,
+ DescriptorSize,
+ EFI_SIZE_TO_PAGES (Size),
+ MemoryType
+ );
+ if (!Result) {
+ gBS->FreePages (
+ ExtentTableMemory,
+ EFI_SIZE_TO_PAGES (sizeof (*ExtentTable))
+ );
+ ExtentTable = NULL;
+ }
+
+ FreePool (MemoryMap);
+
+ return ExtentTable;
+}
+
+BOOLEAN
+OcAppleRamDiskRead (
+ IN APPLE_RAM_DISK_EXTENT_TABLE *ExtentTable,
+ IN UINT64 Offset,
+ IN UINTN Size,
+ OUT VOID *Buffer
+ )
+{
+ UINT8 *BufferBytes;
+
+ UINT32 Index;
+ APPLE_RAM_DISK_EXTENT *Extent;
+
+ UINT64 CurrentOffset;
+ UINT64 LocalOffset;
+ UINTN LocalSize;
+
+ ASSERT (ExtentTable != NULL);
+ INTERNAL_ASSERT_EXTENT_TABLE_VALID (ExtentTable);
+ ASSERT (Size > 0);
+ ASSERT (Buffer != NULL);
+
+ BufferBytes = Buffer;
+
+ for (
+ Index = 0, CurrentOffset = 0;
+ Index < ExtentTable->ExtentCount;
+ ++Index, CurrentOffset += Extent->Length
+ ) {
+ Extent = &ExtentTable->Extents[Index];
+
+ if (Offset >= CurrentOffset) {
+ LocalOffset = (Offset - CurrentOffset);
+ LocalSize = (UINTN)MIN ((Extent->Length - LocalOffset), Size);
+ CopyMem (
+ BufferBytes,
+ (VOID *)((UINTN)Extent->Start + LocalOffset),
+ LocalSize
+ );
+
+ Size -= LocalSize;
+ if (Size == 0) {
+ return TRUE;
+ }
+
+ BufferBytes += LocalSize;
+ Offset += LocalSize;
+ }
+ }
+
+ return FALSE;
+}
+
+BOOLEAN
+OcAppleRamDiskWrite (
+ IN APPLE_RAM_DISK_EXTENT_TABLE *ExtentTable,
+ IN UINT64 Offset,
+ IN UINTN Size,
+ IN CONST VOID *Buffer
+ )
+{
+ CONST UINT8 *BufferBytes;
+
+ UINT32 Index;
+ APPLE_RAM_DISK_EXTENT *Extent;
+
+ UINT64 CurrentOffset;
+ UINT64 LocalOffset;
+ UINTN LocalSize;
+
+ ASSERT (ExtentTable != NULL);
+ INTERNAL_ASSERT_EXTENT_TABLE_VALID (ExtentTable);
+ ASSERT (Size > 0);
+ ASSERT (Buffer != NULL);
+
+ BufferBytes = Buffer;
+
+ for (
+ Index = 0, CurrentOffset = 0;
+ Index < ExtentTable->ExtentCount;
+ ++Index, CurrentOffset += Extent->Length
+ ) {
+ Extent = &ExtentTable->Extents[Index];
+
+ if (Offset >= CurrentOffset) {
+ LocalOffset = (Offset - CurrentOffset);
+ LocalSize = (UINTN)MIN ((Extent->Length - LocalOffset), Size);
+ CopyMem (
+ (VOID *)((UINTN)Extent->Start + LocalOffset),
+ BufferBytes,
+ LocalSize
+ );
+
+ Size -= LocalSize;
+ if (Size == 0) {
+ return TRUE;
+ }
+
+ BufferBytes += LocalSize;
+ Offset += LocalSize;
+ }
+ }
+
+ return FALSE;
+}
+
+BOOLEAN
+OcAppleRamDiskLoadFile (
+ IN OUT APPLE_RAM_DISK_EXTENT_TABLE *ExtentTable,
+ IN EFI_FILE_PROTOCOL *File,
+ IN UINTN FileSize
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN Result;
+
+ UINTN FileBufferSize;
+ VOID *FileBuffer;
+
+ UINTN CurrentSize;
+ UINT64 FilePosition;
+
+ ASSERT (ExtentTable != NULL);
+ INTERNAL_ASSERT_EXTENT_TABLE_VALID (ExtentTable);
+ ASSERT (File != NULL);
+ ASSERT (FileSize > 0);
+
+ FileBufferSize = FileSize;
+
+ while (TRUE) {
+ FileBuffer = AllocatePool (FileBufferSize);
+ if (FileBuffer != NULL) {
+ break;
+ }
+
+ if (FileBufferSize <= 2) {
+ return FALSE;
+ }
+
+ FileBufferSize = ((FileBufferSize / 2) + 1);
+ }
+
+ FilePosition = 0;
+ CurrentSize = FileBufferSize;
+ do {
+ Status = GetFileData (File, FilePosition, CurrentSize, FileBuffer);
+ if (!EFI_ERROR (Status)) {
+ FreePool (FileBuffer);
+ return FALSE;
+ }
+
+ Result = OcAppleRamDiskWrite (
+ ExtentTable,
+ FilePosition,
+ CurrentSize,
+ FileBuffer
+ );
+ if (!Result) {
+ FreePool (FileBuffer);
+ return FALSE;
+ }
+
+ FilePosition += CurrentSize;
+ FileSize -= CurrentSize;
+ CurrentSize = MIN (FileSize, FileBufferSize);
+ } while (FileSize != 0);
+
+ return TRUE;
+}
+
+VOID
+OcAppleRamDiskFree (
+ IN APPLE_RAM_DISK_EXTENT_TABLE *ExtentTable
+ )
+{
+ UINT32 Index;
+
+ ASSERT (ExtentTable != NULL);
+ INTERNAL_ASSERT_EXTENT_TABLE_VALID (ExtentTable);
+
+ for (Index = 0; Index < ExtentTable->ExtentCount; ++Index) {
+ gBS->FreePages (
+ ExtentTable->Extents[Index].Start,
+ EFI_SIZE_TO_PAGES (ExtentTable->Extents[Index].Length)
+ );
+ }
+
+ gBS->FreePages (
+ (UINTN)ExtentTable,
+ EFI_SIZE_TO_PAGES (sizeof (*ExtentTable))
+ );
+}
diff --git a/Library/OcAppleRamDiskLib/OcAppleRamDiskLib.inf b/Library/OcAppleRamDiskLib/OcAppleRamDiskLib.inf
new file mode 100644
index 00000000..8cbf8b68
--- /dev/null
+++ b/Library/OcAppleRamDiskLib/OcAppleRamDiskLib.inf
@@ -0,0 +1,35 @@
+## @file
+# Apple RAM Disk library.
+#
+# Copyright (C) 2019, Download-Fritz. 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 = OcAppleRamDiskLib
+ FILE_GUID = 57734401-29DB-49C6-816C-BF333A72BBA3
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = OcAppleRamDiskLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER SMM_CORE UEFI_APPLICATION UEFI_DRIVER
+
+[Packages]
+ MdePkg/MdePkg.dec
+ EfiPkg/EfiPkg.dec
+ OcSupportPkg/OcSupportPkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ DebugLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+
+[Sources]
+ OcAppleRamDiskLib.c
diff --git a/OcSupportPkg.dec b/OcSupportPkg.dec
index 88d2fe0c..8ef07e8e 100644
--- a/OcSupportPkg.dec
+++ b/OcSupportPkg.dec
@@ -68,6 +68,9 @@
## @libraryclass
OcAppleKeysLib|Include/Library/OcAppleKeysLib.h
+ ## @libraryclass
+ OcAppleRamDiskLib|Include/Library/OcAppleRamDiskLib.h
+
## @libraryclass
OcBootManagementLib|Include/Library/OcBootManagementLib.h
diff --git a/OcSupportPkg.dsc b/OcSupportPkg.dsc
index 4b6489d0..ab240afe 100644
--- a/OcSupportPkg.dsc
+++ b/OcSupportPkg.dsc
@@ -57,6 +57,7 @@
OcAppleImageVerificationLib|OcSupportPkg/Library/OcAppleImageVerificationLib/OcAppleImageVerificationLib.inf
OcAppleKernelLib|OcSupportPkg/Library/OcAppleKernelLib/OcAppleKernelLib.inf
OcAppleKeysLib|OcSupportPkg/Library/OcAppleKeysLib/OcAppleKeysLib.inf
+ OcAppleRamDiskLib|OcSupportPkg/Library/OcAppleRamDiskLib/OcAppleRamDiskLib.inf
OcBootManagementLib|OcSupportPkg/Library/OcBootManagementLib/OcBootManagementLib.inf
OcConsoleLib|OcSupportPkg/Library/OcConsoleLib/OcConsoleLib.inf
OcCpuLib|OcSupportPkg/Library/OcCpuLib/OcCpuLib.inf
@@ -87,6 +88,7 @@
OcSupportPkg/Library/OcAppleDiskImageLib/OcAppleDiskImageLib.inf
OcSupportPkg/Library/OcAppleImageVerificationLib/OcAppleImageVerificationLib.inf
OcSupportPkg/Library/OcAppleKernelLib/OcAppleKernelLib.inf
+ OcSupportPkg/Library/OcAppleRamDiskLib/OcAppleRamDiskLib.inf
OcSupportPkg/Library/OcBootManagementLib/OcBootManagementLib.inf
OcSupportPkg/Library/OcConfigurationLib/OcConfigurationLib.inf
OcSupportPkg/Library/OcCpuLib/OcCpuLib.inf