/** @file The secure boot manager implementation ;****************************************************************************** ;* Copyright (c) 2012 - 2021, Insyde Software Corp. All Rights Reserved. ;* ;* You may not reproduce, distribute, publish, display, perform, modify, adapt, ;* transmit, broadcast, present, recite, release, license or otherwise exploit ;* any part of this publication in any form, by any means, without the prior ;* written permission of Insyde Software Corporation. ;* ;****************************************************************************** */ #include "SecureBootMgr.h" #include "EnrollHash.h" #include "SecureBootVar.h" #include #include #include #include typedef struct _INDEX_NAME_MAP { UINT8 FunctionIndex; CHAR16 *VariableName; } INDEX_NAME_MAP; STATIC INDEX_NAME_MAP mIndexNameMap [] = { {UPDATE_DB_FUN_NUM, EFI_IMAGE_SECURITY_DATABASE}, {UPDATE_DBX_FUN_NUM, EFI_IMAGE_SECURITY_DATABASE1}, {UPDATE_DBT_FUN_NUM, EFI_IMAGE_SECURITY_DATABASE2}, {UPDATE_DBR_FUN_NUM, EFI_IMAGE_SECURITY_DATABASE3} }; /** This function uses to check system whether supports SMM mode or not. @retval TRUE System supports SMM mode @retval FALSE System doesn't support SMM mode. **/ STATIC BOOLEAN IsSmmModeSupported ( VOID ); EFI_GUID mSecureBootGuid = SECURE_BOOT_FORMSET_GUID; BOOLEAN mReadyToBootSignaled = FALSE; EFI_SEND_FORM2 mOrgSendForm = NULL; BOOLEAN mNeedInitializePrivateData = TRUE; SECURE_BOOT_MANAGER_CALLBACK_DATA mSecureBootPrivate = { SECURE_BOOT_CALLBACK_DATA_SIGNATURE, NULL, NULL, { SecureBootExtractConfig, SecureBootRouteConfig, SecureBootCallback } }; STATIC HII_VENDOR_DEVICE_PATH mSecureBootHiiVendorDevicePath = { { { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, { (UINT8) (sizeof (VENDOR_DEVICE_PATH)), (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) } }, SECURE_BOOT_FORMSET_GUID }, { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { (UINT8) (END_DEVICE_PATH_LENGTH), (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) } } }; EFI_LOAD_FILE_PROTOCOL mSecureBootMgrLoadFile = {SecureBootMgrLoadFile}; STATIC UINT8 mDefaultAthenData[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0xdd, 0x26, 0x02, 0x97, 0x9d, 0x44, 0x1f, 0x64, 0x95, 0xf8, 0x88, 0x46, 0xef, 0x9f, 0xb2, 0xa1, 0x6c, 0xbc, 0x89, 0x1c, 0x29, 0xad, 0x4e, 0x5f, 0x67, 0xe0, 0xdb, 0xeb, 0x2f, 0xa4, 0xc0, 0x3f, 0x44, 0x72, 0x5c, 0x93, 0x39, 0x6d, 0xe5, 0x1c, 0xe2, 0x2b, 0xcb, 0x76, 0x11, 0x71, 0x4f, 0xc7, 0xe7, 0xa2, 0xde, 0x1e, 0x07, 0x56, 0x92, 0xfc, 0x63, 0x61, 0xf1, 0x06, 0xbb, 0x77, 0x26, 0xb8, 0x99, 0x7c, 0x0e, 0xb8, 0x81, 0x24, 0x2e, 0x72, 0x78, 0x8c, 0xfa, 0x6a, 0x71, 0x5d, 0x08, 0x42, 0xda, 0xde, 0x86, 0xfe, 0x99, 0x92, 0xf7, 0xf8, 0xa0, 0x3d, 0x1f, 0x52, 0x0b, 0xb8, 0xc6, 0x1b, 0xd5, 0x39, 0xcb, 0x34, 0xdb, 0x2b, 0x25, 0x57, 0x44, 0x72, 0x02, 0x93, 0x67, 0x2a, 0x82, 0x90, 0xa2, 0x5a, 0x76, 0xcb, 0x81, 0x7d, 0x42, 0x39, 0x1a, 0xf8, 0x54, 0xe0, 0x42, 0xbf, 0x49, 0x36, 0x1c, 0x4e, 0x88, 0xda, 0x5c, 0x7b, 0xd4, 0x67, 0xf6, 0x82, 0x30, 0xe4, 0x18, 0xf9, 0xb3, 0xe8, 0xab, 0xa4, 0xca, 0x53, 0x82, 0xcf, 0xf4, 0xac, 0x83, 0x4b, 0xd6, 0xd4, 0xa1, 0xc0, 0x01, 0xfc, 0x16, 0x9d, 0xca, 0xc5, 0x17, 0x2e, 0x70, 0xff, 0xaf, 0x86, 0xc8, 0x43, 0x02, 0xde, 0x52, 0xb1, 0x23, 0xf0, 0x2f, 0xd8, 0x0a, 0x46, 0xd3, 0xaf, 0x6b, 0x7e, 0x77, 0xf6, 0x72, 0x00, 0x66, 0x69, 0x66, 0x37, 0x71, 0x19, 0xc7, 0x7b, 0xf0, 0xd1, 0x41, 0xfd, 0x2b, 0x9b, 0xa1, 0x14, 0xb5, 0xb3, 0x55, 0xb9, 0x96, 0x53, 0x9f, 0x29, 0x63, 0xb2, 0x38, 0x2e, 0x29, 0x10, 0x16, 0x8a, 0xbd, 0x2e, 0xed, 0x3b, 0xdc, 0xb5, 0x40, 0x6f, 0xab, 0x26, 0xea, 0xb5, 0x28, 0x36, 0x6b, 0x4a, 0x68, 0x85, 0xd2, 0xb1, 0xff, 0xbf, 0xe6, 0x0a, 0xd3, 0x8c, 0xe5, 0x01, 0xda, 0xfd, 0x65, 0x75, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }; STRING_DEPOSITORY *mSecureBootFileOptionStrDepository; STATIC UINT8 mEnrollHashSha256Data[] = { // EFI_VARIABLE_AUTHENTICATION_2 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // EFI_SIGNATURE_LIST 0x26, 0x16, 0xc4, 0xc1, 0x4c, 0x50, 0x92, 0x40, 0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28, // gEfiCertSha256Guid 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; STATIC UINT8 mEnrollHashSha1Data[] = { // EFI_VARIABLE_AUTHENTICATION_2 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // EFI_SIGNATURE_LIST 0x12, 0xa5, 0x6c, 0x82, 0x10, 0xcf, 0xc9, 0x4a, 0xb1, 0x87, 0xbe, 0x01, 0x49, 0x66, 0x31, 0xbd, // gEfiCertSha1Guid 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; LIST_ENTRY mSecureBootHashLinkList = INITIALIZE_LIST_HEAD_VARIABLE (mSecureBootHashLinkList); // // Following are the sameple code for how to update PK, KEK, db and dbx variable using Administer Secure Boot interface. // STATIC UINT8 mDefaultHeaderData[] = { // EFI_VARIABLE_AUTHENTICATION_2 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x02, 0xf1, 0x0e, 0x9d, 0xd2, 0xaf, 0x4a, 0xdf, 0x68, 0xee, 0x49, 0x8a, 0xa9, 0x34, 0x7d, 0x37, 0x56, 0x65, 0xa7, // gEfiCertPkcs7Guid 0x00 // one byte for update type // EFI_SIGNATURE_LIST }; // //STATIC UINT8 mTestCert [] = { //0x30, 0x82, 0x02, 0xF0, 0x30, 0x82, 0x01, 0xDC, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x1D, //0x30, 0x50, 0xAC, 0xFD, 0xFF, 0xB5, 0xB7, 0x4E, 0xFF, 0xAC, 0x38, 0x0E, 0x0F, 0x19, 0xB5, 0x30, //0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1D, 0x05, 0x00, 0x30, 0x13, 0x31, 0x11, 0x30, 0x0F, //0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x08, 0x74, 0x65, 0x73, 0x74, 0x6B, 0x65, 0x79, 0x32, 0x30, //0x1E, 0x17, 0x0D, 0x31, 0x30, 0x30, 0x33, 0x33, 0x31, 0x31, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5A, //0x17, 0x0D, 0x32, 0x30, 0x30, 0x35, 0x32, 0x39, 0x31, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x30, //0x13, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x08, 0x74, 0x65, 0x73, 0x74, //0x6B, 0x65, 0x79, 0x32, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, //0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, //0x02, 0x82, 0x01, 0x01, 0x00, 0xAA, 0x2D, 0x41, 0x1A, 0xE7, 0x19, 0x3A, 0xE0, 0xD3, 0x43, 0x72, //0x7D, 0x50, 0x02, 0x0D, 0xDF, 0x98, 0x05, 0x18, 0x45, 0xF2, 0x93, 0x51, 0x6F, 0xB6, 0x81, 0x93, //0x2E, 0x64, 0x89, 0x31, 0x20, 0x58, 0x14, 0x30, 0x2D, 0x95, 0x1A, 0xA4, 0x40, 0x75, 0xD9, 0xEB, //0x67, 0xAD, 0x13, 0xF4, 0x11, 0x2D, 0xDF, 0x40, 0x91, 0xED, 0xCA, 0xE7, 0xEC, 0x99, 0x7D, 0x7A, //0x84, 0x71, 0x61, 0x9F, 0x77, 0x9A, 0xC5, 0x93, 0x8D, 0x14, 0x15, 0x5E, 0x51, 0x2B, 0xF4, 0x64, //0x60, 0x17, 0xFB, 0x03, 0x7F, 0x3C, 0x5D, 0xE7, 0x66, 0x77, 0x67, 0xA5, 0xFC, 0xD1, 0x10, 0x3C, //0x23, 0x91, 0x27, 0x46, 0x9A, 0x8E, 0xF3, 0x51, 0xB6, 0x90, 0x30, 0xCC, 0x6E, 0xD6, 0x15, 0x6F, //0x77, 0x58, 0x68, 0xE7, 0x4D, 0xD2, 0x59, 0xE7, 0x55, 0x20, 0x06, 0xC7, 0xBC, 0x89, 0x66, 0x67, //0x93, 0xDD, 0xD2, 0x26, 0x32, 0x43, 0x47, 0xEC, 0x67, 0x36, 0x66, 0x40, 0xF9, 0x46, 0x16, 0x6B, //0xE8, 0x27, 0x1A, 0xC3, 0x73, 0xD4, 0x39, 0x08, 0x91, 0xCB, 0xA7, 0xEA, 0x03, 0x15, 0x1E, 0xF2, //0xCF, 0x49, 0x1A, 0x1D, 0xB3, 0x99, 0x07, 0x83, 0x48, 0x5A, 0x6E, 0x56, 0xE7, 0x4D, 0x6F, 0xAD, //0x6E, 0x84, 0x61, 0xC6, 0x04, 0xFA, 0x32, 0x01, 0x27, 0x00, 0xF0, 0x4E, 0xEF, 0x04, 0x78, 0x38, //0xA4, 0xC7, 0x85, 0x15, 0x08, 0x40, 0x32, 0x6F, 0x64, 0x10, 0x01, 0x53, 0x75, 0x18, 0x7B, 0x60, //0xDE, 0x66, 0x9F, 0x94, 0xF0, 0x35, 0x03, 0x07, 0x64, 0x67, 0xC3, 0x37, 0x28, 0x9D, 0x70, 0x27, //0x98, 0x7A, 0xC0, 0x7B, 0xCD, 0x74, 0x97, 0x88, 0xB3, 0x1C, 0x86, 0xB2, 0xCF, 0x29, 0x74, 0x8B, //0x0A, 0xEA, 0xBF, 0x7E, 0xF9, 0x1B, 0x81, 0x15, 0xE9, 0x78, 0x1C, 0xC7, 0x55, 0x25, 0xD6, 0x41, //0x72, 0xED, 0xC4, 0x88, 0x69, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x48, 0x30, 0x46, 0x30, 0x44, //0x06, 0x03, 0x55, 0x1D, 0x01, 0x04, 0x3D, 0x30, 0x3B, 0x80, 0x10, 0x06, 0x65, 0x0F, 0xFD, 0x3D, //0xB0, 0xA6, 0x4C, 0xD6, 0x81, 0xE8, 0x66, 0x39, 0xA4, 0x67, 0x44, 0xA1, 0x15, 0x30, 0x13, 0x31, //0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x08, 0x74, 0x65, 0x73, 0x74, 0x6B, 0x65, //0x79, 0x32, 0x82, 0x10, 0x1D, 0x30, 0x50, 0xAC, 0xFD, 0xFF, 0xB5, 0xB7, 0x4E, 0xFF, 0xAC, 0x38, //0x0E, 0x0F, 0x19, 0xB5, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1D, 0x05, 0x00, 0x03, //0x82, 0x01, 0x01, 0x00, 0x1C, 0x74, 0x76, 0x2D, 0x9E, 0x02, 0xB3, 0xFB, 0xFE, 0x00, 0x57, 0x07, //0xB4, 0x55, 0x8D, 0x94, 0x24, 0x54, 0xD4, 0x03, 0x2B, 0xBB, 0x7E, 0x22, 0x6F, 0x1F, 0x38, 0x26, //0x0A, 0x6B, 0x09, 0x02, 0xB9, 0x37, 0x98, 0x81, 0x5C, 0xF4, 0x71, 0x68, 0xF6, 0xA3, 0x7D, 0x17, //0x18, 0xED, 0x00, 0x1D, 0x58, 0xA1, 0xD2, 0x6D, 0x81, 0xF0, 0xC0, 0x27, 0x6C, 0x8F, 0x08, 0xEC, //0x00, 0x64, 0xB0, 0xD4, 0x8A, 0x47, 0x70, 0xFD, 0xE2, 0xFC, 0xAF, 0x87, 0x08, 0xC9, 0x23, 0x2F, //0xA1, 0x65, 0xC1, 0xA1, 0x70, 0xF1, 0xB0, 0x76, 0x68, 0x7C, 0x6C, 0xEC, 0x24, 0x71, 0x1F, 0x39, //0x97, 0x2E, 0xC1, 0xCD, 0x50, 0x22, 0x5B, 0x26, 0xDD, 0xDD, 0xAB, 0x97, 0x83, 0x65, 0x14, 0xBA, //0x30, 0x1F, 0x5E, 0xDF, 0x27, 0x17, 0xDA, 0x2F, 0xE6, 0x81, 0x9A, 0x44, 0xAC, 0xD2, 0x72, 0x63, //0x4C, 0x8D, 0x63, 0xF5, 0x24, 0x61, 0xA4, 0x52, 0x22, 0x57, 0x42, 0x1C, 0x35, 0x00, 0xCE, 0xED, //0xAB, 0xC2, 0x53, 0xAB, 0xE0, 0x1B, 0x04, 0x43, 0x2D, 0xC9, 0x94, 0xB3, 0x02, 0xB6, 0x26, 0x53, //0xC2, 0xF7, 0xB9, 0xA6, 0xB9, 0x10, 0xFB, 0xAF, 0x88, 0x0A, 0xE2, 0xBE, 0x67, 0x5E, 0xAE, 0x9D, //0xB9, 0x20, 0x9E, 0xFD, 0x52, 0x15, 0x59, 0x34, 0x40, 0x65, 0xDB, 0xB3, 0xEB, 0x9E, 0x69, 0x5F, //0xB6, 0x8C, 0x86, 0xF9, 0xA1, 0x5F, 0xD7, 0x8C, 0xAA, 0x5A, 0x98, 0x48, 0x11, 0x95, 0x05, 0xCA, //0x7B, 0xDB, 0xD0, 0x3A, 0xC0, 0x8A, 0x1D, 0xF1, 0x4C, 0x92, 0x80, 0x90, 0xAA, 0x58, 0x81, 0x60, //0x7F, 0xEC, 0x86, 0x69, 0x58, 0xE8, 0xAF, 0xDA, 0xAB, 0x06, 0xED, 0xAA, 0x2A, 0xEB, 0x63, 0xD5, //0x46, 0xF9, 0x51, 0x3B, 0x76, 0x55, 0x0B, 0xE3, 0xFE, 0xD5, 0x53, 0x36, 0x14, 0x25, 0xEA, 0x09, //0xEC, 0x7C, 0x17, 0x54 //}; // // ///** //Internal function uses input certificate, certificate size and update type to create //output EFI_VARIABLE_AUTHENTICATION_2 descriptor. // //@param[in] InputBuffer The content of input certificate. //@param[in] InputSize The size in bytes of the input certificate. //@param[in] OwnerGuid Input owner guid for the input signature owner. If OwnerGuid is NULL, the owner GUID // will be set to all ZERO. //@param[in] UpdateType The Input update type. This update type should be UPDATE_AUTHENTICATED_VARIABLE // or APPEND_AUTHENTICATED_VARIABLE. //@param[out] OutputBuffer A pointer to the output buffer to save the EFI_VARIABLE_AUTHENTICATION_2 descriptor. // This buffer is allocated with a call to the Boot Service AllocatePool(). It is the // caller's responsibility to call the Boot Service FreePool() when the caller no longer // requires the contents of Buffer. //@param[out] OutPutSize The size in bytes of the EFI_VARIABLE_AUTHENTICATION_2 descriptor. // //@retval EFI_SUCCESS Create EFI_VARIABLE_AUTHENTICATION_2 descriptor successfully. //@retval EFI_INVALID_PARAMETER Any input parameter in incorrect. //@retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the EFI_VARIABLE_AUTHENTICATION_2 descriptor. //**/ //STATIC //EFI_STATUS //CreateAuthenData ( //IN UINT8 *InputBuffer, //IN UINTN InputSize, //IN EFI_GUID *OwnerGuid, OPTIONAL //IN UINTN UpdateType, //OUT UINT8 **OutputBuffer, //OUT UINTN *OutPutSize //) //{ //UINTN BufferSize; //UINT8 *Buffer; //EFI_SIGNATURE_LIST *SigList; //EFI_SIGNATURE_DATA *SigData; // //if (OutputBuffer == NULL || OutPutSize == NULL) { // return EFI_INVALID_PARAMETER; //} // //if (UpdateType != UPDATE_AUTHENTICATED_VARIABLE && UpdateType != APPEND_AUTHENTICATED_VARIABLE) { // return EFI_INVALID_PARAMETER; //} //if (InputBuffer == NULL) { // InputSize = 0; //} // //if (InputSize != 0) { // BufferSize = sizeof (mDefaultHeaderData) + sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + InputSize; //} else { // BufferSize = sizeof (mDefaultHeaderData); //} //Buffer = AllocateZeroPool (BufferSize); //if (Buffer == NULL) { // return EFI_OUT_OF_RESOURCES; //} //// //// Update header data and set udpate type (update or append) //// //CopyMem (Buffer, mDefaultHeaderData, sizeof (mDefaultHeaderData)); //*(Buffer + sizeof (mDefaultHeaderData) - sizeof (UINT8)) = (UINT8) UpdateType; // //if (InputSize != 0) { // SigList = (EFI_SIGNATURE_LIST *) (Buffer + sizeof (mDefaultHeaderData)); // CopyMem (&SigList->SignatureType, &gEfiCertX509Guid, sizeof (EFI_GUID)); // SigList->SignatureListSize = (UINT32) (InputSize + sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1); // SigList->SignatureSize = (UINT32) (InputSize + sizeof (EFI_GUID)); // // SigData = (EFI_SIGNATURE_DATA*) (SigList + 1); // // // // Set signature owner according to input owner GUID. Otherwise, keep this signature owner GUID // // as all zero. // // // if (OwnerGuid != NULL) { // CopyMem (&SigData->SignatureOwner, OwnerGuid, sizeof (EFI_GUID)); // } // CopyMem (SigData->SignatureData, InputBuffer, InputSize); //} //*OutputBuffer = Buffer; //*OutPutSize = BufferSize; //return EFI_SUCCESS; //} /** Internal function uses input variable data, variable data size and update type to create output EFI_VARIABLE_AUTHENTICATION_2 descriptor. @param[in] VarData The content of input variable data. @param[in] VarDataSize The size in bytes of the input variable data. @param[in] UpdateType The Input update type. This update type should be UPDATE_AUTHENTICATED_VARIABLE or APPEND_AUTHENTICATED_VARIABLE. @param[out] AuthenVarData A pointer to the output buffer to save the EFI_VARIABLE_AUTHENTICATION_2 descriptor. This buffer is allocated with a call to the Boot Service AllocatePool(). It is the caller's responsibility to call the Boot Service FreePool() when the caller no longer requires the contents of Buffer. @param[out] AuthenVarDataSize The size in bytes of the EFI_VARIABLE_AUTHENTICATION_2 descriptor. @retval EFI_SUCCESS Create EFI_VARIABLE_AUTHENTICATION_2 descriptor successfully. @retval EFI_INVALID_PARAMETER Any input parameter in incorrect. @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the EFI_VARIABLE_AUTHENTICATION_2 descriptor. **/ STATIC EFI_STATUS CreateAuthenVarData ( IN UINT8 *VarData, IN UINTN VarDataSize, IN UINTN UpdateType, OUT UINT8 **AuthenVarData, OUT UINTN *AuthenVarDataSize ) { UINTN BufferSize; UINT8 *Buffer; if (AuthenVarData == NULL || AuthenVarDataSize == NULL) { return EFI_INVALID_PARAMETER; } if (VarData == NULL) { VarDataSize = 0; } BufferSize = sizeof (mDefaultHeaderData) + VarDataSize; Buffer = AllocateZeroPool (BufferSize); if (Buffer == NULL) { return EFI_OUT_OF_RESOURCES; } CopyMem (Buffer, mDefaultHeaderData, sizeof (mDefaultHeaderData)); *(Buffer + sizeof (mDefaultHeaderData) - sizeof (UINT8)) = (UINT8) UpdateType; CopyMem (Buffer + sizeof (mDefaultHeaderData), VarData, VarDataSize); *AuthenVarData = Buffer; *AuthenVarDataSize = BufferSize; return EFI_SUCCESS; } /** Function uses input variable data and size to update PK variable through SMI. This update will not do any certification check no matter system is in setup mode or user mode. @param[in] VarData The content of input variable data. @param[in] VarDataSize The size in bytes of the input variable data. @retval EFI_SUCCESS Update input variable data to PK variable successfully. @retval EFI_INVALID_PARAMETER Any input parameter in incorrect. @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the EFI_VARIABLE_AUTHENTICATION_2 descriptor. **/ EFI_STATUS UpdatePkVariable ( IN UINT8 *VarData, IN UINTN VarDataSize ) { EFI_STATUS Status; UINT8 *Buffer; UINTN BufferSize; Status = CreateAuthenVarData (VarData, VarDataSize, UPDATE_AUTHENTICATED_VARIABLE, &Buffer, &BufferSize); if (EFI_ERROR (Status)) { return Status; } if (IsSmmModeSupported ()) { SmmSecureBootCallWithRuntimeMemory ( Buffer, BufferSize, UPDATE_PK_FUN_NUM ); } else { Status = gRT->SetVariable ( EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS, BufferSize, Buffer ); } FreePool (Buffer); return EFI_SUCCESS; } /** Function uses input variable data and size to update KEK variable through SMI. This update will not do any certification check no matter system is in setup mode or user mode. @param[in] VarData The content of input variable data. @param[in] VarDataSize The size in bytes of the input variable data. @param[in] UpdateType The Input update type. This update type should be UPDATE_AUTHENTICATED_VARIABLE or APPEND_AUTHENTICATED_VARIABLE. @retval EFI_SUCCESS Update input variable data to KEK variable successfully. @retval EFI_INVALID_PARAMETER Any input parameter in incorrect. @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the EFI_VARIABLE_AUTHENTICATION_2 descriptor. **/ EFI_STATUS UpdateKekVariable ( IN UINT8 *VarData, IN UINTN VarDataSize, IN UINTN UpdateType ) { EFI_STATUS Status; UINT8 *Buffer; UINTN BufferSize; UINT32 Attribute; if (UpdateType != UPDATE_AUTHENTICATED_VARIABLE && UpdateType != APPEND_AUTHENTICATED_VARIABLE) { return EFI_INVALID_PARAMETER; } Status = CreateAuthenVarData (VarData, VarDataSize, UpdateType, &Buffer, &BufferSize); if (EFI_ERROR (Status)) { return Status; } if (IsSmmModeSupported ()) { SmmSecureBootCallWithRuntimeMemory ( Buffer, BufferSize, UPDATE_KEK_FUN_NUM ); } else { Attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; if (UpdateType == APPEND_AUTHENTICATED_VARIABLE) { Attribute |= EFI_VARIABLE_APPEND_WRITE; } Status = gRT->SetVariable ( EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, Attribute, BufferSize, Buffer ); } FreePool (Buffer); return EFI_SUCCESS; } /** Get variable name based on input function index. @param[in] FunctionIndex Input function index. return Variable name or NULL if input function index isn't supported. **/ STATIC CHAR16 * GetVariableNameFromFunctionIndex ( IN UINT8 FunctionIndex ) { UINTN Index; UINTN Count; Count = sizeof (mIndexNameMap) / sizeof (INDEX_NAME_MAP); for (Index = 0; Index < Count; Index++) { if (FunctionIndex == mIndexNameMap[Index].FunctionIndex) { return mIndexNameMap[Index].VariableName; } } return NULL; } /** Function uses input variable data and size to update common secure boot variable through SMI. This update will not do any certification check no matter system is in setup mode or user mode. @param[in] VarData The content of input variable data. @param[in] VarDataSize The size in bytes of the input variable data. @param[in] UpdateType The Input update type. This update type should be UPDATE_AUTHENTICATED_VARIABLE or APPEND_AUTHENTICATED_VARIABLE. @param[in] FunctionIndex Input function index. @retval EFI_SUCCESS Update input variable data to common secure boot variable variable successfully. @retval EFI_INVALID_PARAMETER Any input parameter in incorrect. @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the EFI_VARIABLE_AUTHENTICATION_2 descriptor. **/ STATIC EFI_STATUS UpdateCommonSecureBootVariable ( IN UINT8 *VarData, IN UINTN VarDataSize, IN UINTN UpdateType, IN UINT8 FunctionIndex ) { EFI_STATUS Status; UINT8 *Buffer; UINTN BufferSize; UINT32 Attribute; if (UpdateType != UPDATE_AUTHENTICATED_VARIABLE && UpdateType != APPEND_AUTHENTICATED_VARIABLE) { return EFI_INVALID_PARAMETER; } if (FunctionIndex != UPDATE_DB_FUN_NUM && FunctionIndex != UPDATE_DBX_FUN_NUM && FunctionIndex != UPDATE_DBT_FUN_NUM && FunctionIndex != UPDATE_DBR_FUN_NUM) { return EFI_INVALID_PARAMETER; } Status = CreateAuthenVarData (VarData, VarDataSize, UpdateType, &Buffer, &BufferSize); if (EFI_ERROR (Status)) { return Status; } if (IsSmmModeSupported ()) { SmmSecureBootCallWithRuntimeMemory ( Buffer, BufferSize, FunctionIndex ); } else { Attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; if (UpdateType == APPEND_AUTHENTICATED_VARIABLE) { Attribute |= EFI_VARIABLE_APPEND_WRITE; } Status = gRT->SetVariable ( GetVariableNameFromFunctionIndex (FunctionIndex), &gEfiImageSecurityDatabaseGuid, Attribute, BufferSize, Buffer ); } FreePool (Buffer); return EFI_SUCCESS; } /** Function uses input variable data and size to update db variable through SMI. This update will not do any certification check no matter system is in setup mode or user mode. @param[in] VarData The content of input variable data. @param[in] VarDataSize The size in bytes of the input variable data. @param[in] UpdateType The Input update type. This update type should be UPDATE_AUTHENTICATED_VARIABLE or APPEND_AUTHENTICATED_VARIABLE. @retval EFI_SUCCESS Update input variable data to db variable successfully. @retval EFI_INVALID_PARAMETER Any input parameter in incorrect. @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the EFI_VARIABLE_AUTHENTICATION_2 descriptor. **/ EFI_STATUS UpdateDbVariable ( IN UINT8 *VarData, IN UINTN VarDataSize, IN UINTN UpdateType ) { return UpdateCommonSecureBootVariable (VarData, VarDataSize, UpdateType, UPDATE_DB_FUN_NUM); } /** Function uses input variable data and size to update dbx variable through SMI. This update will not do any certification check no matter system is in setup mode or user mode. @param[in] InputBuffer The content of input certificate. @param[in] InputSize The size in bytes of the input certificate. @param[in] OwnerGuid Input owner guid for the input signature owner. If OwnerGuid is NULL, the owner GUID will be set to all ZERO. @param[in] UpdateType The Input update type. This update type should be UPDATE_AUTHENTICATED_VARIABLE or APPEND_AUTHENTICATED_VARIABLE. @retval EFI_SUCCESS Update input certificate to dbx variable successfully. @retval EFI_INVALID_PARAMETER Any input parameter in incorrect. @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the EFI_VARIABLE_AUTHENTICATION_2 descriptor. **/ EFI_STATUS UpdateDbxVariable ( IN UINT8 *VarData, IN UINTN VarDataSize, IN UINTN UpdateType ) { return UpdateCommonSecureBootVariable (VarData, VarDataSize, UpdateType, UPDATE_DBX_FUN_NUM); } /** Function uses input variable data and size to update dbt variable through SMI. This update will not do any certification check no matter system is in setup mode or user mode. @param[in] InputBuffer The content of input certificate. @param[in] InputSize The size in bytes of the input certificate. @param[in] OwnerGuid Input owner guid for the input signature owner. If OwnerGuid is NULL, the owner GUID will be set to all ZERO. @param[in] UpdateType The Input update type. This update type should be UPDATE_AUTHENTICATED_VARIABLE or APPEND_AUTHENTICATED_VARIABLE. @retval EFI_SUCCESS Update input certificate to dbx variable successfully. @retval EFI_INVALID_PARAMETER Any input parameter in incorrect. @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the EFI_VARIABLE_AUTHENTICATION_2 descriptor. **/ EFI_STATUS UpdateDbtVariable ( IN UINT8 *VarData, IN UINTN VarDataSize, IN UINTN UpdateType ) { return UpdateCommonSecureBootVariable (VarData, VarDataSize, UpdateType, UPDATE_DBT_FUN_NUM); } /** Function uses input input variable data and size to update dbr variable through SMI. This update will not do any certification check no matter system is in setup mode or user mode. @param[in] InputBuffer The content of input certificate. @param[in] InputSize The size in bytes of the input certificate. @param[in] OwnerGuid Input owner guid for the input signature owner. If OwnerGuid is NULL, the owner GUID will be set to all ZERO. @param[in] UpdateType The Input update type. This update type should be UPDATE_AUTHENTICATED_VARIABLE or APPEND_AUTHENTICATED_VARIABLE. @retval EFI_SUCCESS Update input certificate to dbx variable successfully. @retval EFI_INVALID_PARAMETER Any input parameter in incorrect. @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the EFI_VARIABLE_AUTHENTICATION_2 descriptor. **/ EFI_STATUS UpdateDbrVariable ( IN UINT8 *VarData, IN UINTN VarDataSize, IN UINTN UpdateType ) { return UpdateCommonSecureBootVariable (VarData, VarDataSize, UpdateType, UPDATE_DBR_FUN_NUM); } /** This function uses to check system whether supports SMM mode or not. @retval TRUE System supports SMM mode @retval FALSE System doesn't support SMM mode. **/ STATIC BOOLEAN IsSmmModeSupported ( VOID ) { EFI_SMM_BASE2_PROTOCOL *SmmBase; BOOLEAN SmmSupport; EFI_STATUS Status; SmmSupport =FALSE; Status = gBS->LocateProtocol ( &gEfiSmmBase2ProtocolGuid, NULL, (VOID **) &SmmBase ); if (!EFI_ERROR (Status)) { SmmSupport = TRUE; } return SmmSupport; } /** Check if the input question ID is a VFR goto question or not. @param[in] QuestionId The question ID @retval TRUE The input question ID is a VFR goto question. @retval FALSE The input question ID is not a VFR goto question. **/ STATIC BOOLEAN IsGotoQuestion ( IN EFI_QUESTION_ID QuestionId ) { if (QuestionId == KEY_ENROLL_HASH || QuestionId == KEY_ENROLL_PK || QuestionId == KEY_ENROLL_KEK || QuestionId == KEY_ENROLL_DB || QuestionId == KEY_ENROLL_DBX || QuestionId == KEY_ENROLL_DBT || QuestionId == KEY_ENROLL_DBR || QuestionId == KEY_PK_FORM || QuestionId == KEY_KEK_FORM || QuestionId == KEY_DB_FORM || QuestionId == KEY_DBX_FORM || QuestionId == KEY_DBT_FORM || QuestionId == KEY_DBR_FORM) { return TRUE; } return FALSE; } /** Update AddHashImage variable by enumerating all hash images from hash linked list. @retval EFI_SUCCESS Update AddHashImage variable successfully. **/ EFI_STATUS UpdateAddHashImageVariable ( VOID ) { LIST_ENTRY *Link; HASH_LINK_LIST *HashLink; UINTN BufferSize; while (!IsListEmpty (&mSecureBootHashLinkList)) { Link = mSecureBootHashLinkList.ForwardLink; HashLink = CR (Link, HASH_LINK_LIST, Link, HASH_LINK_LIST_SIGNATURE); if (HashLink->ShaType == HASHALG_SHA256) { BufferSize = sizeof (mEnrollHashSha256Data); CopyMem ( (VOID *) &mEnrollHashSha256Data[BufferSize - sizeof (EFI_SHA256_HASH)], (VOID*) HashLink->Hash, sizeof (EFI_SHA256_HASH) ); if (IsSmmModeSupported ()) { SmmSecureBootCallWithRuntimeMemory ( mEnrollHashSha256Data, BufferSize, ADD_HASH_IMAGE_FUN_NUM ); } else { gRT->SetVariable ( EFI_ADD_HASH_IMMAGE_NAME, &gEfiGenericVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS | EFI_VARIABLE_APPEND_WRITE, BufferSize, mEnrollHashSha256Data ); } } else { BufferSize = sizeof (mEnrollHashSha1Data); CopyMem ( (VOID *) &mEnrollHashSha1Data[BufferSize - sizeof (EFI_SHA1_HASH)], (VOID*) HashLink->Hash, sizeof (EFI_SHA1_HASH) ); if (IsSmmModeSupported ()) { SmmSecureBootCallWithRuntimeMemory ( mEnrollHashSha1Data, BufferSize, ADD_HASH_IMAGE_FUN_NUM ); } else { gRT->SetVariable ( EFI_ADD_HASH_IMMAGE_NAME, &gEfiGenericVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS | EFI_VARIABLE_APPEND_WRITE, BufferSize, mEnrollHashSha1Data ); } } RemoveEntryList (Link); FreePool (HashLink); } return EFI_SUCCESS; } /** This function uses to save all of administer secure boot settings @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. @retval EFI_SUCCESS The Results is processed successfully. @retval EFI_INVALID_PARAMETER Configuration is NULL. **/ STATIC EFI_STATUS SecureBootSaveChange ( IN EFI_HII_CONFIG_ACCESS_PROTOCOL *This ) { SECURE_BOOT_MANAGER_CALLBACK_DATA *PrivateData; UINTN BufferSize; UINT8 EnforceSecureBoot; UINT8 ResotreFactory; if (This == NULL) { return EFI_INVALID_PARAMETER; } PrivateData = SECURE_BOOT_CALLBACK_DATA_FROM_THIS (This); HiiGetBrowserData (NULL, NULL, sizeof (SECURE_BOOT_NV_DATA), (UINT8 *) &PrivateData->SecureBootData); if (PcdGetBool (PcdH2OUefiCaCertificateSetupAddSupported)) { if (PrivateData->SecureBootData.AddUefiCaCertificate != PrivateData->BackupSecureBootData.AddUefiCaCertificate && PrivateData->SecureBootData.AddUefiCaCertificate == 1) { AddUefiCaCertificateToDb (); PrivateData->BackupSecureBootData.UefiCaCertificateInDb = PrivateData->SecureBootData.UefiCaCertificateInDb; } } SecureBootVarSaveChange (); UpdateAddHashImageVariable (); if (PcdGetBool (PcdH2OSecureBootDisableSupported) && PrivateData->SecureBootData.EnforceSecureBoot != PrivateData->BackupSecureBootData.EnforceSecureBoot) { EnforceSecureBoot = PrivateData->SecureBootData.EnforceSecureBoot; BufferSize = sizeof (mDefaultAthenData); mDefaultAthenData[BufferSize - 1] = (EnforceSecureBoot == 1) ? 1 : 0; if (IsSmmModeSupported ()) { SmmSecureBootCallWithRuntimeMemory ( mDefaultAthenData, BufferSize, SECURE_BOOT_ENFORCE_FUN_NUM ); } else { gRT->SetVariable ( EFI_SECURE_BOOT_ENFORCE_NAME, &gEfiGenericVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, BufferSize, mDefaultAthenData ); } PrivateData->BackupSecureBootData.EnforceSecureBoot = PrivateData->SecureBootData.EnforceSecureBoot; } if (PcdGetBool (PcdH2OSecureBootDisableSupported) && PrivateData->SecureBootData.ClearSecureSettings == 1) { if (IsSmmModeSupported ()) { SmmSecureBootCallWithRuntimeMemory ( NULL, 0, CLEAR_ALL_SECURE_SETTINGS_FUN_NUM ); } else { BufferSize = sizeof (mDefaultAthenData); mDefaultAthenData[BufferSize - 1] = 1; gRT->SetVariable ( EFI_CLEAR_ALL_SECURE_SETTINGS_NAME, &gEfiGenericVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, BufferSize, mDefaultAthenData ); } } // // Move saved restore factory default to the last. This action can make sure system can set CustomSecurity variable to 0 correctly, // even if user also changes ClearSecureSettings or add hash to db. // if (PrivateData->SecureBootData.ResotreFactorySettings != PrivateData->BackupSecureBootData.ResotreFactorySettings) { ResotreFactory = PrivateData->SecureBootData.ResotreFactorySettings; BufferSize = sizeof (mDefaultAthenData); mDefaultAthenData[BufferSize - 1] = (ResotreFactory == 1) ? 1 : 0; if (IsSmmModeSupported ()) { SmmSecureBootCallWithRuntimeMemory ( mDefaultAthenData, BufferSize, RESTORE_FACTORY_DEFAULT_FUN_NUM ); } else { gRT->SetVariable ( EFI_RESTORE_FACTORY_DEFAULT_NAME, &gEfiGenericVariableGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS, BufferSize, mDefaultAthenData ); } PrivateData->BackupSecureBootData.ResotreFactorySettings = PrivateData->SecureBootData.ResotreFactorySettings; } if (!FeaturePcdGet (PcdH2OCustomizedSecureBootSupported)) { return EFI_SUCCESS; } if (PrivateData->SecureBootData.SelectSecureBootMode != PrivateData->SecureBootData.BackupSelectSecureBootMode) { BufferSize = sizeof (mDefaultAthenData); mDefaultAthenData[BufferSize - 1] = PrivateData->SecureBootData.SelectSecureBootMode; SmmSecureBootCallWithRuntimeMemory ( mDefaultAthenData, BufferSize, SELECT_SECURE_BOOT_MODE_FUN_NUM ); } return EFI_SUCCESS; } /** This function uses to get current secur boot mode. @return SecureBootMode Current secure boot mode. **/ STATIC UINT8 GetSecureBootMode ( VOID ) { if (mSecureBootPrivate.SecureBootData.DeployedMode == 1) { return H2O_DEPLOYED_MODE; } else if (mSecureBootPrivate.SecureBootData.AuditMode == 1) { return H2O_AUDIT_MODE; } else if (mSecureBootPrivate.SecureBootData.SetupMode == 0) { return H2O_USER_MODE; } else { return H2O_SETUP_MODE; } } /** Initialize all of system status in Administer Secure Boot menu. @retval EFI_SUCCESS Initialize secure boot system status successful. @retval EFI_NOT_FOUND Cannot find any variable for secure boot system status. **/ EFI_STATUS InitializeSystemStatus ( VOID ) { UINTN BufferSize; UINT8 Data; EFI_STATUS Status; LIST_ENTRY *Link; HASH_LINK_LIST *HashLink; while (!IsListEmpty (&mSecureBootHashLinkList)) { Link = mSecureBootHashLinkList.ForwardLink; HashLink = CR (Link, HASH_LINK_LIST, Link, HASH_LINK_LIST_SIGNATURE); RemoveEntryList (Link); FreePool (HashLink); } SecureBootVarInit (); BufferSize = sizeof (UINT8); Status = gRT->GetVariable ( EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, NULL, &BufferSize, &Data ); if (EFI_ERROR (Status)) { return Status; } mSecureBootPrivate.SecureBootData.SetupMode = Data; mSecureBootPrivate.BackupSecureBootData.SetupMode = Data; mSecureBootPrivate.SecureBootData.AddUefiCaCertificate = 0; mSecureBootPrivate.BackupSecureBootData.AddUefiCaCertificate = 0; if (!IsUefiCaCertificateInDb () && Data == 0) { mSecureBootPrivate.SecureBootData.UefiCaCertificateInDb = 0; mSecureBootPrivate.BackupSecureBootData.UefiCaCertificateInDb = 0; } else { mSecureBootPrivate.SecureBootData.UefiCaCertificateInDb = 1; mSecureBootPrivate.BackupSecureBootData.UefiCaCertificateInDb = 1; } BufferSize = sizeof (UINT8); Status = gRT->GetVariable ( EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, NULL, &BufferSize, &Data ); if (EFI_ERROR (Status)) { return Status; } mSecureBootPrivate.SecureBootData.SecureBoot = Data; mSecureBootPrivate.BackupSecureBootData.SecureBoot = Data; BufferSize = sizeof (UINT8); Status = gRT->GetVariable ( EFI_CUSTOM_SECURITY_NAME, &gEfiGenericVariableGuid, NULL, &BufferSize, &Data ); if (EFI_ERROR (Status)) { return Status; } mSecureBootPrivate.SecureBootData.CustomSecurity = Data; mSecureBootPrivate.BackupSecureBootData.CustomSecurity = Data; mSecureBootPrivate.SecureBootData.ClearSecureSettings = 0; mSecureBootPrivate.BackupSecureBootData.ClearSecureSettings = 0; BufferSize = sizeof (UINT8); Status = gRT->GetVariable ( EFI_RESTORE_FACTORY_DEFAULT_NAME, &gEfiGenericVariableGuid, NULL, &BufferSize, &Data ); if (EFI_ERROR (Status)) { Data = 0; } mSecureBootPrivate.SecureBootData.ResotreFactorySettings = Data; mSecureBootPrivate.BackupSecureBootData.ResotreFactorySettings = Data; // // Initialize secure boot data // mSecureBootPrivate.SecureBootData.EnforceSecureBoot = 1; mSecureBootPrivate.BackupSecureBootData.EnforceSecureBoot = 1; BufferSize = sizeof (UINT8); Status = gRT->GetVariable ( EFI_SECURE_BOOT_ENFORCE_NAME, &gEfiGenericVariableGuid, NULL, &BufferSize, &Data ); if (!EFI_ERROR (Status) && Data == 0) { mSecureBootPrivate.SecureBootData.EnforceSecureBoot = 0; mSecureBootPrivate.BackupSecureBootData.EnforceSecureBoot = 0; } if (!FeaturePcdGet (PcdH2OCustomizedSecureBootSupported)) { return EFI_SUCCESS; } BufferSize = sizeof (UINT8); Status = gRT->GetVariable ( L"AuditMode", &gEfiGlobalVariableGuid, NULL, &BufferSize, &Data ); if (EFI_ERROR (Status)) { return Status; } mSecureBootPrivate.SecureBootData.AuditMode = Data; mSecureBootPrivate.BackupSecureBootData.AuditMode = Data; BufferSize = sizeof (UINT8); Status = gRT->GetVariable ( L"DeployedMode", &gEfiGlobalVariableGuid, NULL, &BufferSize, &Data ); if (EFI_ERROR (Status)) { return Status; } mSecureBootPrivate.SecureBootData.DeployedMode = Data; mSecureBootPrivate.BackupSecureBootData.DeployedMode = Data; mSecureBootPrivate.SecureBootData.SelectSecureBootMode = GetSecureBootMode (); mSecureBootPrivate.SecureBootData.BackupSelectSecureBootMode = GetSecureBootMode (); return EFI_SUCCESS; } /** Initialize HII information for the FrontPage @retval EFI_SUCCESS Initialize HII information successful **/ EFI_STATUS InitializeSecureBoot ( VOID ) { EFI_STATUS Status; // // Install Device Path Protocol and Config Access protocol to driver handle // Status = gBS->InstallMultipleProtocolInterfaces ( &mSecureBootPrivate.DriverHandle, &gEfiDevicePathProtocolGuid, &mSecureBootHiiVendorDevicePath, &gEfiHiiConfigAccessProtocolGuid, &mSecureBootPrivate.ConfigAccess, NULL ); ASSERT_EFI_ERROR (Status); // // Publish our HII data // mSecureBootPrivate.HiiHandle = HiiAddPackages ( &mSecureBootGuid, mSecureBootPrivate.DriverHandle, SecureBootMgrVfrBin, SecureBootMgrDxeStrings, SecureBootMgrDxeImages, NULL ); if (mSecureBootPrivate.HiiHandle == NULL) { return EFI_OUT_OF_RESOURCES; } Status = gBS->LocateProtocol ( &gH2ODialogProtocolGuid, NULL, (VOID **) &mSecureBootPrivate.H2ODialog ); if (EFI_ERROR(Status)) { return Status; } InitializeListHead (&mSecureBootFsOptionMenu.Head); InitializeListHead (&mSecureBootDirectoryMenu.Head); mSecureBootFileOptionStrDepository = AllocateZeroPool (sizeof (STRING_DEPOSITORY)); mSecureBootSigOptionStrDepository = AllocateZeroPool (sizeof (STRING_DEPOSITORY)); return EFI_SUCCESS; } /** Clear the enroll signature GUID sting in HII database and NV data. @param[in] PrivateData Pointer to SECURE_BOOT_MANAGER_CALLBACK_DATA instance @param[in] EnrollSigGuidStrId String ID of enroll signature GUID @retval EFI_SUCCESS Clear the enroll signature GUID sting successfully. @retval EFI_INVALID_PARAMETER Input parameter is NULL or invalid. **/ STATIC EFI_STATUS ClearEnrollSigGuidStrInHiiDatabase ( IN SECURE_BOOT_MANAGER_CALLBACK_DATA *PrivateData, IN EFI_STRING_ID EnrollSigGuidStrId ) { if (PrivateData == NULL || EnrollSigGuidStrId == 0) { return EFI_INVALID_PARAMETER; } HiiSetString (PrivateData->HiiHandle, EnrollSigGuidStrId, L"", NULL); ZeroMem (PrivateData->SecureBootData.EnrollSigGuidStr, sizeof (PrivateData->SecureBootData.EnrollSigGuidStr)); HiiSetBrowserData ( NULL, NULL, sizeof (SECURE_BOOT_NV_DATA), (UINT8 *) &PrivateData->SecureBootData, NULL ); return EFI_SUCCESS; } /** Update the enroll signature GUID of secure boot manager based on input question ID. @param[in] HiiHandle HII handle @param[in] EnrollSigGuidStrId String ID of enroll signature GUID @param[out] EnrollSigOwnerGuid Returns the enroll signature GUID @retval EFI_SUCCESS Update the enroll signature GUID successfully. @retval EFI_INVALID_PARAMETER Input parameter is NULL or invalid. @retval EFI_NOT_FOUND Failed to get enroll signature GUID string . **/ STATIC EFI_STATUS UpdateEnrollSigOwnerGuid ( IN EFI_HII_HANDLE HiiHandle, IN EFI_STRING_ID EnrollSigGuidStrId, OUT EFI_GUID *EnrollSigOwnerGuid ) { CHAR16 *String; EFI_STATUS Status; if (HiiHandle == NULL || EnrollSigGuidStrId == 0 || EnrollSigOwnerGuid == NULL) { return EFI_INVALID_PARAMETER; } String = HiiGetString (HiiHandle, EnrollSigGuidStrId, NULL); if (String == NULL || *String == CHAR_NULL) { SecureBootSafeFreePool ((VOID **) &String); return EFI_NOT_FOUND; } Status = SecureBootStrToGuid (String, EnrollSigOwnerGuid); if (EFI_ERROR (Status)) { SecureBootShowOkConfirmDlg (STRING_TOKEN (STR_INVALID_GUID_STRING_ERROR_MESSAGE)); } FreePool (String); return Status; } /** Update the state of secure boot manager based on input question ID. @param[in] QuestionId Question ID @param[out] SecureBootMgrState Returns the secure boot manager state @retval EFI_SUCCESS Update secure boot manager state successfully. @retval EFI_INVALID_PARAMETER Input parameter is NULL. @retval EFI_UNSUPPORTED There is no state value for input question ID. **/ STATIC EFI_STATUS UpdateSecureBootMgrState ( IN EFI_QUESTION_ID QuestionId, OUT SECURE_BOOT_MANAGER_STATE *SecureBootMgrState ) { if (SecureBootMgrState == NULL) { return EFI_INVALID_PARAMETER; } switch (QuestionId) { case KEY_PK_FORM: *SecureBootMgrState = PkForm; break; case KEY_KEK_FORM: *SecureBootMgrState = KekForm; break; case KEY_DB_FORM: *SecureBootMgrState = DbForm; break; case KEY_DBX_FORM: *SecureBootMgrState = DbxForm; break; case KEY_DBT_FORM: *SecureBootMgrState = DbtForm; break; case KEY_DBR_FORM: *SecureBootMgrState = DbrForm; break; case KEY_ENROLL_HASH: *SecureBootMgrState = HashImageForm; break; default: return EFI_UNSUPPORTED; } return EFI_SUCCESS; } /** This function allows a caller to extract the current configuration for one or more named elements from the target driver. @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. @param Request A null-terminated Unicode string in format. @param Progress On return, points to a character in the Request string. Points to the string's null terminator if request was successful. Points to the most recent '&' before the first failing name/value pair (or the beginning of the string if the failure is in the first name/value pair) if the request was not successful. @param Results A null-terminated Unicode string in format which has all values filled in for the names in the Request string. String to be allocated by the called function. @retval EFI_SUCCESS The Results is filled with the requested values. @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results. @retval EFI_INVALID_PARAMETER Request is NULL, illegal syntax, or unknown name. @retval EFI_NOT_FOUNDv Routing data doesn't match any storage in this driver. **/ EFI_STATUS EFIAPI SecureBootExtractConfig ( IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, IN CONST EFI_STRING Request, OUT EFI_STRING *Progress, OUT EFI_STRING *Results ) { EFI_STATUS Status; UINTN BufferSize; EFI_STRING ConfigRequestHdr; EFI_STRING ConfigRequest; BOOLEAN AllocatedRequest; UINTN Size; EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting; SECURE_BOOT_MANAGER_CALLBACK_DATA *PrivateData; PrivateData = SECURE_BOOT_CALLBACK_DATA_FROM_THIS (This); if (Progress == NULL || Results == NULL) { return EFI_INVALID_PARAMETER; } *Progress = Request; if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &mSecureBootGuid, SECURE_BOOT_DATA_NAME)) { return EFI_NOT_FOUND; } if (mNeedInitializePrivateData) { mNeedInitializePrivateData = FALSE; InitializeSystemStatus (); } ConfigRequestHdr = NULL; ConfigRequest = NULL; AllocatedRequest = FALSE; Size = 0; // // Convert buffer data to by helper function BlockToConfig() // BufferSize = sizeof (SECURE_BOOT_NV_DATA); ConfigRequest = Request; if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) { // // Request has no request element, construct full request string. // Allocate and fill a buffer large enough to hold the template // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator // ConfigRequestHdr = HiiConstructConfigHdr ( &mSecureBootGuid, SECURE_BOOT_DATA_NAME, mSecureBootPrivate.DriverHandle ); if (ConfigRequestHdr == NULL) { return EFI_OUT_OF_RESOURCES; } Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16); ConfigRequest = AllocateZeroPool (Size); ASSERT (ConfigRequest != NULL); AllocatedRequest = TRUE; UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize); FreePool (ConfigRequestHdr); } Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting); if (EFI_ERROR (Status)) { return Status; } Status = HiiConfigRouting->BlockToConfig ( HiiConfigRouting, ConfigRequest, (UINT8 *) &PrivateData->SecureBootData, BufferSize, Results, Progress ); // // Free the allocated config request string. // if (AllocatedRequest) { FreePool (ConfigRequest); ConfigRequest = NULL; } // // Set Progress string to the original request string. // if (Request == NULL) { *Progress = NULL; } else if (StrStr (Request, L"OFFSET") == NULL) { *Progress = Request + StrLen (Request); } return Status; } /** This function processes the results of changes in configuration. @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. @param Configuration A null-terminated Unicode string in format. @param Progress A pointer to a string filled in with the offset of the most recent '&' before the first failing name/value pair (or the beginning of the string if the failure is in the first name/value pair) or the terminating NULL if all was successful. @retval EFI_SUCCESS The Results is processed successfully. @retval EFI_INVALID_PARAMETER This or Configuration or Progress is NULL. @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. **/ EFI_STATUS EFIAPI SecureBootRouteConfig ( IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, IN CONST EFI_STRING Configuration, OUT EFI_STRING *Progress ) { SECURE_BOOT_MANAGER_CALLBACK_DATA *PrivateData; EFI_STATUS Status; UINTN BufferSize; EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting; if (Configuration == NULL || Progress == NULL || This == NULL) { return EFI_INVALID_PARAMETER; } *Progress = Configuration; if (!HiiIsConfigHdrMatch (Configuration, &mSecureBootGuid, SECURE_BOOT_DATA_NAME)) { return EFI_NOT_FOUND; } PrivateData = SECURE_BOOT_CALLBACK_DATA_FROM_THIS (This); Status = gBS->LocateProtocol (&gEfiHiiConfigRoutingProtocolGuid, NULL, (VOID **) &HiiConfigRouting); if (EFI_ERROR (Status)) { return Status; } BufferSize = sizeof (PrivateData->SecureBootData); HiiConfigRouting->ConfigToBlock ( HiiConfigRouting, Configuration, (UINT8 *) &PrivateData->SecureBootData, &BufferSize, Progress ); return SecureBootSaveChange ((EFI_HII_CONFIG_ACCESS_PROTOCOL *) This); } /** This function processes the results of changes in configuration. @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. @param Action Specifies the type of action taken by the browser. @param QuestionId A unique value which is sent to the original exporting driver so that it can identify the type of data to expect. @param Type The type of value for the question. @param Value A pointer to the data being sent to the original exporting driver. @param ActionRequest On return, points to the action requested by the callback function. @retval EFI_SUCCESS The callback successfully handled the action. @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. @retval EFI_DEVICE_ERROR The variable could not be saved. @retval EFI_UNSUPPORTED The specified Action is not supported by the callback. **/ EFI_STATUS EFIAPI SecureBootCallback ( IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, IN EFI_BROWSER_ACTION Action, IN EFI_QUESTION_ID QuestionId, IN UINT8 Type, IN EFI_IFR_TYPE_VALUE *Value, OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest ) { SECURE_BOOT_MANAGER_CALLBACK_DATA *PrivateData; UINTN BufferSize; EFI_STATUS Status; CHAR16 *StringPtr; EFI_INPUT_KEY Key; if (Action == EFI_BROWSER_ACTION_FORM_OPEN) { if (QuestionId == KEY_ROOT_FORM) { if (mReadyToBootSignaled) { SecureBootShowOkConfirmDlg (STRING_TOKEN (STR_READY_TO_BOOT_SIGNALED_STRING)); } return EFI_SUCCESS; } } if (IsGotoQuestion (QuestionId) && Action == EFI_BROWSER_ACTION_CHANGING) { // // Because form browser only send changing action for EFI_IFR_REF_OP opcode, change action to changed to make // the process of EFI_IFR_REF_OP opcode can be executed. // Action = EFI_BROWSER_ACTION_CHANGED; } if (Action != EFI_BROWSER_ACTION_CHANGED) { // // All other action return unsupported. // return EFI_UNSUPPORTED; } PrivateData = SECURE_BOOT_CALLBACK_DATA_FROM_THIS (This); BufferSize = sizeof (SECURE_BOOT_NV_DATA); Status = HiiGetBrowserData ( NULL, NULL, BufferSize, (UINT8 *) &PrivateData->SecureBootData ); UpdateSecureBootMgrState (QuestionId, &PrivateData->SecureBootMgrState); Status = EFI_SUCCESS; switch (QuestionId) { case KEY_PK_FORM: case KEY_KEK_FORM: case KEY_DB_FORM: case KEY_DBX_FORM: case KEY_DBT_FORM: case KEY_DBR_FORM: SecureBootVarUpdateForm (PrivateData->SecureBootMgrState); break; case KEY_ENROLL_HASH: case KEY_ENROLL_PK: case KEY_ENROLL_KEK: case KEY_ENROLL_DB: case KEY_ENROLL_DBX: case KEY_ENROLL_DBT: case KEY_ENROLL_DBR: Status = InitializeEnrollMenu (PrivateData); break; case KEY_SCAN_ESC: StringPtr = HiiGetString ( PrivateData->HiiHandle, STRING_TOKEN (STR_EXIT_MENU_STRING), NULL ); PrivateData->H2ODialog->ConfirmDialog ( DlgYesNo, FALSE, 0, NULL, &Key, StringPtr ); if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) { *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; } FreePool (StringPtr); break; case KEY_SCAN_F10: StringPtr = HiiGetString ( PrivateData->HiiHandle, STRING_TOKEN (STR_SAVE_CHANGE_STRING), NULL ); PrivateData->H2ODialog->ConfirmDialog ( DlgYesNo, FALSE, 0, NULL, &Key, StringPtr ); if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) { SecureBootSaveChange ((EFI_HII_CONFIG_ACCESS_PROTOCOL *) This); SecureBootShowOkConfirmDlg (STRING_TOKEN (STR_OPERATION_FINISH_MESSAGE)); gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); } FreePool (StringPtr); break; default: if (QuestionId >= KEY_DELETE_SIGNATURE_QUESTION_BASE && QuestionId < KEY_DELETE_SIGNATURE_QUESTION_BASE + KEY_DELETE_SIGNATURE_QUESTION_LENGTH) { Key.UnicodeChar = CHAR_CARRIAGE_RETURN; StringPtr = HiiGetString ( PrivateData->HiiHandle, STRING_TOKEN (STR_DELETE_SIGNATURE_CONFIRM_MESSAGE), NULL ); if (StringPtr != NULL) { PrivateData->H2ODialog->ConfirmDialog ( DlgYesNo, FALSE, 0, NULL, &Key, StringPtr ); FreePool (StringPtr); } if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) { Status = SecureBootVarDeleteSignature ( PrivateData->SecureBootMgrState, QuestionId - KEY_DELETE_SIGNATURE_QUESTION_BASE ); } break; } if (QuestionId >= ENROLL_FILE_OPTION_OFFSET) { if (Type == EFI_IFR_TYPE_STRING) { // // Update enroll signature GUID and then clear string in HII database to prevent from displaying GUID string // on the value of enroll file item. // Status = UpdateEnrollSigOwnerGuid (PrivateData->HiiHandle, Value->string, &PrivateData->EmEnrollSigOwnerGuid); ClearEnrollSigGuidStrInHiiDatabase (PrivateData, Value->string); if (EFI_ERROR (Status)) { break; } } if (UpdateEmFileExplorer (PrivateData, QuestionId)) { PrivateData->EmDisplayContext = EM_UNKNOWN_CONTEXT; UpdateEmFileExplorer (PrivateData, 0); } } break; } return Status; } /** Provide user interface to control secure boot relative features **/ VOID InternalCallSecureBootMgr ( VOID ) { EFI_BROWSER_ACTION_REQUEST ActionRequest; EFI_HII_HANDLE HiiHandle; EFI_STATUS Status; EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2; CHAR16 *NewString; EFI_INPUT_KEY HotKey; EFI_FORM_BROWSER_EXTENSION_PROTOCOL *FormBrowserEx; if (mReadyToBootSignaled) { SecureBootShowOkConfirmDlg (STRING_TOKEN (STR_READY_TO_BOOT_SIGNALED_STRING)); return; } if (IsPasswordExist () && NeedSysPasswordCheck ()) { Status = CheckPassword (); if (!EFI_ERROR (Status)) { DisableSysPasswordCheck (); } } else { UnlockPasswordState (NULL, 0); } gBS->RestoreTPL (TPL_APPLICATION); HiiHandle = mSecureBootPrivate.HiiHandle; ActionRequest = EFI_BROWSER_ACTION_REQUEST_NONE; Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2); ASSERT_EFI_ERROR (Status); Status = gBS->LocateProtocol (&gEdkiiFormBrowserExProtocolGuid, NULL, (VOID **) &FormBrowserEx); if (!EFI_ERROR (Status)) { // // First unregister the default hot key F9 and F10. // HotKey.UnicodeChar = CHAR_NULL; HotKey.ScanCode = SCAN_F9; FormBrowserEx->RegisterHotKey (&HotKey, 0, 0, NULL); HotKey.ScanCode = SCAN_F10; FormBrowserEx->RegisterHotKey (&HotKey, 0, 0, NULL); // // Register the default HotKey F9 and F10 again. // HotKey.ScanCode = SCAN_F10; NewString = HiiGetString (HiiHandle, STRING_TOKEN (STR_SAVE_CHANGE_STRING), NULL); ASSERT (NewString != NULL); FormBrowserEx->RegisterHotKey (&HotKey, BROWSER_ACTION_SUBMIT | BROWSER_ACTION_EXIT, 0, NewString); } Status = FormBrowser2->SendForm ( FormBrowser2, &HiiHandle, 1, &mSecureBootGuid, 0, NULL, &ActionRequest ); LockPasswordState (); if (ActionRequest == EFI_BROWSER_ACTION_REQUEST_RESET) { EnableResetRequired (); gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); } return; } /** Enter secure boot manager. @param[in] This Protocol instance pointer. @param[in] FilePath The device specific path of the file to load. @param[in] BootPolicy If TRUE, indicates that the request originates from the boot manager is attempting to load FilePath as a boot selection. If FALSE, then FilePath must match as exact file to be loaded. @param[in, out] BufferSize On input the size of Buffer in bytes. On output with a return code of EFI_SUCCESS, the amount of data transferred to Buffer. On output with a return code of EFI_BUFFER_TOO_SMALL, the size of Buffer required to retrieve the requested file. @param[in] Buffer The memory buffer to transfer the file to. IF Buffer is NULL, then no the size of the requested file is returned in BufferSize. @retval EFI_NOT_FOUND Always return not found. **/ EFI_STATUS EFIAPI SecureBootMgrLoadFile ( IN EFI_LOAD_FILE_PROTOCOL *This, IN EFI_DEVICE_PATH_PROTOCOL *FilePath, IN BOOLEAN BootPolicy, IN OUT UINTN *BufferSize, IN VOID *Buffer OPTIONAL ) { if (mSecureBootPrivate.HiiHandle != NULL) { InternalCallSecureBootMgr (); } return EFI_NOT_FOUND; } /** Initialize HII data. @param[in] Event A pointer to the Event that triggered the callback. @param[in] Handle Checkpoint handle. **/ VOID EFIAPI SecureBootMgrCpInitNotifyFunc ( IN EFI_EVENT Event, IN H2O_CP_HANDLE Handle ) { H2OCpUnregisterHandler (Handle); InitializeSecureBoot (); } EFI_STATUS EFIAPI SecureBootMgrSendForm ( IN CONST EFI_FORM_BROWSER2_PROTOCOL *This, IN EFI_HII_HANDLE *Handles, IN UINTN HandleCount, IN EFI_GUID *FormSetGuid OPTIONAL, IN UINT16 FormId OPTIONAL, IN CONST EFI_SCREEN_DESCRIPTOR *ScreenDimensions OPTIONAL, OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest OPTIONAL ) { mNeedInitializePrivateData = TRUE; return mOrgSendForm ( This, Handles, HandleCount, FormSetGuid, FormId, ScreenDimensions, ActionRequest ); } /** Hook SendForm function of FormBrowser2 protocol. @param[in] Event Event whose notification function is being invoked. @param[in] Context Pointer to the notification function's context. **/ VOID EFIAPI SecureBootMgrFormBrowser2NotifyFn ( IN EFI_EVENT Event, IN VOID *Context ) { EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2; EFI_STATUS Status; Status = gBS->LocateProtocol (&gEfiFormBrowser2ProtocolGuid, NULL, (VOID **) &FormBrowser2); if (EFI_ERROR (Status)) { return; } mOrgSendForm = FormBrowser2->SendForm; FormBrowser2->SendForm = SecureBootMgrSendForm; gBS->CloseEvent (Event); } /** Ready to boot callback function to change mReadyToBootSignaled state. @param[in] Event Event whose notification function is being invoked. @param[in] Context Pointer to the notification function's context. **/ VOID SecureBootMgrReadyToBootCallback ( IN EFI_EVENT Event, IN VOID *Context ) { gBS->CloseEvent (Event); mReadyToBootSignaled = TRUE; } /** Register H2OBdsCpInit notification to initialize HII data. Install the instance of the EFI_LOAD_FILE_PROTOCOL and EFI_DEVICE_PATH_PROTOCOL on new handle. @param[in] ImageHandle The firmware allocated handle for the EFI image. @param[in] SystemTable A pointer to the EFI System Table. @retval EFI_SUCCESS Install protocol successfully. @retval other Fail to install protocol instance. **/ EFI_STATUS EFIAPI SecureBootMgrEntry ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { H2O_CP_HANDLE CpHandle; EFI_HANDLE DriverHandle; EFI_STATUS Status; EFI_EVENT Event; VOID *Registration; if (FeaturePcdGet (PcdH2OBdsCpInitSupported)) { Status = H2OCpRegisterHandler ( &gH2OBdsCpInitGuid, SecureBootMgrCpInitNotifyFunc, H2O_CP_MEDIUM, &CpHandle ); if (EFI_ERROR (Status)) { DEBUG_CP ((DEBUG_ERROR, "Checkpoint Register Fail: %g (%r)\n", &gH2OBdsCpInitGuid, Status)); return Status; } DEBUG_CP ((DEBUG_INFO, "Checkpoint Registered: %g (%r)\n", &gH2OBdsCpInitGuid, Status)); } EfiCreateEventReadyToBootEx (TPL_CALLBACK, SecureBootMgrReadyToBootCallback, NULL, &Event); EfiCreateProtocolNotifyEvent ( &gEfiFormBrowser2ProtocolGuid, TPL_CALLBACK, SecureBootMgrFormBrowser2NotifyFn, NULL, &Registration ); DriverHandle = NULL; Status = gBS->InstallMultipleProtocolInterfaces ( &DriverHandle, &gEfiDevicePathProtocolGuid, &gH2OSecureBootMgrDevicePath, &gEfiLoadFileProtocolGuid, &mSecureBootMgrLoadFile, NULL ); ASSERT_EFI_ERROR (Status); return Status; } /** Initial communication buffer header. @param[in] CommunicationBuffer Input communication buffer. @param[in] CommunicationBufferSize Size of communication buffer in bytes. **/ STATIC VOID InitCommunicationBufferHeader ( IN VOID *CommunicationBuffer, IN UINTN CommunicationBufferSize ) { EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader; if (CommunicationBuffer == NULL || CommunicationBufferSize < SMM_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VAR_BUFFER)) { return; } SmmCommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *) CommunicationBuffer; ZeroMem (SmmCommunicateHeader, SMM_COMMUNICATE_HEADER_SIZE + sizeof (SMM_VAR_BUFFER)); CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gEfiSmmVariableProtocolGuid); SmmCommunicateHeader->MessageLength = SMM_COMMUNICATE_BUFFER_SIZE; } /** Using runtime data type memory to communicate information with variable driver in SMM. @param[in] InputBuff Buffer to communicate information with variable driver. @param[in] DataSize Size of the InPutBuff in bytes. @param[in] SubFunNum sub function number. @retval EFI_SUCCESS Communicate information with variable driver successfully. @retval EFI_OUT_OF_RESOURCES There are not enough memory to communicate information. **/ EFI_STATUS SmmSecureBootCallWithRuntimeMemory ( IN UINT8 *InputBuff, IN UINTN DataSize, IN UINT8 SubFunNum ) { NON_VOLATILE_VARIABLE_PROTOCOL *NonVolatileVariableProtocol; VOID *VariableBuffer; UINTN VariableBufferSize; EFI_STATUS Status; EFI_TPL Tpl; EFI_SMM_COMMUNICATION_PROTOCOL *SmmCommunication; SMM_VAR_BUFFER *SmmVarBuffer; Status = gBS->LocateProtocol ( &gEfiNonVolatileVariableProtocolGuid, NULL, (VOID **) &NonVolatileVariableProtocol ); if (EFI_ERROR (Status)) { return EFI_OUT_OF_RESOURCES; } Status = gBS->LocateProtocol ( &gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &SmmCommunication ); if (EFI_ERROR (Status)) { return EFI_OUT_OF_RESOURCES; } Status = NonVolatileVariableProtocol->GetRuntimeVariableBuffer (&VariableBuffer, &VariableBufferSize); if (EFI_ERROR (Status) || VariableBufferSize < DataSize) { return EFI_OUT_OF_RESOURCES; } // // Because the VariableBuffer will be used in many places, raise TPL to prevent from the data in this // buffer is destroyed in other events. // Tpl = gBS->RaiseTPL (TPL_NOTIFY); InitCommunicationBufferHeader (VariableBuffer, VariableBufferSize); SmmVarBuffer = (SMM_VAR_BUFFER *)((UINTN) VariableBuffer + SMM_COMMUNICATE_HEADER_SIZE); SmmVarBuffer->DataSize = DataSize; SmmVarBuffer->AccessType = SubFunNum; SmmVarBuffer->Status = EFI_UNSUPPORTED; CopyMem (SmmVarBuffer + 1, InputBuff, DataSize); Status = SmmCommunication->Communicate (SmmCommunication, VariableBuffer, &VariableBufferSize); gBS->RestoreTPL (Tpl); return EFI_SUCCESS; }