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