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 PLOADER_PARAMETER_BLOCK OslLoaderBlock
;
23 PVOID UserSharedAddress
;
24 ULONGLONG ArchXCr0BitsToClear
;
25 ULONGLONG ArchCr4BitsToClear
;
26 BOOLEAN BdDebugAfterExitBootServices
;
27 KDESCRIPTOR OslKernelGdt
;
28 KDESCRIPTOR OslKernelIdt
;
30 ULONG_PTR OslImcHiveHandle
;
31 ULONG_PTR OslMachineHiveHandle
;
32 ULONG_PTR OslElamHiveHandle
;
33 ULONG_PTR OslSystemHiveHandle
;
35 PBL_DEVICE_DESCRIPTOR OslLoadDevice
;
39 LIST_ENTRY OslFreeMemoryDesctiptorsList
;
40 LIST_ENTRY OslFinalMemoryMap
;
41 LIST_ENTRY OslCoreExtensionSubGroups
[2];
42 LIST_ENTRY OslLoadedFirmwareDriverList
;
44 BL_BUFFER_DESCRIPTOR OslFinalMemoryMapDescriptorsBuffer
;
46 GUID OslApplicationIdentifier
;
48 ULONG OslResetBootStatus
;
49 BOOLEAN OslImcProcessingValid
;
50 ULONG OslFreeMemoryDesctiptorsListSize
;
51 PVOID OslMemoryDescriptorBuffer
;
53 /* FUNCTIONS *****************************************************************/
58 _In_ ULONG Parameter1
,
59 _In_ ULONG_PTR Parameter2
,
60 _In_ ULONG_PTR Parameter3
63 /* For now just do this */
64 BlStatusPrint(L
"FATAL ERROR IN ROSLOAD: %lx\n", ErrorCode
);
72 /* For now just do this */
73 BlStatusPrint(L
"BOOT ABORTED: %lx\n", Status
);
77 OslBlStatusErrorHandler (
79 _In_ ULONG Parameter1
,
80 _In_ ULONG_PTR Parameter2
,
81 _In_ ULONG_PTR Parameter3
,
82 _In_ ULONG_PTR Parameter4
85 /* We only filter error code 4 */
88 return STATUS_NOT_IMPLEMENTED
;
91 /* Handle error 4 as a fatal error 3 internally */
92 OslFatalErrorEx(3, Parameter1
, Parameter2
, Parameter3
);
93 return STATUS_SUCCESS
;
97 OslpSanitizeLoadOptionsString (
98 _In_ PWCHAR OptionString
,
99 _In_ PWCHAR SanitizeString
107 OslpSanitizeStringOptions (
108 _In_ PBL_BCD_OPTION BcdOptions
116 OslpRemoveInternalApplicationOptions (
124 Status
= STATUS_SUCCESS
;
126 /* Remove attempts to disable integrity checks or ELAM driver load */
127 BlRemoveBootOption(BlpApplicationEntry
.BcdData
,
128 BcdLibraryBoolean_DisableIntegrityChecks
);
129 BlRemoveBootOption(BlpApplicationEntry
.BcdData
,
130 BcdOSLoaderBoolean_DisableElamDrivers
);
132 /* Get the command-line parameters, if any */
133 Status
= BlGetBootOptionString(BlpApplicationEntry
.BcdData
,
134 BcdLibraryString_LoadOptionsString
,
136 if (NT_SUCCESS(Status
))
138 /* Conver to upper case */
141 /* Remove the existing one */
142 //BlRemoveBootOption(BlpApplicationEntry.BcdData,
143 // BcdLibraryString_LoadOptionsString);
145 /* Sanitize strings we don't want */
146 OslpSanitizeLoadOptionsString(LoadString
, L
"DISABLE_INTEGRITY_CHECKS");
147 OslpSanitizeLoadOptionsString(LoadString
, L
"NOINTEGRITYCHECKS");
148 OslpSanitizeLoadOptionsString(LoadString
, L
"DISABLEELAMDRIVERS");
150 /* Add the sanitized one back */
151 //Status = BlAppendBootOptionsString(&BlpApplicationEntry,
152 // BcdLibraryString_LoadOptionsString,
155 /* Free the original BCD one */
156 BlMmFreeHeap(LoadString
);
159 /* One more pass for secure-boot options */
160 OslpSanitizeStringOptions(BlpApplicationEntry
.BcdData
);
168 _Out_ PULONG ReturnFlags
,
174 PBL_DEVICE_DESCRIPTOR OsDevice
;
176 SIZE_T RootLength
, RootLengthWithSep
;
178 ULONG64 StartPerf
, EndPerf
;
180 /* Assume no flags */
183 /* Make all registry handles invalid */
184 OslImcHiveHandle
= -1;
185 OslMachineHiveHandle
= -1;
186 OslElamHiveHandle
= -1;
187 OslSystemHiveHandle
= -1;
189 /* Initialize memory lists */
190 InitializeListHead(&OslFreeMemoryDesctiptorsList
);
191 InitializeListHead(&OslFinalMemoryMap
);
192 InitializeListHead(&OslLoadedFirmwareDriverList
);
193 for (i
= 0; i
< RTL_NUMBER_OF(OslCoreExtensionSubGroups
); i
++)
195 InitializeListHead(&OslCoreExtensionSubGroups
[i
]);
198 /* Initialize the memory map descriptor buffer */
199 RtlZeroMemory(&OslFinalMemoryMapDescriptorsBuffer
,
200 sizeof(OslFinalMemoryMapDescriptorsBuffer
));
202 /* Initialize general pointers */
203 OslLoadDevice
= NULL
;
204 OslLoadOptions
= NULL
;
205 OslSystemRoot
= NULL
;
206 OslLoaderBlock
= NULL
;
207 OslMemoryDescriptorBuffer
= NULL
;
209 /* Initialize general variables */
210 OslResetBootStatus
= 0;
211 OslImcProcessingValid
= FALSE
;
212 OslFreeMemoryDesctiptorsListSize
= 0;
214 /* Capture the current TSC */
215 StartPerf
= BlArchGetPerformanceCounter();
217 #ifdef BL_TPM_SUPPORT
218 BlpSbdiCurrentApplicationType
= 0x10200003;
221 /* Register an error handler */
222 BlpStatusErrorHandler
= OslBlStatusErrorHandler
;
224 /* Get the application identifier and save it */
225 AppId
= BlGetApplicationIdentifier();
228 OslApplicationIdentifier
= *AppId
;
232 #ifdef BL_ETW_SUPPORT
233 TraceLoggingRegister(&TlgOslBootProviderProv
);
236 /* Remove dangerous BCD options */
237 Status
= OslpRemoveInternalApplicationOptions();
238 if (!NT_SUCCESS(Status
))
243 /* Get the OS device */
244 Status
= BlGetBootOptionDevice(BlpApplicationEntry
.BcdData
,
245 BcdOSLoaderDevice_OSDevice
,
248 if (!NT_SUCCESS(Status
))
253 /* If the OS device is the boot device, use the one provided by bootlib */
254 if (OsDevice
->DeviceType
== BootDevice
)
256 OsDevice
= BlpBootDevice
;
259 /* Save it as a global for later */
260 OslLoadDevice
= OsDevice
;
262 /* Get the system root */
263 Status
= BlGetBootOptionString(BlpApplicationEntry
.BcdData
,
264 BcdOSLoaderString_SystemRoot
,
266 if (!NT_SUCCESS(Status
))
271 EfiPrintf(L
"System root: %s\r\n", SystemRoot
);
273 /* Get the system root length and make sure it's slash-terminated */
274 RootLength
= wcslen(SystemRoot
);
275 if (SystemRoot
[RootLength
- 1] == OBJ_NAME_PATH_SEPARATOR
)
277 /* Perfect, set it */
278 OslSystemRoot
= SystemRoot
;
282 /* Allocate a new buffer large enough to contain the slash */
283 RootLengthWithSep
= RootLength
+ sizeof(OBJ_NAME_PATH_SEPARATOR
);
284 OslSystemRoot
= BlMmAllocateHeap(RootLengthWithSep
* sizeof(WCHAR
));
287 /* Bail out if we're out of memory */
288 Status
= STATUS_NO_MEMORY
;
292 /* Make a copy of the path, adding the separator */
293 wcscpy(OslSystemRoot
, SystemRoot
);
294 wcscat(OslSystemRoot
, L
"\\");
296 /* Free the original one from the BCD library */
297 BlMmFreeHeap(SystemRoot
);
300 Status
= STATUS_NOT_IMPLEMENTED
;
303 EndPerf
= BlArchGetPerformanceCounter();
304 EfiPrintf(L
"Delta: %lld\r\n", EndPerf
- StartPerf
);
307 #if BL_BITLOCKER_SUPPORT
308 /* Destroy the RNG/AES library for BitLocker */
309 SymCryptRngAesUninstantiate();
313 OslAbortBoot(Status
);
315 /* This is a failure path, so never do the jump */
318 /* Return error code */
323 OslFwpKernelSetupPhase1 (
324 _In_ PLOADER_PARAMETER_BLOCK LoaderBlock
327 return STATUS_NOT_IMPLEMENTED
;
331 OslArchpKernelSetupPhase0 (
332 _In_ PLOADER_PARAMETER_BLOCK LoaderBlock
335 return STATUS_NOT_IMPLEMENTED
;
339 ArchRestoreProcessorFeatures (
343 /* Any XCR0 bits to clear? */
344 if (ArchXCr0BitsToClear
)
347 #if defined(_MSC_VER) && !defined(__clang__)
348 __xsetbv(0, __xgetbv(0) & ~ArchXCr0BitsToClear
);
350 ArchXCr0BitsToClear
= 0;
353 /* Any CR4 bits to clear? */
354 if (ArchCr4BitsToClear
)
357 __writecr4(__readcr4() & ~ArchCr4BitsToClear
);
358 ArchCr4BitsToClear
= 0;
365 _In_ PLOADER_PARAMETER_BLOCK LoaderBlock
368 /* For phase 0, do architectural setup */
371 return OslArchpKernelSetupPhase0(LoaderBlock
);
374 /* Nothing to do for Phase 1 */
377 return STATUS_SUCCESS
;
380 /* Relocate the self map */
381 BlMmRelocateSelfMap();
383 /* Zero out the HAL Heap */
384 BlMmZeroVirtualAddressRange((PVOID
)MM_HAL_VA_START
,
385 MM_HAL_VA_END
- MM_HAL_VA_START
+ 1);
387 /* Move shared user data in its place */
388 BlMmMoveVirtualAddressRange((PVOID
)KI_USER_SHARED_DATA
,
392 /* Clear XCR0/CR4 CPU features that should be disabled before boot */
393 ArchRestoreProcessorFeatures();
396 return STATUS_SUCCESS
;
400 OslExecuteTransition (
406 /* Is the debugger meant to be kept enabled throughout the boot phase? */
407 if (!BdDebugAfterExitBootServices
)
410 /* No -- disable it */
415 /* Setup Firmware for Phase 1 */
416 Status
= OslFwpKernelSetupPhase1(OslLoaderBlock
);
417 if (NT_SUCCESS(Status
))
419 /* Setup kernel for Phase 2 */
420 Status
= OslArchKernelSetup(2, OslLoaderBlock
);
421 if (NT_SUCCESS(Status
))
424 /* Stop the boot debugger */
427 /* Jump to the kernel entrypoint */
428 OslArchTransferToKernel(OslLoaderBlock
, OslEntryPoint
);
430 /* Infinite loop if we got here */
435 /* Return back with the failure code */
441 _Out_ PULONG ReturnFlags
448 LARGE_INTEGER MiscMsr
;
450 /* Check if the CPU supports NX */
451 BlArchCpuId(0x80000001, 0, &CpuInfo
);
452 if (!(CpuInfo
.Edx
& 0x10000))
454 /* It doesn't, check if this is Intel */
455 EfiPrintf(L
"NX disabled: %lx\r\n", CpuInfo
.Edx
);
456 if (BlArchGetCpuVendor() == CPU_INTEL
)
458 /* Then turn off the MSR disable feature for it, enabling NX */
459 MiscMsr
.QuadPart
= __readmsr(MSR_IA32_MISC_ENABLE
);
460 EfiPrintf(L
"NX being turned on: %llx\r\n", MiscMsr
.QuadPart
);
461 MiscMsr
.HighPart
&= MSR_XD_ENABLE_MASK
;
462 MiscMsr
.QuadPart
= __readmsr(MSR_IA32_MISC_ENABLE
);
463 __writemsr(MSR_IA32_MISC_ENABLE
, MiscMsr
.QuadPart
);
468 /* Turn on NX support with the CPU-generic MSR */
469 __writemsr(MSR_EFER
, __readmsr(MSR_EFER
) | MSR_NXE
);
471 /* Load the kernel */
472 Status
= OslPrepareTarget(ReturnFlags
, &ExecuteJump
);
473 if (NT_SUCCESS(Status
) && (ExecuteJump
))
475 /* Jump to the kernel */
476 Status
= OslExecuteTransition();
479 /* Retore NX support */
480 __writemsr(MSR_EFER
, __readmsr(MSR_EFER
) ^ MSR_NXE
);
482 /* Did we manually enable NX? */
485 /* Turn it back off */
486 MiscMsr
.QuadPart
= __readmsr(MSR_IA32_MISC_ENABLE
);
487 MiscMsr
.HighPart
|= ~MSR_XD_ENABLE_MASK
;
488 __writemsr(MSR_IA32_MISC_ENABLE
, MiscMsr
.QuadPart
);
498 * The OslMain function implements the Windows Boot Application entrypoint for
501 * @param BootParameters
502 * Pointer to the Boot Application Parameter Block.
504 * @return NT_SUCCESS if the image was loaded correctly, relevant error code
511 _In_ PBOOT_APPLICATION_PARAMETER_BLOCK BootParameters
514 BL_LIBRARY_PARAMETERS LibraryParameters
;
516 PBL_RETURN_ARGUMENTS ReturnArguments
;
517 PBL_APPLICATION_ENTRY AppEntry
;
521 /* Get the return arguments structure, and set our version */
522 ReturnArguments
= (PBL_RETURN_ARGUMENTS
)((ULONG_PTR
)BootParameters
+
523 BootParameters
->ReturnArgumentsOffset
);
524 ReturnArguments
->Version
= BL_RETURN_ARGUMENTS_VERSION
;
526 /* Get the application entry, and validate it */
527 AppEntry
= (PBL_APPLICATION_ENTRY
)((ULONG_PTR
)BootParameters
+
528 BootParameters
->AppEntryOffset
);
529 if (!RtlEqualMemory(AppEntry
->Signature
,
530 BL_APP_ENTRY_SIGNATURE
,
531 sizeof(AppEntry
->Signature
)))
533 /* Unrecognized, bail out */
534 Status
= STATUS_INVALID_PARAMETER_9
;
538 /* Check if CPUID 01h is supported */
539 if (BlArchIsCpuIdFunctionSupported(1))
541 /* Query CPU features */
542 BlArchCpuId(1, 0, &CpuInfo
);
544 /* Check if PAE is supported */
545 if (CpuInfo
.Edx
& 0x40)
547 EfiPrintf(L
"PAE Supported, but won't be used\r\n");
551 /* Setup the boot library parameters for this application */
552 BlSetupDefaultParameters(&LibraryParameters
);
553 LibraryParameters
.TranslationType
= BlVirtual
;
554 LibraryParameters
.LibraryFlags
= BL_LIBRARY_FLAG_ZERO_HEAP_ALLOCATIONS_ON_FREE
|
555 BL_LIBRARY_FLAG_REINITIALIZE_ALL
;
556 LibraryParameters
.MinimumAllocationCount
= 1024;
557 LibraryParameters
.MinimumHeapSize
= 2 * 1024 * 1024;
558 LibraryParameters
.HeapAllocationAttributes
= BlMemoryKernelRange
;
559 LibraryParameters
.FontBaseDirectory
= L
"\\Reactos\\Boot\\Fonts";
560 LibraryParameters
.DescriptorCount
= 512;
562 /* Initialize the boot library */
563 Status
= BlInitializeLibrary(BootParameters
, &LibraryParameters
);
564 if (NT_SUCCESS(Status
))
566 /* For testing, draw the logo */
569 /* Call the main routine */
570 Status
= OslpMain(&Flags
);
572 /* Return the flags, and destroy the boot library */
573 ReturnArguments
->Flags
= Flags
;
578 /* Return back to boot manager */
579 ReturnArguments
->Status
= Status
;