[ROSLOAD]: Continue work on target preparation OslPrepareTarget 2/104.
authorAlex Ionescu <aionescu@gmail.com>
Mon, 5 Feb 2018 00:01:38 +0000 (16:01 -0800)
committerAlex Ionescu <aionescu@gmail.com>
Mon, 5 Feb 2018 00:01:38 +0000 (16:01 -0800)
[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
boot/environ/app/rosload/rosload.c
boot/environ/app/rosload/rosload.h
boot/environ/include/bcd.h
boot/environ/include/bl.h
boot/environ/lib/io/device.c
boot/environ/lib/misc/bcdopt.c

index b63e63b..85d501b 100644 (file)
@@ -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:
index 9eda2d3..65fa445 100644 (file)
@@ -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();
index 5b19b4f..c5cad3a 100644 (file)
 
 /* STRUCTURES ****************************************************************/
 
+typedef struct _OSL_BSD_ITEM_TABLE_ENTRY
+{
+    ULONG Offset;
+    ULONG Size;
+} OSL_BSD_ITEM_TABLE_ENTRY;
+
 /* FUNCTIONS *****************************************************************/
 
 VOID
index cee8a0c..d0b8641 100644 (file)
@@ -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
 {
index 0e31deb..82edfbc 100644 (file)
@@ -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,
index 76dbed0..b4fd38e 100644 (file)
@@ -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,
index 0b4f82e..1b16001 100644 (file)
@@ -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));