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