[FREELDR] Make FreeLoader a bit more usable even if FREELDR.INI is missing

CORE-9023

In case FREELDR.INI is missing, or there are no operating systems listed
and available (either the corresponding section is missing, or is empty),
fall back to the FreeLoader Setup and Configuration F2 menu, that allows
performing a minimal number of operations (enabling FreeLoader debugging;
doing a custom boot... and more to come!)

Fix also a bug in `InitOperatingSystemList()`, that would allow
allocating an empty list with zero items. Now it returns NULL if
no operating systems are found.

Default to the Minimal text UI instead of the fullfledged one, if no
"MinimalUI" option can be found in FREELDR.INI (or if the INI is missing).
This commit is contained in:
Hermès Bélusca-Maïto
2026-04-04 22:19:18 +02:00
parent 9ff4e4b9ef
commit bf26ae38a5
6 changed files with 34 additions and 31 deletions
+18 -23
View File
@@ -395,63 +395,53 @@ VOID RunLoader(VOID)
#ifndef UEFIBOOT
/* Load additional SCSI driver (if any) */
if (LoadBootDeviceDriver() != ESUCCESS)
{
UiMessageBoxCritical("Unable to load additional boot device drivers.");
}
#endif
#endif
/* Open FREELDR.INI and load the global FreeLoader settings */
if (!IniFileInitialize())
{
UiMessageBoxCritical("Error initializing .ini file.");
return;
}
LoadSettings(NULL);
#if 0
if (FALSE)
{
UiMessageBoxCritical("Could not load global FreeLoader settings.");
return;
}
#endif
/* Debugger main initialization */
DebugInit(GetBootMgrInfo()->DebugString);
/* UI main initialization */
/* UI main initialization. If it fails, fall back to default UI. */
if (!UiInitialize(TRUE))
{
UiMessageBoxCritical("Unable to initialize UI.");
return;
}
/* If no FREELDR.INI, skip everything else and fall back to the FreeLdr setup menu */
if (IsListEmpty(IniGetFileSectionListHead()))
goto Fallback;
/* Find all the message box settings and run them */
UiShowMessageBoxesInSection(GetBootMgrInfo()->FrLdrSection);
/* Retrieve the list of boot entries */
OperatingSystemList = InitOperatingSystemList(&OperatingSystemCount,
&SelectedOperatingSystem);
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;
UiMessageBox("There are no operating systems listed in freeldr.ini.");
goto Fallback;
}
ASSERT(OperatingSystemCount != 0);
/* Create list of display names */
OperatingSystemDisplayNames = FrLdrTempAlloc(sizeof(PCSTR) * OperatingSystemCount, 'mNSO');
if (!OperatingSystemDisplayNames)
goto Reboot;
goto Fallback;
for (i = 0; i < OperatingSystemCount; i++)
{
OperatingSystemDisplayNames[i] = OperatingSystemList[i].LoadIdentifier;
}
/* Find all the message box settings and run them */
UiShowMessageBoxesInSection(GetBootMgrInfo()->FrLdrSection);
for (;;)
{
/* Redraw the backdrop, but don't overwrite boot options */
@@ -489,6 +479,11 @@ VOID RunLoader(VOID)
UiInitialize(TRUE);
}
Fallback:
/* Fall back to the FreeLdr setup menu */
FreeLdrSetupMenu(NULL);
UiMessageBox("The system will now reboot.");
Reboot:
UiUnInitialize("Rebooting...");
IniCleanup();
+1 -1
View File
@@ -9,7 +9,7 @@
VOID
FreeLdrSetupMenu(
_In_ OperatingSystemItem* OperatingSystem);
_In_opt_ OperatingSystemItem* OperatingSystem);
VOID
DisplayBootTimeOptions(
+4 -3
View File
@@ -51,7 +51,7 @@ static PCSTR FrldrDbgMsg =
VOID
FreeLdrSetupMenu(
_In_ OperatingSystemItem* OperatingSystem)
_In_opt_ OperatingSystemItem* OperatingSystem)
{
ULONG SelectedMenuItem = 0;
@@ -60,7 +60,7 @@ doMenu:
UiDrawBackdrop(UiGetScreenHeight());
if (!UiDisplayMenu(VERSION " Setup and Configuration",
NULL,
OperatingSystem ? NULL : "Press ESC to reboot.",
OptionsMenuList,
RTL_NUMBER_OF(OptionsMenuList),
SelectedMenuItem, -1,
@@ -90,7 +90,8 @@ doMenu:
// break;
#ifdef HAS_OPTION_MENU_EDIT_CMDLINE
case 2: // Edit command line
EditOperatingSystemEntry(OperatingSystem);
if (OperatingSystem)
EditOperatingSystemEntry(OperatingSystem);
break;
#endif
#ifdef HAS_OPTION_MENU_CUSTOM_BOOT
+8
View File
@@ -62,12 +62,20 @@ InitOperatingSystemList(
CHAR BootType[80];
CHAR TempBuffer[_countof(SettingValue)];
/* Default with an empty list */
*OperatingSystemCount = 0;
/* Open the [Operating Systems] section */
if (!IniOpenSection("Operating Systems", &OsSectionId))
{
UiMessageBox("Operating Systems section not found in freeldr.ini");
return NULL;
}
/* Count the number of operating systems in the section */
Count = IniGetNumSectionItems(OsSectionId);
if (Count == 0) /* Fail if no operating systems are found */
return NULL;
/* Allocate memory to hold operating system lists */
Items = FrLdrHeapAlloc(Count * sizeof(OperatingSystemItem), TAG_OS_ITEM);
+2 -3
View File
@@ -163,7 +163,7 @@ LoadSettings(
* If a section is already loaded, skip further checks. */
if (!BootMgrInfo.FrLdrSection)
{
for (ULONG i = 0; i < sizeof(LoaderSections) / sizeof(LoaderSections[0]); i++)
for (ULONG i = 0; i < RTL_NUMBER_OF(LoaderSections); ++i)
{
PCSTR Section = LoaderSections[i];
@@ -173,10 +173,9 @@ LoadSettings(
break;
}
}
if (!FoundLoaderSection)
{
UiMessageBoxCritical("Bootloader Section not found in freeldr.ini");
UiMessageBoxCritical("Bootloader section not found in freeldr.ini");
return;
}
}
+1 -1
View File
@@ -92,7 +92,7 @@ UIVTBL UiVtbl =
BOOLEAN UiInitialize(BOOLEAN ShowUi)
{
VIDEODISPLAYMODE UiDisplayMode; // Tells us if we are in text or graphics mode
BOOLEAN UiMinimal = FALSE; // Tells us if we are using a minimal console-like UI
BOOLEAN UiMinimal = TRUE; // Tells us if we are using a minimal console-like UI
ULONG_PTR SectionId;
ULONG Depth;
CHAR SettingText[260];