[ROSLOAD]: Continue work on loader
[reactos.git] / boot / environ / app / rosload / rosload.c
1 /*
2 * COPYRIGHT: See COPYING.ARM in the top level directory
3 * PROJECT: ReactOS UEFI OS Loader
4 * FILE: boot/environ/app/rosload/rosload.c
5 * PURPOSE: OS Loader Entrypoint
6 * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include "rosload.h"
12
13 NTSTATUS
14 OslArchTransferToKernel (
15 _In_ PLOADER_PARAMETER_BLOCK LoaderBlock,
16 _In_ PVOID KernelEntrypoint
17 );
18
19 /* DATA VARIABLES ************************************************************/
20
21 LOADER_PARAMETER_BLOCK OslLoaderBlock;
22 PVOID OslEntryPoint;
23 PVOID UserSharedAddress;
24 ULONGLONG ArchXCr0BitsToClear;
25 ULONGLONG ArchCr4BitsToClear;
26 BOOLEAN BdDebugAfterExitBootServices;
27 KDESCRIPTOR OslKernelGdt;
28 KDESCRIPTOR OslKernelIdt;
29
30 /* FUNCTIONS *****************************************************************/
31
32 NTSTATUS
33 OslPrepareTarget (
34 _Out_ PULONG ReturnFlags,
35 _Out_ PBOOLEAN Jump
36 )
37 {
38 return STATUS_NOT_IMPLEMENTED;
39 }
40
41 NTSTATUS
42 OslFwpKernelSetupPhase1 (
43 _In_ PLOADER_PARAMETER_BLOCK LoaderBlock
44 )
45 {
46 return STATUS_NOT_IMPLEMENTED;
47 }
48
49 NTSTATUS
50 OslArchpKernelSetupPhase0 (
51 _In_ PLOADER_PARAMETER_BLOCK LoaderBlock
52 )
53 {
54 return STATUS_NOT_IMPLEMENTED;
55 }
56
57 VOID
58 ArchRestoreProcessorFeatures (
59 VOID
60 )
61 {
62 /* Any XCR0 bits to clear? */
63 if (ArchXCr0BitsToClear)
64 {
65 /* Clear them */
66 #ifdef _MSC_VER
67 __xsetbv(0, __xgetbv(0) & ~ArchXCr0BitsToClear);
68 #endif
69 ArchXCr0BitsToClear = 0;
70 }
71
72 /* Any CR4 bits to clear? */
73 if (ArchCr4BitsToClear)
74 {
75 /* Clear them */
76 __writecr4(__readcr4() & ~ArchCr4BitsToClear);
77 ArchCr4BitsToClear = 0;
78 }
79 }
80
81 NTSTATUS
82 OslArchKernelSetup (
83 _In_ ULONG Phase,
84 _In_ PLOADER_PARAMETER_BLOCK LoaderBlock
85 )
86 {
87 /* For phase 0, do architectural setup */
88 if (Phase == 0)
89 {
90 return OslArchpKernelSetupPhase0(LoaderBlock);
91 }
92
93 /* Nothing to do for Phase 1 */
94 if (Phase == 1)
95 {
96 return STATUS_SUCCESS;
97 }
98
99 /* Relocate the self map */
100 BlMmRelocateSelfMap();
101
102 /* Zero out the HAL Heap */
103 BlMmZeroVirtualAddressRange((PVOID)MM_HAL_VA_START,
104 MM_HAL_VA_END - MM_HAL_VA_START + 1);
105
106 /* Move shared user data in its place */
107 BlMmMoveVirtualAddressRange((PVOID)KI_USER_SHARED_DATA,
108 UserSharedAddress,
109 PAGE_SIZE);
110
111 /* Clear XCR0/CR4 CPU features that should be disabled before boot */
112 ArchRestoreProcessorFeatures();
113
114 /* Good to go */
115 return STATUS_SUCCESS;
116 }
117
118 NTSTATUS
119 OslExecuteTransition (
120 VOID
121 )
122 {
123 NTSTATUS Status;
124
125 /* Is the debugger meant to be kept enabled throughout the boot phase? */
126 if (!BdDebugAfterExitBootServices)
127 {
128 #ifdef BL_KD_SUPPORT
129 /* No -- disable it */
130 BlBdStop();
131 #endif
132 }
133
134 /* Setup Firmware for Phase 1 */
135 Status = OslFwpKernelSetupPhase1(&OslLoaderBlock);
136 if (NT_SUCCESS(Status))
137 {
138 /* Setup kernel for Phase 2 */
139 Status = OslArchKernelSetup(2, &OslLoaderBlock);
140 if (NT_SUCCESS(Status))
141 {
142 #ifdef BL_KD_SUPPORT
143 /* Stop the boot debugger */
144 BlBdStop();
145 #endif
146 /* Jump to the kernel entrypoint */
147 OslArchTransferToKernel(&OslLoaderBlock, OslEntryPoint);
148
149 /* Infinite loop if we got here */
150 for (;;);
151 }
152 }
153
154 /* Return back with the failure code */
155 return Status;
156 }
157
158 NTSTATUS
159 OslpMain (
160 _Out_ PULONG ReturnFlags
161 )
162 {
163 CPU_INFO CpuInfo;
164 BOOLEAN NxEnabled;
165 NTSTATUS Status;
166 BOOLEAN ExecuteJump;
167 LARGE_INTEGER MiscMsr;
168
169 /* Check if the CPU supports NX */
170 BlArchCpuId(0x80000001, 0, &CpuInfo);
171 if (!(CpuInfo.Edx & 0x10000))
172 {
173 /* It doesn't, check if this is Intel */
174 EfiPrintf(L"NX disabled: %lx\r\n", CpuInfo.Edx);
175 if (BlArchGetCpuVendor() == CPU_INTEL)
176 {
177 /* Then turn off the MSR disable feature for it, enabling NX */
178 MiscMsr.QuadPart = __readmsr(MSR_IA32_MISC_ENABLE);
179 EfiPrintf(L"NX being turned on: %llx\r\n", MiscMsr.QuadPart);
180 MiscMsr.HighPart &= MSR_XD_ENABLE_MASK;
181 MiscMsr.QuadPart = __readmsr(MSR_IA32_MISC_ENABLE);
182 __writemsr(MSR_IA32_MISC_ENABLE, MiscMsr.QuadPart);
183 NxEnabled = TRUE;
184 }
185 }
186
187 /* Turn on NX support with the CPU-generic MSR */
188 __writemsr(MSR_EFER, __readmsr(MSR_EFER) | MSR_NXE);
189
190 /* Load the kernel */
191 Status = OslPrepareTarget(ReturnFlags, &ExecuteJump);
192 if (NT_SUCCESS(Status) && (ExecuteJump))
193 {
194 /* Jump to the kernel */
195 Status = OslExecuteTransition();
196 }
197
198 /* Retore NX support */
199 __writemsr(MSR_EFER, __readmsr(MSR_EFER) ^ MSR_NXE);
200
201 /* Did we manually enable NX? */
202 if (NxEnabled)
203 {
204 /* Turn it back off */
205 MiscMsr.QuadPart = __readmsr(MSR_IA32_MISC_ENABLE);
206 MiscMsr.HighPart |= ~MSR_XD_ENABLE_MASK;
207 __writemsr(MSR_IA32_MISC_ENABLE, MiscMsr.QuadPart);
208 }
209
210 /* Go back */
211 return Status;
212 }
213
214 /*++
215 * @name OslMain
216 *
217 * The OslMain function implements the Windows Boot Application entrypoint for
218 * the OS Loader.
219 *
220 * @param BootParameters
221 * Pointer to the Boot Application Parameter Block.
222 *
223 * @return NT_SUCCESS if the image was loaded correctly, relevant error code
224 * otherwise.
225 *
226 *--*/
227 NTSTATUS
228 NTAPI
229 OslMain (
230 _In_ PBOOT_APPLICATION_PARAMETER_BLOCK BootParameters
231 )
232 {
233 BL_LIBRARY_PARAMETERS LibraryParameters;
234 NTSTATUS Status;
235 PBL_RETURN_ARGUMENTS ReturnArguments;
236 PBL_APPLICATION_ENTRY AppEntry;
237 CPU_INFO CpuInfo;
238 ULONG Flags;
239
240 /* Get the return arguments structure, and set our version */
241 ReturnArguments = (PBL_RETURN_ARGUMENTS)((ULONG_PTR)BootParameters +
242 BootParameters->ReturnArgumentsOffset);
243 ReturnArguments->Version = BL_RETURN_ARGUMENTS_VERSION;
244
245 /* Get the application entry, and validate it */
246 AppEntry = (PBL_APPLICATION_ENTRY)((ULONG_PTR)BootParameters +
247 BootParameters->AppEntryOffset);
248 if (!RtlEqualMemory(AppEntry->Signature,
249 BL_APP_ENTRY_SIGNATURE,
250 sizeof(AppEntry->Signature)))
251 {
252 /* Unrecognized, bail out */
253 Status = STATUS_INVALID_PARAMETER_9;
254 goto Quickie;
255 }
256
257 /* Check if CPUID 01h is supported */
258 if (BlArchIsCpuIdFunctionSupported(1))
259 {
260 /* Query CPU features */
261 BlArchCpuId(1, 0, &CpuInfo);
262
263 /* Check if PAE is supported */
264 if (CpuInfo.Edx & 0x40)
265 {
266 EfiPrintf(L"PAE Supported, but won't be used\r\n");
267 }
268 }
269
270 /* Setup the boot library parameters for this application */
271 BlSetupDefaultParameters(&LibraryParameters);
272 LibraryParameters.TranslationType = BlVirtual;
273 LibraryParameters.LibraryFlags = BL_LIBRARY_FLAG_ZERO_HEAP_ALLOCATIONS_ON_FREE |
274 BL_LIBRARY_FLAG_REINITIALIZE_ALL;
275 LibraryParameters.MinimumAllocationCount = 1024;
276 LibraryParameters.MinimumHeapSize = 2 * 1024 * 1024;
277 LibraryParameters.HeapAllocationAttributes = BlMemoryKernelRange;
278 LibraryParameters.FontBaseDirectory = L"\\Reactos\\Boot\\Fonts";
279 LibraryParameters.DescriptorCount = 512;
280
281 /* Initialize the boot library */
282 Status = BlInitializeLibrary(BootParameters, &LibraryParameters);
283 if (NT_SUCCESS(Status))
284 {
285 /* For testing, draw the logo */
286 OslDrawLogo();
287
288 /* Call the main routine */
289 Status = OslpMain(&Flags);
290
291 /* Return the flags, and destroy the boot library */
292 ReturnArguments->Flags = Flags;
293 BlDestroyLibrary();
294 }
295
296 Quickie:
297 /* Return back to boot manager */
298 ReturnArguments->Status = Status;
299 return Status;
300 }
301