1*8617a60dSAndroid Build Coastguard Worker /* Copyright 2018 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 * A reference implementation for AP (and supporting images) firmware updater.
6*8617a60dSAndroid Build Coastguard Worker */
7*8617a60dSAndroid Build Coastguard Worker
8*8617a60dSAndroid Build Coastguard Worker #include <assert.h>
9*8617a60dSAndroid Build Coastguard Worker #include <ctype.h>
10*8617a60dSAndroid Build Coastguard Worker #include <sys/stat.h>
11*8617a60dSAndroid Build Coastguard Worker
12*8617a60dSAndroid Build Coastguard Worker #include "2rsa.h"
13*8617a60dSAndroid Build Coastguard Worker #include "cbfstool.h"
14*8617a60dSAndroid Build Coastguard Worker #include "futility.h"
15*8617a60dSAndroid Build Coastguard Worker #include "host_misc.h"
16*8617a60dSAndroid Build Coastguard Worker #include "platform_csme.h"
17*8617a60dSAndroid Build Coastguard Worker #include "updater.h"
18*8617a60dSAndroid Build Coastguard Worker #include "util_misc.h"
19*8617a60dSAndroid Build Coastguard Worker
20*8617a60dSAndroid Build Coastguard Worker #define REMOVE_WP_URL "https://goo.gl/ces83U"
21*8617a60dSAndroid Build Coastguard Worker
22*8617a60dSAndroid Build Coastguard Worker static const char ROOTKEY_HASH_DEV[] =
23*8617a60dSAndroid Build Coastguard Worker "b11d74edd286c144e1135b49e7f0bc20cf041f10";
24*8617a60dSAndroid Build Coastguard Worker
25*8617a60dSAndroid Build Coastguard Worker enum target_type {
26*8617a60dSAndroid Build Coastguard Worker TARGET_SELF,
27*8617a60dSAndroid Build Coastguard Worker TARGET_UPDATE,
28*8617a60dSAndroid Build Coastguard Worker };
29*8617a60dSAndroid Build Coastguard Worker
30*8617a60dSAndroid Build Coastguard Worker enum rootkey_compat_result {
31*8617a60dSAndroid Build Coastguard Worker ROOTKEY_COMPAT_OK,
32*8617a60dSAndroid Build Coastguard Worker ROOTKEY_COMPAT_ERROR,
33*8617a60dSAndroid Build Coastguard Worker ROOTKEY_COMPAT_REKEY,
34*8617a60dSAndroid Build Coastguard Worker ROOTKEY_COMPAT_REKEY_TO_DEV,
35*8617a60dSAndroid Build Coastguard Worker };
36*8617a60dSAndroid Build Coastguard Worker
print_dut_properties(struct updater_config * cfg)37*8617a60dSAndroid Build Coastguard Worker static void print_dut_properties(struct updater_config *cfg)
38*8617a60dSAndroid Build Coastguard Worker {
39*8617a60dSAndroid Build Coastguard Worker int i;
40*8617a60dSAndroid Build Coastguard Worker
41*8617a60dSAndroid Build Coastguard Worker /*
42*8617a60dSAndroid Build Coastguard Worker * There may be error messages when fetching properties from active
43*8617a60dSAndroid Build Coastguard Worker * system, so we want to peek at them first and then print out.
44*8617a60dSAndroid Build Coastguard Worker */
45*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Scanning system properties...\n");
46*8617a60dSAndroid Build Coastguard Worker for (i = 0; i < DUT_PROP_MAX; i++)
47*8617a60dSAndroid Build Coastguard Worker dut_get_property((enum dut_property_type)i, cfg);
48*8617a60dSAndroid Build Coastguard Worker
49*8617a60dSAndroid Build Coastguard Worker printf("System properties: [");
50*8617a60dSAndroid Build Coastguard Worker for (i = 0; i < DUT_PROP_MAX; i++) {
51*8617a60dSAndroid Build Coastguard Worker printf("%d,",
52*8617a60dSAndroid Build Coastguard Worker dut_get_property((enum dut_property_type)i, cfg));
53*8617a60dSAndroid Build Coastguard Worker }
54*8617a60dSAndroid Build Coastguard Worker printf("]\n");
55*8617a60dSAndroid Build Coastguard Worker }
56*8617a60dSAndroid Build Coastguard Worker
57*8617a60dSAndroid Build Coastguard Worker /*
58*8617a60dSAndroid Build Coastguard Worker * Overrides the return value of a system property.
59*8617a60dSAndroid Build Coastguard Worker * After invoked, next call to dut_get_property(type, cfg) will return
60*8617a60dSAndroid Build Coastguard Worker * the given value.
61*8617a60dSAndroid Build Coastguard Worker */
override_dut_property(enum dut_property_type property_type,struct updater_config * cfg,int value)62*8617a60dSAndroid Build Coastguard Worker static void override_dut_property(enum dut_property_type property_type,
63*8617a60dSAndroid Build Coastguard Worker struct updater_config *cfg, int value)
64*8617a60dSAndroid Build Coastguard Worker {
65*8617a60dSAndroid Build Coastguard Worker struct dut_property *prop;
66*8617a60dSAndroid Build Coastguard Worker
67*8617a60dSAndroid Build Coastguard Worker assert(property_type < DUT_PROP_MAX);
68*8617a60dSAndroid Build Coastguard Worker prop = &cfg->dut_properties[property_type];
69*8617a60dSAndroid Build Coastguard Worker prop->initialized = 1;
70*8617a60dSAndroid Build Coastguard Worker prop->value = value;
71*8617a60dSAndroid Build Coastguard Worker }
72*8617a60dSAndroid Build Coastguard Worker
73*8617a60dSAndroid Build Coastguard Worker /*
74*8617a60dSAndroid Build Coastguard Worker * Overrides DUT properties with default values.
75*8617a60dSAndroid Build Coastguard Worker * With emulation, dut_get_property() calls would fail without specifying the
76*8617a60dSAndroid Build Coastguard Worker * fake DUT properties via --sys_props. Therefore, this function provides
77*8617a60dSAndroid Build Coastguard Worker * reasonable default values for emulation.
78*8617a60dSAndroid Build Coastguard Worker */
override_properties_with_default(struct updater_config * cfg)79*8617a60dSAndroid Build Coastguard Worker static void override_properties_with_default(struct updater_config *cfg)
80*8617a60dSAndroid Build Coastguard Worker {
81*8617a60dSAndroid Build Coastguard Worker assert(cfg->emulation);
82*8617a60dSAndroid Build Coastguard Worker
83*8617a60dSAndroid Build Coastguard Worker override_dut_property(DUT_PROP_MAINFW_ACT, cfg, SLOT_A);
84*8617a60dSAndroid Build Coastguard Worker override_dut_property(DUT_PROP_TPM_FWVER, cfg, 0x10001);
85*8617a60dSAndroid Build Coastguard Worker override_dut_property(DUT_PROP_PLATFORM_VER, cfg, 0);
86*8617a60dSAndroid Build Coastguard Worker override_dut_property(DUT_PROP_WP_HW, cfg, 0);
87*8617a60dSAndroid Build Coastguard Worker override_dut_property(DUT_PROP_WP_SW_AP, cfg, 0);
88*8617a60dSAndroid Build Coastguard Worker override_dut_property(DUT_PROP_WP_SW_EC, cfg, 0);
89*8617a60dSAndroid Build Coastguard Worker }
90*8617a60dSAndroid Build Coastguard Worker
91*8617a60dSAndroid Build Coastguard Worker /*
92*8617a60dSAndroid Build Coastguard Worker * Overrides DUT properties from a given list.
93*8617a60dSAndroid Build Coastguard Worker * The list should be string of integers eliminated by comma and/or space.
94*8617a60dSAndroid Build Coastguard Worker * For example, "1 2 3" and "1,2,3" both overrides first 3 properties.
95*8617a60dSAndroid Build Coastguard Worker * To skip some properties you have to use comma, for example
96*8617a60dSAndroid Build Coastguard Worker * "1, , 3" will only override the first and 3rd properties.
97*8617a60dSAndroid Build Coastguard Worker * Invalid characters and fields will be ignored.
98*8617a60dSAndroid Build Coastguard Worker *
99*8617a60dSAndroid Build Coastguard Worker * The current implementation is only for unit testing.
100*8617a60dSAndroid Build Coastguard Worker * In future we may extend this with name=value so users can use it easily on
101*8617a60dSAndroid Build Coastguard Worker * actual systems.
102*8617a60dSAndroid Build Coastguard Worker */
override_properties_from_list(const char * override_list,struct updater_config * cfg)103*8617a60dSAndroid Build Coastguard Worker static void override_properties_from_list(const char *override_list,
104*8617a60dSAndroid Build Coastguard Worker struct updater_config *cfg)
105*8617a60dSAndroid Build Coastguard Worker {
106*8617a60dSAndroid Build Coastguard Worker const char *s = override_list;
107*8617a60dSAndroid Build Coastguard Worker char *e, c;
108*8617a60dSAndroid Build Coastguard Worker int i = 0, wait_comma = 0;
109*8617a60dSAndroid Build Coastguard Worker long int v;
110*8617a60dSAndroid Build Coastguard Worker
111*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Input is <%s>\n", override_list);
112*8617a60dSAndroid Build Coastguard Worker for (c = *s; c; c = *++s) {
113*8617a60dSAndroid Build Coastguard Worker if (c == ',') {
114*8617a60dSAndroid Build Coastguard Worker if (!wait_comma)
115*8617a60dSAndroid Build Coastguard Worker i++;
116*8617a60dSAndroid Build Coastguard Worker wait_comma = 0;
117*8617a60dSAndroid Build Coastguard Worker }
118*8617a60dSAndroid Build Coastguard Worker if (!isascii(c) || !(isdigit(c) || c == '-'))
119*8617a60dSAndroid Build Coastguard Worker continue;
120*8617a60dSAndroid Build Coastguard Worker if (i >= DUT_PROP_MAX) {
121*8617a60dSAndroid Build Coastguard Worker ERROR("Too many fields (max is %d): %s.\n",
122*8617a60dSAndroid Build Coastguard Worker DUT_PROP_MAX, override_list);
123*8617a60dSAndroid Build Coastguard Worker return;
124*8617a60dSAndroid Build Coastguard Worker }
125*8617a60dSAndroid Build Coastguard Worker v = strtol(s, &e, 0);
126*8617a60dSAndroid Build Coastguard Worker s = e - 1;
127*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("property[%d].value = %ld\n", i, v);
128*8617a60dSAndroid Build Coastguard Worker override_dut_property((enum dut_property_type)i, cfg, v);
129*8617a60dSAndroid Build Coastguard Worker wait_comma = 1;
130*8617a60dSAndroid Build Coastguard Worker i++;
131*8617a60dSAndroid Build Coastguard Worker }
132*8617a60dSAndroid Build Coastguard Worker }
133*8617a60dSAndroid Build Coastguard Worker
get_config_quirk(enum quirk_types quirk,const struct updater_config * cfg)134*8617a60dSAndroid Build Coastguard Worker int get_config_quirk(enum quirk_types quirk, const struct updater_config *cfg)
135*8617a60dSAndroid Build Coastguard Worker {
136*8617a60dSAndroid Build Coastguard Worker assert(quirk < QUIRK_MAX);
137*8617a60dSAndroid Build Coastguard Worker return cfg->quirks[quirk].value;
138*8617a60dSAndroid Build Coastguard Worker }
139*8617a60dSAndroid Build Coastguard Worker
updater_list_config_quirks(const struct updater_config * cfg)140*8617a60dSAndroid Build Coastguard Worker void updater_list_config_quirks(const struct updater_config *cfg)
141*8617a60dSAndroid Build Coastguard Worker {
142*8617a60dSAndroid Build Coastguard Worker const struct quirk_entry *entry = cfg->quirks;
143*8617a60dSAndroid Build Coastguard Worker int i;
144*8617a60dSAndroid Build Coastguard Worker
145*8617a60dSAndroid Build Coastguard Worker printf("Supported quirks:\n");
146*8617a60dSAndroid Build Coastguard Worker for (i = 0; i < QUIRK_MAX; i++, entry++) {
147*8617a60dSAndroid Build Coastguard Worker printf(" '%s': %s (default: %d)\n", entry->name,
148*8617a60dSAndroid Build Coastguard Worker entry->help ? entry->help : "(no description)",
149*8617a60dSAndroid Build Coastguard Worker get_config_quirk((enum quirk_types)i, cfg));
150*8617a60dSAndroid Build Coastguard Worker }
151*8617a60dSAndroid Build Coastguard Worker }
152*8617a60dSAndroid Build Coastguard Worker
153*8617a60dSAndroid Build Coastguard Worker /*
154*8617a60dSAndroid Build Coastguard Worker * Applies a quirk if applicable (the value should be non-zero).
155*8617a60dSAndroid Build Coastguard Worker * Returns 0 on success, otherwise failure.
156*8617a60dSAndroid Build Coastguard Worker */
try_apply_quirk(enum quirk_types quirk,struct updater_config * cfg)157*8617a60dSAndroid Build Coastguard Worker static int try_apply_quirk(enum quirk_types quirk, struct updater_config *cfg)
158*8617a60dSAndroid Build Coastguard Worker {
159*8617a60dSAndroid Build Coastguard Worker const struct quirk_entry *entry = cfg->quirks + quirk;
160*8617a60dSAndroid Build Coastguard Worker assert(quirk < QUIRK_MAX);
161*8617a60dSAndroid Build Coastguard Worker
162*8617a60dSAndroid Build Coastguard Worker if (!entry->value)
163*8617a60dSAndroid Build Coastguard Worker return 0;
164*8617a60dSAndroid Build Coastguard Worker
165*8617a60dSAndroid Build Coastguard Worker if (!entry->apply) {
166*8617a60dSAndroid Build Coastguard Worker ERROR("<%s> not implemented.\n", entry->name);
167*8617a60dSAndroid Build Coastguard Worker return -1;
168*8617a60dSAndroid Build Coastguard Worker }
169*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Applying quirk <%s>.\n", entry->name);
170*8617a60dSAndroid Build Coastguard Worker return entry->apply(cfg);
171*8617a60dSAndroid Build Coastguard Worker }
172*8617a60dSAndroid Build Coastguard Worker
173*8617a60dSAndroid Build Coastguard Worker /*
174*8617a60dSAndroid Build Coastguard Worker * Initialize the updater_config quirks from a list of settings.
175*8617a60dSAndroid Build Coastguard Worker * Returns 0 on success, otherwise failure.
176*8617a60dSAndroid Build Coastguard Worker */
setup_config_quirks(const char * quirks,struct updater_config * cfg)177*8617a60dSAndroid Build Coastguard Worker static int setup_config_quirks(const char *quirks, struct updater_config *cfg)
178*8617a60dSAndroid Build Coastguard Worker {
179*8617a60dSAndroid Build Coastguard Worker /*
180*8617a60dSAndroid Build Coastguard Worker * The list should be in NAME[=VALUE],...
181*8617a60dSAndroid Build Coastguard Worker * Value defaults to 1 if not specified.
182*8617a60dSAndroid Build Coastguard Worker */
183*8617a60dSAndroid Build Coastguard Worker int r = 0;
184*8617a60dSAndroid Build Coastguard Worker char *buf = strdup(quirks);
185*8617a60dSAndroid Build Coastguard Worker char *token;
186*8617a60dSAndroid Build Coastguard Worker const char *delimiters = ", \n\r\t";
187*8617a60dSAndroid Build Coastguard Worker
188*8617a60dSAndroid Build Coastguard Worker token = strtok(buf, delimiters);
189*8617a60dSAndroid Build Coastguard Worker for (; token; token = strtok(NULL, delimiters)) {
190*8617a60dSAndroid Build Coastguard Worker const char *name = token;
191*8617a60dSAndroid Build Coastguard Worker char *equ = strchr(token, '=');
192*8617a60dSAndroid Build Coastguard Worker int i, value = 1;
193*8617a60dSAndroid Build Coastguard Worker struct quirk_entry *entry = cfg->quirks;
194*8617a60dSAndroid Build Coastguard Worker
195*8617a60dSAndroid Build Coastguard Worker if (!*name)
196*8617a60dSAndroid Build Coastguard Worker continue;
197*8617a60dSAndroid Build Coastguard Worker
198*8617a60dSAndroid Build Coastguard Worker if (equ) {
199*8617a60dSAndroid Build Coastguard Worker *equ = '\0';
200*8617a60dSAndroid Build Coastguard Worker value = strtol(equ + 1, NULL, 0);
201*8617a60dSAndroid Build Coastguard Worker }
202*8617a60dSAndroid Build Coastguard Worker
203*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Looking for quirk <%s=%d>.\n", name, value);
204*8617a60dSAndroid Build Coastguard Worker for (i = 0; i < QUIRK_MAX; i++, entry++) {
205*8617a60dSAndroid Build Coastguard Worker if (strcmp(name, entry->name))
206*8617a60dSAndroid Build Coastguard Worker continue;
207*8617a60dSAndroid Build Coastguard Worker entry->value = value;
208*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Set quirk %s to %d.\n", entry->name, value);
209*8617a60dSAndroid Build Coastguard Worker break;
210*8617a60dSAndroid Build Coastguard Worker }
211*8617a60dSAndroid Build Coastguard Worker if (i >= QUIRK_MAX) {
212*8617a60dSAndroid Build Coastguard Worker ERROR("Unknown quirk: %s\n", name);
213*8617a60dSAndroid Build Coastguard Worker r++;
214*8617a60dSAndroid Build Coastguard Worker }
215*8617a60dSAndroid Build Coastguard Worker }
216*8617a60dSAndroid Build Coastguard Worker free(buf);
217*8617a60dSAndroid Build Coastguard Worker return r;
218*8617a60dSAndroid Build Coastguard Worker }
219*8617a60dSAndroid Build Coastguard Worker
220*8617a60dSAndroid Build Coastguard Worker /*
221*8617a60dSAndroid Build Coastguard Worker * Checks if the section is filled with given character.
222*8617a60dSAndroid Build Coastguard Worker * If section size is 0, return 0. If section is not empty, return non-zero if
223*8617a60dSAndroid Build Coastguard Worker * the section is filled with same character c, otherwise 0.
224*8617a60dSAndroid Build Coastguard Worker */
section_is_filled_with(const struct firmware_section * section,uint8_t c)225*8617a60dSAndroid Build Coastguard Worker static int section_is_filled_with(const struct firmware_section *section,
226*8617a60dSAndroid Build Coastguard Worker uint8_t c)
227*8617a60dSAndroid Build Coastguard Worker {
228*8617a60dSAndroid Build Coastguard Worker uint32_t i;
229*8617a60dSAndroid Build Coastguard Worker if (!section->size)
230*8617a60dSAndroid Build Coastguard Worker return 0;
231*8617a60dSAndroid Build Coastguard Worker for (i = 0; i < section->size; i++)
232*8617a60dSAndroid Build Coastguard Worker if (section->data[i] != c)
233*8617a60dSAndroid Build Coastguard Worker return 0;
234*8617a60dSAndroid Build Coastguard Worker return 1;
235*8617a60dSAndroid Build Coastguard Worker }
236*8617a60dSAndroid Build Coastguard Worker
237*8617a60dSAndroid Build Coastguard Worker /*
238*8617a60dSAndroid Build Coastguard Worker * Decides which target in RW firmware to manipulate.
239*8617a60dSAndroid Build Coastguard Worker * The `target` argument specifies if we want to know "the section to be
240*8617a60dSAndroid Build Coastguard Worker * update" (TARGET_UPDATE), or "the (active) section * to check" (TARGET_SELF).
241*8617a60dSAndroid Build Coastguard Worker * Returns the section name if success, otherwise NULL.
242*8617a60dSAndroid Build Coastguard Worker */
decide_rw_target(struct updater_config * cfg,enum target_type target)243*8617a60dSAndroid Build Coastguard Worker static const char *decide_rw_target(struct updater_config *cfg,
244*8617a60dSAndroid Build Coastguard Worker enum target_type target)
245*8617a60dSAndroid Build Coastguard Worker {
246*8617a60dSAndroid Build Coastguard Worker const char *a = FMAP_RW_SECTION_A, *b = FMAP_RW_SECTION_B;
247*8617a60dSAndroid Build Coastguard Worker int slot = dut_get_property(DUT_PROP_MAINFW_ACT, cfg);
248*8617a60dSAndroid Build Coastguard Worker
249*8617a60dSAndroid Build Coastguard Worker switch (slot) {
250*8617a60dSAndroid Build Coastguard Worker case SLOT_A:
251*8617a60dSAndroid Build Coastguard Worker return target == TARGET_UPDATE ? b : a;
252*8617a60dSAndroid Build Coastguard Worker
253*8617a60dSAndroid Build Coastguard Worker case SLOT_B:
254*8617a60dSAndroid Build Coastguard Worker return target == TARGET_UPDATE ? a : b;
255*8617a60dSAndroid Build Coastguard Worker }
256*8617a60dSAndroid Build Coastguard Worker
257*8617a60dSAndroid Build Coastguard Worker return NULL;
258*8617a60dSAndroid Build Coastguard Worker }
259*8617a60dSAndroid Build Coastguard Worker
260*8617a60dSAndroid Build Coastguard Worker /*
261*8617a60dSAndroid Build Coastguard Worker * Sets any needed DUT properties to indicate system should try the new
262*8617a60dSAndroid Build Coastguard Worker * firmware on next boot.
263*8617a60dSAndroid Build Coastguard Worker * The `target` argument is an FMAP section name indicating which to try.
264*8617a60dSAndroid Build Coastguard Worker * Returns 0 if success, non-zero if error.
265*8617a60dSAndroid Build Coastguard Worker */
set_try_cookies(struct updater_config * cfg,const char * target,int has_update)266*8617a60dSAndroid Build Coastguard Worker static int set_try_cookies(struct updater_config *cfg, const char *target,
267*8617a60dSAndroid Build Coastguard Worker int has_update)
268*8617a60dSAndroid Build Coastguard Worker {
269*8617a60dSAndroid Build Coastguard Worker int tries = 13;
270*8617a60dSAndroid Build Coastguard Worker const char *slot;
271*8617a60dSAndroid Build Coastguard Worker
272*8617a60dSAndroid Build Coastguard Worker if (!has_update)
273*8617a60dSAndroid Build Coastguard Worker tries = 0;
274*8617a60dSAndroid Build Coastguard Worker
275*8617a60dSAndroid Build Coastguard Worker /* Find new slot according to target (section) name. */
276*8617a60dSAndroid Build Coastguard Worker if (strcmp(target, FMAP_RW_SECTION_A) == 0)
277*8617a60dSAndroid Build Coastguard Worker slot = FWACT_A;
278*8617a60dSAndroid Build Coastguard Worker else if (strcmp(target, FMAP_RW_SECTION_B) == 0)
279*8617a60dSAndroid Build Coastguard Worker slot = FWACT_B;
280*8617a60dSAndroid Build Coastguard Worker else {
281*8617a60dSAndroid Build Coastguard Worker ERROR("Unknown target: %s\n", target);
282*8617a60dSAndroid Build Coastguard Worker return -1;
283*8617a60dSAndroid Build Coastguard Worker }
284*8617a60dSAndroid Build Coastguard Worker
285*8617a60dSAndroid Build Coastguard Worker if (cfg->emulation) {
286*8617a60dSAndroid Build Coastguard Worker INFO("(emulation) %s slot %s on next boot, try_count=%d.\n",
287*8617a60dSAndroid Build Coastguard Worker has_update ? "Try" : "Keep", slot, tries);
288*8617a60dSAndroid Build Coastguard Worker return 0;
289*8617a60dSAndroid Build Coastguard Worker }
290*8617a60dSAndroid Build Coastguard Worker
291*8617a60dSAndroid Build Coastguard Worker if (dut_set_property_string("fw_try_next", slot, cfg)) {
292*8617a60dSAndroid Build Coastguard Worker ERROR("Failed to set fw_try_next to %s.\n", slot);
293*8617a60dSAndroid Build Coastguard Worker return -1;
294*8617a60dSAndroid Build Coastguard Worker }
295*8617a60dSAndroid Build Coastguard Worker if (!has_update &&
296*8617a60dSAndroid Build Coastguard Worker dut_set_property_string("fw_result", "success", cfg)) {
297*8617a60dSAndroid Build Coastguard Worker ERROR("Failed to set fw_result to success.\n");
298*8617a60dSAndroid Build Coastguard Worker return -1;
299*8617a60dSAndroid Build Coastguard Worker }
300*8617a60dSAndroid Build Coastguard Worker
301*8617a60dSAndroid Build Coastguard Worker if (dut_set_property_int("fw_try_count", tries, cfg)) {
302*8617a60dSAndroid Build Coastguard Worker ERROR("Failed to set fw_try_count to %d.\n", tries);
303*8617a60dSAndroid Build Coastguard Worker return -1;
304*8617a60dSAndroid Build Coastguard Worker }
305*8617a60dSAndroid Build Coastguard Worker
306*8617a60dSAndroid Build Coastguard Worker return 0;
307*8617a60dSAndroid Build Coastguard Worker }
308*8617a60dSAndroid Build Coastguard Worker
309*8617a60dSAndroid Build Coastguard Worker /*
310*8617a60dSAndroid Build Coastguard Worker * Returns True if we should start the update process for given image.
311*8617a60dSAndroid Build Coastguard Worker */
has_valid_update(struct updater_config * cfg,const struct firmware_image * image,const char * section_name,int is_host)312*8617a60dSAndroid Build Coastguard Worker static int has_valid_update(struct updater_config *cfg,
313*8617a60dSAndroid Build Coastguard Worker const struct firmware_image *image,
314*8617a60dSAndroid Build Coastguard Worker const char *section_name,
315*8617a60dSAndroid Build Coastguard Worker int is_host)
316*8617a60dSAndroid Build Coastguard Worker {
317*8617a60dSAndroid Build Coastguard Worker if (!image->data) {
318*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("No data in <%s> image.\n", image->programmer);
319*8617a60dSAndroid Build Coastguard Worker return 0;
320*8617a60dSAndroid Build Coastguard Worker }
321*8617a60dSAndroid Build Coastguard Worker if (section_name && !firmware_section_exists(image, section_name)) {
322*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Image %s<%s> does not have section %s.\n",
323*8617a60dSAndroid Build Coastguard Worker image->file_name, image->programmer, section_name);
324*8617a60dSAndroid Build Coastguard Worker return 0;
325*8617a60dSAndroid Build Coastguard Worker }
326*8617a60dSAndroid Build Coastguard Worker /* Currently only host emulation is supported. */
327*8617a60dSAndroid Build Coastguard Worker if (cfg->emulation && !is_host) {
328*8617a60dSAndroid Build Coastguard Worker INFO("(emulation) Update %s from %s to %s (%d bytes), "
329*8617a60dSAndroid Build Coastguard Worker "skipped for non-host targets in emulation.\n",
330*8617a60dSAndroid Build Coastguard Worker section_name ? section_name : "whole image",
331*8617a60dSAndroid Build Coastguard Worker image->file_name, image->programmer, image->size);
332*8617a60dSAndroid Build Coastguard Worker return 0;
333*8617a60dSAndroid Build Coastguard Worker }
334*8617a60dSAndroid Build Coastguard Worker return 1;
335*8617a60dSAndroid Build Coastguard Worker }
336*8617a60dSAndroid Build Coastguard Worker
337*8617a60dSAndroid Build Coastguard Worker /*
338*8617a60dSAndroid Build Coastguard Worker * Preserve the GBB contents from image_from to image_to.
339*8617a60dSAndroid Build Coastguard Worker * HWID is always preserved, and flags are preserved only if preserve_flags set.
340*8617a60dSAndroid Build Coastguard Worker * Returns 0 if success, otherwise -1 if GBB header can't be found or if HWID is
341*8617a60dSAndroid Build Coastguard Worker * too large.
342*8617a60dSAndroid Build Coastguard Worker */
preserve_gbb(const struct firmware_image * image_from,struct firmware_image * image_to,int preserve_flags,int override_flags,uint64_t override_value)343*8617a60dSAndroid Build Coastguard Worker static int preserve_gbb(const struct firmware_image *image_from,
344*8617a60dSAndroid Build Coastguard Worker struct firmware_image *image_to,
345*8617a60dSAndroid Build Coastguard Worker int preserve_flags, int override_flags,
346*8617a60dSAndroid Build Coastguard Worker uint64_t override_value)
347*8617a60dSAndroid Build Coastguard Worker {
348*8617a60dSAndroid Build Coastguard Worker const struct vb2_gbb_header *gbb_from;
349*8617a60dSAndroid Build Coastguard Worker struct vb2_gbb_header *gbb_to;
350*8617a60dSAndroid Build Coastguard Worker
351*8617a60dSAndroid Build Coastguard Worker /* Cast to non-const because we do want to change GBB contents later. */
352*8617a60dSAndroid Build Coastguard Worker gbb_to = (struct vb2_gbb_header *)find_gbb(image_to);
353*8617a60dSAndroid Build Coastguard Worker
354*8617a60dSAndroid Build Coastguard Worker /*
355*8617a60dSAndroid Build Coastguard Worker * For all cases, we need a valid gbb_to. Note for 'override GBB flags
356*8617a60dSAndroid Build Coastguard Worker * on a erased device', we only need gbb_to, not gbb_from.
357*8617a60dSAndroid Build Coastguard Worker */
358*8617a60dSAndroid Build Coastguard Worker if (!gbb_to)
359*8617a60dSAndroid Build Coastguard Worker return -1;
360*8617a60dSAndroid Build Coastguard Worker
361*8617a60dSAndroid Build Coastguard Worker gbb_from = find_gbb(image_from);
362*8617a60dSAndroid Build Coastguard Worker
363*8617a60dSAndroid Build Coastguard Worker /* Preserve (for non-factory mode) or override flags. */
364*8617a60dSAndroid Build Coastguard Worker if (override_flags)
365*8617a60dSAndroid Build Coastguard Worker gbb_to->flags = override_value;
366*8617a60dSAndroid Build Coastguard Worker else if (preserve_flags && gbb_from)
367*8617a60dSAndroid Build Coastguard Worker gbb_to->flags = gbb_from->flags;
368*8617a60dSAndroid Build Coastguard Worker
369*8617a60dSAndroid Build Coastguard Worker if (!gbb_from)
370*8617a60dSAndroid Build Coastguard Worker return -1;
371*8617a60dSAndroid Build Coastguard Worker
372*8617a60dSAndroid Build Coastguard Worker /* Preserve HWID. */
373*8617a60dSAndroid Build Coastguard Worker return futil_set_gbb_hwid(
374*8617a60dSAndroid Build Coastguard Worker gbb_to, (const char *)gbb_from + gbb_from->hwid_offset);
375*8617a60dSAndroid Build Coastguard Worker }
376*8617a60dSAndroid Build Coastguard Worker
377*8617a60dSAndroid Build Coastguard Worker /*
378*8617a60dSAndroid Build Coastguard Worker * Preserves the regions locked by Intel management engine.
379*8617a60dSAndroid Build Coastguard Worker */
preserve_management_engine(struct updater_config * cfg,const struct firmware_image * image_from,struct firmware_image * image_to)380*8617a60dSAndroid Build Coastguard Worker static int preserve_management_engine(struct updater_config *cfg,
381*8617a60dSAndroid Build Coastguard Worker const struct firmware_image *image_from,
382*8617a60dSAndroid Build Coastguard Worker struct firmware_image *image_to)
383*8617a60dSAndroid Build Coastguard Worker {
384*8617a60dSAndroid Build Coastguard Worker struct firmware_section section;
385*8617a60dSAndroid Build Coastguard Worker
386*8617a60dSAndroid Build Coastguard Worker find_firmware_section(§ion, image_from, FMAP_SI_ME);
387*8617a60dSAndroid Build Coastguard Worker if (!section.data) {
388*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Skipped because no section %s.\n", FMAP_SI_ME);
389*8617a60dSAndroid Build Coastguard Worker return 0;
390*8617a60dSAndroid Build Coastguard Worker }
391*8617a60dSAndroid Build Coastguard Worker if (section_is_filled_with(§ion, 0xFF)) {
392*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("ME is probably locked - preserving %s.\n",
393*8617a60dSAndroid Build Coastguard Worker FMAP_SI_DESC);
394*8617a60dSAndroid Build Coastguard Worker return preserve_firmware_section(
395*8617a60dSAndroid Build Coastguard Worker image_from, image_to, FMAP_SI_DESC);
396*8617a60dSAndroid Build Coastguard Worker }
397*8617a60dSAndroid Build Coastguard Worker
398*8617a60dSAndroid Build Coastguard Worker if (!strcmp(cfg->original_programmer, FLASHROM_PROGRAMMER_INTERNAL_AP)) {
399*8617a60dSAndroid Build Coastguard Worker if (try_apply_quirk(QUIRK_PRESERVE_ME, cfg) > 0) {
400*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("ME needs to be preserved - preserving %s.\n",
401*8617a60dSAndroid Build Coastguard Worker FMAP_SI_ME);
402*8617a60dSAndroid Build Coastguard Worker return preserve_firmware_section(image_from, image_to,
403*8617a60dSAndroid Build Coastguard Worker FMAP_SI_ME);
404*8617a60dSAndroid Build Coastguard Worker }
405*8617a60dSAndroid Build Coastguard Worker } else {
406*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Flashing via non-host programmer %s - no need to "
407*8617a60dSAndroid Build Coastguard Worker "preserve ME.\n", image_from->programmer);
408*8617a60dSAndroid Build Coastguard Worker }
409*8617a60dSAndroid Build Coastguard Worker
410*8617a60dSAndroid Build Coastguard Worker return 0;
411*8617a60dSAndroid Build Coastguard Worker }
412*8617a60dSAndroid Build Coastguard Worker
413*8617a60dSAndroid Build Coastguard Worker /* Preserve firmware sections by FMAP area flags. */
preserve_fmap_sections(struct firmware_image * from,struct firmware_image * to,int * count)414*8617a60dSAndroid Build Coastguard Worker static int preserve_fmap_sections(struct firmware_image *from,
415*8617a60dSAndroid Build Coastguard Worker struct firmware_image *to,
416*8617a60dSAndroid Build Coastguard Worker int *count)
417*8617a60dSAndroid Build Coastguard Worker {
418*8617a60dSAndroid Build Coastguard Worker int i, errcnt = 0;
419*8617a60dSAndroid Build Coastguard Worker FmapHeader *fmap = to->fmap_header;
420*8617a60dSAndroid Build Coastguard Worker FmapAreaHeader *ah = (FmapAreaHeader*)(
421*8617a60dSAndroid Build Coastguard Worker (uint8_t *)fmap + sizeof(FmapHeader));
422*8617a60dSAndroid Build Coastguard Worker *count = 0;
423*8617a60dSAndroid Build Coastguard Worker
424*8617a60dSAndroid Build Coastguard Worker for (i = 0; i < fmap->fmap_nareas; i++, ah++) {
425*8617a60dSAndroid Build Coastguard Worker if (!(ah->area_flags & FMAP_AREA_PRESERVE))
426*8617a60dSAndroid Build Coastguard Worker continue;
427*8617a60dSAndroid Build Coastguard Worker /* Warning: area_name 'may' not end with NUL. */
428*8617a60dSAndroid Build Coastguard Worker if (!firmware_section_exists(from, ah->area_name)) {
429*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("FMAP area does not exist in source: %.*s\n",
430*8617a60dSAndroid Build Coastguard Worker FMAP_NAMELEN, ah->area_name);
431*8617a60dSAndroid Build Coastguard Worker continue;
432*8617a60dSAndroid Build Coastguard Worker }
433*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Preserve FMAP area: %.*s\n", FMAP_NAMELEN,
434*8617a60dSAndroid Build Coastguard Worker ah->area_name);
435*8617a60dSAndroid Build Coastguard Worker errcnt += preserve_firmware_section(from, to, ah->area_name);
436*8617a60dSAndroid Build Coastguard Worker (*count)++;
437*8617a60dSAndroid Build Coastguard Worker }
438*8617a60dSAndroid Build Coastguard Worker
439*8617a60dSAndroid Build Coastguard Worker return errcnt;
440*8617a60dSAndroid Build Coastguard Worker }
441*8617a60dSAndroid Build Coastguard Worker
442*8617a60dSAndroid Build Coastguard Worker /*
443*8617a60dSAndroid Build Coastguard Worker * Preserve old images without "preserve" information in FMAP.
444*8617a60dSAndroid Build Coastguard Worker * We have to use the legacy hard-coded list of names.
445*8617a60dSAndroid Build Coastguard Worker */
preserve_known_sections(struct firmware_image * from,struct firmware_image * to)446*8617a60dSAndroid Build Coastguard Worker static int preserve_known_sections(struct firmware_image *from,
447*8617a60dSAndroid Build Coastguard Worker struct firmware_image *to)
448*8617a60dSAndroid Build Coastguard Worker {
449*8617a60dSAndroid Build Coastguard Worker int errcnt = 0, i;
450*8617a60dSAndroid Build Coastguard Worker const char * const names[] = {
451*8617a60dSAndroid Build Coastguard Worker "RW_PRESERVE", /* Only octopus fw branch is using this. */
452*8617a60dSAndroid Build Coastguard Worker FMAP_RO_VPD,
453*8617a60dSAndroid Build Coastguard Worker FMAP_RW_VPD,
454*8617a60dSAndroid Build Coastguard Worker "SMMSTORE",
455*8617a60dSAndroid Build Coastguard Worker "RW_NVRAM",
456*8617a60dSAndroid Build Coastguard Worker "RW_ELOG",
457*8617a60dSAndroid Build Coastguard Worker };
458*8617a60dSAndroid Build Coastguard Worker
459*8617a60dSAndroid Build Coastguard Worker for (i = 0; i < ARRAY_SIZE(names); i++) {
460*8617a60dSAndroid Build Coastguard Worker if (!firmware_section_exists(from, names[i]))
461*8617a60dSAndroid Build Coastguard Worker continue;
462*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Preserve firmware section: %s\n", names[i]);
463*8617a60dSAndroid Build Coastguard Worker errcnt += preserve_firmware_section(from, to, names[i]);
464*8617a60dSAndroid Build Coastguard Worker }
465*8617a60dSAndroid Build Coastguard Worker return errcnt;
466*8617a60dSAndroid Build Coastguard Worker }
467*8617a60dSAndroid Build Coastguard Worker
468*8617a60dSAndroid Build Coastguard Worker /*
469*8617a60dSAndroid Build Coastguard Worker * Preserves the critical sections from the current (active) firmware.
470*8617a60dSAndroid Build Coastguard Worker * Currently preserved sections: GBB (HWID and flags), x86 ME, and any firmware
471*8617a60dSAndroid Build Coastguard Worker * sections with FMAP_AREA_PRESERVE flag set (or a list of known names).
472*8617a60dSAndroid Build Coastguard Worker * Returns 0 if success, non-zero if error.
473*8617a60dSAndroid Build Coastguard Worker */
preserve_images(struct updater_config * cfg)474*8617a60dSAndroid Build Coastguard Worker static int preserve_images(struct updater_config *cfg)
475*8617a60dSAndroid Build Coastguard Worker {
476*8617a60dSAndroid Build Coastguard Worker int errcnt = 0, found;
477*8617a60dSAndroid Build Coastguard Worker struct firmware_image *from = &cfg->image_current, *to = &cfg->image;
478*8617a60dSAndroid Build Coastguard Worker
479*8617a60dSAndroid Build Coastguard Worker errcnt += preserve_gbb(from, to, !cfg->factory_update,
480*8617a60dSAndroid Build Coastguard Worker cfg->override_gbb_flags, cfg->gbb_flags);
481*8617a60dSAndroid Build Coastguard Worker errcnt += preserve_management_engine(cfg, from, to);
482*8617a60dSAndroid Build Coastguard Worker errcnt += preserve_fmap_sections(from, to, &found);
483*8617a60dSAndroid Build Coastguard Worker
484*8617a60dSAndroid Build Coastguard Worker if (!found)
485*8617a60dSAndroid Build Coastguard Worker errcnt += preserve_known_sections(from, to);
486*8617a60dSAndroid Build Coastguard Worker
487*8617a60dSAndroid Build Coastguard Worker return errcnt;
488*8617a60dSAndroid Build Coastguard Worker }
489*8617a60dSAndroid Build Coastguard Worker
490*8617a60dSAndroid Build Coastguard Worker /*
491*8617a60dSAndroid Build Coastguard Worker * Compares if two sections have same size and data.
492*8617a60dSAndroid Build Coastguard Worker * Returns 0 if given sections are the same, otherwise non-zero.
493*8617a60dSAndroid Build Coastguard Worker */
compare_section(const struct firmware_section * a,const struct firmware_section * b)494*8617a60dSAndroid Build Coastguard Worker static int compare_section(const struct firmware_section *a,
495*8617a60dSAndroid Build Coastguard Worker const struct firmware_section *b)
496*8617a60dSAndroid Build Coastguard Worker {
497*8617a60dSAndroid Build Coastguard Worker if (a->size != b->size)
498*8617a60dSAndroid Build Coastguard Worker return a->size - b->size;
499*8617a60dSAndroid Build Coastguard Worker return memcmp(a->data, b->data, a->size);
500*8617a60dSAndroid Build Coastguard Worker }
501*8617a60dSAndroid Build Coastguard Worker
502*8617a60dSAndroid Build Coastguard Worker /*
503*8617a60dSAndroid Build Coastguard Worker * Returns if the images are different (should be updated) in given section.
504*8617a60dSAndroid Build Coastguard Worker * If the section contents are the same or if the section does not exist on both
505*8617a60dSAndroid Build Coastguard Worker * images, return value is 0 (no need to update). Otherwise the return value is
506*8617a60dSAndroid Build Coastguard Worker * non-zero, indicating an update should be performed.
507*8617a60dSAndroid Build Coastguard Worker * If section_name is NULL, compare whole images.
508*8617a60dSAndroid Build Coastguard Worker */
section_needs_update(const struct firmware_image * image_from,const struct firmware_image * image_to,const char * section_name)509*8617a60dSAndroid Build Coastguard Worker static int section_needs_update(const struct firmware_image *image_from,
510*8617a60dSAndroid Build Coastguard Worker const struct firmware_image *image_to,
511*8617a60dSAndroid Build Coastguard Worker const char *section_name)
512*8617a60dSAndroid Build Coastguard Worker {
513*8617a60dSAndroid Build Coastguard Worker struct firmware_section from, to;
514*8617a60dSAndroid Build Coastguard Worker
515*8617a60dSAndroid Build Coastguard Worker if (!section_name) {
516*8617a60dSAndroid Build Coastguard Worker if (image_from->size != image_to->size)
517*8617a60dSAndroid Build Coastguard Worker return -1;
518*8617a60dSAndroid Build Coastguard Worker return memcmp(image_from->data, image_to->data, image_to->size);
519*8617a60dSAndroid Build Coastguard Worker }
520*8617a60dSAndroid Build Coastguard Worker
521*8617a60dSAndroid Build Coastguard Worker find_firmware_section(&from, image_from, section_name);
522*8617a60dSAndroid Build Coastguard Worker find_firmware_section(&to, image_to, section_name);
523*8617a60dSAndroid Build Coastguard Worker
524*8617a60dSAndroid Build Coastguard Worker return compare_section(&from, &to);
525*8617a60dSAndroid Build Coastguard Worker }
526*8617a60dSAndroid Build Coastguard Worker
527*8617a60dSAndroid Build Coastguard Worker /*
528*8617a60dSAndroid Build Coastguard Worker * Checks if the system has locked AP RO (SI_DESC + Ti50 AP RO Verification).
529*8617a60dSAndroid Build Coastguard Worker
530*8617a60dSAndroid Build Coastguard Worker * b/284913015: When running on a DUT with SI_DESC, the SI_DESC may reject CPU
531*8617a60dSAndroid Build Coastguard Worker * (AP) from changing itself. And if we keep updating (and skipped SI_DESC and
532*8617a60dSAndroid Build Coastguard Worker * ME sections), the Ti50 AP RO verification via RO_GSCVD would fail because the
533*8617a60dSAndroid Build Coastguard Worker * hash was from a different SI_DESC (and not updated).
534*8617a60dSAndroid Build Coastguard Worker *
535*8617a60dSAndroid Build Coastguard Worker * As a result, we don't want to do full update in this case. However
536*8617a60dSAndroid Build Coastguard Worker * It is OK to do a full update if we are updating a remote DUT (via servo or
537*8617a60dSAndroid Build Coastguard Worker * other programmers).
538*8617a60dSAndroid Build Coastguard Worker *
539*8617a60dSAndroid Build Coastguard Worker * Returns:
540*8617a60dSAndroid Build Coastguard Worker * True if AP is locked + verification enabled and we should skip updating RO.
541*8617a60dSAndroid Build Coastguard Worker * Otherwise false.
542*8617a60dSAndroid Build Coastguard Worker */
is_ap_ro_locked_with_verification(struct updater_config * cfg)543*8617a60dSAndroid Build Coastguard Worker static bool is_ap_ro_locked_with_verification(struct updater_config *cfg)
544*8617a60dSAndroid Build Coastguard Worker {
545*8617a60dSAndroid Build Coastguard Worker struct firmware_image *current = &cfg->image_current;
546*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Checking if the system has locked AP RO (+verif).\n");
547*8617a60dSAndroid Build Coastguard Worker
548*8617a60dSAndroid Build Coastguard Worker if (cfg->dut_is_remote) {
549*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Remote DUT, assume the AP RO can be reflashed.\n");
550*8617a60dSAndroid Build Coastguard Worker return false;
551*8617a60dSAndroid Build Coastguard Worker }
552*8617a60dSAndroid Build Coastguard Worker if (!firmware_section_exists(current, FMAP_RO_GSCVD)) {
553*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("No %s, AP RO can be updated even if locked.\n", FMAP_RO_GSCVD);
554*8617a60dSAndroid Build Coastguard Worker return false;
555*8617a60dSAndroid Build Coastguard Worker }
556*8617a60dSAndroid Build Coastguard Worker if (!firmware_section_exists(current, FMAP_SI_DESC)) {
557*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("No %s, AP RO won't be locked.\n", FMAP_SI_DESC);
558*8617a60dSAndroid Build Coastguard Worker return false;
559*8617a60dSAndroid Build Coastguard Worker }
560*8617a60dSAndroid Build Coastguard Worker if (!section_needs_update(&cfg->image, current, FMAP_SI_DESC)) {
561*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("%s is exactly the same. RO update should be fine.\n", FMAP_SI_DESC);
562*8617a60dSAndroid Build Coastguard Worker return false;
563*8617a60dSAndroid Build Coastguard Worker }
564*8617a60dSAndroid Build Coastguard Worker return is_flash_descriptor_locked(current);
565*8617a60dSAndroid Build Coastguard Worker }
566*8617a60dSAndroid Build Coastguard Worker
567*8617a60dSAndroid Build Coastguard Worker /* Returns true if the UNLOCK_CSME_* quirks were requested, otherwise false. */
is_unlock_csme_requested(struct updater_config * cfg)568*8617a60dSAndroid Build Coastguard Worker static bool is_unlock_csme_requested(struct updater_config *cfg)
569*8617a60dSAndroid Build Coastguard Worker {
570*8617a60dSAndroid Build Coastguard Worker if (get_config_quirk(QUIRK_UNLOCK_CSME, cfg) ||
571*8617a60dSAndroid Build Coastguard Worker get_config_quirk(QUIRK_UNLOCK_CSME_EVE, cfg))
572*8617a60dSAndroid Build Coastguard Worker return true;
573*8617a60dSAndroid Build Coastguard Worker return false;
574*8617a60dSAndroid Build Coastguard Worker }
575*8617a60dSAndroid Build Coastguard Worker
576*8617a60dSAndroid Build Coastguard Worker /*
577*8617a60dSAndroid Build Coastguard Worker * Checks if the given firmware images are compatible with current platform.
578*8617a60dSAndroid Build Coastguard Worker * In current implementation (following Chrome OS style), we assume the platform
579*8617a60dSAndroid Build Coastguard Worker * is identical to the name before a dot (.) in firmware version.
580*8617a60dSAndroid Build Coastguard Worker * Returns 0 for success, otherwise failure.
581*8617a60dSAndroid Build Coastguard Worker */
check_compatible_platform(struct updater_config * cfg)582*8617a60dSAndroid Build Coastguard Worker static int check_compatible_platform(struct updater_config *cfg)
583*8617a60dSAndroid Build Coastguard Worker {
584*8617a60dSAndroid Build Coastguard Worker int len;
585*8617a60dSAndroid Build Coastguard Worker struct firmware_image *image_from = &cfg->image_current,
586*8617a60dSAndroid Build Coastguard Worker *image_to = &cfg->image;
587*8617a60dSAndroid Build Coastguard Worker const char *from_dot = strchr(image_from->ro_version, '.'),
588*8617a60dSAndroid Build Coastguard Worker *to_dot = strchr(image_to->ro_version, '.');
589*8617a60dSAndroid Build Coastguard Worker
590*8617a60dSAndroid Build Coastguard Worker if (!from_dot || !to_dot) {
591*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Missing dot (from=%p, to=%p)\n", from_dot, to_dot);
592*8617a60dSAndroid Build Coastguard Worker return -1;
593*8617a60dSAndroid Build Coastguard Worker }
594*8617a60dSAndroid Build Coastguard Worker len = from_dot - image_from->ro_version + 1;
595*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Platform: %*.*s\n", len, len, image_from->ro_version);
596*8617a60dSAndroid Build Coastguard Worker return strncasecmp(image_from->ro_version, image_to->ro_version, len);
597*8617a60dSAndroid Build Coastguard Worker }
598*8617a60dSAndroid Build Coastguard Worker
get_rootkey(const struct vb2_gbb_header * gbb)599*8617a60dSAndroid Build Coastguard Worker const struct vb2_packed_key *get_rootkey(
600*8617a60dSAndroid Build Coastguard Worker const struct vb2_gbb_header *gbb)
601*8617a60dSAndroid Build Coastguard Worker {
602*8617a60dSAndroid Build Coastguard Worker struct vb2_packed_key *key = NULL;
603*8617a60dSAndroid Build Coastguard Worker
604*8617a60dSAndroid Build Coastguard Worker key = (struct vb2_packed_key *)((uint8_t *)gbb + gbb->rootkey_offset);
605*8617a60dSAndroid Build Coastguard Worker if (vb2_packed_key_looks_ok(key, gbb->rootkey_size)) {
606*8617a60dSAndroid Build Coastguard Worker ERROR("Invalid root key.\n");
607*8617a60dSAndroid Build Coastguard Worker return NULL;
608*8617a60dSAndroid Build Coastguard Worker }
609*8617a60dSAndroid Build Coastguard Worker return key;
610*8617a60dSAndroid Build Coastguard Worker }
611*8617a60dSAndroid Build Coastguard Worker
612*8617a60dSAndroid Build Coastguard Worker /*
613*8617a60dSAndroid Build Coastguard Worker * Returns a keyblock key from given image section, or NULL on failure.
614*8617a60dSAndroid Build Coastguard Worker */
get_keyblock(const struct firmware_image * image,const char * section_name)615*8617a60dSAndroid Build Coastguard Worker static const struct vb2_keyblock *get_keyblock(
616*8617a60dSAndroid Build Coastguard Worker const struct firmware_image *image,
617*8617a60dSAndroid Build Coastguard Worker const char *section_name)
618*8617a60dSAndroid Build Coastguard Worker {
619*8617a60dSAndroid Build Coastguard Worker struct firmware_section section;
620*8617a60dSAndroid Build Coastguard Worker
621*8617a60dSAndroid Build Coastguard Worker if (find_firmware_section(§ion, image, section_name) != 0) {
622*8617a60dSAndroid Build Coastguard Worker ERROR("Section %s not found", section_name);
623*8617a60dSAndroid Build Coastguard Worker return NULL;
624*8617a60dSAndroid Build Coastguard Worker }
625*8617a60dSAndroid Build Coastguard Worker const struct vb2_keyblock *block = (const struct vb2_keyblock *)section.data;
626*8617a60dSAndroid Build Coastguard Worker if (vb2_check_keyblock(block, section.size, &block->keyblock_signature)) {
627*8617a60dSAndroid Build Coastguard Worker ERROR("Invalid keyblock in %s\n", section_name);
628*8617a60dSAndroid Build Coastguard Worker return NULL;
629*8617a60dSAndroid Build Coastguard Worker }
630*8617a60dSAndroid Build Coastguard Worker /* A keyblock must be followed by a vb2_fw_preamble. */
631*8617a60dSAndroid Build Coastguard Worker if (section.size < block->keyblock_size + sizeof(struct vb2_fw_preamble)) {
632*8617a60dSAndroid Build Coastguard Worker ERROR("Invalid section: %s\n", section_name);
633*8617a60dSAndroid Build Coastguard Worker return NULL;
634*8617a60dSAndroid Build Coastguard Worker }
635*8617a60dSAndroid Build Coastguard Worker return block;
636*8617a60dSAndroid Build Coastguard Worker }
637*8617a60dSAndroid Build Coastguard Worker
638*8617a60dSAndroid Build Coastguard Worker /*
639*8617a60dSAndroid Build Coastguard Worker * Duplicates a keyblock and returns the duplicated block.
640*8617a60dSAndroid Build Coastguard Worker * The caller must free the returned keyblock after being used.
641*8617a60dSAndroid Build Coastguard Worker */
dupe_keyblock(const struct vb2_keyblock * block)642*8617a60dSAndroid Build Coastguard Worker static struct vb2_keyblock *dupe_keyblock(const struct vb2_keyblock *block)
643*8617a60dSAndroid Build Coastguard Worker {
644*8617a60dSAndroid Build Coastguard Worker struct vb2_keyblock *new_block;
645*8617a60dSAndroid Build Coastguard Worker
646*8617a60dSAndroid Build Coastguard Worker new_block = (struct vb2_keyblock *)malloc(block->keyblock_size);
647*8617a60dSAndroid Build Coastguard Worker assert(new_block);
648*8617a60dSAndroid Build Coastguard Worker memcpy(new_block, block, block->keyblock_size);
649*8617a60dSAndroid Build Coastguard Worker return new_block;
650*8617a60dSAndroid Build Coastguard Worker }
651*8617a60dSAndroid Build Coastguard Worker
652*8617a60dSAndroid Build Coastguard Worker /*
653*8617a60dSAndroid Build Coastguard Worker * Verifies if keyblock is signed with given key.
654*8617a60dSAndroid Build Coastguard Worker * Returns 0 on success, otherwise failure.
655*8617a60dSAndroid Build Coastguard Worker */
verify_keyblock(const struct vb2_keyblock * block,const struct vb2_packed_key * sign_key)656*8617a60dSAndroid Build Coastguard Worker static int verify_keyblock(const struct vb2_keyblock *block,
657*8617a60dSAndroid Build Coastguard Worker const struct vb2_packed_key *sign_key) {
658*8617a60dSAndroid Build Coastguard Worker int r;
659*8617a60dSAndroid Build Coastguard Worker uint8_t workbuf[VB2_FIRMWARE_WORKBUF_RECOMMENDED_SIZE]
660*8617a60dSAndroid Build Coastguard Worker __attribute__((aligned(VB2_WORKBUF_ALIGN)));
661*8617a60dSAndroid Build Coastguard Worker struct vb2_workbuf wb;
662*8617a60dSAndroid Build Coastguard Worker struct vb2_public_key key;
663*8617a60dSAndroid Build Coastguard Worker struct vb2_keyblock *new_block;
664*8617a60dSAndroid Build Coastguard Worker
665*8617a60dSAndroid Build Coastguard Worker if (block->keyblock_signature.sig_size == 0) {
666*8617a60dSAndroid Build Coastguard Worker ERROR("Keyblock is not signed.\n");
667*8617a60dSAndroid Build Coastguard Worker return -1;
668*8617a60dSAndroid Build Coastguard Worker }
669*8617a60dSAndroid Build Coastguard Worker vb2_workbuf_init(&wb, workbuf, sizeof(workbuf));
670*8617a60dSAndroid Build Coastguard Worker if (VB2_SUCCESS != vb2_unpack_key(&key, sign_key)) {
671*8617a60dSAndroid Build Coastguard Worker ERROR("Invalid signing key.\n");
672*8617a60dSAndroid Build Coastguard Worker return -1;
673*8617a60dSAndroid Build Coastguard Worker }
674*8617a60dSAndroid Build Coastguard Worker
675*8617a60dSAndroid Build Coastguard Worker /*
676*8617a60dSAndroid Build Coastguard Worker * vb2_verify_keyblock will destroy the signature inside keyblock
677*8617a60dSAndroid Build Coastguard Worker * so we have to verify with a local copy.
678*8617a60dSAndroid Build Coastguard Worker */
679*8617a60dSAndroid Build Coastguard Worker new_block = dupe_keyblock(block);
680*8617a60dSAndroid Build Coastguard Worker r = vb2_verify_keyblock(new_block, new_block->keyblock_size, &key, &wb);
681*8617a60dSAndroid Build Coastguard Worker free(new_block);
682*8617a60dSAndroid Build Coastguard Worker
683*8617a60dSAndroid Build Coastguard Worker if (r != VB2_SUCCESS) {
684*8617a60dSAndroid Build Coastguard Worker ERROR("Failed verifying keyblock.\n");
685*8617a60dSAndroid Build Coastguard Worker return -1;
686*8617a60dSAndroid Build Coastguard Worker }
687*8617a60dSAndroid Build Coastguard Worker return 0;
688*8617a60dSAndroid Build Coastguard Worker }
689*8617a60dSAndroid Build Coastguard Worker
690*8617a60dSAndroid Build Coastguard Worker /*
691*8617a60dSAndroid Build Coastguard Worker * Gets the data key and firmware version from a section on firmware image.
692*8617a60dSAndroid Build Coastguard Worker * The section should contain a vb2_keyblock and a vb2_fw_preamble immediately
693*8617a60dSAndroid Build Coastguard Worker * after keyblock so we can decode and save the data key and firmware version
694*8617a60dSAndroid Build Coastguard Worker * into argument `data_key_version` and `firmware_version`.
695*8617a60dSAndroid Build Coastguard Worker * Returns 0 for success, otherwise failure.
696*8617a60dSAndroid Build Coastguard Worker */
get_key_versions(const struct firmware_image * image,const char * section_name,unsigned int * data_key_version,unsigned int * firmware_version)697*8617a60dSAndroid Build Coastguard Worker static int get_key_versions(const struct firmware_image *image,
698*8617a60dSAndroid Build Coastguard Worker const char *section_name,
699*8617a60dSAndroid Build Coastguard Worker unsigned int *data_key_version,
700*8617a60dSAndroid Build Coastguard Worker unsigned int *firmware_version)
701*8617a60dSAndroid Build Coastguard Worker {
702*8617a60dSAndroid Build Coastguard Worker const struct vb2_keyblock *keyblock = get_keyblock(image, section_name);
703*8617a60dSAndroid Build Coastguard Worker const struct vb2_fw_preamble *pre;
704*8617a60dSAndroid Build Coastguard Worker
705*8617a60dSAndroid Build Coastguard Worker if (!keyblock)
706*8617a60dSAndroid Build Coastguard Worker return -1;
707*8617a60dSAndroid Build Coastguard Worker *data_key_version = keyblock->data_key.key_version;
708*8617a60dSAndroid Build Coastguard Worker pre = (struct vb2_fw_preamble *)((uint8_t*)keyblock +
709*8617a60dSAndroid Build Coastguard Worker keyblock->keyblock_size);
710*8617a60dSAndroid Build Coastguard Worker *firmware_version = pre->firmware_version;
711*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("%s: data key version = %d, firmware version = %d\n",
712*8617a60dSAndroid Build Coastguard Worker image->file_name, *data_key_version, *firmware_version);
713*8617a60dSAndroid Build Coastguard Worker return 0;
714*8617a60dSAndroid Build Coastguard Worker }
715*8617a60dSAndroid Build Coastguard Worker
716*8617a60dSAndroid Build Coastguard Worker /*
717*8617a60dSAndroid Build Coastguard Worker * Checks if the root key in ro_image can verify vblocks in rw_image.
718*8617a60dSAndroid Build Coastguard Worker * Returns 0 for success, otherwise failure.
719*8617a60dSAndroid Build Coastguard Worker */
check_compatible_root_key(const struct firmware_image * ro_image,const struct firmware_image * rw_image)720*8617a60dSAndroid Build Coastguard Worker static enum rootkey_compat_result check_compatible_root_key(
721*8617a60dSAndroid Build Coastguard Worker const struct firmware_image *ro_image,
722*8617a60dSAndroid Build Coastguard Worker const struct firmware_image *rw_image)
723*8617a60dSAndroid Build Coastguard Worker {
724*8617a60dSAndroid Build Coastguard Worker const struct vb2_gbb_header *gbb = find_gbb(ro_image);
725*8617a60dSAndroid Build Coastguard Worker const struct vb2_packed_key *rootkey;
726*8617a60dSAndroid Build Coastguard Worker const struct vb2_keyblock *keyblock;
727*8617a60dSAndroid Build Coastguard Worker
728*8617a60dSAndroid Build Coastguard Worker if (!gbb)
729*8617a60dSAndroid Build Coastguard Worker return ROOTKEY_COMPAT_ERROR;
730*8617a60dSAndroid Build Coastguard Worker
731*8617a60dSAndroid Build Coastguard Worker rootkey = get_rootkey(gbb);
732*8617a60dSAndroid Build Coastguard Worker if (!rootkey)
733*8617a60dSAndroid Build Coastguard Worker return ROOTKEY_COMPAT_ERROR;
734*8617a60dSAndroid Build Coastguard Worker
735*8617a60dSAndroid Build Coastguard Worker /* Assume VBLOCK_A and VBLOCK_B are signed in same way. */
736*8617a60dSAndroid Build Coastguard Worker keyblock = get_keyblock(rw_image, FMAP_RW_VBLOCK_A);
737*8617a60dSAndroid Build Coastguard Worker if (!keyblock)
738*8617a60dSAndroid Build Coastguard Worker return ROOTKEY_COMPAT_ERROR;
739*8617a60dSAndroid Build Coastguard Worker
740*8617a60dSAndroid Build Coastguard Worker if (verify_keyblock(keyblock, rootkey) != 0) {
741*8617a60dSAndroid Build Coastguard Worker const struct vb2_gbb_header *gbb_rw = find_gbb(rw_image);
742*8617a60dSAndroid Build Coastguard Worker const struct vb2_packed_key *rootkey_rw = NULL;
743*8617a60dSAndroid Build Coastguard Worker int is_same_key = 0, to_dev = 0;
744*8617a60dSAndroid Build Coastguard Worker /*
745*8617a60dSAndroid Build Coastguard Worker * Try harder to provide more info.
746*8617a60dSAndroid Build Coastguard Worker * packed_key_sha1_string uses static buffer so don't call
747*8617a60dSAndroid Build Coastguard Worker * it twice in args list of one expression.
748*8617a60dSAndroid Build Coastguard Worker */
749*8617a60dSAndroid Build Coastguard Worker if (gbb_rw)
750*8617a60dSAndroid Build Coastguard Worker rootkey_rw = get_rootkey(gbb_rw);
751*8617a60dSAndroid Build Coastguard Worker if (rootkey_rw) {
752*8617a60dSAndroid Build Coastguard Worker if (rootkey->key_offset == rootkey_rw->key_offset &&
753*8617a60dSAndroid Build Coastguard Worker rootkey->key_size == rootkey_rw->key_size &&
754*8617a60dSAndroid Build Coastguard Worker memcmp(rootkey, rootkey_rw, rootkey->key_size +
755*8617a60dSAndroid Build Coastguard Worker rootkey->key_offset) == 0)
756*8617a60dSAndroid Build Coastguard Worker is_same_key = 1;
757*8617a60dSAndroid Build Coastguard Worker if (strcmp(packed_key_sha1_string(rootkey_rw),
758*8617a60dSAndroid Build Coastguard Worker ROOTKEY_HASH_DEV) == 0)
759*8617a60dSAndroid Build Coastguard Worker to_dev = 1;
760*8617a60dSAndroid Build Coastguard Worker }
761*8617a60dSAndroid Build Coastguard Worker INFO("Current (RO) firmware image has root key: %s\n",
762*8617a60dSAndroid Build Coastguard Worker packed_key_sha1_string(rootkey));
763*8617a60dSAndroid Build Coastguard Worker if (is_same_key) {
764*8617a60dSAndroid Build Coastguard Worker ERROR("Rootkey is same as target (RW) image. \n"
765*8617a60dSAndroid Build Coastguard Worker "Maybe RW corrupted?");
766*8617a60dSAndroid Build Coastguard Worker return ROOTKEY_COMPAT_ERROR;
767*8617a60dSAndroid Build Coastguard Worker }
768*8617a60dSAndroid Build Coastguard Worker WARN("Target (RW) image is signed by root key: %s%s\n",
769*8617a60dSAndroid Build Coastguard Worker rootkey_rw ? packed_key_sha1_string(rootkey_rw) :
770*8617a60dSAndroid Build Coastguard Worker "<invalid>", to_dev ? " (DEV/unsigned)" : "");
771*8617a60dSAndroid Build Coastguard Worker return to_dev ? ROOTKEY_COMPAT_REKEY_TO_DEV :
772*8617a60dSAndroid Build Coastguard Worker ROOTKEY_COMPAT_REKEY;
773*8617a60dSAndroid Build Coastguard Worker }
774*8617a60dSAndroid Build Coastguard Worker return ROOTKEY_COMPAT_OK;
775*8617a60dSAndroid Build Coastguard Worker }
776*8617a60dSAndroid Build Coastguard Worker
777*8617a60dSAndroid Build Coastguard Worker /*
778*8617a60dSAndroid Build Coastguard Worker * Returns non-zero if the RW_LEGACY needs to be updated, otherwise 0.
779*8617a60dSAndroid Build Coastguard Worker */
legacy_needs_update(struct updater_config * cfg)780*8617a60dSAndroid Build Coastguard Worker static int legacy_needs_update(struct updater_config *cfg)
781*8617a60dSAndroid Build Coastguard Worker {
782*8617a60dSAndroid Build Coastguard Worker bool has_from, has_to;
783*8617a60dSAndroid Build Coastguard Worker const char * const tag = "cros_allow_auto_update";
784*8617a60dSAndroid Build Coastguard Worker const char *section = FMAP_RW_LEGACY;
785*8617a60dSAndroid Build Coastguard Worker const char *tmp_to, *tmp_from;
786*8617a60dSAndroid Build Coastguard Worker
787*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Checking %s contents...\n", FMAP_RW_LEGACY);
788*8617a60dSAndroid Build Coastguard Worker
789*8617a60dSAndroid Build Coastguard Worker tmp_to = get_firmware_image_temp_file(&cfg->image, &cfg->tempfiles);
790*8617a60dSAndroid Build Coastguard Worker tmp_from = get_firmware_image_temp_file(&cfg->image_current,
791*8617a60dSAndroid Build Coastguard Worker &cfg->tempfiles);
792*8617a60dSAndroid Build Coastguard Worker if (!tmp_from || !tmp_to)
793*8617a60dSAndroid Build Coastguard Worker return 0;
794*8617a60dSAndroid Build Coastguard Worker
795*8617a60dSAndroid Build Coastguard Worker has_to = cbfstool_file_exists(tmp_to, section, tag);
796*8617a60dSAndroid Build Coastguard Worker has_from = cbfstool_file_exists(tmp_from, section, tag);
797*8617a60dSAndroid Build Coastguard Worker
798*8617a60dSAndroid Build Coastguard Worker if (!has_from || !has_to) {
799*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Current legacy firmware has%s updater tag (%s) and "
800*8617a60dSAndroid Build Coastguard Worker "target firmware has%s updater tag, won't update.\n",
801*8617a60dSAndroid Build Coastguard Worker has_from ? "" : " no", tag, has_to ? "" : " no");
802*8617a60dSAndroid Build Coastguard Worker return 0;
803*8617a60dSAndroid Build Coastguard Worker }
804*8617a60dSAndroid Build Coastguard Worker
805*8617a60dSAndroid Build Coastguard Worker return section_needs_update(
806*8617a60dSAndroid Build Coastguard Worker &cfg->image_current, &cfg->image, FMAP_RW_LEGACY);
807*8617a60dSAndroid Build Coastguard Worker }
808*8617a60dSAndroid Build Coastguard Worker
809*8617a60dSAndroid Build Coastguard Worker /*
810*8617a60dSAndroid Build Coastguard Worker * Checks if the given firmware image is signed with a key that won't be
811*8617a60dSAndroid Build Coastguard Worker * blocked by TPM's anti-rollback detection.
812*8617a60dSAndroid Build Coastguard Worker * Returns 0 for success, otherwise failure.
813*8617a60dSAndroid Build Coastguard Worker */
do_check_compatible_tpm_keys(struct updater_config * cfg,const struct firmware_image * rw_image)814*8617a60dSAndroid Build Coastguard Worker static int do_check_compatible_tpm_keys(struct updater_config *cfg,
815*8617a60dSAndroid Build Coastguard Worker const struct firmware_image *rw_image)
816*8617a60dSAndroid Build Coastguard Worker {
817*8617a60dSAndroid Build Coastguard Worker unsigned int data_key_version = 0, firmware_version = 0,
818*8617a60dSAndroid Build Coastguard Worker tpm_data_key_version = 0, tpm_firmware_version = 0;
819*8617a60dSAndroid Build Coastguard Worker int tpm_fwver = 0;
820*8617a60dSAndroid Build Coastguard Worker
821*8617a60dSAndroid Build Coastguard Worker /* Fail if the given image does not look good. */
822*8617a60dSAndroid Build Coastguard Worker if (get_key_versions(rw_image, FMAP_RW_VBLOCK_A, &data_key_version,
823*8617a60dSAndroid Build Coastguard Worker &firmware_version) != 0)
824*8617a60dSAndroid Build Coastguard Worker return -1;
825*8617a60dSAndroid Build Coastguard Worker
826*8617a60dSAndroid Build Coastguard Worker /* The stored tpm_fwver can be 0 (b/116298359#comment3). */
827*8617a60dSAndroid Build Coastguard Worker tpm_fwver = dut_get_property(DUT_PROP_TPM_FWVER, cfg);
828*8617a60dSAndroid Build Coastguard Worker if (tpm_fwver < 0) {
829*8617a60dSAndroid Build Coastguard Worker /*
830*8617a60dSAndroid Build Coastguard Worker * tpm_fwver is commonly misreported in --ccd mode, so allow
831*8617a60dSAndroid Build Coastguard Worker * force_update to ignore the reported value.
832*8617a60dSAndroid Build Coastguard Worker */
833*8617a60dSAndroid Build Coastguard Worker if (!cfg->force_update)
834*8617a60dSAndroid Build Coastguard Worker ERROR("Invalid tpm_fwver: %d.\n", tpm_fwver);
835*8617a60dSAndroid Build Coastguard Worker return -1;
836*8617a60dSAndroid Build Coastguard Worker }
837*8617a60dSAndroid Build Coastguard Worker
838*8617a60dSAndroid Build Coastguard Worker tpm_data_key_version = tpm_fwver >> 16;
839*8617a60dSAndroid Build Coastguard Worker tpm_firmware_version = tpm_fwver & 0xffff;
840*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("TPM: data_key_version = %d, firmware_version = %d\n",
841*8617a60dSAndroid Build Coastguard Worker tpm_data_key_version, tpm_firmware_version);
842*8617a60dSAndroid Build Coastguard Worker
843*8617a60dSAndroid Build Coastguard Worker if (tpm_data_key_version > data_key_version) {
844*8617a60dSAndroid Build Coastguard Worker ERROR("Data key version rollback detected (%d->%d).\n",
845*8617a60dSAndroid Build Coastguard Worker tpm_data_key_version, data_key_version);
846*8617a60dSAndroid Build Coastguard Worker return -1;
847*8617a60dSAndroid Build Coastguard Worker }
848*8617a60dSAndroid Build Coastguard Worker if (tpm_firmware_version > firmware_version) {
849*8617a60dSAndroid Build Coastguard Worker ERROR("Firmware version rollback detected (%d->%d).\n",
850*8617a60dSAndroid Build Coastguard Worker tpm_firmware_version, firmware_version);
851*8617a60dSAndroid Build Coastguard Worker return -1;
852*8617a60dSAndroid Build Coastguard Worker }
853*8617a60dSAndroid Build Coastguard Worker return 0;
854*8617a60dSAndroid Build Coastguard Worker }
855*8617a60dSAndroid Build Coastguard Worker
856*8617a60dSAndroid Build Coastguard Worker /*
857*8617a60dSAndroid Build Coastguard Worker * Wrapper for do_check_compatible_tpm_keys.
858*8617a60dSAndroid Build Coastguard Worker * Will return 0 if do_check_compatible_tpm_keys success or if cfg.force_update
859*8617a60dSAndroid Build Coastguard Worker * is set; otherwise non-zero.
860*8617a60dSAndroid Build Coastguard Worker */
check_compatible_tpm_keys(struct updater_config * cfg,const struct firmware_image * rw_image)861*8617a60dSAndroid Build Coastguard Worker static int check_compatible_tpm_keys(struct updater_config *cfg,
862*8617a60dSAndroid Build Coastguard Worker const struct firmware_image *rw_image)
863*8617a60dSAndroid Build Coastguard Worker {
864*8617a60dSAndroid Build Coastguard Worker int r = do_check_compatible_tpm_keys(cfg, rw_image);
865*8617a60dSAndroid Build Coastguard Worker if (!r)
866*8617a60dSAndroid Build Coastguard Worker return r;
867*8617a60dSAndroid Build Coastguard Worker if (!cfg->force_update) {
868*8617a60dSAndroid Build Coastguard Worker ERROR("Add --force if you want to waive TPM checks.\n");
869*8617a60dSAndroid Build Coastguard Worker return r;
870*8617a60dSAndroid Build Coastguard Worker }
871*8617a60dSAndroid Build Coastguard Worker WARN("TPM KEYS CHECK IS WAIVED BY --force. YOU ARE ON YOUR OWN.\n");
872*8617a60dSAndroid Build Coastguard Worker return 0;
873*8617a60dSAndroid Build Coastguard Worker }
874*8617a60dSAndroid Build Coastguard Worker
875*8617a60dSAndroid Build Coastguard Worker
876*8617a60dSAndroid Build Coastguard Worker /*
877*8617a60dSAndroid Build Coastguard Worker * Update EC (RO+RW) firmware if possible.
878*8617a60dSAndroid Build Coastguard Worker * If the image has no data or if the section does not exist, ignore and return success.
879*8617a60dSAndroid Build Coastguard Worker * Returns 0 if success, non-zero if error.
880*8617a60dSAndroid Build Coastguard Worker */
update_ec_firmware(struct updater_config * cfg)881*8617a60dSAndroid Build Coastguard Worker static int update_ec_firmware(struct updater_config *cfg)
882*8617a60dSAndroid Build Coastguard Worker {
883*8617a60dSAndroid Build Coastguard Worker struct firmware_image *ec_image = &cfg->ec_image;
884*8617a60dSAndroid Build Coastguard Worker if (!has_valid_update(cfg, ec_image, NULL, 0))
885*8617a60dSAndroid Build Coastguard Worker return 0;
886*8617a60dSAndroid Build Coastguard Worker
887*8617a60dSAndroid Build Coastguard Worker const char *sections[] = {"WP_RO"};
888*8617a60dSAndroid Build Coastguard Worker size_t num_sections = 0;
889*8617a60dSAndroid Build Coastguard Worker int r = try_apply_quirk(QUIRK_EC_PARTIAL_RECOVERY, cfg);
890*8617a60dSAndroid Build Coastguard Worker switch (r) {
891*8617a60dSAndroid Build Coastguard Worker case EC_RECOVERY_FULL:
892*8617a60dSAndroid Build Coastguard Worker break; /* 0 num_sections implies write whole image. */
893*8617a60dSAndroid Build Coastguard Worker
894*8617a60dSAndroid Build Coastguard Worker case EC_RECOVERY_RO: {
895*8617a60dSAndroid Build Coastguard Worker num_sections = ARRAY_SIZE(sections);
896*8617a60dSAndroid Build Coastguard Worker break;
897*8617a60dSAndroid Build Coastguard Worker }
898*8617a60dSAndroid Build Coastguard Worker
899*8617a60dSAndroid Build Coastguard Worker case EC_RECOVERY_DONE:
900*8617a60dSAndroid Build Coastguard Worker /* Done by some quirks, for example EC RO software sync. */
901*8617a60dSAndroid Build Coastguard Worker return 0;
902*8617a60dSAndroid Build Coastguard Worker
903*8617a60dSAndroid Build Coastguard Worker default:
904*8617a60dSAndroid Build Coastguard Worker return r;
905*8617a60dSAndroid Build Coastguard Worker }
906*8617a60dSAndroid Build Coastguard Worker
907*8617a60dSAndroid Build Coastguard Worker if (is_ec_write_protection_enabled(cfg)) {
908*8617a60dSAndroid Build Coastguard Worker ERROR("Target ec is write protected, skip updating.\n");
909*8617a60dSAndroid Build Coastguard Worker return 0;
910*8617a60dSAndroid Build Coastguard Worker }
911*8617a60dSAndroid Build Coastguard Worker
912*8617a60dSAndroid Build Coastguard Worker /* TODO(quasisec): Uses cros_ec to program the EC. */
913*8617a60dSAndroid Build Coastguard Worker return write_system_firmware(cfg, ec_image, sections, num_sections);
914*8617a60dSAndroid Build Coastguard Worker }
915*8617a60dSAndroid Build Coastguard Worker
916*8617a60dSAndroid Build Coastguard Worker const char * const updater_error_messages[] = {
917*8617a60dSAndroid Build Coastguard Worker [UPDATE_ERR_DONE] = "Done (no error)",
918*8617a60dSAndroid Build Coastguard Worker [UPDATE_ERR_NEED_RO_UPDATE] = "RO changed and no WP. Need full update.",
919*8617a60dSAndroid Build Coastguard Worker [UPDATE_ERR_NO_IMAGE] = "No image to update; try specify with -i.",
920*8617a60dSAndroid Build Coastguard Worker [UPDATE_ERR_SYSTEM_IMAGE] = "Cannot load system active firmware.",
921*8617a60dSAndroid Build Coastguard Worker [UPDATE_ERR_INVALID_IMAGE] = "The given firmware image is not valid.",
922*8617a60dSAndroid Build Coastguard Worker [UPDATE_ERR_SET_COOKIES] = "Failed writing system flags to try update.",
923*8617a60dSAndroid Build Coastguard Worker [UPDATE_ERR_WRITE_FIRMWARE] = "Failed writing firmware.",
924*8617a60dSAndroid Build Coastguard Worker [UPDATE_ERR_PLATFORM] = "Your system platform is not compatible.",
925*8617a60dSAndroid Build Coastguard Worker [UPDATE_ERR_TARGET] = "No valid RW target to update. Abort.",
926*8617a60dSAndroid Build Coastguard Worker [UPDATE_ERR_ROOT_KEY] = "RW signed by incompatible root key "
927*8617a60dSAndroid Build Coastguard Worker "(different from RO).",
928*8617a60dSAndroid Build Coastguard Worker [UPDATE_ERR_TPM_ROLLBACK] = "RW not usable due to TPM anti-rollback.",
929*8617a60dSAndroid Build Coastguard Worker [UPDATE_ERR_UNLOCK_CSME] = "The CSME was already locked (b/284913015).",
930*8617a60dSAndroid Build Coastguard Worker [UPDATE_ERR_UNKNOWN] = "Unknown error.",
931*8617a60dSAndroid Build Coastguard Worker };
932*8617a60dSAndroid Build Coastguard Worker
933*8617a60dSAndroid Build Coastguard Worker /*
934*8617a60dSAndroid Build Coastguard Worker * The main updater for "Legacy update".
935*8617a60dSAndroid Build Coastguard Worker * This is equivalent to --mode=legacy.
936*8617a60dSAndroid Build Coastguard Worker * Returns UPDATE_ERR_DONE if success, otherwise error.
937*8617a60dSAndroid Build Coastguard Worker */
update_legacy_firmware(struct updater_config * cfg,struct firmware_image * image_to)938*8617a60dSAndroid Build Coastguard Worker static enum updater_error_codes update_legacy_firmware(
939*8617a60dSAndroid Build Coastguard Worker struct updater_config *cfg,
940*8617a60dSAndroid Build Coastguard Worker struct firmware_image *image_to)
941*8617a60dSAndroid Build Coastguard Worker {
942*8617a60dSAndroid Build Coastguard Worker STATUS("LEGACY UPDATE: Updating firmware %s.\n", FMAP_RW_LEGACY);
943*8617a60dSAndroid Build Coastguard Worker
944*8617a60dSAndroid Build Coastguard Worker const char *sections[] = {FMAP_RW_LEGACY};
945*8617a60dSAndroid Build Coastguard Worker if (write_system_firmware(cfg, image_to, sections,
946*8617a60dSAndroid Build Coastguard Worker ARRAY_SIZE(sections)))
947*8617a60dSAndroid Build Coastguard Worker return UPDATE_ERR_WRITE_FIRMWARE;
948*8617a60dSAndroid Build Coastguard Worker
949*8617a60dSAndroid Build Coastguard Worker return UPDATE_ERR_DONE;
950*8617a60dSAndroid Build Coastguard Worker }
951*8617a60dSAndroid Build Coastguard Worker
952*8617a60dSAndroid Build Coastguard Worker /*
953*8617a60dSAndroid Build Coastguard Worker * The main updater for "Try-RW update", to update only one RW section
954*8617a60dSAndroid Build Coastguard Worker * and try if it can boot properly on reboot.
955*8617a60dSAndroid Build Coastguard Worker * This was also known as --mode=autoupdate,--wp=1 in legacy updater.
956*8617a60dSAndroid Build Coastguard Worker * Returns UPDATE_ERR_DONE if success, otherwise error.
957*8617a60dSAndroid Build Coastguard Worker */
update_try_rw_firmware(struct updater_config * cfg,struct firmware_image * image_from,struct firmware_image * image_to,bool wp_enabled)958*8617a60dSAndroid Build Coastguard Worker static enum updater_error_codes update_try_rw_firmware(
959*8617a60dSAndroid Build Coastguard Worker struct updater_config *cfg,
960*8617a60dSAndroid Build Coastguard Worker struct firmware_image *image_from,
961*8617a60dSAndroid Build Coastguard Worker struct firmware_image *image_to,
962*8617a60dSAndroid Build Coastguard Worker bool wp_enabled)
963*8617a60dSAndroid Build Coastguard Worker {
964*8617a60dSAndroid Build Coastguard Worker const char *target, *self_target;
965*8617a60dSAndroid Build Coastguard Worker int has_update = 1;
966*8617a60dSAndroid Build Coastguard Worker
967*8617a60dSAndroid Build Coastguard Worker preserve_gbb(image_from, image_to, 1, 0, 0);
968*8617a60dSAndroid Build Coastguard Worker if (!wp_enabled && section_needs_update(
969*8617a60dSAndroid Build Coastguard Worker image_from, image_to, FMAP_RO_SECTION))
970*8617a60dSAndroid Build Coastguard Worker return UPDATE_ERR_NEED_RO_UPDATE;
971*8617a60dSAndroid Build Coastguard Worker
972*8617a60dSAndroid Build Coastguard Worker INFO("Checking compatibility...\n");
973*8617a60dSAndroid Build Coastguard Worker if (check_compatible_root_key(image_from, image_to))
974*8617a60dSAndroid Build Coastguard Worker return UPDATE_ERR_ROOT_KEY;
975*8617a60dSAndroid Build Coastguard Worker if (check_compatible_tpm_keys(cfg, image_to))
976*8617a60dSAndroid Build Coastguard Worker return UPDATE_ERR_TPM_ROLLBACK;
977*8617a60dSAndroid Build Coastguard Worker
978*8617a60dSAndroid Build Coastguard Worker self_target = target = decide_rw_target(cfg, TARGET_SELF);
979*8617a60dSAndroid Build Coastguard Worker if (target == NULL) {
980*8617a60dSAndroid Build Coastguard Worker ERROR("TRY-RW update needs system to boot in RW firmware.\n");
981*8617a60dSAndroid Build Coastguard Worker return UPDATE_ERR_TARGET;
982*8617a60dSAndroid Build Coastguard Worker }
983*8617a60dSAndroid Build Coastguard Worker
984*8617a60dSAndroid Build Coastguard Worker INFO("Checking %s contents...\n", target);
985*8617a60dSAndroid Build Coastguard Worker if (!firmware_section_exists(image_to, target)) {
986*8617a60dSAndroid Build Coastguard Worker ERROR("Cannot find section '%s' on firmware image: %s\n",
987*8617a60dSAndroid Build Coastguard Worker target, image_to->file_name);
988*8617a60dSAndroid Build Coastguard Worker return UPDATE_ERR_INVALID_IMAGE;
989*8617a60dSAndroid Build Coastguard Worker }
990*8617a60dSAndroid Build Coastguard Worker if (!(cfg->force_update || cfg->try_update == TRY_UPDATE_DEFERRED_HOLD))
991*8617a60dSAndroid Build Coastguard Worker has_update = section_needs_update(image_from, image_to, target);
992*8617a60dSAndroid Build Coastguard Worker
993*8617a60dSAndroid Build Coastguard Worker if (has_update) {
994*8617a60dSAndroid Build Coastguard Worker target = decide_rw_target(cfg, TARGET_UPDATE);
995*8617a60dSAndroid Build Coastguard Worker STATUS("TRY-RW UPDATE: Updating %s to try on reboot.\n",
996*8617a60dSAndroid Build Coastguard Worker target);
997*8617a60dSAndroid Build Coastguard Worker
998*8617a60dSAndroid Build Coastguard Worker const char *sections[] = {target};
999*8617a60dSAndroid Build Coastguard Worker if (write_system_firmware(cfg, image_to, sections,
1000*8617a60dSAndroid Build Coastguard Worker ARRAY_SIZE(sections)))
1001*8617a60dSAndroid Build Coastguard Worker return UPDATE_ERR_WRITE_FIRMWARE;
1002*8617a60dSAndroid Build Coastguard Worker
1003*8617a60dSAndroid Build Coastguard Worker /*
1004*8617a60dSAndroid Build Coastguard Worker * If the firmware update requested is part of a deferred update
1005*8617a60dSAndroid Build Coastguard Worker * HOLD action, the autoupdater/postinstall will later call
1006*8617a60dSAndroid Build Coastguard Worker * defer update APPLY action to set the correct cookies. So here
1007*8617a60dSAndroid Build Coastguard Worker * it is valid to keep the self slot as the active firmware even
1008*8617a60dSAndroid Build Coastguard Worker * though the target slot is always updated (whether the current
1009*8617a60dSAndroid Build Coastguard Worker * active firmware is the same version or not).
1010*8617a60dSAndroid Build Coastguard Worker */
1011*8617a60dSAndroid Build Coastguard Worker if (cfg->try_update == TRY_UPDATE_DEFERRED_HOLD) {
1012*8617a60dSAndroid Build Coastguard Worker STATUS(
1013*8617a60dSAndroid Build Coastguard Worker "DEFERRED UPDATE: Defer setting cookies for %s\n",
1014*8617a60dSAndroid Build Coastguard Worker target);
1015*8617a60dSAndroid Build Coastguard Worker target = self_target;
1016*8617a60dSAndroid Build Coastguard Worker has_update = 0;
1017*8617a60dSAndroid Build Coastguard Worker }
1018*8617a60dSAndroid Build Coastguard Worker } else {
1019*8617a60dSAndroid Build Coastguard Worker STATUS("NO RW UPDATE: No update for RW firmware.\n");
1020*8617a60dSAndroid Build Coastguard Worker }
1021*8617a60dSAndroid Build Coastguard Worker
1022*8617a60dSAndroid Build Coastguard Worker /* Always set right cookies for next boot. */
1023*8617a60dSAndroid Build Coastguard Worker if (set_try_cookies(cfg, target, has_update))
1024*8617a60dSAndroid Build Coastguard Worker return UPDATE_ERR_SET_COOKIES;
1025*8617a60dSAndroid Build Coastguard Worker
1026*8617a60dSAndroid Build Coastguard Worker /* Do not fail on updating legacy. */
1027*8617a60dSAndroid Build Coastguard Worker if (legacy_needs_update(cfg)) {
1028*8617a60dSAndroid Build Coastguard Worker has_update = 1;
1029*8617a60dSAndroid Build Coastguard Worker update_legacy_firmware(cfg, image_to);
1030*8617a60dSAndroid Build Coastguard Worker }
1031*8617a60dSAndroid Build Coastguard Worker
1032*8617a60dSAndroid Build Coastguard Worker return UPDATE_ERR_DONE;
1033*8617a60dSAndroid Build Coastguard Worker }
1034*8617a60dSAndroid Build Coastguard Worker
1035*8617a60dSAndroid Build Coastguard Worker /*
1036*8617a60dSAndroid Build Coastguard Worker * The main updater for "RW update".
1037*8617a60dSAndroid Build Coastguard Worker * This was also known as --mode=recovery, --wp=1 in legacy updater.
1038*8617a60dSAndroid Build Coastguard Worker * Returns UPDATE_ERR_DONE if success, otherwise error.
1039*8617a60dSAndroid Build Coastguard Worker */
update_rw_firmware(struct updater_config * cfg,struct firmware_image * image_from,struct firmware_image * image_to)1040*8617a60dSAndroid Build Coastguard Worker static enum updater_error_codes update_rw_firmware(
1041*8617a60dSAndroid Build Coastguard Worker struct updater_config *cfg,
1042*8617a60dSAndroid Build Coastguard Worker struct firmware_image *image_from,
1043*8617a60dSAndroid Build Coastguard Worker struct firmware_image *image_to)
1044*8617a60dSAndroid Build Coastguard Worker {
1045*8617a60dSAndroid Build Coastguard Worker int i, num = 0;
1046*8617a60dSAndroid Build Coastguard Worker static const char * const required_sections[] = {
1047*8617a60dSAndroid Build Coastguard Worker FMAP_RW_SECTION_A,
1048*8617a60dSAndroid Build Coastguard Worker FMAP_RW_SECTION_B,
1049*8617a60dSAndroid Build Coastguard Worker };
1050*8617a60dSAndroid Build Coastguard Worker static const char * const optional_sections[] = {
1051*8617a60dSAndroid Build Coastguard Worker FMAP_RW_LEGACY,
1052*8617a60dSAndroid Build Coastguard Worker FMAP_RW_SHARED,
1053*8617a60dSAndroid Build Coastguard Worker };
1054*8617a60dSAndroid Build Coastguard Worker const char *sections[ARRAY_SIZE(required_sections) +
1055*8617a60dSAndroid Build Coastguard Worker ARRAY_SIZE(optional_sections)];
1056*8617a60dSAndroid Build Coastguard Worker
1057*8617a60dSAndroid Build Coastguard Worker STATUS("RW UPDATE: Updating RW sections (%s, %s, %s, and %s).\n",
1058*8617a60dSAndroid Build Coastguard Worker FMAP_RW_SECTION_A, FMAP_RW_SECTION_B, FMAP_RW_SHARED,
1059*8617a60dSAndroid Build Coastguard Worker FMAP_RW_LEGACY);
1060*8617a60dSAndroid Build Coastguard Worker
1061*8617a60dSAndroid Build Coastguard Worker INFO("Checking compatibility...\n");
1062*8617a60dSAndroid Build Coastguard Worker if (check_compatible_root_key(image_from, image_to))
1063*8617a60dSAndroid Build Coastguard Worker return UPDATE_ERR_ROOT_KEY;
1064*8617a60dSAndroid Build Coastguard Worker if (check_compatible_tpm_keys(cfg, image_to))
1065*8617a60dSAndroid Build Coastguard Worker return UPDATE_ERR_TPM_ROLLBACK;
1066*8617a60dSAndroid Build Coastguard Worker
1067*8617a60dSAndroid Build Coastguard Worker for (i = 0; i < ARRAY_SIZE(required_sections); i++)
1068*8617a60dSAndroid Build Coastguard Worker sections[num++] = required_sections[i];
1069*8617a60dSAndroid Build Coastguard Worker
1070*8617a60dSAndroid Build Coastguard Worker /*
1071*8617a60dSAndroid Build Coastguard Worker * The FMAP_RW_LEGACY is a special optional section.
1072*8617a60dSAndroid Build Coastguard Worker * We may also consider only updating legacy if legacy_needs_update()
1073*8617a60dSAndroid Build Coastguard Worker * returns true. However, given this is for 'recovery', it is probably
1074*8617a60dSAndroid Build Coastguard Worker * better to restore everything to the default states. We may revisit
1075*8617a60dSAndroid Build Coastguard Worker * this if a new scenario is found.
1076*8617a60dSAndroid Build Coastguard Worker */
1077*8617a60dSAndroid Build Coastguard Worker for (i = 0; i < ARRAY_SIZE(optional_sections); i++) {
1078*8617a60dSAndroid Build Coastguard Worker const char *name = optional_sections[i];
1079*8617a60dSAndroid Build Coastguard Worker if (!firmware_section_exists(image_from, name) ||
1080*8617a60dSAndroid Build Coastguard Worker !firmware_section_exists(image_to, name)) {
1081*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Skipped optional section: %s\n", name);
1082*8617a60dSAndroid Build Coastguard Worker continue;
1083*8617a60dSAndroid Build Coastguard Worker }
1084*8617a60dSAndroid Build Coastguard Worker sections[num++] = name;
1085*8617a60dSAndroid Build Coastguard Worker }
1086*8617a60dSAndroid Build Coastguard Worker assert(num <= ARRAY_SIZE(sections));
1087*8617a60dSAndroid Build Coastguard Worker
1088*8617a60dSAndroid Build Coastguard Worker if (write_system_firmware(cfg, image_to, sections, num))
1089*8617a60dSAndroid Build Coastguard Worker return UPDATE_ERR_WRITE_FIRMWARE;
1090*8617a60dSAndroid Build Coastguard Worker
1091*8617a60dSAndroid Build Coastguard Worker return UPDATE_ERR_DONE;
1092*8617a60dSAndroid Build Coastguard Worker }
1093*8617a60dSAndroid Build Coastguard Worker
1094*8617a60dSAndroid Build Coastguard Worker /*
1095*8617a60dSAndroid Build Coastguard Worker * The main updater for "Full update".
1096*8617a60dSAndroid Build Coastguard Worker * This was also known as "--mode=factory" or "--mode=recovery, --wp=0" in
1097*8617a60dSAndroid Build Coastguard Worker * legacy updater.
1098*8617a60dSAndroid Build Coastguard Worker * Returns UPDATE_ERR_DONE if success, otherwise error.
1099*8617a60dSAndroid Build Coastguard Worker */
update_whole_firmware(struct updater_config * cfg,struct firmware_image * image_to)1100*8617a60dSAndroid Build Coastguard Worker static enum updater_error_codes update_whole_firmware(
1101*8617a60dSAndroid Build Coastguard Worker struct updater_config *cfg,
1102*8617a60dSAndroid Build Coastguard Worker struct firmware_image *image_to)
1103*8617a60dSAndroid Build Coastguard Worker {
1104*8617a60dSAndroid Build Coastguard Worker STATUS("FULL UPDATE: Updating whole firmware image(s), RO+RW.\n");
1105*8617a60dSAndroid Build Coastguard Worker
1106*8617a60dSAndroid Build Coastguard Worker if (preserve_images(cfg))
1107*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Failed to preserve some sections - ignore.\n");
1108*8617a60dSAndroid Build Coastguard Worker
1109*8617a60dSAndroid Build Coastguard Worker INFO("Checking compatibility...\n");
1110*8617a60dSAndroid Build Coastguard Worker if (!cfg->force_update) {
1111*8617a60dSAndroid Build Coastguard Worker /* Check if the image_to itself is broken */
1112*8617a60dSAndroid Build Coastguard Worker enum rootkey_compat_result r = check_compatible_root_key(
1113*8617a60dSAndroid Build Coastguard Worker image_to, image_to);
1114*8617a60dSAndroid Build Coastguard Worker if (r != ROOTKEY_COMPAT_OK) {
1115*8617a60dSAndroid Build Coastguard Worker ERROR("Target image does not look valid. \n"
1116*8617a60dSAndroid Build Coastguard Worker "Add --force if you really want to use it.");
1117*8617a60dSAndroid Build Coastguard Worker return UPDATE_ERR_ROOT_KEY;
1118*8617a60dSAndroid Build Coastguard Worker }
1119*8617a60dSAndroid Build Coastguard Worker
1120*8617a60dSAndroid Build Coastguard Worker /* Check if the system is going to re-key. */
1121*8617a60dSAndroid Build Coastguard Worker r = check_compatible_root_key(&cfg->image_current, image_to);
1122*8617a60dSAndroid Build Coastguard Worker /* We only allow re-key to non-dev keys. */
1123*8617a60dSAndroid Build Coastguard Worker switch (r) {
1124*8617a60dSAndroid Build Coastguard Worker case ROOTKEY_COMPAT_OK:
1125*8617a60dSAndroid Build Coastguard Worker break;
1126*8617a60dSAndroid Build Coastguard Worker case ROOTKEY_COMPAT_REKEY:
1127*8617a60dSAndroid Build Coastguard Worker INFO("Will change firmware signing key.\n");
1128*8617a60dSAndroid Build Coastguard Worker break;
1129*8617a60dSAndroid Build Coastguard Worker case ROOTKEY_COMPAT_REKEY_TO_DEV:
1130*8617a60dSAndroid Build Coastguard Worker ERROR("Re-key to DEV is not allowed. \n"
1131*8617a60dSAndroid Build Coastguard Worker "Add --force if you really want to do that.");
1132*8617a60dSAndroid Build Coastguard Worker return UPDATE_ERR_ROOT_KEY;
1133*8617a60dSAndroid Build Coastguard Worker default:
1134*8617a60dSAndroid Build Coastguard Worker return UPDATE_ERR_ROOT_KEY;
1135*8617a60dSAndroid Build Coastguard Worker }
1136*8617a60dSAndroid Build Coastguard Worker }
1137*8617a60dSAndroid Build Coastguard Worker if (check_compatible_tpm_keys(cfg, image_to))
1138*8617a60dSAndroid Build Coastguard Worker return UPDATE_ERR_TPM_ROLLBACK;
1139*8617a60dSAndroid Build Coastguard Worker
1140*8617a60dSAndroid Build Coastguard Worker /* FMAP may be different so we should just update all. */
1141*8617a60dSAndroid Build Coastguard Worker if (write_system_firmware(cfg, image_to, NULL, 0) ||
1142*8617a60dSAndroid Build Coastguard Worker update_ec_firmware(cfg))
1143*8617a60dSAndroid Build Coastguard Worker return UPDATE_ERR_WRITE_FIRMWARE;
1144*8617a60dSAndroid Build Coastguard Worker
1145*8617a60dSAndroid Build Coastguard Worker return UPDATE_ERR_DONE;
1146*8617a60dSAndroid Build Coastguard Worker }
1147*8617a60dSAndroid Build Coastguard Worker
update_firmware(struct updater_config * cfg)1148*8617a60dSAndroid Build Coastguard Worker enum updater_error_codes update_firmware(struct updater_config *cfg)
1149*8617a60dSAndroid Build Coastguard Worker {
1150*8617a60dSAndroid Build Coastguard Worker bool done = false;
1151*8617a60dSAndroid Build Coastguard Worker enum updater_error_codes r = UPDATE_ERR_UNKNOWN;
1152*8617a60dSAndroid Build Coastguard Worker
1153*8617a60dSAndroid Build Coastguard Worker /*
1154*8617a60dSAndroid Build Coastguard Worker * For deferred update APPLY action, the only requirement is to set the
1155*8617a60dSAndroid Build Coastguard Worker * correct cookies to the update target slot.
1156*8617a60dSAndroid Build Coastguard Worker */
1157*8617a60dSAndroid Build Coastguard Worker if (cfg->try_update == TRY_UPDATE_DEFERRED_APPLY) {
1158*8617a60dSAndroid Build Coastguard Worker INFO("Apply deferred updates, only setting cookies for the "
1159*8617a60dSAndroid Build Coastguard Worker "next boot slot.\n");
1160*8617a60dSAndroid Build Coastguard Worker if (set_try_cookies(cfg, decide_rw_target(cfg, TARGET_UPDATE),
1161*8617a60dSAndroid Build Coastguard Worker /*has_update=*/1))
1162*8617a60dSAndroid Build Coastguard Worker return UPDATE_ERR_SET_COOKIES;
1163*8617a60dSAndroid Build Coastguard Worker return UPDATE_ERR_DONE;
1164*8617a60dSAndroid Build Coastguard Worker }
1165*8617a60dSAndroid Build Coastguard Worker
1166*8617a60dSAndroid Build Coastguard Worker struct firmware_image *image_from = &cfg->image_current,
1167*8617a60dSAndroid Build Coastguard Worker *image_to = &cfg->image;
1168*8617a60dSAndroid Build Coastguard Worker if (!image_to->data)
1169*8617a60dSAndroid Build Coastguard Worker return UPDATE_ERR_NO_IMAGE;
1170*8617a60dSAndroid Build Coastguard Worker
1171*8617a60dSAndroid Build Coastguard Worker STATUS("Target image: %s (RO:%s, RW/A:%s (w/ECRW:%s), RW/B:%s (w/ECRW:%s)).\n",
1172*8617a60dSAndroid Build Coastguard Worker image_to->file_name, image_to->ro_version,
1173*8617a60dSAndroid Build Coastguard Worker image_to->rw_version_a, image_to->ecrw_version_a,
1174*8617a60dSAndroid Build Coastguard Worker image_to->rw_version_b, image_to->ecrw_version_b);
1175*8617a60dSAndroid Build Coastguard Worker check_firmware_versions(image_to);
1176*8617a60dSAndroid Build Coastguard Worker
1177*8617a60dSAndroid Build Coastguard Worker try_apply_quirk(QUIRK_NO_VERIFY, cfg);
1178*8617a60dSAndroid Build Coastguard Worker if (try_apply_quirk(QUIRK_MIN_PLATFORM_VERSION, cfg)) {
1179*8617a60dSAndroid Build Coastguard Worker if (!cfg->force_update) {
1180*8617a60dSAndroid Build Coastguard Worker ERROR("Add --force to waive checking the version.\n");
1181*8617a60dSAndroid Build Coastguard Worker return UPDATE_ERR_PLATFORM;
1182*8617a60dSAndroid Build Coastguard Worker }
1183*8617a60dSAndroid Build Coastguard Worker }
1184*8617a60dSAndroid Build Coastguard Worker if (!image_from->data) {
1185*8617a60dSAndroid Build Coastguard Worker int ret;
1186*8617a60dSAndroid Build Coastguard Worker
1187*8617a60dSAndroid Build Coastguard Worker INFO("Loading current system firmware...\n");
1188*8617a60dSAndroid Build Coastguard Worker ret = load_system_firmware(cfg, image_from);
1189*8617a60dSAndroid Build Coastguard Worker if (ret == IMAGE_PARSE_FAILURE && cfg->force_update) {
1190*8617a60dSAndroid Build Coastguard Worker WARN("No compatible firmware in system.\n");
1191*8617a60dSAndroid Build Coastguard Worker cfg->check_platform = 0;
1192*8617a60dSAndroid Build Coastguard Worker } else if (ret)
1193*8617a60dSAndroid Build Coastguard Worker return UPDATE_ERR_SYSTEM_IMAGE;
1194*8617a60dSAndroid Build Coastguard Worker }
1195*8617a60dSAndroid Build Coastguard Worker STATUS("Current system: %s (RO:%s, RW/A:%s (w/ECRW:%s), RW/B:%s (w/ECRW:%s)).\n",
1196*8617a60dSAndroid Build Coastguard Worker image_from->file_name, image_from->ro_version,
1197*8617a60dSAndroid Build Coastguard Worker image_from->rw_version_a, image_from->ecrw_version_a,
1198*8617a60dSAndroid Build Coastguard Worker image_from->rw_version_b, image_from->ecrw_version_b);
1199*8617a60dSAndroid Build Coastguard Worker
1200*8617a60dSAndroid Build Coastguard Worker try_apply_quirk(QUIRK_NO_CHECK_PLATFORM, cfg);
1201*8617a60dSAndroid Build Coastguard Worker if (cfg->check_platform && check_compatible_platform(cfg)) {
1202*8617a60dSAndroid Build Coastguard Worker ERROR("The firmware image is not compatible with your system. "
1203*8617a60dSAndroid Build Coastguard Worker "If you really want to proceed, please run again with: "
1204*8617a60dSAndroid Build Coastguard Worker "--quirks=no_check_platform\n");
1205*8617a60dSAndroid Build Coastguard Worker return UPDATE_ERR_PLATFORM;
1206*8617a60dSAndroid Build Coastguard Worker }
1207*8617a60dSAndroid Build Coastguard Worker
1208*8617a60dSAndroid Build Coastguard Worker bool wp_enabled = is_ap_write_protection_enabled(cfg);
1209*8617a60dSAndroid Build Coastguard Worker
1210*8617a60dSAndroid Build Coastguard Worker if (try_apply_quirk(QUIRK_ENLARGE_IMAGE, cfg))
1211*8617a60dSAndroid Build Coastguard Worker return UPDATE_ERR_SYSTEM_IMAGE;
1212*8617a60dSAndroid Build Coastguard Worker
1213*8617a60dSAndroid Build Coastguard Worker if (try_apply_quirk(QUIRK_EVE_SMM_STORE, cfg))
1214*8617a60dSAndroid Build Coastguard Worker return UPDATE_ERR_INVALID_IMAGE;
1215*8617a60dSAndroid Build Coastguard Worker
1216*8617a60dSAndroid Build Coastguard Worker if (try_apply_quirk(QUIRK_CLEAR_MRC_DATA, cfg))
1217*8617a60dSAndroid Build Coastguard Worker return UPDATE_ERR_SYSTEM_IMAGE;
1218*8617a60dSAndroid Build Coastguard Worker
1219*8617a60dSAndroid Build Coastguard Worker if (debugging_enabled)
1220*8617a60dSAndroid Build Coastguard Worker print_dut_properties(cfg);
1221*8617a60dSAndroid Build Coastguard Worker
1222*8617a60dSAndroid Build Coastguard Worker if (cfg->legacy_update)
1223*8617a60dSAndroid Build Coastguard Worker return update_legacy_firmware(cfg, image_to);
1224*8617a60dSAndroid Build Coastguard Worker
1225*8617a60dSAndroid Build Coastguard Worker if (cfg->try_update) {
1226*8617a60dSAndroid Build Coastguard Worker r = update_try_rw_firmware(cfg, image_from, image_to,
1227*8617a60dSAndroid Build Coastguard Worker wp_enabled);
1228*8617a60dSAndroid Build Coastguard Worker if (r == UPDATE_ERR_NEED_RO_UPDATE)
1229*8617a60dSAndroid Build Coastguard Worker WARN("%s\n", updater_error_messages[r]);
1230*8617a60dSAndroid Build Coastguard Worker else
1231*8617a60dSAndroid Build Coastguard Worker done = true;
1232*8617a60dSAndroid Build Coastguard Worker }
1233*8617a60dSAndroid Build Coastguard Worker
1234*8617a60dSAndroid Build Coastguard Worker if (!done) {
1235*8617a60dSAndroid Build Coastguard Worker if (!wp_enabled && is_ap_ro_locked_with_verification(cfg)) {
1236*8617a60dSAndroid Build Coastguard Worker if (is_unlock_csme_requested(cfg))
1237*8617a60dSAndroid Build Coastguard Worker return UPDATE_ERR_UNLOCK_CSME;
1238*8617a60dSAndroid Build Coastguard Worker WARN("The AP RO is locked with verification turned on so we can't do "
1239*8617a60dSAndroid Build Coastguard Worker "full update (b/284913015). Fall back to RW-only update.\n");
1240*8617a60dSAndroid Build Coastguard Worker wp_enabled = 1;
1241*8617a60dSAndroid Build Coastguard Worker }
1242*8617a60dSAndroid Build Coastguard Worker
1243*8617a60dSAndroid Build Coastguard Worker r = wp_enabled ? update_rw_firmware(cfg, image_from, image_to) :
1244*8617a60dSAndroid Build Coastguard Worker update_whole_firmware(cfg, image_to);
1245*8617a60dSAndroid Build Coastguard Worker }
1246*8617a60dSAndroid Build Coastguard Worker
1247*8617a60dSAndroid Build Coastguard Worker /* Providing more hints for what to do on failure. */
1248*8617a60dSAndroid Build Coastguard Worker if (r == UPDATE_ERR_ROOT_KEY && wp_enabled)
1249*8617a60dSAndroid Build Coastguard Worker ERROR("To change keys in RO area, you must first remove "
1250*8617a60dSAndroid Build Coastguard Worker "write protection ( " REMOVE_WP_URL " ).\n");
1251*8617a60dSAndroid Build Coastguard Worker
1252*8617a60dSAndroid Build Coastguard Worker return r;
1253*8617a60dSAndroid Build Coastguard Worker }
1254*8617a60dSAndroid Build Coastguard Worker
updater_new_config(void)1255*8617a60dSAndroid Build Coastguard Worker struct updater_config *updater_new_config(void)
1256*8617a60dSAndroid Build Coastguard Worker {
1257*8617a60dSAndroid Build Coastguard Worker struct updater_config *cfg = (struct updater_config *)calloc(
1258*8617a60dSAndroid Build Coastguard Worker 1, sizeof(struct updater_config));
1259*8617a60dSAndroid Build Coastguard Worker if (!cfg)
1260*8617a60dSAndroid Build Coastguard Worker return cfg;
1261*8617a60dSAndroid Build Coastguard Worker cfg->image.programmer = FLASHROM_PROGRAMMER_INTERNAL_AP;
1262*8617a60dSAndroid Build Coastguard Worker cfg->image_current.programmer = FLASHROM_PROGRAMMER_INTERNAL_AP;
1263*8617a60dSAndroid Build Coastguard Worker cfg->original_programmer = FLASHROM_PROGRAMMER_INTERNAL_AP;
1264*8617a60dSAndroid Build Coastguard Worker cfg->ec_image.programmer = FLASHROM_PROGRAMMER_INTERNAL_EC;
1265*8617a60dSAndroid Build Coastguard Worker
1266*8617a60dSAndroid Build Coastguard Worker cfg->check_platform = 1;
1267*8617a60dSAndroid Build Coastguard Worker cfg->do_verify = 1;
1268*8617a60dSAndroid Build Coastguard Worker
1269*8617a60dSAndroid Build Coastguard Worker dut_init_properties(&cfg->dut_properties[0],
1270*8617a60dSAndroid Build Coastguard Worker ARRAY_SIZE(cfg->dut_properties));
1271*8617a60dSAndroid Build Coastguard Worker updater_register_quirks(cfg);
1272*8617a60dSAndroid Build Coastguard Worker return cfg;
1273*8617a60dSAndroid Build Coastguard Worker }
1274*8617a60dSAndroid Build Coastguard Worker
1275*8617a60dSAndroid Build Coastguard Worker /*
1276*8617a60dSAndroid Build Coastguard Worker * Setup quirks for updating current image.
1277*8617a60dSAndroid Build Coastguard Worker *
1278*8617a60dSAndroid Build Coastguard Worker * Quirks must be loaded after image loaded because we use image contents to
1279*8617a60dSAndroid Build Coastguard Worker * decide default quirks to load. Also, we have to load default quirks first so
1280*8617a60dSAndroid Build Coastguard Worker * user can override them using command line.
1281*8617a60dSAndroid Build Coastguard Worker *
1282*8617a60dSAndroid Build Coastguard Worker * Returns 0 on success, otherwise number of failures.
1283*8617a60dSAndroid Build Coastguard Worker */
updater_setup_quirks(struct updater_config * cfg,const struct updater_config_arguments * arg)1284*8617a60dSAndroid Build Coastguard Worker static int updater_setup_quirks(struct updater_config *cfg,
1285*8617a60dSAndroid Build Coastguard Worker const struct updater_config_arguments *arg)
1286*8617a60dSAndroid Build Coastguard Worker {
1287*8617a60dSAndroid Build Coastguard Worker int errorcnt = 0;
1288*8617a60dSAndroid Build Coastguard Worker const char *model_quirks = updater_get_model_quirks(cfg);
1289*8617a60dSAndroid Build Coastguard Worker char *cbfs_quirks = updater_get_cbfs_quirks(cfg);
1290*8617a60dSAndroid Build Coastguard Worker
1291*8617a60dSAndroid Build Coastguard Worker if (model_quirks)
1292*8617a60dSAndroid Build Coastguard Worker errorcnt += !!setup_config_quirks(model_quirks, cfg);
1293*8617a60dSAndroid Build Coastguard Worker if (cbfs_quirks) {
1294*8617a60dSAndroid Build Coastguard Worker errorcnt += !!setup_config_quirks(cbfs_quirks, cfg);
1295*8617a60dSAndroid Build Coastguard Worker free(cbfs_quirks);
1296*8617a60dSAndroid Build Coastguard Worker }
1297*8617a60dSAndroid Build Coastguard Worker if (arg->quirks)
1298*8617a60dSAndroid Build Coastguard Worker errorcnt += !!setup_config_quirks(arg->quirks, cfg);
1299*8617a60dSAndroid Build Coastguard Worker return errorcnt;
1300*8617a60dSAndroid Build Coastguard Worker }
1301*8617a60dSAndroid Build Coastguard Worker
1302*8617a60dSAndroid Build Coastguard Worker /*
1303*8617a60dSAndroid Build Coastguard Worker * Loads images into updater configuration.
1304*8617a60dSAndroid Build Coastguard Worker * Returns 0 on success, otherwise number of failures.
1305*8617a60dSAndroid Build Coastguard Worker */
updater_load_images(struct updater_config * cfg,const struct updater_config_arguments * arg,const char * image,const char * ec_image)1306*8617a60dSAndroid Build Coastguard Worker static int updater_load_images(struct updater_config *cfg,
1307*8617a60dSAndroid Build Coastguard Worker const struct updater_config_arguments *arg,
1308*8617a60dSAndroid Build Coastguard Worker const char *image,
1309*8617a60dSAndroid Build Coastguard Worker const char *ec_image)
1310*8617a60dSAndroid Build Coastguard Worker {
1311*8617a60dSAndroid Build Coastguard Worker int errorcnt = 0;
1312*8617a60dSAndroid Build Coastguard Worker struct u_archive *ar = cfg->archive;
1313*8617a60dSAndroid Build Coastguard Worker
1314*8617a60dSAndroid Build Coastguard Worker if (!cfg->image.data && image) {
1315*8617a60dSAndroid Build Coastguard Worker if (image && strcmp(image, "-") == 0) {
1316*8617a60dSAndroid Build Coastguard Worker INFO("Reading image from stdin...\n");
1317*8617a60dSAndroid Build Coastguard Worker image = create_temp_file(&cfg->tempfiles);
1318*8617a60dSAndroid Build Coastguard Worker if (image)
1319*8617a60dSAndroid Build Coastguard Worker errorcnt += !!save_file_from_stdin(image);
1320*8617a60dSAndroid Build Coastguard Worker }
1321*8617a60dSAndroid Build Coastguard Worker errorcnt += !!load_firmware_image(&cfg->image, image, ar);
1322*8617a60dSAndroid Build Coastguard Worker if (!errorcnt)
1323*8617a60dSAndroid Build Coastguard Worker errorcnt += updater_setup_quirks(cfg, arg);
1324*8617a60dSAndroid Build Coastguard Worker }
1325*8617a60dSAndroid Build Coastguard Worker
1326*8617a60dSAndroid Build Coastguard Worker /*
1327*8617a60dSAndroid Build Coastguard Worker * In emulation mode, we want to prevent unexpected writing to EC
1328*8617a60dSAndroid Build Coastguard Worker * so we should not load EC; however in output mode that is fine.
1329*8617a60dSAndroid Build Coastguard Worker */
1330*8617a60dSAndroid Build Coastguard Worker if (arg->host_only || (arg->emulation && !cfg->output_only))
1331*8617a60dSAndroid Build Coastguard Worker return errorcnt;
1332*8617a60dSAndroid Build Coastguard Worker
1333*8617a60dSAndroid Build Coastguard Worker if (!cfg->ec_image.data && ec_image)
1334*8617a60dSAndroid Build Coastguard Worker errorcnt += !!load_firmware_image(&cfg->ec_image, ec_image, ar);
1335*8617a60dSAndroid Build Coastguard Worker
1336*8617a60dSAndroid Build Coastguard Worker return errorcnt;
1337*8617a60dSAndroid Build Coastguard Worker }
1338*8617a60dSAndroid Build Coastguard Worker
1339*8617a60dSAndroid Build Coastguard Worker /*
1340*8617a60dSAndroid Build Coastguard Worker * Writes a firmware image to specified file.
1341*8617a60dSAndroid Build Coastguard Worker * Returns 0 on success, otherwise failure.
1342*8617a60dSAndroid Build Coastguard Worker */
updater_output_image(const struct firmware_image * image,const char * fname,const char * root)1343*8617a60dSAndroid Build Coastguard Worker static int updater_output_image(const struct firmware_image *image,
1344*8617a60dSAndroid Build Coastguard Worker const char *fname, const char *root)
1345*8617a60dSAndroid Build Coastguard Worker {
1346*8617a60dSAndroid Build Coastguard Worker int r = 0;
1347*8617a60dSAndroid Build Coastguard Worker char *fpath;
1348*8617a60dSAndroid Build Coastguard Worker
1349*8617a60dSAndroid Build Coastguard Worker if (!image->data)
1350*8617a60dSAndroid Build Coastguard Worker return 0;
1351*8617a60dSAndroid Build Coastguard Worker
1352*8617a60dSAndroid Build Coastguard Worker ASPRINTF(&fpath, "%s/%s", root, fname);
1353*8617a60dSAndroid Build Coastguard Worker r = vb2_write_file(fpath, image->data, image->size);
1354*8617a60dSAndroid Build Coastguard Worker if (r)
1355*8617a60dSAndroid Build Coastguard Worker ERROR("Failed writing firmware image to: %s\n", fpath);
1356*8617a60dSAndroid Build Coastguard Worker else
1357*8617a60dSAndroid Build Coastguard Worker printf("Firmware image saved in: %s\n", fpath);
1358*8617a60dSAndroid Build Coastguard Worker
1359*8617a60dSAndroid Build Coastguard Worker free(fpath);
1360*8617a60dSAndroid Build Coastguard Worker return !!r;
1361*8617a60dSAndroid Build Coastguard Worker }
1362*8617a60dSAndroid Build Coastguard Worker
1363*8617a60dSAndroid Build Coastguard Worker /*
1364*8617a60dSAndroid Build Coastguard Worker * Setup what the updater has to do against an archive.
1365*8617a60dSAndroid Build Coastguard Worker * Returns number of failures, or 0 on success.
1366*8617a60dSAndroid Build Coastguard Worker */
updater_setup_archive(struct updater_config * cfg,const struct updater_config_arguments * arg,struct manifest * manifest,int is_factory)1367*8617a60dSAndroid Build Coastguard Worker static int updater_setup_archive(
1368*8617a60dSAndroid Build Coastguard Worker struct updater_config *cfg,
1369*8617a60dSAndroid Build Coastguard Worker const struct updater_config_arguments *arg,
1370*8617a60dSAndroid Build Coastguard Worker struct manifest *manifest,
1371*8617a60dSAndroid Build Coastguard Worker int is_factory)
1372*8617a60dSAndroid Build Coastguard Worker {
1373*8617a60dSAndroid Build Coastguard Worker int errorcnt = 0;
1374*8617a60dSAndroid Build Coastguard Worker struct u_archive *ar = cfg->archive;
1375*8617a60dSAndroid Build Coastguard Worker const struct model_config *model;
1376*8617a60dSAndroid Build Coastguard Worker
1377*8617a60dSAndroid Build Coastguard Worker if (cfg->detect_model)
1378*8617a60dSAndroid Build Coastguard Worker model = manifest_detect_model_from_frid(cfg, manifest);
1379*8617a60dSAndroid Build Coastguard Worker else
1380*8617a60dSAndroid Build Coastguard Worker model = manifest_find_model(cfg, manifest, arg->model);
1381*8617a60dSAndroid Build Coastguard Worker
1382*8617a60dSAndroid Build Coastguard Worker if (!model)
1383*8617a60dSAndroid Build Coastguard Worker return ++errorcnt;
1384*8617a60dSAndroid Build Coastguard Worker
1385*8617a60dSAndroid Build Coastguard Worker if (arg->detect_model_only) {
1386*8617a60dSAndroid Build Coastguard Worker puts(model->name);
1387*8617a60dSAndroid Build Coastguard Worker /* No additional error. */
1388*8617a60dSAndroid Build Coastguard Worker return errorcnt;
1389*8617a60dSAndroid Build Coastguard Worker }
1390*8617a60dSAndroid Build Coastguard Worker
1391*8617a60dSAndroid Build Coastguard Worker /* Load images now so we can get quirks in custom label checks. */
1392*8617a60dSAndroid Build Coastguard Worker errorcnt += updater_load_images(
1393*8617a60dSAndroid Build Coastguard Worker cfg, arg, model->image, model->ec_image);
1394*8617a60dSAndroid Build Coastguard Worker
1395*8617a60dSAndroid Build Coastguard Worker /*
1396*8617a60dSAndroid Build Coastguard Worker * For custom label devices, we have to read the system firmware
1397*8617a60dSAndroid Build Coastguard Worker * (image_current) to get the tag from VPD. Some quirks may also need
1398*8617a60dSAndroid Build Coastguard Worker * the system firmware to identify if they should override the tags.
1399*8617a60dSAndroid Build Coastguard Worker *
1400*8617a60dSAndroid Build Coastguard Worker * The only exception is `--mode=output` (cfg->output_only), which we
1401*8617a60dSAndroid Build Coastguard Worker * usually add `--model=MODEL` to specify the target model (note some
1402*8617a60dSAndroid Build Coastguard Worker * people may still run without `--model` to get "the image to update
1403*8617a60dSAndroid Build Coastguard Worker * when running on this device"). The MODEL can be either the BASEMODEL
1404*8617a60dSAndroid Build Coastguard Worker * (has_custom_label=true) or BASEMODEL-TAG (has_custom_label=false).
1405*8617a60dSAndroid Build Coastguard Worker * So the only case we have to warn the user that they may forget to
1406*8617a60dSAndroid Build Coastguard Worker * provide the TAG is when has_custom_label=true (only BASEMODEL).
1407*8617a60dSAndroid Build Coastguard Worker */
1408*8617a60dSAndroid Build Coastguard Worker if (cfg->output_only && arg->model && model->has_custom_label) {
1409*8617a60dSAndroid Build Coastguard Worker printf(">> Generating output for a custom label device without tags (e.g., base model). "
1410*8617a60dSAndroid Build Coastguard Worker "The firmware images will be signed using the base model (or DEFAULT) keys. "
1411*8617a60dSAndroid Build Coastguard Worker "To get the images signed by the LOEM keys, "
1412*8617a60dSAndroid Build Coastguard Worker "add the corresponding tag from one of the following list: \n");
1413*8617a60dSAndroid Build Coastguard Worker
1414*8617a60dSAndroid Build Coastguard Worker size_t len = strlen(arg->model);
1415*8617a60dSAndroid Build Coastguard Worker bool printed = false;
1416*8617a60dSAndroid Build Coastguard Worker int i;
1417*8617a60dSAndroid Build Coastguard Worker
1418*8617a60dSAndroid Build Coastguard Worker for (i = 0; i < manifest->num; i++) {
1419*8617a60dSAndroid Build Coastguard Worker const struct model_config *m = &manifest->models[i];
1420*8617a60dSAndroid Build Coastguard Worker if (strncmp(m->name, arg->model, len) || m->name[len] != '-')
1421*8617a60dSAndroid Build Coastguard Worker continue;
1422*8617a60dSAndroid Build Coastguard Worker printf("%s `--model=%s`", printed ? "," : "", m->name);
1423*8617a60dSAndroid Build Coastguard Worker printed = true;
1424*8617a60dSAndroid Build Coastguard Worker }
1425*8617a60dSAndroid Build Coastguard Worker printf("\n\n");
1426*8617a60dSAndroid Build Coastguard Worker } else if (model->has_custom_label) {
1427*8617a60dSAndroid Build Coastguard Worker if (!cfg->image_current.data) {
1428*8617a60dSAndroid Build Coastguard Worker INFO("Loading system firmware for custom label...\n");
1429*8617a60dSAndroid Build Coastguard Worker load_system_firmware(cfg, &cfg->image_current);
1430*8617a60dSAndroid Build Coastguard Worker }
1431*8617a60dSAndroid Build Coastguard Worker
1432*8617a60dSAndroid Build Coastguard Worker if (!cfg->image_current.data) {
1433*8617a60dSAndroid Build Coastguard Worker ERROR("Cannot read the system firmware for tags.\n");
1434*8617a60dSAndroid Build Coastguard Worker return ++errorcnt;
1435*8617a60dSAndroid Build Coastguard Worker }
1436*8617a60dSAndroid Build Coastguard Worker /*
1437*8617a60dSAndroid Build Coastguard Worker * For custom label devices, manifest_find_model may return the
1438*8617a60dSAndroid Build Coastguard Worker * base model instead of the custom label ones so we have to
1439*8617a60dSAndroid Build Coastguard Worker * look up again.
1440*8617a60dSAndroid Build Coastguard Worker */
1441*8617a60dSAndroid Build Coastguard Worker const struct model_config *base_model = model;
1442*8617a60dSAndroid Build Coastguard Worker model = manifest_find_custom_label_model(cfg, manifest, base_model);
1443*8617a60dSAndroid Build Coastguard Worker if (!model)
1444*8617a60dSAndroid Build Coastguard Worker return ++errorcnt;
1445*8617a60dSAndroid Build Coastguard Worker /*
1446*8617a60dSAndroid Build Coastguard Worker * All custom label models should share the same image, so we
1447*8617a60dSAndroid Build Coastguard Worker * don't need to reload again - just pick up the new config and
1448*8617a60dSAndroid Build Coastguard Worker * patch later. We don't care about EC images because that will
1449*8617a60dSAndroid Build Coastguard Worker * be updated by software sync in the end.
1450*8617a60dSAndroid Build Coastguard Worker * Here we want to double check if that assumption is correct.
1451*8617a60dSAndroid Build Coastguard Worker */
1452*8617a60dSAndroid Build Coastguard Worker if (base_model->image) {
1453*8617a60dSAndroid Build Coastguard Worker if (!model->image ||
1454*8617a60dSAndroid Build Coastguard Worker strcmp(base_model->image, model->image)) {
1455*8617a60dSAndroid Build Coastguard Worker ERROR("The firmware image for custom label [%s] "
1456*8617a60dSAndroid Build Coastguard Worker "does not match its base model [%s]\n",
1457*8617a60dSAndroid Build Coastguard Worker base_model->name, model->name);
1458*8617a60dSAndroid Build Coastguard Worker return ++errorcnt;
1459*8617a60dSAndroid Build Coastguard Worker }
1460*8617a60dSAndroid Build Coastguard Worker }
1461*8617a60dSAndroid Build Coastguard Worker }
1462*8617a60dSAndroid Build Coastguard Worker errorcnt += patch_image_by_model(&cfg->image, model, ar);
1463*8617a60dSAndroid Build Coastguard Worker return errorcnt;
1464*8617a60dSAndroid Build Coastguard Worker }
1465*8617a60dSAndroid Build Coastguard Worker
check_arg_compatibility(const struct updater_config_arguments * arg)1466*8617a60dSAndroid Build Coastguard Worker static int check_arg_compatibility(
1467*8617a60dSAndroid Build Coastguard Worker const struct updater_config_arguments *arg)
1468*8617a60dSAndroid Build Coastguard Worker {
1469*8617a60dSAndroid Build Coastguard Worker /*
1470*8617a60dSAndroid Build Coastguard Worker * The following args are mutually exclusive:
1471*8617a60dSAndroid Build Coastguard Worker * - detect_model_only
1472*8617a60dSAndroid Build Coastguard Worker * - do_manifest
1473*8617a60dSAndroid Build Coastguard Worker * - repack
1474*8617a60dSAndroid Build Coastguard Worker * - unpack
1475*8617a60dSAndroid Build Coastguard Worker */
1476*8617a60dSAndroid Build Coastguard Worker if (arg->detect_model_only) {
1477*8617a60dSAndroid Build Coastguard Worker if (arg->do_manifest || arg->repack || arg->unpack) {
1478*8617a60dSAndroid Build Coastguard Worker ERROR("--manifest/--repack/--unpack"
1479*8617a60dSAndroid Build Coastguard Worker " is not compatible with --detect-model-only.\n");
1480*8617a60dSAndroid Build Coastguard Worker return -1;
1481*8617a60dSAndroid Build Coastguard Worker }
1482*8617a60dSAndroid Build Coastguard Worker if (!arg->archive) {
1483*8617a60dSAndroid Build Coastguard Worker ERROR("--detect-model-only needs --archive.\n");
1484*8617a60dSAndroid Build Coastguard Worker return -1;
1485*8617a60dSAndroid Build Coastguard Worker }
1486*8617a60dSAndroid Build Coastguard Worker } else if (arg->do_manifest) {
1487*8617a60dSAndroid Build Coastguard Worker if (arg->repack || arg->unpack) {
1488*8617a60dSAndroid Build Coastguard Worker ERROR("--repack/--unpack"
1489*8617a60dSAndroid Build Coastguard Worker " is not compatible with --manifest.\n");
1490*8617a60dSAndroid Build Coastguard Worker return -1;
1491*8617a60dSAndroid Build Coastguard Worker }
1492*8617a60dSAndroid Build Coastguard Worker if (!arg->archive && !(arg->image || arg->ec_image)) {
1493*8617a60dSAndroid Build Coastguard Worker ERROR("--manifest needs -a, -i or -e.\n");
1494*8617a60dSAndroid Build Coastguard Worker return -1;
1495*8617a60dSAndroid Build Coastguard Worker } else if (arg->archive && (arg->image || arg->ec_image)) {
1496*8617a60dSAndroid Build Coastguard Worker ERROR("--manifest for archive (-a) does not accept"
1497*8617a60dSAndroid Build Coastguard Worker " additional images (--image, --ec_image).\n");
1498*8617a60dSAndroid Build Coastguard Worker return -1;
1499*8617a60dSAndroid Build Coastguard Worker }
1500*8617a60dSAndroid Build Coastguard Worker } else if (arg->repack || arg->unpack) {
1501*8617a60dSAndroid Build Coastguard Worker if (arg->repack && arg->unpack) {
1502*8617a60dSAndroid Build Coastguard Worker ERROR("--unpack is incompatible with --repack.\n");
1503*8617a60dSAndroid Build Coastguard Worker return -1;
1504*8617a60dSAndroid Build Coastguard Worker }
1505*8617a60dSAndroid Build Coastguard Worker if (!arg->archive) {
1506*8617a60dSAndroid Build Coastguard Worker ERROR("--{re,un}pack needs --archive.\n");
1507*8617a60dSAndroid Build Coastguard Worker return -1;
1508*8617a60dSAndroid Build Coastguard Worker }
1509*8617a60dSAndroid Build Coastguard Worker }
1510*8617a60dSAndroid Build Coastguard Worker
1511*8617a60dSAndroid Build Coastguard Worker return 0;
1512*8617a60dSAndroid Build Coastguard Worker }
1513*8617a60dSAndroid Build Coastguard Worker
parse_arg_mode(struct updater_config * cfg,const struct updater_config_arguments * arg)1514*8617a60dSAndroid Build Coastguard Worker static int parse_arg_mode(struct updater_config *cfg,
1515*8617a60dSAndroid Build Coastguard Worker const struct updater_config_arguments *arg)
1516*8617a60dSAndroid Build Coastguard Worker {
1517*8617a60dSAndroid Build Coastguard Worker if (!arg->mode)
1518*8617a60dSAndroid Build Coastguard Worker return 0;
1519*8617a60dSAndroid Build Coastguard Worker
1520*8617a60dSAndroid Build Coastguard Worker if (strcmp(arg->mode, "autoupdate") == 0) {
1521*8617a60dSAndroid Build Coastguard Worker cfg->try_update = TRY_UPDATE_AUTO;
1522*8617a60dSAndroid Build Coastguard Worker } else if (strcmp(arg->mode, "deferupdate_hold") == 0) {
1523*8617a60dSAndroid Build Coastguard Worker cfg->try_update = TRY_UPDATE_DEFERRED_HOLD;
1524*8617a60dSAndroid Build Coastguard Worker } else if (strcmp(arg->mode, "deferupdate_apply") == 0) {
1525*8617a60dSAndroid Build Coastguard Worker cfg->try_update = TRY_UPDATE_DEFERRED_APPLY;
1526*8617a60dSAndroid Build Coastguard Worker } else if (strcmp(arg->mode, "recovery") == 0) {
1527*8617a60dSAndroid Build Coastguard Worker cfg->try_update = TRY_UPDATE_OFF;
1528*8617a60dSAndroid Build Coastguard Worker } else if (strcmp(arg->mode, "legacy") == 0) {
1529*8617a60dSAndroid Build Coastguard Worker cfg->legacy_update = 1;
1530*8617a60dSAndroid Build Coastguard Worker } else if (strcmp(arg->mode, "factory") == 0 ||
1531*8617a60dSAndroid Build Coastguard Worker strcmp(arg->mode, "factory_install") == 0) {
1532*8617a60dSAndroid Build Coastguard Worker cfg->factory_update = 1;
1533*8617a60dSAndroid Build Coastguard Worker } else if (strcmp(arg->mode, "output") == 0) {
1534*8617a60dSAndroid Build Coastguard Worker cfg->output_only = true;
1535*8617a60dSAndroid Build Coastguard Worker } else {
1536*8617a60dSAndroid Build Coastguard Worker ERROR("Invalid mode: %s\n", arg->mode);
1537*8617a60dSAndroid Build Coastguard Worker return -1;
1538*8617a60dSAndroid Build Coastguard Worker }
1539*8617a60dSAndroid Build Coastguard Worker
1540*8617a60dSAndroid Build Coastguard Worker return 0;
1541*8617a60dSAndroid Build Coastguard Worker }
1542*8617a60dSAndroid Build Coastguard Worker
prog_arg_setup(struct updater_config * cfg,const struct updater_config_arguments * arg,bool * check_single_image)1543*8617a60dSAndroid Build Coastguard Worker static void prog_arg_setup(struct updater_config *cfg,
1544*8617a60dSAndroid Build Coastguard Worker const struct updater_config_arguments *arg,
1545*8617a60dSAndroid Build Coastguard Worker bool *check_single_image)
1546*8617a60dSAndroid Build Coastguard Worker {
1547*8617a60dSAndroid Build Coastguard Worker if (!arg->programmer || !strcmp(arg->programmer, cfg->image.programmer))
1548*8617a60dSAndroid Build Coastguard Worker return;
1549*8617a60dSAndroid Build Coastguard Worker
1550*8617a60dSAndroid Build Coastguard Worker *check_single_image = true;
1551*8617a60dSAndroid Build Coastguard Worker /* DUT should be remote if the programmer is changed. */
1552*8617a60dSAndroid Build Coastguard Worker cfg->dut_is_remote = 1;
1553*8617a60dSAndroid Build Coastguard Worker INFO("Configured to update a remote DUT%s.\n",
1554*8617a60dSAndroid Build Coastguard Worker arg->detect_servo ? " via Servo" : "");
1555*8617a60dSAndroid Build Coastguard Worker cfg->image.programmer = arg->programmer;
1556*8617a60dSAndroid Build Coastguard Worker cfg->image_current.programmer = arg->programmer;
1557*8617a60dSAndroid Build Coastguard Worker cfg->original_programmer = arg->programmer;
1558*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("AP (host) programmer changed to %s.\n",
1559*8617a60dSAndroid Build Coastguard Worker arg->programmer);
1560*8617a60dSAndroid Build Coastguard Worker
1561*8617a60dSAndroid Build Coastguard Worker if (arg->archive && !arg->model)
1562*8617a60dSAndroid Build Coastguard Worker cfg->detect_model = true;
1563*8617a60dSAndroid Build Coastguard Worker }
1564*8617a60dSAndroid Build Coastguard Worker
prog_arg_emulation(struct updater_config * cfg,const struct updater_config_arguments * arg,bool * check_single_image)1565*8617a60dSAndroid Build Coastguard Worker static int prog_arg_emulation(struct updater_config *cfg,
1566*8617a60dSAndroid Build Coastguard Worker const struct updater_config_arguments *arg,
1567*8617a60dSAndroid Build Coastguard Worker bool *check_single_image)
1568*8617a60dSAndroid Build Coastguard Worker {
1569*8617a60dSAndroid Build Coastguard Worker if (!arg->emulation)
1570*8617a60dSAndroid Build Coastguard Worker return 0;
1571*8617a60dSAndroid Build Coastguard Worker
1572*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Using file %s for emulation.\n", arg->emulation);
1573*8617a60dSAndroid Build Coastguard Worker *check_single_image = true;
1574*8617a60dSAndroid Build Coastguard Worker struct stat statbuf;
1575*8617a60dSAndroid Build Coastguard Worker if (stat(arg->emulation, &statbuf)) {
1576*8617a60dSAndroid Build Coastguard Worker ERROR("Failed to stat emulation file %s\n",
1577*8617a60dSAndroid Build Coastguard Worker arg->emulation);
1578*8617a60dSAndroid Build Coastguard Worker return -1;
1579*8617a60dSAndroid Build Coastguard Worker }
1580*8617a60dSAndroid Build Coastguard Worker
1581*8617a60dSAndroid Build Coastguard Worker cfg->emulation = arg->emulation;
1582*8617a60dSAndroid Build Coastguard Worker /* Store ownership of the dummy programmer string in
1583*8617a60dSAndroid Build Coastguard Worker cfg->emulation_programmer. */
1584*8617a60dSAndroid Build Coastguard Worker ASPRINTF(&cfg->emulation_programmer,
1585*8617a60dSAndroid Build Coastguard Worker "dummy:emulate=VARIABLE_SIZE,size=%d,image=%s,bus=prog",
1586*8617a60dSAndroid Build Coastguard Worker (int)statbuf.st_size, arg->emulation);
1587*8617a60dSAndroid Build Coastguard Worker
1588*8617a60dSAndroid Build Coastguard Worker cfg->image.programmer = cfg->emulation_programmer;
1589*8617a60dSAndroid Build Coastguard Worker cfg->image_current.programmer = cfg->emulation_programmer;
1590*8617a60dSAndroid Build Coastguard Worker
1591*8617a60dSAndroid Build Coastguard Worker return 0;
1592*8617a60dSAndroid Build Coastguard Worker }
1593*8617a60dSAndroid Build Coastguard Worker
updater_should_update(const struct updater_config_arguments * arg)1594*8617a60dSAndroid Build Coastguard Worker bool updater_should_update(const struct updater_config_arguments *arg)
1595*8617a60dSAndroid Build Coastguard Worker {
1596*8617a60dSAndroid Build Coastguard Worker const bool do_output = arg->mode && !strcmp(arg->mode, "output");
1597*8617a60dSAndroid Build Coastguard Worker if (arg->detect_model_only || arg->do_manifest
1598*8617a60dSAndroid Build Coastguard Worker || arg->repack || arg->unpack || do_output) {
1599*8617a60dSAndroid Build Coastguard Worker return false;
1600*8617a60dSAndroid Build Coastguard Worker }
1601*8617a60dSAndroid Build Coastguard Worker return true;
1602*8617a60dSAndroid Build Coastguard Worker }
1603*8617a60dSAndroid Build Coastguard Worker
1604*8617a60dSAndroid Build Coastguard Worker /*
1605*8617a60dSAndroid Build Coastguard Worker * Prints manifest.
1606*8617a60dSAndroid Build Coastguard Worker *
1607*8617a60dSAndroid Build Coastguard Worker * Returns number of errors on failure, or zero on success.
1608*8617a60dSAndroid Build Coastguard Worker */
print_manifest(const struct updater_config_arguments * arg)1609*8617a60dSAndroid Build Coastguard Worker static int print_manifest(const struct updater_config_arguments *arg)
1610*8617a60dSAndroid Build Coastguard Worker {
1611*8617a60dSAndroid Build Coastguard Worker assert(arg->do_manifest);
1612*8617a60dSAndroid Build Coastguard Worker
1613*8617a60dSAndroid Build Coastguard Worker if (!arg->archive) {
1614*8617a60dSAndroid Build Coastguard Worker char name[] = "default";
1615*8617a60dSAndroid Build Coastguard Worker struct model_config model = {
1616*8617a60dSAndroid Build Coastguard Worker .name = name,
1617*8617a60dSAndroid Build Coastguard Worker .image = arg->image,
1618*8617a60dSAndroid Build Coastguard Worker .ec_image = arg->ec_image,
1619*8617a60dSAndroid Build Coastguard Worker };
1620*8617a60dSAndroid Build Coastguard Worker struct manifest manifest = {
1621*8617a60dSAndroid Build Coastguard Worker .num = 1,
1622*8617a60dSAndroid Build Coastguard Worker .models = &model,
1623*8617a60dSAndroid Build Coastguard Worker };
1624*8617a60dSAndroid Build Coastguard Worker print_json_manifest(&manifest);
1625*8617a60dSAndroid Build Coastguard Worker return 0;
1626*8617a60dSAndroid Build Coastguard Worker }
1627*8617a60dSAndroid Build Coastguard Worker
1628*8617a60dSAndroid Build Coastguard Worker struct u_archive *archive = archive_open(arg->archive);
1629*8617a60dSAndroid Build Coastguard Worker if (!archive) {
1630*8617a60dSAndroid Build Coastguard Worker ERROR("Failed to open archive: %s\n", arg->archive);
1631*8617a60dSAndroid Build Coastguard Worker return 1;
1632*8617a60dSAndroid Build Coastguard Worker }
1633*8617a60dSAndroid Build Coastguard Worker
1634*8617a60dSAndroid Build Coastguard Worker if (arg->fast_update) {
1635*8617a60dSAndroid Build Coastguard Worker /* Quickly load and dump the manifest file from the archive. */
1636*8617a60dSAndroid Build Coastguard Worker const char *manifest_name = "manifest.json";
1637*8617a60dSAndroid Build Coastguard Worker uint8_t *data = NULL;
1638*8617a60dSAndroid Build Coastguard Worker uint32_t size = 0;
1639*8617a60dSAndroid Build Coastguard Worker
1640*8617a60dSAndroid Build Coastguard Worker if (!archive_has_entry(archive, manifest_name) ||
1641*8617a60dSAndroid Build Coastguard Worker archive_read_file(archive, manifest_name, &data, &size,
1642*8617a60dSAndroid Build Coastguard Worker NULL)) {
1643*8617a60dSAndroid Build Coastguard Worker ERROR("Failed to read the cached manifest: %s\n",
1644*8617a60dSAndroid Build Coastguard Worker manifest_name);
1645*8617a60dSAndroid Build Coastguard Worker return 1;
1646*8617a60dSAndroid Build Coastguard Worker }
1647*8617a60dSAndroid Build Coastguard Worker /* data is NUL-terminated. */
1648*8617a60dSAndroid Build Coastguard Worker printf("%s\n", data);
1649*8617a60dSAndroid Build Coastguard Worker free(data);
1650*8617a60dSAndroid Build Coastguard Worker } else {
1651*8617a60dSAndroid Build Coastguard Worker struct manifest *manifest =
1652*8617a60dSAndroid Build Coastguard Worker new_manifest_from_archive(archive);
1653*8617a60dSAndroid Build Coastguard Worker if (!manifest) {
1654*8617a60dSAndroid Build Coastguard Worker ERROR("Failed to read manifest from archive: %s\n",
1655*8617a60dSAndroid Build Coastguard Worker arg->archive);
1656*8617a60dSAndroid Build Coastguard Worker return 1;
1657*8617a60dSAndroid Build Coastguard Worker }
1658*8617a60dSAndroid Build Coastguard Worker print_json_manifest(manifest);
1659*8617a60dSAndroid Build Coastguard Worker delete_manifest(manifest);
1660*8617a60dSAndroid Build Coastguard Worker }
1661*8617a60dSAndroid Build Coastguard Worker
1662*8617a60dSAndroid Build Coastguard Worker return 0;
1663*8617a60dSAndroid Build Coastguard Worker }
1664*8617a60dSAndroid Build Coastguard Worker
updater_setup_config(struct updater_config * cfg,const struct updater_config_arguments * arg)1665*8617a60dSAndroid Build Coastguard Worker int updater_setup_config(struct updater_config *cfg,
1666*8617a60dSAndroid Build Coastguard Worker const struct updater_config_arguments *arg)
1667*8617a60dSAndroid Build Coastguard Worker {
1668*8617a60dSAndroid Build Coastguard Worker int errorcnt = 0;
1669*8617a60dSAndroid Build Coastguard Worker int check_wp_disabled = 0;
1670*8617a60dSAndroid Build Coastguard Worker bool check_single_image = false;
1671*8617a60dSAndroid Build Coastguard Worker const char *archive_path = arg->archive;
1672*8617a60dSAndroid Build Coastguard Worker
1673*8617a60dSAndroid Build Coastguard Worker /* Setup values that may change output or decision of other argument. */
1674*8617a60dSAndroid Build Coastguard Worker cfg->verbosity = arg->verbosity;
1675*8617a60dSAndroid Build Coastguard Worker cfg->use_diff_image = arg->fast_update;
1676*8617a60dSAndroid Build Coastguard Worker cfg->do_verify = !arg->fast_update;
1677*8617a60dSAndroid Build Coastguard Worker cfg->factory_update = arg->is_factory;
1678*8617a60dSAndroid Build Coastguard Worker if (arg->force_update)
1679*8617a60dSAndroid Build Coastguard Worker cfg->force_update = 1;
1680*8617a60dSAndroid Build Coastguard Worker
1681*8617a60dSAndroid Build Coastguard Worker /* Check incompatible options and return early. */
1682*8617a60dSAndroid Build Coastguard Worker if (check_arg_compatibility(arg) < 0)
1683*8617a60dSAndroid Build Coastguard Worker return 1;
1684*8617a60dSAndroid Build Coastguard Worker
1685*8617a60dSAndroid Build Coastguard Worker if (arg->detect_model_only) {
1686*8617a60dSAndroid Build Coastguard Worker cfg->detect_model = true;
1687*8617a60dSAndroid Build Coastguard Worker }
1688*8617a60dSAndroid Build Coastguard Worker
1689*8617a60dSAndroid Build Coastguard Worker /* Setup update mode. */
1690*8617a60dSAndroid Build Coastguard Worker if (arg->try_update)
1691*8617a60dSAndroid Build Coastguard Worker cfg->try_update = TRY_UPDATE_AUTO;
1692*8617a60dSAndroid Build Coastguard Worker
1693*8617a60dSAndroid Build Coastguard Worker if (parse_arg_mode(cfg, arg) < 0)
1694*8617a60dSAndroid Build Coastguard Worker return 1;
1695*8617a60dSAndroid Build Coastguard Worker
1696*8617a60dSAndroid Build Coastguard Worker if (cfg->factory_update) {
1697*8617a60dSAndroid Build Coastguard Worker /* factory_update must be processed after arg->mode. */
1698*8617a60dSAndroid Build Coastguard Worker check_wp_disabled = 1;
1699*8617a60dSAndroid Build Coastguard Worker cfg->try_update = TRY_UPDATE_OFF;
1700*8617a60dSAndroid Build Coastguard Worker }
1701*8617a60dSAndroid Build Coastguard Worker cfg->gbb_flags = arg->gbb_flags;
1702*8617a60dSAndroid Build Coastguard Worker cfg->override_gbb_flags = arg->override_gbb_flags;
1703*8617a60dSAndroid Build Coastguard Worker
1704*8617a60dSAndroid Build Coastguard Worker /* Setup properties and fields that do not have external dependency. */
1705*8617a60dSAndroid Build Coastguard Worker prog_arg_setup(cfg, arg, &check_single_image);
1706*8617a60dSAndroid Build Coastguard Worker if (prog_arg_emulation(cfg, arg, &check_single_image) < 0)
1707*8617a60dSAndroid Build Coastguard Worker return 1;
1708*8617a60dSAndroid Build Coastguard Worker
1709*8617a60dSAndroid Build Coastguard Worker if (arg->emulation)
1710*8617a60dSAndroid Build Coastguard Worker override_properties_with_default(cfg);
1711*8617a60dSAndroid Build Coastguard Worker if (arg->sys_props)
1712*8617a60dSAndroid Build Coastguard Worker override_properties_from_list(arg->sys_props, cfg);
1713*8617a60dSAndroid Build Coastguard Worker if (arg->write_protection) {
1714*8617a60dSAndroid Build Coastguard Worker /* arg->write_protection must be done after arg->sys_props. */
1715*8617a60dSAndroid Build Coastguard Worker int r = strtol(arg->write_protection, NULL, 0);
1716*8617a60dSAndroid Build Coastguard Worker override_dut_property(DUT_PROP_WP_HW, cfg, r);
1717*8617a60dSAndroid Build Coastguard Worker override_dut_property(DUT_PROP_WP_SW_AP, cfg, r);
1718*8617a60dSAndroid Build Coastguard Worker }
1719*8617a60dSAndroid Build Coastguard Worker
1720*8617a60dSAndroid Build Coastguard Worker /* Process the manifest. */
1721*8617a60dSAndroid Build Coastguard Worker if (arg->do_manifest) {
1722*8617a60dSAndroid Build Coastguard Worker errorcnt += print_manifest(arg);
1723*8617a60dSAndroid Build Coastguard Worker return errorcnt;
1724*8617a60dSAndroid Build Coastguard Worker }
1725*8617a60dSAndroid Build Coastguard Worker
1726*8617a60dSAndroid Build Coastguard Worker /* Always load images specified from command line directly. */
1727*8617a60dSAndroid Build Coastguard Worker errorcnt += updater_load_images(
1728*8617a60dSAndroid Build Coastguard Worker cfg, arg, arg->image, arg->ec_image);
1729*8617a60dSAndroid Build Coastguard Worker
1730*8617a60dSAndroid Build Coastguard Worker /* Set up archive. */
1731*8617a60dSAndroid Build Coastguard Worker if (!archive_path)
1732*8617a60dSAndroid Build Coastguard Worker archive_path = ".";
1733*8617a60dSAndroid Build Coastguard Worker cfg->archive = archive_open(archive_path);
1734*8617a60dSAndroid Build Coastguard Worker if (!cfg->archive) {
1735*8617a60dSAndroid Build Coastguard Worker ERROR("Failed to open archive: %s\n", archive_path);
1736*8617a60dSAndroid Build Coastguard Worker return ++errorcnt;
1737*8617a60dSAndroid Build Coastguard Worker }
1738*8617a60dSAndroid Build Coastguard Worker
1739*8617a60dSAndroid Build Coastguard Worker /* Process archives which may not have valid contents. */
1740*8617a60dSAndroid Build Coastguard Worker if (arg->repack || arg->unpack) {
1741*8617a60dSAndroid Build Coastguard Worker const char *work_name = arg->repack ? arg->repack : arg->unpack;
1742*8617a60dSAndroid Build Coastguard Worker struct u_archive *from, *to, *work;
1743*8617a60dSAndroid Build Coastguard Worker
1744*8617a60dSAndroid Build Coastguard Worker work = archive_open(work_name);
1745*8617a60dSAndroid Build Coastguard Worker if (arg->repack) {
1746*8617a60dSAndroid Build Coastguard Worker from = work;
1747*8617a60dSAndroid Build Coastguard Worker to = cfg->archive;
1748*8617a60dSAndroid Build Coastguard Worker } else {
1749*8617a60dSAndroid Build Coastguard Worker to = work;
1750*8617a60dSAndroid Build Coastguard Worker from = cfg->archive;
1751*8617a60dSAndroid Build Coastguard Worker }
1752*8617a60dSAndroid Build Coastguard Worker if (!work) {
1753*8617a60dSAndroid Build Coastguard Worker ERROR("Failed to open: %s\n", work_name);
1754*8617a60dSAndroid Build Coastguard Worker return ++errorcnt;
1755*8617a60dSAndroid Build Coastguard Worker }
1756*8617a60dSAndroid Build Coastguard Worker errorcnt += !!archive_copy(from, to);
1757*8617a60dSAndroid Build Coastguard Worker /* TODO(hungte) Update manifest after copied. */
1758*8617a60dSAndroid Build Coastguard Worker archive_close(work);
1759*8617a60dSAndroid Build Coastguard Worker return errorcnt;
1760*8617a60dSAndroid Build Coastguard Worker }
1761*8617a60dSAndroid Build Coastguard Worker
1762*8617a60dSAndroid Build Coastguard Worker /* Load images from the archive. */
1763*8617a60dSAndroid Build Coastguard Worker if (arg->archive) {
1764*8617a60dSAndroid Build Coastguard Worker struct manifest *m = new_manifest_from_archive(cfg->archive);
1765*8617a60dSAndroid Build Coastguard Worker if (m) {
1766*8617a60dSAndroid Build Coastguard Worker errorcnt += updater_setup_archive(
1767*8617a60dSAndroid Build Coastguard Worker cfg, arg, m, cfg->factory_update);
1768*8617a60dSAndroid Build Coastguard Worker delete_manifest(m);
1769*8617a60dSAndroid Build Coastguard Worker } else {
1770*8617a60dSAndroid Build Coastguard Worker ERROR("Failure in archive: %s\n", arg->archive);
1771*8617a60dSAndroid Build Coastguard Worker ++errorcnt;
1772*8617a60dSAndroid Build Coastguard Worker }
1773*8617a60dSAndroid Build Coastguard Worker }
1774*8617a60dSAndroid Build Coastguard Worker
1775*8617a60dSAndroid Build Coastguard Worker /*
1776*8617a60dSAndroid Build Coastguard Worker * Images should be loaded now (either in first updater_load_images or
1777*8617a60dSAndroid Build Coastguard Worker * second call from updater_setup_archive) and quirks should be loaded.
1778*8617a60dSAndroid Build Coastguard Worker * For invocation without image, we want to get quirks now.
1779*8617a60dSAndroid Build Coastguard Worker */
1780*8617a60dSAndroid Build Coastguard Worker if (!cfg->image.data && arg->quirks)
1781*8617a60dSAndroid Build Coastguard Worker errorcnt += !!setup_config_quirks(arg->quirks, cfg);
1782*8617a60dSAndroid Build Coastguard Worker
1783*8617a60dSAndroid Build Coastguard Worker /* Additional checks. */
1784*8617a60dSAndroid Build Coastguard Worker if (check_single_image && !cfg->output_only && cfg->ec_image.data) {
1785*8617a60dSAndroid Build Coastguard Worker errorcnt++;
1786*8617a60dSAndroid Build Coastguard Worker ERROR("EC/PD images are not supported in current mode.\n");
1787*8617a60dSAndroid Build Coastguard Worker }
1788*8617a60dSAndroid Build Coastguard Worker if (check_wp_disabled && is_ap_write_protection_enabled(cfg)) {
1789*8617a60dSAndroid Build Coastguard Worker errorcnt++;
1790*8617a60dSAndroid Build Coastguard Worker ERROR("Please remove write protection for factory mode \n"
1791*8617a60dSAndroid Build Coastguard Worker "( " REMOVE_WP_URL " ).");
1792*8617a60dSAndroid Build Coastguard Worker }
1793*8617a60dSAndroid Build Coastguard Worker
1794*8617a60dSAndroid Build Coastguard Worker if (cfg->image.data) {
1795*8617a60dSAndroid Build Coastguard Worker /* Apply any quirks to modify the image before updating. */
1796*8617a60dSAndroid Build Coastguard Worker if (arg->unlock_me)
1797*8617a60dSAndroid Build Coastguard Worker cfg->quirks[QUIRK_UNLOCK_CSME].value = 1;
1798*8617a60dSAndroid Build Coastguard Worker errorcnt += try_apply_quirk(QUIRK_UNLOCK_CSME_EVE, cfg);
1799*8617a60dSAndroid Build Coastguard Worker errorcnt += try_apply_quirk(QUIRK_UNLOCK_CSME, cfg);
1800*8617a60dSAndroid Build Coastguard Worker }
1801*8617a60dSAndroid Build Coastguard Worker
1802*8617a60dSAndroid Build Coastguard Worker /* The images are ready for updating. Output if needed. */
1803*8617a60dSAndroid Build Coastguard Worker if (!errorcnt && cfg->output_only) {
1804*8617a60dSAndroid Build Coastguard Worker const char *r = arg->output_dir;
1805*8617a60dSAndroid Build Coastguard Worker if (!r)
1806*8617a60dSAndroid Build Coastguard Worker r = ".";
1807*8617a60dSAndroid Build Coastguard Worker
1808*8617a60dSAndroid Build Coastguard Worker /* TODO(hungte) Remove bios.bin when migration is done. */
1809*8617a60dSAndroid Build Coastguard Worker errorcnt += updater_output_image(&cfg->image, "bios.bin", r);
1810*8617a60dSAndroid Build Coastguard Worker errorcnt += updater_output_image(&cfg->image, "image.bin", r);
1811*8617a60dSAndroid Build Coastguard Worker errorcnt += updater_output_image(&cfg->ec_image, "ec.bin", r);
1812*8617a60dSAndroid Build Coastguard Worker }
1813*8617a60dSAndroid Build Coastguard Worker return errorcnt;
1814*8617a60dSAndroid Build Coastguard Worker }
1815*8617a60dSAndroid Build Coastguard Worker
1816*8617a60dSAndroid Build Coastguard Worker /* Enough to hold standard CCD programmer options plus serial number */
1817*8617a60dSAndroid Build Coastguard Worker static char ccd_programmer[128];
1818*8617a60dSAndroid Build Coastguard Worker
handle_flash_argument(struct updater_config_arguments * args,int opt,char * optarg)1819*8617a60dSAndroid Build Coastguard Worker int handle_flash_argument(struct updater_config_arguments *args, int opt,
1820*8617a60dSAndroid Build Coastguard Worker char *optarg)
1821*8617a60dSAndroid Build Coastguard Worker {
1822*8617a60dSAndroid Build Coastguard Worker int ret;
1823*8617a60dSAndroid Build Coastguard Worker switch (opt) {
1824*8617a60dSAndroid Build Coastguard Worker case 'p':
1825*8617a60dSAndroid Build Coastguard Worker args->use_flash = 1;
1826*8617a60dSAndroid Build Coastguard Worker args->programmer = optarg;
1827*8617a60dSAndroid Build Coastguard Worker break;
1828*8617a60dSAndroid Build Coastguard Worker case OPT_CCD:
1829*8617a60dSAndroid Build Coastguard Worker args->use_flash = 1;
1830*8617a60dSAndroid Build Coastguard Worker args->fast_update = 1;
1831*8617a60dSAndroid Build Coastguard Worker args->force_update = 1;
1832*8617a60dSAndroid Build Coastguard Worker args->write_protection = "0";
1833*8617a60dSAndroid Build Coastguard Worker ret = snprintf(ccd_programmer, sizeof(ccd_programmer),
1834*8617a60dSAndroid Build Coastguard Worker "raiden_debug_spi:target=AP%s%s",
1835*8617a60dSAndroid Build Coastguard Worker optarg ? ",serial=" : "", optarg ?: "");
1836*8617a60dSAndroid Build Coastguard Worker if (ret >= sizeof(ccd_programmer)) {
1837*8617a60dSAndroid Build Coastguard Worker ERROR("%s: CCD serial number was too long\n", __func__);
1838*8617a60dSAndroid Build Coastguard Worker return 0;
1839*8617a60dSAndroid Build Coastguard Worker }
1840*8617a60dSAndroid Build Coastguard Worker args->programmer = ccd_programmer;
1841*8617a60dSAndroid Build Coastguard Worker break;
1842*8617a60dSAndroid Build Coastguard Worker case OPT_EMULATE:
1843*8617a60dSAndroid Build Coastguard Worker args->use_flash = 1;
1844*8617a60dSAndroid Build Coastguard Worker args->emulation = optarg;
1845*8617a60dSAndroid Build Coastguard Worker break;
1846*8617a60dSAndroid Build Coastguard Worker case OPT_SERVO:
1847*8617a60dSAndroid Build Coastguard Worker args->use_flash = 1;
1848*8617a60dSAndroid Build Coastguard Worker args->detect_servo = 1;
1849*8617a60dSAndroid Build Coastguard Worker args->fast_update = 1;
1850*8617a60dSAndroid Build Coastguard Worker args->force_update = 1;
1851*8617a60dSAndroid Build Coastguard Worker args->write_protection = "0";
1852*8617a60dSAndroid Build Coastguard Worker args->host_only = 1;
1853*8617a60dSAndroid Build Coastguard Worker break;
1854*8617a60dSAndroid Build Coastguard Worker case OPT_SERVO_PORT:
1855*8617a60dSAndroid Build Coastguard Worker setenv(ENV_SERVOD_PORT, optarg, 1);
1856*8617a60dSAndroid Build Coastguard Worker args->use_flash = 1;
1857*8617a60dSAndroid Build Coastguard Worker args->detect_servo = 1;
1858*8617a60dSAndroid Build Coastguard Worker args->fast_update = 1;
1859*8617a60dSAndroid Build Coastguard Worker args->force_update = 1;
1860*8617a60dSAndroid Build Coastguard Worker args->write_protection = "0";
1861*8617a60dSAndroid Build Coastguard Worker args->host_only = 1;
1862*8617a60dSAndroid Build Coastguard Worker break;
1863*8617a60dSAndroid Build Coastguard Worker default:
1864*8617a60dSAndroid Build Coastguard Worker return 0;
1865*8617a60dSAndroid Build Coastguard Worker }
1866*8617a60dSAndroid Build Coastguard Worker return 1;
1867*8617a60dSAndroid Build Coastguard Worker }
1868*8617a60dSAndroid Build Coastguard Worker
updater_delete_config(struct updater_config * cfg)1869*8617a60dSAndroid Build Coastguard Worker void updater_delete_config(struct updater_config *cfg)
1870*8617a60dSAndroid Build Coastguard Worker {
1871*8617a60dSAndroid Build Coastguard Worker assert(cfg);
1872*8617a60dSAndroid Build Coastguard Worker free_firmware_image(&cfg->image);
1873*8617a60dSAndroid Build Coastguard Worker free_firmware_image(&cfg->image_current);
1874*8617a60dSAndroid Build Coastguard Worker free_firmware_image(&cfg->ec_image);
1875*8617a60dSAndroid Build Coastguard Worker cfg->image.programmer = cfg->original_programmer;
1876*8617a60dSAndroid Build Coastguard Worker cfg->image_current.programmer = cfg->original_programmer;
1877*8617a60dSAndroid Build Coastguard Worker free(cfg->emulation_programmer);
1878*8617a60dSAndroid Build Coastguard Worker remove_all_temp_files(&cfg->tempfiles);
1879*8617a60dSAndroid Build Coastguard Worker if (cfg->archive)
1880*8617a60dSAndroid Build Coastguard Worker archive_close(cfg->archive);
1881*8617a60dSAndroid Build Coastguard Worker free(cfg);
1882*8617a60dSAndroid Build Coastguard Worker }
1883