static VOID GetHarddiskIdentifier(PCHAR Identifier, UCHAR DriveNumber) { PMASTER_BOOT_RECORD Mbr; ULONG *Buffer; ULONG i; ULONG Checksum; ULONG Signature; CHAR ArcName[256]; PARTITION_TABLE_ENTRY PartitionTableEntry; /* Read the MBR */ if (!MachDiskReadLogicalSectors(DriveNumber, 0ULL, 1, (PVOID)DISKREADBUFFER)) { ERR("Reading MBR failed\n"); return; } Buffer = (ULONG*)DISKREADBUFFER; Mbr = (PMASTER_BOOT_RECORD)DISKREADBUFFER; Signature = Mbr->Signature; TRACE("Signature: %x\n", Signature); /* Calculate the MBR checksum */ Checksum = 0; for (i = 0; i < 128; i++) { Checksum += Buffer[i]; } Checksum = ~Checksum + 1; TRACE("Checksum: %x\n", Checksum); /* Fill out the ARC disk block */ odyssey_arc_disk_info[odyssey_disk_count].Signature = Signature; odyssey_arc_disk_info[odyssey_disk_count].CheckSum = Checksum; sprintf(ArcName, "multi(0)disk(0)rdisk(%lu)", odyssey_disk_count); strcpy(odyssey_arc_strings[odyssey_disk_count], ArcName); odyssey_arc_disk_info[odyssey_disk_count].ArcName = odyssey_arc_strings[odyssey_disk_count]; odyssey_disk_count++; sprintf(ArcName, "multi(0)disk(0)rdisk(%u)partition(0)", DriveNumber - 0x80); FsRegisterDevice(ArcName, &DiskVtbl); /* Add partitions */ i = 1; DiskReportError(FALSE); while (XboxDiskGetPartitionEntry(DriveNumber, i, &PartitionTableEntry)) { if (PartitionTableEntry.SystemIndicator != PARTITION_ENTRY_UNUSED) { sprintf(ArcName, "multi(0)disk(0)rdisk(%u)partition(%lu)", DriveNumber - 0x80, i); FsRegisterDevice(ArcName, &DiskVtbl); } i++; } DiskReportError(TRUE); /* Convert checksum and signature to identifier string */ Identifier[0] = Hex[(Checksum >> 28) & 0x0F]; Identifier[1] = Hex[(Checksum >> 24) & 0x0F]; Identifier[2] = Hex[(Checksum >> 20) & 0x0F]; Identifier[3] = Hex[(Checksum >> 16) & 0x0F]; Identifier[4] = Hex[(Checksum >> 12) & 0x0F]; Identifier[5] = Hex[(Checksum >> 8) & 0x0F]; Identifier[6] = Hex[(Checksum >> 4) & 0x0F]; Identifier[7] = Hex[Checksum & 0x0F]; Identifier[8] = '-'; Identifier[9] = Hex[(Signature >> 28) & 0x0F]; Identifier[10] = Hex[(Signature >> 24) & 0x0F]; Identifier[11] = Hex[(Signature >> 20) & 0x0F]; Identifier[12] = Hex[(Signature >> 16) & 0x0F]; Identifier[13] = Hex[(Signature >> 12) & 0x0F]; Identifier[14] = Hex[(Signature >> 8) & 0x0F]; Identifier[15] = Hex[(Signature >> 4) & 0x0F]; Identifier[16] = Hex[Signature & 0x0F]; Identifier[17] = '-'; Identifier[18] = 'A'; Identifier[19] = 0; TRACE("Identifier: %s\n", Identifier); }
static VOID DetectBiosDisks(PCONFIGURATION_COMPONENT_DATA SystemKey, PCONFIGURATION_COMPONENT_DATA BusKey) { PCM_PARTIAL_RESOURCE_LIST PartialResourceList; PCM_INT13_DRIVE_PARAMETER Int13Drives; GEOMETRY Geometry; PCONFIGURATION_COMPONENT_DATA DiskKey, ControllerKey; UCHAR DiskCount, i; ULONG Size; BOOLEAN Changed; /* Count the number of visible drives */ DiskReportError(FALSE); DiskCount = 0; /* There are some really broken BIOSes out there. There are even BIOSes * that happily report success when you ask them to read from non-existent * harddisks. So, we set the buffer to known contents first, then try to * read. If the BIOS reports success but the buffer contents haven't * changed then we fail anyway */ memset((PVOID) DISKREADBUFFER, 0xcd, 512); while (MachDiskReadLogicalSectors(0x80 + DiskCount, 0ULL, 1, (PVOID)DISKREADBUFFER)) { Changed = FALSE; for (i = 0; ! Changed && i < 512; i++) { Changed = ((PUCHAR)DISKREADBUFFER)[i] != 0xcd; } if (! Changed) { TRACE("BIOS reports success for disk %d but data didn't change\n", (int)DiskCount); break; } DiskCount++; memset((PVOID) DISKREADBUFFER, 0xcd, 512); } DiskReportError(TRUE); TRACE("BIOS reports %d harddisk%s\n", (int)DiskCount, (DiskCount == 1) ? "": "s"); //DetectBiosFloppyController(BusKey); /* Allocate resource descriptor */ Size = sizeof(CM_PARTIAL_RESOURCE_LIST) + sizeof(CM_INT13_DRIVE_PARAMETER) * DiskCount; PartialResourceList = MmHeapAlloc(Size); if (PartialResourceList == NULL) { ERR("Failed to allocate resource descriptor\n"); return; } /* Initialize resource descriptor */ memset(PartialResourceList, 0, Size); PartialResourceList->Version = 1; PartialResourceList->Revision = 1; PartialResourceList->Count = 1; PartialResourceList->PartialDescriptors[0].Type = CmResourceTypeDeviceSpecific; PartialResourceList->PartialDescriptors[0].ShareDisposition = 0; PartialResourceList->PartialDescriptors[0].Flags = 0; PartialResourceList->PartialDescriptors[0].u.DeviceSpecificData.DataSize = sizeof(CM_INT13_DRIVE_PARAMETER) * DiskCount; /* Get harddisk Int13 geometry data */ Int13Drives = (PVOID)(((ULONG_PTR)PartialResourceList) + sizeof(CM_PARTIAL_RESOURCE_LIST)); for (i = 0; i < DiskCount; i++) { if (MachDiskGetDriveGeometry(0x80 + i, &Geometry)) { Int13Drives[i].DriveSelect = 0x80 + i; Int13Drives[i].MaxCylinders = Geometry.Cylinders - 1; Int13Drives[i].SectorsPerTrack = (USHORT)Geometry.Sectors; Int13Drives[i].MaxHeads = (USHORT)Geometry.Heads - 1; Int13Drives[i].NumberDrives = DiskCount; TRACE( "Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n", 0x80 + i, Geometry.Cylinders - 1, Geometry.Heads -1, Geometry.Sectors, Geometry.BytesPerSector); } } FldrCreateComponentKey(BusKey, ControllerClass, DiskController, Output | Input, 0, 0xFFFFFFFF, NULL, PartialResourceList, Size, &ControllerKey); TRACE("Created key: DiskController\\0\n"); MmHeapFree(PartialResourceList); /* Create and fill subkey for each harddisk */ for (i = 0; i < DiskCount; i++) { PCM_PARTIAL_RESOURCE_LIST PartialResourceList; ULONG Size; CHAR Identifier[20]; /* Get disk values */ PartialResourceList = GetHarddiskConfigurationData(0x80 + i, &Size); GetHarddiskIdentifier(Identifier, 0x80 + i); /* Create disk key */ FldrCreateComponentKey(ControllerKey, PeripheralClass, DiskPeripheral, Output | Input, 0, 0xFFFFFFFF, Identifier, PartialResourceList, Size, &DiskKey); if (PartialResourceList) MmHeapFree(PartialResourceList); } }
BOOLEAN HwInitializeBiosDisks(VOID) { UCHAR DiskCount, DriveNumber; ULONG i; BOOLEAN Changed; CHAR BootPath[512]; BOOLEAN BootDriveReported = FALSE; /* Count the number of visible drives */ DiskReportError(FALSE); DiskCount = 0; DriveNumber = 0x80; /* There are some really broken BIOSes out there. There are even BIOSes * that happily report success when you ask them to read from non-existent * harddisks. So, we set the buffer to known contents first, then try to * read. If the BIOS reports success but the buffer contents haven't * changed then we fail anyway */ memset((PVOID) DISKREADBUFFER, 0xcd, 512); while (MachDiskReadLogicalSectors(DriveNumber, 0ULL, 1, (PVOID)DISKREADBUFFER)) { Changed = FALSE; for (i = 0; ! Changed && i < 512; i++) { Changed = ((PUCHAR)DISKREADBUFFER)[i] != 0xcd; } if (! Changed) { TRACE("BIOS reports success for disk %d but data didn't change\n", (int)DiskCount); break; } GetHarddiskInformation(DriveNumber); if (FrldrBootDrive == DriveNumber) BootDriveReported = TRUE; DiskCount++; DriveNumber++; memset((PVOID) DISKREADBUFFER, 0xcd, 512); } DiskReportError(TRUE); /* Get the drive we're booting from */ MachDiskGetBootPath(BootPath, sizeof(BootPath)); /* Add it, if it's a floppy or cdrom */ if ((FrldrBootDrive >= 0x80 && !BootDriveReported) || DiskIsDriveRemovable(FrldrBootDrive)) { /* TODO: Check if it's really a cdrom drive */ ULONG* Buffer; ULONG Checksum = 0; /* Read the MBR */ if (!MachDiskReadLogicalSectors(FrldrBootDrive, 16ULL, 1, (PVOID)DISKREADBUFFER)) { ERR("Reading MBR failed\n"); return FALSE; } Buffer = (ULONG*)DISKREADBUFFER; /* Calculate the MBR checksum */ for (i = 0; i < 2048 / sizeof(ULONG); i++) Checksum += Buffer[i]; Checksum = ~Checksum + 1; TRACE("Checksum: %x\n", Checksum); /* Fill out the ARC disk block */ reactos_arc_disk_info[reactos_disk_count].CheckSum = Checksum; strcpy(reactos_arc_strings[reactos_disk_count], BootPath); reactos_arc_disk_info[reactos_disk_count].ArcName = reactos_arc_strings[reactos_disk_count]; reactos_disk_count++; FsRegisterDevice(BootPath, &DiskVtbl); DiskCount++; } PcBiosDiskCount = DiskCount; TRACE("BIOS reports %d harddisk%s\n", (int)DiskCount, (DiskCount == 1) ? "": "s"); return DiskCount != 0; }