Newer
Older
AMI-Aptio-BIOS-Reversed / SecureBootDXE / SecureBootDXE.c
@Ajax Dong Ajax Dong 2 days ago 18 KB Init
/**
 * SecureBootDXE.c - UEFI Secure Boot DXE Driver
 *
 * Module:     SecureBootDXE.efi
 * Image Size: 0x1ce0
 * SHA256:     ebec12a0eba5a2ff026b85a0f7dddf2a03eb167c35bc015f873d9b2962c715f0
 * Source:     Lenovo HR650X BIOS
 *
 * This DXE driver manages Secure Boot policy on Lenovo HR650X platforms.
 * It handles initialization of UEFI standard table pointers, HOB list
 * discovery, reading the proprietary "SecureBootSetup" variable to determine
 * Secure Boot enable/disable state, provisioning default Secure Boot
 * databases (db, dbx, dbt, dbr, KEK, PK) from firmware volumes into UEFI
 * Runtime Variables, and setting up the SetupMode variable based on
 * provisioning state.
 *
 * Architecture: x86-64, UEFI DXE_DRIVER
 * Build:     VS2015, X64, DEBUG
 * Source:    e:\hs\AmiModulePkg\GenericSio\SioDxeInit.c (build path)
 *            e:\hs\Build\HR6N0XMLK\DEBUG_VS2015\X64\...\AutoGen.c
 */

#include <Uefi.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/DxeServicesLib.h>
#include <Library/UefiMemoryAllocationLib.h>
#include <Library/DxeHobLib.h>
#include <Guid/GlobalVariable.h>
#include <Protocol/FirmwareVolume2.h>
#include <Protocol/Rng.h>
#include "SecureBootDXE.h"

/******************** Module-Level Static Data ********************/

STATIC EFI_SYSTEM_TABLE        *gST;                    /* 0x1A78 */
STATIC EFI_BOOT_SERVICES       *gBS;                    /* 0x1A80 */
STATIC EFI_HANDLE               gImageHandle;           /* 0x1A88 */
STATIC EFI_RUNTIME_SERVICES    *gRT;                    /* 0x1A90 */
STATIC EFI_RUNTIME_SERVICES    *mRuntimeServices;       /* 0x1AA8 */
STATIC EFI_BOOT_SERVICES       *mBootServices;          /* 0x1AB0 */
STATIC EFI_SYSTEM_TABLE        *mSystemTable;           /* 0x1AB8 */
STATIC UINT8                    mDebugLevel;            /* 0x1AC0 */
STATIC VOID                    *gHobList;               /* 0x1AA0 */
STATIC EFI_STATUS               mDebugPrintProtocol;    /* 0x1A98 */

/******************** GUID Constants ********************/

/* 5B1B31A1-9562-11D2-8E3F-00A0C969723B */
STATIC CONST EFI_GUID  mDxeServicesProtocolGuid =
  { 0x5B1B31A1, 0x9562, 0x11D2, { 0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B } };

/* 8BE4DF61-93CA-11D2-AA0D-00E098032B8C (gEfiGlobalVariableGuid) */
STATIC CONST EFI_GUID  mGlobalVariableGuid =
  { 0x8BE4DF61, 0x93CA, 0x11D2, { 0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C } };

/* 7B59104A-C00D-4158-87FF-F04D6396A915 (proprietary SecureBootSetup) */
STATIC CONST EFI_GUID  mSecureBootSetupVarGuid =
  { 0x7B59104A, 0xC00D, 0x4158, { 0x87, 0xFF, 0xF0, 0x4D, 0x63, 0x96, 0xA9, 0x15 } };

/* 220E73B6-6BDB-4413-8405-B974B108619A (gEfiFirmwareVolume2ProtocolGuid) */
STATIC CONST EFI_GUID  mFirmwareVolume2ProtocolGuid =
  { 0x220E73B6, 0x6BDB, 0x4413, { 0x84, 0x05, 0xB9, 0x74, 0xB1, 0x08, 0x61, 0x9A } };

/* D719B2CB-3D3A-4596-A3BC-DAD00E67656F (proprietary storage GUID) */
STATIC CONST EFI_GUID  mVarStorageGuid =
  { 0xD719B2CB, 0x3D3A, 0x4596, { 0xA3, 0xBC, 0xDA, 0xD0, 0x0E, 0x67, 0x65, 0x6F } };

/* 7739F24C-93D7-11D4-9A3A-0090273FC14D (gEfiHobListGuid) */
STATIC CONST EFI_GUID  mHobListGuid =
  { 0x7739F24C, 0x93D7, 0x11D4, { 0x9A, 0x3A, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } };

/* RNG algorithms */
STATIC CONST EFI_GUID  mRngAlgoHash256 =
  { 0x4AAFD29D, 0x68DF, 0x49EE, { 0x8A, 0xA9, 0x34, 0x7D, 0x37, 0x56, 0x65, 0xA7 } };

STATIC CONST EFI_GUID  mRngAlgoHmac256 =
  { 0x7D34A98A, 0x5637, 0xA765, { 0xBF, 0xFB, 0x46, 0xC2, 0x5C, 0xF7, 0xF7, 0x43 } };

/* Certificate type GUIDs for Secure Boot databases */
STATIC CONST EFI_GUID  mCertSha256Guid =
  { 0x9D7A05E9, 0xF740, 0x44C3, { 0x85, 0x8B, 0x75, 0x58, 0x6A, 0x8F, 0x9C, 0x8E } };

STATIC CONST EFI_GUID  mCertX509Guid =
  { 0xC246FBBF, 0xF75C, 0x43F7, { 0x88, 0xA6, 0xB5, 0xFD, 0x0C, 0xF1, 0xDB, 0x7F } };

STATIC CONST EFI_GUID  mCertRsa2048Sha256Guid =
  { 0x5F7CE43D, 0x565A, 0x4420, { 0xB4, 0xF8, 0x22, 0xEC, 0xA7, 0x24, 0x57, 0x55 } };

STATIC CONST EFI_GUID  mCertRsa2048Sha1Guid =
  { 0xFBF95065, 0x427F, 0x47B3, { 0x80, 0x77, 0xD1, 0x3C, 0x60, 0x71, 0x09, 0x98 } };

STATIC CONST EFI_GUID  mCertSha384Guid =
  { 0xCC0F8A3F, 0x3DEA, 0x4376, { 0x96, 0x79, 0x54, 0x26, 0xBA, 0x0A, 0x90, 0x7E } };

STATIC CONST EFI_GUID  mCertSha224Guid =
  { 0x9FE7DE69, 0x0AEA, 0x470A, { 0xB5, 0x0A, 0x13, 0x98, 0x13, 0x64, 0x91, 0x89 } };

/******************** Variable Name Strings ********************/

STATIC CONST CHAR16 *mDbVarName      = L"dbx";
STATIC CONST CHAR16 *mDbtVarName     = L"dbt";
STATIC CONST CHAR16 *mDbrVarName     = L"dbr";
STATIC CONST CHAR16 *mDbVarName2     = L"db";
STATIC CONST CHAR16 *mKekVarName     = L"KEK";
STATIC CONST CHAR16 *mPkVarName      = L"PK";

STATIC CONST CHAR16 *mDbxDefaultName = L"dbxDefault";
STATIC CONST CHAR16 *mDbtDefaultName = L"dbtDefault";
STATIC CONST CHAR16 *mDbrDefaultName = L"dbrDefault";
STATIC CONST CHAR16 *mDbDefaultName  = L"dbDefault";
STATIC CONST CHAR16 *mKekDefaultName = L"KEKDefault";
STATIC CONST CHAR16 *mPkDefaultName  = L"PKDefault";

/******************** Forward Declarations ********************/

EFI_STATUS EFIAPI
SecureBootEntryPoint (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable);

STATIC EFI_STATUS  SecureBootDriverMain (IN EFI_SYSTEM_TABLE  *SystemTable);
STATIC EFI_STATUS  GetDebugPrintProtocol (VOID);
STATIC VOID        DebugPrint (IN UINTN ErrorLevel, IN CONST CHAR8 *Format, ...);
STATIC VOID        AssertBreakPoint (IN CONST CHAR8 *File, IN UINTN Line, IN CONST CHAR8 *Desc);
STATIC UINT64      ReadUnaligned64 (IN CONST VOID *Buffer);
STATIC UINT64      WriteUnaligned64 (OUT VOID *Buffer, IN UINT64 Value);
STATIC UINTN       GetDebugLevel (VOID);
STATIC VOID       *GetHobList (VOID);
STATIC BOOLEAN     IsGuidMatch (IN CONST EFI_CONFIGURATION_TABLE *Entry);
STATIC VOID       *GetConfigurationTable (IN EFI_SYSTEM_TABLE *SystemTable);
STATIC VOID       *GetFirmwareVolumeProtocol (VOID);
STATIC VOID       *GetSectionFromFv (IN CONST EFI_GUID *NameGuid, OUT VOID **Buffer, OUT UINTN *Size);
STATIC EFI_STATUS  GetSectionFromAnyFv (IN CONST EFI_GUID *NameGuid, OUT VOID **Buffer, OUT UINTN *Size);
STATIC VOID       *AllocatePool (IN UINTN Size);
STATIC VOID        GenerateRandomTime (OUT VOID *Buffer);
STATIC EFI_STATUS  SetSecureBootVariable (IN UINT16 Flags, IN CONST CHAR16 *Name,
                     IN CONST CHAR16 *DefaultName, IN CONST EFI_GUID *Guid,
                     IN VOID *Data, IN UINTN DataSize);
STATIC EFI_STATUS  ProvisionSecureBootDatabases (IN UINT16 Flags, IN UINT32 Fmt, IN UINT32 Auth);

/******************** Utility Functions ********************/

STATIC UINT64
ReadUnaligned64 (IN CONST VOID *Buffer)
{
  ASSERT (Buffer != NULL);
  return *(volatile UINT64 *)Buffer;
}

STATIC UINT64
WriteUnaligned64 (OUT VOID *Buffer, IN UINT64 Value)
{
  ASSERT (Buffer != NULL);
  *(volatile UINT64 *)Buffer = Value;
  return Value;
}

STATIC UINTN
GetDebugLevel (VOID)
{
  UINT8  SavedIdx, Value;
  UINT32 Result;

  SavedIdx = IoRead8 (0x70);
  IoWrite8 (0x70, (SavedIdx & 0x80) | 0x4B);
  Value = IoRead8 (0x71);

  if (Value > 3) {
    if (Value == 0)
      Value = (*(volatile UINT8 *)0xFDAF0490 & 2) | 1;
  }

  if ((Value - 1) > 0xFD)
    return 0;
  return (Value == 1) ? 0x80000004 : 0x8000000C;
}

STATIC EFI_STATUS
GetDebugPrintProtocol (VOID)
{
  if (mDebugPrintProtocol) {
    if (mDebugLevel > 0x10) {
      // ...
    }
  }
  return mDebugPrintProtocol;
}

STATIC VOID
DebugPrint (IN UINTN ErrorLevel, IN CONST CHAR8 *Format, ...)
{
  VA_LIST Va;
  VA_START (Va, Format);
  VA_END (Va);
}

STATIC VOID
AssertBreakPoint (IN CONST CHAR8 *File, IN UINTN Line, IN CONST CHAR8 *Desc)
{
  /* Stub: calls DebugPrint then CpuDeadLoop typically */
}

/******************** HOB List ********************/

STATIC VOID *
GetHobList (VOID)
{
  if (gHobList != NULL)
    return gHobList;

  gHobList = NULL;
  if (gST->NumberOfTableEntries > 0) {
    UINTN Index;
    EFI_CONFIGURATION_TABLE *Entry = gST->ConfigurationTable;
    for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
      if (CompareMem (&Entry[Index].VendorGuid, &mHobListGuid, sizeof (EFI_GUID)) == 0) {
        gHobList = Entry[Index].VendorTable;
        return gHobList;
      }
    }
    DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", EFI_NOT_FOUND));
    ASSERT (!EFI_ERROR (EFI_NOT_FOUND));
  }
  if (gHobList == NULL)
    ASSERT (gHobList != NULL);
  return gHobList;
}

/******************** Configuration Table Lookup ********************/

STATIC BOOLEAN
IsGuidMatch (IN CONST EFI_CONFIGURATION_TABLE *Entry)
{
  return CompareMem (&Entry->VendorGuid, &mHobListGuid, sizeof (EFI_GUID)) == 0;
}

STATIC VOID *
GetConfigurationTable (IN EFI_SYSTEM_TABLE *SystemTable)
{
  UINTN Index;
  for (Index = 0; Index < SystemTable->NumberOfTableEntries; Index++)
    if (IsGuidMatch (&SystemTable->ConfigurationTable[Index]))
      return SystemTable->ConfigurationTable[Index].VendorTable;
  return NULL;
}

/******************** Firmware Volume Protocol ********************/

STATIC VOID *
GetFirmwareVolumeProtocol (VOID)
{
  EFI_STATUS Status;
  VOID *Interface = NULL;

  if (gImageHandle) {
    Status = gBS->OpenProtocol (gImageHandle, &mFirmwareVolume2ProtocolGuid,
                                &Interface, gImageHandle, NULL,
                                EFI_OPEN_PROTOCOL_GET_PROTOCOL);
  }
  if (Interface == NULL) {
    Status = gBS->LocateProtocol (&mFirmwareVolume2ProtocolGuid, NULL, &Interface);
  }
  if (Interface == NULL) {
    EFI_HANDLE *Buffer;
    UINTN Count;
    Status = gBS->LocateHandleBuffer (ByProtocol, &mFirmwareVolume2ProtocolGuid,
                                       NULL, &Count, &Buffer);
    if (!EFI_ERROR (Status)) {
      UINTN i;
      for (i = 0; i < Count; i++) {
        Status = gBS->OpenProtocol (Buffer[i], &mFirmwareVolume2ProtocolGuid,
                                     &Interface, gImageHandle, NULL,
                                     EFI_OPEN_PROTOCOL_GET_PROTOCOL);
        if (!EFI_ERROR (Status)) break;
        Interface = NULL;
      }
      gBS->FreePool (Buffer);
    }
  }
  return Interface;
}

/******************** Section Extraction from FV ********************/

STATIC VOID *
GetSectionFromFv (IN CONST EFI_GUID *NameGuid, OUT VOID **Buffer, OUT UINTN *Size)
{
  EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
  UINT32 AuthenticationStatus;

  ASSERT (NameGuid != NULL && Buffer != NULL && Size != NULL);
  *Buffer = NULL; *Size = 0;

  Fv = GetFirmwareVolumeProtocol ();
  if (Fv == NULL) return NULL;

  EFI_STATUS Status;
  Status = Fv->ReadSection (Fv, NameGuid, EFI_SECTION_RAW, 0, Buffer,
                            (UINTN *)Size, &AuthenticationStatus);
  if (EFI_ERROR (Status)) { *Buffer = NULL; *Size = 0; }
  return (VOID *)(UINTN)Status;
}

STATIC EFI_STATUS
GetSectionFromAnyFv (IN CONST EFI_GUID *NameGuid, OUT VOID **Buffer, OUT UINTN *Size)
{
  EFI_STATUS Status;
  Status = (EFI_STATUS)(UINTN)GetSectionFromFv (NameGuid, Buffer, Size);
  if (EFI_ERROR (Status))
    Status = (EFI_STATUS)(UINTN)GetSectionFromFv (NameGuid, Buffer, Size);
  if (Status == EFI_NOT_FOUND) Status = EFI_NOT_FOUND;
  return Status;
}

/******************** Pool Allocation ********************/

STATIC VOID *
AllocatePool (IN UINTN Size)
{
  VOID *Buf = NULL;
  EFI_STATUS Status = gBS->AllocatePool (EfiBootServicesData, Size, &Buf);
  ASSERT (!EFI_ERROR (Status));
  return Buf;
}

/******************** Random Time Generation ********************/

STATIC VOID
GenerateRandomTime (OUT VOID *Buffer)
{
  EFI_TIME Now;
  UINT8 TimeSeed[16];

  ZeroMem (TimeSeed, sizeof (TimeSeed));
  TimeSeed[0] = 4; /* default month */

  if (mRuntimeServices != NULL)
    mRuntimeServices->GetTime (&Now, NULL);

  TimeSeed[0] = (UINT8)(Now.Year & 0xFF);
  TimeSeed[1] = (UINT8)((Now.Year >> 8) & 0xFF);
  TimeSeed[2] = (UINT8)Now.Month;
  TimeSeed[3] = (UINT8)Now.Day;
  TimeSeed[4] = (UINT8)Now.Hour;
  TimeSeed[5] = (UINT8)Now.Minute;
  TimeSeed[6] = (UINT8)Now.Second;
  TimeSeed[7] = 0;

  DEBUG ((EFI_D_INFO,
    "EfiTime Now : (Year=%d Month=%d Day=%d Hour=%d Min=%d Sec=%d)\n",
    TimeSeed[0] | ((UINT16)TimeSeed[1] << 8),
    TimeSeed[2], TimeSeed[3], TimeSeed[4], TimeSeed[5], TimeSeed[6]));

  CopyMem (Buffer, TimeSeed, 16);
  *(UINT16 *)((UINT8 *)Buffer + 16) = 24;
  *(UINT32 *)((UINT8 *)Buffer + 20) = 250675712;

  /* Append 16 bytes of RNG data */
  {
    EFI_RNG_PROTOCOL *Rng;
    EFI_STATUS Status;
    Status = gBS->LocateProtocol (&gEfiRngProtocolGuid, NULL, (VOID **)&Rng);
    if (Rng) {
      UINT64 RngBuf[2];
      Status = Rng->GetRNG (Rng, &mRngAlgoHash256, 16, (UINT8 *)&RngBuf);
      if (EFI_ERROR (Status))
        Status = Rng->GetRNG (Rng, &mRngAlgoHmac256, 16, (UINT8 *)&RngBuf);
      if (!EFI_ERROR (Status)) {
        WriteUnaligned64 ((UINT8 *)Buffer + 24, RngBuf[0]);
        WriteUnaligned64 ((UINT8 *)Buffer + 32, RngBuf[1]);
      }
    }
  }
}

/******************** Secure Boot Variable Set ********************/

STATIC EFI_STATUS
SetSecureBootVariable (
  IN UINT16          Flags,
  IN CONST CHAR16   *Name,
  IN CONST CHAR16   *DefaultName,
  IN CONST EFI_GUID *Guid,
  IN VOID           *Data,
  IN UINTN           DataSize)
{
  EFI_STATUS Status;
  UINTN      OldSize = 0, NewSize = 0;
  UINT32     Attr;
  UINTN      VarSize = 0;

  if (Name == NULL || (DataSize == 0 && Data == NULL))
    return EFI_INVALID_PARAMETER;
  if ((Flags & 4) && (DefaultName == NULL || Guid == NULL))
    return EFI_INVALID_PARAMETER;

  Status = mRuntimeServices->GetVariable ((CHAR16 *)Name, (EFI_GUID *)Guid,
                                           &Attr, &VarSize, NULL);

  if (Status == EFI_NOT_FOUND && (Flags & 1)) {
    GenerateRandomTime (&VarSize); /* stack buffer via local var */
    UINT8 ClearBuf[40];
    GenerateRandomTime (ClearBuf);
    VarSize = 39; Attr = 40;
    Status = mRuntimeServices->SetVariable ((CHAR16 *)Name, (EFI_GUID *)Guid,
                                             VarSize, Attr, ClearBuf);
    DEBUG ((EFI_D_INFO, "Clear NV Var %s(%r)\n", Name, Status));
    if (EFI_ERROR (Status)) return Status;
  }

  if (Status != EFI_BUFFER_TOO_SMALL) OldSize = VarSize;

  if ((Flags & 4)) {
    UINT32 *Hdr = (UINT32 *)Data;
    Status = mRuntimeServices->SetVariable ((CHAR16 *)DefaultName,
               (EFI_GUID *)&mVarStorageGuid, VarSize,
               DataSize - (Hdr[4] + 16), (UINT8 *)Data + Hdr[4] + 16);
    DEBUG ((EFI_D_INFO, "Set RT Var %s(%r)\n", DefaultName, Status));
  }

  if ((Flags & 2)) {
    Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;
    if (!(Flags & 8)) Attr |= 0x40; /* time-based */

    Status = mRuntimeServices->SetVariable ((CHAR16 *)Name, (EFI_GUID *)Guid,
                                             Attr, DataSize, Data);
    DEBUG ((EFI_D_INFO, "Set NV Var %s(%r)\n", Name, Status));
    if (Status == EFI_WRITE_PROTECTED) return EFI_SUCCESS;

    if (!EFI_ERROR (Status)) {
      mRuntimeServices->GetVariable ((CHAR16 *)Name, (EFI_GUID *)Guid,
                                      &Attr, &NewSize, NULL);
      DEBUG ((EFI_D_INFO, "Old Var Size %Xh\nNew Var size %Xh\n", OldSize, NewSize));
      if ((Flags & 8) && OldSize == NewSize) return EFI_ALREADY_STARTED;
    }
  }
  return Status;
}

/******************** Database Provisioning ********************/

STATIC EFI_STATUS
ProvisionSecureBootDatabases (
  IN UINT16  Flags,
  IN UINT32  Fmt,
  IN UINT32  Auth)
{
  struct { CONST CHAR16 *Name; CONST CHAR16 *Def; CONST EFI_GUID *Type; } DB[] = {
    { L"dbx", L"dbxDefault", &mCertSha256Guid },
    { L"dbt", L"dbtDefault", &mCertX509Guid },
    { L"dbr", L"dbrDefault", &mCertRsa2048Sha256Guid },
    { L"db",  L"dbDefault",  &mCertRsa2048Sha1Guid },
    { L"KEK", L"KEKDefault", &mCertX509Guid },
    { L"PK",  L"PKDefault",  &mCertSha384Guid },
  };

  UINTN i;
  for (i = 0; i < ARRAY_SIZE (DB); i++) {
    EFI_STATUS Status;
    VOID  *RawData = NULL;
    UINTN  DataSize = 0;

    Status = GetSectionFromAnyFv (DB[i].Type, &RawData, &DataSize);
    if (EFI_ERROR (Status)) { RawData = NULL; DataSize = 0; }

    DEBUG ((EFI_D_INFO, "Get Raw image %s(%r), sz = %x\n", DB[i].Name, Status, DataSize));
    SetSecureBootVariable (Flags, DB[i].Name, DB[i].Def, DB[i].Type, RawData, DataSize);
    if (RawData) gBS->FreePool (RawData);
  }
  return EFI_SUCCESS;
}

/******************** Secure Boot Driver Main ********************/

STATIC EFI_STATUS
SecureBootDriverMain (IN EFI_SYSTEM_TABLE *SystemTable)
{
  EFI_STATUS           Status;
  SECURE_BOOT_SETUP_VAR Setup;
  UINTN                VarSize;
  UINT32               Attributes;
  UINT8                SetupModeVal;
  UINTN                SetupModeSize;

  if (mSystemTable == NULL) {
    mSystemTable    = SystemTable;
    mBootServices   = SystemTable->BootServices;
    mRuntimeServices = SystemTable->RuntimeServices;
  }

  VarSize = sizeof (Setup);
  Status = mRuntimeServices->GetVariable (L"SecureBootSetup",
              (EFI_GUID *)&mSecureBootSetupVarGuid, &Attributes,
              &VarSize, &Setup);

  DEBUG ((EFI_D_INFO,
    "SecureBootSetup (%r) Attrib=%x,\nSecBoot-%d, SecMode-%d, DefaultProvision-%d\n",
    Status, Attributes, Setup.SecureBoot, Setup.SecureBootMode,
    Setup.DefaultProvisioning));

  GetConfigurationTable (SystemTable);

  if (Setup.DefaultProvisioning == 1) {
    ProvisionSecureBootDatabases (2, 0, 0);

    SetupModeSize = 1;
    mRuntimeServices->GetVariable (L"SetupMode",
      (EFI_GUID *)&mGlobalVariableGuid, &Attributes,
      &SetupModeSize, &SetupModeVal);

    /* Clear SetupMode */
    SetupModeVal = 0;
    SetupModeSize = 1; Attributes = 0;
    mRuntimeServices->SetVariable (L"SetupMode",
      (EFI_GUID *)&mGlobalVariableGuid, Attributes,
      &SetupModeSize, &SetupModeVal);

    SetupModeSize = 1;
    mRuntimeServices->GetVariable (L"SetupMode",
      (EFI_GUID *)&mGlobalVariableGuid, &Attributes,
      &SetupModeSize, &SetupModeVal);

    if (SetupModeVal == 0 && Setup.SecureBoot == 1) {
      mRuntimeServices->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
    }
  }

  ProvisionSecureBootDatabases (4, 0, 0);
  return EFI_SUCCESS;
}

/******************** Module Entry Point ********************/

EFI_STATUS
EFIAPI
SecureBootEntryPoint (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable)
{
  gImageHandle = ImageHandle;  ASSERT (gImageHandle != NULL);
  gST = SystemTable;           ASSERT (gST != NULL);
  gBS = SystemTable->BootServices; ASSERT (gBS != NULL);
  gRT = SystemTable->RuntimeServices; ASSERT (gRT != NULL);

  GetHobList ();
  return SecureBootDriverMain (SystemTable);
}