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