OcAppleRamDiskLib: Initial import

This commit is contained in:
Download-Fritz 2019-04-19 16:33:39 +02:00
parent 31b2151fcb
commit 18c6068cf3
5 changed files with 619 additions and 0 deletions

View File

@ -0,0 +1,54 @@
/** @file
Apple RAM Disk library.
Copyright (C) 2019, Download-Fritz. All rights reserved.<BR>
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 <Protocol/AppleRamDisk.h>
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

View File

@ -0,0 +1,525 @@
/** @file
Apple RAM Disk library.
Copyright (C) 2019, Download-Fritz. All rights reserved.<BR>
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 <Uefi.h>
#include <Protocol/AppleRamDisk.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/OcFileLib.h>
#include <Library/OcGuardLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
#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))
);
}

View File

@ -0,0 +1,35 @@
## @file
# Apple RAM Disk library.
#
# Copyright (C) 2019, Download-Fritz. All rights reserved.<BR>
# 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

View File

@ -68,6 +68,9 @@
## @libraryclass
OcAppleKeysLib|Include/Library/OcAppleKeysLib.h
## @libraryclass
OcAppleRamDiskLib|Include/Library/OcAppleRamDiskLib.h
## @libraryclass
OcBootManagementLib|Include/Library/OcBootManagementLib.h

View File

@ -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