From 1ac657ed0e808b8229e5f6908f109c68aeec0eba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Sun, 3 Apr 2022 02:48:36 +0200 Subject: [PATCH] [FREELDR:NTLDR] Normalize the boot options as soon as possible, and fix the algorithm Use `NtLdrGetNextOption()` to loop over each individual option and move it to its proper place. This automatically trims any '/' option separator, including repeated ones and whitespaces, and allow for straightforward replacement with one single space. --- boot/freeldr/freeldr/ntldr/setupldr.c | 18 ++++---- boot/freeldr/freeldr/ntldr/winldr.c | 64 +++++++++++++++++++-------- boot/freeldr/freeldr/ntldr/winldr.h | 4 ++ 3 files changed, 58 insertions(+), 28 deletions(-) diff --git a/boot/freeldr/freeldr/ntldr/setupldr.c b/boot/freeldr/freeldr/ntldr/setupldr.c index 7a71c8736f3..6eae94852c1 100644 --- a/boot/freeldr/freeldr/ntldr/setupldr.c +++ b/boot/freeldr/freeldr/ntldr/setupldr.c @@ -509,7 +509,7 @@ LoadReactOSSetup( PSETUP_LOADER_BLOCK SetupBlock; CHAR BootPath[MAX_PATH]; CHAR FilePath[MAX_PATH]; - CHAR UserBootOptions[256]; + CHAR UserBootOptions[MAX_OPTIONS_LENGTH+1]; PCSTR BootOptions; static PCSTR SourcePaths[] = @@ -606,8 +606,7 @@ LoadReactOSSetup( BootOptions = GetArgumentValue(Argc, Argv, "Options"); if (!BootOptions) BootOptions = ""; - - TRACE("BootOptions: '%s'\n", BootOptions); + TRACE("BootOptions(1): '%s'\n", BootOptions); /* Check if a RAM disk file was given */ FileName = (PSTR)NtLdrGetOptionEx(BootOptions, "RDPATH=", &FileNameLength); @@ -650,7 +649,6 @@ LoadReactOSSetup( TRACE("BootPath: '%s', SystemPath: '%s'\n", BootPath, SystemPath); // UseLocalSif = NtLdrGetOption(BootOptions, "USELOCALSIF"); - if (NtLdrGetOption(BootOptions, "SIFOPTIONSOVERRIDE")) { PCSTR OptionsToRemove[2] = {"SIFOPTIONSOVERRIDE", NULL}; @@ -665,8 +663,6 @@ LoadReactOSSetup( FALSE, NULL, OptionsToRemove); - - BootOptions = UserBootOptions; } else // if (!*BootOptions || NtLdrGetOption(BootOptions, "SIFOPTIONSADD")) { @@ -778,11 +774,15 @@ LoadReactOSSetup( FrLdrHeapFree(ExtraOptions, TAG_BOOT_OPTIONS); if (HigherPriorityOptions) FrLdrHeapFree(HigherPriorityOptions, TAG_BOOT_OPTIONS); - - BootOptions = UserBootOptions; } - TRACE("BootOptions: '%s'\n", BootOptions); + /* Append boot-time options */ + AppendBootTimeOptions(UserBootOptions); + + /* Post-process the boot options */ + NtLdrNormalizeOptions(UserBootOptions); + BootOptions = UserBootOptions; + TRACE("BootOptions(2): '%s'\n", BootOptions); /* Handle the SOS option */ SosEnabled = !!NtLdrGetOption(BootOptions, "SOS"); diff --git a/boot/freeldr/freeldr/ntldr/winldr.c b/boot/freeldr/freeldr/ntldr/winldr.c index 4fd17e1e10f..9932e4beeb0 100644 --- a/boot/freeldr/freeldr/ntldr/winldr.c +++ b/boot/freeldr/freeldr/ntldr/winldr.c @@ -130,13 +130,12 @@ WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock, { /* * Examples of correct options and paths: - * CHAR Options[] = "/DEBUGPORT=COM1 /BAUDRATE=115200"; - * CHAR Options[] = "/NODEBUG"; + * CHAR Options[] = "DEBUGPORT=COM1 BAUDRATE=115200"; + * CHAR Options[] = "NODEBUG"; * CHAR SystemRoot[] = "\\WINNT\\"; * CHAR ArcBoot[] = "multi(0)disk(0)rdisk(0)partition(1)"; */ - PSTR LoadOptions, NewLoadOptions; CHAR HalPath[] = "\\"; CHAR ArcBoot[MAX_PATH+1]; CHAR MiscFiles[MAX_PATH+1]; @@ -188,18 +187,9 @@ WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock, RtlStringCbCopyA(LoaderBlock->NtHalPathName, sizeof(WinLdrSystemBlock->NtHalPathName), HalPath); LoaderBlock->NtHalPathName = PaToVa(LoaderBlock->NtHalPathName); - /* Fill LoadOptions and strip the '/' switch symbol in front of each option */ - NewLoadOptions = LoadOptions = LoaderBlock->LoadOptions = WinLdrSystemBlock->LoadOptions; + /* Fill LoadOptions */ + LoaderBlock->LoadOptions = WinLdrSystemBlock->LoadOptions; RtlStringCbCopyA(LoaderBlock->LoadOptions, sizeof(WinLdrSystemBlock->LoadOptions), Options); - - do - { - while (*LoadOptions == '/') - ++LoadOptions; - - *NewLoadOptions++ = *LoadOptions; - } while (*LoadOptions++); - LoaderBlock->LoadOptions = PaToVa(LoaderBlock->LoadOptions); /* ARC devices */ @@ -1142,6 +1132,39 @@ WinLdrInitErrataInf( return TRUE; } +/** + * @brief + * Normalize in-place the NT boot options by removing any leading '/', + * normalizing TABs to spaces, etc. + **/ +VOID +NtLdrNormalizeOptions( + _Inout_ PSTR LoadOptions) +{ + PCHAR NewOptions = LoadOptions; + PCSTR Options, Option; + ULONG OptionLength; + + /* Normalize the boot options by successively enumerating each and + * copying them back, stripping and replacing any extra separator + * by one single space. */ + Options = LoadOptions; + while ((Option = NtLdrGetNextOption(&Options, &OptionLength))) + { + if (NewOptions > LoadOptions) + *NewOptions++ = ' '; + + /* If necessary, move the current option back */ + ASSERT(NewOptions <= Option); + if (NewOptions < Option) + RtlMoveMemory(NewOptions, Option, OptionLength * sizeof(CHAR)); + NewOptions += OptionLength; + } + + /* NUL-terminate */ + *NewOptions = ANSI_NULL; +} + ARC_STATUS LoadAndBootWindows( IN ULONG Argc, @@ -1158,7 +1181,7 @@ LoadAndBootWindows( PLOADER_PARAMETER_BLOCK LoaderBlock; CHAR BootPath[MAX_PATH]; CHAR FilePath[MAX_PATH]; - CHAR BootOptions[256]; + CHAR BootOptions[MAX_OPTIONS_LENGTH+1]; /* Retrieve the (mandatory) boot type */ ArgValue = GetArgumentValue(Argc, Argv, "BootType"); @@ -1240,9 +1263,7 @@ LoadAndBootWindows( ArgValue = GetArgumentValue(Argc, Argv, "Options"); if (ArgValue && *ArgValue) RtlStringCbCopyA(BootOptions, sizeof(BootOptions), ArgValue); - - /* Append boot-time options */ - AppendBootTimeOptions(BootOptions); + TRACE("BootOptions(1): '%s'\n", BootOptions); /* * Set the "/HAL=" and "/KERNEL=" options if needed. @@ -1277,7 +1298,12 @@ LoadAndBootWindows( } } - TRACE("BootOptions: '%s'\n", BootOptions); + /* Append boot-time options */ + AppendBootTimeOptions(BootOptions); + + /* Post-process the boot options */ + NtLdrNormalizeOptions(BootOptions); + TRACE("BootOptions(2): '%s'\n", BootOptions); /* Check if a RAM disk file was given */ FileName = NtLdrGetOptionEx(BootOptions, "RDPATH=", &FileNameLength); diff --git a/boot/freeldr/freeldr/ntldr/winldr.h b/boot/freeldr/freeldr/ntldr/winldr.h index 0d8ba5fc264..29c6a55d0e4 100644 --- a/boot/freeldr/freeldr/ntldr/winldr.h +++ b/boot/freeldr/freeldr/ntldr/winldr.h @@ -84,6 +84,10 @@ NtLdrOutputLoadMsg( _In_ PCSTR FileName, _In_opt_ PCSTR Description); +VOID +NtLdrNormalizeOptions( + _Inout_ PSTR LoadOptions); + PVOID WinLdrLoadModule(PCSTR ModuleName, PULONG Size, TYPE_OF_MEMORY MemoryType);