Use Memcpy to access the fw_versions member of RollbackSpaceFirmware.

This structure has two uint8_t members and then fw_versions which is a
uint32_t. That means that fw_versions is 32 bits wide but only has 16 bit
alignment, and architectures that care about that sort of thing won't be able
to access it. ARM generally cares about alignment, but there's a bit which
lets you select whether 32 bit accesses can be unaligned. In the past this bit
was ignored, and because this is a 32 bit data type the right load happened to
be used.

To avoid the unaligned access all together, this change makes vboot use Memcpy
to access fw_versions. The number of accesses should be very small so the
overhead should be minimal.

BUG=chrome-os-partner:17340
TEST=Built and booted depthcharge on Snow. Without this change, there was an
unaligned exception during SetupTPM when the fw_versions member was accessed
as part of a VBDEBUG call. With this change, the exception went away and the
TPM was initialized successfully.
BRANCH=None

Change-Id: I1ed705f2de450c65f986c1c7ba30da15c0150f74
Signed-off-by: Gabe Black <gabeblack@google.com>
Reviewed-on: https://gerrit.chromium.org/gerrit/44499
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Commit-Queue: Gabe Black <gabeblack@chromium.org>
Tested-by: Gabe Black <gabeblack@chromium.org>
diff --git a/firmware/lib/rollback_index.c b/firmware/lib/rollback_index.c
index 0c6e02a..4047bc3 100644
--- a/firmware/lib/rollback_index.c
+++ b/firmware/lib/rollback_index.c
@@ -352,6 +352,7 @@
 	uint8_t disable;
 	uint8_t deactivated;
 	uint32_t result;
+	uint32_t versions;
 
 	VBDEBUG(("TPM: SetupTPM(r%d, d%d)\n", recovery_mode, developer_mode));
 
@@ -434,8 +435,9 @@
 		VBDEBUG(("TPM: Firmware space in a bad state; giving up.\n"));
 		return TPM_E_CORRUPTED_STATE;
 	}
+	Memcpy(&versions, &rsf->fw_versions, sizeof(versions));
 	VBDEBUG(("TPM: Firmware space sv%d f%x v%x\n",
-		 rsf->struct_version, rsf->flags, rsf->fw_versions));
+		 rsf->struct_version, rsf->flags, versions));
 	in_flags = rsf->flags;
 
 	/* If we've been asked to clear the virtual dev-mode flag, do so now */
@@ -577,20 +579,22 @@
 	RETURN_ON_FAILURE(SetupTPM(recovery_mode, is_hw_dev,
 				   disable_dev_request,
 				   clear_tpm_owner_request, &rsf));
-	*version = rsf.fw_versions;
+	Memcpy(version, &rsf.fw_versions, sizeof(*version));
 	*is_virt_dev = (rsf.flags & FLAG_VIRTUAL_DEV_MODE_ON) ? 1 : 0;
-	VBDEBUG(("TPM: RollbackFirmwareSetup %x\n", (int)rsf.fw_versions));
+	VBDEBUG(("TPM: RollbackFirmwareSetup %x\n", (int)*version));
 	return TPM_SUCCESS;
 }
 
 uint32_t RollbackFirmwareWrite(uint32_t version)
 {
 	RollbackSpaceFirmware rsf;
+	uint32_t old_version;
 
 	RETURN_ON_FAILURE(ReadSpaceFirmware(&rsf));
-	VBDEBUG(("TPM: RollbackFirmwareWrite %x --> %x\n", (int)rsf.fw_versions,
+	Memcpy(&old_version, &rsf.fw_versions, sizeof(old_version));
+	VBDEBUG(("TPM: RollbackFirmwareWrite %x --> %x\n", (int)old_version,
 		 (int)version));
-	rsf.fw_versions = version;
+	Memcpy(&rsf.fw_versions, &version, sizeof(version));
 	return WriteSpaceFirmware(&rsf);
 }