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 ADDRESS_RANGE KeMemoryMap
[64];
38 ULONG KeMemoryMapRangeCount
;
40 /* NT Loader Module/Descriptor Count */
44 /* NT Loader Data. Eats up about 100KB! */
45 LOADER_PARAMETER_BLOCK BldrLoaderBlock
; // 0x0000
46 LOADER_PARAMETER_EXTENSION BldrExtensionBlock
; // 0x0060
47 CHAR BldrCommandLine
[256]; // 0x00DC
48 CHAR BldrArcBootPath
[64]; // 0x01DC
49 CHAR BldrArcHalPath
[64]; // 0x021C
50 CHAR BldrNtHalPath
[64]; // 0x025C
51 CHAR BldrNtBootPath
[64]; // 0x029C
52 LDR_DATA_TABLE_ENTRY BldrModules
[64]; // 0x02DC
53 MEMORY_ALLOCATION_DESCRIPTOR BldrMemoryDescriptors
[60]; // 0x14DC
54 WCHAR BldrModuleStrings
[64][260]; // 0x19DC
55 WCHAR BldrModuleStringsFull
[64][260]; // 0x9BDC
56 NLS_DATA_BLOCK BldrNlsDataBlock
; // 0x11DDC
57 SETUP_LOADER_BLOCK BldrSetupBlock
; // 0x11DE8
58 ARC_DISK_INFORMATION BldrArcDiskInfo
; // 0x12134
59 CHAR BldrArcNames
[32][256]; // 0x1213C
60 ARC_DISK_SIGNATURE BldrDiskInfo
[32]; // 0x1413C
61 CHAR BldrArcHwBuffer
[16 * 1024]; // 0x1843C
64 BIOS_MEMORY_DESCRIPTOR BiosMemoryDescriptors
[16] = { { 0, 0 }, };
65 PBIOS_MEMORY_DESCRIPTOR BiosMemoryDescriptorList
= BiosMemoryDescriptors
;
68 ULONG NumberDescriptors
= 0;
69 MEMORY_DESCRIPTOR MDArray
[60] = { { 0, 0, 0 }, };
76 /* Old boot style IDT */
77 KIDTENTRY KiBootIdt
[256];
80 KGDTENTRY KiBootGdt
[256] =
82 {0x0000, 0x0000, {{0x00, 0x00, 0x00, 0x00}}}, /* KGDT_NULL */
83 {0xffff, 0x0000, {{0x00, 0x9b, 0xcf, 0x00}}}, /* KGDT_R0_CODE */
84 {0xffff, 0x0000, {{0x00, 0x93, 0xcf, 0x00}}}, /* KGDT_R0_DATA */
85 {0xffff, 0x0000, {{0x00, 0xfb, 0xcf, 0x00}}}, /* KGDT_R3_CODE */
86 {0xffff, 0x0000, {{0x00, 0xf3, 0xcf, 0x00}}}, /* KGDT_R3_DATA*/
87 {0x0000, 0x0000, {{0x00, 0x00, 0x00, 0x00}}}, /* KGDT_TSS */
88 {0x0001, 0xf000, {{0xdf, 0x93, 0xc0, 0xff}}}, /* KGDT_R0_PCR */
89 {0x0fff, 0x0000, {{0x00, 0xf3, 0x40, 0x00}}}, /* KGDT_R3_TEB */
90 {0x0000, 0x0000, {{0x00, 0x00, 0x00, 0x00}}}, /* KGDT_UNUSED */
91 {0x0000, 0x0000, {{0x00, 0x00, 0x00, 0x00}}}, /* KGDT_LDT */
92 {0x0000, 0x0000, {{0x00, 0x00, 0x00, 0x00}}}, /* KGDT_DF_TSS */
93 {0x0000, 0x0000, {{0x00, 0x00, 0x00, 0x00}}} /* KGDT_NMI_TSS */
97 KDESCRIPTOR KiGdtDescriptor
= {0, sizeof(KiBootGdt
) - 1, (ULONG
)KiBootGdt
};
101 /* FUNCTIONS *****************************************************************/
103 PMEMORY_ALLOCATION_DESCRIPTOR
105 KiRosGetMdFromArray(VOID
)
107 /* Return the next MD from the list, but make sure we don't overflow */
108 if (BldrCurrentMd
> 60) ASSERT(FALSE
);
109 return &BldrMemoryDescriptors
[BldrCurrentMd
++];
114 KiRosAddBiosBlock(ULONG Address
,
117 PBIOS_MEMORY_DESCRIPTOR BiosBlock
= BiosMemoryDescriptorList
;
119 /* Loop our BIOS Memory Descriptor List */
120 while (BiosBlock
->BlockSize
> 0)
122 /* Check if we've found a matching head block */
123 if (Address
+ Size
== BiosBlock
->BlockBase
)
125 /* Simply enlarge and rebase it */
126 BiosBlock
->BlockBase
= Address
;
127 BiosBlock
->BlockSize
+= Size
;
131 /* Check if we've found a matching tail block */
132 if (Address
== (BiosBlock
->BlockBase
+ BiosBlock
->BlockSize
))
134 /* Simply enlarge it */
135 BiosBlock
->BlockSize
+= Size
;
139 /* Nothing suitable found, try the next block */
143 /* No usable blocks found, found a free block instead */
144 if (!BiosBlock
->BlockSize
)
147 BiosBlock
->BlockBase
= Address
;
148 BiosBlock
->BlockSize
= Size
;
150 /* Create a new block and mark it as the end of the array */
152 BiosBlock
->BlockBase
= BiosBlock
->BlockSize
= 0L;
158 KiRosBuildBiosMemoryMap(VOID
)
160 ULONG BlockBegin
, BlockEnd
;
163 /* Loop the BIOS Memory Map */
164 for (j
= 0; j
< KeMemoryMapRangeCount
; j
++)
166 /* Get the start and end addresses */
167 BlockBegin
= KeMemoryMap
[j
].BaseAddrLow
;
168 BlockEnd
= KeMemoryMap
[j
].BaseAddrLow
+ KeMemoryMap
[j
].LengthLow
- 1;
170 /* Make sure this isn't a > 4GB descriptor */
171 if (!KeMemoryMap
[j
].BaseAddrHigh
)
173 /* Make sure we don't overflow */
174 if (BlockEnd
< BlockBegin
) BlockEnd
= 0xFFFFFFFF;
176 /* Check if this is free memory */
177 if (KeMemoryMap
[j
].Type
== 1)
179 /* Add it to our BIOS descriptors */
180 KiRosAddBiosBlock(BlockBegin
, BlockEnd
- BlockBegin
+ 1);
188 KiRosAllocateArcDescriptor(IN ULONG PageBegin
,
190 IN MEMORY_TYPE MemoryType
)
194 /* Loop all our descriptors */
195 for (i
= 0; i
< NumberDescriptors
; i
++)
197 /* Attempt to fing a free block that describes our region */
198 if ((MDArray
[i
].MemoryType
== MemoryFree
) &&
199 (MDArray
[i
].BasePage
<= PageBegin
) &&
200 (MDArray
[i
].BasePage
+ MDArray
[i
].PageCount
> PageBegin
) &&
201 (MDArray
[i
].BasePage
+ MDArray
[i
].PageCount
>= PageEnd
))
208 /* Check if we found no free blocks, and fail if so */
209 if (i
== NumberDescriptors
) return ENOMEM
;
211 /* Check if the block has our base address */
212 if (MDArray
[i
].BasePage
== PageBegin
)
214 /* Check if it also has our ending address */
215 if ((MDArray
[i
].BasePage
+ MDArray
[i
].PageCount
) == PageEnd
)
217 /* Then convert this region into our new memory type */
218 MDArray
[i
].MemoryType
= MemoryType
;
222 /* Otherwise, make sure we have enough descriptors */
223 if (NumberDescriptors
== 60) return ENOMEM
;
225 /* Cut this descriptor short */
226 MDArray
[i
].BasePage
= PageEnd
;
227 MDArray
[i
].PageCount
-= (PageEnd
- PageBegin
);
229 /* And allocate a new descriptor for our memory range */
230 MDArray
[NumberDescriptors
].BasePage
= PageBegin
;
231 MDArray
[NumberDescriptors
].PageCount
= PageEnd
- PageBegin
;
232 MDArray
[NumberDescriptors
].MemoryType
= MemoryType
;
236 else if ((MDArray
[i
].BasePage
+ MDArray
[i
].PageCount
) == PageEnd
)
238 /* This block has our end address, make sure we have a free block */
239 if (NumberDescriptors
== 60) return ENOMEM
;
241 /* Rebase this descriptor */
242 MDArray
[i
].PageCount
= PageBegin
- MDArray
[i
].BasePage
;
244 /* And allocate a new descriptor for our memory range */
245 MDArray
[NumberDescriptors
].BasePage
= PageBegin
;
246 MDArray
[NumberDescriptors
].PageCount
= PageEnd
- PageBegin
;
247 MDArray
[NumberDescriptors
].MemoryType
= MemoryType
;
252 /* We'll need two descriptors, make sure they're available */
253 if ((NumberDescriptors
+ 1) >= 60) return ENOMEM
;
255 /* Allocate a free memory descriptor for what follows us */
256 MDArray
[NumberDescriptors
].BasePage
= PageEnd
;
257 MDArray
[NumberDescriptors
].PageCount
= MDArray
[i
].PageCount
-
258 (PageEnd
- MDArray
[i
].BasePage
);
259 MDArray
[NumberDescriptors
].MemoryType
= MemoryFree
;
262 /* Cut down the current free descriptor */
263 MDArray
[i
].PageCount
= PageBegin
- MDArray
[i
].BasePage
;
265 /* Allocate a new memory descriptor for our memory range */
266 MDArray
[NumberDescriptors
].BasePage
= PageBegin
;
267 MDArray
[NumberDescriptors
].PageCount
= PageEnd
- PageBegin
;
268 MDArray
[NumberDescriptors
].MemoryType
= MemoryType
;
272 /* Everything went well */
273 return STATUS_SUCCESS
;
278 KiRosConfigureArcDescriptor(IN ULONG PageBegin
,
280 IN TYPE_OF_MEMORY MemoryType
)
283 ULONG BlockBegin
, BlockEnd
;
284 MEMORY_TYPE BlockType
;
285 BOOLEAN Combined
= FALSE
;
287 /* If this descriptor seems bogus, just return */
288 if (PageEnd
<= PageBegin
) return STATUS_SUCCESS
;
290 /* Loop every ARC descriptor, trying to find one we can modify */
291 for (i
= 0; i
< NumberDescriptors
; i
++)
293 /* Get its settings */
294 BlockBegin
= MDArray
[i
].BasePage
;
295 BlockEnd
= MDArray
[i
].BasePage
+ MDArray
[i
].PageCount
;
296 BlockType
= MDArray
[i
].MemoryType
;
298 /* Check if we can fit inside this block */
299 if (BlockBegin
< PageBegin
)
301 /* Check if we are larger then it */
302 if ((BlockEnd
> PageBegin
) && (BlockEnd
<= PageEnd
))
304 /* Make it end where we start */
305 BlockEnd
= PageBegin
;
308 /* Check if it ends after we do */
309 if (BlockEnd
> PageEnd
)
311 /* Make sure we can allocate a descriptor */
312 if (NumberDescriptors
== 60) return ENOMEM
;
314 /* Create a descriptor for whatever memory we're not part of */
315 MDArray
[NumberDescriptors
].MemoryType
= BlockType
;
316 MDArray
[NumberDescriptors
].BasePage
= PageEnd
;
317 MDArray
[NumberDescriptors
].PageCount
= BlockEnd
- PageEnd
;
320 /* The next block ending is now where we begin */
321 BlockEnd
= PageBegin
;
326 /* Check if the blog begins inside our range */
327 if (BlockBegin
< PageEnd
)
329 /* Check if it ends before we do */
330 if (BlockEnd
< PageEnd
)
332 /* Then make it disappear */
333 BlockEnd
= BlockBegin
;
337 /* Otherwise make it start where we end */
338 BlockBegin
= PageEnd
;
343 /* Check if the block matches us, and we haven't tried combining yet */
344 if (((TYPE_OF_MEMORY
)BlockType
== MemoryType
) && !(Combined
))
346 /* Check if it starts where we end */
347 if (BlockBegin
== PageEnd
)
349 /* Make it start with us, and combine us */
350 BlockBegin
= PageBegin
;
353 else if (BlockEnd
== PageBegin
)
355 /* Otherwise, it ends where we begin, combine its ending */
361 /* Check the original block data matches with what we came up with */
362 if ((MDArray
[i
].BasePage
== BlockBegin
) &&
363 (MDArray
[i
].PageCount
== BlockEnd
- BlockBegin
))
369 /* Otherwise, set our new settings for this block */
370 MDArray
[i
].BasePage
= BlockBegin
;
371 MDArray
[i
].PageCount
= BlockEnd
- BlockBegin
;
373 /* Check if we are killing the block */
374 if (BlockBegin
== BlockEnd
)
376 /* Delete this block and restart the loop properly */
378 if (i
< NumberDescriptors
) MDArray
[i
] = MDArray
[NumberDescriptors
];
383 /* If we got here without combining, we need to allocate a new block */
384 if (!(Combined
) && (MemoryType
< LoaderMaximum
))
386 /* Make sure there's enough descriptors */
387 if (NumberDescriptors
== 60) return ENOMEM
;
389 /* Allocate a new block with our data */
390 MDArray
[NumberDescriptors
].MemoryType
= MemoryType
;
391 MDArray
[NumberDescriptors
].BasePage
= PageBegin
;
392 MDArray
[NumberDescriptors
].PageCount
= PageEnd
- PageBegin
;
396 /* Changes complete, return success */
397 return STATUS_SUCCESS
;
402 KiRosBuildOsMemoryMap(VOID
)
404 PBIOS_MEMORY_DESCRIPTOR MdBlock
;
405 ULONG BlockStart
, BlockEnd
, BiasedStart
, BiasedEnd
, PageStart
, PageEnd
;
406 NTSTATUS Status
= STATUS_SUCCESS
;
407 ULONG BiosPage
= 0xA0;
409 /* Loop the BIOS Memory Descriptor List */
410 MdBlock
= BiosMemoryDescriptorList
;
411 while (MdBlock
->BlockSize
)
413 /* Get the statrt and end addresses */
414 BlockStart
= MdBlock
->BlockBase
;
415 BlockEnd
= BlockStart
+ MdBlock
->BlockSize
- 1;
417 /* Align them to page boundaries */
418 BiasedStart
= BlockStart
& (PAGE_SIZE
- 1);
419 if (BiasedStart
) BlockStart
= BlockStart
+ PAGE_SIZE
- BiasedStart
;
420 BiasedEnd
= (BlockEnd
+ 1) & (ULONG
)(PAGE_SIZE
- 1);
421 if (BiasedEnd
) BlockEnd
-= BiasedEnd
;
423 /* Get the actual page numbers */
424 PageStart
= BlockStart
>> PAGE_SHIFT
;
425 PageEnd
= (BlockEnd
+ 1) >> PAGE_SHIFT
;
427 /* If we're starting at page 0, then put the BIOS page at the end */
428 if (!PageStart
) BiosPage
= PageEnd
;
430 /* Check if we did any alignment */
433 /* Mark that region as reserved */
434 Status
= KiRosConfigureArcDescriptor(PageStart
- 1,
436 MemorySpecialMemory
);
437 if (Status
!= STATUS_SUCCESS
) break;
440 /* Check if we did any alignment */
443 /* Mark that region as reserved */
444 Status
= KiRosConfigureArcDescriptor(PageEnd
- 1,
446 MemorySpecialMemory
);
447 if (Status
!= STATUS_SUCCESS
) break;
449 /* If the bios page was the last page, use the next one instead */
450 if (BiosPage
== PageEnd
) BiosPage
+= 1;
453 /* Check if the page is below the 16MB Memory hole */
454 if (PageEnd
<= 0xFC0)
456 /* It is, mark the memory a free */
457 Status
= KiRosConfigureArcDescriptor(PageStart
,
461 else if (PageStart
>= 0x1000)
463 /* It's over 16MB, so that memory gets marked as reserve */
464 Status
= KiRosConfigureArcDescriptor(PageStart
,
470 /* Check if it starts below the memory hole */
471 if (PageStart
< 0xFC0)
473 /* Mark that part as free */
474 Status
= KiRosConfigureArcDescriptor(PageStart
,
477 if (Status
!= STATUS_SUCCESS
) break;
479 /* And update the page start for the code below */
483 /* Any code in the memory hole region ends up as reserve */
484 Status
= KiRosConfigureArcDescriptor(PageStart
,
489 /* If we failed, break out, otherwise, go to the next BIOS block */
490 if (Status
!= STATUS_SUCCESS
) break;
494 /* If anything failed until now, return error code */
495 if (Status
!= STATUS_SUCCESS
) return Status
;
498 /* Set the top 16MB region as reserved */
499 Status
= KiRosConfigureArcDescriptor(0xFC0, 0x1000, MemorySpecialMemory
);
500 if (Status
!= STATUS_SUCCESS
) return Status
;
502 /* Setup the BIOS region as reserved */
503 KiRosConfigureArcDescriptor(0xA0, 0x100, LoaderMaximum
);
504 KiRosConfigureArcDescriptor(BiosPage
, 0x100, MemoryFirmwarePermanent
);
506 /* Build an entry for the IVT */
507 Status
= KiRosAllocateArcDescriptor(0, 1, MemoryFirmwarePermanent
);
508 if (Status
!= STATUS_SUCCESS
) return Status
;
511 /* Build an entry for the KPCR and KUSER_SHARED_DATA */
512 Status
= KiRosAllocateArcDescriptor(1, 3, LoaderStartupPcrPage
);
513 if (Status
!= STATUS_SUCCESS
) return Status
;
515 /* Build an entry for the PDE and return the status */
516 Status
= KiRosAllocateArcDescriptor(KeRosLoaderBlock
->
517 PageDirectoryStart
>> PAGE_SHIFT
,
519 PageDirectoryEnd
>> PAGE_SHIFT
,
527 KiRosBuildReservedMemoryMap(VOID
)
530 ULONG BlockBegin
, BlockEnd
, BiasedPage
;
532 /* Loop the BIOS Memory Map */
533 for (j
= 0; j
< KeMemoryMapRangeCount
; j
++)
535 /* Get the start and end addresses */
536 BlockBegin
= KeMemoryMap
[j
].BaseAddrLow
;
537 BlockEnd
= BlockBegin
+ KeMemoryMap
[j
].LengthLow
- 1;
539 /* Make sure it wasn't a > 4GB descriptor */
540 if (!KeMemoryMap
[j
].BaseAddrHigh
)
542 /* Make sure it doesn't overflow */
543 if (BlockEnd
< BlockBegin
) BlockEnd
= 0xFFFFFFFF;
545 /* Check if this was free memory */
546 if (KeMemoryMap
[j
].Type
== 1)
548 /* Get the page-aligned addresses */
549 BiasedPage
= BlockBegin
& (PAGE_SIZE
- 1);
550 BlockBegin
>>= PAGE_SHIFT
;
551 if (BiasedPage
) BlockBegin
++;
552 BlockEnd
= (BlockEnd
>> PAGE_SHIFT
) + 1;
554 /* Check if the block is within the 16MB memory hole */
555 if ((BlockBegin
< 0xFC0) && (BlockEnd
>= 0xFC0))
557 /* Don't allow it to cross this boundary */
561 /* Check if the boundary is across 16MB */
562 if ((BlockEnd
> 0xFFF) && (BlockBegin
<= 0xFFF))
564 /* Don't let it cross */
568 /* Check if the block describes the memory hole */
569 if ((BlockBegin
>= 0xFC0) && (BlockEnd
<= 0xFFF))
571 /* Set this region as temporary */
572 KiRosConfigureArcDescriptor(BlockBegin
,
574 MemoryFirmwareTemporary
);
579 /* Get the page-aligned addresses */
580 BlockBegin
>>= PAGE_SHIFT
;
581 BiasedPage
= (BlockEnd
+ 1) & (PAGE_SIZE
- 1);
582 BlockEnd
>>= PAGE_SHIFT
;
583 if (BiasedPage
) BlockEnd
++;
585 /* Set this memory as reserved */
586 KiRosConfigureArcDescriptor(BlockBegin
,
588 MemorySpecialMemory
);
597 KiRosInsertNtDescriptor(IN PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor
)
599 PLIST_ENTRY ListHead
, PreviousEntry
, NextEntry
;
600 PMEMORY_ALLOCATION_DESCRIPTOR Descriptor
= NULL
, NextDescriptor
= NULL
;
602 /* Loop the memory descriptor list */
603 ListHead
= &KeLoaderBlock
->MemoryDescriptorListHead
;
604 PreviousEntry
= ListHead
;
605 NextEntry
= ListHead
->Flink
;
606 while (NextEntry
!= ListHead
)
608 /* Get the current descriptor and check if it's below ours */
609 NextDescriptor
= CONTAINING_RECORD(NextEntry
,
610 MEMORY_ALLOCATION_DESCRIPTOR
,
612 if (NewDescriptor
->BasePage
< NextDescriptor
->BasePage
) break;
614 /* It isn't, save the previous entry and descriptor, and try again */
615 PreviousEntry
= NextEntry
;
616 Descriptor
= NextDescriptor
;
617 NextEntry
= NextEntry
->Flink
;
620 /* So we found the right spot to insert. Is this free memory? */
621 if (NewDescriptor
->MemoryType
!= LoaderFree
)
623 /* It isn't, so insert us before the last descriptor */
624 InsertHeadList(PreviousEntry
, &NewDescriptor
->ListEntry
);
628 /* We're free memory. Check if the entry we found is also free memory */
629 if ((PreviousEntry
!= ListHead
) &&
630 ((Descriptor
->MemoryType
== LoaderFree
) ||
631 (Descriptor
->MemoryType
== LoaderReserve
)) &&
632 ((Descriptor
->BasePage
+ Descriptor
->PageCount
) ==
633 NewDescriptor
->BasePage
))
635 /* It's free memory, and we're right after it. Enlarge that block */
636 Descriptor
->PageCount
+= NewDescriptor
->PageCount
;
637 NewDescriptor
= Descriptor
;
641 /* Our range scan't be combined, so just insert us separately */
642 InsertHeadList(PreviousEntry
, &NewDescriptor
->ListEntry
);
645 /* Check if we merged with an existing free memory block */
646 if ((NextEntry
!= ListHead
) &&
647 ((NextDescriptor
->MemoryType
== LoaderFree
) ||
648 (NextDescriptor
->MemoryType
== LoaderReserve
)) &&
649 ((NewDescriptor
->BasePage
+ NewDescriptor
->PageCount
) ==
650 NextDescriptor
->BasePage
))
652 /* Update our own block */
653 NewDescriptor
->PageCount
+= NextDescriptor
->PageCount
;
655 /* Remove the next block */
656 RemoveEntryList(&NextDescriptor
->ListEntry
);
663 KiRosBuildNtDescriptor(IN PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor
,
664 IN MEMORY_TYPE MemoryType
,
668 PMEMORY_ALLOCATION_DESCRIPTOR Descriptor
, NextDescriptor
= NULL
;
670 TYPE_OF_MEMORY CurrentType
;
673 /* Check how many pages we'll be consuming */
674 Delta
= BasePage
- MemoryDescriptor
->BasePage
;
675 if (!(Delta
) && (PageCount
== MemoryDescriptor
->PageCount
))
677 /* We can simply convert the current descriptor into our new type */
678 MemoryDescriptor
->MemoryType
= MemoryType
;
682 /* Get the current memory type of the descriptor, and reserve it */
683 CurrentType
= MemoryDescriptor
->MemoryType
;
684 MemoryDescriptor
->MemoryType
= LoaderSpecialMemory
;
686 /* Check if we'll need another descriptor for what's left of memory */
687 UseNext
= ((BasePage
!= MemoryDescriptor
->BasePage
) &&
688 (Delta
+ PageCount
!= MemoryDescriptor
->PageCount
));
690 /* Get a descriptor */
691 Descriptor
= KiRosGetMdFromArray();
692 if (!Descriptor
) return STATUS_INSUFFICIENT_RESOURCES
;
694 /* Check if we are using another descriptor */
697 /* Allocate that one too */
698 NextDescriptor
= KiRosGetMdFromArray();
699 if (!NextDescriptor
) return STATUS_INSUFFICIENT_RESOURCES
;
702 /* Build the descriptor we got */
703 Descriptor
->MemoryType
= MemoryType
;
704 Descriptor
->BasePage
= BasePage
;
705 Descriptor
->PageCount
= PageCount
;
707 /* Check if we're starting at the same place as the old one */
708 if (BasePage
== MemoryDescriptor
->BasePage
)
710 /* Simply decrease the old descriptor and rebase it */
711 MemoryDescriptor
->BasePage
+= PageCount
;
712 MemoryDescriptor
->PageCount
-= PageCount
;
713 MemoryDescriptor
->MemoryType
= CurrentType
;
715 else if (Delta
+ PageCount
== MemoryDescriptor
->PageCount
)
717 /* We finish where the old one did, shorten it */
718 MemoryDescriptor
->PageCount
-= PageCount
;
719 MemoryDescriptor
->MemoryType
= CurrentType
;
723 /* We're inside the current block, mark our free region */
724 NextDescriptor
->MemoryType
= LoaderFree
;
725 NextDescriptor
->BasePage
= BasePage
+ PageCount
;
726 NextDescriptor
->PageCount
= MemoryDescriptor
->PageCount
-
729 /* And cut down the current descriptor */
730 MemoryDescriptor
->PageCount
= Delta
;
731 MemoryDescriptor
->MemoryType
= CurrentType
;
733 /* Finally, insert our new free descriptor into the list */
734 KiRosInsertNtDescriptor(NextDescriptor
);
737 /* Insert the descriptor we allocated */
738 KiRosInsertNtDescriptor(Descriptor
);
742 return STATUS_SUCCESS
;
745 PMEMORY_ALLOCATION_DESCRIPTOR
747 KiRosFindNtDescriptor(IN ULONG BasePage
)
749 PMEMORY_ALLOCATION_DESCRIPTOR MdBlock
= NULL
;
750 PLIST_ENTRY NextEntry
, ListHead
;
752 /* Scan the memory descriptor list */
753 ListHead
= &KeLoaderBlock
->MemoryDescriptorListHead
;
754 NextEntry
= ListHead
->Flink
;
755 while (NextEntry
!= ListHead
)
757 /* Get the current descriptor */
758 MdBlock
= CONTAINING_RECORD(NextEntry
,
759 MEMORY_ALLOCATION_DESCRIPTOR
,
762 /* Check if it can contain our memory range */
763 if ((MdBlock
->BasePage
<= BasePage
) &&
764 (MdBlock
->BasePage
+ MdBlock
->PageCount
> BasePage
))
766 /* It can, break out */
770 /* Go to the next descriptor */
771 NextEntry
= NextEntry
->Flink
;
774 /* Return the descriptor we found, if any */
780 KiRosAllocateNtDescriptor(IN TYPE_OF_MEMORY MemoryType
,
784 OUT PULONG ReturnedBase
)
786 PMEMORY_ALLOCATION_DESCRIPTOR MdBlock
;
787 ULONG AlignedBase
, AlignedLimit
;
788 PMEMORY_ALLOCATION_DESCRIPTOR ActiveMdBlock
;
789 ULONG ActiveAlignedBase
= 0;
790 PLIST_ENTRY NextEntry
, ListHead
;
792 /* If no information was given, make some assumptions */
793 if (!Alignment
) Alignment
= 1;
794 if (!PageCount
) PageCount
= 1;
796 /* Start looking for a matching descvriptor */
799 /* Calculate the limit of the range */
800 AlignedLimit
= PageCount
+ BasePage
;
802 /* Find a descriptor that already contains our base address */
803 MdBlock
= KiRosFindNtDescriptor(BasePage
);
807 /* If it contains our limit as well, break out early */
808 if ((MdBlock
->PageCount
+ MdBlock
->BasePage
) >= AlignedLimit
) break;
811 /* Loop the memory list */
812 ActiveMdBlock
= NULL
;
813 ListHead
= &KeLoaderBlock
->MemoryDescriptorListHead
;
814 NextEntry
= ListHead
->Flink
;
815 while (NextEntry
!= ListHead
)
817 /* Get the current descriptors */
818 MdBlock
= CONTAINING_RECORD(NextEntry
,
819 MEMORY_ALLOCATION_DESCRIPTOR
,
822 /* Align the base address and our limit */
823 AlignedBase
= (MdBlock
->BasePage
+ (Alignment
- 1)) &~ Alignment
;
824 AlignedLimit
= MdBlock
->PageCount
-
828 /* Check if this is a free block that can satisfy us */
829 if ((MdBlock
->MemoryType
== LoaderFree
) &&
830 (AlignedLimit
<= MdBlock
->PageCount
) &&
831 (PageCount
<= AlignedLimit
))
833 /* It is, stop searching */
834 ActiveMdBlock
= MdBlock
;
835 ActiveAlignedBase
= AlignedBase
;
839 /* Try the next block */
840 NextEntry
= NextEntry
->Flink
;
843 /* See if we came up with an adequate block */
846 /* Generate a descriptor in it */
847 *ReturnedBase
= AlignedBase
;
848 return KiRosBuildNtDescriptor(ActiveMdBlock
,
855 /* We found a matching block, generate a descriptor with it */
856 *ReturnedBase
= BasePage
;
857 return KiRosBuildNtDescriptor(MdBlock
, MemoryType
, BasePage
, PageCount
);
862 KiRosBuildArcMemoryList(VOID
)
864 PMEMORY_ALLOCATION_DESCRIPTOR Descriptor
;
865 MEMORY_DESCRIPTOR
*Memory
;
868 /* Loop all BIOS Memory Descriptors */
869 for (i
= 0; i
< NumberDescriptors
; i
++)
871 /* Get the current descriptor */
872 Memory
= &MDArray
[i
];
874 /* Allocate an NT Memory Descriptor */
875 Descriptor
= KiRosGetMdFromArray();
876 if (!Descriptor
) return ENOMEM
;
878 /* Copy the memory type */
879 Descriptor
->MemoryType
= Memory
->MemoryType
;
880 if (Memory
->MemoryType
== MemoryFreeContiguous
)
882 /* Convert this to free */
883 Descriptor
->MemoryType
= LoaderFree
;
885 else if (Memory
->MemoryType
== MemorySpecialMemory
)
887 /* Convert this to special memory */
888 Descriptor
->MemoryType
= LoaderSpecialMemory
;
891 /* Copy the range data */
892 Descriptor
->BasePage
= Memory
->BasePage
;
893 Descriptor
->PageCount
= Memory
->PageCount
;
895 /* Insert the descriptor */
896 if (Descriptor
->PageCount
) KiRosInsertNtDescriptor(Descriptor
);
900 return STATUS_SUCCESS
;
905 KiRosFixupComponentTree(IN PCONFIGURATION_COMPONENT_DATA p
,
908 PCONFIGURATION_COMPONENT pp
;
910 /* Loop each entry */
913 /* Grab the component entry */
914 pp
= &p
->ComponentEntry
;
916 /* Fixup the pointers */
917 if (pp
->Identifier
) pp
->Identifier
= (PVOID
)((ULONG_PTR
)pp
->Identifier
+ i
);
918 if (p
->ConfigurationData
) p
->ConfigurationData
= (PVOID
)((ULONG_PTR
)p
->ConfigurationData
+ i
);
919 if (p
->Parent
) p
->Parent
= (PVOID
)((ULONG_PTR
)p
->Parent
+ i
);
920 if (p
->Sibling
) p
->Sibling
= (PVOID
)((ULONG_PTR
)p
->Sibling
+ i
);
921 if (p
->Child
) p
->Child
= (PVOID
)((ULONG_PTR
)p
->Child
+ i
);
923 /* Check if we have a child */
924 if (p
->Child
) KiRosFixupComponentTree(p
->Child
, i
);
926 /* Get to the next entry */
933 KiRosFrldrLpbToNtLpb(IN PROS_LOADER_PARAMETER_BLOCK RosLoaderBlock
,
934 IN PLOADER_PARAMETER_BLOCK
*NtLoaderBlock
)
936 PLOADER_PARAMETER_BLOCK LoaderBlock
;
937 PLDR_DATA_TABLE_ENTRY LdrEntry
;
938 PLOADER_MODULE RosEntry
= NULL
;
942 PCHAR BootPath
, HalPath
;
943 CHAR CommandLine
[256];
944 PARC_DISK_SIGNATURE RosDiskInfo
, ArcDiskInfo
;
945 PIMAGE_NT_HEADERS NtHeader
;
946 WCHAR PathToDrivers
[] = L
"\\SystemRoot\\System32\\drivers\\";
947 WCHAR PathToSystem32
[] = L
"\\SystemRoot\\System32\\";
948 WCHAR PathSetup
[] = L
"\\SystemRoot\\";
949 CHAR DriverNameLow
[256];
952 ULONG KernelBase
= RosLoaderBlock
->ModsAddr
[0].ModStart
;
955 /* Set the NT Loader block and initialize it */
956 *NtLoaderBlock
= KeLoaderBlock
= LoaderBlock
= &BldrLoaderBlock
;
957 RtlZeroMemory(LoaderBlock
, sizeof(LOADER_PARAMETER_BLOCK
));
959 /* Set the NLS Data block */
960 LoaderBlock
->NlsData
= &BldrNlsDataBlock
;
962 /* Set the ARC Data block */
963 LoaderBlock
->ArcDiskInformation
= &BldrArcDiskInfo
;
965 /* Assume this is from FreeLDR's SetupLdr */
966 LoaderBlock
->SetupLdrBlock
= &BldrSetupBlock
;
968 /* Setup the list heads */
969 InitializeListHead(&LoaderBlock
->LoadOrderListHead
);
970 InitializeListHead(&LoaderBlock
->MemoryDescriptorListHead
);
971 InitializeListHead(&LoaderBlock
->BootDriverListHead
);
972 InitializeListHead(&LoaderBlock
->ArcDiskInformation
->DiskSignatureListHead
);
974 /* Build the free memory map, which uses BIOS Descriptors */
975 KiRosBuildBiosMemoryMap();
977 /* Build entries for ReactOS memory ranges, which uses ARC Descriptors */
978 KiRosBuildOsMemoryMap();
980 #if defined(_X86_) || defined(_M_AMD64)
981 /* Build entries for the reserved map, which uses ARC Descriptors */
982 KiRosBuildReservedMemoryMap();
985 /* Now convert the BIOS and ARC Descriptors into NT Memory Descirptors */
986 KiRosBuildArcMemoryList();
988 /* Loop boot driver list */
989 for (i
= 0; i
< RosLoaderBlock
->ModsCount
; i
++)
991 /* Get the ROS loader entry */
992 RosEntry
= &RosLoaderBlock
->ModsAddr
[i
];
993 DriverName
= (PCHAR
)RosEntry
->String
;
994 ModStart
= (PVOID
)RosEntry
->ModStart
;
995 ModSize
= RosEntry
->ModEnd
- (ULONG_PTR
)ModStart
;
998 ModStart
-= KernelBase
;
1001 /* Check if this is any of the NLS files */
1002 if (!_stricmp(DriverName
, "ansi.nls"))
1004 /* ANSI Code page */
1005 LoaderBlock
->NlsData
->AnsiCodePageData
= KERNEL_RVA(ModStart
);
1007 /* Create an MD for it */
1008 KiRosAllocateNtDescriptor(LoaderNlsData
,
1009 KERNEL_DESCRIPTOR_PAGE(ModStart
),
1010 (ModSize
+ PAGE_SIZE
- 1)>> PAGE_SHIFT
,
1015 else if (!_stricmp(DriverName
, "oem.nls"))
1018 LoaderBlock
->NlsData
->OemCodePageData
= KERNEL_RVA(ModStart
);
1020 /* Create an MD for it */
1021 KiRosAllocateNtDescriptor(LoaderNlsData
,
1022 KERNEL_DESCRIPTOR_PAGE(ModStart
),
1023 (ModSize
+ PAGE_SIZE
- 1)>> PAGE_SHIFT
,
1028 else if (!_stricmp(DriverName
, "casemap.nls"))
1030 /* Unicode Code page */
1031 LoaderBlock
->NlsData
->UnicodeCodePageData
= KERNEL_RVA(ModStart
);
1033 /* Create an MD for it */
1034 KiRosAllocateNtDescriptor(LoaderNlsData
,
1035 KERNEL_DESCRIPTOR_PAGE(ModStart
),
1036 (ModSize
+ PAGE_SIZE
- 1)>> PAGE_SHIFT
,
1042 /* Check if this is the SYSTEM hive */
1043 if (!(_stricmp(DriverName
, "system")) ||
1044 !(_stricmp(DriverName
, "system.hiv")))
1046 /* Save registry data */
1047 LoaderBlock
->RegistryBase
= KERNEL_RVA(ModStart
);
1048 LoaderBlock
->RegistryLength
= ModSize
;
1050 /* Disable setup mode */
1051 LoaderBlock
->SetupLdrBlock
= NULL
;
1053 /* Create an MD for it */
1054 KiRosAllocateNtDescriptor(LoaderRegistryData
,
1055 KERNEL_DESCRIPTOR_PAGE(ModStart
),
1056 (ModSize
+ PAGE_SIZE
- 1)>> PAGE_SHIFT
,
1062 /* Check if this is the HARDWARE hive */
1063 if (!(_stricmp(DriverName
, "hardware")) ||
1064 !(_stricmp(DriverName
, "hardware.hiv")))
1066 /* Create an MD for it */
1067 KiRosAllocateNtDescriptor(LoaderRegistryData
,
1068 KERNEL_DESCRIPTOR_PAGE(ModStart
),
1069 (ModSize
+ PAGE_SIZE
- 1)>> PAGE_SHIFT
,
1075 /* Check if this is the kernel */
1076 if (!(_stricmp(DriverName
, "ntoskrnl.exe")))
1078 /* Create an MD for it */
1079 KiRosAllocateNtDescriptor(LoaderSystemCode
,
1080 KERNEL_DESCRIPTOR_PAGE(ModStart
),
1081 (ModSize
+ PAGE_SIZE
- 1)>> PAGE_SHIFT
,
1085 else if (!(_stricmp(DriverName
, "hal.dll")))
1087 /* Create an MD for the HAL */
1088 KiRosAllocateNtDescriptor(LoaderHalCode
,
1089 KERNEL_DESCRIPTOR_PAGE(ModStart
),
1090 (ModSize
+ PAGE_SIZE
- 1)>> PAGE_SHIFT
,
1096 /* Create an MD for any driver */
1097 KiRosAllocateNtDescriptor(LoaderBootDriver
,
1098 KERNEL_DESCRIPTOR_PAGE(ModStart
),
1099 (ModSize
+ PAGE_SIZE
- 1)>> PAGE_SHIFT
,
1105 ModStart
+= 0x80800000;
1108 /* Lowercase the drivername so we can check its extension later */
1109 strcpy(DriverNameLow
, DriverName
);
1110 _strlwr(DriverNameLow
);
1112 /* Setup the loader entry */
1113 LdrEntry
= &BldrModules
[i
];
1114 RtlZeroMemory(LdrEntry
, sizeof(LDR_DATA_TABLE_ENTRY
));
1116 /* Convert driver name from ANSI to Unicode */
1117 for (j
= 0; j
< strlen(DriverName
); j
++)
1119 BldrModuleStrings
[i
][j
] = DriverName
[j
];
1122 /* Setup driver name */
1123 RtlInitUnicodeString(&LdrEntry
->BaseDllName
, BldrModuleStrings
[i
]);
1125 /* Construct a correct full name */
1126 BldrModuleStringsFull
[i
][0] = 0;
1127 LdrEntry
->FullDllName
.MaximumLength
= 260 * sizeof(WCHAR
);
1128 LdrEntry
->FullDllName
.Length
= 0;
1129 LdrEntry
->FullDllName
.Buffer
= BldrModuleStringsFull
[i
];
1131 /* Guess the path */
1132 if (LoaderBlock
->SetupLdrBlock
)
1134 UNICODE_STRING TempString
;
1135 RtlInitUnicodeString(&TempString
, PathSetup
);
1136 RtlAppendUnicodeStringToString(&LdrEntry
->FullDllName
, &TempString
);
1138 else if (strstr(DriverNameLow
, ".dll") || strstr(DriverNameLow
, ".exe"))
1140 UNICODE_STRING TempString
;
1141 RtlInitUnicodeString(&TempString
, PathToSystem32
);
1142 RtlAppendUnicodeStringToString(&LdrEntry
->FullDllName
, &TempString
);
1146 UNICODE_STRING TempString
;
1147 RtlInitUnicodeString(&TempString
, PathToDrivers
);
1148 RtlAppendUnicodeStringToString(&LdrEntry
->FullDllName
, &TempString
);
1151 /* Append base name of the driver */
1152 RtlAppendUnicodeStringToString(&LdrEntry
->FullDllName
, &LdrEntry
->BaseDllName
);
1154 /* Copy data from Freeldr Module Entry */
1155 LdrEntry
->DllBase
= ModStart
;
1156 LdrEntry
->SizeOfImage
= ModSize
;
1158 /* Copy additional data */
1159 NtHeader
= RtlImageNtHeader(ModStart
);
1160 LdrEntry
->EntryPoint
= RVA(ModStart
,
1162 OptionalHeader
.AddressOfEntryPoint
);
1164 /* Initialize other data */
1165 LdrEntry
->LoadCount
= 1;
1166 LdrEntry
->Flags
= LDRP_IMAGE_DLL
|
1167 LDRP_ENTRY_PROCESSED
;
1168 if (RosEntry
->Reserved
) LdrEntry
->Flags
|= LDRP_ENTRY_INSERTED
;
1170 /* Check if this is HAL */
1171 if (!(_stricmp(DriverName
, "hal.dll")))
1173 /* Check if there is a second entry already */
1174 if (LoaderBlock
->LoadOrderListHead
.Flink
->Flink
!=
1175 &LoaderBlock
->LoadOrderListHead
)
1177 PLIST_ENTRY OldSecondEntry
;
1179 /* Get the second entry */
1181 LoaderBlock
->LoadOrderListHead
.Flink
->Flink
;
1183 /* Set up our entry correctly */
1184 LdrEntry
->InLoadOrderLinks
.Flink
= OldSecondEntry
;
1185 LdrEntry
->InLoadOrderLinks
.Blink
= OldSecondEntry
->Blink
;
1187 /* Make the first entry (always the kernel) point to us */
1188 LoaderBlock
->LoadOrderListHead
.Flink
->Flink
=
1189 &LdrEntry
->InLoadOrderLinks
;
1191 /* Make the old entry point back to us and continue looping */
1192 OldSecondEntry
->Blink
= &LdrEntry
->InLoadOrderLinks
;
1197 /* Insert it into the loader block */
1198 InsertTailList(&LoaderBlock
->LoadOrderListHead
,
1199 &LdrEntry
->InLoadOrderLinks
);
1202 /* Now mark the remainder of the FreeLDR 6MB area as "in use" */
1203 KiRosAllocateNtDescriptor(LoaderMemoryData
,
1204 KERNEL_DESCRIPTOR_PAGE(RosEntry
->ModEnd
),
1205 KERNEL_DESCRIPTOR_PAGE((RosLoaderBlock
->KernelBase
+ 0x600000)) -
1206 KERNEL_DESCRIPTOR_PAGE(RosEntry
->ModEnd
),
1211 // Check if we have a ramdisk
1213 if ((RosLoaderBlock
->RdAddr
) && (RosLoaderBlock
->RdLength
))
1216 // Build a descriptor for it
1218 KiRosAllocateNtDescriptor(LoaderXIPRom
,
1219 KERNEL_DESCRIPTOR_PAGE(RosLoaderBlock
->RdAddr
),
1220 (RosLoaderBlock
->RdLength
+ PAGE_SIZE
- 1) >> PAGE_SHIFT
,
1225 /* Setup command line */
1226 LoaderBlock
->LoadOptions
= BldrCommandLine
;
1227 strcpy(BldrCommandLine
, RosLoaderBlock
->CommandLine
);
1229 /* Setup the extension block */
1230 LoaderBlock
->Extension
= &BldrExtensionBlock
;
1231 LoaderBlock
->Extension
->Size
= sizeof(LOADER_PARAMETER_EXTENSION
);
1232 LoaderBlock
->Extension
->MajorVersion
= 5;
1233 LoaderBlock
->Extension
->MinorVersion
= 2;
1236 // FIXME FIXME FIXME NOW!!!!
1238 /* FreeLDR hackllocates 1536 static pages for the initial boot images */
1239 LoaderBlock
->Extension
->LoaderPagesSpanned
= 1536 * PAGE_SIZE
;
1241 /* ReactOS always boots the kernel at 0x80800000 (just like NT 5.2) */
1242 LoaderBlock
->Extension
->LoaderPagesSpanned
+= 0x80800000 - KSEG0_BASE
;
1244 /* Now convert to pages */
1245 LoaderBlock
->Extension
->LoaderPagesSpanned
/= PAGE_SIZE
;
1247 /* Check if FreeLdr detected a ACPI table */
1248 if (RosLoaderBlock
->Flags
& MB_FLAGS_ACPI_TABLE
)
1250 /* Set the pointer to something for compatibility */
1251 LoaderBlock
->Extension
->AcpiTable
= (PVOID
)1;
1254 /* Now setup the setup block if we have one */
1255 if (LoaderBlock
->SetupLdrBlock
)
1257 /* All we'll setup right now is the flag for text-mode setup */
1258 LoaderBlock
->SetupLdrBlock
->Flags
= SETUPLDR_TEXT_MODE
;
1261 /* Make a copy of the command line */
1262 strcpy(CommandLine
, LoaderBlock
->LoadOptions
);
1264 /* Find the first \, separating the ARC path from NT path */
1265 BootPath
= strchr(CommandLine
, '\\');
1266 *BootPath
= ANSI_NULL
;
1267 strncpy(BldrArcBootPath
, CommandLine
, 63);
1268 LoaderBlock
->ArcBootDeviceName
= BldrArcBootPath
;
1270 /* The rest of the string is the NT path */
1271 HalPath
= strchr(BootPath
+ 1, ' ');
1272 *HalPath
= ANSI_NULL
;
1273 BldrNtBootPath
[0] = '\\';
1274 strncat(BldrNtBootPath
, BootPath
+ 1, 63);
1275 strcat(BldrNtBootPath
,"\\");
1276 LoaderBlock
->NtBootPathName
= BldrNtBootPath
;
1278 /* Set the HAL paths */
1279 strncpy(BldrArcHalPath
, BldrArcBootPath
, 63);
1280 LoaderBlock
->ArcHalDeviceName
= BldrArcHalPath
;
1281 strcpy(BldrNtHalPath
, "\\");
1282 LoaderBlock
->NtHalPathName
= BldrNtHalPath
;
1284 /* Use this new command line */
1285 strncpy(LoaderBlock
->LoadOptions
, HalPath
+ 2, 255);
1287 /* Parse it and change every slash to a space */
1288 BootPath
= LoaderBlock
->LoadOptions
;
1289 do {if (*BootPath
== '/') *BootPath
= ' ';} while (*BootPath
++);
1291 /* Now let's loop ARC disk information */
1292 for (i
= 0; i
< RosLoaderBlock
->DrivesCount
; i
++)
1294 /* Get the ROS loader entry */
1295 RosDiskInfo
= &RosLoaderBlock
->DrivesAddr
[i
];
1297 /* Get the ARC structure */
1298 ArcDiskInfo
= &BldrDiskInfo
[i
];
1300 /* Copy the data over */
1301 ArcDiskInfo
->Signature
= RosDiskInfo
->Signature
;
1302 ArcDiskInfo
->CheckSum
= RosDiskInfo
->CheckSum
;
1304 /* Copy the ARC Name */
1305 strcpy(BldrArcNames
[i
], RosDiskInfo
->ArcName
);
1306 ArcDiskInfo
->ArcName
= BldrArcNames
[i
];
1308 /* Insert into the list */
1309 InsertTailList(&LoaderBlock
->ArcDiskInformation
->DiskSignatureListHead
,
1310 &ArcDiskInfo
->ListEntry
);
1313 /* Copy the ARC Hardware Tree */
1314 RtlCopyMemory(BldrArcHwBuffer
, (PVOID
)RosLoaderBlock
->ArchExtra
, 16 * 1024);
1315 LoaderBlock
->ConfigurationRoot
= (PVOID
)BldrArcHwBuffer
;
1318 KiRosFixupComponentTree(LoaderBlock
->ConfigurationRoot
,
1319 (ULONG_PTR
)BldrArcHwBuffer
-
1320 RosLoaderBlock
->ArchExtra
);
1325 KiSetupSyscallHandler();
1329 KiRosPrepareForSystemStartup(IN PROS_LOADER_PARAMETER_BLOCK LoaderBlock
)
1331 PLOADER_PARAMETER_BLOCK NtLoaderBlock
;
1332 ULONG size
, i
= 0, *ent
;
1335 PKGDTENTRY TssEntry
;
1336 KDESCRIPTOR IdtDescriptor
;
1338 __sidt(&IdtDescriptor
.Limit
);
1339 RtlCopyMemory(KiBootIdt
, (PVOID
)IdtDescriptor
.Base
, IdtDescriptor
.Limit
+ 1);
1340 IdtDescriptor
.Base
= (ULONG
)&KiBootIdt
;
1341 IdtDescriptor
.Limit
= sizeof(KiBootIdt
) - 1;
1343 /* Load the GDT and IDT */
1344 Ke386SetGlobalDescriptorTable(&KiGdtDescriptor
.Limit
);
1345 __lidt(&IdtDescriptor
.Limit
);
1347 /* Initialize the boot TSS */
1349 TssEntry
= &KiBootGdt
[KGDT_TSS
/ sizeof(KGDTENTRY
)];
1350 TssEntry
->HighWord
.Bits
.Type
= I386_TSS
;
1351 TssEntry
->HighWord
.Bits
.Pres
= 1;
1352 TssEntry
->HighWord
.Bits
.Dpl
= 0;
1353 TssEntry
->BaseLow
= (USHORT
)((ULONG_PTR
)Tss
& 0xFFFF);
1354 TssEntry
->HighWord
.Bytes
.BaseMid
= (UCHAR
)((ULONG_PTR
)Tss
>> 16);
1355 TssEntry
->HighWord
.Bytes
.BaseHi
= (UCHAR
)((ULONG_PTR
)Tss
>> 24);
1357 /* Set the TSS selector */
1358 Ke386SetTr(KGDT_TSS
);
1362 // Zero bats. We might have residual bats set that will interfere with
1363 // our mapping of ofwldr.
1364 for (i
= 0; i
< 4; i
++)
1366 SetBat(i
, 0, 0, 0); SetBat(i
, 1, 0, 0);
1368 KiSetupSyscallHandler();
1369 DbgPrint("Kernel Power (%08x)\n", LoaderBlock
);
1370 DbgPrint("ArchExtra (%08x)!\n", LoaderBlock
->ArchExtra
);
1373 /* Save pointer to ROS Block */
1374 KeRosLoaderBlock
= LoaderBlock
;
1376 /* Get debugging function */
1377 FrLdrDbgPrint
= LoaderBlock
->FrLdrDbgPrint
;
1379 /* Save memory manager data */
1380 KeMemoryMapRangeCount
= 0;
1381 if (LoaderBlock
->Flags
& MB_FLAGS_MMAP_INFO
)
1383 /* We have a memory map from the nice BIOS */
1384 ent
= ((PULONG
)(LoaderBlock
->MmapAddr
- sizeof(ULONG
))); // FIXME: this is ugly
1388 /* Map it until we run out of size */
1389 while (i
< LoaderBlock
->MmapLength
)
1391 /* Copy into the Kernel Memory Map */
1392 memcpy (&KeMemoryMap
[KeMemoryMapRangeCount
],
1393 (PVOID
)(LoaderBlock
->MmapAddr
+ i
),
1394 sizeof(ADDRESS_RANGE
));
1396 /* Increase Memory Map Count */
1397 KeMemoryMapRangeCount
++;
1404 LoaderBlock
->MmapLength
= KeMemoryMapRangeCount
* sizeof(ADDRESS_RANGE
);
1405 LoaderBlock
->MmapAddr
= (ULONG_PTR
)KeMemoryMap
;
1409 /* Nothing from BIOS */
1410 LoaderBlock
->MmapLength
= 0;
1411 LoaderBlock
->MmapAddr
= (ULONG_PTR
)KeMemoryMap
;
1414 /* Convert the loader block */
1415 KiRosFrldrLpbToNtLpb(KeRosLoaderBlock
, &NtLoaderBlock
);
1418 DbgPrint("Finished KiRosFrldrLpbToNtLpb\n");
1421 /* Do general System Startup */
1422 KiSystemStartup(NtLoaderBlock
);