mirror of
https://github.com/acidanthera/OpenCorePkg.git
synced 2025-12-08 19:25:01 +00:00
647 lines
17 KiB
C
647 lines
17 KiB
C
/** @file
|
|
OpenCore driver.
|
|
|
|
Copyright (c) 2019, vit9696. 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 <OpenCore.h>
|
|
|
|
#include <Library/BaseLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/MemoryAllocationLib.h>
|
|
#include <Library/OcAppleKernelLib.h>
|
|
#include <Library/OcMiscLib.h>
|
|
#include <Library/OcStringLib.h>
|
|
#include <Library/OcVirtualFsLib.h>
|
|
#include <Library/PrintLib.h>
|
|
#include <Library/UefiBootServicesTableLib.h>
|
|
|
|
STATIC OC_STORAGE_CONTEXT *mOcStorage;
|
|
STATIC OC_GLOBAL_CONFIG *mOcConfiguration;
|
|
STATIC OC_CPU_INFO *mOcCpuInfo;
|
|
|
|
STATIC
|
|
VOID
|
|
OcKernelReadDarwinVersion (
|
|
IN CONST UINT8 *Kernel,
|
|
IN UINT32 KernelSize,
|
|
OUT CHAR8 *DarwinVersion,
|
|
OUT UINT32 DarwinVersionSize
|
|
)
|
|
{
|
|
INT32 Offset;
|
|
UINT32 Index;
|
|
|
|
ASSERT (DarwinVersion > 0);
|
|
|
|
Offset = FindPattern (
|
|
(CONST UINT8 *) "Darwin Kernel Version ",
|
|
NULL,
|
|
L_STR_LEN ("Darwin Kernel Version "),
|
|
Kernel,
|
|
KernelSize,
|
|
0
|
|
);
|
|
|
|
if (Offset < 0) {
|
|
DEBUG ((DEBUG_WARN, "OC: Failed to determine kernel version\n"));
|
|
DarwinVersion[0] = '\0';
|
|
return;
|
|
}
|
|
|
|
Offset += L_STR_LEN ("Darwin Kernel Version ");
|
|
|
|
for (Index = 0; Index < DarwinVersionSize - 1; ++Index, ++Offset) {
|
|
if ((UINT32) Offset >= KernelSize || Kernel[Offset] == ':') {
|
|
break;
|
|
}
|
|
DarwinVersion[Index] = (CHAR8) Kernel[Offset];
|
|
}
|
|
DarwinVersion[Index] = '\0';
|
|
|
|
DEBUG ((DEBUG_INFO, "OC: Read kernel version %a\n", DarwinVersion));
|
|
}
|
|
|
|
STATIC
|
|
UINT32
|
|
OcKernelLoadKextsAndReserve (
|
|
IN OC_STORAGE_CONTEXT *Storage,
|
|
IN OC_GLOBAL_CONFIG *Config
|
|
)
|
|
{
|
|
UINT32 Index;
|
|
UINT32 ReserveSize;
|
|
CHAR8 *BundlePath;
|
|
CHAR8 *PlistPath;
|
|
CHAR8 *ExecutablePath;
|
|
CHAR16 FullPath[128];
|
|
OC_KERNEL_ADD_ENTRY *Kext;
|
|
|
|
ReserveSize = PRELINK_INFO_RESERVE_SIZE;
|
|
|
|
for (Index = 0; Index < Config->Kernel.Add.Count; ++Index) {
|
|
Kext = Config->Kernel.Add.Values[Index];
|
|
|
|
if (!Kext->Enabled) {
|
|
continue;
|
|
}
|
|
|
|
if (Kext->PlistDataSize == 0) {
|
|
BundlePath = OC_BLOB_GET (&Kext->BundlePath);
|
|
PlistPath = OC_BLOB_GET (&Kext->PlistPath);
|
|
if (BundlePath[0] == '\0' || PlistPath[0] == '\0') {
|
|
DEBUG ((DEBUG_ERROR, "OC: Your config has improper for kext info\n"));
|
|
Kext->Enabled = FALSE;
|
|
continue;
|
|
}
|
|
|
|
UnicodeSPrint (
|
|
FullPath,
|
|
sizeof (FullPath),
|
|
OPEN_CORE_KEXT_PATH "%a\\%a",
|
|
BundlePath,
|
|
PlistPath
|
|
);
|
|
|
|
UnicodeUefiSlashes (FullPath);
|
|
|
|
Kext->PlistData = OcStorageReadFileUnicode (
|
|
Storage,
|
|
FullPath,
|
|
&Kext->PlistDataSize
|
|
);
|
|
|
|
if (Kext->PlistData == NULL) {
|
|
DEBUG ((DEBUG_ERROR, "OC: Plist %s is missing for kext %a\n", FullPath, BundlePath));
|
|
Kext->Enabled = FALSE;
|
|
continue;
|
|
}
|
|
|
|
ExecutablePath = OC_BLOB_GET (&Kext->ExecutablePath);
|
|
if (ExecutablePath[0] != '\0') {
|
|
UnicodeSPrint (
|
|
FullPath,
|
|
sizeof (FullPath),
|
|
OPEN_CORE_KEXT_PATH "%a\\%a",
|
|
BundlePath,
|
|
ExecutablePath
|
|
);
|
|
|
|
UnicodeUefiSlashes (FullPath);
|
|
|
|
Kext->ImageData = OcStorageReadFileUnicode (
|
|
Storage,
|
|
FullPath,
|
|
&Kext->ImageDataSize
|
|
);
|
|
|
|
if (Kext->ImageData == NULL) {
|
|
DEBUG ((DEBUG_ERROR, "OC: Image %s is missing for kext %a\n", FullPath, BundlePath));
|
|
Kext->Enabled = FALSE;
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
PrelinkedReserveKextSize (
|
|
&ReserveSize,
|
|
Kext->PlistDataSize,
|
|
Kext->ImageData,
|
|
Kext->ImageDataSize
|
|
);
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO, "Kext reservation size %u\n", ReserveSize));
|
|
|
|
return ReserveSize;
|
|
}
|
|
|
|
STATIC
|
|
VOID
|
|
OcKernelApplyPatches (
|
|
IN OC_GLOBAL_CONFIG *Config,
|
|
IN CONST CHAR8 *DarwinVersion,
|
|
IN PRELINKED_CONTEXT *Context,
|
|
IN OUT UINT8 *Kernel,
|
|
IN UINT32 Size
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
PATCHER_CONTEXT Patcher;
|
|
UINT32 Index;
|
|
PATCHER_GENERIC_PATCH Patch;
|
|
OC_KERNEL_PATCH_ENTRY *UserPatch;
|
|
CONST CHAR8 *Target;
|
|
CONST CHAR8 *MatchKernel;
|
|
BOOLEAN IsKernelPatch;
|
|
|
|
IsKernelPatch = Context == NULL;
|
|
|
|
if (IsKernelPatch) {
|
|
ASSERT (Kernel != NULL);
|
|
|
|
Status = PatcherInitContextFromBuffer (
|
|
&Patcher,
|
|
Kernel,
|
|
Size
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_ERROR, "OC: Kernel patcher kernel init failure - %r\n", Status));
|
|
return;
|
|
}
|
|
}
|
|
|
|
for (Index = 0; Index < Config->Kernel.Patch.Count; ++Index) {
|
|
UserPatch = Config->Kernel.Patch.Values[Index];
|
|
Target = OC_BLOB_GET (&UserPatch->Identifier);
|
|
|
|
if (!UserPatch->Enabled
|
|
|| (AsciiStrCmp (Target, "kernel") == 0) != IsKernelPatch) {
|
|
continue;
|
|
}
|
|
|
|
MatchKernel = OC_BLOB_GET (&UserPatch->MatchKernel);
|
|
|
|
if (AsciiStrnCmp (DarwinVersion, MatchKernel, AsciiStrLen (MatchKernel)) != 0) {
|
|
DEBUG ((
|
|
DEBUG_INFO,
|
|
"OC: Kernel patcher skips %a patch at %u due to version %a vs %a",
|
|
Target,
|
|
Index,
|
|
MatchKernel,
|
|
DarwinVersion
|
|
));
|
|
continue;
|
|
}
|
|
|
|
if (!IsKernelPatch) {
|
|
Status = PatcherInitContextFromPrelinked (
|
|
&Patcher,
|
|
Context,
|
|
Target
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_WARN, "OC: Kernel patcher %a init failure - %r\n", Target, Status));
|
|
continue;
|
|
} else {
|
|
DEBUG ((DEBUG_INFO, "OC: Kernel patcher %a init succeed\n", Target));
|
|
}
|
|
}
|
|
|
|
//
|
|
// Ignore patch if:
|
|
// - There is nothing to replace.
|
|
// - We have neither symbolic base, nor find data.
|
|
// - Find and replace mismatch in size.
|
|
// - Mask and ReplaceMask mismatch in size when are available.
|
|
//
|
|
if (UserPatch->Replace.Size == 0
|
|
|| (OC_BLOB_GET (&UserPatch->Base)[0] == '\0' && UserPatch->Find.Size != UserPatch->Replace.Size)
|
|
|| (UserPatch->Mask.Size > 0 && UserPatch->Find.Size != UserPatch->Mask.Size)
|
|
|| (UserPatch->ReplaceMask.Size > 0 && UserPatch->Find.Size != UserPatch->ReplaceMask.Size)) {
|
|
DEBUG ((DEBUG_ERROR, "OC: Kernel patch %u for %a is borked\n", Index, Target));
|
|
continue;
|
|
}
|
|
|
|
ZeroMem (&Patch, sizeof (Patch));
|
|
|
|
if (OC_BLOB_GET (&UserPatch->Comment)[0] != '\0') {
|
|
Patch.Comment = OC_BLOB_GET (&UserPatch->Comment);
|
|
}
|
|
|
|
if (OC_BLOB_GET (&UserPatch->Base)[0] != '\0') {
|
|
Patch.Base = OC_BLOB_GET (&UserPatch->Base);
|
|
}
|
|
|
|
if (UserPatch->Find.Size > 0) {
|
|
Patch.Find = OC_BLOB_GET (&UserPatch->Find);
|
|
}
|
|
|
|
Patch.Replace = OC_BLOB_GET (&UserPatch->Replace);
|
|
|
|
if (UserPatch->Mask.Size > 0) {
|
|
Patch.Mask = OC_BLOB_GET (&UserPatch->Mask);
|
|
}
|
|
|
|
if (UserPatch->ReplaceMask.Size > 0) {
|
|
Patch.ReplaceMask = OC_BLOB_GET (&UserPatch->ReplaceMask);
|
|
}
|
|
|
|
Patch.Size = UserPatch->Replace.Size;
|
|
Patch.Count = UserPatch->Count;
|
|
Patch.Skip = UserPatch->Skip;
|
|
Patch.Limit = UserPatch->Limit;
|
|
|
|
Status = PatcherApplyGenericPatch (&Patcher, &Patch);
|
|
DEBUG ((
|
|
EFI_ERROR (Status) ? DEBUG_WARN : DEBUG_INFO,
|
|
"OC: Kernel patcher result %u for %a - %r\n",
|
|
Index,
|
|
Target,
|
|
Status
|
|
));
|
|
}
|
|
|
|
if (!IsKernelPatch) {
|
|
if (Config->Kernel.Quirks.AppleCpuPmCfgLock) {
|
|
PatchAppleCpuPmCfgLock (Context);
|
|
}
|
|
|
|
if (Config->Kernel.Quirks.ExternalDiskIcons) {
|
|
PatchForceInternalDiskIcons (Context);
|
|
}
|
|
|
|
if (Config->Kernel.Quirks.ThirdPartyTrim) {
|
|
PatchThirdPartySsdTrim (Context);
|
|
}
|
|
|
|
if (Config->Kernel.Quirks.XhciPortLimit) {
|
|
PatchUsbXhciPortLimit (Context);
|
|
}
|
|
|
|
if (Config->Kernel.Quirks.DisableIoMapper) {
|
|
PatchAppleIoMapperSupport (Context);
|
|
}
|
|
|
|
if (Config->Kernel.Quirks.CustomSmbiosGuid) {
|
|
PatchCustomSmbiosGuid (Context);
|
|
}
|
|
} else {
|
|
if (Config->Kernel.Quirks.AppleXcpmCfgLock) {
|
|
PatchAppleXcpmCfgLock (&Patcher);
|
|
}
|
|
|
|
if (Config->Kernel.Quirks.AppleXcpmExtraMsrs) {
|
|
PatchAppleXcpmExtraMsrs (&Patcher);
|
|
}
|
|
|
|
if (Config->Kernel.Quirks.PanicNoKextDump) {
|
|
PatchPanicKextDump (&Patcher);
|
|
}
|
|
|
|
if (Config->Kernel.Emulate.Cpuid1Data[0] != 0
|
|
|| Config->Kernel.Emulate.Cpuid1Data[1] != 0
|
|
|| Config->Kernel.Emulate.Cpuid1Data[2] != 0
|
|
|| Config->Kernel.Emulate.Cpuid1Data[3] != 0) {
|
|
PatchKernelCpuId (
|
|
&Patcher,
|
|
mOcCpuInfo,
|
|
Config->Kernel.Emulate.Cpuid1Data,
|
|
Config->Kernel.Emulate.Cpuid1Mask
|
|
);
|
|
}
|
|
|
|
if (Config->Kernel.Quirks.LapicKernelPanic) {
|
|
PatchLapicKernelPanic (&Patcher);
|
|
}
|
|
}
|
|
}
|
|
|
|
STATIC
|
|
VOID
|
|
OcKernelBlockKexts (
|
|
IN OC_GLOBAL_CONFIG *Config,
|
|
IN CONST CHAR8 *DarwinVersion,
|
|
IN PRELINKED_CONTEXT *Context
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
PATCHER_CONTEXT Patcher;
|
|
UINT32 Index;
|
|
OC_KERNEL_BLOCK_ENTRY *Kext;
|
|
CONST CHAR8 *Target;
|
|
CONST CHAR8 *MatchKernel;
|
|
|
|
for (Index = 0; Index < Config->Kernel.Block.Count; ++Index) {
|
|
Kext = Config->Kernel.Block.Values[Index];
|
|
Target = OC_BLOB_GET (&Kext->Identifier);
|
|
|
|
if (!Kext->Enabled) {
|
|
continue;
|
|
}
|
|
|
|
MatchKernel = OC_BLOB_GET (&Kext->MatchKernel);
|
|
|
|
if (AsciiStrnCmp (DarwinVersion, MatchKernel, AsciiStrLen (MatchKernel)) != 0) {
|
|
DEBUG ((
|
|
DEBUG_INFO,
|
|
"OC: Prelink blocker skips %a block at %u due to version %a vs %a",
|
|
Target,
|
|
Index,
|
|
MatchKernel,
|
|
DarwinVersion
|
|
));
|
|
continue;
|
|
}
|
|
|
|
Status = PatcherInitContextFromPrelinked (
|
|
&Patcher,
|
|
Context,
|
|
Target
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_WARN, "OC: Prelink blocker %a init failure - %r\n", Target, Status));
|
|
continue;
|
|
}
|
|
|
|
Status = PatcherBlockKext (&Patcher);
|
|
|
|
DEBUG ((
|
|
EFI_ERROR (Status) ? DEBUG_WARN : DEBUG_INFO,
|
|
"OC: Prelink blocker %a - %r\n",
|
|
Target,
|
|
Status
|
|
));
|
|
}
|
|
}
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
OcKernelProcessPrelinked (
|
|
IN OC_GLOBAL_CONFIG *Config,
|
|
IN CONST CHAR8 *DarwinVersion,
|
|
IN OUT UINT8 *Kernel,
|
|
IN UINT32 *KernelSize,
|
|
IN UINT32 AllocatedSize
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
PRELINKED_CONTEXT Context;
|
|
CHAR8 *BundlePath;
|
|
CHAR8 *ExecutablePath;
|
|
UINT32 Index;
|
|
CHAR8 FullPath[128];
|
|
OC_KERNEL_ADD_ENTRY *Kext;
|
|
CONST CHAR8 *MatchKernel;
|
|
|
|
Status = PrelinkedContextInit (&Context, Kernel, *KernelSize, AllocatedSize);
|
|
|
|
if (!EFI_ERROR (Status)) {
|
|
OcKernelApplyPatches (Config, DarwinVersion, &Context, NULL, 0);
|
|
|
|
OcKernelBlockKexts (Config, DarwinVersion, &Context);
|
|
|
|
Status = PrelinkedInjectPrepare (&Context);
|
|
if (!EFI_ERROR (Status)) {
|
|
|
|
for (Index = 0; Index < Config->Kernel.Add.Count; ++Index) {
|
|
Kext = Config->Kernel.Add.Values[Index];
|
|
|
|
if (!Kext->Enabled || Kext->PlistDataSize == 0) {
|
|
continue;
|
|
}
|
|
|
|
BundlePath = OC_BLOB_GET (&Kext->BundlePath);
|
|
MatchKernel = OC_BLOB_GET (&Kext->MatchKernel);
|
|
|
|
if (AsciiStrnCmp (DarwinVersion, MatchKernel, AsciiStrLen (MatchKernel)) != 0) {
|
|
DEBUG ((
|
|
DEBUG_INFO,
|
|
"OC: Prelink injection skips %a kext at %u due to version %a vs %a",
|
|
BundlePath,
|
|
Index,
|
|
MatchKernel,
|
|
DarwinVersion
|
|
));
|
|
continue;
|
|
}
|
|
|
|
AsciiSPrint (FullPath, sizeof (FullPath), "/Library/Extensions/%a", BundlePath);
|
|
if (Kext->ImageData != NULL) {
|
|
ExecutablePath = OC_BLOB_GET (&Kext->ExecutablePath);
|
|
} else {
|
|
ExecutablePath = NULL;
|
|
}
|
|
|
|
Status = PrelinkedInjectKext (
|
|
&Context,
|
|
FullPath,
|
|
Kext->PlistData,
|
|
Kext->PlistDataSize,
|
|
ExecutablePath,
|
|
Kext->ImageData,
|
|
Kext->ImageDataSize
|
|
);
|
|
|
|
DEBUG ((
|
|
EFI_ERROR (Status) ? DEBUG_WARN : DEBUG_INFO,
|
|
"OC: Prelink injection %a - %r\n",
|
|
BundlePath,
|
|
Status
|
|
));
|
|
}
|
|
|
|
Status = PrelinkedInjectComplete (&Context);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_WARN, "OC: Prelink insertion error - %r\n", Status));
|
|
}
|
|
} else {
|
|
DEBUG ((DEBUG_WARN, "OC: Prelink inject prepare error - %r\n", Status));
|
|
}
|
|
|
|
*KernelSize = Context.PrelinkedSize;
|
|
|
|
PrelinkedContextFree (&Context);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
STATIC
|
|
EFI_STATUS
|
|
EFIAPI
|
|
OcKernelFileOpen (
|
|
IN EFI_FILE_PROTOCOL *This,
|
|
OUT EFI_FILE_PROTOCOL **NewHandle,
|
|
IN CHAR16 *FileName,
|
|
IN UINT64 OpenMode,
|
|
IN UINT64 Attributes
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT8 *Kernel;
|
|
UINT32 KernelSize;
|
|
UINT32 AllocatedSize;
|
|
CHAR16 *FileNameCopy;
|
|
EFI_FILE_PROTOCOL *VirtualFileHandle;
|
|
EFI_STATUS PrelinkedStatus;
|
|
EFI_TIME ModificationTime;
|
|
CHAR8 DarwinVersion[16];
|
|
|
|
Status = This->Open (This, NewHandle, FileName, OpenMode, Attributes);
|
|
|
|
DEBUG ((
|
|
DEBUG_VERBOSE,
|
|
"Opening file %s with %u mode gave - %r\n",
|
|
FileName,
|
|
(UINT32) OpenMode,
|
|
Status
|
|
));
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// boot.efi uses /S/L/K/kernel as is to determine valid filesystem.
|
|
// Just skip it to speedup the boot process.
|
|
// On 10.9 mach_kernel is loaded for manual linking aferwards, so we cannot skip it.
|
|
//
|
|
if (OpenMode == EFI_FILE_MODE_READ
|
|
&& StrStr (FileName, L"kernel") != NULL
|
|
&& StrCmp (FileName, L"System\\Library\\Kernels\\kernel") != 0) {
|
|
|
|
DEBUG ((DEBUG_INFO, "Trying XNU hook on %s\n", FileName));
|
|
Status = ReadAppleKernel (
|
|
*NewHandle,
|
|
&Kernel,
|
|
&KernelSize,
|
|
&AllocatedSize,
|
|
OcKernelLoadKextsAndReserve (mOcStorage, mOcConfiguration)
|
|
);
|
|
DEBUG ((DEBUG_INFO, "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)) {
|
|
OcKernelReadDarwinVersion (Kernel, KernelSize, DarwinVersion, sizeof (DarwinVersion));
|
|
OcKernelApplyPatches (mOcConfiguration, DarwinVersion, NULL, Kernel, KernelSize);
|
|
|
|
PrelinkedStatus = OcKernelProcessPrelinked (
|
|
mOcConfiguration,
|
|
DarwinVersion,
|
|
Kernel,
|
|
&KernelSize,
|
|
AllocatedSize
|
|
);
|
|
|
|
DEBUG ((DEBUG_INFO, "Prelinked status - %r\n", PrelinkedStatus));
|
|
|
|
Status = GetFileModifcationTime (*NewHandle, &ModificationTime);
|
|
if (EFI_ERROR (Status)) {
|
|
ZeroMem (&ModificationTime, sizeof (ModificationTime));
|
|
}
|
|
|
|
(*NewHandle)->Close(*NewHandle);
|
|
|
|
//
|
|
// 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_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
Status = CreateVirtualFile (FileNameCopy, Kernel, KernelSize, &ModificationTime, &VirtualFileHandle);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_WARN, "Failed to virtualise kernel file (%a)\n", FileName));
|
|
FreePool (Kernel);
|
|
FreePool (FileNameCopy);
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
//
|
|
// Return our handle.
|
|
//
|
|
*NewHandle = VirtualFileHandle;
|
|
return EFI_SUCCESS;
|
|
}
|
|
}
|
|
|
|
//
|
|
// We recurse the filtering to additionally catch com.apple.boot.[RPS] directories.
|
|
//
|
|
return CreateRealFile (*NewHandle, OcKernelFileOpen, TRUE, NewHandle);
|
|
}
|
|
|
|
VOID
|
|
OcLoadKernelSupport (
|
|
IN OC_STORAGE_CONTEXT *Storage,
|
|
IN OC_GLOBAL_CONFIG *Config,
|
|
IN OC_CPU_INFO *CpuInfo
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
Status = EnableVirtualFs (gBS, OcKernelFileOpen);
|
|
|
|
if (!EFI_ERROR (Status)) {
|
|
mOcStorage = Storage;
|
|
mOcConfiguration = Config;
|
|
mOcCpuInfo = CpuInfo;
|
|
} else {
|
|
DEBUG ((DEBUG_ERROR, "OC: Failed to enable vfs - %r\n", Status));
|
|
}
|
|
}
|
|
|
|
VOID
|
|
OcUnloadKernelSupport (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
if (mOcStorage != NULL) {
|
|
Status = DisableVirtualFs (gBS);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_ERROR, "OC: Failed to disable vfs - %r\n", Status));
|
|
}
|
|
mOcStorage = NULL;
|
|
mOcConfiguration = NULL;
|
|
}
|
|
}
|