6222770b66d0dac65fd9a9c0b07297a0c61249db
[reactos.git] / reactos / hal / halx86 / xbox / part_xbox.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: hal/halx86/xbox/part_xbox.c
6 * PURPOSE: Xbox specific handling of partition tables
7 * PROGRAMMER: Ge van Geldorp (gvg@reactos.com)
8 * UPDATE HISTORY:
9 * 2004/12/04: Created
10 */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <ddk/ntddk.h>
15 #include <hal.h>
16 #include "halxbox.h"
17 #include <internal/ps.h>
18
19 #define NDEBUG
20 #include <internal/debug.h>
21
22 #define XBOX_SIGNATURE_SECTOR 3
23 #define XBOX_SIGNATURE ('B' | ('R' << 8) | ('F' << 16) | ('R' << 24))
24 #define PARTITION_SIGNATURE 0xaa55
25
26 /* VARIABLES ***************************************************************/
27
28 static pHalExamineMBR NtoskrnlExamineMBR;
29 static pHalIoReadPartitionTable NtoskrnlIoReadPartitionTable;
30 static pHalIoSetPartitionInformation NtoskrnlIoSetPartitionInformation;
31 static pHalIoWritePartitionTable NtoskrnlIoWritePartitionTable;
32
33 static struct
34 {
35 ULONG SectorStart;
36 ULONG SectorCount;
37 BYTE PartitionType;
38 } XboxPartitions[] =
39 {
40 /* This is in the \Device\Harddisk0\Partition.. order used by the Xbox kernel */
41 { 0x0055F400, 0x0098f800, PARTITION_FAT32 }, /* Store, E: */
42 { 0x00465400, 0x000FA000, PARTITION_FAT_16 }, /* System, C: */
43 { 0x00000400, 0x00177000, PARTITION_FAT_16 }, /* Cache1, X: */
44 { 0x00177400, 0x00177000, PARTITION_FAT_16 }, /* Cache2, Y: */
45 { 0x002EE400, 0x00177000, PARTITION_FAT_16 } /* Cache3, Z: */
46 };
47
48 #define XBOX_PARTITION_COUNT (sizeof(XboxPartitions) / sizeof(XboxPartitions[0]))
49
50 /* FUNCTIONS ***************************************************************/
51
52
53 static NTSTATUS
54 HalpXboxReadSector(IN PDEVICE_OBJECT DeviceObject,
55 IN ULONG SectorSize,
56 IN PLARGE_INTEGER SectorOffset,
57 IN PVOID Sector)
58 {
59 IO_STATUS_BLOCK StatusBlock;
60 KEVENT Event;
61 PIRP Irp;
62 NTSTATUS Status;
63
64 DPRINT("HalpXboxReadSector(%p %lu 0x%08x%08x %p)\n",
65 DeviceObject, SectorSize, SectorOffset->u.HighPart, SectorOffset->u.LowPart, Sector);
66
67 ASSERT(DeviceObject);
68 ASSERT(Sector);
69
70 KeInitializeEvent(&Event,
71 NotificationEvent,
72 FALSE);
73
74 /* Read the sector */
75 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
76 DeviceObject,
77 Sector,
78 SectorSize,
79 SectorOffset,
80 &Event,
81 &StatusBlock);
82
83 Status = IoCallDriver(DeviceObject,
84 Irp);
85 if (Status == STATUS_PENDING)
86 {
87 KeWaitForSingleObject(&Event,
88 Executive,
89 KernelMode,
90 FALSE,
91 NULL);
92 Status = StatusBlock.Status;
93 }
94
95 if (!NT_SUCCESS(Status))
96 {
97 DPRINT("Reading sector failed (Status 0x%08lx)\n",
98 Status);
99 return Status;
100 }
101
102 return Status;
103 }
104
105 static NTSTATUS FASTCALL
106 HalpXboxDeviceHasXboxPartitioning(PDEVICE_OBJECT DeviceObject,
107 ULONG SectorSize,
108 BOOLEAN *HasXboxPartitioning)
109 {
110 PVOID SectorData;
111 LARGE_INTEGER Offset;
112 NTSTATUS Status;
113
114 DPRINT("HalpXboxDeviceHasXboxPartitioning(%p %lu %p)\n",
115 DeviceObject,
116 SectorSize,
117 HasXboxPartitioning);
118
119 SectorData = ExAllocatePool(PagedPool, SectorSize);
120 if (NULL == SectorData)
121 {
122 return STATUS_NO_MEMORY;
123 }
124
125 Offset.QuadPart = XBOX_SIGNATURE_SECTOR * SectorSize;
126 Status = HalpXboxReadSector(DeviceObject, SectorSize, &Offset, SectorData);
127 if (! NT_SUCCESS(Status))
128 {
129 return Status;
130 }
131
132 DPRINT("Signature 0x%02x 0x%02x 0x%02x 0x%02x\n",
133 *((UCHAR *) SectorData), *((UCHAR *) SectorData + 1), *((UCHAR *) SectorData + 2), *((UCHAR *) SectorData + 3));
134 *HasXboxPartitioning = (XBOX_SIGNATURE == *((ULONG *) SectorData));
135 ExFreePool(SectorData);
136 DPRINT("%s partitioning found\n", *HasXboxPartitioning ? "Xbox" : "MBR");
137
138 return STATUS_SUCCESS;
139 }
140
141 static VOID FASTCALL
142 HalpXboxExamineMBR(IN PDEVICE_OBJECT DeviceObject,
143 IN ULONG SectorSize,
144 IN ULONG MBRTypeIdentifier,
145 OUT PVOID *Buffer)
146 {
147 BOOLEAN HasXboxPartitioning;
148 NTSTATUS Status;
149
150 DPRINT("HalpXboxExamineMBR(%p %lu %lx %p)\n",
151 DeviceObject,
152 SectorSize,
153 MBRTypeIdentifier,
154 Buffer);
155
156 *Buffer = NULL;
157
158 Status = HalpXboxDeviceHasXboxPartitioning(DeviceObject, SectorSize, &HasXboxPartitioning);
159 if (! NT_SUCCESS(Status))
160 {
161 return;
162 }
163
164 if (! HasXboxPartitioning)
165 {
166 DPRINT("Delegating to standard MBR code\n");
167 NtoskrnlExamineMBR(DeviceObject, SectorSize, MBRTypeIdentifier, Buffer);
168 return;
169 }
170
171 /* Buffer already set to NULL */
172 return;
173 }
174
175 static NTSTATUS FASTCALL
176 HalpXboxIoReadPartitionTable(PDEVICE_OBJECT DeviceObject,
177 ULONG SectorSize,
178 BOOLEAN ReturnRecognizedPartitions,
179 PDRIVE_LAYOUT_INFORMATION *PartitionBuffer)
180 {
181 BOOLEAN HasXboxPartitioning;
182 NTSTATUS Status;
183 unsigned Part;
184 PPARTITION_INFORMATION PartInfo;
185
186 DPRINT("HalpXboxIoReadPartitionTable(%p %lu %x %p)\n",
187 DeviceObject,
188 SectorSize,
189 ReturnRecognizedPartitions,
190 PartitionBuffer);
191
192 Status = HalpXboxDeviceHasXboxPartitioning(DeviceObject, SectorSize, &HasXboxPartitioning);
193 if (! NT_SUCCESS(Status))
194 {
195 return Status;
196 }
197
198 if (! HasXboxPartitioning)
199 {
200 DPRINT("Delegating to standard MBR code\n");
201 return NtoskrnlIoReadPartitionTable(DeviceObject, SectorSize,
202 ReturnRecognizedPartitions, PartitionBuffer);
203 }
204
205 *PartitionBuffer = (PDRIVE_LAYOUT_INFORMATION)
206 ExAllocatePool(PagedPool,
207 sizeof(DRIVE_LAYOUT_INFORMATION) +
208 XBOX_PARTITION_COUNT * sizeof(PARTITION_INFORMATION));
209 if (NULL == *PartitionBuffer)
210 {
211 return STATUS_NO_MEMORY;
212 }
213 (*PartitionBuffer)->PartitionCount = XBOX_PARTITION_COUNT;
214 (*PartitionBuffer)->Signature = PARTITION_SIGNATURE;
215 for (Part = 0; Part < XBOX_PARTITION_COUNT; Part++)
216 {
217 PartInfo = (*PartitionBuffer)->PartitionEntry + Part;
218 PartInfo->StartingOffset.QuadPart = (ULONGLONG) XboxPartitions[Part].SectorStart *
219 (ULONGLONG) SectorSize;
220 PartInfo->PartitionLength.QuadPart = (ULONGLONG) XboxPartitions[Part].SectorCount *
221 (ULONGLONG) SectorSize;
222 PartInfo->HiddenSectors = 0;
223 PartInfo->PartitionNumber = Part + 1;
224 PartInfo->PartitionType = XboxPartitions[Part].PartitionType;
225 PartInfo->BootIndicator = FALSE;
226 PartInfo->RecognizedPartition = TRUE;
227 PartInfo->RewritePartition = FALSE;
228 DPRINT(" %ld: nr: %d boot: %1x type: %x start: 0x%I64x count: 0x%I64x rec: %d\n",
229 Part,
230 PartInfo->PartitionNumber,
231 PartInfo->BootIndicator,
232 PartInfo->PartitionType,
233 PartInfo->StartingOffset.QuadPart,
234 PartInfo->PartitionLength.QuadPart,
235 PartInfo->RecognizedPartition);
236 }
237
238 return STATUS_SUCCESS;
239 }
240
241 static NTSTATUS FASTCALL
242 HalpXboxIoSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject,
243 IN ULONG SectorSize,
244 IN ULONG PartitionNumber,
245 IN ULONG PartitionType)
246 {
247 BOOLEAN HasXboxPartitioning;
248 NTSTATUS Status;
249
250 DPRINT("HalpXboxIoSetPartitionInformation(%p %lu %lu %lu)\n",
251 DeviceObject,
252 SectorSize,
253 PartitionNumber,
254 PartitionType);
255
256 Status = HalpXboxDeviceHasXboxPartitioning(DeviceObject, SectorSize, &HasXboxPartitioning);
257 if (! NT_SUCCESS(Status))
258 {
259 return Status;
260 }
261
262 if (! HasXboxPartitioning)
263 {
264 DPRINT("Delegating to standard MBR code\n");
265 return NtoskrnlIoSetPartitionInformation(DeviceObject, SectorSize,
266 PartitionNumber, PartitionType);
267 }
268
269 /* Can't change the partitioning */
270 DPRINT1("Xbox partitions are fixed, can't change them\n");
271 return STATUS_ACCESS_DENIED;
272 }
273
274 static NTSTATUS FASTCALL
275 HalpXboxIoWritePartitionTable(IN PDEVICE_OBJECT DeviceObject,
276 IN ULONG SectorSize,
277 IN ULONG SectorsPerTrack,
278 IN ULONG NumberOfHeads,
279 IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer)
280 {
281 BOOLEAN HasXboxPartitioning;
282 NTSTATUS Status;
283
284 DPRINT("HalpXboxIoWritePartitionTable(%p %lu %lu %lu %p)\n",
285 DeviceObject,
286 SectorSize,
287 SectorsPerTrack,
288 NumberOfHeads,
289 PartitionBuffer);
290
291 Status = HalpXboxDeviceHasXboxPartitioning(DeviceObject, SectorSize, &HasXboxPartitioning);
292 if (! NT_SUCCESS(Status))
293 {
294 return Status;
295 }
296
297 if (! HasXboxPartitioning)
298 {
299 DPRINT("Delegating to standard MBR code\n");
300 return NtoskrnlIoWritePartitionTable(DeviceObject, SectorSize,
301 SectorsPerTrack, NumberOfHeads,
302 PartitionBuffer);
303 }
304
305 /* Can't change the partitioning */
306 DPRINT1("Xbox partitions are fixed, can't change them\n");
307 return STATUS_ACCESS_DENIED;
308 }
309
310 void
311 HalpXboxInitPartIo(void)
312 {
313 NtoskrnlExamineMBR = HalExamineMBR;
314 HalExamineMBR = HalpXboxExamineMBR;
315 NtoskrnlIoReadPartitionTable = HalIoReadPartitionTable;
316 HalIoReadPartitionTable = HalpXboxIoReadPartitionTable;
317 NtoskrnlIoSetPartitionInformation = HalIoSetPartitionInformation;
318 HalIoSetPartitionInformation = HalpXboxIoSetPartitionInformation;
319 NtoskrnlIoWritePartitionTable = HalIoWritePartitionTable;
320 HalIoWritePartitionTable = HalpXboxIoWritePartitionTable;
321 }
322
323 /* EOF */