mirror of
https://github.com/reactos/reactos.git
synced 2024-06-30 18:01:07 +00:00
d05be0da3f
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).
310 lines
10 KiB
C
310 lines
10 KiB
C
/*
|
|
* FreeLoader
|
|
* Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
/* INCLUDES *******************************************************************/
|
|
|
|
#include <freeldr.h>
|
|
#include <debug.h>
|
|
|
|
DBG_DEFAULT_CHANNEL(INIFILE);
|
|
|
|
#define TAG_OS_ITEM 'tISO'
|
|
|
|
/* FUNCTIONS ******************************************************************/
|
|
|
|
static PCSTR CopyString(PCSTR Source)
|
|
{
|
|
PSTR Dest;
|
|
|
|
if (!Source)
|
|
return NULL;
|
|
|
|
Dest = FrLdrHeapAlloc(strlen(Source) + 1, TAG_STRING);
|
|
if (Dest)
|
|
strcpy(Dest, 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(
|
|
OUT PULONG OperatingSystemCount,
|
|
OUT PULONG DefaultOperatingSystem)
|
|
{
|
|
OperatingSystemItem* Items;
|
|
ULONG Count;
|
|
ULONG i;
|
|
ULONG_PTR OsSectionId, SectionId;
|
|
PCHAR TitleStart, TitleEnd;
|
|
PCSTR OsLoadOptions;
|
|
BOOLEAN HadSection;
|
|
BOOLEAN HadNoBootType;
|
|
CHAR SettingName[260];
|
|
CHAR SettingValue[260];
|
|
CHAR BootType[80];
|
|
CHAR TempBuffer[sizeof(SettingValue)/sizeof(CHAR)];
|
|
|
|
/* Open the [Operating Systems] section */
|
|
if (!IniOpenSection("Operating Systems", &OsSectionId))
|
|
return NULL;
|
|
|
|
/* 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);
|
|
if (!Items)
|
|
return NULL;
|
|
|
|
/* Now loop through and read the operating system section and display names */
|
|
for (i = 0; i < Count; ++i)
|
|
{
|
|
IniReadSettingByNumber(OsSectionId, i,
|
|
SettingName, sizeof(SettingName),
|
|
SettingValue, sizeof(SettingValue));
|
|
if (!*SettingName)
|
|
{
|
|
ERR("Invalid OS entry number %lu, skipping.\n", i);
|
|
continue;
|
|
}
|
|
|
|
/* 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 */
|
|
*OperatingSystemCount = Count;
|
|
*DefaultOperatingSystem = GetDefaultOperatingSystem(Items, Count);
|
|
return Items;
|
|
}
|