fix formatting
[reactos.git] / reactos / boot / freeldr / freeldr / arch / i386 / xboxhw.c
1 /* $Id$
2 *
3 * FreeLoader
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
22 #define NDEBUG
23 #include <debug.h>
24
25 static CHAR Hex[] = "0123456789ABCDEF";
26 //static unsigned int delay_count = 1;
27
28 extern ULONG reactos_disk_count;
29 extern ARC_DISK_SIGNATURE reactos_arc_disk_info[];
30 extern char reactos_arc_strings[32][256];
31
32 static VOID
33 SetHarddiskConfigurationData(PCONFIGURATION_COMPONENT_DATA DiskKey,
34 ULONG DriveNumber)
35 {
36 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
37 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry;
38 EXTENDED_GEOMETRY ExtGeometry;
39 GEOMETRY Geometry;
40 ULONG Size;
41
42 /* Set 'Configuration Data' value */
43 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) +
44 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA);
45 PartialResourceList = MmHeapAlloc(Size);
46 if (PartialResourceList == NULL)
47 {
48 DbgPrint((DPRINT_HWDETECT,
49 "Failed to allocate a full resource descriptor\n"));
50 return;
51 }
52
53 memset(PartialResourceList, 0, Size);
54 PartialResourceList->Version = 1;
55 PartialResourceList->Revision = 1;
56 PartialResourceList->Count = 1;
57 PartialResourceList->PartialDescriptors[0].Type =
58 CmResourceTypeDeviceSpecific;
59 // PartialResourceList->PartialDescriptors[0].ShareDisposition =
60 // PartialResourceList->PartialDescriptors[0].Flags =
61 PartialResourceList->PartialDescriptors[0].u.DeviceSpecificData.DataSize =
62 sizeof(CM_DISK_GEOMETRY_DEVICE_DATA);
63
64 /* Get pointer to geometry data */
65 DiskGeometry = (PVOID)(((ULONG_PTR)PartialResourceList) + sizeof(CM_PARTIAL_RESOURCE_LIST));
66
67 /* Get the disk geometry */
68 ExtGeometry.Size = sizeof(EXTENDED_GEOMETRY);
69
70 if(MachDiskGetDriveGeometry(DriveNumber, &Geometry))
71 {
72 DiskGeometry->BytesPerSector = Geometry.BytesPerSector;
73 DiskGeometry->NumberOfCylinders = Geometry.Cylinders;
74 DiskGeometry->SectorsPerTrack = Geometry.Sectors;
75 DiskGeometry->NumberOfHeads = Geometry.Heads;
76 }
77 else
78 {
79 DbgPrint((DPRINT_HWDETECT, "Reading disk geometry failed\n"));
80 MmHeapFree(PartialResourceList);
81 return;
82 }
83 DbgPrint((DPRINT_HWDETECT,
84 "Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
85 DriveNumber,
86 DiskGeometry->NumberOfCylinders,
87 DiskGeometry->NumberOfHeads,
88 DiskGeometry->SectorsPerTrack,
89 DiskGeometry->BytesPerSector));
90
91 FldrSetConfigurationData(DiskKey, PartialResourceList, Size);
92 MmHeapFree(PartialResourceList);
93 }
94
95
96 static VOID
97 SetHarddiskIdentifier(PCONFIGURATION_COMPONENT_DATA DiskKey,
98 ULONG DriveNumber)
99 {
100 PMASTER_BOOT_RECORD Mbr;
101 ULONG *Buffer;
102 ULONG i;
103 ULONG Checksum;
104 ULONG Signature;
105 CHAR Identifier[20];
106 CHAR ArcName[256];
107
108 /* Read the MBR */
109 if (!MachDiskReadLogicalSectors(DriveNumber, 0ULL, 1, (PVOID)DISKREADBUFFER))
110 {
111 DbgPrint((DPRINT_HWDETECT, "Reading MBR failed\n"));
112 return;
113 }
114
115 Buffer = (ULONG*)DISKREADBUFFER;
116 Mbr = (PMASTER_BOOT_RECORD)DISKREADBUFFER;
117
118 Signature = Mbr->Signature;
119 DbgPrint((DPRINT_HWDETECT, "Signature: %x\n", Signature));
120
121 /* Calculate the MBR checksum */
122 Checksum = 0;
123 for (i = 0; i < 128; i++)
124 {
125 Checksum += Buffer[i];
126 }
127 Checksum = ~Checksum + 1;
128 DbgPrint((DPRINT_HWDETECT, "Checksum: %x\n", Checksum));
129
130 /* Fill out the ARC disk block */
131 reactos_arc_disk_info[reactos_disk_count].Signature = Signature;
132 reactos_arc_disk_info[reactos_disk_count].CheckSum = Checksum;
133 sprintf(ArcName, "multi(0)disk(0)rdisk(%lu)", reactos_disk_count);
134 strcpy(reactos_arc_strings[reactos_disk_count], ArcName);
135 reactos_arc_disk_info[reactos_disk_count].ArcName =
136 reactos_arc_strings[reactos_disk_count];
137 reactos_disk_count++;
138
139 /* Convert checksum and signature to identifier string */
140 Identifier[0] = Hex[(Checksum >> 28) & 0x0F];
141 Identifier[1] = Hex[(Checksum >> 24) & 0x0F];
142 Identifier[2] = Hex[(Checksum >> 20) & 0x0F];
143 Identifier[3] = Hex[(Checksum >> 16) & 0x0F];
144 Identifier[4] = Hex[(Checksum >> 12) & 0x0F];
145 Identifier[5] = Hex[(Checksum >> 8) & 0x0F];
146 Identifier[6] = Hex[(Checksum >> 4) & 0x0F];
147 Identifier[7] = Hex[Checksum & 0x0F];
148 Identifier[8] = '-';
149 Identifier[9] = Hex[(Signature >> 28) & 0x0F];
150 Identifier[10] = Hex[(Signature >> 24) & 0x0F];
151 Identifier[11] = Hex[(Signature >> 20) & 0x0F];
152 Identifier[12] = Hex[(Signature >> 16) & 0x0F];
153 Identifier[13] = Hex[(Signature >> 12) & 0x0F];
154 Identifier[14] = Hex[(Signature >> 8) & 0x0F];
155 Identifier[15] = Hex[(Signature >> 4) & 0x0F];
156 Identifier[16] = Hex[Signature & 0x0F];
157 Identifier[17] = '-';
158 Identifier[18] = 'A';
159 Identifier[19] = 0;
160 DbgPrint((DPRINT_HWDETECT, "Identifier: %s\n", Identifier));
161
162 /* Set identifier */
163 FldrSetIdentifier(DiskKey, Identifier);
164 }
165
166 static VOID
167 DetectBiosDisks(PCONFIGURATION_COMPONENT_DATA SystemKey,
168 PCONFIGURATION_COMPONENT_DATA BusKey)
169 {
170 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
171 PCM_INT13_DRIVE_PARAMETER Int13Drives;
172 GEOMETRY Geometry;
173 PCONFIGURATION_COMPONENT_DATA DiskKey, ControllerKey;
174 ULONG DiskCount;
175 ULONG Size;
176 ULONG i;
177 BOOLEAN Changed;
178
179 /* Count the number of visible drives */
180 DiskReportError(FALSE);
181 DiskCount = 0;
182
183 /* There are some really broken BIOSes out there. There are even BIOSes
184 * that happily report success when you ask them to read from non-existent
185 * harddisks. So, we set the buffer to known contents first, then try to
186 * read. If the BIOS reports success but the buffer contents haven't
187 * changed then we fail anyway */
188 memset((PVOID) DISKREADBUFFER, 0xcd, 512);
189 while (MachDiskReadLogicalSectors(0x80 + DiskCount, 0ULL, 1, (PVOID)DISKREADBUFFER))
190 {
191 Changed = FALSE;
192 for (i = 0; ! Changed && i < 512; i++)
193 {
194 Changed = ((PUCHAR)DISKREADBUFFER)[i] != 0xcd;
195 }
196 if (! Changed)
197 {
198 DbgPrint((DPRINT_HWDETECT, "BIOS reports success for disk %d but data didn't change\n",
199 (int)DiskCount));
200 break;
201 }
202 DiskCount++;
203 memset((PVOID) DISKREADBUFFER, 0xcd, 512);
204 }
205 DiskReportError(TRUE);
206 DbgPrint((DPRINT_HWDETECT, "BIOS reports %d harddisk%s\n",
207 (int)DiskCount, (DiskCount == 1) ? "": "s"));
208
209 FldrCreateComponentKey(BusKey,
210 L"DiskController",
211 0,
212 ControllerClass,
213 DiskController,
214 &ControllerKey);
215 DbgPrint((DPRINT_HWDETECT, "Created key: DiskController\\0\n"));
216
217 /* Set 'ComponentInformation' value */
218 FldrSetComponentInformation(ControllerKey,
219 Output | Input | Removable,
220 0,
221 0xFFFFFFFF);
222
223 //DetectBiosFloppyController(BusKey, ControllerKey);
224
225 /* Allocate resource descriptor */
226 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) +
227 sizeof(CM_INT13_DRIVE_PARAMETER) * DiskCount;
228 PartialResourceList = MmHeapAlloc(Size);
229 if (PartialResourceList == NULL)
230 {
231 DbgPrint((DPRINT_HWDETECT,
232 "Failed to allocate resource descriptor\n"));
233 return;
234 }
235
236 /* Initialize resource descriptor */
237 memset(PartialResourceList, 0, Size);
238 PartialResourceList->Version = 1;
239 PartialResourceList->Revision = 1;
240 PartialResourceList->Count = 1;
241 PartialResourceList->PartialDescriptors[0].Type = CmResourceTypeDeviceSpecific;
242 PartialResourceList->PartialDescriptors[0].ShareDisposition = 0;
243 PartialResourceList->PartialDescriptors[0].Flags = 0;
244 PartialResourceList->PartialDescriptors[0].u.DeviceSpecificData.DataSize =
245 sizeof(CM_INT13_DRIVE_PARAMETER) * DiskCount;
246
247 /* Get harddisk Int13 geometry data */
248 Int13Drives = (PVOID)(((ULONG_PTR)PartialResourceList) + sizeof(CM_PARTIAL_RESOURCE_LIST));
249 for (i = 0; i < DiskCount; i++)
250 {
251 if (MachDiskGetDriveGeometry(0x80 + i, &Geometry))
252 {
253 Int13Drives[i].DriveSelect = 0x80 + i;
254 Int13Drives[i].MaxCylinders = Geometry.Cylinders - 1;
255 Int13Drives[i].SectorsPerTrack = Geometry.Sectors;
256 Int13Drives[i].MaxHeads = Geometry.Heads - 1;
257 Int13Drives[i].NumberDrives = DiskCount;
258
259 DbgPrint((DPRINT_HWDETECT,
260 "Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
261 0x80 + i,
262 Geometry.Cylinders - 1,
263 Geometry.Heads -1,
264 Geometry.Sectors,
265 Geometry.BytesPerSector));
266 }
267 }
268
269 /* Set 'Configuration Data' value */
270 FldrSetConfigurationData(SystemKey, PartialResourceList, Size);
271 MmHeapFree(PartialResourceList);
272
273 /* Create and fill subkey for each harddisk */
274 for (i = 0; i < DiskCount; i++)
275 {
276 /* Create disk key */
277 FldrCreateComponentKey(ControllerKey,
278 L"DiskPeripheral",
279 i,
280 PeripheralClass,
281 DiskPeripheral,
282 &DiskKey);
283
284 /* Set 'ComponentInformation' value */
285 FldrSetComponentInformation(DiskKey,
286 Output | Input,
287 0,
288 0xFFFFFFFF);
289
290 /* Set disk values */
291 SetHarddiskConfigurationData(DiskKey, 0x80 + i);
292 SetHarddiskIdentifier(DiskKey, 0x80 + i);
293 }
294 }
295
296 static VOID
297 DetectIsaBios(PCONFIGURATION_COMPONENT_DATA SystemKey, ULONG *BusNumber)
298 {
299 PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
300 PCONFIGURATION_COMPONENT_DATA BusKey;
301 ULONG Size;
302
303 /* Create new bus key */
304 FldrCreateComponentKey(SystemKey,
305 L"MultifunctionAdapter",
306 *BusNumber,
307 AdapterClass,
308 MultiFunctionAdapter,
309 &BusKey);
310
311 /* Set 'Component Information' value similar to my NT4 box */
312 FldrSetComponentInformation(BusKey,
313 0x0,
314 0x0,
315 0xFFFFFFFF);
316
317 /* Increment bus number */
318 (*BusNumber)++;
319
320 /* Set 'Identifier' value */
321 FldrSetIdentifier(BusKey, "ISA");
322
323 /* Set 'Configuration Data' value */
324 Size = sizeof(CM_PARTIAL_RESOURCE_LIST) -
325 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
326 PartialResourceList = MmHeapAlloc(Size);
327 if (PartialResourceList == NULL)
328 {
329 DbgPrint((DPRINT_HWDETECT,
330 "Failed to allocate resource descriptor\n"));
331 return;
332 }
333
334 /* Initialize resource descriptor */
335 memset(PartialResourceList, 0, Size);
336 PartialResourceList->Version = 1;
337 PartialResourceList->Revision = 1;
338 PartialResourceList->Count = 0;
339
340 /* Set 'Configuration Data' value */
341 FldrSetConfigurationData(BusKey, PartialResourceList, Size);
342 MmHeapFree(PartialResourceList);
343
344
345 /* Detect ISA/BIOS devices */
346 DetectBiosDisks(SystemKey, BusKey);
347
348
349 /* FIXME: Detect more ISA devices */
350 }
351
352 PCONFIGURATION_COMPONENT_DATA
353 XboxHwDetect(VOID)
354 {
355 PCONFIGURATION_COMPONENT_DATA SystemKey;
356 ULONG BusNumber = 0;
357
358 DbgPrint((DPRINT_HWDETECT, "DetectHardware()\n"));
359
360 /* Create the 'System' key */
361 FldrCreateSystemKey(&SystemKey);
362
363 /* Set empty component information */
364 FldrSetComponentInformation(SystemKey,
365 0x0,
366 0x0,
367 0xFFFFFFFF);
368
369 /* TODO: Build actual xbox's hardware configuration tree */
370 DetectIsaBios(SystemKey, &BusNumber);
371
372 DbgPrint((DPRINT_HWDETECT, "DetectHardware() Done\n"));
373 return SystemKey;
374 }
375
376 /* EOF */