security/intel/txt: Correct reporting of chipset production fuse state

Implement the chipset production fuse state reporting as described in
the Intel TXT Software Development Guide. Also fix all occurrences
where the production fuse state is checked.

TEST=Dell OptiPlex 9010 with i7-3770/Q77 reports the chipset is
production fused

Signed-off-by: Michał Żygowski <michal.zygowski@3mdeb.com>
Change-Id: Ic86c5a9e1d162630a1cf61435d1014edabf104b0
Reviewed-on: https://review.coreboot.org/c/coreboot/+/59514
Reviewed-by: Patrick Rudolph <siro@das-labor.org>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
diff --git a/src/security/intel/txt/common.c b/src/security/intel/txt/common.c
index e3e2f5c..7e6c55c 100644
--- a/src/security/intel/txt/common.c
+++ b/src/security/intel/txt/common.c
@@ -141,6 +141,22 @@
 	return ret;
 }
 
+bool intel_txt_chipset_is_production_fused(void)
+{
+	/*
+	 * Certain chipsets report production fused information in either
+	 * TXT.VER.FSBIF or TXT.VER.EMIF/TXT.VER.QPIIF.
+	 * Chapter B.1.7 and B.1.9
+	 * Intel TXT Software Development Guide (Document: 315168-015)
+	 */
+	uint32_t reg = read32((void *)TXT_VER_FSBIF);
+
+	if (reg == 0 || reg == UINT32_MAX)
+		reg = read32((void *)TXT_VER_QPIIF);
+
+	return (reg & TXT_VER_PRODUCTION_FUSED) ? true : false;
+}
+
 static struct acm_info_table *find_info_table(const void *ptr)
 {
 	const struct acm_header_v0 *acm_header = (struct acm_header_v0 *)ptr;
@@ -203,8 +219,8 @@
 	if (memcmp(acm_uuid, info->uuid, sizeof(acm_uuid)) != 0)
 		return ACM_E_UUID_NOT_MATCH;
 
-	if ((acm_header->flags & ACM_FORMAT_FLAGS_DEBUG) ==
-	    (read64((void *)TXT_VER_FSBIF) & TXT_VER_PRODUCTION_FUSED))
+	const bool production_acm = !(acm_header->flags & ACM_FORMAT_FLAGS_DEBUG);
+	if (production_acm != intel_txt_chipset_is_production_fused())
 		return ACM_E_PLATFORM_IS_NOT_PROD;
 
 	return 0;