xref: /aosp_15_r20/external/vboot_reference/firmware/2lib/2kernel.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
1*8617a60dSAndroid Build Coastguard Worker /* Copyright 2020 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  * Kernel selection, loading, verification, and booting.
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 "2rsa.h"
13*8617a60dSAndroid Build Coastguard Worker #include "2secdata.h"
14*8617a60dSAndroid Build Coastguard Worker 
vb2api_is_developer_signed(struct vb2_context * ctx)15*8617a60dSAndroid Build Coastguard Worker int vb2api_is_developer_signed(struct vb2_context *ctx)
16*8617a60dSAndroid Build Coastguard Worker {
17*8617a60dSAndroid Build Coastguard Worker 	struct vb2_shared_data *sd = vb2_get_sd(ctx);
18*8617a60dSAndroid Build Coastguard Worker 
19*8617a60dSAndroid Build Coastguard Worker 	if (!sd->kernel_key_offset || !sd->kernel_key_size) {
20*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("ERROR: Cannot call this before kernel_phase1!\n");
21*8617a60dSAndroid Build Coastguard Worker 		return 0;
22*8617a60dSAndroid Build Coastguard Worker 	}
23*8617a60dSAndroid Build Coastguard Worker 
24*8617a60dSAndroid Build Coastguard Worker 	struct vb2_public_key key;
25*8617a60dSAndroid Build Coastguard Worker 	if (vb2_unpack_key(&key, vb2_member_of(sd, sd->kernel_key_offset)))
26*8617a60dSAndroid Build Coastguard Worker 		return 0;
27*8617a60dSAndroid Build Coastguard Worker 
28*8617a60dSAndroid Build Coastguard Worker 	/* This is a debugging aid, not a security-relevant feature. There's no
29*8617a60dSAndroid Build Coastguard Worker 	   reason to hardcode the whole key or waste time computing a hash. Just
30*8617a60dSAndroid Build Coastguard Worker 	   spot check the starting bytes of the pseudorandom part of the key. */
31*8617a60dSAndroid Build Coastguard Worker 	uint32_t devkey_n0inv = ctx->flags & VB2_CONTEXT_RECOVERY_MODE ?
32*8617a60dSAndroid Build Coastguard Worker 		0x18cebcf5 :	/*  recovery_key.vbpubk @0x24 */
33*8617a60dSAndroid Build Coastguard Worker 		0xe0cd87d9;	/* kernel_subkey.vbpubk @0x24 */
34*8617a60dSAndroid Build Coastguard Worker 
35*8617a60dSAndroid Build Coastguard Worker 	if (key.n0inv == devkey_n0inv)
36*8617a60dSAndroid Build Coastguard Worker 		return 1;
37*8617a60dSAndroid Build Coastguard Worker 
38*8617a60dSAndroid Build Coastguard Worker 	return 0;
39*8617a60dSAndroid Build Coastguard Worker }
40*8617a60dSAndroid Build Coastguard Worker 
41*8617a60dSAndroid Build Coastguard Worker test_mockable
vb2api_kernel_phase1(struct vb2_context * ctx)42*8617a60dSAndroid Build Coastguard Worker vb2_error_t vb2api_kernel_phase1(struct vb2_context *ctx)
43*8617a60dSAndroid Build Coastguard Worker {
44*8617a60dSAndroid Build Coastguard Worker 	struct vb2_shared_data *sd = vb2_get_sd(ctx);
45*8617a60dSAndroid Build Coastguard Worker 	struct vb2_workbuf wb;
46*8617a60dSAndroid Build Coastguard Worker 	struct vb2_packed_key *packed_key;
47*8617a60dSAndroid Build Coastguard Worker 	uint32_t flags;
48*8617a60dSAndroid Build Coastguard Worker 	vb2_error_t rv;
49*8617a60dSAndroid Build Coastguard Worker 
50*8617a60dSAndroid Build Coastguard Worker 	vb2_workbuf_from_ctx(ctx, &wb);
51*8617a60dSAndroid Build Coastguard Worker 
52*8617a60dSAndroid Build Coastguard Worker 	/*
53*8617a60dSAndroid Build Coastguard Worker 	 * Init secdata_fwmp spaces. No need to init secdata_firmware or
54*8617a60dSAndroid Build Coastguard Worker 	 * secdata_kernel, since they were already read during firmware
55*8617a60dSAndroid Build Coastguard Worker 	 * verification.  Ignore errors in recovery mode.
56*8617a60dSAndroid Build Coastguard Worker 	 */
57*8617a60dSAndroid Build Coastguard Worker 	rv = vb2_secdata_fwmp_init(ctx);
58*8617a60dSAndroid Build Coastguard Worker 	if (rv && !(ctx->flags & VB2_CONTEXT_RECOVERY_MODE)) {
59*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("TPM: init secdata_fwmp returned %#x\n", rv);
60*8617a60dSAndroid Build Coastguard Worker 		vb2api_fail(ctx, VB2_RECOVERY_SECDATA_FWMP_INIT, rv);
61*8617a60dSAndroid Build Coastguard Worker 		return rv;
62*8617a60dSAndroid Build Coastguard Worker 	}
63*8617a60dSAndroid Build Coastguard Worker 
64*8617a60dSAndroid Build Coastguard Worker 	/* Initialize experimental feature flags while in normal RW path. */
65*8617a60dSAndroid Build Coastguard Worker 	if (!(ctx->flags & VB2_CONTEXT_RECOVERY_MODE)) {
66*8617a60dSAndroid Build Coastguard Worker 		flags = vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_FLAGS);
67*8617a60dSAndroid Build Coastguard Worker 		flags &= ~VB2_SECDATA_KERNEL_FLAG_DIAGNOSTIC_UI_DISABLED;
68*8617a60dSAndroid Build Coastguard Worker 		flags |= VB2_SECDATA_KERNEL_FLAG_HWCRYPTO_ALLOWED;
69*8617a60dSAndroid Build Coastguard Worker 		vb2_secdata_kernel_set(ctx, VB2_SECDATA_KERNEL_FLAGS, flags);
70*8617a60dSAndroid Build Coastguard Worker 	}
71*8617a60dSAndroid Build Coastguard Worker 
72*8617a60dSAndroid Build Coastguard Worker 	/* Read kernel version from secdata. */
73*8617a60dSAndroid Build Coastguard Worker 	sd->kernel_version_secdata =
74*8617a60dSAndroid Build Coastguard Worker 		vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_VERSIONS);
75*8617a60dSAndroid Build Coastguard Worker 
76*8617a60dSAndroid Build Coastguard Worker 	vb2_fill_dev_boot_flags(ctx);
77*8617a60dSAndroid Build Coastguard Worker 
78*8617a60dSAndroid Build Coastguard Worker 	/* Find the key to use to verify the kernel keyblock */
79*8617a60dSAndroid Build Coastguard Worker 	if ((ctx->flags & VB2_CONTEXT_RECOVERY_MODE)) {
80*8617a60dSAndroid Build Coastguard Worker 		/* Load recovery key from GBB. */
81*8617a60dSAndroid Build Coastguard Worker 		rv = vb2_gbb_read_recovery_key(ctx, &packed_key, NULL, &wb);
82*8617a60dSAndroid Build Coastguard Worker 		if (rv) {
83*8617a60dSAndroid Build Coastguard Worker 			if (ctx->boot_mode != VB2_BOOT_MODE_BROKEN_SCREEN)
84*8617a60dSAndroid Build Coastguard Worker 				VB2_DIE("GBB read recovery key failed.\n");
85*8617a60dSAndroid Build Coastguard Worker 			else
86*8617a60dSAndroid Build Coastguard Worker 				/*
87*8617a60dSAndroid Build Coastguard Worker 				 * If we're headed for the BROKEN screen,
88*8617a60dSAndroid Build Coastguard Worker 				 * we won't need the recovery key.  Just
89*8617a60dSAndroid Build Coastguard Worker 				 * short-circuit with success.
90*8617a60dSAndroid Build Coastguard Worker 				 */
91*8617a60dSAndroid Build Coastguard Worker 				return VB2_SUCCESS;
92*8617a60dSAndroid Build Coastguard Worker 		}
93*8617a60dSAndroid Build Coastguard Worker 	} else {
94*8617a60dSAndroid Build Coastguard Worker 		/* Kernel subkey from firmware preamble */
95*8617a60dSAndroid Build Coastguard Worker 		struct vb2_fw_preamble *pre;
96*8617a60dSAndroid Build Coastguard Worker 
97*8617a60dSAndroid Build Coastguard Worker 		/* Make sure we have a firmware preamble loaded */
98*8617a60dSAndroid Build Coastguard Worker 		if (!sd->preamble_size)
99*8617a60dSAndroid Build Coastguard Worker 			return VB2_ERROR_API_KPHASE1_PREAMBLE;
100*8617a60dSAndroid Build Coastguard Worker 
101*8617a60dSAndroid Build Coastguard Worker 		pre = (struct vb2_fw_preamble *)
102*8617a60dSAndroid Build Coastguard Worker 			vb2_member_of(sd, sd->preamble_offset);
103*8617a60dSAndroid Build Coastguard Worker 		packed_key = &pre->kernel_subkey;
104*8617a60dSAndroid Build Coastguard Worker 	}
105*8617a60dSAndroid Build Coastguard Worker 
106*8617a60dSAndroid Build Coastguard Worker 	sd->kernel_key_offset = vb2_offset_of(sd, packed_key);
107*8617a60dSAndroid Build Coastguard Worker 	sd->kernel_key_size = packed_key->key_offset + packed_key->key_size;
108*8617a60dSAndroid Build Coastguard Worker 
109*8617a60dSAndroid Build Coastguard Worker 	vb2_set_workbuf_used(ctx, vb2_offset_of(sd, wb.buf));
110*8617a60dSAndroid Build Coastguard Worker 
111*8617a60dSAndroid Build Coastguard Worker 	if (vb2api_is_developer_signed(ctx))
112*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("This is developer-signed firmware.\n");
113*8617a60dSAndroid Build Coastguard Worker 
114*8617a60dSAndroid Build Coastguard Worker 	return VB2_SUCCESS;
115*8617a60dSAndroid Build Coastguard Worker }
116*8617a60dSAndroid Build Coastguard Worker 
handle_battery_cutoff(struct vb2_context * ctx)117*8617a60dSAndroid Build Coastguard Worker static vb2_error_t handle_battery_cutoff(struct vb2_context *ctx)
118*8617a60dSAndroid Build Coastguard Worker {
119*8617a60dSAndroid Build Coastguard Worker 	/*
120*8617a60dSAndroid Build Coastguard Worker 	 * Check if we need to cut-off battery. This should be done after EC
121*8617a60dSAndroid Build Coastguard Worker 	 * FW and auxfw are updated, and before the kernel is started.  This
122*8617a60dSAndroid Build Coastguard Worker 	 * is to make sure all firmware is up-to-date before shipping (which
123*8617a60dSAndroid Build Coastguard Worker 	 * is the typical use-case for cutoff).
124*8617a60dSAndroid Build Coastguard Worker 	 */
125*8617a60dSAndroid Build Coastguard Worker 	if (vb2_nv_get(ctx, VB2_NV_BATTERY_CUTOFF_REQUEST)) {
126*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Request to cut-off battery\n");
127*8617a60dSAndroid Build Coastguard Worker 		vb2_nv_set(ctx, VB2_NV_BATTERY_CUTOFF_REQUEST, 0);
128*8617a60dSAndroid Build Coastguard Worker 
129*8617a60dSAndroid Build Coastguard Worker 		/* May lose power immediately, so commit our update now. */
130*8617a60dSAndroid Build Coastguard Worker 		VB2_TRY(vb2ex_commit_data(ctx));
131*8617a60dSAndroid Build Coastguard Worker 
132*8617a60dSAndroid Build Coastguard Worker 		vb2ex_ec_battery_cutoff();
133*8617a60dSAndroid Build Coastguard Worker 		return VB2_REQUEST_SHUTDOWN;
134*8617a60dSAndroid Build Coastguard Worker 	}
135*8617a60dSAndroid Build Coastguard Worker 
136*8617a60dSAndroid Build Coastguard Worker 	return VB2_SUCCESS;
137*8617a60dSAndroid Build Coastguard Worker }
138*8617a60dSAndroid Build Coastguard Worker 
vb2api_kernel_phase2(struct vb2_context * ctx)139*8617a60dSAndroid Build Coastguard Worker vb2_error_t vb2api_kernel_phase2(struct vb2_context *ctx)
140*8617a60dSAndroid Build Coastguard Worker {
141*8617a60dSAndroid Build Coastguard Worker 	struct vb2_shared_data *sd = vb2_get_sd(ctx);
142*8617a60dSAndroid Build Coastguard Worker 	vb2_gbb_flags_t gbb_flags = vb2api_gbb_get_flags(ctx);
143*8617a60dSAndroid Build Coastguard Worker 
144*8617a60dSAndroid Build Coastguard Worker 	VB2_DEBUG("GBB flags are %#x\n", gbb_flags);
145*8617a60dSAndroid Build Coastguard Worker 
146*8617a60dSAndroid Build Coastguard Worker 	/*
147*8617a60dSAndroid Build Coastguard Worker 	 * Do EC and auxfw software sync unless we're in recovery mode. This
148*8617a60dSAndroid Build Coastguard Worker 	 * has UI but it's just a single non-interactive WAIT screen.
149*8617a60dSAndroid Build Coastguard Worker 	 */
150*8617a60dSAndroid Build Coastguard Worker 	if (!(ctx->flags & VB2_CONTEXT_RECOVERY_MODE)) {
151*8617a60dSAndroid Build Coastguard Worker 		VB2_TRY(vb2api_ec_sync(ctx));
152*8617a60dSAndroid Build Coastguard Worker 		VB2_TRY(vb2api_auxfw_sync(ctx));
153*8617a60dSAndroid Build Coastguard Worker 		VB2_TRY(handle_battery_cutoff(ctx));
154*8617a60dSAndroid Build Coastguard Worker 	}
155*8617a60dSAndroid Build Coastguard Worker 
156*8617a60dSAndroid Build Coastguard Worker 	/*
157*8617a60dSAndroid Build Coastguard Worker 	 * If in the broken screen, save the recovery reason as subcode.
158*8617a60dSAndroid Build Coastguard Worker 	 * Otherwise, clear any leftover recovery requests or subcodes.
159*8617a60dSAndroid Build Coastguard Worker 	 */
160*8617a60dSAndroid Build Coastguard Worker 	vb2api_clear_recovery(ctx);
161*8617a60dSAndroid Build Coastguard Worker 
162*8617a60dSAndroid Build Coastguard Worker 	/*
163*8617a60dSAndroid Build Coastguard Worker 	 * Clear the diagnostic request flag and commit nvdata to prevent
164*8617a60dSAndroid Build Coastguard Worker 	 * booting back into diagnostic mode when a forced system reset occurs.
165*8617a60dSAndroid Build Coastguard Worker 	 */
166*8617a60dSAndroid Build Coastguard Worker 	if (vb2_nv_get(ctx, VB2_NV_DIAG_REQUEST)) {
167*8617a60dSAndroid Build Coastguard Worker 		vb2_nv_set(ctx, VB2_NV_DIAG_REQUEST, 0);
168*8617a60dSAndroid Build Coastguard Worker 		/*
169*8617a60dSAndroid Build Coastguard Worker 		 * According to current FAFT design (firmware_MiniDiag), we
170*8617a60dSAndroid Build Coastguard Worker 		 * need an AP reset after MiniDiag test items to preserve the
171*8617a60dSAndroid Build Coastguard Worker 		 * CBMEM console logs. So we need to commit nvdata immediately
172*8617a60dSAndroid Build Coastguard Worker 		 * to prevent booting back to VB2_BOOT_MODE_DIAGNOSTICS.
173*8617a60dSAndroid Build Coastguard Worker 		 */
174*8617a60dSAndroid Build Coastguard Worker 		vb2ex_commit_data(ctx);
175*8617a60dSAndroid Build Coastguard Worker 	}
176*8617a60dSAndroid Build Coastguard Worker 
177*8617a60dSAndroid Build Coastguard Worker 	/* Select boot path */
178*8617a60dSAndroid Build Coastguard Worker 	switch (ctx->boot_mode) {
179*8617a60dSAndroid Build Coastguard Worker 	case VB2_BOOT_MODE_MANUAL_RECOVERY:
180*8617a60dSAndroid Build Coastguard Worker 	case VB2_BOOT_MODE_BROKEN_SCREEN:
181*8617a60dSAndroid Build Coastguard Worker 		/* If we're in recovery mode just to do memory retraining, all
182*8617a60dSAndroid Build Coastguard Worker 		   we need to do is reboot. */
183*8617a60dSAndroid Build Coastguard Worker 		if (sd->recovery_reason == VB2_RECOVERY_TRAIN_AND_REBOOT) {
184*8617a60dSAndroid Build Coastguard Worker 			VB2_DEBUG("Reboot after retraining in recovery\n");
185*8617a60dSAndroid Build Coastguard Worker 			return VB2_REQUEST_REBOOT;
186*8617a60dSAndroid Build Coastguard Worker 		}
187*8617a60dSAndroid Build Coastguard Worker 
188*8617a60dSAndroid Build Coastguard Worker 		/*
189*8617a60dSAndroid Build Coastguard Worker 		 * Need to commit nvdata changes immediately, since we will be
190*8617a60dSAndroid Build Coastguard Worker 		 * entering either manual recovery UI or BROKEN screen shortly.
191*8617a60dSAndroid Build Coastguard Worker 		 */
192*8617a60dSAndroid Build Coastguard Worker 		vb2ex_commit_data(ctx);
193*8617a60dSAndroid Build Coastguard Worker 		break;
194*8617a60dSAndroid Build Coastguard Worker 	case VB2_BOOT_MODE_DIAGNOSTICS:
195*8617a60dSAndroid Build Coastguard Worker 	case VB2_BOOT_MODE_DEVELOPER:
196*8617a60dSAndroid Build Coastguard Worker 		break;
197*8617a60dSAndroid Build Coastguard Worker 	case VB2_BOOT_MODE_NORMAL:
198*8617a60dSAndroid Build Coastguard Worker 		if (vb2_nv_get(ctx, VB2_NV_DISPLAY_REQUEST)) {
199*8617a60dSAndroid Build Coastguard Worker 			vb2_nv_set(ctx, VB2_NV_DISPLAY_REQUEST, 0);
200*8617a60dSAndroid Build Coastguard Worker 			VB2_DEBUG("Normal mode: "
201*8617a60dSAndroid Build Coastguard Worker 				  "reboot to unset display request\n");
202*8617a60dSAndroid Build Coastguard Worker 			return VB2_REQUEST_REBOOT;
203*8617a60dSAndroid Build Coastguard Worker 		}
204*8617a60dSAndroid Build Coastguard Worker 		break;
205*8617a60dSAndroid Build Coastguard Worker 	default:
206*8617a60dSAndroid Build Coastguard Worker 		return VB2_ERROR_ESCAPE_NO_BOOT;
207*8617a60dSAndroid Build Coastguard Worker 	}
208*8617a60dSAndroid Build Coastguard Worker 
209*8617a60dSAndroid Build Coastguard Worker 	return VB2_SUCCESS;
210*8617a60dSAndroid Build Coastguard Worker }
211*8617a60dSAndroid Build Coastguard Worker 
update_kernel_version(struct vb2_context * ctx)212*8617a60dSAndroid Build Coastguard Worker static void update_kernel_version(struct vb2_context *ctx)
213*8617a60dSAndroid Build Coastguard Worker {
214*8617a60dSAndroid Build Coastguard Worker 	struct vb2_shared_data *sd = vb2_get_sd(ctx);
215*8617a60dSAndroid Build Coastguard Worker 	uint32_t max_rollforward =
216*8617a60dSAndroid Build Coastguard Worker 		vb2_nv_get(ctx, VB2_NV_KERNEL_MAX_ROLLFORWARD);
217*8617a60dSAndroid Build Coastguard Worker 
218*8617a60dSAndroid Build Coastguard Worker 	VB2_DEBUG("Checking if TPM kernel version needs advancing\n");
219*8617a60dSAndroid Build Coastguard Worker 
220*8617a60dSAndroid Build Coastguard Worker 	/*
221*8617a60dSAndroid Build Coastguard Worker 	 * Special case for when we're trying a slot with new firmware.
222*8617a60dSAndroid Build Coastguard Worker 	 * Firmware updates also usually change the kernel key, which means
223*8617a60dSAndroid Build Coastguard Worker 	 * that the new firmware can only boot a new kernel, and the old
224*8617a60dSAndroid Build Coastguard Worker 	 * firmware in the previous slot can only boot the previous kernel.
225*8617a60dSAndroid Build Coastguard Worker 	 *
226*8617a60dSAndroid Build Coastguard Worker 	 * Don't roll-forward the kernel version, because we don't yet know if
227*8617a60dSAndroid Build Coastguard Worker 	 * the new kernel will successfully boot.
228*8617a60dSAndroid Build Coastguard Worker 	 */
229*8617a60dSAndroid Build Coastguard Worker 	if (vb2_nv_get(ctx, VB2_NV_FW_RESULT) == VB2_FW_RESULT_TRYING) {
230*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Trying new FW; "
231*8617a60dSAndroid Build Coastguard Worker 			  "skip kernel version roll-forward.\n");
232*8617a60dSAndroid Build Coastguard Worker 		return;
233*8617a60dSAndroid Build Coastguard Worker 	}
234*8617a60dSAndroid Build Coastguard Worker 
235*8617a60dSAndroid Build Coastguard Worker 	/*
236*8617a60dSAndroid Build Coastguard Worker 	 * Limit kernel version rollforward if needed.  Can't limit kernel
237*8617a60dSAndroid Build Coastguard Worker 	 * version to less than the version currently in the TPM.  That is,
238*8617a60dSAndroid Build Coastguard Worker 	 * we're limiting rollforward, not allowing rollback.
239*8617a60dSAndroid Build Coastguard Worker 	 */
240*8617a60dSAndroid Build Coastguard Worker 	uint32_t original_kernel_version =
241*8617a60dSAndroid Build Coastguard Worker 		vb2_secdata_kernel_get(ctx, VB2_SECDATA_KERNEL_VERSIONS);
242*8617a60dSAndroid Build Coastguard Worker 
243*8617a60dSAndroid Build Coastguard Worker 	if (max_rollforward < original_kernel_version)
244*8617a60dSAndroid Build Coastguard Worker 		max_rollforward = original_kernel_version;
245*8617a60dSAndroid Build Coastguard Worker 
246*8617a60dSAndroid Build Coastguard Worker 	if (sd->kernel_version_secdata > max_rollforward) {
247*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Limiting TPM kernel version roll-forward "
248*8617a60dSAndroid Build Coastguard Worker 			  "to %#x < %#x\n",
249*8617a60dSAndroid Build Coastguard Worker 			  max_rollforward, sd->kernel_version_secdata);
250*8617a60dSAndroid Build Coastguard Worker 
251*8617a60dSAndroid Build Coastguard Worker 		sd->kernel_version_secdata = max_rollforward;
252*8617a60dSAndroid Build Coastguard Worker 	}
253*8617a60dSAndroid Build Coastguard Worker 
254*8617a60dSAndroid Build Coastguard Worker 	if (sd->kernel_version_secdata > original_kernel_version) {
255*8617a60dSAndroid Build Coastguard Worker 		vb2_secdata_kernel_set(ctx, VB2_SECDATA_KERNEL_VERSIONS,
256*8617a60dSAndroid Build Coastguard Worker 				       sd->kernel_version_secdata);
257*8617a60dSAndroid Build Coastguard Worker 	} else {
258*8617a60dSAndroid Build Coastguard Worker 		sd->kernel_version_secdata = original_kernel_version;
259*8617a60dSAndroid Build Coastguard Worker 	}
260*8617a60dSAndroid Build Coastguard Worker }
261*8617a60dSAndroid Build Coastguard Worker 
vb2api_kernel_finalize(struct vb2_context * ctx)262*8617a60dSAndroid Build Coastguard Worker vb2_error_t vb2api_kernel_finalize(struct vb2_context *ctx)
263*8617a60dSAndroid Build Coastguard Worker {
264*8617a60dSAndroid Build Coastguard Worker 	vb2_gbb_flags_t gbb_flags = vb2api_gbb_get_flags(ctx);
265*8617a60dSAndroid Build Coastguard Worker 
266*8617a60dSAndroid Build Coastguard Worker 	/*
267*8617a60dSAndroid Build Coastguard Worker 	 * Disallow booting to kernel when NO_BOOT flag is set, except when
268*8617a60dSAndroid Build Coastguard Worker 	 * GBB flag disables software sync.
269*8617a60dSAndroid Build Coastguard Worker 	 */
270*8617a60dSAndroid Build Coastguard Worker 	if (!(gbb_flags & VB2_GBB_FLAG_DISABLE_EC_SOFTWARE_SYNC)
271*8617a60dSAndroid Build Coastguard Worker 	    && (ctx->flags & VB2_CONTEXT_EC_SYNC_SUPPORTED)
272*8617a60dSAndroid Build Coastguard Worker 	    && (ctx->flags & VB2_CONTEXT_NO_BOOT)) {
273*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Blocking escape from NO_BOOT mode.\n");
274*8617a60dSAndroid Build Coastguard Worker 		vb2api_fail(ctx, VB2_RECOVERY_ESCAPE_NO_BOOT, 0);
275*8617a60dSAndroid Build Coastguard Worker 		return VB2_ERROR_ESCAPE_NO_BOOT;
276*8617a60dSAndroid Build Coastguard Worker 	}
277*8617a60dSAndroid Build Coastguard Worker 
278*8617a60dSAndroid Build Coastguard Worker 	if (ctx->boot_mode == VB2_BOOT_MODE_NORMAL)
279*8617a60dSAndroid Build Coastguard Worker 		update_kernel_version(ctx);
280*8617a60dSAndroid Build Coastguard Worker 
281*8617a60dSAndroid Build Coastguard Worker 	return VB2_SUCCESS;
282*8617a60dSAndroid Build Coastguard Worker }
283