Implement IopReinitializeBootDrivers, on the model of IopReinitializeDrivers
[reactos.git] / reactos / ntoskrnl / io / iomgr / iomgr.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel
4 * FILE: ntoskrnl/io/iomgr.c
5 * PURPOSE: I/O Manager Initialization and Misc Utility Functions
6 *
7 * PROGRAMMERS: David Welch (welch@mcmail.com)
8 */
9
10 /* INCLUDES ****************************************************************/
11
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <internal/debug.h>
15
16 ULONG IopTraceLevel = IO_IRP_DEBUG;
17
18 /* DATA ********************************************************************/
19
20 POBJECT_TYPE IoDeviceObjectType = NULL;
21 POBJECT_TYPE IoFileObjectType = NULL;
22 extern POBJECT_TYPE IoControllerObjectType;
23 BOOLEAN IoCountOperations;
24 ULONG IoReadOperationCount = 0;
25 LARGE_INTEGER IoReadTransferCount = {{0, 0}};
26 ULONG IoWriteOperationCount = 0;
27 LARGE_INTEGER IoWriteTransferCount = {{0, 0}};
28 ULONG IoOtherOperationCount = 0;
29 LARGE_INTEGER IoOtherTransferCount = {{0, 0}};
30 KSPIN_LOCK IoStatisticsLock = 0;
31
32 GENERIC_MAPPING IopFileMapping = {
33 FILE_GENERIC_READ,
34 FILE_GENERIC_WRITE,
35 FILE_GENERIC_EXECUTE,
36 FILE_ALL_ACCESS};
37
38 extern LIST_ENTRY ShutdownListHead;
39 extern KSPIN_LOCK ShutdownListLock;
40 extern NPAGED_LOOKASIDE_LIST IoCompletionPacketLookaside;
41 extern POBJECT_TYPE IoAdapterObjectType;
42 NPAGED_LOOKASIDE_LIST IoLargeIrpLookaside;
43 NPAGED_LOOKASIDE_LIST IoSmallIrpLookaside;
44 NPAGED_LOOKASIDE_LIST IopMdlLookasideList;
45
46 VOID INIT_FUNCTION IopInitLookasideLists(VOID);
47
48 #if defined (ALLOC_PRAGMA)
49 #pragma alloc_text(INIT, IoInitCancelHandling)
50 #pragma alloc_text(INIT, IoInitShutdownNotification)
51 #pragma alloc_text(INIT, IopInitLookasideLists)
52 #pragma alloc_text(INIT, IoInit)
53 #pragma alloc_text(INIT, IoInit2)
54 #pragma alloc_text(INIT, IoInit3)
55 #endif
56
57 /* INIT FUNCTIONS ************************************************************/
58
59 VOID
60 INIT_FUNCTION
61 IoInitCancelHandling(VOID)
62 {
63 extern KSPIN_LOCK CancelSpinLock;
64 KeInitializeSpinLock(&CancelSpinLock);
65 }
66
67 VOID
68 INIT_FUNCTION
69 IoInitShutdownNotification (VOID)
70 {
71 InitializeListHead(&ShutdownListHead);
72 KeInitializeSpinLock(&ShutdownListLock);
73 }
74
75 VOID
76 INIT_FUNCTION
77 IopInitLookasideLists(VOID)
78 {
79 ULONG LargeIrpSize, SmallIrpSize, MdlSize;
80 LONG i;
81 PKPRCB Prcb;
82 PNPAGED_LOOKASIDE_LIST CurrentList = NULL;
83
84 /* Calculate the sizes */
85 LargeIrpSize = sizeof(IRP) + (8 * sizeof(IO_STACK_LOCATION));
86 SmallIrpSize = sizeof(IRP) + sizeof(IO_STACK_LOCATION);
87 MdlSize = sizeof(MDL) + (23 * sizeof(PFN_NUMBER));
88
89 /* Initialize the Lookaside List for Large IRPs */
90 ExInitializeNPagedLookasideList(&IoLargeIrpLookaside,
91 NULL,
92 NULL,
93 0,
94 LargeIrpSize,
95 IO_LARGEIRP,
96 64);
97
98 /* Initialize the Lookaside List for Small IRPs */
99 ExInitializeNPagedLookasideList(&IoSmallIrpLookaside,
100 NULL,
101 NULL,
102 0,
103 SmallIrpSize,
104 IO_SMALLIRP,
105 32);
106
107 /* Initialize the Lookaside List for I\O Completion */
108 ExInitializeNPagedLookasideList(&IoCompletionPacketLookaside,
109 NULL,
110 NULL,
111 0,
112 sizeof(IO_COMPLETION_PACKET),
113 IOC_TAG1,
114 32);
115
116 /* Initialize the Lookaside List for MDLs */
117 ExInitializeNPagedLookasideList(&IopMdlLookasideList,
118 NULL,
119 NULL,
120 0,
121 MdlSize,
122 TAG_MDL,
123 128);
124
125 /* Now allocate the per-processor lists */
126 for (i = 0; i < KeNumberProcessors; i++)
127 {
128 /* Get the PRCB for this CPU */
129 Prcb = ((PKPCR)(KPCR_BASE + i * PAGE_SIZE))->Prcb;
130 DPRINT("Setting up lookaside for CPU: %x, PRCB: %p\n", i, Prcb);
131
132 /* Set the Large IRP List */
133 Prcb->PPLookasideList[LookasideLargeIrpList].L = &IoLargeIrpLookaside.L;
134 CurrentList = ExAllocatePoolWithTag(NonPagedPool,
135 sizeof(NPAGED_LOOKASIDE_LIST),
136 IO_LARGEIRP_CPU);
137 if (CurrentList)
138 {
139 /* Initialize the Lookaside List for Large IRPs */
140 ExInitializeNPagedLookasideList(CurrentList,
141 NULL,
142 NULL,
143 0,
144 LargeIrpSize,
145 IO_LARGEIRP_CPU,
146 64);
147 }
148 else
149 {
150 CurrentList = &IoLargeIrpLookaside;
151 }
152 Prcb->PPLookasideList[LookasideLargeIrpList].P = &CurrentList->L;
153
154 /* Set the Small IRP List */
155 Prcb->PPLookasideList[LookasideSmallIrpList].L = &IoSmallIrpLookaside.L;
156 CurrentList = ExAllocatePoolWithTag(NonPagedPool,
157 sizeof(NPAGED_LOOKASIDE_LIST),
158 IO_SMALLIRP_CPU);
159 if (CurrentList)
160 {
161 /* Initialize the Lookaside List for Small IRPs */
162 ExInitializeNPagedLookasideList(CurrentList,
163 NULL,
164 NULL,
165 0,
166 SmallIrpSize,
167 IO_SMALLIRP_CPU,
168 32);
169 }
170 else
171 {
172 CurrentList = &IoSmallIrpLookaside;
173 }
174 Prcb->PPLookasideList[LookasideSmallIrpList].P = &CurrentList->L;
175
176 /* Set the I/O Completion List */
177 Prcb->PPLookasideList[LookasideCompletionList].L = &IoCompletionPacketLookaside.L;
178 CurrentList = ExAllocatePoolWithTag(NonPagedPool,
179 sizeof(NPAGED_LOOKASIDE_LIST),
180 IO_SMALLIRP_CPU);
181 if (CurrentList)
182 {
183 /* Initialize the Lookaside List for Large IRPs */
184 ExInitializeNPagedLookasideList(CurrentList,
185 NULL,
186 NULL,
187 0,
188 sizeof(IO_COMPLETION_PACKET),
189 IO_SMALLIRP_CPU,
190 32);
191 }
192 else
193 {
194 CurrentList = &IoCompletionPacketLookaside;
195 }
196 Prcb->PPLookasideList[LookasideCompletionList].P = &CurrentList->L;
197
198 /* Set the MDL Completion List */
199 Prcb->PPLookasideList[LookasideMdlList].L = &IopMdlLookasideList.L;
200 CurrentList = ExAllocatePoolWithTag(NonPagedPool,
201 sizeof(NPAGED_LOOKASIDE_LIST),
202 TAG_MDL);
203 if (CurrentList)
204 {
205 /* Initialize the Lookaside List for MDLs */
206 ExInitializeNPagedLookasideList(CurrentList,
207 NULL,
208 NULL,
209 0,
210 SmallIrpSize,
211 TAG_MDL,
212 128);
213 }
214 else
215 {
216 CurrentList = &IopMdlLookasideList;
217 }
218 Prcb->PPLookasideList[LookasideMdlList].P = &CurrentList->L;
219 }
220
221 DPRINT("Done allocation\n");
222 }
223
224 VOID
225 INIT_FUNCTION
226 IoInit (VOID)
227 {
228 OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
229 UNICODE_STRING Name;
230 OBJECT_ATTRIBUTES ObjectAttributes;
231 UNICODE_STRING DirName;
232 UNICODE_STRING LinkName = RTL_CONSTANT_STRING(L"\\DosDevices");
233 HANDLE Handle;
234
235 IopInitDriverImplementation();
236
237 DPRINT("Creating Device Object Type\n");
238
239 /* Initialize the Driver object type */
240 RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
241 RtlInitUnicodeString(&Name, L"Device");
242 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
243 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(DEVICE_OBJECT);
244 ObjectTypeInitializer.PoolType = NonPagedPool;
245 ObjectTypeInitializer.ValidAccessMask = FILE_ALL_ACCESS;
246 ObjectTypeInitializer.UseDefaultObject = TRUE;
247 ObjectTypeInitializer.GenericMapping = IopFileMapping;
248 ObjectTypeInitializer.ParseProcedure = IopParseDevice;
249 ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &IoDeviceObjectType);
250
251 /* Do the Adapter Type */
252 RtlInitUnicodeString(&Name, L"Adapter");
253 ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &IoAdapterObjectType);
254
255 /* Do the Controller Type */
256 RtlInitUnicodeString(&Name, L"Controller");
257 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(CONTROLLER_OBJECT);
258 ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &IoControllerObjectType);
259
260 /* Initialize the File object type */
261 RtlInitUnicodeString(&Name, L"File");
262 ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
263 ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(FILE_OBJECT);
264 ObjectTypeInitializer.CloseProcedure = IopCloseFile;
265 ObjectTypeInitializer.DeleteProcedure = IopDeleteFile;
266 ObjectTypeInitializer.SecurityProcedure = IopSecurityFile;
267 ObjectTypeInitializer.QueryNameProcedure = IopQueryNameFile;
268 ObjectTypeInitializer.ParseProcedure = IopParseFile;
269 ObjectTypeInitializer.UseDefaultObject = FALSE;
270 ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &IoFileObjectType);
271
272 /*
273 * Create the '\Driver' object directory
274 */
275 RtlInitUnicodeString(&DirName, L"\\Driver");
276 InitializeObjectAttributes(&ObjectAttributes,
277 &DirName,
278 0,
279 NULL,
280 NULL);
281 ZwCreateDirectoryObject(&Handle,
282 0,
283 &ObjectAttributes);
284
285 /*
286 * Create the '\FileSystem' object directory
287 */
288 RtlInitUnicodeString(&DirName,
289 L"\\FileSystem");
290 InitializeObjectAttributes(&ObjectAttributes,
291 &DirName,
292 0,
293 NULL,
294 NULL);
295 ZwCreateDirectoryObject(&Handle,
296 0,
297 &ObjectAttributes);
298
299 /*
300 * Create the '\Device' directory
301 */
302 RtlInitUnicodeString(&DirName,
303 L"\\Device");
304 InitializeObjectAttributes(&ObjectAttributes,
305 &DirName,
306 0,
307 NULL,
308 NULL);
309 ZwCreateDirectoryObject(&Handle,
310 0,
311 &ObjectAttributes);
312
313 /*
314 * Create the '\??' directory
315 */
316 RtlInitUnicodeString(&DirName,
317 L"\\??");
318 InitializeObjectAttributes(&ObjectAttributes,
319 &DirName,
320 0,
321 NULL,
322 NULL);
323 ZwCreateDirectoryObject(&Handle,
324 0,
325 &ObjectAttributes);
326
327 /*
328 * Create the '\ArcName' directory
329 */
330 RtlInitUnicodeString(&DirName,
331 L"\\ArcName");
332 InitializeObjectAttributes(&ObjectAttributes,
333 &DirName,
334 0,
335 NULL,
336 NULL);
337 ZwCreateDirectoryObject(&Handle,
338 0,
339 &ObjectAttributes);
340
341 /*
342 * Initialize remaining subsubsystem
343 */
344 IoInitCancelHandling();
345 IoInitFileSystemImplementation();
346 IoInitVpbImplementation();
347 IoInitShutdownNotification();
348 IopInitPnpNotificationImplementation();
349 IopInitErrorLog();
350 IopInitTimerImplementation();
351 IopInitIoCompletionImplementation();
352 IopInitLookasideLists();
353
354 /*
355 * Create link from '\DosDevices' to '\??' directory
356 */
357 RtlInitUnicodeString(&DirName,
358 L"\\??");
359 IoCreateSymbolicLink(&LinkName,
360 &DirName);
361
362 /*
363 * Initialize PnP manager
364 */
365 PnpInit();
366 }
367
368 VOID
369 INIT_FUNCTION
370 IoInit2(BOOLEAN BootLog)
371 {
372 PDEVICE_NODE DeviceNode;
373 PDRIVER_OBJECT DriverObject;
374 LDR_DATA_TABLE_ENTRY ModuleObject;
375 NTSTATUS Status;
376
377 PnpInit2();
378
379 IoCreateDriverList();
380
381 KeInitializeSpinLock (&IoStatisticsLock);
382
383 /* Initialize raw filesystem driver */
384
385 /* Use IopRootDeviceNode for now */
386 Status = IopCreateDeviceNode(IopRootDeviceNode,
387 NULL,
388 &DeviceNode);
389 if (!NT_SUCCESS(Status))
390 {
391 CPRINT("IopCreateDeviceNode() failed with status (%x)\n", Status);
392 return;
393 }
394
395 ModuleObject.DllBase = NULL;
396 ModuleObject.SizeOfImage = 0;
397 ModuleObject.EntryPoint = RawFsDriverEntry;
398
399 Status = IopInitializeDriverModule(
400 DeviceNode,
401 &ModuleObject,
402 &DeviceNode->ServiceName,
403 TRUE,
404 &DriverObject);
405 if (!NT_SUCCESS(Status))
406 {
407 IopFreeDeviceNode(DeviceNode);
408 CPRINT("IopInitializeDriver() failed with status (%x)\n", Status);
409 return;
410 }
411
412 Status = IopInitializeDevice(DeviceNode, DriverObject);
413 if (!NT_SUCCESS(Status))
414 {
415 IopFreeDeviceNode(DeviceNode);
416 CPRINT("IopInitializeDevice() failed with status (%x)\n", Status);
417 return;
418 }
419
420 Status = IopStartDevice(DeviceNode);
421 if (!NT_SUCCESS(Status))
422 {
423 IopFreeDeviceNode(DeviceNode);
424 CPRINT("IopInitializeDevice() failed with status (%x)\n", Status);
425 return;
426 }
427
428 /*
429 * Initialize PnP root releations
430 */
431 IopInvalidateDeviceRelations(
432 IopRootDeviceNode,
433 BusRelations);
434
435 /* Start boot logging */
436 IopInitBootLog(BootLog);
437
438 /* Load boot start drivers */
439 IopInitializeBootDrivers();
440 }
441
442 VOID
443 STDCALL
444 INIT_FUNCTION
445 IoInit3(VOID)
446 {
447 NTSTATUS Status;
448
449 /* Create ARC names for boot devices */
450 IoCreateArcNames();
451
452 /* Create the SystemRoot symbolic link */
453 DPRINT("CommandLine: %s\n", (PCHAR)KeLoaderBlock.CommandLine);
454 Status = IoCreateSystemRootLink((PCHAR)KeLoaderBlock.CommandLine);
455 if (!NT_SUCCESS(Status)) {
456 CPRINT("IoCreateSystemRootLink FAILED: (0x%x) - ", Status);
457 KEBUGCHECK(INACCESSIBLE_BOOT_DEVICE);
458 }
459
460 /* Read KDB Data */
461 KdbInit();
462
463 /* I/O is now setup for disk access, so phase 3 */
464 KdInitSystem(3, (PROS_LOADER_PARAMETER_BLOCK)&KeLoaderBlock);
465
466 /* Load services for devices found by PnP manager */
467 IopInitializePnpServices(IopRootDeviceNode, FALSE);
468
469 /* Load system start drivers */
470 IopInitializeSystemDrivers();
471 IoDestroyDriverList();
472
473 /* Call back drivers that asked for */
474 IopReinitializeBootDrivers();
475
476 /* Stop boot logging */
477 IopStopBootLog();
478
479 /* Assign drive letters */
480 IoAssignDriveLetters((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock,
481 NULL,
482 NULL,
483 NULL);
484 }
485
486 /* EOF */