Skip to content

Commit

Permalink
OcMainLib: Allow specifying custom kernels on ESP partition (acidanth…
Browse files Browse the repository at this point in the history
  • Loading branch information
PMheart authored Jun 21, 2021
1 parent b0f2db4 commit 21c2acd
Show file tree
Hide file tree
Showing 8 changed files with 198 additions and 11 deletions.
18 changes: 18 additions & 0 deletions Docs/Configuration.tex
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,14 @@ \subsection{Directory Structure}\label{directory-structure}
child [missing] {}
child [missing] {}
child [missing] {}
child { node {Kernels}
child { node [optional] {kernel}}
child { node [optional] {kernelcache}}
child { node [optional] {prelinkedkernel}}
}
child [missing] {}
child [missing] {}
child [missing] {}
child { node [optional] {boot}}
child { node [optional] {nvram.plist}}
child { node [optional] {opencore-YYYY-MM-DD-HHMMSS.txt}}
Expand Down Expand Up @@ -2713,6 +2721,16 @@ \subsection{Scheme Properties}\label{kernelpropsscheme}
to install and troubleshoot such macOS installations.

\begin{enumerate}
\item
\texttt{CustomKernel}\\
\textbf{Type}: \texttt{plist\ boolean}\\
\textbf{Failsafe}: \texttt{false}\\
\textbf{Description}: Use customised kernel cache from the \texttt{Kernels}
directory located at the root of the ESP partition.

Unsupported platforms including \texttt{Atom} and \texttt{AMD} require modified versions
of XNU kernel in order to boot. This option provides the possibility to using a customised
kernel cache which contains such modifications from ESP partition.

\item
\texttt{FuzzyMatch}\\
Expand Down
2 changes: 2 additions & 0 deletions Docs/Sample.plist
Original file line number Diff line number Diff line change
Expand Up @@ -950,6 +950,8 @@
</dict>
<key>Scheme</key>
<dict>
<key>CustomKernel</key>
<false/>
<key>FuzzyMatch</key>
<true/>
<key>KernelArch</key>
Expand Down
2 changes: 2 additions & 0 deletions Docs/SampleCustom.plist
Original file line number Diff line number Diff line change
Expand Up @@ -950,6 +950,8 @@
</dict>
<key>Scheme</key>
<dict>
<key>CustomKernel</key>
<false/>
<key>FuzzyMatch</key>
<true/>
<key>KernelArch</key>
Expand Down
1 change: 1 addition & 0 deletions Include/Acidanthera/Library/OcConfigurationLib.h
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@
#define OC_KERNEL_SCHEME_FIELDS(_, __) \
_(OC_STRING , KernelArch , , OC_STRING_CONSTR ("Auto", _, __), OC_DESTR (OC_STRING)) \
_(OC_STRING , KernelCache , , OC_STRING_CONSTR ("Auto", _, __), OC_DESTR (OC_STRING)) \
_(BOOLEAN , CustomKernel , , FALSE , ()) \
_(BOOLEAN , FuzzyMatch , , FALSE , ())
OC_DECLARE (OC_KERNEL_SCHEME)

Expand Down
38 changes: 38 additions & 0 deletions Include/Acidanthera/Library/OcStringLib.h
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,44 @@ OcStrStrLength (
IN UINTN SearchStringLength
);

/**
Returns a pointer to the first occurrence of Char
in a Null-terminated Unicode string.
If String is NULL, then ASSERT().
@param[in] String The pointer to a Null-terminated Unicode string.
@param[in] Char Character to be located.
@return A pointer to the first occurrence of Char in String.
@retval NULL If Char cannot be found in String.
**/
CHAR16 *
EFIAPI
OcStrChr (
IN CONST CHAR16 *String,
IN CHAR16 Char
);

/**
Returns a pointer to the last occurrence of Char
in a Null-terminated Unicode string.
If String is NULL, then ASSERT().
@param[in] String The pointer to a Null-terminated Unicode string.
@param[in] Char Character to be located.
@return A pointer to the last occurrence of Char in String.
@retval NULL If Char cannot be found in String.
**/
CHAR16 *
EFIAPI
OcStrrChr (
IN CONST CHAR16 *String,
IN CHAR16 Char
);

/**
Alternative to UnicodeSPrint, which checks that the buffer can contain all the characters.
Expand Down
1 change: 1 addition & 0 deletions Library/OcConfigurationLib/OcConfigurationLib.c
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@ mKernelQuirksSchema[] = {
STATIC
OC_SCHEMA
mKernelSchemeSchema[] = {
OC_SCHEMA_BOOLEAN_IN ("CustomKernel", OC_GLOBAL_CONFIG, Kernel.Scheme.CustomKernel),
OC_SCHEMA_BOOLEAN_IN ("FuzzyMatch", OC_GLOBAL_CONFIG, Kernel.Scheme.FuzzyMatch),
OC_SCHEMA_STRING_IN ("KernelArch", OC_GLOBAL_CONFIG, Kernel.Scheme.KernelArch),
OC_SCHEMA_STRING_IN ("KernelCache", OC_GLOBAL_CONFIG, Kernel.Scheme.KernelCache),
Expand Down
97 changes: 86 additions & 11 deletions Library/OcMainLib/OpenCoreKernel.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ STATIC BOOLEAN mUse32BitKernel;
STATIC CACHELESS_CONTEXT mOcCachelessContext;
STATIC BOOLEAN mOcCachelessInProgress;

STATIC EFI_FILE_PROTOCOL *mCustomKernelDirectory;
STATIC BOOLEAN mCustomKernelDirectoryInProgress;

STATIC
VOID
OcKernelConfigureCapabilities (
Expand Down Expand Up @@ -1078,6 +1081,13 @@ OcKernelFileOpen (
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 SafeFileOpen (This, NewHandle, FileName, OpenMode, Attributes);
}

//
// Prevent access to cache files depending on maximum cache type allowed.
Expand Down Expand Up @@ -1136,6 +1146,20 @@ OcKernelFileOpen (
&& 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));

Expand Down Expand Up @@ -1171,6 +1195,29 @@ OcKernelFileOpen (
&& 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 = SafeFileOpen (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.
Expand All @@ -1191,7 +1238,7 @@ OcKernelFileOpen (
);

if (Status == EFI_NOT_FOUND) {
(*NewHandle)->Close(*NewHandle);
(*NewHandle)->Close (*NewHandle);
*NewHandle = NULL;

return Status;
Expand All @@ -1210,7 +1257,7 @@ OcKernelFileOpen (
DEBUG ((DEBUG_INFO, "OC: Blocking prelinked due to ForceKernelCache=%s: %a\n", FileName, ForceCacheType));

FreePool (Kernel);
(*NewHandle)->Close(*NewHandle);
(*NewHandle)->Close (*NewHandle);
*NewHandle = NULL;

return EFI_NOT_FOUND;
Expand Down Expand Up @@ -1248,7 +1295,7 @@ OcKernelFileOpen (
ZeroMem (&ModificationTime, sizeof (ModificationTime));
}

(*NewHandle)->Close(*NewHandle);
(*NewHandle)->Close (*NewHandle);

//
// Virtualise newly created kernel.
Expand Down Expand Up @@ -1280,7 +1327,7 @@ OcKernelFileOpen (
//
if (MaxCacheTypeAllowed == CacheTypeCacheless) {
DEBUG ((DEBUG_INFO, "OC: Blocking mkext due to ForceKernelCache=%s: %a\n", FileName, ForceCacheType));
(*NewHandle)->Close(*NewHandle);
(*NewHandle)->Close (*NewHandle);
*NewHandle = NULL;

return EFI_NOT_FOUND;
Expand Down Expand Up @@ -1337,7 +1384,7 @@ OcKernelFileOpen (
ZeroMem (&ModificationTime, sizeof (ModificationTime));
}

(*NewHandle)->Close(*NewHandle);
(*NewHandle)->Close (*NewHandle);

//
// Virtualise newly created mkext.
Expand Down Expand Up @@ -1441,16 +1488,44 @@ OcLoadKernelSupport (
IN OC_CPU_INFO *CpuInfo
)
{
EFI_STATUS Status;
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;
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 = FindWritableOcFileSystem (&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));
Expand Down
50 changes: 50 additions & 0 deletions Library/OcStringLib/OcUnicodeLib.c
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,56 @@ OcStrStrLength (
return NULL;
}

CHAR16 *
EFIAPI
OcStrChr (
IN CONST CHAR16 *String,
IN CHAR16 Char
)
{
ASSERT (StrSize (String) != 0);

while (*String != '\0') {
//
// Return immediately when matching first occurrence of Char.
//
if (*String == Char) {
return (CHAR16 *) String;
}

++String;
}

return NULL;
}

CHAR16 *
EFIAPI
OcStrrChr (
IN CONST CHAR16 *String,
IN CHAR16 Char
)
{
CHAR16 *Save;

ASSERT (StrSize (String) != 0);

Save = NULL;

while (*String != '\0') {
//
// Record the last occurrence of Char.
//
if (*String == Char) {
Save = (CHAR16 *) String;
}

++String;
}

return Save;
}

VOID
UnicodeUefiSlashes (
IN OUT CHAR16 *String
Expand Down

0 comments on commit 21c2acd

Please sign in to comment.