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