[FREELDR] Some ARC-spec compatibility refactoring + simplifications & fixes.
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Tue, 6 Aug 2019 20:30:54 +0000 (22:30 +0200)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Tue, 6 Aug 2019 21:40:05 +0000 (23:40 +0200)
CORE-9023

- During loading and initialization of the list of operating systems
  available in freeldr.ini, convert any legacy operating system entry
  encountered -- they are like those in NTLDR's boot.ini file, i.e.:

    ArcOsLoadPartition="LoadIdentifier" /List /of /Options

  into a new operating system INI entry, like those used by default in
  FreeLoader. This allows us to avoid treating this corner-case later in
  different parts of the code. Also, the "BootType" value is now
  determined there, only once.

- Convert the OS loaders entry-points to ARC-compatible ones, following
  the "Advanced RISC Computing Specification, Version 1.2" specification
  https://www.netbsd.org/docs/Hardware/Machines/ARC/riscspec.pdf

- Introduce helpers for retrieving options values from the argument vector
  in a simple way.

- Simplify LoadOperatingSystem(), since now the "BootType" value has
  been determined once while loading the list of OSes (see above) and
  is well-defined there. Use the BuildArgvForOsLoader() helper to build
  the ARC-compatible argument vector from the corresponding INI settings
  for the selected operating system entry, and use it when calling the
  corresponding OS loader.

- In the OS loaders, since we can now directly read the settings from
  the argument vector (instead of using INI settings), we can avoid
  using a bunch of fixed-size string buffers, and avoid potentially
  failing IniOpenSection() calls as well.

- Simplify code in the Linux loader (and the RemoveQuotes() function).

- Add UiShowMessageBoxesInArgv() that acts on the "MessageBox=" settings
  passed through the argument vector (equivalent to
  UiShowMessageBoxesInSection() ).

- Use string-safe functions where needed (copy/concatenation/printf on
  fixed-size buffers).

19 files changed:
boot/freeldr/freeldr/CMakeLists.txt
boot/freeldr/freeldr/bootmgr.c
boot/freeldr/freeldr/custom.c
boot/freeldr/freeldr/include/arcsupp.h [new file with mode: 0644]
boot/freeldr/freeldr/include/freeldr.h
boot/freeldr/freeldr/include/linux.h
boot/freeldr/freeldr/include/miscboot.h
boot/freeldr/freeldr/include/oslist.h
boot/freeldr/freeldr/include/ui.h
boot/freeldr/freeldr/include/winldr.h
boot/freeldr/freeldr/lib/arcsupp.c [new file with mode: 0644]
boot/freeldr/freeldr/linuxboot.c
boot/freeldr/freeldr/miscboot.c
boot/freeldr/freeldr/ntldr/setupldr.c
boot/freeldr/freeldr/ntldr/winldr.c
boot/freeldr/freeldr/ntldr/winldr.h
boot/freeldr/freeldr/oslist.c
boot/freeldr/freeldr/ui/directui.c
boot/freeldr/freeldr/ui/ui.c

index 4ffa44a..d426305 100644 (file)
@@ -37,6 +37,7 @@ include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/elf)
 add_definitions(-D_NTHAL_ -D_BLDR_ -D_NTSYSTEM_)
 
 list(APPEND FREELDR_BOOTLIB_SOURCE
+    lib/arcsupp.c
     lib/debug.c
     lib/peloader.c
     lib/comm/rs232.c
index 5df8182..cdd3705 100644 (file)
 #include <freeldr.h>
 #include <debug.h>
 
-/* GLOBALS ********************************************************************/
+DBG_DEFAULT_CHANNEL(INIFILE);
 
-typedef
-VOID
-(*OS_LOADING_METHOD)(IN OperatingSystemItem* OperatingSystem,
-                     IN USHORT OperatingSystemVersion);
+/* GLOBALS ********************************************************************/
 
 static const struct
 {
-    PCHAR BootType;
-    USHORT OperatingSystemVersion;
-    OS_LOADING_METHOD Load;
+    PCSTR BootType;
+    ARC_ENTRY_POINT OsLoader;
 } OSLoadingMethods[] =
 {
-    {"ReactOSSetup", 0                , LoadReactOSSetup     },
+    {"ReactOSSetup", LoadReactOSSetup     },
 
 #ifdef _M_IX86
-    {"BootSector"  , 0                , LoadAndBootBootSector},
-    {"Drive"       , 0                , LoadAndBootDrive     },
-    {"Partition"   , 0                , LoadAndBootPartition },
+    {"BootSector"  , LoadAndBootBootSector},
+    {"Drive"       , LoadAndBootDrive     },
+    {"Partition"   , LoadAndBootPartition },
 
-    {"Linux"       , 0                , LoadAndBootLinux     },
+    {"Linux"       , LoadAndBootLinux     },
 
-    {"Windows"     , 0                , LoadAndBootWindows   },
-    {"WindowsNT40" , _WIN32_WINNT_NT4 , LoadAndBootWindows   },
+    {"Windows"     , LoadAndBootWindows   },
+    {"WindowsNT40" , LoadAndBootWindows   },
 #endif
-    {"Windows2003" , _WIN32_WINNT_WS03, LoadAndBootWindows   },
+    {"Windows2003" , LoadAndBootWindows   },
 };
 
 /* FUNCTIONS ******************************************************************/
 
-VOID LoadOperatingSystem(IN OperatingSystemItem* OperatingSystem)
+PCHAR*
+BuildArgvForOsLoader(
+    IN PCSTR LoadIdentifier,
+    IN ULONG_PTR SectionId,
+    OUT PULONG pArgc)
 {
-    ULONG_PTR SectionId;
-    PCSTR SectionName = OperatingSystem->SystemPartition;
-    CHAR BootType[80];
+    SIZE_T Size;
+    ULONG Count;
     ULONG i;
-
-    /* Try to open the operating system section in the .ini file */
-    if (IniOpenSection(SectionName, &SectionId))
+    ULONG Argc;
+    PCHAR* Argv;
+    PCHAR* Args;
+    PCHAR SettingName, SettingValue;
+
+    /*
+     * Convert the list of key=value options in the given operating system section
+     * into a ARC-compatible argument vector.
+     */
+
+    *pArgc = 0;
+
+    /* Validate the LoadIdentifier (to make tests simpler later) */
+    if (LoadIdentifier && !*LoadIdentifier)
+        LoadIdentifier = NULL;
+
+    /* Count the number of operating systems in the section */
+    Count = IniGetNumSectionItems(SectionId);
+
+    /* The argument vector contains the program name, the LoadIdentifier (optional), and the items in the OS section */
+    Argc = 1 + Count;
+    if (LoadIdentifier)
+        ++Argc;
+
+    /* Calculate the total size needed for the string buffer of the argument vector */
+    Size = 0;
+    /* i == 0: Program name */
+    /* i == 1: LoadIdentifier */
+    if (LoadIdentifier)
     {
-        /* Try to read the boot type */
-        IniReadSettingByName(SectionId, "BootType", BootType, sizeof(BootType));
+        Size += (strlen("LoadIdentifier=") + strlen(LoadIdentifier) + 1) * sizeof(CHAR);
     }
-    else
+    for (i = 0; i < Count; ++i)
     {
-        BootType[0] = ANSI_NULL;
+        Size += IniGetSectionSettingNameSize(SectionId, i);  // Counts also the NULL-terminator, that we transform into the '=' sign separator.
+        Size += IniGetSectionSettingValueSize(SectionId, i); // Counts also the NULL-terminator.
     }
+    Size += sizeof(ANSI_NULL); // Final NULL-terminator.
+
+    /* Allocate memory to hold the argument vector: pointers and string buffer */
+    Argv = FrLdrHeapAlloc(Argc * sizeof(PCHAR) + Size, TAG_STRING);
+    if (!Argv)
+        return NULL;
+
+    /* Initialize the argument vector: loop through the section and copy the key=value options */
+    SettingName = (PCHAR)((ULONG_PTR)Argv + (Argc * sizeof(PCHAR)));
+    Args = Argv;
+    /* i == 0: Program name */
+    *Args++ = NULL;
+    /* i == 1: LoadIdentifier */
+    if (LoadIdentifier)
+    {
+        strcpy(SettingName, "LoadIdentifier=");
+        strcat(SettingName, LoadIdentifier);
 
-    if (BootType[0] == ANSI_NULL && SectionName[0] != ANSI_NULL)
+        *Args++ = SettingName;
+        SettingName += (strlen(SettingName) + 1);
+    }
+    for (i = 0; i < Count; ++i)
     {
-        /* Try to infer the boot type value */
-#ifdef _M_IX86
-        ULONG FileId;
-        if (ArcOpen((PSTR)SectionName, OpenReadOnly, &FileId) == ESUCCESS)
-        {
-            ArcClose(FileId);
-            strcpy(BootType, "BootSector");
-        }
-        else
-#endif
-        {
-            strcpy(BootType, "Windows");
-        }
+        Size = IniGetSectionSettingNameSize(SectionId, i);
+        SettingValue = SettingName + Size;
+        IniReadSettingByNumber(SectionId, i,
+                               SettingName, Size,
+                               SettingValue, IniGetSectionSettingValueSize(SectionId, i));
+        SettingName[Size - 1] = '=';
+
+        *Args++ = SettingName;
+        SettingName += (strlen(SettingName) + 1);
     }
 
-#if defined(_M_IX86)
-    /* Install the drive mapper according to this section drive mappings */
-    DriveMapMapDrivesInSection(SectionName);
-#endif
-
-    /* Loop through the OS loading method table and find a suitable OS to boot */
-    for (i = 0; i < sizeof(OSLoadingMethods) / sizeof(OSLoadingMethods[0]); ++i)
+#if DBG
+    /* Dump the argument vector for debugging */
+    for (i = 0; i < Argc; ++i)
     {
-        if (_stricmp(BootType, OSLoadingMethods[i].BootType) == 0)
-        {
-            OSLoadingMethods[i].Load(OperatingSystem,
-                                     OSLoadingMethods[i].OperatingSystemVersion);
-            return;
-        }
+        TRACE("Argv[%lu]: '%s'\n", i, Argv[i]);
     }
+#endif
+
+    *pArgc = Argc;
+    return Argv;
 }
 
-ULONG GetDefaultOperatingSystem(OperatingSystemItem* OperatingSystemList, ULONG OperatingSystemCount)
+VOID LoadOperatingSystem(IN OperatingSystemItem* OperatingSystem)
 {
-    CHAR      DefaultOSText[80];
-    PCSTR     DefaultOSName;
     ULONG_PTR SectionId;
-    ULONG     DefaultOS = 0;
-    ULONG     Idx;
-
-    if (!IniOpenSection("FreeLoader", &SectionId))
-        return 0;
+    PCSTR SectionName = OperatingSystem->SectionName;
+    ULONG i;
+    ULONG Argc;
+    PCHAR* Argv;
+    CHAR BootType[80];
 
-    DefaultOSName = CmdLineGetDefaultOS();
-    if (DefaultOSName == NULL)
+    /* Try to open the operating system section in the .ini file */
+    if (!IniOpenSection(SectionName, &SectionId))
     {
-        if (IniReadSettingByName(SectionId, "DefaultOS", DefaultOSText, sizeof(DefaultOSText)))
-        {
-            DefaultOSName = DefaultOSText;
-        }
+        UiMessageBox("Section [%s] not found in freeldr.ini.", SectionName);
+        return;
     }
 
-    if (DefaultOSName != NULL)
+    /* 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);
+
+#if defined(_M_IX86)
+    /* Install the drive mapper according to this section drive mappings */
+    DriveMapMapDrivesInSection(SectionName);
+#endif
+
+    /* Loop through the OS loading method table and find a suitable OS to boot */
+    for (i = 0; i < sizeof(OSLoadingMethods) / sizeof(OSLoadingMethods[0]); ++i)
     {
-        for (Idx = 0; Idx < OperatingSystemCount; Idx++)
+        if (_stricmp(BootType, OSLoadingMethods[i].BootType) == 0)
         {
-            if (_stricmp(DefaultOSName, OperatingSystemList[Idx].SystemPartition) == 0)
+            Argv = BuildArgvForOsLoader(OperatingSystem->LoadIdentifier, SectionId, &Argc);
+            if (Argv)
             {
-                DefaultOS = Idx;
-                break;
+                OSLoadingMethods[i].OsLoader(Argc, Argv, NULL);
+                FrLdrHeapFree(Argv, TAG_STRING);
             }
+            return;
         }
     }
-
-    return DefaultOS;
 }
 
 LONG GetTimeOut(VOID)
@@ -176,11 +221,11 @@ BOOLEAN MainBootMenuKeyPressFilter(ULONG KeyPress)
 VOID RunLoader(VOID)
 {
     ULONG_PTR SectionId;
+    LONG      TimeOut;
     ULONG     OperatingSystemCount;
     OperatingSystemItem* OperatingSystemList;
     PCSTR*    OperatingSystemDisplayNames;
     ULONG     DefaultOperatingSystem;
-    LONG      TimeOut;
     ULONG     SelectedOperatingSystem;
     ULONG     i;
 
@@ -222,21 +267,19 @@ VOID RunLoader(VOID)
         return;
     }
 
-    OperatingSystemList = InitOperatingSystemList(&OperatingSystemCount);
+    OperatingSystemList = InitOperatingSystemList(&OperatingSystemCount,
+                                                  &DefaultOperatingSystem);
     if (!OperatingSystemList)
     {
         UiMessageBox("Unable to read operating systems section in freeldr.ini.\nPress ENTER to reboot.");
         goto Reboot;
     }
-
     if (OperatingSystemCount == 0)
     {
         UiMessageBox("There were no operating systems listed in freeldr.ini.\nPress ENTER to reboot.");
         goto Reboot;
     }
 
-    DefaultOperatingSystem = GetDefaultOperatingSystem(OperatingSystemList, OperatingSystemCount);
-
     /* Create list of display names */
     OperatingSystemDisplayNames = FrLdrTempAlloc(sizeof(PCSTR) * OperatingSystemCount, 'mNSO');
     if (!OperatingSystemDisplayNames)
index 02e55b6..25fee60 100644 (file)
@@ -108,7 +108,10 @@ VOID OptionMenuCustomBootDisk(VOID)
 
     /* Generate a unique section name */
     TimeInfo = ArcGetTime();
-    sprintf(SectionName, "CustomBootDisk%u%u%u%u%u%u", TimeInfo->Year, TimeInfo->Day, TimeInfo->Month, TimeInfo->Hour, TimeInfo->Minute, TimeInfo->Second);
+    RtlStringCbPrintfA(SectionName, sizeof(SectionName),
+                       "CustomBootDisk%u%u%u%u%u%u",
+                       TimeInfo->Year, TimeInfo->Day, TimeInfo->Month,
+                       TimeInfo->Hour, TimeInfo->Minute, TimeInfo->Second);
 
     /* Add the section */
     if (!IniAddSection(SectionName, &SectionId))
@@ -124,11 +127,8 @@ VOID OptionMenuCustomBootDisk(VOID)
 
     UiMessageBox(CustomBootPrompt);
 
-    OperatingSystem.SystemPartition = SectionName;
-    OperatingSystem.LoadIdentifier  = NULL;
-    OperatingSystem.OsLoadOptions   = NULL;
-
-    // LoadAndBootDrive(&OperatingSystem, 0);
+    OperatingSystem.SectionName = SectionName;
+    OperatingSystem.LoadIdentifier = NULL;
     LoadOperatingSystem(&OperatingSystem);
 }
 
@@ -153,7 +153,10 @@ VOID OptionMenuCustomBootPartition(VOID)
 
     /* Generate a unique section name */
     TimeInfo = ArcGetTime();
-    sprintf(SectionName, "CustomBootPartition%u%u%u%u%u%u", TimeInfo->Year, TimeInfo->Day, TimeInfo->Month, TimeInfo->Hour, TimeInfo->Minute, TimeInfo->Second);
+    RtlStringCbPrintfA(SectionName, sizeof(SectionName),
+                       "CustomBootPartition%u%u%u%u%u%u",
+                       TimeInfo->Year, TimeInfo->Day, TimeInfo->Month,
+                       TimeInfo->Hour, TimeInfo->Minute, TimeInfo->Second);
 
     /* Add the section */
     if (!IniAddSection(SectionName, &SectionId))
@@ -173,11 +176,8 @@ VOID OptionMenuCustomBootPartition(VOID)
 
     UiMessageBox(CustomBootPrompt);
 
-    OperatingSystem.SystemPartition = SectionName;
-    OperatingSystem.LoadIdentifier  = NULL;
-    OperatingSystem.OsLoadOptions   = NULL;
-
-    // LoadAndBootPartition(&OperatingSystem, 0);
+    OperatingSystem.SectionName = SectionName;
+    OperatingSystem.LoadIdentifier = NULL;
     LoadOperatingSystem(&OperatingSystem);
 }
 
@@ -207,7 +207,10 @@ VOID OptionMenuCustomBootBootSectorFile(VOID)
 
     /* Generate a unique section name */
     TimeInfo = ArcGetTime();
-    sprintf(SectionName, "CustomBootSectorFile%u%u%u%u%u%u", TimeInfo->Year, TimeInfo->Day, TimeInfo->Month, TimeInfo->Hour, TimeInfo->Minute, TimeInfo->Second);
+    RtlStringCbPrintfA(SectionName, sizeof(SectionName),
+                       "CustomBootSectorFile%u%u%u%u%u%u",
+                       TimeInfo->Year, TimeInfo->Day, TimeInfo->Month,
+                       TimeInfo->Hour, TimeInfo->Minute, TimeInfo->Second);
 
     /* Add the section */
     if (!IniAddSection(SectionName, &SectionId))
@@ -231,11 +234,8 @@ VOID OptionMenuCustomBootBootSectorFile(VOID)
 
     UiMessageBox(CustomBootPrompt);
 
-    OperatingSystem.SystemPartition = SectionName;
-    OperatingSystem.LoadIdentifier  = NULL;
-    OperatingSystem.OsLoadOptions   = NULL;
-
-    // LoadAndBootBootSector(&OperatingSystem, 0);
+    OperatingSystem.SectionName = SectionName;
+    OperatingSystem.LoadIdentifier = NULL;
     LoadOperatingSystem(&OperatingSystem);
 }
 
@@ -275,7 +275,10 @@ VOID OptionMenuCustomBootLinux(VOID)
 
     /* Generate a unique section name */
     TimeInfo = ArcGetTime();
-    sprintf(SectionName, "CustomLinux%u%u%u%u%u%u", TimeInfo->Year, TimeInfo->Day, TimeInfo->Month, TimeInfo->Hour, TimeInfo->Minute, TimeInfo->Second);
+    RtlStringCbPrintfA(SectionName, sizeof(SectionName),
+                       "CustomLinux%u%u%u%u%u%u",
+                       TimeInfo->Year, TimeInfo->Day, TimeInfo->Month,
+                       TimeInfo->Hour, TimeInfo->Minute, TimeInfo->Second);
 
     /* Add the section */
     if (!IniAddSection(SectionName, &SectionId))
@@ -298,7 +301,7 @@ VOID OptionMenuCustomBootLinux(VOID)
         return;
 
     /* Add the Initrd */
-    if (strlen(LinuxInitrdString) > 0)
+    if (*LinuxInitrdString)
     {
         if (!IniAddSettingValueToSection(SectionId, "Initrd", LinuxInitrdString))
             return;
@@ -310,11 +313,8 @@ VOID OptionMenuCustomBootLinux(VOID)
 
     UiMessageBox(CustomBootPrompt);
 
-    OperatingSystem.SystemPartition = SectionName;
-    OperatingSystem.LoadIdentifier  = "Custom Linux Setup";
-    OperatingSystem.OsLoadOptions   = NULL;
-
-    // LoadAndBootLinux(&OperatingSystem, 0);
+    OperatingSystem.SectionName = SectionName;
+    OperatingSystem.LoadIdentifier = "Custom Linux Setup";
     LoadOperatingSystem(&OperatingSystem);
 }
 
@@ -352,7 +352,10 @@ VOID OptionMenuCustomBootReactOS(VOID)
 
     /* Generate a unique section name */
     TimeInfo = ArcGetTime();
-    sprintf(SectionName, "CustomReactOS%u%u%u%u%u%u", TimeInfo->Year, TimeInfo->Day, TimeInfo->Month, TimeInfo->Hour, TimeInfo->Minute, TimeInfo->Second);
+    RtlStringCbPrintfA(SectionName, sizeof(SectionName),
+                       "CustomReactOS%u%u%u%u%u%u",
+                       TimeInfo->Year, TimeInfo->Day, TimeInfo->Month,
+                       TimeInfo->Hour, TimeInfo->Minute, TimeInfo->Second);
 
     /* Add the section */
     if (!IniAddSection(SectionName, &SectionId))
@@ -375,11 +378,8 @@ VOID OptionMenuCustomBootReactOS(VOID)
 
     UiMessageBox(CustomBootPrompt);
 
-    OperatingSystem.SystemPartition = SectionName;
-    OperatingSystem.LoadIdentifier  = NULL;
-    OperatingSystem.OsLoadOptions   = NULL; // ReactOSOptions
-
-    // LoadAndBootWindows(&OperatingSystem, _WIN32_WINNT_WS03);
+    OperatingSystem.SectionName = SectionName;
+    OperatingSystem.LoadIdentifier = NULL;
     LoadOperatingSystem(&OperatingSystem);
 }
 
diff --git a/boot/freeldr/freeldr/include/arcsupp.h b/boot/freeldr/freeldr/include/arcsupp.h
new file mode 100644 (file)
index 0000000..7208974
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * PROJECT:     FreeLoader
+ * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE:     Generic ARC Support Functions
+ * COPYRIGHT:   Copyright 2019 Hermes Belusca-Maito
+ */
+
+#pragma once
+
+typedef
+ARC_STATUS
+(__cdecl *ARC_ENTRY_POINT)(
+    IN ULONG Argc,
+    IN PCHAR Argv[],
+    IN PCHAR Envp[]);
+
+PCHAR
+GetNextArgumentValue(
+    IN ULONG Argc,
+    IN PCHAR Argv[],
+    IN OUT PULONG LastIndex OPTIONAL,
+    IN PCHAR ArgumentName);
+
+PCHAR
+GetArgumentValue(
+    IN ULONG Argc,
+    IN PCHAR Argv[],
+    IN PCHAR ArgumentName);
index 82a6b89..71d4788 100644 (file)
@@ -58,6 +58,7 @@
 /* Internal headers */
 // #include <arcemul.h>
 #include <arcname.h>
+#include <arcsupp.h>
 #include <bytesex.h>
 #include <cache.h>
 #include <cmdline.h>
index 78c16bc..3d5c789 100644 (file)
@@ -131,11 +131,17 @@ typedef struct
 VOID    __cdecl BootNewLinuxKernel(VOID);                // Implemented in linux.S
 VOID    __cdecl BootOldLinuxKernel(ULONG KernelSize);        // Implemented in linux.S
 
-VOID
-LoadAndBootLinux(IN OperatingSystemItem* OperatingSystem,
-                 IN USHORT OperatingSystemVersion);
+ARC_STATUS
+LoadAndBootLinux(
+    IN ULONG Argc,
+    IN PCHAR Argv[],
+    IN PCHAR Envp[]);
+
+BOOLEAN
+LinuxParseIniSection(
+    IN ULONG Argc,
+    IN PCHAR Argv[]);
 
-BOOLEAN    LinuxParseIniSection(PCSTR OperatingSystemName);
 BOOLEAN    LinuxReadBootSector(PFILE LinuxKernelFile);
 BOOLEAN    LinuxReadSetupSector(PFILE LinuxKernelFile);
 BOOLEAN    LinuxReadKernel(PFILE LinuxKernelFile);
index d763496..5e80ab0 100644 (file)
 
 #ifdef _M_IX86
 
-VOID
-LoadAndBootBootSector(IN OperatingSystemItem* OperatingSystem,
-                      IN USHORT OperatingSystemVersion);
-VOID
-LoadAndBootPartition(IN OperatingSystemItem* OperatingSystem,
-                     IN USHORT OperatingSystemVersion);
-VOID
-LoadAndBootDrive(IN OperatingSystemItem* OperatingSystem,
-                 IN USHORT OperatingSystemVersion);
+ARC_STATUS
+LoadAndBootBootSector(
+    IN ULONG Argc,
+    IN PCHAR Argv[],
+    IN PCHAR Envp[]);
+
+ARC_STATUS
+LoadAndBootPartition(
+    IN ULONG Argc,
+    IN PCHAR Argv[],
+    IN PCHAR Envp[]);
+
+ARC_STATUS
+LoadAndBootDrive(
+    IN ULONG Argc,
+    IN PCHAR Argv[],
+    IN PCHAR Envp[]);
 
 #endif // _M_IX86
index 934ee62..1676900 100644 (file)
 
 #pragma once
 
+#define TAG_STRING  ' rtS'
+
 typedef struct tagOperatingSystemItem
 {
-    PCSTR SystemPartition;
+    PCSTR SectionName;
     PCSTR LoadIdentifier;
-    PCSTR OsLoadOptions;
 } OperatingSystemItem;
 
-OperatingSystemItem* InitOperatingSystemList(ULONG* OperatingSystemCountPointer);
+OperatingSystemItem*
+InitOperatingSystemList(
+    OUT PULONG OperatingSystemCount,
+    OUT PULONG DefaultOperatingSystem);
index d531448..151c0af 100644 (file)
@@ -70,7 +70,14 @@ VOID    UiMessageBox(PCSTR Format, ...);                        // Displays a me
 VOID    UiMessageBoxCritical(PCSTR MessageText);                // Displays a message box on the screen with an ok button using no system resources
 VOID    UiDrawProgressBarCenter(ULONG Position, ULONG Range, PCHAR ProgressText);            // Draws the progress bar showing nPos percent filled
 VOID    UiDrawProgressBar(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, ULONG Position, ULONG Range, PCHAR ProgressText);            // Draws the progress bar showing nPos percent filled
+
 VOID    UiShowMessageBoxesInSection(PCSTR SectionName);        // Displays all the message boxes in a given section
+
+VOID
+UiShowMessageBoxesInArgv(
+    IN ULONG Argc,
+    IN PCHAR Argv[]);
+
 VOID    UiEscapeString(PCHAR String);                            // Processes a string and changes all occurrences of "\n" to '\n'
 BOOLEAN    UiEditBox(PCSTR MessageText, PCHAR EditTextBuffer, ULONG Length);
 
index 56af2ed..7bd4b58 100644 (file)
@@ -58,17 +58,23 @@ typedef struct _ARC_DISK_SIGNATURE_EX
     CHAR ArcName[MAX_PATH];
 } ARC_DISK_SIGNATURE_EX, *PARC_DISK_SIGNATURE_EX;
 
-///////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
 //
 // ReactOS Loading Functions
 //
-///////////////////////////////////////////////////////////////////////////////////////
-VOID LoadAndBootWindows(IN OperatingSystemItem* OperatingSystem,
-                        IN USHORT OperatingSystemVersion);
-
-VOID
-LoadReactOSSetup(IN OperatingSystemItem* OperatingSystem,
-                 IN USHORT OperatingSystemVersion);
+////////////////////////////////////////////////////////////////////////////////
+
+ARC_STATUS
+LoadAndBootWindows(
+    IN ULONG Argc,
+    IN PCHAR Argv[],
+    IN PCHAR Envp[]);
+
+ARC_STATUS
+LoadReactOSSetup(
+    IN ULONG Argc,
+    IN PCHAR Argv[],
+    IN PCHAR Envp[]);
 
 
 // conversion.c and conversion.h
diff --git a/boot/freeldr/freeldr/lib/arcsupp.c b/boot/freeldr/freeldr/lib/arcsupp.c
new file mode 100644 (file)
index 0000000..1292ece
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * PROJECT:     FreeLoader
+ * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE:     Generic ARC Support Functions
+ * COPYRIGHT:   Copyright 2019 Hermes Belusca-Maito
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <freeldr.h>
+
+/* FUNCTIONS *****************************************************************/
+
+PCHAR
+GetNextArgumentValue(
+    IN ULONG Argc,
+    IN PCHAR Argv[],
+    IN OUT PULONG LastIndex OPTIONAL,
+    IN PCHAR ArgumentName)
+{
+    ULONG i;
+    SIZE_T ArgNameLen = strlen(ArgumentName);
+
+    for (i = (LastIndex ? *LastIndex : 0); i < Argc; ++i)
+    {
+        if (strlen(Argv[i]) >= ArgNameLen + 1 /* Count the '=' sign */ &&
+            _strnicmp(Argv[i], ArgumentName, ArgNameLen) == 0 &&
+            Argv[i][ArgNameLen] == '=')
+        {
+            /* Found it, return the value */
+            if (LastIndex) *LastIndex = i;
+            return &Argv[i][ArgNameLen + 1];
+        }
+    }
+
+    if (LastIndex) *LastIndex = (ULONG)-1;
+    return NULL;
+}
+
+PCHAR
+GetArgumentValue(
+    IN ULONG Argc,
+    IN PCHAR Argv[],
+    IN PCHAR ArgumentName)
+{
+    return GetNextArgumentValue(Argc, Argv, NULL, ArgumentName);
+}
index d59ae16..6ddc8b9 100644 (file)
@@ -38,53 +38,55 @@ ULONG   SetupSectorSize = 0;
 BOOLEAN NewStyleLinuxKernel = FALSE;
 ULONG   LinuxKernelSize = 0;
 ULONG   LinuxInitrdSize = 0;
-CHAR    LinuxKernelName[260];
-CHAR    LinuxInitrdName[260];
-BOOLEAN LinuxHasInitrd = FALSE;
-CHAR    LinuxCommandLine[260] = "";
+PCSTR   LinuxKernelName = NULL;
+PCSTR   LinuxInitrdName = NULL;
+PSTR    LinuxCommandLine = NULL;
 ULONG   LinuxCommandLineSize = 0;
 PVOID   LinuxKernelLoadAddress = NULL;
 PVOID   LinuxInitrdLoadAddress = NULL;
 CHAR    LinuxBootDescription[80];
-CHAR    LinuxBootPath[260] = "";
+PCSTR   LinuxBootPath = NULL;
 
 /* FUNCTIONS ******************************************************************/
 
-BOOLEAN RemoveQuotes(PCHAR QuotedString)
+VOID
+RemoveQuotes(
+    IN OUT PSTR QuotedString)
 {
-    CHAR  TempString[200];
-    PCHAR p;
-    PSTR  Start;
+    PCHAR  p;
+    PSTR   Start;
+    SIZE_T Size;
 
     /* Skip spaces up to " */
     p = QuotedString;
-    while (*p == ' ' || *p == '"')
-        p++;
+    while (*p == ' ' || *p == '\t' || *p == '"')
+        ++p;
     Start = p;
 
     /* Go up to next " */
-    while (*p != '"' && *p != ANSI_NULL)
-        p++;
+    while (*p != ANSI_NULL && *p != '"')
+        ++p;
+    /* NULL-terminate */
     *p = ANSI_NULL;
 
-    /* Copy result */
-    strcpy(TempString, Start);
-    strcpy(QuotedString, TempString);
-
-    return TRUE;
+    /* Move the NULL-terminated string back into 'QuotedString' in place */
+    Size = (strlen(Start) + 1) * sizeof(CHAR);
+    memmove(QuotedString, Start, Size);
 }
 
-VOID
-LoadAndBootLinux(IN OperatingSystemItem* OperatingSystem,
-                 IN USHORT OperatingSystemVersion)
+ARC_STATUS
+LoadAndBootLinux(
+    IN ULONG Argc,
+    IN PCHAR Argv[],
+    IN PCHAR Envp[])
 {
-    PCSTR SectionName = OperatingSystem->SystemPartition;
-    PCSTR Description = OperatingSystem->LoadIdentifier;
+    PCSTR Description;
     PFILE LinuxKernel = 0;
     PFILE LinuxInitrdFile = 0;
 
+    Description = GetArgumentValue(Argc, Argv, "LoadIdentifier");
     if (Description)
-        sprintf(LinuxBootDescription, "Loading %s...", Description);
+        RtlStringCbPrintfA(LinuxBootDescription, sizeof(LinuxBootDescription), "Loading %s...", Description);
     else
         strcpy(LinuxBootDescription, "Loading Linux...");
 
@@ -92,8 +94,11 @@ LoadAndBootLinux(IN OperatingSystemItem* OperatingSystem,
     UiDrawStatusText(LinuxBootDescription);
     UiDrawProgressBarCenter(0, 100, LinuxBootDescription);
 
+    /* Find all the message box settings and run them */
+    UiShowMessageBoxesInArgv(Argc, Argv);
+
     /* Parse the .ini file section */
-    if (!LinuxParseIniSection(SectionName))
+    if (!LinuxParseIniSection(Argc, Argv))
         goto LinuxBootFailed;
 
     /* Open the kernel */
@@ -105,7 +110,7 @@ LoadAndBootLinux(IN OperatingSystemItem* OperatingSystem,
     }
 
     /* Open the initrd file image (if necessary) */
-    if (LinuxHasInitrd)
+    if (LinuxInitrdName)
     {
         LinuxInitrdFile = FsOpenFile(LinuxInitrdName);
         if (!LinuxInitrdFile)
@@ -134,7 +139,7 @@ LoadAndBootLinux(IN OperatingSystemItem* OperatingSystem,
         goto LinuxBootFailed;
 
     /* Read the initrd (if necessary) */
-    if (LinuxHasInitrd)
+    if (LinuxInitrdName)
     {
         if (!LinuxReadInitrd(LinuxInitrdFile))
             goto LinuxBootFailed;
@@ -161,7 +166,9 @@ LoadAndBootLinux(IN OperatingSystemItem* OperatingSystem,
 
     RtlCopyMemory((PVOID)0x90000, LinuxBootSector, 512);
     RtlCopyMemory((PVOID)0x90200, LinuxSetupSector, SetupSectorSize);
-    RtlCopyMemory((PVOID)0x99000, LinuxCommandLine, LinuxCommandLineSize);
+    RtlCopyMemory((PVOID)0x99000,
+                  LinuxCommandLine ? LinuxCommandLine : "",
+                  LinuxCommandLine ? LinuxCommandLineSize : sizeof(ANSI_NULL));
 
     UiUnInitialize("Booting Linux...");
     IniCleanup();
@@ -196,54 +203,52 @@ LinuxBootFailed:
 
     LinuxBootSector = NULL;
     LinuxSetupSector = NULL;
-    LinuxKernelLoadAddress = NULL;
-    LinuxInitrdLoadAddress = NULL;
     SetupSectorSize = 0;
     NewStyleLinuxKernel = FALSE;
     LinuxKernelSize = 0;
-    LinuxHasInitrd = FALSE;
-    strcpy(LinuxCommandLine, "");
+    LinuxInitrdSize = 0;
+    LinuxKernelName = NULL;
+    LinuxInitrdName = NULL;
+    LinuxCommandLine = NULL;
     LinuxCommandLineSize = 0;
+    LinuxKernelLoadAddress = NULL;
+    LinuxInitrdLoadAddress = NULL;
+    *LinuxBootDescription = ANSI_NULL;
+    LinuxBootPath = NULL;
+
+    return ENOEXEC;
 }
 
-BOOLEAN LinuxParseIniSection(PCSTR SectionName)
+BOOLEAN
+LinuxParseIniSection(
+    IN ULONG Argc,
+    IN PCHAR Argv[])
 {
-    ULONG_PTR SectionId;
-
-    /* Find all the message box settings and run them */
-    UiShowMessageBoxesInSection(SectionName);
-
-    /* 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 FALSE;
-    }
-
-    if (!IniReadSettingByName(SectionId, "BootPath", LinuxBootPath, sizeof(LinuxBootPath)))
+    LinuxBootPath = GetArgumentValue(Argc, Argv, "BootPath");
+    if (!LinuxBootPath)
     {
         UiMessageBox("Boot path not specified for selected OS!");
         return FALSE;
     }
 
     /* Get the kernel name */
-    if (!IniReadSettingByName(SectionId, "Kernel", LinuxKernelName, sizeof(LinuxKernelName)))
+    LinuxKernelName = GetArgumentValue(Argc, Argv, "Kernel");
+    if (!LinuxKernelName)
     {
         UiMessageBox("Linux kernel filename not specified for selected OS!");
         return FALSE;
     }
 
-    /* Get the initrd name */
-    if (IniReadSettingByName(SectionId, "Initrd", LinuxInitrdName, sizeof(LinuxInitrdName)))
-    {
-        LinuxHasInitrd = TRUE;
-    }
+    /* Get the initrd name (optional) */
+    LinuxInitrdName = GetArgumentValue(Argc, Argv, "Initrd");
 
-    /* Get the command line */
-    if (IniReadSettingByName(SectionId, "CommandLine", LinuxCommandLine, sizeof(LinuxCommandLine)))
+    /* Get the command line (optional) */
+    LinuxCommandLineSize = 0;
+    LinuxCommandLine = GetArgumentValue(Argc, Argv, "CommandLine");
+    if (LinuxCommandLine)
     {
         RemoveQuotes(LinuxCommandLine);
-        LinuxCommandLineSize = strlen(LinuxCommandLine) + 1;
+        LinuxCommandLineSize = min(strlen(LinuxCommandLine) + 1, 260);
     }
 
     return TRUE;
@@ -270,14 +275,14 @@ BOOLEAN LinuxReadBootSector(PFILE LinuxKernelFile)
 
     // DbgDumpBuffer(DPRINT_LINUX, LinuxBootSector, 512);
 
-    TRACE("SetupSectors: %d\n", LinuxBootSector->SetupSectors);
-    TRACE("RootFlags: 0x%x\n", LinuxBootSector->RootFlags);
-    TRACE("SystemSize: 0x%x\n", LinuxBootSector->SystemSize);
-    TRACE("SwapDevice: 0x%x\n", LinuxBootSector->SwapDevice);
-    TRACE("RamSize: 0x%x\n", LinuxBootSector->RamSize);
-    TRACE("VideoMode: 0x%x\n", LinuxBootSector->VideoMode);
-    TRACE("RootDevice: 0x%x\n", LinuxBootSector->RootDevice);
-    TRACE("BootFlag: 0x%x\n", LinuxBootSector->BootFlag);
+    TRACE("SetupSectors: %d\n"  , LinuxBootSector->SetupSectors);
+    TRACE("RootFlags:    0x%x\n", LinuxBootSector->RootFlags);
+    TRACE("SystemSize:   0x%x\n", LinuxBootSector->SystemSize);
+    TRACE("SwapDevice:   0x%x\n", LinuxBootSector->SwapDevice);
+    TRACE("RamSize:      0x%x\n", LinuxBootSector->RamSize);
+    TRACE("VideoMode:    0x%x\n", LinuxBootSector->VideoMode);
+    TRACE("RootDevice:   0x%x\n", LinuxBootSector->RootDevice);
+    TRACE("BootFlag:     0x%x\n", LinuxBootSector->BootFlag);
 
     return TRUE;
 }
@@ -286,14 +291,13 @@ BOOLEAN LinuxReadSetupSector(PFILE LinuxKernelFile)
 {
     UCHAR TempLinuxSetupSector[512];
 
-    LinuxSetupSector = (PLINUX_SETUPSECTOR)TempLinuxSetupSector;
-
     /* Read first linux setup sector */
     FsSetFilePointer(LinuxKernelFile, 512);
     if (!FsReadFile(LinuxKernelFile, 512, NULL, TempLinuxSetupSector))
         return FALSE;
 
     /* Check the kernel version */
+    LinuxSetupSector = (PLINUX_SETUPSECTOR)TempLinuxSetupSector;
     if (!LinuxCheckKernelVersion())
         return FALSE;
 
@@ -318,18 +322,18 @@ BOOLEAN LinuxReadSetupSector(PFILE LinuxKernelFile)
     // DbgDumpBuffer(DPRINT_LINUX, LinuxSetupSector, SetupSectorSize);
 
     TRACE("SetupHeaderSignature: 0x%x (HdrS)\n", LinuxSetupSector->SetupHeaderSignature);
-    TRACE("Version: 0x%x\n", LinuxSetupSector->Version);
+    TRACE("Version:              0x%x\n", LinuxSetupSector->Version);
     TRACE("RealModeSwitch: 0x%x\n", LinuxSetupSector->RealModeSwitch);
-    TRACE("SetupSeg: 0x%x\n", LinuxSetupSector->SetupSeg);
+    TRACE("SetupSeg:       0x%x\n", LinuxSetupSector->SetupSeg);
     TRACE("StartSystemSeg: 0x%x\n", LinuxSetupSector->StartSystemSeg);
-    TRACE("KernelVersion: 0x%x\n", LinuxSetupSector->KernelVersion);
-    TRACE("TypeOfLoader: 0x%x\n", LinuxSetupSector->TypeOfLoader);
-    TRACE("LoadFlags: 0x%x\n", LinuxSetupSector->LoadFlags);
-    TRACE("SetupMoveSize: 0x%x\n", LinuxSetupSector->SetupMoveSize);
-    TRACE("Code32Start: 0x%x\n", LinuxSetupSector->Code32Start);
+    TRACE("KernelVersion:  0x%x\n", LinuxSetupSector->KernelVersion);
+    TRACE("TypeOfLoader:   0x%x\n", LinuxSetupSector->TypeOfLoader);
+    TRACE("LoadFlags:      0x%x\n", LinuxSetupSector->LoadFlags);
+    TRACE("SetupMoveSize:  0x%x\n", LinuxSetupSector->SetupMoveSize);
+    TRACE("Code32Start:    0x%x\n", LinuxSetupSector->Code32Start);
     TRACE("RamdiskAddress: 0x%x\n", LinuxSetupSector->RamdiskAddress);
-    TRACE("RamdiskSize: 0x%x\n", LinuxSetupSector->RamdiskSize);
-    TRACE("BootSectKludgeOffset: 0x%x\n", LinuxSetupSector->BootSectKludgeOffset);
+    TRACE("RamdiskSize:    0x%x\n", LinuxSetupSector->RamdiskSize);
+    TRACE("BootSectKludgeOffset:  0x%x\n", LinuxSetupSector->BootSectKludgeOffset);
     TRACE("BootSectKludgeSegment: 0x%x\n", LinuxSetupSector->BootSectKludgeSegment);
     TRACE("HeapEnd: 0x%x\n", LinuxSetupSector->HeapEnd);
 
@@ -398,7 +402,7 @@ BOOLEAN LinuxCheckKernelVersion(VOID)
         LinuxSetupSector->LoadFlags |= LINUX_FLAG_CAN_USE_HEAP;
     }
 
-    if ((NewStyleLinuxKernel == FALSE) && (LinuxHasInitrd))
+    if ((NewStyleLinuxKernel == FALSE) && (LinuxInitrdName))
     {
         UiMessageBox("Error: Cannot load a ramdisk (initrd) with an old kernel image.");
         return FALSE;
@@ -437,7 +441,7 @@ BOOLEAN LinuxReadInitrd(PFILE LinuxInitrdFile)
     LinuxSetupSector->RamdiskSize = LinuxInitrdSize;
 
     TRACE("RamdiskAddress: 0x%x\n", LinuxSetupSector->RamdiskAddress);
-    TRACE("RamdiskSize: 0x%x\n", LinuxSetupSector->RamdiskSize);
+    TRACE("RamdiskSize:    0x%x\n", LinuxSetupSector->RamdiskSize);
 
     if (LinuxSetupSector->Version >= 0x0203)
     {
index 4ad2daa..98cb527 100644 (file)
 
 /* FUNCTIONS ******************************************************************/
 
-VOID
-LoadAndBootBootSector(IN OperatingSystemItem* OperatingSystem,
-                      IN USHORT OperatingSystemVersion)
+ARC_STATUS
+LoadAndBootBootSector(
+    IN ULONG Argc,
+    IN PCHAR Argv[],
+    IN PCHAR Envp[])
 {
-    ULONG_PTR SectionId;
-    PCSTR SectionName = OperatingSystem->SystemPartition;
-    CHAR  FileName[260];
+    PCSTR FileName;
     PFILE FilePointer;
     ULONG BytesRead;
 
     /* Find all the message box settings and run them */
-    UiShowMessageBoxesInSection(SectionName);
+    UiShowMessageBoxesInArgv(Argc, Argv);
 
-    /* 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;
-    }
-
-    if (!IniReadSettingByName(SectionId, "BootSectorFile", FileName, sizeof(FileName)))
+    /* Read the file name */
+    FileName = GetArgumentValue(Argc, Argv, "BootSectorFile");
+    if (!FileName)
     {
         UiMessageBox("Boot sector file not specified for selected OS!");
-        return;
+        return EINVAL;
     }
 
     FilePointer = FsOpenFile(FileName);
     if (!FilePointer)
     {
         UiMessageBox("%s not found.", FileName);
-        return;
+        return ENOENT;
     }
 
     /* Read boot sector */
     if (!FsReadFile(FilePointer, 512, &BytesRead, (void*)0x7c00) || (BytesRead != 512))
     {
         UiMessageBox("Unable to read boot sector.");
-        return;
+        return EIO;
     }
 
     /* Check for validity */
     if (*((USHORT*)(0x7c00 + 0x1fe)) != 0xaa55)
     {
         UiMessageBox("Invalid boot sector magic (0xaa55)");
-        return;
+        return ENOEXEC;
     }
 
     UiUnInitialize("Booting...");
@@ -87,65 +82,59 @@ LoadAndBootBootSector(IN OperatingSystemItem* OperatingSystem,
     // DiskStopFloppyMotor();
     // DisableA20();
     ChainLoadBiosBootSectorCode();
+    return ESUCCESS;
 }
 
-VOID
-LoadAndBootPartition(IN OperatingSystemItem* OperatingSystem,
-                     IN USHORT OperatingSystemVersion)
+ARC_STATUS
+LoadAndBootPartition(
+    IN ULONG Argc,
+    IN PCHAR Argv[],
+    IN PCHAR Envp[])
 {
-    ULONG_PTR SectionId;
-    PCSTR SectionName = OperatingSystem->SystemPartition;
-    CHAR  SettingValue[80];
+    PCSTR ArgValue;
     PARTITION_TABLE_ENTRY PartitionTableEntry;
     UCHAR DriveNumber;
     ULONG PartitionNumber;
 
     /* Find all the message box settings and run them */
-    UiShowMessageBoxesInSection(SectionName);
-
-    /* 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;
-    }
+    UiShowMessageBoxesInArgv(Argc, Argv);
 
     /* Read the boot drive */
-    if (!IniReadSettingByName(SectionId, "BootDrive", SettingValue, sizeof(SettingValue)))
+    ArgValue = GetArgumentValue(Argc, Argv, "BootDrive");
+    if (!ArgValue)
     {
         UiMessageBox("Boot drive not specified for selected OS!");
-        return;
+        return EINVAL;
     }
-
-    DriveNumber = DriveMapGetBiosDriveNumber(SettingValue);
+    DriveNumber = DriveMapGetBiosDriveNumber(ArgValue);
 
     /* Read the boot partition */
-    if (!IniReadSettingByName(SectionId, "BootPartition", SettingValue, sizeof(SettingValue)))
+    ArgValue = GetArgumentValue(Argc, Argv, "BootPartition");
+    if (!ArgValue)
     {
         UiMessageBox("Boot partition not specified for selected OS!");
-        return;
+        return EINVAL;
     }
-
-    PartitionNumber = atoi(SettingValue);
+    PartitionNumber = atoi(ArgValue);
 
     /* Get the partition table entry */
     if (!DiskGetPartitionEntry(DriveNumber, PartitionNumber, &PartitionTableEntry))
     {
-        return;
+        return ENOENT;
     }
 
     /* Now try to read the partition boot sector. If this fails then abort. */
     if (!MachDiskReadLogicalSectors(DriveNumber, PartitionTableEntry.SectorCountBeforePartition, 1, (PVOID)0x7C00))
     {
         UiMessageBox("Unable to read partition's boot sector.");
-        return;
+        return EIO;
     }
 
     /* Check for validity */
     if (*((USHORT*)(0x7c00 + 0x1fe)) != 0xaa55)
     {
         UiMessageBox("Invalid boot sector magic (0xaa55)");
-        return;
+        return ENOEXEC;
     }
 
     UiUnInitialize("Booting...");
@@ -164,47 +153,42 @@ LoadAndBootPartition(IN OperatingSystemItem* OperatingSystem,
     // DisableA20();
     FrldrBootDrive = DriveNumber;
     ChainLoadBiosBootSectorCode();
+    return ESUCCESS;
 }
 
-VOID
-LoadAndBootDrive(IN OperatingSystemItem* OperatingSystem,
-                 IN USHORT OperatingSystemVersion)
+ARC_STATUS
+LoadAndBootDrive(
+    IN ULONG Argc,
+    IN PCHAR Argv[],
+    IN PCHAR Envp[])
 {
-    ULONG_PTR SectionId;
-    PCSTR SectionName = OperatingSystem->SystemPartition;
-    CHAR  SettingValue[80];
+    PCSTR ArgValue;
     UCHAR DriveNumber;
 
     /* Find all the message box settings and run them */
-    UiShowMessageBoxesInSection(SectionName);
-
-    /* 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;
-    }
+    UiShowMessageBoxesInArgv(Argc, Argv);
 
-    if (!IniReadSettingByName(SectionId, "BootDrive", SettingValue, sizeof(SettingValue)))
+    /* Read the boot drive */
+    ArgValue = GetArgumentValue(Argc, Argv, "BootDrive");
+    if (!ArgValue)
     {
         UiMessageBox("Boot drive not specified for selected OS!");
-        return;
+        return EINVAL;
     }
-
-    DriveNumber = DriveMapGetBiosDriveNumber(SettingValue);
+    DriveNumber = DriveMapGetBiosDriveNumber(ArgValue);
 
     /* Now try to read the boot sector (or mbr). If this fails then abort. */
     if (!MachDiskReadLogicalSectors(DriveNumber, 0, 1, (PVOID)0x7C00))
     {
         UiMessageBox("Unable to read boot sector");
-        return;
+        return EIO;
     }
 
     /* Check for validity */
     if (*((USHORT*)(0x7c00 + 0x1fe)) != 0xaa55)
     {
         UiMessageBox("Invalid boot sector magic (0xaa55)");
-        return;
+        return ENOEXEC;
     }
 
     UiUnInitialize("Booting...");
@@ -223,6 +207,7 @@ LoadAndBootDrive(IN OperatingSystemItem* OperatingSystem,
     // DisableA20();
     FrldrBootDrive = DriveNumber;
     ChainLoadBiosBootSectorCode();
+    return ESUCCESS;
 }
 
 #endif // _M_IX86
index 68841f8..98b66e8 100644 (file)
@@ -141,18 +141,17 @@ SetupLdrScanBootDrivers(PLIST_ENTRY BootDriverListHead, HINF InfHandle, LPCSTR S
 
 /* SETUP STARTER **************************************************************/
 
-VOID
-LoadReactOSSetup(IN OperatingSystemItem* OperatingSystem,
-                 IN USHORT OperatingSystemVersion)
+ARC_STATUS
+LoadReactOSSetup(
+    IN ULONG Argc,
+    IN PCHAR Argv[],
+    IN PCHAR Envp[])
 {
-    ULONG_PTR SectionId;
-    PCSTR SectionName = OperatingSystem->SystemPartition;
-    CHAR  SettingsValue[80];
-    BOOLEAN HasSection;
-    CHAR  BootOptions2[256];
+    PCSTR ArgValue;
     PCHAR File;
     CHAR FileName[512];
     CHAR BootPath[512];
+    CHAR BootOptions2[256];
     LPCSTR LoadOptions;
     LPSTR BootOptions;
     BOOLEAN BootFromFloppy;
@@ -163,7 +162,8 @@ LoadReactOSSetup(IN OperatingSystemItem* OperatingSystem,
     PLOADER_PARAMETER_BLOCK LoaderBlock;
     PSETUP_LOADER_BLOCK SetupBlock;
     LPCSTR SystemPath;
-    LPCSTR SourcePaths[] =
+
+    static LPCSTR SourcePaths[] =
     {
         "", /* Only for floppy boot */
 #if defined(_M_IX86)
@@ -179,31 +179,27 @@ LoadReactOSSetup(IN OperatingSystemItem* OperatingSystem,
 
     UiDrawStatusText("Setup is loading...");
 
-    /* Get OS setting value */
-    SettingsValue[0] = ANSI_NULL;
-    IniOpenSection("Operating Systems", &SectionId);
-    IniReadSettingByName(SectionId, SectionName, SettingsValue, sizeof(SettingsValue));
-
-    /* Open the operating system section specified in the .ini file */
-    HasSection = IniOpenSection(SectionName, &SectionId);
-
     UiDrawBackdrop();
     UiDrawProgressBarCenter(1, 100, "Loading ReactOS Setup...");
 
-    /* Read the system path is set in the .ini file */
-    BootPath[0] = ANSI_NULL;
-    if (!HasSection || !IniReadSettingByName(SectionId, "SystemPath", BootPath, sizeof(BootPath)))
+    /* Retrieve the system path */
+    *BootPath = ANSI_NULL;
+    ArgValue = GetArgumentValue(Argc, Argv, "SystemPath");
+    if (ArgValue)
+    {
+        RtlStringCbCopyA(BootPath, sizeof(BootPath), ArgValue);
+    }
+    else
     {
         /*
          * IMPROVE: I don't want to call MachDiskGetBootPath here as a
          * default choice because I can call it after (see few lines below).
-         * Also doing the strcpy call as it is done in winldr.c is not
-         * really what we want. Instead I reset BootPath here so that
-         * we can build the full path using the general code from below.
+         * Instead I reset BootPath here so that we can build the full path
+         * using the general code from below.
          */
         // MachDiskGetBootPath(BootPath, sizeof(BootPath));
-        // strcpy(BootPath, SectionName);
-        BootPath[0] = ANSI_NULL;
+        // RtlStringCbCopyA(BootPath, sizeof(BootPath), ArgValue);
+        *BootPath = ANSI_NULL;
     }
 
     /*
@@ -215,65 +211,34 @@ LoadReactOSSetup(IN OperatingSystemItem* OperatingSystem,
     if (strrchr(BootPath, ')') == NULL)
     {
         /* Temporarily save the boot path */
-        strcpy(FileName, BootPath);
+        RtlStringCbCopyA(FileName, sizeof(FileName), BootPath);
 
         /* This is not a full path. Use the current (i.e. boot) device. */
         MachDiskGetBootPath(BootPath, sizeof(BootPath));
 
         /* Append a path separator if needed */
-        if (FileName[0] != '\\' && FileName[0] != '/')
-            strcat(BootPath, "\\");
+        if (*FileName != '\\' && *FileName != '/')
+            RtlStringCbCatA(BootPath, sizeof(BootPath), "\\");
 
         /* Append the remaining path */
-        strcat(BootPath, FileName);
+        RtlStringCbCatA(BootPath, sizeof(BootPath), FileName);
     }
 
     /* Append a backslash if needed */
-    if ((strlen(BootPath) == 0) || BootPath[strlen(BootPath) - 1] != '\\')
-        strcat(BootPath, "\\");
+    if (!*BootPath || BootPath[strlen(BootPath) - 1] != '\\')
+        RtlStringCbCatA(BootPath, sizeof(BootPath), "\\");
 
-    /* Read boot options */
-    BootOptions2[0] = ANSI_NULL;
-    if (!HasSection || !IniReadSettingByName(SectionId, "Options", BootOptions2, sizeof(BootOptions2)))
-    {
-        /* Retrieve the options after the quoted title */
-        PCSTR p = SettingsValue;
-
-        /* Trim any leading whitespace and quotes */
-        while (*p == ' ' || *p == '\t' || *p == '"')
-            ++p;
-        /* Skip all the text up to the first last quote */
-        while (*p != ANSI_NULL && *p != '"')
-            ++p;
-        /* Trim any trailing whitespace and quotes */
-        while (*p == ' ' || *p == '\t' || *p == '"')
-            ++p;
-
-        strcpy(BootOptions2, p);
-        TRACE("BootOptions: '%s'\n", BootOptions2);
-    }
-
-    /* Check if a ramdisk file was given */
-    File = strstr(BootOptions2, "/RDPATH=");
-    if (File)
-    {
-        /* Copy the file name and everything else after it */
-        strcpy(FileName, File + 8);
+    TRACE("BootPath: '%s'\n", BootPath);
 
-        /* Null-terminate */
-        *strstr(FileName, " ") = ANSI_NULL;
+    /* Retrieve the boot options */
+    *BootOptions2 = ANSI_NULL;
+    ArgValue = GetArgumentValue(Argc, Argv, "Options");
+    if (ArgValue)
+        RtlStringCbCopyA(BootOptions2, sizeof(BootOptions2), ArgValue);
 
-        /* Load the ramdisk */
-        if (!RamDiskLoadVirtualFile(FileName))
-        {
-            UiMessageBox("Failed to load RAM disk file %s", FileName);
-            return;
-        }
-    }
+    TRACE("BootOptions: '%s'\n", BootOptions2);
 
-    TRACE("BootPath: '%s'\n", BootPath);
-
-    /* And check if we booted from floppy */
+    /* Check if we booted from floppy */
     BootFromFloppy = strstr(BootPath, "fdisk") != NULL;
 
     /* Open 'txtsetup.sif' from any of source paths */
@@ -284,11 +249,11 @@ LoadReactOSSetup(IN OperatingSystemItem* OperatingSystem,
         if (!SystemPath)
         {
             UiMessageBox("Failed to open txtsetup.sif");
-            return;
+            return ENOENT;
         }
-        strcpy(File, SystemPath);
-        strcpy(FileName, BootPath);
-        strcat(FileName, "txtsetup.sif");
+        RtlStringCbCopyA(File, sizeof(BootPath) - (File - BootPath)*sizeof(CHAR), SystemPath);
+        RtlStringCbCopyA(FileName, sizeof(FileName), BootPath);
+        RtlStringCbCatA(FileName, sizeof(FileName), "txtsetup.sif");
         if (InfOpenFile(&InfHandle, FileName, &ErrorLine))
         {
             break;
@@ -301,13 +266,13 @@ LoadReactOSSetup(IN OperatingSystemItem* OperatingSystem,
     if (!InfFindFirstLine(InfHandle, "SetupData", "OsLoadOptions", &InfContext))
     {
         ERR("Failed to find 'SetupData/OsLoadOptions'\n");
-        return;
+        return EINVAL;
     }
 
     if (!InfGetDataField(&InfContext, 1, &LoadOptions))
     {
         ERR("Failed to get load options\n");
-        return;
+        return EINVAL;
     }
 
 #if DBG
@@ -323,10 +288,29 @@ LoadReactOSSetup(IN OperatingSystemItem* OperatingSystem,
 
     /* Copy loadoptions (original string will be freed) */
     BootOptions = FrLdrTempAlloc(strlen(LoadOptions) + 1, TAG_BOOT_OPTIONS);
+    ASSERT(BootOptions);
     strcpy(BootOptions, LoadOptions);
 
     TRACE("BootOptions: '%s'\n", BootOptions);
 
+    /* Check if a ramdisk file was given */
+    File = strstr(BootOptions2, "/RDPATH=");
+    if (File)
+    {
+        /* Copy the file name and everything else after it */
+        RtlStringCbCopyA(FileName, sizeof(FileName), File + 8);
+
+        /* Null-terminate */
+        *strstr(FileName, " ") = ANSI_NULL;
+
+        /* Load the ramdisk */
+        if (!RamDiskLoadVirtualFile(FileName))
+        {
+            UiMessageBox("Failed to load RAM disk file %s", FileName);
+            return ENOENT;
+        }
+    }
+
     /* Allocate and minimalist-initialize LPB */
     AllocateAndInitLPB(&LoaderBlock);
 
@@ -344,11 +328,11 @@ LoadReactOSSetup(IN OperatingSystemItem* OperatingSystem,
     TRACE("Setup SYSTEM hive %s\n", (Success ? "loaded" : "not loaded"));
     /* Bail out if failure */
     if (!Success)
-        return;
+        return ENOEXEC;
 
     /* Load NLS data, they are in the System32 directory of the installation medium */
-    strcpy(FileName, BootPath);
-    strcat(FileName, "system32\\");
+    RtlStringCbCopyA(FileName, sizeof(FileName), BootPath);
+    RtlStringCbCatA(FileName, sizeof(FileName), "system32\\");
     SetupLdrLoadNlsData(LoaderBlock, InfHandle, FileName);
 
     // UiDrawStatusText("Press F6 if you need to install a 3rd-party SCSI or RAID driver...");
@@ -362,9 +346,9 @@ LoadReactOSSetup(IN OperatingSystemItem* OperatingSystem,
     UiDrawStatusText("The Setup program is starting...");
 
     /* Load ReactOS Setup */
-    LoadAndBootWindowsCommon(_WIN32_WINNT_WS03,
-                             LoaderBlock,
-                             BootOptions,
-                             BootPath,
-                             TRUE);
+    return LoadAndBootWindowsCommon(_WIN32_WINNT_WS03,
+                                    LoaderBlock,
+                                    BootOptions,
+                                    BootPath,
+                                    TRUE);
 }
index e8e2eb2..98de7f2 100644 (file)
@@ -88,16 +88,15 @@ WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock,
 
     LPSTR LoadOptions, NewLoadOptions;
     CHAR  HalPath[] = "\\";
-    CHAR  ArcBoot[256];
-    CHAR  MiscFiles[256];
+    CHAR  ArcBoot[MAX_PATH+1];
+    CHAR  MiscFiles[MAX_PATH+1];
     ULONG i;
     ULONG_PTR PathSeparator;
     PLOADER_PARAMETER_EXTENSION Extension;
 
     /* Construct SystemRoot and ArcBoot from SystemPath */
     PathSeparator = strstr(BootPath, "\\") - BootPath;
-    strncpy(ArcBoot, BootPath, PathSeparator);
-    ArcBoot[PathSeparator] = ANSI_NULL;
+    RtlStringCbCopyNA(ArcBoot, sizeof(ArcBoot), BootPath, PathSeparator);
 
     TRACE("ArcBoot: '%s'\n", ArcBoot);
     TRACE("SystemRoot: '%s'\n", SystemRoot);
@@ -105,7 +104,7 @@ WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock,
 
     /* Fill ARC BootDevice */
     LoaderBlock->ArcBootDeviceName = WinLdrSystemBlock->ArcBootDeviceName;
-    strncpy(LoaderBlock->ArcBootDeviceName, ArcBoot, MAX_PATH);
+    RtlStringCbCopyA(LoaderBlock->ArcBootDeviceName, sizeof(WinLdrSystemBlock->ArcBootDeviceName), ArcBoot);
     LoaderBlock->ArcBootDeviceName = PaToVa(LoaderBlock->ArcBootDeviceName);
 
     /* Fill ARC HalDevice, it matches ArcBoot path */
@@ -114,17 +113,17 @@ WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock,
 
     /* Fill SystemRoot */
     LoaderBlock->NtBootPathName = WinLdrSystemBlock->NtBootPathName;
-    strncpy(LoaderBlock->NtBootPathName, SystemRoot, MAX_PATH);
+    RtlStringCbCopyA(LoaderBlock->NtBootPathName, sizeof(WinLdrSystemBlock->NtBootPathName), SystemRoot);
     LoaderBlock->NtBootPathName = PaToVa(LoaderBlock->NtBootPathName);
 
     /* Fill NtHalPathName */
     LoaderBlock->NtHalPathName = WinLdrSystemBlock->NtHalPathName;
-    strncpy(LoaderBlock->NtHalPathName, HalPath, MAX_PATH);
+    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;
-    strncpy(LoaderBlock->LoadOptions, Options, MAX_OPTIONS_LENGTH);
+    RtlStringCbCopyA(LoaderBlock->LoadOptions, sizeof(WinLdrSystemBlock->LoadOptions), Options);
 
     do
     {
@@ -205,8 +204,8 @@ WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock,
     }
 #endif
     /* Load drivers database */
-    strcpy(MiscFiles, BootPath);
-    strcat(MiscFiles, "AppPatch\\drvmain.sdb");
+    RtlStringCbCopyA(MiscFiles, sizeof(MiscFiles), BootPath);
+    RtlStringCbCatA(MiscFiles, sizeof(MiscFiles), "AppPatch\\drvmain.sdb");
     Extension->DrvDBImage = PaToVa(WinLdrLoadModule(MiscFiles,
                                                     &Extension->DrvDBSize,
                                                     LoaderRegistryData));
@@ -235,21 +234,21 @@ WinLdrLoadDeviceDriver(PLIST_ENTRY LoadOrderListHead,
     PVOID DriverBase = NULL;
 
     // Separate the path to file name and directory path
-    _snprintf(DriverPath, sizeof(DriverPath), "%wZ", FilePath);
+    RtlStringCbPrintfA(DriverPath, sizeof(DriverPath), "%wZ", FilePath);
     DriverNamePos = strrchr(DriverPath, '\\');
     if (DriverNamePos != NULL)
     {
         // Copy the name
-        strcpy(DllName, DriverNamePos+1);
+        RtlStringCbCopyA(DllName, sizeof(DllName), DriverNamePos+1);
 
         // Cut out the name from the path
-        *(DriverNamePos+1) = 0;
+        *(DriverNamePos+1) = ANSI_NULL;
     }
     else
     {
         // There is no directory in the path
-        strcpy(DllName, DriverPath);
-        DriverPath[0] = ANSI_NULL;
+        RtlStringCbCopyA(DllName, sizeof(DllName), DriverPath);
+        *DriverPath = ANSI_NULL;
     }
 
     TRACE("DriverPath: '%s', DllName: '%s', LPB\n", DriverPath, DllName);
@@ -263,7 +262,7 @@ WinLdrLoadDeviceDriver(PLIST_ENTRY LoadOrderListHead,
     }
 
     // It's not loaded, we have to load it
-    _snprintf(FullPath, sizeof(FullPath), "%s%wZ", BootPath, FilePath);
+    RtlStringCbPrintfA(FullPath, sizeof(FullPath), "%s%wZ", BootPath, FilePath);
     Success = WinLdrLoadImage(FullPath, LoaderBootDriver, &DriverBase);
     if (!Success)
         return FALSE;
@@ -280,7 +279,7 @@ WinLdrLoadDeviceDriver(PLIST_ENTRY LoadOrderListHead,
     (*DriverDTE)->Flags |= Flags;
 
     // Look for any dependencies it may have, and load them too
-    sprintf(FullPath,"%s%s", BootPath, DriverPath);
+    RtlStringCbPrintfA(FullPath, sizeof(FullPath), "%s%s", BootPath, DriverPath);
     Success = WinLdrScanImportDescriptorTable(LoadOrderListHead, FullPath, *DriverDTE);
     if (!Success)
     {
@@ -359,7 +358,7 @@ WinLdrLoadModule(PCSTR ModuleName,
 
     /* Inform user we are loading files */
     //UiDrawBackdrop();
-    //sprintf(ProgressString, "Loading %s...", FileName);
+    //RtlStringCbPrintfA(ProgressString, sizeof(ProgressString), "Loading %s...", FileName);
     //UiDrawProgressBarCenter(1, 100, ProgressString);
 
     TRACE("Loading module %s\n", ModuleName);
@@ -441,11 +440,11 @@ LoadModule(
     PVOID BaseAddress = NULL;
 
     UiDrawBackdrop();
-    sprintf(ProgressString, "Loading %s...", File);
+    RtlStringCbPrintfA(ProgressString, sizeof(ProgressString), "Loading %s...", File);
     UiDrawProgressBarCenter(Percentage, 100, ProgressString);
 
-    strcpy(FullFileName, Path);
-    strcat(FullFileName, File);
+    RtlStringCbCopyA(FullFileName, sizeof(FullFileName), Path);
+    RtlStringCbCatA(FullFileName, sizeof(FullFileName), File);
 
     Success = WinLdrLoadImage(FullFileName, MemoryType, &BaseAddress);
     if (!Success)
@@ -488,16 +487,16 @@ LoadWindowsCore(IN USHORT OperatingSystemVersion,
     if (!KernelDTE) return FALSE;
 
     /* Initialize SystemRoot\System32 path */
-    strcpy(DirPath, BootPath);
-    strcat(DirPath, "system32\\");
+    RtlStringCbCopyA(DirPath, sizeof(DirPath), BootPath);
+    RtlStringCbCatA(DirPath, sizeof(DirPath), "system32\\");
 
     //
     // TODO: Parse also the separate INI values "Kernel=" and "Hal="
     //
 
     /* Default KERNEL and HAL file names */
-    strcpy(KernelFileName, "ntoskrnl.exe");
-    strcpy(HalFileName   , "hal.dll");
+    RtlStringCbCopyA(KernelFileName, sizeof(KernelFileName), "ntoskrnl.exe");
+    RtlStringCbCopyA(HalFileName   , sizeof(HalFileName)   , "hal.dll");
 
     /* Find any /KERNEL= or /HAL= switch in the boot options */
     Options = BootOptions;
@@ -528,15 +527,13 @@ LoadWindowsCore(IN USHORT OperatingSystemVersion,
             if (_strnicmp(Options, "KERNEL=", 7) == 0)
             {
                 Options += 7; i -= 7;
-                strncpy(KernelFileName, Options, i);
-                KernelFileName[i] = ANSI_NULL;
+                RtlStringCbCopyNA(KernelFileName, sizeof(KernelFileName), Options, i);
                 _strupr(KernelFileName);
             }
             else if (_strnicmp(Options, "HAL=", 4) == 0)
             {
                 Options += 4; i -= 4;
-                strncpy(HalFileName, Options, i);
-                HalFileName[i] = ANSI_NULL;
+                RtlStringCbCopyNA(HalFileName, sizeof(HalFileName), Options, i);
                 _strupr(HalFileName);
             }
         }
@@ -611,20 +608,20 @@ LoadWindowsCore(IN USHORT OperatingSystemVersion,
              * Format: /DEBUGPORT=COM1 or /DEBUGPORT=FILE:\Device\HarddiskX\PartitionY\debug.log or /DEBUGPORT=FOO
              * If we only have /DEBUGPORT= (i.e. without any port name), defaults it to "COM".
              */
-            strcpy(KdTransportDllName, "KD");
+            RtlStringCbCopyA(KdTransportDllName, sizeof(KdTransportDllName), "KD");
             if (_strnicmp(Options, "COM", 3) == 0 && '0' <= Options[3] && Options[3] <= '9')
             {
-                strncat(KdTransportDllName, Options, 3);
+                RtlStringCbCatNA(KdTransportDllName, sizeof(KdTransportDllName), Options, 3);
             }
             else
             {
                 size_t i = strcspn(Options, " \t:"); /* Skip valid separators: whitespace or colon */
                 if (i == 0)
-                    strcat(KdTransportDllName, "COM");
+                    RtlStringCbCatA(KdTransportDllName, sizeof(KdTransportDllName), "COM");
                 else
-                    strncat(KdTransportDllName, Options, i);
+                    RtlStringCbCatNA(KdTransportDllName, sizeof(KdTransportDllName), Options, i);
             }
-            strcat(KdTransportDllName, ".DLL");
+            RtlStringCbCatA(KdTransportDllName, sizeof(KdTransportDllName), ".DLL");
             _strupr(KdTransportDllName);
 
             /*
@@ -646,38 +643,51 @@ LoadWindowsCore(IN USHORT OperatingSystemVersion,
     return Success;
 }
 
-VOID
-LoadAndBootWindows(IN OperatingSystemItem* OperatingSystem,
-                   IN USHORT OperatingSystemVersion)
+ARC_STATUS
+LoadAndBootWindows(
+    IN ULONG Argc,
+    IN PCHAR Argv[],
+    IN PCHAR Envp[])
 {
-    ULONG_PTR SectionId;
-    PCSTR SectionName = OperatingSystem->SystemPartition;
+    PCSTR ArgValue;
     PCHAR File;
     BOOLEAN Success;
-    BOOLEAN HasSection;
-    CHAR  SettingsValue[80];
+    USHORT OperatingSystemVersion;
+    PLOADER_PARAMETER_BLOCK LoaderBlock;
     CHAR  BootPath[MAX_PATH];
     CHAR  FileName[MAX_PATH];
     CHAR  BootOptions[256];
-    PLOADER_PARAMETER_BLOCK LoaderBlock;
 
-    /* Get OS setting value */
-    SettingsValue[0] = ANSI_NULL;
-    IniOpenSection("Operating Systems", &SectionId);
-    IniReadSettingByName(SectionId, SectionName, SettingsValue, sizeof(SettingsValue));
+    ArgValue = GetArgumentValue(Argc, Argv, "BootType");
+    if (!ArgValue)
+    {
+        ERR("No 'BootType' value, aborting!\n");
+        return EINVAL;
+    }
 
-    /* Open the operating system section specified in the .ini file */
-    HasSection = IniOpenSection(SectionName, &SectionId);
+    if (_stricmp(ArgValue, "Windows") == 0 ||
+        _stricmp(ArgValue, "Windows2003") == 0)
+    {
+        OperatingSystemVersion = _WIN32_WINNT_WS03;
+    }
+    else if (_stricmp(ArgValue, "WindowsNT40") == 0)
+    {
+        OperatingSystemVersion = _WIN32_WINNT_NT4;
+    }
+    else
+    {
+        ERR("Unknown 'BootType' value '%s', aborting!\n", ArgValue);
+        return EINVAL;
+    }
 
     UiDrawBackdrop();
     UiDrawProgressBarCenter(1, 100, "Loading NT...");
 
-    /* Read the system path is set in the .ini file */
-    BootPath[0] = ANSI_NULL;
-    if (!HasSection || !IniReadSettingByName(SectionId, "SystemPath", BootPath, sizeof(BootPath)))
-    {
-        strcpy(BootPath, SectionName);
-    }
+    /* Retrieve the system path */
+    *BootPath = ANSI_NULL;
+    ArgValue = GetArgumentValue(Argc, Argv, "SystemPath");
+    if (ArgValue)
+        RtlStringCbCopyA(BootPath, sizeof(BootPath), ArgValue);
 
     /*
      * Check whether BootPath is a full path
@@ -688,53 +698,42 @@ LoadAndBootWindows(IN OperatingSystemItem* OperatingSystem,
     if (strrchr(BootPath, ')') == NULL)
     {
         /* Temporarily save the boot path */
-        strcpy(FileName, BootPath);
+        RtlStringCbCopyA(FileName, sizeof(FileName), BootPath);
 
         /* This is not a full path. Use the current (i.e. boot) device. */
         MachDiskGetBootPath(BootPath, sizeof(BootPath));
 
         /* Append a path separator if needed */
-        if (FileName[0] != '\\' && FileName[0] != '/')
-            strcat(BootPath, "\\");
+        if (*FileName != '\\' && *FileName != '/')
+            RtlStringCbCatA(BootPath, sizeof(BootPath), "\\");
 
         /* Append the remaining path */
-        strcat(BootPath, FileName);
+        RtlStringCbCatA(BootPath, sizeof(BootPath), FileName);
     }
 
     /* Append a backslash if needed */
-    if ((BootPath[0] == 0) || BootPath[strlen(BootPath) - 1] != '\\')
-        strcat(BootPath, "\\");
+    if (!*BootPath || BootPath[strlen(BootPath) - 1] != '\\')
+        RtlStringCbCatA(BootPath, sizeof(BootPath), "\\");
 
-    /* Read boot options */
-    BootOptions[0] = ANSI_NULL;
-    if (!HasSection || !IniReadSettingByName(SectionId, "Options", BootOptions, sizeof(BootOptions)))
-    {
-        /* Retrieve the options after the quoted title */
-        PCSTR p = SettingsValue;
-
-        /* Trim any leading whitespace and quotes */
-        while (*p == ' ' || *p == '\t' || *p == '"')
-            ++p;
-        /* Skip all the text up to the first last quote */
-        while (*p != ANSI_NULL && *p != '"')
-            ++p;
-        /* Trim any trailing whitespace and quotes */
-        while (*p == ' ' || *p == '\t' || *p == '"')
-            ++p;
-
-        strcpy(BootOptions, p);
-        TRACE("BootOptions: '%s'\n", BootOptions);
-    }
+    TRACE("BootPath: '%s'\n", BootPath);
+
+    /* Retrieve the boot options */
+    *BootOptions = ANSI_NULL;
+    ArgValue = GetArgumentValue(Argc, Argv, "Options");
+    if (ArgValue)
+        RtlStringCbCopyA(BootOptions, sizeof(BootOptions), ArgValue);
 
     /* Append boot-time options */
     AppendBootTimeOptions(BootOptions);
 
+    TRACE("BootOptions: '%s'\n", BootOptions);
+
     /* Check if a ramdisk file was given */
     File = strstr(BootOptions, "/RDPATH=");
     if (File)
     {
         /* Copy the file name and everything else after it */
-        strcpy(FileName, File + 8);
+        RtlStringCbCopyA(FileName, sizeof(FileName), File + 8);
 
         /* Null-terminate */
         *strstr(FileName, " ") = ANSI_NULL;
@@ -743,15 +742,13 @@ LoadAndBootWindows(IN OperatingSystemItem* OperatingSystem,
         if (!RamDiskLoadVirtualFile(FileName))
         {
             UiMessageBox("Failed to load RAM disk file %s", FileName);
-            return;
+            return ENOENT;
         }
     }
 
     /* Let user know we started loading */
     //UiDrawStatusText("Loading...");
 
-    TRACE("BootPath: '%s'\n", BootPath);
-
     /* Allocate and minimalist-initialize LPB */
     AllocateAndInitLPB(&LoaderBlock);
 
@@ -762,24 +759,24 @@ LoadAndBootWindows(IN OperatingSystemItem* OperatingSystem,
     TRACE("SYSTEM hive %s\n", (Success ? "loaded" : "not loaded"));
     /* Bail out if failure */
     if (!Success)
-        return;
+        return ENOEXEC;
 
     /* Load NLS data, OEM font, and prepare boot drivers list */
     Success = WinLdrScanSystemHive(LoaderBlock, BootPath);
     TRACE("SYSTEM hive %s\n", (Success ? "scanned" : "not scanned"));
     /* Bail out if failure */
     if (!Success)
-        return;
+        return ENOEXEC;
 
     /* Finish loading */
-    LoadAndBootWindowsCommon(OperatingSystemVersion,
-                             LoaderBlock,
-                             BootOptions,
-                             BootPath,
-                             FALSE);
+    return LoadAndBootWindowsCommon(OperatingSystemVersion,
+                                    LoaderBlock,
+                                    BootOptions,
+                                    BootPath,
+                                    FALSE);
 }
 
-VOID
+ARC_STATUS
 LoadAndBootWindowsCommon(
     USHORT OperatingSystemVersion,
     PLOADER_PARAMETER_BLOCK LoaderBlock,
@@ -820,7 +817,7 @@ LoadAndBootWindowsCommon(
     if (!Success)
     {
         UiMessageBox("Error loading NTOS core.");
-        return;
+        return ENOEXEC;
     }
 
     /* Load boot drivers */
@@ -875,6 +872,7 @@ LoadAndBootWindowsCommon(
 
     /* Pass control */
     (*KiSystemStartup)(LoaderBlockVA);
+    return ESUCCESS;
 }
 
 VOID
index 31ca33d..b5e43d0 100644 (file)
@@ -142,7 +142,7 @@ WinLdrpDumpBootDriver(PLOADER_PARAMETER_BLOCK LoaderBlock);
 VOID
 WinLdrpDumpArcDisks(PLOADER_PARAMETER_BLOCK LoaderBlock);
 
-VOID
+ARC_STATUS
 LoadAndBootWindowsCommon(
     USHORT OperatingSystemVersion,
     PLOADER_PARAMETER_BLOCK LoaderBlock,
index 967b414..a509e15 100644 (file)
 /* INCLUDES *******************************************************************/
 
 #include <freeldr.h>
+#include <debug.h>
+
+DBG_DEFAULT_CHANNEL(INIFILE);
 
-#define TAG_STRING  ' rtS'
 #define TAG_OS_ITEM 'tISO'
 
 /* FUNCTIONS ******************************************************************/
@@ -40,23 +42,68 @@ static PCSTR CopyString(PCSTR Source)
     return Dest;
 }
 
-OperatingSystemItem* InitOperatingSystemList(ULONG* OperatingSystemCountPointer)
+static ULONG
+GetDefaultOperatingSystem(
+    IN OperatingSystemItem* OperatingSystemList,
+    IN ULONG OperatingSystemCount)
 {
-    ULONG Idx;
-    CHAR SettingName[260];
-    CHAR SettingValue[260];
+    ULONG     DefaultOS = 0;
+    ULONG     i;
     ULONG_PTR SectionId;
+    PCSTR     DefaultOSName;
+    CHAR      DefaultOSText[80];
+
+    if (!IniOpenSection("FreeLoader", &SectionId))
+        return 0;
+
+    DefaultOSName = CmdLineGetDefaultOS();
+    if (DefaultOSName == NULL)
+    {
+        if (IniReadSettingByName(SectionId, "DefaultOS", DefaultOSText, sizeof(DefaultOSText)))
+        {
+            DefaultOSName = DefaultOSText;
+        }
+    }
+
+    if (DefaultOSName != NULL)
+    {
+        for (i = 0; i < OperatingSystemCount; ++i)
+        {
+            if (_stricmp(DefaultOSName, OperatingSystemList[i].SectionName) == 0)
+            {
+                DefaultOS = i;
+                break;
+            }
+        }
+    }
+
+    return DefaultOS;
+}
+
+OperatingSystemItem*
+InitOperatingSystemList(
+    OUT PULONG OperatingSystemCount,
+    OUT PULONG DefaultOperatingSystem)
+{
+    OperatingSystemItem* Items;
+    ULONG Count;
+    ULONG i;
+    ULONG_PTR OsSectionId, SectionId;
     PCHAR TitleStart, TitleEnd;
     PCSTR OsLoadOptions;
-    ULONG Count;
-    OperatingSystemItem* Items;
+    BOOLEAN HadSection;
+    BOOLEAN HadNoBootType;
+    CHAR SettingName[260];
+    CHAR SettingValue[260];
+    CHAR BootType[80];
+    CHAR TempBuffer[sizeof(SettingValue)/sizeof(CHAR)];
 
-    /* Open the [FreeLoader] section */
-    if (!IniOpenSection("Operating Systems", &SectionId))
+    /* Open the [Operating Systems] section */
+    if (!IniOpenSection("Operating Systems", &OsSectionId))
         return NULL;
 
-    /* Count number of operating systems in the section */
-    Count = IniGetNumSectionItems(SectionId);
+    /* Count the number of operating systems in the section */
+    Count = IniGetNumSectionItems(OsSectionId);
 
     /* Allocate memory to hold operating system lists */
     Items = FrLdrHeapAlloc(Count * sizeof(OperatingSystemItem), TAG_OS_ITEM);
@@ -64,33 +111,199 @@ OperatingSystemItem* InitOperatingSystemList(ULONG* OperatingSystemCountPointer)
         return NULL;
 
     /* Now loop through and read the operating system section and display names */
-    for (Idx = 0; Idx < Count; Idx++)
+    for (i = 0; i < Count; ++i)
     {
-        IniReadSettingByNumber(SectionId, Idx, SettingName, sizeof(SettingName), SettingValue, sizeof(SettingValue));
+        IniReadSettingByNumber(OsSectionId, i,
+                               SettingName, sizeof(SettingName),
+                               SettingValue, sizeof(SettingValue));
+        if (!*SettingName)
+        {
+            ERR("Invalid OS entry number %lu, skipping.\n", i);
+            continue;
+        }
 
-        /* Search start and end of the title */
-        OsLoadOptions = NULL;
+        /* Retrieve the start and end of the title */
         TitleStart = SettingValue;
-        while (*TitleStart == ' ' || *TitleStart == '"')
-            TitleStart++;
+        /* Trim any leading whitespace and quotes */
+        while (*TitleStart == ' ' || *TitleStart == '\t' || *TitleStart == '"')
+            ++TitleStart;
         TitleEnd = TitleStart;
-        if (*TitleEnd != ANSI_NULL)
-            TitleEnd++;
+        /* Go up to the first last quote */
         while (*TitleEnd != ANSI_NULL && *TitleEnd != '"')
-            TitleEnd++;
-        if (*TitleEnd != ANSI_NULL)
+            ++TitleEnd;
+
+        /* NULL-terminate the title */
+        if (*TitleEnd)
+            *TitleEnd++ = ANSI_NULL; // Skip the quote too.
+
+        /* Retrieve the options after the quoted title */
+        if (*TitleEnd)
+        {
+            /* Trim any trailing whitespace and quotes */
+            while (*TitleEnd == ' ' || *TitleEnd == '\t' || *TitleEnd == '"')
+                ++TitleEnd;
+        }
+        OsLoadOptions = (*TitleEnd ? TitleEnd : NULL);
+
+        // TRACE("\n"
+              // "SettingName   = '%s'\n"
+              // "TitleStart    = '%s'\n"
+              // "OsLoadOptions = '%s'\n",
+              // SettingName, TitleStart, OsLoadOptions);
+
+        /*
+         * Determine whether this is a legacy operating system entry of the form:
+         *
+         * [Operating Systems]
+         * ArcOsLoadPartition="LoadIdentifier" /List /of /Options
+         *
+         * and if so, convert it into a new operating system INI entry:
+         *
+         * [Operating Systems]
+         * SectionIdentifier="LoadIdentifier"
+         *
+         * [SectionIdentifier]
+         * BootType=...
+         * SystemPath=ArcOsLoadPartition
+         * Options=/List /of /Options
+         *
+         * The "BootType" value is heuristically determined from the form of
+         * the ArcOsLoadPartition: if this is an ARC path, the "BootType" value
+         * is "Windows", otherwise if this is a DOS path the "BootType" value
+         * is "BootSector". This ensures backwards-compatibility with NTLDR.
+         */
+
+        /* Try to open the operating system section in the .ini file */
+        HadSection = IniOpenSection(SettingName, &SectionId);
+        if (HadSection)
+        {
+            /* This is a new OS entry: try to read the boot type */
+            IniReadSettingByName(SectionId, "BootType", BootType, sizeof(BootType));
+        }
+        else
+        {
+            /* This is a legacy OS entry: no explicit BootType specified, we will infer one */
+            *BootType = ANSI_NULL;
+        }
+
+        /* Check whether we have got a BootType value; if not, try to infer one */
+        HadNoBootType = (*BootType == ANSI_NULL);
+        if (HadNoBootType)
+        {
+#ifdef _M_IX86
+            ULONG FileId;
+            if (ArcOpen((PSTR)SettingName, OpenReadOnly, &FileId) == ESUCCESS)
+            {
+                ArcClose(FileId);
+                strcpy(BootType, "BootSector");
+            }
+            else
+#endif
+            {
+                strcpy(BootType, "Windows");
+            }
+        }
+
+        /* This is a legacy OS entry: convert it into a new OS entry */
+        if (!HadSection)
         {
-            *TitleEnd = ANSI_NULL;
-            OsLoadOptions = TitleEnd + 1;
+            TIMEINFO* TimeInfo;
+
+            /* Save the system path from the original SettingName (overwritten below) */
+            RtlStringCbCopyA(TempBuffer, sizeof(TempBuffer), SettingName);
+
+            /* Generate a unique section name */
+            TimeInfo = ArcGetTime();
+            if (_stricmp(BootType, "BootSector") == 0)
+            {
+                RtlStringCbPrintfA(SettingName, sizeof(SettingName),
+                                   "BootSectorFile%u%u%u%u%u%u",
+                                   TimeInfo->Year, TimeInfo->Day, TimeInfo->Month,
+                                   TimeInfo->Hour, TimeInfo->Minute, TimeInfo->Second);
+            }
+            else if (_stricmp(BootType, "Windows") == 0)
+            {
+                RtlStringCbPrintfA(SettingName, sizeof(SettingName),
+                                   "Windows%u%u%u%u%u%u",
+                                   TimeInfo->Year, TimeInfo->Day, TimeInfo->Month,
+                                   TimeInfo->Hour, TimeInfo->Minute, TimeInfo->Second);
+            }
+            else
+            {
+                ASSERT(FALSE);
+            }
+
+            /* Add the section */
+            if (!IniAddSection(SettingName, &SectionId))
+            {
+                ERR("Could not convert legacy OS entry! Continuing...\n");
+                continue;
+            }
+
+            /* Add the system path */
+            if (_stricmp(BootType, "BootSector") == 0)
+            {
+                if (!IniAddSettingValueToSection(SectionId, "BootSectorFile", TempBuffer))
+                {
+                    ERR("Could not convert legacy OS entry! Continuing...\n");
+                    continue;
+                }
+            }
+            else if (_stricmp(BootType, "Windows") == 0)
+            {
+                if (!IniAddSettingValueToSection(SectionId, "SystemPath", TempBuffer))
+                {
+                    ERR("Could not convert legacy OS entry! Continuing...\n");
+                    continue;
+                }
+            }
+            else
+            {
+                ASSERT(FALSE);
+            }
+
+            /* Add the OS options */
+            if (OsLoadOptions && !IniAddSettingValueToSection(SectionId, "Options", OsLoadOptions))
+            {
+                ERR("Could not convert legacy OS entry! Continuing...\n");
+                continue;
+            }
+        }
+
+        /* Add or modify the BootType if needed */
+        if (HadNoBootType && !IniModifySettingValue(SectionId, "BootType", BootType))
+        {
+            ERR("Could not fixup the BootType entry for OS '%s', ignoring.\n", SettingName);
+        }
+
+        /*
+         * If this is a new OS entry, but some options were given appended to
+         * the OS entry item, append them instead to the "Options=" value.
+         */
+        if (HadSection && OsLoadOptions && *OsLoadOptions)
+        {
+            /* Read the original "Options=" value */
+            *TempBuffer = ANSI_NULL;
+            if (!IniReadSettingByName(SectionId, "Options", TempBuffer, sizeof(TempBuffer)))
+                TRACE("No 'Options' value found for OS '%s', ignoring.\n", SettingName);
+
+            /* Concatenate the options together */
+            RtlStringCbCatA(TempBuffer, sizeof(TempBuffer), " ");
+            RtlStringCbCatA(TempBuffer, sizeof(TempBuffer), OsLoadOptions);
+
+            /* Save them */
+            if (!IniModifySettingValue(SectionId, "Options", TempBuffer))
+                ERR("Could not modify the options for OS '%s', ignoring.\n", SettingName);
         }
 
-        /* Copy the system partition, identifier and options */
-        Items[Idx].SystemPartition = CopyString(SettingName);
-        Items[Idx].LoadIdentifier = CopyString(TitleStart);
-        Items[Idx].OsLoadOptions = CopyString(OsLoadOptions);
+        /* Copy the OS section name and identifier */
+        Items[i].SectionName = CopyString(SettingName);
+        Items[i].LoadIdentifier = CopyString(TitleStart);
+        // TRACE("We did Items[%lu]: SectionName = '%s', LoadIdentifier = '%s'\n", i, Items[i].SectionName, Items[i].LoadIdentifier);
     }
 
     /* Return success */
-    *OperatingSystemCountPointer = Count;
+    *OperatingSystemCount = Count;
+    *DefaultOperatingSystem = GetDefaultOperatingSystem(Items, Count);
     return Items;
 }
index a602700..b117cd3 100644 (file)
@@ -257,6 +257,14 @@ UiShowMessageBoxesInSection(IN PCSTR SectionName)
     return;
 }
 
+VOID
+UiShowMessageBoxesInArgv(
+    IN ULONG Argc,
+    IN PCHAR Argv[])
+{
+    return;
+}
+
 VOID
 UiTruncateStringEllipsis(IN PCHAR StringText,
                          IN ULONG MaxChars)
index 7acbdb3..98035ee 100644 (file)
@@ -430,6 +430,43 @@ VOID UiShowMessageBoxesInSection(PCSTR SectionName)
     }
 }
 
+VOID
+UiShowMessageBoxesInArgv(
+    IN ULONG Argc,
+    IN PCHAR Argv[])
+{
+    ULONG LastIndex;
+    PCSTR ArgValue;
+    PCHAR MessageBoxText;
+    ULONG MessageBoxTextSize;
+
+    /* Find all the message box settings and run them */
+    for (LastIndex = 0;
+         (ArgValue = GetNextArgumentValue(Argc, Argv, &LastIndex, "MessageBox")) != NULL;
+         ++LastIndex)
+    {
+        /* Get the real length of the MessageBox text */
+        MessageBoxTextSize = (strlen(ArgValue) + 1) * sizeof(CHAR);
+
+        /* Allocate enough memory to hold the text */
+        MessageBoxText = FrLdrTempAlloc(MessageBoxTextSize, TAG_UI_TEXT);
+        if (MessageBoxText)
+        {
+            /* Get the MessageBox text */
+            strcpy(MessageBoxText, ArgValue);
+
+            /* Fix it up */
+            UiEscapeString(MessageBoxText);
+
+            /* Display it */
+            UiMessageBox(MessageBoxText);
+
+            /* Free the memory */
+            FrLdrTempFree(MessageBoxText, TAG_UI_TEXT);
+        }
+    }
+}
+
 VOID UiEscapeString(PCHAR String)
 {
     ULONG    Idx;