vboot2: factory-initialize kernel space in tpm

This change makes coreboot initialize kernel space and backup space in the tpm
when no firmware space is found in the tpm.

Added a few extra debug messages as a bonus.

BUG=chrome-os-partner:32410,chrome-os-partner:57777
TEST=emerge-nyan_kitty coreboot
BRANCH=firmware-kitty-5771.61.B

Signed-off-by: Daisuke Nojiri <dnojiri@chromium.org>

Original-Change-Id: I777e3cb7004870c769163827543c83665d3732b9
Original-Reviewed-on: https://chromium-review.googlesource.com/220412
Original-Reviewed-by: Julius Werner <jwerner@chromium.org>
Original-Reviewed-by: Randall Spangler <rspangler@chromium.org>
Original-Commit-Queue: Daisuke Nojiri <dnojiri@chromium.org>
Original-Tested-by: Daisuke Nojiri <dnojiri@chromium.org>
(cherry picked from commit d8c0c407bf0fed60d76441ada7bedd36f6fc3a38)

Change-Id: Ic53f4747d792b72f05d50e602d0d18652e236fa4
Reviewed-on: https://chromium-review.googlesource.com/394270
Reviewed-by: Andrey Pronin <apronin@chromium.org>
Commit-Queue: Daisuke Nojiri <dnojiri@chromium.org>
Tested-by: Daisuke Nojiri <dnojiri@chromium.org>
diff --git a/src/include/antirollback.h b/src/include/antirollback.h
index 7437806..31a6a82 100644
--- a/src/include/antirollback.h
+++ b/src/include/antirollback.h
@@ -17,6 +17,9 @@
 
 /* TPM NVRAM location indices. */
 #define FIRMWARE_NV_INDEX               0x1007
+#define KERNEL_NV_INDEX                 0x1008
+/* This is just an opaque space for backup purposes */
+#define BACKUP_NV_INDEX                 0x1009
 
 /* Structure definitions for TPM spaces */
 
diff --git a/src/vendorcode/google/chromeos/antirollback.c b/src/vendorcode/google/chromeos/antirollback.c
index 08945f6..ac81055 100644
--- a/src/vendorcode/google/chromeos/antirollback.c
+++ b/src/vendorcode/google/chromeos/antirollback.c
@@ -34,7 +34,6 @@
 		}							\
 	} while (0)
 
-
 uint32_t tpm_extend_pcr(struct vb2_context *ctx, int pcr,
 			enum vb2_pcr_digest which_digest)
 {
@@ -101,30 +100,36 @@
 	return TPM_E_CORRUPTED_STATE;
 }
 
-static uint32_t write_space_firmware(struct vb2_context *ctx)
+static uint32_t write_secdata(uint32_t index,
+			      const uint8_t *secdata,
+			      uint32_t len)
 {
-	uint8_t secdata[VB2_SECDATA_SIZE];
-	uint32_t r;
+	uint8_t sd[32];
+	uint32_t rv;
 	int attempts = 3;
 
-	memcpy(secdata, ctx->secdata, VB2_SECDATA_SIZE);
+	if (len > sizeof(sd)) {
+		VBDEBUG("TPM: %s() - data is too large\n", __func__);
+		return TPM_E_WRITE_FAILURE;
+	}
+
 	while (attempts--) {
-		r = safe_write(FIRMWARE_NV_INDEX, secdata, VB2_SECDATA_SIZE);
+		rv = safe_write(index, secdata, len);
 		/* Can't write, not gonna try again */
-		if (r != TPM_SUCCESS)
-			return r;
+		if (rv != TPM_SUCCESS)
+			return rv;
 
 		/* Read it back to be sure it got the right values. */
-		r = read_space_firmware(ctx);
-		if (r == TPM_SUCCESS && memcmp(secdata, ctx->secdata,
-		                               VB2_SECDATA_SIZE) == 0)
-			return r;
+		rv = tlcl_read(index, sd, len);
+		if (rv == TPM_SUCCESS && memcmp(secdata, sd, len) == 0)
+			return rv;
 
-		VBDEBUG("TPM: %s() failed\n", __func__);
+		VBDEBUG("TPM: %s() failed. trying again\n", __func__);
 		/* Try writing it again. Maybe it was garbled on the way out. */
 	}
 
 	VBDEBUG("TPM: %s() - too many failures, giving up\n", __func__);
+
 	return TPM_E_CORRUPTED_STATE;
 }
 
@@ -132,6 +137,15 @@
 {
 	TPM_PERMANENT_FLAGS pflags;
 	uint32_t result;
+	/* this is derived from rollback_index.h of vboot_reference. see struct
+	 * RollbackSpaceKernel for details. */
+	static const uint8_t secdata_kernel[] = {
+			0x02,
+			0x4C, 0x57, 0x52, 0x47,
+			0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00,
+			0xE8,
+	};
 
 	VBDEBUG("TPM: factory initialization\n");
 
@@ -177,13 +191,31 @@
 	VBDEBUG("TPM: Clearing owner\n");
 	RETURN_ON_FAILURE(tpm_clear_and_reenable());
 
+	/* Define the backup space. No need to initialize it, though. */
+	RETURN_ON_FAILURE(safe_define_space(BACKUP_NV_INDEX,
+					    TPM_NV_PER_PPWRITE,
+					    VB2_NVDATA_SIZE));
+
+	/* Define and initialize the kernel space */
+	RETURN_ON_FAILURE(safe_define_space(KERNEL_NV_INDEX,
+					    TPM_NV_PER_PPWRITE,
+					    sizeof(secdata_kernel)));
+	RETURN_ON_FAILURE(write_secdata(KERNEL_NV_INDEX,
+					secdata_kernel,
+					sizeof(secdata_kernel)));
+	VBDEBUG("TPM: Kernel space initialized\n");
+
 	/* Defines and sets vb2 secdata space */
 	vb2api_secdata_create(ctx);
 	RETURN_ON_FAILURE(safe_define_space(FIRMWARE_NV_INDEX,
-	                                    TPM_NV_PER_GLOBALLOCK |
-	                                    TPM_NV_PER_PPWRITE,
-	                                    VB2_SECDATA_SIZE));
-	RETURN_ON_FAILURE(write_space_firmware(ctx));
+					    TPM_NV_PER_GLOBALLOCK |
+					    TPM_NV_PER_PPWRITE,
+					    VB2_SECDATA_SIZE));
+	RETURN_ON_FAILURE(write_secdata(FIRMWARE_NV_INDEX,
+					ctx->secdata,
+					VB2_SECDATA_SIZE));
+
+	VBDEBUG("TPM: Firmware space initialized\n");
 
 	return TPM_SUCCESS;
 }
@@ -294,6 +326,7 @@
 		 */
 		VBDEBUG("TPM: Not initialized yet.\n");
 		RETURN_ON_FAILURE(factory_initialize_tpm(ctx));
+		VBDEBUG("TPM: factory initialization successful\n");
 	} else if (rv != TPM_SUCCESS) {
 		VBDEBUG("TPM: Firmware space in a bad state; giving up.\n");
 		//RETURN_ON_FAILURE(factory_initialize_tpm(ctx));
@@ -305,7 +338,7 @@
 
 uint32_t antirollback_write_space_firmware(struct vb2_context *ctx)
 {
-	return write_space_firmware(ctx);
+	return write_secdata(FIRMWARE_NV_INDEX, ctx->secdata, VB2_SECDATA_SIZE);
 }
 
 uint32_t antirollback_lock_space_firmware()