2 * PROJECT: ReactOS Boot Loader
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: boot/freeldr/arch/arm/loader.c
5 * PURPOSE: ARM Kernel Loader
6 * PROGRAMMERS: ReactOS Portable Systems Group
9 /* INCLUDES *******************************************************************/
12 #include <internal/arm/ke.h>
13 #include <internal/arm/mm.h>
14 #include <internal/arm/intrin_i.h>
16 #define KERNEL_DESCRIPTOR_PAGE(x) (((ULONG_PTR)x &~ KSEG0_BASE) >> PAGE_SHIFT)
18 /* GLOBALS ********************************************************************/
20 typedef struct _BIOS_MEMORY_DESCRIPTOR
24 } BIOS_MEMORY_DESCRIPTOR
, *PBIOS_MEMORY_DESCRIPTOR
;
26 ULONG PageDirectoryStart
, PageDirectoryEnd
;
27 PLOADER_PARAMETER_BLOCK ArmLoaderBlock
;
28 CHAR ArmCommandLine
[256];
29 CHAR ArmArcBootPath
[64];
30 CHAR ArmArcHalPath
[64];
31 CHAR ArmNtHalPath
[64];
32 CHAR ArmNtBootPath
[64];
33 PNLS_DATA_BLOCK ArmNlsDataBlock
;
34 PLOADER_PARAMETER_EXTENSION ArmExtension
;
35 BIOS_MEMORY_DESCRIPTOR ArmBoardMemoryDescriptors
[16] = {{0}};
36 PBIOS_MEMORY_DESCRIPTOR ArmBoardMemoryList
= ArmBoardMemoryDescriptors
;
37 ULONG NumberDescriptors
= 0;
38 MEMORY_DESCRIPTOR MDArray
[16] = {{0}};
39 ULONG ArmSharedHeapSize
;
42 extern PAGE_DIRECTORY_ARM startup_pagedirectory
;
43 extern PAGE_TABLE_ARM kernel_pagetable
;
44 extern ROS_KERNEL_ENTRY_POINT KernelEntryPoint
;
45 extern ULONG_PTR KernelBase
;
47 extern ADDRESS_RANGE ArmBoardMemoryMap
[16];
48 extern ULONG ArmBoardMemoryMapRangeCount
;
49 extern ULONG_PTR AnsiData
, OemData
, UnicodeData
, RegistryData
, KernelData
, HalData
, DriverData
[16];
50 extern ULONG RegistrySize
, AnsiSize
, OemSize
, UnicodeSize
, KernelSize
, HalSize
, DriverSize
[16];
51 extern PCHAR DriverName
[16];
53 extern ULONG BootStack
;
71 4 // 4-way associative
78 8 // 8 words per line (32 bytes)
82 // Where to map the serial port
84 #define UART_VIRTUAL 0xE0000000
86 /* FUNCTIONS ******************************************************************/
89 ArmAllocateFromSharedHeap(IN ULONG Size
)
94 // Allocate from the shared heap
96 Buffer
= &ArmSharedHeap
[ArmSharedHeapSize
];
97 ArmSharedHeapSize
+= Size
;
101 PMEMORY_ALLOCATION_DESCRIPTOR
103 ArmAllocateMemoryDescriptor(VOID
)
106 // Allocate a descriptor from the heap
108 return ArmAllocateFromSharedHeap(sizeof(MEMORY_ALLOCATION_DESCRIPTOR
));
113 ArmAddBoardMemoryDescriptor(IN ULONG Address
,
116 PBIOS_MEMORY_DESCRIPTOR BiosBlock
= ArmBoardMemoryList
;
119 // Loop board DRAM configuration
121 while (BiosBlock
->BlockSize
> 0)
123 /* Check if we've found a matching head block */
124 if (Address
+ Size
== BiosBlock
->BlockBase
)
126 /* Simply enlarge and rebase it */
127 BiosBlock
->BlockBase
= Address
;
128 BiosBlock
->BlockSize
+= Size
;
132 /* Check if we've found a matching tail block */
133 if (Address
== (BiosBlock
->BlockBase
+ BiosBlock
->BlockSize
))
135 /* Simply enlarge it */
136 BiosBlock
->BlockSize
+= Size
;
140 /* Nothing suitable found, try the next block */
144 /* No usable blocks found, found a free block instead */
145 if (!BiosBlock
->BlockSize
)
148 BiosBlock
->BlockBase
= Address
;
149 BiosBlock
->BlockSize
= Size
;
151 /* Create a new block and mark it as the end of the array */
153 BiosBlock
->BlockBase
= BiosBlock
->BlockSize
= 0L;
159 ArmBuildBoardMemoryMap(VOID
)
161 ULONG BlockBegin
, BlockEnd
;
164 /* Loop the BIOS Memory Map */
165 for (j
= 0; j
< ArmBoardMemoryMapRangeCount
; j
++)
167 /* Get the start and end addresses */
168 BlockBegin
= ArmBoardMemoryMap
[j
].BaseAddrLow
;
169 BlockEnd
= ArmBoardMemoryMap
[j
].BaseAddrLow
+ ArmBoardMemoryMap
[j
].LengthLow
- 1;
171 /* Make sure this isn't a > 4GB descriptor */
172 if (!ArmBoardMemoryMap
[j
].BaseAddrHigh
)
174 /* Make sure we don't overflow */
175 if (BlockEnd
< BlockBegin
) BlockEnd
= 0xFFFFFFFF;
177 /* Check if this is free memory */
178 if (ArmBoardMemoryMap
[j
].Type
== 1)
180 /* Add it to our BIOS descriptors */
181 ArmAddBoardMemoryDescriptor(BlockBegin
, BlockEnd
- BlockBegin
+ 1);
189 ArmConfigureArcDescriptor(IN ULONG PageBegin
,
191 IN TYPE_OF_MEMORY MemoryType
)
194 ULONG BlockBegin
, BlockEnd
;
195 MEMORY_TYPE BlockType
;
196 BOOLEAN Combined
= FALSE
;
198 /* If this descriptor seems bogus, just return */
199 if (PageEnd
<= PageBegin
) return STATUS_SUCCESS
;
201 /* Loop every ARC descriptor, trying to find one we can modify */
202 for (i
= 0; i
< NumberDescriptors
; i
++)
204 /* Get its settings */
205 BlockBegin
= MDArray
[i
].BasePage
;
206 BlockEnd
= MDArray
[i
].BasePage
+ MDArray
[i
].PageCount
;
207 BlockType
= MDArray
[i
].MemoryType
;
209 /* Check if we can fit inside this block */
210 if (BlockBegin
< PageBegin
)
212 /* Check if we are larger then it */
213 if ((BlockEnd
> PageBegin
) && (BlockEnd
<= PageEnd
))
215 /* Make it end where we start */
216 BlockEnd
= PageBegin
;
219 /* Check if it ends after we do */
220 if (BlockEnd
> PageEnd
)
222 /* Make sure we can allocate a descriptor */
223 if (NumberDescriptors
== 60) return ENOMEM
;
225 /* Create a descriptor for whatever memory we're not part of */
226 MDArray
[NumberDescriptors
].MemoryType
= BlockType
;
227 MDArray
[NumberDescriptors
].BasePage
= PageEnd
;
228 MDArray
[NumberDescriptors
].PageCount
= BlockEnd
- PageEnd
;
231 /* The next block ending is now where we begin */
232 BlockEnd
= PageBegin
;
237 /* Check if the blog begins inside our range */
238 if (BlockBegin
< PageEnd
)
240 /* Check if it ends before we do */
241 if (BlockEnd
< PageEnd
)
243 /* Then make it disappear */
244 BlockEnd
= BlockBegin
;
248 /* Otherwise make it start where we end */
249 BlockBegin
= PageEnd
;
254 /* Check if the block matches us, and we haven't tried combining yet */
255 if ((BlockType
== MemoryType
) && !(Combined
))
257 /* Check if it starts where we end */
258 if (BlockBegin
== PageEnd
)
260 /* Make it start with us, and combine us */
261 BlockBegin
= PageBegin
;
264 else if (BlockEnd
== PageBegin
)
266 /* Otherwise, it ends where we begin, combine its ending */
272 /* Check the original block data matches with what we came up with */
273 if ((MDArray
[i
].BasePage
== BlockBegin
) &&
274 (MDArray
[i
].PageCount
== BlockEnd
- BlockBegin
))
280 /* Otherwise, set our new settings for this block */
281 MDArray
[i
].BasePage
= BlockBegin
;
282 MDArray
[i
].PageCount
= BlockEnd
- BlockBegin
;
284 /* Check if we are killing the block */
285 if (BlockBegin
== BlockEnd
)
287 /* Delete this block and restart the loop properly */
289 if (i
< NumberDescriptors
) MDArray
[i
] = MDArray
[NumberDescriptors
];
294 /* If we got here without combining, we need to allocate a new block */
295 if (!(Combined
) && (MemoryType
< LoaderMaximum
))
297 /* Make sure there's enough descriptors */
298 if (NumberDescriptors
== 60) return ENOMEM
;
300 /* Allocate a new block with our data */
301 MDArray
[NumberDescriptors
].MemoryType
= MemoryType
;
302 MDArray
[NumberDescriptors
].BasePage
= PageBegin
;
303 MDArray
[NumberDescriptors
].PageCount
= PageEnd
- PageBegin
;
307 /* Changes complete, return success */
308 return STATUS_SUCCESS
;
313 ArmBuildOsMemoryMap(VOID
)
315 PBIOS_MEMORY_DESCRIPTOR MdBlock
;
316 ULONG BlockStart
, BlockEnd
, BiasedStart
, BiasedEnd
, PageStart
, PageEnd
;
317 NTSTATUS Status
= STATUS_SUCCESS
;
319 /* Loop the BIOS Memory Descriptor List */
320 MdBlock
= ArmBoardMemoryList
;
321 while (MdBlock
->BlockSize
)
323 /* Get the statrt and end addresses */
324 BlockStart
= MdBlock
->BlockBase
;
325 BlockEnd
= BlockStart
+ MdBlock
->BlockSize
- 1;
327 /* Align them to page boundaries */
328 BiasedStart
= BlockStart
& (PAGE_SIZE
- 1);
329 if (BiasedStart
) BlockStart
= BlockStart
+ PAGE_SIZE
- BiasedStart
;
330 BiasedEnd
= (BlockEnd
+ 1) & (ULONG
)(PAGE_SIZE
- 1);
331 if (BiasedEnd
) BlockEnd
-= BiasedEnd
;
333 /* Get the actual page numbers */
334 PageStart
= BlockStart
>> PAGE_SHIFT
;
335 PageEnd
= (BlockEnd
+ 1) >> PAGE_SHIFT
;
337 /* Check if we did any alignment */
340 /* Mark that region as reserved */
341 Status
= ArmConfigureArcDescriptor(PageStart
- 1,
343 MemorySpecialMemory
);
344 if (Status
!= STATUS_SUCCESS
) break;
347 /* Check if we did any alignment */
350 /* Mark that region as reserved */
351 Status
= ArmConfigureArcDescriptor(PageEnd
- 1,
353 MemorySpecialMemory
);
354 if (Status
!= STATUS_SUCCESS
) break;
357 /* It is, mark the memory a free */
358 Status
= ArmConfigureArcDescriptor(PageStart
,
362 /* If we failed, break out, otherwise, go to the next BIOS block */
363 if (Status
!= STATUS_SUCCESS
) break;
367 /* Return error code */
373 ArmInsertMemoryDescriptor(IN PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor
)
375 PLIST_ENTRY ListHead
, PreviousEntry
, NextEntry
;
376 PMEMORY_ALLOCATION_DESCRIPTOR Descriptor
= NULL
, NextDescriptor
= NULL
;
378 /* Loop the memory descriptor list */
379 ListHead
= &ArmLoaderBlock
->MemoryDescriptorListHead
;
380 PreviousEntry
= ListHead
;
381 NextEntry
= ListHead
->Flink
;
382 while (NextEntry
!= ListHead
)
384 /* Get the current descriptor and check if it's below ours */
385 NextDescriptor
= CONTAINING_RECORD(NextEntry
,
386 MEMORY_ALLOCATION_DESCRIPTOR
,
388 if (NewDescriptor
->BasePage
< NextDescriptor
->BasePage
) break;
390 /* It isn't, save the previous entry and descriptor, and try again */
391 PreviousEntry
= NextEntry
;
392 Descriptor
= NextDescriptor
;
393 NextEntry
= NextEntry
->Flink
;
396 /* So we found the right spot to insert. Is this free memory? */
397 if (NewDescriptor
->MemoryType
!= LoaderFree
)
399 /* It isn't, so insert us before the last descriptor */
400 InsertHeadList(PreviousEntry
, &NewDescriptor
->ListEntry
);
404 /* We're free memory. Check if the entry we found is also free memory */
405 if ((PreviousEntry
!= ListHead
) &&
406 ((Descriptor
->MemoryType
== LoaderFree
) ||
407 (Descriptor
->MemoryType
== LoaderReserve
)) &&
408 ((Descriptor
->BasePage
+ Descriptor
->PageCount
) ==
409 NewDescriptor
->BasePage
))
411 /* It's free memory, and we're right after it. Enlarge that block */
412 Descriptor
->PageCount
+= NewDescriptor
->PageCount
;
413 NewDescriptor
= Descriptor
;
417 /* Our range scan't be combined, so just insert us separately */
418 InsertHeadList(PreviousEntry
, &NewDescriptor
->ListEntry
);
421 /* Check if we merged with an existing free memory block */
422 if ((NextEntry
!= ListHead
) &&
423 ((NextDescriptor
->MemoryType
== LoaderFree
) ||
424 (NextDescriptor
->MemoryType
== LoaderReserve
)) &&
425 ((NewDescriptor
->BasePage
+ NewDescriptor
->PageCount
) ==
426 NextDescriptor
->BasePage
))
428 /* Update our own block */
429 NewDescriptor
->PageCount
+= NextDescriptor
->PageCount
;
431 /* Remove the next block */
432 RemoveEntryList(&NextDescriptor
->ListEntry
);
439 ArmBuildMemoryDescriptor(IN PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor
,
440 IN MEMORY_TYPE MemoryType
,
444 PMEMORY_ALLOCATION_DESCRIPTOR Descriptor
, NextDescriptor
= NULL
;
446 TYPE_OF_MEMORY CurrentType
;
449 /* Check how many pages we'll be consuming */
450 Delta
= BasePage
- MemoryDescriptor
->BasePage
;
451 if (!(Delta
) && (PageCount
== MemoryDescriptor
->PageCount
))
453 /* We can simply convert the current descriptor into our new type */
454 MemoryDescriptor
->MemoryType
= MemoryType
;
458 /* Get the current memory type of the descriptor, and reserve it */
459 CurrentType
= MemoryDescriptor
->MemoryType
;
460 MemoryDescriptor
->MemoryType
= LoaderSpecialMemory
;
462 /* Check if we'll need another descriptor for what's left of memory */
463 UseNext
= ((BasePage
!= MemoryDescriptor
->BasePage
) &&
464 (Delta
+ PageCount
!= MemoryDescriptor
->PageCount
));
466 /* Get a descriptor */
467 Descriptor
= ArmAllocateMemoryDescriptor();
468 if (!Descriptor
) return STATUS_INSUFFICIENT_RESOURCES
;
470 /* Check if we are using another descriptor */
473 /* Allocate that one too */
474 NextDescriptor
= ArmAllocateMemoryDescriptor();
475 if (!NextDescriptor
) return STATUS_INSUFFICIENT_RESOURCES
;
478 /* Build the descriptor we got */
479 Descriptor
->MemoryType
= MemoryType
;
480 Descriptor
->BasePage
= BasePage
;
481 Descriptor
->PageCount
= PageCount
;
483 /* Check if we're starting at the same place as the old one */
484 if (BasePage
== MemoryDescriptor
->BasePage
)
486 /* Simply decrease the old descriptor and rebase it */
487 MemoryDescriptor
->BasePage
+= PageCount
;
488 MemoryDescriptor
->PageCount
-= PageCount
;
489 MemoryDescriptor
->MemoryType
= CurrentType
;
491 else if (Delta
+ PageCount
== MemoryDescriptor
->PageCount
)
493 /* We finish where the old one did, shorten it */
494 MemoryDescriptor
->PageCount
-= PageCount
;
495 MemoryDescriptor
->MemoryType
= CurrentType
;
499 /* We're inside the current block, mark our free region */
500 NextDescriptor
->MemoryType
= LoaderFree
;
501 NextDescriptor
->BasePage
= BasePage
+ PageCount
;
502 NextDescriptor
->PageCount
= MemoryDescriptor
->PageCount
-
505 /* And cut down the current descriptor */
506 MemoryDescriptor
->PageCount
= Delta
;
507 MemoryDescriptor
->MemoryType
= CurrentType
;
509 /* Finally, insert our new free descriptor into the list */
510 ArmInsertMemoryDescriptor(NextDescriptor
);
513 /* Insert the descriptor we allocated */
514 ArmInsertMemoryDescriptor(Descriptor
);
518 return STATUS_SUCCESS
;
521 PMEMORY_ALLOCATION_DESCRIPTOR
523 ArmFindMemoryDescriptor(IN ULONG BasePage
)
525 PMEMORY_ALLOCATION_DESCRIPTOR MdBlock
= NULL
;
526 PLIST_ENTRY NextEntry
, ListHead
;
528 /* Scan the memory descriptor list */
529 ListHead
= &ArmLoaderBlock
->MemoryDescriptorListHead
;
530 NextEntry
= ListHead
->Flink
;
531 while (NextEntry
!= ListHead
)
533 /* Get the current descriptor */
534 MdBlock
= CONTAINING_RECORD(NextEntry
,
535 MEMORY_ALLOCATION_DESCRIPTOR
,
538 /* Check if it can contain our memory range */
539 if ((MdBlock
->BasePage
<= BasePage
) &&
540 (MdBlock
->BasePage
+ MdBlock
->PageCount
> BasePage
))
542 /* It can, break out */
546 /* Go to the next descriptor */
547 NextEntry
= NextEntry
->Flink
;
550 /* Return the descriptor we found, if any */
556 ArmCreateMemoryDescriptor(IN TYPE_OF_MEMORY MemoryType
,
560 OUT PULONG ReturnedBase
)
562 PMEMORY_ALLOCATION_DESCRIPTOR MdBlock
;
563 ULONG AlignedBase
, AlignedLimit
;
564 PMEMORY_ALLOCATION_DESCRIPTOR ActiveMdBlock
;
565 ULONG ActiveAlignedBase
= 0;
566 PLIST_ENTRY NextEntry
, ListHead
;
568 /* If no information was given, make some assumptions */
569 if (!Alignment
) Alignment
= 1;
570 if (!PageCount
) PageCount
= 1;
572 /* Start looking for a matching descvriptor */
575 /* Calculate the limit of the range */
576 AlignedLimit
= PageCount
+ BasePage
;
578 /* Find a descriptor that already contains our base address */
579 MdBlock
= ArmFindMemoryDescriptor(BasePage
);
582 /* If it contains our limit as well, break out early */
583 if ((MdBlock
->PageCount
+ MdBlock
->BasePage
) >= AlignedLimit
) break;
586 /* Loop the memory list */
588 ActiveMdBlock
= NULL
;
589 ListHead
= &ArmLoaderBlock
->MemoryDescriptorListHead
;
590 NextEntry
= ListHead
->Flink
;
591 while (NextEntry
!= ListHead
)
593 /* Get the current descriptors */
594 MdBlock
= CONTAINING_RECORD(NextEntry
,
595 MEMORY_ALLOCATION_DESCRIPTOR
,
598 /* Align the base address and our limit */
599 AlignedBase
= (MdBlock
->BasePage
+ (Alignment
- 1)) &~ Alignment
;
600 AlignedLimit
= MdBlock
->PageCount
-
604 /* Check if this is a free block that can satisfy us */
605 if ((MdBlock
->MemoryType
== LoaderFree
) &&
606 (AlignedLimit
<= MdBlock
->PageCount
) &&
607 (PageCount
<= AlignedLimit
))
609 /* It is, stop searching */
610 ActiveMdBlock
= MdBlock
;
611 ActiveAlignedBase
= AlignedBase
;
615 /* Try the next block */
616 NextEntry
= NextEntry
->Flink
;
619 /* See if we came up with an adequate block */
622 /* Generate a descriptor in it */
623 *ReturnedBase
= AlignedBase
;
624 return ArmBuildMemoryDescriptor(ActiveMdBlock
,
631 /* We found a matching block, generate a descriptor with it */
632 *ReturnedBase
= BasePage
;
633 return ArmBuildMemoryDescriptor(MdBlock
, MemoryType
, BasePage
, PageCount
);
638 ArmBuildLoaderMemoryList(VOID
)
640 PMEMORY_ALLOCATION_DESCRIPTOR Descriptor
;
641 MEMORY_DESCRIPTOR
*Memory
;
644 /* Loop all BIOS Memory Descriptors */
645 for (i
= 0; i
< NumberDescriptors
; i
++)
647 /* Get the current descriptor */
648 Memory
= &MDArray
[i
];
650 /* Allocate an NT Memory Descriptor */
651 Descriptor
= ArmAllocateMemoryDescriptor();
652 if (!Descriptor
) return ENOMEM
;
654 /* Copy the memory type */
655 Descriptor
->MemoryType
= Memory
->MemoryType
;
656 if (Memory
->MemoryType
== MemoryFreeContiguous
)
658 /* Convert this to free */
659 Descriptor
->MemoryType
= LoaderFree
;
661 else if (Memory
->MemoryType
== MemorySpecialMemory
)
663 /* Convert this to special memory */
664 Descriptor
->MemoryType
= LoaderSpecialMemory
;
667 /* Copy the range data */
668 Descriptor
->BasePage
= Memory
->BasePage
;
669 Descriptor
->PageCount
= Memory
->PageCount
;
671 /* Insert the descriptor */
672 if (Descriptor
->PageCount
) ArmInsertMemoryDescriptor(Descriptor
);
676 return STATUS_SUCCESS
;
680 #define LARGE_PFN_SHIFT 20
682 #define PTE_BASE 0xC0000000
683 #define PDE_BASE 0xC0400000
684 #define HAL_BASE 0xFFC00000
685 #define MMIO_BASE 0x10000000
687 #define LowMemPageTableIndex 0
688 #define StartupPtePageTableIndex (PTE_BASE >> PDE_SHIFT)
689 #define StartupPdePageTableIndex (PDE_BASE >> PDE_SHIFT)
690 #define MmioPageTableIndex (MMIO_BASE >> PDE_SHIFT)
691 #define HalPageTableIndex (HAL_BASE >> PDE_SHIFT)
693 /* Converts a Physical Address into a Page Frame Number */
694 #define PaToPfn(p) ((p) >> PFN_SHIFT)
695 #define PaToLargePfn(p) ((p) >> LARGE_PFN_SHIFT)
696 #define PaPtrToPfn(p) (((ULONG_PTR)(p)) >> PFN_SHIFT)
698 /* Converts a Physical Address into a Coarse Page Table PFN */
699 #define PaPtrToPdePfn(p) (((ULONG_PTR)(p)) >> CPT_SHIFT)
701 HARDWARE_PTE_ARMV6 TempPte
;
702 HARDWARE_LARGE_PTE_ARMV6 TempLargePte
;
703 HARDWARE_PDE_ARMV6 TempPde
;
706 ArmSetupPageDirectory(VOID
)
708 PPAGE_DIRECTORY_ARM PageDir
;
709 PPAGE_TABLE_ARM PageTable
, KernelPageTable
;
710 ULONG KernelPageTableIndex
;
712 PHARDWARE_PTE_ARMV6 PointerPte
;
713 PHARDWARE_PDE_ARMV6 PointerPde
;
714 PHARDWARE_LARGE_PTE_ARMV6 LargePte
;
717 /* Setup templates */
718 TempPte
.Accessed
= TempPte
.Valid
= TempLargePte
.LargePage
= TempLargePte
.Accessed
= TempPde
.Valid
= 1;
720 /* Get the Kernel Table Index */
721 KernelPageTableIndex
= KernelBase
>> PDE_SHIFT
;
722 printf("Kernel Base: 0x%p (PDE Index: %lx)\n", KernelBase
, KernelPageTableIndex
);
724 /* Allocate 1MB PDE_BASE and HYPER_SPACE. This will be improved later. Must be 1MB aligned */
725 PageDir
= MmAllocateMemoryAtAddress(1 * 1024 * 1024, (PVOID
)0x700000, LoaderMemoryData
);
726 if (!PageDir
) { printf("FATAL: No memory!\n"); while (TRUE
); }
727 printf("Initial Page Directory: 0x%p\n", PageDir
);
729 /* Setup the Low Memory PDE as an identity-mapped Large Page (1MB) */
730 LargePte
= &PageDir
->Pte
[LowMemPageTableIndex
];
731 *LargePte
= TempLargePte
;
733 /* Setup the MMIO PDE as two identity mapped large pages -- the kernel will blow these away later */
734 LargePte
= &PageDir
->Pte
[MmioPageTableIndex
];
735 Pfn
= PaToLargePfn(0x10000000);
736 for (i
= 0; i
< 2; i
++)
738 TempLargePte
.PageFrameNumber
= Pfn
++;
739 *LargePte
++ = TempLargePte
;
742 /* Allocate 8 page tables (8KB) to describe the 8MB initial kernel region */
743 KernelPageTable
= MmAllocateMemoryWithType(8192, LoaderMemoryData
);
744 if (!KernelPageTable
) { printf("FATAL: No memory!\n"); while (TRUE
); }
745 printf("Kernel Page Tables: 0x%p\n", KernelPageTable
);
747 /* Setup the Kernel PDEs */
748 PointerPde
= &PageDir
->Pde
[KernelPageTableIndex
];
749 Pfn
= PaPtrToPdePfn(KernelPageTable
);
750 for (i
= 0; i
< 8; i
++)
752 TempPde
.PageFrameNumber
= Pfn
++;
753 *PointerPde
++ = TempPde
;
756 /* Setup the Startup PDE */
757 printf("PAGEDIR: %p IDX: %lx PPDE: %p PFN: %lx \n", PageDir
, StartupPdePageTableIndex
, &PageDir
->Pte
[StartupPdePageTableIndex
], PaToLargePfn((ULONG_PTR
)PageDir
));
758 LargePte
= &PageDir
->Pte
[StartupPdePageTableIndex
];
759 TempLargePte
.PageFrameNumber
= PaToLargePfn((ULONG_PTR
)PageDir
);
760 printf("PAGEDIR: %p IDX: %lx PPDE: %p PFN: %lx \n", PageDir
, StartupPdePageTableIndex
, LargePte
, TempLargePte
.PageFrameNumber
);
761 *LargePte
= TempLargePte
;
763 /* After this point, any MiAddressToPde is guaranteed not to fault */
765 /* Allocate 4 page tables (4KB) to describe the 4MB PTE_BASE region */
766 PageTable
= MmAllocateMemoryWithType(4096, LoaderMemoryData
);
767 if (!PageTable
) { printf("FATAL: No memory!\n"); while (TRUE
); }
768 printf("Initial Page Tables: 0x%p\n", PageTable
);
771 * Link them in the Startup PDE.
772 * Note these are the entries in the PD at (MiAddressToPde(PTE_BASE)).
774 PointerPde
= &PageDir
->Pde
[StartupPtePageTableIndex
];
775 Pfn
= PaPtrToPdePfn(PageTable
);
776 for (i
= 0; i
< 4; i
++)
778 TempPde
.PageFrameNumber
= Pfn
++;
779 *PointerPde
++ = TempPde
;
783 * Now map these page tables in PTE space (MiAddressToPte(PTE_BASE)).
784 * Note that they all live on a single page, since each is 1KB.
786 PointerPte
= &PageTable
->Pte
[0x300];
787 TempPte
.PageFrameNumber
= PaPtrToPfn(PageTable
);
788 *PointerPte
= TempPte
;
791 * After this point, MiAddressToPte((PDE_BASE) to MiAddressToPte(PDE_TOP))
792 * is guaranteed not to fault.
793 * Any subsequent page allocation will first need its page table created
794 * and mapped in the PTE_BASE first, then the page table itself will be
795 * editable through its flat PTE address.
797 printf("Paging init done\n");
802 ArmSetupPagingAndJump(IN PVOID PageDirectoryBaseAddress
)
804 ARM_CONTROL_REGISTER ControlRegister
;
805 ARM_TTB_REGISTER TtbRegister
;
806 ARM_DOMAIN_REGISTER DomainRegister
;
809 TtbRegister
.AsUlong
= (ULONG_PTR
)PageDirectoryBaseAddress
;
810 ASSERT(TtbRegister
.Reserved
== 0);
811 KeArmTranslationTableRegisterSet(TtbRegister
);
813 /* Disable domains and simply use access bits on PTEs */
814 DomainRegister
.AsUlong
= 0;
815 DomainRegister
.Domain0
= ClientDomain
;
816 KeArmDomainRegisterSet(DomainRegister
);
818 /* Enable ARMv6+ paging (MMU), caches and the access bit */
819 ControlRegister
= KeArmControlRegisterGet();
820 ControlRegister
.MmuEnabled
= TRUE
;
821 ControlRegister
.ICacheEnabled
= TRUE
;
822 ControlRegister
.DCacheEnabled
= TRUE
;
823 ControlRegister
.ForceAp
= TRUE
;
824 ControlRegister
.ExtendedPageTables
= TRUE
;
825 KeArmControlRegisterSet(ControlRegister
);
828 TuiPrintf("Hello from MMU Enabled!\n");
830 (*KernelEntryPoint
)((PVOID
)((ULONG_PTR
)ArmLoaderBlock
| KSEG0_BASE
));
834 ArmPrepareForReactOS(IN BOOLEAN Setup
)
836 ARM_CACHE_REGISTER CacheReg
;
838 PCHAR BootPath
, HalPath
;
841 PLDR_DATA_TABLE_ENTRY LdrEntry
;
842 PLIST_ENTRY NextEntry
, OldEntry
;
843 PARC_DISK_INFORMATION ArcDiskInformation
;
844 PARC_DISK_SIGNATURE ArcDiskSignature
;
845 ULONG ArcDiskCount
= 0;
848 PMASTER_BOOT_RECORD Mbr
;
851 PWCHAR ArmModuleName
;
854 // Allocate the ARM Shared Heap
856 ArmSharedHeap
= MmAllocateMemoryWithType(PAGE_SIZE
, LoaderOsloaderHeap
);
857 ArmSharedHeapSize
= 0;
858 if (!ArmSharedHeap
) return;
861 // Allocate the loader block and extension
863 ArmLoaderBlock
= ArmAllocateFromSharedHeap(sizeof(LOADER_PARAMETER_BLOCK
));
864 if (!ArmLoaderBlock
) return;
865 ArmExtension
= ArmAllocateFromSharedHeap(sizeof(LOADER_PARAMETER_EXTENSION
));
866 if (!ArmExtension
) return;
869 // Initialize the loader block
871 InitializeListHead(&ArmLoaderBlock
->BootDriverListHead
);
872 InitializeListHead(&ArmLoaderBlock
->LoadOrderListHead
);
873 InitializeListHead(&ArmLoaderBlock
->MemoryDescriptorListHead
);
876 // Setup the extension and setup block
878 ArmLoaderBlock
->Extension
= (PVOID
)((ULONG_PTR
)ArmExtension
| KSEG0_BASE
);
879 ArmLoaderBlock
->SetupLdrBlock
= NULL
;
882 // Add the Board Memory Map from U-Boot into the STARTUP.COM-style
883 // BIOS descriptor format -- this needs to be removed later.
885 ArmBuildBoardMemoryMap();
888 // Now basically convert these entries to the ARC format, so that we can
889 // get a good map of free (usable) memory
891 ArmBuildOsMemoryMap();
894 // NT uses an extended ARC format, with slightly different memory types.
895 // We also want to link the ARC descriptors together into a linked list,
896 // instead of the array, and allocate the semi-permanent storage in which
897 // these entries will be stored so that the kernel can read them.
899 ArmBuildLoaderMemoryList();
902 // Setup descriptor for the shared heap
904 Status
= ArmCreateMemoryDescriptor(LoaderOsloaderHeap
,
905 (ULONG_PTR
)ArmSharedHeap
>> PAGE_SHIFT
,
906 ADDRESS_AND_SIZE_TO_SPAN_PAGES(ArmSharedHeap
,
910 if (Status
!= STATUS_SUCCESS
) return;
913 // Setup descriptor for the boot stack
915 Status
= ArmCreateMemoryDescriptor(LoaderOsloaderStack
,
916 (ULONG_PTR
)&BootStack
>> PAGE_SHIFT
,
920 if (Status
!= STATUS_SUCCESS
) return;
923 // Setup descriptor for the boot page tables
925 Status
= ArmCreateMemoryDescriptor(LoaderMemoryData
,
926 (ULONG_PTR
)&TranslationTableStart
>> PAGE_SHIFT
,
927 ((ULONG_PTR
)&TranslationTableEnd
-
928 (ULONG_PTR
)&TranslationTableStart
) / PAGE_SIZE
,
931 if (Status
!= STATUS_SUCCESS
) return;
934 // Setup descriptor for the kernel
936 Status
= ArmCreateMemoryDescriptor(LoaderSystemCode
,
937 KernelData
>> PAGE_SHIFT
,
938 ADDRESS_AND_SIZE_TO_SPAN_PAGES(KernelData
,
942 if (Status
!= STATUS_SUCCESS
) return;
945 // Setup descriptor for the HAL
947 Status
= ArmCreateMemoryDescriptor(LoaderHalCode
,
948 HalData
>> PAGE_SHIFT
,
949 ADDRESS_AND_SIZE_TO_SPAN_PAGES(HalData
,
953 if (Status
!= STATUS_SUCCESS
) return;
956 // Setup registry data
958 ArmLoaderBlock
->RegistryBase
= (PVOID
)((ULONG_PTR
)RegistryData
| KSEG0_BASE
);
959 ArmLoaderBlock
->RegistryLength
= RegistrySize
;
962 // Create an MD for it
964 Status
= ArmCreateMemoryDescriptor(LoaderRegistryData
,
965 RegistryData
>> PAGE_SHIFT
,
966 ADDRESS_AND_SIZE_TO_SPAN_PAGES(RegistryData
,
970 if (Status
!= STATUS_SUCCESS
) return;
973 // TODO: Setup ARC Hardware tree data
979 ArmNlsDataBlock
= ArmAllocateFromSharedHeap(sizeof(NLS_DATA_BLOCK
));
980 ArmLoaderBlock
->NlsData
= ArmNlsDataBlock
;
981 ArmLoaderBlock
->NlsData
->AnsiCodePageData
= (PVOID
)(AnsiData
| KSEG0_BASE
);
982 ArmLoaderBlock
->NlsData
->OemCodePageData
= (PVOID
)(OemData
| KSEG0_BASE
);
983 ArmLoaderBlock
->NlsData
->UnicodeCodePageData
= (PVOID
)(UnicodeData
| KSEG0_BASE
);
984 ArmLoaderBlock
->NlsData
= (PVOID
)((ULONG_PTR
)ArmLoaderBlock
->NlsData
| KSEG0_BASE
);
987 // Setup ANSI NLS Memory Descriptor
989 Status
= ArmCreateMemoryDescriptor(LoaderNlsData
,
990 AnsiData
>> PAGE_SHIFT
,
991 ADDRESS_AND_SIZE_TO_SPAN_PAGES(AnsiData
,
995 if (Status
!= STATUS_SUCCESS
) return;
998 // Setup OEM NLS Memory Descriptor
1000 Status
= ArmCreateMemoryDescriptor(LoaderNlsData
,
1001 OemData
>> PAGE_SHIFT
,
1002 ADDRESS_AND_SIZE_TO_SPAN_PAGES(OemData
,
1006 if (Status
!= STATUS_SUCCESS
) return;
1009 // Setup Unicode NLS Memory Descriptor
1011 Status
= ArmCreateMemoryDescriptor(LoaderNlsData
,
1012 UnicodeData
>> PAGE_SHIFT
,
1013 ADDRESS_AND_SIZE_TO_SPAN_PAGES(UnicodeData
,
1017 if (Status
!= STATUS_SUCCESS
) return;
1020 // Setup loader entry for the kernel
1022 ArmModuleName
= ArmAllocateFromSharedHeap(64 * sizeof(WCHAR
));
1023 wcscpy(ArmModuleName
, L
"ntoskrnl.exe");
1024 LdrEntry
= ArmAllocateFromSharedHeap(sizeof(LDR_DATA_TABLE_ENTRY
));
1025 RtlZeroMemory(LdrEntry
, sizeof(LDR_DATA_TABLE_ENTRY
));
1026 LdrEntry
->DllBase
= (PVOID
)KernelBase
;
1027 LdrEntry
->SizeOfImage
= KernelSize
;
1028 LdrEntry
->EntryPoint
= KernelEntryPoint
;
1029 LdrEntry
->LoadCount
= 1;
1030 LdrEntry
->Flags
= LDRP_IMAGE_DLL
| LDRP_ENTRY_PROCESSED
;
1031 RtlInitUnicodeString(&LdrEntry
->FullDllName
, ArmModuleName
);
1032 RtlInitUnicodeString(&LdrEntry
->BaseDllName
, ArmModuleName
);
1033 LdrEntry
->FullDllName
.Buffer
= (PVOID
)((ULONG_PTR
)LdrEntry
->FullDllName
.Buffer
| KSEG0_BASE
);
1034 LdrEntry
->BaseDllName
.Buffer
= (PVOID
)((ULONG_PTR
)LdrEntry
->BaseDllName
.Buffer
| KSEG0_BASE
);
1035 InsertTailList(&ArmLoaderBlock
->LoadOrderListHead
, &LdrEntry
->InLoadOrderLinks
);
1038 // Setup loader entry for the HAL
1040 ArmModuleName
= ArmAllocateFromSharedHeap(64 * sizeof(WCHAR
));
1041 wcscpy(ArmModuleName
, L
"hal.dll");
1042 LdrEntry
= ArmAllocateFromSharedHeap(sizeof(LDR_DATA_TABLE_ENTRY
));
1043 RtlZeroMemory(LdrEntry
, sizeof(LDR_DATA_TABLE_ENTRY
));
1044 LdrEntry
->DllBase
= (PVOID
)(HalData
| KSEG0_BASE
);
1045 LdrEntry
->SizeOfImage
= HalSize
;
1046 LdrEntry
->EntryPoint
= (PVOID
)RtlImageNtHeader((PVOID
)HalData
)->
1047 OptionalHeader
.AddressOfEntryPoint
;
1048 LdrEntry
->EntryPoint
= (PVOID
)((ULONG_PTR
)LdrEntry
->EntryPoint
| KSEG0_BASE
);
1049 LdrEntry
->LoadCount
= 1;
1050 LdrEntry
->Flags
= LDRP_IMAGE_DLL
| LDRP_ENTRY_PROCESSED
;
1051 RtlInitUnicodeString(&LdrEntry
->FullDllName
, ArmModuleName
);
1052 RtlInitUnicodeString(&LdrEntry
->BaseDllName
, ArmModuleName
);
1053 LdrEntry
->FullDllName
.Buffer
= (PVOID
)((ULONG_PTR
)LdrEntry
->FullDllName
.Buffer
| KSEG0_BASE
);
1054 LdrEntry
->BaseDllName
.Buffer
= (PVOID
)((ULONG_PTR
)LdrEntry
->BaseDllName
.Buffer
| KSEG0_BASE
);
1055 InsertTailList(&ArmLoaderBlock
->LoadOrderListHead
, &LdrEntry
->InLoadOrderLinks
);
1058 // Build descriptors for the drivers loaded
1060 for (i
= 0; i
< Drivers
; i
++)
1063 // Setup loader entry for the driver
1065 LdrEntry
= ArmAllocateFromSharedHeap(sizeof(LDR_DATA_TABLE_ENTRY
));
1066 RtlZeroMemory(LdrEntry
, sizeof(LDR_DATA_TABLE_ENTRY
));
1067 LdrEntry
->DllBase
= (PVOID
)(DriverData
[i
] | KSEG0_BASE
);
1068 LdrEntry
->SizeOfImage
= DriverSize
[i
];
1069 LdrEntry
->EntryPoint
= (PVOID
)RtlImageNtHeader((PVOID
)DriverData
[i
])->
1070 OptionalHeader
.AddressOfEntryPoint
;
1071 LdrEntry
->EntryPoint
= (PVOID
)((ULONG_PTR
)LdrEntry
->EntryPoint
| KSEG0_BASE
);
1072 LdrEntry
->LoadCount
= 1;
1073 LdrEntry
->Flags
= LDRP_IMAGE_DLL
| LDRP_ENTRY_PROCESSED
;
1074 ArmModuleName
= ArmAllocateFromSharedHeap(64 * sizeof(WCHAR
));
1075 RtlZeroMemory(ArmModuleName
, 64 * sizeof(WCHAR
));
1076 LdrEntry
->FullDllName
.Length
= strlen(DriverName
[i
]) * sizeof(WCHAR
);
1077 LdrEntry
->FullDllName
.MaximumLength
= LdrEntry
->FullDllName
.Length
;
1078 LdrEntry
->FullDllName
.Buffer
= ArmModuleName
;
1079 LdrEntry
->BaseDllName
= LdrEntry
->FullDllName
;
1080 while (*DriverName
[i
]) *ArmModuleName
++ = *DriverName
[i
]++;
1081 LdrEntry
->FullDllName
.Buffer
= (PVOID
)((ULONG_PTR
)LdrEntry
->FullDllName
.Buffer
| KSEG0_BASE
);
1082 LdrEntry
->BaseDllName
.Buffer
= (PVOID
)((ULONG_PTR
)LdrEntry
->BaseDllName
.Buffer
| KSEG0_BASE
);
1083 InsertTailList(&ArmLoaderBlock
->LoadOrderListHead
, &LdrEntry
->InLoadOrderLinks
);
1086 // Build a descriptor for the driver
1088 Status
= ArmCreateMemoryDescriptor(LoaderBootDriver
,
1089 DriverData
[i
] >> PAGE_SHIFT
,
1090 ADDRESS_AND_SIZE_TO_SPAN_PAGES(DriverData
[i
],
1094 if (Status
!= STATUS_SUCCESS
) return;
1100 NextEntry
= ArmLoaderBlock
->LoadOrderListHead
.Flink
;
1101 while (NextEntry
!= &ArmLoaderBlock
->LoadOrderListHead
)
1104 // Remember the physical entry
1106 OldEntry
= NextEntry
->Flink
;
1111 NextEntry
->Flink
= (PVOID
)((ULONG_PTR
)NextEntry
->Flink
| KSEG0_BASE
);
1112 NextEntry
->Blink
= (PVOID
)((ULONG_PTR
)NextEntry
->Blink
| KSEG0_BASE
);
1117 NextEntry
= OldEntry
;
1121 // Now edit the root itself
1123 NextEntry
->Flink
= (PVOID
)((ULONG_PTR
)NextEntry
->Flink
| KSEG0_BASE
);
1124 NextEntry
->Blink
= (PVOID
)((ULONG_PTR
)NextEntry
->Blink
| KSEG0_BASE
);
1127 // Setup extension parameters
1129 ArmExtension
->Size
= sizeof(LOADER_PARAMETER_EXTENSION
);
1130 ArmExtension
->MajorVersion
= 5;
1131 ArmExtension
->MinorVersion
= 2;
1134 // Make a copy of the command line
1136 ArmLoaderBlock
->LoadOptions
= ArmCommandLine
;
1137 strcpy(ArmCommandLine
, reactos_kernel_cmdline
);
1140 // Find the first \, separating the ARC path from NT path
1142 BootPath
= strchr(ArmCommandLine
, '\\');
1143 *BootPath
= ANSI_NULL
;
1146 // Set the ARC Boot Path
1148 strncpy(ArmArcBootPath
, ArmCommandLine
, 63);
1149 ArmLoaderBlock
->ArcBootDeviceName
= (PVOID
)((ULONG_PTR
)ArmArcBootPath
| KSEG0_BASE
);
1152 // The rest of the string is the NT path
1154 HalPath
= strchr(BootPath
+ 1, ' ');
1155 *HalPath
= ANSI_NULL
;
1156 ArmNtBootPath
[0] = '\\';
1157 strncat(ArmNtBootPath
, BootPath
+ 1, 63);
1158 strcat(ArmNtBootPath
,"\\");
1159 ArmLoaderBlock
->NtBootPathName
= (PVOID
)((ULONG_PTR
)ArmNtBootPath
| KSEG0_BASE
);
1162 // Set the HAL paths
1164 strncpy(ArmArcHalPath
, ArmArcBootPath
, 63);
1165 ArmLoaderBlock
->ArcHalDeviceName
= (PVOID
)((ULONG_PTR
)ArmArcHalPath
| KSEG0_BASE
);
1166 strcpy(ArmNtHalPath
, "\\");
1167 ArmLoaderBlock
->NtHalPathName
= (PVOID
)((ULONG_PTR
)ArmNtHalPath
| KSEG0_BASE
);
1170 // Use this new command line
1172 strncpy(ArmLoaderBlock
->LoadOptions
, HalPath
+ 2, 255);
1175 // Parse it and change every slash to a space
1177 BootPath
= ArmLoaderBlock
->LoadOptions
;
1178 do {if (*BootPath
== '/') *BootPath
= ' ';} while (*BootPath
++);
1181 // Fixup command-line pointer
1183 ArmLoaderBlock
->LoadOptions
= (PVOID
)((ULONG_PTR
)ArmLoaderBlock
->LoadOptions
| KSEG0_BASE
);
1186 // Setup cache information
1188 CacheReg
= KeArmCacheRegisterGet();
1189 ArmLoaderBlock
->u
.Arm
.FirstLevelDcacheSize
= SizeBits
[CacheReg
.DSize
];
1190 ArmLoaderBlock
->u
.Arm
.FirstLevelDcacheFillSize
= LenBits
[CacheReg
.DLength
];
1191 ArmLoaderBlock
->u
.Arm
.FirstLevelDcacheFillSize
<<= 2;
1192 ArmLoaderBlock
->u
.Arm
.FirstLevelIcacheSize
= SizeBits
[CacheReg
.ISize
];
1193 ArmLoaderBlock
->u
.Arm
.FirstLevelIcacheFillSize
= LenBits
[CacheReg
.ILength
];
1194 ArmLoaderBlock
->u
.Arm
.FirstLevelIcacheFillSize
<<= 2;
1195 ArmLoaderBlock
->u
.Arm
.SecondLevelDcacheSize
=
1196 ArmLoaderBlock
->u
.Arm
.SecondLevelDcacheFillSize
=
1197 ArmLoaderBlock
->u
.Arm
.SecondLevelIcacheSize
=
1198 ArmLoaderBlock
->u
.Arm
.SecondLevelIcacheFillSize
= 0;
1201 // Allocate the Interrupt stack
1203 Base
= MmAllocateMemoryWithType(KERNEL_STACK_SIZE
, LoaderStartupDpcStack
);
1204 ArmLoaderBlock
->u
.Arm
.InterruptStack
= KSEG0_BASE
| (ULONG
)Base
;
1205 ArmLoaderBlock
->u
.Arm
.InterruptStack
+= KERNEL_STACK_SIZE
;
1208 // Build an entry for it
1210 Status
= ArmCreateMemoryDescriptor(LoaderStartupDpcStack
,
1211 (ULONG_PTR
)Base
>> PAGE_SHIFT
,
1212 KERNEL_STACK_SIZE
/ PAGE_SIZE
,
1215 if (Status
!= STATUS_SUCCESS
) return;
1218 // Allocate the Kernel Boot stack
1220 Base
= MmAllocateMemoryWithType(KERNEL_STACK_SIZE
, LoaderStartupKernelStack
);
1221 ArmLoaderBlock
->KernelStack
= KSEG0_BASE
| (ULONG
)Base
;
1222 ArmLoaderBlock
->KernelStack
+= KERNEL_STACK_SIZE
;
1225 // Build an entry for it
1227 Status
= ArmCreateMemoryDescriptor(LoaderStartupKernelStack
,
1228 (ULONG_PTR
)Base
>> PAGE_SHIFT
,
1229 KERNEL_STACK_SIZE
/ PAGE_SIZE
,
1232 if (Status
!= STATUS_SUCCESS
) return;
1235 // Allocate the Abort stack
1237 Base
= MmAllocateMemoryWithType(KERNEL_STACK_SIZE
, LoaderStartupPanicStack
);
1238 ArmLoaderBlock
->u
.Arm
.PanicStack
= KSEG0_BASE
| (ULONG
)Base
;
1239 ArmLoaderBlock
->u
.Arm
.PanicStack
+= KERNEL_STACK_SIZE
;
1242 // Build an entry for it
1244 Status
= ArmCreateMemoryDescriptor(LoaderStartupPanicStack
,
1245 (ULONG_PTR
)Base
>> PAGE_SHIFT
,
1246 KERNEL_STACK_SIZE
/ PAGE_SIZE
,
1249 if (Status
!= STATUS_SUCCESS
) return;
1252 // Allocate the PCR/KUSER_SHARED page -- align it to 1MB (we only need 2x4KB)
1254 Base
= MmAllocateMemoryWithType(2 * 1024 * 1024, LoaderStartupPcrPage
);
1256 Base
= (PVOID
)ROUND_UP(Base
, 1 * 1024 * 1024);
1257 ArmLoaderBlock
->u
.Arm
.PcrPage
= (ULONG
)Base
>> PDE_SHIFT
;
1260 // Build an entry for the KPCR and KUSER_SHARED_DATA
1262 Status
= ArmCreateMemoryDescriptor(LoaderStartupPcrPage
,
1263 (ULONG_PTR
)MemBase
>> PAGE_SHIFT
,
1264 (2 * 1024 * 1024) / PAGE_SIZE
,
1267 if (Status
!= STATUS_SUCCESS
) return;
1270 // Allocate PDR pages -- align them to 1MB (we only need 3x4KB)
1272 Base
= MmAllocateMemoryWithType(4 * 1024 * 1024, LoaderStartupPdrPage
);
1274 Base
= (PVOID
)ROUND_UP(Base
, 1 * 1024 * 1024);
1275 ArmLoaderBlock
->u
.Arm
.PdrPage
= (ULONG
)Base
>> PDE_SHIFT
;
1278 // Build an entry for the PDR, PRCB and initial KPROCESS/KTHREAD
1280 Status
= ArmCreateMemoryDescriptor(LoaderStartupPdrPage
,
1281 (ULONG_PTR
)MemBase
>> PAGE_SHIFT
,
1282 (4 * 1024 * 1024) / PAGE_SIZE
,
1285 if (Status
!= STATUS_SUCCESS
) return;
1288 // Set initial PRCB, Thread and Process on the last PDR page
1290 Base
= (PVOID
)((ULONG
)Base
+ 2 * 1024 * 1024);
1291 ArmLoaderBlock
->Prcb
= KSEG0_BASE
| (ULONG
)Base
;
1292 ArmLoaderBlock
->Process
= ArmLoaderBlock
->Prcb
+ sizeof(KPRCB
);
1293 ArmLoaderBlock
->Thread
= ArmLoaderBlock
->Process
+ sizeof(EPROCESS
);
1296 // Check if we're booting from RAM disk
1298 if ((gRamDiskBase
) && (gRamDiskSize
))
1301 // Allocate a descriptor to describe it
1303 Status
= ArmCreateMemoryDescriptor(LoaderXIPRom
,
1304 (ULONG_PTR
)gRamDiskBase
>> PAGE_SHIFT
,
1305 gRamDiskSize
/ PAGE_SIZE
,
1308 if (Status
!= STATUS_SUCCESS
) return;
1314 NextEntry
= ArmLoaderBlock
->MemoryDescriptorListHead
.Flink
;
1315 while (NextEntry
!= &ArmLoaderBlock
->MemoryDescriptorListHead
)
1318 // Remember the physical entry
1320 OldEntry
= NextEntry
->Flink
;
1325 NextEntry
->Flink
= (PVOID
)((ULONG_PTR
)NextEntry
->Flink
| KSEG0_BASE
);
1326 NextEntry
->Blink
= (PVOID
)((ULONG_PTR
)NextEntry
->Blink
| KSEG0_BASE
);
1331 NextEntry
= OldEntry
;
1335 // Now edit the root itself
1337 NextEntry
->Flink
= (PVOID
)((ULONG_PTR
)NextEntry
->Flink
| KSEG0_BASE
);
1338 NextEntry
->Blink
= (PVOID
)((ULONG_PTR
)NextEntry
->Blink
| KSEG0_BASE
);
1341 // Allocate ARC disk structure
1343 ArcDiskInformation
= ArmAllocateFromSharedHeap(sizeof(ARC_DISK_INFORMATION
));
1344 InitializeListHead(&ArcDiskInformation
->DiskSignatureListHead
);
1345 ArmLoaderBlock
->ArcDiskInformation
= (PVOID
)((ULONG_PTR
)ArcDiskInformation
| KSEG0_BASE
);
1351 MachDiskReadLogicalSectors(0x49, 0ULL, 1, (PVOID
)DISKREADBUFFER
);
1352 Buffer
= (ULONG
*)DISKREADBUFFER
;
1353 Mbr
= (PMASTER_BOOT_RECORD
)DISKREADBUFFER
;
1356 // Calculate the MBR checksum
1358 for (i
= 0; i
< 128; i
++) Checksum
+= Buffer
[i
];
1359 Checksum
= ~Checksum
+ 1;
1363 // Allocate a disk signature and fill it out
1365 ArcDiskSignature
= ArmAllocateFromSharedHeap(sizeof(ARC_DISK_SIGNATURE
));
1366 ArcDiskSignature
->Signature
= 0xBADAB00B;// Mbr->Signature;
1367 ArcDiskSignature
->CheckSum
= 0xFAB4BEEF; //Checksum;
1370 // Allocare a string for the name and fill it out
1372 ArcDiskSignature
->ArcName
= ArmAllocateFromSharedHeap(256);
1373 sprintf(ArcDiskSignature
->ArcName
, "multi(0)disk(0)rdisk(%lu)", ArcDiskCount
++);
1374 ArcDiskSignature
->ArcName
= (PVOID
)((ULONG_PTR
)ArcDiskSignature
->ArcName
| KSEG0_BASE
);
1377 // Insert the descriptor into the list
1379 InsertTailList(&ArcDiskInformation
->DiskSignatureListHead
,
1380 &ArcDiskSignature
->ListEntry
);
1383 // Loop ARC disk list
1385 NextEntry
= ArcDiskInformation
->DiskSignatureListHead
.Flink
;
1386 while (NextEntry
!= &ArcDiskInformation
->DiskSignatureListHead
)
1389 // Remember the physical entry
1391 OldEntry
= NextEntry
->Flink
;
1396 NextEntry
->Flink
= (PVOID
)((ULONG_PTR
)NextEntry
->Flink
| KSEG0_BASE
);
1397 NextEntry
->Blink
= (PVOID
)((ULONG_PTR
)NextEntry
->Blink
| KSEG0_BASE
);
1402 NextEntry
= OldEntry
;
1406 // Now edit the root itself
1408 NextEntry
->Flink
= (PVOID
)((ULONG_PTR
)NextEntry
->Flink
| KSEG0_BASE
);
1409 NextEntry
->Blink
= (PVOID
)((ULONG_PTR
)NextEntry
->Blink
| KSEG0_BASE
);
1413 FrLdrStartup(IN ULONG Magic
)
1417 // Disable interrupts (already done)
1421 // Set proper CPSR (already done)
1425 // Initialize the page directory
1427 PageDir
= ArmSetupPageDirectory();
1430 // Initialize paging and load NTOSKRNL
1432 ArmSetupPagingAndJump(PageDir
);