Skip to content

Commit

Permalink
OCVAR: Refactor NVRAM code, add OpenVariableRuntimeDxe
Browse files Browse the repository at this point in the history
  • Loading branch information
mikebeaton committed Jun 28, 2022
1 parent e733af2 commit 9546ac6
Show file tree
Hide file tree
Showing 88 changed files with 11,473 additions and 940 deletions.
2 changes: 1 addition & 1 deletion Application/CleanNvram/CleanNvram.c
Expand Up @@ -13,8 +13,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/

#include <Uefi.h>
#include <Library/OcBootManagementLib.h>
#include <Library/OcMiscLib.h>
#include <Library/OcVariableLib.h>
#include <Library/UefiApplicationEntryPoint.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
Expand Down
1 change: 1 addition & 0 deletions Application/CleanNvram/CleanNvram.inf
Expand Up @@ -43,5 +43,6 @@
[LibraryClasses]
OcBootManagementLib
OcConsoleControlEntryModeGenericLib
OcVariableLib
UefiApplicationEntryPoint
UefiBootServicesTableLib
2 changes: 1 addition & 1 deletion Application/CsrUtil/CsrUtil.c
Expand Up @@ -8,7 +8,7 @@
#include <Uefi.h>
#include <Library/OcDebugLogLib.h>
#include <Library/OcMiscLib.h>
#include <Library/OcBootManagementLib.h>
#include <Library/OcVariableLib.h>
#include <Library/UefiApplicationEntryPoint.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
Expand Down
2 changes: 1 addition & 1 deletion Application/CsrUtil/CsrUtil.inf
Expand Up @@ -34,6 +34,6 @@
OpenCorePkg/OpenCorePkg.dec

[LibraryClasses]
OcBootManagementLib
OcVariableLib
UefiBootServicesTableLib
UefiApplicationEntryPoint
2 changes: 2 additions & 0 deletions Application/OpenCore/OpenCore.c
Expand Up @@ -35,6 +35,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Library/OcCpuLib.h>
#include <Library/OcDevicePathLib.h>
#include <Library/OcStorageLib.h>
#include <Library/OcVariableLib.h>
#include <Library/PrintLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
Expand Down Expand Up @@ -135,6 +136,7 @@ OcMain (

DEBUG ((DEBUG_INFO, "OC: OcLoadNvramSupport...\n"));
OcLoadNvramSupport (Storage, &mOpenCoreConfiguration);
OcReportVersion (&mOpenCoreConfiguration);
DEBUG ((DEBUG_INFO, "OC: OcMiscMiddleInit...\n"));
OcMiscMiddleInit (
Storage,
Expand Down
2 changes: 1 addition & 1 deletion Application/ResetSystem/ResetSystem.c
Expand Up @@ -16,7 +16,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include <Uefi.h>
#include <Library/BaseMemoryLib.h>
#include <Library/OcDebugLogLib.h>
#include <Library/OcDeviceMiscLib.h>
#include <Library/OcDirectResetLib.h>
#include <Library/OcMiscLib.h>
#include <Library/OcStringLib.h>
#include <Library/UefiApplicationEntryPoint.h>
Expand Down
2 changes: 1 addition & 1 deletion Application/ResetSystem/ResetSystem.inf
Expand Up @@ -42,7 +42,7 @@
[LibraryClasses]
BaseLib
DebugLib
OcDeviceMiscLib
OcDirectResetLib
OcMiscLib
OcStringLib
UefiApplicationEntryPoint
Expand Down
3 changes: 3 additions & 0 deletions Changelog.md
Expand Up @@ -6,6 +6,9 @@ OpenCore Changelog
- Updated builtin firmware versions for SMBIOS and the rest
- Added macOS 13 support for `AvoidRuntimeDefrag` Booter quirk
- Added injected kext bundle version printing in DEBUG builds
- Added support for NVRAM reset and set default boot entry when using emulated NVRAM
- Upgraded emulated NVRAM logout script to allow unsupervised installation of recent macOS OTA updates
- Added emulated NVRAM driver allowing use separately from OpenDuet

#### v0.8.1
- Improved `ExtendBTFeatureFlags` quirk on newer macOS versions, thx @lvs1974
Expand Down
185 changes: 147 additions & 38 deletions Docs/Configuration.tex
Expand Up @@ -494,7 +494,11 @@ \subsection{Directory Structure}\label{directory-structure}
child [missing] {}
child [missing] {}
child { node [optional] {boot}}
child { node [optional] {nvram.plist}}
child { node {NVRAM}
child { node [optional] {nvram.plist}}
child { node [optional] {nvram.fallback}}
child { node [optional] {nvram.used}}
}
child { node [optional] {opencore-YYYY-MM-DD-HHMMSS.txt}}
child { node [optional] {panic-YYYY-MM-DD-HHMMSS.txt}}
child { node [optional] {SysReport}}
Expand Down Expand Up @@ -567,6 +571,12 @@ \subsection{Directory Structure}\label{directory-structure}
\item
\texttt{nvram.plist} \\
OpenCore variable import file.
\item
\texttt{nvram.fallback} \\
OpenCore variable import fallback file.
\item
\texttt{nvram.used} \\
Renamed previous OpenCore variable import file after switch to fallback file.
\item
\texttt{opencore-YYYY-MM-DD-HHMMSS.txt} \\
OpenCore log file.
Expand Down Expand Up @@ -3957,6 +3967,7 @@ \subsection{Debug Properties}\label{miscdebugprops}
\item \texttt{OCTPL} --- OcTemplateLib
\item \texttt{OCUC} --- OcUnicodeCollationLib
\item \texttt{OCUT} --- OcAppleUserInterfaceThemeLib
\item \texttt{OCVAR} --- OcVariableLib
\item \texttt{OCXML} --- OcXmlLib
\end{itemize}

Expand Down Expand Up @@ -4753,35 +4764,6 @@ \subsection{Properties}\label{nvramprops}
of GUIDs to an array (\texttt{plist\ array}) of variable names in
\texttt{plist\ string} format.

\item
\texttt{LegacyEnable}\\
\textbf{Type}: \texttt{plist\ boolean}\\
\textbf{Failsafe}: \texttt{false}\\
\textbf{Description}: Enables loading a NVRAM variable file named \texttt{nvram.plist}
from EFI volume root.

This file must have a root \texttt{plist\ dictionary} type and contain two fields:
\begin{itemize}
\tightlist
\item \texttt{Version} --- \texttt{plist\ integer}, file version, must be set to 1.
\item \texttt{Add} --- \texttt{plist\ dictionary}, equivalent to \texttt{Add} from
\texttt{config.plist}.
\end{itemize}

Variable loading happens prior to the \texttt{Delete} (and \texttt{Add}) phases. Unless
\texttt{LegacyOverwrite} is enabled, it will not overwrite any existing variable.
Variables allowed to be set must be specified in \texttt{LegacySchema}.

Third-party scripts may be used to create \texttt{nvram.plist}
file. An example of such script can be found in
\href{https://github.com/acidanthera/OpenCorePkg/tree/master/Utilities/LogoutHook}{\texttt{Utilities/LogoutHook}}.
The use of third-party scripts may require \texttt{ExposeSensitiveData} set to \texttt{0x3} to provide
\texttt{boot-path} variable with the OpenCore EFI partition UUID.

\textbf{Warning}: This feature can be dangerous, as it passes unprotected data to
firmware variable services. Only use when no hardware NVRAM implementation is
provided by the firmware or when the NVRAM implementation is incompatible.

\item
\texttt{LegacyOverwrite}\\
\textbf{Type}: \texttt{plist\ boolean}\\
Expand Down Expand Up @@ -6289,7 +6271,7 @@ \subsection{Drivers}\label{uefidrivers}
Loading an incompatible driver may lead the system to unbootable state or
even cause permanent firmware damage. Some of the known drivers are listed below:

\begin{longtable}{p{1.3in}p{5.55in}}
\begin{longtable}{p{1.65in}p{5.25in}}
\href{https://github.com/acidanthera/OpenCorePkg}{\texttt{AudioDxe}}\textbf{*}
& \hyperref[uefiaudio]{HDA audio support driver} in UEFI firmware for most Intel and some other analog audio controllers.
Staging driver, refer to \href{https://github.com/acidanthera/bugtracker/issues/740}{acidanthera/bugtracker\#740}
Expand Down Expand Up @@ -6346,10 +6328,14 @@ \subsection{Drivers}\label{uefidrivers}
& USB keyboard driver adding support for \texttt{AppleKeyMapAggregator} protocols
on top of a custom USB keyboard driver implementation. This is an alternative to
builtin \texttt{KeySupport}, which may work better or worse depending on the firmware. \\
\href{https://github.com/acidanthera/OcBinaryData}{\texttt{OpenPartitionDxe}}\textbf{*}
\href{https://github.com/acidanthera/OpenCorePkg}{\texttt{OpenPartitionDxe}}\textbf{*}
& Partition management driver with Apple Partitioning Scheme support.
This driver can be used to support loading older DMG recoveries such as
macOS 10.9 using Apple Partitioning Scheme. OpenDuet already includes this driver. \\
This driver can be used to support loading older DMG recoveries such as macOS 10.9
using Apple Partitioning Scheme, or for loading other macOS Installers where these were
created using the Apple Partitioning Scheme (creating macOS Installers using GPT avoids
the need for this). OpenDuet already includes this driver. \\
\href{https://github.com/acidanthera/OpenCorePkg}{\texttt{OpenVariableRuntimeDxe}}\textbf{*}
& \hyperref[emunvram]{OpenCore plugin} offering emulated NVRAM support. \\
\href{https://github.com/acidanthera/audk}{\texttt{Ps2KeyboardDxe}}\textbf{*}
& PS/2 keyboard driver from \texttt{MdeModulePkg}. \texttt{OpenDuetPkg} and some types of firmware
may not include this driver, but it is necessary for PS/2 keyboard to work.
Expand Down Expand Up @@ -6954,6 +6940,119 @@ \subsubsection{Configuration}
some other systems. \medskip
\end{itemize}

\subsection{OpenVariableRuntimeDxe}\label{emunvram}

Provides in-memory emulated NVRAM implementation. This can be useful on systems with fragile
(e.g. MacPro5,1, see discussion linked from this \href{https://forums.macrumors.com/threads/opencore-on-the-mac-pro.2207814/page-425?post=30945127#post-30945127}{forum post})
or incompatible NVRAM implementations. This driver is included by default in OpenDuet.

In addition to installing emulated NVRAM, this driver additionally installs an OpenCore compatible
protocol enabling the following:

\begin{itemize}
\tightlist
\item NVRAM values are loaded from \texttt{NVRAM/nvram.plist} (or from \texttt{NVRAM/nvram.fallback}
if it is present and \texttt{NVRAM/nvram.plist} is missing) on boot
\item The Reset NVRAM option installed by the \texttt{ResetNvramEntry} driver removes the above files instead
of affecting underlying NVRAM
\item \texttt{CTRL+Enter} in the OpenCore bootpicker updates or creates \texttt{NVRAM/nvram.plist}
\end{itemize}

Recommended configuration settings for this driver:

\begin{itemize}
\tightlist
\item \texttt{OpenVariableRuntimeDxe.efi} loaded using \texttt{Load=Early} (not required with OpenDuet).
\item \texttt{OpenRuntime.efi} specified after \texttt{OpenVariableRuntimeDxe.efi} in the
\texttt{Drivers} list and loaded using \texttt{Load=Early} (not required with OpenDuet).
\item \texttt{LegacySchema} populated.
\item \texttt{ExposeSensitiveData} with at least bit \texttt{0x1} set to make \texttt{boot-path}
variable containing the OpenCore EFI partition UUID available to the \texttt{Launchd.command} script.
\end{itemize}

Variable loading happens prior to the NVRAM \texttt{Delete} (and \texttt{Add}) phases. Unless
\texttt{LegacyOverwrite} is enabled, it will not overwrite any existing variable.
Variables allowed for loading and for saving with \texttt{CTRL+Enter} must be specified in \texttt{LegacySchema}.

In order to allow changes to NVRAM within macOS to be captured and saved,
an additional script must be installed. An example of such script can be found in
\href{https://github.com/acidanthera/OpenCorePkg/tree/master/Utilities/LogoutHook/Launchd.command}{\texttt{Utilities/LogoutHook/Launchd.command}}.

\emph{Note 1}: This driver requires working FAT write support in firmware, and sufficient free
space on the OpenCore EFI partition for up to three saved NVRAM files.

\emph{Note 2}: The \texttt{nvram.plist} (and \texttt{nvram.fallback} if present) files must have a
root \texttt{plist\ dictionary} type and contain two fields:
\begin{itemize}
\tightlist
\item \texttt{Version} --- \texttt{plist\ integer}, file version, must be set to 1.
\item \texttt{Add} --- \texttt{plist\ dictionary}, equivalent to \texttt{Add} from
\texttt{config.plist}.
\end{itemize}

\emph{Note 3}: When setting up legacy NVRAM, it can be convenient to set \texttt{<string>*</string>}
as the value for the following three GUID keys in \texttt{LegacySchema}:
\begin{itemize}
\tightlist
\item 36C28AB5-6566-4C50-9EBD-CBB920F83843
\item 7C436110-AB2A-4BBB-A880-FE41995C9F82
\item 8BE4DF61-93CA-11D2-AA0D-00E098032B8C
\end{itemize}
This enables all variables saved by \texttt{Launchd.command}, and additionally all arbitrary user
test variables (e.g. as set by \texttt{sudo nvram foo="bar"}), to be saved to \texttt{nvram.plist}.
However, once set up, only allowing strictly required variables (as shown in OpenCore's sample
\texttt{.plist} files) is considerably more secure, and please note the following warning about the
overall security of loading nvram variables from a non-vaulted file.

\textbf{Warning}: The ability to load NVRAM from a file on disk can be dangerous, as it
passes unprotected data to firmware variable services. Only use when no hardware NVRAM
implementation is provided by the firmware or when the NVRAM implementation available in
firmware is incompatible or dangerously fragile (e.g. in a state where excessive use
may cause bricked hardware).

\subsubsection{Managing macOS updates when using emulated NVRAM}

OpenCore combined with \texttt{OpenVariableRuntimeDxe} will only use a given saved \texttt{nvram.plist} file once,
if it is used to launch a \texttt{macOS Installer} boot entry. After that the used settings are moved to \texttt{nvram.used}
and fallback settings, if any, from \texttt{nvram.fallback} are used instead. \texttt{Launchd.command} itself
always copies the previous NVRAM settings to fallback, each time it saves new settings.

This strategy is used to work round the limitation that the \texttt{Launchd.command} script is not running,
and therefore cannot save NVRAM changes (particularly default boot entry changes), during the second
and subsequent restarts of the macOS installer.

In brief, this fallback strategy allows full or incremental OTA updates of recent macOS, which are started from within
an existing macOS (with the \texttt{Launchd.command} script installed), to proceed without manual intervention.

However, for full installs, there can be more than one full restart back to the \texttt{macOS Installer} entry. In this case
the fallback strategy will lose track of the correct startup item (i.e. \texttt{macOS Installer}) from the second reboot
onwards. Equally, if installing to a drive other than the current default boot partition, this will not be automatically selected after
the installer completes, as it would be when using non-emulated NVRAM. (This behaviour remains preferable to not having the fallback strategy,
in which case a \texttt{macOS Installer} entry would be continually recreated in the picker menu, even once it no longer exists).

In both the above two cases it is recommended to use the following settings, to make it easy to manually control which boot
entry is selected during the installer process:

\begin{itemize}
\tightlist
\item Set \texttt{ShowPicker=true}.
\item Set \texttt{Timeout=0}.
\item Set \texttt{DisableWatchdog=true}.
\item If possible, start from a situation where there are no other pending \texttt{macOS Installer} entries in the boot menu
(to avoid potential confusion as to which is relevant).
\end{itemize}

The first reboot should correctly select \texttt{macOS Installer}. For second and subsequent reboots, if a \texttt{macOS Installer}
entry is still present it should be manually selected (using just Enter, not \texttt{CTRL+Enter}). Once a \texttt{macOS Installer}
entry is no longer present, the entry for the new OS will still be automatically selected if it was the previous boot default.
If not, it should be manually selected (at this point, \texttt{CTRL+Enter} is a good idea as any final remaining installion restarts
will be to this entry).

\emph{Note}: When using emulated NVRAM but not installing from within an existing installed macOS (i.e. when installing from
within macOS Recovery, or from an installation USB), please refer to this
\href{https://applelife.ru/threads/ustanovka-macos-big-sur-11-na-intel-pc.2945052/page-393#post-916248}{forum post} (in Russian)
for additional options.

\subsection{Properties}\label{uefiprops}

\begin{enumerate}
Expand Down Expand Up @@ -7636,10 +7735,20 @@ \subsection{Drivers Properties}\label{uefidriversprops}
from \texttt{OC/Drivers} directory.

\item
\texttt{Enabled}\\
\textbf{Type}: \texttt{plist\ boolean}\\
\textbf{Failsafe}: \texttt{false}\\
\textbf{Description}: If \texttt{false} this driver entry will be ignored.
\texttt{Load}\\
\textbf{Type}: \texttt{plist\ string}\\
\textbf{Failsafe}: \texttt{Disabled}\\
\textbf{Description}: When and whether to load this driver.

\begin{itemize}
\tightlist
\item \texttt{Disabled} --- Do not load this driver.
\item \texttt{Enabled} --- Load the driver normally.
\item \texttt{Early} --- Load the driver early in the OpenCore boot processes, before NVRAM setup.
\end{itemize}

\emph{Note}: Do not use the \texttt{Early} option unless specifically recommended to do so for a
given driver and purpose.

\item
\texttt{Arguments}\\
Expand Down

0 comments on commit 9546ac6

Please sign in to comment.