utils/inteltool: Add support to print Key Locker status

Add command-line option "-k" to print status.

Sample output:

$ inteltool -k
============= Dumping INTEL Key Locker status =============
Key Locker supported : YES
AESKL instructions enabled : NO
===========================================================

Change-Id: Icb1b08619b1dbc535640127f7ab5f6b49d70a6fe
Signed-off-by: Pratikkumar Prajapati <pratikkumar.v.prajapati@intel.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/71657
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Sridhar Siricilla <sridhar.siricilla@intel.com>
diff --git a/util/inteltool/cpu.c b/util/inteltool/cpu.c
index 7425229..5b1dbf3 100644
--- a/util/inteltool/cpu.c
+++ b/util/inteltool/cpu.c
@@ -3,6 +3,7 @@
 
 #include <fcntl.h>
 #include <unistd.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -17,16 +18,20 @@
 # define BREG	"%%ebx"
 #endif
 
-#define IA32_FEATURE_CONTROL	0x3a
-#define SGX_GLOBAL_ENABLED	(1 << 18)
-#define FEATURE_CONTROL_LOCKED	(1)
-#define MTRR_CAP_MSR		0xfe
-#define PRMRR_SUPPORTED		(1 << 12)
-#define SGX_SUPPORTED		(1 << 2)
-#define IA32_TME_ACTIVATE	0x982
-#define TME_SUPPORTED		(1 << 13)
-#define TME_LOCKED		(1)
-#define TME_ENABLED		(1 << 1)
+#define CPUID_STRUCT_EXTENDED_FEATURE_FLAGS	0x7
+#define IA32_FEATURE_CONTROL			0x3a
+#define SGX_GLOBAL_ENABLED			(1 << 18)
+#define FEATURE_CONTROL_LOCKED			(1)
+#define MTRR_CAP_MSR				0xfe
+#define PRMRR_SUPPORTED				(1 << 12)
+#define SGX_SUPPORTED				(1 << 2)
+#define IA32_TME_ACTIVATE			0x982
+#define TME_SUPPORTED				(1 << 13)
+#define TME_LOCKED				(1)
+#define TME_ENABLED				(1 << 1)
+#define CPUID_KEYLOCKER_FEATURE_FLAGS 		0x19
+#define KEYLOCKER_SUPPORTED			(1<<23)
+#define KEYLOCKER_AESKL				(1)
 
 int fd_msr;
 
@@ -266,6 +271,49 @@
 #endif
 }
 
+static bool is_keylocker_supported()
+{
+	cpuid_result_t cpuid_regs;
+	msr_t msr;
+
+	/*
+	 * CPUID leaf 0x7 subleaf 0x0 to detect Intel Key Locker support.
+	 * The specification of Key Locker can be found at: https://www.intel.com/
+	 * content/www/us/en/develop/download/intel-key-locker-specification.html
+	 * The spec can also be found via document #343965 on Intel's site.
+	 */
+	cpuid_regs = cpuid_ext(CPUID_STRUCT_EXTENDED_FEATURE_FLAGS, 0x0);
+	msr = rdmsr_from_cpu(0, MTRR_CAP_MSR);
+	return ((cpuid_regs.ecx & KEYLOCKER_SUPPORTED) && (msr.lo & PRMRR_SUPPORTED));
+}
+
+static bool is_aeskl_enabled()
+{
+	cpuid_result_t cpuid_regs;
+
+	/* CPUID leaf 0x19 subleaf 0x0 to detect details of Intel Key Locker feature */
+	cpuid_regs = cpuid_ext(CPUID_KEYLOCKER_FEATURE_FLAGS, 0x0);
+	return (cpuid_regs.ebx & KEYLOCKER_AESKL);
+}
+
+void print_keylocker(void)
+{
+#ifndef __DARWIN__
+	int keylocker_supported = is_keylocker_supported();
+
+	printf("\n============= Dumping INTEL Key Locker status =============\n");
+
+	printf("Key Locker supported : %s\n", keylocker_supported ? "YES" : "NO");
+
+	if (keylocker_supported) {
+		printf("AESKL instructions enabled : %s\n", is_aeskl_enabled() ? "YES" : "NO");
+	}
+	printf("===========================================================\n");
+#else
+	printf("Not Implemented\n");
+#endif
+}
+
 int print_intel_msrs(unsigned int range_start, unsigned int range_end)
 {
 	unsigned int i, core, id;
diff --git a/util/inteltool/inteltool.c b/util/inteltool/inteltool.c
index f4dbc1d..92a981a 100644
--- a/util/inteltool/inteltool.c
+++ b/util/inteltool/inteltool.c
@@ -628,6 +628,7 @@
 	     "   -A | --ambs:                      dump AMB registers\n"
 	     "   -x | --sgx:                       dump SGX status\n"
 	     "   -t | --tme:                       dump TME status\n"
+	     "   -k | --keylocker:                 dump Key Locker status\n"
 	     "   -a | --all:                       dump all known (safe) registers\n"
 	     "        --pcr=PORT_ID:               dump all registers of a PCR port\n"
 	     "                                     (may be specified max %d times)\n"
@@ -689,7 +690,7 @@
 	int dump_pmbase = 0, dump_epbar = 0, dump_dmibar = 0;
 	int dump_pciexbar = 0, dump_coremsrs = 0, dump_ambs = 0;
 	int dump_spi = 0, dump_gfx = 0, dump_ahci = 0, dump_sgx = 0, dump_tme = 0;
-	int dump_lpc = 0;
+	int dump_lpc = 0, dump_keylocker = 0;
 	int show_gpio_diffs = 0;
 	size_t pcr_count = 0;
 	uint8_t dump_pcr[MAX_PCR_PORTS];
@@ -719,10 +720,11 @@
 		{"sgx", 0, 0, 'x'},
 		{"pcr", required_argument, 0, LONG_OPT_PCR},
 		{"tme", 0, 0, 't'},
+		{"keylocker", 0, 0, 'k'},
 		{0, 0, 0, 0}
 	};
 
-	while ((opt = getopt_long(argc, argv, "vh?gGrplmedPMaAsfRS:xt",
+	while ((opt = getopt_long(argc, argv, "vh?gGrplmedPMaAsfRS:xtk",
                                   long_options, &option_index)) != EOF) {
 		switch (opt) {
 		case 'v':
@@ -803,6 +805,7 @@
 			dump_ahci = 1;
 			dump_sgx = 1;
 			dump_tme = 1;
+			dump_keylocker = 1;
 			break;
 		case 'A':
 			dump_ambs = 1;
@@ -816,6 +819,9 @@
 		case 't':
 			dump_tme = 1;
 			break;
+		case 'k':
+			dump_keylocker = 1;
+			break;
 		case LONG_OPT_PCR:
 			if (pcr_count < MAX_PCR_PORTS) {
 				errno = 0;
@@ -1011,6 +1017,9 @@
 	if (dump_tme)
 		print_tme();
 
+	if (dump_keylocker)
+		print_keylocker();
+
 	if (pcr_count)
 		print_pcr_ports(sb, dump_pcr, pcr_count);
 
diff --git a/util/inteltool/inteltool.h b/util/inteltool/inteltool.h
index 5b40721..130e63c 100644
--- a/util/inteltool/inteltool.h
+++ b/util/inteltool/inteltool.h
@@ -498,6 +498,7 @@
 int print_ahci(struct pci_dev *ahci);
 int print_sgx(void);
 void print_tme(void);
+void print_keylocker(void);
 void ivybridge_dump_timings(const char *dump_spd_file);
 
 #endif