1c2c66affSColin Finck /*
2c2c66affSColin Finck * COPYRIGHT: See COPYING.ARM in the top level directory
3c2c66affSColin Finck * PROJECT: ReactOS UEFI OS Loader
4c2c66affSColin Finck * FILE: boot/environ/app/rosload/rosload.c
5c2c66affSColin Finck * PURPOSE: OS Loader Entrypoint
6c2c66affSColin Finck * PROGRAMMER: Alex Ionescu (alex.ionescu@reactos.org)
7c2c66affSColin Finck */
8c2c66affSColin Finck
9c2c66affSColin Finck /* INCLUDES ******************************************************************/
10c2c66affSColin Finck
11c2c66affSColin Finck #include "rosload.h"
12c2c66affSColin Finck
13b6f5520bSAlex Ionescu NTSTATUS
14b6f5520bSAlex Ionescu OslArchTransferToKernel (
15b6f5520bSAlex Ionescu _In_ PLOADER_PARAMETER_BLOCK LoaderBlock,
16b6f5520bSAlex Ionescu _In_ PVOID KernelEntrypoint
17b6f5520bSAlex Ionescu );
18b6f5520bSAlex Ionescu
19c2c66affSColin Finck /* DATA VARIABLES ************************************************************/
20c2c66affSColin Finck
21adcb9bd1SAlex Ionescu PLOADER_PARAMETER_BLOCK OslLoaderBlock;
22b6f5520bSAlex Ionescu PVOID OslEntryPoint;
23b6f5520bSAlex Ionescu PVOID UserSharedAddress;
24b6f5520bSAlex Ionescu ULONGLONG ArchXCr0BitsToClear;
25b6f5520bSAlex Ionescu ULONGLONG ArchCr4BitsToClear;
26b6f5520bSAlex Ionescu BOOLEAN BdDebugAfterExitBootServices;
27b6f5520bSAlex Ionescu KDESCRIPTOR OslKernelGdt;
28b6f5520bSAlex Ionescu KDESCRIPTOR OslKernelIdt;
29c2c66affSColin Finck
30adcb9bd1SAlex Ionescu ULONG_PTR OslImcHiveHandle;
31adcb9bd1SAlex Ionescu ULONG_PTR OslMachineHiveHandle;
32adcb9bd1SAlex Ionescu ULONG_PTR OslElamHiveHandle;
33adcb9bd1SAlex Ionescu ULONG_PTR OslSystemHiveHandle;
34adcb9bd1SAlex Ionescu
35adcb9bd1SAlex Ionescu PBL_DEVICE_DESCRIPTOR OslLoadDevice;
36adcb9bd1SAlex Ionescu PCHAR OslLoadOptions;
37adcb9bd1SAlex Ionescu PWCHAR OslSystemRoot;
38adcb9bd1SAlex Ionescu
39adcb9bd1SAlex Ionescu LIST_ENTRY OslFreeMemoryDesctiptorsList;
40adcb9bd1SAlex Ionescu LIST_ENTRY OslFinalMemoryMap;
41adcb9bd1SAlex Ionescu LIST_ENTRY OslCoreExtensionSubGroups[2];
42adcb9bd1SAlex Ionescu LIST_ENTRY OslLoadedFirmwareDriverList;
43adcb9bd1SAlex Ionescu
44adcb9bd1SAlex Ionescu BL_BUFFER_DESCRIPTOR OslFinalMemoryMapDescriptorsBuffer;
45adcb9bd1SAlex Ionescu
46adcb9bd1SAlex Ionescu GUID OslApplicationIdentifier;
47adcb9bd1SAlex Ionescu
48adcb9bd1SAlex Ionescu ULONG OslResetBootStatus;
49adcb9bd1SAlex Ionescu BOOLEAN OslImcProcessingValid;
50adcb9bd1SAlex Ionescu ULONG OslFreeMemoryDesctiptorsListSize;
51adcb9bd1SAlex Ionescu PVOID OslMemoryDescriptorBuffer;
52adcb9bd1SAlex Ionescu
539ec85c29SAlex Ionescu BcdObjectType BlpSbdiCurrentApplicationType;
549ec85c29SAlex Ionescu
559ec85c29SAlex Ionescu PRTL_BSD_DATA BsdBootStatusData;
569ec85c29SAlex Ionescu
579ec85c29SAlex Ionescu OSL_BSD_ITEM_TABLE_ENTRY OslpBootStatusFields[RtlBsdItemMax] =
589ec85c29SAlex Ionescu {
599ec85c29SAlex Ionescu {
609ec85c29SAlex Ionescu FIELD_OFFSET(RTL_BSD_DATA, Version),
619ec85c29SAlex Ionescu sizeof(&BsdBootStatusData->Version)
629ec85c29SAlex Ionescu }, // RtlBsdItemVersionNumber
639ec85c29SAlex Ionescu {
649ec85c29SAlex Ionescu FIELD_OFFSET(RTL_BSD_DATA, ProductType),
659ec85c29SAlex Ionescu sizeof(&BsdBootStatusData->ProductType)
669ec85c29SAlex Ionescu }, // RtlBsdItemProductType
679ec85c29SAlex Ionescu {
689ec85c29SAlex Ionescu FIELD_OFFSET(RTL_BSD_DATA, AabEnabled),
699ec85c29SAlex Ionescu sizeof(&BsdBootStatusData->AabEnabled)
709ec85c29SAlex Ionescu }, // RtlBsdItemAabEnabled
719ec85c29SAlex Ionescu {
729ec85c29SAlex Ionescu FIELD_OFFSET(RTL_BSD_DATA, AabTimeout),
739ec85c29SAlex Ionescu sizeof(&BsdBootStatusData->AabTimeout)
749ec85c29SAlex Ionescu }, // RtlBsdItemAabTimeout
759ec85c29SAlex Ionescu {
769ec85c29SAlex Ionescu FIELD_OFFSET(RTL_BSD_DATA, LastBootSucceeded),
779ec85c29SAlex Ionescu sizeof(&BsdBootStatusData->LastBootSucceeded)
789ec85c29SAlex Ionescu }, // RtlBsdItemBootGood
799ec85c29SAlex Ionescu {
809ec85c29SAlex Ionescu FIELD_OFFSET(RTL_BSD_DATA, LastBootShutdown),
819ec85c29SAlex Ionescu sizeof(&BsdBootStatusData->LastBootShutdown)
829ec85c29SAlex Ionescu }, // RtlBsdItemBootShutdown
839ec85c29SAlex Ionescu {
849ec85c29SAlex Ionescu FIELD_OFFSET(RTL_BSD_DATA, SleepInProgress),
859ec85c29SAlex Ionescu sizeof(&BsdBootStatusData->SleepInProgress)
869ec85c29SAlex Ionescu }, // RtlBsdSleepInProgress
879ec85c29SAlex Ionescu {
889ec85c29SAlex Ionescu FIELD_OFFSET(RTL_BSD_DATA, PowerTransition),
899ec85c29SAlex Ionescu sizeof(&BsdBootStatusData->PowerTransition)
909ec85c29SAlex Ionescu }, // RtlBsdPowerTransition
919ec85c29SAlex Ionescu {
929ec85c29SAlex Ionescu FIELD_OFFSET(RTL_BSD_DATA, BootAttemptCount),
939ec85c29SAlex Ionescu sizeof(&BsdBootStatusData->BootAttemptCount)
949ec85c29SAlex Ionescu }, // RtlBsdItemBootAttemptCount
959ec85c29SAlex Ionescu {
969ec85c29SAlex Ionescu FIELD_OFFSET(RTL_BSD_DATA, LastBootCheckpoint),
979ec85c29SAlex Ionescu sizeof(&BsdBootStatusData->LastBootCheckpoint)
989ec85c29SAlex Ionescu }, // RtlBsdItemBootCheckpoint
999ec85c29SAlex Ionescu {
1009ec85c29SAlex Ionescu FIELD_OFFSET(RTL_BSD_DATA, LastBootId),
1019ec85c29SAlex Ionescu sizeof(&BsdBootStatusData->LastBootId)
1029ec85c29SAlex Ionescu }, // RtlBsdItemBootId
1039ec85c29SAlex Ionescu {
1049ec85c29SAlex Ionescu FIELD_OFFSET(RTL_BSD_DATA, LastSuccessfulShutdownBootId),
1059ec85c29SAlex Ionescu sizeof(&BsdBootStatusData->LastSuccessfulShutdownBootId)
1069ec85c29SAlex Ionescu }, // RtlBsdItemShutdownBootId
1079ec85c29SAlex Ionescu {
1089ec85c29SAlex Ionescu FIELD_OFFSET(RTL_BSD_DATA, LastReportedAbnormalShutdownBootId),
1099ec85c29SAlex Ionescu sizeof(&BsdBootStatusData->LastReportedAbnormalShutdownBootId)
1109ec85c29SAlex Ionescu }, // RtlBsdItemReportedAbnormalShutdownBootId
1119ec85c29SAlex Ionescu {
1129ec85c29SAlex Ionescu FIELD_OFFSET(RTL_BSD_DATA, ErrorInfo),
1139ec85c29SAlex Ionescu sizeof(&BsdBootStatusData->ErrorInfo)
1149ec85c29SAlex Ionescu }, // RtlBsdItemErrorInfo
1159ec85c29SAlex Ionescu {
1169ec85c29SAlex Ionescu FIELD_OFFSET(RTL_BSD_DATA, PowerButtonPressInfo),
1179ec85c29SAlex Ionescu sizeof(&BsdBootStatusData->PowerButtonPressInfo)
1189ec85c29SAlex Ionescu }, // RtlBsdItemPowerButtonPressInfo
1199ec85c29SAlex Ionescu {
1209ec85c29SAlex Ionescu FIELD_OFFSET(RTL_BSD_DATA, Checksum),
1219ec85c29SAlex Ionescu sizeof(&BsdBootStatusData->Checksum)
1229ec85c29SAlex Ionescu }, // RtlBsdItemChecksum
1239ec85c29SAlex Ionescu };
1249ec85c29SAlex Ionescu
1259ec85c29SAlex Ionescu ULONG OslBootAttemptCount;
1269ec85c29SAlex Ionescu ULONG OslBootCountUpdateRequestForAbort;
1279ec85c29SAlex Ionescu ULONG OslBootAttemptMaximum;
1289ec85c29SAlex Ionescu
1299ec85c29SAlex Ionescu ULONG OslBootCountUpdateIncrement;
1309ec85c29SAlex Ionescu
1319ec85c29SAlex Ionescu BOOLEAN OslCurrentBootCheckpoint;
1329ec85c29SAlex Ionescu BOOLEAN OslCurrentBootSucceeded;
1339ec85c29SAlex Ionescu BOOLEAN OslCurrentBootShutdown;
1349ec85c29SAlex Ionescu
135c2c66affSColin Finck /* FUNCTIONS *****************************************************************/
136c2c66affSColin Finck
137adcb9bd1SAlex Ionescu VOID
OslFatalErrorEx(_In_ ULONG ErrorCode,_In_ ULONG Parameter1,_In_ ULONG_PTR Parameter2,_In_ ULONG_PTR Parameter3)138adcb9bd1SAlex Ionescu OslFatalErrorEx (
139adcb9bd1SAlex Ionescu _In_ ULONG ErrorCode,
140adcb9bd1SAlex Ionescu _In_ ULONG Parameter1,
141adcb9bd1SAlex Ionescu _In_ ULONG_PTR Parameter2,
142adcb9bd1SAlex Ionescu _In_ ULONG_PTR Parameter3
143adcb9bd1SAlex Ionescu )
144adcb9bd1SAlex Ionescu {
145adcb9bd1SAlex Ionescu /* For now just do this */
146adcb9bd1SAlex Ionescu BlStatusPrint(L"FATAL ERROR IN ROSLOAD: %lx\n", ErrorCode);
147adcb9bd1SAlex Ionescu }
148adcb9bd1SAlex Ionescu
149adcb9bd1SAlex Ionescu VOID
OslAbortBoot(_In_ NTSTATUS Status)150adcb9bd1SAlex Ionescu OslAbortBoot (
151adcb9bd1SAlex Ionescu _In_ NTSTATUS Status
152adcb9bd1SAlex Ionescu )
153adcb9bd1SAlex Ionescu {
154adcb9bd1SAlex Ionescu /* For now just do this */
155adcb9bd1SAlex Ionescu BlStatusPrint(L"BOOT ABORTED: %lx\n", Status);
156adcb9bd1SAlex Ionescu }
157adcb9bd1SAlex Ionescu
158adcb9bd1SAlex Ionescu NTSTATUS
OslBlStatusErrorHandler(_In_ ULONG ErrorCode,_In_ ULONG Parameter1,_In_ ULONG_PTR Parameter2,_In_ ULONG_PTR Parameter3,_In_ ULONG_PTR Parameter4)159adcb9bd1SAlex Ionescu OslBlStatusErrorHandler (
160adcb9bd1SAlex Ionescu _In_ ULONG ErrorCode,
161adcb9bd1SAlex Ionescu _In_ ULONG Parameter1,
162adcb9bd1SAlex Ionescu _In_ ULONG_PTR Parameter2,
163adcb9bd1SAlex Ionescu _In_ ULONG_PTR Parameter3,
164adcb9bd1SAlex Ionescu _In_ ULONG_PTR Parameter4
165adcb9bd1SAlex Ionescu )
166adcb9bd1SAlex Ionescu {
167adcb9bd1SAlex Ionescu /* We only filter error code 4 */
168adcb9bd1SAlex Ionescu if (ErrorCode != 4)
169adcb9bd1SAlex Ionescu {
170adcb9bd1SAlex Ionescu return STATUS_NOT_IMPLEMENTED;
171adcb9bd1SAlex Ionescu }
172adcb9bd1SAlex Ionescu
173adcb9bd1SAlex Ionescu /* Handle error 4 as a fatal error 3 internally */
174adcb9bd1SAlex Ionescu OslFatalErrorEx(3, Parameter1, Parameter2, Parameter3);
175adcb9bd1SAlex Ionescu return STATUS_SUCCESS;
176adcb9bd1SAlex Ionescu }
177adcb9bd1SAlex Ionescu
178adcb9bd1SAlex Ionescu VOID
OslpSanitizeLoadOptionsString(_In_ PWCHAR OptionString,_In_ PWCHAR SanitizeString)179adcb9bd1SAlex Ionescu OslpSanitizeLoadOptionsString (
180adcb9bd1SAlex Ionescu _In_ PWCHAR OptionString,
181adcb9bd1SAlex Ionescu _In_ PWCHAR SanitizeString
182adcb9bd1SAlex Ionescu )
183adcb9bd1SAlex Ionescu {
184adcb9bd1SAlex Ionescu /* TODO */
185adcb9bd1SAlex Ionescu return;
186adcb9bd1SAlex Ionescu }
187adcb9bd1SAlex Ionescu
188adcb9bd1SAlex Ionescu VOID
OslpSanitizeStringOptions(_In_ PBL_BCD_OPTION BcdOptions)189adcb9bd1SAlex Ionescu OslpSanitizeStringOptions (
190adcb9bd1SAlex Ionescu _In_ PBL_BCD_OPTION BcdOptions
191adcb9bd1SAlex Ionescu )
192adcb9bd1SAlex Ionescu {
193adcb9bd1SAlex Ionescu /* TODO */
194adcb9bd1SAlex Ionescu return;
195adcb9bd1SAlex Ionescu }
196adcb9bd1SAlex Ionescu
197adcb9bd1SAlex Ionescu NTSTATUS
OslpRemoveInternalApplicationOptions(VOID)198adcb9bd1SAlex Ionescu OslpRemoveInternalApplicationOptions (
199adcb9bd1SAlex Ionescu VOID
200adcb9bd1SAlex Ionescu )
201adcb9bd1SAlex Ionescu {
202adcb9bd1SAlex Ionescu PWCHAR LoadString;
203adcb9bd1SAlex Ionescu NTSTATUS Status;
204adcb9bd1SAlex Ionescu
205adcb9bd1SAlex Ionescu /* Assume success */
206adcb9bd1SAlex Ionescu Status = STATUS_SUCCESS;
207adcb9bd1SAlex Ionescu
208adcb9bd1SAlex Ionescu /* Remove attempts to disable integrity checks or ELAM driver load */
209adcb9bd1SAlex Ionescu BlRemoveBootOption(BlpApplicationEntry.BcdData,
210adcb9bd1SAlex Ionescu BcdLibraryBoolean_DisableIntegrityChecks);
211adcb9bd1SAlex Ionescu BlRemoveBootOption(BlpApplicationEntry.BcdData,
212adcb9bd1SAlex Ionescu BcdOSLoaderBoolean_DisableElamDrivers);
213adcb9bd1SAlex Ionescu
214adcb9bd1SAlex Ionescu /* Get the command-line parameters, if any */
215adcb9bd1SAlex Ionescu Status = BlGetBootOptionString(BlpApplicationEntry.BcdData,
216adcb9bd1SAlex Ionescu BcdLibraryString_LoadOptionsString,
217adcb9bd1SAlex Ionescu &LoadString);
218adcb9bd1SAlex Ionescu if (NT_SUCCESS(Status))
219adcb9bd1SAlex Ionescu {
220adcb9bd1SAlex Ionescu /* Conver to upper case */
221adcb9bd1SAlex Ionescu _wcsupr(LoadString);
222adcb9bd1SAlex Ionescu
223adcb9bd1SAlex Ionescu /* Remove the existing one */
2249ec85c29SAlex Ionescu BlRemoveBootOption(BlpApplicationEntry.BcdData,
2259ec85c29SAlex Ionescu BcdLibraryString_LoadOptionsString);
226adcb9bd1SAlex Ionescu
227adcb9bd1SAlex Ionescu /* Sanitize strings we don't want */
228adcb9bd1SAlex Ionescu OslpSanitizeLoadOptionsString(LoadString, L"DISABLE_INTEGRITY_CHECKS");
229adcb9bd1SAlex Ionescu OslpSanitizeLoadOptionsString(LoadString, L"NOINTEGRITYCHECKS");
230adcb9bd1SAlex Ionescu OslpSanitizeLoadOptionsString(LoadString, L"DISABLEELAMDRIVERS");
231adcb9bd1SAlex Ionescu
232adcb9bd1SAlex Ionescu /* Add the sanitized one back */
2339ec85c29SAlex Ionescu Status = BlAppendBootOptionString(&BlpApplicationEntry,
2349ec85c29SAlex Ionescu BcdLibraryString_LoadOptionsString,
2359ec85c29SAlex Ionescu LoadString);
236adcb9bd1SAlex Ionescu
237adcb9bd1SAlex Ionescu /* Free the original BCD one */
238adcb9bd1SAlex Ionescu BlMmFreeHeap(LoadString);
239adcb9bd1SAlex Ionescu }
240adcb9bd1SAlex Ionescu
241adcb9bd1SAlex Ionescu /* One more pass for secure-boot options */
242adcb9bd1SAlex Ionescu OslpSanitizeStringOptions(BlpApplicationEntry.BcdData);
243adcb9bd1SAlex Ionescu
244adcb9bd1SAlex Ionescu /* All good */
245adcb9bd1SAlex Ionescu return Status;
246adcb9bd1SAlex Ionescu }
247adcb9bd1SAlex Ionescu
248e836d0b5SAlex Ionescu NTSTATUS
OslpCheckForcedFailure(VOID)2499ec85c29SAlex Ionescu OslpCheckForcedFailure (
2509ec85c29SAlex Ionescu VOID
2519ec85c29SAlex Ionescu )
2529ec85c29SAlex Ionescu {
2539ec85c29SAlex Ionescu ULONG64 ForceReason;
2549ec85c29SAlex Ionescu NTSTATUS Status;
2559ec85c29SAlex Ionescu
2569ec85c29SAlex Ionescu /* Read the option */
2579ec85c29SAlex Ionescu Status = BlGetBootOptionInteger(BlpApplicationEntry.BcdData,
2589ec85c29SAlex Ionescu BcdOSLoaderInteger_ForceFailure,
2599ec85c29SAlex Ionescu &ForceReason);
2609ec85c29SAlex Ionescu if (NT_SUCCESS(Status) && (ForceReason < 4))
2619ec85c29SAlex Ionescu {
2629ec85c29SAlex Ionescu /* For reasons above 3, don't actually do anything */
2639ec85c29SAlex Ionescu if (ForceReason > 3)
2649ec85c29SAlex Ionescu {
2659ec85c29SAlex Ionescu return STATUS_SUCCESS;
2669ec85c29SAlex Ionescu }
2679ec85c29SAlex Ionescu }
2689ec85c29SAlex Ionescu
2699ec85c29SAlex Ionescu /* If the option isn't there or invalid, always return success */
2709ec85c29SAlex Ionescu return STATUS_SUCCESS;
2719ec85c29SAlex Ionescu }
2729ec85c29SAlex Ionescu
2739ec85c29SAlex Ionescu VOID
OslpInitializeBootStatusDataLog(VOID)2749ec85c29SAlex Ionescu OslpInitializeBootStatusDataLog (
2759ec85c29SAlex Ionescu VOID
2769ec85c29SAlex Ionescu )
2779ec85c29SAlex Ionescu {
2789ec85c29SAlex Ionescu /* TODO */
2799ec85c29SAlex Ionescu return;
2809ec85c29SAlex Ionescu }
2819ec85c29SAlex Ionescu
2829ec85c29SAlex Ionescu NTSTATUS
OslpReadWriteBootStatusData(_In_ BOOLEAN WriteAccess)2839ec85c29SAlex Ionescu OslpReadWriteBootStatusData (
2849ec85c29SAlex Ionescu _In_ BOOLEAN WriteAccess
2859ec85c29SAlex Ionescu )
2869ec85c29SAlex Ionescu {
2879ec85c29SAlex Ionescu /* Are you trying to write? */
2889ec85c29SAlex Ionescu if (WriteAccess)
2899ec85c29SAlex Ionescu {
2909ec85c29SAlex Ionescu /* Have we already read? */
2919ec85c29SAlex Ionescu if (!BsdBootStatusData)
2929ec85c29SAlex Ionescu {
2939ec85c29SAlex Ionescu /* No -- fail */
2949ec85c29SAlex Ionescu return STATUS_UNSUCCESSFUL;
2959ec85c29SAlex Ionescu }
2969ec85c29SAlex Ionescu }
2979ec85c29SAlex Ionescu else if (BsdBootStatusData)
2989ec85c29SAlex Ionescu {
2999ec85c29SAlex Ionescu /* No -- you're trying to read and we already have the data: no-op */
3009ec85c29SAlex Ionescu return STATUS_SUCCESS;
3019ec85c29SAlex Ionescu }
3029ec85c29SAlex Ionescu
3039ec85c29SAlex Ionescu /* TODO */
3049ec85c29SAlex Ionescu return STATUS_NOT_IMPLEMENTED;
3059ec85c29SAlex Ionescu }
3069ec85c29SAlex Ionescu
3079ec85c29SAlex Ionescu NTSTATUS
OslpGetSetBootStatusData(_In_ BOOLEAN Read,_In_ RTL_BSD_ITEM_TYPE DataClass,_Out_ PVOID Buffer,_Inout_ PULONG Size)3089ec85c29SAlex Ionescu OslpGetSetBootStatusData (
3099ec85c29SAlex Ionescu _In_ BOOLEAN Read,
3109ec85c29SAlex Ionescu _In_ RTL_BSD_ITEM_TYPE DataClass,
3119ec85c29SAlex Ionescu _Out_ PVOID Buffer,
3129ec85c29SAlex Ionescu _Inout_ PULONG Size
3139ec85c29SAlex Ionescu )
3149ec85c29SAlex Ionescu {
3159ec85c29SAlex Ionescu NTSTATUS Status;
3169ec85c29SAlex Ionescu ULONG Length, Offset;
3179ec85c29SAlex Ionescu
3189ec85c29SAlex Ionescu /* No data has been read yet, fail */
3199ec85c29SAlex Ionescu if (!BsdBootStatusData)
3209ec85c29SAlex Ionescu {
3219ec85c29SAlex Ionescu return STATUS_UNSUCCESSFUL;
3229ec85c29SAlex Ionescu }
3239ec85c29SAlex Ionescu
3249ec85c29SAlex Ionescu /* Invalid data item, fail */
3259ec85c29SAlex Ionescu if (DataClass >= RtlBsdItemMax)
3269ec85c29SAlex Ionescu {
3279ec85c29SAlex Ionescu return STATUS_INVALID_PARAMETER;
3289ec85c29SAlex Ionescu }
3299ec85c29SAlex Ionescu
3309ec85c29SAlex Ionescu /* Capture the length and offset */
3319ec85c29SAlex Ionescu Length = OslpBootStatusFields[DataClass].Size;
3329ec85c29SAlex Ionescu Offset = OslpBootStatusFields[DataClass].Offset;
3339ec85c29SAlex Ionescu
3349ec85c29SAlex Ionescu /* Make sure it doesn't overflow past the structure we've read */
3359ec85c29SAlex Ionescu if ((Length + Offset) > BsdBootStatusData->Version)
3369ec85c29SAlex Ionescu {
3379ec85c29SAlex Ionescu return STATUS_REVISION_MISMATCH;
3389ec85c29SAlex Ionescu }
3399ec85c29SAlex Ionescu
3409ec85c29SAlex Ionescu /* Make sure we have enough space */
3419ec85c29SAlex Ionescu if (*Size >= Length)
3429ec85c29SAlex Ionescu {
3439ec85c29SAlex Ionescu /* We do -- is this a read? */
3449ec85c29SAlex Ionescu if (Read)
3459ec85c29SAlex Ionescu {
3469ec85c29SAlex Ionescu /* Yes, copy into the caller's buffer */
3479ec85c29SAlex Ionescu RtlCopyMemory(Buffer,
3489ec85c29SAlex Ionescu (PVOID)((ULONG_PTR)BsdBootStatusData + Offset),
3499ec85c29SAlex Ionescu Length);
3509ec85c29SAlex Ionescu }
3519ec85c29SAlex Ionescu else
3529ec85c29SAlex Ionescu {
3539ec85c29SAlex Ionescu /* It's a write, copy from caller's buffer */
3549ec85c29SAlex Ionescu RtlCopyMemory((PVOID)((ULONG_PTR)BsdBootStatusData + Offset),
3559ec85c29SAlex Ionescu Buffer,
3569ec85c29SAlex Ionescu Length);
3579ec85c29SAlex Ionescu }
3589ec85c29SAlex Ionescu
3599ec85c29SAlex Ionescu /* Set success */
3609ec85c29SAlex Ionescu Status = STATUS_SUCCESS;
3619ec85c29SAlex Ionescu }
3629ec85c29SAlex Ionescu else
3639ec85c29SAlex Ionescu {
3649ec85c29SAlex Ionescu /* Return size needed and failure code */
3659ec85c29SAlex Ionescu *Size = Length;
3669ec85c29SAlex Ionescu Status = STATUS_BUFFER_TOO_SMALL;
3679ec85c29SAlex Ionescu }
3689ec85c29SAlex Ionescu
3699ec85c29SAlex Ionescu /* All good */
3709ec85c29SAlex Ionescu return Status;
3719ec85c29SAlex Ionescu }
3729ec85c29SAlex Ionescu
3739ec85c29SAlex Ionescu NTSTATUS
OslSetBootStatusData(_In_ BOOLEAN LastBootGood,_In_ BOOLEAN LastBootShutdown,_In_ BOOLEAN LastBootCheckpoint,_In_ ULONG UpdateIncrement,_In_ ULONG BootAttemptCount)3749ec85c29SAlex Ionescu OslSetBootStatusData (
3759ec85c29SAlex Ionescu _In_ BOOLEAN LastBootGood,
3769ec85c29SAlex Ionescu _In_ BOOLEAN LastBootShutdown,
3779ec85c29SAlex Ionescu _In_ BOOLEAN LastBootCheckpoint,
3789ec85c29SAlex Ionescu _In_ ULONG UpdateIncrement,
3799ec85c29SAlex Ionescu _In_ ULONG BootAttemptCount
3809ec85c29SAlex Ionescu )
3819ec85c29SAlex Ionescu {
3829ec85c29SAlex Ionescu NTSTATUS Status;
3839ec85c29SAlex Ionescu ULONG Size;
3849ec85c29SAlex Ionescu
3859ec85c29SAlex Ionescu /* Capture the BSD data in our globals, if needed */
3869ec85c29SAlex Ionescu Status = OslpReadWriteBootStatusData(FALSE);
3879ec85c29SAlex Ionescu if (!NT_SUCCESS(Status))
3889ec85c29SAlex Ionescu {
3899ec85c29SAlex Ionescu goto Quickie;
3909ec85c29SAlex Ionescu }
3919ec85c29SAlex Ionescu
3929ec85c29SAlex Ionescu /* Write last boot shutdown */
3939ec85c29SAlex Ionescu Size = sizeof(LastBootShutdown);
3949ec85c29SAlex Ionescu Status = OslpGetSetBootStatusData(FALSE,
3959ec85c29SAlex Ionescu RtlBsdItemBootShutdown,
3969ec85c29SAlex Ionescu &LastBootShutdown,
3979ec85c29SAlex Ionescu &Size);
3989ec85c29SAlex Ionescu if (!NT_SUCCESS(Status))
3999ec85c29SAlex Ionescu {
4009ec85c29SAlex Ionescu goto Quickie;
4019ec85c29SAlex Ionescu }
4029ec85c29SAlex Ionescu
4039ec85c29SAlex Ionescu /* Write last boot good */
4049ec85c29SAlex Ionescu Size = sizeof(LastBootGood);
4059ec85c29SAlex Ionescu Status = OslpGetSetBootStatusData(FALSE,
4069ec85c29SAlex Ionescu RtlBsdItemBootGood,
4079ec85c29SAlex Ionescu &LastBootGood,
4089ec85c29SAlex Ionescu &Size);
4099ec85c29SAlex Ionescu if (!NT_SUCCESS(Status))
4109ec85c29SAlex Ionescu {
4119ec85c29SAlex Ionescu goto Quickie;
4129ec85c29SAlex Ionescu }
4139ec85c29SAlex Ionescu
4149ec85c29SAlex Ionescu /* Write last boot checkpoint */
4159ec85c29SAlex Ionescu Size = sizeof(LastBootCheckpoint);
4169ec85c29SAlex Ionescu Status = OslpGetSetBootStatusData(FALSE,
4179ec85c29SAlex Ionescu RtlBsdItemBootCheckpoint,
4189ec85c29SAlex Ionescu &LastBootCheckpoint,
4199ec85c29SAlex Ionescu &Size);
4209ec85c29SAlex Ionescu if (!NT_SUCCESS(Status))
4219ec85c29SAlex Ionescu {
4229ec85c29SAlex Ionescu goto Quickie;
4239ec85c29SAlex Ionescu }
4249ec85c29SAlex Ionescu
4259ec85c29SAlex Ionescu /* Write boot attempt count */
4269ec85c29SAlex Ionescu Size = sizeof(BootAttemptCount);
4279ec85c29SAlex Ionescu Status = OslpGetSetBootStatusData(FALSE,
4289ec85c29SAlex Ionescu RtlBsdItemBootAttemptCount,
4299ec85c29SAlex Ionescu &BootAttemptCount,
4309ec85c29SAlex Ionescu &Size);
4319ec85c29SAlex Ionescu if (!NT_SUCCESS(Status))
4329ec85c29SAlex Ionescu {
4339ec85c29SAlex Ionescu goto Quickie;
4349ec85c29SAlex Ionescu }
4359ec85c29SAlex Ionescu
4369ec85c29SAlex Ionescu /* TODO: Update Boot ID*/
4379ec85c29SAlex Ionescu
4389ec85c29SAlex Ionescu /* Now write the data */
4399ec85c29SAlex Ionescu Status = OslpReadWriteBootStatusData(TRUE);
4409ec85c29SAlex Ionescu
4419ec85c29SAlex Ionescu Quickie:
4429ec85c29SAlex Ionescu return Status;
4439ec85c29SAlex Ionescu }
4449ec85c29SAlex Ionescu
4459ec85c29SAlex Ionescu NTSTATUS
OslGetBootStatusData(_Out_ PBOOLEAN LastBootGood,_Out_ PBOOLEAN LastBootShutdown,_Out_ PBOOLEAN LastBootCheckpoint,_Out_ PULONG LastBootId,_Out_ PBOOLEAN BootGood,_Out_ PBOOLEAN BootShutdown)4469ec85c29SAlex Ionescu OslGetBootStatusData (
4479ec85c29SAlex Ionescu _Out_ PBOOLEAN LastBootGood,
4489ec85c29SAlex Ionescu _Out_ PBOOLEAN LastBootShutdown,
4499ec85c29SAlex Ionescu _Out_ PBOOLEAN LastBootCheckpoint,
4509ec85c29SAlex Ionescu _Out_ PULONG LastBootId,
4519ec85c29SAlex Ionescu _Out_ PBOOLEAN BootGood,
4529ec85c29SAlex Ionescu _Out_ PBOOLEAN BootShutdown
4539ec85c29SAlex Ionescu )
4549ec85c29SAlex Ionescu {
4559ec85c29SAlex Ionescu NTSTATUS Status;
4569ec85c29SAlex Ionescu ULONG Size;
4579ec85c29SAlex Ionescu ULONG64 BootStatusPolicy;
4589ec85c29SAlex Ionescu BOOLEAN localBootShutdown, localBootGood;
4599ec85c29SAlex Ionescu
4609ec85c29SAlex Ionescu /* Capture the BSD data in our globals, if needed */
4619ec85c29SAlex Ionescu Status = OslpReadWriteBootStatusData(FALSE);
4629ec85c29SAlex Ionescu if (!NT_SUCCESS(Status))
4639ec85c29SAlex Ionescu {
4649ec85c29SAlex Ionescu goto Quickie;
4659ec85c29SAlex Ionescu }
4669ec85c29SAlex Ionescu
4679ec85c29SAlex Ionescu /* Read the last boot ID */
4689ec85c29SAlex Ionescu Size = sizeof(*LastBootId);
4699ec85c29SAlex Ionescu Status = OslpGetSetBootStatusData(TRUE, RtlBsdItemBootId, LastBootId, &Size);
4709ec85c29SAlex Ionescu if (!NT_SUCCESS(Status))
4719ec85c29SAlex Ionescu {
4729ec85c29SAlex Ionescu /* Set to zero if we couldn't find it */
4739ec85c29SAlex Ionescu *LastBootId = 0;
4749ec85c29SAlex Ionescu }
4759ec85c29SAlex Ionescu
4769ec85c29SAlex Ionescu /* Get the boot status policy */
4779ec85c29SAlex Ionescu Status = BlGetBootOptionInteger(BlpApplicationEntry.BcdData,
4789ec85c29SAlex Ionescu BcdOSLoaderInteger_BootStatusPolicy,
4799ec85c29SAlex Ionescu &BootStatusPolicy);
4809ec85c29SAlex Ionescu if (!NT_SUCCESS(Status))
4819ec85c29SAlex Ionescu {
4829ec85c29SAlex Ionescu /* Apply a default if none exists */
4839ec85c29SAlex Ionescu BootStatusPolicy = IgnoreShutdownFailures;
4849ec85c29SAlex Ionescu }
4859ec85c29SAlex Ionescu
4869ec85c29SAlex Ionescu /* Check if this was a good shutdown */
4879ec85c29SAlex Ionescu Size = sizeof(localBootShutdown);
4889ec85c29SAlex Ionescu Status = OslpGetSetBootStatusData(TRUE,
4899ec85c29SAlex Ionescu RtlBsdItemBootShutdown,
4909ec85c29SAlex Ionescu &localBootShutdown,
4919ec85c29SAlex Ionescu &Size);
4929ec85c29SAlex Ionescu if (!NT_SUCCESS(Status))
4939ec85c29SAlex Ionescu {
4949ec85c29SAlex Ionescu goto Quickie;
4959ec85c29SAlex Ionescu }
4969ec85c29SAlex Ionescu
4979ec85c29SAlex Ionescu /* Tell the caller */
4989ec85c29SAlex Ionescu *BootShutdown = localBootShutdown;
4999ec85c29SAlex Ionescu
5009ec85c29SAlex Ionescu /* Check if this was a good boot */
5019ec85c29SAlex Ionescu Size = sizeof(localBootGood);
5029ec85c29SAlex Ionescu Status = OslpGetSetBootStatusData(TRUE,
5039ec85c29SAlex Ionescu RtlBsdItemBootGood,
5049ec85c29SAlex Ionescu &localBootGood,
5059ec85c29SAlex Ionescu &Size);
5069ec85c29SAlex Ionescu if (!NT_SUCCESS(Status))
5079ec85c29SAlex Ionescu {
5089ec85c29SAlex Ionescu goto Quickie;
5099ec85c29SAlex Ionescu }
5109ec85c29SAlex Ionescu
5119ec85c29SAlex Ionescu /* Tell the caller*/
5129ec85c29SAlex Ionescu *BootGood = localBootGood;
5139ec85c29SAlex Ionescu
5149ec85c29SAlex Ionescu /* TODO: Additional logic for checkpoints and such */
5159ec85c29SAlex Ionescu Status = STATUS_NOT_IMPLEMENTED;
5169ec85c29SAlex Ionescu
5179ec85c29SAlex Ionescu Quickie:
5189ec85c29SAlex Ionescu return Status;
5199ec85c29SAlex Ionescu }
5209ec85c29SAlex Ionescu
5219ec85c29SAlex Ionescu BOOLEAN
OslpAdvancedOptionsRequested(VOID)5229ec85c29SAlex Ionescu OslpAdvancedOptionsRequested (
5239ec85c29SAlex Ionescu VOID
5249ec85c29SAlex Ionescu )
5259ec85c29SAlex Ionescu {
5269ec85c29SAlex Ionescu /* TODO */
5279ec85c29SAlex Ionescu return FALSE;
5289ec85c29SAlex Ionescu }
5299ec85c29SAlex Ionescu
5309ec85c29SAlex Ionescu NTSTATUS
OslPrepareTarget(_Out_ PULONG ReturnFlags,_Out_ PBOOLEAN Jump)531e836d0b5SAlex Ionescu OslPrepareTarget (
532e836d0b5SAlex Ionescu _Out_ PULONG ReturnFlags,
533e836d0b5SAlex Ionescu _Out_ PBOOLEAN Jump
534e836d0b5SAlex Ionescu )
535e836d0b5SAlex Ionescu {
536adcb9bd1SAlex Ionescu PGUID AppId;
537adcb9bd1SAlex Ionescu NTSTATUS Status;
538adcb9bd1SAlex Ionescu PBL_DEVICE_DESCRIPTOR OsDevice;
539adcb9bd1SAlex Ionescu PWCHAR SystemRoot;
540adcb9bd1SAlex Ionescu SIZE_T RootLength, RootLengthWithSep;
541adcb9bd1SAlex Ionescu ULONG i;
542adcb9bd1SAlex Ionescu ULONG64 StartPerf, EndPerf;
5439ec85c29SAlex Ionescu RTL_BSD_DATA_POWER_TRANSITION PowerTransitionData;
5449ec85c29SAlex Ionescu PRTL_BSD_DATA_POWER_TRANSITION PowerBuffer;
5459ec85c29SAlex Ionescu ULONG OsDeviceHandle;
5469ec85c29SAlex Ionescu BOOLEAN LastBootGood, LastBootShutdown, LastBootCheckpoint;
5479ec85c29SAlex Ionescu ULONG BootId;
5489ec85c29SAlex Ionescu BOOLEAN BootGood, BootShutdown;
5499ec85c29SAlex Ionescu ULONG BsdSize;
5509ec85c29SAlex Ionescu
5519ec85c29SAlex Ionescu /* Initialize locals */
5529ec85c29SAlex Ionescu PowerBuffer = NULL;
553adcb9bd1SAlex Ionescu
554adcb9bd1SAlex Ionescu /* Assume no flags */
555adcb9bd1SAlex Ionescu *ReturnFlags = 0;
556adcb9bd1SAlex Ionescu
557adcb9bd1SAlex Ionescu /* Make all registry handles invalid */
558adcb9bd1SAlex Ionescu OslImcHiveHandle = -1;
559adcb9bd1SAlex Ionescu OslMachineHiveHandle = -1;
560adcb9bd1SAlex Ionescu OslElamHiveHandle = -1;
561adcb9bd1SAlex Ionescu OslSystemHiveHandle = -1;
562adcb9bd1SAlex Ionescu
563adcb9bd1SAlex Ionescu /* Initialize memory lists */
564adcb9bd1SAlex Ionescu InitializeListHead(&OslFreeMemoryDesctiptorsList);
565adcb9bd1SAlex Ionescu InitializeListHead(&OslFinalMemoryMap);
566adcb9bd1SAlex Ionescu InitializeListHead(&OslLoadedFirmwareDriverList);
567adcb9bd1SAlex Ionescu for (i = 0; i < RTL_NUMBER_OF(OslCoreExtensionSubGroups); i++)
568adcb9bd1SAlex Ionescu {
569adcb9bd1SAlex Ionescu InitializeListHead(&OslCoreExtensionSubGroups[i]);
570adcb9bd1SAlex Ionescu }
571adcb9bd1SAlex Ionescu
572adcb9bd1SAlex Ionescu /* Initialize the memory map descriptor buffer */
573adcb9bd1SAlex Ionescu RtlZeroMemory(&OslFinalMemoryMapDescriptorsBuffer,
574adcb9bd1SAlex Ionescu sizeof(OslFinalMemoryMapDescriptorsBuffer));
575adcb9bd1SAlex Ionescu
576adcb9bd1SAlex Ionescu /* Initialize general pointers */
577adcb9bd1SAlex Ionescu OslLoadDevice = NULL;
578adcb9bd1SAlex Ionescu OslLoadOptions = NULL;
579adcb9bd1SAlex Ionescu OslSystemRoot = NULL;
580adcb9bd1SAlex Ionescu OslLoaderBlock = NULL;
581adcb9bd1SAlex Ionescu OslMemoryDescriptorBuffer = NULL;
582adcb9bd1SAlex Ionescu
583adcb9bd1SAlex Ionescu /* Initialize general variables */
584adcb9bd1SAlex Ionescu OslResetBootStatus = 0;
585adcb9bd1SAlex Ionescu OslImcProcessingValid = FALSE;
586adcb9bd1SAlex Ionescu OslFreeMemoryDesctiptorsListSize = 0;
587adcb9bd1SAlex Ionescu
588adcb9bd1SAlex Ionescu /* Capture the current TSC */
589adcb9bd1SAlex Ionescu StartPerf = BlArchGetPerformanceCounter();
590adcb9bd1SAlex Ionescu
5919ec85c29SAlex Ionescu /* Set our application type for SecureBoot/TPM purposes */
5929ec85c29SAlex Ionescu BlpSbdiCurrentApplicationType.Application.ObjectCode =
5939ec85c29SAlex Ionescu BCD_OBJECT_TYPE_APPLICATION;
5949ec85c29SAlex Ionescu BlpSbdiCurrentApplicationType.Application.ImageCode =
5959ec85c29SAlex Ionescu BCD_IMAGE_TYPE_BOOT_APP;
5969ec85c29SAlex Ionescu BlpSbdiCurrentApplicationType.Application.ApplicationCode =
5979ec85c29SAlex Ionescu BCD_APPLICATION_TYPE_OSLOADER;
5989ec85c29SAlex Ionescu BlpSbdiCurrentApplicationType.Application.Reserved = 0;
599adcb9bd1SAlex Ionescu
600adcb9bd1SAlex Ionescu /* Register an error handler */
601adcb9bd1SAlex Ionescu BlpStatusErrorHandler = OslBlStatusErrorHandler;
602adcb9bd1SAlex Ionescu
603adcb9bd1SAlex Ionescu /* Get the application identifier and save it */
604adcb9bd1SAlex Ionescu AppId = BlGetApplicationIdentifier();
605adcb9bd1SAlex Ionescu if (AppId)
606adcb9bd1SAlex Ionescu {
607adcb9bd1SAlex Ionescu OslApplicationIdentifier = *AppId;
608adcb9bd1SAlex Ionescu }
609adcb9bd1SAlex Ionescu
610adcb9bd1SAlex Ionescu /* Enable tracing */
611adcb9bd1SAlex Ionescu #ifdef BL_ETW_SUPPORT
612adcb9bd1SAlex Ionescu TraceLoggingRegister(&TlgOslBootProviderProv);
613adcb9bd1SAlex Ionescu #endif
614adcb9bd1SAlex Ionescu
615adcb9bd1SAlex Ionescu /* Remove dangerous BCD options */
616adcb9bd1SAlex Ionescu Status = OslpRemoveInternalApplicationOptions();
617adcb9bd1SAlex Ionescu if (!NT_SUCCESS(Status))
618adcb9bd1SAlex Ionescu {
6199ec85c29SAlex Ionescu EfiPrintf(L"Fail here: %d\r\n", __LINE__);
620adcb9bd1SAlex Ionescu goto Quickie;
621adcb9bd1SAlex Ionescu }
622adcb9bd1SAlex Ionescu
623adcb9bd1SAlex Ionescu /* Get the OS device */
624adcb9bd1SAlex Ionescu Status = BlGetBootOptionDevice(BlpApplicationEntry.BcdData,
625adcb9bd1SAlex Ionescu BcdOSLoaderDevice_OSDevice,
626adcb9bd1SAlex Ionescu &OsDevice,
627adcb9bd1SAlex Ionescu 0);
628adcb9bd1SAlex Ionescu if (!NT_SUCCESS(Status))
629adcb9bd1SAlex Ionescu {
6309ec85c29SAlex Ionescu EfiPrintf(L"Fail here: %d\r\n", __LINE__);
631adcb9bd1SAlex Ionescu goto Quickie;
632adcb9bd1SAlex Ionescu }
633adcb9bd1SAlex Ionescu
634adcb9bd1SAlex Ionescu /* If the OS device is the boot device, use the one provided by bootlib */
635adcb9bd1SAlex Ionescu if (OsDevice->DeviceType == BootDevice)
636adcb9bd1SAlex Ionescu {
637adcb9bd1SAlex Ionescu OsDevice = BlpBootDevice;
638adcb9bd1SAlex Ionescu }
639adcb9bd1SAlex Ionescu
640adcb9bd1SAlex Ionescu /* Save it as a global for later */
641adcb9bd1SAlex Ionescu OslLoadDevice = OsDevice;
642adcb9bd1SAlex Ionescu
643adcb9bd1SAlex Ionescu /* Get the system root */
644adcb9bd1SAlex Ionescu Status = BlGetBootOptionString(BlpApplicationEntry.BcdData,
645adcb9bd1SAlex Ionescu BcdOSLoaderString_SystemRoot,
646adcb9bd1SAlex Ionescu &SystemRoot);
647adcb9bd1SAlex Ionescu if (!NT_SUCCESS(Status))
648adcb9bd1SAlex Ionescu {
6499ec85c29SAlex Ionescu EfiPrintf(L"Fail here: %d\r\n", __LINE__);
650adcb9bd1SAlex Ionescu goto Quickie;
651adcb9bd1SAlex Ionescu }
652adcb9bd1SAlex Ionescu
653adcb9bd1SAlex Ionescu EfiPrintf(L"System root: %s\r\n", SystemRoot);
654adcb9bd1SAlex Ionescu
655adcb9bd1SAlex Ionescu /* Get the system root length and make sure it's slash-terminated */
656adcb9bd1SAlex Ionescu RootLength = wcslen(SystemRoot);
657adcb9bd1SAlex Ionescu if (SystemRoot[RootLength - 1] == OBJ_NAME_PATH_SEPARATOR)
658adcb9bd1SAlex Ionescu {
659adcb9bd1SAlex Ionescu /* Perfect, set it */
660adcb9bd1SAlex Ionescu OslSystemRoot = SystemRoot;
661adcb9bd1SAlex Ionescu }
662adcb9bd1SAlex Ionescu else
663adcb9bd1SAlex Ionescu {
664adcb9bd1SAlex Ionescu /* Allocate a new buffer large enough to contain the slash */
665adcb9bd1SAlex Ionescu RootLengthWithSep = RootLength + sizeof(OBJ_NAME_PATH_SEPARATOR);
666adcb9bd1SAlex Ionescu OslSystemRoot = BlMmAllocateHeap(RootLengthWithSep * sizeof(WCHAR));
667adcb9bd1SAlex Ionescu if (!OslSystemRoot)
668adcb9bd1SAlex Ionescu {
669adcb9bd1SAlex Ionescu /* Bail out if we're out of memory */
670adcb9bd1SAlex Ionescu Status = STATUS_NO_MEMORY;
6719ec85c29SAlex Ionescu EfiPrintf(L"Fail here: %d\r\n", __LINE__);
672adcb9bd1SAlex Ionescu goto Quickie;
673adcb9bd1SAlex Ionescu }
674adcb9bd1SAlex Ionescu
675adcb9bd1SAlex Ionescu /* Make a copy of the path, adding the separator */
676adcb9bd1SAlex Ionescu wcscpy(OslSystemRoot, SystemRoot);
677adcb9bd1SAlex Ionescu wcscat(OslSystemRoot, L"\\");
678adcb9bd1SAlex Ionescu
679adcb9bd1SAlex Ionescu /* Free the original one from the BCD library */
680adcb9bd1SAlex Ionescu BlMmFreeHeap(SystemRoot);
681adcb9bd1SAlex Ionescu }
682adcb9bd1SAlex Ionescu
6839ec85c29SAlex Ionescu /* Initialize access to the BSD */
6849ec85c29SAlex Ionescu OslpInitializeBootStatusDataLog();
6859ec85c29SAlex Ionescu
6869ec85c29SAlex Ionescu /* Check if we're supposed to fail on purpose */
6879ec85c29SAlex Ionescu Status = OslpCheckForcedFailure();
6889ec85c29SAlex Ionescu if (!NT_SUCCESS(Status))
6899ec85c29SAlex Ionescu {
6909ec85c29SAlex Ionescu EfiPrintf(L"Fail here: %d\r\n", __LINE__);
6919ec85c29SAlex Ionescu goto Quickie;
6929ec85c29SAlex Ionescu }
6939ec85c29SAlex Ionescu
6949ec85c29SAlex Ionescu /* Always disable VGA mode */
6959ec85c29SAlex Ionescu Status = BlAppendBootOptionBoolean(&BlpApplicationEntry,
6969ec85c29SAlex Ionescu BcdOSLoaderBoolean_DisableVgaMode,
6979ec85c29SAlex Ionescu TRUE);
6989ec85c29SAlex Ionescu if (!NT_SUCCESS(Status))
6999ec85c29SAlex Ionescu {
7009ec85c29SAlex Ionescu EfiPrintf(L"Fail here: %d\r\n", __LINE__);
7019ec85c29SAlex Ionescu goto Quickie;
7029ec85c29SAlex Ionescu }
7039ec85c29SAlex Ionescu
7049ec85c29SAlex Ionescu /* Get telemetry data from the last boot */
7059ec85c29SAlex Ionescu Status = OslGetBootStatusData(&LastBootGood,
7069ec85c29SAlex Ionescu &LastBootShutdown,
7079ec85c29SAlex Ionescu &LastBootCheckpoint,
7089ec85c29SAlex Ionescu &BootId,
7099ec85c29SAlex Ionescu &BootGood,
7109ec85c29SAlex Ionescu &BootShutdown);
7119ec85c29SAlex Ionescu if (!NT_SUCCESS(Status))
7129ec85c29SAlex Ionescu {
7139ec85c29SAlex Ionescu /* Assume this is the very first boot and everything went well */
7149ec85c29SAlex Ionescu BootId = 0;
7159ec85c29SAlex Ionescu LastBootGood = TRUE;
7169ec85c29SAlex Ionescu LastBootShutdown = TRUE;
7179ec85c29SAlex Ionescu LastBootCheckpoint = TRUE;
7189ec85c29SAlex Ionescu BootGood = TRUE;
7199ec85c29SAlex Ionescu BootShutdown = TRUE;
7209ec85c29SAlex Ionescu
7219ec85c29SAlex Ionescu /* Set 0 boot attempts */
7229ec85c29SAlex Ionescu OslBootAttemptCount = 0;
7239ec85c29SAlex Ionescu }
7249ec85c29SAlex Ionescu
7259ec85c29SAlex Ionescu /* Set more attempt variables to their initial state */
7269ec85c29SAlex Ionescu OslResetBootStatus = TRUE;
7279ec85c29SAlex Ionescu OslBootCountUpdateRequestForAbort = 0;
7289ec85c29SAlex Ionescu
7299ec85c29SAlex Ionescu /* Read the current BSD data into the global buffer */
7309ec85c29SAlex Ionescu Status = OslpReadWriteBootStatusData(FALSE);
7319ec85c29SAlex Ionescu if (NT_SUCCESS(Status))
7329ec85c29SAlex Ionescu {
7339ec85c29SAlex Ionescu /* Get the power transition buffer from the BSD */
7349ec85c29SAlex Ionescu BsdSize = sizeof(PowerTransitionData);
7359ec85c29SAlex Ionescu Status = OslpGetSetBootStatusData(TRUE,
7369ec85c29SAlex Ionescu RtlBsdPowerTransition,
7379ec85c29SAlex Ionescu &PowerTransitionData,
7389ec85c29SAlex Ionescu &BsdSize);
7399ec85c29SAlex Ionescu if (NT_SUCCESS(Status))
7409ec85c29SAlex Ionescu {
7419ec85c29SAlex Ionescu /* Save the buffer */
7429ec85c29SAlex Ionescu PowerBuffer = &PowerTransitionData;
7439ec85c29SAlex Ionescu }
7449ec85c29SAlex Ionescu }
7459ec85c29SAlex Ionescu
7469ec85c29SAlex Ionescu /* Check if this is VHD boot, which gets 3 boot attempts instead of 2 */
7479ec85c29SAlex Ionescu OslBootAttemptMaximum = 2;
7489ec85c29SAlex Ionescu OslBootAttemptMaximum += BlDeviceIsVirtualPartitionDevice(OslLoadDevice, NULL);
7499ec85c29SAlex Ionescu
7509ec85c29SAlex Ionescu /* Check if the user wants to see the advanced menu */
7519ec85c29SAlex Ionescu if (!OslpAdvancedOptionsRequested())
7529ec85c29SAlex Ionescu {
7539ec85c29SAlex Ionescu /* The last boot failed more than the maximum */
7549ec85c29SAlex Ionescu if (!(LastBootGood) &&
7559ec85c29SAlex Ionescu (OslBootAttemptCount >= OslBootAttemptMaximum))
7569ec85c29SAlex Ionescu {
7579ec85c29SAlex Ionescu /* Return failure due to boot -- launch recovery */
7589ec85c29SAlex Ionescu *ReturnFlags |= 8;
7599ec85c29SAlex Ionescu
7609ec85c29SAlex Ionescu /* Update the attempt count and status variables */
7619ec85c29SAlex Ionescu OslBootAttemptCount = OslBootAttemptMaximum - 1;
7629ec85c29SAlex Ionescu OslCurrentBootCheckpoint = LastBootCheckpoint;
7639ec85c29SAlex Ionescu OslCurrentBootSucceeded = FALSE;
7649ec85c29SAlex Ionescu OslCurrentBootShutdown = LastBootShutdown;
7659ec85c29SAlex Ionescu
7669ec85c29SAlex Ionescu /* Crash with code 15 and abort boot */
7679ec85c29SAlex Ionescu OslFatalErrorEx(15, 0, 0, 0);
7689ec85c29SAlex Ionescu Status = STATUS_UNSUCCESSFUL;
7699ec85c29SAlex Ionescu EfiPrintf(L"Fail here: %d\r\n", __LINE__);
7709ec85c29SAlex Ionescu goto Quickie;
7719ec85c29SAlex Ionescu }
7729ec85c29SAlex Ionescu
7739ec85c29SAlex Ionescu /* We never made it far enough, more than the maximum */
7749ec85c29SAlex Ionescu if (!(LastBootCheckpoint) &&
7759ec85c29SAlex Ionescu (OslBootAttemptCount >= OslBootAttemptMaximum))
7769ec85c29SAlex Ionescu {
7779ec85c29SAlex Ionescu /* Return crash/dirty shutdown during boot attempt */
7789ec85c29SAlex Ionescu *ReturnFlags |= 0x10;
7799ec85c29SAlex Ionescu
7809ec85c29SAlex Ionescu /* Update the attempt count and status variables */
7819ec85c29SAlex Ionescu OslBootAttemptCount = OslBootAttemptMaximum - 1;
7829ec85c29SAlex Ionescu OslCurrentBootSucceeded = LastBootGood;
7839ec85c29SAlex Ionescu OslCurrentBootShutdown = LastBootShutdown;
7849ec85c29SAlex Ionescu OslCurrentBootCheckpoint = FALSE;
7859ec85c29SAlex Ionescu
7869ec85c29SAlex Ionescu /* Crash with code 16 and abort boot */
7879ec85c29SAlex Ionescu OslFatalErrorEx(16, 0, 0, 0);
7889ec85c29SAlex Ionescu Status = STATUS_UNSUCCESSFUL;
7899ec85c29SAlex Ionescu EfiPrintf(L"Fail here: %d\r\n", __LINE__);
7909ec85c29SAlex Ionescu goto Quickie;
7919ec85c29SAlex Ionescu }
7929ec85c29SAlex Ionescu
7939ec85c29SAlex Ionescu /* We failed to shutdown cleanly, and haven't booted yet */
7949ec85c29SAlex Ionescu if (!(LastBootShutdown) && !(OslBootAttemptCount))
7959ec85c29SAlex Ionescu {
7969ec85c29SAlex Ionescu /* Return crash/dirty shutdown */
7979ec85c29SAlex Ionescu *ReturnFlags |= 0x10;
7989ec85c29SAlex Ionescu
7999ec85c29SAlex Ionescu /* There's no boot attempt, so only update shutdown variables */
8009ec85c29SAlex Ionescu OslCurrentBootSucceeded = LastBootGood;
8019ec85c29SAlex Ionescu OslCurrentBootShutdown = TRUE;
8029ec85c29SAlex Ionescu OslCurrentBootCheckpoint = LastBootCheckpoint;
8039ec85c29SAlex Ionescu
8049ec85c29SAlex Ionescu /* Crash with code 16 and abort boot */
8059ec85c29SAlex Ionescu OslFatalErrorEx(16, 0, 0, 0);
8069ec85c29SAlex Ionescu Status = STATUS_UNSUCCESSFUL;
8079ec85c29SAlex Ionescu EfiPrintf(L"Fail here: %d\r\n", __LINE__);
8089ec85c29SAlex Ionescu goto Quickie;
8099ec85c29SAlex Ionescu }
8109ec85c29SAlex Ionescu }
8119ec85c29SAlex Ionescu
8129ec85c29SAlex Ionescu /* Officially increment the number of boot attempts */
8139ec85c29SAlex Ionescu OslBootAttemptCount++;
8149ec85c29SAlex Ionescu
8159ec85c29SAlex Ionescu /* No success yet, write to boot status file */
8169ec85c29SAlex Ionescu OslCurrentBootCheckpoint = FALSE;
8179ec85c29SAlex Ionescu OslCurrentBootSucceeded = FALSE;
8189ec85c29SAlex Ionescu OslCurrentBootShutdown = FALSE;
8199ec85c29SAlex Ionescu OslSetBootStatusData(FALSE,
8209ec85c29SAlex Ionescu FALSE,
8219ec85c29SAlex Ionescu FALSE,
8229ec85c29SAlex Ionescu OslBootCountUpdateIncrement,
8239ec85c29SAlex Ionescu OslBootAttemptCount);
8249ec85c29SAlex Ionescu
8259ec85c29SAlex Ionescu /* Open the OS Loader Device for Read/Write access */
8269ec85c29SAlex Ionescu Status = BlpDeviceOpen(OslLoadDevice,
8279ec85c29SAlex Ionescu BL_DEVICE_READ_ACCESS | BL_DEVICE_WRITE_ACCESS,
8289ec85c29SAlex Ionescu 0,
8299ec85c29SAlex Ionescu &OsDeviceHandle);
8309ec85c29SAlex Ionescu if (!NT_SUCCESS(Status))
8319ec85c29SAlex Ionescu {
8329ec85c29SAlex Ionescu EfiPrintf(L"Fail here: %d\r\n", __LINE__);
8339ec85c29SAlex Ionescu goto Quickie;
8349ec85c29SAlex Ionescu }
8359ec85c29SAlex Ionescu
8369ec85c29SAlex Ionescu /* That's all for now, folks */
837adcb9bd1SAlex Ionescu Status = STATUS_NOT_IMPLEMENTED;
8389ec85c29SAlex Ionescu DBG_UNREFERENCED_LOCAL_VARIABLE(PowerBuffer);
839adcb9bd1SAlex Ionescu
840adcb9bd1SAlex Ionescu /* Printf perf */
841adcb9bd1SAlex Ionescu EndPerf = BlArchGetPerformanceCounter();
842adcb9bd1SAlex Ionescu EfiPrintf(L"Delta: %lld\r\n", EndPerf - StartPerf);
843adcb9bd1SAlex Ionescu
844adcb9bd1SAlex Ionescu Quickie:
845adcb9bd1SAlex Ionescu #if BL_BITLOCKER_SUPPORT
846adcb9bd1SAlex Ionescu /* Destroy the RNG/AES library for BitLocker */
847adcb9bd1SAlex Ionescu SymCryptRngAesUninstantiate();
848adcb9bd1SAlex Ionescu #endif
849adcb9bd1SAlex Ionescu
850adcb9bd1SAlex Ionescu /* Abort the boot */
851adcb9bd1SAlex Ionescu OslAbortBoot(Status);
852adcb9bd1SAlex Ionescu
853adcb9bd1SAlex Ionescu /* This is a failure path, so never do the jump */
854adcb9bd1SAlex Ionescu *Jump = FALSE;
855adcb9bd1SAlex Ionescu
856adcb9bd1SAlex Ionescu /* Return error code */
857adcb9bd1SAlex Ionescu return Status;
858e836d0b5SAlex Ionescu }
859e836d0b5SAlex Ionescu
860e836d0b5SAlex Ionescu NTSTATUS
OslFwpKernelSetupPhase1(_In_ PLOADER_PARAMETER_BLOCK LoaderBlock)861b6f5520bSAlex Ionescu OslFwpKernelSetupPhase1 (
862b6f5520bSAlex Ionescu _In_ PLOADER_PARAMETER_BLOCK LoaderBlock
863b6f5520bSAlex Ionescu )
864b6f5520bSAlex Ionescu {
865b6f5520bSAlex Ionescu return STATUS_NOT_IMPLEMENTED;
866b6f5520bSAlex Ionescu }
867b6f5520bSAlex Ionescu
868b6f5520bSAlex Ionescu NTSTATUS
OslArchpKernelSetupPhase0(_In_ PLOADER_PARAMETER_BLOCK LoaderBlock)869b6f5520bSAlex Ionescu OslArchpKernelSetupPhase0 (
870b6f5520bSAlex Ionescu _In_ PLOADER_PARAMETER_BLOCK LoaderBlock
871b6f5520bSAlex Ionescu )
872b6f5520bSAlex Ionescu {
873b6f5520bSAlex Ionescu return STATUS_NOT_IMPLEMENTED;
874b6f5520bSAlex Ionescu }
875b6f5520bSAlex Ionescu
876b6f5520bSAlex Ionescu VOID
ArchRestoreProcessorFeatures(VOID)877b6f5520bSAlex Ionescu ArchRestoreProcessorFeatures (
878b6f5520bSAlex Ionescu VOID
879b6f5520bSAlex Ionescu )
880b6f5520bSAlex Ionescu {
881b6f5520bSAlex Ionescu /* Any XCR0 bits to clear? */
882b6f5520bSAlex Ionescu if (ArchXCr0BitsToClear)
883b6f5520bSAlex Ionescu {
884b6f5520bSAlex Ionescu /* Clear them */
885*9592728fSMark Jansen #if defined(_MSC_VER) && !defined(__clang__) && !defined(_M_ARM)
886b6f5520bSAlex Ionescu __xsetbv(0, __xgetbv(0) & ~ArchXCr0BitsToClear);
887b6f5520bSAlex Ionescu #endif
888b6f5520bSAlex Ionescu ArchXCr0BitsToClear = 0;
889b6f5520bSAlex Ionescu }
890b6f5520bSAlex Ionescu
891b6f5520bSAlex Ionescu /* Any CR4 bits to clear? */
892b6f5520bSAlex Ionescu if (ArchCr4BitsToClear)
893b6f5520bSAlex Ionescu {
894b6f5520bSAlex Ionescu /* Clear them */
895*9592728fSMark Jansen #if !defined(_M_ARM)
896b6f5520bSAlex Ionescu __writecr4(__readcr4() & ~ArchCr4BitsToClear);
897*9592728fSMark Jansen #endif
898b6f5520bSAlex Ionescu ArchCr4BitsToClear = 0;
899b6f5520bSAlex Ionescu }
900b6f5520bSAlex Ionescu }
901b6f5520bSAlex Ionescu
902b6f5520bSAlex Ionescu NTSTATUS
OslArchKernelSetup(_In_ ULONG Phase,_In_ PLOADER_PARAMETER_BLOCK LoaderBlock)903b6f5520bSAlex Ionescu OslArchKernelSetup (
904b6f5520bSAlex Ionescu _In_ ULONG Phase,
905b6f5520bSAlex Ionescu _In_ PLOADER_PARAMETER_BLOCK LoaderBlock
906b6f5520bSAlex Ionescu )
907b6f5520bSAlex Ionescu {
908b6f5520bSAlex Ionescu /* For phase 0, do architectural setup */
909b6f5520bSAlex Ionescu if (Phase == 0)
910b6f5520bSAlex Ionescu {
911b6f5520bSAlex Ionescu return OslArchpKernelSetupPhase0(LoaderBlock);
912b6f5520bSAlex Ionescu }
913b6f5520bSAlex Ionescu
914b6f5520bSAlex Ionescu /* Nothing to do for Phase 1 */
915b6f5520bSAlex Ionescu if (Phase == 1)
916b6f5520bSAlex Ionescu {
917b6f5520bSAlex Ionescu return STATUS_SUCCESS;
918b6f5520bSAlex Ionescu }
919b6f5520bSAlex Ionescu
920b6f5520bSAlex Ionescu /* Relocate the self map */
921b6f5520bSAlex Ionescu BlMmRelocateSelfMap();
922b6f5520bSAlex Ionescu
923b6f5520bSAlex Ionescu /* Zero out the HAL Heap */
924b6f5520bSAlex Ionescu BlMmZeroVirtualAddressRange((PVOID)MM_HAL_VA_START,
925b6f5520bSAlex Ionescu MM_HAL_VA_END - MM_HAL_VA_START + 1);
926b6f5520bSAlex Ionescu
927b6f5520bSAlex Ionescu /* Move shared user data in its place */
928b6f5520bSAlex Ionescu BlMmMoveVirtualAddressRange((PVOID)KI_USER_SHARED_DATA,
929b6f5520bSAlex Ionescu UserSharedAddress,
930b6f5520bSAlex Ionescu PAGE_SIZE);
931b6f5520bSAlex Ionescu
932b6f5520bSAlex Ionescu /* Clear XCR0/CR4 CPU features that should be disabled before boot */
933b6f5520bSAlex Ionescu ArchRestoreProcessorFeatures();
934b6f5520bSAlex Ionescu
935b6f5520bSAlex Ionescu /* Good to go */
936b6f5520bSAlex Ionescu return STATUS_SUCCESS;
937b6f5520bSAlex Ionescu }
938b6f5520bSAlex Ionescu
939b6f5520bSAlex Ionescu NTSTATUS
OslExecuteTransition(VOID)940e836d0b5SAlex Ionescu OslExecuteTransition (
941e836d0b5SAlex Ionescu VOID
942e836d0b5SAlex Ionescu )
943e836d0b5SAlex Ionescu {
944b6f5520bSAlex Ionescu NTSTATUS Status;
945b6f5520bSAlex Ionescu
946b6f5520bSAlex Ionescu /* Is the debugger meant to be kept enabled throughout the boot phase? */
947b6f5520bSAlex Ionescu if (!BdDebugAfterExitBootServices)
948b6f5520bSAlex Ionescu {
949b6f5520bSAlex Ionescu #ifdef BL_KD_SUPPORT
950b6f5520bSAlex Ionescu /* No -- disable it */
951b6f5520bSAlex Ionescu BlBdStop();
952b6f5520bSAlex Ionescu #endif
953b6f5520bSAlex Ionescu }
954b6f5520bSAlex Ionescu
955b6f5520bSAlex Ionescu /* Setup Firmware for Phase 1 */
956adcb9bd1SAlex Ionescu Status = OslFwpKernelSetupPhase1(OslLoaderBlock);
957b6f5520bSAlex Ionescu if (NT_SUCCESS(Status))
958b6f5520bSAlex Ionescu {
959b6f5520bSAlex Ionescu /* Setup kernel for Phase 2 */
960adcb9bd1SAlex Ionescu Status = OslArchKernelSetup(2, OslLoaderBlock);
961b6f5520bSAlex Ionescu if (NT_SUCCESS(Status))
962b6f5520bSAlex Ionescu {
963b6f5520bSAlex Ionescu #ifdef BL_KD_SUPPORT
964b6f5520bSAlex Ionescu /* Stop the boot debugger */
965b6f5520bSAlex Ionescu BlBdStop();
966b6f5520bSAlex Ionescu #endif
967b6f5520bSAlex Ionescu /* Jump to the kernel entrypoint */
968adcb9bd1SAlex Ionescu OslArchTransferToKernel(OslLoaderBlock, OslEntryPoint);
969b6f5520bSAlex Ionescu
970b6f5520bSAlex Ionescu /* Infinite loop if we got here */
971b6f5520bSAlex Ionescu for (;;);
972b6f5520bSAlex Ionescu }
973b6f5520bSAlex Ionescu }
974b6f5520bSAlex Ionescu
975b6f5520bSAlex Ionescu /* Return back with the failure code */
976b6f5520bSAlex Ionescu return Status;
977e836d0b5SAlex Ionescu }
978e836d0b5SAlex Ionescu
979e836d0b5SAlex Ionescu NTSTATUS
OslpMain(_Out_ PULONG ReturnFlags)980e836d0b5SAlex Ionescu OslpMain (
981e836d0b5SAlex Ionescu _Out_ PULONG ReturnFlags
982e836d0b5SAlex Ionescu )
983e836d0b5SAlex Ionescu {
984e836d0b5SAlex Ionescu NTSTATUS Status;
985e836d0b5SAlex Ionescu BOOLEAN ExecuteJump;
986*9592728fSMark Jansen #if !defined(_M_ARM)
987*9592728fSMark Jansen CPU_INFO CpuInfo;
988*9592728fSMark Jansen BOOLEAN NxEnabled;
989b6f5520bSAlex Ionescu LARGE_INTEGER MiscMsr;
990e836d0b5SAlex Ionescu
991e836d0b5SAlex Ionescu /* Check if the CPU supports NX */
992478348eaSAlex Ionescu BlArchCpuId(0x80000001, 0, &CpuInfo);
993478348eaSAlex Ionescu if (!(CpuInfo.Edx & 0x10000))
994e836d0b5SAlex Ionescu {
995e836d0b5SAlex Ionescu /* It doesn't, check if this is Intel */
996478348eaSAlex Ionescu EfiPrintf(L"NX disabled: %lx\r\n", CpuInfo.Edx);
997e836d0b5SAlex Ionescu if (BlArchGetCpuVendor() == CPU_INTEL)
998e836d0b5SAlex Ionescu {
999478348eaSAlex Ionescu /* Then turn off the MSR disable feature for it, enabling NX */
1000b6f5520bSAlex Ionescu MiscMsr.QuadPart = __readmsr(MSR_IA32_MISC_ENABLE);
1001b6f5520bSAlex Ionescu EfiPrintf(L"NX being turned on: %llx\r\n", MiscMsr.QuadPart);
1002b6f5520bSAlex Ionescu MiscMsr.HighPart &= MSR_XD_ENABLE_MASK;
1003b6f5520bSAlex Ionescu MiscMsr.QuadPart = __readmsr(MSR_IA32_MISC_ENABLE);
1004b6f5520bSAlex Ionescu __writemsr(MSR_IA32_MISC_ENABLE, MiscMsr.QuadPart);
1005478348eaSAlex Ionescu NxEnabled = TRUE;
1006e836d0b5SAlex Ionescu }
1007e836d0b5SAlex Ionescu }
1008e836d0b5SAlex Ionescu
1009e836d0b5SAlex Ionescu /* Turn on NX support with the CPU-generic MSR */
1010e836d0b5SAlex Ionescu __writemsr(MSR_EFER, __readmsr(MSR_EFER) | MSR_NXE);
1011e836d0b5SAlex Ionescu
1012*9592728fSMark Jansen #endif
1013*9592728fSMark Jansen
1014e836d0b5SAlex Ionescu /* Load the kernel */
1015e836d0b5SAlex Ionescu Status = OslPrepareTarget(ReturnFlags, &ExecuteJump);
1016e836d0b5SAlex Ionescu if (NT_SUCCESS(Status) && (ExecuteJump))
1017e836d0b5SAlex Ionescu {
1018e836d0b5SAlex Ionescu /* Jump to the kernel */
1019e836d0b5SAlex Ionescu Status = OslExecuteTransition();
1020e836d0b5SAlex Ionescu }
1021e836d0b5SAlex Ionescu
1022*9592728fSMark Jansen #if !defined(_M_ARM)
1023e836d0b5SAlex Ionescu /* Retore NX support */
1024e836d0b5SAlex Ionescu __writemsr(MSR_EFER, __readmsr(MSR_EFER) ^ MSR_NXE);
1025e836d0b5SAlex Ionescu
1026478348eaSAlex Ionescu /* Did we manually enable NX? */
1027478348eaSAlex Ionescu if (NxEnabled)
1028e836d0b5SAlex Ionescu {
1029478348eaSAlex Ionescu /* Turn it back off */
1030b6f5520bSAlex Ionescu MiscMsr.QuadPart = __readmsr(MSR_IA32_MISC_ENABLE);
1031b6f5520bSAlex Ionescu MiscMsr.HighPart |= ~MSR_XD_ENABLE_MASK;
1032b6f5520bSAlex Ionescu __writemsr(MSR_IA32_MISC_ENABLE, MiscMsr.QuadPart);
1033e836d0b5SAlex Ionescu }
1034e836d0b5SAlex Ionescu
1035*9592728fSMark Jansen #endif
1036e836d0b5SAlex Ionescu /* Go back */
1037e836d0b5SAlex Ionescu return Status;
1038e836d0b5SAlex Ionescu }
1039e836d0b5SAlex Ionescu
1040c2c66affSColin Finck /*++
1041c2c66affSColin Finck * @name OslMain
1042c2c66affSColin Finck *
1043c2c66affSColin Finck * The OslMain function implements the Windows Boot Application entrypoint for
1044c2c66affSColin Finck * the OS Loader.
1045c2c66affSColin Finck *
1046c2c66affSColin Finck * @param BootParameters
1047c2c66affSColin Finck * Pointer to the Boot Application Parameter Block.
1048c2c66affSColin Finck *
1049c2c66affSColin Finck * @return NT_SUCCESS if the image was loaded correctly, relevant error code
1050c2c66affSColin Finck * otherwise.
1051c2c66affSColin Finck *
1052c2c66affSColin Finck *--*/
1053c2c66affSColin Finck NTSTATUS
1054c2c66affSColin Finck NTAPI
OslMain(_In_ PBOOT_APPLICATION_PARAMETER_BLOCK BootParameters)1055c2c66affSColin Finck OslMain (
1056c2c66affSColin Finck _In_ PBOOT_APPLICATION_PARAMETER_BLOCK BootParameters
1057c2c66affSColin Finck )
1058c2c66affSColin Finck {
1059c2c66affSColin Finck BL_LIBRARY_PARAMETERS LibraryParameters;
1060c2c66affSColin Finck NTSTATUS Status;
1061e836d0b5SAlex Ionescu PBL_RETURN_ARGUMENTS ReturnArguments;
1062e836d0b5SAlex Ionescu PBL_APPLICATION_ENTRY AppEntry;
1063478348eaSAlex Ionescu CPU_INFO CpuInfo;
1064e836d0b5SAlex Ionescu ULONG Flags;
1065e836d0b5SAlex Ionescu
1066e836d0b5SAlex Ionescu /* Get the return arguments structure, and set our version */
1067e836d0b5SAlex Ionescu ReturnArguments = (PBL_RETURN_ARGUMENTS)((ULONG_PTR)BootParameters +
1068e836d0b5SAlex Ionescu BootParameters->ReturnArgumentsOffset);
1069e836d0b5SAlex Ionescu ReturnArguments->Version = BL_RETURN_ARGUMENTS_VERSION;
1070e836d0b5SAlex Ionescu
1071e836d0b5SAlex Ionescu /* Get the application entry, and validate it */
1072e836d0b5SAlex Ionescu AppEntry = (PBL_APPLICATION_ENTRY)((ULONG_PTR)BootParameters +
1073e836d0b5SAlex Ionescu BootParameters->AppEntryOffset);
1074e836d0b5SAlex Ionescu if (!RtlEqualMemory(AppEntry->Signature,
1075e836d0b5SAlex Ionescu BL_APP_ENTRY_SIGNATURE,
1076e836d0b5SAlex Ionescu sizeof(AppEntry->Signature)))
1077e836d0b5SAlex Ionescu {
1078e836d0b5SAlex Ionescu /* Unrecognized, bail out */
1079e836d0b5SAlex Ionescu Status = STATUS_INVALID_PARAMETER_9;
1080e836d0b5SAlex Ionescu goto Quickie;
1081e836d0b5SAlex Ionescu }
1082e836d0b5SAlex Ionescu
1083*9592728fSMark Jansen #if !defined(_M_ARM)
1084e836d0b5SAlex Ionescu /* Check if CPUID 01h is supported */
1085e836d0b5SAlex Ionescu if (BlArchIsCpuIdFunctionSupported(1))
1086e836d0b5SAlex Ionescu {
1087e836d0b5SAlex Ionescu /* Query CPU features */
1088478348eaSAlex Ionescu BlArchCpuId(1, 0, &CpuInfo);
1089e836d0b5SAlex Ionescu
1090e836d0b5SAlex Ionescu /* Check if PAE is supported */
1091478348eaSAlex Ionescu if (CpuInfo.Edx & 0x40)
1092e836d0b5SAlex Ionescu {
1093e836d0b5SAlex Ionescu EfiPrintf(L"PAE Supported, but won't be used\r\n");
1094e836d0b5SAlex Ionescu }
1095e836d0b5SAlex Ionescu }
1096*9592728fSMark Jansen #endif
1097c2c66affSColin Finck
1098c2c66affSColin Finck /* Setup the boot library parameters for this application */
1099c2c66affSColin Finck BlSetupDefaultParameters(&LibraryParameters);
1100c2c66affSColin Finck LibraryParameters.TranslationType = BlVirtual;
1101c2c66affSColin Finck LibraryParameters.LibraryFlags = BL_LIBRARY_FLAG_ZERO_HEAP_ALLOCATIONS_ON_FREE |
1102c2c66affSColin Finck BL_LIBRARY_FLAG_REINITIALIZE_ALL;
1103c2c66affSColin Finck LibraryParameters.MinimumAllocationCount = 1024;
1104c2c66affSColin Finck LibraryParameters.MinimumHeapSize = 2 * 1024 * 1024;
1105c2c66affSColin Finck LibraryParameters.HeapAllocationAttributes = BlMemoryKernelRange;
1106c2c66affSColin Finck LibraryParameters.FontBaseDirectory = L"\\Reactos\\Boot\\Fonts";
1107c2c66affSColin Finck LibraryParameters.DescriptorCount = 512;
1108e836d0b5SAlex Ionescu
1109e836d0b5SAlex Ionescu /* Initialize the boot library */
1110c2c66affSColin Finck Status = BlInitializeLibrary(BootParameters, &LibraryParameters);
1111e836d0b5SAlex Ionescu if (NT_SUCCESS(Status))
1112e836d0b5SAlex Ionescu {
1113b6f5520bSAlex Ionescu /* For testing, draw the logo */
1114b6f5520bSAlex Ionescu OslDrawLogo();
1115c2c66affSColin Finck
1116e836d0b5SAlex Ionescu /* Call the main routine */
1117e836d0b5SAlex Ionescu Status = OslpMain(&Flags);
1118e836d0b5SAlex Ionescu
1119e836d0b5SAlex Ionescu /* Return the flags, and destroy the boot library */
1120e836d0b5SAlex Ionescu ReturnArguments->Flags = Flags;
1121e836d0b5SAlex Ionescu BlDestroyLibrary();
1122e836d0b5SAlex Ionescu }
1123e836d0b5SAlex Ionescu
1124e836d0b5SAlex Ionescu Quickie:
1125e836d0b5SAlex Ionescu /* Return back to boot manager */
1126e836d0b5SAlex Ionescu ReturnArguments->Status = Status;
1127c2c66affSColin Finck return Status;
1128c2c66affSColin Finck }
1129c2c66affSColin Finck
1130