Added support for calling BIOS functions
[reactos.git] / reactos / ntoskrnl / ke / main.c
1 /* $Id: main.c,v 1.69 2000/12/26 05:32:44 dwelch Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ke/main.c
6 * PURPOSE: Initalizes the kernel
7 * PROGRAMMER: David Welch (welch@cwcom.net)
8 * UPDATE HISTORY:
9 * 28/05/98: Created
10 */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <ddk/ntddk.h>
15 #include <internal/ntoskrnl.h>
16 #include <reactos/buildno.h>
17 #include <internal/mm.h>
18 #include <internal/module.h>
19 #include <internal/ldr.h>
20 #include <internal/ex.h>
21 #include <internal/ps.h>
22 #include <internal/hal.h>
23 #include <internal/ke.h>
24 #include <internal/io.h>
25 #include <internal/mmhal.h>
26 #include <internal/i386/segment.h>
27 #include <napi/shared_data.h>
28 #include <internal/v86m.h>
29
30 #define NDEBUG
31 #include <internal/debug.h>
32
33 /* GLOBALS *******************************************************************/
34
35 ULONG EXPORTED NtBuildNumber = KERNEL_VERSION_BUILD;
36 ULONG EXPORTED NtGlobalFlag = 0;
37 CHAR EXPORTED KeNumberProcessors = 1;
38 LOADER_PARAMETER_BLOCK EXPORTED KeLoaderBlock;
39 static LOADER_MODULE KeLoaderModules[64];
40 static UCHAR KeLoaderModuleStrings[64][256];
41 static UCHAR KeLoaderCommandLine[256];
42
43 /* FUNCTIONS ****************************************************************/
44
45 static VOID
46 CreateSystemRootLink (PCSZ ParameterLine)
47 {
48 UNICODE_STRING LinkName;
49 UNICODE_STRING DeviceName;
50 UNICODE_STRING ArcName;
51 UNICODE_STRING BootPath;
52 PCHAR ParamBuffer;
53 PWCHAR ArcNameBuffer;
54 PCHAR p;
55 NTSTATUS Status;
56 ULONG Length;
57 OBJECT_ATTRIBUTES ObjectAttributes;
58 HANDLE Handle;
59
60 /* create local parameter line copy */
61 ParamBuffer = ExAllocatePool (PagedPool, 256);
62 strcpy (ParamBuffer, (char *)ParameterLine);
63
64 DPRINT("%s\n", ParamBuffer);
65 /* Format: <arc_name>\<path> [options...] */
66
67 /* cut options off */
68 p = strchr (ParamBuffer, ' ');
69 if (p)
70 *p = 0;
71 DPRINT("%s\n", ParamBuffer);
72
73 /* extract path */
74 p = strchr (ParamBuffer, '\\');
75 if (p)
76 {
77 DPRINT("Boot path: %s\n", p);
78 RtlCreateUnicodeStringFromAsciiz (&BootPath, p);
79 *p = 0;
80 }
81 else
82 {
83 DPRINT("Boot path: %s\n", "\\");
84 RtlCreateUnicodeStringFromAsciiz (&BootPath, "\\");
85 }
86 DPRINT("Arc name: %s\n", ParamBuffer);
87
88 /* Only arc name left - build full arc name */
89 ArcNameBuffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
90 swprintf (ArcNameBuffer,
91 L"\\ArcName\\%S", ParamBuffer);
92 RtlInitUnicodeString (&ArcName, ArcNameBuffer);
93 DPRINT("Arc name: %wZ\n", &ArcName);
94
95 /* free ParamBuffer */
96 ExFreePool (ParamBuffer);
97
98 /* allocate device name string */
99 DeviceName.Length = 0;
100 DeviceName.MaximumLength = 256 * sizeof(WCHAR);
101 DeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
102
103 InitializeObjectAttributes (&ObjectAttributes,
104 &ArcName,
105 0,
106 NULL,
107 NULL);
108
109 Status = NtOpenSymbolicLinkObject (&Handle,
110 SYMBOLIC_LINK_ALL_ACCESS,
111 &ObjectAttributes);
112 if (!NT_SUCCESS(Status))
113 {
114 RtlFreeUnicodeString (&BootPath);
115 RtlFreeUnicodeString (&DeviceName);
116 DbgPrint("NtOpenSymbolicLinkObject() '%wZ' failed (Status %x)\n",
117 &ArcName,
118 Status);
119 RtlFreeUnicodeString (&ArcName);
120
121 KeBugCheck (0x0);
122 }
123 RtlFreeUnicodeString (&ArcName);
124
125 Status = NtQuerySymbolicLinkObject (Handle,
126 &DeviceName,
127 &Length);
128 NtClose (Handle);
129 if (!NT_SUCCESS(Status))
130 {
131 RtlFreeUnicodeString (&BootPath);
132 RtlFreeUnicodeString (&DeviceName);
133 DbgPrint("NtQuerySymbolicObject() failed (Status %x)\n",
134 Status);
135
136 KeBugCheck (0x0);
137 }
138 DPRINT("Length: %lu DeviceName: %wZ\n", Length, &DeviceName);
139
140 RtlAppendUnicodeStringToString (&DeviceName,
141 &BootPath);
142
143 RtlFreeUnicodeString (&BootPath);
144 DPRINT("DeviceName: %wZ\n", &DeviceName);
145
146 /* create the '\SystemRoot' link */
147 RtlInitUnicodeString (&LinkName,
148 L"\\SystemRoot");
149
150 Status = IoCreateSymbolicLink (&LinkName,
151 &DeviceName);
152 RtlFreeUnicodeString (&DeviceName);
153 if (!NT_SUCCESS(Status))
154 {
155 DbgPrint("IoCreateSymbolicLink() failed (Status %x)\n",
156 Status);
157
158 KeBugCheck (0x0);
159 }
160
161 /* Check if '\SystemRoot'(LinkName) can be opened, otherwise crash it! */
162 InitializeObjectAttributes (&ObjectAttributes,
163 &LinkName,
164 0,
165 NULL,
166 NULL);
167
168 Status = NtOpenSymbolicLinkObject (&Handle,
169 SYMBOLIC_LINK_ALL_ACCESS,
170 &ObjectAttributes);
171 if (!NT_SUCCESS(Status))
172 {
173 DbgPrint("NtOpenSymbolicLinkObject() failed to open '\\SystemRoot' (Status %x)\n",
174 Status);
175 KeBugCheck (0x0);
176 }
177 NtClose(Handle);
178 }
179
180
181 static VOID
182 InitSystemSharedUserPage (PCSZ ParameterLine)
183 {
184 PKUSER_SHARED_DATA SharedPage;
185
186 UNICODE_STRING ArcDeviceName;
187 UNICODE_STRING ArcName;
188 UNICODE_STRING BootPath;
189 UNICODE_STRING DriveDeviceName;
190 UNICODE_STRING DriveName;
191 WCHAR DriveNameBuffer[20];
192 PCHAR ParamBuffer;
193 PWCHAR ArcNameBuffer;
194 PCHAR p;
195 NTSTATUS Status;
196 ULONG Length;
197 OBJECT_ATTRIBUTES ObjectAttributes;
198 HANDLE Handle;
199 ULONG i;
200 BOOLEAN BootDriveFound;
201
202 SharedPage = (PKUSER_SHARED_DATA)KERNEL_SHARED_DATA_BASE;
203 SharedPage->DosDeviceMap = 0;
204 SharedPage->NtProductType = NtProductWinNt;
205 for (i = 0; i < 32; i++)
206 {
207 SharedPage->DosDeviceDriveType[i] = 0;
208 }
209
210 BootDriveFound = FALSE;
211
212 /*
213 * Retrieve the current dos system path
214 * (e.g.: C:\reactos) from the given arc path
215 * (e.g.: multi(0)disk(0)rdisk(0)partititon(1)\reactos)
216 * Format: "<arc_name>\<path> [options...]"
217 */
218
219 /* create local parameter line copy */
220 ParamBuffer = ExAllocatePool (PagedPool, 256);
221 strcpy (ParamBuffer, (char *)ParameterLine);
222 DPRINT("%s\n", ParamBuffer);
223
224 /* cut options off */
225 p = strchr (ParamBuffer, ' ');
226 if (p)
227 {
228 *p = 0;
229 }
230 DPRINT("%s\n", ParamBuffer);
231
232 /* extract path */
233 p = strchr (ParamBuffer, '\\');
234 if (p)
235 {
236 DPRINT("Boot path: %s\n", p);
237 RtlCreateUnicodeStringFromAsciiz (&BootPath, p);
238 *p = 0;
239 }
240 else
241 {
242 DPRINT("Boot path: %s\n", "\\");
243 RtlCreateUnicodeStringFromAsciiz (&BootPath, "\\");
244 }
245 DPRINT("Arc name: %s\n", ParamBuffer);
246
247 /* Only arc name left - build full arc name */
248 ArcNameBuffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
249 swprintf (ArcNameBuffer, L"\\ArcName\\%S", ParamBuffer);
250 RtlInitUnicodeString (&ArcName, ArcNameBuffer);
251 DPRINT("Arc name: %wZ\n", &ArcName);
252
253 /* free ParamBuffer */
254 ExFreePool (ParamBuffer);
255
256 /* allocate arc device name string */
257 ArcDeviceName.Length = 0;
258 ArcDeviceName.MaximumLength = 256 * sizeof(WCHAR);
259 ArcDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
260
261 InitializeObjectAttributes (&ObjectAttributes,
262 &ArcName,
263 0,
264 NULL,
265 NULL);
266
267 Status = NtOpenSymbolicLinkObject (&Handle,
268 SYMBOLIC_LINK_ALL_ACCESS,
269 &ObjectAttributes);
270 RtlFreeUnicodeString (&ArcName);
271 if (!NT_SUCCESS(Status))
272 {
273 RtlFreeUnicodeString (&BootPath);
274 RtlFreeUnicodeString (&ArcDeviceName);
275 DbgPrint("NtOpenSymbolicLinkObject() failed (Status %x)\n",
276 Status);
277
278 KeBugCheck (0x0);
279 }
280
281 Status = NtQuerySymbolicLinkObject (Handle,
282 &ArcDeviceName,
283 &Length);
284 NtClose (Handle);
285 if (!NT_SUCCESS(Status))
286 {
287 RtlFreeUnicodeString (&BootPath);
288 RtlFreeUnicodeString (&ArcDeviceName);
289 DbgPrint("NtQuerySymbolicObject() failed (Status %x)\n",
290 Status);
291
292 KeBugCheck (0x0);
293 }
294 DPRINT("Length: %lu ArcDeviceName: %wZ\n", Length, &ArcDeviceName);
295
296
297 /* allocate device name string */
298 DriveDeviceName.Length = 0;
299 DriveDeviceName.MaximumLength = 256 * sizeof(WCHAR);
300 DriveDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
301
302 for (i = 0; i < 26; i++)
303 {
304 swprintf (DriveNameBuffer, L"\\??\\%C:", 'A' + i);
305 RtlInitUnicodeString (&DriveName,
306 DriveNameBuffer);
307
308 InitializeObjectAttributes (&ObjectAttributes,
309 &DriveName,
310 0,
311 NULL,
312 NULL);
313
314 Status = NtOpenSymbolicLinkObject (&Handle,
315 SYMBOLIC_LINK_ALL_ACCESS,
316 &ObjectAttributes);
317 if (!NT_SUCCESS(Status))
318 {
319 DPRINT("Failed to open link %wZ\n",
320 &DriveName);
321 continue;
322 }
323
324 Status = NtQuerySymbolicLinkObject (Handle,
325 &DriveDeviceName,
326 &Length);
327 if (!NT_SUCCESS(Status))
328 {
329 DPRINT("Failed query open link %wZ\n",
330 &DriveName);
331 continue;
332 }
333 DPRINT("Opened link: %wZ ==> %wZ\n",
334 &DriveName, &DriveDeviceName);
335
336 if (!RtlCompareUnicodeString (&ArcDeviceName, &DriveDeviceName, FALSE))
337 {
338 DPRINT("DOS Boot path: %c:%wZ\n", 'A' + i, &BootPath);
339 swprintf (SharedPage->NtSystemRoot,
340 L"%C:%wZ", 'A' + i, &BootPath);
341
342 BootDriveFound = TRUE;
343 }
344
345 NtClose (Handle);
346
347 /* set bit in dos drives bitmap (drive available) */
348 SharedPage->DosDeviceMap |= (1<<i);
349 }
350
351 RtlFreeUnicodeString (&BootPath);
352 RtlFreeUnicodeString (&DriveDeviceName);
353 RtlFreeUnicodeString (&ArcDeviceName);
354
355 DPRINT("DosDeviceMap: 0x%x\n", SharedPage->DosDeviceMap);
356
357 if (BootDriveFound == FALSE)
358 {
359 DbgPrint("No system drive found!\n");
360 KeBugCheck (0x0);
361 }
362 }
363
364 extern NTSTATUS STDCALL
365 Ke386CallBios(UCHAR Int, KV86M_REGISTERS* Regs);
366
367 struct __attribute__((packed)) vesa_info
368 {
369 UCHAR Signature[4];
370 USHORT Version;
371 ULONG OEMName;
372 ULONG Capabilities;
373 ULONG SupportedModes;
374 USHORT TotalVideoMemory;
375 USHORT OEMVersion;
376 ULONG VendorName;
377 ULONG ProductName;
378 ULONG ProductRevisionString;
379 UCHAR Reserved[478];
380 };
381
382 VOID
383 TestV86Mode(VOID)
384 {
385 ULONG i;
386 extern UCHAR OrigIVT[1024];
387 KV86M_REGISTERS regs;
388 NTSTATUS Status;
389 struct vesa_info* vi;
390
391 for (i = 0; i < (640 / 4); i++)
392 {
393 MmCreateVirtualMapping(NULL,
394 (PVOID)(i * 4096),
395 PAGE_EXECUTE_READWRITE,
396 (ULONG)MmAllocPage(0));
397 }
398 for (; i < (1024 / 4); i++)
399 {
400 MmCreateVirtualMapping(NULL,
401 (PVOID)(i * 4096),
402 PAGE_EXECUTE_READ,
403 i * 4096);
404 }
405 vi = (struct vesa_info*)0x20000;
406 vi->Signature[0] = 'V';
407 vi->Signature[1] = 'B';
408 vi->Signature[2] = 'E';
409 vi->Signature[3] = '2';
410 memset(&regs, 0, sizeof(regs));
411 regs.Eax = 0x4F00;
412 regs.Es = 0x2000;
413 regs.Edi = 0x0;
414 memcpy((PVOID)0x0, OrigIVT, 1024);
415 Status = Ke386CallBios(0x10, &regs);
416 DbgPrint("Finished (Status %x, CS:EIP %x:%x)\n", Status, regs.Cs,
417 regs.Eip);
418 DbgPrint("Eax %x\n", regs.Eax);
419 DbgPrint("Signature %.4s\n", vi->Signature);
420 DbgPrint("TotalVideoMemory %dKB\n", vi->TotalVideoMemory * 64);
421 }
422
423 VOID
424 _main (ULONG MultiBootMagic, PLOADER_PARAMETER_BLOCK _LoaderBlock)
425 /*
426 * FUNCTION: Called by the boot loader to start the kernel
427 * ARGUMENTS:
428 * LoaderBlock = Pointer to boot parameters initialized by the boot
429 * loader
430 * NOTE: The boot parameters are stored in low memory which will become
431 * invalid after the memory managment is initialized so we make a local copy.
432 */
433 {
434 ULONG i;
435 ULONG last_kernel_address;
436 ULONG start;
437
438 /*
439 * Copy the parameters to a local buffer because lowmem will go away
440 */
441 memcpy (&KeLoaderBlock, _LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK));
442 memcpy (&KeLoaderModules, (PVOID)KeLoaderBlock.ModsAddr,
443 sizeof(LOADER_MODULE) * KeLoaderBlock.ModsCount);
444 KeLoaderBlock.ModsAddr = (ULONG)&KeLoaderModules;
445 strcpy (KeLoaderCommandLine, (PUCHAR)KeLoaderBlock.CommandLine);
446 KeLoaderBlock.CommandLine = (ULONG)KeLoaderCommandLine;
447 for (i = 0; i < KeLoaderBlock.ModsCount; i++)
448 {
449 strcpy(KeLoaderModuleStrings[i], (PUCHAR)KeLoaderModules[i].String);
450 KeLoaderModules[i].ModStart -= 0x200000;
451 KeLoaderModules[i].ModStart += 0xc0000000;
452 KeLoaderModules[i].ModEnd -= 0x200000;
453 KeLoaderModules[i].ModEnd += 0xc0000000;
454 KeLoaderModules[i].String = (ULONG)KeLoaderModuleStrings[i];
455 }
456
457 /*
458
459 * FIXME: Preliminary hack!!!!
460 * Initializes the kernel parameter line.
461 * This should be done by the boot loader.
462 */
463 strcpy ((PUCHAR)KeLoaderBlock.CommandLine,
464 "multi(0)disk(0)rdisk(0)partition(1)\\reactos /DEBUGPORT=SCREEN");
465
466 /*
467 * Initialization phase 0
468 */
469 HalInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
470 KeInit1();
471 KeLowerIrql(DISPATCH_LEVEL);
472
473 {
474 char tmpbuf[80];
475 sprintf(tmpbuf,"system with %d MB extended memory\n",
476 (unsigned int)(KeLoaderBlock.MemLower)/1024);
477 HalDisplayString(tmpbuf);
478 }
479
480 /*
481 * Display version number and copyright/warranty message
482 */
483 HalDisplayString("Starting ReactOS "KERNEL_VERSION_STR" (Build "
484 KERNEL_VERSION_BUILD_STR")\n");
485 HalDisplayString("Copyright 2000 (So who owns the copyright?).\n");
486 HalDisplayString("ReactOS is free software, covered by the GNU General "
487 "Public License, and you\n");
488 HalDisplayString("are welcome to change it and/or distribute copies of it "
489 "under certain\n");
490 HalDisplayString("conditions.\n");
491 HalDisplayString("There is absolutely no warranty for ReactOS.\n");
492
493 last_kernel_address = KeLoaderModules[KeLoaderBlock.ModsCount - 1].ModEnd;
494
495 NtEarlyInitVdm();
496 MmInit1(KeLoaderModules[0].ModStart - 0xc0000000 + 0x200000,
497 last_kernel_address - 0xc0000000 + 0x200000,
498 last_kernel_address);
499
500 /*
501 * Initialize the kernel debugger
502 */
503 KdInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
504 if (KdPollBreakIn ())
505 {
506 DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C);
507 }
508
509 /*
510 * Initialization phase 1
511 * Initalize various critical subsystems
512 */
513 HalInitSystem (1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
514 MmInit2();
515 KeInit2();
516
517 /*
518 * Allow interrupts
519 */
520 KeLowerIrql(PASSIVE_LEVEL);
521
522 ObInit();
523 PiInitProcessManager();
524 ExInit();
525 IoInit();
526 LdrInitModuleManagement();
527 CmInitializeRegistry();
528 NtInit();
529 MmInit3();
530
531 /* Report all resources used by hal */
532 HalReportResourceUsage ();
533
534 /*
535 * Initalize services loaded at boot time
536 */
537 DPRINT1("%d files loaded\n",KeLoaderBlock.ModsCount);
538
539 /* Pass 1: load registry chunks passed in */
540 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
541 {
542 start = KeLoaderModules[i].ModStart;
543 if (strcmp ((PCHAR) start, "REGEDIT4") == 0)
544 {
545 DPRINT1("process registry chunk at %08lx\n", start);
546 CmImportHive((PCHAR) start);
547 }
548 }
549
550 /* Pass 2: process boot loaded drivers */
551 for (i=1; i < KeLoaderBlock.ModsCount; i++)
552 {
553 start = KeLoaderModules[i].ModStart;
554 if (strcmp ((PCHAR) start, "REGEDIT4") != 0)
555 {
556 DPRINT1("process module at %08lx\n", start);
557 LdrProcessDriver((PVOID)start);
558 }
559 }
560
561 /* Create the SystemRoot symbolic link */
562 CreateSystemRootLink ((PUCHAR)KeLoaderBlock.CommandLine);
563
564 CmInitializeRegistry2();
565
566 /*
567 * Load Auto configured drivers
568 */
569 LdrLoadAutoConfigDrivers();
570
571 /*
572 * Assign drive letters
573 */
574 IoAssignDriveLetters ((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock,
575 NULL,
576 NULL,
577 NULL);
578
579 /*
580 * Initialize shared user page:
581 * - set dos system path, dos device map, etc.
582 */
583 InitSystemSharedUserPage ((PUCHAR)KeLoaderBlock.CommandLine);
584
585 /*
586 * Launch initial process
587 */
588 #if 0
589 LdrLoadInitialProcess();
590 #endif
591
592 TestV86Mode();
593
594 DbgPrint("Finished main()\n");
595 PsTerminateSystemThread(STATUS_SUCCESS);
596 }
597
598 /* EOF */
599