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