futility: update: Add "servo_noreset" opt to tell CCD not to reset

As can be seen in <https://crrev.com/c/2325190>, flashrom can take a
"custom_rst=true" parameter.  Flashrom passes this on to Cr50 and
tells it not to reset.  Among other things, this can be useful to work
around hardware bugs where asserting reset puts us in a bad state.

Let's add a parameter to futility can specify this mode.  We'll enable
this just for "--servo" mode of flashrom and not "--ccd" mode.
Presumably we want "--ccd" to remain simple / autoconfiguring and this
is a bit more of an advanced tweak.

BRANCH=None
BUG=b:177664356
TEST=Can flash coachz with futility

Change-Id: Iab188a92c4eae6373d38fe68ee4107f3e8aa5851
Signed-off-by: Douglas Anderson <dianders@chromium.org>
Disallow-Recycled-Builds: test-failures
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/2638108
Reviewed-by: Hung-Te Lin <hungte@chromium.org>
Reviewed-by: Bob Moragues <moragues@chromium.org>
diff --git a/futility/cmd_update.c b/futility/cmd_update.c
index 3d99664..57fa083 100644
--- a/futility/cmd_update.c
+++ b/futility/cmd_update.c
@@ -31,6 +31,7 @@
 	OPT_QUIRKS_LIST,
 	OPT_REPACK,
 	OPT_SERVO,
+	OPT_SERVO_NORESET,
 	OPT_SERVO_PORT,
 	OPT_SIGNATURE,
 	OPT_SYS_PROPS,
@@ -54,6 +55,7 @@
 
 	{"ccd", 0, NULL, OPT_CCD},
 	{"servo", 0, NULL, OPT_SERVO},
+	{"servo_noreset", 0, NULL, OPT_SERVO_NORESET},
 	{"servo_port", 1, NULL, OPT_SERVO_PORT},
 	{"emulate", 1, NULL, OPT_EMULATE},
 	{"factory", 0, NULL, OPT_FACTORY},
@@ -130,6 +132,7 @@
 		"    --gbb_flags=FLAG\tOverride new GBB flags\n"
 		"    --ccd           \tDo fast,force,wp=0,p=raiden_debug_spi\n"
 		"    --servo         \tFlash using Servo (v2, v4, micro, ...)\n"
+		"    --servo_noreset \tLike servo but with 'custom_rst=true'\n"
 		"    --servo_port=PRT\tOverride servod port, implies --servo\n"
 		"    --signature_id=S\tOverride signature ID for key files\n"
 		"    --sys_props=LIST\tList of system properties to override\n"
@@ -139,12 +142,29 @@
 		argv[0]);
 }
 
+static char *add_servo_noreset(char *programmer)
+{
+	char *ret;
+
+	if (strstr(programmer, "raiden_debug_spi:target=AP") == NULL) {
+		ERROR("servo_noreset only works for AP flashing over CCD.\n");
+		free(programmer);
+
+		return NULL;
+	}
+
+	ASPRINTF(&ret, "%s,custom_rst=true", programmer);
+	free(programmer);
+
+	return ret;
+}
+
 static int do_update(int argc, char *argv[])
 {
 	struct updater_config *cfg;
 	struct updater_config_arguments args = {0};
 	int i, errorcnt = 0, do_update = 1;
-	int detect_servo = 0, do_servo_cpu_fw_spi = 0;
+	int detect_servo = 0, do_servo_cpu_fw_spi = 0, servo_noreset = 0;
 	char *servo_programmer = NULL;
 	char *endptr;
 
@@ -255,6 +275,14 @@
 			args.host_only = 1;
 			detect_servo = 1;
 			break;
+		case OPT_SERVO_NORESET:
+			args.fast_update = 1;
+			args.force_update = 1;
+			args.write_protection = "0";
+			args.host_only = 1;
+			detect_servo = 1;
+			servo_noreset = 1;
+			break;
 		case OPT_SERVO_PORT:
 			setenv(ENV_SERVOD_PORT, optarg, 1);
 			args.fast_update = 1;
@@ -289,6 +317,10 @@
 
 	if (!errorcnt && detect_servo) {
 		servo_programmer = host_detect_servo(&do_servo_cpu_fw_spi);
+
+		if (servo_programmer && servo_noreset)
+			servo_programmer = add_servo_noreset(servo_programmer);
+
 		if (!servo_programmer)
 			errorcnt++;
 		else if (!args.programmer)