- Add missing KERNEL_LARGE_STACK_COMMIT definition to DDK.
[reactos.git] / reactos / ntoskrnl / ke / freeldr.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ke/freeldr.c
5 * PURPOSE: FreeLDR Bootstrap Support
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 /* INCLUDES *****************************************************************/
10
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 typedef struct _BIOS_MEMORY_DESCRIPTOR
16 {
17 ULONG BlockBase;
18 ULONG BlockSize;
19 } BIOS_MEMORY_DESCRIPTOR, *PBIOS_MEMORY_DESCRIPTOR;
20
21 /* GLOBALS *******************************************************************/
22
23 /* FreeLDR Memory Data */
24 ULONG_PTR MmFreeLdrFirstKrnlPhysAddr, MmFreeLdrLastKrnlPhysAddr;
25 ULONG_PTR MmFreeLdrLastKernelAddress;
26 ULONG MmFreeLdrMemHigher;
27 ULONG MmFreeLdrPageDirectoryEnd;
28
29 /* FreeLDR Loader Data */
30 PROS_LOADER_PARAMETER_BLOCK KeRosLoaderBlock;
31 BOOLEAN AcpiTableDetected;
32 ADDRESS_RANGE KeMemoryMap[64];
33 ULONG KeMemoryMapRangeCount;
34
35 /* NT Loader Module/Descriptor Count */
36 ULONG BldrCurrentMd;
37 ULONG BldrCurrentMod;
38
39 /* NT Loader Data. Eats up about 80KB! */
40 LOADER_PARAMETER_BLOCK BldrLoaderBlock; // 0x0000
41 LOADER_PARAMETER_EXTENSION BldrExtensionBlock; // 0x0060
42 CHAR BldrCommandLine[256]; // 0x00DC
43 CHAR BldrArcBootPath[64]; // 0x01DC
44 CHAR BldrArcHalPath[64]; // 0x021C
45 CHAR BldrNtHalPath[64]; // 0x025C
46 CHAR BldrNtBootPath[64]; // 0x029C
47 LDR_DATA_TABLE_ENTRY BldrModules[64]; // 0x02DC
48 MEMORY_ALLOCATION_DESCRIPTOR BldrMemoryDescriptors[60]; // 0x14DC
49 WCHAR BldrModuleStrings[64][260]; // 0x19DC
50 WCHAR BldrModuleStringsFull[64][260]; // 0x9BDC
51 NLS_DATA_BLOCK BldrNlsDataBlock; // 0x11DDC
52 SETUP_LOADER_BLOCK BldrSetupBlock; // 0x11DE8
53 ARC_DISK_INFORMATION BldrArcDiskInfo; // 0x12134
54 CHAR BldrArcNames[32][256]; // 0x1213C
55 ARC_DISK_SIGNATURE BldrDiskInfo[32]; // 0x1413C
56 // 0x1443C
57
58 /* BIOS Memory Map */
59 BIOS_MEMORY_DESCRIPTOR BiosMemoryDescriptors[16] = {{0}};
60 PBIOS_MEMORY_DESCRIPTOR BiosMemoryDescriptorList = BiosMemoryDescriptors;
61
62 /* ARC Memory Map */
63 ULONG NumberDescriptors = 0;
64 MEMORY_DESCRIPTOR MDArray[60] = {{0}};
65
66 /* FUNCTIONS *****************************************************************/
67
68 PMEMORY_ALLOCATION_DESCRIPTOR
69 NTAPI
70 KiRosGetMdFromArray(VOID)
71 {
72 /* Return the next MD from the list, but make sure we don't overflow */
73 if (BldrCurrentMd > 60) KEBUGCHECK(0);
74 return &BldrMemoryDescriptors[BldrCurrentMd++];
75 }
76
77 VOID
78 NTAPI
79 KiRosAddBiosBlock(ULONG Address,
80 ULONG Size)
81 {
82 PBIOS_MEMORY_DESCRIPTOR BiosBlock = BiosMemoryDescriptorList;
83
84 /* Loop our BIOS Memory Descriptor List */
85 while (BiosBlock->BlockSize > 0)
86 {
87 /* Check if we've found a matching head block */
88 if (Address + Size == BiosBlock->BlockBase)
89 {
90 /* Simply enlarge and rebase it */
91 BiosBlock->BlockBase = Address;
92 BiosBlock->BlockSize += Size;
93 break;
94 }
95
96 /* Check if we've found a matching tail block */
97 if (Address == (BiosBlock->BlockBase + BiosBlock->BlockSize))
98 {
99 /* Simply enlarge it */
100 BiosBlock->BlockSize += Size;
101 break;
102 }
103
104 /* Nothing suitable found, try the next block */
105 BiosBlock++;
106 }
107
108 /* No usable blocks found, found a free block instead */
109 if (!BiosBlock->BlockSize)
110 {
111 /* Write our data */
112 BiosBlock->BlockBase = Address;
113 BiosBlock->BlockSize = Size;
114
115 /* Create a new block and mark it as the end of the array */
116 BiosBlock++;
117 BiosBlock->BlockBase = BiosBlock->BlockSize = 0L;
118 }
119 }
120
121 VOID
122 NTAPI
123 KiRosBuildBiosMemoryMap(VOID)
124 {
125 ULONG j;
126 ULONG BlockBegin, BlockEnd;
127
128 /* Loop the BIOS Memory Map */
129 for (j = 0; j < KeMemoryMapRangeCount; j++)
130 {
131 /* Get the start and end addresses */
132 BlockBegin = KeMemoryMap[j].BaseAddrLow;
133 BlockEnd = KeMemoryMap[j].BaseAddrLow + KeMemoryMap[j].LengthLow - 1;
134
135 /* Make sure this isn't a > 4GB descriptor */
136 if (!KeMemoryMap[j].BaseAddrHigh)
137 {
138 /* Make sure we don't overflow */
139 if (BlockEnd < BlockBegin) BlockEnd = 0xFFFFFFFF;
140
141 /* Check if this is free memory */
142 if (KeMemoryMap[j].Type == 1)
143 {
144 /* Add it to our BIOS descriptors */
145 KiRosAddBiosBlock(BlockBegin, BlockEnd - BlockBegin + 1);
146 }
147 }
148 }
149 }
150
151 NTSTATUS
152 NTAPI
153 KiRosAllocateArcDescriptor(IN ULONG PageBegin,
154 IN ULONG PageEnd,
155 IN MEMORY_TYPE MemoryType)
156 {
157 ULONG i;
158
159 /* Loop all our descriptors */
160 for (i = 0; i < NumberDescriptors; i++)
161 {
162 /* Attempt to fing a free block that describes our region */
163 if ((MDArray[i].MemoryType == MemoryFree) &&
164 (MDArray[i].BasePage <= PageBegin) &&
165 (MDArray[i].BasePage + MDArray[i].PageCount > PageBegin) &&
166 (MDArray[i].BasePage + MDArray[i].PageCount >= PageEnd))
167 {
168 /* Found one! */
169 break;
170 }
171 }
172
173 /* Check if we found no free blocks, and fail if so */
174 if (i == NumberDescriptors) return ENOMEM;
175
176 /* Check if the block has our base address */
177 if (MDArray[i].BasePage == PageBegin)
178 {
179 /* Check if it also has our ending address */
180 if ((MDArray[i].BasePage + MDArray[i].PageCount) == PageEnd)
181 {
182 /* Then convert this region into our new memory type */
183 MDArray[i].MemoryType = MemoryType;
184 }
185 else
186 {
187 /* Otherwise, make sure we have enough descriptors */
188 if (NumberDescriptors == 60) return ENOMEM;
189
190 /* Cut this descriptor short */
191 MDArray[i].BasePage = PageEnd;
192 MDArray[i].PageCount -= (PageEnd - PageBegin);
193
194 /* And allocate a new descriptor for our memory range */
195 MDArray[NumberDescriptors].BasePage = PageBegin;
196 MDArray[NumberDescriptors].PageCount = PageEnd - PageBegin;
197 MDArray[NumberDescriptors].MemoryType = MemoryType;
198 NumberDescriptors++;
199 }
200 }
201 else if ((MDArray[i].BasePage + MDArray[i].PageCount) == PageEnd)
202 {
203 /* This block has our end address, make sure we have a free block */
204 if (NumberDescriptors == 60) return ENOMEM;
205
206 /* Rebase this descriptor */
207 MDArray[i].PageCount = PageBegin - MDArray[i].BasePage;
208
209 /* And allocate a new descriptor for our memory range */
210 MDArray[NumberDescriptors].BasePage = PageBegin;
211 MDArray[NumberDescriptors].PageCount = PageEnd - PageBegin;
212 MDArray[NumberDescriptors].MemoryType = MemoryType;
213 NumberDescriptors++;
214 }
215 else
216 {
217 /* We'll need two descriptors, make sure they're available */
218 if ((NumberDescriptors + 1) >= 60) return ENOMEM;
219
220 /* Allocate a free memory descriptor for what follows us */
221 MDArray[NumberDescriptors].BasePage = PageEnd;
222 MDArray[NumberDescriptors].PageCount = MDArray[i].PageCount -
223 (PageEnd - MDArray[i].BasePage);
224 MDArray[NumberDescriptors].MemoryType = MemoryFree;
225 NumberDescriptors++;
226
227 /* Cut down the current free descriptor */
228 MDArray[i].PageCount = PageBegin - MDArray[i].BasePage;
229
230 /* Allocate a new memory descriptor for our memory range */
231 MDArray[NumberDescriptors].BasePage = PageBegin;
232 MDArray[NumberDescriptors].PageCount = PageEnd - PageBegin;
233 MDArray[NumberDescriptors].MemoryType = MemoryType;
234 NumberDescriptors++;
235 }
236
237 /* Everything went well */
238 return STATUS_SUCCESS;
239 }
240
241 NTSTATUS
242 NTAPI
243 KiRosConfigureArcDescriptor(IN ULONG PageBegin,
244 IN ULONG PageEnd,
245 IN TYPE_OF_MEMORY MemoryType)
246 {
247 ULONG i;
248 ULONG BlockBegin, BlockEnd;
249 MEMORY_TYPE BlockType;
250 BOOLEAN Combined = FALSE;
251
252 /* If this descriptor seems bogus, just return */
253 if (PageEnd <= PageBegin) return STATUS_SUCCESS;
254
255 /* Loop every ARC descriptor, trying to find one we can modify */
256 for (i = 0; i < NumberDescriptors; i++)
257 {
258 /* Get its settings */
259 BlockBegin = MDArray[i].BasePage;
260 BlockEnd = MDArray[i].BasePage + MDArray[i].PageCount;
261 BlockType = MDArray[i].MemoryType;
262
263 /* Check if we can fit inside this block */
264 if (BlockBegin < PageBegin)
265 {
266 /* Check if we are larger then it */
267 if ((BlockEnd > PageBegin) && (BlockEnd <= PageEnd))
268 {
269 /* Make it end where we start */
270 BlockEnd = PageBegin;
271 }
272
273 /* Check if it ends after we do */
274 if (BlockEnd > PageEnd)
275 {
276 /* Make sure we can allocate a descriptor */
277 if (NumberDescriptors == 60) return ENOMEM;
278
279 /* Create a descriptor for whatever memory we're not part of */
280 MDArray[NumberDescriptors].MemoryType = BlockType;
281 MDArray[NumberDescriptors].BasePage = PageEnd;
282 MDArray[NumberDescriptors].PageCount = BlockEnd - PageEnd;
283 NumberDescriptors++;
284
285 /* The next block ending is now where we begin */
286 BlockEnd = PageBegin;
287 }
288 }
289 else
290 {
291 /* Check if the blog begins inside our range */
292 if (BlockBegin < PageEnd)
293 {
294 /* Check if it ends before we do */
295 if (BlockEnd < PageEnd)
296 {
297 /* Then make it disappear */
298 BlockEnd = BlockBegin;
299 }
300 else
301 {
302 /* Otherwise make it start where we end */
303 BlockBegin = PageEnd;
304 }
305 }
306 }
307
308 /* Check if the block matches us, and we haven't tried combining yet */
309 if ((BlockType == MemoryType) && !(Combined))
310 {
311 /* Check if it starts where we end */
312 if (BlockBegin == PageEnd)
313 {
314 /* Make it start with us, and combine us */
315 BlockBegin = PageBegin;
316 Combined = TRUE;
317 }
318 else if (BlockEnd == PageBegin)
319 {
320 /* Otherwise, it ends where we begin, combine its ending */
321 BlockEnd = PageEnd;
322 Combined = TRUE;
323 }
324 }
325
326 /* Check the original block data matches with what we came up with */
327 if ((MDArray[i].BasePage == BlockBegin) &&
328 (MDArray[i].PageCount == BlockEnd - BlockBegin))
329 {
330 /* Then skip it */
331 continue;
332 }
333
334 /* Otherwise, set our new settings for this block */
335 MDArray[i].BasePage = BlockBegin;
336 MDArray[i].PageCount = BlockEnd - BlockBegin;
337
338 /* Check if we are killing the block */
339 if (BlockBegin == BlockEnd)
340 {
341 /* Delete this block and restart the loop properly */
342 NumberDescriptors--;
343 if (i < NumberDescriptors) MDArray[i] = MDArray[NumberDescriptors];
344 i--;
345 }
346 }
347
348 /* If we got here without combining, we need to allocate a new block */
349 if (!(Combined) && (MemoryType < LoaderMaximum))
350 {
351 /* Make sure there's enough descriptors */
352 if (NumberDescriptors == 60) return ENOMEM;
353
354 /* Allocate a new block with our data */
355 MDArray[NumberDescriptors].MemoryType = MemoryType;
356 MDArray[NumberDescriptors].BasePage = PageBegin;
357 MDArray[NumberDescriptors].PageCount = PageEnd - PageBegin;
358 NumberDescriptors++;
359 }
360
361 /* Changes complete, return success */
362 return STATUS_SUCCESS;
363 }
364
365 NTSTATUS
366 NTAPI
367 KiRosBuildOsMemoryMap(VOID)
368 {
369 PBIOS_MEMORY_DESCRIPTOR MdBlock;
370 ULONG BlockStart, BlockEnd, BiasedStart, BiasedEnd, PageStart, PageEnd;
371 NTSTATUS Status = STATUS_SUCCESS;
372 ULONG BiosPage = 0xA0;
373
374 /* Loop the BIOS Memory Descriptor List */
375 MdBlock = BiosMemoryDescriptorList;
376 while (MdBlock->BlockSize)
377 {
378 /* Get the statrt and end addresses */
379 BlockStart = MdBlock->BlockBase;
380 BlockEnd = BlockStart + MdBlock->BlockSize - 1;
381
382 /* Align them to page boundaries */
383 BiasedStart = BlockStart & (PAGE_SIZE - 1);
384 if (BiasedStart) BlockStart = BlockStart + PAGE_SIZE - BiasedStart;
385 BiasedEnd = (BlockEnd + 1) & (ULONG)(PAGE_SIZE - 1);
386 if (BiasedEnd) BlockEnd -= BiasedEnd;
387
388 /* Get the actual page numbers */
389 PageStart = BlockStart >> PAGE_SHIFT;
390 PageEnd = (BlockEnd + 1) >> PAGE_SHIFT;
391
392 /* If we're starting at page 0, then put the BIOS page at the end */
393 if (!PageStart) BiosPage = PageEnd;
394
395 /* Check if we did any alignment */
396 if (BiasedStart)
397 {
398 /* Mark that region as reserved */
399 Status = KiRosConfigureArcDescriptor(PageStart - 1,
400 PageStart,
401 MemorySpecialMemory);
402 if (Status != STATUS_SUCCESS) break;
403 }
404
405 /* Check if we did any alignment */
406 if (BiasedEnd)
407 {
408 /* Mark that region as reserved */
409 Status = KiRosConfigureArcDescriptor(PageEnd - 1,
410 PageEnd,
411 MemorySpecialMemory);
412 if (Status != STATUS_SUCCESS) break;
413
414 /* If the bios page was the last page, use the next one instead */
415 if (BiosPage == PageEnd) BiosPage += 1;
416 }
417
418 /* Check if the page is below the 16MB Memory hole */
419 if (PageEnd <= 0xFC0)
420 {
421 /* It is, mark the memory a free */
422 Status = KiRosConfigureArcDescriptor(PageStart,
423 PageEnd,
424 LoaderFree);
425 }
426 else if (PageStart >= 0x1000)
427 {
428 /* It's over 16MB, so that memory gets marked as reserve */
429 Status = KiRosConfigureArcDescriptor(PageStart,
430 PageEnd,
431 LoaderFree);
432 }
433 else
434 {
435 /* Check if it starts below the memory hole */
436 if (PageStart < 0xFC0)
437 {
438 /* Mark that part as free */
439 Status = KiRosConfigureArcDescriptor(PageStart,
440 0xFC0,
441 MemoryFree);
442 if (Status != STATUS_SUCCESS) break;
443
444 /* And update the page start for the code below */
445 PageStart = 0xFC0;
446 }
447
448 /* Any code in the memory hole region ends up as reserve */
449 Status = KiRosConfigureArcDescriptor(PageStart,
450 PageEnd,
451 LoaderFree);
452 }
453
454 /* If we failed, break out, otherwise, go to the next BIOS block */
455 if (Status != STATUS_SUCCESS) break;
456 MdBlock++;
457 }
458
459 /* If anything failed until now, return error code */
460 if (Status != STATUS_SUCCESS) return Status;
461
462 /* Set the top 16MB region as reserved */
463 Status = KiRosConfigureArcDescriptor(0xFC0, 0x1000, MemorySpecialMemory);
464 if (Status != STATUS_SUCCESS) return Status;
465
466 /* Setup the BIOS region as reserved */
467 KiRosConfigureArcDescriptor(0xA0, 0x100, LoaderMaximum);
468 KiRosConfigureArcDescriptor(BiosPage, 0x100, MemoryFirmwarePermanent);
469
470 /* Build an entry for the IVT */
471 Status = KiRosAllocateArcDescriptor(0, 1, MemoryFirmwarePermanent);
472 if (Status != STATUS_SUCCESS) return Status;
473
474 /* Build an entry for the KPCR and KUSER_SHARED_DATA */
475 Status = KiRosAllocateArcDescriptor(1, 3, LoaderMemoryData);
476 if (Status != STATUS_SUCCESS) return Status;
477
478 /* Build an entry for the PDE and return the status */
479 Status = KiRosAllocateArcDescriptor(KeRosLoaderBlock->
480 PageDirectoryStart >> PAGE_SHIFT,
481 KeRosLoaderBlock->
482 PageDirectoryEnd >> PAGE_SHIFT,
483 LoaderMemoryData);
484 return Status;
485 }
486
487 VOID
488 NTAPI
489 KiRosBuildReservedMemoryMap(VOID)
490 {
491 ULONG j;
492 ULONG BlockBegin, BlockEnd, BiasedPage;
493
494 /* Loop the BIOS Memory Map */
495 for (j = 0; j < KeMemoryMapRangeCount; j++)
496 {
497 /* Get the start and end addresses */
498 BlockBegin = KeMemoryMap[j].BaseAddrLow;
499 BlockEnd = BlockBegin + KeMemoryMap[j].LengthLow - 1;
500
501 /* Make sure it wasn't a > 4GB descriptor */
502 if (!KeMemoryMap[j].BaseAddrHigh)
503 {
504 /* Make sure it doesn't overflow */
505 if (BlockEnd < BlockBegin) BlockEnd = 0xFFFFFFFF;
506
507 /* Check if this was free memory */
508 if (KeMemoryMap[j].Type == 1)
509 {
510 /* Get the page-aligned addresses */
511 BiasedPage = BlockBegin & (PAGE_SIZE - 1);
512 BlockBegin >>= PAGE_SHIFT;
513 if (BiasedPage) BlockBegin++;
514 BlockEnd = (BlockEnd >> PAGE_SHIFT) + 1;
515
516 /* Check if the block is within the 16MB memory hole */
517 if ((BlockBegin < 0xFC0) && (BlockEnd >= 0xFC0))
518 {
519 /* Don't allow it to cross this boundary */
520 BlockBegin = 0xFC0;
521 }
522
523 /* Check if the boundary is across 16MB */
524 if ((BlockEnd > 0xFFF) && (BlockBegin <= 0xFFF))
525 {
526 /* Don't let it cross */
527 BlockEnd = 0xFFF;
528 }
529
530 /* Check if the block describes the memory hole */
531 if ((BlockBegin >= 0xFC0) && (BlockEnd <= 0xFFF))
532 {
533 /* Set this region as temporary */
534 KiRosConfigureArcDescriptor(BlockBegin,
535 BlockEnd,
536 MemoryFirmwareTemporary);
537 }
538 }
539 else
540 {
541 /* Get the page-aligned addresses */
542 BlockBegin >>= PAGE_SHIFT;
543 BiasedPage = (BlockEnd + 1) & (PAGE_SIZE - 1);
544 BlockEnd >>= PAGE_SHIFT;
545 if (BiasedPage) BlockEnd++;
546
547 /* Set this memory as reserved */
548 KiRosConfigureArcDescriptor(BlockBegin,
549 BlockEnd + 1,
550 MemorySpecialMemory);
551 }
552 }
553 }
554 }
555
556 VOID
557 NTAPI
558 KiRosInsertNtDescriptor(IN PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor)
559 {
560 PLIST_ENTRY ListHead, PreviousEntry, NextEntry;
561 PMEMORY_ALLOCATION_DESCRIPTOR Descriptor = NULL, NextDescriptor = NULL;
562
563 /* Loop the memory descriptor list */
564 ListHead = &KeLoaderBlock->MemoryDescriptorListHead;
565 PreviousEntry = ListHead;
566 NextEntry = ListHead->Flink;
567 while (NextEntry != ListHead)
568 {
569 /* Get the current descriptor and check if it's below ours */
570 NextDescriptor = CONTAINING_RECORD(NextEntry,
571 MEMORY_ALLOCATION_DESCRIPTOR,
572 ListEntry);
573 if (NewDescriptor->BasePage < NextDescriptor->BasePage) break;
574
575 /* It isn't, save the previous entry and descriptor, and try again */
576 PreviousEntry = NextEntry;
577 Descriptor = NextDescriptor;
578 NextEntry = NextEntry->Flink;
579 }
580
581 /* So we found the right spot to insert. Is this free memory? */
582 if (NewDescriptor->MemoryType != LoaderFree)
583 {
584 /* It isn't, so insert us before the last descriptor */
585 InsertHeadList(PreviousEntry, &NewDescriptor->ListEntry);
586 }
587 else
588 {
589 /* We're free memory. Check if the entry we found is also free memory */
590 if ((PreviousEntry != ListHead) &&
591 ((Descriptor->MemoryType == LoaderFree) ||
592 (Descriptor->MemoryType == LoaderReserve)) &&
593 ((Descriptor->BasePage + Descriptor->PageCount) ==
594 NewDescriptor->BasePage))
595 {
596 /* It's free memory, and we're right after it. Enlarge that block */
597 Descriptor->PageCount += NewDescriptor->PageCount;
598 NewDescriptor = Descriptor;
599 }
600 else
601 {
602 /* Our range scan't be combined, so just insert us separately */
603 InsertHeadList(PreviousEntry, &NewDescriptor->ListEntry);
604 }
605
606 /* Check if we merged with an existing free memory block */
607 if ((NextEntry != ListHead) &&
608 ((NextDescriptor->MemoryType == LoaderFree) ||
609 (NextDescriptor->MemoryType == LoaderReserve)) &&
610 ((NewDescriptor->BasePage + NewDescriptor->PageCount) ==
611 NextDescriptor->BasePage))
612 {
613 /* Update our own block */
614 NewDescriptor->PageCount += NextDescriptor->PageCount;
615
616 /* Remove the next block */
617 RemoveEntryList(&NextDescriptor->ListEntry);
618 }
619 }
620 }
621
622 NTSTATUS
623 NTAPI
624 KiRosBuildNtDescriptor(IN PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor,
625 IN MEMORY_TYPE MemoryType,
626 IN ULONG BasePage,
627 IN ULONG PageCount)
628 {
629 PMEMORY_ALLOCATION_DESCRIPTOR Descriptor, NextDescriptor = NULL;
630 LONG Delta;
631 TYPE_OF_MEMORY CurrentType;
632 BOOLEAN UseNext;
633
634 /* Check how many pages we'll be consuming */
635 Delta = BasePage - MemoryDescriptor->BasePage;
636 if (!(Delta) && (PageCount == MemoryDescriptor->PageCount))
637 {
638 /* We can simply convert the current descriptor into our new type */
639 MemoryDescriptor->MemoryType = MemoryType;
640 }
641 else
642 {
643 /* Get the current memory type of the descriptor, and reserve it */
644 CurrentType = MemoryDescriptor->MemoryType;
645 MemoryDescriptor->MemoryType = LoaderSpecialMemory;
646
647 /* Check if we'll need another descriptor for what's left of memory */
648 UseNext = ((BasePage != MemoryDescriptor->BasePage) &&
649 (Delta + PageCount != MemoryDescriptor->PageCount));
650
651 /* Get a descriptor */
652 Descriptor = KiRosGetMdFromArray();
653 if (!Descriptor) return STATUS_INSUFFICIENT_RESOURCES;
654
655 /* Check if we are using another descriptor */
656 if (UseNext)
657 {
658 /* Allocate that one too */
659 NextDescriptor = KiRosGetMdFromArray();
660 if (!NextDescriptor) return STATUS_INSUFFICIENT_RESOURCES;
661 }
662
663 /* Build the descriptor we got */
664 Descriptor->MemoryType = MemoryType;
665 Descriptor->BasePage = BasePage;
666 Descriptor->PageCount = PageCount;
667
668 /* Check if we're starting at the same place as the old one */
669 if (BasePage == MemoryDescriptor->BasePage)
670 {
671 /* Simply decrease the old descriptor and rebase it */
672 MemoryDescriptor->BasePage += PageCount;
673 MemoryDescriptor->PageCount -= PageCount;
674 MemoryDescriptor->MemoryType = CurrentType;
675 }
676 else if (Delta + PageCount == MemoryDescriptor->PageCount)
677 {
678 /* We finish where the old one did, shorten it */
679 MemoryDescriptor->PageCount -= PageCount;
680 MemoryDescriptor->MemoryType = CurrentType;
681 }
682 else
683 {
684 /* We're inside the current block, mark our free region */
685 NextDescriptor->MemoryType = LoaderFree;
686 NextDescriptor->BasePage = BasePage + PageCount;
687 NextDescriptor->PageCount = MemoryDescriptor->PageCount -
688 (PageCount + Delta);
689
690 /* And cut down the current descriptor */
691 MemoryDescriptor->PageCount = Delta;
692 MemoryDescriptor->MemoryType = CurrentType;
693
694 /* Finally, insert our new free descriptor into the list */
695 KiRosInsertNtDescriptor(NextDescriptor);
696 }
697
698 /* Insert the descriptor we allocated */
699 KiRosInsertNtDescriptor(Descriptor);
700 }
701
702 /* Return success */
703 return STATUS_SUCCESS;
704 }
705
706 PMEMORY_ALLOCATION_DESCRIPTOR
707 NTAPI
708 KiRosFindNtDescriptor(IN ULONG BasePage)
709 {
710 PMEMORY_ALLOCATION_DESCRIPTOR MdBlock = NULL;
711 PLIST_ENTRY NextEntry, ListHead;
712
713 /* Scan the memory descriptor list */
714 ListHead = &KeLoaderBlock->MemoryDescriptorListHead;
715 NextEntry = ListHead->Flink;
716 while (NextEntry != ListHead)
717 {
718 /* Get the current descriptor */
719 MdBlock = CONTAINING_RECORD(NextEntry,
720 MEMORY_ALLOCATION_DESCRIPTOR,
721 ListEntry);
722
723 /* Check if it can contain our memory range */
724 if ((MdBlock->BasePage <= BasePage) &&
725 (MdBlock->BasePage + MdBlock->PageCount > BasePage))
726 {
727 /* It can, break out */
728 break;
729 }
730
731 /* Go to the next descriptor */
732 NextEntry = NextEntry->Flink;
733 }
734
735 /* Return the descriptor we found, if any */
736 return MdBlock;
737 }
738
739 NTSTATUS
740 NTAPI
741 KiRosAllocateNtDescriptor(IN TYPE_OF_MEMORY MemoryType,
742 IN ULONG BasePage,
743 IN ULONG PageCount,
744 IN ULONG Alignment,
745 OUT PULONG ReturnedBase)
746 {
747 PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
748 ULONG AlignedBase, AlignedLimit;
749 PMEMORY_ALLOCATION_DESCRIPTOR ActiveMdBlock;
750 ULONG ActiveAlignedBase = 0;
751 PLIST_ENTRY NextEntry, ListHead;
752
753 /* If no information was given, make some assumptions */
754 if (!Alignment) Alignment = 1;
755 if (!PageCount) PageCount = 1;
756
757 /* Start looking for a matching descvriptor */
758 do
759 {
760 /* Calculate the limit of the range */
761 AlignedLimit = PageCount + BasePage;
762
763 /* Find a descriptor that already contains our base address */
764 MdBlock = KiRosFindNtDescriptor(BasePage);
765 if (MdBlock)
766 {
767 /* If it contains our limit as well, break out early */
768 if ((MdBlock->PageCount + MdBlock->BasePage) > AlignedLimit) break;
769 }
770
771 /* Loop the memory list */
772 ActiveMdBlock = NULL;
773 ListHead = &KeLoaderBlock->MemoryDescriptorListHead;
774 NextEntry = ListHead->Flink;
775 while (NextEntry != ListHead)
776 {
777 /* Get the current descriptors */
778 MdBlock = CONTAINING_RECORD(NextEntry,
779 MEMORY_ALLOCATION_DESCRIPTOR,
780 ListEntry);
781
782 /* Align the base address and our limit */
783 AlignedBase = (MdBlock->BasePage + (Alignment - 1)) &~ Alignment;
784 AlignedLimit = MdBlock->PageCount -
785 AlignedBase +
786 MdBlock->BasePage;
787
788 /* Check if this is a free block that can satisfy us */
789 if ((MdBlock->MemoryType == LoaderFree) &&
790 (AlignedLimit <= MdBlock->PageCount) &&
791 (PageCount <= AlignedLimit))
792 {
793 /* It is, stop searching */
794 ActiveMdBlock = MdBlock;
795 ActiveAlignedBase = AlignedBase;
796 break;
797 }
798
799 /* Try the next block */
800 NextEntry = NextEntry->Flink;
801 }
802
803 /* See if we came up with an adequate block */
804 if (ActiveMdBlock)
805 {
806 /* Generate a descriptor in it */
807 *ReturnedBase = AlignedBase;
808 return KiRosBuildNtDescriptor(ActiveMdBlock,
809 MemoryType,
810 ActiveAlignedBase,
811 PageCount);
812 }
813 } while (TRUE);
814
815 /* We found a matching block, generate a descriptor with it */
816 *ReturnedBase = BasePage;
817 return KiRosBuildNtDescriptor(MdBlock, MemoryType, BasePage, PageCount);
818 }
819
820 NTSTATUS
821 NTAPI
822 KiRosBuildArcMemoryList(VOID)
823 {
824 PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
825 MEMORY_DESCRIPTOR *Memory;
826 ULONG i;
827
828 /* Loop all BIOS Memory Descriptors */
829 for (i = 0; i < NumberDescriptors; i++)
830 {
831 /* Get the current descriptor */
832 Memory = &MDArray[i];
833
834 /* Allocate an NT Memory Descriptor */
835 Descriptor = KiRosGetMdFromArray();
836 if (!Descriptor) return ENOMEM;
837
838 /* Copy the memory type */
839 Descriptor->MemoryType = Memory->MemoryType;
840 if (Memory->MemoryType == MemoryFreeContiguous)
841 {
842 /* Convert this to free */
843 Descriptor->MemoryType = LoaderFree;
844 }
845 else if (Memory->MemoryType == MemorySpecialMemory)
846 {
847 /* Convert this to special memory */
848 Descriptor->MemoryType = LoaderSpecialMemory;
849 }
850
851 /* Copy the range data */
852 Descriptor->BasePage = Memory->BasePage;
853 Descriptor->PageCount = Memory->PageCount;
854
855 /* Insert the descriptor */
856 if (Descriptor->PageCount) KiRosInsertNtDescriptor(Descriptor);
857 }
858
859 /* All went well */
860 return STATUS_SUCCESS;
861 }
862
863 VOID
864 NTAPI
865 KiRosFrldrLpbToNtLpb(IN PROS_LOADER_PARAMETER_BLOCK RosLoaderBlock,
866 IN PLOADER_PARAMETER_BLOCK *NtLoaderBlock)
867 {
868 PLOADER_PARAMETER_BLOCK LoaderBlock;
869 PLDR_DATA_TABLE_ENTRY LdrEntry;
870 PLOADER_MODULE RosEntry;
871 ULONG i, j, ModSize;
872 PVOID ModStart;
873 PCHAR DriverName;
874 PCHAR BootPath, HalPath;
875 CHAR CommandLine[256];
876 PARC_DISK_SIGNATURE RosDiskInfo, ArcDiskInfo;
877 PIMAGE_NT_HEADERS NtHeader;
878 WCHAR PathToDrivers[] = L"\\SystemRoot\\System32\\drivers\\";
879 WCHAR PathToSystem32[] = L"\\SystemRoot\\System32\\";
880 CHAR DriverNameLow[256];
881 ULONG Base;
882
883 /* First get some kernel-loader globals */
884 AcpiTableDetected = (RosLoaderBlock->Flags & MB_FLAGS_ACPI_TABLE) ? TRUE : FALSE;
885 MmFreeLdrMemHigher = RosLoaderBlock->MemHigher;
886 MmFreeLdrPageDirectoryEnd = RosLoaderBlock->PageDirectoryEnd;
887 if (!MmFreeLdrPageDirectoryEnd) MmFreeLdrPageDirectoryEnd = 0x40000;
888
889 /* Set the NT Loader block and initialize it */
890 *NtLoaderBlock = KeLoaderBlock = LoaderBlock = &BldrLoaderBlock;
891 RtlZeroMemory(LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK));
892
893 /* Set the NLS Data block */
894 LoaderBlock->NlsData = &BldrNlsDataBlock;
895
896 /* Set the ARC Data block */
897 LoaderBlock->ArcDiskInformation = &BldrArcDiskInfo;
898
899 /* Assume this is from FreeLDR's SetupLdr */
900 LoaderBlock->SetupLdrBlock = &BldrSetupBlock;
901
902 /* Setup the list heads */
903 InitializeListHead(&LoaderBlock->LoadOrderListHead);
904 InitializeListHead(&LoaderBlock->MemoryDescriptorListHead);
905 InitializeListHead(&LoaderBlock->BootDriverListHead);
906 InitializeListHead(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead);
907
908 /* Build the free memory map, which uses BIOS Descriptors */
909 KiRosBuildBiosMemoryMap();
910
911 /* Build entries for ReactOS memory ranges, which uses ARC Descriptors */
912 KiRosBuildOsMemoryMap();
913
914 /* Build entries for the reserved map, which uses ARC Descriptors */
915 KiRosBuildReservedMemoryMap();
916
917 /* Now convert the BIOS and ARC Descriptors into NT Memory Descirptors */
918 KiRosBuildArcMemoryList();
919
920 /* Loop boot driver list */
921 for (i = 0; i < RosLoaderBlock->ModsCount; i++)
922 {
923 /* Get the ROS loader entry */
924 RosEntry = &RosLoaderBlock->ModsAddr[i];
925 DriverName = (PCHAR)RosEntry->String;
926 ModStart = (PVOID)RosEntry->ModStart;
927 ModSize = RosEntry->ModEnd - (ULONG_PTR)ModStart;
928
929 /* Check if this is any of the NLS files */
930 if (!_stricmp(DriverName, "ansi.nls"))
931 {
932 /* ANSI Code page */
933 ModStart = RVA(ModStart, KSEG0_BASE);
934 LoaderBlock->NlsData->AnsiCodePageData = ModStart;
935
936 /* Create an MD for it */
937 KiRosAllocateNtDescriptor(LoaderNlsData,
938 ((ULONG_PTR)ModStart &~ KSEG0_BASE) >>
939 PAGE_SHIFT,
940 (ModSize + PAGE_SIZE - 1)>> PAGE_SHIFT,
941 0,
942 &Base);
943 continue;
944 }
945 else if (!_stricmp(DriverName, "oem.nls"))
946 {
947 /* OEM Code page */
948 ModStart = RVA(ModStart, KSEG0_BASE);
949 LoaderBlock->NlsData->OemCodePageData = ModStart;
950
951 /* Create an MD for it */
952 KiRosAllocateNtDescriptor(LoaderNlsData,
953 ((ULONG_PTR)ModStart &~ KSEG0_BASE) >>
954 PAGE_SHIFT,
955 (ModSize + PAGE_SIZE - 1)>> PAGE_SHIFT,
956 0,
957 &Base);
958 continue;
959 }
960 else if (!_stricmp(DriverName, "casemap.nls"))
961 {
962 /* Unicode Code page */
963 ModStart = RVA(ModStart, KSEG0_BASE);
964 LoaderBlock->NlsData->UnicodeCodePageData = ModStart;
965
966 /* Create an MD for it */
967 KiRosAllocateNtDescriptor(LoaderNlsData,
968 ((ULONG_PTR)ModStart &~ KSEG0_BASE) >>
969 PAGE_SHIFT,
970 (ModSize + PAGE_SIZE - 1)>> PAGE_SHIFT,
971 0,
972 &Base);
973 continue;
974 }
975
976 /* Check if this is the SYSTEM hive */
977 if (!(_stricmp(DriverName, "system")) ||
978 !(_stricmp(DriverName, "system.hiv")))
979 {
980 /* Save registry data */
981 ModStart = RVA(ModStart, KSEG0_BASE);
982 LoaderBlock->RegistryBase = ModStart;
983 LoaderBlock->RegistryLength = ModSize;
984
985 /* Disable setup mode */
986 LoaderBlock->SetupLdrBlock = NULL;
987
988 /* Create an MD for it */
989 KiRosAllocateNtDescriptor(LoaderRegistryData,
990 ((ULONG_PTR)ModStart &~ KSEG0_BASE) >>
991 PAGE_SHIFT,
992 (ModSize + PAGE_SIZE - 1)>> PAGE_SHIFT,
993 0,
994 &Base);
995 continue;
996 }
997
998 /* Check if this is the HARDWARE hive */
999 if (!(_stricmp(DriverName, "hardware")) ||
1000 !(_stricmp(DriverName, "hardware.hiv")))
1001 {
1002 /* Create an MD for it */
1003 KiRosAllocateNtDescriptor(LoaderRegistryData,
1004 (ULONG_PTR)ModStart >> PAGE_SHIFT,
1005 (ModSize + PAGE_SIZE - 1)>> PAGE_SHIFT,
1006 0,
1007 &Base);
1008 continue;
1009 }
1010
1011 /* Check if this is the kernel */
1012 if (!(_stricmp(DriverName, "ntoskrnl.exe")))
1013 {
1014 /* Create an MD for it */
1015 KiRosAllocateNtDescriptor(LoaderSystemCode,
1016 ((ULONG_PTR)ModStart &~ KSEG0_BASE) >>
1017 PAGE_SHIFT,
1018 (ModSize + PAGE_SIZE - 1)>> PAGE_SHIFT,
1019 0,
1020 &Base);
1021 }
1022 else if (!(_stricmp(DriverName, "hal.dll")))
1023 {
1024 /* Create an MD for the HAL */
1025 KiRosAllocateNtDescriptor(LoaderHalCode,
1026 ((ULONG_PTR)ModStart &~ KSEG0_BASE) >>
1027 PAGE_SHIFT,
1028 (ModSize + PAGE_SIZE - 1)>> PAGE_SHIFT,
1029 0,
1030 &Base);
1031 }
1032 else
1033 {
1034 /* Create an MD for any driver */
1035 KiRosAllocateNtDescriptor(LoaderBootDriver,
1036 ((ULONG_PTR)ModStart &~ KSEG0_BASE) >>
1037 PAGE_SHIFT,
1038 (ModSize + PAGE_SIZE - 1)>> PAGE_SHIFT,
1039 0,
1040 &Base);
1041 }
1042
1043 /* Lowercase the drivername so we can check its extension later */
1044 strcpy(DriverNameLow, DriverName);
1045 _strlwr(DriverNameLow);
1046
1047 /* Setup the loader entry */
1048 LdrEntry = &BldrModules[i];
1049 RtlZeroMemory(LdrEntry, sizeof(LDR_DATA_TABLE_ENTRY));
1050
1051 /* Convert driver name from ANSI to Unicode */
1052 for (j = 0; j < strlen(DriverName); j++)
1053 {
1054 BldrModuleStrings[i][j] = DriverName[j];
1055 }
1056
1057 /* Setup driver name */
1058 RtlInitUnicodeString(&LdrEntry->BaseDllName, BldrModuleStrings[i]);
1059
1060 /* Construct a correct full name */
1061 BldrModuleStringsFull[i][0] = 0;
1062 LdrEntry->FullDllName.MaximumLength = 260 * sizeof(WCHAR);
1063 LdrEntry->FullDllName.Length = 0;
1064 LdrEntry->FullDllName.Buffer = BldrModuleStringsFull[i];
1065
1066 /* Guess the path */
1067 if (strstr(DriverNameLow, ".dll") || strstr(DriverNameLow, ".exe"))
1068 {
1069 UNICODE_STRING TempString;
1070 RtlInitUnicodeString(&TempString, PathToSystem32);
1071 RtlAppendUnicodeStringToString(&LdrEntry->FullDllName, &TempString);
1072 }
1073 else /* .sys */
1074 {
1075 UNICODE_STRING TempString;
1076 RtlInitUnicodeString(&TempString, PathToDrivers);
1077 RtlAppendUnicodeStringToString(&LdrEntry->FullDllName, &TempString);
1078 }
1079
1080 /* Append base name of the driver */
1081 RtlAppendUnicodeStringToString(&LdrEntry->FullDllName, &LdrEntry->BaseDllName);
1082
1083 /* Copy data from Freeldr Module Entry */
1084 LdrEntry->DllBase = ModStart;
1085 LdrEntry->SizeOfImage = ModSize;
1086
1087 /* Copy additional data */
1088 NtHeader = RtlImageNtHeader(ModStart);
1089 LdrEntry->EntryPoint = RVA(ModStart,
1090 NtHeader->
1091 OptionalHeader.AddressOfEntryPoint);
1092
1093 /* Initialize other data */
1094 LdrEntry->LoadCount = 1;
1095 LdrEntry->Flags = LDRP_IMAGE_DLL |
1096 LDRP_ENTRY_PROCESSED;
1097 if (RosEntry->Reserved) LdrEntry->Flags |= LDRP_ENTRY_INSERTED;
1098
1099 /* Insert it into the loader block */
1100 InsertTailList(&LoaderBlock->LoadOrderListHead,
1101 &LdrEntry->InLoadOrderLinks);
1102 }
1103
1104 /* Setup command line */
1105 LoaderBlock->LoadOptions = BldrCommandLine;
1106 strcpy(BldrCommandLine, RosLoaderBlock->CommandLine);
1107
1108 /* Setup the extension block */
1109 LoaderBlock->Extension = &BldrExtensionBlock;
1110 LoaderBlock->Extension->Size = sizeof(LOADER_PARAMETER_EXTENSION);
1111 LoaderBlock->Extension->MajorVersion = 5;
1112 LoaderBlock->Extension->MinorVersion = 2;
1113
1114 /* FreeLDR hackllocates 1536 static pages for the initial boot images */
1115 LoaderBlock->Extension->LoaderPagesSpanned = 1536 * PAGE_SIZE;
1116
1117 /* ReactOS always boots the kernel at 0x80800000 (just like NT 5.2) */
1118 LoaderBlock->Extension->LoaderPagesSpanned += 0x80800000 - KSEG0_BASE;
1119
1120 /* Now convert to pages */
1121 LoaderBlock->Extension->LoaderPagesSpanned /= PAGE_SIZE;
1122
1123 /* Now setup the setup block if we have one */
1124 if (LoaderBlock->SetupLdrBlock)
1125 {
1126 /* All we'll setup right now is the flag for text-mode setup */
1127 LoaderBlock->SetupLdrBlock->Flags = 1;
1128 }
1129
1130 /* Make a copy of the command line */
1131 strcpy(CommandLine, LoaderBlock->LoadOptions);
1132
1133 /* Find the first \, separating the ARC path from NT path */
1134 BootPath = strchr(CommandLine, '\\');
1135 *BootPath = ANSI_NULL;
1136 strncpy(BldrArcBootPath, CommandLine, 63);
1137 LoaderBlock->ArcBootDeviceName = BldrArcBootPath;
1138
1139 /* The rest of the string is the NT path */
1140 HalPath = strchr(BootPath + 1, ' ');
1141 *HalPath = ANSI_NULL;
1142 BldrNtBootPath[0] = '\\';
1143 strncat(BldrNtBootPath, BootPath + 1, 63);
1144 strcat(BldrNtBootPath,"\\");
1145 LoaderBlock->NtBootPathName = BldrNtBootPath;
1146
1147 /* Set the HAL paths */
1148 strncpy(BldrArcHalPath, BldrArcBootPath, 63);
1149 LoaderBlock->ArcHalDeviceName = BldrArcHalPath;
1150 strcpy(BldrNtHalPath, "\\");
1151 LoaderBlock->NtHalPathName = BldrNtHalPath;
1152
1153 /* Use this new command line */
1154 strncpy(LoaderBlock->LoadOptions, HalPath + 2, 255);
1155
1156 /* Parse it and change every slash to a space */
1157 BootPath = LoaderBlock->LoadOptions;
1158 do {if (*BootPath == '/') *BootPath = ' ';} while (*BootPath++);
1159
1160 /* Now let's loop ARC disk information */
1161 for (i = 0; i < RosLoaderBlock->DrivesCount; i++)
1162 {
1163 /* Get the ROS loader entry */
1164 RosDiskInfo = &RosLoaderBlock->DrivesAddr[i];
1165
1166 /* Get the ARC structure */
1167 ArcDiskInfo = &BldrDiskInfo[i];
1168
1169 /* Copy the data over */
1170 ArcDiskInfo->Signature = RosDiskInfo->Signature;
1171 ArcDiskInfo->CheckSum = RosDiskInfo->CheckSum;
1172
1173 /* Copy the ARC Name */
1174 strcpy(BldrArcNames[i], RosDiskInfo->ArcName);
1175 ArcDiskInfo->ArcName = BldrArcNames[i];
1176
1177 /* Insert into the list */
1178 InsertTailList(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead,
1179 &ArcDiskInfo->ListEntry);
1180 }
1181 }
1182
1183 VOID
1184 FASTCALL
1185 KiRosPrepareForSystemStartup(IN ULONG Dummy,
1186 IN PROS_LOADER_PARAMETER_BLOCK LoaderBlock)
1187 {
1188 PLOADER_PARAMETER_BLOCK NtLoaderBlock;
1189 ULONG size, i;
1190 #if defined(_M_IX86)
1191 PKTSS Tss;
1192 PKGDTENTRY TssEntry;
1193
1194 /* Load the GDT and IDT */
1195 Ke386SetGlobalDescriptorTable(*(PKDESCRIPTOR)&KiGdtDescriptor.Limit);
1196 Ke386SetInterruptDescriptorTable(*(PKDESCRIPTOR)&KiIdtDescriptor.Limit);
1197
1198 /* Initialize the boot TSS */
1199 Tss = &KiBootTss;
1200 TssEntry = &KiBootGdt[KGDT_TSS / sizeof(KGDTENTRY)];
1201 TssEntry->HighWord.Bits.Type = I386_TSS;
1202 TssEntry->HighWord.Bits.Pres = 1;
1203 TssEntry->HighWord.Bits.Dpl = 0;
1204 TssEntry->BaseLow = (USHORT)((ULONG_PTR)Tss & 0xFFFF);
1205 TssEntry->HighWord.Bytes.BaseMid = (UCHAR)((ULONG_PTR)Tss >> 16);
1206 TssEntry->HighWord.Bytes.BaseHi = (UCHAR)((ULONG_PTR)Tss >> 24);
1207 #endif
1208
1209 /* Save pointer to ROS Block */
1210 KeRosLoaderBlock = LoaderBlock;
1211 MmFreeLdrLastKernelAddress = PAGE_ROUND_UP(KeRosLoaderBlock->
1212 ModsAddr[KeRosLoaderBlock->
1213 ModsCount - 1].
1214 ModEnd);
1215 MmFreeLdrFirstKrnlPhysAddr = KeRosLoaderBlock->ModsAddr[0].ModStart -
1216 KSEG0_BASE;
1217 MmFreeLdrLastKrnlPhysAddr = MmFreeLdrLastKernelAddress - KSEG0_BASE;
1218
1219 /* Save memory manager data */
1220 KeMemoryMapRangeCount = 0;
1221 if (LoaderBlock->Flags & MB_FLAGS_MMAP_INFO)
1222 {
1223 /* We have a memory map from the nice BIOS */
1224 size = *((PULONG)(LoaderBlock->MmapAddr - sizeof(ULONG)));
1225 i = 0;
1226
1227 /* Map it until we run out of size */
1228 while (i < LoaderBlock->MmapLength)
1229 {
1230 /* Copy into the Kernel Memory Map */
1231 memcpy (&KeMemoryMap[KeMemoryMapRangeCount],
1232 (PVOID)(LoaderBlock->MmapAddr + i),
1233 sizeof(ADDRESS_RANGE));
1234
1235 /* Increase Memory Map Count */
1236 KeMemoryMapRangeCount++;
1237
1238 /* Increase Size */
1239 i += size;
1240 }
1241
1242 /* Save data */
1243 LoaderBlock->MmapLength = KeMemoryMapRangeCount * sizeof(ADDRESS_RANGE);
1244 LoaderBlock->MmapAddr = (ULONG)KeMemoryMap;
1245 }
1246 else
1247 {
1248 /* Nothing from BIOS */
1249 LoaderBlock->MmapLength = 0;
1250 LoaderBlock->MmapAddr = (ULONG)KeMemoryMap;
1251 }
1252
1253 #if defined(_M_IX86)
1254 /* Set up the VDM Data */
1255 NtEarlyInitVdm();
1256 #endif
1257
1258 /* Convert the loader block */
1259 KiRosFrldrLpbToNtLpb(KeRosLoaderBlock, &NtLoaderBlock);
1260
1261 /* Do general System Startup */
1262 KiSystemStartup(NtLoaderBlock);
1263 }
1264
1265 /* EOF */