3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
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.
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.
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.
19 /* $Id: main.c,v 1.101 2001/07/14 21:10:31 chorns Exp $
21 * PROJECT: ReactOS kernel
22 * FILE: ntoskrnl/ke/main.c
23 * PURPOSE: Initalizes the kernel
24 * PROGRAMMER: David Welch (welch@cwcom.net)
29 /* INCLUDES *****************************************************************/
31 #include <ddk/ntddk.h>
32 #include <internal/ntoskrnl.h>
33 #include <reactos/resource.h>
34 #include <internal/mm.h>
35 #include <internal/module.h>
36 #include <internal/ldr.h>
37 #include <internal/ex.h>
38 #include <internal/ps.h>
39 #include <internal/ke.h>
40 #include <internal/io.h>
41 #include <internal/po.h>
42 //#include <internal/se.h>
43 #include <napi/shared_data.h>
44 #include <internal/v86m.h>
45 #include <internal/kd.h>
46 #include <internal/trap.h>
47 #include "../dbg/kdb.h"
50 #include <internal/debug.h>
52 /* GLOBALS *******************************************************************/
54 ULONG EXPORTED NtBuildNumber
= KERNEL_VERSION_BUILD
;
55 ULONG EXPORTED NtGlobalFlag
= 0;
56 CHAR EXPORTED KeNumberProcessors
;
57 LOADER_PARAMETER_BLOCK EXPORTED KeLoaderBlock
;
58 static LOADER_MODULE KeLoaderModules
[64];
59 static UCHAR KeLoaderModuleStrings
[64][256];
60 static UCHAR KeLoaderCommandLine
[256];
61 static ADDRESS_RANGE KeMemoryMap
[64];
62 static ULONG KeMemoryMapRangeCount
;
63 static ULONG FirstKrnlPhysAddr
;
64 static ULONG LastKrnlPhysAddr
;
65 static ULONG LastKernelAddress
;
66 volatile BOOLEAN Initialized
= FALSE
;
68 /* FUNCTIONS ****************************************************************/
71 RtlpCheckFileNameExtension(PCHAR FileName
,
76 Ext
= strrchr(FileName
, '.');
77 if ((Extension
== NULL
) || (*Extension
== 0))
84 if (*Extension
!= '.')
87 if (_stricmp(Ext
, Extension
) == 0)
94 CreateSystemRootLink (PCSZ ParameterLine
)
96 UNICODE_STRING LinkName
;
97 UNICODE_STRING DeviceName
;
98 UNICODE_STRING ArcName
;
99 UNICODE_STRING BootPath
;
101 PWCHAR ArcNameBuffer
;
105 OBJECT_ATTRIBUTES ObjectAttributes
;
108 /* create local parameter line copy */
109 ParamBuffer
= ExAllocatePool (PagedPool
, 256);
110 strcpy (ParamBuffer
, (char *)ParameterLine
);
112 DPRINT("%s\n", ParamBuffer
);
113 /* Format: <arc_name>\<path> [options...] */
115 /* cut options off */
116 p
= strchr (ParamBuffer
, ' ');
119 DPRINT("%s\n", ParamBuffer
);
122 p
= strchr (ParamBuffer
, '\\');
125 DPRINT("Boot path: %s\n", p
);
126 RtlCreateUnicodeStringFromAsciiz (&BootPath
, p
);
131 DPRINT("Boot path: %s\n", "\\");
132 RtlCreateUnicodeStringFromAsciiz (&BootPath
, "\\");
134 DPRINT("Arc name: %s\n", ParamBuffer
);
136 /* Only arc name left - build full arc name */
137 ArcNameBuffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
138 swprintf (ArcNameBuffer
,
139 L
"\\ArcName\\%S", ParamBuffer
);
140 RtlInitUnicodeString (&ArcName
, ArcNameBuffer
);
141 DPRINT1("Arc name: %wZ\n", &ArcName
);
143 /* free ParamBuffer */
144 ExFreePool (ParamBuffer
);
146 /* allocate device name string */
147 DeviceName
.Length
= 0;
148 DeviceName
.MaximumLength
= 256 * sizeof(WCHAR
);
149 DeviceName
.Buffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
151 InitializeObjectAttributes (&ObjectAttributes
,
157 Status
= NtOpenSymbolicLinkObject (&Handle
,
158 SYMBOLIC_LINK_ALL_ACCESS
,
160 if (!NT_SUCCESS(Status
))
162 RtlFreeUnicodeString (&BootPath
);
163 RtlFreeUnicodeString (&DeviceName
);
164 DPRINT("NtOpenSymbolicLinkObject() '%wZ' failed (Status %x)\n",
167 RtlFreeUnicodeString (&ArcName
);
171 RtlFreeUnicodeString (&ArcName
);
173 Status
= NtQuerySymbolicLinkObject (Handle
,
177 if (!NT_SUCCESS(Status
))
179 RtlFreeUnicodeString (&BootPath
);
180 RtlFreeUnicodeString (&DeviceName
);
181 DbgPrint("NtQuerySymbolicObject() failed (Status %x)\n",
186 DPRINT("Length: %lu DeviceName: %wZ\n", Length
, &DeviceName
);
188 RtlAppendUnicodeStringToString (&DeviceName
,
191 RtlFreeUnicodeString (&BootPath
);
192 DPRINT("DeviceName: %wZ\n", &DeviceName
);
194 /* create the '\SystemRoot' link */
195 RtlInitUnicodeString (&LinkName
,
198 Status
= IoCreateSymbolicLink (&LinkName
,
200 RtlFreeUnicodeString (&DeviceName
);
201 if (!NT_SUCCESS(Status
))
203 DbgPrint("IoCreateSymbolicLink() failed (Status %x)\n",
209 /* Check if '\SystemRoot'(LinkName) can be opened, otherwise crash it! */
210 InitializeObjectAttributes (&ObjectAttributes
,
216 Status
= NtOpenSymbolicLinkObject (&Handle
,
217 SYMBOLIC_LINK_ALL_ACCESS
,
219 if (!NT_SUCCESS(Status
))
221 DbgPrint("NtOpenSymbolicLinkObject() failed to open '\\SystemRoot' (Status %x)\n",
230 InitSystemSharedUserPage (PCSZ ParameterLine
)
232 PKUSER_SHARED_DATA SharedPage
;
234 UNICODE_STRING ArcDeviceName
;
235 UNICODE_STRING ArcName
;
236 UNICODE_STRING BootPath
;
237 UNICODE_STRING DriveDeviceName
;
238 UNICODE_STRING DriveName
;
239 WCHAR DriveNameBuffer
[20];
241 PWCHAR ArcNameBuffer
;
245 OBJECT_ATTRIBUTES ObjectAttributes
;
248 BOOLEAN BootDriveFound
;
250 SharedPage
= (PKUSER_SHARED_DATA
)KERNEL_SHARED_DATA_BASE
;
251 SharedPage
->DosDeviceMap
= 0;
252 SharedPage
->NtProductType
= NtProductWinNt
;
253 for (i
= 0; i
< 32; i
++)
255 SharedPage
->DosDeviceDriveType
[i
] = 0;
258 BootDriveFound
= FALSE
;
261 * Retrieve the current dos system path
262 * (e.g.: C:\reactos) from the given arc path
263 * (e.g.: multi(0)disk(0)rdisk(0)partititon(1)\reactos)
264 * Format: "<arc_name>\<path> [options...]"
267 /* create local parameter line copy */
268 ParamBuffer
= ExAllocatePool (PagedPool
, 256);
269 strcpy (ParamBuffer
, (char *)ParameterLine
);
270 DPRINT("%s\n", ParamBuffer
);
272 /* cut options off */
273 p
= strchr (ParamBuffer
, ' ');
278 DPRINT("%s\n", ParamBuffer
);
281 p
= strchr (ParamBuffer
, '\\');
284 DPRINT("Boot path: %s\n", p
);
285 RtlCreateUnicodeStringFromAsciiz (&BootPath
, p
);
290 DPRINT("Boot path: %s\n", "\\");
291 RtlCreateUnicodeStringFromAsciiz (&BootPath
, "\\");
293 DPRINT("Arc name: %s\n", ParamBuffer
);
295 /* Only arc name left - build full arc name */
296 ArcNameBuffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
297 swprintf (ArcNameBuffer
, L
"\\ArcName\\%S", ParamBuffer
);
298 RtlInitUnicodeString (&ArcName
, ArcNameBuffer
);
299 DPRINT("Arc name: %wZ\n", &ArcName
);
301 /* free ParamBuffer */
302 ExFreePool (ParamBuffer
);
304 /* allocate arc device name string */
305 ArcDeviceName
.Length
= 0;
306 ArcDeviceName
.MaximumLength
= 256 * sizeof(WCHAR
);
307 ArcDeviceName
.Buffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
309 InitializeObjectAttributes (&ObjectAttributes
,
315 Status
= NtOpenSymbolicLinkObject (&Handle
,
316 SYMBOLIC_LINK_ALL_ACCESS
,
318 RtlFreeUnicodeString (&ArcName
);
319 if (!NT_SUCCESS(Status
))
321 RtlFreeUnicodeString (&BootPath
);
322 RtlFreeUnicodeString (&ArcDeviceName
);
323 DbgPrint("NtOpenSymbolicLinkObject() failed (Status %x)\n",
329 Status
= NtQuerySymbolicLinkObject (Handle
,
333 if (!NT_SUCCESS(Status
))
335 RtlFreeUnicodeString (&BootPath
);
336 RtlFreeUnicodeString (&ArcDeviceName
);
337 DbgPrint("NtQuerySymbolicObject() failed (Status %x)\n",
342 DPRINT("Length: %lu ArcDeviceName: %wZ\n", Length
, &ArcDeviceName
);
345 /* allocate device name string */
346 DriveDeviceName
.Length
= 0;
347 DriveDeviceName
.MaximumLength
= 256 * sizeof(WCHAR
);
348 DriveDeviceName
.Buffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
350 for (i
= 0; i
< 26; i
++)
352 swprintf (DriveNameBuffer
, L
"\\??\\%C:", 'A' + i
);
353 RtlInitUnicodeString (&DriveName
,
356 InitializeObjectAttributes (&ObjectAttributes
,
362 Status
= NtOpenSymbolicLinkObject (&Handle
,
363 SYMBOLIC_LINK_ALL_ACCESS
,
365 if (!NT_SUCCESS(Status
))
367 DPRINT("Failed to open link %wZ\n",
372 Status
= NtQuerySymbolicLinkObject (Handle
,
375 if (!NT_SUCCESS(Status
))
377 DPRINT("Failed query open link %wZ\n",
381 DPRINT("Opened link: %wZ ==> %wZ\n",
382 &DriveName
, &DriveDeviceName
);
384 if (!RtlCompareUnicodeString (&ArcDeviceName
, &DriveDeviceName
, FALSE
))
386 DPRINT("DOS Boot path: %c:%wZ\n", 'A' + i
, &BootPath
);
387 swprintf (SharedPage
->NtSystemRoot
,
388 L
"%C:%wZ", 'A' + i
, &BootPath
);
390 BootDriveFound
= TRUE
;
395 /* set bit in dos drives bitmap (drive available) */
396 SharedPage
->DosDeviceMap
|= (1<<i
);
399 RtlFreeUnicodeString (&BootPath
);
400 RtlFreeUnicodeString (&DriveDeviceName
);
401 RtlFreeUnicodeString (&ArcDeviceName
);
403 DPRINT("DosDeviceMap: 0x%x\n", SharedPage
->DosDeviceMap
);
405 if (BootDriveFound
== FALSE
)
407 DbgPrint("No system drive found!\n");
414 VOID
DumpBIOSMemoryMap(VOID
)
418 DbgPrint("Dumping BIOS memory map:\n");
419 DbgPrint("Memory map base: %d\n", KeLoaderBlock
.MmapAddr
);
420 DbgPrint("Memory map size: %d\n", KeLoaderBlock
.MmapLength
);
421 DbgPrint("Address range count: %d\n", KeMemoryMapRangeCount
);
422 for (i
= 0; i
< KeMemoryMapRangeCount
; i
++)
424 DbgPrint("Range: Base (%08X) Length (%08X) Type (%02X)\n",
425 KeMemoryMap
[i
].BaseAddrLow
,
426 KeMemoryMap
[i
].LengthLow
,
427 KeMemoryMap
[i
].Type
);
435 ExpInitializeExecutive(VOID
)
444 * Fail at runtime if someone has changed various structures without
445 * updating the offsets used for the assembler code.
447 assert(FIELD_OFFSET(KTHREAD
, InitialStack
) == KTHREAD_INITIAL_STACK
);
448 assert(FIELD_OFFSET(KTHREAD
, Teb
) == KTHREAD_TEB
);
449 assert(FIELD_OFFSET(KTHREAD
, KernelStack
) == KTHREAD_KERNEL_STACK
);
450 assert(FIELD_OFFSET(KTHREAD
, PreviousMode
) == KTHREAD_PREVIOUS_MODE
);
451 assert(FIELD_OFFSET(KTHREAD
, TrapFrame
) == KTHREAD_TRAP_FRAME
);
452 assert(FIELD_OFFSET(ETHREAD
, ThreadsProcess
) == ETHREAD_THREADS_PROCESS
);
453 assert(FIELD_OFFSET(KPROCESS
, DirectoryTableBase
) ==
454 KPROCESS_DIRECTORY_TABLE_BASE
);
455 assert(FIELD_OFFSET(KTRAP_FRAME
, Reserved9
) == KTRAP_FRAME_RESERVED9
);
456 assert(FIELD_OFFSET(KV86M_TRAP_FRAME
, regs
) == TF_REGS
);
457 assert(FIELD_OFFSET(KV86M_TRAP_FRAME
, orig_ebp
) == TF_ORIG_EBP
);
459 assert(FIELD_OFFSET(KPCR
, ExceptionList
) == KPCR_EXCEPTION_LIST
);
460 assert(FIELD_OFFSET(KPCR
, Self
) == KPCR_SELF
);
461 assert(FIELD_OFFSET(KPCR
, CurrentThread
) == KPCR_CURRENT_THREAD
);
465 KeLowerIrql(DISPATCH_LEVEL
);
469 MmInit1(FirstKrnlPhysAddr
,
472 (PADDRESS_RANGE
)&KeMemoryMap
,
473 KeMemoryMapRangeCount
);
476 * Initialize the kernel debugger
478 KdInitSystem (0, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
479 if (KdPollBreakIn ())
481 DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C
);
487 KeLowerIrql(PASSIVE_LEVEL
);
490 PiInitProcessManager();
493 * Display version number and copyright/warranty message
495 HalDisplayString("Starting ReactOS "KERNEL_VERSION_STR
" (Build "
496 KERNEL_VERSION_BUILD_STR
")\n");
497 HalDisplayString(RES_STR_LEGAL_COPYRIGHT
);
498 HalDisplayString("\n\nReactOS is free software, covered by the GNU General "
499 "Public License, and you\n");
500 HalDisplayString("are welcome to change it and/or distribute copies of it "
502 HalDisplayString("conditions. There is absolutely no warranty for "
505 /* Initialize all processors */
506 KeNumberProcessors
= 0;
508 while (!HalAllProcessorsStarted())
510 if (KeNumberProcessors
!= 0)
512 KePrepareForApplicationProcessorInit(KeNumberProcessors
);
513 PsPrepareForApplicationProcessorInit(KeNumberProcessors
);
515 HalInitializeProcessor(KeNumberProcessors
);
516 KeNumberProcessors
++;
519 if (KeNumberProcessors
> 1)
522 "Found %d system processors. [%lu MB Memory]\n",
524 (KeLoaderBlock
.MemHigher
+ 1088)/ 1024);
529 "Found 1 system processor. [%lu MB Memory]\n",
530 (KeLoaderBlock
.MemHigher
+ 1088)/ 1024);
532 HalDisplayString(str
);
535 * Initialize various critical subsystems
537 HalInitSystem(1, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
542 LdrInitModuleManagement();
543 CmInitializeRegistry();
547 /* Report all resources used by hal */
548 HalReportResourceUsage();
550 // DumpBIOSMemoryMap();
553 * Initalize services loaded at boot time
555 DPRINT1("%d files loaded\n",KeLoaderBlock
.ModsCount
);
556 for (i
=0; i
< KeLoaderBlock
.ModsCount
; i
++)
558 CPRINT("Module: '%s' at %08lx, length 0x%08lx\n",
559 KeLoaderModules
[i
].String
,
560 KeLoaderModules
[i
].ModStart
,
561 KeLoaderModules
[i
].ModEnd
- KeLoaderModules
[i
].ModStart
);
564 /* Pass 1: load nls files */
565 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
567 name
= (PCHAR
)KeLoaderModules
[i
].String
;
568 if (RtlpCheckFileNameExtension(name
, ".nls"))
575 name
= (PCHAR
)KeLoaderModules
[i
+1].String
;
576 if (RtlpCheckFileNameExtension(name
, ".nls"))
578 Mod2Start
= (ULONG
)KeLoaderModules
[i
+1].ModStart
;
579 Mod2End
= (ULONG
)KeLoaderModules
[i
+1].ModEnd
;
581 name
= (PCHAR
)KeLoaderModules
[i
+2].String
;
582 if (RtlpCheckFileNameExtension(name
, ".nls"))
584 Mod3Start
= (ULONG
)KeLoaderModules
[i
+2].ModStart
;
585 Mod3End
= (ULONG
)KeLoaderModules
[i
+2].ModEnd
;
589 /* Initialize nls sections */
590 RtlpInitNlsSections((ULONG
)KeLoaderModules
[i
].ModStart
,
591 (ULONG
)KeLoaderModules
[i
].ModEnd
,
600 /* Pass 2: load registry chunks passed in */
601 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
603 start
= KeLoaderModules
[i
].ModStart
;
604 name
= (PCHAR
)KeLoaderModules
[i
].String
;
605 if (RtlpCheckFileNameExtension(name
, "") ||
606 RtlpCheckFileNameExtension(name
, ".hiv"))
608 CPRINT("Process registry chunk at %08lx\n", start
);
609 CmImportHive((PCHAR
) start
);
614 * Enter the kernel debugger before starting up the boot drivers
620 /* Pass 3: process boot loaded drivers */
621 for (i
=1; i
< KeLoaderBlock
.ModsCount
; i
++)
623 start
= KeLoaderModules
[i
].ModStart
;
624 length
= KeLoaderModules
[i
].ModEnd
- start
;
625 name
= (PCHAR
)KeLoaderModules
[i
].String
;
626 if (RtlpCheckFileNameExtension(name
, ".sys") ||
627 RtlpCheckFileNameExtension(name
, ".sym"))
629 CPRINT("Processing module '%s' at %08lx, length 0x%08lx\n",
630 name
, start
, length
);
631 LdrProcessDriver((PVOID
)start
, name
, length
);
635 /* Create the SystemRoot symbolic link */
636 CPRINT("CommandLine: %s\n", (PUCHAR
)KeLoaderBlock
.CommandLine
);
638 CreateSystemRootLink ((PUCHAR
)KeLoaderBlock
.CommandLine
);
640 #ifdef DBGPRINT_FILE_LOG
641 /* On the assumption that we can now access disks start up the debug
644 #endif /* DBGPRINT_FILE_LOG */
647 CmInitializeRegistry2();
649 PiInitDefaultLocale();
652 * Start the motherboard enumerator (the HAL)
654 HalInitSystem(2, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
657 * Load boot start drivers
659 IopLoadBootStartDrivers();
662 * Load Auto configured drivers
664 LdrLoadAutoConfigDrivers();
667 * Assign drive letters
669 IoAssignDriveLetters ((PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
,
675 * Initialize shared user page:
676 * - set dos system path, dos device map, etc.
678 InitSystemSharedUserPage ((PUCHAR
)KeLoaderBlock
.CommandLine
);
681 * Launch initial process
683 LdrLoadInitialProcess();
685 PsTerminateSystemThread(STATUS_SUCCESS
);
689 KiSystemStartup(BOOLEAN BootProcessor
)
691 HalInitSystem (0, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
695 ExpInitializeExecutive();
698 /* Do application processor initialization */
699 KeApplicationProcessorInit();
700 PsApplicationProcessorInit();
701 KeLowerIrql(PASSIVE_LEVEL
);
702 PsIdleThreadMain(NULL
);
708 _main (ULONG MultiBootMagic
, PLOADER_PARAMETER_BLOCK _LoaderBlock
)
710 * FUNCTION: Called by the boot loader to start the kernel
712 * LoaderBlock = Pointer to boot parameters initialized by the boot
714 * NOTE: The boot parameters are stored in low memory which will become
715 * invalid after the memory managment is initialized so we make a local copy.
720 ULONG last_kernel_address
;
721 extern ULONG _bss_end__
;
724 * Copy the parameters to a local buffer because lowmem will go away
726 memcpy (&KeLoaderBlock
, _LoaderBlock
, sizeof(LOADER_PARAMETER_BLOCK
));
727 memcpy (&KeLoaderModules
[1], (PVOID
)KeLoaderBlock
.ModsAddr
,
728 sizeof(LOADER_MODULE
) * KeLoaderBlock
.ModsCount
);
729 KeLoaderBlock
.ModsCount
++;
730 KeLoaderBlock
.ModsAddr
= (ULONG
)&KeLoaderModules
;
733 * FIXME: Preliminary hack!!!! Add boot device to beginning of command line.
734 * This should be done by the boot loader.
736 strcpy (KeLoaderCommandLine
,
737 "multi(0)disk(0)rdisk(0)partition(1)\\reactos /DEBUGPORT=SCREEN");
738 strcat (KeLoaderCommandLine
, (PUCHAR
)KeLoaderBlock
.CommandLine
);
740 KeLoaderBlock
.CommandLine
= (ULONG
)KeLoaderCommandLine
;
741 strcpy(KeLoaderModuleStrings
[0], "ntoskrnl.exe");
742 KeLoaderModules
[0].String
= (ULONG
)KeLoaderModuleStrings
[0];
743 KeLoaderModules
[0].ModStart
= 0xC0000000;
744 KeLoaderModules
[0].ModEnd
= PAGE_ROUND_UP((ULONG
)&_bss_end__
);
745 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
747 strcpy(KeLoaderModuleStrings
[i
], (PUCHAR
)KeLoaderModules
[i
].String
);
748 KeLoaderModules
[i
].ModStart
-= 0x200000;
749 KeLoaderModules
[i
].ModStart
+= 0xc0000000;
750 KeLoaderModules
[i
].ModEnd
-= 0x200000;
751 KeLoaderModules
[i
].ModEnd
+= 0xc0000000;
752 KeLoaderModules
[i
].String
= (ULONG
)KeLoaderModuleStrings
[i
];
755 last_kernel_address
= KeLoaderModules
[KeLoaderBlock
.ModsCount
- 1].ModEnd
;
757 FirstKrnlPhysAddr
= KeLoaderModules
[0].ModStart
- 0xc0000000 + 0x200000;
758 LastKrnlPhysAddr
= last_kernel_address
- 0xc0000000 + 0x200000;
759 LastKernelAddress
= last_kernel_address
;
762 /* FIXME: VMware does not like it when ReactOS is using the BIOS memory map */
763 KeLoaderBlock
.Flags
&= ~MB_FLAGS_MMAP_INFO
;
766 KeMemoryMapRangeCount
= 0;
767 if (KeLoaderBlock
.Flags
& MB_FLAGS_MMAP_INFO
)
769 /* We have a memory map from the nice BIOS */
770 size
= *((PULONG
)(KeLoaderBlock
.MmapAddr
- sizeof(ULONG
)));
772 while (i
< KeLoaderBlock
.MmapLength
)
774 memcpy (&KeMemoryMap
[KeMemoryMapRangeCount
],
775 (PVOID
)(KeLoaderBlock
.MmapAddr
+ i
),
776 sizeof(ADDRESS_RANGE
));
777 KeMemoryMapRangeCount
++;