diff --git a/Changelog.md b/Changelog.md index b553a0d894790cccde9d60b3d8a7713f681fcb6b..aa09f5b3f31e7527ff3fff524649f01f0c766892 100644 --- a/Changelog.md +++ b/Changelog.md @@ -11,6 +11,9 @@ OpenCore Changelog - Added global MSR 35h fix to `ProvideCurrentCpuInfo`, allowing `-cpu host` in KVM - Fixed potential memory corruption with AVX acceleration enabled - Added `LogModules` for positive and negative log filtering by modules +- Renamed OpenLinuxBoot driver argument from `partuuidopts:{PARTUUID}` to `autoopts:{PARTUUID}` +- Supported booting Linux from stand-alone `/boot` partition without `/loader/entries` files (user must specify full kernel boot options) +- Handled XML entities in driver arguments #### v0.7.8 - Updated ocvalidate to warn about insecure `DmgLoading` with secure `SecureBootModel` (already disallowed in runtime) diff --git a/Docs/Configuration.md5 b/Docs/Configuration.md5 index 79096dab6a788f1b9d12b66f7d13fa722873d5a9..88656cf952e57061fe30b9421a589f5afa34556b 100644 --- a/Docs/Configuration.md5 +++ b/Docs/Configuration.md5 @@ -1 +1 @@ -cc719727cce977f2aed6cdaa5b88c23f +a0a659b25c35186210abda2a59316cf0 diff --git a/Docs/Configuration.pdf b/Docs/Configuration.pdf index 52b72f809c113ee949ea5c56b201993e841b7b71..2b8f18cb85b143a2bc203e48a059dc1ab67fd166 100644 Binary files a/Docs/Configuration.pdf and b/Docs/Configuration.pdf differ diff --git a/Docs/Configuration.tex b/Docs/Configuration.tex index 0d94219023ae0093b05d0fcdc8253e72dd9cfbb2..f79152ebb0f34a9fca6d6c4551463dfa864fc467 100755 --- a/Docs/Configuration.tex +++ b/Docs/Configuration.tex @@ -6405,7 +6405,7 @@ log when booting (or attempting to boot) a given distro against the options seen \texttt{cat /proc/cmdline} when the same distro has been booted via its native bootloader. In general (for safety and security of the running distro) these options should match, and if they do not it is recommended to use the driver arguments below (in particular \texttt{LINUX\_BOOT\_ADD\_RO}, -\texttt{LINUX\_BOOT\_ADD\_RW}, \texttt{partuuidopts} and \texttt{autoopts}) to modify the options as required. +\texttt{LINUX\_BOOT\_ADD\_RW}, \texttt{autoopts:\{PARTUUID\}} and \texttt{autoopts}) to modify the options as required. Note however that the following differences are normal and do not need to be fixed: \begin{itemize} \tightlist @@ -6433,9 +6433,15 @@ The default parameter values should work well with no changes under most circums options for the driver may be specified in \texttt{UEFI/Drivers/Arguments}: \begin{itemize} +\tightlist + \item \texttt{flags} - Default: all flags are set except the following: + \begin{itemize} \tightlist - \item \texttt{flags} - Default: all flags except \texttt{LINUX\_BOOT\_ADD\_DEBUG\_INFO} and - \texttt{LINUX\_BOOT\_LOG\_VERBOSE} are set. \medskip + \item \texttt{LINUX\_BOOT\_ADD\_RW}, + \item \texttt{LINUX\_BOOT\_LOG\_VERBOSE} and + \item \texttt{LINUX\_BOOT\_ADD\_DEBUG\_INFO}. + \end{itemize} + \medskip Available flags are: \medskip @@ -6489,14 +6495,14 @@ options for the driver may be specified in \texttt{UEFI/Drivers/Arguments}: option on autodetected distros; should be harmless but very slightly slow down boot time (due to requried remount as read-write) on distros which do not require it. When there are multiple distros and it is required to specify this option for specific distros only, use - \texttt{partuuidopts:\{partuuid\}+=ro} to manually add the option where required, instead of using this flag. + \texttt{autoopts:\{PARTUUID\}+=ro} to manually add the option where required, instead of using this flag. \item \texttt{0x00000800} (bit \texttt{11}) --- \texttt{LINUX\_BOOT\_ADD\_RW}, Like \texttt{LINUX\_BOOT\_ADD\_RO}, this option applies to autodetected Linux only. It is not required for most distros (which usually require either \texttt{ro} or nothing to be added to detected boot options), but is required on some Arch-derived distros, e.g. EndeavourOS. When there are multiple distros and it is required to specify this option for specific distros only, use - \texttt{partuuidopts:\{partuuid\}+=rw} to manually add the option where required, instead of using this flag. + \texttt{autoopts:\{PARTUUID\}+=rw} to manually add the option where required, instead of using this flag. If this option and \texttt{LINUX\_BOOT\_ADD\_RO} are both specified, only this option is applied and \texttt{LINUX\_BOOT\_ADD\_RO} is ignored. @@ -6520,12 +6526,12 @@ options for the driver may be specified in \texttt{UEFI/Drivers/Arguments}: add or remove, using syntax such as \texttt{flags+=0xC000} to add all debugging options or \texttt{flags-=0x400} to remove the \texttt{LINUX\_BOOT\_ADD\_RO} option. \medskip - \item \texttt{partuuidopts:\{partuuid\}[+]="\{options\}"} - Default: not set. \medskip + \item \texttt{autoopts:\{PARTUUID\}[+]="\{options\}"} - Default: not set. \medskip - Allows specifying kernel options for a given partition only. If specified with \texttt{+=} then - these are used in addition to autodetected options, if specified with \texttt{=} they are used instead. - Used for autodetected Linux only. Values specified here are never used for entries created from - \texttt{/loader/entries/*.conf} files. + Allows manually specifying kernel options to use in autodetect mode for a given partition only. If specified + with \texttt{+=} then these are used in addition to any autodetected options, if specified with \texttt{=} + they are used instead. Used for autodetected Linux only. Values specified here are never used for entries created + from \texttt{/loader/entries/*.conf} files. \medskip \emph{Note}: The \texttt{partuuid} value to be specified here is typically the same as the \texttt{PARTUUID} @@ -6533,15 +6539,15 @@ options for the driver may be specified in \texttt{UEFI/Drivers/Arguments}: \texttt{cat /proc/cmdline}) for autodetected Debian-style distros, but is not the same for Fedora-style distros booted from \texttt{/loader/entries/*.conf} files. \medskip - Typically this option should not be needed in the latter case, but in case it is, to find out the unique - partition uuid to use look for \texttt{LNX:} entries in the OpenCore debug log file. Alternatively, and + Typically this option should not be needed for \texttt{/loader/entries} distros, but in case it is to find out the + unique partition uuid to use look for \texttt{LNX:} entries in the OpenCore debug log file. Alternatively, and for more advanced scenarios, it is possible to examine how the distro's partitions are mounted using the Linux \texttt{mount} command, and then find out the partuuid of relevant mounted partitions by examining the output of \texttt{ls -l /dev/disk/by-partuuid}. \medskip \item \texttt{autoopts[+]="\{options\}"} - Default: None specified. The kernel options to use for autodetected Linux only. The value here is never used for entries created from - \texttt{/loader/entries/*.conf} files. \texttt{partuuidopts} may be more suitable where there are multiple + \texttt{/loader/entries/*.conf} files. \texttt{autoopts:\{PARTUUID\}} may be more suitable where there are multiple distros, but \texttt{autoopts} with no PARTUUID required is more convenient for just one distro. If specified with \texttt{+=} then these are used in addition to autodetected options, if specified with \texttt{=} they are used instead. As example usage, it is possible to use \texttt{+=} format to add @@ -6565,8 +6571,12 @@ boot \texttt{\{boot\}/vmlinuz*} kernel files directly. It links these automatica kernel version in the filename -- to their associated \texttt{\{boot\}/init*} ramdisk files. This applies to most Debian-related distros, including Debian itself, Ubuntu and variants. -When autodetecting, OpenLinuxBoot looks in \texttt{/etc/default/grub} for kernel boot options and -\texttt{/etc/os-release} for the distro name. +When autodetecting in \texttt{/boot} as part of the root filesystem, OpenLinuxBoot looks in \texttt{/etc/default/grub} +for kernel boot options and \texttt{/etc/os-release} for the distro name. When autodetecting in a standalone boot +partition (i.e. when \texttt{/boot} has its own mount point), OpenLinuxBoot cannot autodetect kernel arguments and +all kernel arguments except \texttt{initrd=...} must be fully specified by hand using \texttt{autoopts=...} or +\texttt{autoopts:\{partuuid\}=...} (\texttt{+=} variants of these options will not work, as these only add additional +arguments). BootLoaderSpecByDefault (but not pure Boot Loader Specification) can expand GRUB variables in the \texttt{*.conf} files -- and this is used in practice in certain distros such as CentOS. diff --git a/Docs/Differences/Differences.pdf b/Docs/Differences/Differences.pdf index 7a5b47bb34485658651213ced508cfd4c338d3a0..3a38f12903d037955267e810b6c8692221933ab4 100644 Binary files a/Docs/Differences/Differences.pdf and b/Docs/Differences/Differences.pdf differ diff --git a/Docs/Differences/Differences.tex b/Docs/Differences/Differences.tex index 342380eadb7c115a6c4cf09c4c00ff4537ce757c..5d1ac1bde577c735a4f5a6d4b1f77706cbf212cf 100644 --- a/Docs/Differences/Differences.tex +++ b/Docs/Differences/Differences.tex @@ -1,7 +1,7 @@ \documentclass[]{article} %DIF LATEXDIFF DIFFERENCE FILE -%DIF DEL PreviousConfiguration.tex Fri Feb 11 00:24:26 2022 -%DIF ADD ../Configuration.tex Fri Feb 25 23:37:24 2022 +%DIF DEL PreviousConfiguration.tex Thu Feb 10 01:48:29 2022 +%DIF ADD ../Configuration.tex Sun Feb 27 08:57:52 2022 \usepackage{lmodern} \usepackage{amssymb,amsmath} @@ -118,7 +118,7 @@ %DIF HYPERREF PREAMBLE %DIF PREAMBLE \providecommand{\DIFadd}[1]{\texorpdfstring{\DIFaddtex{#1}}{#1}} %DIF PREAMBLE \providecommand{\DIFdel}[1]{\texorpdfstring{\DIFdeltex{#1}}{}} %DIF PREAMBLE -%DIF COLORLISTINGS PREAMBLE %DIF PREAMBLE +%DIF LISTINGS PREAMBLE %DIF PREAMBLE \RequirePackage{listings} %DIF PREAMBLE \RequirePackage{color} %DIF PREAMBLE \lstdefinelanguage{DIFcode}{ %DIF PREAMBLE @@ -6475,7 +6475,7 @@ log when booting (or attempting to boot) a given distro against the options seen \texttt{cat /proc/cmdline} when the same distro has been booted via its native bootloader. In general (for safety and security of the running distro) these options should match, and if they do not it is recommended to use the driver arguments below (in particular \texttt{LINUX\_BOOT\_ADD\_RO}, -\texttt{LINUX\_BOOT\_ADD\_RW}, \texttt{partuuidopts} and \texttt{autoopts}) to modify the options as required. +\texttt{LINUX\_BOOT\_ADD\_RW}, \texttt{\DIFdelbegin \DIFdel{partuuidopts}\DIFdelend \DIFaddbegin \DIFadd{autoopts:\{PARTUUID\}}\DIFaddend } and \texttt{autoopts}) to modify the options as required. Note however that the following differences are normal and do not need to be fixed: \begin{itemize} \tightlist @@ -6503,9 +6503,17 @@ The default parameter values should work well with no changes under most circums options for the driver may be specified in \texttt{UEFI/Drivers/Arguments}: \begin{itemize} +\tightlist + \item \texttt{flags} - Default: all flags \DIFdelbegin \DIFdel{except }\texttt{\DIFdel{LINUX\_BOOT\_ADD\_DEBUG\_INFO}} %DIFAUXCMD +\DIFdelend \DIFaddbegin \DIFadd{are set except the following: + }\begin{itemize} \tightlist - \item \texttt{flags} - Default: all flags except \texttt{LINUX\_BOOT\_ADD\_DEBUG\_INFO} and - \texttt{LINUX\_BOOT\_LOG\_VERBOSE} are set. \medskip + \item \texttt{\DIFadd{LINUX\_BOOT\_ADD\_RW}}\DIFadd{, + }\item \texttt{\DIFadd{LINUX\_BOOT\_LOG\_VERBOSE}} \DIFaddend and + \DIFdelbegin \texttt{\DIFdel{LINUX\_BOOT\_LOG\_VERBOSE}} %DIFAUXCMD +\DIFdel{are set . }\DIFdelend \DIFaddbegin \item \texttt{\DIFadd{LINUX\_BOOT\_ADD\_DEBUG\_INFO}}\DIFadd{. + }\end{itemize} + \DIFaddend \medskip Available flags are: \medskip @@ -6559,14 +6567,14 @@ options for the driver may be specified in \texttt{UEFI/Drivers/Arguments}: option on autodetected distros; should be harmless but very slightly slow down boot time (due to requried remount as read-write) on distros which do not require it. When there are multiple distros and it is required to specify this option for specific distros only, use - \texttt{partuuidopts:\{partuuid\}+=ro} to manually add the option where required, instead of using this flag. + \texttt{\DIFdelbegin \DIFdel{partuuidopts}\DIFdelend \DIFaddbegin \DIFadd{autoopts}\DIFaddend :\{\DIFdelbegin \DIFdel{partuuid}\DIFdelend \DIFaddbegin \DIFadd{PARTUUID}\DIFaddend \}+=ro} to manually add the option where required, instead of using this flag. \item \texttt{0x00000800} (bit \texttt{11}) --- \texttt{LINUX\_BOOT\_ADD\_RW}, Like \texttt{LINUX\_BOOT\_ADD\_RO}, this option applies to autodetected Linux only. It is not required for most distros (which usually require either \texttt{ro} or nothing to be added to detected boot options), but is required on some Arch-derived distros, e.g. EndeavourOS. When there are multiple distros and it is required to specify this option for specific distros only, use - \texttt{partuuidopts:\{partuuid\}+=rw} to manually add the option where required, instead of using this flag. + \texttt{\DIFdelbegin \DIFdel{partuuidopts}\DIFdelend \DIFaddbegin \DIFadd{autoopts}\DIFaddend :\{\DIFdelbegin \DIFdel{partuuid}\DIFdelend \DIFaddbegin \DIFadd{PARTUUID}\DIFaddend \}+=rw} to manually add the option where required, instead of using this flag. If this option and \texttt{LINUX\_BOOT\_ADD\_RO} are both specified, only this option is applied and \texttt{LINUX\_BOOT\_ADD\_RO} is ignored. @@ -6590,12 +6598,12 @@ options for the driver may be specified in \texttt{UEFI/Drivers/Arguments}: add or remove, using syntax such as \texttt{flags+=0xC000} to add all debugging options or \texttt{flags-=0x400} to remove the \texttt{LINUX\_BOOT\_ADD\_RO} option. \medskip - \item \texttt{partuuidopts:\{partuuid\}[+]="\{options\}"} - Default: not set. \medskip + \item \texttt{\DIFdelbegin \DIFdel{partuuidopts}\DIFdelend \DIFaddbegin \DIFadd{autoopts}\DIFaddend :\{\DIFdelbegin \DIFdel{partuuid}\DIFdelend \DIFaddbegin \DIFadd{PARTUUID}\DIFaddend \}[+]="\{options\}"} - Default: not set. \medskip - Allows specifying kernel options for a given partition only. If specified with \texttt{+=} then - these are used in addition to autodetected options, if specified with \texttt{=} they are used instead. - Used for autodetected Linux only. Values specified here are never used for entries created from - \texttt{/loader/entries/*.conf} files. + Allows \DIFaddbegin \DIFadd{manually }\DIFaddend specifying kernel options \DIFaddbegin \DIFadd{to use in autodetect mode }\DIFaddend for a given partition only. If specified + with \texttt{+=} then these are used in addition to \DIFaddbegin \DIFadd{any }\DIFaddend autodetected options, if specified with \texttt{=} + they are used instead. Used for autodetected Linux only. Values specified here are never used for entries created + from \texttt{/loader/entries/*.conf} files. \medskip \emph{Note}: The \texttt{partuuid} value to be specified here is typically the same as the \texttt{PARTUUID} @@ -6603,15 +6611,15 @@ options for the driver may be specified in \texttt{UEFI/Drivers/Arguments}: \texttt{cat /proc/cmdline}) for autodetected Debian-style distros, but is not the same for Fedora-style distros booted from \texttt{/loader/entries/*.conf} files. \medskip - Typically this option should not be needed in the latter case, but in case it is, to find out the unique - partition uuid to use look for \texttt{LNX:} entries in the OpenCore debug log file. Alternatively, and + Typically this option should not be needed \DIFdelbegin \DIFdel{in the latter case}\DIFdelend \DIFaddbegin \DIFadd{for }\texttt{\DIFadd{/loader/entries}} \DIFadd{distros}\DIFaddend , but in case it is \DIFdelbegin \DIFdel{, }\DIFdelend to find out the + unique partition uuid to use look for \texttt{LNX:} entries in the OpenCore debug log file. Alternatively, and for more advanced scenarios, it is possible to examine how the distro's partitions are mounted using the Linux \texttt{mount} command, and then find out the partuuid of relevant mounted partitions by examining the output of \texttt{ls -l /dev/disk/by-partuuid}. \medskip \item \texttt{autoopts[+]="\{options\}"} - Default: None specified. The kernel options to use for autodetected Linux only. The value here is never used for entries created from - \texttt{/loader/entries/*.conf} files. \texttt{partuuidopts} may be more suitable where there are multiple + \texttt{/loader/entries/*.conf} files. \texttt{\DIFdelbegin \DIFdel{partuuidopts}\DIFdelend \DIFaddbegin \DIFadd{autoopts:\{PARTUUID\}}\DIFaddend } may be more suitable where there are multiple distros, but \texttt{autoopts} with no PARTUUID required is more convenient for just one distro. If specified with \texttt{+=} then these are used in addition to autodetected options, if specified with \texttt{=} they are used instead. As example usage, it is possible to use \texttt{+=} format to add @@ -6635,8 +6643,13 @@ boot \texttt{\{boot\}/vmlinuz*} kernel files directly. It links these automatica kernel version in the filename -- to their associated \texttt{\{boot\}/init*} ramdisk files. This applies to most Debian-related distros, including Debian itself, Ubuntu and variants. -When autodetecting, OpenLinuxBoot looks in \texttt{/etc/default/grub} for kernel boot options and -\texttt{/etc/os-release} for the distro name. +When autodetecting \DIFaddbegin \DIFadd{in }\texttt{\DIFadd{/boot}} \DIFadd{as part of the root filesystem}\DIFaddend , OpenLinuxBoot looks in \texttt{/etc/default/grub} +for kernel boot options and \texttt{/etc/os-release} for the distro name. \DIFaddbegin \DIFadd{When autodetecting in a standalone boot +partition (i.e. when }\texttt{\DIFadd{/boot}} \DIFadd{has its own mount point), OpenLinuxBoot cannot autodetect kernel arguments and +all kernel arguments except }\texttt{\DIFadd{initrd=...}} \DIFadd{must be fully specified by hand using }\texttt{\DIFadd{autoopts=...}} \DIFadd{or +}\texttt{\DIFadd{autoopts:\{partuuid\}=...}} \DIFadd{(}\texttt{\DIFadd{+=}} \DIFadd{variants of these options will not work, as these only add additional +arguments). +}\DIFaddend BootLoaderSpecByDefault (but not pure Boot Loader Specification) can expand GRUB variables in the \texttt{*.conf} files -- and this is used in practice in certain distros such as CentOS. diff --git a/Docs/Errata/Errata.pdf b/Docs/Errata/Errata.pdf index a843644b55b98fc613a22241b495920a61dae0e8..f00821735e86f1efb79cafc855f6e151e6a65048 100644 Binary files a/Docs/Errata/Errata.pdf and b/Docs/Errata/Errata.pdf differ diff --git a/Library/OcBootManagementLib/BootArguments.c b/Library/OcBootManagementLib/BootArguments.c index 522148457b3b80a84565f8edef3978e10fbf17fa..dddb402c375269ff04e33d7d0a9c45b8b50953e9 100644 --- a/Library/OcBootManagementLib/BootArguments.c +++ b/Library/OcBootManagementLib/BootArguments.c @@ -37,7 +37,7 @@ typedef enum PARSE_VARS_STATE_ { #define SHIFT_TOKEN(pos, token, offset) do { \ CopyMem ((UINT8 *)(token) + (offset), (token), (UINT8 *)(pos) - (UINT8 *)(token)); \ (token) = (UINT8 *)(token) + (offset); \ - (pos) = (UINT8 *)(token) + (offset); \ + (pos) = (UINT8 *)(pos) + (offset); \ } while (0) VOID @@ -516,6 +516,7 @@ OcParseVars ( State = PARSE_VARS_SHELL_EXPANSION; } else if (Ch == L'\\') { SHIFT_TOKEN (Pos, Value, IsUnicode ? sizeof (CHAR16) : sizeof (CHAR8)); + Ch = IsUnicode ? *((CHAR16 *) Pos) : *((CHAR8 *) Pos); } else if ( (State == PARSE_VARS_VALUE && (OcIsSpace (Ch) || Ch == CHAR_NULL)) || (State == PARSE_VARS_QUOTED_VALUE && Ch == '"')) { diff --git a/Library/OcMainLib/OpenCoreUefi.c b/Library/OcMainLib/OpenCoreUefi.c index cf032e6a1c2f5fdb79b6405769d67a3068c0281e..c10651be1b8588f615affa0e10554f7457681b17 100644 --- a/Library/OcMainLib/OpenCoreUefi.c +++ b/Library/OcMainLib/OpenCoreUefi.c @@ -104,6 +104,7 @@ OcLoadDrivers ( CONST CHAR8 *DriverComment; CHAR8 *DriverFileName; CONST CHAR8 *DriverArguments; + CONST CHAR8 *UnescapedArguments; DriversToConnectIterator = NULL; if (DriversToConnect != NULL) { @@ -208,7 +209,19 @@ OcLoadDrivers ( FreePool (Driver); continue; } - if (!OcAppendArgumentsToLoadedImage (LoadedImage, &DriverArguments, 1, TRUE)) { + UnescapedArguments = XmlUnescapeString (DriverArguments); + if (UnescapedArguments == NULL) { + DEBUG (( + DEBUG_ERROR, + "OC: Cannot unescape arguments for driver %a at %u\n", + DriverFileName, + Index + )); + gBS->UnloadImage (ImageHandle); + FreePool (Driver); + continue; + } + if (!OcAppendArgumentsToLoadedImage (LoadedImage, &UnescapedArguments, 1, TRUE)) { DEBUG (( DEBUG_ERROR, "OC: Unable to apply arguments to driver %a at %u - %r!\n", @@ -218,8 +231,10 @@ OcLoadDrivers ( )); gBS->UnloadImage (ImageHandle); FreePool (Driver); + FreePool ((CHAR8 *)UnescapedArguments); continue; } + FreePool ((CHAR8 *)UnescapedArguments); } Status = gBS->StartImage ( diff --git a/Platform/OpenLinuxBoot/Autodetect.c b/Platform/OpenLinuxBoot/Autodetect.c index d37f838d7bee50b3e5d71e90ea463bbd1b5ab3c8..395f18cc4a61132ddc5548be25beab06688caa4d 100644 --- a/Platform/OpenLinuxBoot/Autodetect.c +++ b/Platform/OpenLinuxBoot/Autodetect.c @@ -25,6 +25,7 @@ #define GRUB_DEFAULT_FILE L"\\etc\\default\\grub" #define OS_RELEASE_FILE L"\\etc\\os-release" #define AUTODETECT_DIR L"\\boot" +#define ROOT_DIR L"\\" #define ROOT_FS_FILE L"\\bin\\sh" STATIC @@ -59,6 +60,26 @@ STATIC CHAR8 *mEtcDefaultGrubFileContents; +STATIC +OC_FLEX_ARRAY +*mPerPartuuidAutoOpts; + +STATIC +CHAR16 +*mCurrentPartuuidAutoOpts; + +STATIC +CHAR16 +*mCurrentPartuuidAutoOptsPlus; + +STATIC +CHAR16 +*mGlobalAutoOpts; + +STATIC +CHAR16 +*mGlobalAutoOptsPlus; + STATIC EFI_STATUS ProcessVmlinuzFile ( @@ -129,15 +150,18 @@ CreateAsciiRelativePath ( ) { UINTN Size; + BOOLEAN UseDir; + + UseDir = !(DirectoryPathLength == 1 && DirectoryPath[0] == L'\\'); - Size = DirectoryPathLength + FilePathLength + 2; + Size = (UseDir ? DirectoryPathLength : 0) + FilePathLength + 2; *Dest = AllocatePool (Size); if (*Dest == NULL) { return EFI_OUT_OF_RESOURCES; } - AsciiSPrint (*Dest, Size, "%s\\%s", DirectoryPath, FilePath); + AsciiSPrint (*Dest, Size, "%s\\%s", UseDir ? DirectoryPath : L"", FilePath); return EFI_SUCCESS; } @@ -210,26 +234,31 @@ AutodetectTitle ( STATIC EFI_STATUS LoadOsRelease ( - IN CONST EFI_FILE_PROTOCOL *RootDirectory + IN CONST EFI_FILE_PROTOCOL *RootDirectory, + IN CONST BOOLEAN IsStandaloneBoot ) { EFI_STATUS Status; - BOOLEAN ReadRequired; + BOOLEAN TryReading; mEtcOsReleaseOptions = NULL; mEtcOsReleaseFileContents = NULL; mPrettyName = NULL; - ReadRequired = (mDiskLabel == NULL); + TryReading = (mDiskLabel == NULL); DEBUG_CODE_BEGIN (); - ReadRequired = TRUE; + TryReading = TRUE; DEBUG_CODE_END (); + if (IsStandaloneBoot) { + TryReading = FALSE; + } + // // Load distro name from /etc/os-release. // - if (ReadRequired) { + if (TryReading) { mEtcOsReleaseFileContents = OcReadFileFromDirectory (RootDirectory, OS_RELEASE_FILE, NULL, 0); if (mEtcOsReleaseFileContents == NULL) { DEBUG ((DEBUG_WARN, "LNX: %s not found\n", OS_RELEASE_FILE)); @@ -265,7 +294,8 @@ LoadOsRelease ( STATIC EFI_STATUS LoadDefaultGrub ( - IN CONST EFI_FILE_PROTOCOL *RootDirectory + IN CONST EFI_FILE_PROTOCOL *RootDirectory, + IN CONST BOOLEAN IsStandaloneBoot ) { EFI_STATUS Status; @@ -273,6 +303,10 @@ LoadDefaultGrub ( mEtcDefaultGrubOptions = NULL; mEtcDefaultGrubFileContents = NULL; + if (IsStandaloneBoot) { + return EFI_SUCCESS; + } + // // Load kernel options from /etc/default/grub. // @@ -426,135 +460,186 @@ InsertRootOption ( return CreateRootPartuuid (NewOption); } -// -// TODO: Options for rescue versions. Would it be better e.g. just to add "ro" and nothing else? -// However on some installs (e.g. where modules to load are specified in the kernel opts) this -// would not boot at all. -// Maybe upgrade to partuuidopts:{partuuid}r="...": user options for rescue kernels on specified partuuid? -// STATIC +VOID +GetCurrentPartuuidAutoOpts ( + VOID + ) +{ + UINTN Index; + AUTOOPTS *AutoOpts; + + mCurrentPartuuidAutoOpts = NULL; + mCurrentPartuuidAutoOptsPlus = NULL; + + for (Index = 0; Index < mPerPartuuidAutoOpts->Count; Index++) { + AutoOpts = OcFlexArrayItemAt (mPerPartuuidAutoOpts, Index); + if (CompareMem (&gPartuuid, &AutoOpts->Guid, sizeof (EFI_GUID)) == 0) { + if (AutoOpts->PlusOpts) { + mCurrentPartuuidAutoOptsPlus = AutoOpts->Opts; + } else { + mCurrentPartuuidAutoOpts = AutoOpts->Opts; + } + } + } +} + EFI_STATUS -AutodetectBootOptions ( - IN CONST BOOLEAN IsRescue, +InternalPreloadAutoOpts ( IN OC_FLEX_ARRAY *Options -) + ) { EFI_STATUS Status; UINTN Index; - UINTN InsertIndex; - UINTN OptionCount; OC_PARSED_VAR *Option; - EFI_GUID Guid; - CHAR8 *AsciiStrValue; - CHAR8 *GrubVarName; - BOOLEAN FoundOptions; - BOOLEAN PlusOpts; - CHAR8 *AddRxOption; + AUTOOPTS *AutoOpts; + + mGlobalAutoOpts = NULL; + mGlobalAutoOptsPlus = NULL; - OptionCount = 0; - if (gParsedLoadOptions != NULL) { - OptionCount = gParsedLoadOptions->Count; + mPerPartuuidAutoOpts = OcFlexArrayInit (sizeof (AUTOOPTS), NULL); + if (mPerPartuuidAutoOpts == NULL) { + return EFI_OUT_OF_RESOURCES; } - FoundOptions = FALSE; + if (Options == NULL) { + return EFI_SUCCESS; + } // - // Look for user-specified options for this partuuid. + // Look for autoopts. // Remember that although args are ASCII in the OC config file, they are // Unicode by the time they get passed as UEFI LoadOptions. // - for (Index = 0; Index < OptionCount; Index++) { - Option = OcFlexArrayItemAt (gParsedLoadOptions, Index); + for (Index = 0; Index < Options->Count; Index++) { + Option = OcFlexArrayItemAt (Options, Index); // - // partuuidopts:{partuuid}[+]="...": user options for specified partuuid. + // autoopts:{partuuid}[+]="...": user options for specified partuuid. // - if (OcUnicodeStartsWith (Option->Unicode.Name, L"partuuidopts:", TRUE)) { + if (OcUnicodeStartsWith (Option->Unicode.Name, L"autoopts:", TRUE)) { if (Option->Unicode.Value == NULL) { DEBUG ((DEBUG_WARN, "LNX: Missing value for %s\n", Option->Unicode.Name)); continue; } - Status = StrToGuid (&Option->Unicode.Name[L_STR_LEN (L"partuuidopts:")], &Guid); + AutoOpts = OcFlexArrayAddItem (mPerPartuuidAutoOpts); + + Status = StrToGuid (&Option->Unicode.Name[L_STR_LEN (L"autoopts:")], &AutoOpts->Guid); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_WARN, "LNX: Cannot parse partuuid from %s - %r\n", Option->Unicode.Name, Status)); + OcFlexArrayDiscardItem (mPerPartuuidAutoOpts, FALSE); continue; } - if (CompareMem (&gPartuuid, &Guid, sizeof (EFI_GUID)) != 0) { - DEBUG (( - (gLinuxBootFlags & LINUX_BOOT_LOG_VERBOSE) == 0 ? DEBUG_VERBOSE : DEBUG_INFO, - "LNX: No match partuuidopts:%g != %g\n", - &Guid, - &gPartuuid - )); - } else { - PlusOpts = OcUnicodeEndsWith (Option->Unicode.Name, L"+", FALSE); - - DEBUG (( - (gLinuxBootFlags & LINUX_BOOT_LOG_VERBOSE) == 0 ? DEBUG_VERBOSE : DEBUG_INFO, - "LNX: Using partuuidopts%a=\"%s\"\n", - PlusOpts ? "+" : "", - Option->Unicode.Value - )); - - Status = AddOption (Options, Option->Unicode.Value, TRUE); - if (EFI_ERROR (Status)) { - return Status; - } - - if (!PlusOpts) { - return EFI_SUCCESS; - } - - FoundOptions = TRUE; - } - } - } - - // - // Use global defaults, if user has defined any. - // - for (Index = 0; Index < OptionCount; Index++) { - Option = OcFlexArrayItemAt (gParsedLoadOptions, Index); - // - // Don't use autoopts if partition specific partuuidopts already found. - // - if (!FoundOptions && StrCmp (Option->Unicode.Name, L"autoopts") == 0) { + AutoOpts->Opts = Option->Unicode.Value; + AutoOpts->PlusOpts = OcUnicodeEndsWith (Option->Unicode.Name, L"+", FALSE); + } else if (StrCmp (Option->Unicode.Name, L"autoopts") == 0) { if (Option->Unicode.Value == NULL) { DEBUG ((DEBUG_WARN, "LNX: Missing value for %s\n", Option->Unicode.Name)); continue; } - DEBUG (( - (gLinuxBootFlags & LINUX_BOOT_LOG_VERBOSE) == 0 ? DEBUG_VERBOSE : DEBUG_INFO, - "LNX: Using %s=\"%s\"\n", - Option->Unicode.Name, - Option->Unicode.Value - )); - - Status = AddOption (Options, Option->Unicode.Value, TRUE); - return Status; + mGlobalAutoOpts = Option->Unicode.Value; } else if (StrCmp (Option->Unicode.Name, L"autoopts+") == 0) { if (Option->Unicode.Value == NULL) { DEBUG ((DEBUG_WARN, "LNX: Missing value for %s\n", Option->Unicode.Name)); continue; } - DEBUG (( - (gLinuxBootFlags & LINUX_BOOT_LOG_VERBOSE) == 0 ? DEBUG_VERBOSE : DEBUG_INFO, - "LNX: Using %s=\"%s\"\n", - Option->Unicode.Name, - Option->Unicode.Value - )); + mGlobalAutoOptsPlus = Option->Unicode.Value; + } + } - Status = AddOption (Options, Option->Unicode.Value, TRUE); - if (EFI_ERROR (Status)) { - return Status; - } + return EFI_SUCCESS; +} - FoundOptions = TRUE; +// +// TODO: Options for rescue versions. Would it be better e.g. just to add "ro" and nothing else? +// However on some installs (e.g. where modules to load are specified in the kernel opts) this +// would not boot at all. +// Maybe upgrade to autoopts:{partuuid}r="...": user options for rescue kernels on specified partuuid? +// +STATIC +EFI_STATUS +AutodetectBootOptions ( + IN CONST BOOLEAN IsRescue, + IN CONST BOOLEAN IsStandaloneBoot, + IN OC_FLEX_ARRAY *Options +) +{ + EFI_STATUS Status; + UINTN Index; + UINTN InsertIndex; + CHAR8 *AsciiStrValue; + CHAR8 *GrubVarName; + BOOLEAN FoundOptions; + CHAR8 *AddRxOption; + + FoundOptions = FALSE; + + // + // Do we have user-specified options for this partuuid? + // + if (mCurrentPartuuidAutoOpts) { + DEBUG (( + (gLinuxBootFlags & LINUX_BOOT_LOG_VERBOSE) == 0 ? DEBUG_VERBOSE : DEBUG_INFO, + "LNX: Using autoopts:%g%a=\"%s\"\n", + &gPartuuid, + "", + mCurrentPartuuidAutoOpts + )); + Status = AddOption (Options, mCurrentPartuuidAutoOpts, TRUE); + return Status; + } + + if (mCurrentPartuuidAutoOptsPlus) { + DEBUG (( + (gLinuxBootFlags & LINUX_BOOT_LOG_VERBOSE) == 0 ? DEBUG_VERBOSE : DEBUG_INFO, + "LNX: Using autoopts:%g%a=\"%s\"\n", + &gPartuuid, + "+", + mCurrentPartuuidAutoOptsPlus + )); + Status = AddOption (Options, mCurrentPartuuidAutoOptsPlus, TRUE); + if (EFI_ERROR (Status)) { + return Status; } + FoundOptions = TRUE; } + + // + // Don't use autoopts if partition specific autoopts:{partuuid} already found. + // + if (!FoundOptions && mGlobalAutoOpts) { + DEBUG (( + (gLinuxBootFlags & LINUX_BOOT_LOG_VERBOSE) == 0 ? DEBUG_VERBOSE : DEBUG_INFO, + "LNX: Using autoopts%a=\"%s\"\n", + "", + mGlobalAutoOpts + )); + + Status = AddOption (Options, mGlobalAutoOpts, TRUE); + return Status; + } else if (mGlobalAutoOptsPlus) { + DEBUG (( + (gLinuxBootFlags & LINUX_BOOT_LOG_VERBOSE) == 0 ? DEBUG_VERBOSE : DEBUG_INFO, + "LNX: Using autoopts%a=\"%s\"\n", + "+", + mGlobalAutoOptsPlus + )); + + Status = AddOption (Options, mGlobalAutoOptsPlus, TRUE); + if (EFI_ERROR (Status)) { + return Status; + } + + FoundOptions = TRUE; + } + + // + // Should only have attempted to detect kernels on standalone boot partition if we had full user options. + // + ASSERT (!IsStandaloneBoot); // // Code only reaches here and below if has been nothing or only += options above. @@ -661,7 +746,8 @@ AutodetectBootOptions ( STATIC EFI_STATUS GenerateEntriesForVmlinuzFiles ( - IN CHAR16 *DirectoryPath + IN CHAR16 *DirectoryPath, + IN CONST BOOLEAN IsStandaloneBoot ) { EFI_STATUS Status; @@ -780,7 +866,7 @@ GenerateEntriesForVmlinuzFiles ( // // Add all options. // - Status = AutodetectBootOptions (IsRescue, Entry->Options); + Status = AutodetectBootOptions (IsRescue, IsStandaloneBoot, Entry->Options); if (EFI_ERROR (Status)) { return Status; } @@ -791,42 +877,35 @@ GenerateEntriesForVmlinuzFiles ( STATIC EFI_STATUS -InternalAutodetectLinux ( +AutodetectLinuxAtDirectory ( IN EFI_FILE_PROTOCOL *RootDirectory, + IN EFI_FILE_PROTOCOL *VmlinuzDirectory, + IN CHAR16 *AutodetectDir, + IN CONST BOOLEAN IsStandaloneBoot, OUT OC_PICKER_ENTRY **Entries, OUT UINTN *NumEntries ) { EFI_STATUS Status; - EFI_FILE_PROTOCOL *VmlinuzDirectory; EFI_FILE_PROTOCOL *RootFsFile; - // - // For now we are only searching in /boot. - // vmlinuz files in / should not require autodetect, as - // they should be accompanied by /loader/entries (Fedora-style), - // and vmlinuz files in /boot not accompanied by /loader/entries - // is Debian-style, so it seems sensible to wait to see what - // else there is rather than speculatively adding directories. - // - Status = OcSafeFileOpen (RootDirectory, &VmlinuzDirectory, AUTODETECT_DIR, EFI_FILE_MODE_READ, 0); - if (EFI_ERROR (Status)) { - return Status; - } - mVmlinuzFiles = NULL; mInitrdFiles = NULL; - Status = OcSafeFileOpen (RootDirectory, &RootFsFile, ROOT_FS_FILE, EFI_FILE_MODE_READ, 0); - if (!EFI_ERROR (Status)) { - Status = OcEnsureDirectoryFile (RootFsFile, FALSE); + Status = EFI_SUCCESS; + + if (!IsStandaloneBoot) { + Status = OcSafeFileOpen (RootDirectory, &RootFsFile, ROOT_FS_FILE, EFI_FILE_MODE_READ, 0); + if (!EFI_ERROR (Status)) { + Status = OcEnsureDirectoryFile (RootFsFile, FALSE); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "LNX: %s found but not a %a - %r\n", ROOT_FS_FILE, "file", Status)); + } + RootFsFile->Close (RootFsFile); + } if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_WARN, "LNX: %s found but not a %a - %r\n", ROOT_FS_FILE, "file", Status)); + DEBUG ((DEBUG_WARN, "LNX: AutodetectLinux not root fs - %r\n", Status)); } - RootFsFile->Close (RootFsFile); - } - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_WARN, "LNX: Does not appear to be root filesystem - %r\n", Status)); } if (!EFI_ERROR (Status)) { @@ -866,12 +945,12 @@ InternalAutodetectLinux ( Status = EFI_OUT_OF_RESOURCES; } else { LoadAppleDiskLabel (VmlinuzDirectory); - Status = LoadOsRelease (RootDirectory); + Status = LoadOsRelease (RootDirectory, IsStandaloneBoot); if (!EFI_ERROR (Status)) { - Status = LoadDefaultGrub (RootDirectory); + Status = LoadDefaultGrub (RootDirectory, IsStandaloneBoot); } if (!EFI_ERROR (Status)) { - Status = GenerateEntriesForVmlinuzFiles (AUTODETECT_DIR); + Status = GenerateEntriesForVmlinuzFiles (AutodetectDir, IsStandaloneBoot); } FreeEtcFiles (); } @@ -895,25 +974,70 @@ InternalAutodetectLinux ( OcFlexArrayFree (&mInitrdFiles); } - VmlinuzDirectory->Close (VmlinuzDirectory); return Status; } +STATIC EFI_STATUS -AutodetectLinux ( +DoAutodetectLinux ( IN EFI_FILE_PROTOCOL *RootDirectory, + IN EFI_FILE_PROTOCOL *VmlinuzDirectory, + IN CHAR16 *AutodetectDir, + IN CONST BOOLEAN IsStandaloneBoot, OUT OC_PICKER_ENTRY **Entries, OUT UINTN *NumEntries ) { EFI_STATUS Status; - Status = InternalAutodetectLinux (RootDirectory, Entries, NumEntries); + Status = AutodetectLinuxAtDirectory (RootDirectory, VmlinuzDirectory, AutodetectDir, IsStandaloneBoot, Entries, NumEntries); DEBUG (( (EFI_ERROR (Status) && Status != EFI_NOT_FOUND) ? DEBUG_WARN : DEBUG_INFO, - "LNX: AutodetectLinux - %r\n", - Status)); + "LNX: AutodetectLinux %s - %r\n", + AutodetectDir, + Status + )); + + return Status; +} + +EFI_STATUS +InternalAutodetectLinux ( + IN EFI_FILE_PROTOCOL *RootDirectory, + OUT OC_PICKER_ENTRY **Entries, + OUT UINTN *NumEntries + ) +{ + EFI_STATUS Status; + EFI_FILE_PROTOCOL *VmlinuzDirectory; + + GetCurrentPartuuidAutoOpts (); + + // + // Autodetect at /boot if present. + // + Status = OcSafeFileOpen (RootDirectory, &VmlinuzDirectory, AUTODETECT_DIR, EFI_FILE_MODE_READ, 0); + if (!EFI_ERROR (Status)) { + Status = DoAutodetectLinux (RootDirectory, VmlinuzDirectory, AUTODETECT_DIR, FALSE, Entries, NumEntries); + VmlinuzDirectory->Close (VmlinuzDirectory); + } + + // + // Try to autodetect kernels at / only if detecting at /boot failed and we have full user-specified + // options, since we can't autodetect any options on standalone /boot (unless we parse grub.cfg for + // boot entries, and even then not all standalone boot setups have it). + // + if (EFI_ERROR (Status)) { + if (mCurrentPartuuidAutoOpts != NULL || (mGlobalAutoOpts != NULL && mCurrentPartuuidAutoOptsPlus == NULL)) { + Status = DoAutodetectLinux (RootDirectory, RootDirectory, ROOT_DIR, TRUE, Entries, NumEntries); + } else { + DEBUG (( + (gLinuxBootFlags & LINUX_BOOT_LOG_VERBOSE) == 0 ? DEBUG_VERBOSE : DEBUG_INFO, + "LNX: Not trying to autodetect kernel on possible standalone /boot partition without full autoopts\n" + )); + } + } return Status; } diff --git a/Platform/OpenLinuxBoot/LinuxBootInternal.h b/Platform/OpenLinuxBoot/LinuxBootInternal.h index 3767e1f1b02f19de475ca0e07072c421e6ef98c9..9e8dd901aebf334bca537fb6cf4b5d0b8dfa85b4 100644 --- a/Platform/OpenLinuxBoot/LinuxBootInternal.h +++ b/Platform/OpenLinuxBoot/LinuxBootInternal.h @@ -62,12 +62,12 @@ #define LINUX_BOOT_USE_LATEST BIT9 /* If set, add "ro" as initial option to all distros. Can be specified per - FS by using argument partuuidopts:{partuuid}+=ro instead. + FS by using argument autoopts:{partuuid}+=ro instead. */ #define LINUX_BOOT_ADD_RO BIT10 /* If set, add "rw" as initial option to all distros. Can be specified per - FS by using argument partuuidopts:{partuuid}+=rw instead. + FS by using argument autoopts:{partuuid}+=rw instead. */ #define LINUX_BOOT_ADD_RW BIT11 /* @@ -97,6 +97,7 @@ LINUX_BOOT_ALLOW_AUTODETECT | \ LINUX_BOOT_USE_LATEST | \ LINUX_BOOT_ADD_RO | \ + LINUX_BOOT_ADD_RW | \ LINUX_BOOT_ALLOW_CONF_AUTO_ROOT | \ LINUX_BOOT_LOG_VERBOSE | \ LINUX_BOOT_ADD_DEBUG_INFO \ @@ -119,12 +120,6 @@ extern UINTN gLinuxBootFlags; */ extern OC_PICKER_CONTEXT *gPickerContext; -/* - Stored parsed load options. - Would be freed at driver unload, if that happened. - */ -extern OC_FLEX_ARRAY *gParsedLoadOptions; - /* The array of loader entries, either really from *.conf files or generated by autodetect. */ @@ -153,11 +148,6 @@ typedef struct GRUB_VAR_ GRUB_VAR; */ typedef struct LOADER_ENTRY_ LOADER_ENTRY; -/* - Forward declaration of VMLINUZ_FILE structure. -*/ -typedef struct VMLINUZ_FILE_ VMLINUZ_FILE; - /* GRUB vars. */ @@ -329,17 +319,34 @@ struct LOADER_ENTRY_ { BOOLEAN DuplicateIdScanned; }; -struct VMLINUZ_FILE_ { +typedef struct VMLINUZ_FILE_ { CHAR16 *FileName; CHAR16 *Version; UINTN StrLen; -}; +} VMLINUZ_FILE; + +/* + Autodetect options. +*/ +typedef struct AUTOOPTS_ { + EFI_GUID Guid; + CHAR16 *Opts; + BOOLEAN PlusOpts; +} AUTOOPTS; + +/* + Load autoopts. +*/ +EFI_STATUS +InternalPreloadAutoOpts ( + IN OC_FLEX_ARRAY *Options + ); /* Autodetect. */ EFI_STATUS -AutodetectLinux ( +InternalAutodetectLinux ( IN EFI_FILE_PROTOCOL *RootDirectory, OUT OC_PICKER_ENTRY **Entries, OUT UINTN *NumEntries diff --git a/Platform/OpenLinuxBoot/OpenLinuxBoot.c b/Platform/OpenLinuxBoot/OpenLinuxBoot.c index 7a3a0e3285d5979f3cdc9f90942a1a70936697a6..3e1644a20764c5bb5c6b96d8866b47dc8b1e0bf0 100644 --- a/Platform/OpenLinuxBoot/OpenLinuxBoot.c +++ b/Platform/OpenLinuxBoot/OpenLinuxBoot.c @@ -21,10 +21,11 @@ #include -UINTN gLinuxBootFlags = LINUX_BOOT_ALL & ~(LINUX_BOOT_ADD_DEBUG_INFO | LINUX_BOOT_LOG_VERBOSE); +UINTN gLinuxBootFlags = LINUX_BOOT_ALL & ~(LINUX_BOOT_ADD_DEBUG_INFO | LINUX_BOOT_LOG_VERBOSE | LINUX_BOOT_ADD_RW); + +OC_FLEX_ARRAY *mParsedLoadOptions; OC_PICKER_CONTEXT *gPickerContext; -OC_FLEX_ARRAY *gParsedLoadOptions; OC_FLEX_ARRAY *gLoaderEntries; EFI_GUID gPartuuid; CHAR8 *gFileSystemType; @@ -237,17 +238,16 @@ OcGetLinuxBootEntries ( // if no /loader/entries/*.conf files are present, but also if there // are only unusable files in there. // - if (EFI_ERROR (Status)) { + if (EFI_ERROR (Status) + && (gLinuxBootFlags & LINUX_BOOT_ALLOW_AUTODETECT) != 0) { // // Auto-detect vmlinuz and initrd files on own root filesystem (Debian-like). // - if ((gLinuxBootFlags & LINUX_BOOT_ALLOW_AUTODETECT) != 0) { - Status = AutodetectLinux ( - RootDirectory, - Entries, - NumEntries - ); - } + Status = InternalAutodetectLinux ( + RootDirectory, + Entries, + NumEntries + ); } RootDirectory->Close (RootDirectory); @@ -285,17 +285,31 @@ UefiMain ( return Status; } - Status = OcParseLoadOptions (LoadedImage, &gParsedLoadOptions); + // + // Keep mParsedLoadOptions kicking around, as all found options link into its memory. + // + Status = OcParseLoadOptions (LoadedImage, &mParsedLoadOptions); if (!EFI_ERROR (Status)) { AddBootFlags = 0; RemoveBootFlags = 0; - OcParsedVarsGetInt (gParsedLoadOptions, L"flags", &gLinuxBootFlags, TRUE); - OcParsedVarsGetInt (gParsedLoadOptions, L"flags+", &AddBootFlags, TRUE); - OcParsedVarsGetInt (gParsedLoadOptions, L"flags-", &RemoveBootFlags, TRUE); + OcParsedVarsGetInt (mParsedLoadOptions, L"flags", &gLinuxBootFlags, TRUE); + OcParsedVarsGetInt (mParsedLoadOptions, L"flags+", &AddBootFlags, TRUE); + OcParsedVarsGetInt (mParsedLoadOptions, L"flags-", &RemoveBootFlags, TRUE); gLinuxBootFlags |= AddBootFlags; gLinuxBootFlags &= ~RemoveBootFlags; - } else if (Status != EFI_NOT_FOUND) { - return Status; + } else { + if (Status != EFI_NOT_FOUND) { + return Status; + } + ASSERT (mParsedLoadOptions == NULL); + } + + if ((gLinuxBootFlags & LINUX_BOOT_ALLOW_AUTODETECT) != 0) { + Status = InternalPreloadAutoOpts (mParsedLoadOptions); + + if (EFI_ERROR (Status)) { + return Status; + } } Status = gBS->InstallMultipleProtocolInterfaces (