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