提交 86a49fb2 编写于 作者: V vit9696

OpenRuntime: Replaced `RequestBootVarFallback` with `DeduplicateBootOrder` due to bugs

上级 f750d5b7
......@@ -22,6 +22,8 @@ OpenCore Changelog
- Added builtin text renderer compatibility with Shell page mode
- Fixed `FadtEnableReset` with too small FACP tables
- Fixed CPU detection crash with QEMU 5.0 and KVM accelerator
- Removed `RequestBootVarFallback` due to numerous bugs
- Added `DeduplicateBootOrder` UEFI quirk
#### v0.5.8
- Fixed invalid CPU object reference in SSDT-PLUG
......
......@@ -3010,10 +3010,6 @@ use.
When \texttt{RequestBootVarRouting} is used \texttt{Boot}-prefixed variable access
is restricted and protected in a separate namespace. To access the original variables
tools have to be aware of \texttt{OC\_FIRMWARE\_RUNTIME} logic.
\item Assigned NVRAM variables are not always allowed to exceed 512 bytes.\\
This is true for \texttt{Boot}-prefixed variables when \texttt{RequestBootVarFallback}
is used, and for overwriting volatile variables with non-volatile on UEFI 2.8
non-conformant firmwares.
\end{enumerate}
\subsection{Properties}\label{nvramprops}
......@@ -4305,8 +4301,6 @@ functioning. Feature highlights:
\begin{itemize}
\item NVRAM namespaces, allowing to isolate operating systems from accessing select
variables (e.g. \texttt{RequestBootVarRouting} or \texttt{ProtectSecureBoot}).
\item NVRAM proxying, allowing to manipulate multiple variables on variable updates
(e.g. \texttt{RequestBootVarFallback}).
\item Read-only and write-only NVRAM variables, enhancing the security of OpenCore,
Lilu, and Lilu plugins, like VirtualSMC, which implements \texttt{AuthRestart} support.
\item NVRAM isolation, allowing to protect all variables from being written from
......@@ -5098,6 +5092,46 @@ functioning. Feature highlights:
\begin{enumerate}
\item
\texttt{DeduplicateBootOrder}\\
\textbf{Type}: \texttt{plist\ boolean}\\
\textbf{Failsafe}: \texttt{false}\\
\textbf{Description}: Remove duplicate entries in \texttt{BootOrder} variable
in \texttt{EFI\_GLOBAL\_VARIABLE\_GUID}.
This quirk requires \texttt{RequestBootVarRouting} to be enabled and therefore
\texttt{OC\_FIRMWARE\_RUNTIME} protocol implemented in \texttt{OpenRuntime.efi}.
By redirecting \texttt{Boot} prefixed variables to a separate GUID namespace
with the help of \texttt{RequestBootVarRouting} quirk we achieve multiple goals:
\begin{itemize}
\tightlist
\item Operating systems are jailed and only controlled by OpenCore boot
environment to enhance security.
\item Operating systems do not mess with OpenCore boot priority, and guarantee
fluent updates and hibernation wakes for cases that require reboots with OpenCore
in the middle.
\item Potentially incompatible boot entries, such as macOS entries, are not deleted
or anyhow corrupted.
\end{itemize}
However, some firmwares do their own boot option scanning upon startup by checking
file presence on the available disks. Quite often this scanning includes non-standard
locations, such as Windows Bootloader paths. Normally it is not an issue, but some
firmwares, ASUS firmwares on APTIO V in particular, have bugs. For them scanning is
implemented improperly, and firmware preferences may get accidentally corrupted
due to \texttt{BootOrder} entry duplication (each option will be added twice) making
it impossible to boot without cleaning NVRAM.
To trigger the bug one should have some valid boot options (e.g. OpenCore) and then
install Windows with \texttt{RequestBootVarRouting} enabled. As Windows bootloader
option will not be created by Windows installer, the firmware will attempt to create it
itself, and then corrupt its boot option list.
This quirk removes all duplicates in \texttt{BootOrder} variable attempting to resolve
the consequences of the bugs upon OpenCore loading. It is recommended to use this key
along with \texttt{BootProtect} option.
\item
\texttt{ExitBootServicesDelay}\\
\textbf{Type}: \texttt{plist\ integer}\\
......@@ -5131,48 +5165,6 @@ functioning. Feature highlights:
or at least have an option for, select firmwares do not. As a result,
operating system may freeze upon boot. Not recommended unless required.
\item
\texttt{RequestBootVarFallback}\\
\textbf{Type}: \texttt{plist\ boolean}\\
\textbf{Failsafe}: \texttt{false}\\
\textbf{Description}: Request fallback of some \texttt{Boot} prefixed variables from
\texttt{OC\_VENDOR\_VARIABLE\_GUID} to \newline \texttt{EFI\_GLOBAL\_VARIABLE\_GUID}.
This quirk requires \texttt{RequestBootVarRouting} to be enabled and therefore
\texttt{OC\_FIRMWARE\_RUNTIME} protocol implemented in \texttt{OpenRuntime.efi}.
By redirecting \texttt{Boot} prefixed variables to a separate GUID namespace we achieve
multiple goals:
\begin{itemize}
\tightlist
\item Operating systems are jailed and only controlled by OpenCore boot
environment to enhance security.
\item Operating systems do not mess with OpenCore boot priority, and guarantee
fluent updates and hibernation wakes for cases that require reboots with OpenCore
in the middle.
\item Potentially incompatible boot entries, such as macOS entries, are not deleted
or anyhow corrupted.
\end{itemize}
However, some firmwares do their own boot option scanning upon startup by checking
file presence on the available disks. Quite often this scanning includes non-standard
locations, such as Windows Bootloader paths. Normally it is not an issue, but some
firmwares, ASUS firmwares on APTIO V in particular, have bugs. For them scanning is
implemented improperly, and firmware preferences may get accidentally corrupted
due to \texttt{BootOrder} entry duplication (each option will be added twice) making
it impossible to boot without cleaning NVRAM.
To trigger the bug one should have some valid boot options (e.g. OpenCore) and then
install Windows with \texttt{RequestBootVarRouting} enabled. As Windows bootloader
option will not be created by Windows installer, the firmware will attempt to create it
itself, and then corrupt its boot option list.
This quirk forwards all UEFI specification valid boot options, that are not related to
macOS, to the firmware into \texttt{BootF\#\#\#} and \texttt{BootOrder} variables upon
write. As the entries are added to the end of \texttt{BootOrder}, this does not
break boot priority, but ensures that the firmware does not try to append a new option
on its own after Windows installation for instance.
\item
\texttt{RequestBootVarRouting}\\
\textbf{Type}: \texttt{plist\ boolean}\\
......
\documentclass[]{article}
%DIF LATEXDIFF DIFFERENCE FILE
%DIF DEL PreviousConfiguration.tex Mon May 4 15:42:50 2020
%DIF ADD ../Configuration.tex Sun May 10 02:00:26 2020
%DIF DEL PreviousConfiguration.tex Mon May 11 17:11:58 2020
%DIF ADD ../Configuration.tex Wed May 13 16:05:07 2020
\usepackage{lmodern}
\usepackage{amssymb,amsmath}
......@@ -3211,11 +3211,16 @@ use.
When \texttt{RequestBootVarRouting} is used \texttt{Boot}-prefixed variable access
is restricted and protected in a separate namespace. To access the original variables
tools have to be aware of \texttt{OC\_FIRMWARE\_RUNTIME} logic.
\item Assigned NVRAM variables are not always allowed to exceed 512 bytes.\\
This is true for \texttt{Boot}-prefixed variables when \texttt{RequestBootVarFallback}
is used, and for overwriting volatile variables with non-volatile on UEFI 2.8
\DIFdelbegin %DIFDELCMD < \item %%%
\item%DIFAUXCMD
\DIFdel{Assigned NVRAM variables are not always allowed to exceed 512 bytes.}%DIFDELCMD < \\
%DIFDELCMD < %%%
\DIFdel{This is true for }\texttt{\DIFdel{Boot}}%DIFAUXCMD
\DIFdel{-prefixed variables when }\texttt{\DIFdel{RequestBootVarFallback}}
%DIFAUXCMD
\DIFdel{is used, and for overwriting volatile variables with non-volatile on UEFI 2.8
non-conformant firmwares.
\end{enumerate}
}\DIFdelend \end{enumerate}
\subsection{Properties}\label{nvramprops}
......@@ -4508,9 +4513,12 @@ functioning. Feature highlights:
\begin{itemize}
\item NVRAM namespaces, allowing to isolate operating systems from accessing select
variables (e.g. \texttt{RequestBootVarRouting} or \texttt{ProtectSecureBoot}).
\item NVRAM proxying, allowing to manipulate multiple variables on variable updates
(e.g. \texttt{RequestBootVarFallback}).
\item Read-only and write-only NVRAM variables, enhancing the security of OpenCore,
\item \DIFdelbegin \DIFdel{NVRAM proxying, allowing to manipulate multiple variables on variable updates
(e.g. }\texttt{\DIFdel{RequestBootVarFallback}}%DIFAUXCMD
\DIFdel{).
}%DIFDELCMD < \item %%%
\item%DIFAUXCMD
\DIFdelend Read-only and write-only NVRAM variables, enhancing the security of OpenCore,
Lilu, and Lilu plugins, like VirtualSMC, which implements \texttt{AuthRestart} support.
\item NVRAM isolation, allowing to protect all variables from being written from
an untrusted operating system (e.g. \texttt{DisableVariableWrite}).
......@@ -5302,50 +5310,97 @@ functioning. Feature highlights:
\begin{enumerate}
\item
\texttt{ExitBootServicesDelay}\\
\textbf{Type}: \texttt{plist\ integer}\\
\textbf{Failsafe}: \texttt{0}\\
\textbf{Description}: Adds delay in microseconds after \texttt{EXIT\_BOOT\_SERVICES}
event.
\texttt{\DIFdelbegin \DIFdel{ExitBootServicesDelay}\DIFdelend \DIFaddbegin \DIFadd{DeduplicateBootOrder}\DIFaddend }\\
\textbf{Type}: \DIFdelbegin \texttt{\DIFdel{plist\ integer}}%DIFAUXCMD
%DIFDELCMD < \\
%DIFDELCMD < %%%
\textbf{\DIFdel{Failsafe}}%DIFAUXCMD
\DIFdel{: }\texttt{\DIFdel{0}}%DIFAUXCMD
%DIFDELCMD < \\
%DIFDELCMD < %%%
\textbf{\DIFdel{Description}}%DIFAUXCMD
\DIFdel{: Adds delay in microseconds after }\texttt{\DIFdel{EXIT\_BOOT\_SERVICES}}
%DIFAUXCMD
\DIFdel{event.
}%DIFDELCMD <
This is a very ugly quirk to circumvent "Still waiting for root device" message
%DIFDELCMD < %%%
\DIFdel{This is a very ugly quirk to circumvent "Still waiting for root device" message
on select APTIO IV firmwares, namely ASUS Z87-Pro, when using FileVault 2 in particular.
It seems that for some reason they execute code in parallel to \texttt{EXIT\_BOOT\_SERVICES},
It seems that for some reason they execute code in parallel to }\texttt{\DIFdel{EXIT\_BOOT\_SERVICES}}%DIFAUXCMD
\DIFdel{,
which results in SATA controller being inaccessible from macOS. A better approach should be
found in some future. Expect 3-5 seconds to be enough in case the quirk is needed.
}%DIFDELCMD <
\item
\texttt{IgnoreInvalidFlexRatio}\\
\textbf{Type}: \texttt{plist\ boolean}\\
%DIFDELCMD < \item
\item%DIFAUXCMD
%DIFDELCMD < %%%
\texttt{\DIFdel{IgnoreInvalidFlexRatio}}%DIFAUXCMD
%DIFDELCMD < \\
%DIFDELCMD < %%%
\textbf{\DIFdel{Type}}%DIFAUXCMD
\DIFdel{: }\DIFdelend \texttt{plist\ boolean}\\
\textbf{Failsafe}: \texttt{false}\\
\textbf{Description}: Select firmwares, namely APTIO IV, may contain invalid values in
\texttt{MSR\_FLEX\_RATIO} (\texttt{0x194}) MSR register. These values may cause
\textbf{Description}: \DIFdelbegin \DIFdel{Select firmwares, namely APTIO IV, may contain invalid values in }\DIFdelend \DIFaddbegin \DIFadd{Remove duplicate entries in }\DIFaddend \texttt{\DIFdelbegin \DIFdel{MSR\_FLEX\_RATIO}\DIFdelend \DIFaddbegin \DIFadd{BootOrder}\DIFaddend } \DIFdelbegin \DIFdel{(}\texttt{\DIFdel{0x194}}%DIFAUXCMD
\DIFdel{) MSR register. These values may cause
macOS boot failure on Intel platforms.
}%DIFDELCMD <
\emph{Note}: While the option is not supposed to induce harm on unaffected firmwares,
%DIFDELCMD < %%%
\emph{\DIFdel{Note}}%DIFAUXCMD
\DIFdel{: While the option is not supposed to induce harm on unaffected firmwares,
its usage is not recommended when it is not required.
}%DIFDELCMD <
\item
\texttt{ReleaseUsbOwnership}\\
\textbf{Type}: \texttt{plist\ boolean}\\
\textbf{Failsafe}: \texttt{false}\\
\textbf{Description}: Attempt to detach USB controller ownership from
%DIFDELCMD < \item
\item%DIFAUXCMD
%DIFDELCMD < %%%
\texttt{\DIFdel{ReleaseUsbOwnership}}%DIFAUXCMD
%DIFDELCMD < \\
%DIFDELCMD < %%%
\textbf{\DIFdel{Type}}%DIFAUXCMD
\DIFdel{: }\texttt{\DIFdel{plist\ boolean}}%DIFAUXCMD
%DIFDELCMD < \\
%DIFDELCMD < %%%
\textbf{\DIFdel{Failsafe}}%DIFAUXCMD
\DIFdel{: }\texttt{\DIFdel{false}}%DIFAUXCMD
%DIFDELCMD < \\
%DIFDELCMD < %%%
\textbf{\DIFdel{Description}}%DIFAUXCMD
\DIFdel{: Attempt to detach USB controller ownership from
the firmware driver. While most firmwares manage to properly do that,
or at least have an option for, select firmwares do not. As a result,
operating system may freeze upon boot. Not recommended unless required.
}%DIFDELCMD <
\item
\texttt{RequestBootVarFallback}\\
\textbf{Type}: \texttt{plist\ boolean}\\
\textbf{Failsafe}: \texttt{false}\\
\textbf{Description}: Request fallback of some \texttt{Boot} prefixed variables from
\texttt{OC\_VENDOR\_VARIABLE\_GUID} to \newline \texttt{EFI\_GLOBAL\_VARIABLE\_GUID}.
%DIFDELCMD < \item
\item%DIFAUXCMD
%DIFDELCMD < %%%
\texttt{\DIFdel{RequestBootVarFallback}}%DIFAUXCMD
%DIFDELCMD < \\
%DIFDELCMD < %%%
\textbf{\DIFdel{Type}}%DIFAUXCMD
\DIFdel{: }\texttt{\DIFdel{plist\ boolean}}%DIFAUXCMD
%DIFDELCMD < \\
%DIFDELCMD < %%%
\textbf{\DIFdel{Failsafe}}%DIFAUXCMD
\DIFdel{: }\texttt{\DIFdel{false}}%DIFAUXCMD
%DIFDELCMD < \\
%DIFDELCMD < %%%
\textbf{\DIFdel{Description}}%DIFAUXCMD
\DIFdel{: Request fallback of some }\texttt{\DIFdel{Boot}} %DIFAUXCMD
\DIFdel{prefixed variables from
}\texttt{\DIFdel{OC\_VENDOR\_VARIABLE\_GUID}} %DIFAUXCMD
\DIFdel{to }%DIFDELCMD < \newline %%%
\DIFdelend \DIFaddbegin \DIFadd{variable
in }\DIFaddend \texttt{EFI\_GLOBAL\_VARIABLE\_GUID}.
This quirk requires \texttt{RequestBootVarRouting} to be enabled and therefore
\texttt{OC\_FIRMWARE\_RUNTIME} protocol implemented in \texttt{OpenRuntime.efi}.
By redirecting \texttt{Boot} prefixed variables to a separate GUID namespace we achieve
multiple goals:
By redirecting \texttt{Boot} prefixed variables to a separate GUID namespace
\DIFaddbegin \DIFadd{with the help of }\texttt{\DIFadd{RequestBootVarRouting}} \DIFadd{quirk }\DIFaddend we achieve multiple goals:
\begin{itemize}
\tightlist
\item Operating systems are jailed and only controlled by OpenCore boot
......@@ -5370,14 +5425,57 @@ functioning. Feature highlights:
option will not be created by Windows installer, the firmware will attempt to create it
itself, and then corrupt its boot option list.
This quirk forwards all UEFI specification valid boot options, that are not related to
macOS, to the firmware into \texttt{BootF\#\#\#} and \texttt{BootOrder} variables upon
write. As the entries are added to the end of \texttt{BootOrder}, this does not
break boot priority, but ensures that the firmware does not try to append a new option
on its own after Windows installation for instance.
This quirk \DIFdelbegin \DIFdel{forwards all UEFI specification valid boot options, that are not related to macOS,
to the firmware into }\texttt{\DIFdel{BootF\#\#\#}} %DIFAUXCMD
\DIFdel{and }\DIFdelend \DIFaddbegin \DIFadd{removes all duplicates in }\DIFaddend \texttt{BootOrder} \DIFdelbegin \DIFdel{variables upon
write.
As the entries are added to the end of }\texttt{\DIFdel{BootOrder}}%DIFAUXCMD
\DIFdel{,
this does not break boot priority, but ensures that the firmware does not try to append a new option on its own after Windows installation forinstance. }\DIFdelend \DIFaddbegin \DIFadd{variable attempting to resolve
the consequences of the bugs upon OpenCore loading. It is recommended to use this key
along with }\texttt{\DIFadd{BootProtect}} \DIFadd{option.
}\DIFaddend
\item
\DIFaddbegin \texttt{\DIFadd{ExitBootServicesDelay}}\\
\textbf{\DIFadd{Type}}\DIFadd{: }\texttt{\DIFadd{plist\ integer}}\\
\textbf{\DIFadd{Failsafe}}\DIFadd{: }\texttt{\DIFadd{0}}\\
\textbf{\DIFadd{Description}}\DIFadd{: Adds delay in microseconds after }\texttt{\DIFadd{EXIT\_BOOT\_SERVICES}}
\DIFadd{event.
}
\DIFadd{This is a very ugly quirk to circumvent "Still waiting for root device" message
on select APTIO IV firmwares, namely ASUS Z87-Pro, when using FileVault 2 in particular.
It seems that for some reason they execute code in parallel to }\texttt{\DIFadd{EXIT\_BOOT\_SERVICES}}\DIFadd{,
which results in SATA controller being inaccessible from macOS. A better approach should be
found in some future. Expect 3-5 seconds to be enough in case the quirk is needed.
}
\item
\texttt{\DIFadd{IgnoreInvalidFlexRatio}}\\
\textbf{\DIFadd{Type}}\DIFadd{: }\texttt{\DIFadd{plist\ boolean}}\\
\textbf{\DIFadd{Failsafe}}\DIFadd{: }\texttt{\DIFadd{false}}\\
\textbf{\DIFadd{Description}}\DIFadd{: Select firmwares, namely APTIO IV, may contain invalid values in
}\texttt{\DIFadd{MSR\_FLEX\_RATIO}} \DIFadd{(}\texttt{\DIFadd{0x194}}\DIFadd{) MSR register. These values may cause
macOS boot failure on Intel platforms.
}
\emph{\DIFadd{Note}}\DIFadd{: While the option is not supposed to induce harm on unaffected firmwares,
its usage is not recommended when it is not required.
}
\item
\texttt{\DIFadd{ReleaseUsbOwnership}}\\
\textbf{\DIFadd{Type}}\DIFadd{: }\texttt{\DIFadd{plist\ boolean}}\\
\textbf{\DIFadd{Failsafe}}\DIFadd{: }\texttt{\DIFadd{false}}\\
\textbf{\DIFadd{Description}}\DIFadd{: Attempt to detach USB controller ownership from
the firmware driver. While most firmwares manage to properly do that,
or at least have an option for, select firmwares do not. As a result,
operating system may freeze upon boot. Not recommended unless required.
}
\item
\texttt{RequestBootVarRouting}\\
\DIFaddend \texttt{RequestBootVarRouting}\\
\textbf{Type}: \texttt{plist\ boolean}\\
\textbf{Failsafe}: \texttt{false}\\
\textbf{Description}: Request redirect of all \texttt{Boot} prefixed variables from
......
......@@ -914,14 +914,14 @@
</dict>
<key>Quirks</key>
<dict>
<key>DeduplicateBootOrder</key>
<false/>
<key>ExitBootServicesDelay</key>
<integer>0</integer>
<key>IgnoreInvalidFlexRatio</key>
<false/>
<key>ReleaseUsbOwnership</key>
<false/>
<key>RequestBootVarFallback</key>
<false/>
<key>RequestBootVarRouting</key>
<true/>
<key>UnblockFsConnect</key>
......
......@@ -1017,14 +1017,14 @@
</dict>
<key>Quirks</key>
<dict>
<key>DeduplicateBootOrder</key>
<false/>
<key>ExitBootServicesDelay</key>
<integer>0</integer>
<key>IgnoreInvalidFlexRatio</key>
<false/>
<key>ReleaseUsbOwnership</key>
<false/>
<key>RequestBootVarFallback</key>
<false/>
<key>RequestBootVarRouting</key>
<true/>
<key>UnblockFsConnect</key>
......
......@@ -32,13 +32,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
//
#define OC_BOOT_REDIRECT_VARIABLE_NAME L"boot-redirect"
//
// Variable used for OpenCore request to fallback NVRAM Boot variable write.
// Serves for resolving issues with borked ASUS APTIO V BIOSes.
// Boot Services only.
//
#define OC_BOOT_FALLBACK_VARIABLE_NAME L"boot-fallback"
//
// Variable used for exposing OpenCore Security -> LoadPolicy.
// Boot Services only.
......
......@@ -553,9 +553,9 @@ typedef enum {
///
#define OC_UEFI_QUIRKS_FIELDS(_, __) \
_(UINT32 , ExitBootServicesDelay , , 0 , ()) \
_(BOOLEAN , DeduplicateBootOrder , , FALSE , ()) \
_(BOOLEAN , IgnoreInvalidFlexRatio , , FALSE , ()) \
_(BOOLEAN , ReleaseUsbOwnership , , FALSE , ()) \
_(BOOLEAN , RequestBootVarFallback , , FALSE , ()) \
_(BOOLEAN , RequestBootVarRouting , , FALSE , ()) \
_(BOOLEAN , UnblockFsConnect , , FALSE , ())
OC_DECLARE (OC_UEFI_QUIRKS)
......
......@@ -17,7 +17,7 @@
#include <Uefi.h>
#define OC_FIRMWARE_RUNTIME_REVISION 10
#define OC_FIRMWARE_RUNTIME_REVISION 11
/**
OC_FIRMWARE_RUNTIME_PROTOCOL_GUID
......@@ -39,15 +39,6 @@ typedef struct OC_FWRT_CONFIG_ {
///
BOOLEAN BootVariableRedirect;
///
/// Route boot variables back to EfiGlobalVariable when they are compatible.
/// In general we do not want this, as this basically escapes OpenCore security
/// jail, and permits booting operating systems bypassing OpenCore.
/// However, some firmwares, namely ASUS APTIO V, will freeze/fail to boot
/// by manually adding boot entries for Windows after Windows itself did not
/// create them.
///
BOOLEAN BootVariableFallback;
///
/// Make SetVariable do nothing and always return EFI_SECURITY_VIOLATION.
/// When we do not want variables to be stored in NVRAM or NVRAM implementation
/// is buggy we can disable variable writing.
......
......@@ -697,18 +697,6 @@ OcStartImage (
&Config.BootVariableRedirect
);
//
// Do the same thing for Boot#### variable fallback.
//
DataSize = sizeof (Config.BootVariableFallback);
BootCompat->ServicePtrs.GetVariable (
OC_BOOT_FALLBACK_VARIABLE_NAME,
&gOcVendorVariableGuid,
NULL,
&DataSize,
&Config.BootVariableFallback
);
//
// Enable Apple-specific changes if requested.
// Disable them when this is no longer Apple.
......
......@@ -89,7 +89,6 @@ IsDeletableVariable (
// Do not remove OpenCore critical variables.
//
if (StrCmp (Name, OC_BOOT_REDIRECT_VARIABLE_NAME) != 0
&& StrCmp (Name, OC_BOOT_FALLBACK_VARIABLE_NAME) != 0
&& StrCmp (Name, OC_LOAD_POLICY_VARIABLE_NAME) != 0
&& StrCmp (Name, OC_SCAN_POLICY_VARIABLE_NAME) != 0) {
return TRUE;
......
......@@ -532,10 +532,10 @@ mUefiDriversSchema = OC_SCHEMA_STRING (NULL);
STATIC
OC_SCHEMA
mUefiQuirksSchema[] = {
OC_SCHEMA_BOOLEAN_IN ("DeduplicateBootOrder", OC_GLOBAL_CONFIG, Uefi.Quirks.DeduplicateBootOrder),
OC_SCHEMA_INTEGER_IN ("ExitBootServicesDelay", OC_GLOBAL_CONFIG, Uefi.Quirks.ExitBootServicesDelay),
OC_SCHEMA_BOOLEAN_IN ("IgnoreInvalidFlexRatio", OC_GLOBAL_CONFIG, Uefi.Quirks.IgnoreInvalidFlexRatio),
OC_SCHEMA_BOOLEAN_IN ("ReleaseUsbOwnership", OC_GLOBAL_CONFIG, Uefi.Quirks.ReleaseUsbOwnership),
OC_SCHEMA_BOOLEAN_IN ("RequestBootVarFallback", OC_GLOBAL_CONFIG, Uefi.Quirks.RequestBootVarFallback),
OC_SCHEMA_BOOLEAN_IN ("RequestBootVarRouting", OC_GLOBAL_CONFIG, Uefi.Quirks.RequestBootVarRouting),
OC_SCHEMA_BOOLEAN_IN ("UnblockFsConnect", OC_GLOBAL_CONFIG, Uefi.Quirks.UnblockFsConnect)
};
......
......@@ -439,9 +439,9 @@ OcLoadUefiSupport (
DEBUG ((
DEBUG_INFO,
"OC: RBVR %d RBVF %d\n",
"OC: RBVR %d DDBR %d\n",
Config->Uefi.Quirks.RequestBootVarRouting,
Config->Uefi.Quirks.RequestBootVarFallback
Config->Uefi.Quirks.DeduplicateBootOrder
));
//
......@@ -455,15 +455,7 @@ OcLoadUefiSupport (
&Config->Uefi.Quirks.RequestBootVarRouting
);
gRT->SetVariable (
OC_BOOT_FALLBACK_VARIABLE_NAME,
&gOcVendorVariableGuid,
OPEN_CORE_INT_NVRAM_ATTR,
sizeof (Config->Uefi.Quirks.RequestBootVarFallback),
&Config->Uefi.Quirks.RequestBootVarFallback
);
if (Config->Uefi.Quirks.RequestBootVarFallback) {
if (Config->Uefi.Quirks.DeduplicateBootOrder) {
BootOrder = OcGetBootOrder (
&gEfiGlobalVariableGuid,
FALSE,
......
......@@ -57,15 +57,6 @@ STATIC EFI_EVENT mTranslateEvent;
STATIC EFI_GET_VARIABLE mCustomGetVariable;
STATIC BOOLEAN mKernelStarted;
/**
Current boot order before updating.
**/
STATIC UINT16 mTmpBootOrder[16];
STATIC UINTN mTmpBootOrderSize;
STATIC INT32 mOcBootOrderMap[16];
STATIC UINT8 mTmpBootOption[512];
STATIC UINTN mTmpBootOptionSize;
STATIC
VOID
WriteUnprotectorPrologue (
......@@ -117,15 +108,9 @@ STATIC
BOOLEAN
IsEfiBootVar (
IN CHAR16 *VariableName,
IN EFI_GUID *VendorGuid,
OUT BOOLEAN *IsBootOrder OPTIONAL,
OUT INT32 *BootNum OPTIONAL
IN EFI_GUID *VendorGuid
)
{
UINTN Index;
CHAR16 Digit;
INT32 TmpNum;
if (!CompareGuid (VendorGuid, &gEfiGlobalVariableGuid)) {
return FALSE;
}
......@@ -134,29 +119,6 @@ IsEfiBootVar (
return FALSE;
}
if (IsBootOrder != NULL && StrCmp (VariableName, L"BootOrder") == 0) {
*IsBootOrder = TRUE;
return TRUE;
}
if (BootNum != NULL
&& StrLen (VariableName) == L_STR_LEN (L"Boot####")) {
TmpNum = 0;
for (Index = 0; Index < 4; ++Index) {
Digit = VariableName[L_STR_LEN (L"Boot") + Index];
if (Digit >= '0' && Digit <= '9') {
TmpNum = 16 * TmpNum + (INT32) (Digit - '0');
} else if (Digit >= 'A' && Digit <= 'F') {
TmpNum = 16 * TmpNum + (INT32) (Digit - 'A') + 10;
} else {
return TRUE;
}
}
*BootNum = TmpNum;
}
return TRUE;
}
......@@ -324,7 +286,7 @@ WrapGetVariable (
//
// Redirect Boot-prefixed variables to our own GUID.
//
if (gCurrentConfig->BootVariableRedirect && IsEfiBootVar (VariableName, VendorGuid, NULL, NULL)) {
if (gCurrentConfig->BootVariableRedirect && IsEfiBootVar (VariableName, VendorGuid)) {
VendorGuid = &gOcVendorVariableGuid;
}
......@@ -412,7 +374,7 @@ WrapGetNextVariableName (
// then go through the whole variable list and return
// variables except EfiBoot.
//
if (!IsEfiBootVar (TempName, &TempGuid, NULL, NULL)) {
if (!IsEfiBootVar (TempName, &TempGuid)) {
while (TRUE) {
//
// Request for variables.
......@@ -421,7 +383,7 @@ WrapGetNextVariableName (
Status = mStoredGetNextVariableName (&Size, TempName, &TempGuid);
if (!EFI_ERROR (Status)) {
if (!IsEfiBootVar (TempName, &TempGuid, NULL, NULL)) {
if (!IsEfiBootVar (TempName, &TempGuid)) {
Size = StrSize (TempName); ///< Not guaranteed to be updated with EFI_SUCCESS.
if (*VariableNameSize >= Size) {
......@@ -548,348 +510,6 @@ WrapGetNextVariableName (
return EFI_NOT_FOUND;
}
STATIC
VOID
HandleBootOrderFallback (
UINT16 *NewBootOrder,
UINTN NewBootOrderCount,
UINT16 *OldBootOrder,
UINTN OldBootOrderCount
)
{
UINTN Index;
UINTN Index2;
EFI_STATUS Status;
INT32 BootNum;
//
// Look for BootOrder entry addition, assume only one exists if at all.
// Ignore deletions, as we can handle them later.
//
BootNum = -1;
for (Index = 0; Index < NewBootOrderCount; ++Index) {
for (Index2 = 0; Index2 < OldBootOrderCount; ++Index2) {
if (NewBootOrder[Index] == OldBootOrder[Index2]) {
break;
}
}
if (Index2 == OldBootOrderCount) {
BootNum = NewBootOrder[Index];
break;
}
}
if (BootNum < 0) {
return;
}
//
// BootNum now contains the variable added to OcVendorVariable BootOrder.
// Check our pending mapping and submit it to EfiGlobalVariable BootOrder if present.
//
for (Index = 0; Index < ARRAY_SIZE (mOcBootOrderMap); ++Index) {
if (mOcBootOrderMap[Index] >= 0 && mOcBootOrderMap[Index] == BootNum) {
//
// Erase from pending order.
//
mOcBootOrderMap[Index] = -1;
BootNum = (INT32) (Index + OC_GL_BOOT_OPTION_START);
break;
}
}
if (Index == ARRAY_SIZE (mOcBootOrderMap)) {
//
// We do not know how to handle this variable, just ignore.
// Most likely we have already wrote it.
//
return;
}
//
// BootNum now contains the variable we want to add EfiGlobalVariable BootOrder.
// Add it, reusing mTmpBootOrder array.
//
mTmpBootOrderSize = sizeof (mTmpBootOrder) - sizeof (mTmpBootOrder[0]);
Status = mStoredGetVariable (
L"BootOrder",
&gEfiGlobalVariableGuid,
NULL,
&mTmpBootOrderSize,
mTmpBootOrder
);
if (EFI_ERROR (Status)) {
if (Status == EFI_NOT_FOUND) {
mTmpBootOrderSize = 0;
} else {
//
// We did not fit BootOrder into our list, just ignore.
// This should not happen.
//
return;
}
}
mTmpBootOrder[mTmpBootOrderSize / sizeof (mTmpBootOrder[0])] = (UINT16) BootNum;
mTmpBootOrderSize += sizeof (mTmpBootOrder[0]);
mStoredSetVariable (
L"BootOrder",
&gEfiGlobalVariableGuid,
EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
mTmpBootOrderSize,
mTmpBootOrder
);
}
STATIC
EFI_DEVICE_PATH *
GetBootEntryDevicePath (
EFI_LOAD_OPTION *LoadOption,
UINTN LoadOptionSize,
BOOLEAN ForFallback
)
{
UINT8 *LoadOptionPtr;
CONST CHAR16 *Description;
UINTN DescriptionSize;
UINT16 FilePathListSize;
EFI_DEVICE_PATH_PROTOCOL *FilePathList;
EFI_DEVICE_PATH_PROTOCOL *CurrNode;
FILEPATH_DEVICE_PATH *LastNode;
UINTN Index;
UINTN Index2;
UINTN PathLen;
UINTN CurrLen;
if (LoadOptionSize < sizeof (*LoadOption)
|| (LoadOption->Attributes & LOAD_OPTION_ACTIVE) == 0
|| (LoadOption->Attributes & LOAD_OPTION_CATEGORY) != LOAD_OPTION_CATEGORY_BOOT) {
return NULL;
}
FilePathListSize = LoadOption->FilePathListLength;
LoadOptionPtr = (UINT8 *) (LoadOption + 1);
LoadOptionSize -= sizeof (*LoadOption);
if (LoadOption->FilePathListLength > LoadOptionSize) {
return NULL;
}
LoadOptionSize -= FilePathListSize;
Description = (CHAR16 *) LoadOptionPtr;
DescriptionSize = StrnSizeS (Description, (LoadOptionSize / sizeof (CHAR16)));
if (DescriptionSize > LoadOptionSize) {
return NULL;
}
//
// Just discard all macOS entries.
//
if (ForFallback && StrCmp (Description, L"Mac OS X") == 0) {
return NULL;
}
LoadOptionPtr += DescriptionSize;
LoadOptionSize -= DescriptionSize;
FilePathList = (EFI_DEVICE_PATH_PROTOCOL *)LoadOptionPtr;
if (!IsDevicePathValid (FilePathList, FilePathListSize)) {
return NULL;
}
//
// Ignore checks for already stored paths.
//
if (!ForFallback) {
return FilePathList;
}
LastNode = NULL;
for (CurrNode = FilePathList; !IsDevicePathEnd (CurrNode); CurrNode = NextDevicePathNode (CurrNode)) {
if (DevicePathType (CurrNode) == MEDIA_DEVICE_PATH && DevicePathSubType (CurrNode) == MEDIA_FILEPATH_DP) {
LastNode = (FILEPATH_DEVICE_PATH *) CurrNode;
}
}
//
// Also discard entries that do not point to files (or maybe folders).
//
if (LastNode == NULL) {
return NULL;
}
//
// In addition discard several predefined names that are known to be macOS related.
// There obviously are more, but we are unlikely to see them.
//
STATIC CONST CHAR16 *mAppleBootloaders[] = {
L"boot.efi",
L"ThorUtil.efi",
L"MultiUpdater.efi"
};
PathLen = OcFileDevicePathNameLen (LastNode);
for (Index = 0; Index < ARRAY_SIZE (mAppleBootloaders); ++Index) {
CurrLen = StrLen (mAppleBootloaders[Index]);
if (PathLen >= CurrLen) {
Index2 = PathLen - CurrLen;
if ((Index2 == 0 || LastNode->PathName[Index2 - 1] == L'\\')
&& CompareMem (&LastNode->PathName[Index2], mAppleBootloaders[Index], CurrLen) == 0) {
return NULL;
}
}
}
return FilePathList;
}
STATIC
VOID
HandleBootEntryFallback (
UINT16 OcBootNum,
EFI_LOAD_OPTION *LoadOption,
UINTN LoadOptionSize
)
{
EFI_STATUS Status;
UINTN Index;
UINTN Index2;
CHAR16 BootOption[L_STR_LEN (L"Boot####") + 1];
INT32 BootNum;
EFI_DEVICE_PATH *SelfPath;
EFI_DEVICE_PATH *OtherPath;
//
// Check if this device path is eligible for fallback entry.
//
SelfPath = GetBootEntryDevicePath (LoadOption, LoadOptionSize, TRUE);
if (SelfPath == NULL) {
return;
}
//
// Check if this boot entry is not already present.
//
mTmpBootOrderSize = sizeof (mTmpBootOrder);
Status = mStoredGetVariable (
L"BootOrder",
&gEfiGlobalVariableGuid,
NULL,
&mTmpBootOrderSize,
mTmpBootOrder
);
if (EFI_ERROR (Status)) {
if (Status == EFI_NOT_FOUND) {
mTmpBootOrderSize = 0;
} else {
//
// We cannot handle this boot order. Should not happen.
//
return;
}
}
BootOption[0] = 'B';
BootOption[1] = 'o';
BootOption[2] = 'o';
BootOption[3] = 't';
BootOption[8] = '\0';
for (Index = 0; Index < mTmpBootOrderSize / sizeof (mTmpBootOrder[0]); ++Index) {
BootOption[4] = "0123456789ABCDEF"[((UINT32) mTmpBootOrder[Index] >> 12U) & 0xFU];
BootOption[5] = "0123456789ABCDEF"[((UINT32) mTmpBootOrder[Index] >> 8U) & 0xFU];
BootOption[6] = "0123456789ABCDEF"[((UINT32) mTmpBootOrder[Index] >> 4U) & 0xFU];
BootOption[7] = "0123456789ABCDEF"[((UINT32) mTmpBootOrder[Index] ) & 0xFU];
mTmpBootOptionSize = sizeof (mTmpBootOption);
Status = mStoredGetVariable (
BootOption,
&gEfiGlobalVariableGuid,
NULL,
&mTmpBootOptionSize,
mTmpBootOption
);
if (EFI_ERROR (Status)) {
//
// Assume orphan entry or whatever it is.
// It can technically not fit, but this is not expected.
//
continue;
}
OtherPath = GetBootEntryDevicePath ((EFI_LOAD_OPTION *) &mTmpBootOption[0], mTmpBootOptionSize, FALSE);
if (OtherPath == NULL) {
//
// Assume invalid entry or whatever it is, just ignore.
//
continue;
}
//
// Check option device paths for equality.
// In case they match, just ignore this option.
//
if (IsDevicePathEqual (SelfPath, OtherPath)) {
return;
}
}
//
// We now want to fallback this option, and need to decide where.
// Check if this boot entry is not written already.
//
BootNum = -1;
for (Index = 0; Index < ARRAY_SIZE (mOcBootOrderMap); ++Index) {
if (mOcBootOrderMap[Index] >= 0) {
if ((UINT16) mOcBootOrderMap[Index] == OcBootNum) {
BootNum = (INT32) (OC_GL_BOOT_OPTION_START + Index);
break;
}
} else if (BootNum < 0) {
for (Index2 = 0; Index2 < mTmpBootOrderSize / sizeof (mTmpBootOrder[0]); ++Index2) {
if (mTmpBootOrder[Index2] == OC_GL_BOOT_OPTION_START + Index) {
break;
}
}
if (Index2 == mTmpBootOrderSize / sizeof (mTmpBootOrder[0])) {
BootNum = (INT32) (OC_GL_BOOT_OPTION_START + Index);
}
}
}
//
// Unless zero or more we cannot write this entry. Should not happen.
//
if (BootNum < 0) {
return;
}
//
// Store the variable.
//
mOcBootOrderMap[BootNum - OC_GL_BOOT_OPTION_START] = OcBootNum;
BootOption[4] = "0123456789ABCDEF"[((UINT32) BootNum >> 12U) & 0xFU];
BootOption[5] = "0123456789ABCDEF"[((UINT32) BootNum >> 8U) & 0xFU];
BootOption[6] = "0123456789ABCDEF"[((UINT32) BootNum >> 4U) & 0xFU];
BootOption[7] = "0123456789ABCDEF"[((UINT32) BootNum ) & 0xFU];
mStoredSetVariable (
BootOption,
&gEfiGlobalVariableGuid,
EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
LoadOptionSize,
LoadOption
);
}
STATIC
EFI_STATUS
EFIAPI
......@@ -902,11 +522,8 @@ WrapSetVariable (
)
{
EFI_STATUS Status;
INT32 BootNum;
BOOLEAN Ints;
BOOLEAN Wp;
BOOLEAN IsBootOrder;
BOOLEAN DoFallback;
//
// Abort access when running with read-only NVRAM.
......@@ -951,43 +568,13 @@ WrapSetVariable (
//
// Redirect Boot-prefixed variables to our own GUID.
//
DoFallback = FALSE;
IsBootOrder = FALSE;
BootNum = -1;
if (gCurrentConfig->BootVariableRedirect
&& IsEfiBootVar (VariableName, VendorGuid, &IsBootOrder, &BootNum)) {
&& IsEfiBootVar (VariableName, VendorGuid)) {
VendorGuid = &gOcVendorVariableGuid;
DoFallback = gCurrentConfig->BootVariableFallback;
}
WriteUnprotectorPrologue (&Ints, &Wp);
//
// Preserve current BootOrder.
//
if (DoFallback && IsBootOrder) {
mTmpBootOrderSize = sizeof (mTmpBootOrder);
Status = mStoredGetVariable (
VariableName,
VendorGuid,
NULL,
&mTmpBootOrderSize,
mTmpBootOrder
);
//
// This should never happen, but if it does, just ignore this BootOrder update
// as we simply cannot track the difference between current and next.
//
if (EFI_ERROR (Status)) {
if (Status == EFI_NOT_FOUND) {
mTmpBootOrderSize = 0;
} else {
IsBootOrder = FALSE;
}
}
}
Status = mStoredSetVariable (
VariableName,
VendorGuid,
......@@ -996,26 +583,6 @@ WrapSetVariable (
Data
);
if (!EFI_ERROR (Status) && DoFallback && Data != NULL && DataSize > 0) {
//
// So, we need to give back our changes.
//
if (IsBootOrder && OC_TYPE_ALIGNED (UINT16, Data)) {
HandleBootOrderFallback (
Data,
DataSize / sizeof (UINT16),
mTmpBootOrder,
mTmpBootOrderSize / sizeof (UINT16)
);
} else if (BootNum >= 0) {
HandleBootEntryFallback (
(UINT16) BootNum,
Data,
DataSize
);
}
}
WriteUnprotectorEpilogue (Ints, Wp);
return Status;
......@@ -1121,11 +688,6 @@ RedirectRuntimeServices (
)
{
EFI_STATUS Status;
UINTN Index;
for (Index = 0; Index < ARRAY_SIZE (mOcBootOrderMap); ++Index) {
mOcBootOrderMap[Index] = -1;
}
mStoredGetTime = gRT->GetTime;
mStoredSetTime = gRT->SetTime;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册