xref: /aosp_15_r20/external/vboot_reference/firmware/2lib/2ec_sync.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
1*8617a60dSAndroid Build Coastguard Worker /* Copyright 2013 The ChromiumOS Authors
2*8617a60dSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
3*8617a60dSAndroid Build Coastguard Worker  * found in the LICENSE file.
4*8617a60dSAndroid Build Coastguard Worker  *
5*8617a60dSAndroid Build Coastguard Worker  * EC software sync routines for vboot
6*8617a60dSAndroid Build Coastguard Worker  */
7*8617a60dSAndroid Build Coastguard Worker 
8*8617a60dSAndroid Build Coastguard Worker #include "2api.h"
9*8617a60dSAndroid Build Coastguard Worker #include "2common.h"
10*8617a60dSAndroid Build Coastguard Worker #include "2misc.h"
11*8617a60dSAndroid Build Coastguard Worker #include "2nvstorage.h"
12*8617a60dSAndroid Build Coastguard Worker #include "2secdata.h"
13*8617a60dSAndroid Build Coastguard Worker #include "2sysincludes.h"
14*8617a60dSAndroid Build Coastguard Worker 
15*8617a60dSAndroid Build Coastguard Worker #define SYNC_FLAG(select)					\
16*8617a60dSAndroid Build Coastguard Worker 	((select) == VB_SELECT_FIRMWARE_READONLY ?		\
17*8617a60dSAndroid Build Coastguard Worker 	 VB2_SD_FLAG_ECSYNC_EC_RO : VB2_SD_FLAG_ECSYNC_EC_RW)
18*8617a60dSAndroid Build Coastguard Worker 
19*8617a60dSAndroid Build Coastguard Worker /**
20*8617a60dSAndroid Build Coastguard Worker  * Print a hash to debug output
21*8617a60dSAndroid Build Coastguard Worker  *
22*8617a60dSAndroid Build Coastguard Worker  * @param hash		Pointer to the hash
23*8617a60dSAndroid Build Coastguard Worker  * @param hash_size	Size of the hash in bytes
24*8617a60dSAndroid Build Coastguard Worker  * @param desc		Description of what's being hashed
25*8617a60dSAndroid Build Coastguard Worker  */
print_hash(const uint8_t * hash,uint32_t hash_size)26*8617a60dSAndroid Build Coastguard Worker static void print_hash(const uint8_t *hash, uint32_t hash_size)
27*8617a60dSAndroid Build Coastguard Worker {
28*8617a60dSAndroid Build Coastguard Worker 	int i;
29*8617a60dSAndroid Build Coastguard Worker 	for (i = 0; i < hash_size; i++)
30*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG_RAW("%02x", hash[i]);
31*8617a60dSAndroid Build Coastguard Worker 	VB2_DEBUG_RAW("\n");
32*8617a60dSAndroid Build Coastguard Worker }
33*8617a60dSAndroid Build Coastguard Worker 
image_name_to_string(enum vb2_firmware_selection select)34*8617a60dSAndroid Build Coastguard Worker static const char *image_name_to_string(enum vb2_firmware_selection select)
35*8617a60dSAndroid Build Coastguard Worker {
36*8617a60dSAndroid Build Coastguard Worker 	switch (select) {
37*8617a60dSAndroid Build Coastguard Worker 	case VB_SELECT_FIRMWARE_READONLY:
38*8617a60dSAndroid Build Coastguard Worker 		return "RO";
39*8617a60dSAndroid Build Coastguard Worker 	case VB_SELECT_FIRMWARE_EC_ACTIVE:
40*8617a60dSAndroid Build Coastguard Worker 		return "RW(active)";
41*8617a60dSAndroid Build Coastguard Worker 	case VB_SELECT_FIRMWARE_EC_UPDATE:
42*8617a60dSAndroid Build Coastguard Worker 		return "RW(update)";
43*8617a60dSAndroid Build Coastguard Worker 	default:
44*8617a60dSAndroid Build Coastguard Worker 		return "UNKNOWN";
45*8617a60dSAndroid Build Coastguard Worker 	}
46*8617a60dSAndroid Build Coastguard Worker }
47*8617a60dSAndroid Build Coastguard Worker 
48*8617a60dSAndroid Build Coastguard Worker /**
49*8617a60dSAndroid Build Coastguard Worker  * Check if the hash of the EC code matches the expected hash.
50*8617a60dSAndroid Build Coastguard Worker  *
51*8617a60dSAndroid Build Coastguard Worker  * @param ctx		Vboot2 context
52*8617a60dSAndroid Build Coastguard Worker  * @param select	Which firmware image to check
53*8617a60dSAndroid Build Coastguard Worker  * @return VB2_SUCCESS, or non-zero error code.
54*8617a60dSAndroid Build Coastguard Worker  */
check_ec_hash(struct vb2_context * ctx,enum vb2_firmware_selection select)55*8617a60dSAndroid Build Coastguard Worker static vb2_error_t check_ec_hash(struct vb2_context *ctx,
56*8617a60dSAndroid Build Coastguard Worker 				 enum vb2_firmware_selection select)
57*8617a60dSAndroid Build Coastguard Worker {
58*8617a60dSAndroid Build Coastguard Worker 	struct vb2_shared_data *sd = vb2_get_sd(ctx);
59*8617a60dSAndroid Build Coastguard Worker 	const uint8_t *hexp = NULL;
60*8617a60dSAndroid Build Coastguard Worker 	const uint8_t *hmir = NULL;
61*8617a60dSAndroid Build Coastguard Worker 	const uint8_t *heff = NULL;
62*8617a60dSAndroid Build Coastguard Worker 	int hexp_len, heff_len;
63*8617a60dSAndroid Build Coastguard Worker 	const int hmir_len = VB2_SHA256_DIGEST_SIZE;
64*8617a60dSAndroid Build Coastguard Worker 	vb2_error_t rv;
65*8617a60dSAndroid Build Coastguard Worker 
66*8617a60dSAndroid Build Coastguard Worker 	/*
67*8617a60dSAndroid Build Coastguard Worker 	 * Get expected EC hash and length.
68*8617a60dSAndroid Build Coastguard Worker 	 */
69*8617a60dSAndroid Build Coastguard Worker 	VB2_TRY(vb2ex_ec_get_expected_image_hash(select, &hexp, &hexp_len),
70*8617a60dSAndroid Build Coastguard Worker 		ctx, VB2_RECOVERY_EC_EXPECTED_HASH);
71*8617a60dSAndroid Build Coastguard Worker 	VB2_DEBUG("Hexp %10s: ", image_name_to_string(select));
72*8617a60dSAndroid Build Coastguard Worker 	print_hash(hexp, hexp_len);
73*8617a60dSAndroid Build Coastguard Worker 
74*8617a60dSAndroid Build Coastguard Worker 	/*
75*8617a60dSAndroid Build Coastguard Worker 	 * Get mirrored EC hash. This returns NULL on old systems. On new
76*8617a60dSAndroid Build Coastguard Worker 	 * systems without EFS2, Hmir will be updated but unused.
77*8617a60dSAndroid Build Coastguard Worker 	 *
78*8617a60dSAndroid Build Coastguard Worker 	 * If it's called from update_ec, Hmir and Hexp are already synced.
79*8617a60dSAndroid Build Coastguard Worker 	 */
80*8617a60dSAndroid Build Coastguard Worker 	hmir = vb2_secdata_kernel_get_ec_hash(ctx);
81*8617a60dSAndroid Build Coastguard Worker 	if (hmir && select == VB_SELECT_FIRMWARE_EC_ACTIVE) {
82*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("     %10s: ", "Hmir");
83*8617a60dSAndroid Build Coastguard Worker 		print_hash(hmir, hmir_len);
84*8617a60dSAndroid Build Coastguard Worker 		if (hmir_len != hexp_len) {
85*8617a60dSAndroid Build Coastguard Worker 			VB2_DEBUG("Hmir size (%d) != Hexp size (%d)\n",
86*8617a60dSAndroid Build Coastguard Worker 				  hmir_len, hexp_len);
87*8617a60dSAndroid Build Coastguard Worker 			rv = VB2_ERROR_EC_HASH_SIZE;
88*8617a60dSAndroid Build Coastguard Worker 			vb2api_fail(ctx, VB2_RECOVERY_EC_HASH_SIZE, rv);
89*8617a60dSAndroid Build Coastguard Worker 			return rv;
90*8617a60dSAndroid Build Coastguard Worker 		}
91*8617a60dSAndroid Build Coastguard Worker 		if (vb2_safe_memcmp(hmir, hexp, hexp_len)) {
92*8617a60dSAndroid Build Coastguard Worker 			VB2_DEBUG("Hmir != Hexp. Update Hmir.\n");
93*8617a60dSAndroid Build Coastguard Worker 			vb2_secdata_kernel_set_ec_hash(ctx, hexp);
94*8617a60dSAndroid Build Coastguard Worker 			sd->flags |= VB2_SD_FLAG_ECSYNC_HMIR_UPDATED;
95*8617a60dSAndroid Build Coastguard Worker 		}
96*8617a60dSAndroid Build Coastguard Worker 	}
97*8617a60dSAndroid Build Coastguard Worker 
98*8617a60dSAndroid Build Coastguard Worker 	/*
99*8617a60dSAndroid Build Coastguard Worker 	 * Get effective EC hash and length.
100*8617a60dSAndroid Build Coastguard Worker 	 */
101*8617a60dSAndroid Build Coastguard Worker 	VB2_TRY(vb2ex_ec_hash_image(select, &heff, &heff_len),
102*8617a60dSAndroid Build Coastguard Worker 		ctx, VB2_RECOVERY_EC_HASH_FAILED);
103*8617a60dSAndroid Build Coastguard Worker 	VB2_DEBUG("Heff %10s: ", image_name_to_string(select));
104*8617a60dSAndroid Build Coastguard Worker 	print_hash(heff, heff_len);
105*8617a60dSAndroid Build Coastguard Worker 
106*8617a60dSAndroid Build Coastguard Worker 	/* Lengths should match. */
107*8617a60dSAndroid Build Coastguard Worker 	if (heff_len != hexp_len) {
108*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("EC uses %d-byte hash but AP-RW contains %d bytes\n",
109*8617a60dSAndroid Build Coastguard Worker 			  heff_len, hexp_len);
110*8617a60dSAndroid Build Coastguard Worker 		rv = VB2_ERROR_EC_HASH_SIZE;
111*8617a60dSAndroid Build Coastguard Worker 		vb2api_fail(ctx, VB2_RECOVERY_EC_HASH_SIZE, rv);
112*8617a60dSAndroid Build Coastguard Worker 		return rv;
113*8617a60dSAndroid Build Coastguard Worker 	}
114*8617a60dSAndroid Build Coastguard Worker 
115*8617a60dSAndroid Build Coastguard Worker 	if (vb2_safe_memcmp(heff, hexp, hexp_len)) {
116*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Heff != Hexp. Schedule update\n");
117*8617a60dSAndroid Build Coastguard Worker 		sd->flags |= SYNC_FLAG(select);
118*8617a60dSAndroid Build Coastguard Worker 	}
119*8617a60dSAndroid Build Coastguard Worker 
120*8617a60dSAndroid Build Coastguard Worker 	return VB2_SUCCESS;
121*8617a60dSAndroid Build Coastguard Worker }
122*8617a60dSAndroid Build Coastguard Worker 
123*8617a60dSAndroid Build Coastguard Worker /**
124*8617a60dSAndroid Build Coastguard Worker  * Update the specified EC and verify the update succeeded
125*8617a60dSAndroid Build Coastguard Worker  *
126*8617a60dSAndroid Build Coastguard Worker  * @param ctx		Vboot2 context
127*8617a60dSAndroid Build Coastguard Worker  * @param select	Which firmware image to check
128*8617a60dSAndroid Build Coastguard Worker  * @return VB2_SUCCESS, or non-zero error code.
129*8617a60dSAndroid Build Coastguard Worker  */
update_ec(struct vb2_context * ctx,enum vb2_firmware_selection select)130*8617a60dSAndroid Build Coastguard Worker static vb2_error_t update_ec(struct vb2_context *ctx,
131*8617a60dSAndroid Build Coastguard Worker 			     enum vb2_firmware_selection select)
132*8617a60dSAndroid Build Coastguard Worker {
133*8617a60dSAndroid Build Coastguard Worker 	struct vb2_shared_data *sd = vb2_get_sd(ctx);
134*8617a60dSAndroid Build Coastguard Worker 
135*8617a60dSAndroid Build Coastguard Worker 	VB2_DEBUG("Updating %s...\n", image_name_to_string(select));
136*8617a60dSAndroid Build Coastguard Worker 	VB2_TRY(vb2ex_ec_update_image(select), ctx, VB2_RECOVERY_EC_UPDATE);
137*8617a60dSAndroid Build Coastguard Worker 
138*8617a60dSAndroid Build Coastguard Worker 	/* Verify the EC was updated properly */
139*8617a60dSAndroid Build Coastguard Worker 	sd->flags &= ~SYNC_FLAG(select);
140*8617a60dSAndroid Build Coastguard Worker 	VB2_TRY(check_ec_hash(ctx, select));
141*8617a60dSAndroid Build Coastguard Worker 	if (sd->flags & SYNC_FLAG(select)) {
142*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Failed to update\n");
143*8617a60dSAndroid Build Coastguard Worker 		vb2api_fail(ctx, VB2_RECOVERY_EC_UPDATE, 0);
144*8617a60dSAndroid Build Coastguard Worker 		return VB2_REQUEST_REBOOT_EC_TO_RO;
145*8617a60dSAndroid Build Coastguard Worker 	}
146*8617a60dSAndroid Build Coastguard Worker 
147*8617a60dSAndroid Build Coastguard Worker 	VB2_DEBUG("Updated %s successfully\n", image_name_to_string(select));
148*8617a60dSAndroid Build Coastguard Worker 
149*8617a60dSAndroid Build Coastguard Worker 	return VB2_SUCCESS;
150*8617a60dSAndroid Build Coastguard Worker }
151*8617a60dSAndroid Build Coastguard Worker 
152*8617a60dSAndroid Build Coastguard Worker /**
153*8617a60dSAndroid Build Coastguard Worker  * Set VB2_SD_FLAG_ECSYNC_EC_IN_RW flag for the EC
154*8617a60dSAndroid Build Coastguard Worker  *
155*8617a60dSAndroid Build Coastguard Worker  * @param ctx		Vboot2 context
156*8617a60dSAndroid Build Coastguard Worker  * @return VB2_SUCCESS, or non-zero if error.
157*8617a60dSAndroid Build Coastguard Worker  */
check_ec_active(struct vb2_context * ctx)158*8617a60dSAndroid Build Coastguard Worker static vb2_error_t check_ec_active(struct vb2_context *ctx)
159*8617a60dSAndroid Build Coastguard Worker {
160*8617a60dSAndroid Build Coastguard Worker 	struct vb2_shared_data *sd = vb2_get_sd(ctx);
161*8617a60dSAndroid Build Coastguard Worker 	int in_rw = 0;
162*8617a60dSAndroid Build Coastguard Worker 	/*
163*8617a60dSAndroid Build Coastguard Worker 	 * We don't use VB2_CONTEXT_EC_TRUSTED, which checks if not EC_IN_RW.
164*8617a60dSAndroid Build Coastguard Worker 	 * It is controlled by GSC but on some platforms, GSC can't know when
165*8617a60dSAndroid Build Coastguard Worker 	 * a EC resets. So, we trust what EC-RW says. If it lies it's in RO,
166*8617a60dSAndroid Build Coastguard Worker 	 * we'll flash RW while it's in RW.
167*8617a60dSAndroid Build Coastguard Worker 	 */
168*8617a60dSAndroid Build Coastguard Worker 	/* If we couldn't determine where the EC was, reboot to recovery. */
169*8617a60dSAndroid Build Coastguard Worker 	VB2_TRY(vb2ex_ec_running_rw(&in_rw),
170*8617a60dSAndroid Build Coastguard Worker 		ctx, VB2_RECOVERY_EC_UNKNOWN_IMAGE);
171*8617a60dSAndroid Build Coastguard Worker 
172*8617a60dSAndroid Build Coastguard Worker 	if (in_rw)
173*8617a60dSAndroid Build Coastguard Worker 		sd->flags |= VB2_SD_FLAG_ECSYNC_EC_IN_RW;
174*8617a60dSAndroid Build Coastguard Worker 
175*8617a60dSAndroid Build Coastguard Worker 	return VB2_SUCCESS;
176*8617a60dSAndroid Build Coastguard Worker }
177*8617a60dSAndroid Build Coastguard Worker 
178*8617a60dSAndroid Build Coastguard Worker /**
179*8617a60dSAndroid Build Coastguard Worker  * Sync, jump, and protect EC device
180*8617a60dSAndroid Build Coastguard Worker  *
181*8617a60dSAndroid Build Coastguard Worker  * @param ctx		Vboot2 context
182*8617a60dSAndroid Build Coastguard Worker  * @return VB2_SUCCESS, or non-zero if error.
183*8617a60dSAndroid Build Coastguard Worker  */
sync_ec(struct vb2_context * ctx)184*8617a60dSAndroid Build Coastguard Worker static vb2_error_t sync_ec(struct vb2_context *ctx)
185*8617a60dSAndroid Build Coastguard Worker {
186*8617a60dSAndroid Build Coastguard Worker 	struct vb2_shared_data *sd = vb2_get_sd(ctx);
187*8617a60dSAndroid Build Coastguard Worker 
188*8617a60dSAndroid Build Coastguard Worker 	const enum vb2_firmware_selection select_rw = EC_EFS ?
189*8617a60dSAndroid Build Coastguard Worker 		VB_SELECT_FIRMWARE_EC_UPDATE :
190*8617a60dSAndroid Build Coastguard Worker 		VB_SELECT_FIRMWARE_EC_ACTIVE;
191*8617a60dSAndroid Build Coastguard Worker 	VB2_DEBUG("select_rw=%s\n", image_name_to_string(select_rw));
192*8617a60dSAndroid Build Coastguard Worker 
193*8617a60dSAndroid Build Coastguard Worker 	/* Update the RW Image */
194*8617a60dSAndroid Build Coastguard Worker 	if (sd->flags & SYNC_FLAG(select_rw)) {
195*8617a60dSAndroid Build Coastguard Worker 		VB2_TRY(update_ec(ctx, select_rw), ctx, VB2_RECOVERY_EC_UPDATE);
196*8617a60dSAndroid Build Coastguard Worker 		/* Updated successfully. Cold reboot to switch to the new RW. */
197*8617a60dSAndroid Build Coastguard Worker 		if (ctx->flags & VB2_CONTEXT_NO_BOOT) {
198*8617a60dSAndroid Build Coastguard Worker 			VB2_DEBUG("Rebooting to jump to new EC-RW\n");
199*8617a60dSAndroid Build Coastguard Worker 			return VB2_REQUEST_REBOOT_EC_TO_RO;
200*8617a60dSAndroid Build Coastguard Worker 		} else if (EC_EFS) {
201*8617a60dSAndroid Build Coastguard Worker 			VB2_DEBUG("Rebooting to switch to new EC-RW\n");
202*8617a60dSAndroid Build Coastguard Worker 			return VB2_REQUEST_REBOOT_EC_SWITCH_RW;
203*8617a60dSAndroid Build Coastguard Worker 		}
204*8617a60dSAndroid Build Coastguard Worker 	}
205*8617a60dSAndroid Build Coastguard Worker 
206*8617a60dSAndroid Build Coastguard Worker 	if (sd->flags & VB2_SD_FLAG_ECSYNC_HMIR_UPDATED) {
207*8617a60dSAndroid Build Coastguard Worker 		/*
208*8617a60dSAndroid Build Coastguard Worker 		 * After Hmir is updated, EFS needs to be retried since the
209*8617a60dSAndroid Build Coastguard Worker 		 * verification result is revoked.
210*8617a60dSAndroid Build Coastguard Worker 		 */
211*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Reset EC after Hmir update\n");
212*8617a60dSAndroid Build Coastguard Worker 		return VB2_REQUEST_REBOOT_EC_TO_RO;
213*8617a60dSAndroid Build Coastguard Worker 	}
214*8617a60dSAndroid Build Coastguard Worker 
215*8617a60dSAndroid Build Coastguard Worker 	/* We no longer trust the EC once it is already in RW or tries to jump
216*8617a60dSAndroid Build Coastguard Worker 	   to RW. */
217*8617a60dSAndroid Build Coastguard Worker 	ctx->flags &= ~VB2_CONTEXT_EC_TRUSTED;
218*8617a60dSAndroid Build Coastguard Worker 
219*8617a60dSAndroid Build Coastguard Worker 	/* Tell EC to jump to RW. It should already be in RW for EFS2. */
220*8617a60dSAndroid Build Coastguard Worker 	if (!(sd->flags & VB2_SD_FLAG_ECSYNC_EC_IN_RW)) {
221*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("jumping to EC-RW\n");
222*8617a60dSAndroid Build Coastguard Worker 		VB2_TRY(vb2ex_ec_jump_to_rw(), ctx, VB2_RECOVERY_EC_JUMP_RW);
223*8617a60dSAndroid Build Coastguard Worker 	}
224*8617a60dSAndroid Build Coastguard Worker 
225*8617a60dSAndroid Build Coastguard Worker 	/* Might need to update EC-RO */
226*8617a60dSAndroid Build Coastguard Worker 	if (sd->flags & VB2_SD_FLAG_ECSYNC_EC_RO) {
227*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("RO Software Sync\n");
228*8617a60dSAndroid Build Coastguard Worker 
229*8617a60dSAndroid Build Coastguard Worker 		/* Reset RO Software Sync NV flag */
230*8617a60dSAndroid Build Coastguard Worker 		vb2_nv_set(ctx, VB2_NV_TRY_RO_SYNC, 0);
231*8617a60dSAndroid Build Coastguard Worker 
232*8617a60dSAndroid Build Coastguard Worker 		/* Update the RO Image */
233*8617a60dSAndroid Build Coastguard Worker 		VB2_TRY(update_ec(ctx, VB_SELECT_FIRMWARE_READONLY),
234*8617a60dSAndroid Build Coastguard Worker 			ctx, VB2_RECOVERY_EC_UPDATE);
235*8617a60dSAndroid Build Coastguard Worker 	}
236*8617a60dSAndroid Build Coastguard Worker 
237*8617a60dSAndroid Build Coastguard Worker 	/* Protect RW flash */
238*8617a60dSAndroid Build Coastguard Worker 	VB2_TRY(vb2ex_ec_protect(), ctx, VB2_RECOVERY_EC_PROTECT);
239*8617a60dSAndroid Build Coastguard Worker 
240*8617a60dSAndroid Build Coastguard Worker 	/* Disable further sysjumps */
241*8617a60dSAndroid Build Coastguard Worker 	VB2_TRY(vb2ex_ec_disable_jump(), ctx, VB2_RECOVERY_EC_SOFTWARE_SYNC);
242*8617a60dSAndroid Build Coastguard Worker 
243*8617a60dSAndroid Build Coastguard Worker 	return VB2_SUCCESS;
244*8617a60dSAndroid Build Coastguard Worker }
245*8617a60dSAndroid Build Coastguard Worker 
246*8617a60dSAndroid Build Coastguard Worker /**
247*8617a60dSAndroid Build Coastguard Worker  * EC sync, phase 1
248*8617a60dSAndroid Build Coastguard Worker  *
249*8617a60dSAndroid Build Coastguard Worker  * This checks whether the EC is running the correct image to do EC sync, and
250*8617a60dSAndroid Build Coastguard Worker  * whether any updates are necessary.
251*8617a60dSAndroid Build Coastguard Worker  *
252*8617a60dSAndroid Build Coastguard Worker  * @param ctx		Vboot2 context
253*8617a60dSAndroid Build Coastguard Worker  * @return VB2_SUCCESS, VB2_REQUEST_REBOOT_EC_TO_RO if the EC must reboot back
254*8617a60dSAndroid Build Coastguard Worker  * to its RO code to continue EC sync, or other non-zero error code.
255*8617a60dSAndroid Build Coastguard Worker  */
ec_sync_phase1(struct vb2_context * ctx)256*8617a60dSAndroid Build Coastguard Worker static vb2_error_t ec_sync_phase1(struct vb2_context *ctx)
257*8617a60dSAndroid Build Coastguard Worker {
258*8617a60dSAndroid Build Coastguard Worker 	struct vb2_shared_data *sd = vb2_get_sd(ctx);
259*8617a60dSAndroid Build Coastguard Worker 	struct vb2_gbb_header *gbb = vb2_get_gbb(ctx);
260*8617a60dSAndroid Build Coastguard Worker 
261*8617a60dSAndroid Build Coastguard Worker 	/* Reasons not to do sync at all */
262*8617a60dSAndroid Build Coastguard Worker 	if (!(ctx->flags & VB2_CONTEXT_EC_SYNC_SUPPORTED))
263*8617a60dSAndroid Build Coastguard Worker 		return VB2_SUCCESS;
264*8617a60dSAndroid Build Coastguard Worker 	if (gbb->flags & VB2_GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC)
265*8617a60dSAndroid Build Coastguard Worker 		return VB2_SUCCESS;
266*8617a60dSAndroid Build Coastguard Worker 
267*8617a60dSAndroid Build Coastguard Worker 	/* Set VB2_SD_FLAG_ECSYNC_EC_IN_RW flag */
268*8617a60dSAndroid Build Coastguard Worker 	if (check_ec_active(ctx))
269*8617a60dSAndroid Build Coastguard Worker 		return VB2_REQUEST_REBOOT_EC_TO_RO;
270*8617a60dSAndroid Build Coastguard Worker 
271*8617a60dSAndroid Build Coastguard Worker 	/* Check if we need to update RW. Failures trigger recovery mode. */
272*8617a60dSAndroid Build Coastguard Worker 	if (check_ec_hash(ctx, VB_SELECT_FIRMWARE_EC_ACTIVE))
273*8617a60dSAndroid Build Coastguard Worker 		return VB2_REQUEST_REBOOT_EC_TO_RO;
274*8617a60dSAndroid Build Coastguard Worker 
275*8617a60dSAndroid Build Coastguard Worker 	/* See if we need to update EC-RO. */
276*8617a60dSAndroid Build Coastguard Worker 	if (vb2_nv_get(ctx, VB2_NV_TRY_RO_SYNC) &&
277*8617a60dSAndroid Build Coastguard Worker 	    check_ec_hash(ctx, VB_SELECT_FIRMWARE_READONLY)) {
278*8617a60dSAndroid Build Coastguard Worker 		return VB2_REQUEST_REBOOT_EC_TO_RO;
279*8617a60dSAndroid Build Coastguard Worker 	}
280*8617a60dSAndroid Build Coastguard Worker 
281*8617a60dSAndroid Build Coastguard Worker 	/*
282*8617a60dSAndroid Build Coastguard Worker 	 * If we're in RW, we need to reboot back to RO because RW can't be
283*8617a60dSAndroid Build Coastguard Worker 	 * updated while we're running it.
284*8617a60dSAndroid Build Coastguard Worker 	 *
285*8617a60dSAndroid Build Coastguard Worker 	 * If EC supports RW-A/B slots, we can proceed but we need
286*8617a60dSAndroid Build Coastguard Worker 	 * to jump to the new RW version later.
287*8617a60dSAndroid Build Coastguard Worker 	 */
288*8617a60dSAndroid Build Coastguard Worker 	if ((sd->flags & SYNC_FLAG(VB_SELECT_FIRMWARE_EC_ACTIVE)) &&
289*8617a60dSAndroid Build Coastguard Worker 	    (sd->flags & VB2_SD_FLAG_ECSYNC_EC_IN_RW) && !EC_EFS) {
290*8617a60dSAndroid Build Coastguard Worker 		if (ctx->flags & VB2_CONTEXT_EC_SYNC_SLOW) {
291*8617a60dSAndroid Build Coastguard Worker 			/* Ignore the return value. */
292*8617a60dSAndroid Build Coastguard Worker 			vb2api_need_reboot_for_display(ctx);
293*8617a60dSAndroid Build Coastguard Worker 		}
294*8617a60dSAndroid Build Coastguard Worker 		return VB2_REQUEST_REBOOT_EC_TO_RO;
295*8617a60dSAndroid Build Coastguard Worker 	}
296*8617a60dSAndroid Build Coastguard Worker 
297*8617a60dSAndroid Build Coastguard Worker 	return VB2_SUCCESS;
298*8617a60dSAndroid Build Coastguard Worker }
299*8617a60dSAndroid Build Coastguard Worker 
300*8617a60dSAndroid Build Coastguard Worker /**
301*8617a60dSAndroid Build Coastguard Worker  * determine if we can update the EC
302*8617a60dSAndroid Build Coastguard Worker  *
303*8617a60dSAndroid Build Coastguard Worker  * @param ctx		Vboot2 context
304*8617a60dSAndroid Build Coastguard Worker  * @return boolean (true iff we can update the EC)
305*8617a60dSAndroid Build Coastguard Worker  */
306*8617a60dSAndroid Build Coastguard Worker 
ec_sync_allowed(struct vb2_context * ctx)307*8617a60dSAndroid Build Coastguard Worker static int ec_sync_allowed(struct vb2_context *ctx)
308*8617a60dSAndroid Build Coastguard Worker {
309*8617a60dSAndroid Build Coastguard Worker 	struct vb2_gbb_header *gbb = vb2_get_gbb(ctx);
310*8617a60dSAndroid Build Coastguard Worker 
311*8617a60dSAndroid Build Coastguard Worker 	/* Reasons not to do sync at all */
312*8617a60dSAndroid Build Coastguard Worker 	if (!(ctx->flags & VB2_CONTEXT_EC_SYNC_SUPPORTED))
313*8617a60dSAndroid Build Coastguard Worker 		return 0;
314*8617a60dSAndroid Build Coastguard Worker 	if (gbb->flags & VB2_GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC)
315*8617a60dSAndroid Build Coastguard Worker 		return 0;
316*8617a60dSAndroid Build Coastguard Worker 	if (ctx->flags & VB2_CONTEXT_RECOVERY_MODE)
317*8617a60dSAndroid Build Coastguard Worker 		return 0;
318*8617a60dSAndroid Build Coastguard Worker 	return 1;
319*8617a60dSAndroid Build Coastguard Worker }
320*8617a60dSAndroid Build Coastguard Worker 
321*8617a60dSAndroid Build Coastguard Worker /**
322*8617a60dSAndroid Build Coastguard Worker  * EC sync, phase 2
323*8617a60dSAndroid Build Coastguard Worker  *
324*8617a60dSAndroid Build Coastguard Worker  * This updates the EC if necessary, makes sure it has protected its image(s),
325*8617a60dSAndroid Build Coastguard Worker  * and makes sure it has jumped to the correct image.
326*8617a60dSAndroid Build Coastguard Worker  *
327*8617a60dSAndroid Build Coastguard Worker  * @param ctx		Vboot2 context
328*8617a60dSAndroid Build Coastguard Worker  * @return VB2_SUCCESS, VB2_REQUEST_REBOOT_EC_TO_RO if the EC must
329*8617a60dSAndroid Build Coastguard Worker  * reboot back to its RO code to continue EC sync, or other non-zero error
330*8617a60dSAndroid Build Coastguard Worker  * code.
331*8617a60dSAndroid Build Coastguard Worker  */
ec_sync_phase2(struct vb2_context * ctx)332*8617a60dSAndroid Build Coastguard Worker static vb2_error_t ec_sync_phase2(struct vb2_context *ctx)
333*8617a60dSAndroid Build Coastguard Worker {
334*8617a60dSAndroid Build Coastguard Worker 	if (!ec_sync_allowed(ctx))
335*8617a60dSAndroid Build Coastguard Worker 		return VB2_SUCCESS;
336*8617a60dSAndroid Build Coastguard Worker 
337*8617a60dSAndroid Build Coastguard Worker 	/* Handle updates and jumps for EC */
338*8617a60dSAndroid Build Coastguard Worker 	return sync_ec(ctx);
339*8617a60dSAndroid Build Coastguard Worker }
340*8617a60dSAndroid Build Coastguard Worker 
341*8617a60dSAndroid Build Coastguard Worker test_mockable
vb2api_ec_sync(struct vb2_context * ctx)342*8617a60dSAndroid Build Coastguard Worker vb2_error_t vb2api_ec_sync(struct vb2_context *ctx)
343*8617a60dSAndroid Build Coastguard Worker {
344*8617a60dSAndroid Build Coastguard Worker 	struct vb2_shared_data *sd = vb2_get_sd(ctx);
345*8617a60dSAndroid Build Coastguard Worker 
346*8617a60dSAndroid Build Coastguard Worker 	/*
347*8617a60dSAndroid Build Coastguard Worker 	 * If the status indicates that the EC has already gone through
348*8617a60dSAndroid Build Coastguard Worker 	 * software sync this boot, then don't do it again.
349*8617a60dSAndroid Build Coastguard Worker 	 */
350*8617a60dSAndroid Build Coastguard Worker 	if (sd->status & VB2_SD_STATUS_EC_SYNC_COMPLETE) {
351*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("EC software sync already performed this boot, skipping\n");
352*8617a60dSAndroid Build Coastguard Worker 		return VB2_SUCCESS;
353*8617a60dSAndroid Build Coastguard Worker 	}
354*8617a60dSAndroid Build Coastguard Worker 
355*8617a60dSAndroid Build Coastguard Worker 	/*
356*8617a60dSAndroid Build Coastguard Worker 	 * If the device is in recovery mode, then EC sync should
357*8617a60dSAndroid Build Coastguard Worker 	 * not be performed.
358*8617a60dSAndroid Build Coastguard Worker 	 */
359*8617a60dSAndroid Build Coastguard Worker 	if (ctx->flags & VB2_CONTEXT_RECOVERY_MODE) {
360*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("In recovery mode, skipping EC sync\n");
361*8617a60dSAndroid Build Coastguard Worker 		return VB2_SUCCESS;
362*8617a60dSAndroid Build Coastguard Worker 	}
363*8617a60dSAndroid Build Coastguard Worker 
364*8617a60dSAndroid Build Coastguard Worker 	/* Phase 1; this determines if we need an update */
365*8617a60dSAndroid Build Coastguard Worker 	VB2_TRY(ec_sync_phase1(ctx));
366*8617a60dSAndroid Build Coastguard Worker 
367*8617a60dSAndroid Build Coastguard Worker 	/* Phase 2; Applies update and/or jumps to the correct EC image */
368*8617a60dSAndroid Build Coastguard Worker 	VB2_TRY(ec_sync_phase2(ctx));
369*8617a60dSAndroid Build Coastguard Worker 
370*8617a60dSAndroid Build Coastguard Worker 	/* Phase 3; Let the platform know that EC software sync is now done */
371*8617a60dSAndroid Build Coastguard Worker 	VB2_TRY(vb2ex_ec_vboot_done(ctx));
372*8617a60dSAndroid Build Coastguard Worker 
373*8617a60dSAndroid Build Coastguard Worker 	/* Establish that EC software sync is complete and successful */
374*8617a60dSAndroid Build Coastguard Worker 	sd->status |= VB2_SD_STATUS_EC_SYNC_COMPLETE;
375*8617a60dSAndroid Build Coastguard Worker 
376*8617a60dSAndroid Build Coastguard Worker 	return VB2_SUCCESS;
377*8617a60dSAndroid Build Coastguard Worker }
378