1*8617a60dSAndroid Build Coastguard Worker /* Copyright 2019 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 * Auxiliary firmware (auxfw) 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
13*8617a60dSAndroid Build Coastguard Worker /**
14*8617a60dSAndroid Build Coastguard Worker * Determine if we are allowed to update auxfw.
15*8617a60dSAndroid Build Coastguard Worker *
16*8617a60dSAndroid Build Coastguard Worker * @param ctx Vboot2 context
17*8617a60dSAndroid Build Coastguard Worker * @return boolean (true iff we can update auxfw)
18*8617a60dSAndroid Build Coastguard Worker */
auxfw_sync_allowed(struct vb2_context * ctx)19*8617a60dSAndroid Build Coastguard Worker static int auxfw_sync_allowed(struct vb2_context *ctx)
20*8617a60dSAndroid Build Coastguard Worker {
21*8617a60dSAndroid Build Coastguard Worker struct vb2_gbb_header *gbb = vb2_get_gbb(ctx);
22*8617a60dSAndroid Build Coastguard Worker
23*8617a60dSAndroid Build Coastguard Worker /* Reasons not to do sync at all */
24*8617a60dSAndroid Build Coastguard Worker if (gbb->flags & VB2_GBB_FLAG_DISABLE_AUXFW_SOFTWARE_SYNC)
25*8617a60dSAndroid Build Coastguard Worker return 0;
26*8617a60dSAndroid Build Coastguard Worker if (ctx->flags & VB2_CONTEXT_RECOVERY_MODE)
27*8617a60dSAndroid Build Coastguard Worker return 0;
28*8617a60dSAndroid Build Coastguard Worker return 1;
29*8617a60dSAndroid Build Coastguard Worker }
30*8617a60dSAndroid Build Coastguard Worker
31*8617a60dSAndroid Build Coastguard Worker /**
32*8617a60dSAndroid Build Coastguard Worker * Decides if auxfw sync is allowed to be performed.
33*8617a60dSAndroid Build Coastguard Worker *
34*8617a60dSAndroid Build Coastguard Worker * If sync is allowed, invokes the external callback,
35*8617a60dSAndroid Build Coastguard Worker * vb2ex_auxfw_check() to allow the client to decide on the auxfw
36*8617a60dSAndroid Build Coastguard Worker * update severity.
37*8617a60dSAndroid Build Coastguard Worker *
38*8617a60dSAndroid Build Coastguard Worker * @param ctx Vboot2 context
39*8617a60dSAndroid Build Coastguard Worker * @return VB2_SUCCESS, or non-zero error code.
40*8617a60dSAndroid Build Coastguard Worker */
auxfw_sync_check_update(struct vb2_context * ctx,enum vb2_auxfw_update_severity * severity)41*8617a60dSAndroid Build Coastguard Worker static vb2_error_t auxfw_sync_check_update(struct vb2_context *ctx,
42*8617a60dSAndroid Build Coastguard Worker enum vb2_auxfw_update_severity *severity)
43*8617a60dSAndroid Build Coastguard Worker {
44*8617a60dSAndroid Build Coastguard Worker if (!auxfw_sync_allowed(ctx)) {
45*8617a60dSAndroid Build Coastguard Worker *severity = VB2_AUXFW_NO_UPDATE;
46*8617a60dSAndroid Build Coastguard Worker return VB2_SUCCESS;
47*8617a60dSAndroid Build Coastguard Worker }
48*8617a60dSAndroid Build Coastguard Worker
49*8617a60dSAndroid Build Coastguard Worker return vb2ex_auxfw_check(severity);
50*8617a60dSAndroid Build Coastguard Worker }
51*8617a60dSAndroid Build Coastguard Worker
52*8617a60dSAndroid Build Coastguard Worker test_mockable
vb2api_auxfw_sync(struct vb2_context * ctx)53*8617a60dSAndroid Build Coastguard Worker vb2_error_t vb2api_auxfw_sync(struct vb2_context *ctx)
54*8617a60dSAndroid Build Coastguard Worker {
55*8617a60dSAndroid Build Coastguard Worker enum vb2_auxfw_update_severity fw_update = VB2_AUXFW_NO_UPDATE;
56*8617a60dSAndroid Build Coastguard Worker
57*8617a60dSAndroid Build Coastguard Worker /* Check for update severity */
58*8617a60dSAndroid Build Coastguard Worker VB2_TRY(auxfw_sync_check_update(ctx, &fw_update), ctx,
59*8617a60dSAndroid Build Coastguard Worker VB2_RECOVERY_AUXFW_UPDATE);
60*8617a60dSAndroid Build Coastguard Worker
61*8617a60dSAndroid Build Coastguard Worker if (fw_update > VB2_AUXFW_NO_UPDATE) {
62*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Updating auxfw\n");
63*8617a60dSAndroid Build Coastguard Worker VB2_TRY(vb2ex_auxfw_update(), ctx, VB2_RECOVERY_AUXFW_UPDATE);
64*8617a60dSAndroid Build Coastguard Worker /*
65*8617a60dSAndroid Build Coastguard Worker * EC sync (if any) happens before auxfw sync. Now that auxfw
66*8617a60dSAndroid Build Coastguard Worker * sync is applied successfully, we are almost sure there will
67*8617a60dSAndroid Build Coastguard Worker * be no EC/auxfw sync in the next boot. Therefore, clear
68*8617a60dSAndroid Build Coastguard Worker * DISPLAY_REQUEST in advance so that the device can boot to
69*8617a60dSAndroid Build Coastguard Worker * kernel in normal mode where DISPLAY_REQUEST is not allowed.
70*8617a60dSAndroid Build Coastguard Worker */
71*8617a60dSAndroid Build Coastguard Worker vb2_nv_set(ctx, VB2_NV_DISPLAY_REQUEST, 0);
72*8617a60dSAndroid Build Coastguard Worker /*
73*8617a60dSAndroid Build Coastguard Worker * Request EC reboot to RO, so that the chips that had FW update
74*8617a60dSAndroid Build Coastguard Worker * get reset to a clean state.
75*8617a60dSAndroid Build Coastguard Worker */
76*8617a60dSAndroid Build Coastguard Worker return VB2_REQUEST_REBOOT_EC_TO_RO;
77*8617a60dSAndroid Build Coastguard Worker }
78*8617a60dSAndroid Build Coastguard Worker
79*8617a60dSAndroid Build Coastguard Worker return vb2ex_auxfw_finalize(ctx);
80*8617a60dSAndroid Build Coastguard Worker }
81