[FREELDR] Add "Edit Boot Command Line" feature. (#1763)
authorYaroslav Kibysh <yanet.prod@gmail.com>
Sun, 28 Jul 2019 17:23:41 +0000 (20:23 +0300)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Wed, 7 Aug 2019 16:50:23 +0000 (18:50 +0200)
CORE-9023 CORE-16260

Co-authored-by: Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
boot/freeldr/freeldr/bootmgr.c
boot/freeldr/freeldr/custom.c
boot/freeldr/freeldr/include/custom.h
boot/freeldr/freeldr/include/freeldr.h
boot/freeldr/freeldr/include/options.h
boot/freeldr/freeldr/options.c

index 756f74e..d0ce314 100644 (file)
@@ -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 },
-
-    {"Linux"       , LoadAndBootLinux     },
+    {"Drive"       , EditCustomBootDisk      , LoadAndBootDrive     },
+    {"Partition"   , EditCustomBootPartition , LoadAndBootPartition },
+    {"BootSector"  , EditCustomBootSectorFile, LoadAndBootBootSector},
 
-    {"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)
index 0ef5f5a..319cbcd 100644 (file)
@@ -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,29 +211,45 @@ 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, sizeof(BootPartitionString)))
         return;
 
-    if (!UiEditBox(BootPartitionPrompt, BootPartitionString, 20))
+    if (!UiEditBox(BootSectorFilePrompt, BootSectorFileString, sizeof(BootSectorFileString)))
         return;
 
-    if (!UiEditBox(BootSectorFilePrompt, BootSectorFileString, 200))
+    /* 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();
@@ -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))
-        return;
+    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 (!UiEditBox(BootPartitionPrompt, BootPartitionString, 20))
-        return;
+    if (SectionId == 0)
+    {
+        if (!UiEditBox(BootDrivePrompt, BootDriveString, sizeof(BootDriveString)))
+            return;
 
-    if (!UiEditBox(ReactOSSystemPathPrompt, ReactOSSystemPath, 200))
+        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(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
index c139d53..0bf8d68 100644 (file)
 
 #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
index d981dc2..0ef42e4 100644 (file)
 
 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);
 
index 5ff2a45..f742779 100644 (file)
@@ -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);
index 701f869..ac30225 100644 (file)
@@ -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