From 3995cce1bac1b66f7e5be1dcf5807eb6d5919cc3 Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Mon, 6 Sep 2010 01:46:06 +0000 Subject: [PATCH] [USETUP] The VBR (volume boot sector) contains a structure called BPB (bios parameter block) that describes the disk and the partition. The HiddenSectors member contains the number of the first sector of the partition. This is used by the VBR code to load the secondary sector containing additional boot code that is located at secor 14 relative to the partition start. Previously we were copying the BPB (plus additionally the OemName, which makes no sense) from the old VBR. Now Linux is a bit lame and doesn't put the correct value into the HiddenSectors field. Instead it sets it to the number of sectors per track which seems to be the default value. When now the linux partition manager decides to do a non standard partitioning, aligning the partition to 0x800, then the VBR fails to load it's 2nd sector. Fix this by correcting the value in the BPB with the value from the partition info. See issue #2733 for more details. svn path=/trunk/; revision=48706 --- reactos/base/setup/usetup/bootsup.c | 163 ++++++++++++++----- reactos/base/setup/usetup/interface/usetup.c | 3 +- 2 files changed, 121 insertions(+), 45 deletions(-) diff --git a/reactos/base/setup/usetup/bootsup.c b/reactos/base/setup/usetup/bootsup.c index 780d96a2e99..3f880c97feb 100644 --- a/reactos/base/setup/usetup/bootsup.c +++ b/reactos/base/setup/usetup/bootsup.c @@ -31,6 +31,75 @@ #define SECTORSIZE 512 +#include +typedef struct _FAT_BOOTSECTOR +{ + UCHAR JumpBoot[3]; // Jump instruction to boot code + CHAR OemName[8]; // "MSWIN4.1" for MS formatted volumes + USHORT BytesPerSector; // Bytes per sector + UCHAR SectorsPerCluster; // Number of sectors in a cluster + USHORT ReservedSectors; // Reserved sectors, usually 1 (the bootsector) + UCHAR NumberOfFats; // Number of FAT tables + USHORT RootDirEntries; // Number of root directory entries (fat12/16) + USHORT TotalSectors; // Number of total sectors on the drive, 16-bit + UCHAR MediaDescriptor; // Media descriptor byte + USHORT SectorsPerFat; // Sectors per FAT table (fat12/16) + USHORT SectorsPerTrack; // Number of sectors in a track + USHORT NumberOfHeads; // Number of heads on the disk + ULONG HiddenSectors; // Hidden sectors (sectors before the partition start like the partition table) + ULONG TotalSectorsBig; // This field is the new 32-bit total count of sectors on the volume + UCHAR DriveNumber; // Int 0x13 drive number (e.g. 0x80) + UCHAR Reserved1; // Reserved (used by Windows NT). Code that formats FAT volumes should always set this byte to 0. + UCHAR BootSignature; // Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present. + ULONG VolumeSerialNumber; // Volume serial number + CHAR VolumeLabel[11]; // Volume label. This field matches the 11-byte volume label recorded in the root directory + CHAR FileSystemType[8]; // One of the strings "FAT12 ", "FAT16 ", or "FAT " + + UCHAR BootCodeAndData[448]; // The remainder of the boot sector + + USHORT BootSectorMagic; // 0xAA55 + +} FAT_BOOTSECTOR, *PFAT_BOOTSECTOR; + +typedef struct _FAT32_BOOTSECTOR +{ + UCHAR JumpBoot[3]; // Jump instruction to boot code + CHAR OemName[8]; // "MSWIN4.1" for MS formatted volumes + USHORT BytesPerSector; // Bytes per sector + UCHAR SectorsPerCluster; // Number of sectors in a cluster + USHORT ReservedSectors; // Reserved sectors, usually 1 (the bootsector) + UCHAR NumberOfFats; // Number of FAT tables + USHORT RootDirEntries; // Number of root directory entries (fat12/16) + USHORT TotalSectors; // Number of total sectors on the drive, 16-bit + UCHAR MediaDescriptor; // Media descriptor byte + USHORT SectorsPerFat; // Sectors per FAT table (fat12/16) + USHORT SectorsPerTrack; // Number of sectors in a track + USHORT NumberOfHeads; // Number of heads on the disk + ULONG HiddenSectors; // Hidden sectors (sectors before the partition start like the partition table) + ULONG TotalSectorsBig; // This field is the new 32-bit total count of sectors on the volume + ULONG SectorsPerFatBig; // This field is the FAT32 32-bit count of sectors occupied by ONE FAT. BPB_FATSz16 must be 0 + USHORT ExtendedFlags; // Extended flags (fat32) + USHORT FileSystemVersion; // File system version (fat32) + ULONG RootDirStartCluster; // Starting cluster of the root directory (fat32) + USHORT FsInfo; // Sector number of FSINFO structure in the reserved area of the FAT32 volume. Usually 1. + USHORT BackupBootSector; // If non-zero, indicates the sector number in the reserved area of the volume of a copy of the boot record. Usually 6. + UCHAR Reserved[12]; // Reserved for future expansion + UCHAR DriveNumber; // Int 0x13 drive number (e.g. 0x80) + UCHAR Reserved1; // Reserved (used by Windows NT). Code that formats FAT volumes should always set this byte to 0. + UCHAR BootSignature; // Extended boot signature (0x29). This is a signature byte that indicates that the following three fields in the boot sector are present. + ULONG VolumeSerialNumber; // Volume serial number + CHAR VolumeLabel[11]; // Volume label. This field matches the 11-byte volume label recorded in the root directory + CHAR FileSystemType[8]; // Always set to the string "FAT32 " + + UCHAR BootCodeAndData[420]; // The remainder of the boot sector + + USHORT BootSectorMagic; // 0xAA55 + +} FAT32_BOOTSECTOR, *PFAT32_BOOTSECTOR; +#include + +extern PPARTLIST PartitionList; + /* FUNCTIONS ****************************************************************/ @@ -1094,53 +1163,53 @@ NTSTATUS InstallMbrBootCodeToDisk (PWSTR SrcPath, PWSTR RootPath) { - OBJECT_ATTRIBUTES ObjectAttributes; - IO_STATUS_BLOCK IoStatusBlock; - UNICODE_STRING Name; - HANDLE FileHandle; - NTSTATUS Status; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING Name; + HANDLE FileHandle; + NTSTATUS Status; PPARTITION_SECTOR OrigBootSector; PPARTITION_SECTOR NewBootSector; - /* Allocate buffer for original bootsector */ + /* Allocate buffer for original bootsector */ OrigBootSector = (PPARTITION_SECTOR)RtlAllocateHeap(ProcessHeap, 0, sizeof(PARTITION_SECTOR)); if (OrigBootSector == NULL) return(STATUS_INSUFFICIENT_RESOURCES); - /* Read current boot sector into buffer */ + /* Read current boot sector into buffer */ RtlInitUnicodeString(&Name, RootPath); - InitializeObjectAttributes(&ObjectAttributes, - &Name, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); + InitializeObjectAttributes(&ObjectAttributes, + &Name, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); - Status = NtOpenFile(&FileHandle, - GENERIC_READ, - &ObjectAttributes, - &IoStatusBlock, - 0, - FILE_SYNCHRONOUS_IO_NONALERT); + Status = NtOpenFile(&FileHandle, + GENERIC_READ, + &ObjectAttributes, + &IoStatusBlock, + 0, + FILE_SYNCHRONOUS_IO_NONALERT); if (!NT_SUCCESS(Status)) { RtlFreeHeap(ProcessHeap, 0, OrigBootSector); return(Status); } - Status = NtReadFile(FileHandle, - NULL, - NULL, - NULL, - &IoStatusBlock, + Status = NtReadFile(FileHandle, + NULL, + NULL, + NULL, + &IoStatusBlock, OrigBootSector, - SECTORSIZE, - NULL, - NULL); - NtClose(FileHandle); + SECTORSIZE, + NULL, + NULL); + NtClose(FileHandle); if (!NT_SUCCESS(Status)) { RtlFreeHeap(ProcessHeap, 0, OrigBootSector); @@ -1256,11 +1325,12 @@ InstallFat16BootCodeToDisk(PWSTR SrcPath, UNICODE_STRING Name; HANDLE FileHandle; NTSTATUS Status; - PUCHAR OrigBootSector; - PUCHAR NewBootSector; + PFAT_BOOTSECTOR OrigBootSector; + PFAT_BOOTSECTOR NewBootSector; + PARTITION_INFORMATION *PartInfo; /* Allocate buffer for original bootsector */ - OrigBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap, + OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE); if (OrigBootSector == NULL) @@ -1306,7 +1376,7 @@ InstallFat16BootCodeToDisk(PWSTR SrcPath, /* Allocate buffer for new bootsector */ - NewBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap, + NewBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE); if (NewBootSector == NULL) @@ -1356,9 +1426,12 @@ InstallFat16BootCodeToDisk(PWSTR SrcPath, } /* Adjust bootsector (copy a part of the FAT16 BPB) */ - memcpy((NewBootSector + 3), - (OrigBootSector + 3), - 59); /* FAT16 BPB length*/ + memcpy(&NewBootSector->BytesPerSector, + &OrigBootSector->BytesPerSector, + 51); /* FAT16 BPB length */ + + PartInfo = &PartitionList->CurrentPartition->PartInfo[PartitionList->CurrentPartitionNumber]; + NewBootSector->HiddenSectors = PartInfo->HiddenSectors; /* Free the original boot sector */ RtlFreeHeap(ProcessHeap, 0, OrigBootSector); @@ -1416,13 +1489,14 @@ InstallFat32BootCodeToDisk(PWSTR SrcPath, UNICODE_STRING Name; HANDLE FileHandle; NTSTATUS Status; - PUCHAR OrigBootSector; - PUCHAR NewBootSector; + PFAT32_BOOTSECTOR OrigBootSector; + PFAT32_BOOTSECTOR NewBootSector; LARGE_INTEGER FileOffset; USHORT BackupBootSector; + PARTITION_INFORMATION *PartInfo; /* Allocate buffer for original bootsector */ - OrigBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap, + OrigBootSector = RtlAllocateHeap(ProcessHeap, 0, SECTORSIZE); if (OrigBootSector == NULL) @@ -1468,7 +1542,7 @@ InstallFat32BootCodeToDisk(PWSTR SrcPath, /* Allocate buffer for new bootsector (2 sectors) */ - NewBootSector = (PUCHAR)RtlAllocateHeap(ProcessHeap, + NewBootSector = RtlAllocateHeap(ProcessHeap, 0, 2 * SECTORSIZE); if (NewBootSector == NULL) @@ -1518,12 +1592,15 @@ InstallFat32BootCodeToDisk(PWSTR SrcPath, } /* Adjust bootsector (copy a part of the FAT32 BPB) */ - memcpy((NewBootSector + 3), - (OrigBootSector + 3), - 87); /* FAT32 BPB length */ + memcpy(&NewBootSector->BytesPerSector, + &OrigBootSector->BytesPerSector, + 79); /* FAT32 BPB length */ + + PartInfo = &PartitionList->CurrentPartition->PartInfo[PartitionList->CurrentPartitionNumber]; + NewBootSector->HiddenSectors = PartInfo->HiddenSectors; /* Get the location of the backup boot sector */ - BackupBootSector = (OrigBootSector[0x33] << 8) + OrigBootSector[0x32]; + BackupBootSector = OrigBootSector->BackupBootSector; /* Free the original boot sector */ RtlFreeHeap(ProcessHeap, 0, OrigBootSector); @@ -1599,7 +1676,7 @@ InstallFat32BootCodeToDisk(PWSTR SrcPath, NULL, NULL, &IoStatusBlock, - (NewBootSector + SECTORSIZE), + ((PUCHAR)NewBootSector + SECTORSIZE), SECTORSIZE, &FileOffset, NULL); diff --git a/reactos/base/setup/usetup/interface/usetup.c b/reactos/base/setup/usetup/interface/usetup.c index 2faad50456b..607ed4e96c1 100644 --- a/reactos/base/setup/usetup/interface/usetup.c +++ b/reactos/base/setup/usetup/interface/usetup.c @@ -51,11 +51,10 @@ WCHAR DefaultLanguage[20]; WCHAR DefaultKBLayout[20]; BOOLEAN RepairUpdateFlag = FALSE; HANDLE hPnpThread = INVALID_HANDLE_VALUE; +PPARTLIST PartitionList = NULL; /* LOCALS *******************************************************************/ -static PPARTLIST PartitionList = NULL; - static PFILE_SYSTEM_LIST FileSystemList = NULL; static UNICODE_STRING InstallPath;