[NTOSKRNL]
[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 #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 size_t Remaining;
951 WCHAR *StringEnd;
952 #if defined(_PPC_)
953 ULONG KernelBase = RosLoaderBlock->ModsAddr[0].ModStart;
954 #endif
955
956 /* Set the NT Loader block and initialize it */
957 *NtLoaderBlock = KeLoaderBlock = LoaderBlock = &BldrLoaderBlock;
958 RtlZeroMemory(LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK));
959
960 /* Set the NLS Data block */
961 LoaderBlock->NlsData = &BldrNlsDataBlock;
962
963 /* Set the ARC Data block */
964 LoaderBlock->ArcDiskInformation = &BldrArcDiskInfo;
965
966 /* Assume this is from FreeLDR's SetupLdr */
967 LoaderBlock->SetupLdrBlock = &BldrSetupBlock;
968
969 /* Setup the list heads */
970 InitializeListHead(&LoaderBlock->LoadOrderListHead);
971 InitializeListHead(&LoaderBlock->MemoryDescriptorListHead);
972 InitializeListHead(&LoaderBlock->BootDriverListHead);
973 InitializeListHead(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead);
974
975 /* Build the free memory map, which uses BIOS Descriptors */
976 KiRosBuildBiosMemoryMap();
977
978 /* Build entries for ReactOS memory ranges, which uses ARC Descriptors */
979 KiRosBuildOsMemoryMap();
980
981 #if defined(_X86_)
982 /* Build entries for the reserved map, which uses ARC Descriptors */
983 KiRosBuildReservedMemoryMap();
984 #endif
985
986 /* Now convert the BIOS and ARC Descriptors into NT Memory Descirptors */
987 KiRosBuildArcMemoryList();
988
989 /* Loop boot driver list */
990 for (i = 0; i < RosLoaderBlock->ModsCount; i++)
991 {
992 /* Get the ROS loader entry */
993 RosEntry = &RosLoaderBlock->ModsAddr[i];
994 DriverName = (PCHAR)RosEntry->String;
995 ModStart = (PVOID)RosEntry->ModStart;
996 ModSize = RosEntry->ModEnd - (ULONG_PTR)ModStart;
997
998 #if defined(_PPC_)
999 ModStart -= KernelBase;
1000 #endif
1001
1002 /* Check if this is any of the NLS files */
1003 if (!_stricmp(DriverName, "ansi.nls"))
1004 {
1005 /* ANSI Code page */
1006 LoaderBlock->NlsData->AnsiCodePageData = KERNEL_RVA(ModStart);
1007
1008 /* Create an MD for it */
1009 KiRosAllocateNtDescriptor(LoaderNlsData,
1010 KERNEL_DESCRIPTOR_PAGE(ModStart),
1011 (ModSize + PAGE_SIZE - 1)>> PAGE_SHIFT,
1012 0,
1013 &Base);
1014 continue;
1015 }
1016 else if (!_stricmp(DriverName, "oem.nls"))
1017 {
1018 /* OEM Code page */
1019 LoaderBlock->NlsData->OemCodePageData = KERNEL_RVA(ModStart);
1020
1021 /* Create an MD for it */
1022 KiRosAllocateNtDescriptor(LoaderNlsData,
1023 KERNEL_DESCRIPTOR_PAGE(ModStart),
1024 (ModSize + PAGE_SIZE - 1)>> PAGE_SHIFT,
1025 0,
1026 &Base);
1027 continue;
1028 }
1029 else if (!_stricmp(DriverName, "casemap.nls"))
1030 {
1031 /* Unicode Code page */
1032 LoaderBlock->NlsData->UnicodeCodePageData = KERNEL_RVA(ModStart);
1033
1034 /* Create an MD for it */
1035 KiRosAllocateNtDescriptor(LoaderNlsData,
1036 KERNEL_DESCRIPTOR_PAGE(ModStart),
1037 (ModSize + PAGE_SIZE - 1)>> PAGE_SHIFT,
1038 0,
1039 &Base);
1040 continue;
1041 }
1042
1043 /* Check if this is the SYSTEM hive */
1044 if (!(_stricmp(DriverName, "system")) ||
1045 !(_stricmp(DriverName, "system.hiv")))
1046 {
1047 /* Save registry data */
1048 LoaderBlock->RegistryBase = KERNEL_RVA(ModStart);
1049 LoaderBlock->RegistryLength = ModSize;
1050
1051 /* Disable setup mode */
1052 LoaderBlock->SetupLdrBlock = NULL;
1053
1054 /* Create an MD for it */
1055 KiRosAllocateNtDescriptor(LoaderRegistryData,
1056 KERNEL_DESCRIPTOR_PAGE(ModStart),
1057 (ModSize + PAGE_SIZE - 1)>> PAGE_SHIFT,
1058 0,
1059 &Base);
1060 continue;
1061 }
1062
1063 /* Check if this is the HARDWARE hive */
1064 if (!(_stricmp(DriverName, "hardware")) ||
1065 !(_stricmp(DriverName, "hardware.hiv")))
1066 {
1067 /* Create an MD for it */
1068 KiRosAllocateNtDescriptor(LoaderRegistryData,
1069 KERNEL_DESCRIPTOR_PAGE(ModStart),
1070 (ModSize + PAGE_SIZE - 1)>> PAGE_SHIFT,
1071 0,
1072 &Base);
1073 continue;
1074 }
1075
1076 /* Check if this is the kernel */
1077 if (!(_stricmp(DriverName, "ntoskrnl.exe")))
1078 {
1079 /* Create an MD for it */
1080 KiRosAllocateNtDescriptor(LoaderSystemCode,
1081 KERNEL_DESCRIPTOR_PAGE(ModStart),
1082 (ModSize + PAGE_SIZE - 1)>> PAGE_SHIFT,
1083 0,
1084 &Base);
1085 }
1086 else if (!(_stricmp(DriverName, "hal.dll")))
1087 {
1088 /* Create an MD for the HAL */
1089 KiRosAllocateNtDescriptor(LoaderHalCode,
1090 KERNEL_DESCRIPTOR_PAGE(ModStart),
1091 (ModSize + PAGE_SIZE - 1)>> PAGE_SHIFT,
1092 0,
1093 &Base);
1094 }
1095 else
1096 {
1097 /* Create an MD for any driver */
1098 KiRosAllocateNtDescriptor(LoaderBootDriver,
1099 KERNEL_DESCRIPTOR_PAGE(ModStart),
1100 (ModSize + PAGE_SIZE - 1)>> PAGE_SHIFT,
1101 0,
1102 &Base);
1103 }
1104
1105 #if defined(_PPC_)
1106 ModStart += 0x80800000;
1107 #endif
1108
1109 /* Lowercase the drivername so we can check its extension later */
1110 strcpy(DriverNameLow, DriverName);
1111 _strlwr(DriverNameLow);
1112
1113 /* Setup the loader entry */
1114 LdrEntry = &BldrModules[i];
1115 RtlZeroMemory(LdrEntry, sizeof(LDR_DATA_TABLE_ENTRY));
1116
1117 /* Convert driver name from ANSI to Unicode */
1118 for (j = 0; j < strlen(DriverName); j++)
1119 {
1120 BldrModuleStrings[i][j] = DriverName[j];
1121 }
1122
1123 /* Setup driver name */
1124 RtlInitUnicodeString(&LdrEntry->BaseDllName, BldrModuleStrings[i]);
1125
1126 /* Construct a correct full name */
1127 BldrModuleStringsFull[i][0] = 0;
1128 LdrEntry->FullDllName.MaximumLength = sizeof(BldrModuleStringsFull[i]);
1129 LdrEntry->FullDllName.Length = 0;
1130 LdrEntry->FullDllName.Buffer = BldrModuleStringsFull[i];
1131
1132 /* Guess the path */
1133 if (LoaderBlock->SetupLdrBlock)
1134 {
1135 UNICODE_STRING TempString;
1136 RtlInitUnicodeString(&TempString, PathSetup);
1137 RtlAppendUnicodeStringToString(&LdrEntry->FullDllName, &TempString);
1138 }
1139 else if (strstr(DriverNameLow, ".dll") || strstr(DriverNameLow, ".exe"))
1140 {
1141 UNICODE_STRING TempString;
1142 RtlInitUnicodeString(&TempString, PathToSystem32);
1143 RtlAppendUnicodeStringToString(&LdrEntry->FullDllName, &TempString);
1144 }
1145 else /* .sys */
1146 {
1147 UNICODE_STRING TempString;
1148 RtlInitUnicodeString(&TempString, PathToDrivers);
1149 RtlAppendUnicodeStringToString(&LdrEntry->FullDllName, &TempString);
1150 }
1151
1152 /* Append base name of the driver */
1153 RtlAppendUnicodeStringToString(&LdrEntry->FullDllName, &LdrEntry->BaseDllName);
1154
1155 /* Copy data from Freeldr Module Entry */
1156 LdrEntry->DllBase = ModStart;
1157 LdrEntry->SizeOfImage = ModSize;
1158
1159 /* Copy additional data */
1160 NtHeader = RtlImageNtHeader(ModStart);
1161 LdrEntry->EntryPoint = RVA(ModStart,
1162 NtHeader->
1163 OptionalHeader.AddressOfEntryPoint);
1164
1165 /* Initialize other data */
1166 LdrEntry->LoadCount = 1;
1167 LdrEntry->Flags = LDRP_IMAGE_DLL |
1168 LDRP_ENTRY_PROCESSED;
1169 if (RosEntry->Reserved) LdrEntry->Flags |= LDRP_ENTRY_INSERTED;
1170
1171 /* Check if this is HAL */
1172 if (!(_stricmp(DriverName, "hal.dll")))
1173 {
1174 /* Check if there is a second entry already */
1175 if (LoaderBlock->LoadOrderListHead.Flink->Flink !=
1176 &LoaderBlock->LoadOrderListHead)
1177 {
1178 PLIST_ENTRY OldSecondEntry;
1179
1180 /* Get the second entry */
1181 OldSecondEntry =
1182 LoaderBlock->LoadOrderListHead.Flink->Flink;
1183
1184 /* Set up our entry correctly */
1185 LdrEntry->InLoadOrderLinks.Flink = OldSecondEntry;
1186 LdrEntry->InLoadOrderLinks.Blink = OldSecondEntry->Blink;
1187
1188 /* Make the first entry (always the kernel) point to us */
1189 LoaderBlock->LoadOrderListHead.Flink->Flink =
1190 &LdrEntry->InLoadOrderLinks;
1191
1192 /* Make the old entry point back to us and continue looping */
1193 OldSecondEntry->Blink = &LdrEntry->InLoadOrderLinks;
1194 continue;
1195 }
1196 }
1197
1198 /* Insert it into the loader block */
1199 InsertTailList(&LoaderBlock->LoadOrderListHead,
1200 &LdrEntry->InLoadOrderLinks);
1201 }
1202
1203 /* Now mark the remainder of the FreeLDR 6MB area as "in use" */
1204 KiRosAllocateNtDescriptor(LoaderMemoryData,
1205 KERNEL_DESCRIPTOR_PAGE(RosEntry->ModEnd),
1206 KERNEL_DESCRIPTOR_PAGE((0x80800000 + 0x600000)) -
1207 KERNEL_DESCRIPTOR_PAGE(RosEntry->ModEnd),
1208 0,
1209 &Base);
1210
1211 /* Check if we have a ramdisk */
1212 if ((RosLoaderBlock->RdAddr) && (RosLoaderBlock->RdLength))
1213 {
1214 /* Build a descriptor for it */
1215 KiRosAllocateNtDescriptor(LoaderXIPRom,
1216 KERNEL_DESCRIPTOR_PAGE(RosLoaderBlock->RdAddr),
1217 (RosLoaderBlock->RdLength + PAGE_SIZE - 1) >> PAGE_SHIFT,
1218 0,
1219 &Base);
1220 }
1221
1222 /* Setup command line */
1223 LoaderBlock->LoadOptions = BldrCommandLine;
1224 strcpy(BldrCommandLine, RosLoaderBlock->CommandLine);
1225
1226 /* Setup the extension block */
1227 LoaderBlock->Extension = &BldrExtensionBlock;
1228 LoaderBlock->Extension->Size = sizeof(LOADER_PARAMETER_EXTENSION);
1229 LoaderBlock->Extension->MajorVersion = 5;
1230 LoaderBlock->Extension->MinorVersion = 2;
1231
1232 /* FreeLDR hackllocates 1536 static pages for the initial boot images */
1233 LoaderBlock->Extension->LoaderPagesSpanned = 1536 * PAGE_SIZE;
1234
1235 /* ReactOS always boots the kernel at 0x80800000 (just like NT 5.2) */
1236 LoaderBlock->Extension->LoaderPagesSpanned += 0x80800000 - KSEG0_BASE;
1237
1238 /* Now convert to pages */
1239 LoaderBlock->Extension->LoaderPagesSpanned /= PAGE_SIZE;
1240
1241 /* Check if FreeLdr detected a ACPI table */
1242 if (RosLoaderBlock->Flags & MB_FLAGS_ACPI_TABLE)
1243 {
1244 /* Set the pointer to something for compatibility */
1245 LoaderBlock->Extension->AcpiTable = (PVOID)1;
1246 }
1247
1248 /* Now setup the setup block if we have one */
1249 if (LoaderBlock->SetupLdrBlock)
1250 {
1251 /* All we'll setup right now is the flag for text-mode setup */
1252 LoaderBlock->SetupLdrBlock->Flags = SETUPLDR_TEXT_MODE;
1253 }
1254
1255 /* Make a copy of the command line */
1256 strcpy(CommandLine, LoaderBlock->LoadOptions);
1257
1258 /* Find the first \, separating the ARC path from NT path */
1259 BootPath = strchr(CommandLine, '\\');
1260 *BootPath = ANSI_NULL;
1261 RtlStringCbCopyA(BldrArcBootPath, sizeof(BldrArcBootPath), CommandLine);
1262 LoaderBlock->ArcBootDeviceName = BldrArcBootPath;
1263
1264 /* The rest of the string is the NT path */
1265 HalPath = strchr(BootPath + 1, ' ');
1266 *HalPath = ANSI_NULL;
1267 Remaining = sizeof(BldrNtBootPath);
1268 RtlStringCbCopyExA(BldrNtBootPath, Remaining, "\\", &StringEnd, &Remaining, 0);
1269 RtlStringCbCopyExA(StringEnd, Remaining, BootPath + 1, &StringEnd, &Remaining, 0);
1270 RtlStringCbCopyA(StringEnd, Remaining, "\\");
1271 LoaderBlock->NtBootPathName = BldrNtBootPath;
1272
1273 /* Set the HAL paths */
1274 RtlStringCbCopyA(BldrArcHalPath, sizeof(BldrArcHalPath), BldrArcBootPath);
1275 LoaderBlock->ArcHalDeviceName = BldrArcHalPath;
1276 strcpy(BldrNtHalPath, "\\");
1277 LoaderBlock->NtHalPathName = BldrNtHalPath;
1278
1279 /* Use this new command line */
1280 RtlStringCbCopyA(LoaderBlock->LoadOptions, 255, HalPath + 2);
1281
1282 /* Parse it and change every slash to a space */
1283 BootPath = LoaderBlock->LoadOptions;
1284 do {if (*BootPath == '/') *BootPath = ' ';} while (*BootPath++);
1285
1286 /* Now let's loop ARC disk information */
1287 for (i = 0; i < RosLoaderBlock->DrivesCount; i++)
1288 {
1289 /* Get the ROS loader entry */
1290 RosDiskInfo = &RosLoaderBlock->DrivesAddr[i];
1291
1292 /* Get the ARC structure */
1293 ArcDiskInfo = &BldrDiskInfo[i];
1294
1295 /* Copy the data over */
1296 ArcDiskInfo->Signature = RosDiskInfo->Signature;
1297 ArcDiskInfo->CheckSum = RosDiskInfo->CheckSum;
1298
1299 /* Copy the ARC Name */
1300 strcpy(BldrArcNames[i], RosDiskInfo->ArcName);
1301 ArcDiskInfo->ArcName = BldrArcNames[i];
1302
1303 /* Insert into the list */
1304 InsertTailList(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead,
1305 &ArcDiskInfo->ListEntry);
1306 }
1307
1308 /* Copy the ARC Hardware Tree */
1309 RtlCopyMemory(BldrArcHwBuffer, (PVOID)RosLoaderBlock->ArchExtra, 16 * 1024);
1310 LoaderBlock->ConfigurationRoot = (PVOID)BldrArcHwBuffer;
1311
1312 /* Apply fixups */
1313 KiRosFixupComponentTree(LoaderBlock->ConfigurationRoot,
1314 (ULONG_PTR)BldrArcHwBuffer -
1315 RosLoaderBlock->ArchExtra);
1316 }
1317
1318 VOID
1319 NTAPI
1320 KiSetupSyscallHandler();
1321
1322 VOID
1323 NTAPI
1324 KiRosPrepareForSystemStartup(IN PROS_LOADER_PARAMETER_BLOCK LoaderBlock)
1325 {
1326 PLOADER_PARAMETER_BLOCK NtLoaderBlock;
1327 ULONG size, i = 0, *ent;
1328 #if defined(_X86_)
1329 PKTSS Tss;
1330 PKGDTENTRY TssEntry;
1331 KDESCRIPTOR IdtDescriptor;
1332
1333 __sidt(&IdtDescriptor.Limit);
1334 RtlCopyMemory(KiBootIdt, (PVOID)IdtDescriptor.Base, IdtDescriptor.Limit + 1);
1335 IdtDescriptor.Base = (ULONG)&KiBootIdt;
1336 IdtDescriptor.Limit = sizeof(KiBootIdt) - 1;
1337
1338 /* Load the GDT and IDT */
1339 Ke386SetGlobalDescriptorTable(&KiGdtDescriptor.Limit);
1340 __lidt(&IdtDescriptor.Limit);
1341
1342 /* Initialize the boot TSS */
1343 Tss = &KiBootTss;
1344 TssEntry = &KiBootGdt[KGDT_TSS / sizeof(KGDTENTRY)];
1345 TssEntry->HighWord.Bits.Type = I386_TSS;
1346 TssEntry->HighWord.Bits.Pres = 1;
1347 TssEntry->HighWord.Bits.Dpl = 0;
1348 TssEntry->BaseLow = (USHORT)((ULONG_PTR)Tss & 0xFFFF);
1349 TssEntry->HighWord.Bytes.BaseMid = (UCHAR)((ULONG_PTR)Tss >> 16);
1350 TssEntry->HighWord.Bytes.BaseHi = (UCHAR)((ULONG_PTR)Tss >> 24);
1351
1352 /* Set the TSS selector */
1353 Ke386SetTr(KGDT_TSS);
1354 #endif
1355
1356 #if defined(_M_PPC)
1357 // Zero bats. We might have residual bats set that will interfere with
1358 // our mapping of ofwldr.
1359 for (i = 0; i < 4; i++)
1360 {
1361 SetBat(i, 0, 0, 0); SetBat(i, 1, 0, 0);
1362 }
1363 KiSetupSyscallHandler();
1364 DbgPrint("Kernel Power (%08x)\n", LoaderBlock);
1365 DbgPrint("ArchExtra (%08x)!\n", LoaderBlock->ArchExtra);
1366 #endif
1367
1368 /* Save pointer to ROS Block */
1369 KeRosLoaderBlock = LoaderBlock;
1370
1371 /* Save memory manager data */
1372 KeMemoryMapRangeCount = 0;
1373 if (LoaderBlock->Flags & MB_FLAGS_MMAP_INFO)
1374 {
1375 /* We have a memory map from the nice BIOS */
1376 ent = ((PULONG)(LoaderBlock->MmapAddr - sizeof(ULONG)));
1377 size = *ent;
1378 i = 0;
1379
1380 /* Map it until we run out of size */
1381 while (i < LoaderBlock->MmapLength)
1382 {
1383 /* Copy into the Kernel Memory Map */
1384 memcpy (&KeMemoryMap[KeMemoryMapRangeCount],
1385 (PVOID)(LoaderBlock->MmapAddr + i),
1386 sizeof(ADDRESS_RANGE));
1387
1388 /* Increase Memory Map Count */
1389 KeMemoryMapRangeCount++;
1390
1391 /* Increase Size */
1392 i += size;
1393 }
1394
1395 /* Save data */
1396 LoaderBlock->MmapLength = KeMemoryMapRangeCount * sizeof(ADDRESS_RANGE);
1397 LoaderBlock->MmapAddr = (ULONG)KeMemoryMap;
1398 }
1399 else
1400 {
1401 /* Nothing from BIOS */
1402 LoaderBlock->MmapLength = 0;
1403 LoaderBlock->MmapAddr = (ULONG)KeMemoryMap;
1404 }
1405
1406 /* Convert the loader block */
1407 KiRosFrldrLpbToNtLpb(KeRosLoaderBlock, &NtLoaderBlock);
1408
1409 #if defined(_M_PPC)
1410 DbgPrint("Finished KiRosFrldrLpbToNtLpb\n");
1411 #endif
1412
1413 /* Do general System Startup */
1414 KiSystemStartup(NtLoaderBlock);
1415 }
1416 #endif