* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+/* INCLUDES *******************************************************************/
+
#include <freeldr.h>
-ARC_DISK_SIGNATURE reactos_arc_disk_info[32]; // ARC Disk Information
-ULONG reactos_disk_count = 0;
-CHAR reactos_arc_strings[32][256];
+#include <debug.h>
+DBG_DEFAULT_CHANNEL(INIFILE);
+
+/* GLOBALS ********************************************************************/
typedef
VOID
-(*OS_LOADING_METHOD)(IN OperatingSystemItem* OperatingSystem,
- IN USHORT OperatingSystemVersion);
+(*EDIT_OS_ENTRY_PROC)(
+ IN OUT OperatingSystemItem* OperatingSystem);
-struct
+static VOID
+EditCustomBootReactOSSetup(
+ IN OUT OperatingSystemItem* OperatingSystem)
{
- CHAR BootType[80];
- USHORT OperatingSystemVersion;
- OS_LOADING_METHOD Load;
+ EditCustomBootReactOS(OperatingSystem, TRUE);
+}
+
+static VOID
+EditCustomBootNTOS(
+ IN OUT OperatingSystemItem* OperatingSystem)
+{
+ EditCustomBootReactOS(OperatingSystem, FALSE);
+}
+
+static const struct
+{
+ PCSTR BootType;
+ EDIT_OS_ENTRY_PROC EditOsEntry;
+ ARC_ENTRY_POINT OsLoader;
} OSLoadingMethods[] =
{
-#ifdef FREELDR_REACTOS_SETUP
- {"ReactOSSetup", 0 , LoadReactOSSetup },
-#endif
+ {"ReactOSSetup", EditCustomBootReactOSSetup, LoadReactOSSetup},
#ifdef _M_IX86
- {"BootSector" , 0 , LoadAndBootBootSector},
- {"Drive" , 0 , LoadAndBootDrive },
- {"Partition" , 0 , LoadAndBootPartition },
-
- {"Linux" , 0 , LoadAndBootLinux },
+ {"Drive" , EditCustomBootDisk , LoadAndBootDrive },
+ {"Partition" , EditCustomBootPartition , LoadAndBootPartition },
+ {"BootSector" , EditCustomBootSectorFile, LoadAndBootBootSector},
- {"Windows" , 0 , LoadAndBootWindows },
- {"WindowsNT40" , _WIN32_WINNT_NT4 , LoadAndBootWindows },
+ {"Linux" , EditCustomBootLinux, LoadAndBootLinux },
+ {"WindowsNT40" , EditCustomBootNTOS , LoadAndBootWindows},
#endif
- {"Windows2003" , _WIN32_WINNT_WS03, LoadAndBootWindows },
-
-// {"Not found" , 0 , NULL }
+ {"Windows" , EditCustomBootNTOS , LoadAndBootWindows},
+ {"Windows2003" , EditCustomBootNTOS , LoadAndBootWindows},
};
-VOID LoadOperatingSystem(IN OperatingSystemItem* OperatingSystem)
+/* 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,
+ IN ULONG_PTR SectionId,
+ OUT PULONG pArgc)
{
- ULONG_PTR SectionId;
- PCSTR SectionName = OperatingSystem->SystemPartition;
- CHAR BootType[80];
+ SIZE_T Size;
+ ULONG Count;
ULONG i;
+ ULONG Argc;
+ PCHAR* Argv;
+ PCHAR* Args;
+ PCHAR SettingName, SettingValue;
+
+ *pArgc = 0;
+
+ ASSERT(SectionId != 0);
+
+ /* Validate the LoadIdentifier (to make tests simpler later) */
+ if (LoadIdentifier && !*LoadIdentifier)
+ LoadIdentifier = NULL;
+
+ /* Count the number of operating systems in the section */
+ Count = IniGetNumSectionItems(SectionId);
+
+ /*
+ * The argument vector contains the program name, the 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: SystemPartition : from where FreeLdr has been started */
+ Size += (strlen("SystemPartition=") + strlen(FrldrBootPath) + 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);
+ }
+ for (i = 0; i < Count; ++i)
+ {
+ Size += IniGetSectionSettingNameSize(SectionId, i); // Counts also the NULL-terminator, that we transform into the '=' sign separator.
+ Size += IniGetSectionSettingValueSize(SectionId, i); // Counts also the NULL-terminator.
+ }
+ Size += sizeof(ANSI_NULL); // Final NULL-terminator.
+
+ /* Allocate memory to hold the argument vector: pointers and string buffer */
+ Argv = FrLdrHeapAlloc(Argc * sizeof(PCHAR) + Size, TAG_STRING);
+ if (!Argv)
+ return NULL;
+
+ /* Initialize the argument vector: loop through the section and copy the key=value options */
+ SettingName = (PCHAR)((ULONG_PTR)Argv + (Argc * sizeof(PCHAR)));
+ Args = Argv;
+ /* i == 0: Program name */
+ *Args++ = NULL;
+ /* i == 1: SystemPartition */
+ {
+ strcpy(SettingName, "SystemPartition=");
+ strcat(SettingName, FrldrBootPath);
- // Try to open the operating system section in the .ini file
- if (IniOpenSection(SectionName, &SectionId))
+ *Args++ = SettingName;
+ SettingName += (strlen(SettingName) + 1);
+ }
+ /* i == 2: LoadIdentifier */
+ if (LoadIdentifier)
{
- // Try to read the boot type
- IniReadSettingByName(SectionId, "BootType", BootType, sizeof(BootType));
+ strcpy(SettingName, "LoadIdentifier=");
+ strcat(SettingName, LoadIdentifier);
+
+ *Args++ = SettingName;
+ SettingName += (strlen(SettingName) + 1);
}
- else
+ for (i = 0; i < Count; ++i)
{
- BootType[0] = ANSI_NULL;
+ Size = IniGetSectionSettingNameSize(SectionId, i);
+ SettingValue = SettingName + Size;
+ IniReadSettingByNumber(SectionId, i,
+ SettingName, Size,
+ SettingValue, IniGetSectionSettingValueSize(SectionId, i));
+ SettingName[Size - 1] = '=';
+
+ *Args++ = SettingName;
+ SettingName += (strlen(SettingName) + 1);
}
- if (BootType[0] == ANSI_NULL && SectionName[0] != ANSI_NULL)
+#if DBG
+ /* Dump the argument vector for debugging */
+ for (i = 0; i < Argc; ++i)
{
- // Try to infere the boot type value
-#ifdef _M_IX86
- ULONG FileId;
- if (ArcOpen((PSTR)SectionName, OpenReadOnly, &FileId) == ESUCCESS)
- {
- ArcClose(FileId);
- strcpy(BootType, "BootSector");
- }
- else
-#endif
- {
- strcpy(BootType, "Windows");
- }
+ TRACE("Argv[%lu]: '%s'\n", i, Argv[i]);
}
+#endif
+
+ *pArgc = Argc;
+ return Argv;
+}
+
+VOID LoadOperatingSystem(IN OperatingSystemItem* OperatingSystem)
+{
+ ULONG_PTR SectionId = OperatingSystem->SectionId;
+ ULONG i;
+ ULONG Argc;
+ PCHAR* Argv;
+ CHAR BootType[80];
+
+ /* The operating system section has been opened by InitOperatingSystemList() */
+ ASSERT(SectionId != 0);
+
+ /* Try to read the boot type */
+ *BootType = ANSI_NULL;
+ IniReadSettingByName(SectionId, "BootType", BootType, sizeof(BootType));
+
+ /* We must have the "BootType" value (it has been possibly added by InitOperatingSystemList()) */
+ ASSERT(*BootType);
- // Install the drive mapper according to this section drive mappings
-#if defined(_M_IX86) && !defined(_MSC_VER)
- DriveMapMapDrivesInSection(SectionName);
+#ifdef _M_IX86
+ /* Install the drive mapper according to this section drive mappings */
+ DriveMapMapDrivesInSection(SectionId);
#endif
- // Loop through the OS loading method table and find a suitable OS to boot
+ /* Loop through the OS loading method table and find a suitable OS to boot */
for (i = 0; i < sizeof(OSLoadingMethods) / sizeof(OSLoadingMethods[0]); ++i)
{
if (_stricmp(BootType, OSLoadingMethods[i].BootType) == 0)
{
- OSLoadingMethods[i].Load(OperatingSystem,
- OSLoadingMethods[i].OperatingSystemVersion);
+ Argv = BuildArgvForOsLoader(OperatingSystem->LoadIdentifier, SectionId, &Argc);
+ if (Argv)
+ {
+ OSLoadingMethods[i].OsLoader(Argc, Argv, NULL);
+ FrLdrHeapFree(Argv, TAG_STRING);
+ }
return;
}
}
}
-ULONG GetDefaultOperatingSystem(OperatingSystemItem* OperatingSystemList, ULONG OperatingSystemCount)
+#ifdef HAS_OPTION_MENU_EDIT_CMDLINE
+
+VOID EditOperatingSystemEntry(IN OperatingSystemItem* OperatingSystem)
{
- CHAR DefaultOSText[80];
- PCSTR DefaultOSName;
- ULONG_PTR SectionId;
- ULONG DefaultOS = 0;
- ULONG Idx;
+ ULONG_PTR SectionId = OperatingSystem->SectionId;
+ ULONG i;
+ CHAR BootType[80];
- if (!IniOpenSection("FreeLoader", &SectionId))
- {
- return 0;
- }
+ /* The operating system section has been opened by InitOperatingSystemList() */
+ ASSERT(SectionId != 0);
- DefaultOSName = CmdLineGetDefaultOS();
- if (NULL == DefaultOSName)
- {
- if (IniReadSettingByName(SectionId, "DefaultOS", DefaultOSText, sizeof(DefaultOSText)))
- {
- DefaultOSName = DefaultOSText;
- }
- }
+ /* Try to read the boot type */
+ *BootType = ANSI_NULL;
+ IniReadSettingByName(SectionId, "BootType", BootType, sizeof(BootType));
+
+ /* We must have the "BootType" value (it has been possibly added by InitOperatingSystemList()) */
+ ASSERT(*BootType);
- if (NULL != DefaultOSName)
+ /* Loop through the OS loading method table and find a suitable OS entry editor */
+ for (i = 0; i < sizeof(OSLoadingMethods) / sizeof(OSLoadingMethods[0]); ++i)
{
- for (Idx=0; Idx<OperatingSystemCount; Idx++)
+ if (_stricmp(BootType, OSLoadingMethods[i].BootType) == 0)
{
- if (_stricmp(DefaultOSName, OperatingSystemList[Idx].SystemPartition) == 0)
- {
- DefaultOS = Idx;
- break;
- }
+ OSLoadingMethods[i].EditOsEntry(OperatingSystem);
+ return;
}
}
-
- return DefaultOS;
}
-LONG GetTimeOut(VOID)
+#endif // HAS_OPTION_MENU_EDIT_CMDLINE
+
+static LONG
+GetTimeOut(
+ IN ULONG_PTR FrLdrSectionId)
{
- CHAR TimeOutText[20];
- LONG TimeOut;
- ULONG_PTR SectionId;
+ LONG TimeOut = -1;
+ CHAR TimeOutText[20];
TimeOut = CmdLineGetTimeOut();
- if (0 <= TimeOut)
- {
+ 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;
}
-BOOLEAN MainBootMenuKeyPressFilter(ULONG KeyPress)
+BOOLEAN
+MainBootMenuKeyPressFilter(
+ IN ULONG KeyPress,
+ IN ULONG SelectedMenuItem,
+ IN PVOID Context OPTIONAL)
{
- if (KeyPress == KEY_F8)
+ switch (KeyPress)
{
- DoOptionsMenu();
+ case KEY_F8:
+ DoOptionsMenu(&((OperatingSystemItem*)Context)[SelectedMenuItem]);
+ return TRUE;
+#ifdef HAS_OPTION_MENU_EDIT_CMDLINE
+ case KEY_F10:
+ EditOperatingSystemEntry(&((OperatingSystemItem*)Context)[SelectedMenuItem]);
return TRUE;
- }
+#endif
- // We didn't handle the key
- return FALSE;
+ default:
+ /* We didn't handle the key */
+ return FALSE;
+ }
}
VOID RunLoader(VOID)
{
- ULONG_PTR SectionId;
- ULONG OperatingSystemCount;
- OperatingSystemItem* OperatingSystemList;
- PCSTR* OperatingSystemDisplayNames;
- ULONG DefaultOperatingSystem;
- LONG TimeOut;
- ULONG SelectedOperatingSystem;
- ULONG i;
+ ULONG_PTR SectionId;
+ LONG TimeOut;
+ ULONG OperatingSystemCount;
+ OperatingSystemItem* OperatingSystemList;
+ PCSTR* OperatingSystemDisplayNames;
+ ULONG DefaultOperatingSystem;
+ ULONG SelectedOperatingSystem;
+ ULONG i;
if (!MachInitializeBootDevices())
{
- UiMessageBoxCritical("Error when detecting hardware");
+ UiMessageBoxCritical("Error when detecting hardware.");
return;
}
#ifdef _M_IX86
- // Load additional SCSI driver (if any)
+ /* Load additional SCSI driver (if any) */
if (LoadBootDeviceDriver() != ESUCCESS)
{
- UiMessageBoxCritical("Unable to load additional boot device driver");
+ UiMessageBoxCritical("Unable to load additional boot device drivers.");
}
#endif
if (!IniFileInitialize())
{
- UiMessageBoxCritical("Error initializing .ini file");
+ UiMessageBoxCritical("Error initializing .ini file.");
return;
}
+ /* 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))
{
UiMessageBoxCritical("Unable to initialize UI.");
return;
}
- OperatingSystemList = InitOperatingSystemList(&OperatingSystemCount);
+ OperatingSystemList = InitOperatingSystemList(SectionId,
+ &OperatingSystemCount,
+ &DefaultOperatingSystem);
if (!OperatingSystemList)
{
UiMessageBox("Unable to read operating systems section in freeldr.ini.\nPress ENTER to reboot.");
- goto reboot;
+ goto Reboot;
}
-
if (OperatingSystemCount == 0)
{
UiMessageBox("There were no operating systems listed in freeldr.ini.\nPress ENTER to reboot.");
- goto reboot;
+ goto Reboot;
}
- DefaultOperatingSystem = GetDefaultOperatingSystem(OperatingSystemList, OperatingSystemCount);
-
- //
- // Create list of display names
- //
+ /* Create list of display names */
OperatingSystemDisplayNames = FrLdrTempAlloc(sizeof(PCSTR) * OperatingSystemCount, 'mNSO');
if (!OperatingSystemDisplayNames)
- {
- goto reboot;
- }
+ goto Reboot;
+
for (i = 0; i < OperatingSystemCount; i++)
{
OperatingSystemDisplayNames[i] = OperatingSystemList[i].LoadIdentifier;
}
- //
- // Find all the message box settings and run them
- //
- UiShowMessageBoxesInSection("FreeLoader");
+ /* Find all the message box settings and run them */
+ UiShowMessageBoxesInSection(SectionId);
for (;;)
{
- // Redraw the backdrop
+ /* Redraw the backdrop */
UiDrawBackdrop();
- // Show the operating system list menu
+ /* Show the operating system list menu */
if (!UiDisplayMenu("Please select the operating system to start:",
"For troubleshooting and advanced startup options for "
"ReactOS, press F8.",
TimeOut,
&SelectedOperatingSystem,
FALSE,
- MainBootMenuKeyPressFilter))
+ MainBootMenuKeyPressFilter,
+ OperatingSystemList))
{
UiMessageBox("Press ENTER to reboot.");
- goto reboot;
+ goto Reboot;
}
TimeOut = -1;
- // Load the chosen operating system
+ /* Load the chosen operating system */
LoadOperatingSystem(&OperatingSystemList[SelectedOperatingSystem]);
}
-reboot:
+Reboot:
UiUnInitialize("Rebooting...");
+ IniCleanup();
return;
}