2 * PROJECT: ReactOS Boot Loader
3 * LICENSE: GPL - See COPYING 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 /* GLOBALS ********************************************************************/
18 ULONG PageDirectoryStart
, PageDirectoryEnd
;
19 LOADER_PARAMETER_BLOCK ArmLoaderBlock
;
20 LOADER_PARAMETER_EXTENSION ArmExtension
;
21 extern ARM_TRANSLATION_TABLE ArmTranslationTable
;
22 extern ROS_KERNEL_ENTRY_POINT KernelEntryPoint
;
40 4 // 4-way associative
47 8 // 8 words per line (32 bytes)
50 /* FUNCTIONS ******************************************************************/
53 ArmSetupPageDirectory(VOID
)
55 ARM_TTB_REGISTER TtbRegister
;
56 ARM_DOMAIN_REGISTER DomainRegister
;
59 PARM_TRANSLATION_TABLE TranslationTable
;
62 // Allocate translation table buffer.
63 // During bootstrap, this will be a simple L1 (Master) Page Table with
64 // Section entries for KSEG0 and the first MB of RAM.
66 TranslationTable
= &ArmTranslationTable
;
67 if (!TranslationTable
) return;
72 TtbRegister
.AsUlong
= (ULONG
)TranslationTable
;
73 ASSERT(TtbRegister
.Reserved
== 0);
74 KeArmTranslationTableRegisterSet(TtbRegister
);
77 // Use Domain 0, enforce AP bits (client)
79 DomainRegister
.AsUlong
= 0;
80 DomainRegister
.Domain0
= ClientDomain
;
81 KeArmDomainRegisterSet(DomainRegister
);
84 // Set Fault PTEs everywhere
86 RtlZeroMemory(TranslationTable
, 4096 * sizeof(ARM_PTE
));
89 // Build the template PTE
91 Pte
.L1
.Section
.Type
= SectionPte
;
92 Pte
.L1
.Section
.Buffered
= FALSE
;
93 Pte
.L1
.Section
.Cached
= FALSE
;
94 Pte
.L1
.Section
.Reserved
= 1; // ARM926EJ-S manual recommends setting to 1
95 Pte
.L1
.Section
.Domain
= Domain0
;
96 Pte
.L1
.Section
.Access
= SupervisorAccess
;
97 Pte
.L1
.Section
.BaseAddress
= 0;
98 Pte
.L1
.Section
.Ignored
= Pte
.L1
.Section
.Ignored1
= 0;
101 // Map KSEG0 (0x80000000 - 0xA0000000) to 0x00000000 - 0x20000000
102 // In this way, the KERNEL_PHYS_ADDR (0x800000) becomes 0x80800000
103 // which is the entrypoint, just like on x86.
105 for (i
= (KSEG0_BASE
>> TTB_SHIFT
); i
< ((KSEG0_BASE
+ 0x20000000) >> TTB_SHIFT
); i
++)
108 // Write PTE and update the base address (next MB) for the next one
110 TranslationTable
->Pte
[i
] = Pte
;
111 Pte
.L1
.Section
.BaseAddress
++;
115 // Identity map the first MB of memory as well
117 Pte
.L1
.Section
.BaseAddress
= 0;
118 TranslationTable
->Pte
[0] = Pte
;
122 ArmSetupPagingAndJump(IN ULONG Magic
)
124 ARM_CONTROL_REGISTER ControlRegister
;
127 // Enable MMU, DCache and ICache
129 ControlRegister
= KeArmControlRegisterGet();
130 ControlRegister
.MmuEnabled
= TRUE
;
131 ControlRegister
.ICacheEnabled
= TRUE
;
132 ControlRegister
.DCacheEnabled
= TRUE
;
133 KeArmControlRegisterSet(ControlRegister
);
138 (*KernelEntryPoint
)(Magic
, (PVOID
)&ArmLoaderBlock
);
142 ArmPrepareForReactOS(IN BOOLEAN Setup
)
144 ARM_CACHE_REGISTER CacheReg
;
148 // Initialize the loader block
150 InitializeListHead(&ArmLoaderBlock
.BootDriverListHead
);
151 InitializeListHead(&ArmLoaderBlock
.LoadOrderListHead
);
152 InitializeListHead(&ArmLoaderBlock
.MemoryDescriptorListHead
);
155 // Setup the extension and setup block
157 ArmLoaderBlock
.Extension
= &ArmExtension
;
158 ArmLoaderBlock
.SetupLdrBlock
= NULL
;
161 // TODO: Setup memory descriptors
165 // TODO: Setup registry data
169 // TODO: Setup ARC Hardware tree data
173 // TODO: Setup NLS data
177 // TODO: Setup boot-driver data
181 // TODO: Setup extension parameters
185 // Send the command line
187 ArmLoaderBlock
.LoadOptions
= reactos_kernel_cmdline
;
190 // Setup cache information
192 CacheReg
= KeArmCacheRegisterGet();
193 ArmLoaderBlock
.u
.Arm
.FirstLevelDcacheSize
= SizeBits
[CacheReg
.DSize
];
194 ArmLoaderBlock
.u
.Arm
.FirstLevelDcacheFillSize
= LenBits
[CacheReg
.DLength
];
195 ArmLoaderBlock
.u
.Arm
.FirstLevelDcacheFillSize
<<= 2;
196 ArmLoaderBlock
.u
.Arm
.FirstLevelIcacheSize
= SizeBits
[CacheReg
.ISize
];
197 ArmLoaderBlock
.u
.Arm
.FirstLevelIcacheFillSize
= LenBits
[CacheReg
.ILength
];
198 ArmLoaderBlock
.u
.Arm
.FirstLevelIcacheFillSize
<<= 2;
199 ArmLoaderBlock
.u
.Arm
.SecondLevelDcacheSize
=
200 ArmLoaderBlock
.u
.Arm
.SecondLevelDcacheFillSize
=
201 ArmLoaderBlock
.u
.Arm
.SecondLevelIcacheSize
=
202 ArmLoaderBlock
.u
.Arm
.SecondLevelIcacheFillSize
= 0;
205 // Allocate the Interrupt stack
207 Base
= MmAllocateMemoryWithType(KERNEL_STACK_SIZE
, LoaderStartupDpcStack
);
208 ArmLoaderBlock
.u
.Arm
.InterruptStack
= KSEG0_BASE
| (ULONG
)Base
;
211 // Allocate the Kernel Boot stack
213 Base
= MmAllocateMemoryWithType(KERNEL_STACK_SIZE
, LoaderStartupKernelStack
);
214 ArmLoaderBlock
.KernelStack
= KSEG0_BASE
| (ULONG
)Base
;
217 // Allocate the Abort stack
219 Base
= MmAllocateMemoryWithType(KERNEL_STACK_SIZE
, LoaderStartupPanicStack
);
220 ArmLoaderBlock
.u
.Arm
.PanicStack
= KSEG0_BASE
| (ULONG
)Base
;
223 // Allocate the PCRs (1MB each for now!)
225 Base
= MmAllocateMemoryWithType(2 * 1024 * 1024, LoaderStartupPcrPage
);
226 ArmLoaderBlock
.u
.Arm
.PcrPage
= (ULONG
)Base
>> TTB_SHIFT
;
227 ArmLoaderBlock
.u
.Arm
.PcrPage2
= ArmLoaderBlock
.u
.Arm
.PcrPage
+ 1;
230 // Allocate PDR pages
232 Base
= MmAllocateMemoryWithType(3 * 1024 * 1024, LoaderStartupPdrPage
);
233 ArmLoaderBlock
.u
.Arm
.PdrPage
= (ULONG
)Base
>> TTB_SHIFT
;
236 // Set initial PRCB, Thread and Process on the last PDR page
238 Base
= (PVOID
)((ULONG
)Base
+ 2 * 1024 * 1024);
239 ArmLoaderBlock
.Prcb
= KSEG0_BASE
| (ULONG
)Base
;
240 ArmLoaderBlock
.Process
= ArmLoaderBlock
.Prcb
+ sizeof(KPRCB
);
241 ArmLoaderBlock
.Thread
= ArmLoaderBlock
.Process
+ sizeof(EPROCESS
);
245 FrLdrStartup(IN ULONG Magic
)
248 // Disable interrupts (aleady done)
252 // Set proper CPSR (already done)
256 // Initialize the page directory
258 ArmSetupPageDirectory();
261 // Initialize paging and load NTOSKRNL
263 TuiPrintf("Kernel Command Line: %s\n", ArmLoaderBlock
.LoadOptions
);
264 ArmSetupPagingAndJump(Magic
);