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