|
|
1.1 ! root 1: /* ! 2: Copyright (c) 2008 TrueCrypt Foundation. All rights reserved. ! 3: ! 4: Governed by the TrueCrypt License 2.4 the full text of which is contained ! 5: in the file License.txt included in TrueCrypt binary and source code ! 6: distribution packages. ! 7: */ ! 8: ! 9: #include "Bios.h" ! 10: #include "BootConsoleIo.h" ! 11: #include "BootDebug.h" ! 12: #include "BootDiskIo.h" ! 13: ! 14: ! 15: bool IsLbaSupported (byte drive) ! 16: { ! 17: uint16 result = 0; ! 18: __asm ! 19: { ! 20: mov bx, 0x55aa ! 21: mov dl, drive ! 22: mov ah, 0x41 ! 23: int 0x13 ! 24: jc err ! 25: mov result, bx ! 26: err: ! 27: } ! 28: ! 29: return result == 0xaa55; ! 30: } ! 31: ! 32: ! 33: void PrintDiskError (BiosResult error, bool write, byte drive, const uint64 *sector, const ChsAddress *chs) ! 34: { ! 35: PrintEndl(); ! 36: Print (write ? "Write" : "Read"); Print (" error:"); ! 37: PrintHex (error); ! 38: Print (" Drive:"); ! 39: Print (drive < TC_FIRST_BIOS_DRIVE ? drive : drive - TC_FIRST_BIOS_DRIVE); ! 40: ! 41: if (sector) ! 42: { ! 43: Print (" Sector:"); ! 44: Print (*sector); ! 45: } ! 46: ! 47: if (chs) ! 48: { ! 49: Print (" CHS:"); ! 50: Print (*chs); ! 51: } ! 52: ! 53: PrintEndl(); ! 54: Beep(); ! 55: } ! 56: ! 57: ! 58: void Print (const ChsAddress &chs) ! 59: { ! 60: Print (chs.Cylinder); ! 61: PrintChar ('/'); ! 62: Print (chs.Head); ! 63: PrintChar ('/'); ! 64: Print (chs.Sector); ! 65: } ! 66: ! 67: ! 68: BiosResult ReadWriteSectors (bool write, byte *buffer, byte drive, const ChsAddress &chs, byte sectorCount, bool silent) ! 69: { ! 70: byte cylinderLow = (byte) chs.Cylinder; ! 71: byte sector = chs.Sector; ! 72: sector |= byte (chs.Cylinder >> 2) & 0xc0; ! 73: byte function = write ? 0x03 : 0x02; ! 74: ! 75: BiosResult result; ! 76: __asm ! 77: { ! 78: push es ! 79: mov ax, ds ! 80: mov es, ax ! 81: mov bx, ss:buffer ! 82: mov dl, ss:drive ! 83: mov ch, ss:cylinderLow ! 84: mov si, chs ! 85: mov dh, ss:[si].Head ! 86: mov cl, ss:sector ! 87: mov al, ss:sectorCount ! 88: mov ah, function ! 89: int 0x13 ! 90: mov result, ah ! 91: pop es ! 92: } ! 93: ! 94: if (result == BiosResultEccCorrected) ! 95: result = BiosResultSuccess; ! 96: ! 97: if (!silent && result != BiosResultSuccess) ! 98: PrintDiskError (result, write, drive, nullptr, &chs); ! 99: ! 100: return result; ! 101: } ! 102: ! 103: ! 104: BiosResult ReadSectors (byte *buffer, byte drive, const ChsAddress &chs, byte sectorCount, bool silent) ! 105: { ! 106: return ReadWriteSectors (false, buffer, drive, chs, sectorCount, silent); ! 107: } ! 108: ! 109: ! 110: BiosResult WriteSectors (byte *buffer, byte drive, const ChsAddress &chs, byte sectorCount, bool silent) ! 111: { ! 112: return ReadWriteSectors (true, buffer, drive, chs, sectorCount, silent); ! 113: } ! 114: ! 115: ! 116: static BiosResult ReadWriteSectors (bool write, BiosLbaPacket &dapPacket, byte drive, const uint64 §or, uint16 sectorCount, bool silent) ! 117: { ! 118: dapPacket.Size = sizeof (dapPacket); ! 119: dapPacket.Reserved = 0; ! 120: dapPacket.SectorCount = sectorCount; ! 121: dapPacket.Sector = sector; ! 122: ! 123: byte function = write ? 0x43 : 0x42; ! 124: ! 125: BiosResult result; ! 126: __asm ! 127: { ! 128: mov bx, 0x55aa ! 129: mov dl, drive ! 130: mov si, [dapPacket] ! 131: mov ah, function ! 132: xor al, al ! 133: int 0x13 ! 134: mov result, ah ! 135: } ! 136: ! 137: if (result == BiosResultEccCorrected) ! 138: result = BiosResultSuccess; ! 139: ! 140: if (!silent && result != BiosResultSuccess) ! 141: PrintDiskError (result, write, drive, §or); ! 142: ! 143: return result; ! 144: } ! 145: ! 146: ! 147: static BiosResult ReadWriteSectors (bool write, byte *buffer, byte drive, const uint64 §or, uint16 sectorCount, bool silent) ! 148: { ! 149: BiosLbaPacket dapPacket; ! 150: dapPacket.Buffer = (uint32) buffer; ! 151: return ReadWriteSectors (write, dapPacket, drive, sector, sectorCount, silent); ! 152: } ! 153: ! 154: ! 155: BiosResult ReadWriteSectors (bool write, uint16 bufferSegment, uint16 bufferOffset, byte drive, const uint64 §or, uint16 sectorCount, bool silent) ! 156: { ! 157: BiosLbaPacket dapPacket; ! 158: dapPacket.Buffer = ((uint32) bufferSegment << 16) | bufferOffset; ! 159: return ReadWriteSectors (write, dapPacket, drive, sector, sectorCount, silent); ! 160: } ! 161: ! 162: ! 163: BiosResult ReadSectors (byte *buffer, byte drive, const uint64 §or, uint16 sectorCount, bool silent) ! 164: { ! 165: if (IsLbaSupported (drive)) ! 166: return ReadWriteSectors (false, buffer, drive, sector, sectorCount, silent); ! 167: ! 168: DriveGeometry geometry; ! 169: ! 170: BiosResult result = GetDriveGeometry (drive, geometry, silent); ! 171: if (result != BiosResultSuccess) ! 172: return result; ! 173: ! 174: ChsAddress chs; ! 175: LbaToChs (geometry, sector, chs); ! 176: return ReadWriteSectors (false, buffer, drive, chs, sectorCount, silent); ! 177: } ! 178: ! 179: ! 180: BiosResult WriteSectors (byte *buffer, byte drive, const uint64 §or, uint16 sectorCount, bool silent) ! 181: { ! 182: return ReadWriteSectors (true, buffer, drive, sector, sectorCount, silent); ! 183: } ! 184: ! 185: ! 186: BiosResult GetDriveGeometry (byte drive, DriveGeometry &geometry, bool silent) ! 187: { ! 188: byte maxCylinderLow, maxHead, maxSector; ! 189: BiosResult result; ! 190: __asm ! 191: { ! 192: push es ! 193: mov dl, drive ! 194: mov ah, 0x08 ! 195: int 0x13 ! 196: ! 197: mov result, ah ! 198: jc err ! 199: mov maxCylinderLow, ch ! 200: mov maxSector, cl ! 201: mov maxHead, dh ! 202: err: ! 203: pop es ! 204: } ! 205: ! 206: if (result == BiosResultSuccess) ! 207: { ! 208: geometry.Cylinders = (maxCylinderLow | (uint16 (maxSector & 0xc0) << 2)) + 1; ! 209: geometry.Heads = maxHead + 1; ! 210: geometry.Sectors = maxSector & ~0xc0; ! 211: } ! 212: else if (!silent) ! 213: { ! 214: PrintError ("Cannot get geometry of drive ", true, false); ! 215: Print (drive); ! 216: PrintEndl(); ! 217: } ! 218: ! 219: return result; ! 220: } ! 221: ! 222: ! 223: void ChsToLba (const DriveGeometry &geometry, const ChsAddress &chs, uint64 &lba) ! 224: { ! 225: lba.HighPart = 0; ! 226: lba.LowPart = (uint32 (chs.Cylinder) * geometry.Heads + chs.Head) * geometry.Sectors + chs.Sector - 1; ! 227: } ! 228: ! 229: ! 230: void LbaToChs (const DriveGeometry &geometry, const uint64 &lba, ChsAddress &chs) ! 231: { ! 232: chs.Sector = (lba.LowPart % geometry.Sectors) + 1; ! 233: uint32 ch = lba.LowPart / geometry.Sectors; ! 234: chs.Head = ch % geometry.Heads; ! 235: chs.Cylinder = ch / geometry.Heads; ! 236: } ! 237: ! 238: ! 239: BiosResult ReadMBR (byte drive, MBR &mbr, bool silent) ! 240: { ! 241: ChsAddress chs; ! 242: chs.Cylinder = 0; ! 243: chs.Head = 0; ! 244: chs.Sector = 1; ! 245: ! 246: return ReadSectors ((byte *) &mbr, drive, chs, 1, silent); ! 247: } ! 248: ! 249: ! 250: void PartitionEntryMBRToPartition (const PartitionEntryMBR &partEntry, Partition &partition) ! 251: { ! 252: partition.Active = partEntry.BootIndicator == 0x80; ! 253: partition.EndSector.HighPart = 0; ! 254: partition.EndSector.LowPart = partEntry.StartLBA + partEntry.SectorCountLBA - 1; ! 255: partition.SectorCount.HighPart = 0; ! 256: partition.SectorCount.LowPart = partEntry.SectorCountLBA; ! 257: partition.StartSector.HighPart = 0; ! 258: partition.StartSector.LowPart = partEntry.StartLBA; ! 259: ! 260: partition.StartChsAddress.Cylinder = partEntry.StartCylinder | (uint16 (partEntry.StartCylSector & 0xc0) << 2); ! 261: partition.StartChsAddress.Head = partEntry.StartHead; ! 262: partition.StartChsAddress.Sector = partEntry.StartCylSector & ~0xc0; ! 263: ! 264: partition.Type = partEntry.Type; ! 265: } ! 266: ! 267: ! 268: BiosResult GetDrivePartitions (byte drive, Partition *partitionArray, size_t partitionArrayCapacity, size_t &partitionCount, bool activeOnly, bool silent) ! 269: { ! 270: MBR mbr; ! 271: BiosResult result = ReadMBR (drive, mbr, silent); ! 272: partitionCount = 0; ! 273: ! 274: if (result != BiosResultSuccess || mbr.Signature != 0xaa55) ! 275: return result; ! 276: ! 277: size_t partitionArrayPos = 0, partitionNumber; ! 278: ! 279: for (partitionNumber = 0; ! 280: partitionNumber < array_capacity (mbr.Partitions) && partitionArrayPos < partitionArrayCapacity; ! 281: ++partitionNumber) ! 282: { ! 283: const PartitionEntryMBR &partEntry = mbr.Partitions[partitionNumber]; ! 284: ! 285: if (partEntry.SectorCountLBA > 0) ! 286: { ! 287: Partition &partition = partitionArray[partitionArrayPos]; ! 288: PartitionEntryMBRToPartition (partEntry, partition); ! 289: ! 290: if (activeOnly && !partition.Active) ! 291: continue; ! 292: ! 293: partition.Drive = drive; ! 294: partition.Number = partitionNumber; ! 295: ! 296: if (partEntry.Type == 0x5 || partEntry.Type == 0xf) // Extended partition ! 297: { ! 298: if (IsLbaSupported (drive)) ! 299: { ! 300: // Find all extended partitions ! 301: uint64 firstExtStartLBA = partition.StartSector; ! 302: uint64 extStartLBA = partition.StartSector; ! 303: MBR extMbr; ! 304: ! 305: while (partitionArrayPos < partitionArrayCapacity && ! 306: (result = ReadSectors ((byte *) &extMbr, drive, extStartLBA, 1, silent)) == BiosResultSuccess ! 307: && extMbr.Signature == 0xaa55) ! 308: { ! 309: if (extMbr.Partitions[0].SectorCountLBA > 0) ! 310: { ! 311: Partition &logPart = partitionArray[partitionArrayPos++]; ! 312: PartitionEntryMBRToPartition (extMbr.Partitions[0], logPart); ! 313: logPart.Drive = drive; ! 314: ! 315: logPart.Number = partitionNumber++; ! 316: logPart.Primary = false; ! 317: ! 318: logPart.StartSector.LowPart += extStartLBA.LowPart; ! 319: logPart.EndSector.LowPart += extStartLBA.LowPart; ! 320: } ! 321: ! 322: // Secondary extended ! 323: if (extMbr.Partitions[1].Type != 0x5 && extMbr.Partitions[1].Type == 0xf ! 324: || extMbr.Partitions[1].SectorCountLBA == 0) ! 325: break; ! 326: ! 327: extStartLBA.LowPart = extMbr.Partitions[1].StartLBA + firstExtStartLBA.LowPart; ! 328: } ! 329: } ! 330: } ! 331: else ! 332: { ! 333: ++partitionArrayPos; ! 334: partition.Primary = true; ! 335: } ! 336: } ! 337: } ! 338: ! 339: partitionCount = partitionArrayPos; ! 340: return result; ! 341: } ! 342: ! 343: ! 344: BiosResult GetActivePartition (byte drive, Partition &partition, size_t &partitionCount, bool silent) ! 345: { ! 346: return GetDrivePartitions (drive, &partition, 1, partitionCount, true, silent); ! 347: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.