vboot: Add VBOOT_CBFS_INTEGRATION support

This patch introduces support signing and verification of firmware
slots using CBFS metadata hash verification method for faster initial
verification. To have complete verification, CBFS_VERIFICATION should
also be enabled, as metadata hash covers only files metadata, not their
contents.

This patch also adapts mainboards and SoCs to new vboot reset
requirements.

TEST=Google Volteer/Voxel boots with VBOOT_CBFS_INTEGRATION enabled

Signed-off-by: Jakub Czapiga <jacz@semihalf.com>
Change-Id: I40ae01c477c4e4f7a1c90e4026a8a868ae64b5ca
Reviewed-on: https://review.coreboot.org/c/coreboot/+/66909
Reviewed-by: Yu-Ping Wu <yupingso@google.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
diff --git a/src/security/vboot/vboot_logic.c b/src/security/vboot/vboot_logic.c
index 660b7da..98a044c 100644
--- a/src/security/vboot/vboot_logic.c
+++ b/src/security/vboot/vboot_logic.c
@@ -54,7 +54,7 @@
 	return VB2_SUCCESS;
 }
 
-static int handle_digest_result(void *slot_hash, size_t slot_hash_sz)
+static vb2_error_t handle_digest_result(void *slot_hash, size_t slot_hash_sz)
 {
 	int is_resume;
 
@@ -63,14 +63,14 @@
 	 * vboot_retrieve_hash(), if Chrome EC is not enabled then return.
 	 */
 	if (!CONFIG(EC_GOOGLE_CHROMEEC))
-		return 0;
+		return VB2_SUCCESS;
 
 	/*
 	 * Nothing to do since resuming on the platform doesn't require
 	 * vboot verification again.
 	 */
 	if (!CONFIG(RESUME_PATH_SAME_AS_BOOT))
-		return 0;
+		return VB2_SUCCESS;
 
 	/*
 	 * Assume that if vboot doesn't start in bootblock verified
@@ -78,7 +78,7 @@
 	 * lives in RO CBFS.
 	 */
 	if (!CONFIG(VBOOT_STARTS_IN_BOOTBLOCK))
-		return 0;
+		return VB2_SUCCESS;
 
 	is_resume = platform_is_resuming();
 
@@ -92,12 +92,12 @@
 
 		if (vboot_retrieve_hash(saved_hash, saved_hash_sz)) {
 			printk(BIOS_ERR, "Couldn't retrieve saved hash.\n");
-			return -1;
+			return VB2_ERROR_UNKNOWN;
 		}
 
 		if (memcmp(saved_hash, slot_hash, slot_hash_sz)) {
 			printk(BIOS_ERR, "Hash mismatch on resume.\n");
-			return -1;
+			return VB2_ERROR_UNKNOWN;
 		}
 	} else if (is_resume < 0)
 		printk(BIOS_ERR, "Unable to determine if platform resuming.\n");
@@ -111,10 +111,10 @@
 		 * lead to a reboot loop. The consequence of this is that
 		 * we will most likely fail resuming because of EC issues or
 		 * the hash digest not matching. */
-		return 0;
+		return VB2_SUCCESS;
 	}
 
-	return 0;
+	return VB2_SUCCESS;
 }
 
 static vb2_error_t hash_body(struct vb2_context *ctx,
@@ -179,10 +179,7 @@
 
 	timestamp_add_now(TS_HASH_BODY_END);
 
-	if (handle_digest_result(hash_digest, hash_digest_sz))
-		return VB2_ERROR_UNKNOWN;
-
-	return VB2_SUCCESS;
+	return handle_digest_result(hash_digest, hash_digest_sz);
 }
 
 static uint32_t extend_pcrs(struct vb2_context *ctx)
@@ -236,16 +233,10 @@
 		ctx->flags |= VB2_CONTEXT_EC_TRUSTED;
 }
 
-/**
- * Verify and select the firmware in the RW image
- *
- * TODO: Avoid loading a stage twice (once in hash_body & again in load_stage).
- * when per-stage verification is ready.
- */
+/* Verify and select the firmware in the RW image */
 void verstage_main(void)
 {
 	struct vb2_context *ctx;
-	struct region_device fw_body;
 	vb2_error_t rv;
 
 	timestamp_add_now(TS_VBOOT_START);
@@ -326,7 +317,6 @@
 			extend_pcrs(ctx); /* ignore failures */
 			goto verstage_main_exit;
 		}
-
 		vboot_save_and_reboot(ctx, rv);
 	}
 
@@ -345,12 +335,22 @@
 		vboot_save_and_reboot(ctx, rv);
 
 	printk(BIOS_INFO, "Phase 4\n");
-	rv = vboot_locate_firmware(ctx, &fw_body);
-	if (rv)
-		die_with_post_code(POST_INVALID_ROM,
-			"Failed to read FMAP to locate firmware");
+	if (CONFIG(VBOOT_CBFS_INTEGRATION)) {
+		struct vb2_hash *metadata_hash;
+		rv = vb2api_get_metadata_hash(ctx, &metadata_hash);
+		if (rv == VB2_SUCCESS)
+			rv = handle_digest_result(metadata_hash->raw,
+						  vb2_digest_size(metadata_hash->algo));
+	} else {
+		struct region_device fw_body;
+		rv = vboot_locate_firmware(ctx, &fw_body);
+		if (rv)
+			die_with_post_code(POST_INVALID_ROM,
+					   "Failed to read FMAP to locate firmware");
 
-	rv = hash_body(ctx, &fw_body);
+		rv = hash_body(ctx, &fw_body);
+	}
+
 	if (rv)
 		vboot_save_and_reboot(ctx, rv);
 	vboot_save_data(ctx);