xref: /aosp_15_r20/external/vboot_reference/host/lib/cbfstool.c (revision 8617a60d3594060b7ecbd21bc622a7c14f3cf2bc)
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 
6*8617a60dSAndroid Build Coastguard Worker #include "2common.h"
7*8617a60dSAndroid Build Coastguard Worker #include "2crypto.h"
8*8617a60dSAndroid Build Coastguard Worker #include "2return_codes.h"
9*8617a60dSAndroid Build Coastguard Worker #include "cbfstool.h"
10*8617a60dSAndroid Build Coastguard Worker #include "host_misc.h"
11*8617a60dSAndroid Build Coastguard Worker #include "subprocess.h"
12*8617a60dSAndroid Build Coastguard Worker #include "vboot_host.h"
13*8617a60dSAndroid Build Coastguard Worker 
14*8617a60dSAndroid Build Coastguard Worker #define ARGV_END(region) region ? "-r" : NULL, region, NULL,
15*8617a60dSAndroid Build Coastguard Worker 
get_cbfstool_path(void)16*8617a60dSAndroid Build Coastguard Worker static const char *get_cbfstool_path(void)
17*8617a60dSAndroid Build Coastguard Worker {
18*8617a60dSAndroid Build Coastguard Worker 	static const char *cbfstool = NULL;
19*8617a60dSAndroid Build Coastguard Worker 
20*8617a60dSAndroid Build Coastguard Worker 	if (cbfstool)
21*8617a60dSAndroid Build Coastguard Worker 		return cbfstool;
22*8617a60dSAndroid Build Coastguard Worker 
23*8617a60dSAndroid Build Coastguard Worker 	const char *env_cbfstool = getenv(ENV_CBFSTOOL);
24*8617a60dSAndroid Build Coastguard Worker 	if (env_cbfstool && env_cbfstool[0] != '\0') {
25*8617a60dSAndroid Build Coastguard Worker 		cbfstool = strdup(env_cbfstool);
26*8617a60dSAndroid Build Coastguard Worker 		return cbfstool;
27*8617a60dSAndroid Build Coastguard Worker 	}
28*8617a60dSAndroid Build Coastguard Worker 
29*8617a60dSAndroid Build Coastguard Worker 	cbfstool = DEFAULT_CBFSTOOL;
30*8617a60dSAndroid Build Coastguard Worker 	return cbfstool;
31*8617a60dSAndroid Build Coastguard Worker }
32*8617a60dSAndroid Build Coastguard Worker 
find_cbfs_file(const char * buf,const char * name)33*8617a60dSAndroid Build Coastguard Worker static bool find_cbfs_file(const char *buf, const char *name)
34*8617a60dSAndroid Build Coastguard Worker {
35*8617a60dSAndroid Build Coastguard Worker 	char *to_find = NULL;
36*8617a60dSAndroid Build Coastguard Worker 	if (asprintf(&to_find, "\n%s\t", name) < 0) {
37*8617a60dSAndroid Build Coastguard Worker 		fprintf(stderr, "Out of Memory\n");
38*8617a60dSAndroid Build Coastguard Worker 		exit(1);
39*8617a60dSAndroid Build Coastguard Worker 	}
40*8617a60dSAndroid Build Coastguard Worker 
41*8617a60dSAndroid Build Coastguard Worker 	const char *start = strstr(buf, to_find);
42*8617a60dSAndroid Build Coastguard Worker 
43*8617a60dSAndroid Build Coastguard Worker 	free(to_find);
44*8617a60dSAndroid Build Coastguard Worker 	return !!start;
45*8617a60dSAndroid Build Coastguard Worker }
46*8617a60dSAndroid Build Coastguard Worker 
cbfstool_file_exists(const char * image_file,const char * region,const char * name)47*8617a60dSAndroid Build Coastguard Worker bool cbfstool_file_exists(const char *image_file, const char *region,
48*8617a60dSAndroid Build Coastguard Worker 			  const char *name)
49*8617a60dSAndroid Build Coastguard Worker {
50*8617a60dSAndroid Build Coastguard Worker 	int status;
51*8617a60dSAndroid Build Coastguard Worker 	char *buffer;
52*8617a60dSAndroid Build Coastguard Worker 	const size_t buffer_size = 1024 * 128;
53*8617a60dSAndroid Build Coastguard Worker 	const char *cbfstool = get_cbfstool_path();
54*8617a60dSAndroid Build Coastguard Worker 	bool res = false;
55*8617a60dSAndroid Build Coastguard Worker 
56*8617a60dSAndroid Build Coastguard Worker 	buffer = malloc(buffer_size);
57*8617a60dSAndroid Build Coastguard Worker 	if (!buffer)
58*8617a60dSAndroid Build Coastguard Worker 		goto done;
59*8617a60dSAndroid Build Coastguard Worker 
60*8617a60dSAndroid Build Coastguard Worker 	struct subprocess_target output = {
61*8617a60dSAndroid Build Coastguard Worker 		.type = TARGET_BUFFER_NULL_TERMINATED,
62*8617a60dSAndroid Build Coastguard Worker 		.buffer = {
63*8617a60dSAndroid Build Coastguard Worker 			.buf = buffer,
64*8617a60dSAndroid Build Coastguard Worker 			.size = buffer_size,
65*8617a60dSAndroid Build Coastguard Worker 		},
66*8617a60dSAndroid Build Coastguard Worker 	};
67*8617a60dSAndroid Build Coastguard Worker 	const char *const argv[] = {
68*8617a60dSAndroid Build Coastguard Worker 		cbfstool, image_file, "print", "-k", ARGV_END(region)
69*8617a60dSAndroid Build Coastguard Worker 	};
70*8617a60dSAndroid Build Coastguard Worker 
71*8617a60dSAndroid Build Coastguard Worker 	status = subprocess_run(argv, &subprocess_null, &output,
72*8617a60dSAndroid Build Coastguard Worker 				&subprocess_null);
73*8617a60dSAndroid Build Coastguard Worker 	if (status < 0) {
74*8617a60dSAndroid Build Coastguard Worker 		fprintf(stderr, "%s(): cbfstool invocation failed: %m\n",
75*8617a60dSAndroid Build Coastguard Worker 			__func__);
76*8617a60dSAndroid Build Coastguard Worker 		exit(1);
77*8617a60dSAndroid Build Coastguard Worker 	}
78*8617a60dSAndroid Build Coastguard Worker 	if (status > 0)
79*8617a60dSAndroid Build Coastguard Worker 		goto done;
80*8617a60dSAndroid Build Coastguard Worker 
81*8617a60dSAndroid Build Coastguard Worker 	res = find_cbfs_file(buffer, name);
82*8617a60dSAndroid Build Coastguard Worker 
83*8617a60dSAndroid Build Coastguard Worker done:
84*8617a60dSAndroid Build Coastguard Worker 	free(buffer);
85*8617a60dSAndroid Build Coastguard Worker 	return res;
86*8617a60dSAndroid Build Coastguard Worker }
87*8617a60dSAndroid Build Coastguard Worker 
cbfstool_extract(const char * image_file,const char * region,const char * name,const char * file)88*8617a60dSAndroid Build Coastguard Worker int cbfstool_extract(const char *image_file, const char *region,
89*8617a60dSAndroid Build Coastguard Worker 		     const char *name, const char *file)
90*8617a60dSAndroid Build Coastguard Worker {
91*8617a60dSAndroid Build Coastguard Worker 	int status;
92*8617a60dSAndroid Build Coastguard Worker 	const char *cbfstool = get_cbfstool_path();
93*8617a60dSAndroid Build Coastguard Worker 
94*8617a60dSAndroid Build Coastguard Worker 	const char *const argv[] = {
95*8617a60dSAndroid Build Coastguard Worker 		cbfstool, image_file, "extract", "-n", name, "-f", file,
96*8617a60dSAndroid Build Coastguard Worker 		ARGV_END(region)
97*8617a60dSAndroid Build Coastguard Worker 	};
98*8617a60dSAndroid Build Coastguard Worker 
99*8617a60dSAndroid Build Coastguard Worker 	status = subprocess_run(argv, &subprocess_null, &subprocess_null,
100*8617a60dSAndroid Build Coastguard Worker 				&subprocess_null);
101*8617a60dSAndroid Build Coastguard Worker 	if (status < 0) {
102*8617a60dSAndroid Build Coastguard Worker 		fprintf(stderr, "%s(): cbfstool invocation failed: %m\n",
103*8617a60dSAndroid Build Coastguard Worker 			__func__);
104*8617a60dSAndroid Build Coastguard Worker 		exit(1);
105*8617a60dSAndroid Build Coastguard Worker 	}
106*8617a60dSAndroid Build Coastguard Worker 
107*8617a60dSAndroid Build Coastguard Worker 	return status;
108*8617a60dSAndroid Build Coastguard Worker }
109*8617a60dSAndroid Build Coastguard Worker 
cbfstool_truncate(const char * file,const char * region,size_t * new_size)110*8617a60dSAndroid Build Coastguard Worker vb2_error_t cbfstool_truncate(const char *file, const char *region,
111*8617a60dSAndroid Build Coastguard Worker 			      size_t *new_size)
112*8617a60dSAndroid Build Coastguard Worker {
113*8617a60dSAndroid Build Coastguard Worker 	int status;
114*8617a60dSAndroid Build Coastguard Worker 	char output_buffer[128];
115*8617a60dSAndroid Build Coastguard Worker 	const char *cbfstool = get_cbfstool_path();
116*8617a60dSAndroid Build Coastguard Worker 
117*8617a60dSAndroid Build Coastguard Worker 	struct subprocess_target output = {
118*8617a60dSAndroid Build Coastguard Worker 		.type = TARGET_BUFFER_NULL_TERMINATED,
119*8617a60dSAndroid Build Coastguard Worker 		.buffer = {
120*8617a60dSAndroid Build Coastguard Worker 			.buf = output_buffer,
121*8617a60dSAndroid Build Coastguard Worker 			.size = sizeof(output_buffer),
122*8617a60dSAndroid Build Coastguard Worker 		},
123*8617a60dSAndroid Build Coastguard Worker 	};
124*8617a60dSAndroid Build Coastguard Worker 	const char *const argv[] = {
125*8617a60dSAndroid Build Coastguard Worker 		cbfstool, file, "truncate", "-r", region, NULL,
126*8617a60dSAndroid Build Coastguard Worker 	};
127*8617a60dSAndroid Build Coastguard Worker 
128*8617a60dSAndroid Build Coastguard Worker 	status = subprocess_run(argv, &subprocess_null, &output,
129*8617a60dSAndroid Build Coastguard Worker 				&subprocess_null);
130*8617a60dSAndroid Build Coastguard Worker 
131*8617a60dSAndroid Build Coastguard Worker 	if (status < 0) {
132*8617a60dSAndroid Build Coastguard Worker 		fprintf(stderr, "%s(): cbfstool invocation failed: %m\n",
133*8617a60dSAndroid Build Coastguard Worker 			__func__);
134*8617a60dSAndroid Build Coastguard Worker 		exit(1);
135*8617a60dSAndroid Build Coastguard Worker 	}
136*8617a60dSAndroid Build Coastguard Worker 
137*8617a60dSAndroid Build Coastguard Worker 	/* Positive exit code means something is wrong with image. Return zero
138*8617a60dSAndroid Build Coastguard Worker 	   as new size, because it might be problem with missing CBFS.*/
139*8617a60dSAndroid Build Coastguard Worker 	if (status > 0) {
140*8617a60dSAndroid Build Coastguard Worker 		*new_size = 0;
141*8617a60dSAndroid Build Coastguard Worker 		return VB2_ERROR_CBFSTOOL;
142*8617a60dSAndroid Build Coastguard Worker 	}
143*8617a60dSAndroid Build Coastguard Worker 
144*8617a60dSAndroid Build Coastguard Worker 	if (sscanf(output_buffer, "%zi", new_size) != 1) {
145*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Failed to parse command output. Unexpected "
146*8617a60dSAndroid Build Coastguard Worker 			  "output.\n");
147*8617a60dSAndroid Build Coastguard Worker 		*new_size = 0;
148*8617a60dSAndroid Build Coastguard Worker 		return VB2_ERROR_CBFSTOOL;
149*8617a60dSAndroid Build Coastguard Worker 	}
150*8617a60dSAndroid Build Coastguard Worker 
151*8617a60dSAndroid Build Coastguard Worker 	return VB2_SUCCESS;
152*8617a60dSAndroid Build Coastguard Worker }
153*8617a60dSAndroid Build Coastguard Worker 
154*8617a60dSAndroid Build Coastguard Worker /* Requires null-terminated buffer */
extract_metadata_hash(const char * buf,struct vb2_hash * hash)155*8617a60dSAndroid Build Coastguard Worker static vb2_error_t extract_metadata_hash(const char *buf, struct vb2_hash *hash)
156*8617a60dSAndroid Build Coastguard Worker {
157*8617a60dSAndroid Build Coastguard Worker 	enum vb2_hash_algorithm algo;
158*8617a60dSAndroid Build Coastguard Worker 	const char *to_find = "\n[METADATA HASH]";
159*8617a60dSAndroid Build Coastguard Worker 	char *algo_str = NULL;
160*8617a60dSAndroid Build Coastguard Worker 	char *hash_str = NULL;
161*8617a60dSAndroid Build Coastguard Worker 	vb2_error_t rv = VB2_ERROR_CBFSTOOL;
162*8617a60dSAndroid Build Coastguard Worker 
163*8617a60dSAndroid Build Coastguard Worker 	const char *start = strstr(buf, to_find);
164*8617a60dSAndroid Build Coastguard Worker 	if (start)
165*8617a60dSAndroid Build Coastguard Worker 		start += strlen(to_find);
166*8617a60dSAndroid Build Coastguard Worker 
167*8617a60dSAndroid Build Coastguard Worker 	if (start) {
168*8617a60dSAndroid Build Coastguard Worker 		const int matches = sscanf(start, " %m[^:\n\t ]:%m[^:\n\t ]",
169*8617a60dSAndroid Build Coastguard Worker 					   &algo_str, &hash_str);
170*8617a60dSAndroid Build Coastguard Worker 
171*8617a60dSAndroid Build Coastguard Worker 		if (matches < 2)
172*8617a60dSAndroid Build Coastguard Worker 			goto done;
173*8617a60dSAndroid Build Coastguard Worker 
174*8617a60dSAndroid Build Coastguard Worker 		if (!algo_str || !vb2_lookup_hash_alg(algo_str, &algo) ||
175*8617a60dSAndroid Build Coastguard Worker 		    algo == VB2_HASH_INVALID)
176*8617a60dSAndroid Build Coastguard Worker 			goto done;
177*8617a60dSAndroid Build Coastguard Worker 		hash->algo = algo;
178*8617a60dSAndroid Build Coastguard Worker 
179*8617a60dSAndroid Build Coastguard Worker 		if (!hash_str ||
180*8617a60dSAndroid Build Coastguard Worker 		    strlen(hash_str) != (vb2_digest_size(algo) * 2) ||
181*8617a60dSAndroid Build Coastguard Worker 		    !parse_hash(&hash->raw[0], vb2_digest_size(algo), hash_str))
182*8617a60dSAndroid Build Coastguard Worker 			goto done;
183*8617a60dSAndroid Build Coastguard Worker 
184*8617a60dSAndroid Build Coastguard Worker 		if (!strstr(buf, "]\tfully valid"))
185*8617a60dSAndroid Build Coastguard Worker 			goto done;
186*8617a60dSAndroid Build Coastguard Worker 
187*8617a60dSAndroid Build Coastguard Worker 		rv = VB2_SUCCESS;
188*8617a60dSAndroid Build Coastguard Worker 	}
189*8617a60dSAndroid Build Coastguard Worker 
190*8617a60dSAndroid Build Coastguard Worker done:
191*8617a60dSAndroid Build Coastguard Worker 	if (rv != VB2_SUCCESS)
192*8617a60dSAndroid Build Coastguard Worker 		hash->algo = VB2_HASH_INVALID;
193*8617a60dSAndroid Build Coastguard Worker 
194*8617a60dSAndroid Build Coastguard Worker 	free(algo_str);
195*8617a60dSAndroid Build Coastguard Worker 	free(hash_str);
196*8617a60dSAndroid Build Coastguard Worker 
197*8617a60dSAndroid Build Coastguard Worker 	return rv;
198*8617a60dSAndroid Build Coastguard Worker }
199*8617a60dSAndroid Build Coastguard Worker 
cbfstool_get_metadata_hash(const char * file,const char * region,struct vb2_hash * hash)200*8617a60dSAndroid Build Coastguard Worker vb2_error_t cbfstool_get_metadata_hash(const char *file, const char *region,
201*8617a60dSAndroid Build Coastguard Worker 				       struct vb2_hash *hash)
202*8617a60dSAndroid Build Coastguard Worker {
203*8617a60dSAndroid Build Coastguard Worker 	int status;
204*8617a60dSAndroid Build Coastguard Worker 	const char *cbfstool = get_cbfstool_path();
205*8617a60dSAndroid Build Coastguard Worker 	const size_t data_buffer_sz = 1024 * 1024;
206*8617a60dSAndroid Build Coastguard Worker 	char *data_buffer = malloc(data_buffer_sz);
207*8617a60dSAndroid Build Coastguard Worker 	vb2_error_t rv = VB2_ERROR_CBFSTOOL;
208*8617a60dSAndroid Build Coastguard Worker 
209*8617a60dSAndroid Build Coastguard Worker 	if (!data_buffer)
210*8617a60dSAndroid Build Coastguard Worker 		goto done;
211*8617a60dSAndroid Build Coastguard Worker 
212*8617a60dSAndroid Build Coastguard Worker 	memset(hash, 0, sizeof(*hash));
213*8617a60dSAndroid Build Coastguard Worker 	hash->algo = VB2_HASH_INVALID;
214*8617a60dSAndroid Build Coastguard Worker 
215*8617a60dSAndroid Build Coastguard Worker 	struct subprocess_target output = {
216*8617a60dSAndroid Build Coastguard Worker 		.type = TARGET_BUFFER_NULL_TERMINATED,
217*8617a60dSAndroid Build Coastguard Worker 		.buffer = {
218*8617a60dSAndroid Build Coastguard Worker 			.buf = data_buffer,
219*8617a60dSAndroid Build Coastguard Worker 			.size = data_buffer_sz,
220*8617a60dSAndroid Build Coastguard Worker 		},
221*8617a60dSAndroid Build Coastguard Worker 	};
222*8617a60dSAndroid Build Coastguard Worker 	const char *argv[] = {
223*8617a60dSAndroid Build Coastguard Worker 		cbfstool, file, "print", "-kv", ARGV_END(region)
224*8617a60dSAndroid Build Coastguard Worker 	};
225*8617a60dSAndroid Build Coastguard Worker 
226*8617a60dSAndroid Build Coastguard Worker 	status = subprocess_run(argv, &subprocess_null, &output,
227*8617a60dSAndroid Build Coastguard Worker 				&subprocess_null);
228*8617a60dSAndroid Build Coastguard Worker 
229*8617a60dSAndroid Build Coastguard Worker 	if (status < 0) {
230*8617a60dSAndroid Build Coastguard Worker 		fprintf(stderr, "%s(): cbfstool invocation failed: %m\n",
231*8617a60dSAndroid Build Coastguard Worker 			__func__);
232*8617a60dSAndroid Build Coastguard Worker 		exit(1);
233*8617a60dSAndroid Build Coastguard Worker 	}
234*8617a60dSAndroid Build Coastguard Worker 
235*8617a60dSAndroid Build Coastguard Worker 	if (status > 0)
236*8617a60dSAndroid Build Coastguard Worker 		goto done;
237*8617a60dSAndroid Build Coastguard Worker 
238*8617a60dSAndroid Build Coastguard Worker 	rv = extract_metadata_hash(data_buffer, hash);
239*8617a60dSAndroid Build Coastguard Worker 
240*8617a60dSAndroid Build Coastguard Worker done:
241*8617a60dSAndroid Build Coastguard Worker 	free(data_buffer);
242*8617a60dSAndroid Build Coastguard Worker 	return rv;
243*8617a60dSAndroid Build Coastguard Worker }
244*8617a60dSAndroid Build Coastguard Worker 
245*8617a60dSAndroid Build Coastguard Worker /* Requires null-terminated buffer */
extract_config_value(const char * buf,const char * config_field)246*8617a60dSAndroid Build Coastguard Worker static char *extract_config_value(const char *buf, const char *config_field)
247*8617a60dSAndroid Build Coastguard Worker {
248*8617a60dSAndroid Build Coastguard Worker 	char *to_find = NULL;
249*8617a60dSAndroid Build Coastguard Worker 
250*8617a60dSAndroid Build Coastguard Worker 	if (asprintf(&to_find, "\n%s=", config_field) == -1) {
251*8617a60dSAndroid Build Coastguard Worker 		fprintf(stderr, "Out of Memory\n");
252*8617a60dSAndroid Build Coastguard Worker 		VB2_DIE("Out of memory\n");
253*8617a60dSAndroid Build Coastguard Worker 	}
254*8617a60dSAndroid Build Coastguard Worker 
255*8617a60dSAndroid Build Coastguard Worker 	const char *start = strstr(buf, to_find);
256*8617a60dSAndroid Build Coastguard Worker 	if (start)
257*8617a60dSAndroid Build Coastguard Worker 		start += strlen(to_find);
258*8617a60dSAndroid Build Coastguard Worker 
259*8617a60dSAndroid Build Coastguard Worker 	free(to_find);
260*8617a60dSAndroid Build Coastguard Worker 
261*8617a60dSAndroid Build Coastguard Worker 	if (start) {
262*8617a60dSAndroid Build Coastguard Worker 		char *end = strchr(start, '\n');
263*8617a60dSAndroid Build Coastguard Worker 		if (end)
264*8617a60dSAndroid Build Coastguard Worker 			return strndup(start, end - start);
265*8617a60dSAndroid Build Coastguard Worker 	}
266*8617a60dSAndroid Build Coastguard Worker 
267*8617a60dSAndroid Build Coastguard Worker 	return NULL;
268*8617a60dSAndroid Build Coastguard Worker }
269*8617a60dSAndroid Build Coastguard Worker 
get_config_value(const char * file,const char * region,const char * config_field,char ** value)270*8617a60dSAndroid Build Coastguard Worker static vb2_error_t get_config_value(const char *file, const char *region,
271*8617a60dSAndroid Build Coastguard Worker 				    const char *config_field, char **value)
272*8617a60dSAndroid Build Coastguard Worker {
273*8617a60dSAndroid Build Coastguard Worker 	int status;
274*8617a60dSAndroid Build Coastguard Worker 	const char *cbfstool = get_cbfstool_path();
275*8617a60dSAndroid Build Coastguard Worker 	const size_t data_buffer_sz = 1024 * 1024;
276*8617a60dSAndroid Build Coastguard Worker 	char *data_buffer = malloc(data_buffer_sz);
277*8617a60dSAndroid Build Coastguard Worker 	vb2_error_t rv = VB2_ERROR_CBFSTOOL;
278*8617a60dSAndroid Build Coastguard Worker 
279*8617a60dSAndroid Build Coastguard Worker 	*value = NULL;
280*8617a60dSAndroid Build Coastguard Worker 
281*8617a60dSAndroid Build Coastguard Worker 	if (!data_buffer)
282*8617a60dSAndroid Build Coastguard Worker 		goto done;
283*8617a60dSAndroid Build Coastguard Worker 
284*8617a60dSAndroid Build Coastguard Worker 	struct subprocess_target output = {
285*8617a60dSAndroid Build Coastguard Worker 		.type = TARGET_BUFFER_NULL_TERMINATED,
286*8617a60dSAndroid Build Coastguard Worker 		.buffer = {
287*8617a60dSAndroid Build Coastguard Worker 			.buf = data_buffer,
288*8617a60dSAndroid Build Coastguard Worker 			.size = data_buffer_sz,
289*8617a60dSAndroid Build Coastguard Worker 		},
290*8617a60dSAndroid Build Coastguard Worker 	};
291*8617a60dSAndroid Build Coastguard Worker 	const char *argv[] = {
292*8617a60dSAndroid Build Coastguard Worker 		cbfstool, file, "extract", "-n", "config", "-f", "/dev/stdout",
293*8617a60dSAndroid Build Coastguard Worker 		ARGV_END(region)
294*8617a60dSAndroid Build Coastguard Worker 	};
295*8617a60dSAndroid Build Coastguard Worker 
296*8617a60dSAndroid Build Coastguard Worker 	status = subprocess_run(argv, &subprocess_null, &output,
297*8617a60dSAndroid Build Coastguard Worker 				&subprocess_null);
298*8617a60dSAndroid Build Coastguard Worker 
299*8617a60dSAndroid Build Coastguard Worker 	if (status < 0) {
300*8617a60dSAndroid Build Coastguard Worker 		fprintf(stderr, "%s(): cbfstool invocation failed: %m\n",
301*8617a60dSAndroid Build Coastguard Worker 			__func__);
302*8617a60dSAndroid Build Coastguard Worker 		exit(1);
303*8617a60dSAndroid Build Coastguard Worker 	}
304*8617a60dSAndroid Build Coastguard Worker 
305*8617a60dSAndroid Build Coastguard Worker 	if (status > 0)
306*8617a60dSAndroid Build Coastguard Worker 		goto done;
307*8617a60dSAndroid Build Coastguard Worker 
308*8617a60dSAndroid Build Coastguard Worker 	*value = extract_config_value(data_buffer, config_field);
309*8617a60dSAndroid Build Coastguard Worker 
310*8617a60dSAndroid Build Coastguard Worker 	rv = VB2_SUCCESS;
311*8617a60dSAndroid Build Coastguard Worker done:
312*8617a60dSAndroid Build Coastguard Worker 	free(data_buffer);
313*8617a60dSAndroid Build Coastguard Worker 	return rv;
314*8617a60dSAndroid Build Coastguard Worker }
315*8617a60dSAndroid Build Coastguard Worker 
cbfstool_get_config_bool(const char * file,const char * region,const char * config_field,bool * value)316*8617a60dSAndroid Build Coastguard Worker vb2_error_t cbfstool_get_config_bool(const char *file, const char *region,
317*8617a60dSAndroid Build Coastguard Worker 				     const char *config_field, bool *value)
318*8617a60dSAndroid Build Coastguard Worker {
319*8617a60dSAndroid Build Coastguard Worker 	vb2_error_t rv;
320*8617a60dSAndroid Build Coastguard Worker 	char *raw_value = NULL;
321*8617a60dSAndroid Build Coastguard Worker 
322*8617a60dSAndroid Build Coastguard Worker 	*value = false;
323*8617a60dSAndroid Build Coastguard Worker 
324*8617a60dSAndroid Build Coastguard Worker 	rv = get_config_value(file, region, config_field, &raw_value);
325*8617a60dSAndroid Build Coastguard Worker 	if (rv)
326*8617a60dSAndroid Build Coastguard Worker 		return rv;
327*8617a60dSAndroid Build Coastguard Worker 
328*8617a60dSAndroid Build Coastguard Worker 	if (raw_value && strcmp(raw_value, "y") == 0)
329*8617a60dSAndroid Build Coastguard Worker 		*value = true;
330*8617a60dSAndroid Build Coastguard Worker 
331*8617a60dSAndroid Build Coastguard Worker 	free(raw_value);
332*8617a60dSAndroid Build Coastguard Worker 	return VB2_SUCCESS;
333*8617a60dSAndroid Build Coastguard Worker }
334*8617a60dSAndroid Build Coastguard Worker 
cbfstool_get_config_string(const char * file,const char * region,const char * config_field,char ** value)335*8617a60dSAndroid Build Coastguard Worker vb2_error_t cbfstool_get_config_string(const char *file, const char *region,
336*8617a60dSAndroid Build Coastguard Worker 				       const char *config_field, char **value)
337*8617a60dSAndroid Build Coastguard Worker {
338*8617a60dSAndroid Build Coastguard Worker 	vb2_error_t rv;
339*8617a60dSAndroid Build Coastguard Worker 	char *raw_value = NULL;
340*8617a60dSAndroid Build Coastguard Worker 
341*8617a60dSAndroid Build Coastguard Worker 	*value = NULL;
342*8617a60dSAndroid Build Coastguard Worker 
343*8617a60dSAndroid Build Coastguard Worker 	rv = get_config_value(file, region, config_field, &raw_value);
344*8617a60dSAndroid Build Coastguard Worker 	if (rv)
345*8617a60dSAndroid Build Coastguard Worker 		return rv;
346*8617a60dSAndroid Build Coastguard Worker 
347*8617a60dSAndroid Build Coastguard Worker 	/*
348*8617a60dSAndroid Build Coastguard Worker 	 * With CL:4085654, all the valid configs of type 'str' should be
349*8617a60dSAndroid Build Coastguard Worker 	 * present in the "config" CBFS file.
350*8617a60dSAndroid Build Coastguard Worker 	 */
351*8617a60dSAndroid Build Coastguard Worker 	if (!raw_value) {
352*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("Config '%s' not found in %s.", config_field, file);
353*8617a60dSAndroid Build Coastguard Worker 		return VB2_ERROR_CBFSTOOL;
354*8617a60dSAndroid Build Coastguard Worker 	}
355*8617a60dSAndroid Build Coastguard Worker 
356*8617a60dSAndroid Build Coastguard Worker 	size_t len = strlen(raw_value);
357*8617a60dSAndroid Build Coastguard Worker 	if (len < 2 || raw_value[0] != '"' || raw_value[len - 1] != '"') {
358*8617a60dSAndroid Build Coastguard Worker 		VB2_DEBUG("%s value '%s' is not enclosed with double quotes.",
359*8617a60dSAndroid Build Coastguard Worker 			  config_field, raw_value);
360*8617a60dSAndroid Build Coastguard Worker 		rv = VB2_ERROR_CBFSTOOL;
361*8617a60dSAndroid Build Coastguard Worker 		goto done;
362*8617a60dSAndroid Build Coastguard Worker 	}
363*8617a60dSAndroid Build Coastguard Worker 
364*8617a60dSAndroid Build Coastguard Worker 	*value = strndup(&raw_value[1], len - 2);
365*8617a60dSAndroid Build Coastguard Worker 
366*8617a60dSAndroid Build Coastguard Worker done:
367*8617a60dSAndroid Build Coastguard Worker 	free(raw_value);
368*8617a60dSAndroid Build Coastguard Worker 	return rv;
369*8617a60dSAndroid Build Coastguard Worker }
370