From 9ec85c29e31206918868e05beff71fa4ecb47559 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Sun, 4 Feb 2018 16:01:38 -0800 Subject: [PATCH] [ROSLOAD]: Continue work on target preparation OslPrepareTarget 2/104. [ROSLOAD]: Stubplement OslpCheckForcedFailure, OslpGetSetBootStatusData, OslSetBootStatusData, OslGetBootStatusData. [ROSLOAD]: Stub OslpInitializeBootStatusDataLog, OslpReadWriteBootStatusData. [BOOTLIB]: Fix BlAppendBootOptionString to accept an actual BCD ID instead of hardcoding LibraryPath. [BOOTLIB]: Fix BlAppendBootOptionBoolean to accept an actual BOOLEAN value instead of hardcoding TRUE. [BOOTLIB]: Implement BlDeviceIsVirtualPartitionDevice. [BOOTLIB]: Add missing BcdOSLoaderInteger_ForceFailure BCD value. Add BCDE_OSLOADER_TYPE_BOOT_STATUS_POLICY based on BcdEdit.exe and Geoff Chappel site. --- boot/environ/app/bootmgr/bootmgr.c | 18 +- boot/environ/app/rosload/rosload.c | 554 ++++++++++++++++++++++++++++- boot/environ/app/rosload/rosload.h | 6 + boot/environ/include/bcd.h | 20 +- boot/environ/include/bl.h | 14 +- boot/environ/lib/io/device.c | 33 ++ boot/environ/lib/misc/bcdopt.c | 8 +- 7 files changed, 632 insertions(+), 21 deletions(-) diff --git a/boot/environ/app/bootmgr/bootmgr.c b/boot/environ/app/bootmgr/bootmgr.c index b63e63b201a..85d501b3100 100644 --- a/boot/environ/app/bootmgr/bootmgr.c +++ b/boot/environ/app/bootmgr/bootmgr.c @@ -1357,7 +1357,9 @@ BmpPopulateBootEntryList ( L"\\Windows\\System32\\winload.efi"; /* Add the path to the boot entry */ - Status = BlAppendBootOptionString(BootEntry, LoaderPath); + Status = BlAppendBootOptionString(BootEntry, + BcdLibraryString_ApplicationPath, + LoaderPath); if (!NT_SUCCESS(Status)) { goto Quickie; @@ -2511,7 +2513,8 @@ TryAgain: { /* Set the option this once */ BlAppendBootOptionBoolean(BootEntry, - BcdLibraryBoolean_DisplayAdvancedOptions); + BcdLibraryBoolean_DisplayAdvancedOptions, + TRUE); } else { @@ -2536,7 +2539,8 @@ TryAgain: { /* Set the option this once */ BlAppendBootOptionBoolean(BootEntry, - BcdLibraryBoolean_DisplayOptionsEdit); + BcdLibraryBoolean_DisplayOptionsEdit, + TRUE); } else { @@ -2686,12 +2690,16 @@ Quickie: case AdvancedOptions: /* Show the advanced options next iteration */ - BlAppendBootOptionBoolean(BootEntry, BcdOSLoaderBoolean_AdvancedOptionsOneTime); + BlAppendBootOptionBoolean(BootEntry, + BcdOSLoaderBoolean_AdvancedOptionsOneTime, + TRUE); goto TryAgain; case BootOptions: /* Show the options editor next iteration */ - BlAppendBootOptionBoolean(BootEntry, BcdOSLoaderBoolean_OptionsEditOneTime); + BlAppendBootOptionBoolean(BootEntry, + BcdOSLoaderBoolean_OptionsEditOneTime, + TRUE); goto TryAgain; case Recover: diff --git a/boot/environ/app/rosload/rosload.c b/boot/environ/app/rosload/rosload.c index 9eda2d31fec..65fa445c773 100644 --- a/boot/environ/app/rosload/rosload.c +++ b/boot/environ/app/rosload/rosload.c @@ -50,6 +50,88 @@ BOOLEAN OslImcProcessingValid; ULONG OslFreeMemoryDesctiptorsListSize; PVOID OslMemoryDescriptorBuffer; +BcdObjectType BlpSbdiCurrentApplicationType; + +PRTL_BSD_DATA BsdBootStatusData; + +OSL_BSD_ITEM_TABLE_ENTRY OslpBootStatusFields[RtlBsdItemMax] = +{ + { + FIELD_OFFSET(RTL_BSD_DATA, Version), + sizeof(&BsdBootStatusData->Version) + }, // RtlBsdItemVersionNumber + { + FIELD_OFFSET(RTL_BSD_DATA, ProductType), + sizeof(&BsdBootStatusData->ProductType) + }, // RtlBsdItemProductType + { + FIELD_OFFSET(RTL_BSD_DATA, AabEnabled), + sizeof(&BsdBootStatusData->AabEnabled) + }, // RtlBsdItemAabEnabled + { + FIELD_OFFSET(RTL_BSD_DATA, AabTimeout), + sizeof(&BsdBootStatusData->AabTimeout) + }, // RtlBsdItemAabTimeout + { + FIELD_OFFSET(RTL_BSD_DATA, LastBootSucceeded), + sizeof(&BsdBootStatusData->LastBootSucceeded) + }, // RtlBsdItemBootGood + { + FIELD_OFFSET(RTL_BSD_DATA, LastBootShutdown), + sizeof(&BsdBootStatusData->LastBootShutdown) + }, // RtlBsdItemBootShutdown + { + FIELD_OFFSET(RTL_BSD_DATA, SleepInProgress), + sizeof(&BsdBootStatusData->SleepInProgress) + }, // RtlBsdSleepInProgress + { + FIELD_OFFSET(RTL_BSD_DATA, PowerTransition), + sizeof(&BsdBootStatusData->PowerTransition) + }, // RtlBsdPowerTransition + { + FIELD_OFFSET(RTL_BSD_DATA, BootAttemptCount), + sizeof(&BsdBootStatusData->BootAttemptCount) + }, // RtlBsdItemBootAttemptCount + { + FIELD_OFFSET(RTL_BSD_DATA, LastBootCheckpoint), + sizeof(&BsdBootStatusData->LastBootCheckpoint) + }, // RtlBsdItemBootCheckpoint + { + FIELD_OFFSET(RTL_BSD_DATA, LastBootId), + sizeof(&BsdBootStatusData->LastBootId) + }, // RtlBsdItemBootId + { + FIELD_OFFSET(RTL_BSD_DATA, LastSuccessfulShutdownBootId), + sizeof(&BsdBootStatusData->LastSuccessfulShutdownBootId) + }, // RtlBsdItemShutdownBootId + { + FIELD_OFFSET(RTL_BSD_DATA, LastReportedAbnormalShutdownBootId), + sizeof(&BsdBootStatusData->LastReportedAbnormalShutdownBootId) + }, // RtlBsdItemReportedAbnormalShutdownBootId + { + FIELD_OFFSET(RTL_BSD_DATA, ErrorInfo), + sizeof(&BsdBootStatusData->ErrorInfo) + }, // RtlBsdItemErrorInfo + { + FIELD_OFFSET(RTL_BSD_DATA, PowerButtonPressInfo), + sizeof(&BsdBootStatusData->PowerButtonPressInfo) + }, // RtlBsdItemPowerButtonPressInfo + { + FIELD_OFFSET(RTL_BSD_DATA, Checksum), + sizeof(&BsdBootStatusData->Checksum) + }, // RtlBsdItemChecksum +}; + +ULONG OslBootAttemptCount; +ULONG OslBootCountUpdateRequestForAbort; +ULONG OslBootAttemptMaximum; + +ULONG OslBootCountUpdateIncrement; + +BOOLEAN OslCurrentBootCheckpoint; +BOOLEAN OslCurrentBootSucceeded; +BOOLEAN OslCurrentBootShutdown; + /* FUNCTIONS *****************************************************************/ VOID @@ -139,8 +221,8 @@ OslpRemoveInternalApplicationOptions ( _wcsupr(LoadString); /* Remove the existing one */ - //BlRemoveBootOption(BlpApplicationEntry.BcdData, - // BcdLibraryString_LoadOptionsString); + BlRemoveBootOption(BlpApplicationEntry.BcdData, + BcdLibraryString_LoadOptionsString); /* Sanitize strings we don't want */ OslpSanitizeLoadOptionsString(LoadString, L"DISABLE_INTEGRITY_CHECKS"); @@ -148,9 +230,9 @@ OslpRemoveInternalApplicationOptions ( OslpSanitizeLoadOptionsString(LoadString, L"DISABLEELAMDRIVERS"); /* Add the sanitized one back */ - //Status = BlAppendBootOptionsString(&BlpApplicationEntry, - // BcdLibraryString_LoadOptionsString, - // LoadString); + Status = BlAppendBootOptionString(&BlpApplicationEntry, + BcdLibraryString_LoadOptionsString, + LoadString); /* Free the original BCD one */ BlMmFreeHeap(LoadString); @@ -163,6 +245,288 @@ OslpRemoveInternalApplicationOptions ( return Status; } +NTSTATUS +OslpCheckForcedFailure ( + VOID + ) +{ + ULONG64 ForceReason; + NTSTATUS Status; + + /* Read the option */ + Status = BlGetBootOptionInteger(BlpApplicationEntry.BcdData, + BcdOSLoaderInteger_ForceFailure, + &ForceReason); + if (NT_SUCCESS(Status) && (ForceReason < 4)) + { + /* For reasons above 3, don't actually do anything */ + if (ForceReason > 3) + { + return STATUS_SUCCESS; + } + } + + /* If the option isn't there or invalid, always return success */ + return STATUS_SUCCESS; +} + +VOID +OslpInitializeBootStatusDataLog ( + VOID + ) +{ + /* TODO */ + return; +} + +NTSTATUS +OslpReadWriteBootStatusData ( + _In_ BOOLEAN WriteAccess + ) +{ + /* Are you trying to write? */ + if (WriteAccess) + { + /* Have we already read? */ + if (!BsdBootStatusData) + { + /* No -- fail */ + return STATUS_UNSUCCESSFUL; + } + } + else if (BsdBootStatusData) + { + /* No -- you're trying to read and we already have the data: no-op */ + return STATUS_SUCCESS; + } + + /* TODO */ + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +OslpGetSetBootStatusData ( + _In_ BOOLEAN Read, + _In_ RTL_BSD_ITEM_TYPE DataClass, + _Out_ PVOID Buffer, + _Inout_ PULONG Size + ) +{ + NTSTATUS Status; + ULONG Length, Offset; + + /* No data has been read yet, fail */ + if (!BsdBootStatusData) + { + return STATUS_UNSUCCESSFUL; + } + + /* Invalid data item, fail */ + if (DataClass >= RtlBsdItemMax) + { + return STATUS_INVALID_PARAMETER; + } + + /* Capture the length and offset */ + Length = OslpBootStatusFields[DataClass].Size; + Offset = OslpBootStatusFields[DataClass].Offset; + + /* Make sure it doesn't overflow past the structure we've read */ + if ((Length + Offset) > BsdBootStatusData->Version) + { + return STATUS_REVISION_MISMATCH; + } + + /* Make sure we have enough space */ + if (*Size >= Length) + { + /* We do -- is this a read? */ + if (Read) + { + /* Yes, copy into the caller's buffer */ + RtlCopyMemory(Buffer, + (PVOID)((ULONG_PTR)BsdBootStatusData + Offset), + Length); + } + else + { + /* It's a write, copy from caller's buffer */ + RtlCopyMemory((PVOID)((ULONG_PTR)BsdBootStatusData + Offset), + Buffer, + Length); + } + + /* Set success */ + Status = STATUS_SUCCESS; + } + else + { + /* Return size needed and failure code */ + *Size = Length; + Status = STATUS_BUFFER_TOO_SMALL; + } + + /* All good */ + return Status; +} + +NTSTATUS +OslSetBootStatusData ( + _In_ BOOLEAN LastBootGood, + _In_ BOOLEAN LastBootShutdown, + _In_ BOOLEAN LastBootCheckpoint, + _In_ ULONG UpdateIncrement, + _In_ ULONG BootAttemptCount + ) +{ + NTSTATUS Status; + ULONG Size; + + /* Capture the BSD data in our globals, if needed */ + Status = OslpReadWriteBootStatusData(FALSE); + if (!NT_SUCCESS(Status)) + { + goto Quickie; + } + + /* Write last boot shutdown */ + Size = sizeof(LastBootShutdown); + Status = OslpGetSetBootStatusData(FALSE, + RtlBsdItemBootShutdown, + &LastBootShutdown, + &Size); + if (!NT_SUCCESS(Status)) + { + goto Quickie; + } + + /* Write last boot good */ + Size = sizeof(LastBootGood); + Status = OslpGetSetBootStatusData(FALSE, + RtlBsdItemBootGood, + &LastBootGood, + &Size); + if (!NT_SUCCESS(Status)) + { + goto Quickie; + } + + /* Write last boot checkpoint */ + Size = sizeof(LastBootCheckpoint); + Status = OslpGetSetBootStatusData(FALSE, + RtlBsdItemBootCheckpoint, + &LastBootCheckpoint, + &Size); + if (!NT_SUCCESS(Status)) + { + goto Quickie; + } + + /* Write boot attempt count */ + Size = sizeof(BootAttemptCount); + Status = OslpGetSetBootStatusData(FALSE, + RtlBsdItemBootAttemptCount, + &BootAttemptCount, + &Size); + if (!NT_SUCCESS(Status)) + { + goto Quickie; + } + + /* TODO: Update Boot ID*/ + + /* Now write the data */ + Status = OslpReadWriteBootStatusData(TRUE); + +Quickie: + return Status; +} + +NTSTATUS +OslGetBootStatusData ( + _Out_ PBOOLEAN LastBootGood, + _Out_ PBOOLEAN LastBootShutdown, + _Out_ PBOOLEAN LastBootCheckpoint, + _Out_ PULONG LastBootId, + _Out_ PBOOLEAN BootGood, + _Out_ PBOOLEAN BootShutdown + ) +{ + NTSTATUS Status; + ULONG Size; + ULONG64 BootStatusPolicy; + BOOLEAN localBootShutdown, localBootGood; + + /* Capture the BSD data in our globals, if needed */ + Status = OslpReadWriteBootStatusData(FALSE); + if (!NT_SUCCESS(Status)) + { + goto Quickie; + } + + /* Read the last boot ID */ + Size = sizeof(*LastBootId); + Status = OslpGetSetBootStatusData(TRUE, RtlBsdItemBootId, LastBootId, &Size); + if (!NT_SUCCESS(Status)) + { + /* Set to zero if we couldn't find it */ + *LastBootId = 0; + } + + /* Get the boot status policy */ + Status = BlGetBootOptionInteger(BlpApplicationEntry.BcdData, + BcdOSLoaderInteger_BootStatusPolicy, + &BootStatusPolicy); + if (!NT_SUCCESS(Status)) + { + /* Apply a default if none exists */ + BootStatusPolicy = IgnoreShutdownFailures; + } + + /* Check if this was a good shutdown */ + Size = sizeof(localBootShutdown); + Status = OslpGetSetBootStatusData(TRUE, + RtlBsdItemBootShutdown, + &localBootShutdown, + &Size); + if (!NT_SUCCESS(Status)) + { + goto Quickie; + } + + /* Tell the caller */ + *BootShutdown = localBootShutdown; + + /* Check if this was a good boot */ + Size = sizeof(localBootGood); + Status = OslpGetSetBootStatusData(TRUE, + RtlBsdItemBootGood, + &localBootGood, + &Size); + if (!NT_SUCCESS(Status)) + { + goto Quickie; + } + + /* Tell the caller*/ + *BootGood = localBootGood; + + /* TODO: Additional logic for checkpoints and such */ + Status = STATUS_NOT_IMPLEMENTED; + +Quickie: + return Status; +} + +BOOLEAN +OslpAdvancedOptionsRequested ( + VOID + ) +{ + /* TODO */ + return FALSE; +} + NTSTATUS OslPrepareTarget ( _Out_ PULONG ReturnFlags, @@ -176,6 +540,16 @@ OslPrepareTarget ( SIZE_T RootLength, RootLengthWithSep; ULONG i; ULONG64 StartPerf, EndPerf; + RTL_BSD_DATA_POWER_TRANSITION PowerTransitionData; + PRTL_BSD_DATA_POWER_TRANSITION PowerBuffer; + ULONG OsDeviceHandle; + BOOLEAN LastBootGood, LastBootShutdown, LastBootCheckpoint; + ULONG BootId; + BOOLEAN BootGood, BootShutdown; + ULONG BsdSize; + + /* Initialize locals */ + PowerBuffer = NULL; /* Assume no flags */ *ReturnFlags = 0; @@ -214,9 +588,14 @@ OslPrepareTarget ( /* Capture the current TSC */ StartPerf = BlArchGetPerformanceCounter(); -#ifdef BL_TPM_SUPPORT - BlpSbdiCurrentApplicationType = 0x10200003; -#endif + /* Set our application type for SecureBoot/TPM purposes */ + BlpSbdiCurrentApplicationType.Application.ObjectCode = + BCD_OBJECT_TYPE_APPLICATION; + BlpSbdiCurrentApplicationType.Application.ImageCode = + BCD_IMAGE_TYPE_BOOT_APP; + BlpSbdiCurrentApplicationType.Application.ApplicationCode = + BCD_APPLICATION_TYPE_OSLOADER; + BlpSbdiCurrentApplicationType.Application.Reserved = 0; /* Register an error handler */ BlpStatusErrorHandler = OslBlStatusErrorHandler; @@ -237,6 +616,7 @@ OslPrepareTarget ( Status = OslpRemoveInternalApplicationOptions(); if (!NT_SUCCESS(Status)) { + EfiPrintf(L"Fail here: %d\r\n", __LINE__); goto Quickie; } @@ -247,6 +627,7 @@ OslPrepareTarget ( 0); if (!NT_SUCCESS(Status)) { + EfiPrintf(L"Fail here: %d\r\n", __LINE__); goto Quickie; } @@ -265,6 +646,7 @@ OslPrepareTarget ( &SystemRoot); if (!NT_SUCCESS(Status)) { + EfiPrintf(L"Fail here: %d\r\n", __LINE__); goto Quickie; } @@ -286,6 +668,7 @@ OslPrepareTarget ( { /* Bail out if we're out of memory */ Status = STATUS_NO_MEMORY; + EfiPrintf(L"Fail here: %d\r\n", __LINE__); goto Quickie; } @@ -297,7 +680,162 @@ OslPrepareTarget ( BlMmFreeHeap(SystemRoot); } + /* Initialize access to the BSD */ + OslpInitializeBootStatusDataLog(); + + /* Check if we're supposed to fail on purpose */ + Status = OslpCheckForcedFailure(); + if (!NT_SUCCESS(Status)) + { + EfiPrintf(L"Fail here: %d\r\n", __LINE__); + goto Quickie; + } + + /* Always disable VGA mode */ + Status = BlAppendBootOptionBoolean(&BlpApplicationEntry, + BcdOSLoaderBoolean_DisableVgaMode, + TRUE); + if (!NT_SUCCESS(Status)) + { + EfiPrintf(L"Fail here: %d\r\n", __LINE__); + goto Quickie; + } + + /* Get telemetry data from the last boot */ + Status = OslGetBootStatusData(&LastBootGood, + &LastBootShutdown, + &LastBootCheckpoint, + &BootId, + &BootGood, + &BootShutdown); + if (!NT_SUCCESS(Status)) + { + /* Assume this is the very first boot and everything went well */ + BootId = 0; + LastBootGood = TRUE; + LastBootShutdown = TRUE; + LastBootCheckpoint = TRUE; + BootGood = TRUE; + BootShutdown = TRUE; + + /* Set 0 boot attempts */ + OslBootAttemptCount = 0; + } + + /* Set more attempt variables to their initial state */ + OslResetBootStatus = TRUE; + OslBootCountUpdateRequestForAbort = 0; + + /* Read the current BSD data into the global buffer */ + Status = OslpReadWriteBootStatusData(FALSE); + if (NT_SUCCESS(Status)) + { + /* Get the power transition buffer from the BSD */ + BsdSize = sizeof(PowerTransitionData); + Status = OslpGetSetBootStatusData(TRUE, + RtlBsdPowerTransition, + &PowerTransitionData, + &BsdSize); + if (NT_SUCCESS(Status)) + { + /* Save the buffer */ + PowerBuffer = &PowerTransitionData; + } + } + + /* Check if this is VHD boot, which gets 3 boot attempts instead of 2 */ + OslBootAttemptMaximum = 2; + OslBootAttemptMaximum += BlDeviceIsVirtualPartitionDevice(OslLoadDevice, NULL); + + /* Check if the user wants to see the advanced menu */ + if (!OslpAdvancedOptionsRequested()) + { + /* The last boot failed more than the maximum */ + if (!(LastBootGood) && + (OslBootAttemptCount >= OslBootAttemptMaximum)) + { + /* Return failure due to boot -- launch recovery */ + *ReturnFlags |= 8; + + /* Update the attempt count and status variables */ + OslBootAttemptCount = OslBootAttemptMaximum - 1; + OslCurrentBootCheckpoint = LastBootCheckpoint; + OslCurrentBootSucceeded = FALSE; + OslCurrentBootShutdown = LastBootShutdown; + + /* Crash with code 15 and abort boot */ + OslFatalErrorEx(15, 0, 0, 0); + Status = STATUS_UNSUCCESSFUL; + EfiPrintf(L"Fail here: %d\r\n", __LINE__); + goto Quickie; + } + + /* We never made it far enough, more than the maximum */ + if (!(LastBootCheckpoint) && + (OslBootAttemptCount >= OslBootAttemptMaximum)) + { + /* Return crash/dirty shutdown during boot attempt */ + *ReturnFlags |= 0x10; + + /* Update the attempt count and status variables */ + OslBootAttemptCount = OslBootAttemptMaximum - 1; + OslCurrentBootSucceeded = LastBootGood; + OslCurrentBootShutdown = LastBootShutdown; + OslCurrentBootCheckpoint = FALSE; + + /* Crash with code 16 and abort boot */ + OslFatalErrorEx(16, 0, 0, 0); + Status = STATUS_UNSUCCESSFUL; + EfiPrintf(L"Fail here: %d\r\n", __LINE__); + goto Quickie; + } + + /* We failed to shutdown cleanly, and haven't booted yet */ + if (!(LastBootShutdown) && !(OslBootAttemptCount)) + { + /* Return crash/dirty shutdown */ + *ReturnFlags |= 0x10; + + /* There's no boot attempt, so only update shutdown variables */ + OslCurrentBootSucceeded = LastBootGood; + OslCurrentBootShutdown = TRUE; + OslCurrentBootCheckpoint = LastBootCheckpoint; + + /* Crash with code 16 and abort boot */ + OslFatalErrorEx(16, 0, 0, 0); + Status = STATUS_UNSUCCESSFUL; + EfiPrintf(L"Fail here: %d\r\n", __LINE__); + goto Quickie; + } + } + + /* Officially increment the number of boot attempts */ + OslBootAttemptCount++; + + /* No success yet, write to boot status file */ + OslCurrentBootCheckpoint = FALSE; + OslCurrentBootSucceeded = FALSE; + OslCurrentBootShutdown = FALSE; + OslSetBootStatusData(FALSE, + FALSE, + FALSE, + OslBootCountUpdateIncrement, + OslBootAttemptCount); + + /* Open the OS Loader Device for Read/Write access */ + Status = BlpDeviceOpen(OslLoadDevice, + BL_DEVICE_READ_ACCESS | BL_DEVICE_WRITE_ACCESS, + 0, + &OsDeviceHandle); + if (!NT_SUCCESS(Status)) + { + EfiPrintf(L"Fail here: %d\r\n", __LINE__); + goto Quickie; + } + + /* That's all for now, folks */ Status = STATUS_NOT_IMPLEMENTED; + DBG_UNREFERENCED_LOCAL_VARIABLE(PowerBuffer); /* Printf perf */ EndPerf = BlArchGetPerformanceCounter(); diff --git a/boot/environ/app/rosload/rosload.h b/boot/environ/app/rosload/rosload.h index 5b19b4f1617..c5cad3a4930 100644 --- a/boot/environ/app/rosload/rosload.h +++ b/boot/environ/app/rosload/rosload.h @@ -34,6 +34,12 @@ /* STRUCTURES ****************************************************************/ +typedef struct _OSL_BSD_ITEM_TABLE_ENTRY +{ + ULONG Offset; + ULONG Size; +} OSL_BSD_ITEM_TABLE_ENTRY; + /* FUNCTIONS *****************************************************************/ VOID diff --git a/boot/environ/include/bcd.h b/boot/environ/include/bcd.h index cee8a0c79ea..d0b8641cd3a 100644 --- a/boot/environ/include/bcd.h +++ b/boot/environ/include/bcd.h @@ -150,8 +150,9 @@ typedef enum BcdOSLoaderElementTypes BcdOSLoaderBoolean_UsePlatformClock = 0x260000A2, BcdOSLoaderBoolean_ForceLegacyPlatform = 0x260000A3, BcdOSLoaderInteger_TscSyncPolicy = 0x250000A6, - BcdOSLoaderBoolean_EmsEnabled = 0x260000b0, - BcdOSLoaderInteger_DriverLoadFailurePolicy = 0x250000c1, + BcdOSLoaderBoolean_EmsEnabled = 0x260000B0, + BcdOSLoaderInteger_ForceFailure = 0x250000C0, + BcdOSLoaderInteger_DriverLoadFailurePolicy = 0x250000C1, BcdOSLoaderInteger_BootMenuPolicy = 0x250000C2, BcdOSLoaderBoolean_AdvancedOptionsOneTime = 0x260000C3, BcdOSLoaderBoolean_OptionsEditOneTime = 0x260000C4, /* Undocumented */ @@ -195,7 +196,8 @@ typedef enum BcdBootMgrElementTypes BcdBootMgrBoolean_PersistBootSequence = 0x26000031 } BcdBootMgrElementTypes; -typedef enum _BcdResumeElementTypes { +typedef enum _BcdResumeElementTypes +{ Reserved1 = 0x21000001, Reserved2 = 0x22000002, BcdResumeBoolean_UseCustomSettings = 0x26000003, @@ -204,6 +206,18 @@ typedef enum _BcdResumeElementTypes { BcdResumeInteger_BootMenuPolicy = 0x25000008 } BcdResumeElementTypes; +typedef enum _BCDE_OSLOADER_TYPE_BOOT_STATUS_POLICY +{ + DisplayAllFailures, + IgnoreAllFailures, + IgnoreShutdownFailures, + IgnoreBootFailures, + IgnoreCheckpointFailures, + DisplayShutdownFailures, + DisplayBootFailures, + DisplayCheckpointFailures +} BCDE_OSLOADER_TYPE_BOOT_STATUS_POLICY; + /* Undocumented */ typedef enum BcdStartupElementTypes { diff --git a/boot/environ/include/bl.h b/boot/environ/include/bl.h index 0e31deb8e92..82edfbcb008 100644 --- a/boot/environ/include/bl.h +++ b/boot/environ/include/bl.h @@ -923,7 +923,7 @@ typedef struct _BL_HARDDISK_DEVICE typedef struct _BL_LOCAL_DEVICE { - ULONG Type; + BL_LOCAL_DEVICE_TYPE Type; union { struct @@ -933,6 +933,8 @@ typedef struct _BL_LOCAL_DEVICE BL_HARDDISK_DEVICE HardDisk; + BL_HARDDISK_DEVICE VirtualHardDisk; + struct { PHYSICAL_ADDRESS ImageBase; @@ -2008,7 +2010,8 @@ BlCopyBootOptions ( NTSTATUS BlAppendBootOptionBoolean ( _In_ PBL_LOADED_APPLICATION_ENTRY AppEntry, - _In_ ULONG OptionId + _In_ ULONG OptionId, + _In_ BOOLEAN Value ); NTSTATUS @@ -2021,6 +2024,7 @@ BlAppendBootOptionInteger ( NTSTATUS BlAppendBootOptionString ( _In_ PBL_LOADED_APPLICATION_ENTRY AppEntry, + _In_ ULONG OptionId, _In_ PWCHAR OptionString ); @@ -2430,6 +2434,12 @@ BlDeviceClose ( _In_ ULONG DeviceId ); +BOOLEAN +BlDeviceIsVirtualPartitionDevice ( + _In_ PBL_DEVICE_DESCRIPTOR InputDevice, + _Outptr_ PBL_DEVICE_DESCRIPTOR* VirtualDevice + ); + NTSTATUS BlpDeviceOpen ( _In_ PBL_DEVICE_DESCRIPTOR Device, diff --git a/boot/environ/lib/io/device.c b/boot/environ/lib/io/device.c index 76dbed06746..b4fd38e1781 100644 --- a/boot/environ/lib/io/device.c +++ b/boot/environ/lib/io/device.c @@ -608,6 +608,39 @@ BlockIoGetInformation ( return STATUS_SUCCESS; } +BOOLEAN +BlDeviceIsVirtualPartitionDevice ( + _In_ PBL_DEVICE_DESCRIPTOR InputDevice, + _Outptr_ PBL_DEVICE_DESCRIPTOR* VirtualDevice + ) +{ + BOOLEAN IsVirtual; + PBL_LOCAL_DEVICE ParentDisk; + + /* Assume it isn't */ + IsVirtual = FALSE; + + /* Check if this is a partition device */ + if ((InputDevice->DeviceType == LegacyPartitionDevice) || + (InputDevice->DeviceType == PartitionDevice)) + { + /* Check if the parent disk is a VHD */ + ParentDisk = &InputDevice->Partition.Disk; + if (ParentDisk->Type == VirtualDiskDevice) + { + /* This is a virtual partition device -- does the caller want it? */ + IsVirtual = TRUE; + if (VirtualDevice) + { + *VirtualDevice = (PBL_DEVICE_DESCRIPTOR)(&ParentDisk->VirtualHardDisk + 1); + } + } + } + + /* Return */ + return IsVirtual; +} + NTSTATUS BlDeviceSetInformation ( _In_ ULONG DeviceId, diff --git a/boot/environ/lib/misc/bcdopt.c b/boot/environ/lib/misc/bcdopt.c index 0b4f82e4677..1b1600182ce 100644 --- a/boot/environ/lib/misc/bcdopt.c +++ b/boot/environ/lib/misc/bcdopt.c @@ -624,7 +624,8 @@ BlCopyBootOptions ( NTSTATUS BlAppendBootOptionBoolean ( _In_ PBL_LOADED_APPLICATION_ENTRY AppEntry, - _In_ ULONG OptionId + _In_ ULONG OptionId, + _In_ BOOLEAN Value ) { NTSTATUS Status; @@ -642,7 +643,7 @@ BlAppendBootOptionBoolean ( Option->DataSize = sizeof(USHORT); Option->Type = OptionId; Option->DataOffset = sizeof(*Option); - *(PBOOLEAN)(Option + 1) = TRUE; + *(PBOOLEAN)(Option + 1) = Value; /* Append it */ Status = BlAppendBootOptions(AppEntry, Option); @@ -687,6 +688,7 @@ BlAppendBootOptionInteger ( NTSTATUS BlAppendBootOptionString ( _In_ PBL_LOADED_APPLICATION_ENTRY AppEntry, + _In_ ULONG OptionId, _In_ PWCHAR OptionString ) { @@ -719,7 +721,7 @@ BlAppendBootOptionString ( /* Initialize it and copy the string value */ RtlZeroMemory(Option, sizeof(*Option) + StringSize); Option->DataSize = StringSize; - Option->Type = BcdLibraryString_ApplicationPath; + Option->Type = OptionId; Option->DataOffset = sizeof(*Option); wcsncpy((PWCHAR)Option + 1, OptionString, StringSize / sizeof(WCHAR)); -- 2.17.1