[FREELDR] Code fixes and enhancements.
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Fri, 30 Aug 2019 22:49:37 +0000 (00:49 +0200)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Fri, 30 Aug 2019 23:42:46 +0000 (01:42 +0200)
CORE-9023

FIXES:
======

- Fix parsing of the multiboot options string.
  NOTE: They are not yet treated in a case-insensitive manner!

- Fix a bug in ArcOpen() so that it correctly skips the first path
  separator (after the adapter-controller-peripheral ARC descriptors).
  The path separator can be either a backslash or a slash (both are
  allowed according to the specs); they were also already handled
  correctly in other parts of the code.

- Fix DissectArcPath() so as to:
  * **OPTIONALLY** (and not mandatorily!) return the path part that follows
    the ARC adapter-controller-peripheral elements in the ARC path;

  * make it correctly handle the (yes, optional!!) partition() part in the
    ARC path, for the multi(x)disk(y)rdisk(z) cases.

ENHANCEMENTS:
=============

- Directly retrieve the default OS entry as we enumerate them and
  build their list (i.e. merge the GetDefaultOperatingSystem() helper
  within InitOperatingSystemList()).

- Directly use the opened 'FreeLoader' INI section via its ID in the
  different functions that need it.

- Make the custom-boot and linux loaders honour the boot options they are
  supposed to support (see FREELDR.INI documentation / template).
  This includes the 'BootDrive' and 'BootPartition' (alternatively the ARC
  'BootPath').
  This also allows them to take into account the user-specified choices in the
  FreeLdr custom-boot editors.

- Modify the FreeLdr custom-boot editors so as to correctly honour
  the  priorities of the boot options as specified in the FREELDR.INI
  documentation / template.

- Use stack trick (union of structs) to reduce stack usage in the
  FreeLdr custom-boot editors, because there are strings buffers that are
  used in an alternate manner.

- Extract out from the editors the LoadOperatingSystem() calls, and
  move it back into OptionMenuCustomBoot(), so that when this latter
  function is called there is no risk of having a stack almost full.

- When building the ARC-compatible argument vector for the loaders, add
  the mandatory "SystemPartition" path. This allows the loaders to NOT
  call the machine-specific MachDiskGetBootPath() later on (this data is
  indeed passed to them by the boot manager part of FreeLdr).

- Improve the FsOpenFile() helper so as to make it:
  * return an adequate ARC_STATUS instead of a mere uninformative BOOLEAN;
  * take open options, as well as a default path (optional) that would be
    prepended to the file name in case the latter is a relative one.

- Make RamDiskLoadVirtualFile() return an actual descriptive ARC_STATUS
  value, and make it take an optional default path (same usage as the one
  in FsOpenFile() ).
  + Remove useless NTAPI .

- UiInitialize() and TuiTextToColor(), TuiTextToFillStyle(): load or
  convert named settings into corresponding values using setting table and
  a tight for-loop, instead of duplicating 10x the same parameter reading
  logic.

- UiInitialize(): Open the "Display" INI section just once. Remove usage
  of DisplayModeText[] buffer.

- UiShowMessageBoxesInSection() and UiShowMessageBoxesInArgv(): reduce
  code indentation level.

ENHANCEMENTS for NT OS loader:
==============================

- Don't use MachDiskGetBootPath() but use instead the "SystemPartition"
  value passed via the ARC argument vector by the boot manager
  (+ validation checks). Use it as the "default path" when calling
  FsOpenFile() or loading the ramdisk.

- Honour the FreeLdr-specific "Hal=" and "Kernel=" options by converting
  them into NT standard "/HAL=" and "/KERNEL=" options in the boot
  command line.

  Note that if the latter ones are already present on the standard "Options="
  option line, they would take precedence over those passed via the separate
  "Hal=" and "Kernel=" FreeLdr-specific options.

  Also add some documentation links to Geoff Chappell's website about
  how the default HAL and KERNEL names are chosen depending on the
  detected underlying platform on which the NT OS loader is running.

30 files changed:
boot/freeldr/freeldr/arch/i386/drivemap.c
boot/freeldr/freeldr/arch/i386/hwdisk.c
boot/freeldr/freeldr/arcname.c
boot/freeldr/freeldr/bootmgr.c
boot/freeldr/freeldr/cmdline.c
boot/freeldr/freeldr/custom.c
boot/freeldr/freeldr/disk/ramdisk.c
boot/freeldr/freeldr/freeldr.c
boot/freeldr/freeldr/include/arch/i386/drivemap.h
boot/freeldr/freeldr/include/arcname.h
boot/freeldr/freeldr/include/cmdline.h
boot/freeldr/freeldr/include/custom.h
boot/freeldr/freeldr/include/debug.h
boot/freeldr/freeldr/include/fs.h
boot/freeldr/freeldr/include/linux.h
boot/freeldr/freeldr/include/oslist.h
boot/freeldr/freeldr/include/ramdisk.h
boot/freeldr/freeldr/include/ui.h
boot/freeldr/freeldr/lib/debug.c
boot/freeldr/freeldr/lib/fs/fs.c
boot/freeldr/freeldr/lib/peloader.c
boot/freeldr/freeldr/linuxboot.c
boot/freeldr/freeldr/miscboot.c
boot/freeldr/freeldr/ntldr/inffile.c
boot/freeldr/freeldr/ntldr/setupldr.c
boot/freeldr/freeldr/ntldr/winldr.c
boot/freeldr/freeldr/oslist.c
boot/freeldr/freeldr/ui/directui.c
boot/freeldr/freeldr/ui/tui.c
boot/freeldr/freeldr/ui/ui.c

index 2d38f34..1fc96c0 100644 (file)
@@ -18,8 +18,8 @@
  */
 
 #include <freeldr.h>
-#include <debug.h>
 
+#include <debug.h>
 DBG_DEFAULT_CHANNEL(DISK);
 
 #ifdef _M_IX86
@@ -92,24 +92,23 @@ UCHAR DriveMapGetBiosDriveNumber(PCSTR DeviceName)
 
 #ifdef _M_IX86
 
-VOID DriveMapMapDrivesInSection(PCSTR SectionName)
+VOID
+DriveMapMapDrivesInSection(
+    IN ULONG_PTR SectionId)
 {
     CHAR           SettingName[80];
     CHAR           SettingValue[80];
     CHAR           Drive1[80];
     CHAR           Drive2[80];
-    ULONG_PTR      SectionId;
     ULONG          SectionItemCount;
     ULONG          Index;
     ULONG          Index2;
     DRIVE_MAP_LIST DriveMapList;
 
-    RtlZeroMemory(&DriveMapList, sizeof(DRIVE_MAP_LIST));
-
-    if (!IniOpenSection(SectionName, &SectionId))
-    {
+    if (SectionId == 0)
         return;
-    }
+
+    RtlZeroMemory(&DriveMapList, sizeof(DRIVE_MAP_LIST));
 
     // Get the number of items in this section
     SectionItemCount = IniGetNumSectionItems(SectionId);
@@ -125,7 +124,7 @@ VOID DriveMapMapDrivesInSection(PCSTR SectionName)
                 // Make sure we haven't exceeded the drive map max count
                 if (DriveMapList.DriveMapCount >= 4)
                 {
-                    UiMessageBox("Max DriveMap count exceeded in section [%s]:\n\n%s=%s", SectionName, SettingName, SettingValue);
+                    UiMessageBox("Max DriveMap count exceeded in section [%s]:\n\n%s=%s", ((PINI_SECTION)SectionId)->SectionName, SettingName, SettingValue);
                     continue;
                 }
 
@@ -150,7 +149,7 @@ VOID DriveMapMapDrivesInSection(PCSTR SectionName)
                 // Make sure we got good values before we add them to the map
                 if (!DriveMapIsValidDriveString(Drive1) || !DriveMapIsValidDriveString(Drive2))
                 {
-                    UiMessageBox("Error in DriveMap setting in section [%s]:\n\n%s=%s", SectionName, SettingName, SettingValue);
+                    UiMessageBox("Error in DriveMap setting in section [%s]:\n\n%s=%s", ((PINI_SECTION)SectionId)->SectionName, SettingName, SettingValue);
                     continue;
                 }
 
index fde0d8a..d3601ec 100644 (file)
@@ -22,7 +22,6 @@
 #include <freeldr.h>
 
 #include <debug.h>
-
 DBG_DEFAULT_CHANNEL(HWDETECT);
 
 /*
@@ -80,7 +79,6 @@ DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
     ULONGLONG SectorOffset = 0;
     ULONGLONG SectorCount = 0;
     PARTITION_TABLE_ENTRY PartitionTableEntry;
-    CHAR FileName[1];
 
     if (DiskReadBufferSize == 0)
     {
@@ -89,7 +87,7 @@ DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
         return ENOMEM;
     }
 
-    if (!DissectArcPath(Path, FileName, &DriveNumber, &DrivePartition))
+    if (!DissectArcPath(Path, NULL, &DriveNumber, &DrivePartition))
         return EINVAL;
 
     if (DrivePartition == 0xff)
index 8e8cf1e..26ba703 100644 (file)
 
 #include <freeldr.h>
 
-BOOLEAN DissectArcPath(CHAR *ArcPath, CHAR *BootPath, UCHAR* BootDrive, ULONG* BootPartition)
+BOOLEAN
+DissectArcPath(
+    IN  PCSTR ArcPath,
+    OUT PCSTR* Path OPTIONAL,
+    OUT PUCHAR DriveNumber,
+    OUT PULONG PartitionNumber)
 {
-    char *p;
+    PCCH p;
 
     /* Detect ramdisk path */
     if (_strnicmp(ArcPath, "ramdisk(0)", 10) == 0)
     {
         /* Magic value for ramdisks */
-        *BootDrive = 0x49;
-        *BootPartition = 1;
-
-        /* Get the path */
-        p = ArcPath + 11;
-        strcpy(BootPath, p);
+        *DriveNumber = 0x49;
+        *PartitionNumber = 1;
+
+        /* Get the path (optional) */
+        if (Path)
+        {
+            p = ArcPath + 11;
+            *Path = p;
+        }
         return TRUE;
     }
 
+    /* NOTE: We are currently limited when handling multi()disk() paths!! */
     if (_strnicmp(ArcPath, "multi(0)disk(0)", 15) != 0)
         return FALSE;
 
@@ -49,12 +58,12 @@ BOOLEAN DissectArcPath(CHAR *ArcPath, CHAR *BootPath, UCHAR* BootDrive, ULONG* B
          *  multi(0)disk(0)fdisk(x)\path
          */
         p = p + 6;
-        *BootDrive = atoi(p);
+        *DriveNumber = atoi(p);
         p = strchr(p, ')');
         if (p == NULL)
             return FALSE;
-        p++;
-        *BootPartition = 0;
+        ++p;
+        *PartitionNumber = 0;
     }
     else if (_strnicmp(p, "cdrom(", 6) == 0)
     {
@@ -63,37 +72,48 @@ BOOLEAN DissectArcPath(CHAR *ArcPath, CHAR *BootPath, UCHAR* BootDrive, ULONG* B
          *  multi(0)disk(0)cdrom(x)\path
          */
         p = p + 6;
-        *BootDrive = atoi(p) + 0x80;
+        *DriveNumber = atoi(p) + 0x80;
         p = strchr(p, ')');
         if (p == NULL)
             return FALSE;
-        p++;
-        *BootPartition = 0xff;
+        ++p;
+        *PartitionNumber = 0xff;
     }
     else if (_strnicmp(p, "rdisk(", 6) == 0)
     {
         /*
          * Hard disk path:
-         *  multi(0)disk(0)rdisk(x)partition(y)\path
+         *  multi(0)disk(0)rdisk(x)[partition(y)][\path]
          */
         p = p + 6;
-        *BootDrive = atoi(p) + 0x80;
-        p = strchr(p, ')');
-        if ((p == NULL) || (_strnicmp(p, ")partition(", 11) != 0))
-            return FALSE;
-        p = p + 11;
-        *BootPartition = atoi(p);
+        *DriveNumber = atoi(p) + 0x80;
         p = strchr(p, ')');
         if (p == NULL)
             return FALSE;
-        p++;
+        ++p;
+        /* The partition is optional */
+        if (_strnicmp(p, "partition(", 10) == 0)
+        {
+            p = p + 10;
+            *PartitionNumber = atoi(p);
+            p = strchr(p, ')');
+            if (p == NULL)
+                return FALSE;
+            ++p;
+        }
+        else
+        {
+            *PartitionNumber = 0;
+        }
     }
     else
     {
         return FALSE;
     }
 
-    strcpy(BootPath, p);
+    /* Get the path (optional) */
+    if (Path)
+        *Path = p;
 
     return TRUE;
 }
@@ -101,12 +121,12 @@ BOOLEAN DissectArcPath(CHAR *ArcPath, CHAR *BootPath, UCHAR* BootDrive, ULONG* B
 /* PathSyntax: scsi() = 0, multi() = 1, ramdisk() = 2 */
 BOOLEAN
 DissectArcPath2(
-    IN CHAR* ArcPath,
-    OUT ULONG* x,
-    OUT ULONG* y,
-    OUT ULONG* z,
-    OUT ULONG* Partition,
-    OUT ULONG *PathSyntax)
+    IN  PCSTR ArcPath,
+    OUT PULONG x,
+    OUT PULONG y,
+    OUT PULONG z,
+    OUT PULONG Partition,
+    OUT PULONG PathSyntax)
 {
     /* Detect ramdisk() */
     if (_strnicmp(ArcPath, "ramdisk(0)", 10) == 0)
index 8c97eea..7cf5feb 100644 (file)
@@ -20,8 +20,8 @@
 /* INCLUDES *******************************************************************/
 
 #include <freeldr.h>
-#include <debug.h>
 
+#include <debug.h>
 DBG_DEFAULT_CHANNEL(INIFILE);
 
 /* GLOBALS ********************************************************************/
@@ -29,20 +29,20 @@ DBG_DEFAULT_CHANNEL(INIFILE);
 typedef
 VOID
 (*EDIT_OS_ENTRY_PROC)(
-    IN ULONG_PTR SectionId OPTIONAL);
+    IN OUT OperatingSystemItem* OperatingSystem);
 
 static VOID
 EditCustomBootReactOSSetup(
-    IN ULONG_PTR SectionId OPTIONAL)
+    IN OUT OperatingSystemItem* OperatingSystem)
 {
-    EditCustomBootReactOS(SectionId, TRUE);
+    EditCustomBootReactOS(OperatingSystem, TRUE);
 }
 
 static VOID
 EditCustomBootNTOS(
-    IN ULONG_PTR SectionId OPTIONAL)
+    IN OUT OperatingSystemItem* OperatingSystem)
 {
-    EditCustomBootReactOS(SectionId, FALSE);
+    EditCustomBootReactOS(OperatingSystem, FALSE);
 }
 
 static const struct
@@ -68,6 +68,12 @@ static const struct
 
 /* FUNCTIONS ******************************************************************/
 
+/*
+ * This function converts the list of key=value options in the given operating
+ * system section into an ARC-compatible argument vector, providing in addition
+ * the extra mandatory Software Loading Environment Variables, following the
+ * ARC specification.
+ */
 PCHAR*
 BuildArgvForOsLoader(
     IN PCSTR LoadIdentifier,
@@ -81,30 +87,34 @@ BuildArgvForOsLoader(
     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.
-     */
+    CHAR BootPath[MAX_PATH];
 
     *pArgc = 0;
 
+    ASSERT(SectionId != 0);
+
     /* Validate the LoadIdentifier (to make tests simpler later) */
     if (LoadIdentifier && !*LoadIdentifier)
         LoadIdentifier = NULL;
 
+    /* Get the boot path we're booting from (the "SystemPartition") */
+    MachDiskGetBootPath(BootPath, sizeof(BootPath));
+
     /* 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;
+    /*
+     * The argument vector contains the program name, the SystemPartition,
+     * the LoadIdentifier (optional), and the items in the OS section.
+     */
+    Argc = 2 + (LoadIdentifier ? 1 : 0) + Count;
 
     /* Calculate the total size needed for the string buffer of the argument vector */
     Size = 0;
     /* i == 0: Program name */
-    /* i == 1: LoadIdentifier */
+    /* i == 1: SystemPartition : from where FreeLdr has been started */
+    Size += (strlen("SystemPartition=") + strlen(BootPath) + 1) * sizeof(CHAR);
+    /* i == 2: LoadIdentifier  : ASCII string that may be used to associate an identifier with a set of load parameters */
     if (LoadIdentifier)
     {
         Size += (strlen("LoadIdentifier=") + strlen(LoadIdentifier) + 1) * sizeof(CHAR);
@@ -126,7 +136,15 @@ BuildArgvForOsLoader(
     Args = Argv;
     /* i == 0: Program name */
     *Args++ = NULL;
-    /* i == 1: LoadIdentifier */
+    /* i == 1: SystemPartition */
+    {
+        strcpy(SettingName, "SystemPartition=");
+        strcat(SettingName, BootPath);
+
+        *Args++ = SettingName;
+        SettingName += (strlen(SettingName) + 1);
+    }
+    /* i == 2: LoadIdentifier */
     if (LoadIdentifier)
     {
         strcpy(SettingName, "LoadIdentifier=");
@@ -162,19 +180,14 @@ BuildArgvForOsLoader(
 
 VOID LoadOperatingSystem(IN OperatingSystemItem* OperatingSystem)
 {
-    ULONG_PTR SectionId;
-    PCSTR SectionName = OperatingSystem->SectionName;
+    ULONG_PTR SectionId = OperatingSystem->SectionId;
     ULONG i;
     ULONG Argc;
     PCHAR* Argv;
     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;
-    }
+    /* The operating system section has been opened by InitOperatingSystemList() */
+    ASSERT(SectionId != 0);
 
     /* Try to read the boot type */
     *BootType = ANSI_NULL;
@@ -185,7 +198,7 @@ VOID LoadOperatingSystem(IN OperatingSystemItem* OperatingSystem)
 
 #ifdef _M_IX86
     /* Install the drive mapper according to this section drive mappings */
-    DriveMapMapDrivesInSection(SectionName);
+    DriveMapMapDrivesInSection(SectionId);
 #endif
 
     /* Loop through the OS loading method table and find a suitable OS to boot */
@@ -208,17 +221,12 @@ VOID LoadOperatingSystem(IN OperatingSystemItem* OperatingSystem)
 
 VOID EditOperatingSystemEntry(IN OperatingSystemItem* OperatingSystem)
 {
-    ULONG_PTR SectionId;
-    PCSTR SectionName = OperatingSystem->SectionName;
+    ULONG_PTR SectionId = OperatingSystem->SectionId;
     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;
-    }
+    /* The operating system section has been opened by InitOperatingSystemList() */
+    ASSERT(SectionId != 0);
 
     /* Try to read the boot type */
     *BootType = ANSI_NULL;
@@ -232,7 +240,7 @@ VOID EditOperatingSystemEntry(IN OperatingSystemItem* OperatingSystem)
     {
         if (_stricmp(BootType, OSLoadingMethods[i].BootType) == 0)
         {
-            OSLoadingMethods[i].EditOsEntry(SectionId);
+            OSLoadingMethods[i].EditOsEntry(OperatingSystem);
             return;
         }
     }
@@ -240,23 +248,24 @@ VOID EditOperatingSystemEntry(IN OperatingSystemItem* OperatingSystem)
 
 #endif // HAS_OPTION_MENU_EDIT_CMDLINE
 
-LONG GetTimeOut(VOID)
+static LONG
+GetTimeOut(
+    IN ULONG_PTR FrLdrSectionId)
 {
-    CHAR    TimeOutText[20];
-    LONG        TimeOut;
-    ULONG_PTR    SectionId;
+    LONG TimeOut = -1;
+    CHAR TimeOutText[20];
 
     TimeOut = CmdLineGetTimeOut();
     if (TimeOut >= 0)
         return TimeOut;
 
-    if (!IniOpenSection("FreeLoader", &SectionId))
-        return -1;
+    TimeOut = -1;
 
-    if (IniReadSettingByName(SectionId, "TimeOut", TimeOutText, sizeof(TimeOutText)))
+    if ((FrLdrSectionId != 0) &&
+        IniReadSettingByName(FrLdrSectionId, "TimeOut", TimeOutText, sizeof(TimeOutText)))
+    {
         TimeOut = atoi(TimeOutText);
-    else
-        TimeOut = -1;
+    }
 
     return TimeOut;
 }
@@ -316,16 +325,18 @@ VOID RunLoader(VOID)
         return;
     }
 
-    /* Debugger main initialization */
-    DebugInit(TRUE);
-
+    /* Open the [FreeLoader] section */
     if (!IniOpenSection("FreeLoader", &SectionId))
     {
         UiMessageBoxCritical("Section [FreeLoader] not found in freeldr.ini.");
         return;
     }
 
-    TimeOut = GetTimeOut();
+    /* Debugger main initialization */
+    DebugInit(SectionId);
+
+    /* Retrieve the default timeout */
+    TimeOut = GetTimeOut(SectionId);
 
     /* UI main initialization */
     if (!UiInitialize(TRUE))
@@ -334,7 +345,8 @@ VOID RunLoader(VOID)
         return;
     }
 
-    OperatingSystemList = InitOperatingSystemList(&OperatingSystemCount,
+    OperatingSystemList = InitOperatingSystemList(SectionId,
+                                                  &OperatingSystemCount,
                                                   &DefaultOperatingSystem);
     if (!OperatingSystemList)
     {
@@ -358,7 +370,7 @@ VOID RunLoader(VOID)
     }
 
     /* Find all the message box settings and run them */
-    UiShowMessageBoxesInSection("FreeLoader");
+    UiShowMessageBoxesInSection(SectionId);
 
     for (;;)
     {
index 001c946..19fba95 100644 (file)
@@ -14,9 +14,9 @@
 
 typedef struct tagCMDLINEINFO
 {
-    PCCH DebugString;
-    PCCH DefaultOperatingSystem;
-    LONG TimeOut;
+    PCSTR DebugString;
+    PCSTR DefaultOperatingSystem;
+    LONG  TimeOut;
 } CMDLINEINFO, *PCMDLINEINFO;
 
 CCHAR DebugString[256];
@@ -26,7 +26,7 @@ CMDLINEINFO CmdLineInfo;
 /* FUNCTIONS ******************************************************************/
 
 VOID
-CmdLineParse(IN PCCH CmdLine)
+CmdLineParse(IN PCSTR CmdLine)
 {
     PCHAR End, Setting;
     ULONG_PTR Length, Offset = 0;
@@ -46,16 +46,12 @@ CmdLineParse(IN PCCH CmdLine)
     if (Setting)
     {
         /* Check if there are more command-line parameters following */
-        Setting += sizeof("debug=") + sizeof(ANSI_NULL);
+        Setting += sizeof("debug=") - sizeof(ANSI_NULL);
         End = strstr(Setting, " ");
-        if (End)
-            Length = End - Setting;
-        else
-            Length = sizeof(DebugString);
+        Length = (End ? (End - Setting) : strlen(Setting));
 
         /* Copy the debug string and upcase it */
-        strncpy(DebugString, Setting, Length);
-        DebugString[Length - 1] = ANSI_NULL;
+        RtlStringCbCopyNA(DebugString, sizeof(DebugString), Setting, Length);
         _strupr(DebugString);
 
         /* Replace all separators ';' by spaces */
@@ -71,63 +67,65 @@ CmdLineParse(IN PCCH CmdLine)
 
     /* Get timeout */
     Setting = strstr(CmdLine, "timeout=");
-    if (Setting) CmdLineInfo.TimeOut = atoi(Setting +
-                                            sizeof("timeout=") +
-                                            sizeof(ANSI_NULL));
+    if (Setting)
+    {
+        CmdLineInfo.TimeOut = atoi(Setting +
+                                   sizeof("timeout=") - sizeof(ANSI_NULL));
+    }
 
     /* Get default OS */
     Setting = strstr(CmdLine, "defaultos=");
     if (Setting)
     {
         /* Check if there are more command-line parameters following */
-        Setting += sizeof("defaultos=") + sizeof(ANSI_NULL);
+        Setting += sizeof("defaultos=") - sizeof(ANSI_NULL);
         End = strstr(Setting, " ");
-        if (End)
-            Length = End - Setting;
-        else
-            Length = sizeof(DefaultOs);
+        Length = (End ? (End - Setting) : strlen(Setting));
 
         /* Copy the default OS */
-        strncpy(DefaultOs, Setting, Length);
-        DefaultOs[Length - 1] = ANSI_NULL;
+        RtlStringCbCopyNA(DefaultOs, sizeof(DefaultOs), Setting, Length);
         CmdLineInfo.DefaultOperatingSystem = DefaultOs;
     }
 
     /* Get ramdisk base address */
     Setting = strstr(CmdLine, "rdbase=");
-    if (Setting) gRamDiskBase = (PVOID)(ULONG_PTR)strtoull(Setting +
-                                               sizeof("rdbase=") -
-                                               sizeof(ANSI_NULL),
-                                               NULL,
-                                               0);
+    if (Setting)
+    {
+        gRamDiskBase =
+            (PVOID)(ULONG_PTR)strtoull(Setting +
+                                       sizeof("rdbase=") - sizeof(ANSI_NULL),
+                                       NULL, 0);
+    }
 
     /* Get ramdisk size */
     Setting = strstr(CmdLine, "rdsize=");
-    if (Setting) gRamDiskSize = strtoul(Setting +
-                                        sizeof("rdsize=") -
-                                        sizeof(ANSI_NULL),
-                                        NULL,
-                                        0);
+    if (Setting)
+    {
+        gRamDiskSize = strtoul(Setting +
+                               sizeof("rdsize=") - sizeof(ANSI_NULL),
+                               NULL, 0);
+    }
 
     /* Get ramdisk offset */
     Setting = strstr(CmdLine, "rdoffset=");
-    if (Setting) Offset = strtoul(Setting +
-                                  sizeof("rdoffset=") -
-                                  sizeof(ANSI_NULL),
-                                  NULL,
-                                  0);
+    if (Setting)
+    {
+        Offset = strtoul(Setting +
+                         sizeof("rdoffset=") - sizeof(ANSI_NULL),
+                         NULL, 0);
+    }
 
     /* Fix it up */
     gRamDiskBase = (PVOID)((ULONG_PTR)gRamDiskBase + Offset);
 }
 
-PCCH
+PCSTR
 CmdLineGetDebugString(VOID)
 {
     return CmdLineInfo.DebugString;
 }
 
-PCCH
+PCSTR
 CmdLineGetDefaultOS(VOID)
 {
     return CmdLineInfo.DefaultOperatingSystem;
index dfeba30..e0afc7b 100644 (file)
@@ -34,6 +34,7 @@ const CHAR LinuxCommandLinePrompt[] = "Enter the Linux kernel command line.\n\nE
 
 const CHAR BootDrivePrompt[] = "Enter the boot drive.\n\nExamples:\nfd0 - first floppy drive\nhd0 - first hard drive\nhd1 - second hard drive\ncd0 - first CD-ROM drive.\n\nBIOS drive numbers may also be used:\n0 - first floppy drive\n0x80 - first hard drive\n0x81 - second hard drive";
 const CHAR BootPartitionPrompt[] = "Enter the boot partition.\n\nEnter 0 for the active (bootable) partition.";
+const CHAR ARCPathPrompt[] = "Enter the boot ARC path.\n\nExamples:\nmulti(0)disk(0)rdisk(0)partition(1)\nmulti(0)disk(0)fdisk(0)";
 const CHAR ReactOSSystemPathPrompt[] = "Enter the path to your ReactOS system directory.\n\nExamples:\n\\REACTOS\n\\ROS";
 const CHAR ReactOSOptionsPrompt[] = "Enter the options you want passed to the kernel.\n\nExamples:\n/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200\n/FASTDETECT /SOS /NOGUIBOOT\n/BASEVIDEO /MAXMEM=64\n/KERNEL=NTKRNLMP.EXE /HAL=HALMPS.DLL";
 const CHAR CustomBootPrompt[] = "Press ENTER to boot your custom boot setup.";
@@ -55,6 +56,7 @@ VOID OptionMenuCustomBoot(VOID)
         "ReactOS Setup"
         };
     ULONG SelectedMenuItem;
+    OperatingSystemItem OperatingSystem;
 
     if (!UiDisplayMenu("Please choose a boot method:", NULL,
                        FALSE,
@@ -69,65 +71,111 @@ VOID OptionMenuCustomBoot(VOID)
         return;
     }
 
+    /* Initialize a new custom OS entry */
+    OperatingSystem.SectionId = 0;
     switch (SelectedMenuItem)
     {
 #ifdef _M_IX86
         case 0: // Disk
-            EditCustomBootDisk(0);
+            EditCustomBootDisk(&OperatingSystem);
             break;
         case 1: // Partition
-            EditCustomBootPartition(0);
+            EditCustomBootPartition(&OperatingSystem);
             break;
         case 2: // Boot Sector File
-            EditCustomBootSectorFile(0);
+            EditCustomBootSectorFile(&OperatingSystem);
             break;
         case 3: // Linux
-            EditCustomBootLinux(0);
+            EditCustomBootLinux(&OperatingSystem);
             break;
         case 4: // ReactOS
-            EditCustomBootReactOS(0, FALSE);
+            EditCustomBootReactOS(&OperatingSystem, FALSE);
             break;
         case 5: // ReactOS Setup
-            EditCustomBootReactOS(0, TRUE);
+            EditCustomBootReactOS(&OperatingSystem, TRUE);
             break;
 #else
         case 0: // ReactOS
-            EditCustomBootReactOS(0, FALSE);
+            EditCustomBootReactOS(&OperatingSystem, FALSE);
             break;
         case 1: // ReactOS Setup
-            EditCustomBootReactOS(0, TRUE);
+            EditCustomBootReactOS(&OperatingSystem, TRUE);
             break;
 #endif
     }
+
+    /* And boot it */
+    if (OperatingSystem.SectionId != 0)
+    {
+        UiMessageBox(CustomBootPrompt);
+        LoadOperatingSystem(&OperatingSystem);
+    }
 }
 
 #endif // HAS_OPTION_MENU_CUSTOM_BOOT
 
 #ifdef _M_IX86
 
-VOID EditCustomBootDisk(IN ULONG_PTR SectionId OPTIONAL)
+VOID
+EditCustomBootDisk(
+    IN OUT OperatingSystemItem* OperatingSystem)
 {
     TIMEINFO* TimeInfo;
-    OperatingSystemItem OperatingSystem;
+    ULONG_PTR SectionId = OperatingSystem->SectionId;
     CHAR SectionName[100];
-    CHAR BootDriveString[20];
+    /* The following is a trick for saving some stack space */
+    union
+    {
+        struct
+        {
+            CHAR Guard1;
+            CHAR Drive[20];
+            CHAR Guard2;
+        };
+        CHAR ArcPath[200];
+    } BootStrings;
 
     RtlZeroMemory(SectionName, sizeof(SectionName));
-    RtlZeroMemory(BootDriveString, sizeof(BootDriveString));
+    RtlZeroMemory(&BootStrings, sizeof(BootStrings));
 
     if (SectionId != 0)
     {
         /* Load the settings */
-        IniReadSettingByName(SectionId, "BootDrive", BootDriveString, sizeof(BootDriveString));
+
+        /* Check whether we have a "BootPath" value (takes precedence over "BootDrive") */
+        *BootStrings.ArcPath = ANSI_NULL;
+        IniReadSettingByName(SectionId, "BootPath", BootStrings.ArcPath, sizeof(BootStrings.ArcPath));
+        if (!*BootStrings.ArcPath)
+        {
+            /* We don't, retrieve the boot drive value instead */
+            IniReadSettingByName(SectionId, "BootDrive", BootStrings.Drive, sizeof(BootStrings.Drive));
+        }
     }
 
-    if (!UiEditBox(BootDrivePrompt, BootDriveString, sizeof(BootDriveString)))
-        return;
+    if (!*BootStrings.ArcPath)
+    {
+        if (!UiEditBox(BootDrivePrompt, BootStrings.Drive, sizeof(BootStrings.Drive)))
+            return;
+    }
+    if (!*BootStrings.Drive)
+    {
+        if (!UiEditBox(ARCPathPrompt, BootStrings.ArcPath, sizeof(BootStrings.ArcPath)))
+            return;
+    }
 
     /* Modify the settings values and return if we were in edit mode */
     if (SectionId != 0)
     {
-        IniModifySettingValue(SectionId, "BootDrive", BootDriveString);
+        /* Modify the BootPath if we have one */
+        if (*BootStrings.ArcPath)
+        {
+            IniModifySettingValue(SectionId, "BootPath", BootStrings.ArcPath);
+        }
+        else if (*BootStrings.Drive)
+        {
+            /* Otherwise, modify the BootDrive */
+            IniModifySettingValue(SectionId, "BootDrive", BootStrings.Drive);
+        }
         return;
     }
 
@@ -146,47 +194,95 @@ VOID EditCustomBootDisk(IN ULONG_PTR SectionId OPTIONAL)
     if (!IniAddSettingValueToSection(SectionId, "BootType", "Drive"))
         return;
 
-    /* Add the BootDrive */
-    if (!IniAddSettingValueToSection(SectionId, "BootDrive", BootDriveString))
-        return;
-
-    UiMessageBox(CustomBootPrompt);
+    /* Add the BootPath if we have one */
+    if (*BootStrings.ArcPath)
+    {
+        if (!IniAddSettingValueToSection(SectionId, "BootPath", BootStrings.ArcPath))
+            return;
+    }
+    else if (*BootStrings.Drive)
+    {
+        /* Otherwise, add the BootDrive */
+        if (!IniAddSettingValueToSection(SectionId, "BootDrive", BootStrings.Drive))
+            return;
+    }
 
-    OperatingSystem.SectionName = SectionName;
-    OperatingSystem.LoadIdentifier = NULL;
-    LoadOperatingSystem(&OperatingSystem);
+    OperatingSystem->SectionId = SectionId;
+    OperatingSystem->LoadIdentifier = NULL;
 }
 
-VOID EditCustomBootPartition(IN ULONG_PTR SectionId OPTIONAL)
+VOID
+EditCustomBootPartition(
+    IN OUT OperatingSystemItem* OperatingSystem)
 {
     TIMEINFO* TimeInfo;
-    OperatingSystemItem OperatingSystem;
+    ULONG_PTR SectionId = OperatingSystem->SectionId;
     CHAR SectionName[100];
-    CHAR BootDriveString[20];
-    CHAR BootPartitionString[20];
+    /* The following is a trick for saving some stack space */
+    union
+    {
+        struct
+        {
+            CHAR Guard1;
+            CHAR Drive[20];
+            CHAR Partition[20];
+            CHAR Guard2;
+        };
+        CHAR ArcPath[200];
+    } BootStrings;
 
     RtlZeroMemory(SectionName, sizeof(SectionName));
-    RtlZeroMemory(BootDriveString, sizeof(BootDriveString));
-    RtlZeroMemory(BootPartitionString, sizeof(BootPartitionString));
+    RtlZeroMemory(&BootStrings, sizeof(BootStrings));
 
     if (SectionId != 0)
     {
         /* Load the settings */
-        IniReadSettingByName(SectionId, "BootDrive", BootDriveString, sizeof(BootDriveString));
-        IniReadSettingByName(SectionId, "BootPartition", BootPartitionString, sizeof(BootPartitionString));
+
+        /*
+         * Check whether we have a "BootPath" value (takes precedence
+         * over both "BootDrive" and "BootPartition").
+         */
+        *BootStrings.ArcPath = ANSI_NULL;
+        IniReadSettingByName(SectionId, "BootPath", BootStrings.ArcPath, sizeof(BootStrings.ArcPath));
+        if (!*BootStrings.ArcPath)
+        {
+            /* We don't, retrieve the boot drive and partition values instead */
+            IniReadSettingByName(SectionId, "BootDrive", BootStrings.Drive, sizeof(BootStrings.Drive));
+            IniReadSettingByName(SectionId, "BootPartition", BootStrings.Partition, sizeof(BootStrings.Partition));
+        }
     }
 
-    if (!UiEditBox(BootDrivePrompt, BootDriveString, sizeof(BootDriveString)))
-        return;
+    if (!*BootStrings.ArcPath)
+    {
+        if (!UiEditBox(BootDrivePrompt, BootStrings.Drive, sizeof(BootStrings.Drive)))
+            return;
 
-    if (!UiEditBox(BootPartitionPrompt, BootPartitionString, sizeof(BootPartitionString)))
-        return;
+        if (*BootStrings.Drive)
+        {
+            if (!UiEditBox(BootPartitionPrompt, BootStrings.Partition, sizeof(BootStrings.Partition)))
+                return;
+        }
+    }
+    if (!*BootStrings.Drive)
+    {
+        if (!UiEditBox(ARCPathPrompt, BootStrings.ArcPath, sizeof(BootStrings.ArcPath)))
+            return;
+    }
 
     /* Modify the settings values and return if we were in edit mode */
     if (SectionId != 0)
     {
-        IniModifySettingValue(SectionId, "BootDrive", BootDriveString);
-        IniModifySettingValue(SectionId, "BootPartition", BootPartitionString);
+        /* Modify the BootPath if we have one */
+        if (*BootStrings.ArcPath)
+        {
+            IniModifySettingValue(SectionId, "BootPath", BootStrings.ArcPath);
+        }
+        else if (*BootStrings.Drive)
+        {
+            /* Otherwise, modify the BootDrive and BootPartition */
+            IniModifySettingValue(SectionId, "BootDrive", BootStrings.Drive);
+            IniModifySettingValue(SectionId, "BootPartition", BootStrings.Partition);
+        }
         return;
     }
 
@@ -205,48 +301,87 @@ VOID EditCustomBootPartition(IN ULONG_PTR SectionId OPTIONAL)
     if (!IniAddSettingValueToSection(SectionId, "BootType", "Partition"))
         return;
 
-    /* Add the BootDrive */
-    if (!IniAddSettingValueToSection(SectionId, "BootDrive", BootDriveString))
-        return;
-
-    /* Add the BootPartition */
-    if (!IniAddSettingValueToSection(SectionId, "BootPartition", BootPartitionString))
-        return;
+    /* Add the BootPath if we have one */
+    if (*BootStrings.ArcPath)
+    {
+        if (!IniAddSettingValueToSection(SectionId, "BootPath", BootStrings.ArcPath))
+            return;
+    }
+    else if (*BootStrings.Drive)
+    {
+        /* Otherwise, add the BootDrive and BootPartition */
+        if (!IniAddSettingValueToSection(SectionId, "BootDrive", BootStrings.Drive))
+            return;
 
-    UiMessageBox(CustomBootPrompt);
+        if (!IniAddSettingValueToSection(SectionId, "BootPartition", BootStrings.Partition))
+            return;
+    }
 
-    OperatingSystem.SectionName = SectionName;
-    OperatingSystem.LoadIdentifier = NULL;
-    LoadOperatingSystem(&OperatingSystem);
+    OperatingSystem->SectionId = SectionId;
+    OperatingSystem->LoadIdentifier = NULL;
 }
 
-VOID EditCustomBootSectorFile(IN ULONG_PTR SectionId OPTIONAL)
+VOID
+EditCustomBootSectorFile(
+    IN OUT OperatingSystemItem* OperatingSystem)
 {
     TIMEINFO* TimeInfo;
-    OperatingSystemItem OperatingSystem;
+    ULONG_PTR SectionId = OperatingSystem->SectionId;
     CHAR SectionName[100];
-    CHAR BootDriveString[20];
-    CHAR BootPartitionString[20];
+    /* The following is a trick for saving some stack space */
+    union
+    {
+        struct
+        {
+            CHAR Guard1;
+            CHAR Drive[20];
+            CHAR Partition[20];
+            CHAR Guard2;
+        };
+        CHAR ArcPath[200];
+    } BootStrings;
     CHAR BootSectorFileString[200];
 
     RtlZeroMemory(SectionName, sizeof(SectionName));
-    RtlZeroMemory(BootDriveString, sizeof(BootDriveString));
-    RtlZeroMemory(BootPartitionString, sizeof(BootPartitionString));
+    RtlZeroMemory(&BootStrings, sizeof(BootStrings));
     RtlZeroMemory(BootSectorFileString, sizeof(BootSectorFileString));
 
     if (SectionId != 0)
     {
         /* Load the settings */
-        IniReadSettingByName(SectionId, "BootDrive", BootDriveString, sizeof(BootDriveString));
-        IniReadSettingByName(SectionId, "BootPartition", BootPartitionString, sizeof(BootPartitionString));
+
+        /*
+         * Check whether we have a "BootPath" value (takes precedence
+         * over both "BootDrive" and "BootPartition").
+         */
+        *BootStrings.ArcPath = ANSI_NULL;
+        IniReadSettingByName(SectionId, "BootPath", BootStrings.ArcPath, sizeof(BootStrings.ArcPath));
+        if (!*BootStrings.ArcPath)
+        {
+            /* We don't, retrieve the boot drive and partition values instead */
+            IniReadSettingByName(SectionId, "BootDrive", BootStrings.Drive, sizeof(BootStrings.Drive));
+            IniReadSettingByName(SectionId, "BootPartition", BootStrings.Partition, sizeof(BootStrings.Partition));
+        }
+
         IniReadSettingByName(SectionId, "BootSectorFile", BootSectorFileString, sizeof(BootSectorFileString));
     }
 
-    if (!UiEditBox(BootDrivePrompt, BootDriveString, sizeof(BootDriveString)))
-        return;
+    if (!*BootStrings.ArcPath)
+    {
+        if (!UiEditBox(BootDrivePrompt, BootStrings.Drive, sizeof(BootStrings.Drive)))
+            return;
 
-    if (!UiEditBox(BootPartitionPrompt, BootPartitionString, sizeof(BootPartitionString)))
-        return;
+        if (*BootStrings.Drive)
+        {
+            if (!UiEditBox(BootPartitionPrompt, BootStrings.Partition, sizeof(BootStrings.Partition)))
+                return;
+        }
+    }
+    if (!*BootStrings.Drive)
+    {
+        if (!UiEditBox(ARCPathPrompt, BootStrings.ArcPath, sizeof(BootStrings.ArcPath)))
+            return;
+    }
 
     if (!UiEditBox(BootSectorFilePrompt, BootSectorFileString, sizeof(BootSectorFileString)))
         return;
@@ -254,8 +389,28 @@ VOID EditCustomBootSectorFile(IN ULONG_PTR SectionId OPTIONAL)
     /* Modify the settings values and return if we were in edit mode */
     if (SectionId != 0)
     {
-        IniModifySettingValue(SectionId, "BootDrive", BootDriveString);
-        IniModifySettingValue(SectionId, "BootPartition", BootPartitionString);
+        /* Modify the BootPath if we have one */
+        if (*BootStrings.ArcPath)
+        {
+            IniModifySettingValue(SectionId, "BootPath", BootStrings.ArcPath);
+        }
+        else if (*BootStrings.Drive)
+        {
+            /* Otherwise, modify the BootDrive and BootPartition */
+            IniModifySettingValue(SectionId, "BootDrive", BootStrings.Drive);
+            IniModifySettingValue(SectionId, "BootPartition", BootStrings.Partition);
+        }
+        else
+        {
+            /*
+             * Otherwise, zero out all values: BootSectorFile will be
+             * relative to the default system partition.
+             */
+            IniModifySettingValue(SectionId, "BootPath", "");
+            IniModifySettingValue(SectionId, "BootDrive", "");
+            IniModifySettingValue(SectionId, "BootPartition", "");
+        }
+
         IniModifySettingValue(SectionId, "BootSectorFile", BootSectorFileString);
         return;
     }
@@ -275,39 +430,55 @@ VOID EditCustomBootSectorFile(IN ULONG_PTR SectionId OPTIONAL)
     if (!IniAddSettingValueToSection(SectionId, "BootType", "BootSector"))
         return;
 
-    /* Add the BootDrive */
-    if (!IniAddSettingValueToSection(SectionId, "BootDrive", BootDriveString))
-        return;
+    /* Add the BootPath if we have one */
+    if (*BootStrings.ArcPath)
+    {
+        if (!IniAddSettingValueToSection(SectionId, "BootPath", BootStrings.ArcPath))
+            return;
+    }
+    else if (*BootStrings.Drive)
+    {
+        /* Otherwise, add the BootDrive and BootPartition */
+        if (!IniAddSettingValueToSection(SectionId, "BootDrive", BootStrings.Drive))
+            return;
 
-    /* Add the BootPartition */
-    if (!IniAddSettingValueToSection(SectionId, "BootPartition", BootPartitionString))
-        return;
+        if (!IniAddSettingValueToSection(SectionId, "BootPartition", BootStrings.Partition))
+            return;
+    }
 
     /* Add the BootSectorFile */
     if (!IniAddSettingValueToSection(SectionId, "BootSectorFile", BootSectorFileString))
         return;
 
-    UiMessageBox(CustomBootPrompt);
-
-    OperatingSystem.SectionName = SectionName;
-    OperatingSystem.LoadIdentifier = NULL;
-    LoadOperatingSystem(&OperatingSystem);
+    OperatingSystem->SectionId = SectionId;
+    OperatingSystem->LoadIdentifier = NULL;
 }
 
-VOID EditCustomBootLinux(IN ULONG_PTR SectionId OPTIONAL)
+VOID
+EditCustomBootLinux(
+    IN OUT OperatingSystemItem* OperatingSystem)
 {
     TIMEINFO* TimeInfo;
-    OperatingSystemItem OperatingSystem;
+    ULONG_PTR SectionId = OperatingSystem->SectionId;
     CHAR SectionName[100];
-    CHAR BootDriveString[20];
-    CHAR BootPartitionString[20];
+    /* The following is a trick for saving some stack space */
+    union
+    {
+        struct
+        {
+            CHAR Guard1;
+            CHAR Drive[20];
+            CHAR Partition[20];
+            CHAR Guard2;
+        };
+        CHAR ArcPath[200];
+    } BootStrings;
     CHAR LinuxKernelString[200];
     CHAR LinuxInitrdString[200];
     CHAR LinuxCommandLineString[200];
 
     RtlZeroMemory(SectionName, sizeof(SectionName));
-    RtlZeroMemory(BootDriveString, sizeof(BootDriveString));
-    RtlZeroMemory(BootPartitionString, sizeof(BootPartitionString));
+    RtlZeroMemory(&BootStrings, sizeof(BootStrings));
     RtlZeroMemory(LinuxKernelString, sizeof(LinuxKernelString));
     RtlZeroMemory(LinuxInitrdString, sizeof(LinuxInitrdString));
     RtlZeroMemory(LinuxCommandLineString, sizeof(LinuxCommandLineString));
@@ -315,18 +486,41 @@ VOID EditCustomBootLinux(IN ULONG_PTR SectionId OPTIONAL)
     if (SectionId != 0)
     {
         /* Load the settings */
-        IniReadSettingByName(SectionId, "BootDrive", BootDriveString, sizeof(BootDriveString));
-        IniReadSettingByName(SectionId, "BootPartition", BootPartitionString, sizeof(BootPartitionString));
+
+        /*
+         * Check whether we have a "BootPath" value (takes precedence
+         * over both "BootDrive" and "BootPartition").
+         */
+        *BootStrings.ArcPath = ANSI_NULL;
+        IniReadSettingByName(SectionId, "BootPath", BootStrings.ArcPath, sizeof(BootStrings.ArcPath));
+        if (!*BootStrings.ArcPath)
+        {
+            /* We don't, retrieve the boot drive and partition values instead */
+            IniReadSettingByName(SectionId, "BootDrive", BootStrings.Drive, sizeof(BootStrings.Drive));
+            IniReadSettingByName(SectionId, "BootPartition", BootStrings.Partition, sizeof(BootStrings.Partition));
+        }
+
         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 (!*BootStrings.ArcPath)
+    {
+        if (!UiEditBox(BootDrivePrompt, BootStrings.Drive, sizeof(BootStrings.Drive)))
+            return;
 
-    if (!UiEditBox(BootPartitionPrompt, BootPartitionString, sizeof(BootPartitionString)))
-        return;
+        if (*BootStrings.Drive)
+        {
+            if (!UiEditBox(BootPartitionPrompt, BootStrings.Partition, sizeof(BootStrings.Partition)))
+                return;
+        }
+    }
+    if (!*BootStrings.Drive)
+    {
+        if (!UiEditBox(ARCPathPrompt, BootStrings.ArcPath, sizeof(BootStrings.ArcPath)))
+            return;
+    }
 
     if (!UiEditBox(LinuxKernelPrompt, LinuxKernelString, sizeof(LinuxKernelString)))
         return;
@@ -340,8 +534,28 @@ VOID EditCustomBootLinux(IN ULONG_PTR SectionId OPTIONAL)
     /* Modify the settings values and return if we were in edit mode */
     if (SectionId != 0)
     {
-        IniModifySettingValue(SectionId, "BootDrive", BootDriveString);
-        IniModifySettingValue(SectionId, "BootPartition", BootPartitionString);
+        /* Modify the BootPath if we have one */
+        if (*BootStrings.ArcPath)
+        {
+            IniModifySettingValue(SectionId, "BootPath", BootStrings.ArcPath);
+        }
+        else if (*BootStrings.Drive)
+        {
+            /* Otherwise, modify the BootDrive and BootPartition */
+            IniModifySettingValue(SectionId, "BootDrive", BootStrings.Drive);
+            IniModifySettingValue(SectionId, "BootPartition", BootStrings.Partition);
+        }
+        else
+        {
+            /*
+             * Otherwise, zero out all values: BootSectorFile will be
+             * relative to the default system partition.
+             */
+            IniModifySettingValue(SectionId, "BootPath", "");
+            IniModifySettingValue(SectionId, "BootDrive", "");
+            IniModifySettingValue(SectionId, "BootPartition", "");
+        }
+
         IniModifySettingValue(SectionId, "Kernel", LinuxKernelString);
         IniModifySettingValue(SectionId, "Initrd", LinuxInitrdString);
         IniModifySettingValue(SectionId, "CommandLine", LinuxCommandLineString);
@@ -363,13 +577,21 @@ VOID EditCustomBootLinux(IN ULONG_PTR SectionId OPTIONAL)
     if (!IniAddSettingValueToSection(SectionId, "BootType", "Linux"))
         return;
 
-    /* Add the BootDrive */
-    if (!IniAddSettingValueToSection(SectionId, "BootDrive", BootDriveString))
-        return;
+    /* Add the BootPath if we have one */
+    if (*BootStrings.ArcPath)
+    {
+        if (!IniAddSettingValueToSection(SectionId, "BootPath", BootStrings.ArcPath))
+            return;
+    }
+    else if (*BootStrings.Drive)
+    {
+        /* Otherwise, add the BootDrive and BootPartition */
+        if (!IniAddSettingValueToSection(SectionId, "BootDrive", BootStrings.Drive))
+            return;
 
-    /* Add the BootPartition */
-    if (!IniAddSettingValueToSection(SectionId, "BootPartition", BootPartitionString))
-        return;
+        if (!IniAddSettingValueToSection(SectionId, "BootPartition", BootStrings.Partition))
+            return;
+    }
 
     /* Add the Kernel */
     if (!IniAddSettingValueToSection(SectionId, "Kernel", LinuxKernelString))
@@ -386,22 +608,19 @@ VOID EditCustomBootLinux(IN ULONG_PTR SectionId OPTIONAL)
     if (!IniAddSettingValueToSection(SectionId, "CommandLine", LinuxCommandLineString))
         return;
 
-    UiMessageBox(CustomBootPrompt);
-
-    OperatingSystem.SectionName = SectionName;
-    OperatingSystem.LoadIdentifier = "Custom Linux Setup";
-    LoadOperatingSystem(&OperatingSystem);
+    OperatingSystem->SectionId = SectionId;
+    OperatingSystem->LoadIdentifier = "Custom Linux Setup";
 }
 
 #endif // _M_IX86
 
 VOID
 EditCustomBootReactOS(
-    IN ULONG_PTR SectionId OPTIONAL,
+    IN OUT OperatingSystemItem* OperatingSystem,
     IN BOOLEAN IsSetup)
 {
     TIMEINFO* TimeInfo;
-    OperatingSystemItem OperatingSystem;
+    ULONG_PTR SectionId = OperatingSystem->SectionId;
     CHAR SectionName[100];
     CHAR BootDriveString[20];
     CHAR BootPartitionString[20];
@@ -419,7 +638,6 @@ EditCustomBootReactOS(
     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));
     }
@@ -478,11 +696,8 @@ EditCustomBootReactOS(
     if (!IniAddSettingValueToSection(SectionId, "Options", ReactOSOptions))
         return;
 
-    UiMessageBox(CustomBootPrompt);
-
-    OperatingSystem.SectionName = SectionName;
-    OperatingSystem.LoadIdentifier = NULL;
-    LoadOperatingSystem(&OperatingSystem);
+    OperatingSystem->SectionId = SectionId;
+    OperatingSystem->LoadIdentifier = NULL;
 }
 
 #ifdef HAS_OPTION_MENU_REBOOT
index c9a0963..905c409 100644 (file)
@@ -109,62 +109,52 @@ static const DEVVTBL RamDiskVtbl = {
 };
 
 VOID
-NTAPI
 RamDiskInitialize(VOID)
 {
     /* Register the RAMDISK device */
     FsRegisterDevice("ramdisk(0)", &RamDiskVtbl);
 }
 
-BOOLEAN
-NTAPI
-RamDiskLoadVirtualFile(IN PCHAR FileName)
+ARC_STATUS
+RamDiskLoadVirtualFile(
+    IN PCSTR FileName,
+    IN PCSTR DefaultPath OPTIONAL)
 {
+    ARC_STATUS Status;
     ULONG RamFileId;
     ULONG TotalRead, ChunkSize, Count;
     PCHAR MsgBuffer = "Loading RamDisk...";
     ULONG PercentPerChunk, Percent;
     FILEINFORMATION Information;
     LARGE_INTEGER Position;
-    ARC_STATUS Status;
 
-    //
-    // Display progress
-    //
+    /* Display progress */
     UiDrawBackdrop();
     UiDrawProgressBarCenter(1, 100, MsgBuffer);
 
-    //
-    // Try opening the ramdisk file
-    //
-    RamFileId = FsOpenFile(FileName);
-    if (!RamFileId)
-        return FALSE;
+    /* Try opening the ramdisk file */
+    Status = FsOpenFile(FileName, DefaultPath, OpenReadOnly, &RamFileId);
+    if (Status != ESUCCESS)
+        return Status;
 
-    //
-    // Get the file size
-    //
+    /* Get the file size */
     Status = ArcGetFileInformation(RamFileId, &Information);
     if (Status != ESUCCESS)
     {
         ArcClose(RamFileId);
-        return FALSE;
+        return Status;
     }
 
-    //
-    // For now, limit RAM disks to 4GB
-    //
+    /* For now, limit RAM disks to 4GB */
     if (Information.EndingAddress.HighPart != 0)
     {
         UiMessageBox("RAM disk too big.");
         ArcClose(RamFileId);
-        return FALSE;
+        return ENOMEM;
     }
     gRamDiskSize = Information.EndingAddress.LowPart;
 
-    //
-    // Allocate memory for it
-    //
+    /* Allocate memory for it */
     ChunkSize = 8 * 1024 * 1024;
     if (gRamDiskSize < ChunkSize)
         Percent = PercentPerChunk = 0;
@@ -175,34 +165,26 @@ RamDiskLoadVirtualFile(IN PCHAR FileName)
     {
         UiMessageBox("Failed to allocate memory for RAM disk.");
         ArcClose(RamFileId);
-        return FALSE;
+        return ENOMEM;
     }
 
-    //
-    // Read it in chunks
-    //
+    /*
+     * Read it in chunks
+     */
     for (TotalRead = 0; TotalRead < gRamDiskSize; TotalRead += ChunkSize)
     {
-        //
-        // Check if we're at the last chunk
-        //
+        /* Check if we're at the last chunk */
         if ((gRamDiskSize - TotalRead) < ChunkSize)
         {
-            //
-            // Only need the actual data required
-            //
+            /* Only need the actual data required */
             ChunkSize = gRamDiskSize - TotalRead;
         }
 
-        //
-        // Draw progress
-        //
+        /* Draw progress */
         UiDrawProgressBarCenter(Percent, 100, MsgBuffer);
         Percent += PercentPerChunk;
 
-        //
-        // Copy the contents
-        //
+        /* Copy the contents */
         Position.HighPart = 0;
         Position.LowPart = TotalRead;
         Status = ArcSeek(RamFileId, &Position, SeekAbsolute);
@@ -214,17 +196,15 @@ RamDiskLoadVirtualFile(IN PCHAR FileName)
                              &Count);
         }
 
-        //
-        // Check for success
-        //
-        if (Status != ESUCCESS || Count != ChunkSize)
+        /* Check for success */
+        if ((Status != ESUCCESS) || (Count != ChunkSize))
         {
             MmFreeMemory(gRamDiskBase);
             gRamDiskBase = NULL;
             gRamDiskSize = 0;
             ArcClose(RamFileId);
             UiMessageBox("Failed to read RAM disk.");
-            return FALSE;
+            return ((Status != ESUCCESS) ? Status : EIO);
         }
     }
 
@@ -233,5 +213,5 @@ RamDiskLoadVirtualFile(IN PCHAR FileName)
     /* Setup the RAMDISK device */
     RamDiskInitialize();
 
-    return TRUE;
+    return ESUCCESS;
 }
index b1f7296..f967573 100644 (file)
@@ -20,8 +20,8 @@
 /* INCLUDES *******************************************************************/
 
 #include <freeldr.h>
-#include <debug.h>
 
+#include <debug.h>
 DBG_DEFAULT_CHANNEL(WARNING);
 
 /* FUNCTIONS ******************************************************************/
@@ -31,7 +31,7 @@ VOID __cdecl BootMain(IN PCCH CmdLine)
     CmdLineParse(CmdLine);
 
     /* Debugger pre-initialization */
-    DebugInit(FALSE);
+    DebugInit(0);
 
     TRACE("BootMain() called.\n");
 
index 8c1d108..0737dca 100644 (file)
@@ -36,7 +36,10 @@ UCHAR   DriveMapGetBiosDriveNumber(PCSTR DeviceName);   // Returns a BIOS drive
 
 #ifdef _M_IX86
 
-VOID DriveMapMapDrivesInSection(PCSTR SectionName);
+VOID
+DriveMapMapDrivesInSection(
+    IN ULONG_PTR SectionId);
+
 VOID DriveMapInstallInt13Handler(PDRIVE_MAP_LIST DriveMap); // Installs the int 13h handler for the drive mapper
 VOID DriveMapRemoveInt13Handler(VOID);                      // Removes a previously installed int 13h drive map handler
 
index a5df320..1b30f46 100644 (file)
 // ARC Path Functions
 //
 ///////////////////////////////////////////////////////////////////////////////////////
+
+BOOLEAN
+DissectArcPath(
+    IN  PCSTR ArcPath,
+    OUT PCSTR* Path OPTIONAL,
+    OUT PUCHAR DriveNumber,
+    OUT PULONG PartitionNumber);
+
 BOOLEAN
 DissectArcPath2(
-    IN CHAR* ArcPath,
-    OUT ULONG* x,
-    OUT ULONG* y,
-    OUT ULONG* z,
-    OUT ULONG* Partition,
-    OUT ULONG *PathSyntax);
-BOOLEAN DissectArcPath(CHAR *ArcPath, CHAR *BootPath, UCHAR* BootDrive, ULONG* BootPartition);
+    IN  PCSTR ArcPath,
+    OUT PULONG x,
+    OUT PULONG y,
+    OUT PULONG z,
+    OUT PULONG Partition,
+    OUT PULONG PathSyntax);
+
 VOID ConstructArcPath(PCHAR ArcPath, PCHAR SystemFolder, UCHAR Disk, ULONG Partition);
+
 #if 0
 UCHAR ConvertArcNameToBiosDriveNumber(PCHAR ArcPath);
 #endif
index 3ab13c2..47a733b 100644 (file)
 
 #pragma once
 
-VOID CmdLineParse(IN PCCH CmdLine);
+VOID  CmdLineParse(IN PCSTR CmdLine);
 
-PCCH CmdLineGetDebugString(VOID);
-PCCH CmdLineGetDefaultOS(VOID);
-LONG CmdLineGetTimeOut(VOID);
+PCSTR CmdLineGetDebugString(VOID);
+PCSTR CmdLineGetDefaultOS(VOID);
+LONG  CmdLineGetTimeOut(VOID);
 
 /* EOF */
index b38241f..57164b8 100644 (file)
 #define HAS_OPTION_MENU_CUSTOM_BOOT
 #define HAS_OPTION_MENU_REBOOT
 
+#ifdef HAS_OPTION_MENU_CUSTOM_BOOT
+VOID OptionMenuCustomBoot(VOID);
+#endif
+
 #ifdef _M_IX86
 
-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);
+VOID
+EditCustomBootDisk(
+    IN OUT OperatingSystemItem* OperatingSystem);
 
-#endif // _M_IX86
+VOID
+EditCustomBootPartition(
+    IN OUT OperatingSystemItem* OperatingSystem);
 
-#ifdef HAS_OPTION_MENU_CUSTOM_BOOT
-VOID OptionMenuCustomBoot(VOID);
-#endif
+VOID
+EditCustomBootSectorFile(
+    IN OUT OperatingSystemItem* OperatingSystem);
+
+VOID
+EditCustomBootLinux(
+    IN OUT OperatingSystemItem* OperatingSystem);
+
+#endif // _M_IX86
 
 VOID
 EditCustomBootReactOS(
-    IN ULONG_PTR SectionId OPTIONAL,
+    IN OUT OperatingSystemItem* OperatingSystem,
     IN BOOLEAN IsSetup);
 
 #ifdef HAS_OPTION_MENU_REBOOT
index 9cf62eb..1862220 100644 (file)
@@ -40,7 +40,7 @@
 
 #if DBG && !defined(_M_ARM)
 
-    VOID    DebugInit(BOOLEAN MainInit);
+    VOID    DebugInit(IN ULONG_PTR FrLdrSectionId);
     ULONG   DbgPrint(const char *Format, ...);
     VOID    DbgPrint2(ULONG Mask, ULONG Level, const char *File, ULONG Line, char *Format, ...);
     VOID    DebugDumpBuffer(ULONG Mask, PVOID Buffer, ULONG Length);
@@ -113,7 +113,7 @@ void    MEMORY_WRITE_BREAKPOINT4(unsigned long addr);
 
     #define UNIMPLEMENTED
 
-    #define DebugInit(init)
+    #define DebugInit(FrLdrSectionId)
     #define BugCheck(fmt, ...)
     #define DbgDumpBuffer(mask, buf, len)
     #define DbgParseDebugChannels(val)
index 2d77465..68489c9 100644 (file)
@@ -40,7 +40,14 @@ ARC_STATUS ArcSeek(ULONG FileId, LARGE_INTEGER* Position, SEEKMODE SeekMode);
 ARC_STATUS ArcGetFileInformation(ULONG FileId, FILEINFORMATION* Information);
 
 VOID  FileSystemError(PCSTR ErrorString);
-ULONG FsOpenFile(PCSTR FileName);
+
+ARC_STATUS
+FsOpenFile(
+    IN PCSTR FileName,
+    IN PCSTR DefaultPath OPTIONAL,
+    IN OPENMODE OpenMode,
+    OUT PULONG FileId);
+
 ULONG FsGetNumPathParts(PCSTR Path);
 VOID  FsGetFirstNameFromPath(PCHAR Buffer, PCSTR Path);
 
index 72043f8..d0b3510 100644 (file)
@@ -137,17 +137,6 @@ LoadAndBootLinux(
     IN PCHAR Argv[],
     IN PCHAR Envp[]);
 
-BOOLEAN
-LinuxParseIniSection(
-    IN ULONG Argc,
-    IN PCHAR Argv[]);
-
-BOOLEAN LinuxReadBootSector(ULONG LinuxKernelFile);
-BOOLEAN LinuxReadSetupSector(ULONG LinuxKernelFile);
-BOOLEAN LinuxReadKernel(ULONG LinuxKernelFile);
-BOOLEAN LinuxCheckKernelVersion(VOID);
-BOOLEAN LinuxReadInitrd(ULONG LinuxInitrdFile);
-
 #endif // _M_IX86
 
 #endif // defined __LINUX_H
index 1676900..b4bf62f 100644 (file)
 
 typedef struct tagOperatingSystemItem
 {
-    PCSTR SectionName;
+    ULONG_PTR SectionId;
     PCSTR LoadIdentifier;
 } OperatingSystemItem;
 
 OperatingSystemItem*
 InitOperatingSystemList(
+    IN ULONG_PTR FrLdrSectionId,
     OUT PULONG OperatingSystemCount,
     OUT PULONG DefaultOperatingSystem);
index 2e56a37..a9dd199 100644 (file)
 //
 // Ramdisk Routines
 //
-BOOLEAN
-NTAPI
+ARC_STATUS
 RamDiskLoadVirtualFile(
-    IN PCHAR FileName
-);
+    IN PCSTR FileName,
+    IN PCSTR DefaultPath OPTIONAL);
 
 VOID
-NTAPI
-RamDiskInitialize(
-    VOID
-);
+RamDiskInitialize(VOID);
 
 extern PVOID gRamDiskBase;
 extern ULONG gRamDiskSize;
index f773ae8..f5abbe6 100644 (file)
@@ -71,7 +71,10 @@ VOID    UiMessageBoxCritical(PCSTR MessageText);                // Displays a me
 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
+// Displays all the message boxes in a given section.
+VOID
+UiShowMessageBoxesInSection(
+    IN ULONG_PTR SectionId);
 
 VOID
 UiShowMessageBoxesInArgv(
index 1f01f86..24c074d 100644 (file)
@@ -49,7 +49,7 @@ ULONG PortIrq  = 0; // Not used at the moment.
 
 BOOLEAN DebugStartOfLine = TRUE;
 
-VOID DebugInit(BOOLEAN MainInit)
+VOID DebugInit(IN ULONG_PTR FrLdrSectionId)
 {
     PCHAR CommandLine, PortString, BaudString, IrqString;
     ULONG Value;
@@ -78,7 +78,7 @@ VOID DebugInit(BOOLEAN MainInit)
 #endif
 
     /* Check for pre- or main initialization phase */
-    if (!MainInit)
+    if (FrLdrSectionId == 0)
     {
         /* Pre-initialization phase: use the FreeLdr command-line debugging string */
         CommandLine = (PCHAR)CmdLineGetDebugString();
@@ -92,14 +92,10 @@ VOID DebugInit(BOOLEAN MainInit)
     else
     {
         /* Main initialization phase: use the FreeLdr INI debugging string */
-
-        ULONG_PTR SectionId;
-
-        if (!IniOpenSection("FreeLoader", &SectionId))
-            return;
-
-        if (!IniReadSettingByName(SectionId, "Debug", DebugString, sizeof(DebugString)))
+        if (!IniReadSettingByName(FrLdrSectionId, "Debug", DebugString, sizeof(DebugString)))
+        {
             return;
+        }
     }
 
     /* Get the Command Line */
index 4000b44..9aa7ca1 100644 (file)
@@ -23,7 +23,6 @@
 #include <freeldr.h>
 
 #include <debug.h>
-
 DBG_DEFAULT_CHANNEL(FILESYSTEM);
 
 /* GLOBALS ********************************************************************/
@@ -199,8 +198,8 @@ ARC_STATUS ArcOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
     if (i == MAX_FDS)
         return EMFILE;
 
-    /* Skip leading backslash, if any */
-    if (*FileName == '\\')
+    /* Skip leading path separator, if any */
+    if (*FileName == '\\' || *FileName == '/')
         FileName++;
 
     /* Open the file */
@@ -263,47 +262,62 @@ VOID FileSystemError(PCSTR ErrorString)
     UiMessageBox(ErrorString);
 }
 
-ULONG FsOpenFile(PCSTR FileName)
+ARC_STATUS
+FsOpenFile(
+    IN PCSTR FileName,
+    IN PCSTR DefaultPath OPTIONAL,
+    IN OPENMODE OpenMode,
+    OUT PULONG FileId)
 {
+    NTSTATUS Status;
+    SIZE_T cchPathLen;
     CHAR FullPath[MAX_PATH] = "";
-    ULONG FileId;
-    ARC_STATUS Status;
 
-    //
-    // Print status message
-    //
-    TRACE("Opening file '%s'...\n", FileName);
-
-    //
-    // Check whether FileName is a full path
-    // and if not, create a full file name.
-    //
-    // See ArcOpen: Search last ')', which delimits device and path.
-    //
+    /*
+     * Check whether FileName is a full path and if not, create a full
+     * file name using the user-provided default path (if present).
+     *
+     * See ArcOpen(): Search last ')', which delimits device and path.
+     */
     if (strrchr(FileName, ')') == NULL)
     {
-        /* This is not a full path. Use the current (i.e. boot) device. */
-        MachDiskGetBootPath(FullPath, sizeof(FullPath));
+        /* This is not a full path: prepend the user-provided default path */
+        if (DefaultPath)
+        {
+            Status = RtlStringCbCopyA(FullPath, sizeof(FullPath), DefaultPath);
+            if (!NT_SUCCESS(Status))
+                return ENAMETOOLONG;
+        }
 
         /* Append a path separator if needed */
-        if (FileName[0] != '\\' && FileName[0] != '/')
-            strcat(FullPath, "\\");
-    }
-    // Append (or just copy) the remaining file name.
-    strcat(FullPath, FileName);
 
-    //
-    // Open the file
-    //
-    Status = ArcOpen(FullPath, OpenReadOnly, &FileId);
+        cchPathLen = min(sizeof(FullPath)/sizeof(CHAR), strlen(FullPath));
+        if (cchPathLen >= sizeof(FullPath)/sizeof(CHAR))
+            return ENAMETOOLONG;
 
-    //
-    // Check for success
-    //
-    if (Status == ESUCCESS)
-        return FileId;
-    else
-        return 0;
+        if ((*FileName != '\\' && *FileName != '/') &&
+            cchPathLen > 0 && (FullPath[cchPathLen-1] != '\\' && FullPath[cchPathLen-1] != '/'))
+        {
+            /* FileName does not start with '\' and FullPath does not end with '\' */
+            Status = RtlStringCbCatA(FullPath, sizeof(FullPath), "\\");
+            if (!NT_SUCCESS(Status))
+                return ENAMETOOLONG;
+        }
+        else if ((*FileName == '\\' || *FileName == '/') &&
+                 cchPathLen > 0 && (FullPath[cchPathLen-1] == '\\' || FullPath[cchPathLen-1] == '/'))
+        {
+            /* FileName starts with '\' and FullPath ends with '\' */
+            while (*FileName == '\\' || *FileName == '/')
+                ++FileName; // Skip any backslash
+        }
+    }
+    /* Append (or just copy) the remaining file name */
+    Status = RtlStringCbCatA(FullPath, sizeof(FullPath), FileName);
+    if (!NT_SUCCESS(Status))
+        return ENAMETOOLONG;
+
+    /* Open the file */
+    return ArcOpen(FullPath, OpenMode, FileId);
 }
 
 /*
@@ -422,8 +436,4 @@ VOID FsInit(VOID)
         FileData[i].DeviceId = (ULONG)-1;
 
     InitializeListHead(&DeviceListHead);
-
-    // FIXME: Retrieve the current boot device with MachDiskGetBootPath
-    // and store it somewhere in order to not call again and again this
-    // function.
 }
index 0d4cb3c..c306375 100644 (file)
@@ -286,7 +286,7 @@ WinLdrLoadImage(IN PCHAR FileName,
     TRACE("WinLdrLoadImage(%s, %ld, *)\n", FileName, MemoryType);
 
     /* Open the image file */
-    Status = ArcOpen(FileName, OpenReadOnly, &FileId);
+    Status = ArcOpen((PSTR)FileName, OpenReadOnly, &FileId);
     if (Status != ESUCCESS)
     {
         WARN("ArcOpen(FileName: '%s') failed. Status: %u\n", FileName, Status);
index 9f0a53e..0779466 100644 (file)
@@ -29,8 +29,8 @@
 /* INCLUDES *******************************************************************/
 
 #include <freeldr.h>
-#include <debug.h>
 
+#include <debug.h>
 DBG_DEFAULT_CHANNEL(LINUX);
 
 /* GLOBALS ********************************************************************/
@@ -50,11 +50,16 @@ ULONG   LinuxCommandLineSize = 0;
 PVOID   LinuxKernelLoadAddress = NULL;
 PVOID   LinuxInitrdLoadAddress = NULL;
 CHAR    LinuxBootDescription[80];
-PCSTR   LinuxBootPath = NULL;
 
 /* FUNCTIONS ******************************************************************/
 
-VOID
+static BOOLEAN LinuxReadBootSector(ULONG LinuxKernelFile);
+static BOOLEAN LinuxReadSetupSector(ULONG LinuxKernelFile);
+static BOOLEAN LinuxReadKernel(ULONG LinuxKernelFile);
+static BOOLEAN LinuxCheckKernelVersion(VOID);
+static BOOLEAN LinuxReadInitrd(ULONG LinuxInitrdFile);
+
+static VOID
 RemoveQuotes(
     IN OUT PSTR QuotedString)
 {
@@ -85,14 +90,19 @@ LoadAndBootLinux(
     IN PCHAR Argv[],
     IN PCHAR Envp[])
 {
+    ARC_STATUS Status;
     PCSTR Description;
+    PCSTR ArgValue;
+    PCSTR BootPath;
+    UCHAR DriveNumber = 0;
+    ULONG PartitionNumber = 0;
     ULONG LinuxKernel = 0;
     ULONG LinuxInitrdFile = 0;
-    ARC_STATUS Status;
     FILEINFORMATION FileInfo;
+    CHAR ArcPath[MAX_PATH];
 
     Description = GetArgumentValue(Argc, Argv, "LoadIdentifier");
-    if (Description)
+    if (Description && *Description)
         RtlStringCbPrintfA(LinuxBootDescription, sizeof(LinuxBootDescription), "Loading %s...", Description);
     else
         strcpy(LinuxBootDescription, "Loading Linux...");
@@ -104,34 +114,91 @@ LoadAndBootLinux(
     /* Find all the message box settings and run them */
     UiShowMessageBoxesInArgv(Argc, Argv);
 
-    /* Parse the .ini file section */
-    if (!LinuxParseIniSection(Argc, Argv))
+    /*
+     * Check whether we have a "BootPath" value (takes precedence
+     * over both "BootDrive" and "BootPartition").
+     */
+    BootPath = GetArgumentValue(Argc, Argv, "BootPath");
+    if (!BootPath || !*BootPath)
+    {
+        /* We don't have one, check whether we use "BootDrive" and "BootPartition" */
+
+        /* Retrieve the boot drive (optional, fall back to using default path otherwise) */
+        ArgValue = GetArgumentValue(Argc, Argv, "BootDrive");
+        if (ArgValue && *ArgValue)
+        {
+            DriveNumber = DriveMapGetBiosDriveNumber(ArgValue);
+
+            /* Retrieve the boot partition (not optional and cannot be zero) */
+            PartitionNumber = 0;
+            ArgValue = GetArgumentValue(Argc, Argv, "BootPartition");
+            if (ArgValue && *ArgValue)
+                PartitionNumber = atoi(ArgValue);
+            if (PartitionNumber == 0)
+            {
+                UiMessageBox("Boot partition cannot be 0!");
+                goto LinuxBootFailed;
+                // return EINVAL;
+            }
+
+            /* Construct the corresponding ARC path */
+            ConstructArcPath(ArcPath, "", DriveNumber, PartitionNumber);
+            *strrchr(ArcPath, '\\') = ANSI_NULL; // Trim the trailing path separator.
+
+            BootPath = ArcPath;
+        }
+        else
+        {
+            /* Fall back to using the system partition as default path */
+            BootPath = GetArgumentValue(Argc, Argv, "SystemPartition");
+        }
+    }
+
+    /* Get the kernel name */
+    LinuxKernelName = GetArgumentValue(Argc, Argv, "Kernel");
+    if (!LinuxKernelName || !*LinuxKernelName)
+    {
+        UiMessageBox("Linux kernel filename not specified for selected OS!");
         goto LinuxBootFailed;
+    }
+
+    /* Get the initrd name (optional) */
+    LinuxInitrdName = GetArgumentValue(Argc, Argv, "Initrd");
+
+    /* Get the command line (optional) */
+    LinuxCommandLineSize = 0;
+    LinuxCommandLine = GetArgumentValue(Argc, Argv, "CommandLine");
+    if (LinuxCommandLine && *LinuxCommandLine)
+    {
+        RemoveQuotes(LinuxCommandLine);
+        LinuxCommandLineSize = (ULONG)strlen(LinuxCommandLine) + 1;
+        LinuxCommandLineSize = min(LinuxCommandLineSize, 260);
+    }
 
     /* Open the kernel */
-    LinuxKernel = FsOpenFile(LinuxKernelName);
-    if (!LinuxKernel)
+    Status = FsOpenFile(LinuxKernelName, BootPath, OpenReadOnly, &LinuxKernel);
+    if (Status != ESUCCESS)
     {
-        UiMessageBox("Linux kernel \'%s\' not found.", LinuxKernelName);
+        UiMessageBox("Linux kernel '%s' not found.", LinuxKernelName);
         goto LinuxBootFailed;
     }
 
     /* Open the initrd file image (if necessary) */
     if (LinuxInitrdName)
     {
-        LinuxInitrdFile = FsOpenFile(LinuxInitrdName);
-        if (!LinuxInitrdFile)
+        Status = FsOpenFile(LinuxInitrdName, BootPath, OpenReadOnly, &LinuxInitrdFile);
+        if (Status != ESUCCESS)
         {
-            UiMessageBox("Linux initrd image \'%s\' not found.", LinuxInitrdName);
+            UiMessageBox("Linux initrd image '%s' not found.", LinuxInitrdName);
             goto LinuxBootFailed;
         }
     }
 
-    /* Read the boot sector */
+    /* Load the boot sector */
     if (!LinuxReadBootSector(LinuxKernel))
         goto LinuxBootFailed;
 
-    /* Read the setup sector */
+    /* Load the setup sector */
     if (!LinuxReadSetupSector(LinuxKernel))
         goto LinuxBootFailed;
 
@@ -153,11 +220,11 @@ LoadAndBootLinux(
             LinuxInitrdSize = FileInfo.EndingAddress.LowPart;
     }
 
-    /* Read the kernel */
+    /* Load the kernel */
     if (!LinuxReadKernel(LinuxKernel))
         goto LinuxBootFailed;
 
-    /* Read the initrd (if necessary) */
+    /* Load the initrd (if necessary) */
     if (LinuxInitrdName)
     {
         if (!LinuxReadInitrd(LinuxInitrdFile))
@@ -233,50 +300,11 @@ LinuxBootFailed:
     LinuxKernelLoadAddress = NULL;
     LinuxInitrdLoadAddress = NULL;
     *LinuxBootDescription = ANSI_NULL;
-    LinuxBootPath = NULL;
 
     return ENOEXEC;
 }
 
-BOOLEAN
-LinuxParseIniSection(
-    IN ULONG Argc,
-    IN PCHAR Argv[])
-{
-#if 0
-    LinuxBootPath = GetArgumentValue(Argc, Argv, "BootPath");
-    if (!LinuxBootPath)
-    {
-        UiMessageBox("Boot path not specified for selected OS!");
-        return FALSE;
-    }
-#endif
-
-    /* Get the kernel name */
-    LinuxKernelName = GetArgumentValue(Argc, Argv, "Kernel");
-    if (!LinuxKernelName)
-    {
-        UiMessageBox("Linux kernel filename not specified for selected OS!");
-        return FALSE;
-    }
-
-    /* Get the initrd name (optional) */
-    LinuxInitrdName = GetArgumentValue(Argc, Argv, "Initrd");
-
-    /* Get the command line (optional) */
-    LinuxCommandLineSize = 0;
-    LinuxCommandLine = GetArgumentValue(Argc, Argv, "CommandLine");
-    if (LinuxCommandLine)
-    {
-        RemoveQuotes(LinuxCommandLine);
-        LinuxCommandLineSize = (ULONG)strlen(LinuxCommandLine) + 1;
-        LinuxCommandLineSize = min(LinuxCommandLineSize, 260);
-    }
-
-    return TRUE;
-}
-
-BOOLEAN LinuxReadBootSector(ULONG LinuxKernelFile)
+static BOOLEAN LinuxReadBootSector(ULONG LinuxKernelFile)
 {
     LARGE_INTEGER Position;
 
@@ -285,7 +313,7 @@ BOOLEAN LinuxReadBootSector(ULONG LinuxKernelFile)
     if (LinuxBootSector == NULL)
         return FALSE;
 
-    /* Read linux boot sector */
+    /* Load the linux boot sector */
     Position.QuadPart = 0;
     if (ArcSeek(LinuxKernelFile, &Position, SeekAbsolute) != ESUCCESS)
         return FALSE;
@@ -313,12 +341,12 @@ BOOLEAN LinuxReadBootSector(ULONG LinuxKernelFile)
     return TRUE;
 }
 
-BOOLEAN LinuxReadSetupSector(ULONG LinuxKernelFile)
+static BOOLEAN LinuxReadSetupSector(ULONG LinuxKernelFile)
 {
     LARGE_INTEGER Position;
     UCHAR TempLinuxSetupSector[512];
 
-    /* Read first linux setup sector */
+    /* Load the first linux setup sector */
     Position.QuadPart = 512;
     if (ArcSeek(LinuxKernelFile, &Position, SeekAbsolute) != ESUCCESS)
         return FALSE;
@@ -343,7 +371,7 @@ BOOLEAN LinuxReadSetupSector(ULONG LinuxKernelFile)
     /* Copy over first setup sector */
     RtlCopyMemory(LinuxSetupSector, TempLinuxSetupSector, 512);
 
-    /* Read in the rest of the linux setup sectors */
+    /* Load the rest of the linux setup sectors */
     Position.QuadPart = 1024;
     if (ArcSeek(LinuxKernelFile, &Position, SeekAbsolute) != ESUCCESS)
         return FALSE;
@@ -371,7 +399,7 @@ BOOLEAN LinuxReadSetupSector(ULONG LinuxKernelFile)
     return TRUE;
 }
 
-BOOLEAN LinuxReadKernel(ULONG LinuxKernelFile)
+static BOOLEAN LinuxReadKernel(ULONG LinuxKernelFile)
 {
     PVOID LoadAddress;
     LARGE_INTEGER Position;
@@ -390,7 +418,7 @@ BOOLEAN LinuxReadKernel(ULONG LinuxKernelFile)
 
     LoadAddress = LinuxKernelLoadAddress;
 
-    /* Read linux kernel to 0x100000 (1mb) */
+    /* Load the linux kernel at 0x100000 (1mb) */
     Position.QuadPart = 512 + SetupSectorSize;
     if (ArcSeek(LinuxKernelFile, &Position, SeekAbsolute) != ESUCCESS)
         return FALSE;
@@ -408,7 +436,7 @@ BOOLEAN LinuxReadKernel(ULONG LinuxKernelFile)
     return TRUE;
 }
 
-BOOLEAN LinuxCheckKernelVersion(VOID)
+static BOOLEAN LinuxCheckKernelVersion(VOID)
 {
     /* Just assume old kernel until we find otherwise */
     NewStyleLinuxKernel = FALSE;
@@ -445,7 +473,7 @@ BOOLEAN LinuxCheckKernelVersion(VOID)
     return TRUE;
 }
 
-BOOLEAN LinuxReadInitrd(ULONG LinuxInitrdFile)
+static BOOLEAN LinuxReadInitrd(ULONG LinuxInitrdFile)
 {
     ULONG        BytesLoaded;
     CHAR    StatusText[260];
@@ -482,7 +510,7 @@ BOOLEAN LinuxReadInitrd(ULONG LinuxInitrdFile)
         TRACE("InitrdAddressMax: 0x%x\n", LinuxSetupSector->InitrdAddressMax);
     }
 
-    /* Read in the ramdisk */
+    /* Load the ramdisk */
     for (BytesLoaded=0; BytesLoaded<LinuxInitrdSize; )
     {
         if (ArcRead(LinuxInitrdFile, (PVOID)LinuxInitrdLoadAddress, LINUX_READ_CHUNK_SIZE, NULL) != ESUCCESS)
index f7a0e2a..7d40c8a 100644 (file)
@@ -32,34 +32,79 @@ LoadAndBootBootSector(
     IN PCHAR Envp[])
 {
     ARC_STATUS Status;
+    PCSTR ArgValue;
+    PCSTR BootPath;
     PCSTR FileName;
+    UCHAR DriveNumber = 0;
+    ULONG PartitionNumber = 0;
     ULONG FileId;
     ULONG BytesRead;
+    CHAR ArcPath[MAX_PATH];
 
     /* Find all the message box settings and run them */
     UiShowMessageBoxesInArgv(Argc, Argv);
 
-    /* Read the file name */
+    /*
+     * Check whether we have a "BootPath" value (takes precedence
+     * over both "BootDrive" and "BootPartition").
+     */
+    BootPath = GetArgumentValue(Argc, Argv, "BootPath");
+    if (!BootPath || !*BootPath)
+    {
+        /* We don't have one, check whether we use "BootDrive" and "BootPartition" */
+
+        /* Retrieve the boot drive (optional, fall back to using default path otherwise) */
+        ArgValue = GetArgumentValue(Argc, Argv, "BootDrive");
+        if (ArgValue && *ArgValue)
+        {
+            DriveNumber = DriveMapGetBiosDriveNumber(ArgValue);
+
+            /* Retrieve the boot partition (not optional and cannot be zero) */
+            PartitionNumber = 0;
+            ArgValue = GetArgumentValue(Argc, Argv, "BootPartition");
+            if (ArgValue && *ArgValue)
+                PartitionNumber = atoi(ArgValue);
+            if (PartitionNumber == 0)
+            {
+                UiMessageBox("Boot partition cannot be 0!");
+                return EINVAL;
+            }
+
+            /* Construct the corresponding ARC path */
+            ConstructArcPath(ArcPath, "", DriveNumber, PartitionNumber);
+            *strrchr(ArcPath, '\\') = ANSI_NULL; // Trim the trailing path separator.
+
+            BootPath = ArcPath;
+        }
+        else
+        {
+            /* Fall back to using the system partition as default path */
+            BootPath = GetArgumentValue(Argc, Argv, "SystemPartition");
+        }
+    }
+
+    /* Retrieve the file name */
     FileName = GetArgumentValue(Argc, Argv, "BootSectorFile");
-    if (!FileName)
+    if (!FileName || !*FileName)
     {
         UiMessageBox("Boot sector file not specified for selected OS!");
         return EINVAL;
     }
 
-    FileId = FsOpenFile(FileName);
-    if (!FileId)
+    /* Open the boot sector file */
+    Status = FsOpenFile(FileName, BootPath, OpenReadOnly, &FileId);
+    if (Status != ESUCCESS)
     {
-        UiMessageBox("%s not found.", FileName);
-        return ENOENT;
+        UiMessageBox("Unable to open %s", FileName);
+        return Status;
     }
 
-    /* Read boot sector */
+    /* Now try to load the boot sector. If this fails then abort. */
     Status = ArcRead(FileId, (PVOID)0x7c00, 512, &BytesRead);
     ArcClose(FileId);
     if ((Status != ESUCCESS) || (BytesRead != 512))
     {
-        UiMessageBox("Unable to read boot sector.");
+        UiMessageBox("Unable to load boot sector.");
         return EIO;
     }
 
@@ -92,27 +137,51 @@ LoadAndBootBootSector(
 static ARC_STATUS
 LoadAndBootPartitionOrDrive(
     IN UCHAR DriveNumber,
-    IN ULONG PartitionNumber OPTIONAL)
+    IN ULONG PartitionNumber OPTIONAL,
+    IN PCSTR BootPath OPTIONAL)
 {
     ARC_STATUS Status;
     ULONG FileId;
     ULONG BytesRead;
     CHAR ArcPath[MAX_PATH];
 
-    /* Construct the corresponding ARC path */
-    ConstructArcPath(ArcPath, "", DriveNumber, PartitionNumber);
-    *strrchr(ArcPath, '\\') = ANSI_NULL; // Trim the trailing path separator.
+    /*
+     * If the user specifies an ARC "BootPath" value, it takes precedence
+     * over both the DriveNumber and PartitionNumber options.
+     */
+    if (BootPath && *BootPath)
+    {
+        PCSTR FileName = NULL;
+
+        /*
+         * Retrieve the BIOS drive and partition numbers; verify also that the
+         * path is "valid" in the sense that it must not contain any file name.
+         */
+        if (!DissectArcPath(BootPath, &FileName, &DriveNumber, &PartitionNumber) ||
+            (FileName && *FileName))
+        {
+            return EINVAL;
+        }
+    }
+    else
+    {
+        /* We don't have one, so construct the corresponding ARC path */
+        ConstructArcPath(ArcPath, "", DriveNumber, PartitionNumber);
+        *strrchr(ArcPath, '\\') = ANSI_NULL; // Trim the trailing path separator.
+
+        BootPath = ArcPath;
+    }
 
     /* Open the volume */
-    Status = ArcOpen(ArcPath, OpenReadOnly, &FileId);
+    Status = ArcOpen((PSTR)BootPath, OpenReadOnly, &FileId);
     if (Status != ESUCCESS)
     {
-        UiMessageBox("Unable to open %s", ArcPath);
-        return ENOENT;
+        UiMessageBox("Unable to open %s", BootPath);
+        return Status;
     }
 
     /*
-     * Now try to read the partition boot sector or the MBR (when PartitionNumber == 0).
+     * Now try to load the partition boot sector or the MBR (when PartitionNumber == 0).
      * If this fails then abort.
      */
     Status = ArcRead(FileId, (PVOID)0x7c00, 512, &BytesRead);
@@ -120,9 +189,9 @@ LoadAndBootPartitionOrDrive(
     if ((Status != ESUCCESS) || (BytesRead != 512))
     {
         if (PartitionNumber != 0)
-            UiMessageBox("Unable to read partition's boot sector.");
+            UiMessageBox("Unable to load partition's boot sector.");
         else
-            UiMessageBox("Unable to read MBR boot sector.");
+            UiMessageBox("Unable to load MBR boot sector.");
         return EIO;
     }
 
@@ -160,31 +229,39 @@ LoadAndBootPartition(
     IN PCHAR Envp[])
 {
     PCSTR ArgValue;
-    UCHAR DriveNumber;
-    ULONG PartitionNumber;
+    PCSTR BootPath;
+    UCHAR DriveNumber = 0;
+    ULONG PartitionNumber = 0;
 
     /* Find all the message box settings and run them */
     UiShowMessageBoxesInArgv(Argc, Argv);
 
-    /* Read the boot drive */
-    ArgValue = GetArgumentValue(Argc, Argv, "BootDrive");
-    if (!ArgValue)
+    /*
+     * Check whether we have a "BootPath" value (takes precedence
+     * over both "BootDrive" and "BootPartition").
+     */
+    BootPath = GetArgumentValue(Argc, Argv, "BootPath");
+    if (!BootPath || !*BootPath)
     {
-        UiMessageBox("Boot drive not specified for selected OS!");
-        return EINVAL;
-    }
-    DriveNumber = DriveMapGetBiosDriveNumber(ArgValue);
+        /* We don't have one */
 
-    /* Read the boot partition */
-    ArgValue = GetArgumentValue(Argc, Argv, "BootPartition");
-    if (!ArgValue)
-    {
-        UiMessageBox("Boot partition not specified for selected OS!");
-        return EINVAL;
+        /* Retrieve the boot drive */
+        ArgValue = GetArgumentValue(Argc, Argv, "BootDrive");
+        if (!ArgValue || !*ArgValue)
+        {
+            UiMessageBox("Boot drive not specified for selected OS!");
+            return EINVAL;
+        }
+        DriveNumber = DriveMapGetBiosDriveNumber(ArgValue);
+
+        /* Retrieve the boot partition (optional, fall back to zero otherwise) */
+        PartitionNumber = 0;
+        ArgValue = GetArgumentValue(Argc, Argv, "BootPartition");
+        if (ArgValue && *ArgValue)
+            PartitionNumber = atoi(ArgValue);
     }
-    PartitionNumber = atoi(ArgValue);
 
-    return LoadAndBootPartitionOrDrive(DriveNumber, PartitionNumber);
+    return LoadAndBootPartitionOrDrive(DriveNumber, PartitionNumber, BootPath);
 }
 
 ARC_STATUS
@@ -194,21 +271,39 @@ LoadAndBootDrive(
     IN PCHAR Envp[])
 {
     PCSTR ArgValue;
-    UCHAR DriveNumber;
+    PCSTR BootPath;
+    UCHAR DriveNumber = 0;
 
     /* Find all the message box settings and run them */
     UiShowMessageBoxesInArgv(Argc, Argv);
 
-    /* Read the boot drive */
-    ArgValue = GetArgumentValue(Argc, Argv, "BootDrive");
-    if (!ArgValue)
+    /* Check whether we have a "BootPath" value (takes precedence over "BootDrive") */
+    BootPath = GetArgumentValue(Argc, Argv, "BootPath");
+    if (BootPath && *BootPath)
     {
-        UiMessageBox("Boot drive not specified for selected OS!");
-        return EINVAL;
+        /*
+         * We have one, check that it does not contain any
+         * "partition()" specification, and fail if so.
+         */
+        if (strstr(BootPath, ")partition("))
+        {
+            UiMessageBox("Invalid 'BootPath' value!");
+            return EINVAL;
+        }
+    }
+    else
+    {
+        /* We don't, retrieve the boot drive value instead */
+        ArgValue = GetArgumentValue(Argc, Argv, "BootDrive");
+        if (!ArgValue || !*ArgValue)
+        {
+            UiMessageBox("Boot drive not specified for selected OS!");
+            return EINVAL;
+        }
+        DriveNumber = DriveMapGetBiosDriveNumber(ArgValue);
     }
-    DriveNumber = DriveMapGetBiosDriveNumber(ArgValue);
 
-    return LoadAndBootPartitionOrDrive(DriveNumber, 0);
+    return LoadAndBootPartitionOrDrive(DriveNumber, 0, BootPath);
 }
 
 #endif // _M_IX86
index 950accb..b3c4060 100644 (file)
@@ -934,7 +934,7 @@ InfOpenFile(
     //
     // Open the .inf file
     //
-    Status = ArcOpen((PCHAR)FileName, OpenReadOnly, &FileId);
+    Status = ArcOpen((PSTR)FileName, OpenReadOnly, &FileId);
     if (Status != ESUCCESS)
     {
         return FALSE;
index 0fe5c1f..81e76fe 100644 (file)
@@ -135,10 +135,12 @@ LoadReactOSSetup(
     IN PCHAR Argv[],
     IN PCHAR Envp[])
 {
+    ARC_STATUS Status;
     PCSTR ArgValue;
+    PCSTR SystemPartition;
     PCHAR File;
-    CHAR FileName[512];
-    CHAR BootPath[512];
+    CHAR FileName[MAX_PATH];
+    CHAR BootPath[MAX_PATH];
     CHAR BootOptions2[256];
     PCSTR LoadOptions;
     PSTR BootOptions;
@@ -165,6 +167,14 @@ LoadReactOSSetup(
         NULL
     };
 
+    /* Retrieve the (mandatory) system partition */
+    SystemPartition = GetArgumentValue(Argc, Argv, "SystemPartition");
+    if (!SystemPartition || !*SystemPartition)
+    {
+        ERR("No 'SystemPartition' specified, aborting!\n");
+        return EINVAL;
+    }
+
     UiDrawStatusText("Setup is loading...");
 
     UiDrawBackdrop();
@@ -180,13 +190,12 @@ LoadReactOSSetup(
     else
     {
         /*
-         * IMPROVE: I don't want to call MachDiskGetBootPath here as a
-         * default choice because I can call it after (see few lines below).
+         * IMPROVE: I don't want to use the SystemPartition here as a
+         * default choice because I can do it after (see few lines below).
          * Instead I reset BootPath here so that we can build the full path
          * using the general code from below.
          */
-        // MachDiskGetBootPath(BootPath, sizeof(BootPath));
-        // RtlStringCbCopyA(BootPath, sizeof(BootPath), ArgValue);
+        // RtlStringCbCopyA(BootPath, sizeof(BootPath), SystemPartition);
         *BootPath = ANSI_NULL;
     }
 
@@ -201,8 +210,8 @@ LoadReactOSSetup(
         /* Temporarily save the boot path */
         RtlStringCbCopyA(FileName, sizeof(FileName), BootPath);
 
-        /* This is not a full path. Use the current (i.e. boot) device. */
-        MachDiskGetBootPath(BootPath, sizeof(BootPath));
+        /* This is not a full path: prepend the SystemPartition */
+        RtlStringCbCopyA(BootPath, sizeof(BootPath), SystemPartition);
 
         /* Append a path separator if needed */
         if (*FileName != '\\' && *FileName != '/')
@@ -212,7 +221,7 @@ LoadReactOSSetup(
         RtlStringCbCatA(BootPath, sizeof(BootPath), FileName);
     }
 
-    /* Append a backslash if needed */
+    /* Append a path separator if needed */
     if (!*BootPath || BootPath[strlen(BootPath) - 1] != '\\')
         RtlStringCbCatA(BootPath, sizeof(BootPath), "\\");
 
@@ -221,7 +230,7 @@ LoadReactOSSetup(
     /* Retrieve the boot options */
     *BootOptions2 = ANSI_NULL;
     ArgValue = GetArgumentValue(Argc, Argv, "Options");
-    if (ArgValue)
+    if (ArgValue && *ArgValue)
         RtlStringCbCopyA(BootOptions2, sizeof(BootOptions2), ArgValue);
 
     TRACE("BootOptions: '%s'\n", BootOptions2);
@@ -237,10 +246,11 @@ LoadReactOSSetup(
         *strstr(FileName, " ") = ANSI_NULL;
 
         /* Load the ramdisk */
-        if (!RamDiskLoadVirtualFile(FileName))
+        Status = RamDiskLoadVirtualFile(FileName, SystemPartition);
+        if (Status != ESUCCESS)
         {
             UiMessageBox("Failed to load RAM disk file %s", FileName);
-            return ENOENT;
+            return Status;
         }
     }
 
@@ -292,7 +302,7 @@ LoadReactOSSetup(
     }
 #endif
 
-    /* Copy loadoptions (original string will be freed) */
+    /* Copy LoadOptions (original string will be freed) */
     BootOptions = FrLdrTempAlloc(strlen(LoadOptions) + 1, TAG_BOOT_OPTIONS);
     ASSERT(BootOptions);
     strcpy(BootOptions, LoadOptions);
index b114adb..a30d763 100644 (file)
@@ -65,11 +65,13 @@ WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock,
                        PCSTR BootPath,
                        USHORT VersionToBoot)
 {
-    /* Examples of correct options and paths */
-    //CHAR    Options[] = "/DEBUGPORT=COM1 /BAUDRATE=115200";
-    //CHAR    Options[] = "/NODEBUG";
-    //CHAR    SystemRoot[] = "\\WINNT\\";
-    //CHAR    ArcBoot[] = "multi(0)disk(0)rdisk(0)partition(1)";
+    /*
+     * Examples of correct options and paths:
+     * CHAR Options[] = "/DEBUGPORT=COM1 /BAUDRATE=115200";
+     * CHAR Options[] = "/NODEBUG";
+     * CHAR SystemRoot[] = "\\WINNT\\";
+     * CHAR ArcBoot[] = "multi(0)disk(0)rdisk(0)partition(1)";
+     */
 
     PSTR  LoadOptions, NewLoadOptions;
     CHAR  HalPath[] = "\\";
@@ -367,7 +369,7 @@ WinLdrLoadModule(PCSTR ModuleName,
     *Size = 0;
 
     /* Open the image file */
-    Status = ArcOpen((PCHAR)ModuleName, OpenReadOnly, &FileId);
+    Status = ArcOpen((PSTR)ModuleName, OpenReadOnly, &FileId);
     if (Status != ESUCCESS)
     {
         /* In case of errors, we just return, without complaining to the user */
@@ -413,17 +415,16 @@ WinLdrDetectVersion(VOID)
     LONG rc;
     HKEY hKey;
 
-    rc = RegOpenKey(
-        NULL,
-        L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Terminal Server",
-        &hKey);
+    rc = RegOpenKey(NULL,
+                    L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Terminal Server",
+                    &hKey);
     if (rc != ERROR_SUCCESS)
     {
-        // Key doesn't exist; assume NT 4.0
+        /* Key doesn't exist; assume NT 4.0 */
         return _WIN32_WINNT_NT4;
     }
 
-    // We may here want to read the value of ProductVersion
+    /* We may here want to read the value of ProductVersion */
     return _WIN32_WINNT_WS03;
 }
 
@@ -483,8 +484,8 @@ LoadWindowsCore(IN USHORT OperatingSystemVersion,
     BOOLEAN Success;
     PCSTR Options;
     CHAR DirPath[MAX_PATH];
-    CHAR KernelFileName[MAX_PATH];
     CHAR HalFileName[MAX_PATH];
+    CHAR KernelFileName[MAX_PATH];
     CHAR KdTransportDllName[MAX_PATH];
     PLDR_DATA_TABLE_ENTRY HalDTE, KdComDTE = NULL;
 
@@ -494,25 +495,27 @@ LoadWindowsCore(IN USHORT OperatingSystemVersion,
     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 */
-    RtlStringCbCopyA(KernelFileName, sizeof(KernelFileName), "ntoskrnl.exe");
+    /*
+     * Default HAL and KERNEL file names.
+     * See the following links to know how the file names are actually chosen:
+     * https://www.geoffchappell.com/notes/windows/boot/bcd/osloader/detecthal.htm
+     * https://www.geoffchappell.com/notes/windows/boot/bcd/osloader/hal.htm
+     * https://www.geoffchappell.com/notes/windows/boot/bcd/osloader/kernel.htm
+     */
     RtlStringCbCopyA(HalFileName   , sizeof(HalFileName)   , "hal.dll");
+    RtlStringCbCopyA(KernelFileName, sizeof(KernelFileName), "ntoskrnl.exe");
 
-    /* Find any /KERNEL= or /HAL= switch in the boot options */
+    /* Find any "/HAL=" or "/KERNEL=" switch in the boot options */
     Options = BootOptions;
     while (Options)
     {
         /* Skip possible initial whitespace */
         Options += strspn(Options, " \t");
 
-        /* Check whether a new option starts and it is either KERNEL or HAL */
+        /* Check whether a new option starts and it is either HAL or KERNEL */
         if (*Options != '/' || (++Options,
-            !(_strnicmp(Options, "KERNEL=", 7) == 0 ||
-              _strnicmp(Options, "HAL=",    4) == 0)) )
+            !(_strnicmp(Options, "HAL=",    4) == 0 ||
+              _strnicmp(Options, "KERNEL=", 7) == 0)) )
         {
             /* Search for another whitespace */
             Options = strpbrk(Options, " \t");
@@ -527,23 +530,23 @@ LoadWindowsCore(IN USHORT OperatingSystemVersion,
                 break;
             }
 
-            /* We have found either KERNEL or HAL options */
-            if (_strnicmp(Options, "KERNEL=", 7) == 0)
-            {
-                Options += 7; i -= 7;
-                RtlStringCbCopyNA(KernelFileName, sizeof(KernelFileName), Options, i);
-                _strupr(KernelFileName);
-            }
-            else if (_strnicmp(Options, "HAL=", 4) == 0)
+            /* We have found either HAL or KERNEL options */
+            if (_strnicmp(Options, "HAL=", 4) == 0)
             {
                 Options += 4; i -= 4;
                 RtlStringCbCopyNA(HalFileName, sizeof(HalFileName), Options, i);
                 _strupr(HalFileName);
             }
+            else if (_strnicmp(Options, "KERNEL=", 7) == 0)
+            {
+                Options += 7; i -= 7;
+                RtlStringCbCopyNA(KernelFileName, sizeof(KernelFileName), Options, i);
+                _strupr(KernelFileName);
+            }
         }
     }
 
-    TRACE("Kernel file = '%s' ; HAL file = '%s'\n", KernelFileName, HalFileName);
+    TRACE("HAL file = '%s' ; Kernel file = '%s'\n", HalFileName, KernelFileName);
 
     /* Load the Kernel */
     LoadModule(LoaderBlock, DirPath, KernelFileName, "ntoskrnl.exe", LoaderSystemCode, KernelDTE, 30);
@@ -653,7 +656,9 @@ LoadAndBootWindows(
     IN PCHAR Argv[],
     IN PCHAR Envp[])
 {
+    ARC_STATUS Status;
     PCSTR ArgValue;
+    PCSTR SystemPartition;
     PCHAR File;
     BOOLEAN Success;
     USHORT OperatingSystemVersion;
@@ -662,13 +667,15 @@ LoadAndBootWindows(
     CHAR  FileName[MAX_PATH];
     CHAR  BootOptions[256];
 
+    /* Retrieve the (mandatory) boot type */
     ArgValue = GetArgumentValue(Argc, Argv, "BootType");
-    if (!ArgValue)
+    if (!ArgValue || !*ArgValue)
     {
         ERR("No 'BootType' value, aborting!\n");
         return EINVAL;
     }
 
+    /* Convert it to an OS version */
     if (_stricmp(ArgValue, "Windows") == 0 ||
         _stricmp(ArgValue, "Windows2003") == 0)
     {
@@ -684,6 +691,14 @@ LoadAndBootWindows(
         return EINVAL;
     }
 
+    /* Retrieve the (mandatory) system partition */
+    SystemPartition = GetArgumentValue(Argc, Argv, "SystemPartition");
+    if (!SystemPartition || !*SystemPartition)
+    {
+        ERR("No 'SystemPartition' specified, aborting!\n");
+        return EINVAL;
+    }
+
     UiDrawBackdrop();
     UiDrawProgressBarCenter(1, 100, "Loading NT...");
 
@@ -704,8 +719,8 @@ LoadAndBootWindows(
         /* Temporarily save the boot path */
         RtlStringCbCopyA(FileName, sizeof(FileName), BootPath);
 
-        /* This is not a full path. Use the current (i.e. boot) device. */
-        MachDiskGetBootPath(BootPath, sizeof(BootPath));
+        /* This is not a full path: prepend the SystemPartition */
+        RtlStringCbCopyA(BootPath, sizeof(BootPath), SystemPartition);
 
         /* Append a path separator if needed */
         if (*FileName != '\\' && *FileName != '/')
@@ -715,7 +730,7 @@ LoadAndBootWindows(
         RtlStringCbCatA(BootPath, sizeof(BootPath), FileName);
     }
 
-    /* Append a backslash if needed */
+    /* Append a path separator if needed */
     if (!*BootPath || BootPath[strlen(BootPath) - 1] != '\\')
         RtlStringCbCatA(BootPath, sizeof(BootPath), "\\");
 
@@ -724,12 +739,45 @@ LoadAndBootWindows(
     /* Retrieve the boot options */
     *BootOptions = ANSI_NULL;
     ArgValue = GetArgumentValue(Argc, Argv, "Options");
-    if (ArgValue)
+    if (ArgValue && *ArgValue)
         RtlStringCbCopyA(BootOptions, sizeof(BootOptions), ArgValue);
 
     /* Append boot-time options */
     AppendBootTimeOptions(BootOptions);
 
+    /*
+     * Set "/HAL=" and "/KERNEL=" options if needed.
+     * If already present on the standard "Options=" option line, they take
+     * precedence over those passed via the separate "Hal=" and "Kernel="
+     * options.
+     */
+    if (strstr(BootOptions, "/HAL=") != 0)
+    {
+        /*
+         * Not found in the options, try to retrieve the
+         * separate value and append it to the options.
+         */
+        ArgValue = GetArgumentValue(Argc, Argv, "Hal");
+        if (ArgValue && *ArgValue)
+        {
+            RtlStringCbCatA(BootOptions, sizeof(BootOptions), " /HAL=");
+            RtlStringCbCatA(BootOptions, sizeof(BootOptions), ArgValue);
+        }
+    }
+    if (strstr(BootOptions, "/KERNEL=") != 0)
+    {
+        /*
+         * Not found in the options, try to retrieve the
+         * separate value and append it to the options.
+         */
+        ArgValue = GetArgumentValue(Argc, Argv, "Kernel");
+        if (ArgValue && *ArgValue)
+        {
+            RtlStringCbCatA(BootOptions, sizeof(BootOptions), " /KERNEL=");
+            RtlStringCbCatA(BootOptions, sizeof(BootOptions), ArgValue);
+        }
+    }
+
     TRACE("BootOptions: '%s'\n", BootOptions);
 
     /* Check if a ramdisk file was given */
@@ -743,10 +791,11 @@ LoadAndBootWindows(
         *strstr(FileName, " ") = ANSI_NULL;
 
         /* Load the ramdisk */
-        if (!RamDiskLoadVirtualFile(FileName))
+        Status = RamDiskLoadVirtualFile(FileName, SystemPartition);
+        if (Status != ESUCCESS)
         {
             UiMessageBox("Failed to load RAM disk file %s", FileName);
-            return ENOENT;
+            return Status;
         }
     }
 
index a509e15..3a05ebd 100644 (file)
@@ -20,8 +20,8 @@
 /* INCLUDES *******************************************************************/
 
 #include <freeldr.h>
-#include <debug.h>
 
+#include <debug.h>
 DBG_DEFAULT_CHANNEL(INIFILE);
 
 #define TAG_OS_ITEM 'tISO'
@@ -42,49 +42,16 @@ static PCSTR CopyString(PCSTR Source)
     return Dest;
 }
 
-static ULONG
-GetDefaultOperatingSystem(
-    IN OperatingSystemItem* OperatingSystemList,
-    IN ULONG OperatingSystemCount)
-{
-    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(
+    IN ULONG_PTR FrLdrSectionId,
     OUT PULONG OperatingSystemCount,
     OUT PULONG DefaultOperatingSystem)
 {
+    ULONG DefaultOS = 0;
+    PCSTR DefaultOSName = NULL;
+    CHAR  DefaultOSText[80];
+
     OperatingSystemItem* Items;
     ULONG Count;
     ULONG i;
@@ -110,7 +77,18 @@ InitOperatingSystemList(
     if (!Items)
         return NULL;
 
-    /* Now loop through and read the operating system section and display names */
+    /* Retrieve which OS is the default one */
+    DefaultOSName = CmdLineGetDefaultOS();
+    if (!DefaultOSName || !*DefaultOSName)
+    {
+        if ((FrLdrSectionId != 0) &&
+            IniReadSettingByName(FrLdrSectionId, "DefaultOS", DefaultOSText, sizeof(DefaultOSText)))
+        {
+            DefaultOSName = DefaultOSText;
+        }
+    }
+
+    /* Now loop through the operating system section and load each item */
     for (i = 0; i < Count; ++i)
     {
         IniReadSettingByNumber(OsSectionId, i,
@@ -118,7 +96,7 @@ InitOperatingSystemList(
                                SettingValue, sizeof(SettingValue));
         if (!*SettingName)
         {
-            ERR("Invalid OS entry number %lu, skipping.\n", i);
+            ERR("Invalid OS entry %lu, skipping.\n", i);
             continue;
         }
 
@@ -151,6 +129,13 @@ InitOperatingSystemList(
               // "OsLoadOptions = '%s'\n",
               // SettingName, TitleStart, OsLoadOptions);
 
+        /* Find the default OS item while we haven't got one */
+        if (DefaultOSName && _stricmp(DefaultOSName, SettingName) == 0)
+        {
+            DefaultOS = i;
+            DefaultOSName = NULL; // We have found the first one, don't search for others.
+        }
+
         /*
          * Determine whether this is a legacy operating system entry of the form:
          *
@@ -174,6 +159,7 @@ InitOperatingSystemList(
          */
 
         /* Try to open the operating system section in the .ini file */
+        SectionId = 0;
         HadSection = IniOpenSection(SettingName, &SectionId);
         if (HadSection)
         {
@@ -192,7 +178,7 @@ InitOperatingSystemList(
         {
 #ifdef _M_IX86
             ULONG FileId;
-            if (ArcOpen((PSTR)SettingName, OpenReadOnly, &FileId) == ESUCCESS)
+            if (ArcOpen(SettingName, OpenReadOnly, &FileId) == ESUCCESS)
             {
                 ArcClose(FileId);
                 strcpy(BootType, "BootSector");
@@ -236,7 +222,7 @@ InitOperatingSystemList(
             /* Add the section */
             if (!IniAddSection(SettingName, &SectionId))
             {
-                ERR("Could not convert legacy OS entry! Continuing...\n");
+                ERR("Could not convert legacy OS entry %lu, skipping.\n", i);
                 continue;
             }
 
@@ -245,7 +231,7 @@ InitOperatingSystemList(
             {
                 if (!IniAddSettingValueToSection(SectionId, "BootSectorFile", TempBuffer))
                 {
-                    ERR("Could not convert legacy OS entry! Continuing...\n");
+                    ERR("Could not convert legacy OS entry %lu, skipping.\n", i);
                     continue;
                 }
             }
@@ -253,7 +239,7 @@ InitOperatingSystemList(
             {
                 if (!IniAddSettingValueToSection(SectionId, "SystemPath", TempBuffer))
                 {
-                    ERR("Could not convert legacy OS entry! Continuing...\n");
+                    ERR("Could not convert legacy OS entry %lu, skipping.\n", i);
                     continue;
                 }
             }
@@ -265,7 +251,7 @@ InitOperatingSystemList(
             /* Add the OS options */
             if (OsLoadOptions && !IniAddSettingValueToSection(SectionId, "Options", OsLoadOptions))
             {
-                ERR("Could not convert legacy OS entry! Continuing...\n");
+                ERR("Could not convert legacy OS entry %lu, skipping.\n", i);
                 continue;
             }
         }
@@ -296,14 +282,15 @@ InitOperatingSystemList(
                 ERR("Could not modify the options for OS '%s', ignoring.\n", SettingName);
         }
 
-        /* Copy the OS section name and identifier */
-        Items[i].SectionName = CopyString(SettingName);
+        /* Copy the OS section ID and its identifier */
+        Items[i].SectionId = SectionId;
         Items[i].LoadIdentifier = CopyString(TitleStart);
-        // TRACE("We did Items[%lu]: SectionName = '%s', LoadIdentifier = '%s'\n", i, Items[i].SectionName, Items[i].LoadIdentifier);
+        // TRACE("We did Items[%lu]: SectionName = '%s' (SectionId = 0x%p), LoadIdentifier = '%s'\n",
+              // i, SettingName, Items[i].SectionId, Items[i].LoadIdentifier);
     }
 
     /* Return success */
     *OperatingSystemCount = Count;
-    *DefaultOperatingSystem = GetDefaultOperatingSystem(Items, Count);
+    *DefaultOperatingSystem = DefaultOS;
     return Items;
 }
index 519fd51..d4fec81 100644 (file)
@@ -10,7 +10,6 @@
 /* INCLUDES *******************************************************************/
 
 #include <freeldr.h>
-#include <debug.h>
 
 /* GLOBALS ********************************************************************/
 
@@ -252,7 +251,8 @@ UiDrawProgressBar(IN ULONG Left,
 }
 
 VOID
-UiShowMessageBoxesInSection(IN PCSTR SectionName)
+UiShowMessageBoxesInSection(
+    IN ULONG_PTR SectionId)
 {
     return;
 }
@@ -270,7 +270,8 @@ UiTruncateStringEllipsis(IN PCHAR StringText,
                          IN ULONG MaxChars)
 {
     /* If it's too large, just add some ellipsis past the maximum */
-    if (strlen(StringText) > MaxChars) strcpy(&StringText[MaxChars - 3], "...");
+    if (strlen(StringText) > MaxChars)
+        strcpy(&StringText[MaxChars - 3], "...");
 }
 
 VOID
index 44f8016..9b5fad7 100644 (file)
@@ -22,7 +22,7 @@
 #define TAG_TUI_SCREENBUFFER 'SiuT'
 #define TAG_TAG_TUI_PALETTE 'PiuT'
 
-PVOID    TextVideoBuffer = NULL;
+PVOID TextVideoBuffer = NULL;
 
 /*
  * TuiPrintf()
@@ -699,55 +699,58 @@ VOID TuiDrawProgressBar(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, ULONG
 
 UCHAR TuiTextToColor(PCSTR ColorText)
 {
-    if (_stricmp(ColorText, "Black") == 0)
-        return COLOR_BLACK;
-    else if (_stricmp(ColorText, "Blue") == 0)
-        return COLOR_BLUE;
-    else if (_stricmp(ColorText, "Green") == 0)
-        return COLOR_GREEN;
-    else if (_stricmp(ColorText, "Cyan") == 0)
-        return COLOR_CYAN;
-    else if (_stricmp(ColorText, "Red") == 0)
-        return COLOR_RED;
-    else if (_stricmp(ColorText, "Magenta") == 0)
-        return COLOR_MAGENTA;
-    else if (_stricmp(ColorText, "Brown") == 0)
-        return COLOR_BROWN;
-    else if (_stricmp(ColorText, "Gray") == 0)
-        return COLOR_GRAY;
-    else if (_stricmp(ColorText, "DarkGray") == 0)
-        return COLOR_DARKGRAY;
-    else if (_stricmp(ColorText, "LightBlue") == 0)
-        return COLOR_LIGHTBLUE;
-    else if (_stricmp(ColorText, "LightGreen") == 0)
-        return COLOR_LIGHTGREEN;
-    else if (_stricmp(ColorText, "LightCyan") == 0)
-        return COLOR_LIGHTCYAN;
-    else if (_stricmp(ColorText, "LightRed") == 0)
-        return COLOR_LIGHTRED;
-    else if (_stricmp(ColorText, "LightMagenta") == 0)
-        return COLOR_LIGHTMAGENTA;
-    else if (_stricmp(ColorText, "Yellow") == 0)
-        return COLOR_YELLOW;
-    else if (_stricmp(ColorText, "White") == 0)
-        return COLOR_WHITE;
+    static const struct
+    {
+        PCSTR ColorName;
+        UCHAR ColorValue;
+    } Colors[] =
+    {
+        {"Black"  , COLOR_BLACK  },
+        {"Blue"   , COLOR_BLUE   },
+        {"Green"  , COLOR_GREEN  },
+        {"Cyan"   , COLOR_CYAN   },
+        {"Red"    , COLOR_RED    },
+        {"Magenta", COLOR_MAGENTA},
+        {"Brown"  , COLOR_BROWN  },
+        {"Gray"   , COLOR_GRAY   },
+        {"DarkGray"    , COLOR_DARKGRAY    },
+        {"LightBlue"   , COLOR_LIGHTBLUE   },
+        {"LightGreen"  , COLOR_LIGHTGREEN  },
+        {"LightCyan"   , COLOR_LIGHTCYAN   },
+        {"LightRed"    , COLOR_LIGHTRED    },
+        {"LightMagenta", COLOR_LIGHTMAGENTA},
+        {"Yellow"      , COLOR_YELLOW      },
+        {"White"       , COLOR_WHITE       },
+    };
+    ULONG i;
+
+    for (i = 0; i < sizeof(Colors)/sizeof(Colors[0]); ++i)
+    {
+        if (_stricmp(ColorText, Colors[i].ColorName) == 0)
+            return Colors[i].ColorValue;
+    }
 
     return COLOR_BLACK;
 }
 
 UCHAR TuiTextToFillStyle(PCSTR FillStyleText)
 {
-    if (_stricmp(FillStyleText, "Light") == 0)
+    static const struct
     {
-        return LIGHT_FILL;
-    }
-    else if (_stricmp(FillStyleText, "Medium") == 0)
+        PCSTR FillStyleName;
+        UCHAR FillStyleValue;
+    } FillStyles[] =
     {
-        return MEDIUM_FILL;
-    }
-    else if (_stricmp(FillStyleText, "Dark") == 0)
+        {"Light" , LIGHT_FILL },
+        {"Medium", MEDIUM_FILL},
+        {"Dark"  , DARK_FILL  },
+    };
+    ULONG i;
+
+    for (i = 0; i < sizeof(FillStyles)/sizeof(FillStyles[0]); ++i)
     {
-        return DARK_FILL;
+        if (_stricmp(FillStyleText, FillStyles[i].FillStyleName) == 0)
+            return FillStyles[i].FillStyleValue;
     }
 
     return LIGHT_FILL;
index e9124fb..fa06f73 100644 (file)
 #ifndef _M_ARM
 
 #include <freeldr.h>
+
 #include <debug.h>
+DBG_DEFAULT_CHANNEL(UI);
 
 #define TAG_UI_TEXT 'xTiU'
 
-DBG_DEFAULT_CHANNEL(UI);
-
-ULONG    UiScreenWidth;                                        // Screen Width
-ULONG    UiScreenHeight;                                        // Screen Height
-
-UCHAR    UiStatusBarFgColor            = COLOR_BLACK;            // Status bar foreground color
-UCHAR    UiStatusBarBgColor            = COLOR_CYAN;            // Status bar background color
-UCHAR    UiBackdropFgColor            = COLOR_WHITE;            // Backdrop foreground color
-UCHAR    UiBackdropBgColor            = COLOR_BLUE;            // Backdrop background color
-UCHAR    UiBackdropFillStyle            = MEDIUM_FILL;            // Backdrop fill style
-UCHAR    UiTitleBoxFgColor            = COLOR_WHITE;            // Title box foreground color
-UCHAR    UiTitleBoxBgColor            = COLOR_RED;            // Title box background color
-UCHAR    UiMessageBoxFgColor            = COLOR_WHITE;            // Message box foreground color
-UCHAR    UiMessageBoxBgColor            = COLOR_BLUE;            // Message box background color
-UCHAR    UiMenuFgColor                = COLOR_WHITE;            // Menu foreground color
-UCHAR    UiMenuBgColor                = COLOR_BLUE;            // Menu background color
-UCHAR    UiTextColor                    = COLOR_YELLOW;            // Normal text color
-UCHAR    UiSelectedTextColor            = COLOR_BLACK;            // Selected text color
-UCHAR    UiSelectedTextBgColor        = COLOR_GRAY;            // Selected text background color
-UCHAR    UiEditBoxTextColor            = COLOR_WHITE;            // Edit box text color
-UCHAR    UiEditBoxBgColor            = COLOR_BLACK;            // Edit box text background color
-
-CHAR    UiTitleBoxTitleText[260]    = "Boot Menu";            // Title box's title text
-
-BOOLEAN    UiUseSpecialEffects            = FALSE;                // Tells us if we should use fade effects
-BOOLEAN    UiDrawTime                    = TRUE;                    // Tells us if we should draw the time
-BOOLEAN    UiCenterMenu                = TRUE;                    // Tells us if we should use a centered or left-aligned menu
-BOOLEAN    UiMenuBox                    = TRUE;                    // Tells us if we should draw a box around the menu
+ULONG UiScreenWidth;    // Screen Width
+ULONG UiScreenHeight;   // Screen Height
+
+UCHAR UiStatusBarFgColor    = COLOR_BLACK;  // Status bar foreground color
+UCHAR UiStatusBarBgColor    = COLOR_CYAN;   // Status bar background color
+UCHAR UiBackdropFgColor     = COLOR_WHITE;  // Backdrop foreground color
+UCHAR UiBackdropBgColor     = COLOR_BLUE;   // Backdrop background color
+UCHAR UiBackdropFillStyle   = MEDIUM_FILL;  // Backdrop fill style
+UCHAR UiTitleBoxFgColor     = COLOR_WHITE;  // Title box foreground color
+UCHAR UiTitleBoxBgColor     = COLOR_RED;    // Title box background color
+UCHAR UiMessageBoxFgColor   = COLOR_WHITE;  // Message box foreground color
+UCHAR UiMessageBoxBgColor   = COLOR_BLUE;   // Message box background color
+UCHAR UiMenuFgColor         = COLOR_WHITE;  // Menu foreground color
+UCHAR UiMenuBgColor         = COLOR_BLUE;   // Menu background color
+UCHAR UiTextColor           = COLOR_YELLOW; // Normal text color
+UCHAR UiSelectedTextColor   = COLOR_BLACK;  // Selected text color
+UCHAR UiSelectedTextBgColor = COLOR_GRAY;   // Selected text background color
+UCHAR UiEditBoxTextColor    = COLOR_WHITE;  // Edit box text color
+UCHAR UiEditBoxBgColor      = COLOR_BLACK;  // Edit box text background color
+
+CHAR UiTitleBoxTitleText[260] = "Boot Menu";    // Title box's title text
+
+BOOLEAN UiUseSpecialEffects = FALSE;    // Tells us if we should use fade effects
+BOOLEAN UiDrawTime          = TRUE;     // Tells us if we should draw the time
+BOOLEAN UiCenterMenu        = TRUE;     // Tells us if we should use a centered or left-aligned menu
+BOOLEAN UiMenuBox           = TRUE;     // Tells us if we should draw a box around the menu
 CHAR    UiTimeText[260] = "[Time Remaining: ] ";
 
-const CHAR    UiMonthNames[12][15] = { "January ", "February ", "March ", "April ", "May ", "June ", "July ", "August ", "September ", "October ", "November ", "December " };
+const CHAR UiMonthNames[12][15] = { "January ", "February ", "March ", "April ", "May ", "June ", "July ", "August ", "September ", "October ", "November ", "December " };
 
 UIVTBL UiVtbl =
 {
@@ -83,12 +83,11 @@ UIVTBL UiVtbl =
 
 BOOLEAN UiInitialize(BOOLEAN ShowGui)
 {
-    VIDEODISPLAYMODE    UiDisplayMode; // Tells us if we are in text or graphics mode
-    BOOLEAN UiMinimal = FALSE; // Tells us if we are using a minimal console-like UI
+    VIDEODISPLAYMODE UiDisplayMode; // Tells us if we are in text or graphics mode
+    BOOLEAN UiMinimal = FALSE;      // Tells us if we are using a minimal console-like UI
     ULONG_PTR SectionId;
-    CHAR    DisplayModeText[260];
-    CHAR    SettingText[260];
-    ULONG    Depth;
+    ULONG Depth;
+    CHAR  SettingText[260];
 
     if (!ShowGui)
     {
@@ -101,25 +100,28 @@ BOOLEAN UiInitialize(BOOLEAN ShowGui)
     }
 
     TRACE("Initializing User Interface.\n");
-    TRACE("Reading in UI settings from [Display] section.\n");
+    TRACE("Reading UI settings from [Display] section.\n");
+
+    /* Open the [Display] section */
+    if (!IniOpenSection("Display", &SectionId))
+        SectionId = 0;
 
-    DisplayModeText[0] = '\0';
-    if (IniOpenSection("Display", &SectionId))
+    /* Select the video mode */
+    SettingText[0] = '\0';
+    if ((SectionId != 0) && !IniReadSettingByName(SectionId, "DisplayMode", SettingText, sizeof(SettingText)))
     {
-        if (!IniReadSettingByName(SectionId, "DisplayMode", DisplayModeText, sizeof(DisplayModeText)))
-        {
-            DisplayModeText[0] = '\0';
-        }
-        if (IniReadSettingByName(SectionId, "MinimalUI", SettingText, sizeof(SettingText)))
-        {
-            UiMinimal = (_stricmp(SettingText, "Yes") == 0 && strlen(SettingText) == 3);
-        }
+        SettingText[0] = '\0';
     }
-
-    UiDisplayMode = MachVideoSetDisplayMode(DisplayModeText, TRUE);
+    UiDisplayMode = MachVideoSetDisplayMode(SettingText, TRUE);
     MachVideoGetDisplaySize(&UiScreenWidth, &UiScreenHeight, &Depth);
 
-    if (VideoTextMode == UiDisplayMode)
+    /* Select the UI */
+    if ((SectionId != 0) && IniReadSettingByName(SectionId, "MinimalUI", SettingText, sizeof(SettingText)))
+    {
+        UiMinimal = (_stricmp(SettingText, "Yes") == 0 && strlen(SettingText) == 3);
+    }
+
+    if (UiDisplayMode == VideoTextMode)
         UiVtbl = (UiMinimal ? MiniTuiVtbl : TuiVtbl);
     else
         UiVtbl = GuiVtbl;
@@ -130,99 +132,70 @@ BOOLEAN UiInitialize(BOOLEAN ShowGui)
         return FALSE;
     }
 
-    if (IniOpenSection("Display", &SectionId))
+    /* Load the settings */
+    if (SectionId != 0)
     {
-        if (IniReadSettingByName(SectionId, "TitleText", SettingText, sizeof(SettingText)))
-        {
-            strcpy(UiTitleBoxTitleText, SettingText);
-        }
-        if (IniReadSettingByName(SectionId, "TimeText", SettingText, sizeof(SettingText)))
-        {
-            strcpy(UiTimeText, SettingText);
-        }
-        if (IniReadSettingByName(SectionId, "StatusBarColor", SettingText, sizeof(SettingText)))
-        {
-            UiStatusBarBgColor = UiTextToColor(SettingText);
-        }
-        if (IniReadSettingByName(SectionId, "StatusBarTextColor", SettingText, sizeof(SettingText)))
-        {
-            UiStatusBarFgColor = UiTextToColor(SettingText);
-        }
-        if (IniReadSettingByName(SectionId, "BackdropTextColor", SettingText, sizeof(SettingText)))
-        {
-            UiBackdropFgColor = UiTextToColor(SettingText);
-        }
-        if (IniReadSettingByName(SectionId, "BackdropColor", SettingText, sizeof(SettingText)))
-        {
-            UiBackdropBgColor = UiTextToColor(SettingText);
-        }
-        if (IniReadSettingByName(SectionId, "BackdropFillStyle", SettingText, sizeof(SettingText)))
-        {
-            UiBackdropFillStyle = UiTextToFillStyle(SettingText);
-        }
-        if (IniReadSettingByName(SectionId, "TitleBoxTextColor", SettingText, sizeof(SettingText)))
-        {
-            UiTitleBoxFgColor = UiTextToColor(SettingText);
-        }
-        if (IniReadSettingByName(SectionId, "TitleBoxColor", SettingText, sizeof(SettingText)))
-        {
-            UiTitleBoxBgColor = UiTextToColor(SettingText);
-        }
-        if (IniReadSettingByName(SectionId, "MessageBoxTextColor", SettingText, sizeof(SettingText)))
-        {
-            UiMessageBoxFgColor = UiTextToColor(SettingText);
-        }
-        if (IniReadSettingByName(SectionId, "MessageBoxColor", SettingText, sizeof(SettingText)))
-        {
-            UiMessageBoxBgColor = UiTextToColor(SettingText);
-        }
-        if (IniReadSettingByName(SectionId, "MenuTextColor", SettingText, sizeof(SettingText)))
-        {
-            UiMenuFgColor = UiTextToColor(SettingText);
-        }
-        if (IniReadSettingByName(SectionId, "MenuColor", SettingText, sizeof(SettingText)))
+        static const struct
         {
-            UiMenuBgColor = UiTextToColor(SettingText);
-        }
-        if (IniReadSettingByName(SectionId, "TextColor", SettingText, sizeof(SettingText)))
-        {
-            UiTextColor = UiTextToColor(SettingText);
-        }
-        if (IniReadSettingByName(SectionId, "SelectedTextColor", SettingText, sizeof(SettingText)))
-        {
-            UiSelectedTextColor = UiTextToColor(SettingText);
-        }
-        if (IniReadSettingByName(SectionId, "SelectedColor", SettingText, sizeof(SettingText)))
+            PCSTR SettingName;
+            PVOID SettingVar;
+            UCHAR SettingType; // 0: Text, 1: Yes/No, 2: Color, 3: Fill style
+        } Settings[] =
         {
-            UiSelectedTextBgColor = UiTextToColor(SettingText);
-        }
-        if (IniReadSettingByName(SectionId, "EditBoxTextColor", SettingText, sizeof(SettingText)))
-        {
-            UiEditBoxTextColor = UiTextToColor(SettingText);
-        }
-        if (IniReadSettingByName(SectionId, "EditBoxColor", SettingText, sizeof(SettingText)))
-        {
-            UiEditBoxBgColor = UiTextToColor(SettingText);
-        }
-        if (IniReadSettingByName(SectionId, "SpecialEffects", SettingText, sizeof(SettingText)))
+            {"TitleText", &UiTitleBoxTitleText, 0},
+            {"TimeText" , &UiTimeText         , 0},
+
+            {"SpecialEffects", &UiUseSpecialEffects, 1},
+            {"ShowTime"      , &UiDrawTime         , 1},
+            {"MenuBox"       , &UiMenuBox          , 1},
+            {"CenterMenu"    , &UiCenterMenu       , 1},
+
+            {"BackdropColor"      , &UiBackdropBgColor    , 2},
+            {"BackdropTextColor"  , &UiBackdropFgColor    , 2},
+            {"StatusBarColor"     , &UiStatusBarBgColor   , 2},
+            {"StatusBarTextColor" , &UiStatusBarFgColor   , 2},
+            {"TitleBoxColor"      , &UiTitleBoxBgColor    , 2},
+            {"TitleBoxTextColor"  , &UiTitleBoxFgColor    , 2},
+            {"MessageBoxColor"    , &UiMessageBoxBgColor  , 2},
+            {"MessageBoxTextColor", &UiMessageBoxFgColor  , 2},
+            {"MenuColor"          , &UiMenuBgColor        , 2},
+            {"MenuTextColor"      , &UiMenuFgColor        , 2},
+            {"TextColor"          , &UiTextColor          , 2},
+            {"SelectedColor"      , &UiSelectedTextBgColor, 2},
+            {"SelectedTextColor"  , &UiSelectedTextColor  , 2},
+            {"EditBoxColor"       , &UiEditBoxBgColor     , 2},
+            {"EditBoxTextColor"   , &UiEditBoxTextColor   , 2},
+
+            {"BackdropFillStyle", &UiBackdropFillStyle, 3},
+        };
+        ULONG i;
+
+        for (i = 0; i < sizeof(Settings)/sizeof(Settings[0]); ++i)
         {
-            UiUseSpecialEffects = (_stricmp(SettingText, "Yes") == 0 && strlen(SettingText) == 3);
-        }
-        if (IniReadSettingByName(SectionId, "ShowTime", SettingText, sizeof(SettingText)))
-        {
-            UiDrawTime = (_stricmp(SettingText, "Yes") == 0 && strlen(SettingText) == 3);
-        }
-        if (IniReadSettingByName(SectionId, "MenuBox", SettingText, sizeof(SettingText)))
-        {
-            UiMenuBox = (_stricmp(SettingText, "Yes") == 0 && strlen(SettingText) == 3);
-        }
-        if (IniReadSettingByName(SectionId, "CenterMenu", SettingText, sizeof(SettingText)))
-        {
-            UiCenterMenu = (_stricmp(SettingText, "Yes") == 0 && strlen(SettingText) == 3);
+            if (!IniReadSettingByName(SectionId, Settings[i].SettingName, SettingText, sizeof(SettingText)))
+                continue;
+
+            switch (Settings[i].SettingType)
+            {
+            case 0: // Text
+                strcpy((PCHAR)Settings[i].SettingVar, SettingText);
+                break;
+            case 1: // Yes/No
+                *(PBOOLEAN)Settings[i].SettingVar = (_stricmp(SettingText, "Yes") == 0 && strlen(SettingText) == 3);
+                break;
+            case 2: // Color
+                *(PUCHAR)Settings[i].SettingVar = UiTextToColor(SettingText);
+                break;
+            case 3: // Fill style
+                *(PUCHAR)Settings[i].SettingVar = UiTextToFillStyle(SettingText);
+                break;
+            default:
+                break;
+            }
         }
     }
 
-    // Draw the backdrop and fade it in if special effects are enabled
+    /* Draw the backdrop and fade it in if special effects are enabled */
     UiFadeInBackdrop();
 
     TRACE("UiInitialize() returning TRUE.\n");
@@ -380,53 +353,47 @@ VOID UiDrawProgressBar(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, ULONG P
     UiVtbl.DrawProgressBar(Left, Top, Right, Bottom, Position, Range, ProgressText);
 }
 
-VOID UiShowMessageBoxesInSection(PCSTR SectionName)
+VOID
+UiShowMessageBoxesInSection(
+    IN ULONG_PTR SectionId)
 {
-    ULONG    Idx;
-    CHAR    SettingName[80];
-    CHAR    SettingValue[80];
-    PCHAR    MessageBoxText;
-    ULONG        MessageBoxTextSize;
-    ULONG_PTR    SectionId;
+    ULONG Idx;
+    CHAR  SettingName[80];
+    CHAR  SettingValue[80];
+    PCHAR MessageBoxText;
+    ULONG MessageBoxTextSize;
 
-    if (!IniOpenSection(SectionName, &SectionId))
-    {
+    if (SectionId == 0)
         return;
-    }
 
-    //
-    // Find all the message box settings and run them
-    //
-    for (Idx=0; Idx<IniGetNumSectionItems(SectionId); Idx++)
+    /* Find all the message box settings and run them */
+    for (Idx = 0; Idx < IniGetNumSectionItems(SectionId); Idx++)
     {
         IniReadSettingByNumber(SectionId, Idx, SettingName, sizeof(SettingName), SettingValue, sizeof(SettingValue));
+        if (_stricmp(SettingName, "MessageBox") != 0)
+            continue;
 
-        if (_stricmp(SettingName, "MessageBox") == 0)
-        {
-            // Get the real length of the MessageBox text
-            MessageBoxTextSize = IniGetSectionSettingValueSize(SectionId, Idx);
+        /* Get the real length of the MessageBox text */
+        MessageBoxTextSize = IniGetSectionSettingValueSize(SectionId, Idx);
+        // if (MessageBoxTextSize <= 0)
+            // continue;
 
-            //if (MessageBoxTextSize > 0)
-            {
-                // Allocate enough memory to hold the text
-                MessageBoxText = FrLdrTempAlloc(MessageBoxTextSize, TAG_UI_TEXT);
+        /* Allocate enough memory to hold the text */
+        MessageBoxText = FrLdrTempAlloc(MessageBoxTextSize, TAG_UI_TEXT);
+        if (!MessageBoxText)
+            continue;
 
-                if (MessageBoxText)
-                {
-                    // Get the MessageBox text
-                    IniReadSettingByNumber(SectionId, Idx, SettingName, sizeof(SettingName), MessageBoxText, MessageBoxTextSize);
+        /* Get the MessageBox text */
+        IniReadSettingByNumber(SectionId, Idx, SettingName, sizeof(SettingName), MessageBoxText, MessageBoxTextSize);
 
-                    // Fix it up
-                    UiEscapeString(MessageBoxText);
+        /* Fix it up */
+        UiEscapeString(MessageBoxText);
 
-                    // Display it
-                    UiMessageBox(MessageBoxText);
+        /* Display it */
+        UiMessageBox(MessageBoxText);
 
-                    // Free the memory
-                    FrLdrTempFree(MessageBoxText, TAG_UI_TEXT);
-                }
-            }
-        }
+        /* Free the memory */
+        FrLdrTempFree(MessageBoxText, TAG_UI_TEXT);
     }
 }
 
@@ -450,20 +417,20 @@ UiShowMessageBoxesInArgv(
 
         /* Allocate enough memory to hold the text */
         MessageBoxText = FrLdrTempAlloc(MessageBoxTextSize, TAG_UI_TEXT);
-        if (MessageBoxText)
-        {
-            /* Get the MessageBox text */
-            strcpy(MessageBoxText, ArgValue);
+        if (!MessageBoxText)
+            continue;
 
-            /* Fix it up */
-            UiEscapeString(MessageBoxText);
+        /* Get the MessageBox text */
+        strcpy(MessageBoxText, ArgValue);
 
-            /* Display it */
-            UiMessageBox(MessageBoxText);
+        /* Fix it up */
+        UiEscapeString(MessageBoxText);
 
-            /* Free the memory */
-            FrLdrTempFree(MessageBoxText, TAG_UI_TEXT);
-        }
+        /* Display it */
+        UiMessageBox(MessageBoxText);
+
+        /* Free the memory */
+        FrLdrTempFree(MessageBoxText, TAG_UI_TEXT);
     }
 }
 
@@ -487,10 +454,9 @@ VOID UiEscapeString(PCHAR String)
 
 VOID UiTruncateStringEllipsis(PCHAR StringText, ULONG MaxChars)
 {
+    /* If it's too large, just add some ellipsis past the maximum */
     if (strlen(StringText) > MaxChars)
-    {
         strcpy(&StringText[MaxChars - 3], "...");
-    }
 }
 
 BOOLEAN