futility: updater: always set new boot/try cookies

If the update target is same as the active image, the firmware updater
will do nothing on vboot2. However, if the system already have
fw_try_next set to other slot (for example after multiple updates
applied without rebooting) then the next boot will not pick the right
firmware. So we have to ensure fw_try_next is set to right value.
In the meantime, if fw_try_count and fw_result are not configured at the
same time, the system may start "trying" again and increase the chance
to fail.

To fix that, we should clear trial cookies when there is no update, just
like chromeos-setgoodfirmware.

BUG=b:162866548
TEST=make runtests
BRANCH=None

Signed-off-by: Hung-Te Lin <hungte@chromium.org>
Change-Id: I41ecac445000a850d050d77f0f694ee431926424
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/2340172
Reviewed-by: Joel Kitching <kitching@chromium.org>
Reviewed-by: Jack Rosenthal <jrosenth@chromium.org>
diff --git a/futility/updater.c b/futility/updater.c
index 49a94b8..10efd63 100644
--- a/futility/updater.c
+++ b/futility/updater.c
@@ -270,7 +270,7 @@
  * Returns 0 if success, non-zero if error.
  */
 static int set_try_cookies(struct updater_config *cfg, const char *target,
-			   int is_vboot2)
+			   int has_update, int is_vboot2)
 {
 	int tries = 6;
 	const char *slot;
@@ -279,6 +279,9 @@
 	if (cfg->ec_image.data)
 		tries += 2;
 
+	if (!has_update)
+		tries = 0;
+
 	/* Find new slot according to target (section) name. */
 	if (strcmp(target, FMAP_RW_SECTION_A) == 0)
 		slot = FWACT_A;
@@ -290,19 +293,29 @@
 	}
 
 	if (cfg->emulation) {
-		INFO("(emulation) Setting try_next to %s, try_count to %d.\n",
-		     slot, tries);
+		INFO("(emulation) %s slot %s on next boot, try_count=%d.\n",
+		     has_update ? "Try" : "Keep", slot, tries);
 		return 0;
 	}
 
-	if (is_vboot2 && VbSetSystemPropertyString("fw_try_next", slot)) {
-		ERROR("Failed to set fw_try_next to %s.\n", slot);
-		return -1;
+	if (is_vboot2) {
+		if (VbSetSystemPropertyString("fw_try_next", slot)) {
+			ERROR("Failed to set fw_try_next to %s.\n", slot);
+			return -1;
+		}
+		if (!has_update &&
+		    VbSetSystemPropertyString("fw_result", "success")) {
+			ERROR("Failed to set fw_result to success.\n");
+			return -1;
+		}
 	}
+
+	/* fw_try_count is identical to fwb_tries in vboot1. */
 	if (VbSetSystemPropertyInt("fw_try_count", tries)) {
 		ERROR("Failed to set fw_try_count to %d.\n", tries);
 		return -1;
 	}
+
 	return 0;
 }
 
@@ -1019,14 +1032,12 @@
 
 		if (write_firmware(cfg, image_to, target))
 			return UPDATE_ERR_WRITE_FIRMWARE;
-		if (set_try_cookies(cfg, target, is_vboot2))
-			return UPDATE_ERR_SET_COOKIES;
-	} else {
-		/* Clear trial cookies for vboot1. */
-		if (!is_vboot2 && !cfg->emulation)
-			VbSetSystemPropertyInt("fwb_tries", 0);
 	}
 
+	/* Always set right cookies for next boot. */
+	if (set_try_cookies(cfg, target, has_update, is_vboot2))
+		return UPDATE_ERR_SET_COOKIES;
+
 	/* Do not fail on updating legacy. */
 	if (legacy_needs_update(cfg)) {
 		has_update = 1;