eafe8787266fb056697d249454af314809236dc5
[reactos.git] / freeldr / freeldr / disk / disk.c
1 /*
2 * FreeLoader
3 * Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #include <freeldr.h>
21 #include <disk.h>
22 #include <fs.h>
23 #include <rtl.h>
24 #include <ui.h>
25 #include <arch.h>
26 #include <debug.h>
27
28
29 /////////////////////////////////////////////////////////////////////////////////////////////
30 // FUNCTIONS
31 /////////////////////////////////////////////////////////////////////////////////////////////
32
33 VOID DiskError(PUCHAR ErrorString)
34 {
35 UCHAR ErrorCodeString[80];
36
37 sprintf(ErrorCodeString, "%s\nError Code: 0x%x", ErrorString, BiosInt13GetLastErrorCode());
38
39 DbgPrint((DPRINT_DISK, "%s\n", ErrorCodeString));
40
41 if (UserInterfaceUp)
42 {
43 MessageBox(ErrorCodeString);
44 }
45 else
46 {
47 printf("%s", ErrorCodeString);
48 printf("\nPress any key\n");
49 getch();
50 }
51 }
52
53 BOOL DiskReadLogicalSectors(ULONG DriveNumber, ULONG SectorNumber, ULONG SectorCount, PVOID Buffer)
54 {
55 ULONG PhysicalSector;
56 ULONG PhysicalHead;
57 ULONG PhysicalTrack;
58 GEOMETRY DriveGeometry;
59 ULONG NumberOfSectorsToRead;
60
61 DbgPrint((DPRINT_DISK, "ReadLogicalSector() DriveNumber: 0x%x SectorNumber: %d Buffer: 0x%x\n", DriveNumber, SectorNumber, Buffer));
62
63 //
64 // Check to see if it is a fixed disk drive
65 // If so then check to see if Int13 extensions work
66 // If they do then use them, otherwise default back to BIOS calls
67 //
68 if ((DriveNumber >= 0x80) && (BiosInt13ExtensionsSupported(DriveNumber)))
69 {
70 DbgPrint((DPRINT_DISK, "Using Int 13 Extensions for read. BiosInt13ExtensionsSupported(%d) = %s\n", DriveNumber, BiosInt13ExtensionsSupported(DriveNumber) ? "TRUE" : "FALSE"));
71
72 //
73 // LBA is easy, nothing to calculate
74 // Just do the read
75 //
76 if (!BiosInt13ReadExtended(DriveNumber, SectorNumber, 1, Buffer))
77 {
78 DiskError("Disk read error.");
79 return FALSE;
80 }
81 }
82 else
83 {
84 //
85 // Get the drive geometry
86 //
87 if (!DiskGetDriveGeometry(DriveNumber, &DriveGeometry))
88 {
89 return FALSE;
90 }
91
92 while (SectorCount)
93 {
94
95 //
96 // Calculate the physical disk offsets
97 //
98 PhysicalSector = 1 + (SectorNumber % DriveGeometry.Sectors);
99 PhysicalHead = (SectorNumber / DriveGeometry.Sectors) % DriveGeometry.Heads;
100 PhysicalTrack = (SectorNumber / DriveGeometry.Sectors) / DriveGeometry.Heads;
101
102 //
103 // Calculate how many sectors we are supposed to read
104 //
105 if (PhysicalSector > 1)
106 {
107 if (SectorCount >= (DriveGeometry.Sectors - (PhysicalSector - 1)))
108 NumberOfSectorsToRead = (DriveGeometry.Sectors - (PhysicalSector - 1));
109 else
110 NumberOfSectorsToRead = SectorCount;
111 }
112 else
113 {
114 if (SectorCount >= DriveGeometry.Sectors)
115 NumberOfSectorsToRead = DriveGeometry.Sectors;
116 else
117 NumberOfSectorsToRead = SectorCount;
118 }
119
120 DbgPrint((DPRINT_DISK, "Calling BiosInt13Read() with PhysicalHead: %d\n", PhysicalHead));
121 DbgPrint((DPRINT_DISK, "Calling BiosInt13Read() with PhysicalTrack: %d\n", PhysicalTrack));
122 DbgPrint((DPRINT_DISK, "Calling BiosInt13Read() with PhysicalSector: %d\n", PhysicalSector));
123 DbgPrint((DPRINT_DISK, "Calling BiosInt13Read() with NumberOfSectorsToRead: %d\n", NumberOfSectorsToRead));
124
125 //
126 // Make sure the read is within the geometry boundaries
127 //
128 if ((PhysicalHead >= DriveGeometry.Heads) ||
129 (PhysicalTrack >= DriveGeometry.Cylinders) ||
130 ((NumberOfSectorsToRead + PhysicalSector) > (DriveGeometry.Sectors + 1)) ||
131 (PhysicalSector > DriveGeometry.Sectors))
132 {
133 DiskError("Disk read exceeds drive geometry limits.");
134 return FALSE;
135 }
136
137 //
138 // Perform the read
139 //
140 if (!BiosInt13Read(DriveNumber, PhysicalHead, PhysicalTrack, PhysicalSector, NumberOfSectorsToRead, Buffer))
141 {
142 DiskError("Disk read error.");
143 return FALSE;
144 }
145
146 Buffer += (NumberOfSectorsToRead * DriveGeometry.BytesPerSector);
147 SectorCount -= NumberOfSectorsToRead;
148 SectorNumber += NumberOfSectorsToRead;
149 }
150 }
151
152 return TRUE;
153 }