From b34d516e814b841de4c54d85c31c1ce9b8d1829c Mon Sep 17 00:00:00 2001 From: Yaroslav Kibysh Date: Sun, 28 Jul 2019 20:23:41 +0300 Subject: [PATCH] [FREELDR] Add "Edit Boot Command Line" feature. (#1763) CORE-9023 CORE-16260 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Hermès Bélusca-Maïto --- boot/freeldr/freeldr/bootmgr.c | 77 +++++++++-- boot/freeldr/freeldr/custom.c | 182 +++++++++++++++++++------ boot/freeldr/freeldr/include/custom.h | 24 ++-- boot/freeldr/freeldr/include/freeldr.h | 3 + boot/freeldr/freeldr/include/options.h | 6 +- boot/freeldr/freeldr/options.c | 14 +- 6 files changed, 233 insertions(+), 73 deletions(-) diff --git a/boot/freeldr/freeldr/bootmgr.c b/boot/freeldr/freeldr/bootmgr.c index 756f74e69dd..d0ce314bb46 100644 --- a/boot/freeldr/freeldr/bootmgr.c +++ b/boot/freeldr/freeldr/bootmgr.c @@ -26,25 +26,30 @@ DBG_DEFAULT_CHANNEL(INIFILE); /* GLOBALS ********************************************************************/ +typedef +VOID +(*EDIT_OS_ENTRY_PROC)( + IN ULONG_PTR SectionId OPTIONAL); + static const struct { PCSTR BootType; + EDIT_OS_ENTRY_PROC EditOsEntry; ARC_ENTRY_POINT OsLoader; } OSLoadingMethods[] = { - {"ReactOSSetup", LoadReactOSSetup }, + {"ReactOSSetup", EditCustomBootReactOS, LoadReactOSSetup}, #ifdef _M_IX86 - {"BootSector" , LoadAndBootBootSector}, - {"Drive" , LoadAndBootDrive }, - {"Partition" , LoadAndBootPartition }, + {"Drive" , EditCustomBootDisk , LoadAndBootDrive }, + {"Partition" , EditCustomBootPartition , LoadAndBootPartition }, + {"BootSector" , EditCustomBootSectorFile, LoadAndBootBootSector}, - {"Linux" , LoadAndBootLinux }, - - {"Windows" , LoadAndBootWindows }, - {"WindowsNT40" , LoadAndBootWindows }, + {"Linux" , EditCustomBootLinux , LoadAndBootLinux }, + {"WindowsNT40" , EditCustomBootReactOS, LoadAndBootWindows}, #endif - {"Windows2003" , LoadAndBootWindows }, + {"Windows" , EditCustomBootReactOS, LoadAndBootWindows}, + {"Windows2003" , EditCustomBootReactOS, LoadAndBootWindows}, }; /* FUNCTIONS ******************************************************************/ @@ -185,6 +190,42 @@ VOID LoadOperatingSystem(IN OperatingSystemItem* OperatingSystem) } } +#ifdef HAS_OPTION_MENU_EDIT_CMDLINE + +VOID EditOperatingSystemEntry(IN OperatingSystemItem* OperatingSystem) +{ + ULONG_PTR SectionId; + PCSTR SectionName = OperatingSystem->SectionName; + ULONG i; + CHAR BootType[80]; + + /* Try to open the operating system section in the .ini file */ + if (!IniOpenSection(SectionName, &SectionId)) + { + UiMessageBox("Section [%s] not found in freeldr.ini.", SectionName); + return; + } + + /* Try to read the boot type */ + *BootType = ANSI_NULL; + IniReadSettingByName(SectionId, "BootType", BootType, sizeof(BootType)); + + /* We must have the "BootType" value (it has been possibly added by InitOperatingSystemList()) */ + ASSERT(*BootType); + + /* Loop through the OS loading method table and find a suitable OS entry editor */ + for (i = 0; i < sizeof(OSLoadingMethods) / sizeof(OSLoadingMethods[0]); ++i) + { + if (_stricmp(BootType, OSLoadingMethods[i].BootType) == 0) + { + OSLoadingMethods[i].EditOsEntry(SectionId); + return; + } + } +} + +#endif // HAS_OPTION_MENU_EDIT_CMDLINE + LONG GetTimeOut(VOID) { CHAR TimeOutText[20]; @@ -212,14 +253,22 @@ MainBootMenuKeyPressFilter( IN ULONG SelectedMenuItem, IN PVOID Context OPTIONAL) { - if (KeyPress == KEY_F8) + switch (KeyPress) { - DoOptionsMenu(); + case KEY_F8: + DoOptionsMenu(&((OperatingSystemItem*)Context)[SelectedMenuItem]); return TRUE; - } - /* We didn't handle the key */ - return FALSE; +#ifdef HAS_OPTION_MENU_EDIT_CMDLINE + case KEY_F10: + EditOperatingSystemEntry(&((OperatingSystemItem*)Context)[SelectedMenuItem]); + return TRUE; +#endif + + default: + /* We didn't handle the key */ + return FALSE; + } } VOID RunLoader(VOID) diff --git a/boot/freeldr/freeldr/custom.c b/boot/freeldr/freeldr/custom.c index 0ef5f5af160..319cbcd61a7 100644 --- a/boot/freeldr/freeldr/custom.c +++ b/boot/freeldr/freeldr/custom.c @@ -40,6 +40,8 @@ const CHAR CustomBootPrompt[] = "Press ENTER to boot your custom boot setup."; /* FUNCTIONS ******************************************************************/ +#ifdef HAS_OPTION_MENU_CUSTOM_BOOT + VOID OptionMenuCustomBoot(VOID) { PCSTR CustomBootMenuList[] = { @@ -70,42 +72,56 @@ VOID OptionMenuCustomBoot(VOID) { #ifdef _M_IX86 case 0: // Disk - OptionMenuCustomBootDisk(); + EditCustomBootDisk(0); break; case 1: // Partition - OptionMenuCustomBootPartition(); + EditCustomBootPartition(0); break; case 2: // Boot Sector File - OptionMenuCustomBootBootSectorFile(); + EditCustomBootSectorFile(0); break; case 3: // Linux - OptionMenuCustomBootLinux(); + EditCustomBootLinux(0); break; case 4: // ReactOS #else case 0: #endif - OptionMenuCustomBootReactOS(); + EditCustomBootReactOS(0); break; } } +#endif // HAS_OPTION_MENU_CUSTOM_BOOT + #ifdef _M_IX86 -VOID OptionMenuCustomBootDisk(VOID) +VOID EditCustomBootDisk(IN ULONG_PTR SectionId OPTIONAL) { - ULONG_PTR SectionId; - CHAR SectionName[100]; - CHAR BootDriveString[20]; TIMEINFO* TimeInfo; OperatingSystemItem OperatingSystem; + CHAR SectionName[100]; + CHAR BootDriveString[20]; RtlZeroMemory(SectionName, sizeof(SectionName)); RtlZeroMemory(BootDriveString, sizeof(BootDriveString)); - if (!UiEditBox(BootDrivePrompt, BootDriveString, 20)) + if (SectionId != 0) + { + /* Load the settings */ + IniReadSettingByName(SectionId, "BootDrive", BootDriveString, sizeof(BootDriveString)); + } + + if (!UiEditBox(BootDrivePrompt, BootDriveString, sizeof(BootDriveString))) return; + /* Modify the settings values and return if we were in edit mode */ + if (SectionId != 0) + { + IniModifySettingValue(SectionId, "BootDrive", BootDriveString); + return; + } + /* Generate a unique section name */ TimeInfo = ArcGetTime(); RtlStringCbPrintfA(SectionName, sizeof(SectionName), @@ -132,25 +148,39 @@ VOID OptionMenuCustomBootDisk(VOID) LoadOperatingSystem(&OperatingSystem); } -VOID OptionMenuCustomBootPartition(VOID) +VOID EditCustomBootPartition(IN ULONG_PTR SectionId OPTIONAL) { - ULONG_PTR SectionId; + TIMEINFO* TimeInfo; + OperatingSystemItem OperatingSystem; CHAR SectionName[100]; CHAR BootDriveString[20]; CHAR BootPartitionString[20]; - TIMEINFO* TimeInfo; - OperatingSystemItem OperatingSystem; RtlZeroMemory(SectionName, sizeof(SectionName)); RtlZeroMemory(BootDriveString, sizeof(BootDriveString)); RtlZeroMemory(BootPartitionString, sizeof(BootPartitionString)); - if (!UiEditBox(BootDrivePrompt, BootDriveString, 20)) + if (SectionId != 0) + { + /* Load the settings */ + IniReadSettingByName(SectionId, "BootDrive", BootDriveString, sizeof(BootDriveString)); + IniReadSettingByName(SectionId, "BootPartition", BootPartitionString, sizeof(BootPartitionString)); + } + + if (!UiEditBox(BootDrivePrompt, BootDriveString, sizeof(BootDriveString))) return; - if (!UiEditBox(BootPartitionPrompt, BootPartitionString, 20)) + if (!UiEditBox(BootPartitionPrompt, BootPartitionString, sizeof(BootPartitionString))) return; + /* Modify the settings values and return if we were in edit mode */ + if (SectionId != 0) + { + IniModifySettingValue(SectionId, "BootDrive", BootDriveString); + IniModifySettingValue(SectionId, "BootPartition", BootPartitionString); + return; + } + /* Generate a unique section name */ TimeInfo = ArcGetTime(); RtlStringCbPrintfA(SectionName, sizeof(SectionName), @@ -181,30 +211,46 @@ VOID OptionMenuCustomBootPartition(VOID) LoadOperatingSystem(&OperatingSystem); } -VOID OptionMenuCustomBootBootSectorFile(VOID) +VOID EditCustomBootSectorFile(IN ULONG_PTR SectionId OPTIONAL) { - ULONG_PTR SectionId; + TIMEINFO* TimeInfo; + OperatingSystemItem OperatingSystem; CHAR SectionName[100]; CHAR BootDriveString[20]; CHAR BootPartitionString[20]; CHAR BootSectorFileString[200]; - TIMEINFO* TimeInfo; - OperatingSystemItem OperatingSystem; RtlZeroMemory(SectionName, sizeof(SectionName)); RtlZeroMemory(BootDriveString, sizeof(BootDriveString)); RtlZeroMemory(BootPartitionString, sizeof(BootPartitionString)); RtlZeroMemory(BootSectorFileString, sizeof(BootSectorFileString)); - if (!UiEditBox(BootDrivePrompt, BootDriveString, 20)) + if (SectionId != 0) + { + /* Load the settings */ + IniReadSettingByName(SectionId, "BootDrive", BootDriveString, sizeof(BootDriveString)); + IniReadSettingByName(SectionId, "BootPartition", BootPartitionString, sizeof(BootPartitionString)); + IniReadSettingByName(SectionId, "BootSectorFile", BootSectorFileString, sizeof(BootSectorFileString)); + } + + if (!UiEditBox(BootDrivePrompt, BootDriveString, sizeof(BootDriveString))) return; - if (!UiEditBox(BootPartitionPrompt, BootPartitionString, 20)) + if (!UiEditBox(BootPartitionPrompt, BootPartitionString, sizeof(BootPartitionString))) return; - if (!UiEditBox(BootSectorFilePrompt, BootSectorFileString, 200)) + if (!UiEditBox(BootSectorFilePrompt, BootSectorFileString, sizeof(BootSectorFileString))) return; + /* Modify the settings values and return if we were in edit mode */ + if (SectionId != 0) + { + IniModifySettingValue(SectionId, "BootDrive", BootDriveString); + IniModifySettingValue(SectionId, "BootPartition", BootPartitionString); + IniModifySettingValue(SectionId, "BootSectorFile", BootSectorFileString); + return; + } + /* Generate a unique section name */ TimeInfo = ArcGetTime(); RtlStringCbPrintfA(SectionName, sizeof(SectionName), @@ -239,17 +285,16 @@ VOID OptionMenuCustomBootBootSectorFile(VOID) LoadOperatingSystem(&OperatingSystem); } -VOID OptionMenuCustomBootLinux(VOID) +VOID EditCustomBootLinux(IN ULONG_PTR SectionId OPTIONAL) { - ULONG_PTR SectionId; + TIMEINFO* TimeInfo; + OperatingSystemItem OperatingSystem; CHAR SectionName[100]; CHAR BootDriveString[20]; CHAR BootPartitionString[20]; CHAR LinuxKernelString[200]; CHAR LinuxInitrdString[200]; CHAR LinuxCommandLineString[200]; - TIMEINFO* TimeInfo; - OperatingSystemItem OperatingSystem; RtlZeroMemory(SectionName, sizeof(SectionName)); RtlZeroMemory(BootDriveString, sizeof(BootDriveString)); @@ -258,21 +303,42 @@ VOID OptionMenuCustomBootLinux(VOID) RtlZeroMemory(LinuxInitrdString, sizeof(LinuxInitrdString)); RtlZeroMemory(LinuxCommandLineString, sizeof(LinuxCommandLineString)); - if (!UiEditBox(BootDrivePrompt, BootDriveString, 20)) + if (SectionId != 0) + { + /* Load the settings */ + IniReadSettingByName(SectionId, "BootDrive", BootDriveString, sizeof(BootDriveString)); + IniReadSettingByName(SectionId, "BootPartition", BootPartitionString, sizeof(BootPartitionString)); + IniReadSettingByName(SectionId, "Kernel", LinuxKernelString, sizeof(LinuxKernelString)); + IniReadSettingByName(SectionId, "Initrd", LinuxInitrdString, sizeof(LinuxInitrdString)); + IniReadSettingByName(SectionId, "CommandLine", LinuxCommandLineString, sizeof(LinuxCommandLineString)); + } + + if (!UiEditBox(BootDrivePrompt, BootDriveString, sizeof(BootDriveString))) return; - if (!UiEditBox(BootPartitionPrompt, BootPartitionString, 20)) + if (!UiEditBox(BootPartitionPrompt, BootPartitionString, sizeof(BootPartitionString))) return; - if (!UiEditBox(LinuxKernelPrompt, LinuxKernelString, 200)) + if (!UiEditBox(LinuxKernelPrompt, LinuxKernelString, sizeof(LinuxKernelString))) return; - if (!UiEditBox(LinuxInitrdPrompt, LinuxInitrdString, 200)) + if (!UiEditBox(LinuxInitrdPrompt, LinuxInitrdString, sizeof(LinuxInitrdString))) return; - if (!UiEditBox(LinuxCommandLinePrompt, LinuxCommandLineString, 200)) + if (!UiEditBox(LinuxCommandLinePrompt, LinuxCommandLineString, sizeof(LinuxCommandLineString))) return; + /* Modify the settings values and return if we were in edit mode */ + if (SectionId != 0) + { + IniModifySettingValue(SectionId, "BootDrive", BootDriveString); + IniModifySettingValue(SectionId, "BootPartition", BootPartitionString); + IniModifySettingValue(SectionId, "Kernel", LinuxKernelString); + IniModifySettingValue(SectionId, "Initrd", LinuxInitrdString); + IniModifySettingValue(SectionId, "CommandLine", LinuxCommandLineString); + return; + } + /* Generate a unique section name */ TimeInfo = ArcGetTime(); RtlStringCbPrintfA(SectionName, sizeof(SectionName), @@ -320,35 +386,59 @@ VOID OptionMenuCustomBootLinux(VOID) #endif // _M_IX86 -VOID OptionMenuCustomBootReactOS(VOID) +VOID EditCustomBootReactOS(IN ULONG_PTR SectionId OPTIONAL) { - ULONG_PTR SectionId; + TIMEINFO* TimeInfo; + OperatingSystemItem OperatingSystem; CHAR SectionName[100]; CHAR BootDriveString[20]; CHAR BootPartitionString[20]; CHAR ReactOSSystemPath[200]; CHAR ReactOSARCPath[200]; CHAR ReactOSOptions[200]; - TIMEINFO* TimeInfo; - OperatingSystemItem OperatingSystem; RtlZeroMemory(SectionName, sizeof(SectionName)); RtlZeroMemory(BootDriveString, sizeof(BootDriveString)); RtlZeroMemory(BootPartitionString, sizeof(BootPartitionString)); RtlZeroMemory(ReactOSSystemPath, sizeof(ReactOSSystemPath)); + RtlZeroMemory(ReactOSARCPath, sizeof(ReactOSARCPath)); RtlZeroMemory(ReactOSOptions, sizeof(ReactOSOptions)); - if (!UiEditBox(BootDrivePrompt, BootDriveString, 20)) + if (SectionId != 0) + { + /* Load the settings */ + // TODO? Maybe use DissectArcPath(CHAR *ArcPath, CHAR *BootPath, UCHAR* BootDrive, ULONG* BootPartition) to get back to the small elements. + IniReadSettingByName(SectionId, "SystemPath", ReactOSARCPath, sizeof(ReactOSARCPath)); + IniReadSettingByName(SectionId, "Options", ReactOSOptions, sizeof(ReactOSOptions)); + } + + if (SectionId == 0) + { + if (!UiEditBox(BootDrivePrompt, BootDriveString, sizeof(BootDriveString))) + return; + + if (!UiEditBox(BootPartitionPrompt, BootPartitionString, sizeof(BootPartitionString))) + return; + + if (!UiEditBox(ReactOSSystemPathPrompt, ReactOSSystemPath, sizeof(ReactOSSystemPath))) + return; + } + else + { + if (!UiEditBox(ReactOSSystemPathPrompt, ReactOSARCPath, sizeof(ReactOSARCPath))) + return; + } + + if (!UiEditBox(ReactOSOptionsPrompt, ReactOSOptions, sizeof(ReactOSOptions))) return; - if (!UiEditBox(BootPartitionPrompt, BootPartitionString, 20)) - return; - - if (!UiEditBox(ReactOSSystemPathPrompt, ReactOSSystemPath, 200)) - return; - - if (!UiEditBox(ReactOSOptionsPrompt, ReactOSOptions, 200)) + /* Modify the settings values and return if we were in edit mode */ + if (SectionId != 0) + { + IniModifySettingValue(SectionId, "SystemPath", ReactOSARCPath); + IniModifySettingValue(SectionId, "Options", ReactOSOptions); return; + } /* Generate a unique section name */ TimeInfo = ArcGetTime(); @@ -383,6 +473,8 @@ VOID OptionMenuCustomBootReactOS(VOID) LoadOperatingSystem(&OperatingSystem); } +#ifdef HAS_OPTION_MENU_REBOOT + VOID OptionMenuReboot(VOID) { UiMessageBox("The system will now reboot."); @@ -392,3 +484,5 @@ VOID OptionMenuReboot(VOID) #endif Reboot(); } + +#endif // HAS_OPTION_MENU_REBOOT diff --git a/boot/freeldr/freeldr/include/custom.h b/boot/freeldr/freeldr/include/custom.h index c139d532004..0bf8d680f32 100644 --- a/boot/freeldr/freeldr/include/custom.h +++ b/boot/freeldr/freeldr/include/custom.h @@ -19,19 +19,25 @@ #pragma once -#ifdef _M_IX86 - +#define HAS_OPTION_MENU_EDIT_CMDLINE #define HAS_OPTION_MENU_CUSTOM_BOOT #define HAS_OPTION_MENU_REBOOT -VOID OptionMenuReboot(VOID); +#ifdef _M_IX86 -VOID OptionMenuCustomBoot(VOID); -VOID OptionMenuCustomBootDisk(VOID); -VOID OptionMenuCustomBootPartition(VOID); -VOID OptionMenuCustomBootBootSectorFile(VOID); -VOID OptionMenuCustomBootLinux(VOID); +VOID EditCustomBootDisk(IN ULONG_PTR SectionId OPTIONAL); +VOID EditCustomBootPartition(IN ULONG_PTR SectionId OPTIONAL); +VOID EditCustomBootSectorFile(IN ULONG_PTR SectionId OPTIONAL); +VOID EditCustomBootLinux(IN ULONG_PTR SectionId OPTIONAL); #endif // _M_IX86 -VOID OptionMenuCustomBootReactOS(VOID); +#ifdef HAS_OPTION_MENU_CUSTOM_BOOT +VOID OptionMenuCustomBoot(VOID); +#endif + +VOID EditCustomBootReactOS(IN ULONG_PTR SectionId OPTIONAL); + +#ifdef HAS_OPTION_MENU_REBOOT +VOID OptionMenuReboot(VOID); +#endif diff --git a/boot/freeldr/freeldr/include/freeldr.h b/boot/freeldr/freeldr/include/freeldr.h index d981dc2649a..0ef42e40595 100644 --- a/boot/freeldr/freeldr/include/freeldr.h +++ b/boot/freeldr/freeldr/include/freeldr.h @@ -126,6 +126,9 @@ VOID __cdecl BootMain(IN PCCH CmdLine); VOID LoadOperatingSystem(IN OperatingSystemItem* OperatingSystem); +#ifdef HAS_OPTION_MENU_EDIT_CMDLINE +VOID EditOperatingSystemEntry(IN OperatingSystemItem* OperatingSystem); +#endif VOID RunLoader(VOID); VOID FrLdrCheckCpuCompatibility(VOID); diff --git a/boot/freeldr/freeldr/include/options.h b/boot/freeldr/freeldr/include/options.h index 5ff2a45f999..f7427798366 100644 --- a/boot/freeldr/freeldr/include/options.h +++ b/boot/freeldr/freeldr/include/options.h @@ -19,6 +19,6 @@ #pragma once -VOID DoOptionsMenu(VOID); -VOID DisplayBootTimeOptions(VOID); -VOID AppendBootTimeOptions(PCHAR BootOptions); +VOID DoOptionsMenu(IN OperatingSystemItem* OperatingSystem); +VOID DisplayBootTimeOptions(VOID); +VOID AppendBootTimeOptions(PCHAR BootOptions); diff --git a/boot/freeldr/freeldr/options.c b/boot/freeldr/freeldr/options.c index 701f8693893..ac302254bf5 100644 --- a/boot/freeldr/freeldr/options.c +++ b/boot/freeldr/freeldr/options.c @@ -42,6 +42,9 @@ PCSTR OptionsMenuList[] = NULL, "Start ReactOS normally", +#ifdef HAS_OPTION_MENU_EDIT_CMDLINE + "Edit Boot Command Line (F10)", +#endif #ifdef HAS_OPTION_MENU_CUSTOM_BOOT "Custom Boot", #endif @@ -86,7 +89,7 @@ static BOOLEAN DebuggingMode = FALSE; /* FUNCTIONS ******************************************************************/ -VOID DoOptionsMenu(VOID) +VOID DoOptionsMenu(IN OperatingSystemItem* OperatingSystem) { ULONG SelectedMenuItem; CHAR DebugChannelString[100]; @@ -157,13 +160,18 @@ VOID DoOptionsMenu(VOID) VgaMode = FALSE; DebuggingMode = FALSE; break; +#ifdef HAS_OPTION_MENU_EDIT_CMDLINE + case 12: // Edit command line + EditOperatingSystemEntry(OperatingSystem); + break; +#endif #ifdef HAS_OPTION_MENU_CUSTOM_BOOT - case 12: // Custom Boot + case 13: // Custom Boot OptionMenuCustomBoot(); break; #endif #ifdef HAS_OPTION_MENU_REBOOT - case 13: // Reboot + case 14: // Reboot OptionMenuReboot(); break; #endif