2 HII Config Access protocol implementation of SecureBoot configuration module.
4 Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "SecureBootConfigImpl.h"
17 CHAR16 mSecureBootStorageName
[] = L
"SECUREBOOT_CONFIGURATION";
19 SECUREBOOT_CONFIG_PRIVATE_DATA mSecureBootConfigPrivateDateTemplate
= {
20 SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE
,
22 SecureBootExtractConfig
,
23 SecureBootRouteConfig
,
28 HII_VENDOR_DEVICE_PATH mSecureBootHiiVendorDevicePath
= {
34 (UINT8
) (sizeof (VENDOR_DEVICE_PATH
)),
35 (UINT8
) ((sizeof (VENDOR_DEVICE_PATH
)) >> 8)
38 SECUREBOOT_CONFIG_FORM_SET_GUID
42 END_ENTIRE_DEVICE_PATH_SUBTYPE
,
44 (UINT8
) (END_DEVICE_PATH_LENGTH
),
45 (UINT8
) ((END_DEVICE_PATH_LENGTH
) >> 8)
51 BOOLEAN mIsEnterSecureBootForm
= FALSE
;
54 // OID ASN.1 Value for Hash Algorithms
56 UINT8 mHashOidValue
[] = {
57 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, // OBJ_md5
58 0x2B, 0x0E, 0x03, 0x02, 0x1A, // OBJ_sha1
59 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, // OBJ_sha224
60 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, // OBJ_sha256
61 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, // OBJ_sha384
62 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, // OBJ_sha512
65 HASH_TABLE mHash
[] = {
66 { L
"SHA1", 20, &mHashOidValue
[8], 5, Sha1GetContextSize
, Sha1Init
, Sha1Update
, Sha1Final
},
67 { L
"SHA224", 28, &mHashOidValue
[13], 9, NULL
, NULL
, NULL
, NULL
},
68 { L
"SHA256", 32, &mHashOidValue
[22], 9, Sha256GetContextSize
,Sha256Init
, Sha256Update
, Sha256Final
},
69 { L
"SHA384", 48, &mHashOidValue
[31], 9, NULL
, NULL
, NULL
, NULL
},
70 { L
"SHA512", 64, &mHashOidValue
[40], 9, NULL
, NULL
, NULL
, NULL
}
74 // Variable Definitions
76 UINT32 mPeCoffHeaderOffset
= 0;
77 WIN_CERTIFICATE
*mCertificate
= NULL
;
78 IMAGE_TYPE mImageType
;
79 UINT8
*mImageBase
= NULL
;
81 UINT8 mImageDigest
[MAX_DIGEST_SIZE
];
82 UINTN mImageDigestSize
;
84 EFI_IMAGE_SECURITY_DATA_DIRECTORY
*mSecDataDir
= NULL
;
85 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader
;
88 // Possible DER-encoded certificate file suffixes, end with NULL pointer.
90 CHAR16
* mDerEncodedSuffix
[] = {
96 CHAR16
* mSupportX509Suffix
= L
"*.cer/der/crt";
99 This code checks if the FileSuffix is one of the possible DER-encoded certificate suffix.
101 @param[in] FileSuffix The suffix of the input certificate file
103 @retval TRUE It's a DER-encoded certificate.
104 @retval FALSE It's NOT a DER-encoded certificate.
108 IsDerEncodeCertificate (
109 IN CONST CHAR16
*FileSuffix
113 for (Index
= 0; mDerEncodedSuffix
[Index
] != NULL
; Index
++) {
114 if (StrCmp (FileSuffix
, mDerEncodedSuffix
[Index
]) == 0) {
122 Set Secure Boot option into variable space.
124 @param[in] VarValue The option of Secure Boot.
126 @retval EFI_SUCCESS The operation is finished successfully.
127 @retval Others Other errors as indicated.
131 SaveSecureBootVariable (
137 Status
= gRT
->SetVariable (
138 EFI_SECURE_BOOT_ENABLE_NAME
,
139 &gEfiSecureBootEnableDisableGuid
,
140 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
148 Create a time based data payload by concatenating the EFI_VARIABLE_AUTHENTICATION_2
149 descriptor with the input data. NO authentication is required in this function.
151 @param[in, out] DataSize On input, the size of Data buffer in bytes.
152 On output, the size of data returned in Data
154 @param[in, out] Data On input, Pointer to data buffer to be wrapped or
155 pointer to NULL to wrap an empty payload.
156 On output, Pointer to the new payload date buffer allocated from pool,
157 it's caller's responsibility to free the memory when finish using it.
159 @retval EFI_SUCCESS Create time based payload successfully.
160 @retval EFI_OUT_OF_RESOURCES There are not enough memory resourses to create time based payload.
161 @retval EFI_INVALID_PARAMETER The parameter is invalid.
162 @retval Others Unexpected error happens.
166 CreateTimeBasedPayload (
167 IN OUT UINTN
*DataSize
,
175 EFI_VARIABLE_AUTHENTICATION_2
*DescriptorData
;
176 UINTN DescriptorSize
;
179 if (Data
== NULL
|| DataSize
== NULL
) {
180 return EFI_INVALID_PARAMETER
;
184 // In Setup mode or Custom mode, the variable does not need to be signed but the
185 // parameters to the SetVariable() call still need to be prepared as authenticated
186 // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate
190 PayloadSize
= *DataSize
;
192 DescriptorSize
= OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2
, AuthInfo
) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID
, CertData
);
193 NewData
= (UINT8
*) AllocateZeroPool (DescriptorSize
+ PayloadSize
);
194 if (NewData
== NULL
) {
195 return EFI_OUT_OF_RESOURCES
;
198 if ((Payload
!= NULL
) && (PayloadSize
!= 0)) {
199 CopyMem (NewData
+ DescriptorSize
, Payload
, PayloadSize
);
202 DescriptorData
= (EFI_VARIABLE_AUTHENTICATION_2
*) (NewData
);
204 ZeroMem (&Time
, sizeof (EFI_TIME
));
205 Status
= gRT
->GetTime (&Time
, NULL
);
206 if (EFI_ERROR (Status
)) {
215 CopyMem (&DescriptorData
->TimeStamp
, &Time
, sizeof (EFI_TIME
));
217 DescriptorData
->AuthInfo
.Hdr
.dwLength
= OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID
, CertData
);
218 DescriptorData
->AuthInfo
.Hdr
.wRevision
= 0x0200;
219 DescriptorData
->AuthInfo
.Hdr
.wCertificateType
= WIN_CERT_TYPE_EFI_GUID
;
220 CopyGuid (&DescriptorData
->AuthInfo
.CertType
, &gEfiCertPkcs7Guid
);
222 if (Payload
!= NULL
) {
226 *DataSize
= DescriptorSize
+ PayloadSize
;
232 Internal helper function to delete a Variable given its name and GUID, NO authentication
235 @param[in] VariableName Name of the Variable.
236 @param[in] VendorGuid GUID of the Variable.
238 @retval EFI_SUCCESS Variable deleted successfully.
239 @retval Others The driver failed to start the device.
244 IN CHAR16
*VariableName
,
245 IN EFI_GUID
*VendorGuid
254 GetVariable2 (VariableName
, VendorGuid
, &Variable
, NULL
);
255 if (Variable
== NULL
) {
262 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_BOOTSERVICE_ACCESS
263 | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
265 Status
= CreateTimeBasedPayload (&DataSize
, &Data
);
266 if (EFI_ERROR (Status
)) {
267 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
271 Status
= gRT
->SetVariable (
286 Set the platform secure boot mode into "Custom" or "Standard" mode.
288 @param[in] SecureBootMode New secure boot mode: STANDARD_SECURE_BOOT_MODE or
289 CUSTOM_SECURE_BOOT_MODE.
291 @return EFI_SUCCESS The platform has switched to the special mode successfully.
292 @return other Fail to operate the secure boot mode.
297 IN UINT8 SecureBootMode
300 return gRT
->SetVariable (
301 EFI_CUSTOM_MODE_NAME
,
302 &gEfiCustomModeEnableGuid
,
303 EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
310 Generate the PK signature list from the X509 Certificate storing file (.cer)
312 @param[in] X509File FileHandle of X509 Certificate storing file.
313 @param[out] PkCert Point to the data buffer to store the signature list.
315 @return EFI_UNSUPPORTED Unsupported Key Length.
316 @return EFI_OUT_OF_RESOURCES There are not enough memory resourses to form the signature list.
320 CreatePkX509SignatureList (
321 IN EFI_FILE_HANDLE X509File
,
322 OUT EFI_SIGNATURE_LIST
**PkCert
328 EFI_SIGNATURE_DATA
*PkCertData
;
334 Status
= ReadFileContent (X509File
, (VOID
**) &X509Data
, &X509DataSize
, 0);
335 if (EFI_ERROR (Status
)) {
338 ASSERT (X509Data
!= NULL
);
341 // Allocate space for PK certificate list and initialize it.
342 // Create PK database entry with SignatureHeaderSize equals 0.
344 *PkCert
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (
345 sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1
348 if (*PkCert
== NULL
) {
349 Status
= EFI_OUT_OF_RESOURCES
;
353 (*PkCert
)->SignatureListSize
= (UINT32
) (sizeof(EFI_SIGNATURE_LIST
)
354 + sizeof(EFI_SIGNATURE_DATA
) - 1
356 (*PkCert
)->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
357 (*PkCert
)->SignatureHeaderSize
= 0;
358 CopyGuid (&(*PkCert
)->SignatureType
, &gEfiCertX509Guid
);
359 PkCertData
= (EFI_SIGNATURE_DATA
*) ((UINTN
)(*PkCert
)
360 + sizeof(EFI_SIGNATURE_LIST
)
361 + (*PkCert
)->SignatureHeaderSize
);
362 CopyGuid (&PkCertData
->SignatureOwner
, &gEfiGlobalVariableGuid
);
364 // Fill the PK database with PKpub data from X509 certificate file.
366 CopyMem (&(PkCertData
->SignatureData
[0]), X509Data
, X509DataSize
);
370 if (X509Data
!= NULL
) {
374 if (EFI_ERROR(Status
) && *PkCert
!= NULL
) {
383 Enroll new PK into the System without original PK's authentication.
385 The SignatureOwner GUID will be the same with PK's vendorguid.
387 @param[in] PrivateData The module's private data.
389 @retval EFI_SUCCESS New PK enrolled successfully.
390 @retval EFI_INVALID_PARAMETER The parameter is invalid.
391 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
396 IN SECUREBOOT_CONFIG_PRIVATE_DATA
* Private
402 EFI_SIGNATURE_LIST
*PkCert
;
406 if (Private
->FileContext
->FileName
== NULL
) {
407 return EFI_INVALID_PARAMETER
;
412 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
413 if (EFI_ERROR (Status
)) {
418 // Parse the file's postfix. Only support DER encoded X.509 certificate files.
420 NameLength
= StrLen (Private
->FileContext
->FileName
);
421 if (NameLength
<= 4) {
422 return EFI_INVALID_PARAMETER
;
424 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
425 if (!IsDerEncodeCertificate(FilePostFix
)) {
426 DEBUG ((EFI_D_ERROR
, "Unsupported file type, only DER encoded certificate (%s) is supported.", mSupportX509Suffix
));
427 return EFI_INVALID_PARAMETER
;
429 DEBUG ((EFI_D_INFO
, "FileName= %s\n", Private
->FileContext
->FileName
));
430 DEBUG ((EFI_D_INFO
, "FilePostFix = %s\n", FilePostFix
));
433 // Prase the selected PK file and generature PK certificate list.
435 Status
= CreatePkX509SignatureList (
436 Private
->FileContext
->FHandle
,
439 if (EFI_ERROR (Status
)) {
442 ASSERT (PkCert
!= NULL
);
445 // Set Platform Key variable.
447 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
448 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
449 DataSize
= PkCert
->SignatureListSize
;
450 Status
= CreateTimeBasedPayload (&DataSize
, (UINT8
**) &PkCert
);
451 if (EFI_ERROR (Status
)) {
452 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
456 Status
= gRT
->SetVariable(
457 EFI_PLATFORM_KEY_NAME
,
458 &gEfiGlobalVariableGuid
,
463 if (EFI_ERROR (Status
)) {
464 if (Status
== EFI_OUT_OF_RESOURCES
) {
465 DEBUG ((EFI_D_ERROR
, "Enroll PK failed with out of resource.\n"));
472 if (PkCert
!= NULL
) {
476 if (Private
->FileContext
->FHandle
!= NULL
) {
477 CloseFile (Private
->FileContext
->FHandle
);
478 Private
->FileContext
->FHandle
= NULL
;
485 Remove the PK variable.
487 @retval EFI_SUCCESS Delete PK successfully.
488 @retval Others Could not allow to delete PK.
498 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
499 if (EFI_ERROR (Status
)) {
503 Status
= DeleteVariable (
504 EFI_PLATFORM_KEY_NAME
,
505 &gEfiGlobalVariableGuid
511 Enroll a new KEK item from public key storing file (*.pbk).
513 @param[in] PrivateData The module's private data.
515 @retval EFI_SUCCESS New KEK enrolled successfully.
516 @retval EFI_INVALID_PARAMETER The parameter is invalid.
517 @retval EFI_UNSUPPORTED Unsupported command.
518 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
523 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
529 EFI_SIGNATURE_LIST
*KekSigList
;
532 CPL_KEY_INFO
*KeyInfo
;
533 EFI_SIGNATURE_DATA
*KEKSigData
;
534 UINTN KekSigListSize
;
549 // Form the KeKpub certificate list into EFI_SIGNATURE_LIST type.
550 // First, We have to parse out public key data from the pbk key file.
552 Status
= ReadFileContent (
553 Private
->FileContext
->FHandle
,
558 if (EFI_ERROR (Status
)) {
561 ASSERT (KeyBlob
!= NULL
);
562 KeyInfo
= (CPL_KEY_INFO
*) KeyBlob
;
563 if (KeyInfo
->KeyLengthInBits
/ 8 != WIN_CERT_UEFI_RSA2048_SIZE
) {
564 DEBUG ((DEBUG_ERROR
, "Unsupported key length, Only RSA2048 is supported.\n"));
565 Status
= EFI_UNSUPPORTED
;
570 // Convert the Public key to fix octet string format represented in RSA PKCS#1.
572 KeyLenInBytes
= KeyInfo
->KeyLengthInBits
/ 8;
573 KeyBuffer
= AllocateZeroPool (KeyLenInBytes
);
574 if (KeyBuffer
== NULL
) {
575 Status
= EFI_OUT_OF_RESOURCES
;
579 (UINTN
*) (KeyBlob
+ sizeof (CPL_KEY_INFO
)),
580 KeyLenInBytes
/ sizeof (UINTN
),
584 CopyMem(KeyBlob
+ sizeof(CPL_KEY_INFO
), KeyBuffer
, KeyLenInBytes
);
587 // Form an new EFI_SIGNATURE_LIST.
589 KekSigListSize
= sizeof(EFI_SIGNATURE_LIST
)
590 + sizeof(EFI_SIGNATURE_DATA
) - 1
591 + WIN_CERT_UEFI_RSA2048_SIZE
;
593 KekSigList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (KekSigListSize
);
594 if (KekSigList
== NULL
) {
595 Status
= EFI_OUT_OF_RESOURCES
;
599 KekSigList
->SignatureListSize
= sizeof(EFI_SIGNATURE_LIST
)
600 + sizeof(EFI_SIGNATURE_DATA
) - 1
601 + WIN_CERT_UEFI_RSA2048_SIZE
;
602 KekSigList
->SignatureHeaderSize
= 0;
603 KekSigList
->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + WIN_CERT_UEFI_RSA2048_SIZE
;
604 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertRsa2048Guid
);
606 KEKSigData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)KekSigList
+ sizeof(EFI_SIGNATURE_LIST
));
607 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
609 KEKSigData
->SignatureData
,
610 KeyBlob
+ sizeof(CPL_KEY_INFO
),
611 WIN_CERT_UEFI_RSA2048_SIZE
615 // Check if KEK entry has been already existed.
616 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
617 // new KEK to original variable.
619 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
620 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
621 Status
= CreateTimeBasedPayload (&KekSigListSize
, (UINT8
**) &KekSigList
);
622 if (EFI_ERROR (Status
)) {
623 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
627 Status
= gRT
->GetVariable(
628 EFI_KEY_EXCHANGE_KEY_NAME
,
629 &gEfiGlobalVariableGuid
,
634 if (Status
== EFI_BUFFER_TOO_SMALL
) {
635 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
636 } else if (Status
!= EFI_NOT_FOUND
) {
641 // Done. Now we have formed the correct KEKpub database item, just set it into variable storage,
643 Status
= gRT
->SetVariable(
644 EFI_KEY_EXCHANGE_KEY_NAME
,
645 &gEfiGlobalVariableGuid
,
650 if (EFI_ERROR (Status
)) {
656 CloseFile (Private
->FileContext
->FHandle
);
657 Private
->FileContext
->FHandle
= NULL
;
658 Private
->FileContext
->FileName
= NULL
;
660 if (Private
->SignatureGUID
!= NULL
) {
661 FreePool (Private
->SignatureGUID
);
662 Private
->SignatureGUID
= NULL
;
665 if (KeyBlob
!= NULL
) {
668 if (KeyBuffer
!= NULL
) {
669 FreePool (KeyBuffer
);
671 if (KekSigList
!= NULL
) {
672 FreePool (KekSigList
);
679 Enroll a new KEK item from X509 certificate file.
681 @param[in] PrivateData The module's private data.
683 @retval EFI_SUCCESS New X509 is enrolled successfully.
684 @retval EFI_INVALID_PARAMETER The parameter is invalid.
685 @retval EFI_UNSUPPORTED Unsupported command.
686 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
691 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
697 EFI_SIGNATURE_DATA
*KEKSigData
;
698 EFI_SIGNATURE_LIST
*KekSigList
;
700 UINTN KekSigListSize
;
710 Status
= ReadFileContent (
711 Private
->FileContext
->FHandle
,
716 if (EFI_ERROR (Status
)) {
719 ASSERT (X509Data
!= NULL
);
721 KekSigListSize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
722 KekSigList
= (EFI_SIGNATURE_LIST
*) AllocateZeroPool (KekSigListSize
);
723 if (KekSigList
== NULL
) {
724 Status
= EFI_OUT_OF_RESOURCES
;
729 // Fill Certificate Database parameters.
731 KekSigList
->SignatureListSize
= (UINT32
) KekSigListSize
;
732 KekSigList
->SignatureHeaderSize
= 0;
733 KekSigList
->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
734 CopyGuid (&KekSigList
->SignatureType
, &gEfiCertX509Guid
);
736 KEKSigData
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) KekSigList
+ sizeof (EFI_SIGNATURE_LIST
));
737 CopyGuid (&KEKSigData
->SignatureOwner
, Private
->SignatureGUID
);
738 CopyMem (KEKSigData
->SignatureData
, X509Data
, X509DataSize
);
741 // Check if KEK been already existed.
742 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
743 // new kek to original variable
745 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
746 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
747 Status
= CreateTimeBasedPayload (&KekSigListSize
, (UINT8
**) &KekSigList
);
748 if (EFI_ERROR (Status
)) {
749 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
753 Status
= gRT
->GetVariable(
754 EFI_KEY_EXCHANGE_KEY_NAME
,
755 &gEfiGlobalVariableGuid
,
760 if (Status
== EFI_BUFFER_TOO_SMALL
) {
761 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
762 } else if (Status
!= EFI_NOT_FOUND
) {
766 Status
= gRT
->SetVariable(
767 EFI_KEY_EXCHANGE_KEY_NAME
,
768 &gEfiGlobalVariableGuid
,
773 if (EFI_ERROR (Status
)) {
779 CloseFile (Private
->FileContext
->FHandle
);
780 Private
->FileContext
->FileName
= NULL
;
781 Private
->FileContext
->FHandle
= NULL
;
783 if (Private
->SignatureGUID
!= NULL
) {
784 FreePool (Private
->SignatureGUID
);
785 Private
->SignatureGUID
= NULL
;
788 if (KekSigList
!= NULL
) {
789 FreePool (KekSigList
);
796 Enroll new KEK into the System without PK's authentication.
797 The SignatureOwner GUID will be Private->SignatureGUID.
799 @param[in] PrivateData The module's private data.
801 @retval EFI_SUCCESS New KEK enrolled successful.
802 @retval EFI_INVALID_PARAMETER The parameter is invalid.
803 @retval others Fail to enroll KEK data.
807 EnrollKeyExchangeKey (
808 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
815 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
816 return EFI_INVALID_PARAMETER
;
819 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
820 if (EFI_ERROR (Status
)) {
825 // Parse the file's postfix. Supports DER-encoded X509 certificate,
826 // and .pbk as RSA public key file.
828 NameLength
= StrLen (Private
->FileContext
->FileName
);
829 if (NameLength
<= 4) {
830 return EFI_INVALID_PARAMETER
;
832 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
833 if (IsDerEncodeCertificate(FilePostFix
)) {
834 return EnrollX509ToKek (Private
);
835 } else if (CompareMem (FilePostFix
, L
".pbk",4) == 0) {
836 return EnrollRsa2048ToKek (Private
);
838 return EFI_INVALID_PARAMETER
;
843 Enroll a new X509 certificate into Signature Database (DB or DBX) without
844 KEK's authentication.
846 @param[in] PrivateData The module's private data.
847 @param[in] VariableName Variable name of signature database, must be
848 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
850 @retval EFI_SUCCESS New X509 is enrolled successfully.
851 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
856 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
857 IN CHAR16
*VariableName
863 EFI_SIGNATURE_LIST
*SigDBCert
;
864 EFI_SIGNATURE_DATA
*SigDBCertData
;
875 SigDBCertData
= NULL
;
878 Status
= ReadFileContent (
879 Private
->FileContext
->FHandle
,
884 if (EFI_ERROR (Status
)) {
887 ASSERT (X509Data
!= NULL
);
889 SigDBSize
= sizeof(EFI_SIGNATURE_LIST
) + sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
;
891 Data
= AllocateZeroPool (SigDBSize
);
893 Status
= EFI_OUT_OF_RESOURCES
;
898 // Fill Certificate Database parameters.
900 SigDBCert
= (EFI_SIGNATURE_LIST
*) Data
;
901 SigDBCert
->SignatureListSize
= (UINT32
) SigDBSize
;
902 SigDBCert
->SignatureHeaderSize
= 0;
903 SigDBCert
->SignatureSize
= (UINT32
) (sizeof(EFI_SIGNATURE_DATA
) - 1 + X509DataSize
);
904 CopyGuid (&SigDBCert
->SignatureType
, &gEfiCertX509Guid
);
906 SigDBCertData
= (EFI_SIGNATURE_DATA
*) ((UINT8
* ) SigDBCert
+ sizeof (EFI_SIGNATURE_LIST
));
907 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
908 CopyMem ((UINT8
* ) (SigDBCertData
->SignatureData
), X509Data
, X509DataSize
);
911 // Check if signature database entry has been already existed.
912 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
913 // new signature data to original variable
915 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
916 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
917 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**) &Data
);
918 if (EFI_ERROR (Status
)) {
919 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
923 Status
= gRT
->GetVariable(
925 &gEfiImageSecurityDatabaseGuid
,
930 if (Status
== EFI_BUFFER_TOO_SMALL
) {
931 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
932 } else if (Status
!= EFI_NOT_FOUND
) {
936 Status
= gRT
->SetVariable(
938 &gEfiImageSecurityDatabaseGuid
,
943 if (EFI_ERROR (Status
)) {
949 CloseFile (Private
->FileContext
->FHandle
);
950 Private
->FileContext
->FileName
= NULL
;
951 Private
->FileContext
->FHandle
= NULL
;
953 if (Private
->SignatureGUID
!= NULL
) {
954 FreePool (Private
->SignatureGUID
);
955 Private
->SignatureGUID
= NULL
;
962 if (X509Data
!= NULL
) {
970 Load PE/COFF image information into internal buffer and check its validity.
972 @retval EFI_SUCCESS Successful
973 @retval EFI_UNSUPPORTED Invalid PE/COFF file
974 @retval EFI_ABORTED Serious error occurs, like file I/O error etc.
982 EFI_IMAGE_DOS_HEADER
*DosHdr
;
983 EFI_IMAGE_NT_HEADERS32
*NtHeader32
;
984 EFI_IMAGE_NT_HEADERS64
*NtHeader64
;
989 // Read the Dos header
991 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)(mImageBase
);
992 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
)
995 // DOS image header is present,
996 // So read the PE header after the DOS image header
998 mPeCoffHeaderOffset
= DosHdr
->e_lfanew
;
1002 mPeCoffHeaderOffset
= 0;
1006 // Read PE header and check the signature validity and machine compatibility
1008 NtHeader32
= (EFI_IMAGE_NT_HEADERS32
*) (mImageBase
+ mPeCoffHeaderOffset
);
1009 if (NtHeader32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
)
1011 return EFI_UNSUPPORTED
;
1014 mNtHeader
.Pe32
= NtHeader32
;
1017 // Check the architecture field of PE header and get the Certificate Data Directory data
1018 // Note the size of FileHeader field is constant for both IA32 and X64 arch
1020 if ((NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA32
)
1021 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_EBC
)) {
1023 // IA-32 Architecture
1025 mImageType
= ImageType_IA32
;
1026 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*) &(NtHeader32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
1028 else if ((NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_IA64
)
1029 || (NtHeader32
->FileHeader
.Machine
== EFI_IMAGE_MACHINE_X64
)) {
1031 // 64-bits Architecture
1033 mImageType
= ImageType_X64
;
1034 NtHeader64
= (EFI_IMAGE_NT_HEADERS64
*) (mImageBase
+ mPeCoffHeaderOffset
);
1035 mSecDataDir
= (EFI_IMAGE_SECURITY_DATA_DIRECTORY
*) &(NtHeader64
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]);
1037 return EFI_UNSUPPORTED
;
1044 Calculate hash of Pe/Coff image based on the authenticode image hashing in
1045 PE/COFF Specification 8.0 Appendix A
1047 @param[in] HashAlg Hash algorithm type.
1049 @retval TRUE Successfully hash image.
1050 @retval FALSE Fail in hash image.
1060 EFI_IMAGE_SECTION_HEADER
*Section
;
1065 UINTN SumOfBytesHashed
;
1066 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1071 SectionHeader
= NULL
;
1074 if ((HashAlg
!= HASHALG_SHA1
) && (HashAlg
!= HASHALG_SHA256
)) {
1079 // Initialize context of hash.
1081 ZeroMem (mImageDigest
, MAX_DIGEST_SIZE
);
1083 if (HashAlg
== HASHALG_SHA1
) {
1084 mImageDigestSize
= SHA1_DIGEST_SIZE
;
1085 mCertType
= gEfiCertSha1Guid
;
1086 } else if (HashAlg
== HASHALG_SHA256
) {
1087 mImageDigestSize
= SHA256_DIGEST_SIZE
;
1088 mCertType
= gEfiCertSha256Guid
;
1091 CtxSize
= mHash
[HashAlg
].GetContextSize();
1093 HashCtx
= AllocatePool (CtxSize
);
1094 ASSERT (HashCtx
!= NULL
);
1096 // 1. Load the image header into memory.
1098 // 2. Initialize a SHA hash context.
1099 Status
= mHash
[HashAlg
].HashInit(HashCtx
);
1104 // Measuring PE/COFF Image Header;
1105 // But CheckSum field and SECURITY data directory (certificate) are excluded
1107 if (mNtHeader
.Pe32
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
&& mNtHeader
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1109 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
1110 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
1111 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
1112 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
1114 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
1117 // Get the magic value from the PE/COFF Optional Header
1119 Magic
= mNtHeader
.Pe32
->OptionalHeader
.Magic
;
1123 // 3. Calculate the distance from the base of the image header to the image checksum address.
1124 // 4. Hash the image header from its base to beginning of the image checksum.
1126 HashBase
= mImageBase
;
1127 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1131 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.CheckSum
) - HashBase
);
1134 // Use PE32+ offset.
1136 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
) - HashBase
);
1139 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1144 // 5. Skip over the image checksum (it occupies a single ULONG).
1145 // 6. Get the address of the beginning of the Cert Directory.
1146 // 7. Hash everything from the end of the checksum to the start of the Cert Directory.
1148 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1152 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1153 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
1156 // Use PE32+ offset.
1158 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.CheckSum
+ sizeof (UINT32
);
1159 HashSize
= (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
]) - HashBase
);
1162 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1167 // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)
1168 // 9. Hash everything from the end of the Cert Directory to the end of image header.
1170 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1174 HashBase
= (UINT8
*) &mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1175 HashSize
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
- (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - mImageBase
);
1178 // Use PE32+ offset.
1180 HashBase
= (UINT8
*) &mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1];
1181 HashSize
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
- (UINTN
) ((UINT8
*) (&mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
+ 1]) - mImageBase
);
1184 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1189 // 10. Set the SUM_OF_BYTES_HASHED to the size of the header.
1191 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1195 SumOfBytesHashed
= mNtHeader
.Pe32
->OptionalHeader
.SizeOfHeaders
;
1200 SumOfBytesHashed
= mNtHeader
.Pe32Plus
->OptionalHeader
.SizeOfHeaders
;
1204 // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER
1205 // structures in the image. The 'NumberOfSections' field of the image
1206 // header indicates how big the table should be. Do not include any
1207 // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero.
1209 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER
) * mNtHeader
.Pe32
->FileHeader
.NumberOfSections
);
1210 ASSERT (SectionHeader
!= NULL
);
1212 // 12. Using the 'PointerToRawData' in the referenced section headers as
1213 // a key, arrange the elements in the table in ascending order. In other
1214 // words, sort the section headers according to the disk-file offset of
1217 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
1219 mPeCoffHeaderOffset
+
1221 sizeof (EFI_IMAGE_FILE_HEADER
) +
1222 mNtHeader
.Pe32
->FileHeader
.SizeOfOptionalHeader
1224 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1226 while ((Pos
> 0) && (Section
->PointerToRawData
< SectionHeader
[Pos
- 1].PointerToRawData
)) {
1227 CopyMem (&SectionHeader
[Pos
], &SectionHeader
[Pos
- 1], sizeof (EFI_IMAGE_SECTION_HEADER
));
1230 CopyMem (&SectionHeader
[Pos
], Section
, sizeof (EFI_IMAGE_SECTION_HEADER
));
1235 // 13. Walk through the sorted table, bring the corresponding section
1236 // into memory, and hash the entire section (using the 'SizeOfRawData'
1237 // field in the section header to determine the amount of data to hash).
1238 // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED .
1239 // 15. Repeat steps 13 and 14 for all the sections in the sorted table.
1241 for (Index
= 0; Index
< mNtHeader
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1242 Section
= &SectionHeader
[Index
];
1243 if (Section
->SizeOfRawData
== 0) {
1246 HashBase
= mImageBase
+ Section
->PointerToRawData
;
1247 HashSize
= (UINTN
) Section
->SizeOfRawData
;
1249 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1254 SumOfBytesHashed
+= HashSize
;
1258 // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra
1259 // data in the file that needs to be added to the hash. This data begins
1260 // at file offset SUM_OF_BYTES_HASHED and its length is:
1261 // FileSize - (CertDirectory->Size)
1263 if (mImageSize
> SumOfBytesHashed
) {
1264 HashBase
= mImageBase
+ SumOfBytesHashed
;
1265 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1271 mNtHeader
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
1275 // Use PE32+ offset.
1279 mNtHeader
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY
].Size
-
1283 Status
= mHash
[HashAlg
].HashUpdate(HashCtx
, HashBase
, HashSize
);
1289 Status
= mHash
[HashAlg
].HashFinal(HashCtx
, mImageDigest
);
1292 if (HashCtx
!= NULL
) {
1295 if (SectionHeader
!= NULL
) {
1296 FreePool (SectionHeader
);
1302 Recognize the Hash algorithm in PE/COFF Authenticode and caculate hash of
1303 Pe/Coff image based on the authenticated image hashing in PE/COFF Specification
1306 @retval EFI_UNSUPPORTED Hash algorithm is not supported.
1307 @retval EFI_SUCCESS Hash successfully.
1316 WIN_CERTIFICATE_EFI_PKCS
*PkcsCertData
;
1318 PkcsCertData
= (WIN_CERTIFICATE_EFI_PKCS
*) (mImageBase
+ mSecDataDir
->Offset
);
1320 for (Index
= 0; Index
< HASHALG_MAX
; Index
++) {
1322 // Check the Hash algorithm in PE/COFF Authenticode.
1323 // According to PKCS#7 Definition:
1324 // SignedData ::= SEQUENCE {
1326 // digestAlgorithms DigestAlgorithmIdentifiers,
1327 // contentInfo ContentInfo,
1329 // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
1330 // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
1331 // Fixed offset (+32) is calculated based on two bytes of length encoding.
1333 if ((*(PkcsCertData
->CertData
+ 1) & TWO_BYTE_ENCODE
) != TWO_BYTE_ENCODE
) {
1335 // Only support two bytes of Long Form of Length Encoding.
1341 if (CompareMem (PkcsCertData
->CertData
+ 32, mHash
[Index
].OidValue
, mHash
[Index
].OidLength
) == 0) {
1346 if (Index
== HASHALG_MAX
) {
1347 return EFI_UNSUPPORTED
;
1351 // HASH PE Image based on Hash algorithm in PE/COFF Authenticode.
1353 if (!HashPeImage(Index
)) {
1354 return EFI_UNSUPPORTED
;
1361 Enroll a new executable's signature into Signature Database.
1363 @param[in] PrivateData The module's private data.
1364 @param[in] VariableName Variable name of signature database, must be
1365 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
1367 @retval EFI_SUCCESS New signature is enrolled successfully.
1368 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1369 @retval EFI_UNSUPPORTED Unsupported command.
1370 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1374 EnrollImageSignatureToSigDB (
1375 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1376 IN CHAR16
*VariableName
1380 EFI_SIGNATURE_LIST
*SigDBCert
;
1381 EFI_SIGNATURE_DATA
*SigDBCertData
;
1386 WIN_CERTIFICATE_UEFI_GUID
*GuidCertData
;
1389 GuidCertData
= NULL
;
1392 // Form the SigDB certificate list.
1393 // Format the data item into EFI_SIGNATURE_LIST type.
1395 // We need to parse executable's signature data from specified signed executable file.
1396 // In current implementation, we simply trust the pass-in signed executable file.
1397 // In reality, it's OS's responsibility to verify the signed executable file.
1401 // Read the whole file content
1403 Status
= ReadFileContent(
1404 Private
->FileContext
->FHandle
,
1405 (VOID
**) &mImageBase
,
1409 if (EFI_ERROR (Status
)) {
1412 ASSERT (mImageBase
!= NULL
);
1414 Status
= LoadPeImage ();
1415 if (EFI_ERROR (Status
)) {
1419 if (mSecDataDir
->SizeOfCert
== 0) {
1420 if (!HashPeImage (HASHALG_SHA256
)) {
1421 Status
= EFI_SECURITY_VIOLATION
;
1427 // Read the certificate data
1429 mCertificate
= (WIN_CERTIFICATE
*)(mImageBase
+ mSecDataDir
->Offset
);
1431 if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_EFI_GUID
) {
1432 GuidCertData
= (WIN_CERTIFICATE_UEFI_GUID
*) mCertificate
;
1433 if (CompareMem (&GuidCertData
->CertType
, &gEfiCertTypeRsa2048Sha256Guid
, sizeof(EFI_GUID
)) != 0) {
1434 Status
= EFI_ABORTED
;
1438 if (!HashPeImage (HASHALG_SHA256
)) {
1439 Status
= EFI_ABORTED
;
1443 } else if (mCertificate
->wCertificateType
== WIN_CERT_TYPE_PKCS_SIGNED_DATA
) {
1445 Status
= HashPeImageByType ();
1446 if (EFI_ERROR (Status
)) {
1450 Status
= EFI_ABORTED
;
1456 // Create a new SigDB entry.
1458 SigDBSize
= sizeof(EFI_SIGNATURE_LIST
)
1459 + sizeof(EFI_SIGNATURE_DATA
) - 1
1460 + (UINT32
) mImageDigestSize
;
1462 Data
= (UINT8
*) AllocateZeroPool (SigDBSize
);
1464 Status
= EFI_OUT_OF_RESOURCES
;
1469 // Adjust the Certificate Database parameters.
1471 SigDBCert
= (EFI_SIGNATURE_LIST
*) Data
;
1472 SigDBCert
->SignatureListSize
= (UINT32
) SigDBSize
;
1473 SigDBCert
->SignatureHeaderSize
= 0;
1474 SigDBCert
->SignatureSize
= sizeof(EFI_SIGNATURE_DATA
) - 1 + (UINT32
) mImageDigestSize
;
1475 CopyGuid (&SigDBCert
->SignatureType
, &mCertType
);
1477 SigDBCertData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)SigDBCert
+ sizeof(EFI_SIGNATURE_LIST
));
1478 CopyGuid (&SigDBCertData
->SignatureOwner
, Private
->SignatureGUID
);
1479 CopyMem (SigDBCertData
->SignatureData
, mImageDigest
, mImageDigestSize
);
1481 Attr
= EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_RUNTIME_ACCESS
1482 | EFI_VARIABLE_BOOTSERVICE_ACCESS
| EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
;
1483 Status
= CreateTimeBasedPayload (&SigDBSize
, (UINT8
**) &Data
);
1484 if (EFI_ERROR (Status
)) {
1485 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
1490 // Check if SigDB variable has been already existed.
1491 // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
1492 // new signature data to original variable
1495 Status
= gRT
->GetVariable(
1497 &gEfiImageSecurityDatabaseGuid
,
1502 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1503 Attr
|= EFI_VARIABLE_APPEND_WRITE
;
1504 } else if (Status
!= EFI_NOT_FOUND
) {
1509 // Enroll the variable.
1511 Status
= gRT
->SetVariable(
1513 &gEfiImageSecurityDatabaseGuid
,
1518 if (EFI_ERROR (Status
)) {
1524 CloseFile (Private
->FileContext
->FHandle
);
1525 Private
->FileContext
->FHandle
= NULL
;
1526 Private
->FileContext
->FileName
= NULL
;
1528 if (Private
->SignatureGUID
!= NULL
) {
1529 FreePool (Private
->SignatureGUID
);
1530 Private
->SignatureGUID
= NULL
;
1537 if (mImageBase
!= NULL
) {
1538 FreePool (mImageBase
);
1546 Enroll signature into DB/DBX without KEK's authentication.
1547 The SignatureOwner GUID will be Private->SignatureGUID.
1549 @param[in] PrivateData The module's private data.
1550 @param[in] VariableName Variable name of signature database, must be
1551 EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1.
1553 @retval EFI_SUCCESS New signature enrolled successfully.
1554 @retval EFI_INVALID_PARAMETER The parameter is invalid.
1555 @retval others Fail to enroll signature data.
1559 EnrollSignatureDatabase (
1560 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
,
1561 IN CHAR16
*VariableName
1564 UINT16
* FilePostFix
;
1568 if ((Private
->FileContext
->FileName
== NULL
) || (Private
->FileContext
->FHandle
== NULL
) || (Private
->SignatureGUID
== NULL
)) {
1569 return EFI_INVALID_PARAMETER
;
1572 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
1573 if (EFI_ERROR (Status
)) {
1578 // Parse the file's postfix.
1580 NameLength
= StrLen (Private
->FileContext
->FileName
);
1581 if (NameLength
<= 4) {
1582 return EFI_INVALID_PARAMETER
;
1584 FilePostFix
= Private
->FileContext
->FileName
+ NameLength
- 4;
1585 if (IsDerEncodeCertificate(FilePostFix
)) {
1587 // Supports DER-encoded X509 certificate.
1589 return EnrollX509toSigDB (Private
, VariableName
);
1592 return EnrollImageSignatureToSigDB (Private
, VariableName
);
1596 List all signatures in specified signature database (e.g. KEK/DB/DBX)
1597 by GUID in the page for user to select and delete as needed.
1599 @param[in] PrivateData Module's private data.
1600 @param[in] VariableName The variable name of the vendor's signature database.
1601 @param[in] VendorGuid A unique identifier for the vendor.
1602 @param[in] LabelNumber Label number to insert opcodes.
1603 @param[in] FormId Form ID of current page.
1604 @param[in] QuestionIdBase Base question id of the signature list.
1606 @retval EFI_SUCCESS Success to update the signature list page
1607 @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources.
1612 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
1613 IN CHAR16
*VariableName
,
1614 IN EFI_GUID
*VendorGuid
,
1615 IN UINT16 LabelNumber
,
1616 IN EFI_FORM_ID FormId
,
1617 IN EFI_QUESTION_ID QuestionIdBase
1624 VOID
*StartOpCodeHandle
;
1625 VOID
*EndOpCodeHandle
;
1626 EFI_IFR_GUID_LABEL
*StartLabel
;
1627 EFI_IFR_GUID_LABEL
*EndLabel
;
1630 EFI_SIGNATURE_LIST
*CertList
;
1631 EFI_SIGNATURE_DATA
*Cert
;
1632 UINT32 ItemDataSize
;
1634 EFI_STRING_ID GuidID
;
1641 StartOpCodeHandle
= NULL
;
1642 EndOpCodeHandle
= NULL
;
1645 // Initialize the container for dynamic opcodes.
1647 StartOpCodeHandle
= HiiAllocateOpCodeHandle ();
1648 if (StartOpCodeHandle
== NULL
) {
1649 Status
= EFI_OUT_OF_RESOURCES
;
1653 EndOpCodeHandle
= HiiAllocateOpCodeHandle ();
1654 if (EndOpCodeHandle
== NULL
) {
1655 Status
= EFI_OUT_OF_RESOURCES
;
1660 // Create Hii Extend Label OpCode.
1662 StartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
1666 sizeof (EFI_IFR_GUID_LABEL
)
1668 StartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1669 StartLabel
->Number
= LabelNumber
;
1671 EndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
1675 sizeof (EFI_IFR_GUID_LABEL
)
1677 EndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
1678 EndLabel
->Number
= LABEL_END
;
1684 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
1685 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
1689 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1691 Status
= EFI_OUT_OF_RESOURCES
;
1695 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, Data
);
1696 if (EFI_ERROR (Status
)) {
1700 GuidStr
= AllocateZeroPool (100);
1701 if (GuidStr
== NULL
) {
1702 Status
= EFI_OUT_OF_RESOURCES
;
1707 // Enumerate all KEK pub data.
1709 ItemDataSize
= (UINT32
) DataSize
;
1710 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
1713 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
1715 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
)) {
1716 Help
= STRING_TOKEN (STR_CERT_TYPE_RSA2048_SHA256_GUID
);
1717 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
1718 Help
= STRING_TOKEN (STR_CERT_TYPE_PCKS7_GUID
);
1719 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
)) {
1720 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA1_GUID
);
1721 } else if (CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
)) {
1722 Help
= STRING_TOKEN (STR_CERT_TYPE_SHA256_GUID
);
1725 // The signature type is not supported in current implementation.
1727 ItemDataSize
-= CertList
->SignatureListSize
;
1728 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1732 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1733 for (Index
= 0; Index
< CertCount
; Index
++) {
1734 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
1735 + sizeof (EFI_SIGNATURE_LIST
)
1736 + CertList
->SignatureHeaderSize
1737 + Index
* CertList
->SignatureSize
);
1739 // Display GUID and help
1741 GuidToString (&Cert
->SignatureOwner
, GuidStr
, 100);
1742 GuidID
= HiiSetString (PrivateData
->HiiHandle
, 0, GuidStr
, NULL
);
1743 HiiCreateCheckBoxOpCode (
1745 (EFI_QUESTION_ID
) (QuestionIdBase
+ GuidIndex
++),
1750 EFI_IFR_FLAG_CALLBACK
,
1756 ItemDataSize
-= CertList
->SignatureListSize
;
1757 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1762 PrivateData
->HiiHandle
,
1763 &gSecureBootConfigFormSetGuid
,
1769 if (StartOpCodeHandle
!= NULL
) {
1770 HiiFreeOpCodeHandle (StartOpCodeHandle
);
1773 if (EndOpCodeHandle
!= NULL
) {
1774 HiiFreeOpCodeHandle (EndOpCodeHandle
);
1781 if (GuidStr
!= NULL
) {
1789 Delete a KEK entry from KEK database.
1791 @param[in] PrivateData Module's private data.
1792 @param[in] QuestionId Question id of the KEK item to delete.
1794 @retval EFI_SUCCESS Delete kek item successfully.
1795 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1799 DeleteKeyExchangeKey (
1800 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
1801 IN EFI_QUESTION_ID QuestionId
1810 EFI_SIGNATURE_LIST
*CertList
;
1811 EFI_SIGNATURE_LIST
*NewCertList
;
1812 EFI_SIGNATURE_DATA
*Cert
;
1815 BOOLEAN IsKEKItemFound
;
1817 UINTN DeleteKekIndex
;
1825 DeleteKekIndex
= QuestionId
- OPTION_DEL_KEK_QUESTION_ID
;
1827 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
1828 if (EFI_ERROR (Status
)) {
1833 // Get original KEK variable.
1836 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, NULL
, &DataSize
, NULL
);
1837 if (EFI_ERROR(Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
1841 OldData
= (UINT8
*)AllocateZeroPool(DataSize
);
1842 if (OldData
== NULL
) {
1843 Status
= EFI_OUT_OF_RESOURCES
;
1847 Status
= gRT
->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
, &Attr
, &DataSize
, OldData
);
1848 if (EFI_ERROR(Status
)) {
1853 // Allocate space for new variable.
1855 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
1857 Status
= EFI_OUT_OF_RESOURCES
;
1862 // Enumerate all KEK pub data and erasing the target item.
1864 IsKEKItemFound
= FALSE
;
1865 KekDataSize
= (UINT32
) DataSize
;
1866 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
1869 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
1870 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
1871 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
)) {
1872 CopyMem (Data
+ Offset
, CertList
, (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
1873 NewCertList
= (EFI_SIGNATURE_LIST
*)(Data
+ Offset
);
1874 Offset
+= (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1875 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
1876 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1877 for (Index
= 0; Index
< CertCount
; Index
++) {
1878 if (GuidIndex
== DeleteKekIndex
) {
1880 // Find it! Skip it!
1882 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
1883 IsKEKItemFound
= TRUE
;
1886 // This item doesn't match. Copy it to the Data buffer.
1888 CopyMem (Data
+ Offset
, Cert
, CertList
->SignatureSize
);
1889 Offset
+= CertList
->SignatureSize
;
1892 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
1896 // This List doesn't match. Copy it to the Data buffer.
1898 CopyMem (Data
+ Offset
, CertList
, CertList
->SignatureListSize
);
1899 Offset
+= CertList
->SignatureListSize
;
1902 KekDataSize
-= CertList
->SignatureListSize
;
1903 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1906 if (!IsKEKItemFound
) {
1908 // Doesn't find the Kek Item!
1910 Status
= EFI_NOT_FOUND
;
1915 // Delete the Signature header if there is no signature in the list.
1917 KekDataSize
= Offset
;
1918 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
1920 ZeroMem (OldData
, KekDataSize
);
1921 while ((KekDataSize
> 0) && (KekDataSize
>= CertList
->SignatureListSize
)) {
1922 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
1923 DEBUG ((DEBUG_ERROR
, " CertCount = %x\n", CertCount
));
1924 if (CertCount
!= 0) {
1925 CopyMem (OldData
+ Offset
, CertList
, CertList
->SignatureListSize
);
1926 Offset
+= CertList
->SignatureListSize
;
1928 KekDataSize
-= CertList
->SignatureListSize
;
1929 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
1933 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
1934 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
);
1935 if (EFI_ERROR (Status
)) {
1936 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
1941 Status
= gRT
->SetVariable(
1942 EFI_KEY_EXCHANGE_KEY_NAME
,
1943 &gEfiGlobalVariableGuid
,
1948 if (EFI_ERROR (Status
)) {
1949 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
1958 if (OldData
!= NULL
) {
1962 return UpdateDeletePage (
1964 EFI_KEY_EXCHANGE_KEY_NAME
,
1965 &gEfiGlobalVariableGuid
,
1967 FORMID_DELETE_KEK_FORM
,
1968 OPTION_DEL_KEK_QUESTION_ID
1973 Delete a signature entry from siganture database.
1975 @param[in] PrivateData Module's private data.
1976 @param[in] VariableName The variable name of the vendor's signature database.
1977 @param[in] VendorGuid A unique identifier for the vendor.
1978 @param[in] LabelNumber Label number to insert opcodes.
1979 @param[in] FormId Form ID of current page.
1980 @param[in] QuestionIdBase Base question id of the signature list.
1981 @param[in] DeleteIndex Signature index to delete.
1983 @retval EFI_SUCCESS Delete siganture successfully.
1984 @retval EFI_NOT_FOUND Can't find the signature item,
1985 @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.
1989 IN SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
,
1990 IN CHAR16
*VariableName
,
1991 IN EFI_GUID
*VendorGuid
,
1992 IN UINT16 LabelNumber
,
1993 IN EFI_FORM_ID FormId
,
1994 IN EFI_QUESTION_ID QuestionIdBase
,
1995 IN UINTN DeleteIndex
2004 EFI_SIGNATURE_LIST
*CertList
;
2005 EFI_SIGNATURE_LIST
*NewCertList
;
2006 EFI_SIGNATURE_DATA
*Cert
;
2009 BOOLEAN IsItemFound
;
2010 UINT32 ItemDataSize
;
2019 Status
= SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE
);
2020 if (EFI_ERROR (Status
)) {
2025 // Get original signature list data.
2028 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, NULL
, &DataSize
, NULL
);
2029 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
2033 OldData
= (UINT8
*) AllocateZeroPool (DataSize
);
2034 if (OldData
== NULL
) {
2035 Status
= EFI_OUT_OF_RESOURCES
;
2039 Status
= gRT
->GetVariable (VariableName
, VendorGuid
, &Attr
, &DataSize
, OldData
);
2040 if (EFI_ERROR(Status
)) {
2045 // Allocate space for new variable.
2047 Data
= (UINT8
*) AllocateZeroPool (DataSize
);
2049 Status
= EFI_OUT_OF_RESOURCES
;
2054 // Enumerate all signature data and erasing the target item.
2056 IsItemFound
= FALSE
;
2057 ItemDataSize
= (UINT32
) DataSize
;
2058 CertList
= (EFI_SIGNATURE_LIST
*) OldData
;
2061 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2062 if (CompareGuid (&CertList
->SignatureType
, &gEfiCertRsa2048Guid
) ||
2063 CompareGuid (&CertList
->SignatureType
, &gEfiCertX509Guid
) ||
2064 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha1Guid
) ||
2065 CompareGuid (&CertList
->SignatureType
, &gEfiCertSha256Guid
)
2068 // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.
2070 CopyMem (Data
+ Offset
, CertList
, (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
));
2071 NewCertList
= (EFI_SIGNATURE_LIST
*) (Data
+ Offset
);
2072 Offset
+= (sizeof(EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2073 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) CertList
+ sizeof (EFI_SIGNATURE_LIST
) + CertList
->SignatureHeaderSize
);
2074 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2075 for (Index
= 0; Index
< CertCount
; Index
++) {
2076 if (GuidIndex
== DeleteIndex
) {
2078 // Find it! Skip it!
2080 NewCertList
->SignatureListSize
-= CertList
->SignatureSize
;
2084 // This item doesn't match. Copy it to the Data buffer.
2086 CopyMem (Data
+ Offset
, (UINT8
*)(Cert
), CertList
->SignatureSize
);
2087 Offset
+= CertList
->SignatureSize
;
2090 Cert
= (EFI_SIGNATURE_DATA
*) ((UINT8
*) Cert
+ CertList
->SignatureSize
);
2094 // This List doesn't match. Just copy it to the Data buffer.
2096 CopyMem (Data
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
2097 Offset
+= CertList
->SignatureListSize
;
2100 ItemDataSize
-= CertList
->SignatureListSize
;
2101 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2106 // Doesn't find the signature Item!
2108 Status
= EFI_NOT_FOUND
;
2113 // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.
2115 ItemDataSize
= Offset
;
2116 CertList
= (EFI_SIGNATURE_LIST
*) Data
;
2118 ZeroMem (OldData
, ItemDataSize
);
2119 while ((ItemDataSize
> 0) && (ItemDataSize
>= CertList
->SignatureListSize
)) {
2120 CertCount
= (CertList
->SignatureListSize
- sizeof (EFI_SIGNATURE_LIST
) - CertList
->SignatureHeaderSize
) / CertList
->SignatureSize
;
2121 DEBUG ((DEBUG_ERROR
, " CertCount = %x\n", CertCount
));
2122 if (CertCount
!= 0) {
2123 CopyMem (OldData
+ Offset
, (UINT8
*)(CertList
), CertList
->SignatureListSize
);
2124 Offset
+= CertList
->SignatureListSize
;
2126 ItemDataSize
-= CertList
->SignatureListSize
;
2127 CertList
= (EFI_SIGNATURE_LIST
*) ((UINT8
*) CertList
+ CertList
->SignatureListSize
);
2131 if ((Attr
& EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
) != 0) {
2132 Status
= CreateTimeBasedPayload (&DataSize
, &OldData
);
2133 if (EFI_ERROR (Status
)) {
2134 DEBUG ((EFI_D_ERROR
, "Fail to create time-based data payload: %r", Status
));
2139 Status
= gRT
->SetVariable(
2146 if (EFI_ERROR (Status
)) {
2147 DEBUG ((DEBUG_ERROR
, "Failed to set variable, Status = %r\n", Status
));
2156 if (OldData
!= NULL
) {
2160 return UpdateDeletePage (
2171 This function extracts configuration from variable.
2173 @param[in, out] ConfigData Point to SecureBoot configuration private data.
2177 SecureBootExtractConfigFromVariable (
2178 IN OUT SECUREBOOT_CONFIGURATION
*ConfigData
2181 UINT8
*SecureBootEnable
;
2183 UINT8
*SecureBootMode
;
2185 SecureBootEnable
= NULL
;
2187 SecureBootMode
= NULL
;
2190 // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable
2193 ConfigData
->AttemptSecureBoot
= FALSE
;
2194 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
2195 if (SecureBootEnable
== NULL
) {
2196 ConfigData
->HideSecureBoot
= TRUE
;
2198 ConfigData
->HideSecureBoot
= FALSE
;
2199 if ((*SecureBootEnable
) == SECURE_BOOT_ENABLE
) {
2200 ConfigData
->AttemptSecureBoot
= TRUE
;
2205 // If it is Physical Presence User, set the PhysicalPresent to true.
2207 if (UserPhysicalPresent()) {
2208 ConfigData
->PhysicalPresent
= TRUE
;
2210 ConfigData
->PhysicalPresent
= FALSE
;
2214 // If there is no PK then the Delete Pk button will be gray.
2216 GetVariable2 (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SetupMode
, NULL
);
2217 if (SetupMode
== NULL
|| (*SetupMode
) == SETUP_MODE
) {
2218 ConfigData
->HasPk
= FALSE
;
2220 ConfigData
->HasPk
= TRUE
;
2224 // Get the SecureBootMode from CustomMode variable.
2226 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
2227 if (SecureBootMode
== NULL
) {
2228 ConfigData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
2230 ConfigData
->SecureBootMode
= *(SecureBootMode
);
2233 if (SecureBootEnable
!= NULL
) {
2234 FreePool (SecureBootEnable
);
2236 if (SetupMode
!= NULL
) {
2237 FreePool (SetupMode
);
2239 if (SecureBootMode
!= NULL
) {
2240 FreePool (SecureBootMode
);
2245 This function allows a caller to extract the current configuration for one
2246 or more named elements from the target driver.
2248 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2249 @param[in] Request A null-terminated Unicode string in
2250 <ConfigRequest> format.
2251 @param[out] Progress On return, points to a character in the Request
2252 string. Points to the string's null terminator if
2253 request was successful. Points to the most recent
2254 '&' before the first failing name/value pair (or
2255 the beginning of the string if the failure is in
2256 the first name/value pair) if the request was not
2258 @param[out] Results A null-terminated Unicode string in
2259 <ConfigAltResp> format which has all values filled
2260 in for the names in the Request string. String to
2261 be allocated by the called function.
2263 @retval EFI_SUCCESS The Results is filled with the requested values.
2264 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
2265 @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name.
2266 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
2272 SecureBootExtractConfig (
2273 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2274 IN CONST EFI_STRING Request
,
2275 OUT EFI_STRING
*Progress
,
2276 OUT EFI_STRING
*Results
2282 SECUREBOOT_CONFIGURATION Configuration
;
2283 EFI_STRING ConfigRequest
;
2284 EFI_STRING ConfigRequestHdr
;
2285 SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
;
2286 BOOLEAN AllocatedRequest
;
2289 if (Progress
== NULL
|| Results
== NULL
) {
2290 return EFI_INVALID_PARAMETER
;
2293 AllocatedRequest
= FALSE
;
2294 ConfigRequestHdr
= NULL
;
2295 ConfigRequest
= NULL
;
2299 ZeroMem (&Configuration
, sizeof (Configuration
));
2300 PrivateData
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
2301 *Progress
= Request
;
2303 if ((Request
!= NULL
) && !HiiIsConfigHdrMatch (Request
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
2304 return EFI_NOT_FOUND
;
2308 // Get Configuration from Variable.
2310 SecureBootExtractConfigFromVariable (&Configuration
);
2313 // Update current secure boot state.
2315 GetVariable2 (EFI_SECURE_BOOT_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SecureBoot
, NULL
);
2316 if (SecureBoot
!= NULL
&& *SecureBoot
== SECURE_BOOT_MODE_ENABLE
) {
2317 HiiSetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Enabled", NULL
);
2319 HiiSetString (PrivateData
->HiiHandle
, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT
), L
"Disabled", NULL
);
2321 if (SecureBoot
!= NULL
) {
2322 FreePool (SecureBoot
);
2325 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
2326 ConfigRequest
= Request
;
2327 if ((Request
== NULL
) || (StrStr (Request
, L
"OFFSET") == NULL
)) {
2329 // Request is set to NULL or OFFSET is NULL, construct full request string.
2331 // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
2332 // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
2334 ConfigRequestHdr
= HiiConstructConfigHdr (&gSecureBootConfigFormSetGuid
, mSecureBootStorageName
, PrivateData
->DriverHandle
);
2335 Size
= (StrLen (ConfigRequestHdr
) + 32 + 1) * sizeof (CHAR16
);
2336 ConfigRequest
= AllocateZeroPool (Size
);
2337 ASSERT (ConfigRequest
!= NULL
);
2338 AllocatedRequest
= TRUE
;
2339 UnicodeSPrint (ConfigRequest
, Size
, L
"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr
, (UINT64
)BufferSize
);
2340 FreePool (ConfigRequestHdr
);
2341 ConfigRequestHdr
= NULL
;
2344 Status
= gHiiConfigRouting
->BlockToConfig (
2347 (UINT8
*) &Configuration
,
2354 // Free the allocated config request string.
2356 if (AllocatedRequest
) {
2357 FreePool (ConfigRequest
);
2361 // Set Progress string to the original request string.
2363 if (Request
== NULL
) {
2365 } else if (StrStr (Request
, L
"OFFSET") == NULL
) {
2366 *Progress
= Request
+ StrLen (Request
);
2373 This function processes the results of changes in configuration.
2375 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2376 @param[in] Configuration A null-terminated Unicode string in <ConfigResp>
2378 @param[out] Progress A pointer to a string filled in with the offset of
2379 the most recent '&' before the first failing
2380 name/value pair (or the beginning of the string if
2381 the failure is in the first name/value pair) or
2382 the terminating NULL if all was successful.
2384 @retval EFI_SUCCESS The Results is processed successfully.
2385 @retval EFI_INVALID_PARAMETER Configuration is NULL.
2386 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this
2392 SecureBootRouteConfig (
2393 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2394 IN CONST EFI_STRING Configuration
,
2395 OUT EFI_STRING
*Progress
2398 UINT8
*SecureBootEnable
;
2399 SECUREBOOT_CONFIGURATION IfrNvData
;
2403 if (Configuration
== NULL
|| Progress
== NULL
) {
2404 return EFI_INVALID_PARAMETER
;
2407 *Progress
= Configuration
;
2408 if (!HiiIsConfigHdrMatch (Configuration
, &gSecureBootConfigFormSetGuid
, mSecureBootStorageName
)) {
2409 return EFI_NOT_FOUND
;
2413 // Get Configuration from Variable.
2415 SecureBootExtractConfigFromVariable (&IfrNvData
);
2418 // Map the Configuration to the configuration block.
2420 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
2421 Status
= gHiiConfigRouting
->ConfigToBlock (
2424 (UINT8
*)&IfrNvData
,
2428 if (EFI_ERROR (Status
)) {
2433 // Store Buffer Storage back to EFI variable if needed
2435 SecureBootEnable
= NULL
;
2436 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
2437 if (NULL
!= SecureBootEnable
) {
2438 FreePool (SecureBootEnable
);
2439 Status
= SaveSecureBootVariable (IfrNvData
.AttemptSecureBoot
);
2440 if (EFI_ERROR (Status
)) {
2445 *Progress
= Configuration
+ StrLen (Configuration
);
2450 This function is called to provide results data to the driver.
2452 @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
2453 @param[in] Action Specifies the type of action taken by the browser.
2454 @param[in] QuestionId A unique value which is sent to the original
2455 exporting driver so that it can identify the type
2457 @param[in] Type The type of value for the question.
2458 @param[in] Value A pointer to the data being sent to the original
2460 @param[out] ActionRequest On return, points to the action requested by the
2463 @retval EFI_SUCCESS The callback successfully handled the action.
2464 @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the
2465 variable and its data.
2466 @retval EFI_DEVICE_ERROR The variable could not be saved.
2467 @retval EFI_UNSUPPORTED The specified Action is not supported by the
2473 SecureBootCallback (
2474 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
2475 IN EFI_BROWSER_ACTION Action
,
2476 IN EFI_QUESTION_ID QuestionId
,
2478 IN EFI_IFR_TYPE_VALUE
*Value
,
2479 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
2484 SECUREBOOT_CONFIG_PRIVATE_DATA
*Private
;
2486 SECUREBOOT_CONFIGURATION
*IfrNvData
;
2488 UINT8
*SecureBootEnable
;
2489 UINT8
*SecureBootMode
;
2491 CHAR16 PromptString
[100];
2493 SecureBootEnable
= NULL
;
2494 SecureBootMode
= NULL
;
2497 if ((This
== NULL
) || (Value
== NULL
) || (ActionRequest
== NULL
)) {
2498 return EFI_INVALID_PARAMETER
;
2501 if (Action
== EFI_BROWSER_ACTION_FORM_OPEN
) {
2502 if (QuestionId
== KEY_SECURE_BOOT_MODE
) {
2503 mIsEnterSecureBootForm
= TRUE
;
2509 if (Action
== EFI_BROWSER_ACTION_RETRIEVE
) {
2510 Status
= EFI_UNSUPPORTED
;
2511 if (QuestionId
== KEY_SECURE_BOOT_MODE
) {
2512 if (mIsEnterSecureBootForm
) {
2513 Value
->u8
= SECURE_BOOT_MODE_STANDARD
;
2514 Status
= EFI_SUCCESS
;
2520 if ((Action
!= EFI_BROWSER_ACTION_CHANGED
) &&
2521 (Action
!= EFI_BROWSER_ACTION_CHANGING
) &&
2522 (Action
!= EFI_BROWSER_ACTION_FORM_CLOSE
) &&
2523 (Action
!= EFI_BROWSER_ACTION_DEFAULT_STANDARD
)) {
2524 return EFI_UNSUPPORTED
;
2527 Private
= SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This
);
2530 // Retrieve uncommitted data from Browser
2532 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
2533 IfrNvData
= AllocateZeroPool (BufferSize
);
2534 if (IfrNvData
== NULL
) {
2535 return EFI_OUT_OF_RESOURCES
;
2538 Status
= EFI_SUCCESS
;
2540 HiiGetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
);
2542 if (Action
== EFI_BROWSER_ACTION_CHANGING
) {
2544 switch (QuestionId
) {
2545 case KEY_SECURE_BOOT_ENABLE
:
2546 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
2547 if (NULL
!= SecureBootEnable
) {
2548 FreePool (SecureBootEnable
);
2549 if (EFI_ERROR (SaveSecureBootVariable (Value
->u8
))) {
2551 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2553 L
"Only Physical Presence User could disable secure boot!",
2556 Status
= EFI_UNSUPPORTED
;
2559 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2561 L
"Configuration changed, please reset the platform to take effect!",
2568 case KEY_SECURE_BOOT_OPTION
:
2569 FreeMenu (&DirectoryMenu
);
2570 FreeMenu (&FsOptionMenu
);
2573 case KEY_SECURE_BOOT_KEK_OPTION
:
2574 case KEY_SECURE_BOOT_DB_OPTION
:
2575 case KEY_SECURE_BOOT_DBX_OPTION
:
2577 // Clear Signature GUID.
2579 ZeroMem (IfrNvData
->SignatureGuid
, sizeof (IfrNvData
->SignatureGuid
));
2580 if (Private
->SignatureGUID
== NULL
) {
2581 Private
->SignatureGUID
= (EFI_GUID
*) AllocateZeroPool (sizeof (EFI_GUID
));
2582 if (Private
->SignatureGUID
== NULL
) {
2583 return EFI_OUT_OF_RESOURCES
;
2587 if (QuestionId
== KEY_SECURE_BOOT_DB_OPTION
) {
2588 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DB
;
2589 } else if (QuestionId
== KEY_SECURE_BOOT_DBX_OPTION
) {
2590 LabelId
= SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
;
2592 LabelId
= FORMID_ENROLL_KEK_FORM
;
2596 // Refresh selected file.
2598 CleanUpPage (LabelId
, Private
);
2601 case SECUREBOOT_ADD_PK_FILE_FORM_ID
:
2602 case FORMID_ENROLL_KEK_FORM
:
2603 case SECUREBOOT_ENROLL_SIGNATURE_TO_DB
:
2604 case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX
:
2605 if (QuestionId
== SECUREBOOT_ADD_PK_FILE_FORM_ID
) {
2606 Private
->FeCurrentState
= FileExplorerStateEnrollPkFile
;
2607 } else if (QuestionId
== FORMID_ENROLL_KEK_FORM
) {
2608 Private
->FeCurrentState
= FileExplorerStateEnrollKekFile
;
2609 } else if (QuestionId
== SECUREBOOT_ENROLL_SIGNATURE_TO_DB
) {
2610 Private
->FeCurrentState
= FileExplorerStateEnrollSignatureFileToDb
;
2612 Private
->FeCurrentState
= FileExplorerStateEnrollSignatureFileToDbx
;
2615 Private
->FeDisplayContext
= FileExplorerDisplayUnknown
;
2616 CleanUpPage (FORM_FILE_EXPLORER_ID
, Private
);
2617 UpdateFileExplorer (Private
, 0);
2620 case KEY_SECURE_BOOT_DELETE_PK
:
2623 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2625 L
"Are you sure you want to delete PK? Secure boot will be disabled!",
2626 L
"Press 'Y' to delete PK and exit, 'N' to discard change and return",
2629 if (Key
.UnicodeChar
== 'y' || Key
.UnicodeChar
== 'Y') {
2630 Status
= DeletePlatformKey ();
2631 if (EFI_ERROR (Status
)) {
2633 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2635 L
"Only Physical Presence User could delete PK in custom mode!",
2643 case KEY_DELETE_KEK
:
2646 EFI_KEY_EXCHANGE_KEY_NAME
,
2647 &gEfiGlobalVariableGuid
,
2649 FORMID_DELETE_KEK_FORM
,
2650 OPTION_DEL_KEK_QUESTION_ID
2654 case SECUREBOOT_DELETE_SIGNATURE_FROM_DB
:
2657 EFI_IMAGE_SECURITY_DATABASE
,
2658 &gEfiImageSecurityDatabaseGuid
,
2660 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
2661 OPTION_DEL_DB_QUESTION_ID
2665 case SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
:
2668 EFI_IMAGE_SECURITY_DATABASE1
,
2669 &gEfiImageSecurityDatabaseGuid
,
2671 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
,
2672 OPTION_DEL_DBX_QUESTION_ID
2677 case KEY_VALUE_SAVE_AND_EXIT_KEK
:
2678 Status
= EnrollKeyExchangeKey (Private
);
2679 if (EFI_ERROR (Status
)) {
2681 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2683 L
"ERROR: Unsupported file type!",
2684 L
"Only supports DER-encoded X509 certificate",
2690 case KEY_VALUE_SAVE_AND_EXIT_DB
:
2691 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE
);
2692 if (EFI_ERROR (Status
)) {
2694 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2696 L
"ERROR: Unsupported file type!",
2697 L
"Only supports DER-encoded X509 certificate and executable EFI image",
2703 case KEY_VALUE_SAVE_AND_EXIT_DBX
:
2704 Status
= EnrollSignatureDatabase (Private
, EFI_IMAGE_SECURITY_DATABASE1
);
2705 if (EFI_ERROR (Status
)) {
2707 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2709 L
"ERROR: Unsupported file type!",
2710 L
"Only supports DER-encoded X509 certificate and executable EFI image",
2717 if (QuestionId
>= FILE_OPTION_OFFSET
) {
2718 UpdateFileExplorer (Private
, QuestionId
);
2719 } else if ((QuestionId
>= OPTION_DEL_KEK_QUESTION_ID
) &&
2720 (QuestionId
< (OPTION_DEL_KEK_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
2721 DeleteKeyExchangeKey (Private
, QuestionId
);
2722 } else if ((QuestionId
>= OPTION_DEL_DB_QUESTION_ID
) &&
2723 (QuestionId
< (OPTION_DEL_DB_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
2726 EFI_IMAGE_SECURITY_DATABASE
,
2727 &gEfiImageSecurityDatabaseGuid
,
2729 SECUREBOOT_DELETE_SIGNATURE_FROM_DB
,
2730 OPTION_DEL_DB_QUESTION_ID
,
2731 QuestionId
- OPTION_DEL_DB_QUESTION_ID
2733 } else if ((QuestionId
>= OPTION_DEL_DBX_QUESTION_ID
) &&
2734 (QuestionId
< (OPTION_DEL_DBX_QUESTION_ID
+ OPTION_CONFIG_RANGE
))) {
2737 EFI_IMAGE_SECURITY_DATABASE1
,
2738 &gEfiImageSecurityDatabaseGuid
,
2740 SECUREBOOT_DELETE_SIGNATURE_FROM_DBX
,
2741 OPTION_DEL_DBX_QUESTION_ID
,
2742 QuestionId
- OPTION_DEL_DBX_QUESTION_ID
2747 } else if (Action
== EFI_BROWSER_ACTION_CHANGED
) {
2748 switch (QuestionId
) {
2749 case KEY_SECURE_BOOT_ENABLE
:
2750 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2752 case KEY_VALUE_SAVE_AND_EXIT_PK
:
2753 Status
= EnrollPlatformKey (Private
);
2754 if (EFI_ERROR (Status
)) {
2757 sizeof (PromptString
),
2758 L
"Only DER encoded certificate file (%s) is supported.",
2762 EFI_LIGHTGRAY
| EFI_BACKGROUND_BLUE
,
2764 L
"ERROR: Unsupported file type!",
2769 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_RESET
;
2773 case KEY_VALUE_NO_SAVE_AND_EXIT_PK
:
2774 case KEY_VALUE_NO_SAVE_AND_EXIT_KEK
:
2775 case KEY_VALUE_NO_SAVE_AND_EXIT_DB
:
2776 case KEY_VALUE_NO_SAVE_AND_EXIT_DBX
:
2777 if (Private
->FileContext
->FHandle
!= NULL
) {
2778 CloseFile (Private
->FileContext
->FHandle
);
2779 Private
->FileContext
->FHandle
= NULL
;
2780 Private
->FileContext
->FileName
= NULL
;
2783 if (Private
->SignatureGUID
!= NULL
) {
2784 FreePool (Private
->SignatureGUID
);
2785 Private
->SignatureGUID
= NULL
;
2787 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_EXIT
;
2790 case KEY_SECURE_BOOT_MODE
:
2791 mIsEnterSecureBootForm
= FALSE
;
2794 case KEY_SECURE_BOOT_KEK_GUID
:
2795 case KEY_SECURE_BOOT_SIGNATURE_GUID_DB
:
2796 case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX
:
2797 ASSERT (Private
->SignatureGUID
!= NULL
);
2798 Status
= StringToGuid (
2799 IfrNvData
->SignatureGuid
,
2800 StrLen (IfrNvData
->SignatureGuid
),
2801 Private
->SignatureGUID
2803 if (EFI_ERROR (Status
)) {
2807 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2810 case KEY_SECURE_BOOT_DELETE_PK
:
2811 GetVariable2 (EFI_SETUP_MODE_NAME
, &gEfiGlobalVariableGuid
, (VOID
**)&SetupMode
, NULL
);
2812 if (SetupMode
== NULL
|| (*SetupMode
) == SETUP_MODE
) {
2813 IfrNvData
->DeletePk
= TRUE
;
2814 IfrNvData
->HasPk
= FALSE
;
2815 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
2817 IfrNvData
->DeletePk
= FALSE
;
2818 IfrNvData
->HasPk
= TRUE
;
2819 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_FORM_APPLY
;
2821 if (SetupMode
!= NULL
) {
2822 FreePool (SetupMode
);
2826 } else if (Action
== EFI_BROWSER_ACTION_DEFAULT_STANDARD
) {
2827 if (QuestionId
== KEY_HIDE_SECURE_BOOT
) {
2828 GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME
, &gEfiSecureBootEnableDisableGuid
, (VOID
**)&SecureBootEnable
, NULL
);
2829 if (SecureBootEnable
== NULL
) {
2830 IfrNvData
->HideSecureBoot
= TRUE
;
2832 FreePool (SecureBootEnable
);
2833 IfrNvData
->HideSecureBoot
= FALSE
;
2835 Value
->b
= IfrNvData
->HideSecureBoot
;
2837 } else if (Action
== EFI_BROWSER_ACTION_FORM_CLOSE
) {
2839 // Force the platform back to Standard Mode once user leave the setup screen.
2841 GetVariable2 (EFI_CUSTOM_MODE_NAME
, &gEfiCustomModeEnableGuid
, (VOID
**)&SecureBootMode
, NULL
);
2842 if (NULL
!= SecureBootMode
&& *SecureBootMode
== CUSTOM_SECURE_BOOT_MODE
) {
2843 IfrNvData
->SecureBootMode
= STANDARD_SECURE_BOOT_MODE
;
2844 SetSecureBootMode(STANDARD_SECURE_BOOT_MODE
);
2846 if (SecureBootMode
!= NULL
) {
2847 FreePool (SecureBootMode
);
2851 if (!EFI_ERROR (Status
)) {
2852 BufferSize
= sizeof (SECUREBOOT_CONFIGURATION
);
2853 HiiSetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) IfrNvData
, NULL
);
2855 FreePool (IfrNvData
);
2861 This function publish the SecureBoot configuration Form.
2863 @param[in, out] PrivateData Points to SecureBoot configuration private data.
2865 @retval EFI_SUCCESS HII Form is installed successfully.
2866 @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation.
2867 @retval Others Other errors as indicated.
2871 InstallSecureBootConfigForm (
2872 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
2876 EFI_HII_HANDLE HiiHandle
;
2877 EFI_HANDLE DriverHandle
;
2878 EFI_HII_CONFIG_ACCESS_PROTOCOL
*ConfigAccess
;
2880 DriverHandle
= NULL
;
2881 ConfigAccess
= &PrivateData
->ConfigAccess
;
2882 Status
= gBS
->InstallMultipleProtocolInterfaces (
2884 &gEfiDevicePathProtocolGuid
,
2885 &mSecureBootHiiVendorDevicePath
,
2886 &gEfiHiiConfigAccessProtocolGuid
,
2890 if (EFI_ERROR (Status
)) {
2894 PrivateData
->DriverHandle
= DriverHandle
;
2897 // Publish the HII package list
2899 HiiHandle
= HiiAddPackages (
2900 &gSecureBootConfigFormSetGuid
,
2902 SecureBootConfigDxeStrings
,
2903 SecureBootConfigBin
,
2906 if (HiiHandle
== NULL
) {
2907 gBS
->UninstallMultipleProtocolInterfaces (
2909 &gEfiDevicePathProtocolGuid
,
2910 &mSecureBootHiiVendorDevicePath
,
2911 &gEfiHiiConfigAccessProtocolGuid
,
2915 return EFI_OUT_OF_RESOURCES
;
2918 PrivateData
->HiiHandle
= HiiHandle
;
2920 PrivateData
->FileContext
= AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT
));
2921 PrivateData
->MenuEntry
= AllocateZeroPool (sizeof (SECUREBOOT_MENU_ENTRY
));
2923 if (PrivateData
->FileContext
== NULL
|| PrivateData
->MenuEntry
== NULL
) {
2924 UninstallSecureBootConfigForm (PrivateData
);
2925 return EFI_OUT_OF_RESOURCES
;
2928 PrivateData
->FeCurrentState
= FileExplorerStateInActive
;
2929 PrivateData
->FeDisplayContext
= FileExplorerDisplayUnknown
;
2931 InitializeListHead (&FsOptionMenu
.Head
);
2932 InitializeListHead (&DirectoryMenu
.Head
);
2935 // Init OpCode Handle and Allocate space for creation of Buffer
2937 mStartOpCodeHandle
= HiiAllocateOpCodeHandle ();
2938 if (mStartOpCodeHandle
== NULL
) {
2939 UninstallSecureBootConfigForm (PrivateData
);
2940 return EFI_OUT_OF_RESOURCES
;
2943 mEndOpCodeHandle
= HiiAllocateOpCodeHandle ();
2944 if (mEndOpCodeHandle
== NULL
) {
2945 UninstallSecureBootConfigForm (PrivateData
);
2946 return EFI_OUT_OF_RESOURCES
;
2950 // Create Hii Extend Label OpCode as the start opcode
2952 mStartLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
2956 sizeof (EFI_IFR_GUID_LABEL
)
2958 mStartLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2961 // Create Hii Extend Label OpCode as the end opcode
2963 mEndLabel
= (EFI_IFR_GUID_LABEL
*) HiiCreateGuidOpCode (
2967 sizeof (EFI_IFR_GUID_LABEL
)
2969 mEndLabel
->ExtendOpCode
= EFI_IFR_EXTEND_OP_LABEL
;
2970 mEndLabel
->Number
= LABEL_END
;
2976 This function removes SecureBoot configuration Form.
2978 @param[in, out] PrivateData Points to SecureBoot configuration private data.
2982 UninstallSecureBootConfigForm (
2983 IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA
*PrivateData
2987 // Uninstall HII package list
2989 if (PrivateData
->HiiHandle
!= NULL
) {
2990 HiiRemovePackages (PrivateData
->HiiHandle
);
2991 PrivateData
->HiiHandle
= NULL
;
2995 // Uninstall HII Config Access Protocol
2997 if (PrivateData
->DriverHandle
!= NULL
) {
2998 gBS
->UninstallMultipleProtocolInterfaces (
2999 PrivateData
->DriverHandle
,
3000 &gEfiDevicePathProtocolGuid
,
3001 &mSecureBootHiiVendorDevicePath
,
3002 &gEfiHiiConfigAccessProtocolGuid
,
3003 &PrivateData
->ConfigAccess
,
3006 PrivateData
->DriverHandle
= NULL
;
3009 if (PrivateData
->SignatureGUID
!= NULL
) {
3010 FreePool (PrivateData
->SignatureGUID
);
3013 if (PrivateData
->MenuEntry
!= NULL
) {
3014 FreePool (PrivateData
->MenuEntry
);
3017 if (PrivateData
->FileContext
!= NULL
) {
3018 FreePool (PrivateData
->FileContext
);
3021 FreePool (PrivateData
);
3023 FreeMenu (&DirectoryMenu
);
3024 FreeMenu (&FsOptionMenu
);
3026 if (mStartOpCodeHandle
!= NULL
) {
3027 HiiFreeOpCodeHandle (mStartOpCodeHandle
);
3030 if (mEndOpCodeHandle
!= NULL
) {
3031 HiiFreeOpCodeHandle (mEndOpCodeHandle
);