xref: /aosp_15_r20/external/gsc-utils/extra/usb_updater/verify_ro.c (revision 4f2df630800bdcf1d4f0decf95d8a1cb87344f5f)
1*4f2df630SAndroid Build Coastguard Worker /*
2*4f2df630SAndroid Build Coastguard Worker  * Copyright 2018 The ChromiumOS Authors
3*4f2df630SAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
4*4f2df630SAndroid Build Coastguard Worker  * found in the LICENSE file.
5*4f2df630SAndroid Build Coastguard Worker  */
6*4f2df630SAndroid Build Coastguard Worker 
7*4f2df630SAndroid Build Coastguard Worker #include <errno.h>
8*4f2df630SAndroid Build Coastguard Worker #include <stdbool.h>
9*4f2df630SAndroid Build Coastguard Worker #include <stdio.h>
10*4f2df630SAndroid Build Coastguard Worker #include <stdlib.h>
11*4f2df630SAndroid Build Coastguard Worker #include <string.h>
12*4f2df630SAndroid Build Coastguard Worker 
13*4f2df630SAndroid Build Coastguard Worker #include "config.h"
14*4f2df630SAndroid Build Coastguard Worker #include "desc_parser.h"
15*4f2df630SAndroid Build Coastguard Worker #include "gsctool.h"
16*4f2df630SAndroid Build Coastguard Worker #include "tpm_vendor_cmds.h"
17*4f2df630SAndroid Build Coastguard Worker #include "verify_ro.h"
18*4f2df630SAndroid Build Coastguard Worker 
19*4f2df630SAndroid Build Coastguard Worker /* Index of the matching hash variant. */
20*4f2df630SAndroid Build Coastguard Worker static ssize_t matching_variant;
21*4f2df630SAndroid Build Coastguard Worker 
22*4f2df630SAndroid Build Coastguard Worker /*
23*4f2df630SAndroid Build Coastguard Worker  * Print out passed in buffer contents in hex, 16 bytes per line, each line
24*4f2df630SAndroid Build Coastguard Worker  * starting with the base address value.
25*4f2df630SAndroid Build Coastguard Worker  *
26*4f2df630SAndroid Build Coastguard Worker  * If the passed in base address is not aligned at 16 byte boundary, skip
27*4f2df630SAndroid Build Coastguard Worker  * positions in the dump line so that the address is displayed rounded down to
28*4f2df630SAndroid Build Coastguard Worker  * the closest lower 16 byte boundary.
29*4f2df630SAndroid Build Coastguard Worker  *
30*4f2df630SAndroid Build Coastguard Worker  * For instance passing base of 0x4007 and size of 20 will result in a
31*4f2df630SAndroid Build Coastguard Worker  * printout like:
32*4f2df630SAndroid Build Coastguard Worker  *
33*4f2df630SAndroid Build Coastguard Worker  * 004000                      e0 00 00 00 00 66 c7 05 04
34*4f2df630SAndroid Build Coastguard Worker  * 004010 80 06 e0 06 00 66 c7 05 20 90 06
35*4f2df630SAndroid Build Coastguard Worker  *
36*4f2df630SAndroid Build Coastguard Worker  * If title is nonzero - print out the string it points to before printing
37*4f2df630SAndroid Build Coastguard Worker  * out buffer contents.
38*4f2df630SAndroid Build Coastguard Worker  */
print_buffer_aligned(const char * title,uint32_t base,size_t size,const void * data)39*4f2df630SAndroid Build Coastguard Worker static void print_buffer_aligned(const char *title, uint32_t base, size_t size,
40*4f2df630SAndroid Build Coastguard Worker 				 const void *data)
41*4f2df630SAndroid Build Coastguard Worker {
42*4f2df630SAndroid Build Coastguard Worker 	const uint8_t *bytes = data;
43*4f2df630SAndroid Build Coastguard Worker 	size_t i;
44*4f2df630SAndroid Build Coastguard Worker 	uint8_t alignment;
45*4f2df630SAndroid Build Coastguard Worker 
46*4f2df630SAndroid Build Coastguard Worker 	/*
47*4f2df630SAndroid Build Coastguard Worker 	 * Calculate how many characters we need to skip in the first dump
48*4f2df630SAndroid Build Coastguard Worker 	 * line.
49*4f2df630SAndroid Build Coastguard Worker 	 */
50*4f2df630SAndroid Build Coastguard Worker 	alignment = base % 16;
51*4f2df630SAndroid Build Coastguard Worker 	if (alignment) {
52*4f2df630SAndroid Build Coastguard Worker 		size += alignment;
53*4f2df630SAndroid Build Coastguard Worker 		base &= ~0xf;
54*4f2df630SAndroid Build Coastguard Worker 	}
55*4f2df630SAndroid Build Coastguard Worker 
56*4f2df630SAndroid Build Coastguard Worker 	if (title)
57*4f2df630SAndroid Build Coastguard Worker 		printf("%s\n", title);
58*4f2df630SAndroid Build Coastguard Worker 
59*4f2df630SAndroid Build Coastguard Worker 	/* Let's print data space separated 16 bytes per line. */
60*4f2df630SAndroid Build Coastguard Worker 	for (i = 0; i < size; i++) {
61*4f2df630SAndroid Build Coastguard Worker 		if (!(i % 16))
62*4f2df630SAndroid Build Coastguard Worker 			printf("\n%06zx", base + i);
63*4f2df630SAndroid Build Coastguard Worker 
64*4f2df630SAndroid Build Coastguard Worker 		if (i < alignment)
65*4f2df630SAndroid Build Coastguard Worker 			printf("   ");
66*4f2df630SAndroid Build Coastguard Worker 		else
67*4f2df630SAndroid Build Coastguard Worker 			printf(" %02x", bytes[i - alignment]);
68*4f2df630SAndroid Build Coastguard Worker 	}
69*4f2df630SAndroid Build Coastguard Worker }
70*4f2df630SAndroid Build Coastguard Worker 
71*4f2df630SAndroid Build Coastguard Worker /* Change the DUT spihash range to the new_type value. */
set_new_range(struct transfer_descriptor * td,enum range_type_t new_type)72*4f2df630SAndroid Build Coastguard Worker static int set_new_range(struct transfer_descriptor *td,
73*4f2df630SAndroid Build Coastguard Worker 			 enum range_type_t new_type)
74*4f2df630SAndroid Build Coastguard Worker {
75*4f2df630SAndroid Build Coastguard Worker 	uint32_t rv;
76*4f2df630SAndroid Build Coastguard Worker 	struct vendor_cc_spi_hash_request req;
77*4f2df630SAndroid Build Coastguard Worker 
78*4f2df630SAndroid Build Coastguard Worker 	memset(&req, 0, sizeof(req));
79*4f2df630SAndroid Build Coastguard Worker 
80*4f2df630SAndroid Build Coastguard Worker 	/* Need to send command to change spihash mode. */
81*4f2df630SAndroid Build Coastguard Worker 	switch (new_type) {
82*4f2df630SAndroid Build Coastguard Worker 	case AP_RANGE:
83*4f2df630SAndroid Build Coastguard Worker 		req.subcmd = SPI_HASH_SUBCMD_AP;
84*4f2df630SAndroid Build Coastguard Worker 		break;
85*4f2df630SAndroid Build Coastguard Worker 	case EC_RANGE:
86*4f2df630SAndroid Build Coastguard Worker 		req.subcmd = SPI_HASH_SUBCMD_EC;
87*4f2df630SAndroid Build Coastguard Worker 		break;
88*4f2df630SAndroid Build Coastguard Worker 	case EC_GANG_RANGE:
89*4f2df630SAndroid Build Coastguard Worker 		req.subcmd = SPI_HASH_SUBCMD_EC;
90*4f2df630SAndroid Build Coastguard Worker 		req.flags = SPI_HASH_FLAG_EC_GANG;
91*4f2df630SAndroid Build Coastguard Worker 		break;
92*4f2df630SAndroid Build Coastguard Worker 	default: /* Should never happen. */
93*4f2df630SAndroid Build Coastguard Worker 		return -EINVAL;
94*4f2df630SAndroid Build Coastguard Worker 	}
95*4f2df630SAndroid Build Coastguard Worker 
96*4f2df630SAndroid Build Coastguard Worker 	rv = send_vendor_command(td, VENDOR_CC_SPI_HASH, &req, sizeof(req), 0,
97*4f2df630SAndroid Build Coastguard Worker 				 NULL);
98*4f2df630SAndroid Build Coastguard Worker 
99*4f2df630SAndroid Build Coastguard Worker 	if (!rv)
100*4f2df630SAndroid Build Coastguard Worker 		return 0;
101*4f2df630SAndroid Build Coastguard Worker 
102*4f2df630SAndroid Build Coastguard Worker 	if (rv == VENDOR_RC_IN_PROGRESS) {
103*4f2df630SAndroid Build Coastguard Worker 		/* This will exit() on error. */
104*4f2df630SAndroid Build Coastguard Worker 		poll_for_pp(td, VENDOR_CC_SPI_HASH, SPI_HASH_PP_POLL);
105*4f2df630SAndroid Build Coastguard Worker 	} else {
106*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "%s: failed setting range type %d, error %d\n",
107*4f2df630SAndroid Build Coastguard Worker 			__func__, new_type, rv);
108*4f2df630SAndroid Build Coastguard Worker 		return -EINVAL;
109*4f2df630SAndroid Build Coastguard Worker 	}
110*4f2df630SAndroid Build Coastguard Worker 
111*4f2df630SAndroid Build Coastguard Worker 	return 0;
112*4f2df630SAndroid Build Coastguard Worker }
113*4f2df630SAndroid Build Coastguard Worker 
114*4f2df630SAndroid Build Coastguard Worker /*
115*4f2df630SAndroid Build Coastguard Worker  * Verify a dump descriptor hash section defined by 'range'. The passed in by
116*4f2df630SAndroid Build Coastguard Worker  * pointer structure req has the range offset and size already initialized.
117*4f2df630SAndroid Build Coastguard Worker  *
118*4f2df630SAndroid Build Coastguard Worker  * Make sure that matching hashes are at the same index in the hash variants
119*4f2df630SAndroid Build Coastguard Worker  * arrays within the same board section.
120*4f2df630SAndroid Build Coastguard Worker  */
verify_hash_section(struct transfer_descriptor * td,struct vendor_cc_spi_hash_request * req,struct addr_range * range)121*4f2df630SAndroid Build Coastguard Worker static int verify_hash_section(struct transfer_descriptor *td,
122*4f2df630SAndroid Build Coastguard Worker 			       struct vendor_cc_spi_hash_request *req,
123*4f2df630SAndroid Build Coastguard Worker 			       struct addr_range *range)
124*4f2df630SAndroid Build Coastguard Worker {
125*4f2df630SAndroid Build Coastguard Worker 	size_t i;
126*4f2df630SAndroid Build Coastguard Worker 	uint8_t response[sizeof(range->variants->expected_result)];
127*4f2df630SAndroid Build Coastguard Worker 	size_t response_size;
128*4f2df630SAndroid Build Coastguard Worker 	int rv;
129*4f2df630SAndroid Build Coastguard Worker 
130*4f2df630SAndroid Build Coastguard Worker 	/* First retrieve hash from the DUT. */
131*4f2df630SAndroid Build Coastguard Worker 	response_size = sizeof(response);
132*4f2df630SAndroid Build Coastguard Worker 	req->subcmd = SPI_HASH_SUBCMD_SHA256;
133*4f2df630SAndroid Build Coastguard Worker 	rv = send_vendor_command(td, VENDOR_CC_SPI_HASH, req, sizeof(*req),
134*4f2df630SAndroid Build Coastguard Worker 				 response, &response_size);
135*4f2df630SAndroid Build Coastguard Worker 
136*4f2df630SAndroid Build Coastguard Worker 	if (rv) {
137*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr,
138*4f2df630SAndroid Build Coastguard Worker 			"%s: failed retrieving hash at %x, tpm error %d\n",
139*4f2df630SAndroid Build Coastguard Worker 			__func__, req->offset, rv);
140*4f2df630SAndroid Build Coastguard Worker 		return -EINVAL;
141*4f2df630SAndroid Build Coastguard Worker 	}
142*4f2df630SAndroid Build Coastguard Worker 
143*4f2df630SAndroid Build Coastguard Worker 	if (response_size != sizeof(response)) {
144*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "got %zd bytes in response for range %x:%x\n",
145*4f2df630SAndroid Build Coastguard Worker 			response_size, req->offset, req->size);
146*4f2df630SAndroid Build Coastguard Worker 		return -EINVAL;
147*4f2df630SAndroid Build Coastguard Worker 	}
148*4f2df630SAndroid Build Coastguard Worker 
149*4f2df630SAndroid Build Coastguard Worker 	if (matching_variant < 0) {
150*4f2df630SAndroid Build Coastguard Worker 		/* This is the first hash range to be processed. */
151*4f2df630SAndroid Build Coastguard Worker 		struct result_node *variant = range->variants;
152*4f2df630SAndroid Build Coastguard Worker 
153*4f2df630SAndroid Build Coastguard Worker 		for (i = 0; i < range->variant_count; i++) {
154*4f2df630SAndroid Build Coastguard Worker 			if (!memcmp(variant->expected_result, response,
155*4f2df630SAndroid Build Coastguard Worker 				    response_size)) {
156*4f2df630SAndroid Build Coastguard Worker 				matching_variant = i;
157*4f2df630SAndroid Build Coastguard Worker 				return 0;
158*4f2df630SAndroid Build Coastguard Worker 			}
159*4f2df630SAndroid Build Coastguard Worker 			variant++;
160*4f2df630SAndroid Build Coastguard Worker 		}
161*4f2df630SAndroid Build Coastguard Worker 
162*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "no matching hash found for range %x:%x\n",
163*4f2df630SAndroid Build Coastguard Worker 			req->offset, req->size);
164*4f2df630SAndroid Build Coastguard Worker 		return -EINVAL;
165*4f2df630SAndroid Build Coastguard Worker 	}
166*4f2df630SAndroid Build Coastguard Worker 
167*4f2df630SAndroid Build Coastguard Worker 	if (!memcmp(range->variants[matching_variant].expected_result, response,
168*4f2df630SAndroid Build Coastguard Worker 		    response_size))
169*4f2df630SAndroid Build Coastguard Worker 		return 0;
170*4f2df630SAndroid Build Coastguard Worker 
171*4f2df630SAndroid Build Coastguard Worker 	fprintf(stderr, "hash mismatch for range %x:%x\n", req->offset,
172*4f2df630SAndroid Build Coastguard Worker 		req->size);
173*4f2df630SAndroid Build Coastguard Worker 
174*4f2df630SAndroid Build Coastguard Worker 	return -EINVAL;
175*4f2df630SAndroid Build Coastguard Worker }
176*4f2df630SAndroid Build Coastguard Worker 
177*4f2df630SAndroid Build Coastguard Worker /*
178*4f2df630SAndroid Build Coastguard Worker  * Dump DUT's memory in the range defined by contents of the passed in req
179*4f2df630SAndroid Build Coastguard Worker  * structure.
180*4f2df630SAndroid Build Coastguard Worker  *
181*4f2df630SAndroid Build Coastguard Worker  * The Cr50 SPI hash dump vendor command implementation limits size of the
182*4f2df630SAndroid Build Coastguard Worker  * dump to 32, so in case the caller requests more than 32 bytes retrieve them
183*4f2df630SAndroid Build Coastguard Worker  * in 32 byte blocks.
184*4f2df630SAndroid Build Coastguard Worker  *
185*4f2df630SAndroid Build Coastguard Worker  * If base address of the range is not aligned at 16, retrieve smaller
186*4f2df630SAndroid Build Coastguard Worker  * quantity such that the following transactions retrieve block starting at
187*4f2df630SAndroid Build Coastguard Worker  * aligned addresses, this makes for a better looking hex dump.
188*4f2df630SAndroid Build Coastguard Worker  */
dump_range(struct transfer_descriptor * td,struct vendor_cc_spi_hash_request * req)189*4f2df630SAndroid Build Coastguard Worker static int dump_range(struct transfer_descriptor *td,
190*4f2df630SAndroid Build Coastguard Worker 		      struct vendor_cc_spi_hash_request *req)
191*4f2df630SAndroid Build Coastguard Worker {
192*4f2df630SAndroid Build Coastguard Worker 	size_t remaining_size = req->size;
193*4f2df630SAndroid Build Coastguard Worker 	size_t response_size;
194*4f2df630SAndroid Build Coastguard Worker 	/* Max size of a single shot is 32 bytes. */
195*4f2df630SAndroid Build Coastguard Worker 	const size_t max_transfer = 32;
196*4f2df630SAndroid Build Coastguard Worker 	uint8_t response[max_transfer];
197*4f2df630SAndroid Build Coastguard Worker 
198*4f2df630SAndroid Build Coastguard Worker 	req->subcmd = SPI_HASH_SUBCMD_DUMP;
199*4f2df630SAndroid Build Coastguard Worker 	while (remaining_size) {
200*4f2df630SAndroid Build Coastguard Worker 		size_t shot_size = max_transfer;
201*4f2df630SAndroid Build Coastguard Worker 		uint8_t alignment;
202*4f2df630SAndroid Build Coastguard Worker 		uint32_t rv;
203*4f2df630SAndroid Build Coastguard Worker 
204*4f2df630SAndroid Build Coastguard Worker 		alignment = req->offset % 16;
205*4f2df630SAndroid Build Coastguard Worker 
206*4f2df630SAndroid Build Coastguard Worker 		if (alignment && ((alignment + remaining_size) > max_transfer))
207*4f2df630SAndroid Build Coastguard Worker 			/* first line should be truncated. */
208*4f2df630SAndroid Build Coastguard Worker 			shot_size = max_transfer - alignment;
209*4f2df630SAndroid Build Coastguard Worker 		else if (shot_size > remaining_size)
210*4f2df630SAndroid Build Coastguard Worker 			shot_size = remaining_size;
211*4f2df630SAndroid Build Coastguard Worker 
212*4f2df630SAndroid Build Coastguard Worker 		req->size = shot_size;
213*4f2df630SAndroid Build Coastguard Worker 		response_size = shot_size;
214*4f2df630SAndroid Build Coastguard Worker 		rv = send_vendor_command(td, VENDOR_CC_SPI_HASH, req,
215*4f2df630SAndroid Build Coastguard Worker 					 sizeof(*req), response,
216*4f2df630SAndroid Build Coastguard Worker 					 &response_size);
217*4f2df630SAndroid Build Coastguard Worker 		if (rv) {
218*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr,
219*4f2df630SAndroid Build Coastguard Worker 				"%s: failed getting dump contents at %x\n",
220*4f2df630SAndroid Build Coastguard Worker 				__func__, req->offset);
221*4f2df630SAndroid Build Coastguard Worker 			return -EINVAL;
222*4f2df630SAndroid Build Coastguard Worker 		}
223*4f2df630SAndroid Build Coastguard Worker 
224*4f2df630SAndroid Build Coastguard Worker 		if (response_size != shot_size) {
225*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr,
226*4f2df630SAndroid Build Coastguard Worker 				"%s: dump error: got %zd bytes, expected %zd\n",
227*4f2df630SAndroid Build Coastguard Worker 				__func__, response_size, shot_size);
228*4f2df630SAndroid Build Coastguard Worker 			return -EINVAL;
229*4f2df630SAndroid Build Coastguard Worker 		}
230*4f2df630SAndroid Build Coastguard Worker 
231*4f2df630SAndroid Build Coastguard Worker 		print_buffer_aligned(NULL, req->offset, shot_size, response);
232*4f2df630SAndroid Build Coastguard Worker 		remaining_size -= shot_size;
233*4f2df630SAndroid Build Coastguard Worker 		req->offset += shot_size;
234*4f2df630SAndroid Build Coastguard Worker 	}
235*4f2df630SAndroid Build Coastguard Worker 	printf("\n");
236*4f2df630SAndroid Build Coastguard Worker 
237*4f2df630SAndroid Build Coastguard Worker 	return 0;
238*4f2df630SAndroid Build Coastguard Worker }
239*4f2df630SAndroid Build Coastguard Worker 
240*4f2df630SAndroid Build Coastguard Worker /*
241*4f2df630SAndroid Build Coastguard Worker  * Iterate through sections of a board descriptor database, retrieving hashes
242*4f2df630SAndroid Build Coastguard Worker  * or straight memory blocks as defined by description sections.
243*4f2df630SAndroid Build Coastguard Worker  */
process_descriptor_sections(struct transfer_descriptor * td)244*4f2df630SAndroid Build Coastguard Worker static int process_descriptor_sections(struct transfer_descriptor *td)
245*4f2df630SAndroid Build Coastguard Worker {
246*4f2df630SAndroid Build Coastguard Worker 	struct vendor_cc_spi_hash_request req;
247*4f2df630SAndroid Build Coastguard Worker 	int rv;
248*4f2df630SAndroid Build Coastguard Worker 	struct addr_range *range;
249*4f2df630SAndroid Build Coastguard Worker 	enum range_type_t current_range = NOT_A_RANGE;
250*4f2df630SAndroid Build Coastguard Worker 
251*4f2df630SAndroid Build Coastguard Worker 	do {
252*4f2df630SAndroid Build Coastguard Worker 		/*
253*4f2df630SAndroid Build Coastguard Worker 		 * Retrieve next range descriptor section from the descriptor
254*4f2df630SAndroid Build Coastguard Worker 		 * database. The function below is guaranteed to set range to
255*4f2df630SAndroid Build Coastguard Worker 		 * NULL on any error.
256*4f2df630SAndroid Build Coastguard Worker 		 */
257*4f2df630SAndroid Build Coastguard Worker 		rv = parser_get_next_range(&range);
258*4f2df630SAndroid Build Coastguard Worker 		if (rv) {
259*4f2df630SAndroid Build Coastguard Worker 			/*
260*4f2df630SAndroid Build Coastguard Worker 			 * ENODATA means all board's sections have been
261*4f2df630SAndroid Build Coastguard Worker 			 * processed.
262*4f2df630SAndroid Build Coastguard Worker 			 */
263*4f2df630SAndroid Build Coastguard Worker 			if (rv == -ENODATA)
264*4f2df630SAndroid Build Coastguard Worker 				rv = 0;
265*4f2df630SAndroid Build Coastguard Worker 			break;
266*4f2df630SAndroid Build Coastguard Worker 		}
267*4f2df630SAndroid Build Coastguard Worker 
268*4f2df630SAndroid Build Coastguard Worker 		if (current_range != range->range_type) {
269*4f2df630SAndroid Build Coastguard Worker 			rv = set_new_range(td, range->range_type);
270*4f2df630SAndroid Build Coastguard Worker 			if (rv)
271*4f2df630SAndroid Build Coastguard Worker 				break;
272*4f2df630SAndroid Build Coastguard Worker 		}
273*4f2df630SAndroid Build Coastguard Worker 
274*4f2df630SAndroid Build Coastguard Worker 		memset(&req, 0, sizeof(req));
275*4f2df630SAndroid Build Coastguard Worker 		req.offset = range->base_addr;
276*4f2df630SAndroid Build Coastguard Worker 		req.size = range->range_size;
277*4f2df630SAndroid Build Coastguard Worker 
278*4f2df630SAndroid Build Coastguard Worker 		if (range->variant_count)
279*4f2df630SAndroid Build Coastguard Worker 			rv = verify_hash_section(td, &req, range);
280*4f2df630SAndroid Build Coastguard Worker 		else
281*4f2df630SAndroid Build Coastguard Worker 			rv = dump_range(td, &req);
282*4f2df630SAndroid Build Coastguard Worker 
283*4f2df630SAndroid Build Coastguard Worker 		free(range);
284*4f2df630SAndroid Build Coastguard Worker 		range = NULL;
285*4f2df630SAndroid Build Coastguard Worker 	} while (!rv);
286*4f2df630SAndroid Build Coastguard Worker 
287*4f2df630SAndroid Build Coastguard Worker 	if (range)
288*4f2df630SAndroid Build Coastguard Worker 		free(range);
289*4f2df630SAndroid Build Coastguard Worker 
290*4f2df630SAndroid Build Coastguard Worker 	return rv;
291*4f2df630SAndroid Build Coastguard Worker }
292*4f2df630SAndroid Build Coastguard Worker 
verify_ro(struct transfer_descriptor * td,const char * desc_file_name,bool show_machine_output)293*4f2df630SAndroid Build Coastguard Worker int verify_ro(struct transfer_descriptor *td, const char *desc_file_name,
294*4f2df630SAndroid Build Coastguard Worker 	      bool show_machine_output)
295*4f2df630SAndroid Build Coastguard Worker {
296*4f2df630SAndroid Build Coastguard Worker 	/* First find out board ID of the target. */
297*4f2df630SAndroid Build Coastguard Worker 	struct board_id bid;
298*4f2df630SAndroid Build Coastguard Worker 	char rlz_code[sizeof(bid.type) + 1];
299*4f2df630SAndroid Build Coastguard Worker 	int section_count = 0;
300*4f2df630SAndroid Build Coastguard Worker 	int rv = 0;
301*4f2df630SAndroid Build Coastguard Worker 
302*4f2df630SAndroid Build Coastguard Worker 	/*
303*4f2df630SAndroid Build Coastguard Worker 	 * Find out what Board ID is the device we are talking to. This
304*4f2df630SAndroid Build Coastguard Worker 	 * function calls exit() on any error.
305*4f2df630SAndroid Build Coastguard Worker 	 */
306*4f2df630SAndroid Build Coastguard Worker 	process_bid(td, bid_get, &bid, show_machine_output);
307*4f2df630SAndroid Build Coastguard Worker 
308*4f2df630SAndroid Build Coastguard Worker 	if (bid.type != ~bid.type_inv) {
309*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Inconsistent board ID: %08x != ~%08x\n",
310*4f2df630SAndroid Build Coastguard Worker 			bid.type, bid.type_inv);
311*4f2df630SAndroid Build Coastguard Worker 		return -EINVAL;
312*4f2df630SAndroid Build Coastguard Worker 	}
313*4f2df630SAndroid Build Coastguard Worker 
314*4f2df630SAndroid Build Coastguard Worker 	/*
315*4f2df630SAndroid Build Coastguard Worker 	 * Convert bid from int to asciiz so that it could be used for
316*4f2df630SAndroid Build Coastguard Worker 	 * strcmp() on the descriptor file section headers.
317*4f2df630SAndroid Build Coastguard Worker 	 */
318*4f2df630SAndroid Build Coastguard Worker 	memcpy(rlz_code, &bid.type, sizeof(rlz_code) - 1);
319*4f2df630SAndroid Build Coastguard Worker 	rlz_code[sizeof(rlz_code) - 1] = '\0';
320*4f2df630SAndroid Build Coastguard Worker 
321*4f2df630SAndroid Build Coastguard Worker 	while (!parser_find_board(desc_file_name, rlz_code)) {
322*4f2df630SAndroid Build Coastguard Worker 		/*
323*4f2df630SAndroid Build Coastguard Worker 		 * Each board section might have different index of the
324*4f2df630SAndroid Build Coastguard Worker 		 * matching hash variant.
325*4f2df630SAndroid Build Coastguard Worker 		 */
326*4f2df630SAndroid Build Coastguard Worker 		matching_variant = -1;
327*4f2df630SAndroid Build Coastguard Worker 
328*4f2df630SAndroid Build Coastguard Worker 		section_count++;
329*4f2df630SAndroid Build Coastguard Worker 		rv = process_descriptor_sections(td);
330*4f2df630SAndroid Build Coastguard Worker 		if (rv)
331*4f2df630SAndroid Build Coastguard Worker 			break;
332*4f2df630SAndroid Build Coastguard Worker 	}
333*4f2df630SAndroid Build Coastguard Worker 
334*4f2df630SAndroid Build Coastguard Worker 	if (section_count != 2) {
335*4f2df630SAndroid Build Coastguard Worker 		printf("Found wrong number of sections (%d) for board ID %s\n",
336*4f2df630SAndroid Build Coastguard Worker 		       section_count, rlz_code);
337*4f2df630SAndroid Build Coastguard Worker 		rv = -EINVAL;
338*4f2df630SAndroid Build Coastguard Worker 	} else if (!rv) {
339*4f2df630SAndroid Build Coastguard Worker 		/*
340*4f2df630SAndroid Build Coastguard Worker 		 * Check was successful, send command to exit verification
341*4f2df630SAndroid Build Coastguard Worker 		 * mode.
342*4f2df630SAndroid Build Coastguard Worker 		 */
343*4f2df630SAndroid Build Coastguard Worker 		struct vendor_cc_spi_hash_request req;
344*4f2df630SAndroid Build Coastguard Worker 
345*4f2df630SAndroid Build Coastguard Worker 		memset(&req, 0, sizeof(req));
346*4f2df630SAndroid Build Coastguard Worker 		req.subcmd = SPI_HASH_SUBCMD_DISABLE;
347*4f2df630SAndroid Build Coastguard Worker 		rv = send_vendor_command(td, VENDOR_CC_SPI_HASH, &req,
348*4f2df630SAndroid Build Coastguard Worker 					 sizeof(req), 0, NULL);
349*4f2df630SAndroid Build Coastguard Worker 		if (rv) {
350*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr, "%s: spi hash disable TPM error %d\n",
351*4f2df630SAndroid Build Coastguard Worker 				__func__, rv);
352*4f2df630SAndroid Build Coastguard Worker 			rv = -EINVAL;
353*4f2df630SAndroid Build Coastguard Worker 		}
354*4f2df630SAndroid Build Coastguard Worker 	}
355*4f2df630SAndroid Build Coastguard Worker 
356*4f2df630SAndroid Build Coastguard Worker 	parser_done();
357*4f2df630SAndroid Build Coastguard Worker 	return rv;
358*4f2df630SAndroid Build Coastguard Worker }
359