1*8617a60dSAndroid Build Coastguard Worker /* Copyright 2022 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 * Build up the list of updater resources from an archive.
6*8617a60dSAndroid Build Coastguard Worker */
7*8617a60dSAndroid Build Coastguard Worker
8*8617a60dSAndroid Build Coastguard Worker #include <assert.h>
9*8617a60dSAndroid Build Coastguard Worker #if defined(__OpenBSD__)
10*8617a60dSAndroid Build Coastguard Worker #include <sys/types.h>
11*8617a60dSAndroid Build Coastguard Worker #endif
12*8617a60dSAndroid Build Coastguard Worker
13*8617a60dSAndroid Build Coastguard Worker #include "updater.h"
14*8617a60dSAndroid Build Coastguard Worker #include "util_misc.h"
15*8617a60dSAndroid Build Coastguard Worker
16*8617a60dSAndroid Build Coastguard Worker /*
17*8617a60dSAndroid Build Coastguard Worker * The updater reads image files from a package. The package is usually an
18*8617a60dSAndroid Build Coastguard Worker * archive (see updater_archive.c) with image files and configuration files, and
19*8617a60dSAndroid Build Coastguard Worker * the meta data is maintained by a "manifest" that described below.
20*8617a60dSAndroid Build Coastguard Worker *
21*8617a60dSAndroid Build Coastguard Worker * A package for a single board (i.e., not Unified Build) will have all the
22*8617a60dSAndroid Build Coastguard Worker * image files in the top folder:
23*8617a60dSAndroid Build Coastguard Worker * - host: 'image.bin'
24*8617a60dSAndroid Build Coastguard Worker * - ec: 'ec.bin'
25*8617a60dSAndroid Build Coastguard Worker *
26*8617a60dSAndroid Build Coastguard Worker * A package for Unified Build is more complicated.
27*8617a60dSAndroid Build Coastguard Worker *
28*8617a60dSAndroid Build Coastguard Worker * You need to look at the signer_config.csv file to find the columns of
29*8617a60dSAndroid Build Coastguard Worker * model_name, image files (firmware_image, ec_image) and then search for
30*8617a60dSAndroid Build Coastguard Worker * patch files (root key, vblock files, GSC verification data, ...) in the
31*8617a60dSAndroid Build Coastguard Worker * keyset/ folder:
32*8617a60dSAndroid Build Coastguard Worker *
33*8617a60dSAndroid Build Coastguard Worker * - rootkey.$MODEL_NAME
34*8617a60dSAndroid Build Coastguard Worker * - vblock_A.$MODEL_NAME
35*8617a60dSAndroid Build Coastguard Worker * - vblock_B.$MODEL_NAME
36*8617a60dSAndroid Build Coastguard Worker * - gscvd.$MODEL_NAME
37*8617a60dSAndroid Build Coastguard Worker *
38*8617a60dSAndroid Build Coastguard Worker * In the runtime, the updater should query for firmware manifest key (
39*8617a60dSAndroid Build Coastguard Worker * `crosid -f FIRMWARE_MANIFEST_KEY`) and use that to match the 'model_name'
40*8617a60dSAndroid Build Coastguard Worker * in the manifest database.
41*8617a60dSAndroid Build Coastguard Worker *
42*8617a60dSAndroid Build Coastguard Worker * If the model_name in `signer_config.csv` contains '-' then it is a custom
43*8617a60dSAndroid Build Coastguard Worker * label device. Today the FIRMWARE_MANIFEST_KEY from crosid won't handle custom
44*8617a60dSAndroid Build Coastguard Worker * label information and we have to add the custom label tag in the matching
45*8617a60dSAndroid Build Coastguard Worker * process.
46*8617a60dSAndroid Build Coastguard Worker *
47*8617a60dSAndroid Build Coastguard Worker * To do that, find the custom label tag from the VPD.
48*8617a60dSAndroid Build Coastguard Worker * - Newer devices: model_name = FIRMWARE_MANIFEST_KEY-$custom_label_tag
49*8617a60dSAndroid Build Coastguard Worker * - Old devices: model_name = FIRMWARE_MANIFEST_KEY-$whitelabel_tag
50*8617a60dSAndroid Build Coastguard Worker *
51*8617a60dSAndroid Build Coastguard Worker * For legacy devices manufactured before Unified Build, they have the VPD
52*8617a60dSAndroid Build Coastguard Worker * 'customization_id' in a special format: LOEM[-VARIANT].
53*8617a60dSAndroid Build Coastguard Worker * For example: "A-B" => LOEM="A".
54*8617a60dSAndroid Build Coastguard Worker * - Legacy devices: model_name = FIRMWARE_MANIFEST_KEY-$LOEM
55*8617a60dSAndroid Build Coastguard Worker */
56*8617a60dSAndroid Build Coastguard Worker
57*8617a60dSAndroid Build Coastguard Worker static const char * const DEFAULT_MODEL_NAME = "default",
58*8617a60dSAndroid Build Coastguard Worker * const VPD_CUSTOM_LABEL_TAG = "custom_label_tag",
59*8617a60dSAndroid Build Coastguard Worker * const VPD_CUSTOM_LABEL_TAG_LEGACY = "whitelabel_tag",
60*8617a60dSAndroid Build Coastguard Worker * const VPD_CUSTOMIZATION_ID = "customization_id",
61*8617a60dSAndroid Build Coastguard Worker * const PATH_KEYSET_FOLDER = "keyset/",
62*8617a60dSAndroid Build Coastguard Worker * const PATH_SIGNER_CONFIG = "signer_config.csv";
63*8617a60dSAndroid Build Coastguard Worker
64*8617a60dSAndroid Build Coastguard Worker /* Utility function to convert a string. */
str_convert(char * s,int (* convert)(int c))65*8617a60dSAndroid Build Coastguard Worker static void str_convert(char *s, int (*convert)(int c))
66*8617a60dSAndroid Build Coastguard Worker {
67*8617a60dSAndroid Build Coastguard Worker int c;
68*8617a60dSAndroid Build Coastguard Worker
69*8617a60dSAndroid Build Coastguard Worker for (; *s; s++) {
70*8617a60dSAndroid Build Coastguard Worker c = *s;
71*8617a60dSAndroid Build Coastguard Worker if (!isascii(c))
72*8617a60dSAndroid Build Coastguard Worker continue;
73*8617a60dSAndroid Build Coastguard Worker *s = convert(c);
74*8617a60dSAndroid Build Coastguard Worker }
75*8617a60dSAndroid Build Coastguard Worker }
76*8617a60dSAndroid Build Coastguard Worker
77*8617a60dSAndroid Build Coastguard Worker /* Returns the VPD value by given key name, or NULL on error (or no value). */
vpd_get_value(const char * fpath,const char * key)78*8617a60dSAndroid Build Coastguard Worker static char *vpd_get_value(const char *fpath, const char *key)
79*8617a60dSAndroid Build Coastguard Worker {
80*8617a60dSAndroid Build Coastguard Worker char *command, *result;
81*8617a60dSAndroid Build Coastguard Worker
82*8617a60dSAndroid Build Coastguard Worker assert(fpath);
83*8617a60dSAndroid Build Coastguard Worker ASPRINTF(&command, "vpd -g %s -f %s 2>/dev/null", key, fpath);
84*8617a60dSAndroid Build Coastguard Worker result = host_shell(command);
85*8617a60dSAndroid Build Coastguard Worker free(command);
86*8617a60dSAndroid Build Coastguard Worker
87*8617a60dSAndroid Build Coastguard Worker if (result && !*result) {
88*8617a60dSAndroid Build Coastguard Worker free(result);
89*8617a60dSAndroid Build Coastguard Worker result = NULL;
90*8617a60dSAndroid Build Coastguard Worker }
91*8617a60dSAndroid Build Coastguard Worker return result;
92*8617a60dSAndroid Build Coastguard Worker }
93*8617a60dSAndroid Build Coastguard Worker
94*8617a60dSAndroid Build Coastguard Worker /*
95*8617a60dSAndroid Build Coastguard Worker * Changes the rootkey in firmware GBB to given new key.
96*8617a60dSAndroid Build Coastguard Worker * Returns 0 on success, otherwise failure.
97*8617a60dSAndroid Build Coastguard Worker */
change_gbb_rootkey(struct firmware_image * image,const char * section_name,const uint8_t * rootkey,uint32_t rootkey_len)98*8617a60dSAndroid Build Coastguard Worker static int change_gbb_rootkey(struct firmware_image *image,
99*8617a60dSAndroid Build Coastguard Worker const char *section_name,
100*8617a60dSAndroid Build Coastguard Worker const uint8_t *rootkey, uint32_t rootkey_len)
101*8617a60dSAndroid Build Coastguard Worker {
102*8617a60dSAndroid Build Coastguard Worker const struct vb2_gbb_header *gbb = find_gbb(image);
103*8617a60dSAndroid Build Coastguard Worker uint8_t *gbb_rootkey;
104*8617a60dSAndroid Build Coastguard Worker if (!gbb) {
105*8617a60dSAndroid Build Coastguard Worker ERROR("Cannot find GBB in image %s.\n", image->file_name);
106*8617a60dSAndroid Build Coastguard Worker return -1;
107*8617a60dSAndroid Build Coastguard Worker }
108*8617a60dSAndroid Build Coastguard Worker if (gbb->rootkey_size < rootkey_len) {
109*8617a60dSAndroid Build Coastguard Worker ERROR("New root key (%u bytes) larger than GBB (%u bytes).\n",
110*8617a60dSAndroid Build Coastguard Worker rootkey_len, gbb->rootkey_size);
111*8617a60dSAndroid Build Coastguard Worker return -1;
112*8617a60dSAndroid Build Coastguard Worker }
113*8617a60dSAndroid Build Coastguard Worker
114*8617a60dSAndroid Build Coastguard Worker gbb_rootkey = (uint8_t *)gbb + gbb->rootkey_offset;
115*8617a60dSAndroid Build Coastguard Worker /* See cmd_gbb_utility: root key must be first cleared with zero. */
116*8617a60dSAndroid Build Coastguard Worker memset(gbb_rootkey, 0, gbb->rootkey_size);
117*8617a60dSAndroid Build Coastguard Worker memcpy(gbb_rootkey, rootkey, rootkey_len);
118*8617a60dSAndroid Build Coastguard Worker return 0;
119*8617a60dSAndroid Build Coastguard Worker }
120*8617a60dSAndroid Build Coastguard Worker
121*8617a60dSAndroid Build Coastguard Worker /*
122*8617a60dSAndroid Build Coastguard Worker * Changes the firmware section (for example vblock or GSCVD) to new data.
123*8617a60dSAndroid Build Coastguard Worker * Returns 0 on success, otherwise failure.
124*8617a60dSAndroid Build Coastguard Worker */
change_section(struct firmware_image * image,const char * section_name,const uint8_t * data,uint32_t data_len)125*8617a60dSAndroid Build Coastguard Worker static int change_section(struct firmware_image *image,
126*8617a60dSAndroid Build Coastguard Worker const char *section_name,
127*8617a60dSAndroid Build Coastguard Worker const uint8_t *data, uint32_t data_len)
128*8617a60dSAndroid Build Coastguard Worker {
129*8617a60dSAndroid Build Coastguard Worker struct firmware_section section;
130*8617a60dSAndroid Build Coastguard Worker
131*8617a60dSAndroid Build Coastguard Worker find_firmware_section(§ion, image, section_name);
132*8617a60dSAndroid Build Coastguard Worker if (!section.data) {
133*8617a60dSAndroid Build Coastguard Worker ERROR("Need section %s in image %s.\n", section_name,
134*8617a60dSAndroid Build Coastguard Worker image->file_name);
135*8617a60dSAndroid Build Coastguard Worker return -1;
136*8617a60dSAndroid Build Coastguard Worker }
137*8617a60dSAndroid Build Coastguard Worker if (section.size < data_len) {
138*8617a60dSAndroid Build Coastguard Worker ERROR("'%s' is too small (%zu bytes) for patching %u bytes.\n",
139*8617a60dSAndroid Build Coastguard Worker section_name, section.size, data_len);
140*8617a60dSAndroid Build Coastguard Worker return -1;
141*8617a60dSAndroid Build Coastguard Worker }
142*8617a60dSAndroid Build Coastguard Worker /* First erase (0xff) the section in case the new data is smaller. */
143*8617a60dSAndroid Build Coastguard Worker memset(section.data, 0xff, section.size);
144*8617a60dSAndroid Build Coastguard Worker memcpy(section.data, data, data_len);
145*8617a60dSAndroid Build Coastguard Worker return 0;
146*8617a60dSAndroid Build Coastguard Worker }
147*8617a60dSAndroid Build Coastguard Worker
148*8617a60dSAndroid Build Coastguard Worker /*
149*8617a60dSAndroid Build Coastguard Worker * Applies a key file to firmware image.
150*8617a60dSAndroid Build Coastguard Worker * Returns 0 on success, otherwise failure.
151*8617a60dSAndroid Build Coastguard Worker */
apply_key_file(struct firmware_image * image,const char * path,struct u_archive * archive,const char * section_name,int (* apply)(struct firmware_image * image,const char * section,const uint8_t * data,uint32_t len))152*8617a60dSAndroid Build Coastguard Worker static int apply_key_file(
153*8617a60dSAndroid Build Coastguard Worker struct firmware_image *image, const char *path,
154*8617a60dSAndroid Build Coastguard Worker struct u_archive *archive, const char *section_name,
155*8617a60dSAndroid Build Coastguard Worker int (*apply)(struct firmware_image *image, const char *section,
156*8617a60dSAndroid Build Coastguard Worker const uint8_t *data, uint32_t len))
157*8617a60dSAndroid Build Coastguard Worker {
158*8617a60dSAndroid Build Coastguard Worker int r = 0;
159*8617a60dSAndroid Build Coastguard Worker uint8_t *data = NULL;
160*8617a60dSAndroid Build Coastguard Worker uint32_t len;
161*8617a60dSAndroid Build Coastguard Worker
162*8617a60dSAndroid Build Coastguard Worker r = archive_read_file(archive, path, &data, &len, NULL);
163*8617a60dSAndroid Build Coastguard Worker if (r == 0) {
164*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Loaded file: %s\n", path);
165*8617a60dSAndroid Build Coastguard Worker r = apply(image, section_name, data, len);
166*8617a60dSAndroid Build Coastguard Worker if (r)
167*8617a60dSAndroid Build Coastguard Worker ERROR("Failed applying %s to %s\n", path, section_name);
168*8617a60dSAndroid Build Coastguard Worker } else {
169*8617a60dSAndroid Build Coastguard Worker ERROR("Failed reading: %s\n", path);
170*8617a60dSAndroid Build Coastguard Worker }
171*8617a60dSAndroid Build Coastguard Worker free(data);
172*8617a60dSAndroid Build Coastguard Worker return r;
173*8617a60dSAndroid Build Coastguard Worker }
174*8617a60dSAndroid Build Coastguard Worker
175*8617a60dSAndroid Build Coastguard Worker /*
176*8617a60dSAndroid Build Coastguard Worker * Modifies a firmware image from patch information specified in model config.
177*8617a60dSAndroid Build Coastguard Worker * Returns 0 on success, otherwise number of failures.
178*8617a60dSAndroid Build Coastguard Worker */
patch_image_by_model(struct firmware_image * image,const struct model_config * model,struct u_archive * archive)179*8617a60dSAndroid Build Coastguard Worker int patch_image_by_model(
180*8617a60dSAndroid Build Coastguard Worker struct firmware_image *image, const struct model_config *model,
181*8617a60dSAndroid Build Coastguard Worker struct u_archive *archive)
182*8617a60dSAndroid Build Coastguard Worker {
183*8617a60dSAndroid Build Coastguard Worker int err = 0;
184*8617a60dSAndroid Build Coastguard Worker if (model->patches.rootkey)
185*8617a60dSAndroid Build Coastguard Worker err += !!apply_key_file(
186*8617a60dSAndroid Build Coastguard Worker image, model->patches.rootkey, archive,
187*8617a60dSAndroid Build Coastguard Worker FMAP_RO_GBB, change_gbb_rootkey);
188*8617a60dSAndroid Build Coastguard Worker if (model->patches.vblock_a)
189*8617a60dSAndroid Build Coastguard Worker err += !!apply_key_file(
190*8617a60dSAndroid Build Coastguard Worker image, model->patches.vblock_a, archive,
191*8617a60dSAndroid Build Coastguard Worker FMAP_RW_VBLOCK_A, change_section);
192*8617a60dSAndroid Build Coastguard Worker if (model->patches.vblock_b)
193*8617a60dSAndroid Build Coastguard Worker err += !!apply_key_file(
194*8617a60dSAndroid Build Coastguard Worker image, model->patches.vblock_b, archive,
195*8617a60dSAndroid Build Coastguard Worker FMAP_RW_VBLOCK_B, change_section);
196*8617a60dSAndroid Build Coastguard Worker if (model->patches.gscvd)
197*8617a60dSAndroid Build Coastguard Worker err += !!apply_key_file(
198*8617a60dSAndroid Build Coastguard Worker image, model->patches.gscvd, archive,
199*8617a60dSAndroid Build Coastguard Worker FMAP_RO_GSCVD, change_section);
200*8617a60dSAndroid Build Coastguard Worker return err;
201*8617a60dSAndroid Build Coastguard Worker }
202*8617a60dSAndroid Build Coastguard Worker
203*8617a60dSAndroid Build Coastguard Worker /*
204*8617a60dSAndroid Build Coastguard Worker * Finds available patch files by given model.
205*8617a60dSAndroid Build Coastguard Worker * Updates `model` argument with path of patch files.
206*8617a60dSAndroid Build Coastguard Worker */
find_patches_for_model(struct model_config * model,struct u_archive * archive)207*8617a60dSAndroid Build Coastguard Worker static void find_patches_for_model(struct model_config *model,
208*8617a60dSAndroid Build Coastguard Worker struct u_archive *archive)
209*8617a60dSAndroid Build Coastguard Worker {
210*8617a60dSAndroid Build Coastguard Worker char *path;
211*8617a60dSAndroid Build Coastguard Worker int i;
212*8617a60dSAndroid Build Coastguard Worker
213*8617a60dSAndroid Build Coastguard Worker const char * const names[] = {
214*8617a60dSAndroid Build Coastguard Worker "rootkey",
215*8617a60dSAndroid Build Coastguard Worker "vblock_A",
216*8617a60dSAndroid Build Coastguard Worker "vblock_B",
217*8617a60dSAndroid Build Coastguard Worker "gscvd",
218*8617a60dSAndroid Build Coastguard Worker };
219*8617a60dSAndroid Build Coastguard Worker
220*8617a60dSAndroid Build Coastguard Worker char **targets[] = {
221*8617a60dSAndroid Build Coastguard Worker &model->patches.rootkey,
222*8617a60dSAndroid Build Coastguard Worker &model->patches.vblock_a,
223*8617a60dSAndroid Build Coastguard Worker &model->patches.vblock_b,
224*8617a60dSAndroid Build Coastguard Worker &model->patches.gscvd,
225*8617a60dSAndroid Build Coastguard Worker };
226*8617a60dSAndroid Build Coastguard Worker
227*8617a60dSAndroid Build Coastguard Worker assert(ARRAY_SIZE(names) == ARRAY_SIZE(targets));
228*8617a60dSAndroid Build Coastguard Worker for (i = 0; i < ARRAY_SIZE(names); i++) {
229*8617a60dSAndroid Build Coastguard Worker ASPRINTF(&path, "%s%s.%s", PATH_KEYSET_FOLDER, names[i], model->name);
230*8617a60dSAndroid Build Coastguard Worker if (archive_has_entry(archive, path))
231*8617a60dSAndroid Build Coastguard Worker *targets[i] = path;
232*8617a60dSAndroid Build Coastguard Worker else
233*8617a60dSAndroid Build Coastguard Worker free(path);
234*8617a60dSAndroid Build Coastguard Worker }
235*8617a60dSAndroid Build Coastguard Worker }
236*8617a60dSAndroid Build Coastguard Worker
237*8617a60dSAndroid Build Coastguard Worker /*
238*8617a60dSAndroid Build Coastguard Worker * Adds and copies one new model config to the existing list of given manifest.
239*8617a60dSAndroid Build Coastguard Worker * Returns a pointer to the newly allocated config, or NULL on failure.
240*8617a60dSAndroid Build Coastguard Worker */
manifest_add_model(struct manifest * manifest,const struct model_config * cfg)241*8617a60dSAndroid Build Coastguard Worker static struct model_config *manifest_add_model(
242*8617a60dSAndroid Build Coastguard Worker struct manifest *manifest,
243*8617a60dSAndroid Build Coastguard Worker const struct model_config *cfg)
244*8617a60dSAndroid Build Coastguard Worker {
245*8617a60dSAndroid Build Coastguard Worker struct model_config *model;
246*8617a60dSAndroid Build Coastguard Worker manifest->num++;
247*8617a60dSAndroid Build Coastguard Worker manifest->models = (struct model_config *)realloc(
248*8617a60dSAndroid Build Coastguard Worker manifest->models, manifest->num * sizeof(*model));
249*8617a60dSAndroid Build Coastguard Worker if (!manifest->models) {
250*8617a60dSAndroid Build Coastguard Worker ERROR("Internal error: failed to allocate buffer.\n");
251*8617a60dSAndroid Build Coastguard Worker return NULL;
252*8617a60dSAndroid Build Coastguard Worker }
253*8617a60dSAndroid Build Coastguard Worker model = &manifest->models[manifest->num - 1];
254*8617a60dSAndroid Build Coastguard Worker memcpy(model, cfg, sizeof(*model));
255*8617a60dSAndroid Build Coastguard Worker return model;
256*8617a60dSAndroid Build Coastguard Worker }
257*8617a60dSAndroid Build Coastguard Worker
258*8617a60dSAndroid Build Coastguard Worker /*
259*8617a60dSAndroid Build Coastguard Worker * A callback function for manifest to scan files in raw /firmware archive.
260*8617a60dSAndroid Build Coastguard Worker * Returns 0 to keep scanning, or non-zero to stop.
261*8617a60dSAndroid Build Coastguard Worker */
manifest_scan_raw_entries(const char * name,void * arg)262*8617a60dSAndroid Build Coastguard Worker static int manifest_scan_raw_entries(const char *name, void *arg)
263*8617a60dSAndroid Build Coastguard Worker {
264*8617a60dSAndroid Build Coastguard Worker struct manifest *manifest = (struct manifest *)arg;
265*8617a60dSAndroid Build Coastguard Worker struct u_archive *archive = manifest->archive;
266*8617a60dSAndroid Build Coastguard Worker struct model_config model = {0};
267*8617a60dSAndroid Build Coastguard Worker char *ec_name = NULL;
268*8617a60dSAndroid Build Coastguard Worker int chars_read = 0;
269*8617a60dSAndroid Build Coastguard Worker
270*8617a60dSAndroid Build Coastguard Worker /*
271*8617a60dSAndroid Build Coastguard Worker * /build/$BOARD/firmware (or CPFE firmware archives) layout:
272*8617a60dSAndroid Build Coastguard Worker * - image-${MODEL}{,.serial,.dev...}.bin
273*8617a60dSAndroid Build Coastguard Worker * - ${MODEL}/ec.bin
274*8617a60dSAndroid Build Coastguard Worker */
275*8617a60dSAndroid Build Coastguard Worker
276*8617a60dSAndroid Build Coastguard Worker if (sscanf(name, "image-%m[^.].bin%n", &model.name, &chars_read) != 1)
277*8617a60dSAndroid Build Coastguard Worker return 0;
278*8617a60dSAndroid Build Coastguard Worker
279*8617a60dSAndroid Build Coastguard Worker /* Ignore the names with extra modifiers like image-$MODEL.serial.bin */
280*8617a60dSAndroid Build Coastguard Worker if (!chars_read || name[chars_read]) {
281*8617a60dSAndroid Build Coastguard Worker free(model.name);
282*8617a60dSAndroid Build Coastguard Worker return 0;
283*8617a60dSAndroid Build Coastguard Worker }
284*8617a60dSAndroid Build Coastguard Worker
285*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Found model <%s>: %s\n", model.name, name);
286*8617a60dSAndroid Build Coastguard Worker model.image = strdup(name);
287*8617a60dSAndroid Build Coastguard Worker
288*8617a60dSAndroid Build Coastguard Worker ASPRINTF(&ec_name, "%s/ec.bin", model.name);
289*8617a60dSAndroid Build Coastguard Worker if (archive_has_entry(archive, ec_name))
290*8617a60dSAndroid Build Coastguard Worker model.ec_image = strdup(ec_name);
291*8617a60dSAndroid Build Coastguard Worker free(ec_name);
292*8617a60dSAndroid Build Coastguard Worker
293*8617a60dSAndroid Build Coastguard Worker return !manifest_add_model(manifest, &model);
294*8617a60dSAndroid Build Coastguard Worker }
295*8617a60dSAndroid Build Coastguard Worker
296*8617a60dSAndroid Build Coastguard Worker /* Returns the matched model config from the manifest, or NULL if not found. */
manifest_get_model_config(const struct manifest * manifest,const char * name)297*8617a60dSAndroid Build Coastguard Worker static struct model_config *manifest_get_model_config(
298*8617a60dSAndroid Build Coastguard Worker const struct manifest *manifest, const char *name)
299*8617a60dSAndroid Build Coastguard Worker {
300*8617a60dSAndroid Build Coastguard Worker int i = 0;
301*8617a60dSAndroid Build Coastguard Worker
302*8617a60dSAndroid Build Coastguard Worker for (i = 0; i < manifest->num; i++) {
303*8617a60dSAndroid Build Coastguard Worker if (!strcmp(name, manifest->models[i].name))
304*8617a60dSAndroid Build Coastguard Worker return &manifest->models[i];
305*8617a60dSAndroid Build Coastguard Worker }
306*8617a60dSAndroid Build Coastguard Worker return NULL;
307*8617a60dSAndroid Build Coastguard Worker }
308*8617a60dSAndroid Build Coastguard Worker
309*8617a60dSAndroid Build Coastguard Worker /* Releases (and zeros) the data inside a patch config. */
clear_patch_config(struct patch_config * patch)310*8617a60dSAndroid Build Coastguard Worker static void clear_patch_config(struct patch_config *patch)
311*8617a60dSAndroid Build Coastguard Worker {
312*8617a60dSAndroid Build Coastguard Worker free(patch->rootkey);
313*8617a60dSAndroid Build Coastguard Worker free(patch->vblock_a);
314*8617a60dSAndroid Build Coastguard Worker free(patch->vblock_b);
315*8617a60dSAndroid Build Coastguard Worker free(patch->gscvd);
316*8617a60dSAndroid Build Coastguard Worker memset(patch, 0, sizeof(*patch));
317*8617a60dSAndroid Build Coastguard Worker }
318*8617a60dSAndroid Build Coastguard Worker
319*8617a60dSAndroid Build Coastguard Worker /*
320*8617a60dSAndroid Build Coastguard Worker * Creates the manifest from the 'signer_config.csv' file.
321*8617a60dSAndroid Build Coastguard Worker * Returns 0 on success (loaded), otherwise failure.
322*8617a60dSAndroid Build Coastguard Worker */
manifest_from_signer_config(struct manifest * manifest)323*8617a60dSAndroid Build Coastguard Worker static int manifest_from_signer_config(struct manifest *manifest)
324*8617a60dSAndroid Build Coastguard Worker {
325*8617a60dSAndroid Build Coastguard Worker struct u_archive *archive = manifest->archive;
326*8617a60dSAndroid Build Coastguard Worker uint32_t size;
327*8617a60dSAndroid Build Coastguard Worker uint8_t *data;
328*8617a60dSAndroid Build Coastguard Worker char *s, *tok_ptr = NULL;
329*8617a60dSAndroid Build Coastguard Worker
330*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Try to build the manifest from %s\n", PATH_SIGNER_CONFIG);
331*8617a60dSAndroid Build Coastguard Worker
332*8617a60dSAndroid Build Coastguard Worker if (!archive_has_entry(archive, PATH_SIGNER_CONFIG))
333*8617a60dSAndroid Build Coastguard Worker return -1;
334*8617a60dSAndroid Build Coastguard Worker
335*8617a60dSAndroid Build Coastguard Worker /*
336*8617a60dSAndroid Build Coastguard Worker * CSV format: model_name,firmware_image,key_id,ec_image
337*8617a60dSAndroid Build Coastguard Worker *
338*8617a60dSAndroid Build Coastguard Worker * Note the key_id is for signer and won't be used by the updater,
339*8617a60dSAndroid Build Coastguard Worker * and ec_image may be optional (for example sarien).
340*8617a60dSAndroid Build Coastguard Worker */
341*8617a60dSAndroid Build Coastguard Worker
342*8617a60dSAndroid Build Coastguard Worker if (archive_read_file(archive, PATH_SIGNER_CONFIG, &data, &size,NULL)) {
343*8617a60dSAndroid Build Coastguard Worker ERROR("Failed reading: %s\n", PATH_SIGNER_CONFIG);
344*8617a60dSAndroid Build Coastguard Worker return -1;
345*8617a60dSAndroid Build Coastguard Worker }
346*8617a60dSAndroid Build Coastguard Worker
347*8617a60dSAndroid Build Coastguard Worker /* Skip headers. */
348*8617a60dSAndroid Build Coastguard Worker s = strtok_r((char *)data, "\n", &tok_ptr);
349*8617a60dSAndroid Build Coastguard Worker if (!s || !strchr(s, ',')) {
350*8617a60dSAndroid Build Coastguard Worker ERROR("Invalid %s: missing header.\n", PATH_SIGNER_CONFIG);
351*8617a60dSAndroid Build Coastguard Worker free(data);
352*8617a60dSAndroid Build Coastguard Worker return -1;
353*8617a60dSAndroid Build Coastguard Worker }
354*8617a60dSAndroid Build Coastguard Worker
355*8617a60dSAndroid Build Coastguard Worker for (s = strtok_r(NULL, "\n", &tok_ptr); s != NULL;
356*8617a60dSAndroid Build Coastguard Worker s = strtok_r(NULL, "\n", &tok_ptr)) {
357*8617a60dSAndroid Build Coastguard Worker
358*8617a60dSAndroid Build Coastguard Worker struct model_config model = {0};
359*8617a60dSAndroid Build Coastguard Worker
360*8617a60dSAndroid Build Coastguard Worker /*
361*8617a60dSAndroid Build Coastguard Worker * Both keyid (%3) and ec_image (%4) are optional so we want to
362*8617a60dSAndroid Build Coastguard Worker * read at least 2 fields.
363*8617a60dSAndroid Build Coastguard Worker */
364*8617a60dSAndroid Build Coastguard Worker if (sscanf(s, "%m[^,],%m[^,],%*[^,],%m[^,]",
365*8617a60dSAndroid Build Coastguard Worker &model.name, &model.image, &model.ec_image) < 2) {
366*8617a60dSAndroid Build Coastguard Worker ERROR("Invalid entry(%s): %s\n", PATH_SIGNER_CONFIG, s);
367*8617a60dSAndroid Build Coastguard Worker free(model.name);
368*8617a60dSAndroid Build Coastguard Worker free(model.image);
369*8617a60dSAndroid Build Coastguard Worker free(model.ec_image);
370*8617a60dSAndroid Build Coastguard Worker continue;
371*8617a60dSAndroid Build Coastguard Worker }
372*8617a60dSAndroid Build Coastguard Worker
373*8617a60dSAndroid Build Coastguard Worker if (strchr(model.name, '-')) {
374*8617a60dSAndroid Build Coastguard Worker /* format: BaseModelName-CustomLabelTag */
375*8617a60dSAndroid Build Coastguard Worker struct model_config *base_model;
376*8617a60dSAndroid Build Coastguard Worker char *tok_dash;
377*8617a60dSAndroid Build Coastguard Worker char *base_name = strdup(model.name);
378*8617a60dSAndroid Build Coastguard Worker
379*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Found custom-label: %s\n", model.name);
380*8617a60dSAndroid Build Coastguard Worker base_name = strtok_r(base_name, "-", &tok_dash);
381*8617a60dSAndroid Build Coastguard Worker assert(base_name);
382*8617a60dSAndroid Build Coastguard Worker
383*8617a60dSAndroid Build Coastguard Worker /*
384*8617a60dSAndroid Build Coastguard Worker * Currently we assume the base model (e.g., base_name)
385*8617a60dSAndroid Build Coastguard Worker * is always listed before CL models in the CSV file -
386*8617a60dSAndroid Build Coastguard Worker * this is based on how the signerbot and the
387*8617a60dSAndroid Build Coastguard Worker * chromeos-config works today (validated on octopus).
388*8617a60dSAndroid Build Coastguard Worker */
389*8617a60dSAndroid Build Coastguard Worker base_model = manifest_get_model_config(manifest, base_name);
390*8617a60dSAndroid Build Coastguard Worker
391*8617a60dSAndroid Build Coastguard Worker if (!base_model) {
392*8617a60dSAndroid Build Coastguard Worker ERROR("Invalid base model for custom label: %s\n", base_name);
393*8617a60dSAndroid Build Coastguard Worker } else if (!base_model->has_custom_label) {
394*8617a60dSAndroid Build Coastguard Worker base_model->has_custom_label = true;
395*8617a60dSAndroid Build Coastguard Worker }
396*8617a60dSAndroid Build Coastguard Worker
397*8617a60dSAndroid Build Coastguard Worker free(base_name);
398*8617a60dSAndroid Build Coastguard Worker }
399*8617a60dSAndroid Build Coastguard Worker
400*8617a60dSAndroid Build Coastguard Worker /* Find patch files. */
401*8617a60dSAndroid Build Coastguard Worker find_patches_for_model(&model, archive);
402*8617a60dSAndroid Build Coastguard Worker
403*8617a60dSAndroid Build Coastguard Worker if (!manifest_add_model(manifest, &model))
404*8617a60dSAndroid Build Coastguard Worker break;
405*8617a60dSAndroid Build Coastguard Worker }
406*8617a60dSAndroid Build Coastguard Worker free(data);
407*8617a60dSAndroid Build Coastguard Worker return 0;
408*8617a60dSAndroid Build Coastguard Worker }
409*8617a60dSAndroid Build Coastguard Worker
410*8617a60dSAndroid Build Coastguard Worker /*
411*8617a60dSAndroid Build Coastguard Worker * Creates the manifest from a simple (legacy) folder with only 1 set of
412*8617a60dSAndroid Build Coastguard Worker * firmware images.
413*8617a60dSAndroid Build Coastguard Worker * Returns 0 on success (loaded), otherwise failure.
414*8617a60dSAndroid Build Coastguard Worker */
manifest_from_simple_folder(struct manifest * manifest)415*8617a60dSAndroid Build Coastguard Worker static int manifest_from_simple_folder(struct manifest *manifest)
416*8617a60dSAndroid Build Coastguard Worker {
417*8617a60dSAndroid Build Coastguard Worker const char * const host_image_name = "image.bin",
418*8617a60dSAndroid Build Coastguard Worker * const old_host_image_name = "bios.bin",
419*8617a60dSAndroid Build Coastguard Worker * const ec_name = "ec.bin";
420*8617a60dSAndroid Build Coastguard Worker struct u_archive *archive = manifest->archive;
421*8617a60dSAndroid Build Coastguard Worker const char *image_name = NULL;
422*8617a60dSAndroid Build Coastguard Worker struct firmware_image image = {0};
423*8617a60dSAndroid Build Coastguard Worker struct model_config model = {0};
424*8617a60dSAndroid Build Coastguard Worker
425*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Try to build the manifest from a simple folder\n");
426*8617a60dSAndroid Build Coastguard Worker
427*8617a60dSAndroid Build Coastguard Worker /* Try to load from current folder. */
428*8617a60dSAndroid Build Coastguard Worker if (archive_has_entry(archive, old_host_image_name))
429*8617a60dSAndroid Build Coastguard Worker image_name = old_host_image_name;
430*8617a60dSAndroid Build Coastguard Worker else if (archive_has_entry(archive, host_image_name))
431*8617a60dSAndroid Build Coastguard Worker image_name = host_image_name;
432*8617a60dSAndroid Build Coastguard Worker else
433*8617a60dSAndroid Build Coastguard Worker return 1;
434*8617a60dSAndroid Build Coastguard Worker
435*8617a60dSAndroid Build Coastguard Worker model.image = strdup(image_name);
436*8617a60dSAndroid Build Coastguard Worker if (archive_has_entry(archive, ec_name))
437*8617a60dSAndroid Build Coastguard Worker model.ec_image = strdup(ec_name);
438*8617a60dSAndroid Build Coastguard Worker /* Extract model name from FWID: $Vendor_$Platform.$Version */
439*8617a60dSAndroid Build Coastguard Worker if (!load_firmware_image(&image, image_name, archive)) {
440*8617a60dSAndroid Build Coastguard Worker char *token = NULL;
441*8617a60dSAndroid Build Coastguard Worker if (strtok(image.ro_version, "_"))
442*8617a60dSAndroid Build Coastguard Worker token = strtok(NULL, ".");
443*8617a60dSAndroid Build Coastguard Worker if (token && *token) {
444*8617a60dSAndroid Build Coastguard Worker str_convert(token, tolower);
445*8617a60dSAndroid Build Coastguard Worker model.name = strdup(token);
446*8617a60dSAndroid Build Coastguard Worker }
447*8617a60dSAndroid Build Coastguard Worker free_firmware_image(&image);
448*8617a60dSAndroid Build Coastguard Worker }
449*8617a60dSAndroid Build Coastguard Worker if (!model.name)
450*8617a60dSAndroid Build Coastguard Worker model.name = strdup(DEFAULT_MODEL_NAME);
451*8617a60dSAndroid Build Coastguard Worker manifest_add_model(manifest, &model);
452*8617a60dSAndroid Build Coastguard Worker manifest->default_model = manifest->num - 1;
453*8617a60dSAndroid Build Coastguard Worker
454*8617a60dSAndroid Build Coastguard Worker return 0;
455*8617a60dSAndroid Build Coastguard Worker }
456*8617a60dSAndroid Build Coastguard Worker
457*8617a60dSAndroid Build Coastguard Worker /*
458*8617a60dSAndroid Build Coastguard Worker * Finds the existing model_config from manifest that best matches current
459*8617a60dSAndroid Build Coastguard Worker * system (as defined by model_name).
460*8617a60dSAndroid Build Coastguard Worker * Returns a model_config from manifest, or NULL if not found.
461*8617a60dSAndroid Build Coastguard Worker */
manifest_find_model(struct updater_config * cfg,const struct manifest * manifest,const char * model_name)462*8617a60dSAndroid Build Coastguard Worker const struct model_config *manifest_find_model(struct updater_config *cfg,
463*8617a60dSAndroid Build Coastguard Worker const struct manifest *manifest,
464*8617a60dSAndroid Build Coastguard Worker const char *model_name)
465*8617a60dSAndroid Build Coastguard Worker {
466*8617a60dSAndroid Build Coastguard Worker char *manifest_key = NULL;
467*8617a60dSAndroid Build Coastguard Worker const struct model_config *model = NULL;
468*8617a60dSAndroid Build Coastguard Worker int i;
469*8617a60dSAndroid Build Coastguard Worker int matched_index;
470*8617a60dSAndroid Build Coastguard Worker
471*8617a60dSAndroid Build Coastguard Worker /*
472*8617a60dSAndroid Build Coastguard Worker * For manifest with single model defined, we should just return because
473*8617a60dSAndroid Build Coastguard Worker * there are other mechanisms like platform name check to double confirm
474*8617a60dSAndroid Build Coastguard Worker * if the firmware is valid.
475*8617a60dSAndroid Build Coastguard Worker */
476*8617a60dSAndroid Build Coastguard Worker if (manifest->num == 1)
477*8617a60dSAndroid Build Coastguard Worker return &manifest->models[0];
478*8617a60dSAndroid Build Coastguard Worker
479*8617a60dSAndroid Build Coastguard Worker if (!model_name) {
480*8617a60dSAndroid Build Coastguard Worker matched_index = dut_get_manifest_key(&manifest_key, cfg);
481*8617a60dSAndroid Build Coastguard Worker if (matched_index < 0) {
482*8617a60dSAndroid Build Coastguard Worker ERROR("Failed to get device identity. "
483*8617a60dSAndroid Build Coastguard Worker "Run \"crosid -v\" for explanation.\n");
484*8617a60dSAndroid Build Coastguard Worker return NULL;
485*8617a60dSAndroid Build Coastguard Worker }
486*8617a60dSAndroid Build Coastguard Worker
487*8617a60dSAndroid Build Coastguard Worker INFO("Identified the device using libcrosid, "
488*8617a60dSAndroid Build Coastguard Worker "matched chromeos-config index: %d, "
489*8617a60dSAndroid Build Coastguard Worker "manifest key (model): %s\n",
490*8617a60dSAndroid Build Coastguard Worker matched_index, manifest_key);
491*8617a60dSAndroid Build Coastguard Worker model_name = manifest_key;
492*8617a60dSAndroid Build Coastguard Worker }
493*8617a60dSAndroid Build Coastguard Worker
494*8617a60dSAndroid Build Coastguard Worker model = manifest_get_model_config(manifest, model_name);
495*8617a60dSAndroid Build Coastguard Worker
496*8617a60dSAndroid Build Coastguard Worker if (!model) {
497*8617a60dSAndroid Build Coastguard Worker ERROR("Unsupported model: '%s'.\n", model_name);
498*8617a60dSAndroid Build Coastguard Worker
499*8617a60dSAndroid Build Coastguard Worker fprintf(stderr,
500*8617a60dSAndroid Build Coastguard Worker "The firmware manifest key '%s' is not present in this "
501*8617a60dSAndroid Build Coastguard Worker "updater archive. The known keys to this updater "
502*8617a60dSAndroid Build Coastguard Worker "archive are:\n", model_name);
503*8617a60dSAndroid Build Coastguard Worker
504*8617a60dSAndroid Build Coastguard Worker for (i = 0; i < manifest->num; i++)
505*8617a60dSAndroid Build Coastguard Worker fprintf(stderr, " %s", manifest->models[i].name);
506*8617a60dSAndroid Build Coastguard Worker fprintf(stderr, "\n\n");
507*8617a60dSAndroid Build Coastguard Worker fprintf(stderr,
508*8617a60dSAndroid Build Coastguard Worker "Perhaps you are trying to use an updater archive for "
509*8617a60dSAndroid Build Coastguard Worker "the wrong board, or designed for an older OS version "
510*8617a60dSAndroid Build Coastguard Worker "before this model was supported.\n");
511*8617a60dSAndroid Build Coastguard Worker fprintf(stderr,
512*8617a60dSAndroid Build Coastguard Worker "Hint: Read the FIRMWARE_MANIFEST_KEY from the output "
513*8617a60dSAndroid Build Coastguard Worker "of the crosid command.\n");
514*8617a60dSAndroid Build Coastguard Worker }
515*8617a60dSAndroid Build Coastguard Worker
516*8617a60dSAndroid Build Coastguard Worker
517*8617a60dSAndroid Build Coastguard Worker free(manifest_key);
518*8617a60dSAndroid Build Coastguard Worker return model;
519*8617a60dSAndroid Build Coastguard Worker }
520*8617a60dSAndroid Build Coastguard Worker
521*8617a60dSAndroid Build Coastguard Worker const struct model_config *
manifest_detect_model_from_frid(struct updater_config * cfg,struct manifest * manifest)522*8617a60dSAndroid Build Coastguard Worker manifest_detect_model_from_frid(struct updater_config *cfg,
523*8617a60dSAndroid Build Coastguard Worker struct manifest *manifest)
524*8617a60dSAndroid Build Coastguard Worker {
525*8617a60dSAndroid Build Coastguard Worker const struct model_config *result = NULL;
526*8617a60dSAndroid Build Coastguard Worker struct firmware_image current_ro_frid = {0};
527*8617a60dSAndroid Build Coastguard Worker current_ro_frid.programmer = cfg->image_current.programmer;
528*8617a60dSAndroid Build Coastguard Worker int error = flashrom_read_region(¤t_ro_frid, FMAP_RO_FRID,
529*8617a60dSAndroid Build Coastguard Worker cfg->verbosity + 1);
530*8617a60dSAndroid Build Coastguard Worker const char *from_dot;
531*8617a60dSAndroid Build Coastguard Worker int len;
532*8617a60dSAndroid Build Coastguard Worker
533*8617a60dSAndroid Build Coastguard Worker if (error)
534*8617a60dSAndroid Build Coastguard Worker return NULL;
535*8617a60dSAndroid Build Coastguard Worker
536*8617a60dSAndroid Build Coastguard Worker current_ro_frid.data[current_ro_frid.size - 1] = '\0';
537*8617a60dSAndroid Build Coastguard Worker from_dot = strchr((const char *)current_ro_frid.data, '.');
538*8617a60dSAndroid Build Coastguard Worker if (!from_dot) {
539*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Missing dot (%s)\n",
540*8617a60dSAndroid Build Coastguard Worker (const char *)current_ro_frid.data);
541*8617a60dSAndroid Build Coastguard Worker goto cleanup;
542*8617a60dSAndroid Build Coastguard Worker }
543*8617a60dSAndroid Build Coastguard Worker len = from_dot - (const char *)current_ro_frid.data + 1;
544*8617a60dSAndroid Build Coastguard Worker
545*8617a60dSAndroid Build Coastguard Worker for (int i = 0; i < manifest->num && !result; ++i) {
546*8617a60dSAndroid Build Coastguard Worker struct model_config *m = &manifest->models[i];
547*8617a60dSAndroid Build Coastguard Worker struct firmware_image image = {0};
548*8617a60dSAndroid Build Coastguard Worker
549*8617a60dSAndroid Build Coastguard Worker if (load_firmware_image(&image, m->image, manifest->archive))
550*8617a60dSAndroid Build Coastguard Worker return NULL;
551*8617a60dSAndroid Build Coastguard Worker
552*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Comparing '%*.*s' with '%*.*s'\n", len, len,
553*8617a60dSAndroid Build Coastguard Worker (const char *)current_ro_frid.data, len, len,
554*8617a60dSAndroid Build Coastguard Worker image.ro_version);
555*8617a60dSAndroid Build Coastguard Worker if (strncasecmp((const char *)current_ro_frid.data,
556*8617a60dSAndroid Build Coastguard Worker image.ro_version, len) == 0) {
557*8617a60dSAndroid Build Coastguard Worker result = m;
558*8617a60dSAndroid Build Coastguard Worker }
559*8617a60dSAndroid Build Coastguard Worker free_firmware_image(&image);
560*8617a60dSAndroid Build Coastguard Worker }
561*8617a60dSAndroid Build Coastguard Worker if (result) {
562*8617a60dSAndroid Build Coastguard Worker INFO("Detected model: '%s'\n", result->name);
563*8617a60dSAndroid Build Coastguard Worker } else {
564*8617a60dSAndroid Build Coastguard Worker ERROR("Unsupported FRID: '%*.*s'.\n", len - 1, len - 1,
565*8617a60dSAndroid Build Coastguard Worker (const char *)current_ro_frid.data);
566*8617a60dSAndroid Build Coastguard Worker }
567*8617a60dSAndroid Build Coastguard Worker cleanup:
568*8617a60dSAndroid Build Coastguard Worker free_firmware_image(¤t_ro_frid);
569*8617a60dSAndroid Build Coastguard Worker
570*8617a60dSAndroid Build Coastguard Worker return result;
571*8617a60dSAndroid Build Coastguard Worker }
572*8617a60dSAndroid Build Coastguard Worker
573*8617a60dSAndroid Build Coastguard Worker /*
574*8617a60dSAndroid Build Coastguard Worker * Determines the custom label tag.
575*8617a60dSAndroid Build Coastguard Worker * Returns the tag string, or NULL if not found.
576*8617a60dSAndroid Build Coastguard Worker * Caller must free the returned string.
577*8617a60dSAndroid Build Coastguard Worker */
get_custom_label_tag(const char * image_file)578*8617a60dSAndroid Build Coastguard Worker static char *get_custom_label_tag(const char *image_file)
579*8617a60dSAndroid Build Coastguard Worker {
580*8617a60dSAndroid Build Coastguard Worker /* TODO(hungte) Switch to look at /sys/firmware/vpd/ro/$KEY. */
581*8617a60dSAndroid Build Coastguard Worker char *tag;
582*8617a60dSAndroid Build Coastguard Worker
583*8617a60dSAndroid Build Coastguard Worker tag = vpd_get_value(image_file, VPD_CUSTOM_LABEL_TAG);
584*8617a60dSAndroid Build Coastguard Worker if (tag)
585*8617a60dSAndroid Build Coastguard Worker return tag;
586*8617a60dSAndroid Build Coastguard Worker
587*8617a60dSAndroid Build Coastguard Worker tag = vpd_get_value(image_file, VPD_CUSTOM_LABEL_TAG_LEGACY);
588*8617a60dSAndroid Build Coastguard Worker if (tag)
589*8617a60dSAndroid Build Coastguard Worker return tag;
590*8617a60dSAndroid Build Coastguard Worker
591*8617a60dSAndroid Build Coastguard Worker tag = vpd_get_value(image_file, VPD_CUSTOMIZATION_ID);
592*8617a60dSAndroid Build Coastguard Worker /* VPD_CUSTOMIZATION_ID is complicated and can't be returned directly. */
593*8617a60dSAndroid Build Coastguard Worker if (!tag)
594*8617a60dSAndroid Build Coastguard Worker return NULL;
595*8617a60dSAndroid Build Coastguard Worker
596*8617a60dSAndroid Build Coastguard Worker /* For VPD_CUSTOMIZATION_ID=LOEM[-VARIANT], we need only capitalized LOEM. */
597*8617a60dSAndroid Build Coastguard Worker INFO("Using deprecated custom label tag: %s=%s\n", VPD_CUSTOMIZATION_ID, tag);
598*8617a60dSAndroid Build Coastguard Worker char *dash = strchr(tag, '-');
599*8617a60dSAndroid Build Coastguard Worker if (dash)
600*8617a60dSAndroid Build Coastguard Worker *dash = '\0';
601*8617a60dSAndroid Build Coastguard Worker str_convert(tag, toupper);
602*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Applied tag from %s: %s\n", tag, VPD_CUSTOMIZATION_ID);
603*8617a60dSAndroid Build Coastguard Worker return tag;
604*8617a60dSAndroid Build Coastguard Worker }
605*8617a60dSAndroid Build Coastguard Worker
manifest_find_custom_label_model(struct updater_config * cfg,const struct manifest * manifest,const struct model_config * base_model)606*8617a60dSAndroid Build Coastguard Worker const struct model_config *manifest_find_custom_label_model(
607*8617a60dSAndroid Build Coastguard Worker struct updater_config *cfg,
608*8617a60dSAndroid Build Coastguard Worker const struct manifest *manifest,
609*8617a60dSAndroid Build Coastguard Worker const struct model_config *base_model)
610*8617a60dSAndroid Build Coastguard Worker {
611*8617a60dSAndroid Build Coastguard Worker const struct model_config *model;
612*8617a60dSAndroid Build Coastguard Worker
613*8617a60dSAndroid Build Coastguard Worker /*
614*8617a60dSAndroid Build Coastguard Worker * Some custom label devices shipped with wrong key and must change
615*8617a60dSAndroid Build Coastguard Worker * their model names to match the right data.
616*8617a60dSAndroid Build Coastguard Worker */
617*8617a60dSAndroid Build Coastguard Worker if (get_config_quirk(QUIRK_OVERRIDE_CUSTOM_LABEL, cfg)) {
618*8617a60dSAndroid Build Coastguard Worker model = quirk_override_custom_label(cfg, manifest, base_model);
619*8617a60dSAndroid Build Coastguard Worker if (model)
620*8617a60dSAndroid Build Coastguard Worker return model;
621*8617a60dSAndroid Build Coastguard Worker }
622*8617a60dSAndroid Build Coastguard Worker
623*8617a60dSAndroid Build Coastguard Worker assert(cfg->image_current.data);
624*8617a60dSAndroid Build Coastguard Worker const char *tmp_image = get_firmware_image_temp_file(
625*8617a60dSAndroid Build Coastguard Worker &cfg->image_current, &cfg->tempfiles);
626*8617a60dSAndroid Build Coastguard Worker if (!tmp_image) {
627*8617a60dSAndroid Build Coastguard Worker ERROR("Failed to save the system firmware to a file.\n");
628*8617a60dSAndroid Build Coastguard Worker return NULL;
629*8617a60dSAndroid Build Coastguard Worker }
630*8617a60dSAndroid Build Coastguard Worker
631*8617a60dSAndroid Build Coastguard Worker char *tag = get_custom_label_tag(tmp_image);
632*8617a60dSAndroid Build Coastguard Worker if (!tag) {
633*8617a60dSAndroid Build Coastguard Worker WARN("No custom label tag (VPD '%s'). "
634*8617a60dSAndroid Build Coastguard Worker "Use default keys from the base model '%s'.\n",
635*8617a60dSAndroid Build Coastguard Worker VPD_CUSTOM_LABEL_TAG, base_model->name);
636*8617a60dSAndroid Build Coastguard Worker return base_model;
637*8617a60dSAndroid Build Coastguard Worker }
638*8617a60dSAndroid Build Coastguard Worker
639*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Found custom label tag: %s (base=%s)\n", tag, base_model->name);
640*8617a60dSAndroid Build Coastguard Worker char *name;
641*8617a60dSAndroid Build Coastguard Worker ASPRINTF(&name, "%s-%s", base_model->name, tag);
642*8617a60dSAndroid Build Coastguard Worker free(tag);
643*8617a60dSAndroid Build Coastguard Worker
644*8617a60dSAndroid Build Coastguard Worker INFO("Find custom label model info using '%s'...\n", name);
645*8617a60dSAndroid Build Coastguard Worker model = manifest_find_model(cfg, manifest, name);
646*8617a60dSAndroid Build Coastguard Worker
647*8617a60dSAndroid Build Coastguard Worker if (model) {
648*8617a60dSAndroid Build Coastguard Worker INFO("Applied custom label model: %s\n", name);
649*8617a60dSAndroid Build Coastguard Worker } else {
650*8617a60dSAndroid Build Coastguard Worker ERROR("Invalid custom label model: %s\n", name);
651*8617a60dSAndroid Build Coastguard Worker }
652*8617a60dSAndroid Build Coastguard Worker free(name);
653*8617a60dSAndroid Build Coastguard Worker return model;
654*8617a60dSAndroid Build Coastguard Worker }
655*8617a60dSAndroid Build Coastguard Worker
manifest_from_build_artifacts(struct manifest * manifest)656*8617a60dSAndroid Build Coastguard Worker static int manifest_from_build_artifacts(struct manifest *manifest) {
657*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Try to build the manifest from a */firmware folder\n");
658*8617a60dSAndroid Build Coastguard Worker return archive_walk(manifest->archive, manifest, manifest_scan_raw_entries);
659*8617a60dSAndroid Build Coastguard Worker }
660*8617a60dSAndroid Build Coastguard Worker
661*8617a60dSAndroid Build Coastguard Worker /*
662*8617a60dSAndroid Build Coastguard Worker * Creates a new manifest object by scanning files in archive.
663*8617a60dSAndroid Build Coastguard Worker * Returns the manifest on success, otherwise NULL for failure.
664*8617a60dSAndroid Build Coastguard Worker */
new_manifest_from_archive(struct u_archive * archive)665*8617a60dSAndroid Build Coastguard Worker struct manifest *new_manifest_from_archive(struct u_archive *archive)
666*8617a60dSAndroid Build Coastguard Worker {
667*8617a60dSAndroid Build Coastguard Worker int i;
668*8617a60dSAndroid Build Coastguard Worker struct manifest manifest = {0}, *new_manifest;
669*8617a60dSAndroid Build Coastguard Worker int (*manifest_builders[])(struct manifest *) = {
670*8617a60dSAndroid Build Coastguard Worker manifest_from_signer_config,
671*8617a60dSAndroid Build Coastguard Worker manifest_from_build_artifacts,
672*8617a60dSAndroid Build Coastguard Worker manifest_from_simple_folder,
673*8617a60dSAndroid Build Coastguard Worker };
674*8617a60dSAndroid Build Coastguard Worker
675*8617a60dSAndroid Build Coastguard Worker manifest.archive = archive;
676*8617a60dSAndroid Build Coastguard Worker manifest.default_model = -1;
677*8617a60dSAndroid Build Coastguard Worker
678*8617a60dSAndroid Build Coastguard Worker for (i = 0; !manifest.num && i < ARRAY_SIZE(manifest_builders); i++) {
679*8617a60dSAndroid Build Coastguard Worker /*
680*8617a60dSAndroid Build Coastguard Worker * For archives manually updated (for testing), it is possible a
681*8617a60dSAndroid Build Coastguard Worker * builder can successfully scan the archive but no valid models
682*8617a60dSAndroid Build Coastguard Worker * were found, so here we don't need to check the return value.
683*8617a60dSAndroid Build Coastguard Worker * Only stop when manifest.num is non-zero.
684*8617a60dSAndroid Build Coastguard Worker */
685*8617a60dSAndroid Build Coastguard Worker (void) manifest_builders[i](&manifest);
686*8617a60dSAndroid Build Coastguard Worker }
687*8617a60dSAndroid Build Coastguard Worker
688*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("%d model(s) loaded.\n", manifest.num);
689*8617a60dSAndroid Build Coastguard Worker if (!manifest.num) {
690*8617a60dSAndroid Build Coastguard Worker ERROR("No valid configurations found from the archive.\n");
691*8617a60dSAndroid Build Coastguard Worker return NULL;
692*8617a60dSAndroid Build Coastguard Worker }
693*8617a60dSAndroid Build Coastguard Worker
694*8617a60dSAndroid Build Coastguard Worker new_manifest = (struct manifest *)malloc(sizeof(manifest));
695*8617a60dSAndroid Build Coastguard Worker if (!new_manifest) {
696*8617a60dSAndroid Build Coastguard Worker ERROR("Internal error: memory allocation error.\n");
697*8617a60dSAndroid Build Coastguard Worker return NULL;
698*8617a60dSAndroid Build Coastguard Worker }
699*8617a60dSAndroid Build Coastguard Worker memcpy(new_manifest, &manifest, sizeof(manifest));
700*8617a60dSAndroid Build Coastguard Worker return new_manifest;
701*8617a60dSAndroid Build Coastguard Worker }
702*8617a60dSAndroid Build Coastguard Worker
703*8617a60dSAndroid Build Coastguard Worker /* Releases all resources allocated by given manifest object. */
delete_manifest(struct manifest * manifest)704*8617a60dSAndroid Build Coastguard Worker void delete_manifest(struct manifest *manifest)
705*8617a60dSAndroid Build Coastguard Worker {
706*8617a60dSAndroid Build Coastguard Worker int i;
707*8617a60dSAndroid Build Coastguard Worker assert(manifest);
708*8617a60dSAndroid Build Coastguard Worker for (i = 0; i < manifest->num; i++) {
709*8617a60dSAndroid Build Coastguard Worker struct model_config *model = &manifest->models[i];
710*8617a60dSAndroid Build Coastguard Worker free(model->name);
711*8617a60dSAndroid Build Coastguard Worker free(model->image);
712*8617a60dSAndroid Build Coastguard Worker free(model->ec_image);
713*8617a60dSAndroid Build Coastguard Worker clear_patch_config(&model->patches);
714*8617a60dSAndroid Build Coastguard Worker }
715*8617a60dSAndroid Build Coastguard Worker free(manifest->models);
716*8617a60dSAndroid Build Coastguard Worker free(manifest);
717*8617a60dSAndroid Build Coastguard Worker }
718*8617a60dSAndroid Build Coastguard Worker
get_gbb_key_hash(const struct vb2_gbb_header * gbb,int32_t offset,int32_t size)719*8617a60dSAndroid Build Coastguard Worker static const char *get_gbb_key_hash(const struct vb2_gbb_header *gbb,
720*8617a60dSAndroid Build Coastguard Worker int32_t offset, int32_t size)
721*8617a60dSAndroid Build Coastguard Worker {
722*8617a60dSAndroid Build Coastguard Worker struct vb2_packed_key *key;
723*8617a60dSAndroid Build Coastguard Worker
724*8617a60dSAndroid Build Coastguard Worker if (!gbb)
725*8617a60dSAndroid Build Coastguard Worker return "<No GBB>";
726*8617a60dSAndroid Build Coastguard Worker key = (struct vb2_packed_key *)((uint8_t *)gbb + offset);
727*8617a60dSAndroid Build Coastguard Worker if (vb2_packed_key_looks_ok(key, size))
728*8617a60dSAndroid Build Coastguard Worker return "<Invalid key>";
729*8617a60dSAndroid Build Coastguard Worker return packed_key_sha1_string(key);
730*8617a60dSAndroid Build Coastguard Worker }
731*8617a60dSAndroid Build Coastguard Worker
732*8617a60dSAndroid Build Coastguard Worker /* Prints the information of given image file in JSON format. */
print_json_image(const char * name,const char * fpath,struct model_config * m,struct u_archive * archive,int indent,int is_host,bool is_first)733*8617a60dSAndroid Build Coastguard Worker static void print_json_image(
734*8617a60dSAndroid Build Coastguard Worker const char *name, const char *fpath, struct model_config *m,
735*8617a60dSAndroid Build Coastguard Worker struct u_archive *archive, int indent, int is_host,
736*8617a60dSAndroid Build Coastguard Worker bool is_first)
737*8617a60dSAndroid Build Coastguard Worker {
738*8617a60dSAndroid Build Coastguard Worker struct firmware_image image = {0};
739*8617a60dSAndroid Build Coastguard Worker const struct vb2_gbb_header *gbb = NULL;
740*8617a60dSAndroid Build Coastguard Worker if (!fpath)
741*8617a60dSAndroid Build Coastguard Worker return;
742*8617a60dSAndroid Build Coastguard Worker if (load_firmware_image(&image, fpath, archive))
743*8617a60dSAndroid Build Coastguard Worker return;
744*8617a60dSAndroid Build Coastguard Worker if (!is_first)
745*8617a60dSAndroid Build Coastguard Worker printf(",\n");
746*8617a60dSAndroid Build Coastguard Worker printf("%*s\"%s\": {", indent, "", name);
747*8617a60dSAndroid Build Coastguard Worker indent += 2;
748*8617a60dSAndroid Build Coastguard Worker printf("\n%*s\"versions\": {", indent, "");
749*8617a60dSAndroid Build Coastguard Worker indent += 2;
750*8617a60dSAndroid Build Coastguard Worker printf("\n%*s\"ro\": \"%s\"", indent, "", image.ro_version);
751*8617a60dSAndroid Build Coastguard Worker printf(",\n%*s\"rw\": \"%s\"", indent, "", image.rw_version_a);
752*8617a60dSAndroid Build Coastguard Worker if (is_host && image.ecrw_version_a[0] != '\0')
753*8617a60dSAndroid Build Coastguard Worker printf(",\n%*s\"ecrw\": \"%s\"", indent, "",
754*8617a60dSAndroid Build Coastguard Worker image.ecrw_version_a);
755*8617a60dSAndroid Build Coastguard Worker indent -= 2;
756*8617a60dSAndroid Build Coastguard Worker printf("\n%*s},", indent, "");
757*8617a60dSAndroid Build Coastguard Worker if (is_host) {
758*8617a60dSAndroid Build Coastguard Worker if (patch_image_by_model(&image, m, archive))
759*8617a60dSAndroid Build Coastguard Worker ERROR("Failed to patch images by model: %s\n", m->name);
760*8617a60dSAndroid Build Coastguard Worker else
761*8617a60dSAndroid Build Coastguard Worker gbb = find_gbb(&image);
762*8617a60dSAndroid Build Coastguard Worker }
763*8617a60dSAndroid Build Coastguard Worker if (gbb != NULL) {
764*8617a60dSAndroid Build Coastguard Worker printf("\n%*s\"keys\": { \"root\": \"%s\", ",
765*8617a60dSAndroid Build Coastguard Worker indent, "",
766*8617a60dSAndroid Build Coastguard Worker get_gbb_key_hash(gbb, gbb->rootkey_offset,
767*8617a60dSAndroid Build Coastguard Worker gbb->rootkey_size));
768*8617a60dSAndroid Build Coastguard Worker printf("\"recovery\": \"%s\" },",
769*8617a60dSAndroid Build Coastguard Worker get_gbb_key_hash(gbb, gbb->recovery_key_offset,
770*8617a60dSAndroid Build Coastguard Worker gbb->recovery_key_size));
771*8617a60dSAndroid Build Coastguard Worker }
772*8617a60dSAndroid Build Coastguard Worker printf("\n%*s\"image\": \"%s\"", indent, "", fpath);
773*8617a60dSAndroid Build Coastguard Worker indent -= 2;
774*8617a60dSAndroid Build Coastguard Worker printf("\n%*s}", indent, "");
775*8617a60dSAndroid Build Coastguard Worker check_firmware_versions(&image);
776*8617a60dSAndroid Build Coastguard Worker free_firmware_image(&image);
777*8617a60dSAndroid Build Coastguard Worker }
778*8617a60dSAndroid Build Coastguard Worker
779*8617a60dSAndroid Build Coastguard Worker /* Prints the information of objects in manifest (models and images) in JSON. */
print_json_manifest(const struct manifest * manifest)780*8617a60dSAndroid Build Coastguard Worker void print_json_manifest(const struct manifest *manifest)
781*8617a60dSAndroid Build Coastguard Worker {
782*8617a60dSAndroid Build Coastguard Worker int i, j, indent;
783*8617a60dSAndroid Build Coastguard Worker struct u_archive *ar = manifest->archive;
784*8617a60dSAndroid Build Coastguard Worker
785*8617a60dSAndroid Build Coastguard Worker printf("{\n");
786*8617a60dSAndroid Build Coastguard Worker for (i = 0, indent = 2; i < manifest->num; i++) {
787*8617a60dSAndroid Build Coastguard Worker struct model_config *m = &manifest->models[i];
788*8617a60dSAndroid Build Coastguard Worker struct {
789*8617a60dSAndroid Build Coastguard Worker const char *name;
790*8617a60dSAndroid Build Coastguard Worker const char *fpath;
791*8617a60dSAndroid Build Coastguard Worker bool is_host;
792*8617a60dSAndroid Build Coastguard Worker } images[] = {
793*8617a60dSAndroid Build Coastguard Worker {"host", m->image, true},
794*8617a60dSAndroid Build Coastguard Worker {"ec", m->ec_image},
795*8617a60dSAndroid Build Coastguard Worker };
796*8617a60dSAndroid Build Coastguard Worker bool is_first = true;
797*8617a60dSAndroid Build Coastguard Worker printf("%s%*s\"%s\": {\n", i ? ",\n" : "", indent, "", m->name);
798*8617a60dSAndroid Build Coastguard Worker indent += 2;
799*8617a60dSAndroid Build Coastguard Worker for (j = 0; j < ARRAY_SIZE(images); j++) {
800*8617a60dSAndroid Build Coastguard Worker if (!images[j].fpath)
801*8617a60dSAndroid Build Coastguard Worker continue;
802*8617a60dSAndroid Build Coastguard Worker print_json_image(images[j].name, images[j].fpath, m, ar,
803*8617a60dSAndroid Build Coastguard Worker indent, images[j].is_host, is_first);
804*8617a60dSAndroid Build Coastguard Worker is_first = false;
805*8617a60dSAndroid Build Coastguard Worker }
806*8617a60dSAndroid Build Coastguard Worker if (m->patches.rootkey) {
807*8617a60dSAndroid Build Coastguard Worker struct patch_config *p = &m->patches;
808*8617a60dSAndroid Build Coastguard Worker printf(",\n%*s\"patches\": { \"rootkey\": \"%s\", "
809*8617a60dSAndroid Build Coastguard Worker "\"vblock_a\": \"%s\", \"vblock_b\": \"%s\"",
810*8617a60dSAndroid Build Coastguard Worker indent, "", p->rootkey, p->vblock_a,
811*8617a60dSAndroid Build Coastguard Worker p->vblock_b);
812*8617a60dSAndroid Build Coastguard Worker if (p->gscvd)
813*8617a60dSAndroid Build Coastguard Worker printf(", \"gscvd\": \"%s\"", p->gscvd);
814*8617a60dSAndroid Build Coastguard Worker printf(" }");
815*8617a60dSAndroid Build Coastguard Worker }
816*8617a60dSAndroid Build Coastguard Worker printf("\n }");
817*8617a60dSAndroid Build Coastguard Worker indent -= 2;
818*8617a60dSAndroid Build Coastguard Worker assert(indent == 2);
819*8617a60dSAndroid Build Coastguard Worker }
820*8617a60dSAndroid Build Coastguard Worker printf("\n}\n");
821*8617a60dSAndroid Build Coastguard Worker }
822