[SETUPLIB] Use new BootPath value for BootSector boot entries (#6815)

The BootDrive and BootPartition values are deprecated, and support
for them will soon be removed from FreeLoader.

Add an helper function to migrate these values during ReactOS
(re)installation / update.
This commit is contained in:
Hermès Bélusca-Maïto 2024-04-23 17:02:06 +02:00
parent 5a287473fd
commit 2b43390d04
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
3 changed files with 292 additions and 94 deletions

View file

@ -189,15 +189,80 @@ CreateFreeLoaderIniForReactOSAndBootSector(
IN PCWSTR ArcPath,
IN PCWSTR Section,
IN PCWSTR Description,
IN PCWSTR BootDrive,
IN PCWSTR BootPartition,
IN PCWSTR BootPath,
IN PCWSTR BootSector)
{
NTSTATUS Status;
PVOID BootStoreHandle;
UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(BOOT_SECTOR_OPTIONS)];
UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) + sizeof(BOOTSECTOR_OPTIONS)];
PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry;
PBOOT_SECTOR_OPTIONS Options = (PBOOT_SECTOR_OPTIONS)&BootEntry->OsOptions;
PBOOTSECTOR_OPTIONS Options = (PBOOTSECTOR_OPTIONS)&BootEntry->OsOptions;
WCHAR BootPathBuffer[MAX_PATH] = L"";
/* Since the BootPath given here is in NT format
* (not ARC), we need to hack-generate a mapping */
ULONG DiskNumber = 0, PartitionNumber = 0;
PCWSTR PathComponent = NULL;
/* From the NT path, compute the disk, partition and path components */
// NOTE: this function doesn't support stuff like \Device\FloppyX ...
if (NtPathToDiskPartComponents(BootPath, &DiskNumber, &PartitionNumber, &PathComponent))
{
DPRINT1("BootPath = '%S' points to disk #%d, partition #%d, path '%S'\n",
BootPath, DiskNumber, PartitionNumber, PathComponent);
/* HACK-build a possible ARC path:
* Hard disk path: multi(0)disk(0)rdisk(x)partition(y)[\path] */
RtlStringCchPrintfW(BootPathBuffer, _countof(BootPathBuffer),
L"multi(0)disk(0)rdisk(%lu)partition(%lu)",
DiskNumber, PartitionNumber);
if (PathComponent && *PathComponent &&
(PathComponent[0] != L'\\' || PathComponent[1]))
{
RtlStringCchCatW(BootPathBuffer, _countof(BootPathBuffer),
PathComponent);
}
}
else
{
PCWSTR Path = BootPath;
if ((_wcsnicmp(Path, L"\\Device\\Floppy", 14) == 0) &&
(Path += 14) && iswdigit(*Path))
{
DiskNumber = wcstoul(Path, (PWSTR*)&PathComponent, 10);
if (PathComponent && *PathComponent && *PathComponent != L'\\')
PathComponent = NULL;
/* HACK-build a possible ARC path:
* Floppy disk path: multi(0)disk(0)fdisk(x)[\path] */
RtlStringCchPrintfW(BootPathBuffer, _countof(BootPathBuffer),
L"multi(0)disk(0)fdisk(%lu)", DiskNumber);
if (PathComponent && *PathComponent &&
(PathComponent[0] != L'\\' || PathComponent[1]))
{
RtlStringCchCatW(BootPathBuffer, _countof(BootPathBuffer),
PathComponent);
}
}
else
{
/* HACK: Just keep the unresolved NT path and hope for the best... */
/* Remove any trailing backslash if needed */
UNICODE_STRING RootPartition;
RtlInitUnicodeString(&RootPartition, BootPath);
TrimTrailingPathSeparators_UStr(&RootPartition);
/* RootPartition is BootPath without counting any trailing
* path separator. Because of this, we need to copy the string
* in the buffer, instead of just using a pointer to it. */
RtlStringCchPrintfW(BootPathBuffer, _countof(BootPathBuffer),
L"%wZ", &RootPartition);
DPRINT1("Unhandled NT path '%S'\n", BootPath);
}
}
/* Initialize the INI file and create the common FreeLdr sections */
Status = OpenBootStore(&BootStoreHandle, IniPath, FreeLdr,
@ -211,14 +276,13 @@ CreateFreeLoaderIniForReactOSAndBootSector(
BootEntry->Version = FreeLdr;
BootEntry->BootFilePath = NULL;
BootEntry->OsOptionsLength = sizeof(BOOT_SECTOR_OPTIONS);
BootEntry->OsOptionsLength = sizeof(BOOTSECTOR_OPTIONS);
RtlCopyMemory(Options->Signature,
BOOT_SECTOR_OPTIONS_SIGNATURE,
RTL_FIELD_SIZE(BOOT_SECTOR_OPTIONS, Signature));
BOOTSECTOR_OPTIONS_SIGNATURE,
RTL_FIELD_SIZE(BOOTSECTOR_OPTIONS, Signature));
Options->Drive = BootDrive;
Options->Partition = BootPartition;
Options->BootSectorFileName = BootSector;
Options->BootPath = BootPathBuffer;
Options->FileName = BootSector;
// BootEntry->BootEntryKey = MAKESTRKEY(Section);
BootEntry->FriendlyName = Description;
@ -933,8 +997,6 @@ InstallFatBootcodeToPartition(
PCWSTR Section;
PCWSTR Description;
PCWSTR BootDrive;
PCWSTR BootPartition;
PCWSTR BootSector;
/* Search for COMPAQ MS-DOS 1.x (1.11, 1.12, based on MS-DOS 1.25) boot loader */
@ -943,11 +1005,9 @@ InstallFatBootcodeToPartition(
{
DPRINT1("Found COMPAQ MS-DOS 1.x (1.11, 1.12) / MS-DOS 1.25 boot loader\n");
Section = L"CPQDOS";
Description = L"\"COMPAQ MS-DOS 1.x / MS-DOS 1.25\"";
BootDrive = L"hd0";
BootPartition = L"1";
BootSector = L"BOOTSECT.DOS";
Section = L"CPQDOS";
Description = L"\"COMPAQ MS-DOS 1.x / MS-DOS 1.25\"";
BootSector = L"BOOTSECT.DOS";
}
else
/* Search for Microsoft DOS or Windows 9x boot loader */
@ -957,11 +1017,9 @@ InstallFatBootcodeToPartition(
{
DPRINT1("Found Microsoft DOS or Windows 9x boot loader\n");
Section = L"MSDOS";
Description = L"\"MS-DOS/Windows\"";
BootDrive = L"hd0";
BootPartition = L"1";
BootSector = L"BOOTSECT.DOS";
Section = L"MSDOS";
Description = L"\"MS-DOS/Windows\"";
BootSector = L"BOOTSECT.DOS";
}
else
/* Search for IBM PC-DOS or DR-DOS 5.x boot loader */
@ -971,11 +1029,9 @@ InstallFatBootcodeToPartition(
{
DPRINT1("Found IBM PC-DOS or DR-DOS 5.x or IBM OS/2 1.0\n");
Section = L"IBMDOS";
Description = L"\"IBM PC-DOS or DR-DOS 5.x or IBM OS/2 1.0\"";
BootDrive = L"hd0";
BootPartition = L"1";
BootSector = L"BOOTSECT.DOS";
Section = L"IBMDOS";
Description = L"\"IBM PC-DOS or DR-DOS 5.x or IBM OS/2 1.0\"";
BootSector = L"BOOTSECT.DOS";
}
else
/* Search for DR-DOS 3.x boot loader */
@ -984,11 +1040,9 @@ InstallFatBootcodeToPartition(
{
DPRINT1("Found DR-DOS 3.x\n");
Section = L"DRDOS";
Description = L"\"DR-DOS 3.x\"";
BootDrive = L"hd0";
BootPartition = L"1";
BootSector = L"BOOTSECT.DOS";
Section = L"DRDOS";
Description = L"\"DR-DOS 3.x\"";
BootSector = L"BOOTSECT.DOS";
}
else
/* Search for Dell Real-Mode Kernel (DRMK) OS */
@ -997,11 +1051,9 @@ InstallFatBootcodeToPartition(
{
DPRINT1("Found Dell Real-Mode Kernel OS\n");
Section = L"DRMK";
Description = L"\"Dell Real-Mode Kernel OS\"";
BootDrive = L"hd0";
BootPartition = L"1";
BootSector = L"BOOTSECT.DOS";
Section = L"DRMK";
Description = L"\"Dell Real-Mode Kernel OS\"";
BootSector = L"BOOTSECT.DOS";
}
else
/* Search for MS OS/2 1.x */
@ -1011,11 +1063,9 @@ InstallFatBootcodeToPartition(
{
DPRINT1("Found MS OS/2 1.x\n");
Section = L"MSOS2";
Description = L"\"MS OS/2 1.x\"";
BootDrive = L"hd0";
BootPartition = L"1";
BootSector = L"BOOTSECT.OS2";
Section = L"MSOS2";
Description = L"\"MS OS/2 1.x\"";
BootSector = L"BOOTSECT.OS2";
}
else
/* Search for MS or IBM OS/2 */
@ -1025,11 +1075,9 @@ InstallFatBootcodeToPartition(
{
DPRINT1("Found MS/IBM OS/2\n");
Section = L"IBMOS2";
Description = L"\"MS/IBM OS/2\"";
BootDrive = L"hd0";
BootPartition = L"1";
BootSector = L"BOOTSECT.OS2";
Section = L"IBMOS2";
Description = L"\"MS/IBM OS/2\"";
BootSector = L"BOOTSECT.OS2";
}
else
/* Search for FreeDOS boot loader */
@ -1037,22 +1085,18 @@ InstallFatBootcodeToPartition(
{
DPRINT1("Found FreeDOS boot loader\n");
Section = L"FDOS";
Description = L"\"FreeDOS\"";
BootDrive = L"hd0";
BootPartition = L"1";
BootSector = L"BOOTSECT.DOS";
Section = L"FDOS";
Description = L"\"FreeDOS\"";
BootSector = L"BOOTSECT.DOS";
}
else
{
/* No or unknown boot loader */
DPRINT1("No or unknown boot loader found\n");
Section = L"Unknown";
Description = L"\"Unknown Operating System\"";
BootDrive = L"hd0";
BootPartition = L"1";
BootSector = L"BOOTSECT.OLD";
Section = L"Unknown";
Description = L"\"Unknown Operating System\"";
BootSector = L"BOOTSECT.OLD";
}
/* Create or update 'freeldr.ini' */
@ -1066,7 +1110,7 @@ InstallFatBootcodeToPartition(
Status = CreateFreeLoaderIniForReactOSAndBootSector(
SystemRootPath->Buffer, DestinationArcPath->Buffer,
Section, Description,
BootDrive, BootPartition, BootSector);
SystemRootPath->Buffer, BootSector);
if (!NT_SUCCESS(Status))
{
DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status);
@ -1187,7 +1231,7 @@ InstallBtrfsBootcodeToPartition(
Status = CreateFreeLoaderIniForReactOSAndBootSector(
SystemRootPath->Buffer, DestinationArcPath->Buffer,
L"Linux", L"\"Linux\"",
L"hd0", L"1", BootSector);
SystemRootPath->Buffer, BootSector);
if (!NT_SUCCESS(Status))
{
DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status);
@ -1288,7 +1332,7 @@ InstallNtfsBootcodeToPartition(
Status = CreateFreeLoaderIniForReactOSAndBootSector(
SystemRootPath->Buffer, DestinationArcPath->Buffer,
L"Linux", L"\"Linux\"",
L"hd0", L"1", BootSector);
SystemRootPath->Buffer, BootSector);
if (!NT_SUCCESS(Status))
{
DPRINT1("CreateFreeLoaderIniForReactOSAndBootSector() failed (Status %lx)\n", Status);

View file

@ -211,6 +211,163 @@ FindBootStore( // By handle
}
//
// TEMPORARY functions to migrate the DEPRECATED BootDrive and BootPartition
// values of BootSector boot entries in FREELDR.INI to the newer BootPath value.
//
// REMOVE THEM once they won't be necessary anymore,
// after the removal of their support in FreeLoader!
//
static VOID
FreeLdrMigrateBootDrivePartWorker(
_In_ PINI_SECTION OsIniSection)
{
PCWSTR KeyData;
PINI_KEYWORD OldKey;
/*
* Check whether we have a "BootPath" value (takes precedence
* over both "BootDrive" and "BootPartition").
*/
if (IniGetKey(OsIniSection, L"BootPath", &KeyData) && KeyData && *KeyData)
{
/* We already have a BootPath value, do nothing more */
return;
}
/* We don't have one: retrieve the BIOS drive and
* partition and convert them to a valid ARC path */
/* Retrieve the boot drive */
OldKey = IniGetKey(OsIniSection, L"BootDrive", &KeyData);
if (OldKey)
{
PCWSTR OldDrive = KeyData;
ULONG DriveNumber = 0;
ULONG PartitionNumber = 0;
UCHAR DriveType = 0;
WCHAR BufferBootPath[80]; // 80 chars is enough for "multi(0)disk(0)rdisk(x)partition(y)", with (x,y) == MAXULONG
/* If a number string is given, then just
* convert it to decimal (BIOS HW only) */
PCWCH p = KeyData;
if (p[0] >= L'0' && p[0] <= L'9')
{
DriveNumber = wcstoul(p, (PWCHAR*)&p, 0);
if (DriveNumber >= 0x80)
{
/* It's quite probably a hard disk */
DriveNumber -= 0x80;
DriveType = L'h';
}
else
{
/* It's quite probably a floppy */
DriveType = L'f';
}
}
else if (p[0] && towlower(p[1]) == L'd')
{
/* Convert the drive number string into a number: 'hd1' = 1 */
DriveType = tolower(p[0]);
DriveNumber = _wtoi(&p[2]);
}
/* Retrieve the boot partition (optional, fall back to zero otherwise) */
if (IniGetKey(OsIniSection, L"BootPartition", &KeyData))
PartitionNumber = _wtoi(KeyData);
if (DriveType == L'f')
{
/* Floppy disk path: multi(0)disk(0)fdisk(x) */
RtlStringCchPrintfW(BufferBootPath, _countof(BufferBootPath),
L"multi(0)disk(0)fdisk(%lu)", DriveNumber);
}
else if (DriveType == L'h')
{
/* Hard disk path: multi(0)disk(0)rdisk(x)partition(y) */
RtlStringCchPrintfW(BufferBootPath, _countof(BufferBootPath),
L"multi(0)disk(0)rdisk(%lu)partition(%lu)",
DriveNumber, PartitionNumber);
}
else if (DriveType == L'c')
{
/* CD-ROM disk path: multi(0)disk(0)cdrom(x) */
RtlStringCchPrintfW(BufferBootPath, _countof(BufferBootPath),
L"multi(0)disk(0)cdrom(%lu)", DriveNumber);
}
else
{
/* This case should rarely happen, if ever */
DPRINT1("Unrecognized BootDrive type '%C'\n", DriveType ? DriveType : L'?');
/* Build the boot path in the form: hdX,Y */
RtlStringCchCopyW(BufferBootPath, _countof(BufferBootPath), OldDrive);
if (KeyData && *KeyData)
{
RtlStringCchCatW(BufferBootPath, _countof(BufferBootPath), L",");
RtlStringCchCatW(BufferBootPath, _countof(BufferBootPath), KeyData);
}
}
/* Add the new BootPath value */
IniInsertKey(OsIniSection, OldKey, INSERT_BEFORE, L"BootPath", BufferBootPath);
}
/* Delete the deprecated BootDrive and BootPartition values */
IniRemoveKeyByName(OsIniSection, L"BootDrive");
IniRemoveKeyByName(OsIniSection, L"BootPartition");
}
static VOID
FreeLdrMigrateBootDrivePart(
_In_ PBOOT_STORE_INI_CONTEXT BootStore)
{
PINICACHEITERATOR Iterator;
PINI_SECTION OsIniSection;
PCWSTR SectionName, KeyData;
/* Enumerate all the valid entries in the "Operating Systems" section */
Iterator = IniFindFirstValue(BootStore->OsIniSection, &SectionName, &KeyData);
if (!Iterator) return;
do
{
/* Search for an existing boot entry section */
OsIniSection = IniGetSection(BootStore->IniCache, SectionName);
if (!OsIniSection)
continue;
/* Check for boot type to migrate */
if (!IniGetKey(OsIniSection, L"BootType", &KeyData) || !KeyData)
{
/* Certainly not a ReactOS installation */
DPRINT1("No BootType value present\n");
continue;
}
if ((_wcsicmp(KeyData, L"Drive") == 0) ||
(_wcsicmp(KeyData, L"\"Drive\"") == 0) ||
(_wcsicmp(KeyData, L"Partition") == 0) ||
(_wcsicmp(KeyData, L"\"Partition\"") == 0))
{
/* Modify the BootPath value */
IniAddKey(OsIniSection, L"BootType", L"BootSector");
goto migrate_drivepart;
}
if ((_wcsicmp(KeyData, L"BootSector") == 0) ||
(_wcsicmp(KeyData, L"\"BootSector\"") == 0))
{
migrate_drivepart:
DPRINT("This is a '%S' boot entry\n", KeyData);
FreeLdrMigrateBootDrivePartWorker(OsIniSection);
}
}
while (IniFindNextValue(Iterator, &SectionName, &KeyData));
IniFindClose(Iterator);
}
//////////////
static VOID
CreateCommonFreeLdrSections(
IN OUT PBOOT_STORE_INI_CONTEXT BootStore)
@ -514,6 +671,12 @@ OpenIniBootLoaderStore(
DPRINT1("OpenIniBootLoaderStore: Failed to retrieve 'Operating Systems' section!\n");
BootStore->OsIniSection = IniSection;
//
// TEMPORARY: Migrate the DEPRECATED BootDrive and BootPartition
// values of BootSector boot entries to the newer BootPath value.
//
FreeLdrMigrateBootDrivePart(BootStore);
}
else
if (Type == NtLdr)
@ -868,7 +1031,6 @@ CloseBootStore(
}
static
NTSTATUS
CreateNTOSEntry(
@ -899,19 +1061,18 @@ CreateNTOSEntry(
IniAddKey(IniSection, L"Options", Options->OsLoadOptions);
}
else
if (BootEntry->OsOptionsLength >= sizeof(BOOT_SECTOR_OPTIONS) &&
if (BootEntry->OsOptionsLength >= sizeof(BOOTSECTOR_OPTIONS) &&
RtlCompareMemory(&BootEntry->OsOptions /* Signature */,
BOOT_SECTOR_OPTIONS_SIGNATURE,
RTL_FIELD_SIZE(BOOT_SECTOR_OPTIONS, Signature)) ==
RTL_FIELD_SIZE(BOOT_SECTOR_OPTIONS, Signature))
BOOTSECTOR_OPTIONS_SIGNATURE,
RTL_FIELD_SIZE(BOOTSECTOR_OPTIONS, Signature)) ==
RTL_FIELD_SIZE(BOOTSECTOR_OPTIONS, Signature))
{
PBOOT_SECTOR_OPTIONS Options = (PBOOT_SECTOR_OPTIONS)&BootEntry->OsOptions;
PBOOTSECTOR_OPTIONS Options = (PBOOTSECTOR_OPTIONS)&BootEntry->OsOptions;
/* BootType, BootDrive, BootPartition and BootSector */
/* BootType, BootPath and BootSector */
IniAddKey(IniSection, L"BootType", L"BootSector");
IniAddKey(IniSection, L"BootDrive", Options->Drive);
IniAddKey(IniSection, L"BootPartition", Options->Partition);
IniAddKey(IniSection, L"BootSectorFile", Options->BootSectorFileName);
IniAddKey(IniSection, L"BootPath", Options->BootPath);
IniAddKey(IniSection, L"BootSectorFile", Options->FileName);
}
else
{
@ -1237,7 +1398,6 @@ SetBootStoreOptions(
}
static NTSTATUS
FreeLdrEnumerateBootEntries(
IN PBOOT_STORE_INI_CONTEXT BootStore,
@ -1250,7 +1410,7 @@ FreeLdrEnumerateBootEntries(
PINI_SECTION OsIniSection;
PCWSTR SectionName, KeyData;
UCHAR xxBootEntry[FIELD_OFFSET(BOOT_STORE_ENTRY, OsOptions) +
max(sizeof(NTOS_OPTIONS), sizeof(BOOT_SECTOR_OPTIONS))];
max(sizeof(NTOS_OPTIONS), sizeof(BOOTSECTOR_OPTIONS))];
PBOOT_STORE_ENTRY BootEntry = (PBOOT_STORE_ENTRY)&xxBootEntry;
PWCHAR Buffer;
@ -1318,7 +1478,7 @@ FreeLdrEnumerateBootEntries(
if (!IniGetKey(OsIniSection, L"BootType", &KeyData) || !KeyData)
{
/* Certainly not a ReactOS installation */
DPRINT1("No BootType value present!\n");
DPRINT1("No BootType value present\n");
goto DoEnum;
}
@ -1354,31 +1514,26 @@ FreeLdrEnumerateBootEntries(
(_wcsicmp(KeyData, L"\"BootSector\"") == 0))
{
/* BootType is BootSector */
PBOOT_SECTOR_OPTIONS Options = (PBOOT_SECTOR_OPTIONS)&BootEntry->OsOptions;
PBOOTSECTOR_OPTIONS Options = (PBOOTSECTOR_OPTIONS)&BootEntry->OsOptions;
DPRINT("This is a '%S' boot entry\n", KeyData);
BootEntry->OsOptionsLength = sizeof(BOOT_SECTOR_OPTIONS);
BootEntry->OsOptionsLength = sizeof(BOOTSECTOR_OPTIONS);
RtlCopyMemory(Options->Signature,
BOOT_SECTOR_OPTIONS_SIGNATURE,
RTL_FIELD_SIZE(BOOT_SECTOR_OPTIONS, Signature));
BOOTSECTOR_OPTIONS_SIGNATURE,
RTL_FIELD_SIZE(BOOTSECTOR_OPTIONS, Signature));
// BootEntry->BootFilePath = NULL;
/* Check its BootDrive */
Options->Drive = NULL;
if (IniGetKey(OsIniSection, L"BootDrive", &KeyData))
Options->Drive = KeyData;
/* Check its BootPartition */
Options->Partition = NULL;
if (IniGetKey(OsIniSection, L"BootPartition", &KeyData))
Options->Partition = KeyData;
/* Check its BootPath */
Options->BootPath = NULL;
if (IniGetKey(OsIniSection, L"BootPath", &KeyData))
Options->BootPath = KeyData;
/* Check its BootSector */
Options->BootSectorFileName = NULL;
Options->FileName = NULL;
if (IniGetKey(OsIniSection, L"BootSectorFile", &KeyData))
Options->BootSectorFileName = KeyData;
Options->FileName = KeyData;
}
else
{

View file

@ -102,17 +102,16 @@ typedef struct _NTOS_OPTIONS
#define NTOS_OPTIONS_SIGNATURE "NTOS_5\0\0"
/* Options for boot-sector boot entries */
typedef struct _BOOT_SECTOR_OPTIONS
typedef struct _BOOTSECTOR_OPTIONS
{
UCHAR Signature[8]; // "BootSect"
// ULONG Version;
// ULONG Length;
PCWSTR Drive;
PCWSTR Partition;
PCWSTR BootSectorFileName;
} BOOT_SECTOR_OPTIONS, *PBOOT_SECTOR_OPTIONS;
PCWSTR BootPath;
PCWSTR FileName;
} BOOTSECTOR_OPTIONS, *PBOOTSECTOR_OPTIONS;
#define BOOT_SECTOR_OPTIONS_SIGNATURE "BootSect"
#define BOOTSECTOR_OPTIONS_SIGNATURE "BootSect"
typedef NTSTATUS