745a202b11386b8e65a62d5b0d5000ed9531d95a
[reactos.git] / reactos / boot / freeldr / freeldr / arch / arm / stubs.c
1 /*
2 * PROJECT: ReactOS Boot Loader
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: boot/freeldr/arch/arm/stubs.c
5 * PURPOSE: Non-completed ARM hardware-specific routines
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include <freeldr.h>
12 #include <internal/arm/ke.h>
13 #include <internal/arm/mm.h>
14 #include <internal/arm/intrin_i.h>
15
16 /* GLOBALS ********************************************************************/
17
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;
23
24 /* FUNCTIONS ******************************************************************/
25
26 BOOLEAN
27 ArmDiskGetDriveGeometry(IN ULONG DriveNumber,
28 OUT PGEOMETRY Geometry)
29 {
30 ASSERT(gRamDiskBase == NULL);
31 return FALSE;
32 }
33
34 BOOLEAN
35 ArmDiskReadLogicalSectors(IN ULONG DriveNumber,
36 IN ULONGLONG SectorNumber,
37 IN ULONG SectorCount,
38 IN PVOID Buffer)
39 {
40 ASSERT(gRamDiskBase == NULL);
41 return FALSE;
42 }
43
44 ULONG
45 ArmDiskGetCacheableBlockCount(IN ULONG DriveNumber)
46 {
47 ASSERT(gRamDiskBase == NULL);
48 return FALSE;
49 }
50
51 VOID
52 ArmSetupPageDirectory(VOID)
53 {
54 ARM_TTB_REGISTER TtbRegister;
55 ARM_DOMAIN_REGISTER DomainRegister;
56 ARM_PTE Pte;
57 ULONG i;
58 PARM_TRANSLATION_TABLE TranslationTable;
59
60 //
61 // Allocate translation table buffer.
62 // During bootstrap, this will be a simple L1 (Master) Page Table with
63 // Section entries for KSEG0 and the first MB of RAM.
64 //
65 TranslationTable = &ArmTranslationTable;
66 if (!TranslationTable) return;
67
68 //
69 // Set it as the TTB
70 //
71 TtbRegister.AsUlong = (ULONG)TranslationTable;
72 ASSERT(TtbRegister.Reserved == 0);
73 KeArmTranslationTableRegisterSet(TtbRegister);
74
75 //
76 // Use Domain 0, enforce AP bits (client)
77 //
78 DomainRegister.AsUlong = 0;
79 DomainRegister.Domain0 = ClientDomain;
80 KeArmDomainRegisterSet(DomainRegister);
81
82 //
83 // Set Fault PTEs everywhere
84 //
85 RtlZeroMemory(TranslationTable, 4096 * sizeof(ARM_PTE));
86
87 //
88 // Build the template PTE
89 //
90 Pte.L1.Section.Type = SectionPte;
91 Pte.L1.Section.Buffered = FALSE;
92 Pte.L1.Section.Cached = FALSE;
93 Pte.L1.Section.Reserved = 1; // ARM926EJ-S manual recommends setting to 1
94 Pte.L1.Section.Domain = Domain0;
95 Pte.L1.Section.Access = SupervisorAccess;
96 Pte.L1.Section.BaseAddress = 0;
97 Pte.L1.Section.Ignored = Pte.L1.Section.Ignored1 = 0;
98
99 //
100 // Map KSEG0 (0x80000000 - 0xA0000000) to 0x00000000 - 0x80000000
101 // In this way, the KERNEL_PHYS_ADDR (0x800000) becomes 0x80800000
102 // which is the entrypoint, just like on x86.
103 //
104 for (i = (KSEG0_BASE >> TTB_SHIFT); i < ((KSEG0_BASE + 0x20000000) >> TTB_SHIFT); i++)
105 {
106 //
107 // Write PTE and update the base address (next MB) for the next one
108 //
109 TranslationTable->Pte[i] = Pte;
110 Pte.L1.Section.BaseAddress++;
111 }
112
113 //
114 // Identity map the first MB of memory as well
115 //
116 Pte.L1.Section.BaseAddress = 0;
117 TranslationTable->Pte[0] = Pte;
118 }
119
120 VOID
121 ArmSetupPagingAndJump(IN ULONG Magic)
122 {
123 ARM_CONTROL_REGISTER ControlRegister;
124
125 //
126 // Enable MMU, DCache and ICache
127 //
128 ControlRegister = KeArmControlRegisterGet();
129 ControlRegister.MmuEnabled = TRUE;
130 ControlRegister.ICacheEnabled = TRUE;
131 ControlRegister.DCacheEnabled = TRUE;
132 KeArmControlRegisterSet(ControlRegister);
133
134 //
135 // Jump to Kernel
136 //
137 (*KernelEntryPoint)(Magic, (PVOID)&ArmLoaderBlock);
138 }
139
140 VOID
141 ArmPrepareForReactOS(IN BOOLEAN Setup)
142 {
143 //
144 // Initialize the loader block
145 //
146 InitializeListHead(&ArmLoaderBlock.BootDriverListHead);
147 InitializeListHead(&ArmLoaderBlock.LoadOrderListHead);
148 InitializeListHead(&ArmLoaderBlock.MemoryDescriptorListHead);
149
150 //
151 // Setup the extension and setup block
152 //
153 ArmLoaderBlock.Extension = &ArmExtension;
154 ArmLoaderBlock.SetupLdrBlock = NULL;
155
156 //
157 // TODO: Setup memory descriptors
158 //
159
160 //
161 // TODO: Setup registry data
162 //
163
164 //
165 // TODO: Setup ARC Hardware tree data
166 //
167
168 //
169 // TODO: Setup NLS data
170 //
171
172 //
173 // TODO: Setup boot-driver data
174 //
175
176 //
177 // TODO: Setup extension parameters
178 //
179
180 //
181 // TODO: Setup ARM-specific block
182 //
183 }
184
185 PCONFIGURATION_COMPONENT_DATA
186 ArmHwDetect(VOID)
187 {
188 PCONFIGURATION_COMPONENT_DATA RootNode;
189
190 //
191 // Create the root node
192 //
193 FldrCreateSystemKey(&RootNode);
194
195 //
196 // Write null component information
197 //
198 FldrSetComponentInformation(RootNode,
199 0x0,
200 0x0,
201 0xFFFFFFFF);
202
203 //
204 // TODO:
205 // There's no such thing as "PnP" on embedded hardware.
206 // The boot loader will send us a device tree, similar to ACPI
207 // or OpenFirmware device trees, and we will convert it to ARC.
208 //
209
210 //
211 // Return the root node
212 //
213 return RootNode;
214 }
215
216 ULONG
217 ArmMemGetMemoryMap(OUT PBIOS_MEMORY_MAP BiosMemoryMap,
218 IN ULONG MaxMemoryMapSize)
219 {
220 //
221 // Return whatever the board returned to us (CS0 Base + Size and FLASH0)
222 //
223 RtlCopyMemory(BiosMemoryMap,
224 ArmBoardBlock->MemoryMap,
225 ArmBoardBlock->MemoryMapEntryCount * sizeof(BIOS_MEMORY_MAP));
226 return ArmBoardBlock->MemoryMapEntryCount;
227 }
228
229 VOID
230 MachInit(IN PCCH CommandLine)
231 {
232 //
233 // Setup board-specific ARM routines
234 //
235 switch (ArmBoardBlock->BoardType)
236 {
237 //
238 // Check for Feroceon-base boards
239 //
240 case MACH_TYPE_FEROCEON:
241
242 //
243 // These boards use a UART16550. Set us up for 115200 bps
244 //
245 ArmFeroSerialInit(115200);
246 MachVtbl.ConsPutChar = ArmFeroPutChar;
247 MachVtbl.ConsKbHit = ArmFeroKbHit;
248 MachVtbl.ConsGetCh = ArmFeroGetCh;
249 break;
250
251 //
252 // Check for ARM Versatile PB boards
253 //
254 case MACH_TYPE_VERSATILE_PB:
255
256 //
257 // These boards use a PrimeCell UART (PL011)
258 //
259 ArmVersaSerialInit(115200);
260 MachVtbl.ConsPutChar = ArmVersaPutChar;
261 MachVtbl.ConsKbHit = ArmVersaKbHit;
262 MachVtbl.ConsGetCh = ArmVersaGetCh;
263 break;
264
265 default:
266 ASSERT(FALSE);
267 }
268
269 //
270 // Setup generic ARM routines for all boards
271 //
272 MachVtbl.PrepareForReactOS = ArmPrepareForReactOS;
273 MachVtbl.GetMemoryMap = ArmMemGetMemoryMap;
274 MachVtbl.HwDetect = ArmHwDetect;
275
276 //
277 // Setup disk I/O routines, switch to ramdisk ones for non-NAND boot
278 //
279 MachVtbl.DiskReadLogicalSectors = ArmDiskReadLogicalSectors;
280 MachVtbl.DiskGetDriveGeometry = ArmDiskGetDriveGeometry;
281 MachVtbl.DiskGetCacheableBlockCount = ArmDiskGetCacheableBlockCount;
282 RamDiskSwitchFromBios();
283
284 //
285 // Now set default disk handling routines -- we don't need to override
286 //
287 MachVtbl.DiskGetBootVolume = DiskGetBootVolume;
288 MachVtbl.DiskGetSystemVolume = DiskGetSystemVolume;
289 MachVtbl.DiskGetBootPath = DiskGetBootPath;
290 MachVtbl.DiskGetBootDevice = DiskGetBootDevice;
291 MachVtbl.DiskBootingFromFloppy = DiskBootingFromFloppy;
292 MachVtbl.DiskNormalizeSystemPath = DiskNormalizeSystemPath;
293 MachVtbl.DiskGetPartitionEntry = DiskGetPartitionEntry;
294
295 //
296 // We can now print to the console
297 //
298 TuiPrintf("%s for ARM\n", GetFreeLoaderVersionString());
299 TuiPrintf("Bootargs: %s\n", CommandLine);
300 }
301
302 VOID
303 FrLdrStartup(IN ULONG Magic)
304 {
305 //
306 // Disable interrupts (aleady done)
307 //
308
309 //
310 // Set proper CPSR (already done)
311 //
312
313 //
314 // Initialize the page directory
315 //
316 ArmSetupPageDirectory();
317
318 //
319 // Initialize paging and load NTOSKRNL
320 //
321 ArmSetupPagingAndJump(Magic);
322 }