1*8617a60dSAndroid Build Coastguard Worker /* Copyright 2019 The ChromiumOS Authors
2*8617a60dSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
3*8617a60dSAndroid Build Coastguard Worker * found in the LICENSE file.
4*8617a60dSAndroid Build Coastguard Worker *
5*8617a60dSAndroid Build Coastguard Worker * The utility functions for 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 <limits.h>
10*8617a60dSAndroid Build Coastguard Worker #include <stdbool.h>
11*8617a60dSAndroid Build Coastguard Worker #include <sys/stat.h>
12*8617a60dSAndroid Build Coastguard Worker #include <sys/types.h>
13*8617a60dSAndroid Build Coastguard Worker #include <string.h>
14*8617a60dSAndroid Build Coastguard Worker #include <unistd.h>
15*8617a60dSAndroid Build Coastguard Worker #if defined (__FreeBSD__) || defined(__OpenBSD__)
16*8617a60dSAndroid Build Coastguard Worker #include <sys/wait.h>
17*8617a60dSAndroid Build Coastguard Worker #endif
18*8617a60dSAndroid Build Coastguard Worker
19*8617a60dSAndroid Build Coastguard Worker #include "2common.h"
20*8617a60dSAndroid Build Coastguard Worker #include "cbfstool.h"
21*8617a60dSAndroid Build Coastguard Worker #include "host_misc.h"
22*8617a60dSAndroid Build Coastguard Worker #include "util_misc.h"
23*8617a60dSAndroid Build Coastguard Worker #include "updater.h"
24*8617a60dSAndroid Build Coastguard Worker
25*8617a60dSAndroid Build Coastguard Worker #define COMMAND_BUFFER_SIZE 256
26*8617a60dSAndroid Build Coastguard Worker
strip_string(char * s,const char * pattern)27*8617a60dSAndroid Build Coastguard Worker void strip_string(char *s, const char *pattern)
28*8617a60dSAndroid Build Coastguard Worker {
29*8617a60dSAndroid Build Coastguard Worker int len;
30*8617a60dSAndroid Build Coastguard Worker assert(s);
31*8617a60dSAndroid Build Coastguard Worker
32*8617a60dSAndroid Build Coastguard Worker len = strlen(s);
33*8617a60dSAndroid Build Coastguard Worker while (len-- > 0) {
34*8617a60dSAndroid Build Coastguard Worker if (pattern) {
35*8617a60dSAndroid Build Coastguard Worker if (!strchr(pattern, s[len]))
36*8617a60dSAndroid Build Coastguard Worker break;
37*8617a60dSAndroid Build Coastguard Worker } else {
38*8617a60dSAndroid Build Coastguard Worker if (!isascii(s[len]) || !isspace(s[len]))
39*8617a60dSAndroid Build Coastguard Worker break;
40*8617a60dSAndroid Build Coastguard Worker }
41*8617a60dSAndroid Build Coastguard Worker s[len] = '\0';
42*8617a60dSAndroid Build Coastguard Worker }
43*8617a60dSAndroid Build Coastguard Worker }
44*8617a60dSAndroid Build Coastguard Worker
save_file_from_stdin(const char * output)45*8617a60dSAndroid Build Coastguard Worker int save_file_from_stdin(const char *output)
46*8617a60dSAndroid Build Coastguard Worker {
47*8617a60dSAndroid Build Coastguard Worker FILE *in = stdin, *out = fopen(output, "wb");
48*8617a60dSAndroid Build Coastguard Worker char buffer[4096];
49*8617a60dSAndroid Build Coastguard Worker size_t sz;
50*8617a60dSAndroid Build Coastguard Worker
51*8617a60dSAndroid Build Coastguard Worker assert(in);
52*8617a60dSAndroid Build Coastguard Worker if (!out)
53*8617a60dSAndroid Build Coastguard Worker return -1;
54*8617a60dSAndroid Build Coastguard Worker
55*8617a60dSAndroid Build Coastguard Worker while (!feof(in)) {
56*8617a60dSAndroid Build Coastguard Worker sz = fread(buffer, 1, sizeof(buffer), in);
57*8617a60dSAndroid Build Coastguard Worker if (fwrite(buffer, 1, sz, out) != sz) {
58*8617a60dSAndroid Build Coastguard Worker fclose(out);
59*8617a60dSAndroid Build Coastguard Worker return -1;
60*8617a60dSAndroid Build Coastguard Worker }
61*8617a60dSAndroid Build Coastguard Worker }
62*8617a60dSAndroid Build Coastguard Worker fclose(out);
63*8617a60dSAndroid Build Coastguard Worker return 0;
64*8617a60dSAndroid Build Coastguard Worker }
65*8617a60dSAndroid Build Coastguard Worker
66*8617a60dSAndroid Build Coastguard Worker /*
67*8617a60dSAndroid Build Coastguard Worker * Loads the firmware information from an FMAP section in loaded firmware image.
68*8617a60dSAndroid Build Coastguard Worker * The section should only contain ASCIIZ string as firmware version.
69*8617a60dSAndroid Build Coastguard Worker * Returns 0 if a non-empty version string is stored in *version, otherwise -1.
70*8617a60dSAndroid Build Coastguard Worker */
load_firmware_version(struct firmware_image * image,const char * section_name,char ** version)71*8617a60dSAndroid Build Coastguard Worker static int load_firmware_version(struct firmware_image *image,
72*8617a60dSAndroid Build Coastguard Worker const char *section_name,
73*8617a60dSAndroid Build Coastguard Worker char **version)
74*8617a60dSAndroid Build Coastguard Worker {
75*8617a60dSAndroid Build Coastguard Worker struct firmware_section fwid;
76*8617a60dSAndroid Build Coastguard Worker int len = 0;
77*8617a60dSAndroid Build Coastguard Worker
78*8617a60dSAndroid Build Coastguard Worker /*
79*8617a60dSAndroid Build Coastguard Worker * section_name is NULL when parsing the RW versions on a non-vboot
80*8617a60dSAndroid Build Coastguard Worker * image (and already warned in load_firmware_image). We still need to
81*8617a60dSAndroid Build Coastguard Worker * initialize *version with empty string.
82*8617a60dSAndroid Build Coastguard Worker */
83*8617a60dSAndroid Build Coastguard Worker if (section_name) {
84*8617a60dSAndroid Build Coastguard Worker find_firmware_section(&fwid, image, section_name);
85*8617a60dSAndroid Build Coastguard Worker if (fwid.size)
86*8617a60dSAndroid Build Coastguard Worker len = fwid.size;
87*8617a60dSAndroid Build Coastguard Worker else
88*8617a60dSAndroid Build Coastguard Worker WARN("No valid section '%s', missing version info.\n",
89*8617a60dSAndroid Build Coastguard Worker section_name);
90*8617a60dSAndroid Build Coastguard Worker }
91*8617a60dSAndroid Build Coastguard Worker
92*8617a60dSAndroid Build Coastguard Worker if (!len) {
93*8617a60dSAndroid Build Coastguard Worker *version = strdup("");
94*8617a60dSAndroid Build Coastguard Worker return -1;
95*8617a60dSAndroid Build Coastguard Worker }
96*8617a60dSAndroid Build Coastguard Worker
97*8617a60dSAndroid Build Coastguard Worker /*
98*8617a60dSAndroid Build Coastguard Worker * For 'system current' images, the version string may contain
99*8617a60dSAndroid Build Coastguard Worker * invalid characters that we do want to strip.
100*8617a60dSAndroid Build Coastguard Worker */
101*8617a60dSAndroid Build Coastguard Worker *version = strndup((const char *)fwid.data, len);
102*8617a60dSAndroid Build Coastguard Worker strip_string(*version, "\xff");
103*8617a60dSAndroid Build Coastguard Worker return 0;
104*8617a60dSAndroid Build Coastguard Worker }
105*8617a60dSAndroid Build Coastguard Worker
has_printable_ecrw_version(const struct firmware_image * image)106*8617a60dSAndroid Build Coastguard Worker static bool has_printable_ecrw_version(const struct firmware_image *image)
107*8617a60dSAndroid Build Coastguard Worker {
108*8617a60dSAndroid Build Coastguard Worker /*
109*8617a60dSAndroid Build Coastguard Worker * Wilco family (sarien & drallion) has binary ecrw version which may
110*8617a60dSAndroid Build Coastguard Worker * contain non-printable characters. Those images can be identified by
111*8617a60dSAndroid Build Coastguard Worker * checking if the DIAG_NVRAM FMAP section exists or not.
112*8617a60dSAndroid Build Coastguard Worker */
113*8617a60dSAndroid Build Coastguard Worker return !firmware_section_exists(image, FMAP_RW_DIAG_NVRAM);
114*8617a60dSAndroid Build Coastguard Worker }
115*8617a60dSAndroid Build Coastguard Worker
116*8617a60dSAndroid Build Coastguard Worker /*
117*8617a60dSAndroid Build Coastguard Worker * Loads the version of "ecrw" CBFS file within `section_name` of `image_file`.
118*8617a60dSAndroid Build Coastguard Worker * Returns the version string on success; otherwise an empty string.
119*8617a60dSAndroid Build Coastguard Worker */
load_ecrw_version(const struct firmware_image * image,const char * image_file,const char * section_name)120*8617a60dSAndroid Build Coastguard Worker static char *load_ecrw_version(const struct firmware_image *image,
121*8617a60dSAndroid Build Coastguard Worker const char *image_file,
122*8617a60dSAndroid Build Coastguard Worker const char *section_name)
123*8617a60dSAndroid Build Coastguard Worker {
124*8617a60dSAndroid Build Coastguard Worker char *version = NULL;
125*8617a60dSAndroid Build Coastguard Worker struct tempfile tempfile_head = {0};
126*8617a60dSAndroid Build Coastguard Worker
127*8617a60dSAndroid Build Coastguard Worker /* EC image or older AP images may not have the section. */
128*8617a60dSAndroid Build Coastguard Worker if (!firmware_section_exists(image, section_name))
129*8617a60dSAndroid Build Coastguard Worker goto done;
130*8617a60dSAndroid Build Coastguard Worker
131*8617a60dSAndroid Build Coastguard Worker if (!has_printable_ecrw_version(image))
132*8617a60dSAndroid Build Coastguard Worker goto done;
133*8617a60dSAndroid Build Coastguard Worker
134*8617a60dSAndroid Build Coastguard Worker const char *ecrw_version_file = create_temp_file(&tempfile_head);
135*8617a60dSAndroid Build Coastguard Worker if (!ecrw_version_file)
136*8617a60dSAndroid Build Coastguard Worker goto done;
137*8617a60dSAndroid Build Coastguard Worker
138*8617a60dSAndroid Build Coastguard Worker /* "ecrw.version" doesn't exist in old images. */
139*8617a60dSAndroid Build Coastguard Worker const char *ecrw_version_name = "ecrw.version";
140*8617a60dSAndroid Build Coastguard Worker if (!cbfstool_file_exists(image_file, section_name, ecrw_version_name))
141*8617a60dSAndroid Build Coastguard Worker goto done;
142*8617a60dSAndroid Build Coastguard Worker
143*8617a60dSAndroid Build Coastguard Worker if (cbfstool_extract(image_file, section_name, ecrw_version_name,
144*8617a60dSAndroid Build Coastguard Worker ecrw_version_file)) {
145*8617a60dSAndroid Build Coastguard Worker ERROR("Failed to extract %s from %s\n",
146*8617a60dSAndroid Build Coastguard Worker ecrw_version_name, section_name);
147*8617a60dSAndroid Build Coastguard Worker goto done;
148*8617a60dSAndroid Build Coastguard Worker }
149*8617a60dSAndroid Build Coastguard Worker
150*8617a60dSAndroid Build Coastguard Worker uint8_t *data;
151*8617a60dSAndroid Build Coastguard Worker uint32_t size;
152*8617a60dSAndroid Build Coastguard Worker if (vb2_read_file(ecrw_version_file, &data, &size) != VB2_SUCCESS)
153*8617a60dSAndroid Build Coastguard Worker goto done;
154*8617a60dSAndroid Build Coastguard Worker
155*8617a60dSAndroid Build Coastguard Worker version = strndup((const char *)data, size);
156*8617a60dSAndroid Build Coastguard Worker
157*8617a60dSAndroid Build Coastguard Worker done:
158*8617a60dSAndroid Build Coastguard Worker if (!version)
159*8617a60dSAndroid Build Coastguard Worker version = strdup("");
160*8617a60dSAndroid Build Coastguard Worker remove_all_temp_files(&tempfile_head);
161*8617a60dSAndroid Build Coastguard Worker return version;
162*8617a60dSAndroid Build Coastguard Worker }
163*8617a60dSAndroid Build Coastguard Worker
164*8617a60dSAndroid Build Coastguard Worker /* Loads the version of "ecrw" CBFS file for FW_MAIN_A and FW_MAIN_B. */
load_ecrw_versions(struct firmware_image * image)165*8617a60dSAndroid Build Coastguard Worker static void load_ecrw_versions(struct firmware_image *image)
166*8617a60dSAndroid Build Coastguard Worker {
167*8617a60dSAndroid Build Coastguard Worker struct tempfile tempfile_head = {0};
168*8617a60dSAndroid Build Coastguard Worker const char *image_file = get_firmware_image_temp_file(
169*8617a60dSAndroid Build Coastguard Worker image, &tempfile_head);
170*8617a60dSAndroid Build Coastguard Worker
171*8617a60dSAndroid Build Coastguard Worker if (image_file) {
172*8617a60dSAndroid Build Coastguard Worker image->ecrw_version_a = load_ecrw_version(
173*8617a60dSAndroid Build Coastguard Worker image, image_file, FMAP_RW_FW_MAIN_A);
174*8617a60dSAndroid Build Coastguard Worker image->ecrw_version_b = load_ecrw_version(
175*8617a60dSAndroid Build Coastguard Worker image, image_file, FMAP_RW_FW_MAIN_B);
176*8617a60dSAndroid Build Coastguard Worker }
177*8617a60dSAndroid Build Coastguard Worker
178*8617a60dSAndroid Build Coastguard Worker remove_all_temp_files(&tempfile_head);
179*8617a60dSAndroid Build Coastguard Worker }
180*8617a60dSAndroid Build Coastguard Worker
181*8617a60dSAndroid Build Coastguard Worker /*
182*8617a60dSAndroid Build Coastguard Worker * Fills in the other fields of image using image->data.
183*8617a60dSAndroid Build Coastguard Worker * Returns IMAGE_LOAD_SUCCESS or IMAGE_PARSE_FAILURE.
184*8617a60dSAndroid Build Coastguard Worker */
parse_firmware_image(struct firmware_image * image)185*8617a60dSAndroid Build Coastguard Worker static int parse_firmware_image(struct firmware_image *image)
186*8617a60dSAndroid Build Coastguard Worker {
187*8617a60dSAndroid Build Coastguard Worker int ret = IMAGE_LOAD_SUCCESS;
188*8617a60dSAndroid Build Coastguard Worker const char *section_a = NULL, *section_b = NULL;
189*8617a60dSAndroid Build Coastguard Worker
190*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Image size: %d\n", image->size);
191*8617a60dSAndroid Build Coastguard Worker assert(image->data);
192*8617a60dSAndroid Build Coastguard Worker
193*8617a60dSAndroid Build Coastguard Worker image->fmap_header = fmap_find(image->data, image->size);
194*8617a60dSAndroid Build Coastguard Worker
195*8617a60dSAndroid Build Coastguard Worker if (!image->fmap_header) {
196*8617a60dSAndroid Build Coastguard Worker ERROR("Invalid image file (missing FMAP): %s\n", image->file_name);
197*8617a60dSAndroid Build Coastguard Worker ret = IMAGE_PARSE_FAILURE;
198*8617a60dSAndroid Build Coastguard Worker }
199*8617a60dSAndroid Build Coastguard Worker
200*8617a60dSAndroid Build Coastguard Worker if (load_firmware_version(image, FMAP_RO_FRID, &image->ro_version))
201*8617a60dSAndroid Build Coastguard Worker ret = IMAGE_PARSE_FAILURE;
202*8617a60dSAndroid Build Coastguard Worker
203*8617a60dSAndroid Build Coastguard Worker if (firmware_section_exists(image, FMAP_RW_FWID_A)) {
204*8617a60dSAndroid Build Coastguard Worker section_a = FMAP_RW_FWID_A;
205*8617a60dSAndroid Build Coastguard Worker section_b = FMAP_RW_FWID_B;
206*8617a60dSAndroid Build Coastguard Worker } else if (firmware_section_exists(image, FMAP_RW_FWID)) {
207*8617a60dSAndroid Build Coastguard Worker section_a = FMAP_RW_FWID;
208*8617a60dSAndroid Build Coastguard Worker section_b = FMAP_RW_FWID;
209*8617a60dSAndroid Build Coastguard Worker } else if (!ret) {
210*8617a60dSAndroid Build Coastguard Worker ERROR("Unsupported VBoot firmware (no RW ID): %s\n", image->file_name);
211*8617a60dSAndroid Build Coastguard Worker ret = IMAGE_PARSE_FAILURE;
212*8617a60dSAndroid Build Coastguard Worker }
213*8617a60dSAndroid Build Coastguard Worker
214*8617a60dSAndroid Build Coastguard Worker /*
215*8617a60dSAndroid Build Coastguard Worker * Load and initialize both RW A and B sections.
216*8617a60dSAndroid Build Coastguard Worker * Note some unit tests will create only RW A.
217*8617a60dSAndroid Build Coastguard Worker */
218*8617a60dSAndroid Build Coastguard Worker load_firmware_version(image, section_a, &image->rw_version_a);
219*8617a60dSAndroid Build Coastguard Worker load_firmware_version(image, section_b, &image->rw_version_b);
220*8617a60dSAndroid Build Coastguard Worker
221*8617a60dSAndroid Build Coastguard Worker load_ecrw_versions(image);
222*8617a60dSAndroid Build Coastguard Worker
223*8617a60dSAndroid Build Coastguard Worker return ret;
224*8617a60dSAndroid Build Coastguard Worker }
225*8617a60dSAndroid Build Coastguard Worker
load_firmware_image(struct firmware_image * image,const char * file_name,struct u_archive * archive)226*8617a60dSAndroid Build Coastguard Worker int load_firmware_image(struct firmware_image *image, const char *file_name,
227*8617a60dSAndroid Build Coastguard Worker struct u_archive *archive)
228*8617a60dSAndroid Build Coastguard Worker {
229*8617a60dSAndroid Build Coastguard Worker if (!file_name) {
230*8617a60dSAndroid Build Coastguard Worker ERROR("No file name given\n");
231*8617a60dSAndroid Build Coastguard Worker return IMAGE_READ_FAILURE;
232*8617a60dSAndroid Build Coastguard Worker }
233*8617a60dSAndroid Build Coastguard Worker
234*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Load image file from %s...\n", file_name);
235*8617a60dSAndroid Build Coastguard Worker
236*8617a60dSAndroid Build Coastguard Worker if (!archive_has_entry(archive, file_name)) {
237*8617a60dSAndroid Build Coastguard Worker ERROR("Does not exist: %s\n", file_name);
238*8617a60dSAndroid Build Coastguard Worker return IMAGE_READ_FAILURE;
239*8617a60dSAndroid Build Coastguard Worker }
240*8617a60dSAndroid Build Coastguard Worker if (archive_read_file(archive, file_name, &image->data, &image->size,
241*8617a60dSAndroid Build Coastguard Worker NULL) != VB2_SUCCESS) {
242*8617a60dSAndroid Build Coastguard Worker ERROR("Failed to load %s\n", file_name);
243*8617a60dSAndroid Build Coastguard Worker return IMAGE_READ_FAILURE;
244*8617a60dSAndroid Build Coastguard Worker }
245*8617a60dSAndroid Build Coastguard Worker
246*8617a60dSAndroid Build Coastguard Worker image->file_name = strdup(file_name);
247*8617a60dSAndroid Build Coastguard Worker
248*8617a60dSAndroid Build Coastguard Worker return parse_firmware_image(image);
249*8617a60dSAndroid Build Coastguard Worker }
250*8617a60dSAndroid Build Coastguard Worker
check_firmware_versions(const struct firmware_image * image)251*8617a60dSAndroid Build Coastguard Worker void check_firmware_versions(const struct firmware_image *image)
252*8617a60dSAndroid Build Coastguard Worker {
253*8617a60dSAndroid Build Coastguard Worker if (strcmp(image->rw_version_a, image->rw_version_b))
254*8617a60dSAndroid Build Coastguard Worker WARN("Different versions in %s (%s) and %s (%s).\n",
255*8617a60dSAndroid Build Coastguard Worker FMAP_RW_FWID_A, image->rw_version_a,
256*8617a60dSAndroid Build Coastguard Worker FMAP_RW_FWID_B, image->rw_version_b);
257*8617a60dSAndroid Build Coastguard Worker if (image->ecrw_version_a && image->ecrw_version_b &&
258*8617a60dSAndroid Build Coastguard Worker strcmp(image->ecrw_version_a, image->ecrw_version_b))
259*8617a60dSAndroid Build Coastguard Worker WARN("Different ecrw versions in %s (%s) and %s (%s).\n",
260*8617a60dSAndroid Build Coastguard Worker FMAP_RW_FW_MAIN_A, image->ecrw_version_a,
261*8617a60dSAndroid Build Coastguard Worker FMAP_RW_FW_MAIN_B, image->ecrw_version_b);
262*8617a60dSAndroid Build Coastguard Worker }
263*8617a60dSAndroid Build Coastguard Worker
get_firmware_image_temp_file(const struct firmware_image * image,struct tempfile * tempfiles)264*8617a60dSAndroid Build Coastguard Worker const char *get_firmware_image_temp_file(const struct firmware_image *image,
265*8617a60dSAndroid Build Coastguard Worker struct tempfile *tempfiles)
266*8617a60dSAndroid Build Coastguard Worker {
267*8617a60dSAndroid Build Coastguard Worker const char *tmp_path = create_temp_file(tempfiles);
268*8617a60dSAndroid Build Coastguard Worker if (!tmp_path)
269*8617a60dSAndroid Build Coastguard Worker return NULL;
270*8617a60dSAndroid Build Coastguard Worker
271*8617a60dSAndroid Build Coastguard Worker if (vb2_write_file(tmp_path, image->data, image->size) != VB2_SUCCESS) {
272*8617a60dSAndroid Build Coastguard Worker ERROR("Failed writing %s firmware image (%u bytes) to %s.\n",
273*8617a60dSAndroid Build Coastguard Worker image->programmer ? image->programmer : "temp",
274*8617a60dSAndroid Build Coastguard Worker image->size, tmp_path);
275*8617a60dSAndroid Build Coastguard Worker return NULL;
276*8617a60dSAndroid Build Coastguard Worker }
277*8617a60dSAndroid Build Coastguard Worker return tmp_path;
278*8617a60dSAndroid Build Coastguard Worker }
279*8617a60dSAndroid Build Coastguard Worker
free_firmware_image(struct firmware_image * image)280*8617a60dSAndroid Build Coastguard Worker void free_firmware_image(struct firmware_image *image)
281*8617a60dSAndroid Build Coastguard Worker {
282*8617a60dSAndroid Build Coastguard Worker /*
283*8617a60dSAndroid Build Coastguard Worker * The programmer is not allocated by load_firmware_image and must be
284*8617a60dSAndroid Build Coastguard Worker * preserved explicitly.
285*8617a60dSAndroid Build Coastguard Worker */
286*8617a60dSAndroid Build Coastguard Worker const char *programmer = image->programmer;
287*8617a60dSAndroid Build Coastguard Worker
288*8617a60dSAndroid Build Coastguard Worker free(image->data);
289*8617a60dSAndroid Build Coastguard Worker free(image->file_name);
290*8617a60dSAndroid Build Coastguard Worker free(image->ro_version);
291*8617a60dSAndroid Build Coastguard Worker free(image->rw_version_a);
292*8617a60dSAndroid Build Coastguard Worker free(image->rw_version_b);
293*8617a60dSAndroid Build Coastguard Worker free(image->ecrw_version_a);
294*8617a60dSAndroid Build Coastguard Worker free(image->ecrw_version_b);
295*8617a60dSAndroid Build Coastguard Worker memset(image, 0, sizeof(*image));
296*8617a60dSAndroid Build Coastguard Worker image->programmer = programmer;
297*8617a60dSAndroid Build Coastguard Worker }
298*8617a60dSAndroid Build Coastguard Worker
reload_firmware_image(const char * file_path,struct firmware_image * image)299*8617a60dSAndroid Build Coastguard Worker int reload_firmware_image(const char *file_path, struct firmware_image *image)
300*8617a60dSAndroid Build Coastguard Worker {
301*8617a60dSAndroid Build Coastguard Worker free_firmware_image(image);
302*8617a60dSAndroid Build Coastguard Worker return load_firmware_image(image, file_path, NULL);
303*8617a60dSAndroid Build Coastguard Worker }
304*8617a60dSAndroid Build Coastguard Worker
find_firmware_section(struct firmware_section * section,const struct firmware_image * image,const char * section_name)305*8617a60dSAndroid Build Coastguard Worker int find_firmware_section(struct firmware_section *section,
306*8617a60dSAndroid Build Coastguard Worker const struct firmware_image *image,
307*8617a60dSAndroid Build Coastguard Worker const char *section_name)
308*8617a60dSAndroid Build Coastguard Worker {
309*8617a60dSAndroid Build Coastguard Worker FmapAreaHeader *fah = NULL;
310*8617a60dSAndroid Build Coastguard Worker uint8_t *ptr;
311*8617a60dSAndroid Build Coastguard Worker
312*8617a60dSAndroid Build Coastguard Worker section->data = NULL;
313*8617a60dSAndroid Build Coastguard Worker section->size = 0;
314*8617a60dSAndroid Build Coastguard Worker ptr = fmap_find_by_name(
315*8617a60dSAndroid Build Coastguard Worker image->data, image->size, image->fmap_header,
316*8617a60dSAndroid Build Coastguard Worker section_name, &fah);
317*8617a60dSAndroid Build Coastguard Worker if (!ptr)
318*8617a60dSAndroid Build Coastguard Worker return -1;
319*8617a60dSAndroid Build Coastguard Worker section->data = (uint8_t *)ptr;
320*8617a60dSAndroid Build Coastguard Worker section->size = fah->area_size;
321*8617a60dSAndroid Build Coastguard Worker return 0;
322*8617a60dSAndroid Build Coastguard Worker }
323*8617a60dSAndroid Build Coastguard Worker
firmware_section_exists(const struct firmware_image * image,const char * section_name)324*8617a60dSAndroid Build Coastguard Worker int firmware_section_exists(const struct firmware_image *image,
325*8617a60dSAndroid Build Coastguard Worker const char *section_name)
326*8617a60dSAndroid Build Coastguard Worker {
327*8617a60dSAndroid Build Coastguard Worker struct firmware_section section;
328*8617a60dSAndroid Build Coastguard Worker find_firmware_section(§ion, image, section_name);
329*8617a60dSAndroid Build Coastguard Worker return section.data != NULL;
330*8617a60dSAndroid Build Coastguard Worker }
331*8617a60dSAndroid Build Coastguard Worker
preserve_firmware_section(const struct firmware_image * image_from,struct firmware_image * image_to,const char * section_name)332*8617a60dSAndroid Build Coastguard Worker int preserve_firmware_section(const struct firmware_image *image_from,
333*8617a60dSAndroid Build Coastguard Worker struct firmware_image *image_to,
334*8617a60dSAndroid Build Coastguard Worker const char *section_name)
335*8617a60dSAndroid Build Coastguard Worker {
336*8617a60dSAndroid Build Coastguard Worker struct firmware_section from, to;
337*8617a60dSAndroid Build Coastguard Worker
338*8617a60dSAndroid Build Coastguard Worker find_firmware_section(&from, image_from, section_name);
339*8617a60dSAndroid Build Coastguard Worker find_firmware_section(&to, image_to, section_name);
340*8617a60dSAndroid Build Coastguard Worker if (!from.data || !to.data) {
341*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Cannot find section %.*s: from=%p, to=%p\n",
342*8617a60dSAndroid Build Coastguard Worker FMAP_NAMELEN, section_name, from.data, to.data);
343*8617a60dSAndroid Build Coastguard Worker return -1;
344*8617a60dSAndroid Build Coastguard Worker }
345*8617a60dSAndroid Build Coastguard Worker if (from.size > to.size) {
346*8617a60dSAndroid Build Coastguard Worker WARN("Section %.*s is truncated after updated.\n",
347*8617a60dSAndroid Build Coastguard Worker FMAP_NAMELEN, section_name);
348*8617a60dSAndroid Build Coastguard Worker }
349*8617a60dSAndroid Build Coastguard Worker /* Use memmove in case if we need to deal with sections that overlap. */
350*8617a60dSAndroid Build Coastguard Worker memmove(to.data, from.data, VB2_MIN(from.size, to.size));
351*8617a60dSAndroid Build Coastguard Worker return 0;
352*8617a60dSAndroid Build Coastguard Worker }
353*8617a60dSAndroid Build Coastguard Worker
find_gbb(const struct firmware_image * image)354*8617a60dSAndroid Build Coastguard Worker const struct vb2_gbb_header *find_gbb(const struct firmware_image *image)
355*8617a60dSAndroid Build Coastguard Worker {
356*8617a60dSAndroid Build Coastguard Worker struct firmware_section section;
357*8617a60dSAndroid Build Coastguard Worker struct vb2_gbb_header *gbb_header;
358*8617a60dSAndroid Build Coastguard Worker
359*8617a60dSAndroid Build Coastguard Worker find_firmware_section(§ion, image, FMAP_RO_GBB);
360*8617a60dSAndroid Build Coastguard Worker gbb_header = (struct vb2_gbb_header *)section.data;
361*8617a60dSAndroid Build Coastguard Worker if (!futil_valid_gbb_header(gbb_header, section.size, NULL)) {
362*8617a60dSAndroid Build Coastguard Worker ERROR("Cannot find GBB in image: %s.\n", image->file_name);
363*8617a60dSAndroid Build Coastguard Worker return NULL;
364*8617a60dSAndroid Build Coastguard Worker }
365*8617a60dSAndroid Build Coastguard Worker return gbb_header;
366*8617a60dSAndroid Build Coastguard Worker }
367*8617a60dSAndroid Build Coastguard Worker
368*8617a60dSAndroid Build Coastguard Worker /*
369*8617a60dSAndroid Build Coastguard Worker * Different settings may have different SWWP programmers.
370*8617a60dSAndroid Build Coastguard Worker */
is_write_protection_enabled(struct updater_config * cfg,const char * programmer,enum dut_property_type swwp_type)371*8617a60dSAndroid Build Coastguard Worker static bool is_write_protection_enabled(struct updater_config *cfg,
372*8617a60dSAndroid Build Coastguard Worker const char *programmer,
373*8617a60dSAndroid Build Coastguard Worker enum dut_property_type swwp_type)
374*8617a60dSAndroid Build Coastguard Worker {
375*8617a60dSAndroid Build Coastguard Worker /* Assume HW/SW WP are enabled if -1 error code is returned */
376*8617a60dSAndroid Build Coastguard Worker bool hwwp = !!dut_get_property(DUT_PROP_WP_HW, cfg);
377*8617a60dSAndroid Build Coastguard Worker bool swwp = !!dut_get_property(swwp_type, cfg);
378*8617a60dSAndroid Build Coastguard Worker bool wp_enabled = hwwp && swwp;
379*8617a60dSAndroid Build Coastguard Worker STATUS("Write protection (%s): %d (%s; HW=%d, SW=%d).\n", programmer,
380*8617a60dSAndroid Build Coastguard Worker wp_enabled, wp_enabled ? "enabled" : "disabled", hwwp, swwp);
381*8617a60dSAndroid Build Coastguard Worker return wp_enabled;
382*8617a60dSAndroid Build Coastguard Worker }
383*8617a60dSAndroid Build Coastguard Worker
is_ap_write_protection_enabled(struct updater_config * cfg)384*8617a60dSAndroid Build Coastguard Worker inline bool is_ap_write_protection_enabled(struct updater_config *cfg)
385*8617a60dSAndroid Build Coastguard Worker {
386*8617a60dSAndroid Build Coastguard Worker return is_write_protection_enabled(cfg, cfg->image.programmer, DUT_PROP_WP_SW_AP);
387*8617a60dSAndroid Build Coastguard Worker }
388*8617a60dSAndroid Build Coastguard Worker
is_ec_write_protection_enabled(struct updater_config * cfg)389*8617a60dSAndroid Build Coastguard Worker inline bool is_ec_write_protection_enabled(struct updater_config *cfg)
390*8617a60dSAndroid Build Coastguard Worker {
391*8617a60dSAndroid Build Coastguard Worker return is_write_protection_enabled(cfg, cfg->ec_image.programmer, DUT_PROP_WP_SW_EC);
392*8617a60dSAndroid Build Coastguard Worker }
393*8617a60dSAndroid Build Coastguard Worker
host_shell(const char * command)394*8617a60dSAndroid Build Coastguard Worker char *host_shell(const char *command)
395*8617a60dSAndroid Build Coastguard Worker {
396*8617a60dSAndroid Build Coastguard Worker /* Currently all commands we use do not have large output. */
397*8617a60dSAndroid Build Coastguard Worker char buf[COMMAND_BUFFER_SIZE];
398*8617a60dSAndroid Build Coastguard Worker
399*8617a60dSAndroid Build Coastguard Worker int result;
400*8617a60dSAndroid Build Coastguard Worker FILE *fp = popen(command, "r");
401*8617a60dSAndroid Build Coastguard Worker
402*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("%s\n", command);
403*8617a60dSAndroid Build Coastguard Worker buf[0] = '\0';
404*8617a60dSAndroid Build Coastguard Worker if (!fp) {
405*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Execution error for %s.\n", command);
406*8617a60dSAndroid Build Coastguard Worker return strdup(buf);
407*8617a60dSAndroid Build Coastguard Worker }
408*8617a60dSAndroid Build Coastguard Worker
409*8617a60dSAndroid Build Coastguard Worker if (fgets(buf, sizeof(buf), fp))
410*8617a60dSAndroid Build Coastguard Worker strip_string(buf, NULL);
411*8617a60dSAndroid Build Coastguard Worker result = pclose(fp);
412*8617a60dSAndroid Build Coastguard Worker if (!WIFEXITED(result) || WEXITSTATUS(result) != 0) {
413*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Execution failure with exit code %d: %s\n",
414*8617a60dSAndroid Build Coastguard Worker WEXITSTATUS(result), command);
415*8617a60dSAndroid Build Coastguard Worker /*
416*8617a60dSAndroid Build Coastguard Worker * Discard all output if command failed, for example command
417*8617a60dSAndroid Build Coastguard Worker * syntax failure may lead to garbage in stdout.
418*8617a60dSAndroid Build Coastguard Worker */
419*8617a60dSAndroid Build Coastguard Worker buf[0] = '\0';
420*8617a60dSAndroid Build Coastguard Worker }
421*8617a60dSAndroid Build Coastguard Worker return strdup(buf);
422*8617a60dSAndroid Build Coastguard Worker }
423*8617a60dSAndroid Build Coastguard Worker
prepare_servo_control(const char * control_name,bool on)424*8617a60dSAndroid Build Coastguard Worker void prepare_servo_control(const char *control_name, bool on)
425*8617a60dSAndroid Build Coastguard Worker {
426*8617a60dSAndroid Build Coastguard Worker char *cmd;
427*8617a60dSAndroid Build Coastguard Worker if (!control_name)
428*8617a60dSAndroid Build Coastguard Worker return;
429*8617a60dSAndroid Build Coastguard Worker
430*8617a60dSAndroid Build Coastguard Worker ASPRINTF(&cmd, "dut-control %s:%s", control_name, on ? "on" : "off");
431*8617a60dSAndroid Build Coastguard Worker free(host_shell(cmd));
432*8617a60dSAndroid Build Coastguard Worker free(cmd);
433*8617a60dSAndroid Build Coastguard Worker }
434*8617a60dSAndroid Build Coastguard Worker
host_detect_servo(const char ** prepare_ctrl_name)435*8617a60dSAndroid Build Coastguard Worker char *host_detect_servo(const char **prepare_ctrl_name)
436*8617a60dSAndroid Build Coastguard Worker {
437*8617a60dSAndroid Build Coastguard Worker const char *servo_port = getenv(ENV_SERVOD_PORT);
438*8617a60dSAndroid Build Coastguard Worker const char *servo_name = getenv(ENV_SERVOD_NAME);
439*8617a60dSAndroid Build Coastguard Worker const char *servo_id = servo_port, *servo_id_type = ENV_SERVOD_PORT;
440*8617a60dSAndroid Build Coastguard Worker char *servo_type = host_shell("dut-control -o servo_type 2>/dev/null");
441*8617a60dSAndroid Build Coastguard Worker const char *programmer = NULL;
442*8617a60dSAndroid Build Coastguard Worker char *ret = NULL;
443*8617a60dSAndroid Build Coastguard Worker char *servo_serial = NULL;
444*8617a60dSAndroid Build Coastguard Worker
445*8617a60dSAndroid Build Coastguard Worker static const char * const raiden_debug_spi = "raiden_debug_spi";
446*8617a60dSAndroid Build Coastguard Worker static const char * const cpu_fw_spi = "cpu_fw_spi";
447*8617a60dSAndroid Build Coastguard Worker static const char * const ccd_cpu_fw_spi = "ccd_cpu_fw_spi";
448*8617a60dSAndroid Build Coastguard Worker const char *serial_cmd = "dut-control -o serialname 2>/dev/null";
449*8617a60dSAndroid Build Coastguard Worker
450*8617a60dSAndroid Build Coastguard Worker /* By default, no control is needed. */
451*8617a60dSAndroid Build Coastguard Worker *prepare_ctrl_name = NULL;
452*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("servo_type: %s\n", servo_type);
453*8617a60dSAndroid Build Coastguard Worker
454*8617a60dSAndroid Build Coastguard Worker /* dut-control defaults to port 9999, or non-empty servo_name. */
455*8617a60dSAndroid Build Coastguard Worker if (!servo_id || !*servo_id) {
456*8617a60dSAndroid Build Coastguard Worker if (servo_name && *servo_name) {
457*8617a60dSAndroid Build Coastguard Worker servo_id = servo_name;
458*8617a60dSAndroid Build Coastguard Worker servo_id_type = ENV_SERVOD_NAME;
459*8617a60dSAndroid Build Coastguard Worker } else {
460*8617a60dSAndroid Build Coastguard Worker servo_id = "9999";
461*8617a60dSAndroid Build Coastguard Worker }
462*8617a60dSAndroid Build Coastguard Worker }
463*8617a60dSAndroid Build Coastguard Worker assert(servo_id && *servo_id);
464*8617a60dSAndroid Build Coastguard Worker
465*8617a60dSAndroid Build Coastguard Worker /* servo_type names: chromite/lib/firmware/servo_lib.py */
466*8617a60dSAndroid Build Coastguard Worker if (!*servo_type) {
467*8617a60dSAndroid Build Coastguard Worker ERROR("Failed to get servo type. Check servod.\n");
468*8617a60dSAndroid Build Coastguard Worker } else if (strcmp(servo_type, "servo_v2") == 0) {
469*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Selected Servo V2.\n");
470*8617a60dSAndroid Build Coastguard Worker programmer = "ft2232_spi:type=google-servo-v2";
471*8617a60dSAndroid Build Coastguard Worker *prepare_ctrl_name = cpu_fw_spi;
472*8617a60dSAndroid Build Coastguard Worker } else if (strstr(servo_type, "servo_micro")) {
473*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Selected Servo Micro.\n");
474*8617a60dSAndroid Build Coastguard Worker programmer = raiden_debug_spi;
475*8617a60dSAndroid Build Coastguard Worker *prepare_ctrl_name = cpu_fw_spi;
476*8617a60dSAndroid Build Coastguard Worker serial_cmd = ("dut-control -o servo_micro_serialname"
477*8617a60dSAndroid Build Coastguard Worker " 2>/dev/null");
478*8617a60dSAndroid Build Coastguard Worker } else if (strstr(servo_type, "ccd_cr50") ||
479*8617a60dSAndroid Build Coastguard Worker strstr(servo_type, "ccd_gsc") ||
480*8617a60dSAndroid Build Coastguard Worker strstr(servo_type, "ccd_ti50")) {
481*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Selected CCD.\n");
482*8617a60dSAndroid Build Coastguard Worker programmer = "raiden_debug_spi:target=AP,custom_rst=true";
483*8617a60dSAndroid Build Coastguard Worker *prepare_ctrl_name = ccd_cpu_fw_spi;
484*8617a60dSAndroid Build Coastguard Worker serial_cmd = "dut-control -o ccd_serialname 2>/dev/null";
485*8617a60dSAndroid Build Coastguard Worker } else if (strstr(servo_type, "c2d2")) {
486*8617a60dSAndroid Build Coastguard Worker /* Most C2D2 devices don't support flashing AP, so this must
487*8617a60dSAndroid Build Coastguard Worker * come after CCD.
488*8617a60dSAndroid Build Coastguard Worker */
489*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Selected C2D2.\n");
490*8617a60dSAndroid Build Coastguard Worker programmer = raiden_debug_spi;
491*8617a60dSAndroid Build Coastguard Worker *prepare_ctrl_name = cpu_fw_spi;
492*8617a60dSAndroid Build Coastguard Worker serial_cmd = ("dut-control -o c2d2_serialname"
493*8617a60dSAndroid Build Coastguard Worker " 2>/dev/null");
494*8617a60dSAndroid Build Coastguard Worker } else {
495*8617a60dSAndroid Build Coastguard Worker WARN("Unknown servo: %s\nAssuming debug header.\n", servo_type);
496*8617a60dSAndroid Build Coastguard Worker programmer = raiden_debug_spi;
497*8617a60dSAndroid Build Coastguard Worker *prepare_ctrl_name = cpu_fw_spi;
498*8617a60dSAndroid Build Coastguard Worker }
499*8617a60dSAndroid Build Coastguard Worker
500*8617a60dSAndroid Build Coastguard Worker /*
501*8617a60dSAndroid Build Coastguard Worker * To support "multiple servos connected but only one servod running" we
502*8617a60dSAndroid Build Coastguard Worker * should always try to get the serial number.
503*8617a60dSAndroid Build Coastguard Worker */
504*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Select servod by %s=%s\n", servo_id_type, servo_id);
505*8617a60dSAndroid Build Coastguard Worker servo_serial = host_shell(serial_cmd);
506*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Servo SN=%s (serial cmd: %s)\n", servo_serial, serial_cmd);
507*8617a60dSAndroid Build Coastguard Worker if (!(servo_serial && *servo_serial)) {
508*8617a60dSAndroid Build Coastguard Worker ERROR("Failed to get serial: %s=%s\n", servo_id_type, servo_id);
509*8617a60dSAndroid Build Coastguard Worker /* If there is no servo serial, undo the prepare_ctrl_name. */
510*8617a60dSAndroid Build Coastguard Worker *prepare_ctrl_name = NULL;
511*8617a60dSAndroid Build Coastguard Worker } else if (programmer) {
512*8617a60dSAndroid Build Coastguard Worker if (!servo_serial) {
513*8617a60dSAndroid Build Coastguard Worker ret = strdup(programmer);
514*8617a60dSAndroid Build Coastguard Worker } else {
515*8617a60dSAndroid Build Coastguard Worker const char prefix = strchr(programmer, ':') ? ',' : ':';
516*8617a60dSAndroid Build Coastguard Worker ASPRINTF(&ret, "%s%cserial=%s", programmer, prefix,
517*8617a60dSAndroid Build Coastguard Worker servo_serial);
518*8617a60dSAndroid Build Coastguard Worker }
519*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Servo programmer: %s\n", ret);
520*8617a60dSAndroid Build Coastguard Worker }
521*8617a60dSAndroid Build Coastguard Worker
522*8617a60dSAndroid Build Coastguard Worker free(servo_type);
523*8617a60dSAndroid Build Coastguard Worker free(servo_serial);
524*8617a60dSAndroid Build Coastguard Worker
525*8617a60dSAndroid Build Coastguard Worker return ret;
526*8617a60dSAndroid Build Coastguard Worker }
527*8617a60dSAndroid Build Coastguard Worker
528*8617a60dSAndroid Build Coastguard Worker /*
529*8617a60dSAndroid Build Coastguard Worker * Returns 1 if the programmers in image1 and image2 are the same.
530*8617a60dSAndroid Build Coastguard Worker */
is_the_same_programmer(const struct firmware_image * image1,const struct firmware_image * image2)531*8617a60dSAndroid Build Coastguard Worker static int is_the_same_programmer(const struct firmware_image *image1,
532*8617a60dSAndroid Build Coastguard Worker const struct firmware_image *image2)
533*8617a60dSAndroid Build Coastguard Worker {
534*8617a60dSAndroid Build Coastguard Worker assert(image1 && image2);
535*8617a60dSAndroid Build Coastguard Worker
536*8617a60dSAndroid Build Coastguard Worker /* Including if both are NULL. */
537*8617a60dSAndroid Build Coastguard Worker if (image1->programmer == image2->programmer)
538*8617a60dSAndroid Build Coastguard Worker return 1;
539*8617a60dSAndroid Build Coastguard Worker
540*8617a60dSAndroid Build Coastguard Worker /* Not the same if either one is NULL. */
541*8617a60dSAndroid Build Coastguard Worker if (!image1->programmer || !image2->programmer)
542*8617a60dSAndroid Build Coastguard Worker return 0;
543*8617a60dSAndroid Build Coastguard Worker
544*8617a60dSAndroid Build Coastguard Worker return strcmp(image1->programmer, image2->programmer) == 0;
545*8617a60dSAndroid Build Coastguard Worker }
546*8617a60dSAndroid Build Coastguard Worker
load_system_firmware(struct updater_config * cfg,struct firmware_image * image)547*8617a60dSAndroid Build Coastguard Worker int load_system_firmware(struct updater_config *cfg,
548*8617a60dSAndroid Build Coastguard Worker struct firmware_image *image)
549*8617a60dSAndroid Build Coastguard Worker {
550*8617a60dSAndroid Build Coastguard Worker if (!strcmp(image->programmer, FLASHROM_PROGRAMMER_INTERNAL_EC))
551*8617a60dSAndroid Build Coastguard Worker WARN("%s: flashrom support for CrOS EC is EOL.\n", __func__);
552*8617a60dSAndroid Build Coastguard Worker
553*8617a60dSAndroid Build Coastguard Worker int r, i;
554*8617a60dSAndroid Build Coastguard Worker const int tries = 1 + get_config_quirk(QUIRK_EXTRA_RETRIES, cfg);
555*8617a60dSAndroid Build Coastguard Worker
556*8617a60dSAndroid Build Coastguard Worker int verbose = cfg->verbosity + 1; /* libflashrom verbose 1 = WARN. */
557*8617a60dSAndroid Build Coastguard Worker
558*8617a60dSAndroid Build Coastguard Worker for (i = 1, r = -1; i <= tries && r != 0; i++, verbose++) {
559*8617a60dSAndroid Build Coastguard Worker if (i > 1)
560*8617a60dSAndroid Build Coastguard Worker WARN("Retry reading firmware (%d/%d)...\n", i, tries);
561*8617a60dSAndroid Build Coastguard Worker INFO("Reading SPI Flash..\n");
562*8617a60dSAndroid Build Coastguard Worker r = flashrom_read_image(image, NULL, 0, verbose);
563*8617a60dSAndroid Build Coastguard Worker }
564*8617a60dSAndroid Build Coastguard Worker if (r) {
565*8617a60dSAndroid Build Coastguard Worker /* Read failure, the content cannot be trusted. */
566*8617a60dSAndroid Build Coastguard Worker free_firmware_image(image);
567*8617a60dSAndroid Build Coastguard Worker } else {
568*8617a60dSAndroid Build Coastguard Worker /*
569*8617a60dSAndroid Build Coastguard Worker * Parse the contents. Note the image->data will remain even
570*8617a60dSAndroid Build Coastguard Worker * if parsing failed - this is important for system firmware
571*8617a60dSAndroid Build Coastguard Worker * because we may be trying to recover a device with corrupted
572*8617a60dSAndroid Build Coastguard Worker * firmware.
573*8617a60dSAndroid Build Coastguard Worker */
574*8617a60dSAndroid Build Coastguard Worker r = parse_firmware_image(image);
575*8617a60dSAndroid Build Coastguard Worker }
576*8617a60dSAndroid Build Coastguard Worker return r;
577*8617a60dSAndroid Build Coastguard Worker }
578*8617a60dSAndroid Build Coastguard Worker
write_system_firmware(struct updater_config * cfg,const struct firmware_image * image,const char * const regions[],const size_t regions_len)579*8617a60dSAndroid Build Coastguard Worker int write_system_firmware(struct updater_config *cfg,
580*8617a60dSAndroid Build Coastguard Worker const struct firmware_image *image,
581*8617a60dSAndroid Build Coastguard Worker const char * const regions[],
582*8617a60dSAndroid Build Coastguard Worker const size_t regions_len)
583*8617a60dSAndroid Build Coastguard Worker {
584*8617a60dSAndroid Build Coastguard Worker if (!strcmp(image->programmer, FLASHROM_PROGRAMMER_INTERNAL_EC)) {
585*8617a60dSAndroid Build Coastguard Worker WARN("%s: flashrom support for CrOS EC is EOL.\n", __func__);
586*8617a60dSAndroid Build Coastguard Worker }
587*8617a60dSAndroid Build Coastguard Worker
588*8617a60dSAndroid Build Coastguard Worker int r = 0, i;
589*8617a60dSAndroid Build Coastguard Worker const int tries = 1 + get_config_quirk(QUIRK_EXTRA_RETRIES, cfg);
590*8617a60dSAndroid Build Coastguard Worker struct firmware_image *flash_contents = NULL;
591*8617a60dSAndroid Build Coastguard Worker
592*8617a60dSAndroid Build Coastguard Worker if (cfg->use_diff_image && cfg->image_current.data &&
593*8617a60dSAndroid Build Coastguard Worker is_the_same_programmer(&cfg->image_current, image))
594*8617a60dSAndroid Build Coastguard Worker flash_contents = &cfg->image_current;
595*8617a60dSAndroid Build Coastguard Worker
596*8617a60dSAndroid Build Coastguard Worker int verbose = cfg->verbosity + 1; /* libflashrom verbose 1 = WARN. */
597*8617a60dSAndroid Build Coastguard Worker
598*8617a60dSAndroid Build Coastguard Worker for (i = 1, r = -1; i <= tries && r != 0; i++, verbose++) {
599*8617a60dSAndroid Build Coastguard Worker if (i > 1)
600*8617a60dSAndroid Build Coastguard Worker WARN("Retry writing firmware (%d/%d)...\n", i, tries);
601*8617a60dSAndroid Build Coastguard Worker INFO("Writing SPI Flash..\n");
602*8617a60dSAndroid Build Coastguard Worker r = flashrom_write_image(image, regions, regions_len,
603*8617a60dSAndroid Build Coastguard Worker flash_contents, cfg->do_verify,
604*8617a60dSAndroid Build Coastguard Worker verbose);
605*8617a60dSAndroid Build Coastguard Worker /*
606*8617a60dSAndroid Build Coastguard Worker * Force a newline to flush stdout in case if
607*8617a60dSAndroid Build Coastguard Worker * flashrom_write_image left some messages in the buffer.
608*8617a60dSAndroid Build Coastguard Worker */
609*8617a60dSAndroid Build Coastguard Worker fprintf(stdout, "\n");
610*8617a60dSAndroid Build Coastguard Worker
611*8617a60dSAndroid Build Coastguard Worker }
612*8617a60dSAndroid Build Coastguard Worker return r;
613*8617a60dSAndroid Build Coastguard Worker }
614*8617a60dSAndroid Build Coastguard Worker
create_temp_file(struct tempfile * head)615*8617a60dSAndroid Build Coastguard Worker const char *create_temp_file(struct tempfile *head)
616*8617a60dSAndroid Build Coastguard Worker {
617*8617a60dSAndroid Build Coastguard Worker struct tempfile *new_temp;
618*8617a60dSAndroid Build Coastguard Worker char new_path[] = VBOOT_TMP_DIR "/fwupdater.XXXXXX";
619*8617a60dSAndroid Build Coastguard Worker
620*8617a60dSAndroid Build Coastguard Worker int fd;
621*8617a60dSAndroid Build Coastguard Worker mode_t umask_save;
622*8617a60dSAndroid Build Coastguard Worker
623*8617a60dSAndroid Build Coastguard Worker /* Set the umask before mkstemp for security considerations. */
624*8617a60dSAndroid Build Coastguard Worker umask_save = umask(077);
625*8617a60dSAndroid Build Coastguard Worker fd = mkstemp(new_path);
626*8617a60dSAndroid Build Coastguard Worker umask(umask_save);
627*8617a60dSAndroid Build Coastguard Worker if (fd < 0) {
628*8617a60dSAndroid Build Coastguard Worker ERROR("Failed to create new temp file in %s\n", new_path);
629*8617a60dSAndroid Build Coastguard Worker return NULL;
630*8617a60dSAndroid Build Coastguard Worker }
631*8617a60dSAndroid Build Coastguard Worker close(fd);
632*8617a60dSAndroid Build Coastguard Worker new_temp = (struct tempfile *)malloc(sizeof(*new_temp));
633*8617a60dSAndroid Build Coastguard Worker if (new_temp)
634*8617a60dSAndroid Build Coastguard Worker new_temp->filepath = strdup(new_path);
635*8617a60dSAndroid Build Coastguard Worker if (!new_temp || !new_temp->filepath) {
636*8617a60dSAndroid Build Coastguard Worker remove(new_path);
637*8617a60dSAndroid Build Coastguard Worker free(new_temp);
638*8617a60dSAndroid Build Coastguard Worker ERROR("Failed to allocate buffer for new temp file.\n");
639*8617a60dSAndroid Build Coastguard Worker return NULL;
640*8617a60dSAndroid Build Coastguard Worker }
641*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Created new temporary file: %s.\n", new_path);
642*8617a60dSAndroid Build Coastguard Worker new_temp->next = NULL;
643*8617a60dSAndroid Build Coastguard Worker while (head->next)
644*8617a60dSAndroid Build Coastguard Worker head = head->next;
645*8617a60dSAndroid Build Coastguard Worker head->next = new_temp;
646*8617a60dSAndroid Build Coastguard Worker return new_temp->filepath;
647*8617a60dSAndroid Build Coastguard Worker }
648*8617a60dSAndroid Build Coastguard Worker
remove_all_temp_files(struct tempfile * head)649*8617a60dSAndroid Build Coastguard Worker void remove_all_temp_files(struct tempfile *head)
650*8617a60dSAndroid Build Coastguard Worker {
651*8617a60dSAndroid Build Coastguard Worker /* head itself is dummy and should not be removed. */
652*8617a60dSAndroid Build Coastguard Worker assert(!head->filepath);
653*8617a60dSAndroid Build Coastguard Worker struct tempfile *next = head->next;
654*8617a60dSAndroid Build Coastguard Worker head->next = NULL;
655*8617a60dSAndroid Build Coastguard Worker while (next) {
656*8617a60dSAndroid Build Coastguard Worker head = next;
657*8617a60dSAndroid Build Coastguard Worker next = head->next;
658*8617a60dSAndroid Build Coastguard Worker assert(head->filepath);
659*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Remove temporary file: %s.\n", head->filepath);
660*8617a60dSAndroid Build Coastguard Worker remove(head->filepath);
661*8617a60dSAndroid Build Coastguard Worker free(head->filepath);
662*8617a60dSAndroid Build Coastguard Worker free(head);
663*8617a60dSAndroid Build Coastguard Worker }
664*8617a60dSAndroid Build Coastguard Worker }
665*8617a60dSAndroid Build Coastguard Worker
get_firmware_rootkey_hash(const struct firmware_image * image)666*8617a60dSAndroid Build Coastguard Worker const char *get_firmware_rootkey_hash(const struct firmware_image *image)
667*8617a60dSAndroid Build Coastguard Worker {
668*8617a60dSAndroid Build Coastguard Worker const struct vb2_gbb_header *gbb = NULL;
669*8617a60dSAndroid Build Coastguard Worker const struct vb2_packed_key *rootkey = NULL;
670*8617a60dSAndroid Build Coastguard Worker
671*8617a60dSAndroid Build Coastguard Worker assert(image->data);
672*8617a60dSAndroid Build Coastguard Worker
673*8617a60dSAndroid Build Coastguard Worker gbb = find_gbb(image);
674*8617a60dSAndroid Build Coastguard Worker if (!gbb) {
675*8617a60dSAndroid Build Coastguard Worker WARN("No GBB found in image.\n");
676*8617a60dSAndroid Build Coastguard Worker return NULL;
677*8617a60dSAndroid Build Coastguard Worker }
678*8617a60dSAndroid Build Coastguard Worker
679*8617a60dSAndroid Build Coastguard Worker rootkey = get_rootkey(gbb);
680*8617a60dSAndroid Build Coastguard Worker if (!rootkey) {
681*8617a60dSAndroid Build Coastguard Worker WARN("No rootkey found in image.\n");
682*8617a60dSAndroid Build Coastguard Worker return NULL;
683*8617a60dSAndroid Build Coastguard Worker }
684*8617a60dSAndroid Build Coastguard Worker
685*8617a60dSAndroid Build Coastguard Worker return packed_key_sha1_string(rootkey);
686*8617a60dSAndroid Build Coastguard Worker }
687*8617a60dSAndroid Build Coastguard Worker
overwrite_section(struct firmware_image * image,const char * fmap_section,size_t offset,size_t size,const uint8_t * new_values)688*8617a60dSAndroid Build Coastguard Worker int overwrite_section(struct firmware_image *image,
689*8617a60dSAndroid Build Coastguard Worker const char *fmap_section, size_t offset,
690*8617a60dSAndroid Build Coastguard Worker size_t size, const uint8_t *new_values)
691*8617a60dSAndroid Build Coastguard Worker {
692*8617a60dSAndroid Build Coastguard Worker struct firmware_section section;
693*8617a60dSAndroid Build Coastguard Worker
694*8617a60dSAndroid Build Coastguard Worker find_firmware_section(§ion, image, fmap_section);
695*8617a60dSAndroid Build Coastguard Worker if (section.size < offset + size) {
696*8617a60dSAndroid Build Coastguard Worker ERROR("Section smaller than given offset + size\n");
697*8617a60dSAndroid Build Coastguard Worker return -1;
698*8617a60dSAndroid Build Coastguard Worker }
699*8617a60dSAndroid Build Coastguard Worker
700*8617a60dSAndroid Build Coastguard Worker if (memcmp(section.data + offset, new_values, size) == 0) {
701*8617a60dSAndroid Build Coastguard Worker VB2_DEBUG("Section already contains given values.\n");
702*8617a60dSAndroid Build Coastguard Worker return 0;
703*8617a60dSAndroid Build Coastguard Worker }
704*8617a60dSAndroid Build Coastguard Worker
705*8617a60dSAndroid Build Coastguard Worker memcpy(section.data + offset, new_values, size);
706*8617a60dSAndroid Build Coastguard Worker return 0;
707*8617a60dSAndroid Build Coastguard Worker }
708