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