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