[BOOTMGFW]: Implement additional startup logic
authorAlex Ionescu <aionescu@gmail.com>
Fri, 8 Jan 2016 06:03:55 +0000 (06:03 +0000)
committerAlex Ionescu <aionescu@gmail.com>
Fri, 8 Jan 2016 06:03:55 +0000 (06:03 +0000)
[BOOTLIB]: Implement initial SecureBoot support.
[BOOTLIB]: Implement UEFI Variable query support.

svn path=/trunk/; revision=70543

reactos/boot/environ/app/bootmgr/bootmgr.c
reactos/boot/environ/include/bl.h
reactos/boot/environ/include/efi/GlobalVariable.h [new file with mode: 0644]
reactos/boot/environ/lib/firmware/efi/firmware.c
reactos/boot/environ/lib/misc/util.c

index 87625df..12c8bd1 100644 (file)
@@ -1041,6 +1041,16 @@ BmpBgDisplayClearScreen (
     return STATUS_NOT_IMPLEMENTED;
 }
 
+NTSTATUS
+BlXmiWrite (
+    _In_ PWCHAR XmlTag
+    )
+{
+    /* Sigh */
+    EfiPrintf(L"XML: %s\r\n", XmlTag);
+    return STATUS_NOT_IMPLEMENTED;
+}
+
 NTSTATUS
 BlXmiInitialize (
     _In_ PWCHAR Stylesheet
@@ -1082,17 +1092,77 @@ BmFwVerifySelfIntegrity (
     VOID
     )
 {
-    EfiPrintf(L"Device Type %d Local Type %d\r\n", BlpBootDevice->DeviceType, BlpBootDevice->Local.Type);
+    /* Check if we're booted by UEFI off the DVD directlry */
     if ((BlpBootDevice->DeviceType == LocalDevice) &&
         (BlpBootDevice->Local.Type == CdRomDevice) &&
         (BlpApplicationFlags & BL_APPLICATION_FLAG_CONVERTED_FROM_EFI))
     {
+        /* Windows actually bypasses integrity checks in this case. Works for us */
         return STATUS_SUCCESS;
     }
 
+    /* Our binaries aren't signed, so always return failure */
     return 0xC0000428;
 }
 
+NTSTATUS
+BmFwRegisterRevocationList (
+    VOID
+    )
+{
+    NTSTATUS Status;
+    BOOLEAN SecureBootEnabled;
+
+    /* Is SecureBoot enabled? */
+    Status = BlSecureBootIsEnabled(&SecureBootEnabled);
+    if ((NT_SUCCESS(Status)) && (SecureBootEnabled))
+    {
+        EfiPrintf(L"SB not implemented revok\r\n");
+        return STATUS_NOT_IMPLEMENTED;
+    }
+    else
+    {
+        /* Nothing to do without SecureBoot */
+        Status = STATUS_SUCCESS;
+    }
+
+    /* Return revocation result back to caller */
+    return Status;
+}
+
+NTSTATUS
+BmResumeFromHibernate (
+    _Out_ PHANDLE BcdResumeHandle
+    )
+{
+    NTSTATUS Status;
+    BOOLEAN AttemptResume;
+
+    /* Should we attempt to resume from hibernation? */
+    Status = BlGetBootOptionBoolean(BlpApplicationEntry.BcdData,
+                                    BcdBootMgrBoolean_AttemptResume,
+                                    &AttemptResume);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Nope. Is automatic restart on crash enabled? */
+        AttemptResume = FALSE;
+        Status = BlGetBootOptionBoolean(BlpApplicationEntry.BcdData,
+                                        BcdOSLoaderBoolean_DisableCrashAutoReboot,
+                                        &AttemptResume);
+        AttemptResume = (NT_SUCCESS(Status) && (AttemptResume));
+    }
+
+    /* Don't do anything if there's no need to resume anything */
+    if (!AttemptResume)
+    {
+        return STATUS_SUCCESS;
+    }
+
+    /* Not yet implemented */
+    EfiPrintf(L"Resume not supported\r\n");
+    return STATUS_NOT_IMPLEMENTED;
+}
+
 /*++
  * @name BmMain
  *
@@ -1116,7 +1186,7 @@ BmMain (
     PBL_RETURN_ARGUMENTS ReturnArguments;
     BOOLEAN RebootOnError;
     PGUID AppIdentifier;
-    HANDLE BcdHandle;
+    HANDLE BcdHandle, ResumeBcdHandle;
     PBL_BCD_OPTION EarlyOptions;
     PWCHAR Stylesheet;
     BOOLEAN XmlLoaded, DisableIntegrity, TestSigning;
@@ -1267,14 +1337,36 @@ BmMain (
         }
     }
 
-//        BlXmiWrite(L"<bootmgr/>");
+    /* Write out the first XML tag */
+    BlXmiWrite(L"<bootmgr/>");
 
-    //BlSecureBootCheckForFactoryReset();
+    /* Check for factory resset */
+    BlSecureBootCheckForFactoryReset();
+
+    /* Load the revocation list */
+    Status = BmFwRegisterRevocationList();
+    if (!NT_SUCCESS(Status))
+    {
+        goto Failure;
+    }
+
+    /* Register our custom progress routine */
+    BlUtlRegisterProgressRoutine();
+
+    /* Display state is not currently cached */
+    BmDisplayStateCached = FALSE;
+
+    /* Check if w need to resume from hibernate */
+    Status = BmResumeFromHibernate(&ResumeBcdHandle);
+    if (!NT_SUCCESS(Status))
+    {
+        goto Failure;
+    }
 
 
     /* do more stuff!! */
-    EfiPrintf(BlResourceFindMessage(BM_MSG_TEST));
-    EfiPrintf(Stylesheet);
+    //EfiPrintf(BlResourceFindMessage(BM_MSG_TEST));
+    //EfiPrintf(Stylesheet);
     EfiStall(10000000);
 
 Failure:
index c78683e..1b24b40 100644 (file)
@@ -39,6 +39,7 @@
 #include <UgaDraw.h>
 #include <BlockIo.h>
 #include <Acpi.h>
+#include <GlobalVariable.h>
 
 /* Registry Headers */
 #define __FREELDR_H
@@ -1528,6 +1529,11 @@ BlUtlInitialize (
     VOID
     );
 
+NTSTATUS
+BlUtlRegisterProgressRoutine (
+    VOID
+    );
+
 VOID
 BlFwReboot (
     VOID
@@ -1538,6 +1544,21 @@ BlGetApplicationIdentifier (
     VOID
     );
 
+NTSTATUS
+BlpSecureBootEFIIsEnabled (
+    VOID
+    );
+
+NTSTATUS
+BlSecureBootIsEnabled (
+    _Out_ PBOOLEAN SecureBootEnabled
+    );
+
+NTSTATUS
+BlSecureBootCheckForFactoryReset (
+    VOID
+    );
+
 NTSTATUS
 BlGetApplicationBaseAndSize (
     _Out_ PVOID* ImageBase,
@@ -2302,6 +2323,7 @@ extern EFI_GUID EfiBlockIoProtocol;
 extern EFI_GUID EfiSimpleTextInputExProtocol;
 extern EFI_GUID EfiRootAcpiTableGuid;
 extern EFI_GUID EfiRootAcpiTable10Guid;
+extern EFI_GUID EfiGlobalVariable;
 extern ULONG ConsoleGraphicalResolutionListFlags;
 extern BL_DISPLAY_MODE ConsoleGraphicalResolutionList[];
 extern BL_DISPLAY_MODE ConsoleTextResolutionList[];
diff --git a/reactos/boot/environ/include/efi/GlobalVariable.h b/reactos/boot/environ/include/efi/GlobalVariable.h
new file mode 100644 (file)
index 0000000..f9737b3
--- /dev/null
@@ -0,0 +1,192 @@
+/** @file
+  GUID for EFI (NVRAM) Variables.
+
+  Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials                          
+  are licensed and made available under the terms and conditions of the BSD License         
+  which accompanies this distribution.  The full text of the license may be found at        
+  http://opensource.org/licenses/bsd-license.php                                            
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
+
+  @par Revision Reference:
+  GUID defined in UEFI 2.1
+**/
+
+#ifndef __GLOBAL_VARIABLE_GUID_H__
+#define __GLOBAL_VARIABLE_GUID_H__
+
+#define EFI_GLOBAL_VARIABLE \
+  { \
+    0x8BE4DF61, 0x93CA, 0x11d2, {0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C } \
+  }
+
+extern EFI_GUID gEfiGlobalVariableGuid;
+
+//
+// Follow UEFI 2.4 spec:
+// To prevent name collisions with possible future globally defined variables,
+// other internal firmware data variables that are not defined here must be
+// saved with a unique VendorGuid other than EFI_GLOBAL_VARIABLE or
+// any other GUID defined by the UEFI Specification. Implementations must
+// only permit the creation of variables with a UEFI Specification-defined
+// VendorGuid when these variables are documented in the UEFI Specification.
+//
+// Note: except the globally defined variables defined below, the spec also defines
+// L"Boot####"      - A boot load option.
+// L"Driver####"    - A driver load option.
+// L"SysPrep####"   - A System Prep application load option.
+// L"Key####"       - Describes hot key relationship with a Boot#### load option.
+// The attribute for them is NV+BS+RT, #### is a printed hex value, and no 0x or h
+// is included in the hex value. They can not be expressed as a #define like other globally
+// defined variables, it is because we can not list the Boot0000, Boot0001, etc one by one.
+//
+
+///
+/// The language codes that the firmware supports. This value is deprecated.
+/// Its attribute is BS+RT.
+///
+#define EFI_LANG_CODES_VARIABLE_NAME                L"LangCodes"
+///
+/// The language code that the system is configured for. This value is deprecated.
+/// Its attribute is NV+BS+RT.
+///
+#define EFI_LANG_VARIABLE_NAME                      L"Lang"
+///
+/// The firmware's boot managers timeout, in seconds, before initiating the default boot selection.
+/// Its attribute is NV+BS+RT.
+///
+#define EFI_TIME_OUT_VARIABLE_NAME                  L"Timeout"
+///
+/// The language codes that the firmware supports.
+/// Its attribute is BS+RT.
+///
+#define EFI_PLATFORM_LANG_CODES_VARIABLE_NAME       L"PlatformLangCodes"
+///
+/// The language code that the system is configured for.
+/// Its attribute is NV+BS+RT.
+///
+#define EFI_PLATFORM_LANG_VARIABLE_NAME             L"PlatformLang"
+///
+/// The device path of the default input/output/error output console.
+/// Its attribute is NV+BS+RT.
+///
+#define EFI_CON_IN_VARIABLE_NAME                    L"ConIn"
+#define EFI_CON_OUT_VARIABLE_NAME                   L"ConOut"
+#define EFI_ERR_OUT_VARIABLE_NAME                   L"ErrOut"
+///
+/// The device path of all possible input/output/error output devices.
+/// Its attribute is BS+RT.
+///
+#define EFI_CON_IN_DEV_VARIABLE_NAME                L"ConInDev"
+#define EFI_CON_OUT_DEV_VARIABLE_NAME               L"ConOutDev"
+#define EFI_ERR_OUT_DEV_VARIABLE_NAME               L"ErrOutDev"
+///
+/// The ordered boot option load list.
+/// Its attribute is NV+BS+RT.
+///
+#define EFI_BOOT_ORDER_VARIABLE_NAME                L"BootOrder"
+///
+/// The boot option for the next boot only.
+/// Its attribute is NV+BS+RT.
+///
+#define EFI_BOOT_NEXT_VARIABLE_NAME                 L"BootNext"
+///
+/// The boot option that was selected for the current boot.
+/// Its attribute is BS+RT.
+///
+#define EFI_BOOT_CURRENT_VARIABLE_NAME              L"BootCurrent"
+///
+/// The types of boot options supported by the boot manager. Should be treated as read-only.
+/// Its attribute is BS+RT.
+///
+#define EFI_BOOT_OPTION_SUPPORT_VARIABLE_NAME       L"BootOptionSupport"
+///
+/// The ordered driver load option list.
+/// Its attribute is NV+BS+RT.
+///
+#define EFI_DRIVER_ORDER_VARIABLE_NAME              L"DriverOrder"
+///
+/// The ordered System Prep Application load option list.
+/// Its attribute is NV+BS+RT.
+///
+#define EFI_SYS_PREP_ORDER_VARIABLE_NAME            L"SysPrepOrder"
+///
+/// Identifies the level of hardware error record persistence
+/// support implemented by the platform. This variable is
+/// only modified by firmware and is read-only to the OS.
+/// Its attribute is NV+BS+RT.
+///
+#define EFI_HW_ERR_REC_SUPPORT_VARIABLE_NAME        L"HwErrRecSupport"
+///
+/// Whether the system is operating in setup mode (1) or not (0).
+/// All other values are reserved. Should be treated as read-only.
+/// Its attribute is BS+RT.
+///
+#define EFI_SETUP_MODE_NAME                         L"SetupMode"
+///
+/// The Key Exchange Key Signature Database.
+/// Its attribute is NV+BS+RT+AT.
+///
+#define EFI_KEY_EXCHANGE_KEY_NAME                   L"KEK"
+///
+/// The public Platform Key.
+/// Its attribute is NV+BS+RT+AT.
+///
+#define EFI_PLATFORM_KEY_NAME                       L"PK"
+///
+/// Array of GUIDs representing the type of signatures supported
+/// by the platform firmware. Should be treated as read-only.
+/// Its attribute is BS+RT.
+///
+#define EFI_SIGNATURE_SUPPORT_NAME                  L"SignatureSupport"
+///
+/// Whether the platform firmware is operating in Secure boot mode (1) or not (0).
+/// All other values are reserved. Should be treated as read-only.
+/// Its attribute is BS+RT.
+///
+#define EFI_SECURE_BOOT_MODE_NAME                   L"SecureBoot"
+///
+/// The OEM's default Key Exchange Key Signature Database. Should be treated as read-only.
+/// Its attribute is BS+RT.
+///
+#define EFI_KEK_DEFAULT_VARIABLE_NAME               L"KEKDefault"
+///
+/// The OEM's default public Platform Key. Should be treated as read-only.
+/// Its attribute is BS+RT.
+///
+#define EFI_PK_DEFAULT_VARIABLE_NAME                L"PKDefault"
+///
+/// The OEM's default secure boot signature store. Should be treated as read-only.
+/// Its attribute is BS+RT.
+///
+#define EFI_DB_DEFAULT_VARIABLE_NAME                L"dbDefault"
+///
+/// The OEM's default secure boot blacklist signature store. Should be treated as read-only.
+/// Its attribute is BS+RT.
+///
+#define EFI_DBX_DEFAULT_VARIABLE_NAME               L"dbxDefault"
+///
+/// The OEM's default secure boot timestamp signature store. Should be treated as read-only.
+/// Its attribute is BS+RT.
+///
+#define EFI_DBT_DEFAULT_VARIABLE_NAME               L"dbtDefault"
+///
+/// Allows the firmware to indicate supported features and actions to the OS.
+/// Its attribute is BS+RT.
+///
+#define EFI_OS_INDICATIONS_SUPPORT_VARIABLE_NAME    L"OsIndicationsSupported"
+///
+/// Allows the OS to request the firmware to enable certain features and to take certain actions.
+/// Its attribute is NV+BS+RT.
+///
+#define EFI_OS_INDICATIONS_VARIABLE_NAME            L"OsIndications"
+///
+/// Whether the system is configured to use only vendor provided
+/// keys or not. Should be treated as read-only.
+/// Its attribute is BS+RT.
+///
+#define EFI_VENDOR_KEYS_VARIABLE_NAME               L"VendorKeys"
+
+#endif
index 97c592f..3f520f8 100644 (file)
@@ -33,9 +33,14 @@ EFI_GUID EfiSimpleTextInputExProtocol = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID;
 EFI_GUID EfiBlockIoProtocol = EFI_BLOCK_IO_PROTOCOL_GUID;
 EFI_GUID EfiRootAcpiTableGuid = EFI_ACPI_20_TABLE_GUID;
 EFI_GUID EfiRootAcpiTable10Guid = EFI_ACPI_TABLE_GUID;
+EFI_GUID EfiGlobalVariable = EFI_GLOBAL_VARIABLE;
+EFI_GUID BlpEfiSecureBootPrivateNamespace = { 0x77FA9ABD , 0x0359, 0x4D32, { 0xBD, 0x60, 0x28, 0xF4, 0xE7, 0x8F, 0x78, 0x4B } };
 
 WCHAR BlScratchBuffer[8192];
 
+BOOLEAN BlpFirmwareChecked;
+BOOLEAN BlpFirmwareEnabled;
+
 /* FUNCTIONS *****************************************************************/
 
 EFI_DEVICE_PATH *
@@ -268,6 +273,159 @@ EfiCloseProtocol (
     return Status;
 }
 
+NTSTATUS
+EfiGetVariable (
+    _In_ PWCHAR VariableName,
+    _In_ EFI_GUID* VendorGuid,
+    _Out_opt_ PULONG Attributes,
+    _Inout_ PULONG DataSize,
+    _Out_ PVOID Data
+    )
+{
+    EFI_STATUS EfiStatus;
+    NTSTATUS Status;
+    BL_ARCH_MODE OldMode;
+    ULONG LocalAttributes;
+
+    /* Are we in protected mode? */
+    OldMode = CurrentExecutionContext->Mode;
+    if (OldMode != BlRealMode)
+    {
+        /* FIXME: Not yet implemented */
+        return STATUS_NOT_IMPLEMENTED;
+    }
+
+    /* Call the runtime API */
+    EfiStatus = EfiRT->GetVariable(VariableName,
+                                   VendorGuid,
+                                   (UINT32*)&LocalAttributes,
+                                   (UINTN*)DataSize,
+                                   Data);
+
+    /* Switch back to protected mode if we came from there */
+    if (OldMode != BlRealMode)
+    {
+        BlpArchSwitchContext(OldMode);
+    }
+
+    /* Return attributes back to the caller if asked to */
+    if (Attributes)
+    {
+        *Attributes = LocalAttributes;
+    }
+
+    /* Convert the errot to an NTSTATUS and return it */
+    Status = EfiGetNtStatusCode(EfiStatus);
+    return Status;
+}
+
+NTSTATUS
+BlpSecureBootEFIIsEnabled (
+    VOID
+    )
+{
+    NTSTATUS Status;
+    BOOLEAN SetupMode, SecureBoot;
+    ULONG DataSize;
+
+    /* Assume setup mode enabled, and no secure boot */
+    SecureBoot = FALSE;
+    SetupMode = TRUE;
+
+    /* Get the SetupMode variable */
+    DataSize = sizeof(SetupMode);
+    Status = EfiGetVariable(L"SetupMode",
+                            &EfiGlobalVariable,
+                            NULL,
+                            &DataSize,
+                            &SetupMode);
+    if (NT_SUCCESS(Status))
+    {
+        /* If it worked, get the SecureBoot variable */
+        DataSize = sizeof(SecureBoot);
+        Status = EfiGetVariable(L"SecureBoot",
+                                &EfiGlobalVariable,
+                                NULL,
+                                &DataSize,
+                                &SecureBoot);
+        if (NT_SUCCESS(Status))
+        {
+            /* In setup mode or without secureboot turned on, return failure */
+            if ((SecureBoot != TRUE) || (SetupMode))
+            {
+                Status = STATUS_INVALID_SIGNATURE;
+            }
+
+            // BlpSbdiStateFlags |= 8u;
+        }
+    }
+
+    /* Return secureboot status */
+    return Status;
+}
+
+NTSTATUS
+BlSecureBootIsEnabled (
+    _Out_ PBOOLEAN SecureBootEnabled
+    )
+{
+    NTSTATUS Status;
+
+    /* Have we checked before ? */
+    if (!BlpFirmwareChecked)
+    {
+        /* First time checking */
+        Status = BlpSecureBootEFIIsEnabled();
+        if NT_SUCCESS(Status)
+        {
+            /* Yep, it's on */
+            BlpFirmwareEnabled = TRUE;
+        }
+
+        /* Don't check again */
+        BlpFirmwareChecked = TRUE;
+    }
+
+    /* Return the firmware result */
+    *SecureBootEnabled = BlpFirmwareEnabled;
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+BlSecureBootCheckForFactoryReset (
+    VOID
+    )
+{
+    BOOLEAN SecureBootEnabled;
+    NTSTATUS Status;
+    ULONG DataSize;
+
+    /* Initialize locals */
+    DataSize = 0;
+    SecureBootEnabled = FALSE;
+
+    /* Check if secureboot is enabled */
+    Status = BlSecureBootIsEnabled(&SecureBootEnabled);
+    if (!(NT_SUCCESS(Status)) || !(SecureBootEnabled))
+    {
+        /* It's not. Check if there's a revocation list */
+        Status = EfiGetVariable(L"RevocationList",
+                                &BlpEfiSecureBootPrivateNamespace,
+                                NULL,
+                                &DataSize,
+                                NULL);
+        if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_TOO_SMALL))
+        {
+            /* We don't support this yet */
+            EfiPrintf(L"Not yet supported\r\n");
+            Status = STATUS_NOT_IMPLEMENTED;
+        }
+    }
+
+    /* Return back to the caller */
+    return Status;
+}
+
 NTSTATUS
 EfiConInReset (
     VOID
index dbeb79a..bd37beb 100644 (file)
@@ -28,6 +28,8 @@ ULONG UtlNextUpdatePercentage;
 BOOLEAN UtlProgressNeedsInfoUpdate;
 PVOID UtlProgressInfo;
 
+
+
 /* FUNCTIONS *****************************************************************/
 
 NTSTATUS
@@ -176,6 +178,7 @@ BlUtlGetAcpiTable (
     return STATUS_NOT_FOUND;
 }
 
+
 VOID
 BlUtlUpdateProgress (
     _In_ ULONG Percentage,
@@ -216,6 +219,58 @@ BlUtlInitialize (
     return STATUS_SUCCESS;
 }
 
+VOID
+BmUpdateProgressInfo (
+    _In_ PVOID Uknown,
+    _In_ PWCHAR ProgressInfo
+    )
+{
+    EfiPrintf(L"Progress Info: %s\r\n", ProgressInfo);
+}
+
+VOID
+BmUpdateProgress (
+    _In_ PVOID Unknown,
+    _In_ ULONG Percent,
+    _Out_ PBOOLEAN Completed
+    )
+{
+    EfiPrintf(L"Progress: %d\r\n", Percent);
+    if (Completed)
+    {
+        *Completed = TRUE;
+    }
+}
+
+NTSTATUS
+BlUtlRegisterProgressRoutine (
+    VOID
+    )
+{
+    /* One shouldn't already exist */
+    if (UtlProgressRoutine)
+    {
+        return STATUS_UNSUCCESSFUL;
+    }
+
+    /* Set the routine, and no context */
+    UtlProgressRoutine = BmUpdateProgress;
+    UtlProgressContext = NULL;
+
+    /* Progress increases by one */
+    UtlProgressGranularity = 1;
+
+    /* Set progress to zero for now */
+    UtlCurrentPercentComplete = 0;
+    UtlNextUpdatePercentage = 0;
+
+    /* Set the info routine if there is one */
+    UtlProgressInfoRoutine = BmUpdateProgressInfo;
+
+    /* All good */
+    return STATUS_SUCCESS;
+}
+
 PVOID
 BlTblFindEntry (
     _In_ PVOID *Table,