diff --git a/base/setup/lib/bootsup.c b/base/setup/lib/bootsup.c index f02fd571f3c..313c006b93f 100644 --- a/base/setup/lib/bootsup.c +++ b/base/setup/lib/bootsup.c @@ -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); diff --git a/base/setup/lib/utils/bldrsup.c b/base/setup/lib/utils/bldrsup.c index 966da4afea9..af3acfd042c 100644 --- a/base/setup/lib/utils/bldrsup.c +++ b/base/setup/lib/utils/bldrsup.c @@ -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 { diff --git a/base/setup/lib/utils/bldrsup.h b/base/setup/lib/utils/bldrsup.h index edefad6464c..4496cbbea3d 100644 --- a/base/setup/lib/utils/bldrsup.h +++ b/base/setup/lib/utils/bldrsup.h @@ -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