1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/zsl588-OpenCorePkg

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
OpenCoreKernel.c 41 КБ
Копировать Редактировать Исходные данные Просмотреть построчно История
Marvin Häuser Отправлено 4 лет назад 3db6e1b
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552
/** @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 <Base.h>
#include <Library/OcMainLib.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/OcAfterBootCompatLib.h>
#include <Library/OcAppleKernelLib.h>
#include <Library/OcMiscLib.h>
#include <Library/OcAppleImg4Lib.h>
#include <Library/OcStringLib.h>
#include <Library/OcVirtualFsLib.h>
#include <Library/PrintLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
STATIC OC_STORAGE_CONTEXT *mOcStorage;
STATIC OC_GLOBAL_CONFIG *mOcConfiguration;
STATIC OC_CPU_INFO *mOcCpuInfo;
STATIC UINT8 mKernelDigest[SHA384_DIGEST_SIZE];
STATIC UINT32 mOcDarwinVersion;
STATIC BOOLEAN mUse32BitKernel;
STATIC CACHELESS_CONTEXT mOcCachelessContext;
STATIC BOOLEAN mOcCachelessInProgress;
STATIC EFI_FILE_PROTOCOL *mCustomKernelDirectory;
STATIC BOOLEAN mCustomKernelDirectoryInProgress;
STATIC
VOID
OcKernelConfigureCapabilities (
IN OUT EFI_LOADED_IMAGE_PROTOCOL *LoadedImage,
IN UINT32 Capabilities
)
{
CONST CHAR8 *KernelArch;
CHAR8 *AppleArchValue;
CONST CHAR8 *NewArguments[2];
UINT32 ArgumentCount;
UINT32 RequestedArch;
BOOLEAN HasAppleArch;
UINT32 KernelVersion;
BOOLEAN IsSnowLeo;
BOOLEAN IsLion;
DEBUG ((DEBUG_VERBOSE, "OC: Supported boot capabilities %u\n", Capabilities));
//
// Reset to the default value.
// Capabilities will always have K64 stripped when compiled for IA32.
//
mUse32BitKernel = (Capabilities & OC_KERN_CAPABILITY_K64_U64) == 0;
//
// Skip if not Apple image.
//
if (LoadedImage->FilePath == NULL
|| (OcGetBootDevicePathType (LoadedImage->FilePath, NULL, NULL) & OC_BOOT_APPLE_ANY) == 0) {
return;
}
//
// arch boot argument overrides any compatibility checks.
//
HasAppleArch = OcCheckArgumentFromEnv (
LoadedImage,
gRT->GetVariable,
"arch=",
L_STR_LEN ("arch="),
&AppleArchValue
);
if (HasAppleArch) {
mUse32BitKernel = AsciiStrCmp (AppleArchValue, "i386") == 0;
DEBUG ((DEBUG_INFO, "OC: Arch %a overrides capabilities %u\n", AppleArchValue, Capabilities));
FreePool (AppleArchValue);
return;
}
//
// Determine the current operating system.
//
IsSnowLeo = FALSE;
IsLion = FALSE;
if ((Capabilities & OC_KERN_CAPABILITY_ALL) == OC_KERN_CAPABILITY_ALL) {
KernelVersion = KERNEL_VERSION_SNOW_LEOPARD_MIN;
IsSnowLeo = TRUE;
} else if ((Capabilities & OC_KERN_CAPABILITY_ALL) == OC_KERN_CAPABILITY_K32_K64_U64) {
KernelVersion = KERNEL_VERSION_LION_MIN;
IsLion = TRUE;
} else if ((Capabilities & OC_KERN_CAPABILITY_ALL) == OC_KERN_CAPABILITY_K32_U32_U64) {
KernelVersion = KERNEL_VERSION_LEOPARD_MIN;
} else {
KernelVersion = KERNEL_VERSION_MOUNTAIN_LION_MIN;
}
//
// Determine requested arch.
//
// There are issues with booting with -legacy on 10.4 and 10.5, and EFI64.
// We can only use this on 10.6, or on 10.4/10.5 if on EFI32.
//
// i386-user32 is not supported on 10.7, fallback to i386.
//
KernelArch = OC_BLOB_GET (&mOcConfiguration->Kernel.Scheme.KernelArch);
if (AsciiStrCmp (KernelArch, "x86_64") == 0) {
RequestedArch = OC_KERN_CAPABILITY_K64_U64;
} else if (AsciiStrCmp (KernelArch, "i386") == 0) {
RequestedArch = OC_KERN_CAPABILITY_K32_U64;
} else if (AsciiStrCmp (KernelArch, "i386-user32") == 0
#if defined(MDE_CPU_X64)
&& (IsSnowLeo || IsLion)
#endif
) {
if (!IsLion) {
RequestedArch = OC_KERN_CAPABILITY_K32_U32;
} else {
DEBUG ((DEBUG_INFO, "OC: Requested arch i386-user32 is not supported on 10.7, falling back to i386\n"));
RequestedArch = OC_KERN_CAPABILITY_K32_U64;
}
} else {
RequestedArch = 0;
}
//
// In automatic mode, if we do not support SSSE3 and can downgrade to U32, do it.
// See also note above regarding 10.4 and 10.5.
//
if (RequestedArch == 0
#if defined(MDE_CPU_X64)
&& IsSnowLeo
#endif
&& (mOcCpuInfo->ExtFeatures & CPUID_EXTFEATURE_EM64T) != 0
&& (mOcCpuInfo->Features & CPUID_FEATURE_SSSE3) == 0
&& (Capabilities & OC_KERN_CAPABILITY_K32_U32) != 0) {
//
// Should be guaranteed that we support 32-bit kernel with a 64-bit userspace.
//
ASSERT ((Capabilities & OC_KERN_CAPABILITY_K32_U64) != 0);
DEBUG ((DEBUG_INFO, "OC: Missing SSSE3 disables U64 capabilities %u\n", Capabilities));
Capabilities = OC_KERN_CAPABILITY_K32_U32;
}
//
// If we support K64 mode, check whether the board supports it.
//
if ((Capabilities & OC_KERN_CAPABILITY_K64_U64) != 0
&& !OcPlatformIs64BitSupported (KernelVersion)) {
DEBUG ((DEBUG_INFO, "OC: K64 forbidden due to current platform on version %u\n", KernelVersion));
Capabilities &= ~(OC_KERN_CAPABILITY_K64_U64);
}
//
// If we are not choosing the architecture automatically, try to use the requested one.
// Otherwise try best available.
//
if (RequestedArch != 0 && (Capabilities & RequestedArch) != 0) {
Capabilities = RequestedArch;
} else if ((Capabilities & OC_KERN_CAPABILITY_K64_U64) != 0) {
Capabilities = OC_KERN_CAPABILITY_K64_U64;
} else if ((Capabilities & OC_KERN_CAPABILITY_K32_U64) != 0) {
Capabilities = OC_KERN_CAPABILITY_K32_U64;
} else if ((Capabilities & OC_KERN_CAPABILITY_K32_U32) != 0) {
Capabilities = OC_KERN_CAPABILITY_K32_U32;
} else {
ASSERT (FALSE);
}
//
// Pass arch argument when we are:
// - SnowLeo64 and try to boot x86_64.
// - SnowLeo64 or Lion64 and try to boot i386.
//
ArgumentCount = 0;
if (Capabilities == OC_KERN_CAPABILITY_K64_U64 && IsSnowLeo) {
NewArguments[ArgumentCount++] = "arch=x86_64";
} else if (Capabilities != OC_KERN_CAPABILITY_K64_U64 && (IsSnowLeo || IsLion)) {
NewArguments[ArgumentCount++] = "arch=i386";
}
//
// Pass legacy argument when we are booting i386.
//
if (Capabilities == OC_KERN_CAPABILITY_K32_U32
&& !OcCheckArgumentFromEnv (LoadedImage, gRT->GetVariable, "-legacy", L_STR_LEN ("-legacy"), NULL)) {
NewArguments[ArgumentCount++] = "-legacy";
}
//
// Update argument list.
//
if (ArgumentCount > 0) {
OcAppendArgumentsToLoadedImage (
LoadedImage,
&NewArguments[0],
ArgumentCount,
FALSE
);
}
//
// If we do not support K64 for this target, force 32.
//
if ((Capabilities & OC_KERN_CAPABILITY_K64_U64) == 0) {
mUse32BitKernel = TRUE;
}
}
STATIC
VOID
OcKernelLoadAndReserveKext (
IN OC_KERNEL_ADD_ENTRY *Kext,
IN UINT32 Index,
IN BOOLEAN IsForced,
IN EFI_FILE_PROTOCOL *RootFile,
IN OC_STORAGE_CONTEXT *Storage,
IN OC_GLOBAL_CONFIG *Config,
IN KERNEL_CACHE_TYPE CacheType,
IN BOOLEAN Is32Bit,
IN OUT UINT32 *ReservedExeSize,
IN OUT UINT32 *ReservedInfoSize,
IN OUT UINT32 *NumReservedKexts
)
{
EFI_STATUS Status;
CHAR8 *Identifier;
CHAR8 *BundlePath;
CHAR8 *Comment;
CONST CHAR8 *Arch;
CHAR8 *PlistPath;
CHAR8 *ExecutablePath;
CHAR16 FullPath[OC_STORAGE_SAFE_PATH_MAX];
if (!Kext->Enabled) {
return;
}
//
// Free existing data if present, but only for forced kexts.
// Injected kexts will never change.
//
if (IsForced && Kext->PlistData != NULL) {
FreePool (Kext->PlistData);
Kext->PlistDataSize = 0;
Kext->PlistData = NULL;
if (Kext->ImageData != NULL) {
FreePool (Kext->ImageData);
Kext->ImageDataSize = 0;
Kext->ImageData = NULL;
}
}
Identifier = OC_BLOB_GET (&Kext->Identifier);
BundlePath = OC_BLOB_GET (&Kext->BundlePath);
Comment = OC_BLOB_GET (&Kext->Comment);
Arch = OC_BLOB_GET (&Kext->Arch);
PlistPath = OC_BLOB_GET (&Kext->PlistPath);
if (BundlePath[0] == '\0' || PlistPath[0] == '\0' || (IsForced && Identifier[0] == '\0')) {
DEBUG ((
DEBUG_ERROR,
"OC: %s kext %u (%a) has invalid info\n",
IsForced ? L"Forced" : L"Injected",
Index,
Comment
));
Kext->Enabled = FALSE;
return;
}
if (AsciiStrCmp (Arch, Is32Bit ? "x86_64" : "i386") == 0) {
DEBUG ((
DEBUG_INFO,
"OC: %s kext %a (%a) at %u skipped due to arch %a != %a\n",
IsForced ? L"Forced" : L"Injected",
BundlePath,
Comment,
Index,
Arch,
Is32Bit ? "i386" : "x86_64"
));
return;
}
//
// Required for possible cacheless force injection later on.
//
AsciiUefiSlashes (BundlePath);
//
// Get plist path and data.
//
Status = OcUnicodeSafeSPrint (
FullPath,
sizeof (FullPath),
IsForced ? L"%a\\%a" : OPEN_CORE_KEXT_PATH "%a\\%a",
BundlePath,
PlistPath
);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_WARN,
"OC: Failed to fit %s kext path %s%a\\%a",
IsForced ? L"forced" : L"injected",
IsForced ? L"" : OPEN_CORE_KEXT_PATH,
BundlePath,
PlistPath
));
Kext->Enabled = IsForced;
return;
}
UnicodeUefiSlashes (FullPath);
if (IsForced) {
Kext->PlistData = OcReadFileFromDirectory (
RootFile,
FullPath,
&Kext->PlistDataSize,
0
);
} else {
Kext->PlistData = OcStorageReadFileUnicode (
Storage,
FullPath,
&Kext->PlistDataSize
);
}
if (Kext->PlistData == NULL) {
DEBUG ((
IsForced ? DEBUG_INFO : DEBUG_ERROR,
"OC: Plist %s is missing for %s kext %a (%a)\n",
FullPath,
IsForced ? L"forced" : L"injected",
BundlePath,
Comment
));
Kext->Enabled = IsForced;
return;
}
//
// Get executable path and data, if present.
//
ExecutablePath = OC_BLOB_GET (&Kext->ExecutablePath);
if (ExecutablePath[0] != '\0') {
Status = OcUnicodeSafeSPrint (
FullPath,
sizeof (FullPath),
IsForced ? L"%a\\%a" : OPEN_CORE_KEXT_PATH "%a\\%a",
BundlePath,
ExecutablePath
);
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_WARN,
"OC: Failed to fit %s kext path %s%a\\%a",
IsForced ? L"forced" : L"injected",
IsForced ? L"" : OPEN_CORE_KEXT_PATH,
BundlePath,
ExecutablePath
));
Kext->Enabled = IsForced;
FreePool (Kext->PlistData);
Kext->PlistData = NULL;
return;
}
UnicodeUefiSlashes (FullPath);
if (IsForced) {
Kext->ImageData = OcReadFileFromDirectory (
RootFile,
FullPath,
&Kext->ImageDataSize,
0
);
} else {
Kext->ImageData = OcStorageReadFileUnicode (
Storage,
FullPath,
&Kext->ImageDataSize
);
}
if (Kext->ImageData == NULL) {
DEBUG ((
IsForced ? DEBUG_INFO : DEBUG_ERROR,
"OC: Image %s is missing for %s kext %a (%a)\n",
FullPath,
IsForced ? L"forced" : L"injected",
BundlePath,
Comment
));
Kext->Enabled = IsForced;
FreePool (Kext->PlistData);
Kext->PlistData = NULL;
return;
}
}
if (CacheType == CacheTypeCacheless || CacheType == CacheTypeMkext) {
Status = MkextReserveKextSize (
ReservedInfoSize,
ReservedExeSize,
Kext->PlistDataSize,
Kext->ImageData,
Kext->ImageDataSize,
Is32Bit
);
} else if (CacheType == CacheTypePrelinked) {
Status = PrelinkedReserveKextSize (
ReservedInfoSize,
ReservedExeSize,
Kext->PlistDataSize,
Kext->ImageData,
Kext->ImageDataSize,
Is32Bit
);
}
if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_INFO,
"OC: Failed to fit %s kext %a (%a) - %r\n",
Is32Bit ? L"32-bit" : L"64-bit",
BundlePath,
Comment,
Status
));
if (Kext->ImageData != NULL) {
FreePool (Kext->ImageData);
Kext->ImageData = NULL;
}
FreePool (Kext->PlistData);
Kext->PlistData = NULL;
return;
}
(*NumReservedKexts)++;
}
STATIC
EFI_STATUS
OcKernelLoadKextsAndReserve (
IN EFI_FILE_PROTOCOL *RootFile,
IN OC_STORAGE_CONTEXT *Storage,
IN OC_GLOBAL_CONFIG *Config,
IN KERNEL_CACHE_TYPE CacheType,
IN BOOLEAN Is32Bit,
OUT UINT32 *ReservedExeSize,
OUT UINT32 *ReservedInfoSize,
OUT UINT32 *NumReservedKexts
)
{
UINT32 Index;
OC_KERNEL_ADD_ENTRY *Kext;
*ReservedInfoSize = PRELINK_INFO_RESERVE_SIZE;
*ReservedExeSize = 0;
*NumReservedKexts = 0;
//
// Process system kexts to be force injected.
//
for (Index = 0; Index < Config->Kernel.Force.Count; Index++) {
Kext = Config->Kernel.Force.Values[Index];
OcKernelLoadAndReserveKext (
Kext,
Index,
TRUE,
RootFile,
Storage,
Config,
CacheType,
Is32Bit,
ReservedExeSize,
ReservedInfoSize,
NumReservedKexts
);
}
//
// Process kexts to be injected.
//
for (Index = 0; Index < Config->Kernel.Add.Count; Index++) {
Kext = Config->Kernel.Add.Values[Index];
OcKernelLoadAndReserveKext (
Kext,
Index,
FALSE,
RootFile,
Storage,
Config,
CacheType,
Is32Bit,
ReservedExeSize,
ReservedInfoSize,
NumReservedKexts
);
}
if (CacheType == CacheTypePrelinked) {
if (*ReservedExeSize > PRELINKED_KEXTS_MAX_SIZE
|| *ReservedInfoSize + *ReservedExeSize < *ReservedExeSize) {
return EFI_UNSUPPORTED;
}
}
DEBUG ((
DEBUG_INFO,
"OC: Kext reservation size info %X exe %X\n",
*ReservedInfoSize, *ReservedExeSize
));
return EFI_SUCCESS;
}
STATIC
VOID
OcKernelInjectKext (
IN OC_KERNEL_ADD_ENTRY *Kext,
IN UINT32 Index,
IN BOOLEAN IsForced,
IN KERNEL_CACHE_TYPE CacheType,
IN VOID *Context,
IN UINT32 DarwinVersion,
IN BOOLEAN Is32Bit
)
{
EFI_STATUS Status;
CONST CHAR8 *Identifier;
CONST CHAR8 *BundlePath;
CONST CHAR8 *ExecutablePath;
CONST CHAR8 *Comment;
CHAR8 FullPath[OC_STORAGE_SAFE_PATH_MAX];
UINT32 MaxKernel;
UINT32 MinKernel;
if (!Kext->Enabled || Kext->PlistData == NULL) {
return;
}
Identifier = OC_BLOB_GET (&Kext->Identifier);
BundlePath = OC_BLOB_GET (&Kext->BundlePath);
Comment = OC_BLOB_GET (&Kext->Comment);
MaxKernel = OcParseDarwinVersion (OC_BLOB_GET (&Kext->MaxKernel));
MinKernel = OcParseDarwinVersion (OC_BLOB_GET (&Kext->MinKernel));
if (!OcMatchDarwinVersion (DarwinVersion, MinKernel, MaxKernel)) {
DEBUG ((
DEBUG_INFO,
"OC: %a%a injection skips %a (%a) kext at %u due to version %u <= %u <= %u\n",
PRINT_KERNEL_CACHE_TYPE (CacheType),
IsForced ? " force" : "",
BundlePath,
Comment,
Index,
MinKernel,
DarwinVersion,
MaxKernel
));
return;
}
if (Kext->ImageData != NULL) {
ExecutablePath = OC_BLOB_GET (&Kext->ExecutablePath);
} else {
ExecutablePath = NULL;
}
if (!IsForced) {
Status = OcAsciiSafeSPrint (FullPath, sizeof (FullPath), "/Library/Extensions/%a", BundlePath);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "OC: Failed to fit kext path /Library/Extensions/%a", BundlePath));
return;
}
}
if (CacheType == CacheTypeCacheless) {
if (IsForced
&& AsciiStrnCmp (BundlePath, "System\\Library\\Extensions", L_STR_LEN ("System\\Library\\Extensions")) == 0) {
Status = CachelessContextForceKext (Context, Identifier);
} else {
Status = CachelessContextAddKext (
Context,
Kext->PlistData,
Kext->PlistDataSize,
Kext->ImageData,
Kext->ImageDataSize
);
}
} else if (CacheType == CacheTypeMkext) {
Status = MkextInjectKext (
Context,
IsForced ? Identifier : NULL,
IsForced ? BundlePath : FullPath,
Kext->PlistData,
Kext->PlistDataSize,
Kext->ImageData,
Kext->ImageDataSize
);
} else if (CacheType == CacheTypePrelinked) {
Status = PrelinkedInjectKext (
Context,
IsForced ? Identifier : NULL,
IsForced ? BundlePath : FullPath,
Kext->PlistData,
Kext->PlistDataSize,
ExecutablePath,
Kext->ImageData,
Kext->ImageDataSize
);
} else {
Status = EFI_UNSUPPORTED;
}
DEBUG ((
!IsForced && EFI_ERROR (Status) ? DEBUG_WARN : DEBUG_INFO,
"OC: %a%a injection %a (%a) - %r\n",
PRINT_KERNEL_CACHE_TYPE (CacheType),
IsForced ? " force" : "",
BundlePath,
Comment,
Status
));
}
STATIC
VOID
OcKernelInjectKexts (
IN OC_GLOBAL_CONFIG *Config,
IN KERNEL_CACHE_TYPE CacheType,
IN VOID *Context,
IN UINT32 DarwinVersion,
IN BOOLEAN Is32Bit,
IN UINT32 LinkedExpansion,
IN UINT32 ReservedExeSize
)
{
EFI_STATUS Status;
UINT32 Index;
if (CacheType == CacheTypePrelinked) {
Status = PrelinkedInjectPrepare (
Context,
LinkedExpansion,
ReservedExeSize
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "OC: Prelink inject prepare error - %r\n", Status));
return;
}
}
//
// Process system kexts to be force injected.
//
for (Index = 0; Index < Config->Kernel.Force.Count; Index++) {
OcKernelInjectKext (
Config->Kernel.Force.Values[Index],
Index,
TRUE,
CacheType,
Context,
DarwinVersion,
Is32Bit
);
}
//
// Process kexts to be injected.
//
for (Index = 0; Index < Config->Kernel.Add.Count; Index++) {
OcKernelInjectKext (
Config->Kernel.Add.Values[Index],
Index,
FALSE,
CacheType,
Context,
DarwinVersion,
Is32Bit
);
}
if (CacheType == CacheTypeCacheless || CacheType == CacheTypeMkext) {
Status = EFI_SUCCESS;
} else if (CacheType == CacheTypePrelinked) {
DEBUG ((
DEBUG_INFO,
"OC: Prelink size %u kext offset %u reserved %u\n",
((PRELINKED_CONTEXT *) Context)->PrelinkedSize,
((PRELINKED_CONTEXT *) Context)->KextsFileOffset,
ReservedExeSize
));
ASSERT (
((PRELINKED_CONTEXT *) Context)->PrelinkedSize -
((PRELINKED_CONTEXT *) Context)->KextsFileOffset <= ReservedExeSize
);
Status = PrelinkedInjectComplete (Context);
} else {
Status = EFI_UNSUPPORTED;
}
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "OC: %a insertion error - %r\n", PRINT_KERNEL_CACHE_TYPE (CacheType), Status));
}
}
STATIC
EFI_STATUS
OcKernelProcessPrelinked (
IN OC_GLOBAL_CONFIG *Config,
IN UINT32 DarwinVersion,
IN BOOLEAN Is32Bit,
IN OUT UINT8 *Kernel,
IN UINT32 *KernelSize,
IN UINT32 AllocatedSize,
IN UINT32 LinkedExpansion,
IN UINT32 ReservedExeSize
)
{
EFI_STATUS Status;
PRELINKED_CONTEXT Context;
Status = PrelinkedContextInit (&Context, Kernel, *KernelSize, AllocatedSize, Is32Bit);
if (!EFI_ERROR (Status)) {
OcKernelInjectKexts (Config, CacheTypePrelinked, &Context, DarwinVersion, Is32Bit, LinkedExpansion, ReservedExeSize);
OcKernelApplyPatches (Config, mOcCpuInfo, DarwinVersion, Is32Bit, CacheTypePrelinked, &Context, NULL, 0);
OcKernelBlockKexts (Config, DarwinVersion, Is32Bit, CacheTypePrelinked, &Context);
*KernelSize = Context.PrelinkedSize;
PrelinkedContextFree (&Context);
}
return Status;
}
STATIC
EFI_STATUS
OcKernelProcessMkext (
IN OC_GLOBAL_CONFIG *Config,
IN UINT32 DarwinVersion,
IN BOOLEAN Is32Bit,
IN OUT UINT8 *Mkext,
IN OUT UINT32 *MkextSize,
IN UINT32 AllocatedSize
)
{
EFI_STATUS Status;
MKEXT_CONTEXT Context;
Status = MkextContextInit (&Context, Mkext, *MkextSize, AllocatedSize);
if (EFI_ERROR (Status)) {
return Status;
}
OcKernelInjectKexts (Config, CacheTypeMkext, &Context, DarwinVersion, Is32Bit, 0, 0);
OcKernelApplyPatches (Config, mOcCpuInfo, DarwinVersion, Is32Bit, CacheTypeMkext, &Context, NULL, 0);
OcKernelBlockKexts (Config, DarwinVersion, Is32Bit, CacheTypeMkext, &Context);
MkextInjectPatchComplete (&Context);
*MkextSize = Context.MkextSize;
MkextContextFree (&Context);
return Status;
}
STATIC
EFI_STATUS
OcKernelInitCacheless (
IN OC_GLOBAL_CONFIG *Config,
IN CACHELESS_CONTEXT *Context,
IN UINT32 DarwinVersion,
IN BOOLEAN Is32Bit,
IN CHAR16 *FileName,
IN EFI_FILE_PROTOCOL *ExtensionsDir,
OUT EFI_FILE_PROTOCOL **File
)
{
EFI_STATUS Status;
Status = CachelessContextInit (
Context,
FileName,
ExtensionsDir,
DarwinVersion,
Is32Bit
);
if (EFI_ERROR (Status)) {
return Status;
}
OcKernelInjectKexts (Config, CacheTypeCacheless, Context, DarwinVersion, Is32Bit, 0, 0);
OcKernelApplyPatches (Config, mOcCpuInfo, DarwinVersion, Is32Bit, CacheTypeCacheless, Context, NULL, 0);
OcKernelBlockKexts (Config, DarwinVersion, Is32Bit, CacheTypeCacheless, Context);
return CachelessContextOverlayExtensionsDir (Context, File);
}
STATIC
EFI_STATUS
OcKernelReadAppleKernel (
IN EFI_FILE_PROTOCOL *RootFile,
IN EFI_FILE_PROTOCOL *KernelFile,
IN CHAR16 *FileName,
IN BOOLEAN Is32Bit,
IN OUT UINT32 *DarwinVersion,
OUT UINT8 **Kernel,
OUT UINT32 *KernelSize,
OUT UINT32 *AllocatedSize,
OUT UINT32 *ReservedExeSize,
OUT UINT32 *LinkedExpansion,
OUT UINT8 *Digest OPTIONAL
)
{
EFI_STATUS Status;
BOOLEAN Result;
UINT32 DarwinVersionNew;
BOOLEAN IsKernel32Bit;
UINT32 ReservedInfoSize;
UINT32 NumReservedKexts;
UINT32 ReservedFullSize;
OcKernelLoadKextsAndReserve (
RootFile,
mOcStorage,
mOcConfiguration,
CacheTypePrelinked,
Is32Bit,
ReservedExeSize,
&ReservedInfoSize,
&NumReservedKexts
);
*LinkedExpansion = KcGetSegmentFixupChainsSize (*ReservedExeSize);
if (*LinkedExpansion == 0) {
return EFI_UNSUPPORTED;
}
Result = OcOverflowTriAddU32 (
ReservedInfoSize,
*ReservedExeSize,
*LinkedExpansion,
&ReservedFullSize
);
if (Result) {
return EFI_UNSUPPORTED;
}
//
// Read last requested architecture for kernel.
//
DEBUG ((DEBUG_INFO, "OC: Trying %a XNU hook on %s\n", Is32Bit ? "32-bit" : "64-bit", FileName));
Status = ReadAppleKernel (
KernelFile,
Is32Bit,
&IsKernel32Bit,
Kernel,
KernelSize,
AllocatedSize,
ReservedFullSize,
Digest
);
DEBUG ((
DEBUG_INFO,
"OC: Result of %a XNU hook on %s (%02X%02X%02X%02X) is %r\n",
IsKernel32Bit ? "32-bit" : "64-bit",
FileName,
Digest != NULL ? Digest[0] : 0,
Digest != NULL ? Digest[1] : 0,
Digest != NULL ? Digest[2] : 0,
Digest != NULL ? Digest[3] : 0,
Status
));
if (!EFI_ERROR (Status)) {
//
// 10.6 and below may keep older prelinkedkernels around, do not load those.
//
DarwinVersionNew = OcKernelReadDarwinVersion (*Kernel, *KernelSize);
if (DarwinVersionNew < *DarwinVersion) {
FreePool (*Kernel);
*Kernel = NULL;
return EFI_INVALID_PARAMETER;
}
//
// If we failed to obtain the requested bitness for the platform, abort.
//
if (Is32Bit != IsKernel32Bit) {
DEBUG ((DEBUG_WARN, "OC: %a kernel architecture is not available, aborting.\n", Is32Bit ? "32-bit" : "64-bit"));
FreePool (*Kernel);
*Kernel = NULL;
return EFI_NOT_FOUND;
}
*DarwinVersion = DarwinVersionNew;
}
return Status;
}
STATIC
EFI_STATUS
OcKernelFuzzyMatch (
IN EFI_FILE_PROTOCOL *RootFile,
IN CHAR16 *FileName,
IN UINT64 OpenMode,
IN UINT64 Attributes,
IN BOOLEAN Is32Bit,
IN OUT UINT32 *DarwinVersion,
OUT EFI_FILE_PROTOCOL **KernelFile,
OUT UINT8 **Kernel,
OUT UINT32 *KernelSize,
OUT UINT32 *AllocatedSize,
OUT UINT32 *ReservedExeSize,
OUT UINT32 *LinkedExpansion,
OUT UINT8 *Digest OPTIONAL
)
{
EFI_STATUS Status;
EFI_FILE_PROTOCOL *FileDirectory;
CHAR16 *FileNameDir;
UINTN FileNameDirLength;
EFI_FILE_INFO *FileInfo;
EFI_FILE_INFO *FileInfoNext;
CHAR16 *FileNameCacheNew;
UINTN FileNameCacheNewLength;
UINTN FileNameCacheNewSize;
DIRECTORY_SEARCH_CONTEXT Context;
FileInfo = NULL;
FileNameCacheNew = NULL;
//
// Open parent directory.
//
FileNameDirLength = OcStriStr (FileName, L"\\kernelcache") - FileName;
FileNameDir = AllocateZeroPool (StrnSizeS (FileName, FileNameDirLength));
if (FileNameDir == NULL) {
return EFI_OUT_OF_RESOURCES;
}
CopyMem (FileNameDir, FileName, StrnSizeS (FileName, FileNameDirLength) - sizeof (*FileName));
Status = OcSafeFileOpen (RootFile, &FileDirectory, FileNameDir, EFI_FILE_MODE_READ, 0);
if (EFI_ERROR (Status)) {
FreePool (FileNameDir);
return Status;
}
//
// Search for kernelcache files, trying each one.
//
OcDirectorySeachContextInit (&Context);
do {
Status = OcGetNewestFileFromDirectory (
&Context,
FileDirectory,
L"kernelcache",
&FileInfoNext
);
if (EFI_ERROR (Status)) {
break;
}
if (FileInfo != NULL) {
FreePool (FileInfo);
}
if (FileNameCacheNew != NULL) {
FreePool (FileNameCacheNew);
}
FileInfo = FileInfoNext;
FileNameCacheNewLength = FileNameDirLength + L_STR_LEN ("\\") + StrLen (FileInfo->FileName);
FileNameCacheNewSize = (FileNameCacheNewLength + 1) * sizeof (*FileNameCacheNew);
FileNameCacheNew = AllocateZeroPool (FileNameCacheNewSize);
if (FileNameCacheNew == NULL) {
Status = EFI_OUT_OF_RESOURCES;
break;
}
Status = OcUnicodeSafeSPrint (FileNameCacheNew, FileNameCacheNewSize, L"%s\\%s", FileNameDir, FileInfo->FileName);
if (EFI_ERROR (Status)) {
break;
}
Status = OcSafeFileOpen (RootFile, KernelFile, FileNameCacheNew, OpenMode, Attributes);
if (EFI_ERROR (Status)) {
continue;
}
Status = OcKernelReadAppleKernel (
RootFile,
*KernelFile,
FileNameCacheNew,
Is32Bit,
DarwinVersion,
Kernel,
KernelSize,
AllocatedSize,
ReservedExeSize,
LinkedExpansion,
Digest
);
} while (EFI_ERROR (Status));
if (FileInfo != NULL) {
FreePool (FileInfo);
}
if (FileNameCacheNew != NULL) {
FreePool (FileNameCacheNew);
}
FreePool (FileNameDir);
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;
BOOLEAN Result;
CONST CHAR8 *ForceCacheType;
CONST CHAR8 *SecureBootModel;
KERNEL_CACHE_TYPE MaxCacheTypeAllowed;
BOOLEAN UseSecureBoot;
UINT8 *Kernel;
UINT32 KernelSize;
UINT32 AllocatedSize;
EFI_FILE_PROTOCOL *VirtualFileHandle;
EFI_STATUS PrelinkedStatus;
EFI_TIME ModificationTime;
UINT32 ReservedInfoSize;
UINT32 ReservedExeSize;
UINT32 NumReservedKexts;
UINT32 LinkedExpansion;
UINT32 ReservedFullSize;
CHAR16 *NewFileName;
EFI_FILE_PROTOCOL *EspNewHandle;
if (mCustomKernelDirectoryInProgress) {
DEBUG ((DEBUG_INFO, "OC: Skipping OpenFile hooking on ESP Kernels directory\n"));
return OcSafeFileOpen (This, NewHandle, FileName, OpenMode, Attributes);
}
//
// Prevent access to cache files depending on maximum cache type allowed.
//
ForceCacheType = OC_BLOB_GET (&mOcConfiguration->Kernel.Scheme.KernelCache);
if (AsciiStrCmp (ForceCacheType, "Cacheless") == 0) {
MaxCacheTypeAllowed = CacheTypeCacheless;
} else if (AsciiStrCmp (ForceCacheType, "Mkext") == 0) {
MaxCacheTypeAllowed = CacheTypeMkext;
} else if (AsciiStrCmp (ForceCacheType, "Prelinked") == 0) {
MaxCacheTypeAllowed = CacheTypePrelinked;
} else {
MaxCacheTypeAllowed = CacheTypeNone;
}
//
// We only want to calculate kernel hashes if secure boot is enabled.
//
SecureBootModel = OC_BLOB_GET (&mOcConfiguration->Misc.Security.SecureBootModel);
UseSecureBoot = AsciiStrCmp (SecureBootModel, OC_SB_MODEL_DISABLED) != 0;
//
// Hook injected OcXXXXXXXX.kext reads from /S/L/E.
//
if (mOcCachelessInProgress
&& OpenMode == EFI_FILE_MODE_READ
&& StrnCmp (FileName, L"System\\Library\\Extensions\\Oc", L_STR_LEN (L"System\\Library\\Extensions\\Oc")) == 0) {
Status = CachelessContextPerformInject (&mOcCachelessContext, FileName, NewHandle);
DEBUG ((
DEBUG_INFO,
"OC: Hooking SLE injected file %s with %u mode gave - %r\n",
FileName,
(UINT32) OpenMode,
Status
));
return Status;
}
Status = OcSafeFileOpen (This, NewHandle, FileName, OpenMode, Attributes);
DEBUG ((
DEBUG_VERBOSE,
"OC: Opening file %s with %u mode gave - %r\n",
FileName,
(UINT32) OpenMode,
Status
));
//
// Hook kernelcache read attempts for fuzzy kernelcache matching.
// Only hook if the desired kernelcache file does not exist.
//
Kernel = NULL;
if (mOcConfiguration->Kernel.Scheme.FuzzyMatch
&& Status == EFI_NOT_FOUND
&& OpenMode == EFI_FILE_MODE_READ
&& (StrStr (FileName, L"\\kernelcache") != NULL)) {
//
// Change the target to the custom one if requested CustomKernel.
//
if (mCustomKernelDirectory != NULL) {
DEBUG ((DEBUG_INFO, "OC: Redirecting %s to the custom one on ESP\n", FileName));
NewFileName = OcStrrChr (FileName, L'\\');
if (NewFileName == NULL) {
NewFileName = FileName;
}
DEBUG ((DEBUG_INFO, "OC: Filename after redirection: %s\n", NewFileName));
This = mCustomKernelDirectory;
FileName = NewFileName;
}
DEBUG ((DEBUG_INFO, "OC: Trying kernelcache fuzzy matching on %s\n", FileName));
Status = OcKernelFuzzyMatch (
This,
FileName,
OpenMode,
Attributes,
mUse32BitKernel,
&mOcDarwinVersion,
NewHandle,
&Kernel,
&KernelSize,
&AllocatedSize,
&ReservedExeSize,
&LinkedExpansion,
UseSecureBoot ? mKernelDigest : NULL
);
}
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.
// We also want to skip files named "kernel" that are part of kext bundles, and im4m.
//
if (OpenMode == EFI_FILE_MODE_READ
&& OcStriStr (FileName, L"kernel") != NULL
&& StrCmp (FileName, L"System\\Library\\Kernels\\kernel") != 0
&& OcStriStr (FileName, L".kext\\") == NULL
&& OcStriStr (FileName, L".im4m") == NULL) {
//
// Change the target to the custom one if requested CustomKernel.
//
if (mCustomKernelDirectory != NULL) {
DEBUG ((DEBUG_INFO, "OC: Redirecting %s to the custom one on ESP\n", FileName));
NewFileName = OcStrrChr (FileName, L'\\');
if (NewFileName == NULL) {
NewFileName = FileName;
}
DEBUG ((DEBUG_INFO, "OC: Filename after redirection: %s\n", NewFileName));
mCustomKernelDirectoryInProgress = TRUE;
Status = OcSafeFileOpen (mCustomKernelDirectory, &EspNewHandle, NewFileName, OpenMode, Attributes);
mCustomKernelDirectoryInProgress = FALSE;
if (!EFI_ERROR (Status)) {
(*NewHandle)->Close (*NewHandle);
This = mCustomKernelDirectory;
*NewHandle = EspNewHandle;
FileName = NewFileName;
}
}
//
// Kernel loading for fuzzy kernelcache is performed earlier.
//
if (Kernel == NULL) {
Status = OcKernelReadAppleKernel (
This,
*NewHandle,
FileName,
mUse32BitKernel,
&mOcDarwinVersion,
&Kernel,
&KernelSize,
&AllocatedSize,
&ReservedExeSize,
&LinkedExpansion,
UseSecureBoot ? mKernelDigest : NULL
);
if (Status == EFI_NOT_FOUND) {
(*NewHandle)->Close (*NewHandle);
*NewHandle = NULL;
return Status;
}
}
if (!EFI_ERROR (Status)) {
//
// Disable prelinked if forcing mkext or cacheless, but only on appropriate versions.
// We also disable prelinked on 10.5 or older due to prelinked on those versions being unsupported.
//
if ((OcStriStr (FileName, L"kernelcache") != NULL || OcStriStr (FileName, L"prelinkedkernel") != NULL)
&& ((MaxCacheTypeAllowed == CacheTypeNone && mOcDarwinVersion <= KERNEL_VERSION_LEOPARD_MAX)
|| (MaxCacheTypeAllowed == CacheTypeMkext && mOcDarwinVersion <= KERNEL_VERSION_SNOW_LEOPARD_MAX)
|| (MaxCacheTypeAllowed == CacheTypeCacheless && mOcDarwinVersion <= KERNEL_VERSION_MAVERICKS_MAX))) {
DEBUG ((DEBUG_INFO, "OC: Blocking prelinked due to ForceKernelCache=%a: %s\n", ForceCacheType, FileName));
FreePool (Kernel);
(*NewHandle)->Close (*NewHandle);
*NewHandle = NULL;
return EFI_NOT_FOUND;
}
//
// Apply patches to kernel itself, and then process prelinked.
//
OcKernelApplyPatches (
mOcConfiguration,
mOcCpuInfo,
mOcDarwinVersion,
mUse32BitKernel,
CacheTypeNone,
NULL,
Kernel,
KernelSize
);
PrelinkedStatus = OcKernelProcessPrelinked (
mOcConfiguration,
mOcDarwinVersion,
mUse32BitKernel,
Kernel,
&KernelSize,
AllocatedSize,
LinkedExpansion,
ReservedExeSize
);
DEBUG ((DEBUG_INFO, "OC: Prelinked status - %r\n", PrelinkedStatus));
Status = OcGetFileModificationTime (*NewHandle, &ModificationTime);
if (EFI_ERROR (Status)) {
ZeroMem (&ModificationTime, sizeof (ModificationTime));
}
(*NewHandle)->Close (*NewHandle);
//
// Virtualise newly created kernel.
//
Status = CreateVirtualFileFileNameCopy (FileName, Kernel, KernelSize, &ModificationTime, &VirtualFileHandle);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "OC: Failed to virtualise kernel file (%s) - %r\n", FileName, Status));
FreePool (Kernel);
return EFI_OUT_OF_RESOURCES;
}
if (UseSecureBoot) {
OcAppleImg4RegisterOverride (mKernelDigest, Kernel, KernelSize);
}
//
// Return our handle.
//
*NewHandle = VirtualFileHandle;
return EFI_SUCCESS;
}
}
if (OpenMode == EFI_FILE_MODE_READ
&& OcStriStr (FileName, L"Extensions.mkext") != NULL) {
//
// Disable mkext booting if forcing cacheless.
//
if (MaxCacheTypeAllowed == CacheTypeCacheless) {
DEBUG ((DEBUG_INFO, "OC: Blocking mkext due to ForceKernelCache=%a: %s\n", ForceCacheType, FileName));
(*NewHandle)->Close (*NewHandle);
*NewHandle = NULL;
return EFI_NOT_FOUND;
}
OcKernelLoadKextsAndReserve (
This,
mOcStorage,
mOcConfiguration,
CacheTypeMkext,
mUse32BitKernel,
&ReservedExeSize,
&ReservedInfoSize,
&NumReservedKexts
);
Result = OcOverflowAddU32 (
ReservedInfoSize,
ReservedExeSize,
&ReservedFullSize
);
if (Result) {
return EFI_UNSUPPORTED;
}
DEBUG ((DEBUG_INFO, "OC: Trying %a mkext hook on %s\n", mUse32BitKernel ? "32-bit" : "64-bit", FileName));
Status = ReadAppleMkext (
*NewHandle,
mUse32BitKernel,
&Kernel,
&KernelSize,
&AllocatedSize,
ReservedFullSize,
NumReservedKexts
);
DEBUG ((DEBUG_INFO, "OC: Result of mkext hook on %s is %r\n", FileName, Status));
if (!EFI_ERROR (Status)) {
//
// Process mkext.
//
Status = OcKernelProcessMkext (
mOcConfiguration,
mOcDarwinVersion,
mUse32BitKernel,
Kernel,
&KernelSize,
AllocatedSize
);
DEBUG ((DEBUG_INFO, "OC: Mkext status - %r\n", Status));
if (!EFI_ERROR (Status)) {
Status = OcGetFileModificationTime (*NewHandle, &ModificationTime);
if (EFI_ERROR (Status)) {
ZeroMem (&ModificationTime, sizeof (ModificationTime));
}
(*NewHandle)->Close (*NewHandle);
//
// Virtualise newly created mkext.
//
Status = CreateVirtualFileFileNameCopy (FileName, Kernel, KernelSize, &ModificationTime, &VirtualFileHandle);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_WARN, "OC: Failed to virtualise mkext file (%s) - %r\n", FileName, Status));
FreePool (Kernel);
return EFI_OUT_OF_RESOURCES;
}
*NewHandle = VirtualFileHandle;
return EFI_SUCCESS;
} else {
FreePool (Kernel);
}
}
}
//
// Hook /S/L/E for cacheless boots.
//
if (OpenMode == EFI_FILE_MODE_READ
&& StrCmp (FileName, L"System\\Library\\Extensions") == 0) {
//
// Free existing context if we are re-opening Extensions directory.
//
if (mOcCachelessInProgress) {
CachelessContextFree (&mOcCachelessContext);
}
mOcCachelessInProgress = FALSE;
OcKernelLoadKextsAndReserve (
This,
mOcStorage,
mOcConfiguration,
CacheTypeCacheless,
mUse32BitKernel,
&ReservedExeSize,
&ReservedInfoSize,
&NumReservedKexts
);
//
// Initialize Extensions directory overlay for cacheless injection.
//
Status = OcKernelInitCacheless (
mOcConfiguration,
&mOcCachelessContext,
mOcDarwinVersion,
mUse32BitKernel,
FileName,
*NewHandle,
&VirtualFileHandle
);
DEBUG ((DEBUG_INFO, "OC: Result of SLE hook on %s is %r\n", FileName, Status));
if (!EFI_ERROR (Status)) {
mOcCachelessInProgress = TRUE;
*NewHandle = VirtualFileHandle;
return EFI_SUCCESS;
}
}
//
// Hook /S/L/E contents for processing during cacheless boots.
//
if (mOcCachelessInProgress
&& OpenMode == EFI_FILE_MODE_READ
&& StrnCmp (FileName, L"System\\Library\\Extensions\\", L_STR_LEN (L"System\\Library\\Extensions\\")) == 0) {
Status = CachelessContextHookBuiltin (
&mOcCachelessContext,
FileName,
*NewHandle,
&VirtualFileHandle
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OC: Error SLE hooking %s - %r\n", FileName, Status));
}
if (!EFI_ERROR (Status) && VirtualFileHandle != NULL) {
*NewHandle = VirtualFileHandle;
return EFI_SUCCESS;
}
}
//
// This is not Apple kernel, just return the original file.
// 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;
EFI_FILE_PROTOCOL *Root;
Status = EnableVirtualFs (gBS, OcKernelFileOpen);
if (!EFI_ERROR (Status)) {
mOcStorage = Storage;
mOcConfiguration = Config;
mOcCpuInfo = CpuInfo;
mOcDarwinVersion = 0;
mOcCachelessInProgress = FALSE;
mCustomKernelDirectoryInProgress = FALSE;
//
// Open customised Kernels if needed.
//
mCustomKernelDirectory = NULL;
if (mOcConfiguration->Kernel.Scheme.CustomKernel) {
Status = OcFindWritableOcFileSystem (&Root);
if (!EFI_ERROR (Status)) {
//
// Open Kernels directory.
//
Status = Root->Open (
Root,
&mCustomKernelDirectory,
L"Kernels",
EFI_FILE_MODE_READ,
EFI_FILE_DIRECTORY
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OC: Unable to open Kernels folder for custom kernel - %r, falling back to normal one\n", Status));
mCustomKernelDirectory = NULL;
}
} else {
DEBUG ((DEBUG_INFO, "OC: Unable to find root writable filesystem for custom kernel - %r, falling back to normal one\n", Status));
}
}
OcImageLoaderRegisterConfigure (OcKernelConfigureCapabilities);
} else {
DEBUG ((DEBUG_ERROR, "OC: Failed to enable vfs - %r\n", Status));
}
}
VOID
OcUnloadKernelSupport (
VOID
)
{
EFI_STATUS Status;
if (mOcStorage != NULL) {
OcImageLoaderRegisterConfigure (NULL);
Status = DisableVirtualFs (gBS);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "OC: Failed to disable vfs - %r\n", Status));
}
mOcStorage = NULL;
mOcConfiguration = NULL;
}
}

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://gitlife.ru/oschina-mirror/zsl588-OpenCorePkg.git
git@gitlife.ru:oschina-mirror/zsl588-OpenCorePkg.git
oschina-mirror
zsl588-OpenCorePkg
zsl588-OpenCorePkg
0.7.7