|
|
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.