xref: /reactos/boot/environ/app/rosload/rosload.c (revision 9393fc32)
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