Software sync checks for shutdown-requested in all code paths

Previously,
1) AP-RO, EC-RO -> checked
2) AP-RW, EC-RO transition to EC-RW -> checked
3) AP-RW, EC-RW already -> NOT checked

Now, (3) calls VbExIsShutdownRequested() as well.

This fix is needed to avoid inconsistent behavior of software sync
after we ship a RW update.

Whether we *should* actually shut down or not based on how/why we
booted is a separate issue to be addressed by the U-boot
implementation of VbExIsShutdownRequested() in a separate CL.

BUG=chromium-os:38645
BRANCH=all
TEST=make runtests

Manual testing also possible - force AP-RW firmware, then reboot with
lid closed.  Previously, the first boot would shut down because of
(2), but subsequent reboots of the AP only wouldn't because of (3).

Change-Id: I226202f48d793b88a30ffa62731de878f8c22315
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/43044
Reviewed-by: Simon Glass <sjg@chromium.org>
diff --git a/firmware/lib/vboot_api_kernel.c b/firmware/lib/vboot_api_kernel.c
index 9b596fc..a55d806 100644
--- a/firmware/lib/vboot_api_kernel.c
+++ b/firmware/lib/vboot_api_kernel.c
@@ -742,6 +742,18 @@
 		}
 
 		VBDEBUG(("VbEcSoftwareSync() in EC-RW and it matches\n"));
+
+		/*
+		 * If shutdown is requested, just power the AP back off.  This
+		 * covers the case where the lid is closed when then system
+		 * boots.
+		 */
+		if (VbExIsShutdownRequested()) {
+			VBDEBUG(("VbEcSoftwareSync() "
+				 "sees shutdown-requested\n"));
+			return VBERROR_SHUTDOWN_REQUESTED;
+		}
+
 		return VBERROR_SUCCESS;
 	}
 
diff --git a/tests/vboot_api_kernel3_tests.c b/tests/vboot_api_kernel3_tests.c
index 836a48d..9ec6f19 100644
--- a/tests/vboot_api_kernel3_tests.c
+++ b/tests/vboot_api_kernel3_tests.c
@@ -35,6 +35,7 @@
 static int update_retval;
 static int ec_updated;
 static int get_expected_retval;
+static int shutdown_request_calls_left;
 
 static uint8_t mock_ec_hash[32];
 static int mock_ec_hash_size;
@@ -79,6 +80,7 @@
 	update_retval = VBERROR_SUCCESS;
 	run_retval = VBERROR_SUCCESS;
 	get_expected_retval = VBERROR_SUCCESS;
+	shutdown_request_calls_left = -1;
 
 	Memset(mock_ec_hash, 0, sizeof(mock_ec_hash));
 	mock_ec_hash[0] = 42;
@@ -99,6 +101,16 @@
 
 /* Mock functions */
 
+uint32_t VbExIsShutdownRequested(void)
+{
+	if (shutdown_request_calls_left == 0)
+		return 1;
+	else if (shutdown_request_calls_left > 0)
+		shutdown_request_calls_left--;
+
+	return 0;
+}
+
 int VbExTrustEC(void)
 {
 	return trust_ec;
@@ -232,6 +244,11 @@
 	test_ssync(VBERROR_SIMULATED,
 		   VBNV_RECOVERY_EC_PROTECT, "Protect error");
 
+	ResetMocks();
+	shared->flags |= VBSD_LF_USE_RO_NORMAL;
+	shutdown_request_calls_left = 0;
+	test_ssync(VBERROR_SHUTDOWN_REQUESTED, 0, "AP-RO shutdown requested");
+
 	/* Calculate hashes */
 	ResetMocks();
 	mock_ec_hash_size = 0;
@@ -325,6 +342,16 @@
 	protect_retval = VBERROR_SIMULATED;
 	test_ssync(VBERROR_SIMULATED,
 		   VBNV_RECOVERY_EC_PROTECT, "Protect error");
+
+	ResetMocks();
+	shutdown_request_calls_left = 0;
+	test_ssync(VBERROR_SHUTDOWN_REQUESTED, 0,
+		   "AP-RW, EC-RO -> EC-RW shutdown requested");
+
+	ResetMocks();
+	mock_in_rw = 1;
+	shutdown_request_calls_left = 0;
+	test_ssync(VBERROR_SHUTDOWN_REQUESTED, 0, "AP-RW shutdown requested");
 }
 
 int main(void)