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)
9 /* INCLUDES *****************************************************************/
16 #include <ppcmmu/mmu.h>
17 #define KERNEL_RVA(x) RVA(x,0x80800000)
18 #define KERNEL_DESCRIPTOR_PAGE(x) (((ULONG_PTR)(x) + KernelBase) >> PAGE_SHIFT)
20 #define KERNEL_RVA(x) RVA(x,KSEG0_BASE)
21 #define KERNEL_DESCRIPTOR_PAGE(x) (((ULONG_PTR)(x) & ~KSEG0_BASE) >> PAGE_SHIFT)
24 typedef struct _BIOS_MEMORY_DESCRIPTOR
28 } BIOS_MEMORY_DESCRIPTOR
, *PBIOS_MEMORY_DESCRIPTOR
;
30 /* GLOBALS *******************************************************************/
32 /* Function pointer for early debug prints */
33 ULONG (*FrLdrDbgPrint
)(const char *Format
, ...);
35 /* FreeLDR Loader Data */
36 PROS_LOADER_PARAMETER_BLOCK KeRosLoaderBlock
;
37 BOOLEAN AcpiTableDetected
= FALSE
;
38 ADDRESS_RANGE KeMemoryMap
[64];
39 ULONG KeMemoryMapRangeCount
;
41 /* NT Loader Module/Descriptor Count */
45 /* NT Loader Data. Eats up about 100KB! */
46 LOADER_PARAMETER_BLOCK BldrLoaderBlock
; // 0x0000
47 LOADER_PARAMETER_EXTENSION BldrExtensionBlock
; // 0x0060
48 CHAR BldrCommandLine
[256]; // 0x00DC
49 CHAR BldrArcBootPath
[64]; // 0x01DC
50 CHAR BldrArcHalPath
[64]; // 0x021C
51 CHAR BldrNtHalPath
[64]; // 0x025C
52 CHAR BldrNtBootPath
[64]; // 0x029C
53 LDR_DATA_TABLE_ENTRY BldrModules
[64]; // 0x02DC
54 MEMORY_ALLOCATION_DESCRIPTOR BldrMemoryDescriptors
[60]; // 0x14DC
55 WCHAR BldrModuleStrings
[64][260]; // 0x19DC
56 WCHAR BldrModuleStringsFull
[64][260]; // 0x9BDC
57 NLS_DATA_BLOCK BldrNlsDataBlock
; // 0x11DDC
58 SETUP_LOADER_BLOCK BldrSetupBlock
; // 0x11DE8
59 ARC_DISK_INFORMATION BldrArcDiskInfo
; // 0x12134
60 CHAR BldrArcNames
[32][256]; // 0x1213C
61 ARC_DISK_SIGNATURE BldrDiskInfo
[32]; // 0x1413C
62 CHAR BldrArcHwBuffer
[16 * 1024]; // 0x1843C
65 BIOS_MEMORY_DESCRIPTOR BiosMemoryDescriptors
[16] = { { 0, 0 }, };
66 PBIOS_MEMORY_DESCRIPTOR BiosMemoryDescriptorList
= BiosMemoryDescriptors
;
69 ULONG NumberDescriptors
= 0;
70 MEMORY_DESCRIPTOR MDArray
[60] = { { 0, 0, 0 }, };
72 /* Old boot style IDT */
73 KIDTENTRY KiHackIdt
[256];
75 /* FUNCTIONS *****************************************************************/
77 PMEMORY_ALLOCATION_DESCRIPTOR
79 KiRosGetMdFromArray(VOID
)
81 /* Return the next MD from the list, but make sure we don't overflow */
82 if (BldrCurrentMd
> 60) ASSERT(FALSE
);
83 return &BldrMemoryDescriptors
[BldrCurrentMd
++];
88 KiRosAddBiosBlock(ULONG Address
,
91 PBIOS_MEMORY_DESCRIPTOR BiosBlock
= BiosMemoryDescriptorList
;
93 /* Loop our BIOS Memory Descriptor List */
94 while (BiosBlock
->BlockSize
> 0)
96 /* Check if we've found a matching head block */
97 if (Address
+ Size
== BiosBlock
->BlockBase
)
99 /* Simply enlarge and rebase it */
100 BiosBlock
->BlockBase
= Address
;
101 BiosBlock
->BlockSize
+= Size
;
105 /* Check if we've found a matching tail block */
106 if (Address
== (BiosBlock
->BlockBase
+ BiosBlock
->BlockSize
))
108 /* Simply enlarge it */
109 BiosBlock
->BlockSize
+= Size
;
113 /* Nothing suitable found, try the next block */
117 /* No usable blocks found, found a free block instead */
118 if (!BiosBlock
->BlockSize
)
121 BiosBlock
->BlockBase
= Address
;
122 BiosBlock
->BlockSize
= Size
;
124 /* Create a new block and mark it as the end of the array */
126 BiosBlock
->BlockBase
= BiosBlock
->BlockSize
= 0L;
132 KiRosBuildBiosMemoryMap(VOID
)
134 ULONG BlockBegin
, BlockEnd
;
137 /* Loop the BIOS Memory Map */
138 for (j
= 0; j
< KeMemoryMapRangeCount
; j
++)
140 /* Get the start and end addresses */
141 BlockBegin
= KeMemoryMap
[j
].BaseAddrLow
;
142 BlockEnd
= KeMemoryMap
[j
].BaseAddrLow
+ KeMemoryMap
[j
].LengthLow
- 1;
144 /* Make sure this isn't a > 4GB descriptor */
145 if (!KeMemoryMap
[j
].BaseAddrHigh
)
147 /* Make sure we don't overflow */
148 if (BlockEnd
< BlockBegin
) BlockEnd
= 0xFFFFFFFF;
150 /* Check if this is free memory */
151 if (KeMemoryMap
[j
].Type
== 1)
153 /* Add it to our BIOS descriptors */
154 KiRosAddBiosBlock(BlockBegin
, BlockEnd
- BlockBegin
+ 1);
162 KiRosAllocateArcDescriptor(IN ULONG PageBegin
,
164 IN MEMORY_TYPE MemoryType
)
168 /* Loop all our descriptors */
169 for (i
= 0; i
< NumberDescriptors
; i
++)
171 /* Attempt to fing a free block that describes our region */
172 if ((MDArray
[i
].MemoryType
== MemoryFree
) &&
173 (MDArray
[i
].BasePage
<= PageBegin
) &&
174 (MDArray
[i
].BasePage
+ MDArray
[i
].PageCount
> PageBegin
) &&
175 (MDArray
[i
].BasePage
+ MDArray
[i
].PageCount
>= PageEnd
))
182 /* Check if we found no free blocks, and fail if so */
183 if (i
== NumberDescriptors
) return ENOMEM
;
185 /* Check if the block has our base address */
186 if (MDArray
[i
].BasePage
== PageBegin
)
188 /* Check if it also has our ending address */
189 if ((MDArray
[i
].BasePage
+ MDArray
[i
].PageCount
) == PageEnd
)
191 /* Then convert this region into our new memory type */
192 MDArray
[i
].MemoryType
= MemoryType
;
196 /* Otherwise, make sure we have enough descriptors */
197 if (NumberDescriptors
== 60) return ENOMEM
;
199 /* Cut this descriptor short */
200 MDArray
[i
].BasePage
= PageEnd
;
201 MDArray
[i
].PageCount
-= (PageEnd
- PageBegin
);
203 /* And allocate a new descriptor for our memory range */
204 MDArray
[NumberDescriptors
].BasePage
= PageBegin
;
205 MDArray
[NumberDescriptors
].PageCount
= PageEnd
- PageBegin
;
206 MDArray
[NumberDescriptors
].MemoryType
= MemoryType
;
210 else if ((MDArray
[i
].BasePage
+ MDArray
[i
].PageCount
) == PageEnd
)
212 /* This block has our end address, make sure we have a free block */
213 if (NumberDescriptors
== 60) return ENOMEM
;
215 /* Rebase this descriptor */
216 MDArray
[i
].PageCount
= PageBegin
- MDArray
[i
].BasePage
;
218 /* And allocate a new descriptor for our memory range */
219 MDArray
[NumberDescriptors
].BasePage
= PageBegin
;
220 MDArray
[NumberDescriptors
].PageCount
= PageEnd
- PageBegin
;
221 MDArray
[NumberDescriptors
].MemoryType
= MemoryType
;
226 /* We'll need two descriptors, make sure they're available */
227 if ((NumberDescriptors
+ 1) >= 60) return ENOMEM
;
229 /* Allocate a free memory descriptor for what follows us */
230 MDArray
[NumberDescriptors
].BasePage
= PageEnd
;
231 MDArray
[NumberDescriptors
].PageCount
= MDArray
[i
].PageCount
-
232 (PageEnd
- MDArray
[i
].BasePage
);
233 MDArray
[NumberDescriptors
].MemoryType
= MemoryFree
;
236 /* Cut down the current free descriptor */
237 MDArray
[i
].PageCount
= PageBegin
- MDArray
[i
].BasePage
;
239 /* Allocate a new memory descriptor for our memory range */
240 MDArray
[NumberDescriptors
].BasePage
= PageBegin
;
241 MDArray
[NumberDescriptors
].PageCount
= PageEnd
- PageBegin
;
242 MDArray
[NumberDescriptors
].MemoryType
= MemoryType
;
246 /* Everything went well */
247 return STATUS_SUCCESS
;
252 KiRosConfigureArcDescriptor(IN ULONG PageBegin
,
254 IN TYPE_OF_MEMORY MemoryType
)
257 ULONG BlockBegin
, BlockEnd
;
258 MEMORY_TYPE BlockType
;
259 BOOLEAN Combined
= FALSE
;
261 /* If this descriptor seems bogus, just return */
262 if (PageEnd
<= PageBegin
) return STATUS_SUCCESS
;
264 /* Loop every ARC descriptor, trying to find one we can modify */
265 for (i
= 0; i
< NumberDescriptors
; i
++)
267 /* Get its settings */
268 BlockBegin
= MDArray
[i
].BasePage
;
269 BlockEnd
= MDArray
[i
].BasePage
+ MDArray
[i
].PageCount
;
270 BlockType
= MDArray
[i
].MemoryType
;
272 /* Check if we can fit inside this block */
273 if (BlockBegin
< PageBegin
)
275 /* Check if we are larger then it */
276 if ((BlockEnd
> PageBegin
) && (BlockEnd
<= PageEnd
))
278 /* Make it end where we start */
279 BlockEnd
= PageBegin
;
282 /* Check if it ends after we do */
283 if (BlockEnd
> PageEnd
)
285 /* Make sure we can allocate a descriptor */
286 if (NumberDescriptors
== 60) return ENOMEM
;
288 /* Create a descriptor for whatever memory we're not part of */
289 MDArray
[NumberDescriptors
].MemoryType
= BlockType
;
290 MDArray
[NumberDescriptors
].BasePage
= PageEnd
;
291 MDArray
[NumberDescriptors
].PageCount
= BlockEnd
- PageEnd
;
294 /* The next block ending is now where we begin */
295 BlockEnd
= PageBegin
;
300 /* Check if the blog begins inside our range */
301 if (BlockBegin
< PageEnd
)
303 /* Check if it ends before we do */
304 if (BlockEnd
< PageEnd
)
306 /* Then make it disappear */
307 BlockEnd
= BlockBegin
;
311 /* Otherwise make it start where we end */
312 BlockBegin
= PageEnd
;
317 /* Check if the block matches us, and we haven't tried combining yet */
318 if (((TYPE_OF_MEMORY
)BlockType
== MemoryType
) && !(Combined
))
320 /* Check if it starts where we end */
321 if (BlockBegin
== PageEnd
)
323 /* Make it start with us, and combine us */
324 BlockBegin
= PageBegin
;
327 else if (BlockEnd
== PageBegin
)
329 /* Otherwise, it ends where we begin, combine its ending */
335 /* Check the original block data matches with what we came up with */
336 if ((MDArray
[i
].BasePage
== BlockBegin
) &&
337 (MDArray
[i
].PageCount
== BlockEnd
- BlockBegin
))
343 /* Otherwise, set our new settings for this block */
344 MDArray
[i
].BasePage
= BlockBegin
;
345 MDArray
[i
].PageCount
= BlockEnd
- BlockBegin
;
347 /* Check if we are killing the block */
348 if (BlockBegin
== BlockEnd
)
350 /* Delete this block and restart the loop properly */
352 if (i
< NumberDescriptors
) MDArray
[i
] = MDArray
[NumberDescriptors
];
357 /* If we got here without combining, we need to allocate a new block */
358 if (!(Combined
) && (MemoryType
< LoaderMaximum
))
360 /* Make sure there's enough descriptors */
361 if (NumberDescriptors
== 60) return ENOMEM
;
363 /* Allocate a new block with our data */
364 MDArray
[NumberDescriptors
].MemoryType
= MemoryType
;
365 MDArray
[NumberDescriptors
].BasePage
= PageBegin
;
366 MDArray
[NumberDescriptors
].PageCount
= PageEnd
- PageBegin
;
370 /* Changes complete, return success */
371 return STATUS_SUCCESS
;
376 KiRosBuildOsMemoryMap(VOID
)
378 PBIOS_MEMORY_DESCRIPTOR MdBlock
;
379 ULONG BlockStart
, BlockEnd
, BiasedStart
, BiasedEnd
, PageStart
, PageEnd
;
380 NTSTATUS Status
= STATUS_SUCCESS
;
381 ULONG BiosPage
= 0xA0;
383 /* Loop the BIOS Memory Descriptor List */
384 MdBlock
= BiosMemoryDescriptorList
;
385 while (MdBlock
->BlockSize
)
387 /* Get the statrt and end addresses */
388 BlockStart
= MdBlock
->BlockBase
;
389 BlockEnd
= BlockStart
+ MdBlock
->BlockSize
- 1;
391 /* Align them to page boundaries */
392 BiasedStart
= BlockStart
& (PAGE_SIZE
- 1);
393 if (BiasedStart
) BlockStart
= BlockStart
+ PAGE_SIZE
- BiasedStart
;
394 BiasedEnd
= (BlockEnd
+ 1) & (ULONG
)(PAGE_SIZE
- 1);
395 if (BiasedEnd
) BlockEnd
-= BiasedEnd
;
397 /* Get the actual page numbers */
398 PageStart
= BlockStart
>> PAGE_SHIFT
;
399 PageEnd
= (BlockEnd
+ 1) >> PAGE_SHIFT
;
401 /* If we're starting at page 0, then put the BIOS page at the end */
402 if (!PageStart
) BiosPage
= PageEnd
;
404 /* Check if we did any alignment */
407 /* Mark that region as reserved */
408 Status
= KiRosConfigureArcDescriptor(PageStart
- 1,
410 MemorySpecialMemory
);
411 if (Status
!= STATUS_SUCCESS
) break;
414 /* Check if we did any alignment */
417 /* Mark that region as reserved */
418 Status
= KiRosConfigureArcDescriptor(PageEnd
- 1,
420 MemorySpecialMemory
);
421 if (Status
!= STATUS_SUCCESS
) break;
423 /* If the bios page was the last page, use the next one instead */
424 if (BiosPage
== PageEnd
) BiosPage
+= 1;
427 /* Check if the page is below the 16MB Memory hole */
428 if (PageEnd
<= 0xFC0)
430 /* It is, mark the memory a free */
431 Status
= KiRosConfigureArcDescriptor(PageStart
,
435 else if (PageStart
>= 0x1000)
437 /* It's over 16MB, so that memory gets marked as reserve */
438 Status
= KiRosConfigureArcDescriptor(PageStart
,
444 /* Check if it starts below the memory hole */
445 if (PageStart
< 0xFC0)
447 /* Mark that part as free */
448 Status
= KiRosConfigureArcDescriptor(PageStart
,
451 if (Status
!= STATUS_SUCCESS
) break;
453 /* And update the page start for the code below */
457 /* Any code in the memory hole region ends up as reserve */
458 Status
= KiRosConfigureArcDescriptor(PageStart
,
463 /* If we failed, break out, otherwise, go to the next BIOS block */
464 if (Status
!= STATUS_SUCCESS
) break;
468 /* If anything failed until now, return error code */
469 if (Status
!= STATUS_SUCCESS
) return Status
;
472 /* Set the top 16MB region as reserved */
473 Status
= KiRosConfigureArcDescriptor(0xFC0, 0x1000, MemorySpecialMemory
);
474 if (Status
!= STATUS_SUCCESS
) return Status
;
476 /* Setup the BIOS region as reserved */
477 KiRosConfigureArcDescriptor(0xA0, 0x100, LoaderMaximum
);
478 KiRosConfigureArcDescriptor(BiosPage
, 0x100, MemoryFirmwarePermanent
);
480 /* Build an entry for the IVT */
481 Status
= KiRosAllocateArcDescriptor(0, 1, MemoryFirmwarePermanent
);
482 if (Status
!= STATUS_SUCCESS
) return Status
;
485 /* Build an entry for the KPCR and KUSER_SHARED_DATA */
486 Status
= KiRosAllocateArcDescriptor(1, 3, LoaderStartupPcrPage
);
487 if (Status
!= STATUS_SUCCESS
) return Status
;
489 /* Build an entry for the PDE and return the status */
490 Status
= KiRosAllocateArcDescriptor(KeRosLoaderBlock
->
491 PageDirectoryStart
>> PAGE_SHIFT
,
493 PageDirectoryEnd
>> PAGE_SHIFT
,
500 KiRosBuildReservedMemoryMap(VOID
)
503 ULONG BlockBegin
, BlockEnd
, BiasedPage
;
505 /* Loop the BIOS Memory Map */
506 for (j
= 0; j
< KeMemoryMapRangeCount
; j
++)
508 /* Get the start and end addresses */
509 BlockBegin
= KeMemoryMap
[j
].BaseAddrLow
;
510 BlockEnd
= BlockBegin
+ KeMemoryMap
[j
].LengthLow
- 1;
512 /* Make sure it wasn't a > 4GB descriptor */
513 if (!KeMemoryMap
[j
].BaseAddrHigh
)
515 /* Make sure it doesn't overflow */
516 if (BlockEnd
< BlockBegin
) BlockEnd
= 0xFFFFFFFF;
518 /* Check if this was free memory */
519 if (KeMemoryMap
[j
].Type
== 1)
521 /* Get the page-aligned addresses */
522 BiasedPage
= BlockBegin
& (PAGE_SIZE
- 1);
523 BlockBegin
>>= PAGE_SHIFT
;
524 if (BiasedPage
) BlockBegin
++;
525 BlockEnd
= (BlockEnd
>> PAGE_SHIFT
) + 1;
527 /* Check if the block is within the 16MB memory hole */
528 if ((BlockBegin
< 0xFC0) && (BlockEnd
>= 0xFC0))
530 /* Don't allow it to cross this boundary */
534 /* Check if the boundary is across 16MB */
535 if ((BlockEnd
> 0xFFF) && (BlockBegin
<= 0xFFF))
537 /* Don't let it cross */
541 /* Check if the block describes the memory hole */
542 if ((BlockBegin
>= 0xFC0) && (BlockEnd
<= 0xFFF))
544 /* Set this region as temporary */
545 KiRosConfigureArcDescriptor(BlockBegin
,
547 MemoryFirmwareTemporary
);
552 /* Get the page-aligned addresses */
553 BlockBegin
>>= PAGE_SHIFT
;
554 BiasedPage
= (BlockEnd
+ 1) & (PAGE_SIZE
- 1);
555 BlockEnd
>>= PAGE_SHIFT
;
556 if (BiasedPage
) BlockEnd
++;
558 /* Set this memory as reserved */
559 KiRosConfigureArcDescriptor(BlockBegin
,
561 MemorySpecialMemory
);
569 KiRosInsertNtDescriptor(IN PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor
)
571 PLIST_ENTRY ListHead
, PreviousEntry
, NextEntry
;
572 PMEMORY_ALLOCATION_DESCRIPTOR Descriptor
= NULL
, NextDescriptor
= NULL
;
574 /* Loop the memory descriptor list */
575 ListHead
= &KeLoaderBlock
->MemoryDescriptorListHead
;
576 PreviousEntry
= ListHead
;
577 NextEntry
= ListHead
->Flink
;
578 while (NextEntry
!= ListHead
)
580 /* Get the current descriptor and check if it's below ours */
581 NextDescriptor
= CONTAINING_RECORD(NextEntry
,
582 MEMORY_ALLOCATION_DESCRIPTOR
,
584 if (NewDescriptor
->BasePage
< NextDescriptor
->BasePage
) break;
586 /* It isn't, save the previous entry and descriptor, and try again */
587 PreviousEntry
= NextEntry
;
588 Descriptor
= NextDescriptor
;
589 NextEntry
= NextEntry
->Flink
;
592 /* So we found the right spot to insert. Is this free memory? */
593 if (NewDescriptor
->MemoryType
!= LoaderFree
)
595 /* It isn't, so insert us before the last descriptor */
596 InsertHeadList(PreviousEntry
, &NewDescriptor
->ListEntry
);
600 /* We're free memory. Check if the entry we found is also free memory */
601 if ((PreviousEntry
!= ListHead
) &&
602 ((Descriptor
->MemoryType
== LoaderFree
) ||
603 (Descriptor
->MemoryType
== LoaderReserve
)) &&
604 ((Descriptor
->BasePage
+ Descriptor
->PageCount
) ==
605 NewDescriptor
->BasePage
))
607 /* It's free memory, and we're right after it. Enlarge that block */
608 Descriptor
->PageCount
+= NewDescriptor
->PageCount
;
609 NewDescriptor
= Descriptor
;
613 /* Our range scan't be combined, so just insert us separately */
614 InsertHeadList(PreviousEntry
, &NewDescriptor
->ListEntry
);
617 /* Check if we merged with an existing free memory block */
618 if ((NextEntry
!= ListHead
) &&
619 ((NextDescriptor
->MemoryType
== LoaderFree
) ||
620 (NextDescriptor
->MemoryType
== LoaderReserve
)) &&
621 ((NewDescriptor
->BasePage
+ NewDescriptor
->PageCount
) ==
622 NextDescriptor
->BasePage
))
624 /* Update our own block */
625 NewDescriptor
->PageCount
+= NextDescriptor
->PageCount
;
627 /* Remove the next block */
628 RemoveEntryList(&NextDescriptor
->ListEntry
);
635 KiRosBuildNtDescriptor(IN PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor
,
636 IN MEMORY_TYPE MemoryType
,
640 PMEMORY_ALLOCATION_DESCRIPTOR Descriptor
, NextDescriptor
= NULL
;
642 TYPE_OF_MEMORY CurrentType
;
645 /* Check how many pages we'll be consuming */
646 Delta
= BasePage
- MemoryDescriptor
->BasePage
;
647 if (!(Delta
) && (PageCount
== MemoryDescriptor
->PageCount
))
649 /* We can simply convert the current descriptor into our new type */
650 MemoryDescriptor
->MemoryType
= MemoryType
;
654 /* Get the current memory type of the descriptor, and reserve it */
655 CurrentType
= MemoryDescriptor
->MemoryType
;
656 MemoryDescriptor
->MemoryType
= LoaderSpecialMemory
;
658 /* Check if we'll need another descriptor for what's left of memory */
659 UseNext
= ((BasePage
!= MemoryDescriptor
->BasePage
) &&
660 (Delta
+ PageCount
!= MemoryDescriptor
->PageCount
));
662 /* Get a descriptor */
663 Descriptor
= KiRosGetMdFromArray();
664 if (!Descriptor
) return STATUS_INSUFFICIENT_RESOURCES
;
666 /* Check if we are using another descriptor */
669 /* Allocate that one too */
670 NextDescriptor
= KiRosGetMdFromArray();
671 if (!NextDescriptor
) return STATUS_INSUFFICIENT_RESOURCES
;
674 /* Build the descriptor we got */
675 Descriptor
->MemoryType
= MemoryType
;
676 Descriptor
->BasePage
= BasePage
;
677 Descriptor
->PageCount
= PageCount
;
679 /* Check if we're starting at the same place as the old one */
680 if (BasePage
== MemoryDescriptor
->BasePage
)
682 /* Simply decrease the old descriptor and rebase it */
683 MemoryDescriptor
->BasePage
+= PageCount
;
684 MemoryDescriptor
->PageCount
-= PageCount
;
685 MemoryDescriptor
->MemoryType
= CurrentType
;
687 else if (Delta
+ PageCount
== MemoryDescriptor
->PageCount
)
689 /* We finish where the old one did, shorten it */
690 MemoryDescriptor
->PageCount
-= PageCount
;
691 MemoryDescriptor
->MemoryType
= CurrentType
;
695 /* We're inside the current block, mark our free region */
696 NextDescriptor
->MemoryType
= LoaderFree
;
697 NextDescriptor
->BasePage
= BasePage
+ PageCount
;
698 NextDescriptor
->PageCount
= MemoryDescriptor
->PageCount
-
701 /* And cut down the current descriptor */
702 MemoryDescriptor
->PageCount
= Delta
;
703 MemoryDescriptor
->MemoryType
= CurrentType
;
705 /* Finally, insert our new free descriptor into the list */
706 KiRosInsertNtDescriptor(NextDescriptor
);
709 /* Insert the descriptor we allocated */
710 KiRosInsertNtDescriptor(Descriptor
);
714 return STATUS_SUCCESS
;
717 PMEMORY_ALLOCATION_DESCRIPTOR
719 KiRosFindNtDescriptor(IN ULONG BasePage
)
721 PMEMORY_ALLOCATION_DESCRIPTOR MdBlock
= NULL
;
722 PLIST_ENTRY NextEntry
, ListHead
;
724 /* Scan the memory descriptor list */
725 ListHead
= &KeLoaderBlock
->MemoryDescriptorListHead
;
726 NextEntry
= ListHead
->Flink
;
727 while (NextEntry
!= ListHead
)
729 /* Get the current descriptor */
730 MdBlock
= CONTAINING_RECORD(NextEntry
,
731 MEMORY_ALLOCATION_DESCRIPTOR
,
734 /* Check if it can contain our memory range */
735 if ((MdBlock
->BasePage
<= BasePage
) &&
736 (MdBlock
->BasePage
+ MdBlock
->PageCount
> BasePage
))
738 /* It can, break out */
742 /* Go to the next descriptor */
743 NextEntry
= NextEntry
->Flink
;
746 /* Return the descriptor we found, if any */
752 KiRosAllocateNtDescriptor(IN TYPE_OF_MEMORY MemoryType
,
756 OUT PULONG ReturnedBase
)
758 PMEMORY_ALLOCATION_DESCRIPTOR MdBlock
;
759 ULONG AlignedBase
, AlignedLimit
;
760 PMEMORY_ALLOCATION_DESCRIPTOR ActiveMdBlock
;
761 ULONG ActiveAlignedBase
= 0;
762 PLIST_ENTRY NextEntry
, ListHead
;
764 /* If no information was given, make some assumptions */
765 if (!Alignment
) Alignment
= 1;
766 if (!PageCount
) PageCount
= 1;
768 /* Start looking for a matching descvriptor */
771 /* Calculate the limit of the range */
772 AlignedLimit
= PageCount
+ BasePage
;
774 /* Find a descriptor that already contains our base address */
775 MdBlock
= KiRosFindNtDescriptor(BasePage
);
779 /* If it contains our limit as well, break out early */
780 if ((MdBlock
->PageCount
+ MdBlock
->BasePage
) >= AlignedLimit
) break;
783 /* Loop the memory list */
784 ActiveMdBlock
= NULL
;
785 ListHead
= &KeLoaderBlock
->MemoryDescriptorListHead
;
786 NextEntry
= ListHead
->Flink
;
787 while (NextEntry
!= ListHead
)
789 /* Get the current descriptors */
790 MdBlock
= CONTAINING_RECORD(NextEntry
,
791 MEMORY_ALLOCATION_DESCRIPTOR
,
794 /* Align the base address and our limit */
795 AlignedBase
= (MdBlock
->BasePage
+ (Alignment
- 1)) &~ Alignment
;
796 AlignedLimit
= MdBlock
->PageCount
-
800 /* Check if this is a free block that can satisfy us */
801 if ((MdBlock
->MemoryType
== LoaderFree
) &&
802 (AlignedLimit
<= MdBlock
->PageCount
) &&
803 (PageCount
<= AlignedLimit
))
805 /* It is, stop searching */
806 ActiveMdBlock
= MdBlock
;
807 ActiveAlignedBase
= AlignedBase
;
811 /* Try the next block */
812 NextEntry
= NextEntry
->Flink
;
815 /* See if we came up with an adequate block */
818 /* Generate a descriptor in it */
819 *ReturnedBase
= AlignedBase
;
820 return KiRosBuildNtDescriptor(ActiveMdBlock
,
827 /* We found a matching block, generate a descriptor with it */
828 *ReturnedBase
= BasePage
;
829 return KiRosBuildNtDescriptor(MdBlock
, MemoryType
, BasePage
, PageCount
);
834 KiRosBuildArcMemoryList(VOID
)
836 PMEMORY_ALLOCATION_DESCRIPTOR Descriptor
;
837 MEMORY_DESCRIPTOR
*Memory
;
840 /* Loop all BIOS Memory Descriptors */
841 for (i
= 0; i
< NumberDescriptors
; i
++)
843 /* Get the current descriptor */
844 Memory
= &MDArray
[i
];
846 /* Allocate an NT Memory Descriptor */
847 Descriptor
= KiRosGetMdFromArray();
848 if (!Descriptor
) return ENOMEM
;
850 /* Copy the memory type */
851 Descriptor
->MemoryType
= Memory
->MemoryType
;
852 if (Memory
->MemoryType
== MemoryFreeContiguous
)
854 /* Convert this to free */
855 Descriptor
->MemoryType
= LoaderFree
;
857 else if (Memory
->MemoryType
== MemorySpecialMemory
)
859 /* Convert this to special memory */
860 Descriptor
->MemoryType
= LoaderSpecialMemory
;
863 /* Copy the range data */
864 Descriptor
->BasePage
= Memory
->BasePage
;
865 Descriptor
->PageCount
= Memory
->PageCount
;
867 /* Insert the descriptor */
868 if (Descriptor
->PageCount
) KiRosInsertNtDescriptor(Descriptor
);
872 return STATUS_SUCCESS
;
877 KiRosFixupComponentTree(IN PCONFIGURATION_COMPONENT_DATA p
,
880 PCONFIGURATION_COMPONENT pp
;
882 /* Loop each entry */
885 /* Grab the component entry */
886 pp
= &p
->ComponentEntry
;
888 /* Fixup the pointers */
889 if (pp
->Identifier
) pp
->Identifier
= (PVOID
)((ULONG_PTR
)pp
->Identifier
+ i
);
890 if (p
->ConfigurationData
) p
->ConfigurationData
= (PVOID
)((ULONG_PTR
)p
->ConfigurationData
+ i
);
891 if (p
->Parent
) p
->Parent
= (PVOID
)((ULONG_PTR
)p
->Parent
+ i
);
892 if (p
->Sibling
) p
->Sibling
= (PVOID
)((ULONG_PTR
)p
->Sibling
+ i
);
893 if (p
->Child
) p
->Child
= (PVOID
)((ULONG_PTR
)p
->Child
+ i
);
895 /* Check if we have a child */
896 if (p
->Child
) KiRosFixupComponentTree(p
->Child
, i
);
898 /* Get to the next entry */
905 KiRosFrldrLpbToNtLpb(IN PROS_LOADER_PARAMETER_BLOCK RosLoaderBlock
,
906 IN PLOADER_PARAMETER_BLOCK
*NtLoaderBlock
)
908 PLOADER_PARAMETER_BLOCK LoaderBlock
;
909 PLDR_DATA_TABLE_ENTRY LdrEntry
;
910 PLOADER_MODULE RosEntry
= NULL
;
914 PCHAR BootPath
, HalPath
;
915 CHAR CommandLine
[256];
916 PARC_DISK_SIGNATURE RosDiskInfo
, ArcDiskInfo
;
917 PIMAGE_NT_HEADERS NtHeader
;
918 WCHAR PathToDrivers
[] = L
"\\SystemRoot\\System32\\drivers\\";
919 WCHAR PathToSystem32
[] = L
"\\SystemRoot\\System32\\";
920 WCHAR PathSetup
[] = L
"\\SystemRoot\\";
921 CHAR DriverNameLow
[256];
924 ULONG KernelBase
= RosLoaderBlock
->ModsAddr
[0].ModStart
;
927 /* First get some kernel-loader globals */
928 AcpiTableDetected
= (RosLoaderBlock
->Flags
& MB_FLAGS_ACPI_TABLE
) ? TRUE
: FALSE
;
930 /* Set the NT Loader block and initialize it */
931 *NtLoaderBlock
= KeLoaderBlock
= LoaderBlock
= &BldrLoaderBlock
;
932 RtlZeroMemory(LoaderBlock
, sizeof(LOADER_PARAMETER_BLOCK
));
934 /* Set the NLS Data block */
935 LoaderBlock
->NlsData
= &BldrNlsDataBlock
;
937 /* Set the ARC Data block */
938 LoaderBlock
->ArcDiskInformation
= &BldrArcDiskInfo
;
940 /* Assume this is from FreeLDR's SetupLdr */
941 LoaderBlock
->SetupLdrBlock
= &BldrSetupBlock
;
943 /* Setup the list heads */
944 InitializeListHead(&LoaderBlock
->LoadOrderListHead
);
945 InitializeListHead(&LoaderBlock
->MemoryDescriptorListHead
);
946 InitializeListHead(&LoaderBlock
->BootDriverListHead
);
947 InitializeListHead(&LoaderBlock
->ArcDiskInformation
->DiskSignatureListHead
);
949 /* Build the free memory map, which uses BIOS Descriptors */
950 KiRosBuildBiosMemoryMap();
952 /* Build entries for ReactOS memory ranges, which uses ARC Descriptors */
953 KiRosBuildOsMemoryMap();
955 #if defined(_M_IX86) || defined(_M_AMD64)
956 /* Build entries for the reserved map, which uses ARC Descriptors */
957 KiRosBuildReservedMemoryMap();
960 /* Now convert the BIOS and ARC Descriptors into NT Memory Descirptors */
961 KiRosBuildArcMemoryList();
963 /* Loop boot driver list */
964 for (i
= 0; i
< RosLoaderBlock
->ModsCount
; i
++)
966 /* Get the ROS loader entry */
967 RosEntry
= &RosLoaderBlock
->ModsAddr
[i
];
968 DriverName
= (PCHAR
)RosEntry
->String
;
969 ModStart
= (PVOID
)RosEntry
->ModStart
;
970 ModSize
= RosEntry
->ModEnd
- (ULONG_PTR
)ModStart
;
973 ModStart
-= KernelBase
;
976 /* Check if this is any of the NLS files */
977 if (!_stricmp(DriverName
, "ansi.nls"))
980 LoaderBlock
->NlsData
->AnsiCodePageData
= KERNEL_RVA(ModStart
);
982 /* Create an MD for it */
983 KiRosAllocateNtDescriptor(LoaderNlsData
,
984 KERNEL_DESCRIPTOR_PAGE(ModStart
),
985 (ModSize
+ PAGE_SIZE
- 1)>> PAGE_SHIFT
,
990 else if (!_stricmp(DriverName
, "oem.nls"))
993 LoaderBlock
->NlsData
->OemCodePageData
= KERNEL_RVA(ModStart
);
995 /* Create an MD for it */
996 KiRosAllocateNtDescriptor(LoaderNlsData
,
997 KERNEL_DESCRIPTOR_PAGE(ModStart
),
998 (ModSize
+ PAGE_SIZE
- 1)>> PAGE_SHIFT
,
1003 else if (!_stricmp(DriverName
, "casemap.nls"))
1005 /* Unicode Code page */
1006 LoaderBlock
->NlsData
->UnicodeCodePageData
= KERNEL_RVA(ModStart
);
1008 /* Create an MD for it */
1009 KiRosAllocateNtDescriptor(LoaderNlsData
,
1010 KERNEL_DESCRIPTOR_PAGE(ModStart
),
1011 (ModSize
+ PAGE_SIZE
- 1)>> PAGE_SHIFT
,
1017 /* Check if this is the SYSTEM hive */
1018 if (!(_stricmp(DriverName
, "system")) ||
1019 !(_stricmp(DriverName
, "system.hiv")))
1021 /* Save registry data */
1022 LoaderBlock
->RegistryBase
= KERNEL_RVA(ModStart
);
1023 LoaderBlock
->RegistryLength
= ModSize
;
1025 /* Disable setup mode */
1026 LoaderBlock
->SetupLdrBlock
= NULL
;
1028 /* Create an MD for it */
1029 KiRosAllocateNtDescriptor(LoaderRegistryData
,
1030 KERNEL_DESCRIPTOR_PAGE(ModStart
),
1031 (ModSize
+ PAGE_SIZE
- 1)>> PAGE_SHIFT
,
1037 /* Check if this is the HARDWARE hive */
1038 if (!(_stricmp(DriverName
, "hardware")) ||
1039 !(_stricmp(DriverName
, "hardware.hiv")))
1041 /* Create an MD for it */
1042 KiRosAllocateNtDescriptor(LoaderRegistryData
,
1043 KERNEL_DESCRIPTOR_PAGE(ModStart
),
1044 (ModSize
+ PAGE_SIZE
- 1)>> PAGE_SHIFT
,
1050 /* Check if this is the kernel */
1051 if (!(_stricmp(DriverName
, "ntoskrnl.exe")))
1053 /* Create an MD for it */
1054 KiRosAllocateNtDescriptor(LoaderSystemCode
,
1055 KERNEL_DESCRIPTOR_PAGE(ModStart
),
1056 (ModSize
+ PAGE_SIZE
- 1)>> PAGE_SHIFT
,
1060 else if (!(_stricmp(DriverName
, "hal.dll")))
1062 /* Create an MD for the HAL */
1063 KiRosAllocateNtDescriptor(LoaderHalCode
,
1064 KERNEL_DESCRIPTOR_PAGE(ModStart
),
1065 (ModSize
+ PAGE_SIZE
- 1)>> PAGE_SHIFT
,
1071 /* Create an MD for any driver */
1072 KiRosAllocateNtDescriptor(LoaderBootDriver
,
1073 KERNEL_DESCRIPTOR_PAGE(ModStart
),
1074 (ModSize
+ PAGE_SIZE
- 1)>> PAGE_SHIFT
,
1080 ModStart
+= 0x80800000;
1083 /* Lowercase the drivername so we can check its extension later */
1084 strcpy(DriverNameLow
, DriverName
);
1085 _strlwr(DriverNameLow
);
1087 /* Setup the loader entry */
1088 LdrEntry
= &BldrModules
[i
];
1089 RtlZeroMemory(LdrEntry
, sizeof(LDR_DATA_TABLE_ENTRY
));
1091 /* Convert driver name from ANSI to Unicode */
1092 for (j
= 0; j
< strlen(DriverName
); j
++)
1094 BldrModuleStrings
[i
][j
] = DriverName
[j
];
1097 /* Setup driver name */
1098 RtlInitUnicodeString(&LdrEntry
->BaseDllName
, BldrModuleStrings
[i
]);
1100 /* Construct a correct full name */
1101 BldrModuleStringsFull
[i
][0] = 0;
1102 LdrEntry
->FullDllName
.MaximumLength
= 260 * sizeof(WCHAR
);
1103 LdrEntry
->FullDllName
.Length
= 0;
1104 LdrEntry
->FullDllName
.Buffer
= BldrModuleStringsFull
[i
];
1106 /* Guess the path */
1107 if (LoaderBlock
->SetupLdrBlock
)
1109 UNICODE_STRING TempString
;
1110 RtlInitUnicodeString(&TempString
, PathSetup
);
1111 RtlAppendUnicodeStringToString(&LdrEntry
->FullDllName
, &TempString
);
1113 else if (strstr(DriverNameLow
, ".dll") || strstr(DriverNameLow
, ".exe"))
1115 UNICODE_STRING TempString
;
1116 RtlInitUnicodeString(&TempString
, PathToSystem32
);
1117 RtlAppendUnicodeStringToString(&LdrEntry
->FullDllName
, &TempString
);
1121 UNICODE_STRING TempString
;
1122 RtlInitUnicodeString(&TempString
, PathToDrivers
);
1123 RtlAppendUnicodeStringToString(&LdrEntry
->FullDllName
, &TempString
);
1126 /* Append base name of the driver */
1127 RtlAppendUnicodeStringToString(&LdrEntry
->FullDllName
, &LdrEntry
->BaseDllName
);
1129 /* Copy data from Freeldr Module Entry */
1130 LdrEntry
->DllBase
= ModStart
;
1131 LdrEntry
->SizeOfImage
= ModSize
;
1133 /* Copy additional data */
1134 NtHeader
= RtlImageNtHeader(ModStart
);
1135 LdrEntry
->EntryPoint
= RVA(ModStart
,
1137 OptionalHeader
.AddressOfEntryPoint
);
1139 /* Initialize other data */
1140 LdrEntry
->LoadCount
= 1;
1141 LdrEntry
->Flags
= LDRP_IMAGE_DLL
|
1142 LDRP_ENTRY_PROCESSED
;
1143 if (RosEntry
->Reserved
) LdrEntry
->Flags
|= LDRP_ENTRY_INSERTED
;
1145 /* Insert it into the loader block */
1146 InsertTailList(&LoaderBlock
->LoadOrderListHead
,
1147 &LdrEntry
->InLoadOrderLinks
);
1150 /* Now mark the remainder of the FreeLDR 6MB area as "in use" */
1151 KiRosAllocateNtDescriptor(LoaderMemoryData
,
1152 KERNEL_DESCRIPTOR_PAGE(RosEntry
->ModEnd
),
1153 KERNEL_DESCRIPTOR_PAGE((RosLoaderBlock
->KernelBase
+ 0x600000)) -
1154 KERNEL_DESCRIPTOR_PAGE(RosEntry
->ModEnd
),
1159 // Check if we have a ramdisk
1161 if ((RosLoaderBlock
->RdAddr
) && (RosLoaderBlock
->RdLength
))
1164 // Build a descriptor for it
1166 KiRosAllocateNtDescriptor(LoaderXIPRom
,
1167 KERNEL_DESCRIPTOR_PAGE(RosLoaderBlock
->RdAddr
),
1168 (RosLoaderBlock
->RdLength
+ PAGE_SIZE
- 1) >> PAGE_SHIFT
,
1173 /* Setup command line */
1174 LoaderBlock
->LoadOptions
= BldrCommandLine
;
1175 strcpy(BldrCommandLine
, RosLoaderBlock
->CommandLine
);
1177 /* Setup the extension block */
1178 LoaderBlock
->Extension
= &BldrExtensionBlock
;
1179 LoaderBlock
->Extension
->Size
= sizeof(LOADER_PARAMETER_EXTENSION
);
1180 LoaderBlock
->Extension
->MajorVersion
= 5;
1181 LoaderBlock
->Extension
->MinorVersion
= 2;
1184 // FIXME FIXME FIXME NOW!!!!
1186 /* FreeLDR hackllocates 1536 static pages for the initial boot images */
1187 LoaderBlock
->Extension
->LoaderPagesSpanned
= 1536 * PAGE_SIZE
;
1189 /* ReactOS always boots the kernel at 0x80800000 (just like NT 5.2) */
1190 LoaderBlock
->Extension
->LoaderPagesSpanned
+= 0x80800000 - KSEG0_BASE
;
1192 /* Now convert to pages */
1193 LoaderBlock
->Extension
->LoaderPagesSpanned
/= PAGE_SIZE
;
1195 /* Now setup the setup block if we have one */
1196 if (LoaderBlock
->SetupLdrBlock
)
1198 /* All we'll setup right now is the flag for text-mode setup */
1199 LoaderBlock
->SetupLdrBlock
->Flags
= SETUPLDR_TEXT_MODE
;
1202 /* Make a copy of the command line */
1203 strcpy(CommandLine
, LoaderBlock
->LoadOptions
);
1205 /* Find the first \, separating the ARC path from NT path */
1206 BootPath
= strchr(CommandLine
, '\\');
1207 *BootPath
= ANSI_NULL
;
1208 strncpy(BldrArcBootPath
, CommandLine
, 63);
1209 LoaderBlock
->ArcBootDeviceName
= BldrArcBootPath
;
1211 /* The rest of the string is the NT path */
1212 HalPath
= strchr(BootPath
+ 1, ' ');
1213 *HalPath
= ANSI_NULL
;
1214 BldrNtBootPath
[0] = '\\';
1215 strncat(BldrNtBootPath
, BootPath
+ 1, 63);
1216 strcat(BldrNtBootPath
,"\\");
1217 LoaderBlock
->NtBootPathName
= BldrNtBootPath
;
1219 /* Set the HAL paths */
1220 strncpy(BldrArcHalPath
, BldrArcBootPath
, 63);
1221 LoaderBlock
->ArcHalDeviceName
= BldrArcHalPath
;
1222 strcpy(BldrNtHalPath
, "\\");
1223 LoaderBlock
->NtHalPathName
= BldrNtHalPath
;
1225 /* Use this new command line */
1226 strncpy(LoaderBlock
->LoadOptions
, HalPath
+ 2, 255);
1228 /* Parse it and change every slash to a space */
1229 BootPath
= LoaderBlock
->LoadOptions
;
1230 do {if (*BootPath
== '/') *BootPath
= ' ';} while (*BootPath
++);
1232 /* Now let's loop ARC disk information */
1233 for (i
= 0; i
< RosLoaderBlock
->DrivesCount
; i
++)
1235 /* Get the ROS loader entry */
1236 RosDiskInfo
= &RosLoaderBlock
->DrivesAddr
[i
];
1238 /* Get the ARC structure */
1239 ArcDiskInfo
= &BldrDiskInfo
[i
];
1241 /* Copy the data over */
1242 ArcDiskInfo
->Signature
= RosDiskInfo
->Signature
;
1243 ArcDiskInfo
->CheckSum
= RosDiskInfo
->CheckSum
;
1245 /* Copy the ARC Name */
1246 strcpy(BldrArcNames
[i
], RosDiskInfo
->ArcName
);
1247 ArcDiskInfo
->ArcName
= BldrArcNames
[i
];
1249 /* Insert into the list */
1250 InsertTailList(&LoaderBlock
->ArcDiskInformation
->DiskSignatureListHead
,
1251 &ArcDiskInfo
->ListEntry
);
1254 /* Copy the ARC Hardware Tree */
1255 RtlCopyMemory(BldrArcHwBuffer
, (PVOID
)RosLoaderBlock
->ArchExtra
, 16 * 1024);
1256 LoaderBlock
->ConfigurationRoot
= (PVOID
)BldrArcHwBuffer
;
1259 KiRosFixupComponentTree(LoaderBlock
->ConfigurationRoot
,
1260 (ULONG_PTR
)BldrArcHwBuffer
-
1261 RosLoaderBlock
->ArchExtra
);
1266 KiSetupSyscallHandler();
1270 KiRosPrepareForSystemStartup(IN ULONG Dummy
,
1271 IN PROS_LOADER_PARAMETER_BLOCK LoaderBlock
)
1273 PLOADER_PARAMETER_BLOCK NtLoaderBlock
;
1274 ULONG size
, i
= 0, *ent
;
1275 #if defined(_M_IX86)
1277 PKGDTENTRY TssEntry
;
1278 KDESCRIPTOR IdtDescriptor
;
1280 __sidt(&IdtDescriptor
.Limit
);
1281 RtlCopyMemory(KiHackIdt
, (PVOID
)IdtDescriptor
.Base
, IdtDescriptor
.Limit
+ 1);
1282 IdtDescriptor
.Base
= (ULONG
)&KiHackIdt
;
1283 IdtDescriptor
.Limit
= sizeof(KiHackIdt
) - 1;
1285 /* Load the GDT and IDT */
1286 Ke386SetGlobalDescriptorTable(&KiGdtDescriptor
.Limit
);
1287 __lidt(&IdtDescriptor
.Limit
);
1289 /* Initialize the boot TSS */
1291 TssEntry
= &KiBootGdt
[KGDT_TSS
/ sizeof(KGDTENTRY
)];
1292 TssEntry
->HighWord
.Bits
.Type
= I386_TSS
;
1293 TssEntry
->HighWord
.Bits
.Pres
= 1;
1294 TssEntry
->HighWord
.Bits
.Dpl
= 0;
1295 TssEntry
->BaseLow
= (USHORT
)((ULONG_PTR
)Tss
& 0xFFFF);
1296 TssEntry
->HighWord
.Bytes
.BaseMid
= (UCHAR
)((ULONG_PTR
)Tss
>> 16);
1297 TssEntry
->HighWord
.Bytes
.BaseHi
= (UCHAR
)((ULONG_PTR
)Tss
>> 24);
1301 // Zero bats. We might have residual bats set that will interfere with
1302 // our mapping of ofwldr.
1303 for (i
= 0; i
< 4; i
++)
1305 SetBat(i
, 0, 0, 0); SetBat(i
, 1, 0, 0);
1307 KiSetupSyscallHandler();
1308 DbgPrint("Kernel Power (%08x)\n", LoaderBlock
);
1309 DbgPrint("ArchExtra (%08x)!\n", LoaderBlock
->ArchExtra
);
1312 /* Save pointer to ROS Block */
1313 KeRosLoaderBlock
= LoaderBlock
;
1315 /* Get debugging function */
1316 FrLdrDbgPrint
= LoaderBlock
->FrLdrDbgPrint
;
1318 /* Save memory manager data */
1319 KeMemoryMapRangeCount
= 0;
1320 if (LoaderBlock
->Flags
& MB_FLAGS_MMAP_INFO
)
1322 /* We have a memory map from the nice BIOS */
1323 ent
= ((PULONG
)(LoaderBlock
->MmapAddr
- sizeof(ULONG
))); // FIXME: this is ugly
1327 /* Map it until we run out of size */
1328 while (i
< LoaderBlock
->MmapLength
)
1330 /* Copy into the Kernel Memory Map */
1331 memcpy (&KeMemoryMap
[KeMemoryMapRangeCount
],
1332 (PVOID
)(LoaderBlock
->MmapAddr
+ i
),
1333 sizeof(ADDRESS_RANGE
));
1335 /* Increase Memory Map Count */
1336 KeMemoryMapRangeCount
++;
1343 LoaderBlock
->MmapLength
= KeMemoryMapRangeCount
* sizeof(ADDRESS_RANGE
);
1344 LoaderBlock
->MmapAddr
= (ULONG_PTR
)KeMemoryMap
;
1348 /* Nothing from BIOS */
1349 LoaderBlock
->MmapLength
= 0;
1350 LoaderBlock
->MmapAddr
= (ULONG_PTR
)KeMemoryMap
;
1353 /* Convert the loader block */
1354 KiRosFrldrLpbToNtLpb(KeRosLoaderBlock
, &NtLoaderBlock
);
1357 DbgPrint("Finished KiRosFrldrLpbToNtLpb\n");
1360 /* Do general System Startup */
1361 KiSystemStartupReal(NtLoaderBlock
);