security/vboot: Update vbnv_init signature

If the temporary nvdata storage inside the vboot context is already
initialized then return immediately without reinitializing from the
backup NV storage. This allows vbnv_init to be called more than once.

Also the check to enable USB Device Controller (UDC) happens after
NVdata is initialized. Hence the nvdata in vboot context can be used
instead of reading from the backup storage again.

BUG=b:242825052
TEST=Build Skyrim BIOS image and boot to OS in Skyrim.

Change-Id: Id72709e2fc3fe6a12ee96df8df25e55cf11e50a7
Signed-off-by: Karthikeyan Ramasubramanian <kramasub@google.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/70380
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Yu-Ping Wu <yupingso@google.com>
Reviewed-by: Julius Werner <jwerner@chromium.org>
diff --git a/src/security/vboot/vbnv.c b/src/security/vboot/vbnv.c
index e9223c0..1428a30 100644
--- a/src/security/vboot/vbnv.c
+++ b/src/security/vboot/vbnv.c
@@ -3,11 +3,12 @@
 #include <assert.h>
 #include <string.h>
 #include <types.h>
+#include <security/vboot/misc.h>
 #include <security/vboot/vbnv.h>
 #include <security/vboot/vbnv_layout.h>
+#include <vb2_api.h>
 
-static int vbnv_initialized;
-static uint8_t vbnv[VBOOT_VBNV_BLOCK_SIZE];
+static bool vbnv_initialized;
 
 /* Return CRC-8 of the data, using x^8 + x^2 + x + 1 polynomial. */
 static uint8_t crc8_vbnv(const uint8_t *data, int len)
@@ -32,15 +33,6 @@
 	memset(vbnv_copy, 0, VBOOT_VBNV_BLOCK_SIZE);
 }
 
-/* Read VBNV data into cache. */
-static void vbnv_setup(void)
-{
-	if (!vbnv_initialized) {
-		read_vbnv(vbnv);
-		vbnv_initialized = 1;
-	}
-}
-
 /* Verify VBNV header and checksum. */
 int verify_vbnv(uint8_t *vbnv_copy)
 {
@@ -84,21 +76,31 @@
 		save_vbnv_flash(vbnv_copy);
 	else
 		dead_code();
-
-	/* Clear initialized flag to force cached data to be updated */
-	vbnv_initialized = 0;
 }
 
 /* Read the USB Device Controller(UDC) enable flag from VBNV. */
 int vbnv_udc_enable_flag(void)
 {
-	vbnv_setup();
-	return (vbnv[DEV_FLAGS_OFFSET] & DEV_ENABLE_UDC) ? 1 : 0;
+	struct vb2_context *ctx = vboot_get_context();
+
+	/* This function is expected to be called after temporary nvdata storage in vboot
+	   context is initialized. */
+	assert(vbnv_initialized);
+
+	return (ctx->nvdata[DEV_FLAGS_OFFSET] & DEV_ENABLE_UDC) ? 1 : 0;
 }
 
-void vbnv_init(uint8_t *vbnv_copy)
+void vbnv_init(void)
 {
+	struct vb2_context *ctx;
+
+	/* NV data already initialized and read */
+	if (vbnv_initialized)
+		return;
+
+	ctx = vboot_get_context();
 	if (CONFIG(VBOOT_VBNV_CMOS))
-		vbnv_init_cmos(vbnv_copy);
-	read_vbnv(vbnv_copy);
+		vbnv_init_cmos(ctx->nvdata);
+	read_vbnv(ctx->nvdata);
+	vbnv_initialized = true;
 }
diff --git a/src/security/vboot/vbnv.h b/src/security/vboot/vbnv.h
index eb435e2..c4112a2 100644
--- a/src/security/vboot/vbnv.h
+++ b/src/security/vboot/vbnv.h
@@ -15,7 +15,7 @@
 int vbnv_udc_enable_flag(void);
 
 /* Initialize and read vbnv. This is used in the main vboot logic path. */
-void vbnv_init(uint8_t *vbnv_copy);
+void vbnv_init(void);
 /* Reset vbnv snapshot to a known state. */
 void vbnv_reset(uint8_t *vbnv_copy);
 
diff --git a/src/security/vboot/vboot_logic.c b/src/security/vboot/vboot_logic.c
index f7b4801..a72ea87 100644
--- a/src/security/vboot/vboot_logic.c
+++ b/src/security/vboot/vboot_logic.c
@@ -249,7 +249,7 @@
 	ctx = vboot_get_context();
 
 	/* Initialize and read nvdata from non-volatile storage. */
-	vbnv_init(ctx->nvdata);
+	vbnv_init();
 
 	/* Set S3 resume flag if vboot should behave differently when selecting
 	 * which slot to boot.  This is only relevant to vboot if the platform