Skip to content
Permalink
Browse files

[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).
  • Loading branch information...
HBelusca committed Aug 6, 2019
1 parent d21ffe6 commit d05be0da3f4d8c5c3bc60e1b8249b586212642bc
@@ -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
@@ -22,122 +22,167 @@
#include <freeldr.h>
#include <debug.h>

/* GLOBALS ********************************************************************/
DBG_DEFAULT_CHANNEL(INIFILE);

typedef
VOID
(*OS_LOADING_METHOD)(IN OperatingSystemItem* OperatingSystem,
IN USHORT OperatingSystemVersion);
/* GLOBALS ********************************************************************/

static const struct
{
PCHAR BootType;
USHORT OperatingSystemVersion;
OS_LOADING_METHOD Load;
PCSTR BootType;
ARC_ENTRY_POINT OsLoader;
} OSLoadingMethods[] =
{
{"ReactOSSetup", 0 , LoadReactOSSetup },
{"ReactOSSetup", LoadReactOSSetup },

#ifdef _M_IX86
{"BootSector" , 0 , LoadAndBootBootSector},
{"Drive" , 0 , LoadAndBootDrive },
{"Partition" , 0 , LoadAndBootPartition },
{"BootSector" , LoadAndBootBootSector},
{"Drive" , LoadAndBootDrive },
{"Partition" , LoadAndBootPartition },

{"Linux" , 0 , LoadAndBootLinux },
{"Linux" , LoadAndBootLinux },

{"Windows" , 0 , LoadAndBootWindows },
{"WindowsNT40" , _WIN32_WINNT_NT4 , LoadAndBootWindows },
{"Windows" , LoadAndBootWindows },
{"WindowsNT40" , LoadAndBootWindows },
#endif
{"Windows2003" , _WIN32_WINNT_WS03, LoadAndBootWindows },
{"Windows2003" , LoadAndBootWindows },
};

/* FUNCTIONS ******************************************************************/

VOID LoadOperatingSystem(IN OperatingSystemItem* OperatingSystem)
PCHAR*
BuildArgvForOsLoader(
IN PCSTR LoadIdentifier,
IN ULONG_PTR SectionId,
OUT PULONG pArgc)
{
ULONG_PTR SectionId;
PCSTR SectionName = OperatingSystem->SystemPartition;
CHAR BootType[80];
SIZE_T Size;
ULONG Count;
ULONG i;

/* Try to open the operating system section in the .ini file */
if (IniOpenSection(SectionName, &SectionId))
ULONG Argc;
PCHAR* Argv;
PCHAR* Args;
PCHAR SettingName, SettingValue;

/*
* Convert the list of key=value options in the given operating system section
* into a ARC-compatible argument vector.
*/

*pArgc = 0;

/* Validate the LoadIdentifier (to make tests simpler later) */
if (LoadIdentifier && !*LoadIdentifier)
LoadIdentifier = NULL;

/* Count the number of operating systems in the section */
Count = IniGetNumSectionItems(SectionId);

/* The argument vector contains the program name, the LoadIdentifier (optional), and the items in the OS section */
Argc = 1 + Count;
if (LoadIdentifier)
++Argc;

/* Calculate the total size needed for the string buffer of the argument vector */
Size = 0;
/* i == 0: Program name */
/* i == 1: LoadIdentifier */
if (LoadIdentifier)
{
/* Try to read the boot type */
IniReadSettingByName(SectionId, "BootType", BootType, sizeof(BootType));
Size += (strlen("LoadIdentifier=") + strlen(LoadIdentifier) + 1) * sizeof(CHAR);
}
else
for (i = 0; i < Count; ++i)
{
BootType[0] = ANSI_NULL;
Size += IniGetSectionSettingNameSize(SectionId, i); // Counts also the NULL-terminator, that we transform into the '=' sign separator.
Size += IniGetSectionSettingValueSize(SectionId, i); // Counts also the NULL-terminator.
}
Size += sizeof(ANSI_NULL); // Final NULL-terminator.

/* Allocate memory to hold the argument vector: pointers and string buffer */
Argv = FrLdrHeapAlloc(Argc * sizeof(PCHAR) + Size, TAG_STRING);
if (!Argv)
return NULL;

/* Initialize the argument vector: loop through the section and copy the key=value options */
SettingName = (PCHAR)((ULONG_PTR)Argv + (Argc * sizeof(PCHAR)));
Args = Argv;
/* i == 0: Program name */
*Args++ = NULL;
/* i == 1: LoadIdentifier */
if (LoadIdentifier)
{
strcpy(SettingName, "LoadIdentifier=");
strcat(SettingName, LoadIdentifier);

if (BootType[0] == ANSI_NULL && SectionName[0] != ANSI_NULL)
*Args++ = SettingName;
SettingName += (strlen(SettingName) + 1);
}
for (i = 0; i < Count; ++i)
{
/* Try to infer the boot type value */
#ifdef _M_IX86
ULONG FileId;
if (ArcOpen((PSTR)SectionName, OpenReadOnly, &FileId) == ESUCCESS)
{
ArcClose(FileId);
strcpy(BootType, "BootSector");
}
else
#endif
{
strcpy(BootType, "Windows");
}
Size = IniGetSectionSettingNameSize(SectionId, i);
SettingValue = SettingName + Size;
IniReadSettingByNumber(SectionId, i,
SettingName, Size,
SettingValue, IniGetSectionSettingValueSize(SectionId, i));
SettingName[Size - 1] = '=';

*Args++ = SettingName;
SettingName += (strlen(SettingName) + 1);
}

#if defined(_M_IX86)
/* Install the drive mapper according to this section drive mappings */
DriveMapMapDrivesInSection(SectionName);
#endif

/* Loop through the OS loading method table and find a suitable OS to boot */
for (i = 0; i < sizeof(OSLoadingMethods) / sizeof(OSLoadingMethods[0]); ++i)
#if DBG
/* Dump the argument vector for debugging */
for (i = 0; i < Argc; ++i)
{
if (_stricmp(BootType, OSLoadingMethods[i].BootType) == 0)
{
OSLoadingMethods[i].Load(OperatingSystem,
OSLoadingMethods[i].OperatingSystemVersion);
return;
}
TRACE("Argv[%lu]: '%s'\n", i, Argv[i]);
}
#endif

*pArgc = Argc;
return Argv;
}

ULONG GetDefaultOperatingSystem(OperatingSystemItem* OperatingSystemList, ULONG OperatingSystemCount)
VOID LoadOperatingSystem(IN OperatingSystemItem* OperatingSystem)
{
CHAR DefaultOSText[80];
PCSTR DefaultOSName;
ULONG_PTR SectionId;
ULONG DefaultOS = 0;
ULONG Idx;

if (!IniOpenSection("FreeLoader", &SectionId))
return 0;
PCSTR SectionName = OperatingSystem->SectionName;
ULONG i;
ULONG Argc;
PCHAR* Argv;
CHAR BootType[80];

DefaultOSName = CmdLineGetDefaultOS();
if (DefaultOSName == NULL)
/* Try to open the operating system section in the .ini file */
if (!IniOpenSection(SectionName, &SectionId))
{
if (IniReadSettingByName(SectionId, "DefaultOS", DefaultOSText, sizeof(DefaultOSText)))
{
DefaultOSName = DefaultOSText;
}
UiMessageBox("Section [%s] not found in freeldr.ini.", SectionName);
return;
}

if (DefaultOSName != NULL)
/* Try to read the boot type */
*BootType = ANSI_NULL;
IniReadSettingByName(SectionId, "BootType", BootType, sizeof(BootType));

/* We must have the "BootType" value (it has been possibly added by InitOperatingSystemList()) */
ASSERT(*BootType);

#if defined(_M_IX86)
/* Install the drive mapper according to this section drive mappings */
DriveMapMapDrivesInSection(SectionName);
#endif

/* Loop through the OS loading method table and find a suitable OS to boot */
for (i = 0; i < sizeof(OSLoadingMethods) / sizeof(OSLoadingMethods[0]); ++i)
{
for (Idx = 0; Idx < OperatingSystemCount; Idx++)
if (_stricmp(BootType, OSLoadingMethods[i].BootType) == 0)
{
if (_stricmp(DefaultOSName, OperatingSystemList[Idx].SystemPartition) == 0)
Argv = BuildArgvForOsLoader(OperatingSystem->LoadIdentifier, SectionId, &Argc);
if (Argv)
{
DefaultOS = Idx;
break;
OSLoadingMethods[i].OsLoader(Argc, Argv, NULL);
FrLdrHeapFree(Argv, TAG_STRING);
}
return;
}
}

return DefaultOS;
}

LONG GetTimeOut(VOID)
@@ -176,11 +221,11 @@ BOOLEAN MainBootMenuKeyPressFilter(ULONG KeyPress)
VOID RunLoader(VOID)
{
ULONG_PTR SectionId;
LONG TimeOut;
ULONG OperatingSystemCount;
OperatingSystemItem* OperatingSystemList;
PCSTR* OperatingSystemDisplayNames;
ULONG DefaultOperatingSystem;
LONG TimeOut;
ULONG SelectedOperatingSystem;
ULONG i;

@@ -222,21 +267,19 @@ VOID RunLoader(VOID)
return;
}

OperatingSystemList = InitOperatingSystemList(&OperatingSystemCount);
OperatingSystemList = InitOperatingSystemList(&OperatingSystemCount,
&DefaultOperatingSystem);
if (!OperatingSystemList)
{
UiMessageBox("Unable to read operating systems section in freeldr.ini.\nPress ENTER to reboot.");
goto Reboot;
}

if (OperatingSystemCount == 0)
{
UiMessageBox("There were no operating systems listed in freeldr.ini.\nPress ENTER to reboot.");
goto Reboot;
}

DefaultOperatingSystem = GetDefaultOperatingSystem(OperatingSystemList, OperatingSystemCount);

/* Create list of display names */
OperatingSystemDisplayNames = FrLdrTempAlloc(sizeof(PCSTR) * OperatingSystemCount, 'mNSO');
if (!OperatingSystemDisplayNames)

0 comments on commit d05be0d

Please sign in to comment.
You can’t perform that action at this time.