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)
9 /* INCLUDES ******************************************************************/
14 OslArchTransferToKernel (
15 _In_ PLOADER_PARAMETER_BLOCK LoaderBlock
,
16 _In_ PVOID KernelEntrypoint
19 /* DATA VARIABLES ************************************************************/
21 LOADER_PARAMETER_BLOCK OslLoaderBlock
;
23 PVOID UserSharedAddress
;
24 ULONGLONG ArchXCr0BitsToClear
;
25 ULONGLONG ArchCr4BitsToClear
;
26 BOOLEAN BdDebugAfterExitBootServices
;
27 KDESCRIPTOR OslKernelGdt
;
28 KDESCRIPTOR OslKernelIdt
;
30 /* FUNCTIONS *****************************************************************/
34 _Out_ PULONG ReturnFlags
,
38 return STATUS_NOT_IMPLEMENTED
;
42 OslFwpKernelSetupPhase1 (
43 _In_ PLOADER_PARAMETER_BLOCK LoaderBlock
46 return STATUS_NOT_IMPLEMENTED
;
50 OslArchpKernelSetupPhase0 (
51 _In_ PLOADER_PARAMETER_BLOCK LoaderBlock
54 return STATUS_NOT_IMPLEMENTED
;
58 ArchRestoreProcessorFeatures (
62 /* Any XCR0 bits to clear? */
63 if (ArchXCr0BitsToClear
)
67 __xsetbv(0, __xgetbv(0) & ~ArchXCr0BitsToClear
);
69 ArchXCr0BitsToClear
= 0;
72 /* Any CR4 bits to clear? */
73 if (ArchCr4BitsToClear
)
76 __writecr4(__readcr4() & ~ArchCr4BitsToClear
);
77 ArchCr4BitsToClear
= 0;
84 _In_ PLOADER_PARAMETER_BLOCK LoaderBlock
87 /* For phase 0, do architectural setup */
90 return OslArchpKernelSetupPhase0(LoaderBlock
);
93 /* Nothing to do for Phase 1 */
96 return STATUS_SUCCESS
;
99 /* Relocate the self map */
100 BlMmRelocateSelfMap();
102 /* Zero out the HAL Heap */
103 BlMmZeroVirtualAddressRange((PVOID
)MM_HAL_VA_START
,
104 MM_HAL_VA_END
- MM_HAL_VA_START
+ 1);
106 /* Move shared user data in its place */
107 BlMmMoveVirtualAddressRange((PVOID
)KI_USER_SHARED_DATA
,
111 /* Clear XCR0/CR4 CPU features that should be disabled before boot */
112 ArchRestoreProcessorFeatures();
115 return STATUS_SUCCESS
;
119 OslExecuteTransition (
125 /* Is the debugger meant to be kept enabled throughout the boot phase? */
126 if (!BdDebugAfterExitBootServices
)
129 /* No -- disable it */
134 /* Setup Firmware for Phase 1 */
135 Status
= OslFwpKernelSetupPhase1(&OslLoaderBlock
);
136 if (NT_SUCCESS(Status
))
138 /* Setup kernel for Phase 2 */
139 Status
= OslArchKernelSetup(2, &OslLoaderBlock
);
140 if (NT_SUCCESS(Status
))
143 /* Stop the boot debugger */
146 /* Jump to the kernel entrypoint */
147 OslArchTransferToKernel(&OslLoaderBlock
, OslEntryPoint
);
149 /* Infinite loop if we got here */
154 /* Return back with the failure code */
160 _Out_ PULONG ReturnFlags
167 LARGE_INTEGER MiscMsr
;
169 /* Check if the CPU supports NX */
170 BlArchCpuId(0x80000001, 0, &CpuInfo
);
171 if (!(CpuInfo
.Edx
& 0x10000))
173 /* It doesn't, check if this is Intel */
174 EfiPrintf(L
"NX disabled: %lx\r\n", CpuInfo
.Edx
);
175 if (BlArchGetCpuVendor() == CPU_INTEL
)
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
);
187 /* Turn on NX support with the CPU-generic MSR */
188 __writemsr(MSR_EFER
, __readmsr(MSR_EFER
) | MSR_NXE
);
190 /* Load the kernel */
191 Status
= OslPrepareTarget(ReturnFlags
, &ExecuteJump
);
192 if (NT_SUCCESS(Status
) && (ExecuteJump
))
194 /* Jump to the kernel */
195 Status
= OslExecuteTransition();
198 /* Retore NX support */
199 __writemsr(MSR_EFER
, __readmsr(MSR_EFER
) ^ MSR_NXE
);
201 /* Did we manually enable NX? */
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
);
217 * The OslMain function implements the Windows Boot Application entrypoint for
220 * @param BootParameters
221 * Pointer to the Boot Application Parameter Block.
223 * @return NT_SUCCESS if the image was loaded correctly, relevant error code
230 _In_ PBOOT_APPLICATION_PARAMETER_BLOCK BootParameters
233 BL_LIBRARY_PARAMETERS LibraryParameters
;
235 PBL_RETURN_ARGUMENTS ReturnArguments
;
236 PBL_APPLICATION_ENTRY AppEntry
;
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
;
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
)))
252 /* Unrecognized, bail out */
253 Status
= STATUS_INVALID_PARAMETER_9
;
257 /* Check if CPUID 01h is supported */
258 if (BlArchIsCpuIdFunctionSupported(1))
260 /* Query CPU features */
261 BlArchCpuId(1, 0, &CpuInfo
);
263 /* Check if PAE is supported */
264 if (CpuInfo
.Edx
& 0x40)
266 EfiPrintf(L
"PAE Supported, but won't be used\r\n");
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;
281 /* Initialize the boot library */
282 Status
= BlInitializeLibrary(BootParameters
, &LibraryParameters
);
283 if (NT_SUCCESS(Status
))
285 /* For testing, draw the logo */
288 /* Call the main routine */
289 Status
= OslpMain(&Flags
);
291 /* Return the flags, and destroy the boot library */
292 ReturnArguments
->Flags
= Flags
;
297 /* Return back to boot manager */
298 ReturnArguments
->Status
= Status
;