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