xref: /aosp_15_r20/external/gsc-utils/extra/usb_updater/gsctool.c (revision 4f2df630800bdcf1d4f0decf95d8a1cb87344f5f)
1*4f2df630SAndroid Build Coastguard Worker /*
2*4f2df630SAndroid Build Coastguard Worker  * Copyright 2015 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 <asm/byteorder.h>
8*4f2df630SAndroid Build Coastguard Worker #include <ctype.h>
9*4f2df630SAndroid Build Coastguard Worker #include <endian.h>
10*4f2df630SAndroid Build Coastguard Worker #include <errno.h>
11*4f2df630SAndroid Build Coastguard Worker #include <fcntl.h>
12*4f2df630SAndroid Build Coastguard Worker #include <getopt.h>
13*4f2df630SAndroid Build Coastguard Worker #include <libusb.h>
14*4f2df630SAndroid Build Coastguard Worker #include <openssl/evp.h>
15*4f2df630SAndroid Build Coastguard Worker #include <openssl/sha.h>
16*4f2df630SAndroid Build Coastguard Worker #include <stdarg.h>
17*4f2df630SAndroid Build Coastguard Worker #include <stdbool.h>
18*4f2df630SAndroid Build Coastguard Worker #include <stdint.h>
19*4f2df630SAndroid Build Coastguard Worker #include <stdio.h>
20*4f2df630SAndroid Build Coastguard Worker #include <stdlib.h>
21*4f2df630SAndroid Build Coastguard Worker #include <string.h>
22*4f2df630SAndroid Build Coastguard Worker #include <sys/stat.h>
23*4f2df630SAndroid Build Coastguard Worker #include <sys/types.h>
24*4f2df630SAndroid Build Coastguard Worker #include <termios.h>
25*4f2df630SAndroid Build Coastguard Worker #include <unistd.h>
26*4f2df630SAndroid Build Coastguard Worker 
27*4f2df630SAndroid Build Coastguard Worker #include "config.h"
28*4f2df630SAndroid Build Coastguard Worker 
29*4f2df630SAndroid Build Coastguard Worker #include "ap_ro_integrity_check.h"
30*4f2df630SAndroid Build Coastguard Worker #include "ccd_config.h"
31*4f2df630SAndroid Build Coastguard Worker #include "compile_time_macros.h"
32*4f2df630SAndroid Build Coastguard Worker #include "dauntless_event.h"
33*4f2df630SAndroid Build Coastguard Worker #include "flash_log.h"
34*4f2df630SAndroid Build Coastguard Worker #include "generated_version.h"
35*4f2df630SAndroid Build Coastguard Worker #include "gsctool.h"
36*4f2df630SAndroid Build Coastguard Worker #include "misc_util.h"
37*4f2df630SAndroid Build Coastguard Worker #include "signed_header.h"
38*4f2df630SAndroid Build Coastguard Worker #include "signed_manifest.h"
39*4f2df630SAndroid Build Coastguard Worker #include "tpm_registers.h"
40*4f2df630SAndroid Build Coastguard Worker #include "tpm_vendor_cmds.h"
41*4f2df630SAndroid Build Coastguard Worker #include "upgrade_fw.h"
42*4f2df630SAndroid Build Coastguard Worker #include "u2f.h"
43*4f2df630SAndroid Build Coastguard Worker #include "usb_descriptor.h"
44*4f2df630SAndroid Build Coastguard Worker #include "verify_ro.h"
45*4f2df630SAndroid Build Coastguard Worker 
46*4f2df630SAndroid Build Coastguard Worker /*
47*4f2df630SAndroid Build Coastguard Worker  * This enum must match CcdCap enum in applications/sys_mgr/src/ccd.rs in the
48*4f2df630SAndroid Build Coastguard Worker  * Ti50 common git tree.
49*4f2df630SAndroid Build Coastguard Worker  */
50*4f2df630SAndroid Build Coastguard Worker enum Ti50CcdCapabilities {
51*4f2df630SAndroid Build Coastguard Worker 	TI50_CCD_CAP_UART_GSC_RX_AP_TX = 0,
52*4f2df630SAndroid Build Coastguard Worker 	TI50_CCD_CAP_UART_GSC_TX_AP_RX,
53*4f2df630SAndroid Build Coastguard Worker 	TI50_CCD_CAP_UART_GSC_RX_EC_TX,
54*4f2df630SAndroid Build Coastguard Worker 	TI50_CCD_CAP_UART_GSC_TX_EC_RX,
55*4f2df630SAndroid Build Coastguard Worker 	TI50_CCD_CAP_UART_GSC_RX_FPMCU_TX,
56*4f2df630SAndroid Build Coastguard Worker 	TI50_CCD_CAP_UART_GSC_TX_FPMCU_RX,
57*4f2df630SAndroid Build Coastguard Worker 	TI50_CCD_CAP_FLASH_AP,
58*4f2df630SAndroid Build Coastguard Worker 	TI50_CCD_CAP_FLASH_EC,
59*4f2df630SAndroid Build Coastguard Worker 	TI50_CCD_CAP_OVERRIDE_WP,
60*4f2df630SAndroid Build Coastguard Worker 	TI50_CCD_CAP_REBOOT_ECAP,
61*4f2df630SAndroid Build Coastguard Worker 	TI50_CCD_CAP_GSC_FULL_CONSOLE,
62*4f2df630SAndroid Build Coastguard Worker 	TI50_CCD_CAP_UNLOCK_NO_REBOOT,
63*4f2df630SAndroid Build Coastguard Worker 	TI50_CCD_CAP_UNLOCK_NO_SHORT_PP,
64*4f2df630SAndroid Build Coastguard Worker 	TI50_CCD_CAP_OPEN_NO_TPM_WIPE,
65*4f2df630SAndroid Build Coastguard Worker 	TI50_CCD_CAP_OPEN_NO_LONG_PP,
66*4f2df630SAndroid Build Coastguard Worker 	TI50_CCD_CAP_REMOVE_BATTERY_BYPASS_PP,
67*4f2df630SAndroid Build Coastguard Worker 	TI50_CCD_CAP_I2_C,
68*4f2df630SAndroid Build Coastguard Worker 	TI50_CCD_CAP_FLASH_READ,
69*4f2df630SAndroid Build Coastguard Worker 	TI50_CCD_CAP_OPEN_NO_DEV_MODE,
70*4f2df630SAndroid Build Coastguard Worker 	TI50_CCD_CAP_OPEN_FROM_USB,
71*4f2df630SAndroid Build Coastguard Worker 	TI50_CCD_CAP_OVERRIDE_BATT,
72*4f2df630SAndroid Build Coastguard Worker 	TI50_CCD_CAP_BOOT_UNVERIFIED_RO,
73*4f2df630SAndroid Build Coastguard Worker 	TI50_CCD_CAP_COUNT,
74*4f2df630SAndroid Build Coastguard Worker };
75*4f2df630SAndroid Build Coastguard Worker 
76*4f2df630SAndroid Build Coastguard Worker static const struct ccd_capability_info ti50_cap_info[] = {
77*4f2df630SAndroid Build Coastguard Worker 	{ "UartGscRxAPTx", CCD_CAP_STATE_ALWAYS },
78*4f2df630SAndroid Build Coastguard Worker 	{ "UartGscTxAPRx", CCD_CAP_STATE_ALWAYS },
79*4f2df630SAndroid Build Coastguard Worker 	{ "UartGscRxECTx", CCD_CAP_STATE_ALWAYS },
80*4f2df630SAndroid Build Coastguard Worker 	{ "UartGscTxECRx", CCD_CAP_STATE_IF_OPENED },
81*4f2df630SAndroid Build Coastguard Worker 	{ "UartGscRxFpmcuTx", CCD_CAP_STATE_ALWAYS },
82*4f2df630SAndroid Build Coastguard Worker 	{ "UartGscTxFpmcuRx", CCD_CAP_STATE_IF_OPENED },
83*4f2df630SAndroid Build Coastguard Worker 	{ "FlashAP", CCD_CAP_STATE_IF_OPENED },
84*4f2df630SAndroid Build Coastguard Worker 	{ "FlashEC", CCD_CAP_STATE_IF_OPENED },
85*4f2df630SAndroid Build Coastguard Worker 	{ "OverrideWP", CCD_CAP_STATE_IF_OPENED },
86*4f2df630SAndroid Build Coastguard Worker 	{ "RebootECAP", CCD_CAP_STATE_IF_OPENED },
87*4f2df630SAndroid Build Coastguard Worker 	{ "GscFullConsole", CCD_CAP_STATE_IF_OPENED },
88*4f2df630SAndroid Build Coastguard Worker 	{ "UnlockNoReboot", CCD_CAP_STATE_ALWAYS },
89*4f2df630SAndroid Build Coastguard Worker 	{ "UnlockNoShortPP", CCD_CAP_STATE_ALWAYS },
90*4f2df630SAndroid Build Coastguard Worker 	{ "OpenNoTPMWipe", CCD_CAP_STATE_IF_OPENED },
91*4f2df630SAndroid Build Coastguard Worker 	{ "OpenNoLongPP", CCD_CAP_STATE_IF_OPENED },
92*4f2df630SAndroid Build Coastguard Worker 	{ "RemoveBatteryBypassPP", CCD_CAP_STATE_ALWAYS },
93*4f2df630SAndroid Build Coastguard Worker 	{ "I2C", CCD_CAP_STATE_IF_OPENED },
94*4f2df630SAndroid Build Coastguard Worker 	{ "FlashRead", CCD_CAP_STATE_ALWAYS },
95*4f2df630SAndroid Build Coastguard Worker 	/*
96*4f2df630SAndroid Build Coastguard Worker 	 * The below two settings do not match ccd.rs value, which is
97*4f2df630SAndroid Build Coastguard Worker 	 * controlled at compile time.
98*4f2df630SAndroid Build Coastguard Worker 	 */
99*4f2df630SAndroid Build Coastguard Worker 	{ "OpenNoDevMode", CCD_CAP_STATE_IF_OPENED },
100*4f2df630SAndroid Build Coastguard Worker 	{ "OpenFromUSB", CCD_CAP_STATE_IF_OPENED },
101*4f2df630SAndroid Build Coastguard Worker 	{ "OverrideBatt", CCD_CAP_STATE_IF_OPENED },
102*4f2df630SAndroid Build Coastguard Worker 	/* The below capability is presently set to 'never' in ccd.rs. */
103*4f2df630SAndroid Build Coastguard Worker 	{ "AllowUnverifiedRo", CCD_CAP_STATE_IF_OPENED },
104*4f2df630SAndroid Build Coastguard Worker };
105*4f2df630SAndroid Build Coastguard Worker 
106*4f2df630SAndroid Build Coastguard Worker #define CR50_CCD_CAP_COUNT CCD_CAP_COUNT
107*4f2df630SAndroid Build Coastguard Worker 
108*4f2df630SAndroid Build Coastguard Worker /*
109*4f2df630SAndroid Build Coastguard Worker  * One of the basic assumptions of the code handling multiple ccd_info layouts
110*4f2df630SAndroid Build Coastguard Worker  * is that the number of words in the capabilities array is the same for all
111*4f2df630SAndroid Build Coastguard Worker  * layouts. Let's verify this at compile time.
112*4f2df630SAndroid Build Coastguard Worker  */
113*4f2df630SAndroid Build Coastguard Worker BUILD_ASSERT((CR50_CCD_CAP_COUNT / 32) == (TI50_CCD_CAP_COUNT / 32));
114*4f2df630SAndroid Build Coastguard Worker 
115*4f2df630SAndroid Build Coastguard Worker /*
116*4f2df630SAndroid Build Coastguard Worker  * Version 0 CCD info packet does not include the header, the actual packet
117*4f2df630SAndroid Build Coastguard Worker  * size is used to conclude that the received payload is of version 0.
118*4f2df630SAndroid Build Coastguard Worker  *
119*4f2df630SAndroid Build Coastguard Worker  * Let's hardcode this size to make sure that it is fixed even if the
120*4f2df630SAndroid Build Coastguard Worker  * underlying structure (struct ccd_info_response) size changes in the future.
121*4f2df630SAndroid Build Coastguard Worker  */
122*4f2df630SAndroid Build Coastguard Worker #define CCD_INFO_V0_SIZE 23
123*4f2df630SAndroid Build Coastguard Worker 
124*4f2df630SAndroid Build Coastguard Worker /*
125*4f2df630SAndroid Build Coastguard Worker  * This file contains the source code of a Linux application used to update
126*4f2df630SAndroid Build Coastguard Worker  * CR50 device firmware.
127*4f2df630SAndroid Build Coastguard Worker  *
128*4f2df630SAndroid Build Coastguard Worker  * The CR50 firmware image consists of multiple sections, of interest to this
129*4f2df630SAndroid Build Coastguard Worker  * app are the RO and RW code sections, two of each. When firmware update
130*4f2df630SAndroid Build Coastguard Worker  * session is established, the CR50 device reports locations of backup RW and RO
131*4f2df630SAndroid Build Coastguard Worker  * sections (those not used by the device at the time of transfer).
132*4f2df630SAndroid Build Coastguard Worker  *
133*4f2df630SAndroid Build Coastguard Worker  * Based on this information this app carves out the appropriate sections form
134*4f2df630SAndroid Build Coastguard Worker  * the full CR50 firmware binary image and sends them to the device for
135*4f2df630SAndroid Build Coastguard Worker  * programming into flash. Once the new sections are programmed and the device
136*4f2df630SAndroid Build Coastguard Worker  * is restarted, the new RO and RW are used if they pass verification and are
137*4f2df630SAndroid Build Coastguard Worker  * logically newer than the existing sections.
138*4f2df630SAndroid Build Coastguard Worker  *
139*4f2df630SAndroid Build Coastguard Worker  * There are two ways to communicate with the CR50 device: USB and /dev/tpm0
140*4f2df630SAndroid Build Coastguard Worker  * (when this app is running on a chromebook with the CR50 device). Originally
141*4f2df630SAndroid Build Coastguard Worker  * different protocols were used to communicate over different channels,
142*4f2df630SAndroid Build Coastguard Worker  * starting with version 3 the same protocol is used.
143*4f2df630SAndroid Build Coastguard Worker  *
144*4f2df630SAndroid Build Coastguard Worker  * This app provides backwards compatibility to ensure that earlier CR50
145*4f2df630SAndroid Build Coastguard Worker  * devices still can be updated.
146*4f2df630SAndroid Build Coastguard Worker  *
147*4f2df630SAndroid Build Coastguard Worker  *
148*4f2df630SAndroid Build Coastguard Worker  * The host (either a local AP or a workstation) is controlling the firmware
149*4f2df630SAndroid Build Coastguard Worker  * update protocol, it sends data to the cr50 device, which proceeses it and
150*4f2df630SAndroid Build Coastguard Worker  * responds.
151*4f2df630SAndroid Build Coastguard Worker  *
152*4f2df630SAndroid Build Coastguard Worker  * The encapsultation format is different between the /dev/tpm0 and USB cases:
153*4f2df630SAndroid Build Coastguard Worker  *
154*4f2df630SAndroid Build Coastguard Worker  *   4 bytes      4 bytes         4 bytes               variable size
155*4f2df630SAndroid Build Coastguard Worker  * +-----------+--------------+---------------+----------~~--------------+
156*4f2df630SAndroid Build Coastguard Worker  * + total size| block digest |  dest address |           data           |
157*4f2df630SAndroid Build Coastguard Worker  * +-----------+--------------+---------------+----------~~--------------+
158*4f2df630SAndroid Build Coastguard Worker  *  \           \                                                       /
159*4f2df630SAndroid Build Coastguard Worker  *   \           \                                                     /
160*4f2df630SAndroid Build Coastguard Worker  *    \           +----- FW update PDU sent over /dev/tpm0 -----------+
161*4f2df630SAndroid Build Coastguard Worker  *     \                                                             /
162*4f2df630SAndroid Build Coastguard Worker  *      +--------- USB frame, requires total size field ------------+
163*4f2df630SAndroid Build Coastguard Worker  *
164*4f2df630SAndroid Build Coastguard Worker  * The update protocol data unints (PDUs) are passed over /dev/tpm0, the
165*4f2df630SAndroid Build Coastguard Worker  * encapsulation includes integritiy verification and destination address of
166*4f2df630SAndroid Build Coastguard Worker  * the data (more of this later). /dev/tpm0 transactions pretty much do not
167*4f2df630SAndroid Build Coastguard Worker  * have size limits, whereas the USB data is sent in chunks of the size
168*4f2df630SAndroid Build Coastguard Worker  * determined when the USB connestion is set up. This is why USB requires an
169*4f2df630SAndroid Build Coastguard Worker  * additional encapsulation into frames to communicate the PDU size to the
170*4f2df630SAndroid Build Coastguard Worker  * client side so that the PDU can be reassembled before passing to the
171*4f2df630SAndroid Build Coastguard Worker  * programming function.
172*4f2df630SAndroid Build Coastguard Worker  *
173*4f2df630SAndroid Build Coastguard Worker  * In general, the protocol consists of two phases: connection establishment
174*4f2df630SAndroid Build Coastguard Worker  * and actual image transfer.
175*4f2df630SAndroid Build Coastguard Worker  *
176*4f2df630SAndroid Build Coastguard Worker  * The very first PDU of the transfer session is used to establish the
177*4f2df630SAndroid Build Coastguard Worker  * connection. The first PDU does not have any data, and the dest. address
178*4f2df630SAndroid Build Coastguard Worker  * field is set to zero. Receiving such a PDU signals the programming function
179*4f2df630SAndroid Build Coastguard Worker  * that the host intends to transfer a new image.
180*4f2df630SAndroid Build Coastguard Worker  *
181*4f2df630SAndroid Build Coastguard Worker  * The response to the first PDU varies depending on the protocol version.
182*4f2df630SAndroid Build Coastguard Worker  *
183*4f2df630SAndroid Build Coastguard Worker  * Note that protocol versions before 5 are described here for completeness,
184*4f2df630SAndroid Build Coastguard Worker  * but are not supported any more by this utility.
185*4f2df630SAndroid Build Coastguard Worker  *
186*4f2df630SAndroid Build Coastguard Worker  * Version 1 is used over /dev/tpm0. The response is either 4 or 1 bytes in
187*4f2df630SAndroid Build Coastguard Worker  * size. The 4 byte response is the *base address* of the backup RW section,
188*4f2df630SAndroid Build Coastguard Worker  * no support for RO updates. The one byte response is an error indication,
189*4f2df630SAndroid Build Coastguard Worker  * possibly reporting flash erase failure, command format error, etc.
190*4f2df630SAndroid Build Coastguard Worker  *
191*4f2df630SAndroid Build Coastguard Worker  * Version 2 is used over USB. The response is 8 bytes in size. The first four
192*4f2df630SAndroid Build Coastguard Worker  * bytes are either the *base address* of the backup RW section (still no RO
193*4f2df630SAndroid Build Coastguard Worker  * updates), or an error code, the same as in Version 1. The second 4 bytes
194*4f2df630SAndroid Build Coastguard Worker  * are the protocol version number (set to 2).
195*4f2df630SAndroid Build Coastguard Worker  *
196*4f2df630SAndroid Build Coastguard Worker  * All versions above 2 behave the same over /dev/tpm0 and USB.
197*4f2df630SAndroid Build Coastguard Worker  *
198*4f2df630SAndroid Build Coastguard Worker  * Version 3 response is 16 bytes in size. The first 4 bytes are the error code
199*4f2df630SAndroid Build Coastguard Worker  * the second 4 bytes are the protocol version (set to 3) and then 4 byte
200*4f2df630SAndroid Build Coastguard Worker  * *offset* of the RO section followed by the 4 byte *offset* of the RW section.
201*4f2df630SAndroid Build Coastguard Worker  *
202*4f2df630SAndroid Build Coastguard Worker  * Version 4 response in addition to version 3 provides header revision fields
203*4f2df630SAndroid Build Coastguard Worker  * for active RO and RW images running on the target.
204*4f2df630SAndroid Build Coastguard Worker  *
205*4f2df630SAndroid Build Coastguard Worker  * Once the connection is established, the image to be programmed into flash
206*4f2df630SAndroid Build Coastguard Worker  * is transferred to the CR50 in 1K PDUs. In versions 1 and 2 the address in
207*4f2df630SAndroid Build Coastguard Worker  * the header is the absolute address to place the block to, in version 3 and
208*4f2df630SAndroid Build Coastguard Worker  * later it is the offset into the flash.
209*4f2df630SAndroid Build Coastguard Worker  *
210*4f2df630SAndroid Build Coastguard Worker  * Protocol version 5 includes RO and RW key ID information into the first PDU
211*4f2df630SAndroid Build Coastguard Worker  * response. The key ID could be used to tell between prod and dev signing
212*4f2df630SAndroid Build Coastguard Worker  * modes, among other things.
213*4f2df630SAndroid Build Coastguard Worker  *
214*4f2df630SAndroid Build Coastguard Worker  * Protocol version 6 does not change the format of the first PDU response,
215*4f2df630SAndroid Build Coastguard Worker  * but it indicates the target's ablitiy to channel TPM vendor commands
216*4f2df630SAndroid Build Coastguard Worker  * through USB connection.
217*4f2df630SAndroid Build Coastguard Worker  *
218*4f2df630SAndroid Build Coastguard Worker  * When channeling TPM vendor commands the USB frame looks as follows:
219*4f2df630SAndroid Build Coastguard Worker  *
220*4f2df630SAndroid Build Coastguard Worker  *   4 bytes      4 bytes         4 bytes       2 bytes      variable size
221*4f2df630SAndroid Build Coastguard Worker  * +-----------+--------------+---------------+-----------+------~~~-------+
222*4f2df630SAndroid Build Coastguard Worker  * + total size| block digest |    EXT_CMD    | Vend. sub.|      data      |
223*4f2df630SAndroid Build Coastguard Worker  * +-----------+--------------+---------------+-----------+------~~~-------+
224*4f2df630SAndroid Build Coastguard Worker  *
225*4f2df630SAndroid Build Coastguard Worker  * Where 'Vend. sub' is the vendor subcommand, and data field is subcommand
226*4f2df630SAndroid Build Coastguard Worker  * dependent. The target tells between update PDUs and encapsulated vendor
227*4f2df630SAndroid Build Coastguard Worker  * subcommands by looking at the EXT_CMD value - it is set to 0xbaccd00a and
228*4f2df630SAndroid Build Coastguard Worker  * as such is guaranteed not to be a valid update PDU destination address.
229*4f2df630SAndroid Build Coastguard Worker  *
230*4f2df630SAndroid Build Coastguard Worker  * The vendor command response size is not fixed, it is subcommand dependent.
231*4f2df630SAndroid Build Coastguard Worker  *
232*4f2df630SAndroid Build Coastguard Worker  * The CR50 device responds to each update PDU with a confirmation which is 4
233*4f2df630SAndroid Build Coastguard Worker  * bytes in size in protocol version 2, and 1 byte in size in all other
234*4f2df630SAndroid Build Coastguard Worker  * versions. Zero value means success, non zero value is the error code
235*4f2df630SAndroid Build Coastguard Worker  * reported by CR50.
236*4f2df630SAndroid Build Coastguard Worker  *
237*4f2df630SAndroid Build Coastguard Worker  * Again, vendor command responses are subcommand specific.
238*4f2df630SAndroid Build Coastguard Worker  */
239*4f2df630SAndroid Build Coastguard Worker 
240*4f2df630SAndroid Build Coastguard Worker /* Look for Cr50 FW update interface */
241*4f2df630SAndroid Build Coastguard Worker #define H1_PID	 0x5014
242*4f2df630SAndroid Build Coastguard Worker #define D2_PID	 0x504A
243*4f2df630SAndroid Build Coastguard Worker #define NT_PID	 0x5066
244*4f2df630SAndroid Build Coastguard Worker #define SUBCLASS USB_SUBCLASS_GOOGLE_CR50
245*4f2df630SAndroid Build Coastguard Worker #define PROTOCOL USB_PROTOCOL_GOOGLE_CR50_NON_HC_FW_UPDATE
246*4f2df630SAndroid Build Coastguard Worker 
247*4f2df630SAndroid Build Coastguard Worker /*
248*4f2df630SAndroid Build Coastguard Worker  * CCD Info from GSC is communicated using different structure layouts.
249*4f2df630SAndroid Build Coastguard Worker  * Version 0 does not have a header and includes just the payload information.
250*4f2df630SAndroid Build Coastguard Worker  * Version 2 is prepended by a header which has a distinct value in the first
251*4f2df630SAndroid Build Coastguard Worker  * word, and the version number and the total size in the two halfwords after
252*4f2df630SAndroid Build Coastguard Worker  * that.
253*4f2df630SAndroid Build Coastguard Worker  *
254*4f2df630SAndroid Build Coastguard Worker  * Once the payload is received, the absence of the distinct value in the
255*4f2df630SAndroid Build Coastguard Worker  * first word and the match of the payload size to the expected size of the
256*4f2df630SAndroid Build Coastguard Worker  * version 0 payload indicates that this is indeed a version 0 packet. The
257*4f2df630SAndroid Build Coastguard Worker  * distinct first header value and the match of the size field indicates that
258*4f2df630SAndroid Build Coastguard Worker  * this is a later version packet.
259*4f2df630SAndroid Build Coastguard Worker  */
260*4f2df630SAndroid Build Coastguard Worker #define CCD_INFO_MAGIC 0x49444343 /* This is 'CCDI' in little endian. */
261*4f2df630SAndroid Build Coastguard Worker #define CCD_VERSION    1 /* Ti50 CCD INFO layout. */
262*4f2df630SAndroid Build Coastguard Worker 
263*4f2df630SAndroid Build Coastguard Worker struct ccd_info_response_header {
264*4f2df630SAndroid Build Coastguard Worker 	uint32_t ccd_magic;
265*4f2df630SAndroid Build Coastguard Worker 	uint16_t ccd_version;
266*4f2df630SAndroid Build Coastguard Worker 	uint16_t ccd_size;
267*4f2df630SAndroid Build Coastguard Worker } __packed;
268*4f2df630SAndroid Build Coastguard Worker 
269*4f2df630SAndroid Build Coastguard Worker struct ccd_info_response_packet {
270*4f2df630SAndroid Build Coastguard Worker 	struct ccd_info_response_header cir_header;
271*4f2df630SAndroid Build Coastguard Worker 	struct ccd_info_response cir_body;
272*4f2df630SAndroid Build Coastguard Worker };
273*4f2df630SAndroid Build Coastguard Worker 
274*4f2df630SAndroid Build Coastguard Worker /*
275*4f2df630SAndroid Build Coastguard Worker  * Need to create an entire TPM PDU when upgrading over /dev/tpm0 and need to
276*4f2df630SAndroid Build Coastguard Worker  * have space to prepare the entire PDU.
277*4f2df630SAndroid Build Coastguard Worker  */
278*4f2df630SAndroid Build Coastguard Worker struct upgrade_pkt {
279*4f2df630SAndroid Build Coastguard Worker 	__be16 tag;
280*4f2df630SAndroid Build Coastguard Worker 	__be32 length;
281*4f2df630SAndroid Build Coastguard Worker 	__be32 ordinal;
282*4f2df630SAndroid Build Coastguard Worker 	__be16 subcmd;
283*4f2df630SAndroid Build Coastguard Worker 	union {
284*4f2df630SAndroid Build Coastguard Worker 		/*
285*4f2df630SAndroid Build Coastguard Worker 		 * Upgrade PDUs as opposed to all other vendor and extension
286*4f2df630SAndroid Build Coastguard Worker 		 * commands include two additional fields in the header.
287*4f2df630SAndroid Build Coastguard Worker 		 */
288*4f2df630SAndroid Build Coastguard Worker 		struct {
289*4f2df630SAndroid Build Coastguard Worker 			__be32 digest;
290*4f2df630SAndroid Build Coastguard Worker 			__be32 address;
291*4f2df630SAndroid Build Coastguard Worker 			char data[0];
292*4f2df630SAndroid Build Coastguard Worker 		} upgrade;
293*4f2df630SAndroid Build Coastguard Worker 		struct {
294*4f2df630SAndroid Build Coastguard Worker 			char data[0];
295*4f2df630SAndroid Build Coastguard Worker 		} command;
296*4f2df630SAndroid Build Coastguard Worker 	};
297*4f2df630SAndroid Build Coastguard Worker } __packed;
298*4f2df630SAndroid Build Coastguard Worker 
299*4f2df630SAndroid Build Coastguard Worker /*
300*4f2df630SAndroid Build Coastguard Worker  * Structure used to simplify mapping command line options into Boolean
301*4f2df630SAndroid Build Coastguard Worker  * variables. If an option is present, the corresponding integer value is set
302*4f2df630SAndroid Build Coastguard Worker  * to 1.
303*4f2df630SAndroid Build Coastguard Worker  */
304*4f2df630SAndroid Build Coastguard Worker struct options_map {
305*4f2df630SAndroid Build Coastguard Worker 	char opt;
306*4f2df630SAndroid Build Coastguard Worker 	int *flag;
307*4f2df630SAndroid Build Coastguard Worker };
308*4f2df630SAndroid Build Coastguard Worker 
309*4f2df630SAndroid Build Coastguard Worker /*
310*4f2df630SAndroid Build Coastguard Worker  * Type of the GSC device. This is used to represent which type of GSC we are
311*4f2df630SAndroid Build Coastguard Worker  * connected to and to tag an image file for compatibility.
312*4f2df630SAndroid Build Coastguard Worker  * for downloading.
313*4f2df630SAndroid Build Coastguard Worker  */
314*4f2df630SAndroid Build Coastguard Worker enum gsc_device {
315*4f2df630SAndroid Build Coastguard Worker 	GSC_DEVICE_H1,
316*4f2df630SAndroid Build Coastguard Worker 	GSC_DEVICE_DT,
317*4f2df630SAndroid Build Coastguard Worker 	GSC_DEVICE_NT,
318*4f2df630SAndroid Build Coastguard Worker };
319*4f2df630SAndroid Build Coastguard Worker 
320*4f2df630SAndroid Build Coastguard Worker /* Index to refer to a section within sections array */
321*4f2df630SAndroid Build Coastguard Worker enum section {
322*4f2df630SAndroid Build Coastguard Worker 	RO_A,
323*4f2df630SAndroid Build Coastguard Worker 	RW_A,
324*4f2df630SAndroid Build Coastguard Worker 	RO_B,
325*4f2df630SAndroid Build Coastguard Worker 	RW_B,
326*4f2df630SAndroid Build Coastguard Worker 	NUM_SECTIONS,
327*4f2df630SAndroid Build Coastguard Worker };
328*4f2df630SAndroid Build Coastguard Worker 
329*4f2df630SAndroid Build Coastguard Worker /* Human-readable section names */
330*4f2df630SAndroid Build Coastguard Worker const char *SECTION_NAMES[NUM_SECTIONS] = { [RO_A] = "RO_A",
331*4f2df630SAndroid Build Coastguard Worker 					    [RW_A] = "RW_A",
332*4f2df630SAndroid Build Coastguard Worker 					    [RO_B] = "RO_B",
333*4f2df630SAndroid Build Coastguard Worker 					    [RW_B] = "RW_B" };
334*4f2df630SAndroid Build Coastguard Worker 
335*4f2df630SAndroid Build Coastguard Worker /* Describes each of the sections found in the GSC image */
336*4f2df630SAndroid Build Coastguard Worker struct section_t {
337*4f2df630SAndroid Build Coastguard Worker 	uint32_t offset;
338*4f2df630SAndroid Build Coastguard Worker 	uint32_t size;
339*4f2df630SAndroid Build Coastguard Worker 	bool update_needed;
340*4f2df630SAndroid Build Coastguard Worker 	struct signed_header_version shv;
341*4f2df630SAndroid Build Coastguard Worker 	uint32_t keyid;
342*4f2df630SAndroid Build Coastguard Worker };
343*4f2df630SAndroid Build Coastguard Worker 
344*4f2df630SAndroid Build Coastguard Worker /* Holds a GSC image from disk that can be transfer to a GSC as an update */
345*4f2df630SAndroid Build Coastguard Worker struct image {
346*4f2df630SAndroid Build Coastguard Worker 	uint8_t *data;
347*4f2df630SAndroid Build Coastguard Worker 	size_t data_len;
348*4f2df630SAndroid Build Coastguard Worker 	enum gsc_device type;
349*4f2df630SAndroid Build Coastguard Worker 	const char *file_path;
350*4f2df630SAndroid Build Coastguard Worker 	struct section_t sections[NUM_SECTIONS];
351*4f2df630SAndroid Build Coastguard Worker };
352*4f2df630SAndroid Build Coastguard Worker 
353*4f2df630SAndroid Build Coastguard Worker /* A header with a GSC device type */
354*4f2df630SAndroid Build Coastguard Worker struct typed_image_header {
355*4f2df630SAndroid Build Coastguard Worker 	enum gsc_device type;
356*4f2df630SAndroid Build Coastguard Worker 	union {
357*4f2df630SAndroid Build Coastguard Worker 		struct SignedHeader *h;
358*4f2df630SAndroid Build Coastguard Worker 		struct SignedManifest *m;
359*4f2df630SAndroid Build Coastguard Worker 	};
360*4f2df630SAndroid Build Coastguard Worker };
361*4f2df630SAndroid Build Coastguard Worker 
362*4f2df630SAndroid Build Coastguard Worker /*
363*4f2df630SAndroid Build Coastguard Worker  * Structure used to combine option description used by getopt_long() and help
364*4f2df630SAndroid Build Coastguard Worker  * text for the option.
365*4f2df630SAndroid Build Coastguard Worker  */
366*4f2df630SAndroid Build Coastguard Worker struct option_container {
367*4f2df630SAndroid Build Coastguard Worker 	struct option opt;
368*4f2df630SAndroid Build Coastguard Worker 	const char *help_text;
369*4f2df630SAndroid Build Coastguard Worker };
370*4f2df630SAndroid Build Coastguard Worker 
371*4f2df630SAndroid Build Coastguard Worker static void sha_init(EVP_MD_CTX *ctx);
372*4f2df630SAndroid Build Coastguard Worker static void sha_update(EVP_MD_CTX *ctx, const void *data, size_t len);
373*4f2df630SAndroid Build Coastguard Worker static void sha_final_into_block_digest(EVP_MD_CTX *ctx, void *block_digest,
374*4f2df630SAndroid Build Coastguard Worker 					size_t size);
375*4f2df630SAndroid Build Coastguard Worker 
376*4f2df630SAndroid Build Coastguard Worker /* Type of the GSC device we are talking to, determined at run time. */
377*4f2df630SAndroid Build Coastguard Worker static enum gsc_device gsc_dev = GSC_DEVICE_H1;
378*4f2df630SAndroid Build Coastguard Worker 
379*4f2df630SAndroid Build Coastguard Worker /*
380*4f2df630SAndroid Build Coastguard Worker  * Current AP RO verification config setting version
381*4f2df630SAndroid Build Coastguard Worker  */
382*4f2df630SAndroid Build Coastguard Worker #define ARV_CONFIG_SETTING_CURRENT_VERSION 0x01
383*4f2df630SAndroid Build Coastguard Worker 
384*4f2df630SAndroid Build Coastguard Worker /*
385*4f2df630SAndroid Build Coastguard Worker  * AP RO verification config setting command choices
386*4f2df630SAndroid Build Coastguard Worker  */
387*4f2df630SAndroid Build Coastguard Worker enum arv_config_setting_command_e {
388*4f2df630SAndroid Build Coastguard Worker 	arv_config_setting_command_spi_addressing_mode = 0,
389*4f2df630SAndroid Build Coastguard Worker 	arv_config_setting_command_write_protect_descriptors = 1,
390*4f2df630SAndroid Build Coastguard Worker };
391*4f2df630SAndroid Build Coastguard Worker 
392*4f2df630SAndroid Build Coastguard Worker /*
393*4f2df630SAndroid Build Coastguard Worker  * AP RO verification config setting state
394*4f2df630SAndroid Build Coastguard Worker  */
395*4f2df630SAndroid Build Coastguard Worker enum arv_config_setting_state_e {
396*4f2df630SAndroid Build Coastguard Worker 	arv_config_setting_state_present = 0,
397*4f2df630SAndroid Build Coastguard Worker 	arv_config_setting_state_not_present = 1,
398*4f2df630SAndroid Build Coastguard Worker 	arv_config_setting_state_corrupted = 2,
399*4f2df630SAndroid Build Coastguard Worker 	arv_config_setting_state_invalid = 3,
400*4f2df630SAndroid Build Coastguard Worker };
401*4f2df630SAndroid Build Coastguard Worker 
402*4f2df630SAndroid Build Coastguard Worker /*
403*4f2df630SAndroid Build Coastguard Worker  * AP RO verification SPI read/write addressing mode configuration choices
404*4f2df630SAndroid Build Coastguard Worker  */
405*4f2df630SAndroid Build Coastguard Worker enum arv_config_spi_addr_mode_e {
406*4f2df630SAndroid Build Coastguard Worker 	arv_config_spi_addr_mode_none = 0,
407*4f2df630SAndroid Build Coastguard Worker 	arv_config_spi_addr_mode_get = 1,
408*4f2df630SAndroid Build Coastguard Worker 	arv_config_spi_addr_mode_set_3byte = 2,
409*4f2df630SAndroid Build Coastguard Worker 	arv_config_spi_addr_mode_set_4byte = 3,
410*4f2df630SAndroid Build Coastguard Worker };
411*4f2df630SAndroid Build Coastguard Worker 
412*4f2df630SAndroid Build Coastguard Worker /*
413*4f2df630SAndroid Build Coastguard Worker  * AP RO verification write protect descriptor configuration choices
414*4f2df630SAndroid Build Coastguard Worker  */
415*4f2df630SAndroid Build Coastguard Worker enum arv_config_wpsr_choice_e {
416*4f2df630SAndroid Build Coastguard Worker 	arv_config_wpsr_choice_none = 0,
417*4f2df630SAndroid Build Coastguard Worker 	arv_config_wpsr_choice_get = 1,
418*4f2df630SAndroid Build Coastguard Worker 	arv_config_wpsr_choice_set = 2,
419*4f2df630SAndroid Build Coastguard Worker };
420*4f2df630SAndroid Build Coastguard Worker 
421*4f2df630SAndroid Build Coastguard Worker /*
422*4f2df630SAndroid Build Coastguard Worker  * AP RO verification write protect descriptor information
423*4f2df630SAndroid Build Coastguard Worker  */
424*4f2df630SAndroid Build Coastguard Worker struct __attribute__((__packed__)) arv_config_wpd {
425*4f2df630SAndroid Build Coastguard Worker 	/* See `arv_config_setting_state_e` */
426*4f2df630SAndroid Build Coastguard Worker 	uint8_t state;
427*4f2df630SAndroid Build Coastguard Worker 	uint8_t expected_value;
428*4f2df630SAndroid Build Coastguard Worker 	uint8_t mask;
429*4f2df630SAndroid Build Coastguard Worker };
430*4f2df630SAndroid Build Coastguard Worker 
431*4f2df630SAndroid Build Coastguard Worker /*
432*4f2df630SAndroid Build Coastguard Worker  * AP RO verification write protect descriptors. This is a helper type to
433*4f2df630SAndroid Build Coastguard Worker  * represent the three write protect descriptors.
434*4f2df630SAndroid Build Coastguard Worker  */
435*4f2df630SAndroid Build Coastguard Worker struct __attribute__((__packed__)) arv_config_wpds {
436*4f2df630SAndroid Build Coastguard Worker 	struct arv_config_wpd data[3];
437*4f2df630SAndroid Build Coastguard Worker };
438*4f2df630SAndroid Build Coastguard Worker 
439*4f2df630SAndroid Build Coastguard Worker /*
440*4f2df630SAndroid Build Coastguard Worker  * This matches the largest vendor command response size we ever expect.
441*4f2df630SAndroid Build Coastguard Worker  */
442*4f2df630SAndroid Build Coastguard Worker #define MAX_RX_BUF_SIZE 2048
443*4f2df630SAndroid Build Coastguard Worker 
444*4f2df630SAndroid Build Coastguard Worker /*
445*4f2df630SAndroid Build Coastguard Worker  * Maximum update payload block size plus packet header size.
446*4f2df630SAndroid Build Coastguard Worker  */
447*4f2df630SAndroid Build Coastguard Worker #define MAX_TX_BUF_SIZE (SIGNED_TRANSFER_SIZE + sizeof(struct upgrade_pkt))
448*4f2df630SAndroid Build Coastguard Worker 
449*4f2df630SAndroid Build Coastguard Worker /*
450*4f2df630SAndroid Build Coastguard Worker  * Max. length of the board ID string representation.
451*4f2df630SAndroid Build Coastguard Worker  *
452*4f2df630SAndroid Build Coastguard Worker  * Board ID is either a 4-character ASCII alphanumeric string or an 8-digit
453*4f2df630SAndroid Build Coastguard Worker  * hex.
454*4f2df630SAndroid Build Coastguard Worker  */
455*4f2df630SAndroid Build Coastguard Worker #define MAX_BOARD_ID_LENGTH 9
456*4f2df630SAndroid Build Coastguard Worker 
457*4f2df630SAndroid Build Coastguard Worker /*
458*4f2df630SAndroid Build Coastguard Worker  * Length, in bytes, of the SN Bits serial number bits.
459*4f2df630SAndroid Build Coastguard Worker  */
460*4f2df630SAndroid Build Coastguard Worker #define SN_BITS_SIZE (96 >> 3)
461*4f2df630SAndroid Build Coastguard Worker 
462*4f2df630SAndroid Build Coastguard Worker /*
463*4f2df630SAndroid Build Coastguard Worker  * Max. length of FW version in the format of <epoch>.<major>.<minor>
464*4f2df630SAndroid Build Coastguard Worker  * (3 uint32_t string representation + 2 separators + NULL terminator).
465*4f2df630SAndroid Build Coastguard Worker  */
466*4f2df630SAndroid Build Coastguard Worker #define MAX_FW_VER_LENGTH 33
467*4f2df630SAndroid Build Coastguard Worker 
468*4f2df630SAndroid Build Coastguard Worker static int verbose_mode;
469*4f2df630SAndroid Build Coastguard Worker static uint32_t protocol_version;
470*4f2df630SAndroid Build Coastguard Worker static char *progname;
471*4f2df630SAndroid Build Coastguard Worker 
472*4f2df630SAndroid Build Coastguard Worker /*
473*4f2df630SAndroid Build Coastguard Worker  * List of command line options, ***sorted by the short form***.
474*4f2df630SAndroid Build Coastguard Worker  *
475*4f2df630SAndroid Build Coastguard Worker  * The help_text field does not include the short and long option strings,
476*4f2df630SAndroid Build Coastguard Worker  * they are retrieved from the opt structure. In case the help text needs to
477*4f2df630SAndroid Build Coastguard Worker  * have something printed immediately after the option strings (for example,
478*4f2df630SAndroid Build Coastguard Worker  * an optional parameter), it should be included in the beginning of help_text
479*4f2df630SAndroid Build Coastguard Worker  * string separated by the % character.
480*4f2df630SAndroid Build Coastguard Worker  *
481*4f2df630SAndroid Build Coastguard Worker  * usage() function which prints out the help message will concatenate the
482*4f2df630SAndroid Build Coastguard Worker  * short and long options and the optional parameter, if present, and then
483*4f2df630SAndroid Build Coastguard Worker  * print the rest of the text message at a fixed indentation.
484*4f2df630SAndroid Build Coastguard Worker  */
485*4f2df630SAndroid Build Coastguard Worker static const struct option_container cmd_line_options[] = {
486*4f2df630SAndroid Build Coastguard Worker 	/* {{name   has_arg    *flag  val} long_desc dev_type} */
487*4f2df630SAndroid Build Coastguard Worker 	{ { "get_apro_hash", no_argument, NULL, 'A' },
488*4f2df630SAndroid Build Coastguard Worker 	  "get the stored ap ro hash" },
489*4f2df630SAndroid Build Coastguard Worker 	{ { "any", no_argument, NULL, 'a' },
490*4f2df630SAndroid Build Coastguard Worker 	  "Try any interfaces to find Cr50"
491*4f2df630SAndroid Build Coastguard Worker 	  " (-d, -s, -t are all ignored)" },
492*4f2df630SAndroid Build Coastguard Worker 	{ { "apro_boot", optional_argument, NULL, 'B' },
493*4f2df630SAndroid Build Coastguard Worker 	  "[start] get the stored ap ro boot state or start ap ro verify" },
494*4f2df630SAndroid Build Coastguard Worker 	{ { "binvers", no_argument, NULL, 'b' },
495*4f2df630SAndroid Build Coastguard Worker 	  "Report versions of Cr50 image's "
496*4f2df630SAndroid Build Coastguard Worker 	  "RW and RO headers, do not update" },
497*4f2df630SAndroid Build Coastguard Worker 	{ { "apro_config_spi_mode", optional_argument, NULL, 'C' },
498*4f2df630SAndroid Build Coastguard Worker 	  "Get/set the ap ro verify spi mode either to `3byte` or `4byte`" },
499*4f2df630SAndroid Build Coastguard Worker 	{ { "corrupt", no_argument, NULL, 'c' }, "Corrupt the inactive rw" },
500*4f2df630SAndroid Build Coastguard Worker 	{ { "dauntless", no_argument, NULL, 'D' },
501*4f2df630SAndroid Build Coastguard Worker 	  "Deprecated. No longer needed as runtime selection is used." },
502*4f2df630SAndroid Build Coastguard Worker 	{ { "device", required_argument, NULL, 'd' },
503*4f2df630SAndroid Build Coastguard Worker 	  "VID:PID%USB device (default 18d1:5014 or 18d1:504a based on"
504*4f2df630SAndroid Build Coastguard Worker 	  " image)" },
505*4f2df630SAndroid Build Coastguard Worker 	{ { "apro_config_write_protect", optional_argument, NULL, 'E' },
506*4f2df630SAndroid Build Coastguard Worker 	  "Get/set the ap ro verify write protect descriptors with hex "
507*4f2df630SAndroid Build Coastguard Worker 	  "bytes (ex: 0x01, 0x1, 01 or 1) in the following format: "
508*4f2df630SAndroid Build Coastguard Worker 	  "[sr1 mask1 [sr2 mask2] [sr3 mask3]]" },
509*4f2df630SAndroid Build Coastguard Worker 	{ { "endorsement_seed", optional_argument, NULL, 'e' },
510*4f2df630SAndroid Build Coastguard Worker 	  "[state]%get/set the endorsement key seed" },
511*4f2df630SAndroid Build Coastguard Worker 	{ { "factory", required_argument, NULL, 'F' },
512*4f2df630SAndroid Build Coastguard Worker 	  "[enable|disable]%Control factory mode" },
513*4f2df630SAndroid Build Coastguard Worker 	{ { "fwver", no_argument, NULL, 'f' },
514*4f2df630SAndroid Build Coastguard Worker 	  "Report running Cr50 firmware versions" },
515*4f2df630SAndroid Build Coastguard Worker 	{ { "get_time", no_argument, NULL, 'G' },
516*4f2df630SAndroid Build Coastguard Worker 	  "Get time since last cold reset" },
517*4f2df630SAndroid Build Coastguard Worker 	{ { "getbootmode", no_argument, NULL, 'g' },
518*4f2df630SAndroid Build Coastguard Worker 	  "Get the system boot mode" },
519*4f2df630SAndroid Build Coastguard Worker 	{ { "erase_ap_ro_hash", no_argument, NULL, 'H' },
520*4f2df630SAndroid Build Coastguard Worker 	  "Erase AP RO hash (possible only if Board ID is not set)" },
521*4f2df630SAndroid Build Coastguard Worker 	{ { "help", no_argument, NULL, 'h' }, "Show this message" },
522*4f2df630SAndroid Build Coastguard Worker 	{ { "ccd_info", optional_argument, NULL, 'I' },
523*4f2df630SAndroid Build Coastguard Worker 	  "[capability:value]%Get information about CCD state or set capability"
524*4f2df630SAndroid Build Coastguard Worker 	  " value if allowed" },
525*4f2df630SAndroid Build Coastguard Worker 	{ { "board_id", optional_argument, NULL, 'i' },
526*4f2df630SAndroid Build Coastguard Worker 	  "[ID[:FLAGS]]%Get or set Info1 board ID fields. ID could be 32 bit "
527*4f2df630SAndroid Build Coastguard Worker 	  "hex or 4 character string." },
528*4f2df630SAndroid Build Coastguard Worker 	{ { "boot_trace", optional_argument, NULL, 'J' },
529*4f2df630SAndroid Build Coastguard Worker 	  "[erase]%Retrieve boot trace from the chip, optionally erasing "
530*4f2df630SAndroid Build Coastguard Worker 	  "the trace buffer" },
531*4f2df630SAndroid Build Coastguard Worker 	{ { "get_value", required_argument, NULL, 'K' },
532*4f2df630SAndroid Build Coastguard Worker 	  "[chassis_open|dev_ids]%Get properties values" },
533*4f2df630SAndroid Build Coastguard Worker 	{ { "ccd_lock", no_argument, NULL, 'k' }, "Lock CCD" },
534*4f2df630SAndroid Build Coastguard Worker 	{ { "flog", optional_argument, NULL, 'L' },
535*4f2df630SAndroid Build Coastguard Worker 	  "[prev entry]%Retrieve contents of the flash log"
536*4f2df630SAndroid Build Coastguard Worker 	  " (newer than <prev entry> if specified)" },
537*4f2df630SAndroid Build Coastguard Worker 	{ { "console", no_argument, NULL, 'l' },
538*4f2df630SAndroid Build Coastguard Worker 	  "Get console logs. This may need to be run multiple times to collect "
539*4f2df630SAndroid Build Coastguard Worker 	  "all available logs." },
540*4f2df630SAndroid Build Coastguard Worker 	{ { "machine", no_argument, NULL, 'M' },
541*4f2df630SAndroid Build Coastguard Worker 	  "Output in a machine-friendly way. "
542*4f2df630SAndroid Build Coastguard Worker 	  "Effective with -b, -f, -i, -J, -r, and -O." },
543*4f2df630SAndroid Build Coastguard Worker 	{ { "tpm_mode", optional_argument, NULL, 'm' },
544*4f2df630SAndroid Build Coastguard Worker 	  "[enable|disable]%Change or query tpm_mode" },
545*4f2df630SAndroid Build Coastguard Worker 	{ { "serial", required_argument, NULL, 'n' }, "GSC USB serial number" },
546*4f2df630SAndroid Build Coastguard Worker 	{ { "openbox_rma", required_argument, NULL, 'O' },
547*4f2df630SAndroid Build Coastguard Worker 	  "<desc_file>%Verify other device's RO integrity using information "
548*4f2df630SAndroid Build Coastguard Worker 	  "provided in <desc file>" },
549*4f2df630SAndroid Build Coastguard Worker 	{ { "ccd_open", no_argument, NULL, 'o' }, "Start CCD open sequence" },
550*4f2df630SAndroid Build Coastguard Worker 	{ { "password", no_argument, NULL, 'P' },
551*4f2df630SAndroid Build Coastguard Worker 	  "Set or clear CCD password. Use 'clear:<cur password>' to clear it" },
552*4f2df630SAndroid Build Coastguard Worker 	{ { "post_reset", no_argument, NULL, 'p' },
553*4f2df630SAndroid Build Coastguard Worker 	  "Request post reset after transfer" },
554*4f2df630SAndroid Build Coastguard Worker 	{ { "force_ro", no_argument, NULL, 'q' }, "Force inactive RO update" },
555*4f2df630SAndroid Build Coastguard Worker 	{ { "sn_rma_inc", required_argument, NULL, 'R' },
556*4f2df630SAndroid Build Coastguard Worker 	  "RMA_INC%Increment SN RMA count by RMA_INC. RMA_INC should be 0-7." },
557*4f2df630SAndroid Build Coastguard Worker 	{ { "rma_auth", optional_argument, NULL, 'r' },
558*4f2df630SAndroid Build Coastguard Worker 	  "[auth_code]%Request RMA challenge, process "
559*4f2df630SAndroid Build Coastguard Worker 	  "RMA authentication code" },
560*4f2df630SAndroid Build Coastguard Worker 	{ { "sn_bits", required_argument, NULL, 'S' },
561*4f2df630SAndroid Build Coastguard Worker 	  "SN_BITS%Set Info1 SN bits fields. SN_BITS should be 96 bit hex." },
562*4f2df630SAndroid Build Coastguard Worker 	{ { "systemdev", no_argument, NULL, 's' },
563*4f2df630SAndroid Build Coastguard Worker 	  "Use /dev/tpm0 (-d is ignored)" },
564*4f2df630SAndroid Build Coastguard Worker 	{ { "tstamp", optional_argument, NULL, 'T' },
565*4f2df630SAndroid Build Coastguard Worker 	  "[<tstamp>]%Get or set flash log timestamp base" },
566*4f2df630SAndroid Build Coastguard Worker 	{ { "trunks_send", no_argument, NULL, 't' },
567*4f2df630SAndroid Build Coastguard Worker 	  "Use `trunks_send --raw' (-d is ignored)" },
568*4f2df630SAndroid Build Coastguard Worker 	{ { "ccd_unlock", no_argument, NULL, 'U' },
569*4f2df630SAndroid Build Coastguard Worker 	  "Start CCD unlock sequence" },
570*4f2df630SAndroid Build Coastguard Worker 	{ { "upstart", no_argument, NULL, 'u' },
571*4f2df630SAndroid Build Coastguard Worker 	  "Upstart mode (strict header checks)" },
572*4f2df630SAndroid Build Coastguard Worker 	{ { "verbose", no_argument, NULL, 'V' }, "Enable debug messages" },
573*4f2df630SAndroid Build Coastguard Worker 	{ { "version", no_argument, NULL, 'v' },
574*4f2df630SAndroid Build Coastguard Worker 	  "Report this utility version" },
575*4f2df630SAndroid Build Coastguard Worker 	{ { "metrics", no_argument, NULL, 'W' }, "Get GSC metrics" },
576*4f2df630SAndroid Build Coastguard Worker 	{ { "wp", optional_argument, NULL, 'w' },
577*4f2df630SAndroid Build Coastguard Worker 	  "[enable|disable|follow]%Get or set the write protect setting" },
578*4f2df630SAndroid Build Coastguard Worker 	{ { "clog", no_argument, NULL, 'x' },
579*4f2df630SAndroid Build Coastguard Worker 	  "Retrieve contents of the most recent crash log." },
580*4f2df630SAndroid Build Coastguard Worker 	{ { "factory_config", optional_argument, NULL, 'y' },
581*4f2df630SAndroid Build Coastguard Worker 	  "[value]%Sets the factory config bits in INFO. value should be 64 "
582*4f2df630SAndroid Build Coastguard Worker 	  "bit hex." },
583*4f2df630SAndroid Build Coastguard Worker 	{ { "reboot", optional_argument, NULL, 'z' },
584*4f2df630SAndroid Build Coastguard Worker 	  "Tell the GSC to reboot with an optional reset timeout parameter "
585*4f2df630SAndroid Build Coastguard Worker 	  "in milliseconds" },
586*4f2df630SAndroid Build Coastguard Worker };
587*4f2df630SAndroid Build Coastguard Worker 
588*4f2df630SAndroid Build Coastguard Worker /* Helper to print debug messages when verbose flag is specified. */
debug(const char * fmt,...)589*4f2df630SAndroid Build Coastguard Worker static void debug(const char *fmt, ...)
590*4f2df630SAndroid Build Coastguard Worker {
591*4f2df630SAndroid Build Coastguard Worker 	va_list args;
592*4f2df630SAndroid Build Coastguard Worker 
593*4f2df630SAndroid Build Coastguard Worker 	if (verbose_mode) {
594*4f2df630SAndroid Build Coastguard Worker 		va_start(args, fmt);
595*4f2df630SAndroid Build Coastguard Worker 		vprintf(fmt, args);
596*4f2df630SAndroid Build Coastguard Worker 		va_end(args);
597*4f2df630SAndroid Build Coastguard Worker 	}
598*4f2df630SAndroid Build Coastguard Worker }
599*4f2df630SAndroid Build Coastguard Worker 
600*4f2df630SAndroid Build Coastguard Worker /* Helpers to convert between binary and hex ascii and back. */
to_hexascii(uint8_t c)601*4f2df630SAndroid Build Coastguard Worker static char to_hexascii(uint8_t c)
602*4f2df630SAndroid Build Coastguard Worker {
603*4f2df630SAndroid Build Coastguard Worker 	if (c <= 9)
604*4f2df630SAndroid Build Coastguard Worker 		return '0' + c;
605*4f2df630SAndroid Build Coastguard Worker 	return 'a' + c - 10;
606*4f2df630SAndroid Build Coastguard Worker }
607*4f2df630SAndroid Build Coastguard Worker 
from_hexascii(char c)608*4f2df630SAndroid Build Coastguard Worker static int from_hexascii(char c)
609*4f2df630SAndroid Build Coastguard Worker {
610*4f2df630SAndroid Build Coastguard Worker 	/* convert to lower case. */
611*4f2df630SAndroid Build Coastguard Worker 	c = tolower(c);
612*4f2df630SAndroid Build Coastguard Worker 
613*4f2df630SAndroid Build Coastguard Worker 	if (c < '0' || c > 'f' || ((c > '9') && (c < 'a')))
614*4f2df630SAndroid Build Coastguard Worker 		return -1; /* Not an ascii character. */
615*4f2df630SAndroid Build Coastguard Worker 
616*4f2df630SAndroid Build Coastguard Worker 	if (c <= '9')
617*4f2df630SAndroid Build Coastguard Worker 		return c - '0';
618*4f2df630SAndroid Build Coastguard Worker 
619*4f2df630SAndroid Build Coastguard Worker 	return c - 'a' + 10;
620*4f2df630SAndroid Build Coastguard Worker }
621*4f2df630SAndroid Build Coastguard Worker 
622*4f2df630SAndroid Build Coastguard Worker /* Returns true if the connected GSC device has Ti50-based firmware. */
is_ti50_device(void)623*4f2df630SAndroid Build Coastguard Worker static bool is_ti50_device(void)
624*4f2df630SAndroid Build Coastguard Worker {
625*4f2df630SAndroid Build Coastguard Worker 	/* Assume Ti50 is not H1 device. */
626*4f2df630SAndroid Build Coastguard Worker 	return gsc_dev != GSC_DEVICE_H1;
627*4f2df630SAndroid Build Coastguard Worker }
628*4f2df630SAndroid Build Coastguard Worker 
629*4f2df630SAndroid Build Coastguard Worker /* Functions to communicate with the TPM over the trunks_send --raw channel. */
630*4f2df630SAndroid Build Coastguard Worker 
631*4f2df630SAndroid Build Coastguard Worker /* File handle to share between write and read sides. */
632*4f2df630SAndroid Build Coastguard Worker static FILE *tpm_output;
ts_write(const void * out,size_t len)633*4f2df630SAndroid Build Coastguard Worker static int ts_write(const void *out, size_t len)
634*4f2df630SAndroid Build Coastguard Worker {
635*4f2df630SAndroid Build Coastguard Worker 	const char *cmd_head = "PATH=\"${PATH}:/usr/sbin:/vendor/bin/hw\" "
636*4f2df630SAndroid Build Coastguard Worker 			       "${TRUNKS_SEND_BIN:-trunks_send} --raw ";
637*4f2df630SAndroid Build Coastguard Worker 	size_t head_size = strlen(cmd_head);
638*4f2df630SAndroid Build Coastguard Worker 	char full_command[head_size + 2 * len + 1];
639*4f2df630SAndroid Build Coastguard Worker 	size_t i;
640*4f2df630SAndroid Build Coastguard Worker 
641*4f2df630SAndroid Build Coastguard Worker 	strcpy(full_command, cmd_head);
642*4f2df630SAndroid Build Coastguard Worker 	/*
643*4f2df630SAndroid Build Coastguard Worker 	 * Need to convert binary input into hex ascii output to pass to the
644*4f2df630SAndroid Build Coastguard Worker 	 * trunks_send command.
645*4f2df630SAndroid Build Coastguard Worker 	 */
646*4f2df630SAndroid Build Coastguard Worker 	for (i = 0; i < len; i++) {
647*4f2df630SAndroid Build Coastguard Worker 		uint8_t c = ((const uint8_t *)out)[i];
648*4f2df630SAndroid Build Coastguard Worker 
649*4f2df630SAndroid Build Coastguard Worker 		full_command[head_size + 2 * i] = to_hexascii(c >> 4);
650*4f2df630SAndroid Build Coastguard Worker 		full_command[head_size + 2 * i + 1] = to_hexascii(c & 0xf);
651*4f2df630SAndroid Build Coastguard Worker 	}
652*4f2df630SAndroid Build Coastguard Worker 
653*4f2df630SAndroid Build Coastguard Worker 	/* Make it a proper zero terminated string. */
654*4f2df630SAndroid Build Coastguard Worker 	full_command[sizeof(full_command) - 1] = 0;
655*4f2df630SAndroid Build Coastguard Worker 	debug("cmd: %s\n", full_command);
656*4f2df630SAndroid Build Coastguard Worker 	tpm_output = popen(full_command, "r");
657*4f2df630SAndroid Build Coastguard Worker 	if (tpm_output)
658*4f2df630SAndroid Build Coastguard Worker 		return len;
659*4f2df630SAndroid Build Coastguard Worker 
660*4f2df630SAndroid Build Coastguard Worker 	fprintf(stderr, "Error: failed to launch trunks_send --raw\n");
661*4f2df630SAndroid Build Coastguard Worker 	return -1;
662*4f2df630SAndroid Build Coastguard Worker }
663*4f2df630SAndroid Build Coastguard Worker 
ts_read(void * buf,size_t max_rx_size)664*4f2df630SAndroid Build Coastguard Worker static int ts_read(void *buf, size_t max_rx_size)
665*4f2df630SAndroid Build Coastguard Worker {
666*4f2df630SAndroid Build Coastguard Worker 	int i;
667*4f2df630SAndroid Build Coastguard Worker 	int pclose_rv;
668*4f2df630SAndroid Build Coastguard Worker 	int rv;
669*4f2df630SAndroid Build Coastguard Worker 	/* +1 to account for '\n' added by trunks_send. */
670*4f2df630SAndroid Build Coastguard Worker 	char response[max_rx_size * 2 + 1];
671*4f2df630SAndroid Build Coastguard Worker 
672*4f2df630SAndroid Build Coastguard Worker 	if (!tpm_output) {
673*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Error: attempt to read empty output\n");
674*4f2df630SAndroid Build Coastguard Worker 		return -1;
675*4f2df630SAndroid Build Coastguard Worker 	}
676*4f2df630SAndroid Build Coastguard Worker 
677*4f2df630SAndroid Build Coastguard Worker 	rv = fread(response, 1, sizeof(response), tpm_output);
678*4f2df630SAndroid Build Coastguard Worker 	if (rv > 0)
679*4f2df630SAndroid Build Coastguard Worker 		rv -= 1; /* Discard the \n character added by trunks_send. */
680*4f2df630SAndroid Build Coastguard Worker 
681*4f2df630SAndroid Build Coastguard Worker 	debug("response of size %d, max rx size %zd: %s\n", rv, max_rx_size,
682*4f2df630SAndroid Build Coastguard Worker 	      response);
683*4f2df630SAndroid Build Coastguard Worker 
684*4f2df630SAndroid Build Coastguard Worker 	pclose_rv = pclose(tpm_output);
685*4f2df630SAndroid Build Coastguard Worker 	if (pclose_rv < 0) {
686*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Error: pclose failed: error %d (%s)\n", errno,
687*4f2df630SAndroid Build Coastguard Worker 			strerror(errno));
688*4f2df630SAndroid Build Coastguard Worker 		return -1;
689*4f2df630SAndroid Build Coastguard Worker 	}
690*4f2df630SAndroid Build Coastguard Worker 
691*4f2df630SAndroid Build Coastguard Worker 	tpm_output = NULL;
692*4f2df630SAndroid Build Coastguard Worker 
693*4f2df630SAndroid Build Coastguard Worker 	if (rv & 1) {
694*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr,
695*4f2df630SAndroid Build Coastguard Worker 			"Error: trunks_send returned odd number of bytes: %s\n",
696*4f2df630SAndroid Build Coastguard Worker 			response);
697*4f2df630SAndroid Build Coastguard Worker 		return -1;
698*4f2df630SAndroid Build Coastguard Worker 	}
699*4f2df630SAndroid Build Coastguard Worker 
700*4f2df630SAndroid Build Coastguard Worker 	for (i = 0; i < rv / 2; i++) {
701*4f2df630SAndroid Build Coastguard Worker 		uint8_t byte;
702*4f2df630SAndroid Build Coastguard Worker 		char c;
703*4f2df630SAndroid Build Coastguard Worker 		int nibble;
704*4f2df630SAndroid Build Coastguard Worker 
705*4f2df630SAndroid Build Coastguard Worker 		c = response[2 * i];
706*4f2df630SAndroid Build Coastguard Worker 		nibble = from_hexascii(c);
707*4f2df630SAndroid Build Coastguard Worker 		if (nibble < 0) {
708*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr,
709*4f2df630SAndroid Build Coastguard Worker 				"Error: "
710*4f2df630SAndroid Build Coastguard Worker 				"trunks_send returned non hex character %c\n",
711*4f2df630SAndroid Build Coastguard Worker 				c);
712*4f2df630SAndroid Build Coastguard Worker 			return -1;
713*4f2df630SAndroid Build Coastguard Worker 		}
714*4f2df630SAndroid Build Coastguard Worker 		byte = nibble << 4;
715*4f2df630SAndroid Build Coastguard Worker 
716*4f2df630SAndroid Build Coastguard Worker 		c = response[2 * i + 1];
717*4f2df630SAndroid Build Coastguard Worker 		nibble = from_hexascii(c);
718*4f2df630SAndroid Build Coastguard Worker 		if (nibble < 0) {
719*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr,
720*4f2df630SAndroid Build Coastguard Worker 				"Error: "
721*4f2df630SAndroid Build Coastguard Worker 				"trunks_send returned non hex character %c\n",
722*4f2df630SAndroid Build Coastguard Worker 				c);
723*4f2df630SAndroid Build Coastguard Worker 			return -1;
724*4f2df630SAndroid Build Coastguard Worker 		}
725*4f2df630SAndroid Build Coastguard Worker 		byte |= nibble;
726*4f2df630SAndroid Build Coastguard Worker 
727*4f2df630SAndroid Build Coastguard Worker 		((uint8_t *)buf)[i] = byte;
728*4f2df630SAndroid Build Coastguard Worker 	}
729*4f2df630SAndroid Build Coastguard Worker 
730*4f2df630SAndroid Build Coastguard Worker 	return rv / 2;
731*4f2df630SAndroid Build Coastguard Worker }
732*4f2df630SAndroid Build Coastguard Worker 
733*4f2df630SAndroid Build Coastguard Worker /*
734*4f2df630SAndroid Build Coastguard Worker  * Prepare and transfer a block to either to /dev/tpm0 or through trunks_send
735*4f2df630SAndroid Build Coastguard Worker  * --raw, get a reply.
736*4f2df630SAndroid Build Coastguard Worker  */
tpm_send_pkt(struct transfer_descriptor * td,unsigned int digest,unsigned int addr,const void * data,int size,void * response,size_t * response_size,uint16_t subcmd)737*4f2df630SAndroid Build Coastguard Worker static int tpm_send_pkt(struct transfer_descriptor *td, unsigned int digest,
738*4f2df630SAndroid Build Coastguard Worker 			unsigned int addr, const void *data, int size,
739*4f2df630SAndroid Build Coastguard Worker 			void *response, size_t *response_size, uint16_t subcmd)
740*4f2df630SAndroid Build Coastguard Worker {
741*4f2df630SAndroid Build Coastguard Worker 	/* Used by transfer to /dev/tpm0 */
742*4f2df630SAndroid Build Coastguard Worker 	static uint8_t outbuf[MAX_TX_BUF_SIZE];
743*4f2df630SAndroid Build Coastguard Worker 	static uint8_t
744*4f2df630SAndroid Build Coastguard Worker 		raw_response[MAX_RX_BUF_SIZE + sizeof(struct upgrade_pkt)];
745*4f2df630SAndroid Build Coastguard Worker 	struct upgrade_pkt *out = (struct upgrade_pkt *)outbuf;
746*4f2df630SAndroid Build Coastguard Worker 	int len, done;
747*4f2df630SAndroid Build Coastguard Worker 	int response_offset = offsetof(struct upgrade_pkt, command.data);
748*4f2df630SAndroid Build Coastguard Worker 	void *payload;
749*4f2df630SAndroid Build Coastguard Worker 	size_t header_size;
750*4f2df630SAndroid Build Coastguard Worker 	uint32_t rv;
751*4f2df630SAndroid Build Coastguard Worker 	const size_t rx_size = sizeof(raw_response);
752*4f2df630SAndroid Build Coastguard Worker 
753*4f2df630SAndroid Build Coastguard Worker 	debug("%s: sending to %#x %d bytes\n", __func__, addr, size);
754*4f2df630SAndroid Build Coastguard Worker 
755*4f2df630SAndroid Build Coastguard Worker 	out->tag = htobe16(0x8001);
756*4f2df630SAndroid Build Coastguard Worker 	out->subcmd = htobe16(subcmd);
757*4f2df630SAndroid Build Coastguard Worker 
758*4f2df630SAndroid Build Coastguard Worker 	if (subcmd <= LAST_EXTENSION_COMMAND)
759*4f2df630SAndroid Build Coastguard Worker 		out->ordinal = htobe32(CONFIG_EXTENSION_COMMAND);
760*4f2df630SAndroid Build Coastguard Worker 	else
761*4f2df630SAndroid Build Coastguard Worker 		out->ordinal = htobe32(TPM_CC_VENDOR_BIT_MASK);
762*4f2df630SAndroid Build Coastguard Worker 
763*4f2df630SAndroid Build Coastguard Worker 	if (subcmd == EXTENSION_FW_UPGRADE) {
764*4f2df630SAndroid Build Coastguard Worker 		/* FW Upgrade PDU header includes a couple of extra fields. */
765*4f2df630SAndroid Build Coastguard Worker 		out->upgrade.digest = digest;
766*4f2df630SAndroid Build Coastguard Worker 		out->upgrade.address = htobe32(addr);
767*4f2df630SAndroid Build Coastguard Worker 		header_size = offsetof(struct upgrade_pkt, upgrade.data);
768*4f2df630SAndroid Build Coastguard Worker 	} else {
769*4f2df630SAndroid Build Coastguard Worker 		header_size = offsetof(struct upgrade_pkt, command.data);
770*4f2df630SAndroid Build Coastguard Worker 	}
771*4f2df630SAndroid Build Coastguard Worker 
772*4f2df630SAndroid Build Coastguard Worker 	payload = outbuf + header_size;
773*4f2df630SAndroid Build Coastguard Worker 	len = size + header_size;
774*4f2df630SAndroid Build Coastguard Worker 
775*4f2df630SAndroid Build Coastguard Worker 	out->length = htobe32(len);
776*4f2df630SAndroid Build Coastguard Worker 	memcpy(payload, data, size);
777*4f2df630SAndroid Build Coastguard Worker 
778*4f2df630SAndroid Build Coastguard Worker 	if (verbose_mode) {
779*4f2df630SAndroid Build Coastguard Worker 		int i;
780*4f2df630SAndroid Build Coastguard Worker 
781*4f2df630SAndroid Build Coastguard Worker 		debug("Writing %d bytes to TPM at %x\n", len, addr);
782*4f2df630SAndroid Build Coastguard Worker 		for (i = 0; i < MIN(len, 20); i++)
783*4f2df630SAndroid Build Coastguard Worker 			debug("%2.2x ", outbuf[i]);
784*4f2df630SAndroid Build Coastguard Worker 		debug("\n");
785*4f2df630SAndroid Build Coastguard Worker 	}
786*4f2df630SAndroid Build Coastguard Worker 
787*4f2df630SAndroid Build Coastguard Worker 	switch (td->ep_type) {
788*4f2df630SAndroid Build Coastguard Worker 	case dev_xfer:
789*4f2df630SAndroid Build Coastguard Worker 		done = write(td->tpm_fd, out, len);
790*4f2df630SAndroid Build Coastguard Worker 		break;
791*4f2df630SAndroid Build Coastguard Worker 	case ts_xfer:
792*4f2df630SAndroid Build Coastguard Worker 		done = ts_write(out, len);
793*4f2df630SAndroid Build Coastguard Worker 		break;
794*4f2df630SAndroid Build Coastguard Worker 	default:
795*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Error: %s:%d: unknown transfer type %d\n",
796*4f2df630SAndroid Build Coastguard Worker 			__func__, __LINE__, td->ep_type);
797*4f2df630SAndroid Build Coastguard Worker 		return -1;
798*4f2df630SAndroid Build Coastguard Worker 	}
799*4f2df630SAndroid Build Coastguard Worker 
800*4f2df630SAndroid Build Coastguard Worker 	if (done < 0) {
801*4f2df630SAndroid Build Coastguard Worker 		perror("Could not write to TPM");
802*4f2df630SAndroid Build Coastguard Worker 		return -1;
803*4f2df630SAndroid Build Coastguard Worker 	} else if (done != len) {
804*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Error: Wrote %d bytes, expected to write %d\n",
805*4f2df630SAndroid Build Coastguard Worker 			done, len);
806*4f2df630SAndroid Build Coastguard Worker 		return -1;
807*4f2df630SAndroid Build Coastguard Worker 	}
808*4f2df630SAndroid Build Coastguard Worker 
809*4f2df630SAndroid Build Coastguard Worker 	switch (td->ep_type) {
810*4f2df630SAndroid Build Coastguard Worker 	case dev_xfer: {
811*4f2df630SAndroid Build Coastguard Worker 		int read_count;
812*4f2df630SAndroid Build Coastguard Worker 
813*4f2df630SAndroid Build Coastguard Worker 		len = 0;
814*4f2df630SAndroid Build Coastguard Worker 		do {
815*4f2df630SAndroid Build Coastguard Worker 			uint8_t *rx_buf = raw_response + len;
816*4f2df630SAndroid Build Coastguard Worker 			size_t rx_to_go = rx_size - len;
817*4f2df630SAndroid Build Coastguard Worker 
818*4f2df630SAndroid Build Coastguard Worker 			read_count = read(td->tpm_fd, rx_buf, rx_to_go);
819*4f2df630SAndroid Build Coastguard Worker 
820*4f2df630SAndroid Build Coastguard Worker 			len += read_count;
821*4f2df630SAndroid Build Coastguard Worker 		} while (read_count);
822*4f2df630SAndroid Build Coastguard Worker 		break;
823*4f2df630SAndroid Build Coastguard Worker 	}
824*4f2df630SAndroid Build Coastguard Worker 	case ts_xfer:
825*4f2df630SAndroid Build Coastguard Worker 		len = ts_read(raw_response, rx_size);
826*4f2df630SAndroid Build Coastguard Worker 		break;
827*4f2df630SAndroid Build Coastguard Worker 	default:
828*4f2df630SAndroid Build Coastguard Worker 		/*
829*4f2df630SAndroid Build Coastguard Worker 		 * This sure will never happen, type is verifed in the
830*4f2df630SAndroid Build Coastguard Worker 		 * previous switch statement.
831*4f2df630SAndroid Build Coastguard Worker 		 */
832*4f2df630SAndroid Build Coastguard Worker 		len = -1;
833*4f2df630SAndroid Build Coastguard Worker 		break;
834*4f2df630SAndroid Build Coastguard Worker 	}
835*4f2df630SAndroid Build Coastguard Worker 
836*4f2df630SAndroid Build Coastguard Worker 	debug("Read %d bytes from TPM\n", len);
837*4f2df630SAndroid Build Coastguard Worker 	if (len > 0) {
838*4f2df630SAndroid Build Coastguard Worker 		int i;
839*4f2df630SAndroid Build Coastguard Worker 
840*4f2df630SAndroid Build Coastguard Worker 		for (i = 0; i < len; i++)
841*4f2df630SAndroid Build Coastguard Worker 			debug("%2.2x ", raw_response[i]);
842*4f2df630SAndroid Build Coastguard Worker 		debug("\n");
843*4f2df630SAndroid Build Coastguard Worker 	}
844*4f2df630SAndroid Build Coastguard Worker 	len = len - response_offset;
845*4f2df630SAndroid Build Coastguard Worker 	if (len < 0) {
846*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Problems reading from TPM, got %d bytes\n",
847*4f2df630SAndroid Build Coastguard Worker 			len + response_offset);
848*4f2df630SAndroid Build Coastguard Worker 		return -1;
849*4f2df630SAndroid Build Coastguard Worker 	}
850*4f2df630SAndroid Build Coastguard Worker 
851*4f2df630SAndroid Build Coastguard Worker 	if (response && response_size) {
852*4f2df630SAndroid Build Coastguard Worker 		len = MIN(len, *response_size);
853*4f2df630SAndroid Build Coastguard Worker 		memcpy(response, raw_response + response_offset, len);
854*4f2df630SAndroid Build Coastguard Worker 		*response_size = len;
855*4f2df630SAndroid Build Coastguard Worker 	}
856*4f2df630SAndroid Build Coastguard Worker 
857*4f2df630SAndroid Build Coastguard Worker 	/* Return the actual return code from the TPM response header. */
858*4f2df630SAndroid Build Coastguard Worker 	memcpy(&rv, &((struct upgrade_pkt *)raw_response)->ordinal, sizeof(rv));
859*4f2df630SAndroid Build Coastguard Worker 	rv = be32toh(rv);
860*4f2df630SAndroid Build Coastguard Worker 
861*4f2df630SAndroid Build Coastguard Worker 	/* Clear out vendor command return value offset.*/
862*4f2df630SAndroid Build Coastguard Worker 	if ((rv & VENDOR_RC_ERR) == VENDOR_RC_ERR)
863*4f2df630SAndroid Build Coastguard Worker 		rv &= ~VENDOR_RC_ERR;
864*4f2df630SAndroid Build Coastguard Worker 
865*4f2df630SAndroid Build Coastguard Worker 	return rv;
866*4f2df630SAndroid Build Coastguard Worker }
867*4f2df630SAndroid Build Coastguard Worker 
868*4f2df630SAndroid Build Coastguard Worker /* Release USB device and return error to the OS. */
shut_down(struct usb_endpoint * uep)869*4f2df630SAndroid Build Coastguard Worker static void shut_down(struct usb_endpoint *uep)
870*4f2df630SAndroid Build Coastguard Worker {
871*4f2df630SAndroid Build Coastguard Worker 	usb_shut_down(uep);
872*4f2df630SAndroid Build Coastguard Worker 	exit(update_error);
873*4f2df630SAndroid Build Coastguard Worker }
874*4f2df630SAndroid Build Coastguard Worker 
usage(int errs)875*4f2df630SAndroid Build Coastguard Worker static void usage(int errs)
876*4f2df630SAndroid Build Coastguard Worker {
877*4f2df630SAndroid Build Coastguard Worker 	size_t i;
878*4f2df630SAndroid Build Coastguard Worker 	const int indent = 27; /* This is the size used by gsctool all along. */
879*4f2df630SAndroid Build Coastguard Worker 
880*4f2df630SAndroid Build Coastguard Worker 	printf("\nUsage: %s [options] [<binary image>]\n"
881*4f2df630SAndroid Build Coastguard Worker 	       "\n"
882*4f2df630SAndroid Build Coastguard Worker 	       "This utility allows to update Cr50 RW firmware, configure\n"
883*4f2df630SAndroid Build Coastguard Worker 	       "various aspects of Cr50 operation, analyze Cr50 binary\n"
884*4f2df630SAndroid Build Coastguard Worker 	       "images, etc.\n\n"
885*4f2df630SAndroid Build Coastguard Worker 	       "<binary image> is the file name of a full RO+RW binary image.\n"
886*4f2df630SAndroid Build Coastguard Worker 	       "\n"
887*4f2df630SAndroid Build Coastguard Worker 	       "Options:\n\n",
888*4f2df630SAndroid Build Coastguard Worker 	       progname);
889*4f2df630SAndroid Build Coastguard Worker 
890*4f2df630SAndroid Build Coastguard Worker 	for (i = 0; i < ARRAY_SIZE(cmd_line_options); i++) {
891*4f2df630SAndroid Build Coastguard Worker 		const char *help_text = cmd_line_options[i].help_text;
892*4f2df630SAndroid Build Coastguard Worker 		int printed_length;
893*4f2df630SAndroid Build Coastguard Worker 		const char *separator;
894*4f2df630SAndroid Build Coastguard Worker 
895*4f2df630SAndroid Build Coastguard Worker 		/*
896*4f2df630SAndroid Build Coastguard Worker 		 * First print the short and long forms of the command line
897*4f2df630SAndroid Build Coastguard Worker 		 * option.
898*4f2df630SAndroid Build Coastguard Worker 		 */
899*4f2df630SAndroid Build Coastguard Worker 		printed_length = printf(" -%c,--%s",
900*4f2df630SAndroid Build Coastguard Worker 					cmd_line_options[i].opt.val,
901*4f2df630SAndroid Build Coastguard Worker 					cmd_line_options[i].opt.name);
902*4f2df630SAndroid Build Coastguard Worker 
903*4f2df630SAndroid Build Coastguard Worker 		/*
904*4f2df630SAndroid Build Coastguard Worker 		 * If there is something to print immediately after the
905*4f2df630SAndroid Build Coastguard Worker 		 * options, print it.
906*4f2df630SAndroid Build Coastguard Worker 		 */
907*4f2df630SAndroid Build Coastguard Worker 		separator = strchr(help_text, '%');
908*4f2df630SAndroid Build Coastguard Worker 		if (separator) {
909*4f2df630SAndroid Build Coastguard Worker 			char buffer[80];
910*4f2df630SAndroid Build Coastguard Worker 			size_t extra_size;
911*4f2df630SAndroid Build Coastguard Worker 
912*4f2df630SAndroid Build Coastguard Worker 			extra_size = separator - help_text;
913*4f2df630SAndroid Build Coastguard Worker 			if (extra_size >= sizeof(buffer)) {
914*4f2df630SAndroid Build Coastguard Worker 				fprintf(stderr, "misformatted help text: %s\n",
915*4f2df630SAndroid Build Coastguard Worker 					help_text);
916*4f2df630SAndroid Build Coastguard Worker 				exit(-1);
917*4f2df630SAndroid Build Coastguard Worker 			}
918*4f2df630SAndroid Build Coastguard Worker 			memcpy(buffer, help_text, extra_size);
919*4f2df630SAndroid Build Coastguard Worker 			buffer[extra_size] = '\0';
920*4f2df630SAndroid Build Coastguard Worker 			printed_length += printf(" %s", buffer);
921*4f2df630SAndroid Build Coastguard Worker 			help_text = separator + 1;
922*4f2df630SAndroid Build Coastguard Worker 		}
923*4f2df630SAndroid Build Coastguard Worker 
924*4f2df630SAndroid Build Coastguard Worker 		/*
925*4f2df630SAndroid Build Coastguard Worker 		 * If printed length exceeds or is too close to indent, print
926*4f2df630SAndroid Build Coastguard Worker 		 * help text on the next line.
927*4f2df630SAndroid Build Coastguard Worker 		 */
928*4f2df630SAndroid Build Coastguard Worker 		if (printed_length >= (indent - 1)) {
929*4f2df630SAndroid Build Coastguard Worker 			printf("\n");
930*4f2df630SAndroid Build Coastguard Worker 			printed_length = 0;
931*4f2df630SAndroid Build Coastguard Worker 		}
932*4f2df630SAndroid Build Coastguard Worker 
933*4f2df630SAndroid Build Coastguard Worker 		while (printed_length++ < indent)
934*4f2df630SAndroid Build Coastguard Worker 			printf(" ");
935*4f2df630SAndroid Build Coastguard Worker 		printf("%s\n", help_text);
936*4f2df630SAndroid Build Coastguard Worker 	}
937*4f2df630SAndroid Build Coastguard Worker 	printf("\n");
938*4f2df630SAndroid Build Coastguard Worker 	exit(errs ? update_error : noop);
939*4f2df630SAndroid Build Coastguard Worker }
940*4f2df630SAndroid Build Coastguard Worker 
941*4f2df630SAndroid Build Coastguard Worker /* Read file into buffer */
get_file_or_die(const char * filename,size_t * len_ptr)942*4f2df630SAndroid Build Coastguard Worker static uint8_t *get_file_or_die(const char *filename, size_t *len_ptr)
943*4f2df630SAndroid Build Coastguard Worker {
944*4f2df630SAndroid Build Coastguard Worker 	FILE *fp;
945*4f2df630SAndroid Build Coastguard Worker 	struct stat st;
946*4f2df630SAndroid Build Coastguard Worker 	uint8_t *data;
947*4f2df630SAndroid Build Coastguard Worker 	size_t len;
948*4f2df630SAndroid Build Coastguard Worker 
949*4f2df630SAndroid Build Coastguard Worker 	fp = fopen(filename, "rb");
950*4f2df630SAndroid Build Coastguard Worker 	if (!fp) {
951*4f2df630SAndroid Build Coastguard Worker 		perror(filename);
952*4f2df630SAndroid Build Coastguard Worker 		exit(update_error);
953*4f2df630SAndroid Build Coastguard Worker 	}
954*4f2df630SAndroid Build Coastguard Worker 	if (fstat(fileno(fp), &st)) {
955*4f2df630SAndroid Build Coastguard Worker 		perror("stat");
956*4f2df630SAndroid Build Coastguard Worker 		exit(update_error);
957*4f2df630SAndroid Build Coastguard Worker 	}
958*4f2df630SAndroid Build Coastguard Worker 
959*4f2df630SAndroid Build Coastguard Worker 	len = st.st_size;
960*4f2df630SAndroid Build Coastguard Worker 
961*4f2df630SAndroid Build Coastguard Worker 	data = malloc(len);
962*4f2df630SAndroid Build Coastguard Worker 	if (!data) {
963*4f2df630SAndroid Build Coastguard Worker 		perror("malloc");
964*4f2df630SAndroid Build Coastguard Worker 		exit(update_error);
965*4f2df630SAndroid Build Coastguard Worker 	}
966*4f2df630SAndroid Build Coastguard Worker 
967*4f2df630SAndroid Build Coastguard Worker 	if (1 != fread(data, st.st_size, 1, fp)) {
968*4f2df630SAndroid Build Coastguard Worker 		perror("fread");
969*4f2df630SAndroid Build Coastguard Worker 		exit(update_error);
970*4f2df630SAndroid Build Coastguard Worker 	}
971*4f2df630SAndroid Build Coastguard Worker 
972*4f2df630SAndroid Build Coastguard Worker 	fclose(fp);
973*4f2df630SAndroid Build Coastguard Worker 
974*4f2df630SAndroid Build Coastguard Worker 	*len_ptr = len;
975*4f2df630SAndroid Build Coastguard Worker 	return data;
976*4f2df630SAndroid Build Coastguard Worker }
977*4f2df630SAndroid Build Coastguard Worker 
978*4f2df630SAndroid Build Coastguard Worker /* Returns true if parsed. */
parse_vidpid(const char * input,uint16_t * vid_ptr,uint16_t * pid_ptr)979*4f2df630SAndroid Build Coastguard Worker static int parse_vidpid(const char *input, uint16_t *vid_ptr, uint16_t *pid_ptr)
980*4f2df630SAndroid Build Coastguard Worker {
981*4f2df630SAndroid Build Coastguard Worker 	char *copy, *s, *e = 0;
982*4f2df630SAndroid Build Coastguard Worker 
983*4f2df630SAndroid Build Coastguard Worker 	copy = strdup(input);
984*4f2df630SAndroid Build Coastguard Worker 
985*4f2df630SAndroid Build Coastguard Worker 	s = strchr(copy, ':');
986*4f2df630SAndroid Build Coastguard Worker 	if (!s)
987*4f2df630SAndroid Build Coastguard Worker 		return 0;
988*4f2df630SAndroid Build Coastguard Worker 	*s++ = '\0';
989*4f2df630SAndroid Build Coastguard Worker 
990*4f2df630SAndroid Build Coastguard Worker 	*vid_ptr = (uint16_t)strtoul(copy, &e, 16);
991*4f2df630SAndroid Build Coastguard Worker 	if (!*optarg || (e && *e))
992*4f2df630SAndroid Build Coastguard Worker 		return 0;
993*4f2df630SAndroid Build Coastguard Worker 
994*4f2df630SAndroid Build Coastguard Worker 	*pid_ptr = (uint16_t)strtoul(s, &e, 16);
995*4f2df630SAndroid Build Coastguard Worker 	if (!*optarg || (e && *e))
996*4f2df630SAndroid Build Coastguard Worker 		return 0;
997*4f2df630SAndroid Build Coastguard Worker 
998*4f2df630SAndroid Build Coastguard Worker 	return 1;
999*4f2df630SAndroid Build Coastguard Worker }
1000*4f2df630SAndroid Build Coastguard Worker 
1001*4f2df630SAndroid Build Coastguard Worker struct update_pdu {
1002*4f2df630SAndroid Build Coastguard Worker 	uint32_t block_size; /* Total block size, include this field's size. */
1003*4f2df630SAndroid Build Coastguard Worker 	struct upgrade_command cmd;
1004*4f2df630SAndroid Build Coastguard Worker 	/* The actual payload goes here. */
1005*4f2df630SAndroid Build Coastguard Worker };
1006*4f2df630SAndroid Build Coastguard Worker 
do_xfer(struct usb_endpoint * uep,void * outbuf,int outlen,void * inbuf,int inlen,int allow_less,size_t * rxed_count)1007*4f2df630SAndroid Build Coastguard Worker static void do_xfer(struct usb_endpoint *uep, void *outbuf, int outlen,
1008*4f2df630SAndroid Build Coastguard Worker 		    void *inbuf, int inlen, int allow_less, size_t *rxed_count)
1009*4f2df630SAndroid Build Coastguard Worker {
1010*4f2df630SAndroid Build Coastguard Worker 	if (usb_trx(uep, outbuf, outlen, inbuf, inlen, allow_less, rxed_count))
1011*4f2df630SAndroid Build Coastguard Worker 		shut_down(uep);
1012*4f2df630SAndroid Build Coastguard Worker }
1013*4f2df630SAndroid Build Coastguard Worker 
transfer_block(struct usb_endpoint * uep,struct update_pdu * updu,uint8_t * transfer_data_ptr,size_t payload_size)1014*4f2df630SAndroid Build Coastguard Worker static int transfer_block(struct usb_endpoint *uep, struct update_pdu *updu,
1015*4f2df630SAndroid Build Coastguard Worker 			  uint8_t *transfer_data_ptr, size_t payload_size)
1016*4f2df630SAndroid Build Coastguard Worker {
1017*4f2df630SAndroid Build Coastguard Worker 	size_t transfer_size;
1018*4f2df630SAndroid Build Coastguard Worker 	uint32_t reply;
1019*4f2df630SAndroid Build Coastguard Worker 	int actual;
1020*4f2df630SAndroid Build Coastguard Worker 	int r;
1021*4f2df630SAndroid Build Coastguard Worker 
1022*4f2df630SAndroid Build Coastguard Worker 	/* First send the header. */
1023*4f2df630SAndroid Build Coastguard Worker 	do_xfer(uep, updu, sizeof(*updu), NULL, 0, 0, NULL);
1024*4f2df630SAndroid Build Coastguard Worker 
1025*4f2df630SAndroid Build Coastguard Worker 	/* Now send the block, chunk by chunk. */
1026*4f2df630SAndroid Build Coastguard Worker 	for (transfer_size = 0; transfer_size < payload_size;) {
1027*4f2df630SAndroid Build Coastguard Worker 		int chunk_size;
1028*4f2df630SAndroid Build Coastguard Worker 
1029*4f2df630SAndroid Build Coastguard Worker 		chunk_size = MIN(uep->chunk_len, payload_size - transfer_size);
1030*4f2df630SAndroid Build Coastguard Worker 		do_xfer(uep, transfer_data_ptr, chunk_size, NULL, 0, 0, NULL);
1031*4f2df630SAndroid Build Coastguard Worker 		transfer_data_ptr += chunk_size;
1032*4f2df630SAndroid Build Coastguard Worker 		transfer_size += chunk_size;
1033*4f2df630SAndroid Build Coastguard Worker 	}
1034*4f2df630SAndroid Build Coastguard Worker 
1035*4f2df630SAndroid Build Coastguard Worker 	/* Now get the reply. */
1036*4f2df630SAndroid Build Coastguard Worker 	r = libusb_bulk_transfer(uep->devh, uep->ep_num | 0x80, (void *)&reply,
1037*4f2df630SAndroid Build Coastguard Worker 				 sizeof(reply), &actual, 1000);
1038*4f2df630SAndroid Build Coastguard Worker 	if (r) {
1039*4f2df630SAndroid Build Coastguard Worker 		if (r == -7) {
1040*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr, "Timeout!\n");
1041*4f2df630SAndroid Build Coastguard Worker 			return r;
1042*4f2df630SAndroid Build Coastguard Worker 		}
1043*4f2df630SAndroid Build Coastguard Worker 		USB_ERROR("libusb_bulk_transfer", r);
1044*4f2df630SAndroid Build Coastguard Worker 		shut_down(uep);
1045*4f2df630SAndroid Build Coastguard Worker 	}
1046*4f2df630SAndroid Build Coastguard Worker 
1047*4f2df630SAndroid Build Coastguard Worker 	reply = *((uint8_t *)&reply);
1048*4f2df630SAndroid Build Coastguard Worker 	if (reply) {
1049*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Error: status %#x\n", reply);
1050*4f2df630SAndroid Build Coastguard Worker 		exit(update_error);
1051*4f2df630SAndroid Build Coastguard Worker 	}
1052*4f2df630SAndroid Build Coastguard Worker 
1053*4f2df630SAndroid Build Coastguard Worker 	return 0;
1054*4f2df630SAndroid Build Coastguard Worker }
1055*4f2df630SAndroid Build Coastguard Worker 
1056*4f2df630SAndroid Build Coastguard Worker /**
1057*4f2df630SAndroid Build Coastguard Worker  * Transfer an image section (typically RW or RO).
1058*4f2df630SAndroid Build Coastguard Worker  *
1059*4f2df630SAndroid Build Coastguard Worker  * td           - transfer descriptor to use to communicate with the target
1060*4f2df630SAndroid Build Coastguard Worker  * data_ptr     - pointer at the section base in the image
1061*4f2df630SAndroid Build Coastguard Worker  * section_addr - address of the section in the target memory space
1062*4f2df630SAndroid Build Coastguard Worker  * data_len     - section size
1063*4f2df630SAndroid Build Coastguard Worker  */
transfer_section(struct transfer_descriptor * td,uint8_t * data_ptr,uint32_t section_addr,size_t data_len)1064*4f2df630SAndroid Build Coastguard Worker static void transfer_section(struct transfer_descriptor *td, uint8_t *data_ptr,
1065*4f2df630SAndroid Build Coastguard Worker 			     uint32_t section_addr, size_t data_len)
1066*4f2df630SAndroid Build Coastguard Worker {
1067*4f2df630SAndroid Build Coastguard Worker 	/*
1068*4f2df630SAndroid Build Coastguard Worker 	 * Actually, we can skip trailing chunks of 0xff, as the entire
1069*4f2df630SAndroid Build Coastguard Worker 	 * section space must be erased before the update is attempted.
1070*4f2df630SAndroid Build Coastguard Worker 	 */
1071*4f2df630SAndroid Build Coastguard Worker 	while (data_len && (data_ptr[data_len - 1] == 0xff))
1072*4f2df630SAndroid Build Coastguard Worker 		data_len--;
1073*4f2df630SAndroid Build Coastguard Worker 
1074*4f2df630SAndroid Build Coastguard Worker 	/*
1075*4f2df630SAndroid Build Coastguard Worker 	 * Make sure total size is 4 bytes aligned, this is required for
1076*4f2df630SAndroid Build Coastguard Worker 	 * successful flashing.
1077*4f2df630SAndroid Build Coastguard Worker 	 */
1078*4f2df630SAndroid Build Coastguard Worker 	data_len = (data_len + 3) & ~3;
1079*4f2df630SAndroid Build Coastguard Worker 
1080*4f2df630SAndroid Build Coastguard Worker 	printf("sending 0x%zx bytes to %#x\n", data_len, section_addr);
1081*4f2df630SAndroid Build Coastguard Worker 	while (data_len) {
1082*4f2df630SAndroid Build Coastguard Worker 		size_t payload_size;
1083*4f2df630SAndroid Build Coastguard Worker 		EVP_MD_CTX *ctx;
1084*4f2df630SAndroid Build Coastguard Worker 		int max_retries;
1085*4f2df630SAndroid Build Coastguard Worker 		struct update_pdu updu;
1086*4f2df630SAndroid Build Coastguard Worker 
1087*4f2df630SAndroid Build Coastguard Worker 		/* prepare the header to prepend to the block. */
1088*4f2df630SAndroid Build Coastguard Worker 		payload_size = MIN(data_len, SIGNED_TRANSFER_SIZE);
1089*4f2df630SAndroid Build Coastguard Worker 		updu.block_size =
1090*4f2df630SAndroid Build Coastguard Worker 			htobe32(payload_size + sizeof(struct update_pdu));
1091*4f2df630SAndroid Build Coastguard Worker 
1092*4f2df630SAndroid Build Coastguard Worker 		updu.cmd.block_base = htobe32(section_addr);
1093*4f2df630SAndroid Build Coastguard Worker 
1094*4f2df630SAndroid Build Coastguard Worker 		/* Calculate the digest. */
1095*4f2df630SAndroid Build Coastguard Worker 		ctx = EVP_MD_CTX_new();
1096*4f2df630SAndroid Build Coastguard Worker 		sha_init(ctx);
1097*4f2df630SAndroid Build Coastguard Worker 		sha_update(ctx, &updu.cmd.block_base,
1098*4f2df630SAndroid Build Coastguard Worker 			   sizeof(updu.cmd.block_base));
1099*4f2df630SAndroid Build Coastguard Worker 		sha_update(ctx, data_ptr, payload_size);
1100*4f2df630SAndroid Build Coastguard Worker 		sha_final_into_block_digest(ctx, &updu.cmd.block_digest,
1101*4f2df630SAndroid Build Coastguard Worker 					    sizeof(updu.cmd.block_digest));
1102*4f2df630SAndroid Build Coastguard Worker 		EVP_MD_CTX_free(ctx);
1103*4f2df630SAndroid Build Coastguard Worker 
1104*4f2df630SAndroid Build Coastguard Worker 		if (td->ep_type == usb_xfer) {
1105*4f2df630SAndroid Build Coastguard Worker 			for (max_retries = 10; max_retries; max_retries--)
1106*4f2df630SAndroid Build Coastguard Worker 				if (!transfer_block(&td->uep, &updu, data_ptr,
1107*4f2df630SAndroid Build Coastguard Worker 						    payload_size))
1108*4f2df630SAndroid Build Coastguard Worker 					break;
1109*4f2df630SAndroid Build Coastguard Worker 
1110*4f2df630SAndroid Build Coastguard Worker 			if (!max_retries) {
1111*4f2df630SAndroid Build Coastguard Worker 				fprintf(stderr,
1112*4f2df630SAndroid Build Coastguard Worker 					"Failed to transfer block, %zd to go\n",
1113*4f2df630SAndroid Build Coastguard Worker 					data_len);
1114*4f2df630SAndroid Build Coastguard Worker 				exit(update_error);
1115*4f2df630SAndroid Build Coastguard Worker 			}
1116*4f2df630SAndroid Build Coastguard Worker 		} else {
1117*4f2df630SAndroid Build Coastguard Worker 			uint8_t error_code[4];
1118*4f2df630SAndroid Build Coastguard Worker 			size_t rxed_size = sizeof(error_code);
1119*4f2df630SAndroid Build Coastguard Worker 			uint32_t block_addr;
1120*4f2df630SAndroid Build Coastguard Worker 
1121*4f2df630SAndroid Build Coastguard Worker 			block_addr = section_addr;
1122*4f2df630SAndroid Build Coastguard Worker 
1123*4f2df630SAndroid Build Coastguard Worker 			/*
1124*4f2df630SAndroid Build Coastguard Worker 			 * A single byte response is expected, but let's give
1125*4f2df630SAndroid Build Coastguard Worker 			 * the driver a few extra bytes to catch cases when a
1126*4f2df630SAndroid Build Coastguard Worker 			 * different amount of data is transferred (which
1127*4f2df630SAndroid Build Coastguard Worker 			 * would indicate a synchronization problem).
1128*4f2df630SAndroid Build Coastguard Worker 			 */
1129*4f2df630SAndroid Build Coastguard Worker 			if (tpm_send_pkt(td, updu.cmd.block_digest, block_addr,
1130*4f2df630SAndroid Build Coastguard Worker 					 data_ptr, payload_size, error_code,
1131*4f2df630SAndroid Build Coastguard Worker 					 &rxed_size,
1132*4f2df630SAndroid Build Coastguard Worker 					 EXTENSION_FW_UPGRADE) < 0) {
1133*4f2df630SAndroid Build Coastguard Worker 				fprintf(stderr,
1134*4f2df630SAndroid Build Coastguard Worker 					"Failed to trasfer block, %zd to go\n",
1135*4f2df630SAndroid Build Coastguard Worker 					data_len);
1136*4f2df630SAndroid Build Coastguard Worker 				exit(update_error);
1137*4f2df630SAndroid Build Coastguard Worker 			}
1138*4f2df630SAndroid Build Coastguard Worker 			if (rxed_size != 1) {
1139*4f2df630SAndroid Build Coastguard Worker 				fprintf(stderr, "Unexpected return size %zd\n",
1140*4f2df630SAndroid Build Coastguard Worker 					rxed_size);
1141*4f2df630SAndroid Build Coastguard Worker 				exit(update_error);
1142*4f2df630SAndroid Build Coastguard Worker 			}
1143*4f2df630SAndroid Build Coastguard Worker 
1144*4f2df630SAndroid Build Coastguard Worker 			if (error_code[0]) {
1145*4f2df630SAndroid Build Coastguard Worker 				fprintf(stderr, "Error %d\n", error_code[0]);
1146*4f2df630SAndroid Build Coastguard Worker 				exit(update_error);
1147*4f2df630SAndroid Build Coastguard Worker 			}
1148*4f2df630SAndroid Build Coastguard Worker 		}
1149*4f2df630SAndroid Build Coastguard Worker 		data_len -= payload_size;
1150*4f2df630SAndroid Build Coastguard Worker 		data_ptr += payload_size;
1151*4f2df630SAndroid Build Coastguard Worker 		section_addr += payload_size;
1152*4f2df630SAndroid Build Coastguard Worker 	}
1153*4f2df630SAndroid Build Coastguard Worker }
1154*4f2df630SAndroid Build Coastguard Worker 
1155*4f2df630SAndroid Build Coastguard Worker /* Information about the target */
1156*4f2df630SAndroid Build Coastguard Worker static struct first_response_pdu targ;
1157*4f2df630SAndroid Build Coastguard Worker 
1158*4f2df630SAndroid Build Coastguard Worker /* The well known CR50 section location and sizes. These are not scanned for. */
1159*4f2df630SAndroid Build Coastguard Worker const struct section_t CR50_SECTIONS[NUM_SECTIONS] = {
1160*4f2df630SAndroid Build Coastguard Worker 	[RO_A] = { CONFIG_RO_MEM_OFF, CONFIG_RO_SIZE },
1161*4f2df630SAndroid Build Coastguard Worker 	[RW_A] = { CONFIG_RW_MEM_OFF, CONFIG_RW_SIZE },
1162*4f2df630SAndroid Build Coastguard Worker 	[RO_B] = { CHIP_RO_B_MEM_OFF, CONFIG_RO_SIZE },
1163*4f2df630SAndroid Build Coastguard Worker 	[RW_B] = { CONFIG_RW_B_MEM_OFF, CONFIG_RW_SIZE }
1164*4f2df630SAndroid Build Coastguard Worker };
1165*4f2df630SAndroid Build Coastguard Worker 
1166*4f2df630SAndroid Build Coastguard Worker /*
1167*4f2df630SAndroid Build Coastguard Worker  * Remove these definitions so a developer doesn't accidentally use them in
1168*4f2df630SAndroid Build Coastguard Worker  * the future. All lookups should go through the sections array.
1169*4f2df630SAndroid Build Coastguard Worker  */
1170*4f2df630SAndroid Build Coastguard Worker #undef CONFIG_RO_MEM_OFF
1171*4f2df630SAndroid Build Coastguard Worker #undef CONFIG_RW_MEM_OFF
1172*4f2df630SAndroid Build Coastguard Worker #undef CHIP_RO_B_MEM_OFF
1173*4f2df630SAndroid Build Coastguard Worker #undef CONFIG_RW_B_MEM_OFF
1174*4f2df630SAndroid Build Coastguard Worker #undef CONFIG_RO_SIZE
1175*4f2df630SAndroid Build Coastguard Worker #undef CONFIG_RW_SIZE
1176*4f2df630SAndroid Build Coastguard Worker #undef CONFIG_FLASH_SIZE
1177*4f2df630SAndroid Build Coastguard Worker 
1178*4f2df630SAndroid Build Coastguard Worker /* Returns true if the specified signed header is valid */
valid_signed_header(const struct SignedHeader * const h,const size_t size)1179*4f2df630SAndroid Build Coastguard Worker static bool valid_signed_header(const struct SignedHeader *const h,
1180*4f2df630SAndroid Build Coastguard Worker 				const size_t size)
1181*4f2df630SAndroid Build Coastguard Worker {
1182*4f2df630SAndroid Build Coastguard Worker 	if (size < sizeof(struct SignedHeader))
1183*4f2df630SAndroid Build Coastguard Worker 		return false;
1184*4f2df630SAndroid Build Coastguard Worker 
1185*4f2df630SAndroid Build Coastguard Worker 	/* Only H1 and D2 are currently supported. */
1186*4f2df630SAndroid Build Coastguard Worker 	if (h->magic != MAGIC_HAVEN && h->magic != MAGIC_DAUNTLESS)
1187*4f2df630SAndroid Build Coastguard Worker 		return false;
1188*4f2df630SAndroid Build Coastguard Worker 
1189*4f2df630SAndroid Build Coastguard Worker 	if (h->image_size > size)
1190*4f2df630SAndroid Build Coastguard Worker 		return false;
1191*4f2df630SAndroid Build Coastguard Worker 
1192*4f2df630SAndroid Build Coastguard Worker 	if (h->image_size < CONFIG_FLASH_BANK_SIZE)
1193*4f2df630SAndroid Build Coastguard Worker 		return false;
1194*4f2df630SAndroid Build Coastguard Worker 
1195*4f2df630SAndroid Build Coastguard Worker 	/*
1196*4f2df630SAndroid Build Coastguard Worker 	 * Both Rx base and Ro base are the memory mapped address, but they
1197*4f2df630SAndroid Build Coastguard Worker 	 * should have the same offset. The rx section starts after the header.
1198*4f2df630SAndroid Build Coastguard Worker 	 */
1199*4f2df630SAndroid Build Coastguard Worker 	if (h->rx_base != h->ro_base + sizeof(struct SignedHeader))
1200*4f2df630SAndroid Build Coastguard Worker 		return false;
1201*4f2df630SAndroid Build Coastguard Worker 
1202*4f2df630SAndroid Build Coastguard Worker 	/* Ensure each section falls within full size */
1203*4f2df630SAndroid Build Coastguard Worker 	if (h->ro_max - h->ro_base > size)
1204*4f2df630SAndroid Build Coastguard Worker 		return false;
1205*4f2df630SAndroid Build Coastguard Worker 
1206*4f2df630SAndroid Build Coastguard Worker 	if (h->rx_max - h->rx_base > size)
1207*4f2df630SAndroid Build Coastguard Worker 		return false;
1208*4f2df630SAndroid Build Coastguard Worker 
1209*4f2df630SAndroid Build Coastguard Worker 	return true;
1210*4f2df630SAndroid Build Coastguard Worker }
1211*4f2df630SAndroid Build Coastguard Worker 
1212*4f2df630SAndroid Build Coastguard Worker /* Returns true if the specified opentitan manifest header is valid */
valid_nt_manifest(const struct SignedManifest * const m,const size_t size)1213*4f2df630SAndroid Build Coastguard Worker static bool valid_nt_manifest(const struct SignedManifest *const m,
1214*4f2df630SAndroid Build Coastguard Worker 			      const size_t size)
1215*4f2df630SAndroid Build Coastguard Worker {
1216*4f2df630SAndroid Build Coastguard Worker 	if (size < sizeof(struct SignedManifest))
1217*4f2df630SAndroid Build Coastguard Worker 		return false;
1218*4f2df630SAndroid Build Coastguard Worker 
1219*4f2df630SAndroid Build Coastguard Worker 	if (m->identifier != ID_ROM_EXT && m->identifier != ID_OWNER_FW)
1220*4f2df630SAndroid Build Coastguard Worker 		return false;
1221*4f2df630SAndroid Build Coastguard Worker 
1222*4f2df630SAndroid Build Coastguard Worker 	if (m->length > size)
1223*4f2df630SAndroid Build Coastguard Worker 		return false;
1224*4f2df630SAndroid Build Coastguard Worker 
1225*4f2df630SAndroid Build Coastguard Worker 	if (m->code_start > m->code_end)
1226*4f2df630SAndroid Build Coastguard Worker 		return false;
1227*4f2df630SAndroid Build Coastguard Worker 
1228*4f2df630SAndroid Build Coastguard Worker 	if (m->code_start > m->length)
1229*4f2df630SAndroid Build Coastguard Worker 		return false;
1230*4f2df630SAndroid Build Coastguard Worker 
1231*4f2df630SAndroid Build Coastguard Worker 	if (m->code_end > m->length)
1232*4f2df630SAndroid Build Coastguard Worker 		return false;
1233*4f2df630SAndroid Build Coastguard Worker 
1234*4f2df630SAndroid Build Coastguard Worker 	if (m->entry_point > m->code_end)
1235*4f2df630SAndroid Build Coastguard Worker 		return false;
1236*4f2df630SAndroid Build Coastguard Worker 
1237*4f2df630SAndroid Build Coastguard Worker 	if (m->entry_point < m->code_start)
1238*4f2df630SAndroid Build Coastguard Worker 		return false;
1239*4f2df630SAndroid Build Coastguard Worker 
1240*4f2df630SAndroid Build Coastguard Worker 	return true;
1241*4f2df630SAndroid Build Coastguard Worker }
1242*4f2df630SAndroid Build Coastguard Worker 
1243*4f2df630SAndroid Build Coastguard Worker /* Returns true if the specified image header is valid */
valid_image_header(const struct typed_image_header h,const size_t size,enum gsc_device * out_device)1244*4f2df630SAndroid Build Coastguard Worker static bool valid_image_header(const struct typed_image_header h,
1245*4f2df630SAndroid Build Coastguard Worker 			       const size_t size, enum gsc_device *out_device)
1246*4f2df630SAndroid Build Coastguard Worker {
1247*4f2df630SAndroid Build Coastguard Worker 	if (valid_nt_manifest(h.m, size)) {
1248*4f2df630SAndroid Build Coastguard Worker 		enum gsc_device type = GSC_DEVICE_NT;
1249*4f2df630SAndroid Build Coastguard Worker 
1250*4f2df630SAndroid Build Coastguard Worker 		if (out_device) {
1251*4f2df630SAndroid Build Coastguard Worker 			*out_device = type;
1252*4f2df630SAndroid Build Coastguard Worker 			return true;
1253*4f2df630SAndroid Build Coastguard Worker 		} else {
1254*4f2df630SAndroid Build Coastguard Worker 			return h.type == type;
1255*4f2df630SAndroid Build Coastguard Worker 		}
1256*4f2df630SAndroid Build Coastguard Worker 	}
1257*4f2df630SAndroid Build Coastguard Worker 	if (valid_signed_header(h.h, size)) {
1258*4f2df630SAndroid Build Coastguard Worker 		enum gsc_device type = GSC_DEVICE_H1;
1259*4f2df630SAndroid Build Coastguard Worker 
1260*4f2df630SAndroid Build Coastguard Worker 		if (h.h->magic == MAGIC_DAUNTLESS) {
1261*4f2df630SAndroid Build Coastguard Worker 			type = GSC_DEVICE_DT;
1262*4f2df630SAndroid Build Coastguard Worker 		} else if (h.h->magic != MAGIC_HAVEN) {
1263*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr,
1264*4f2df630SAndroid Build Coastguard Worker 				"Error: Cannot determine image type.\n");
1265*4f2df630SAndroid Build Coastguard Worker 			/* Unsupported image type */
1266*4f2df630SAndroid Build Coastguard Worker 			exit(update_error);
1267*4f2df630SAndroid Build Coastguard Worker 		}
1268*4f2df630SAndroid Build Coastguard Worker 		if (out_device) {
1269*4f2df630SAndroid Build Coastguard Worker 			*out_device = type;
1270*4f2df630SAndroid Build Coastguard Worker 			return true;
1271*4f2df630SAndroid Build Coastguard Worker 		} else {
1272*4f2df630SAndroid Build Coastguard Worker 			return h.type == type;
1273*4f2df630SAndroid Build Coastguard Worker 		}
1274*4f2df630SAndroid Build Coastguard Worker 	}
1275*4f2df630SAndroid Build Coastguard Worker 	return false;
1276*4f2df630SAndroid Build Coastguard Worker }
1277*4f2df630SAndroid Build Coastguard Worker 
1278*4f2df630SAndroid Build Coastguard Worker /* Returns the image size from the header. This assumes it is valid */
get_size_from_header(const struct typed_image_header h)1279*4f2df630SAndroid Build Coastguard Worker static uint32_t get_size_from_header(const struct typed_image_header h)
1280*4f2df630SAndroid Build Coastguard Worker {
1281*4f2df630SAndroid Build Coastguard Worker 	if (h.type == GSC_DEVICE_H1 || h.type == GSC_DEVICE_DT)
1282*4f2df630SAndroid Build Coastguard Worker 		return h.h->image_size;
1283*4f2df630SAndroid Build Coastguard Worker 
1284*4f2df630SAndroid Build Coastguard Worker 	if (h.type == GSC_DEVICE_NT)
1285*4f2df630SAndroid Build Coastguard Worker 		return h.m->length;
1286*4f2df630SAndroid Build Coastguard Worker 
1287*4f2df630SAndroid Build Coastguard Worker 	fprintf(stderr, "Error: Cannot determine image type.\n");
1288*4f2df630SAndroid Build Coastguard Worker 	/* Unsupported image type */
1289*4f2df630SAndroid Build Coastguard Worker 	exit(update_error);
1290*4f2df630SAndroid Build Coastguard Worker 	return 0;
1291*4f2df630SAndroid Build Coastguard Worker }
1292*4f2df630SAndroid Build Coastguard Worker 
1293*4f2df630SAndroid Build Coastguard Worker /* Rounds and address up to the next 2KB boundary if not one already */
round_up_2kb(const uint32_t addr)1294*4f2df630SAndroid Build Coastguard Worker static inline uint32_t round_up_2kb(const uint32_t addr)
1295*4f2df630SAndroid Build Coastguard Worker {
1296*4f2df630SAndroid Build Coastguard Worker 	const uint32_t mask = (2 * 1024) - 1;
1297*4f2df630SAndroid Build Coastguard Worker 
1298*4f2df630SAndroid Build Coastguard Worker 	return (addr + mask) & ~mask;
1299*4f2df630SAndroid Build Coastguard Worker }
1300*4f2df630SAndroid Build Coastguard Worker 
as_header(const struct image * image,uint32_t offset)1301*4f2df630SAndroid Build Coastguard Worker static struct typed_image_header as_header(const struct image *image,
1302*4f2df630SAndroid Build Coastguard Worker 					   uint32_t offset)
1303*4f2df630SAndroid Build Coastguard Worker {
1304*4f2df630SAndroid Build Coastguard Worker 	struct typed_image_header ret = {
1305*4f2df630SAndroid Build Coastguard Worker 		image->type,
1306*4f2df630SAndroid Build Coastguard Worker 		{ (void *)((uintptr_t)image->data + offset) },
1307*4f2df630SAndroid Build Coastguard Worker 	};
1308*4f2df630SAndroid Build Coastguard Worker 	return ret;
1309*4f2df630SAndroid Build Coastguard Worker }
1310*4f2df630SAndroid Build Coastguard Worker 
1311*4f2df630SAndroid Build Coastguard Worker /* Returns the RW header or -1 if one cannot be found */
find_rw_header(const struct image * image,uint32_t offset,const uint32_t end)1312*4f2df630SAndroid Build Coastguard Worker static int32_t find_rw_header(const struct image *image, uint32_t offset,
1313*4f2df630SAndroid Build Coastguard Worker 			      const uint32_t end)
1314*4f2df630SAndroid Build Coastguard Worker {
1315*4f2df630SAndroid Build Coastguard Worker 	offset = round_up_2kb(offset);
1316*4f2df630SAndroid Build Coastguard Worker 
1317*4f2df630SAndroid Build Coastguard Worker 	while (offset < end) {
1318*4f2df630SAndroid Build Coastguard Worker 		if (valid_image_header(as_header(image, offset), end - offset,
1319*4f2df630SAndroid Build Coastguard Worker 				       NULL))
1320*4f2df630SAndroid Build Coastguard Worker 			return offset;
1321*4f2df630SAndroid Build Coastguard Worker 		offset = round_up_2kb(offset + 1);
1322*4f2df630SAndroid Build Coastguard Worker 	}
1323*4f2df630SAndroid Build Coastguard Worker 
1324*4f2df630SAndroid Build Coastguard Worker 	return -1;
1325*4f2df630SAndroid Build Coastguard Worker }
1326*4f2df630SAndroid Build Coastguard Worker 
1327*4f2df630SAndroid Build Coastguard Worker /* Return true if we located headers and set sections correctly */
locate_headers(struct image * image)1328*4f2df630SAndroid Build Coastguard Worker static bool locate_headers(struct image *image)
1329*4f2df630SAndroid Build Coastguard Worker {
1330*4f2df630SAndroid Build Coastguard Worker 	const uint32_t slot_a_end = image->data_len / 2;
1331*4f2df630SAndroid Build Coastguard Worker 	struct section_t *sections = image->sections;
1332*4f2df630SAndroid Build Coastguard Worker 	int32_t rw_offset;
1333*4f2df630SAndroid Build Coastguard Worker 
1334*4f2df630SAndroid Build Coastguard Worker 	/*
1335*4f2df630SAndroid Build Coastguard Worker 	 * We assume that all 512KB images are "valid" H1 images. The DBG images
1336*4f2df630SAndroid Build Coastguard Worker 	 * from the signer do not set the magic to -1 and no not set valid
1337*4f2df630SAndroid Build Coastguard Worker 	 * section offsets. We do not want to break this case as it is used in
1338*4f2df630SAndroid Build Coastguard Worker 	 * testing. The H1 offsets are also static, so we don't need to scan
1339*4f2df630SAndroid Build Coastguard Worker 	 * for RW headers.
1340*4f2df630SAndroid Build Coastguard Worker 	 */
1341*4f2df630SAndroid Build Coastguard Worker 	if (image->data_len == (512 * 1024)) {
1342*4f2df630SAndroid Build Coastguard Worker 		image->type = GSC_DEVICE_H1;
1343*4f2df630SAndroid Build Coastguard Worker 		memcpy(sections, CR50_SECTIONS, sizeof(CR50_SECTIONS));
1344*4f2df630SAndroid Build Coastguard Worker 		return true;
1345*4f2df630SAndroid Build Coastguard Worker 	}
1346*4f2df630SAndroid Build Coastguard Worker 
1347*4f2df630SAndroid Build Coastguard Worker 	/*
1348*4f2df630SAndroid Build Coastguard Worker 	 * We know that all other image types supported (i.e. Dauntless,
1349*4f2df630SAndroid Build Coastguard Worker 	 * NuvoTitan) are 1MB in size.
1350*4f2df630SAndroid Build Coastguard Worker 	 */
1351*4f2df630SAndroid Build Coastguard Worker 	if (image->data_len != (1024 * 1024)) {
1352*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "\nERROR: Image size (%zd KB) is invalid\n",
1353*4f2df630SAndroid Build Coastguard Worker 			image->data_len / 1024);
1354*4f2df630SAndroid Build Coastguard Worker 		return false;
1355*4f2df630SAndroid Build Coastguard Worker 	}
1356*4f2df630SAndroid Build Coastguard Worker 
1357*4f2df630SAndroid Build Coastguard Worker 	/* Validate the RO_A header */
1358*4f2df630SAndroid Build Coastguard Worker 	if (!valid_image_header(as_header(image, 0), slot_a_end,
1359*4f2df630SAndroid Build Coastguard Worker 				&image->type)) {
1360*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "\nERROR: RO_A header is invalid\n");
1361*4f2df630SAndroid Build Coastguard Worker 		return false;
1362*4f2df630SAndroid Build Coastguard Worker 	}
1363*4f2df630SAndroid Build Coastguard Worker 
1364*4f2df630SAndroid Build Coastguard Worker 	sections[RO_A].offset = 0;
1365*4f2df630SAndroid Build Coastguard Worker 	sections[RO_A].size = get_size_from_header(as_header(image, 0));
1366*4f2df630SAndroid Build Coastguard Worker 
1367*4f2df630SAndroid Build Coastguard Worker 	/* Find RW_A */
1368*4f2df630SAndroid Build Coastguard Worker 	rw_offset = find_rw_header(
1369*4f2df630SAndroid Build Coastguard Worker 		image, sections[RO_A].offset + sections[RO_A].size, slot_a_end);
1370*4f2df630SAndroid Build Coastguard Worker 	if (rw_offset == -1) {
1371*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "\nERROR: RW_A header cannot be found\n");
1372*4f2df630SAndroid Build Coastguard Worker 		return false;
1373*4f2df630SAndroid Build Coastguard Worker 	}
1374*4f2df630SAndroid Build Coastguard Worker 	sections[RW_A].offset = rw_offset;
1375*4f2df630SAndroid Build Coastguard Worker 	sections[RW_A].size = get_size_from_header(as_header(image, rw_offset));
1376*4f2df630SAndroid Build Coastguard Worker 
1377*4f2df630SAndroid Build Coastguard Worker 	/* Validate the RO_B header */
1378*4f2df630SAndroid Build Coastguard Worker 	if (!valid_image_header(as_header(image, slot_a_end),
1379*4f2df630SAndroid Build Coastguard Worker 				image->data_len - slot_a_end, NULL)) {
1380*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "\nERROR: RO_B header is invalid\n");
1381*4f2df630SAndroid Build Coastguard Worker 		return false;
1382*4f2df630SAndroid Build Coastguard Worker 	}
1383*4f2df630SAndroid Build Coastguard Worker 	sections[RO_B].offset = slot_a_end;
1384*4f2df630SAndroid Build Coastguard Worker 	sections[RO_B].size =
1385*4f2df630SAndroid Build Coastguard Worker 		get_size_from_header(as_header(image, slot_a_end));
1386*4f2df630SAndroid Build Coastguard Worker 
1387*4f2df630SAndroid Build Coastguard Worker 	/* Find RW_B */
1388*4f2df630SAndroid Build Coastguard Worker 	rw_offset = find_rw_header(image,
1389*4f2df630SAndroid Build Coastguard Worker 				   sections[RO_B].offset + sections[RO_B].size,
1390*4f2df630SAndroid Build Coastguard Worker 				   image->data_len);
1391*4f2df630SAndroid Build Coastguard Worker 	if (rw_offset == -1) {
1392*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "\nERROR: RW_B header cannot be found\n");
1393*4f2df630SAndroid Build Coastguard Worker 		return false;
1394*4f2df630SAndroid Build Coastguard Worker 	}
1395*4f2df630SAndroid Build Coastguard Worker 	sections[RW_B].offset = rw_offset;
1396*4f2df630SAndroid Build Coastguard Worker 	sections[RW_B].size = get_size_from_header(as_header(image, rw_offset));
1397*4f2df630SAndroid Build Coastguard Worker 
1398*4f2df630SAndroid Build Coastguard Worker 	/* We found all of the headers and updated offset/size in sections */
1399*4f2df630SAndroid Build Coastguard Worker 	return true;
1400*4f2df630SAndroid Build Coastguard Worker }
1401*4f2df630SAndroid Build Coastguard Worker 
1402*4f2df630SAndroid Build Coastguard Worker /*
1403*4f2df630SAndroid Build Coastguard Worker  * Scan the new image and retrieve versions of all four sections, two RO and
1404*4f2df630SAndroid Build Coastguard Worker  * two RW, verifying that image size is not too short along the way.
1405*4f2df630SAndroid Build Coastguard Worker  */
fetch_header_versions(struct image * image)1406*4f2df630SAndroid Build Coastguard Worker static bool fetch_header_versions(struct image *image)
1407*4f2df630SAndroid Build Coastguard Worker {
1408*4f2df630SAndroid Build Coastguard Worker 	size_t i;
1409*4f2df630SAndroid Build Coastguard Worker 	struct section_t *const sections = image->sections;
1410*4f2df630SAndroid Build Coastguard Worker 
1411*4f2df630SAndroid Build Coastguard Worker 	for (i = 0; i < NUM_SECTIONS; i++) {
1412*4f2df630SAndroid Build Coastguard Worker 		const struct typed_image_header h =
1413*4f2df630SAndroid Build Coastguard Worker 			as_header(image, sections[i].offset);
1414*4f2df630SAndroid Build Coastguard Worker 
1415*4f2df630SAndroid Build Coastguard Worker 		if (get_size_from_header(h) < CONFIG_FLASH_BANK_SIZE) {
1416*4f2df630SAndroid Build Coastguard Worker 			/*
1417*4f2df630SAndroid Build Coastguard Worker 			 * Return an error for incorrectly signed images. If
1418*4f2df630SAndroid Build Coastguard Worker 			 * it's a RO image with 0 as its size, ignore the error.
1419*4f2df630SAndroid Build Coastguard Worker 			 *
1420*4f2df630SAndroid Build Coastguard Worker 			 * TODO(b/273510573): revisit after dbg versioning is
1421*4f2df630SAndroid Build Coastguard Worker 			 * figured out.
1422*4f2df630SAndroid Build Coastguard Worker 			 */
1423*4f2df630SAndroid Build Coastguard Worker 			if (get_size_from_header(h) || sections[i].offset) {
1424*4f2df630SAndroid Build Coastguard Worker 				fprintf(stderr,
1425*4f2df630SAndroid Build Coastguard Worker 					"Image at offset %#5x too short "
1426*4f2df630SAndroid Build Coastguard Worker 					"(%d bytes)\n",
1427*4f2df630SAndroid Build Coastguard Worker 					sections[i].offset, h.h->image_size);
1428*4f2df630SAndroid Build Coastguard Worker 				return false;
1429*4f2df630SAndroid Build Coastguard Worker 			}
1430*4f2df630SAndroid Build Coastguard Worker 
1431*4f2df630SAndroid Build Coastguard Worker 			printf("warning: invalid RO_A (size 0)\n");
1432*4f2df630SAndroid Build Coastguard Worker 		}
1433*4f2df630SAndroid Build Coastguard Worker 		if (h.type == GSC_DEVICE_H1 || h.type == GSC_DEVICE_DT) {
1434*4f2df630SAndroid Build Coastguard Worker 			sections[i].shv.epoch = h.h->epoch_;
1435*4f2df630SAndroid Build Coastguard Worker 			sections[i].shv.major = h.h->major_;
1436*4f2df630SAndroid Build Coastguard Worker 			sections[i].shv.minor = h.h->minor_;
1437*4f2df630SAndroid Build Coastguard Worker 			sections[i].keyid = h.h->keyid;
1438*4f2df630SAndroid Build Coastguard Worker 		} else if (h.type == GSC_DEVICE_NT) {
1439*4f2df630SAndroid Build Coastguard Worker 			sections[i].shv.epoch = h.m->security_version;
1440*4f2df630SAndroid Build Coastguard Worker 			sections[i].shv.major = h.m->version_major;
1441*4f2df630SAndroid Build Coastguard Worker 			sections[i].shv.minor = h.m->version_minor;
1442*4f2df630SAndroid Build Coastguard Worker 			sections[i].keyid = 0;
1443*4f2df630SAndroid Build Coastguard Worker 		} else {
1444*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr, "\nERROR: Unknown image type.\n");
1445*4f2df630SAndroid Build Coastguard Worker 			exit(update_error);
1446*4f2df630SAndroid Build Coastguard Worker 		}
1447*4f2df630SAndroid Build Coastguard Worker 	}
1448*4f2df630SAndroid Build Coastguard Worker 	return true;
1449*4f2df630SAndroid Build Coastguard Worker }
1450*4f2df630SAndroid Build Coastguard Worker 
1451*4f2df630SAndroid Build Coastguard Worker /* Compare to signer headers and determine which one is newer. */
a_newer_than_b(const struct signed_header_version * a,const struct signed_header_version * b)1452*4f2df630SAndroid Build Coastguard Worker static int a_newer_than_b(const struct signed_header_version *a,
1453*4f2df630SAndroid Build Coastguard Worker 			  const struct signed_header_version *b)
1454*4f2df630SAndroid Build Coastguard Worker {
1455*4f2df630SAndroid Build Coastguard Worker 	uint32_t fields[][3] = {
1456*4f2df630SAndroid Build Coastguard Worker 		{ a->epoch, a->major, a->minor },
1457*4f2df630SAndroid Build Coastguard Worker 		{ b->epoch, b->major, b->minor },
1458*4f2df630SAndroid Build Coastguard Worker 	};
1459*4f2df630SAndroid Build Coastguard Worker 	size_t i;
1460*4f2df630SAndroid Build Coastguard Worker 
1461*4f2df630SAndroid Build Coastguard Worker 	for (i = 0; i < ARRAY_SIZE(fields[0]); i++) {
1462*4f2df630SAndroid Build Coastguard Worker 		uint32_t a_value;
1463*4f2df630SAndroid Build Coastguard Worker 		uint32_t b_value;
1464*4f2df630SAndroid Build Coastguard Worker 
1465*4f2df630SAndroid Build Coastguard Worker 		a_value = fields[0][i];
1466*4f2df630SAndroid Build Coastguard Worker 		b_value = fields[1][i];
1467*4f2df630SAndroid Build Coastguard Worker 
1468*4f2df630SAndroid Build Coastguard Worker 		/*
1469*4f2df630SAndroid Build Coastguard Worker 		 * Let's filter out images where the section is not
1470*4f2df630SAndroid Build Coastguard Worker 		 * initialized and the version field value is set to all ones.
1471*4f2df630SAndroid Build Coastguard Worker 		 */
1472*4f2df630SAndroid Build Coastguard Worker 		if (a_value == 0xffffffff)
1473*4f2df630SAndroid Build Coastguard Worker 			a_value = 0;
1474*4f2df630SAndroid Build Coastguard Worker 
1475*4f2df630SAndroid Build Coastguard Worker 		if (b_value == 0xffffffff)
1476*4f2df630SAndroid Build Coastguard Worker 			b_value = 0;
1477*4f2df630SAndroid Build Coastguard Worker 
1478*4f2df630SAndroid Build Coastguard Worker 		if (a_value != b_value)
1479*4f2df630SAndroid Build Coastguard Worker 			return a_value > b_value;
1480*4f2df630SAndroid Build Coastguard Worker 	}
1481*4f2df630SAndroid Build Coastguard Worker 
1482*4f2df630SAndroid Build Coastguard Worker 	return 0; /* All else being equal A is no newer than B. */
1483*4f2df630SAndroid Build Coastguard Worker }
1484*4f2df630SAndroid Build Coastguard Worker 
1485*4f2df630SAndroid Build Coastguard Worker /*
1486*4f2df630SAndroid Build Coastguard Worker  * Pick sections to transfer based on information retrieved from the target,
1487*4f2df630SAndroid Build Coastguard Worker  * the new image, and the protocol version the target is running.
1488*4f2df630SAndroid Build Coastguard Worker  */
pick_sections(struct transfer_descriptor * td,struct image * image)1489*4f2df630SAndroid Build Coastguard Worker static void pick_sections(struct transfer_descriptor *td, struct image *image)
1490*4f2df630SAndroid Build Coastguard Worker {
1491*4f2df630SAndroid Build Coastguard Worker 	size_t i;
1492*4f2df630SAndroid Build Coastguard Worker 	struct section_t *sections = image->sections;
1493*4f2df630SAndroid Build Coastguard Worker 
1494*4f2df630SAndroid Build Coastguard Worker 	for (i = 0; i < NUM_SECTIONS; i++) {
1495*4f2df630SAndroid Build Coastguard Worker 		uint32_t offset = sections[i].offset;
1496*4f2df630SAndroid Build Coastguard Worker 
1497*4f2df630SAndroid Build Coastguard Worker 		if ((i == RW_A) || (i == RW_B)) {
1498*4f2df630SAndroid Build Coastguard Worker 			/* Skip currently active RW section. */
1499*4f2df630SAndroid Build Coastguard Worker 			bool active_rw_slot_b = td->rw_offset <
1500*4f2df630SAndroid Build Coastguard Worker 						sections[RO_B].offset;
1501*4f2df630SAndroid Build Coastguard Worker 			if ((i == RW_B) == active_rw_slot_b)
1502*4f2df630SAndroid Build Coastguard Worker 				continue;
1503*4f2df630SAndroid Build Coastguard Worker 			/*
1504*4f2df630SAndroid Build Coastguard Worker 			 * Ok, this would be the RW section to transfer to the
1505*4f2df630SAndroid Build Coastguard Worker 			 * device. Is it newer in the new image than the
1506*4f2df630SAndroid Build Coastguard Worker 			 * running RW section on the device?
1507*4f2df630SAndroid Build Coastguard Worker 			 *
1508*4f2df630SAndroid Build Coastguard Worker 			 * If not in 'upstart' mode - transfer even if
1509*4f2df630SAndroid Build Coastguard Worker 			 * versions are the same, timestamps could be
1510*4f2df630SAndroid Build Coastguard Worker 			 * different.
1511*4f2df630SAndroid Build Coastguard Worker 			 */
1512*4f2df630SAndroid Build Coastguard Worker 
1513*4f2df630SAndroid Build Coastguard Worker 			if (a_newer_than_b(&sections[i].shv, &targ.shv[1]) ||
1514*4f2df630SAndroid Build Coastguard Worker 			    !td->upstart_mode) {
1515*4f2df630SAndroid Build Coastguard Worker 				sections[i].update_needed = true;
1516*4f2df630SAndroid Build Coastguard Worker 			}
1517*4f2df630SAndroid Build Coastguard Worker 			/* Rest of loop is RO */
1518*4f2df630SAndroid Build Coastguard Worker 			continue;
1519*4f2df630SAndroid Build Coastguard Worker 		}
1520*4f2df630SAndroid Build Coastguard Worker 
1521*4f2df630SAndroid Build Coastguard Worker 		/* Skip currently active RO section. */
1522*4f2df630SAndroid Build Coastguard Worker 		if (offset != td->ro_offset)
1523*4f2df630SAndroid Build Coastguard Worker 			continue;
1524*4f2df630SAndroid Build Coastguard Worker 		/*
1525*4f2df630SAndroid Build Coastguard Worker 		 * Ok, this would be the RO section to transfer to the device.
1526*4f2df630SAndroid Build Coastguard Worker 		 * Is it newer in the new image than the running RO section on
1527*4f2df630SAndroid Build Coastguard Worker 		 * the device?
1528*4f2df630SAndroid Build Coastguard Worker 		 */
1529*4f2df630SAndroid Build Coastguard Worker 		if (a_newer_than_b(&sections[i].shv, &targ.shv[0]) ||
1530*4f2df630SAndroid Build Coastguard Worker 		    td->force_ro)
1531*4f2df630SAndroid Build Coastguard Worker 			sections[i].update_needed = true;
1532*4f2df630SAndroid Build Coastguard Worker 	}
1533*4f2df630SAndroid Build Coastguard Worker }
1534*4f2df630SAndroid Build Coastguard Worker 
1535*4f2df630SAndroid Build Coastguard Worker /*
1536*4f2df630SAndroid Build Coastguard Worker  * Indicate to the target that update image transfer has been completed. Upon
1537*4f2df630SAndroid Build Coastguard Worker  * receiving of this message the target state machine transitions into the
1538*4f2df630SAndroid Build Coastguard Worker  * 'rx_idle' state. The host may send an extension command to reset the target
1539*4f2df630SAndroid Build Coastguard Worker  * after this.
1540*4f2df630SAndroid Build Coastguard Worker  */
send_done(struct usb_endpoint * uep)1541*4f2df630SAndroid Build Coastguard Worker static void send_done(struct usb_endpoint *uep)
1542*4f2df630SAndroid Build Coastguard Worker {
1543*4f2df630SAndroid Build Coastguard Worker 	uint32_t out;
1544*4f2df630SAndroid Build Coastguard Worker 
1545*4f2df630SAndroid Build Coastguard Worker 	/* Send stop request, ignoring reply. */
1546*4f2df630SAndroid Build Coastguard Worker 	out = htobe32(UPGRADE_DONE);
1547*4f2df630SAndroid Build Coastguard Worker 	do_xfer(uep, &out, sizeof(out), &out, 1, 0, NULL);
1548*4f2df630SAndroid Build Coastguard Worker }
1549*4f2df630SAndroid Build Coastguard Worker 
1550*4f2df630SAndroid Build Coastguard Worker /*
1551*4f2df630SAndroid Build Coastguard Worker  * Gets and caches the GSC version information from the currently connected
1552*4f2df630SAndroid Build Coastguard Worker  * device.
1553*4f2df630SAndroid Build Coastguard Worker  */
get_version(struct transfer_descriptor * td,bool leave_pending)1554*4f2df630SAndroid Build Coastguard Worker static void get_version(struct transfer_descriptor *td, bool leave_pending)
1555*4f2df630SAndroid Build Coastguard Worker {
1556*4f2df630SAndroid Build Coastguard Worker 	size_t rxed_size;
1557*4f2df630SAndroid Build Coastguard Worker 	size_t i;
1558*4f2df630SAndroid Build Coastguard Worker 	uint32_t error_code;
1559*4f2df630SAndroid Build Coastguard Worker 
1560*4f2df630SAndroid Build Coastguard Worker 	/*
1561*4f2df630SAndroid Build Coastguard Worker 	 * Need to be backwards compatible, communicate with targets running
1562*4f2df630SAndroid Build Coastguard Worker 	 * different protocol versions.
1563*4f2df630SAndroid Build Coastguard Worker 	 */
1564*4f2df630SAndroid Build Coastguard Worker 	union {
1565*4f2df630SAndroid Build Coastguard Worker 		struct first_response_pdu rpdu;
1566*4f2df630SAndroid Build Coastguard Worker 		uint32_t legacy_resp;
1567*4f2df630SAndroid Build Coastguard Worker 	} start_resp;
1568*4f2df630SAndroid Build Coastguard Worker 
1569*4f2df630SAndroid Build Coastguard Worker 	if (td->ep_type == usb_xfer) {
1570*4f2df630SAndroid Build Coastguard Worker 		struct update_pdu updu;
1571*4f2df630SAndroid Build Coastguard Worker 
1572*4f2df630SAndroid Build Coastguard Worker 		memset(&updu, 0, sizeof(updu));
1573*4f2df630SAndroid Build Coastguard Worker 		updu.block_size = htobe32(sizeof(updu));
1574*4f2df630SAndroid Build Coastguard Worker 		do_xfer(&td->uep, &updu, sizeof(updu), &start_resp,
1575*4f2df630SAndroid Build Coastguard Worker 			sizeof(start_resp), 1, &rxed_size);
1576*4f2df630SAndroid Build Coastguard Worker 	} else {
1577*4f2df630SAndroid Build Coastguard Worker 		rxed_size = sizeof(start_resp);
1578*4f2df630SAndroid Build Coastguard Worker 		if (tpm_send_pkt(td, 0, 0, NULL, 0, &start_resp, &rxed_size,
1579*4f2df630SAndroid Build Coastguard Worker 				 EXTENSION_FW_UPGRADE) < 0) {
1580*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr, "Failed to start transfer\n");
1581*4f2df630SAndroid Build Coastguard Worker 			exit(update_error);
1582*4f2df630SAndroid Build Coastguard Worker 		}
1583*4f2df630SAndroid Build Coastguard Worker 	}
1584*4f2df630SAndroid Build Coastguard Worker 
1585*4f2df630SAndroid Build Coastguard Worker 	/* We got something. Check for errors in response */
1586*4f2df630SAndroid Build Coastguard Worker 	if (rxed_size < 8) {
1587*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Unexpected response size %zd: ", rxed_size);
1588*4f2df630SAndroid Build Coastguard Worker 		for (i = 0; i < rxed_size; i++)
1589*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr, " %02x", ((uint8_t *)&start_resp)[i]);
1590*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "\n");
1591*4f2df630SAndroid Build Coastguard Worker 		exit(update_error);
1592*4f2df630SAndroid Build Coastguard Worker 	}
1593*4f2df630SAndroid Build Coastguard Worker 
1594*4f2df630SAndroid Build Coastguard Worker 	protocol_version = be32toh(start_resp.rpdu.protocol_version);
1595*4f2df630SAndroid Build Coastguard Worker 	if (protocol_version < 5) {
1596*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Unsupported protocol version %d\n",
1597*4f2df630SAndroid Build Coastguard Worker 			protocol_version);
1598*4f2df630SAndroid Build Coastguard Worker 		exit(update_error);
1599*4f2df630SAndroid Build Coastguard Worker 	}
1600*4f2df630SAndroid Build Coastguard Worker 
1601*4f2df630SAndroid Build Coastguard Worker 	error_code = be32toh(start_resp.rpdu.return_value);
1602*4f2df630SAndroid Build Coastguard Worker 
1603*4f2df630SAndroid Build Coastguard Worker 	if (error_code) {
1604*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Target reporting error %d\n", error_code);
1605*4f2df630SAndroid Build Coastguard Worker 		if (td->ep_type == usb_xfer)
1606*4f2df630SAndroid Build Coastguard Worker 			shut_down(&td->uep);
1607*4f2df630SAndroid Build Coastguard Worker 		exit(update_error);
1608*4f2df630SAndroid Build Coastguard Worker 	}
1609*4f2df630SAndroid Build Coastguard Worker 
1610*4f2df630SAndroid Build Coastguard Worker 	td->rw_offset = be32toh(start_resp.rpdu.backup_rw_offset);
1611*4f2df630SAndroid Build Coastguard Worker 	td->ro_offset = be32toh(start_resp.rpdu.backup_ro_offset);
1612*4f2df630SAndroid Build Coastguard Worker 
1613*4f2df630SAndroid Build Coastguard Worker 	/* Running header versions. */
1614*4f2df630SAndroid Build Coastguard Worker 	for (i = 0; i < ARRAY_SIZE(targ.shv); i++) {
1615*4f2df630SAndroid Build Coastguard Worker 		targ.shv[i].minor = be32toh(start_resp.rpdu.shv[i].minor);
1616*4f2df630SAndroid Build Coastguard Worker 		targ.shv[i].major = be32toh(start_resp.rpdu.shv[i].major);
1617*4f2df630SAndroid Build Coastguard Worker 		targ.shv[i].epoch = be32toh(start_resp.rpdu.shv[i].epoch);
1618*4f2df630SAndroid Build Coastguard Worker 	}
1619*4f2df630SAndroid Build Coastguard Worker 
1620*4f2df630SAndroid Build Coastguard Worker 	for (i = 0; i < ARRAY_SIZE(targ.keyid); i++)
1621*4f2df630SAndroid Build Coastguard Worker 		targ.keyid[i] = be32toh(start_resp.rpdu.keyid[i]);
1622*4f2df630SAndroid Build Coastguard Worker 
1623*4f2df630SAndroid Build Coastguard Worker 	if (!leave_pending && td->ep_type == usb_xfer)
1624*4f2df630SAndroid Build Coastguard Worker 		send_done(&td->uep);
1625*4f2df630SAndroid Build Coastguard Worker }
1626*4f2df630SAndroid Build Coastguard Worker 
setup_connection(struct transfer_descriptor * td)1627*4f2df630SAndroid Build Coastguard Worker static void setup_connection(struct transfer_descriptor *td)
1628*4f2df630SAndroid Build Coastguard Worker {
1629*4f2df630SAndroid Build Coastguard Worker 	/* Send start request. */
1630*4f2df630SAndroid Build Coastguard Worker 	printf("start\n");
1631*4f2df630SAndroid Build Coastguard Worker 
1632*4f2df630SAndroid Build Coastguard Worker 	get_version(td, true);
1633*4f2df630SAndroid Build Coastguard Worker 
1634*4f2df630SAndroid Build Coastguard Worker 	printf("keyids: RO 0x%08x, RW 0x%08x\n", targ.keyid[0], targ.keyid[1]);
1635*4f2df630SAndroid Build Coastguard Worker 	printf("offsets: backup RO at %#x, backup RW at %#x\n", td->ro_offset,
1636*4f2df630SAndroid Build Coastguard Worker 	       td->rw_offset);
1637*4f2df630SAndroid Build Coastguard Worker }
1638*4f2df630SAndroid Build Coastguard Worker 
1639*4f2df630SAndroid Build Coastguard Worker /*
1640*4f2df630SAndroid Build Coastguard Worker  * Channel TPM extension/vendor command over USB. The payload of the USB frame
1641*4f2df630SAndroid Build Coastguard Worker  * in this case consists of the 2 byte subcommand code concatenated with the
1642*4f2df630SAndroid Build Coastguard Worker  * command body. The caller needs to indicate if a response is expected, and
1643*4f2df630SAndroid Build Coastguard Worker  * if it is - of what maximum size.
1644*4f2df630SAndroid Build Coastguard Worker  */
ext_cmd_over_usb(struct usb_endpoint * uep,uint16_t subcommand,const void * cmd_body,size_t body_size,void * resp,size_t * resp_size)1645*4f2df630SAndroid Build Coastguard Worker static int ext_cmd_over_usb(struct usb_endpoint *uep, uint16_t subcommand,
1646*4f2df630SAndroid Build Coastguard Worker 			    const void *cmd_body, size_t body_size, void *resp,
1647*4f2df630SAndroid Build Coastguard Worker 			    size_t *resp_size)
1648*4f2df630SAndroid Build Coastguard Worker {
1649*4f2df630SAndroid Build Coastguard Worker 	struct update_frame_header *ufh;
1650*4f2df630SAndroid Build Coastguard Worker 	uint16_t *frame_ptr;
1651*4f2df630SAndroid Build Coastguard Worker 	size_t usb_msg_size;
1652*4f2df630SAndroid Build Coastguard Worker 	EVP_MD_CTX *ctx;
1653*4f2df630SAndroid Build Coastguard Worker 
1654*4f2df630SAndroid Build Coastguard Worker 	usb_msg_size = sizeof(struct update_frame_header) + sizeof(subcommand) +
1655*4f2df630SAndroid Build Coastguard Worker 		       body_size;
1656*4f2df630SAndroid Build Coastguard Worker 
1657*4f2df630SAndroid Build Coastguard Worker 	ufh = malloc(usb_msg_size);
1658*4f2df630SAndroid Build Coastguard Worker 	if (!ufh) {
1659*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "%s: failed to allocate %zd bytes\n", __func__,
1660*4f2df630SAndroid Build Coastguard Worker 			usb_msg_size);
1661*4f2df630SAndroid Build Coastguard Worker 		return -1;
1662*4f2df630SAndroid Build Coastguard Worker 	}
1663*4f2df630SAndroid Build Coastguard Worker 
1664*4f2df630SAndroid Build Coastguard Worker 	ufh->block_size = htobe32(usb_msg_size);
1665*4f2df630SAndroid Build Coastguard Worker 	ufh->cmd.block_base = htobe32(CONFIG_EXTENSION_COMMAND);
1666*4f2df630SAndroid Build Coastguard Worker 	frame_ptr = (uint16_t *)(ufh + 1);
1667*4f2df630SAndroid Build Coastguard Worker 	*frame_ptr = htobe16(subcommand);
1668*4f2df630SAndroid Build Coastguard Worker 
1669*4f2df630SAndroid Build Coastguard Worker 	if (body_size)
1670*4f2df630SAndroid Build Coastguard Worker 		memcpy(frame_ptr + 1, cmd_body, body_size);
1671*4f2df630SAndroid Build Coastguard Worker 
1672*4f2df630SAndroid Build Coastguard Worker 	/* Calculate the digest. */
1673*4f2df630SAndroid Build Coastguard Worker 	ctx = EVP_MD_CTX_new();
1674*4f2df630SAndroid Build Coastguard Worker 	sha_init(ctx);
1675*4f2df630SAndroid Build Coastguard Worker 	sha_update(ctx, &ufh->cmd.block_base,
1676*4f2df630SAndroid Build Coastguard Worker 		   usb_msg_size - offsetof(struct update_frame_header,
1677*4f2df630SAndroid Build Coastguard Worker 					   cmd.block_base));
1678*4f2df630SAndroid Build Coastguard Worker 	sha_final_into_block_digest(ctx, &ufh->cmd.block_digest,
1679*4f2df630SAndroid Build Coastguard Worker 				    sizeof(ufh->cmd.block_digest));
1680*4f2df630SAndroid Build Coastguard Worker 	EVP_MD_CTX_free(ctx);
1681*4f2df630SAndroid Build Coastguard Worker 
1682*4f2df630SAndroid Build Coastguard Worker 	do_xfer(uep, ufh, usb_msg_size, resp, resp_size ? *resp_size : 0, 1,
1683*4f2df630SAndroid Build Coastguard Worker 		resp_size);
1684*4f2df630SAndroid Build Coastguard Worker 
1685*4f2df630SAndroid Build Coastguard Worker 	free(ufh);
1686*4f2df630SAndroid Build Coastguard Worker 	return 0;
1687*4f2df630SAndroid Build Coastguard Worker }
1688*4f2df630SAndroid Build Coastguard Worker 
1689*4f2df630SAndroid Build Coastguard Worker /*
1690*4f2df630SAndroid Build Coastguard Worker  * Old cr50 images fail the update if sections are sent out of order. They
1691*4f2df630SAndroid Build Coastguard Worker  * require each block to have an offset greater than the block that was sent
1692*4f2df630SAndroid Build Coastguard Worker  * before. RO has a lower offset than RW, so old cr50 images reject RO if it's
1693*4f2df630SAndroid Build Coastguard Worker  * sent right after RW.
1694*4f2df630SAndroid Build Coastguard Worker  * This offset restriction expires after 60 seconds. Delay the RO update long
1695*4f2df630SAndroid Build Coastguard Worker  * enough for cr50 to not care that it has a lower offset than RW.
1696*4f2df630SAndroid Build Coastguard Worker  *
1697*4f2df630SAndroid Build Coastguard Worker  * Make the delay 65 seconds instead of 60 to cover differences in the speed of
1698*4f2df630SAndroid Build Coastguard Worker  * H1's clock and the host clock.
1699*4f2df630SAndroid Build Coastguard Worker  */
1700*4f2df630SAndroid Build Coastguard Worker #define NEXT_SECTION_DELAY 65
1701*4f2df630SAndroid Build Coastguard Worker 
1702*4f2df630SAndroid Build Coastguard Worker /*
1703*4f2df630SAndroid Build Coastguard Worker  * H1 support for flashing RO immediately after RW added in 0.3.20/0.4.20.
1704*4f2df630SAndroid Build Coastguard Worker  * D2 support exists in all versions.
1705*4f2df630SAndroid Build Coastguard Worker  * NT support exists in all versions.
1706*4f2df630SAndroid Build Coastguard Worker  */
supports_reordered_section_updates(struct signed_header_version * rw)1707*4f2df630SAndroid Build Coastguard Worker static int supports_reordered_section_updates(struct signed_header_version *rw)
1708*4f2df630SAndroid Build Coastguard Worker {
1709*4f2df630SAndroid Build Coastguard Worker 	switch (gsc_dev) {
1710*4f2df630SAndroid Build Coastguard Worker 	case GSC_DEVICE_H1:
1711*4f2df630SAndroid Build Coastguard Worker 		return (rw->epoch || rw->major > 4 ||
1712*4f2df630SAndroid Build Coastguard Worker 			(rw->major >= 3 && rw->minor >= 20));
1713*4f2df630SAndroid Build Coastguard Worker 	case GSC_DEVICE_DT:
1714*4f2df630SAndroid Build Coastguard Worker 		return true;
1715*4f2df630SAndroid Build Coastguard Worker 	case GSC_DEVICE_NT:
1716*4f2df630SAndroid Build Coastguard Worker 		return true;
1717*4f2df630SAndroid Build Coastguard Worker 	default:
1718*4f2df630SAndroid Build Coastguard Worker 		return false;
1719*4f2df630SAndroid Build Coastguard Worker 	}
1720*4f2df630SAndroid Build Coastguard Worker }
1721*4f2df630SAndroid Build Coastguard Worker 
1722*4f2df630SAndroid Build Coastguard Worker /* Returns number of successfully transmitted image sections. */
transfer_image(struct transfer_descriptor * td,struct image * image)1723*4f2df630SAndroid Build Coastguard Worker static int transfer_image(struct transfer_descriptor *td, struct image *image)
1724*4f2df630SAndroid Build Coastguard Worker {
1725*4f2df630SAndroid Build Coastguard Worker 	size_t i;
1726*4f2df630SAndroid Build Coastguard Worker 	int num_txed_sections = 0;
1727*4f2df630SAndroid Build Coastguard Worker 	int needs_delay = !supports_reordered_section_updates(&targ.shv[1]);
1728*4f2df630SAndroid Build Coastguard Worker 	struct section_t *sections = image->sections;
1729*4f2df630SAndroid Build Coastguard Worker 
1730*4f2df630SAndroid Build Coastguard Worker 	/*
1731*4f2df630SAndroid Build Coastguard Worker 	 * In case both RO and RW updates are required, make sure the RW
1732*4f2df630SAndroid Build Coastguard Worker 	 * section is updated before the RO. The array below keeps sections
1733*4f2df630SAndroid Build Coastguard Worker 	 * offsets in the required order.
1734*4f2df630SAndroid Build Coastguard Worker 	 */
1735*4f2df630SAndroid Build Coastguard Worker 	const enum section update_order[] = { RW_A, RW_B, RO_A, RO_B };
1736*4f2df630SAndroid Build Coastguard Worker 
1737*4f2df630SAndroid Build Coastguard Worker 	/* Now that we have an active connection and an image, pick sections */
1738*4f2df630SAndroid Build Coastguard Worker 	pick_sections(td, image);
1739*4f2df630SAndroid Build Coastguard Worker 	for (i = 0; i < ARRAY_SIZE(update_order); i++) {
1740*4f2df630SAndroid Build Coastguard Worker 		const enum section sect = update_order[i];
1741*4f2df630SAndroid Build Coastguard Worker 
1742*4f2df630SAndroid Build Coastguard Worker 		if (!sections[sect].update_needed)
1743*4f2df630SAndroid Build Coastguard Worker 			continue;
1744*4f2df630SAndroid Build Coastguard Worker 		if (num_txed_sections && needs_delay) {
1745*4f2df630SAndroid Build Coastguard Worker 			/*
1746*4f2df630SAndroid Build Coastguard Worker 			 * Delays more than 5 seconds cause the update
1747*4f2df630SAndroid Build Coastguard Worker 			 * to timeout. End the update before the delay
1748*4f2df630SAndroid Build Coastguard Worker 			 * and set it up after to recover from the
1749*4f2df630SAndroid Build Coastguard Worker 			 * timeout.
1750*4f2df630SAndroid Build Coastguard Worker 			 */
1751*4f2df630SAndroid Build Coastguard Worker 			if (td->ep_type == usb_xfer)
1752*4f2df630SAndroid Build Coastguard Worker 				send_done(&td->uep);
1753*4f2df630SAndroid Build Coastguard Worker 			printf("Waiting %ds for %s update.\n",
1754*4f2df630SAndroid Build Coastguard Worker 			       NEXT_SECTION_DELAY, SECTION_NAMES[sect]);
1755*4f2df630SAndroid Build Coastguard Worker 			sleep(NEXT_SECTION_DELAY);
1756*4f2df630SAndroid Build Coastguard Worker 			setup_connection(td);
1757*4f2df630SAndroid Build Coastguard Worker 			/* Pick sections again in case GSC versions changed. */
1758*4f2df630SAndroid Build Coastguard Worker 			pick_sections(td, image);
1759*4f2df630SAndroid Build Coastguard Worker 		}
1760*4f2df630SAndroid Build Coastguard Worker 
1761*4f2df630SAndroid Build Coastguard Worker 		transfer_section(td, image->data + sections[sect].offset,
1762*4f2df630SAndroid Build Coastguard Worker 				 sections[sect].offset, sections[sect].size);
1763*4f2df630SAndroid Build Coastguard Worker 		num_txed_sections++;
1764*4f2df630SAndroid Build Coastguard Worker 	}
1765*4f2df630SAndroid Build Coastguard Worker 
1766*4f2df630SAndroid Build Coastguard Worker 	if (!num_txed_sections)
1767*4f2df630SAndroid Build Coastguard Worker 		printf("nothing to do\n");
1768*4f2df630SAndroid Build Coastguard Worker 	else
1769*4f2df630SAndroid Build Coastguard Worker 		printf("-------\nupdate complete\n");
1770*4f2df630SAndroid Build Coastguard Worker 	return num_txed_sections;
1771*4f2df630SAndroid Build Coastguard Worker }
1772*4f2df630SAndroid Build Coastguard Worker 
send_vendor_command(struct transfer_descriptor * td,uint16_t subcommand,const void * command_body,size_t command_body_size,void * response,size_t * response_size)1773*4f2df630SAndroid Build Coastguard Worker uint32_t send_vendor_command(struct transfer_descriptor *td,
1774*4f2df630SAndroid Build Coastguard Worker 			     uint16_t subcommand, const void *command_body,
1775*4f2df630SAndroid Build Coastguard Worker 			     size_t command_body_size, void *response,
1776*4f2df630SAndroid Build Coastguard Worker 			     size_t *response_size)
1777*4f2df630SAndroid Build Coastguard Worker {
1778*4f2df630SAndroid Build Coastguard Worker 	int32_t rv;
1779*4f2df630SAndroid Build Coastguard Worker 
1780*4f2df630SAndroid Build Coastguard Worker 	if (td->ep_type == usb_xfer) {
1781*4f2df630SAndroid Build Coastguard Worker 		/*
1782*4f2df630SAndroid Build Coastguard Worker 		 * When communicating over USB the response is always supposed
1783*4f2df630SAndroid Build Coastguard Worker 		 * to have the result code in the first byte of the response,
1784*4f2df630SAndroid Build Coastguard Worker 		 * to be stripped from the actual response body by this
1785*4f2df630SAndroid Build Coastguard Worker 		 * function.
1786*4f2df630SAndroid Build Coastguard Worker 		 */
1787*4f2df630SAndroid Build Coastguard Worker 		uint8_t temp_response[MAX_RX_BUF_SIZE];
1788*4f2df630SAndroid Build Coastguard Worker 		size_t max_response_size;
1789*4f2df630SAndroid Build Coastguard Worker 
1790*4f2df630SAndroid Build Coastguard Worker 		if (!response_size) {
1791*4f2df630SAndroid Build Coastguard Worker 			max_response_size = 1;
1792*4f2df630SAndroid Build Coastguard Worker 		} else if (*response_size < (sizeof(temp_response))) {
1793*4f2df630SAndroid Build Coastguard Worker 			max_response_size = *response_size + 1;
1794*4f2df630SAndroid Build Coastguard Worker 		} else {
1795*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr,
1796*4f2df630SAndroid Build Coastguard Worker 				"Error: Expected response too large (%zd)\n",
1797*4f2df630SAndroid Build Coastguard Worker 				*response_size);
1798*4f2df630SAndroid Build Coastguard Worker 			/* Should happen only when debugging. */
1799*4f2df630SAndroid Build Coastguard Worker 			exit(update_error);
1800*4f2df630SAndroid Build Coastguard Worker 		}
1801*4f2df630SAndroid Build Coastguard Worker 
1802*4f2df630SAndroid Build Coastguard Worker 		ext_cmd_over_usb(&td->uep, subcommand, command_body,
1803*4f2df630SAndroid Build Coastguard Worker 				 command_body_size, temp_response,
1804*4f2df630SAndroid Build Coastguard Worker 				 &max_response_size);
1805*4f2df630SAndroid Build Coastguard Worker 		if (!max_response_size) {
1806*4f2df630SAndroid Build Coastguard Worker 			/*
1807*4f2df630SAndroid Build Coastguard Worker 			 * we must be talking to an older Cr50 firmware, which
1808*4f2df630SAndroid Build Coastguard Worker 			 * does not return the result code in the first byte
1809*4f2df630SAndroid Build Coastguard Worker 			 * on success, nothing to do.
1810*4f2df630SAndroid Build Coastguard Worker 			 */
1811*4f2df630SAndroid Build Coastguard Worker 			if (response_size)
1812*4f2df630SAndroid Build Coastguard Worker 				*response_size = 0;
1813*4f2df630SAndroid Build Coastguard Worker 			rv = 0;
1814*4f2df630SAndroid Build Coastguard Worker 		} else {
1815*4f2df630SAndroid Build Coastguard Worker 			rv = temp_response[0];
1816*4f2df630SAndroid Build Coastguard Worker 			if (response_size) {
1817*4f2df630SAndroid Build Coastguard Worker 				*response_size = max_response_size - 1;
1818*4f2df630SAndroid Build Coastguard Worker 				memcpy(response, temp_response + 1,
1819*4f2df630SAndroid Build Coastguard Worker 				       *response_size);
1820*4f2df630SAndroid Build Coastguard Worker 			}
1821*4f2df630SAndroid Build Coastguard Worker 		}
1822*4f2df630SAndroid Build Coastguard Worker 	} else {
1823*4f2df630SAndroid Build Coastguard Worker 		rv = tpm_send_pkt(td, 0, 0, command_body, command_body_size,
1824*4f2df630SAndroid Build Coastguard Worker 				  response, response_size, subcommand);
1825*4f2df630SAndroid Build Coastguard Worker 
1826*4f2df630SAndroid Build Coastguard Worker 		if (rv == -1) {
1827*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr,
1828*4f2df630SAndroid Build Coastguard Worker 				"Error: Failed to send vendor command %d\n",
1829*4f2df630SAndroid Build Coastguard Worker 				subcommand);
1830*4f2df630SAndroid Build Coastguard Worker 			exit(update_error);
1831*4f2df630SAndroid Build Coastguard Worker 		}
1832*4f2df630SAndroid Build Coastguard Worker 	}
1833*4f2df630SAndroid Build Coastguard Worker 
1834*4f2df630SAndroid Build Coastguard Worker 	return rv; /* This will be converted into uint32_t */
1835*4f2df630SAndroid Build Coastguard Worker }
1836*4f2df630SAndroid Build Coastguard Worker 
1837*4f2df630SAndroid Build Coastguard Worker /*
1838*4f2df630SAndroid Build Coastguard Worker  * Corrupt the header of the inactive rw image to make sure the system can't
1839*4f2df630SAndroid Build Coastguard Worker  * rollback
1840*4f2df630SAndroid Build Coastguard Worker  */
invalidate_inactive_rw(struct transfer_descriptor * td)1841*4f2df630SAndroid Build Coastguard Worker static void invalidate_inactive_rw(struct transfer_descriptor *td)
1842*4f2df630SAndroid Build Coastguard Worker {
1843*4f2df630SAndroid Build Coastguard Worker 	/* Corrupt the rw image that is not running. */
1844*4f2df630SAndroid Build Coastguard Worker 	uint32_t rv;
1845*4f2df630SAndroid Build Coastguard Worker 
1846*4f2df630SAndroid Build Coastguard Worker 	rv = send_vendor_command(td, VENDOR_CC_INVALIDATE_INACTIVE_RW, NULL, 0,
1847*4f2df630SAndroid Build Coastguard Worker 				 NULL, NULL);
1848*4f2df630SAndroid Build Coastguard Worker 	if (!rv) {
1849*4f2df630SAndroid Build Coastguard Worker 		printf("Inactive header invalidated\n");
1850*4f2df630SAndroid Build Coastguard Worker 		return;
1851*4f2df630SAndroid Build Coastguard Worker 	}
1852*4f2df630SAndroid Build Coastguard Worker 
1853*4f2df630SAndroid Build Coastguard Worker 	fprintf(stderr, "*%s: Error %#x\n", __func__, rv);
1854*4f2df630SAndroid Build Coastguard Worker 	exit(update_error);
1855*4f2df630SAndroid Build Coastguard Worker }
1856*4f2df630SAndroid Build Coastguard Worker 
1857*4f2df630SAndroid Build Coastguard Worker /*
1858*4f2df630SAndroid Build Coastguard Worker  * Try setting CCD capability.
1859*4f2df630SAndroid Build Coastguard Worker  *
1860*4f2df630SAndroid Build Coastguard Worker  * The 'parameter' string includes capability and desired new state separated
1861*4f2df630SAndroid Build Coastguard Worker  * by a ':', both parts could be abbreviated and checked for the match as case
1862*4f2df630SAndroid Build Coastguard Worker  * insensitive.
1863*4f2df630SAndroid Build Coastguard Worker  *
1864*4f2df630SAndroid Build Coastguard Worker  * The result of the attempt depends on the policies installed on
1865*4f2df630SAndroid Build Coastguard Worker  * Ti50. The result could be on of the following:
1866*4f2df630SAndroid Build Coastguard Worker  *
1867*4f2df630SAndroid Build Coastguard Worker  * - success (capability is successfully changed, or is already at the
1868*4f2df630SAndroid Build Coastguard Worker  *   requested level),
1869*4f2df630SAndroid Build Coastguard Worker  * - various errors if setting the capability is not allowed or something
1870*4f2df630SAndroid Build Coastguard Worker  *   goes wrong on Ti50
1871*4f2df630SAndroid Build Coastguard Worker  * - request for physical presence confirmation
1872*4f2df630SAndroid Build Coastguard Worker  */
process_set_capabililty(struct transfer_descriptor * td,const char * parameter)1873*4f2df630SAndroid Build Coastguard Worker static enum exit_values process_set_capabililty(struct transfer_descriptor *td,
1874*4f2df630SAndroid Build Coastguard Worker 						const char *parameter)
1875*4f2df630SAndroid Build Coastguard Worker {
1876*4f2df630SAndroid Build Coastguard Worker 	const char *colon;
1877*4f2df630SAndroid Build Coastguard Worker 	size_t len;
1878*4f2df630SAndroid Build Coastguard Worker 	size_t cap_index;
1879*4f2df630SAndroid Build Coastguard Worker 	size_t i;
1880*4f2df630SAndroid Build Coastguard Worker 	uint8_t rc;
1881*4f2df630SAndroid Build Coastguard Worker 	const char *error_text;
1882*4f2df630SAndroid Build Coastguard Worker 	const char *cr50_err =
1883*4f2df630SAndroid Build Coastguard Worker 		"Note: setting capabilities not available on Cr50\n";
1884*4f2df630SAndroid Build Coastguard Worker 	/*
1885*4f2df630SAndroid Build Coastguard Worker 	 * The payload is three bytes, command version, capability, and
1886*4f2df630SAndroid Build Coastguard Worker 	 * desired state, all expressed as u8.
1887*4f2df630SAndroid Build Coastguard Worker 	 */
1888*4f2df630SAndroid Build Coastguard Worker 	struct __attribute__((__packed__)) {
1889*4f2df630SAndroid Build Coastguard Worker 		uint8_t version;
1890*4f2df630SAndroid Build Coastguard Worker 		uint8_t cap;
1891*4f2df630SAndroid Build Coastguard Worker 		uint8_t value;
1892*4f2df630SAndroid Build Coastguard Worker 	} command;
1893*4f2df630SAndroid Build Coastguard Worker 	/*
1894*4f2df630SAndroid Build Coastguard Worker 	 * Translation table of possible desired capabilities, Cr50 values
1895*4f2df630SAndroid Build Coastguard Worker 	 * and duplicated in common/syscalls/src/ccd.rs::CcdCapState.
1896*4f2df630SAndroid Build Coastguard Worker 	 */
1897*4f2df630SAndroid Build Coastguard Worker 	struct {
1898*4f2df630SAndroid Build Coastguard Worker 		const char *state_name;
1899*4f2df630SAndroid Build Coastguard Worker 		enum ccd_capability_state desired_state;
1900*4f2df630SAndroid Build Coastguard Worker 	} states[] = {
1901*4f2df630SAndroid Build Coastguard Worker 		{ "default", CCD_CAP_STATE_DEFAULT },
1902*4f2df630SAndroid Build Coastguard Worker 		{ "always", CCD_CAP_STATE_ALWAYS },
1903*4f2df630SAndroid Build Coastguard Worker 		{ "if_opened", CCD_CAP_STATE_IF_OPENED },
1904*4f2df630SAndroid Build Coastguard Worker 	};
1905*4f2df630SAndroid Build Coastguard Worker 
1906*4f2df630SAndroid Build Coastguard Worker 	/*
1907*4f2df630SAndroid Build Coastguard Worker 	 * Possible responses from Ti50 when trying to modify AllowUnverifiedRo
1908*4f2df630SAndroid Build Coastguard Worker 	 * capability. The values come from
1909*4f2df630SAndroid Build Coastguard Worker 	 * common/libs/tpm2/extension/src/lib.rs::TpmvReturnCode.
1910*4f2df630SAndroid Build Coastguard Worker 	 */
1911*4f2df630SAndroid Build Coastguard Worker 	enum set_allow_unverified_ro_responses {
1912*4f2df630SAndroid Build Coastguard Worker 		AUR_SUCCESS = 0,
1913*4f2df630SAndroid Build Coastguard Worker 		AUR_BOGUS_ARGS = 1,
1914*4f2df630SAndroid Build Coastguard Worker 		AUR_INTERNAL_ERROR = 6,
1915*4f2df630SAndroid Build Coastguard Worker 		AUR_NOT_ALLOWED = 7,
1916*4f2df630SAndroid Build Coastguard Worker 		AUR_IN_PROGRESS = 9,
1917*4f2df630SAndroid Build Coastguard Worker 	};
1918*4f2df630SAndroid Build Coastguard Worker 
1919*4f2df630SAndroid Build Coastguard Worker 	/*
1920*4f2df630SAndroid Build Coastguard Worker 	 * Validate the parameter, for starters make sure that the colon
1921*4f2df630SAndroid Build Coastguard Worker 	 * symbol is present and is neither the first nor the last character
1922*4f2df630SAndroid Build Coastguard Worker 	 * in the string.
1923*4f2df630SAndroid Build Coastguard Worker 	 */
1924*4f2df630SAndroid Build Coastguard Worker 	colon = strchr(parameter, ':');
1925*4f2df630SAndroid Build Coastguard Worker 	if (!colon || (colon == parameter) || (colon[1] == '\0')) {
1926*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Misformatted capability parameter: %s\n",
1927*4f2df630SAndroid Build Coastguard Worker 			parameter);
1928*4f2df630SAndroid Build Coastguard Worker 		exit(update_error);
1929*4f2df630SAndroid Build Coastguard Worker 	}
1930*4f2df630SAndroid Build Coastguard Worker 
1931*4f2df630SAndroid Build Coastguard Worker 	/*
1932*4f2df630SAndroid Build Coastguard Worker 	 * Find the capability index in the table, reject ambiguous
1933*4f2df630SAndroid Build Coastguard Worker 	 * abbreviations.
1934*4f2df630SAndroid Build Coastguard Worker 	 */
1935*4f2df630SAndroid Build Coastguard Worker 	len = colon - parameter;
1936*4f2df630SAndroid Build Coastguard Worker 	for (i = 0, cap_index = ARRAY_SIZE(ti50_cap_info);
1937*4f2df630SAndroid Build Coastguard Worker 	     i < ARRAY_SIZE(ti50_cap_info); i++) {
1938*4f2df630SAndroid Build Coastguard Worker 		if (!strncasecmp(ti50_cap_info[i].name, parameter, len)) {
1939*4f2df630SAndroid Build Coastguard Worker 			if (cap_index != ARRAY_SIZE(ti50_cap_info)) {
1940*4f2df630SAndroid Build Coastguard Worker 				fprintf(stderr, "Ambiguous capability name\n");
1941*4f2df630SAndroid Build Coastguard Worker 				exit(update_error);
1942*4f2df630SAndroid Build Coastguard Worker 			}
1943*4f2df630SAndroid Build Coastguard Worker 			cap_index = i;
1944*4f2df630SAndroid Build Coastguard Worker 		}
1945*4f2df630SAndroid Build Coastguard Worker 	}
1946*4f2df630SAndroid Build Coastguard Worker 	if (cap_index == ARRAY_SIZE(ti50_cap_info)) {
1947*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Unknown capability name\n%s", cr50_err);
1948*4f2df630SAndroid Build Coastguard Worker 		exit(update_error);
1949*4f2df630SAndroid Build Coastguard Worker 	}
1950*4f2df630SAndroid Build Coastguard Worker 
1951*4f2df630SAndroid Build Coastguard Worker 	/* Calculate length of the desired value. */
1952*4f2df630SAndroid Build Coastguard Worker 	len = strlen(parameter) - len - 1;
1953*4f2df630SAndroid Build Coastguard Worker 
1954*4f2df630SAndroid Build Coastguard Worker 	/* Find the value index in the table. */
1955*4f2df630SAndroid Build Coastguard Worker 	for (i = 0; i < ARRAY_SIZE(states); i++) {
1956*4f2df630SAndroid Build Coastguard Worker 		if (!strncasecmp(states[i].state_name, colon + 1, len))
1957*4f2df630SAndroid Build Coastguard Worker 			break;
1958*4f2df630SAndroid Build Coastguard Worker 	}
1959*4f2df630SAndroid Build Coastguard Worker 	if (i == ARRAY_SIZE(states)) {
1960*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Unsupported capability value\n");
1961*4f2df630SAndroid Build Coastguard Worker 		return update_error;
1962*4f2df630SAndroid Build Coastguard Worker 	}
1963*4f2df630SAndroid Build Coastguard Worker 
1964*4f2df630SAndroid Build Coastguard Worker 	/* Prepare and send vendor command to request setting capability. */
1965*4f2df630SAndroid Build Coastguard Worker 	command.version = CCD_VERSION;
1966*4f2df630SAndroid Build Coastguard Worker 	command.cap = (uint8_t)cap_index;
1967*4f2df630SAndroid Build Coastguard Worker 	command.value = (uint8_t)states[i].desired_state;
1968*4f2df630SAndroid Build Coastguard Worker 
1969*4f2df630SAndroid Build Coastguard Worker 	i = 0;
1970*4f2df630SAndroid Build Coastguard Worker 	len = 1;
1971*4f2df630SAndroid Build Coastguard Worker 	send_vendor_command(td, VENDOR_CC_SET_CAPABILITY, &command,
1972*4f2df630SAndroid Build Coastguard Worker 			    sizeof(command), &rc, &len);
1973*4f2df630SAndroid Build Coastguard Worker 
1974*4f2df630SAndroid Build Coastguard Worker 	if (len != 1) {
1975*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Unexpected return message size %zd\n", len);
1976*4f2df630SAndroid Build Coastguard Worker 		if (len == 0)
1977*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr, "%s", cr50_err);
1978*4f2df630SAndroid Build Coastguard Worker 		return update_error;
1979*4f2df630SAndroid Build Coastguard Worker 	}
1980*4f2df630SAndroid Build Coastguard Worker 
1981*4f2df630SAndroid Build Coastguard Worker 	switch (rc) {
1982*4f2df630SAndroid Build Coastguard Worker 	case AUR_IN_PROGRESS:
1983*4f2df630SAndroid Build Coastguard Worker 		/*
1984*4f2df630SAndroid Build Coastguard Worker 		 * Physical presence poll is required, note fall through to
1985*4f2df630SAndroid Build Coastguard Worker 		 * the next case.
1986*4f2df630SAndroid Build Coastguard Worker 		 */
1987*4f2df630SAndroid Build Coastguard Worker 		poll_for_pp(td, VENDOR_CC_CCD, CCDV_PP_POLL_SET_CAPABILITY);
1988*4f2df630SAndroid Build Coastguard Worker 	case AUR_SUCCESS:
1989*4f2df630SAndroid Build Coastguard Worker 		return noop; /* All is well, no need to do anything. */
1990*4f2df630SAndroid Build Coastguard Worker 	case AUR_BOGUS_ARGS:
1991*4f2df630SAndroid Build Coastguard Worker 		error_text = "BogusArgs";
1992*4f2df630SAndroid Build Coastguard Worker 		break;
1993*4f2df630SAndroid Build Coastguard Worker 	case AUR_INTERNAL_ERROR:
1994*4f2df630SAndroid Build Coastguard Worker 		error_text = "InternalError";
1995*4f2df630SAndroid Build Coastguard Worker 		break;
1996*4f2df630SAndroid Build Coastguard Worker 	case AUR_NOT_ALLOWED:
1997*4f2df630SAndroid Build Coastguard Worker 		error_text = "NotAllowed";
1998*4f2df630SAndroid Build Coastguard Worker 		break;
1999*4f2df630SAndroid Build Coastguard Worker 	default:
2000*4f2df630SAndroid Build Coastguard Worker 		error_text = "Unknown";
2001*4f2df630SAndroid Build Coastguard Worker 		break;
2002*4f2df630SAndroid Build Coastguard Worker 	}
2003*4f2df630SAndroid Build Coastguard Worker 	fprintf(stderr, "Got error %d(%s)\n", rc, error_text);
2004*4f2df630SAndroid Build Coastguard Worker 	return update_error;
2005*4f2df630SAndroid Build Coastguard Worker }
2006*4f2df630SAndroid Build Coastguard Worker 
process_erase_ap_ro_hash(struct transfer_descriptor * td)2007*4f2df630SAndroid Build Coastguard Worker static void process_erase_ap_ro_hash(struct transfer_descriptor *td)
2008*4f2df630SAndroid Build Coastguard Worker {
2009*4f2df630SAndroid Build Coastguard Worker 	/* Try erasing AP RO hash, could fail if board ID is programmed. */
2010*4f2df630SAndroid Build Coastguard Worker 	uint32_t rv;
2011*4f2df630SAndroid Build Coastguard Worker 	uint8_t response;
2012*4f2df630SAndroid Build Coastguard Worker 	size_t response_size;
2013*4f2df630SAndroid Build Coastguard Worker 	char error_details[64];
2014*4f2df630SAndroid Build Coastguard Worker 
2015*4f2df630SAndroid Build Coastguard Worker 	response_size = sizeof(response);
2016*4f2df630SAndroid Build Coastguard Worker 	rv = send_vendor_command(td, VENDOR_CC_SEED_AP_RO_CHECK, NULL, 0,
2017*4f2df630SAndroid Build Coastguard Worker 				 &response, &response_size);
2018*4f2df630SAndroid Build Coastguard Worker 	if (!rv) {
2019*4f2df630SAndroid Build Coastguard Worker 		printf("AP RO hash erased\n");
2020*4f2df630SAndroid Build Coastguard Worker 		exit(0);
2021*4f2df630SAndroid Build Coastguard Worker 	}
2022*4f2df630SAndroid Build Coastguard Worker 
2023*4f2df630SAndroid Build Coastguard Worker 	if (response_size == sizeof(response)) {
2024*4f2df630SAndroid Build Coastguard Worker 		switch (response) {
2025*4f2df630SAndroid Build Coastguard Worker 		case ARCVE_FLASH_ERASE_FAILED:
2026*4f2df630SAndroid Build Coastguard Worker 			snprintf(error_details, sizeof(error_details),
2027*4f2df630SAndroid Build Coastguard Worker 				 "erase failure");
2028*4f2df630SAndroid Build Coastguard Worker 			break;
2029*4f2df630SAndroid Build Coastguard Worker 		case ARCVE_BID_PROGRAMMED:
2030*4f2df630SAndroid Build Coastguard Worker 			snprintf(error_details, sizeof(error_details),
2031*4f2df630SAndroid Build Coastguard Worker 				 "BID already programmed");
2032*4f2df630SAndroid Build Coastguard Worker 			break;
2033*4f2df630SAndroid Build Coastguard Worker 		default:
2034*4f2df630SAndroid Build Coastguard Worker 			snprintf(error_details, sizeof(error_details),
2035*4f2df630SAndroid Build Coastguard Worker 				 "Unexpected error rc %d, response %d", rv,
2036*4f2df630SAndroid Build Coastguard Worker 				 response);
2037*4f2df630SAndroid Build Coastguard Worker 			break;
2038*4f2df630SAndroid Build Coastguard Worker 		}
2039*4f2df630SAndroid Build Coastguard Worker 	} else {
2040*4f2df630SAndroid Build Coastguard Worker 		snprintf(error_details, sizeof(error_details),
2041*4f2df630SAndroid Build Coastguard Worker 			 "misconfigured response, rc=%d, size %zd", rv,
2042*4f2df630SAndroid Build Coastguard Worker 			 response_size);
2043*4f2df630SAndroid Build Coastguard Worker 	}
2044*4f2df630SAndroid Build Coastguard Worker 
2045*4f2df630SAndroid Build Coastguard Worker 	fprintf(stderr, "Error: %s\n", error_details);
2046*4f2df630SAndroid Build Coastguard Worker 
2047*4f2df630SAndroid Build Coastguard Worker 	exit(update_error);
2048*4f2df630SAndroid Build Coastguard Worker }
2049*4f2df630SAndroid Build Coastguard Worker 
generate_reset_request(struct transfer_descriptor * td)2050*4f2df630SAndroid Build Coastguard Worker static void generate_reset_request(struct transfer_descriptor *td)
2051*4f2df630SAndroid Build Coastguard Worker {
2052*4f2df630SAndroid Build Coastguard Worker 	size_t response_size;
2053*4f2df630SAndroid Build Coastguard Worker 	uint8_t response;
2054*4f2df630SAndroid Build Coastguard Worker 	uint16_t subcommand;
2055*4f2df630SAndroid Build Coastguard Worker 	uint8_t command_body[2]; /* Max command body size. */
2056*4f2df630SAndroid Build Coastguard Worker 	size_t command_body_size;
2057*4f2df630SAndroid Build Coastguard Worker 	const char *reset_type;
2058*4f2df630SAndroid Build Coastguard Worker 	int rv;
2059*4f2df630SAndroid Build Coastguard Worker 
2060*4f2df630SAndroid Build Coastguard Worker 	if (protocol_version < 6) {
2061*4f2df630SAndroid Build Coastguard Worker 		if (td->ep_type == usb_xfer) {
2062*4f2df630SAndroid Build Coastguard Worker 			/*
2063*4f2df630SAndroid Build Coastguard Worker 			 * Send a second stop request, which should reboot
2064*4f2df630SAndroid Build Coastguard Worker 			 * without replying.
2065*4f2df630SAndroid Build Coastguard Worker 			 */
2066*4f2df630SAndroid Build Coastguard Worker 			send_done(&td->uep);
2067*4f2df630SAndroid Build Coastguard Worker 		}
2068*4f2df630SAndroid Build Coastguard Worker 		/* Nothing we can do over /dev/tpm0 running versions below 6. */
2069*4f2df630SAndroid Build Coastguard Worker 		return;
2070*4f2df630SAndroid Build Coastguard Worker 	}
2071*4f2df630SAndroid Build Coastguard Worker 
2072*4f2df630SAndroid Build Coastguard Worker 	/*
2073*4f2df630SAndroid Build Coastguard Worker 	 * If this is an upstart request, don't post a request now. The target
2074*4f2df630SAndroid Build Coastguard Worker 	 * should handle it on the next reboot.
2075*4f2df630SAndroid Build Coastguard Worker 	 */
2076*4f2df630SAndroid Build Coastguard Worker 	if (td->upstart_mode)
2077*4f2df630SAndroid Build Coastguard Worker 		return;
2078*4f2df630SAndroid Build Coastguard Worker 
2079*4f2df630SAndroid Build Coastguard Worker 	/*
2080*4f2df630SAndroid Build Coastguard Worker 	 * If the user explicitly wants it, request post reset instead of
2081*4f2df630SAndroid Build Coastguard Worker 	 * immediate reset. In this case next time the target reboots, the GSC
2082*4f2df630SAndroid Build Coastguard Worker 	 * will reboot as well, and will consider running the uploaded code.
2083*4f2df630SAndroid Build Coastguard Worker 	 *
2084*4f2df630SAndroid Build Coastguard Worker 	 * Otherwise, to reset the target the host is supposed to send the
2085*4f2df630SAndroid Build Coastguard Worker 	 * command to enable the uploaded image disabled by default.
2086*4f2df630SAndroid Build Coastguard Worker 	 */
2087*4f2df630SAndroid Build Coastguard Worker 	response_size = 1;
2088*4f2df630SAndroid Build Coastguard Worker 	if (td->post_reset) {
2089*4f2df630SAndroid Build Coastguard Worker 		subcommand = EXTENSION_POST_RESET;
2090*4f2df630SAndroid Build Coastguard Worker 		command_body_size = 0;
2091*4f2df630SAndroid Build Coastguard Worker 		reset_type = "posted";
2092*4f2df630SAndroid Build Coastguard Worker 	} else {
2093*4f2df630SAndroid Build Coastguard Worker 		subcommand = VENDOR_CC_TURN_UPDATE_ON;
2094*4f2df630SAndroid Build Coastguard Worker 		command_body_size = sizeof(command_body);
2095*4f2df630SAndroid Build Coastguard Worker 		command_body[0] = 0;
2096*4f2df630SAndroid Build Coastguard Worker 		command_body[1] = 100; /* Reset in 100 ms. */
2097*4f2df630SAndroid Build Coastguard Worker 		reset_type = "requested";
2098*4f2df630SAndroid Build Coastguard Worker 	}
2099*4f2df630SAndroid Build Coastguard Worker 
2100*4f2df630SAndroid Build Coastguard Worker 	rv = send_vendor_command(td, subcommand, command_body,
2101*4f2df630SAndroid Build Coastguard Worker 				 command_body_size, &response, &response_size);
2102*4f2df630SAndroid Build Coastguard Worker 
2103*4f2df630SAndroid Build Coastguard Worker 	if (rv) {
2104*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "*%s: Error %#x\n", __func__, rv);
2105*4f2df630SAndroid Build Coastguard Worker 		exit(update_error);
2106*4f2df630SAndroid Build Coastguard Worker 	}
2107*4f2df630SAndroid Build Coastguard Worker 	printf("reboot %s\n", reset_type);
2108*4f2df630SAndroid Build Coastguard Worker }
2109*4f2df630SAndroid Build Coastguard Worker 
2110*4f2df630SAndroid Build Coastguard Worker /* Forward to correct SHA implementation based on image type */
sha_init(EVP_MD_CTX * ctx)2111*4f2df630SAndroid Build Coastguard Worker static void sha_init(EVP_MD_CTX *ctx)
2112*4f2df630SAndroid Build Coastguard Worker {
2113*4f2df630SAndroid Build Coastguard Worker 	if (gsc_dev == GSC_DEVICE_H1)
2114*4f2df630SAndroid Build Coastguard Worker 		EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
2115*4f2df630SAndroid Build Coastguard Worker 	else if (gsc_dev == GSC_DEVICE_DT || gsc_dev == GSC_DEVICE_NT)
2116*4f2df630SAndroid Build Coastguard Worker 		EVP_DigestInit_ex(ctx, EVP_sha256(), NULL);
2117*4f2df630SAndroid Build Coastguard Worker 	else {
2118*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Error: unknown GSC device type\n");
2119*4f2df630SAndroid Build Coastguard Worker 		exit(update_error);
2120*4f2df630SAndroid Build Coastguard Worker 	}
2121*4f2df630SAndroid Build Coastguard Worker }
2122*4f2df630SAndroid Build Coastguard Worker 
2123*4f2df630SAndroid Build Coastguard Worker /* Forward to correct SHA implementation based on image type */
sha_update(EVP_MD_CTX * ctx,const void * data,size_t len)2124*4f2df630SAndroid Build Coastguard Worker static void sha_update(EVP_MD_CTX *ctx, const void *data, size_t len)
2125*4f2df630SAndroid Build Coastguard Worker {
2126*4f2df630SAndroid Build Coastguard Worker 	EVP_DigestUpdate(ctx, data, len);
2127*4f2df630SAndroid Build Coastguard Worker }
2128*4f2df630SAndroid Build Coastguard Worker 
2129*4f2df630SAndroid Build Coastguard Worker /* Forward to correct SHA implementation based on image type */
sha_final_into_block_digest(EVP_MD_CTX * ctx,void * block_digest,size_t size)2130*4f2df630SAndroid Build Coastguard Worker static void sha_final_into_block_digest(EVP_MD_CTX *ctx, void *block_digest,
2131*4f2df630SAndroid Build Coastguard Worker 					size_t size)
2132*4f2df630SAndroid Build Coastguard Worker {
2133*4f2df630SAndroid Build Coastguard Worker 	/* Big enough for either hash algo */
2134*4f2df630SAndroid Build Coastguard Worker 	uint8_t full_digest[SHA256_DIGEST_LENGTH];
2135*4f2df630SAndroid Build Coastguard Worker 	unsigned int length;
2136*4f2df630SAndroid Build Coastguard Worker 
2137*4f2df630SAndroid Build Coastguard Worker 	EVP_DigestFinal(ctx, full_digest, &length);
2138*4f2df630SAndroid Build Coastguard Worker 
2139*4f2df630SAndroid Build Coastguard Worker 	/* Copy out the smaller of the 2 byte counts. */
2140*4f2df630SAndroid Build Coastguard Worker 	memcpy(block_digest, full_digest, MIN(size, length));
2141*4f2df630SAndroid Build Coastguard Worker }
2142*4f2df630SAndroid Build Coastguard Worker 
2143*4f2df630SAndroid Build Coastguard Worker /*
2144*4f2df630SAndroid Build Coastguard Worker  * Machine output is formatted as "key=value", one key-value pair per line, and
2145*4f2df630SAndroid Build Coastguard Worker  * parsed by other programs (e.g., debugd). The value part should be specified
2146*4f2df630SAndroid Build Coastguard Worker  * in the printf-like way. For example:
2147*4f2df630SAndroid Build Coastguard Worker  *
2148*4f2df630SAndroid Build Coastguard Worker  *           print_machine_output("date", "%d/%d/%d", 2018, 1, 1),
2149*4f2df630SAndroid Build Coastguard Worker  *
2150*4f2df630SAndroid Build Coastguard Worker  * which outputs this line in console:
2151*4f2df630SAndroid Build Coastguard Worker  *
2152*4f2df630SAndroid Build Coastguard Worker  *           date=2018/1/1
2153*4f2df630SAndroid Build Coastguard Worker  *
2154*4f2df630SAndroid Build Coastguard Worker  * The key part should not contain '=' or newline. The value part may contain
2155*4f2df630SAndroid Build Coastguard Worker  * special characters like spaces, quotes, brackets, but not newlines. The
2156*4f2df630SAndroid Build Coastguard Worker  * newline character means end of value.
2157*4f2df630SAndroid Build Coastguard Worker  *
2158*4f2df630SAndroid Build Coastguard Worker  * Any output format change in this function may require similar changes on the
2159*4f2df630SAndroid Build Coastguard Worker  * programs that are using this gsctool.
2160*4f2df630SAndroid Build Coastguard Worker  */
print_machine_output(const char * key,const char * format,...)2161*4f2df630SAndroid Build Coastguard Worker __attribute__((__format__(__printf__, 2, 3))) static void print_machine_output(
2162*4f2df630SAndroid Build Coastguard Worker 	const char *key, const char *format, ...)
2163*4f2df630SAndroid Build Coastguard Worker {
2164*4f2df630SAndroid Build Coastguard Worker 	va_list args;
2165*4f2df630SAndroid Build Coastguard Worker 
2166*4f2df630SAndroid Build Coastguard Worker 	if (strchr(key, '=') != NULL || strchr(key, '\n') != NULL) {
2167*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr,
2168*4f2df630SAndroid Build Coastguard Worker 			"Error: key %s contains '=' or a newline character.\n",
2169*4f2df630SAndroid Build Coastguard Worker 			key);
2170*4f2df630SAndroid Build Coastguard Worker 		return;
2171*4f2df630SAndroid Build Coastguard Worker 	}
2172*4f2df630SAndroid Build Coastguard Worker 
2173*4f2df630SAndroid Build Coastguard Worker 	if (strchr(format, '\n') != NULL) {
2174*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr,
2175*4f2df630SAndroid Build Coastguard Worker 			"Error: value format %s contains a newline character. "
2176*4f2df630SAndroid Build Coastguard Worker 			"\n",
2177*4f2df630SAndroid Build Coastguard Worker 			format);
2178*4f2df630SAndroid Build Coastguard Worker 		return;
2179*4f2df630SAndroid Build Coastguard Worker 	}
2180*4f2df630SAndroid Build Coastguard Worker 
2181*4f2df630SAndroid Build Coastguard Worker 	va_start(args, format);
2182*4f2df630SAndroid Build Coastguard Worker 
2183*4f2df630SAndroid Build Coastguard Worker 	printf("%s=", key);
2184*4f2df630SAndroid Build Coastguard Worker 	vprintf(format, args);
2185*4f2df630SAndroid Build Coastguard Worker 	printf("\n");
2186*4f2df630SAndroid Build Coastguard Worker 
2187*4f2df630SAndroid Build Coastguard Worker 	va_end(args);
2188*4f2df630SAndroid Build Coastguard Worker }
2189*4f2df630SAndroid Build Coastguard Worker 
2190*4f2df630SAndroid Build Coastguard Worker /*
2191*4f2df630SAndroid Build Coastguard Worker  * Prints out the header, including FW versions and board IDs, of the given
2192*4f2df630SAndroid Build Coastguard Worker  * image. Output in a machine-friendly format if show_machine_output is true.
2193*4f2df630SAndroid Build Coastguard Worker  */
show_headers_versions(const struct image * image,bool show_machine_output)2194*4f2df630SAndroid Build Coastguard Worker static int show_headers_versions(const struct image *image,
2195*4f2df630SAndroid Build Coastguard Worker 				 bool show_machine_output)
2196*4f2df630SAndroid Build Coastguard Worker {
2197*4f2df630SAndroid Build Coastguard Worker 	/*
2198*4f2df630SAndroid Build Coastguard Worker 	 * There are 2 FW slots in an image, and each slot has 2 sections, RO
2199*4f2df630SAndroid Build Coastguard Worker 	 * and RW. The 2 slots should have identical FW versions and board
2200*4f2df630SAndroid Build Coastguard Worker 	 * IDs.
2201*4f2df630SAndroid Build Coastguard Worker 	 */
2202*4f2df630SAndroid Build Coastguard Worker 	const size_t kNumSlots = 2;
2203*4f2df630SAndroid Build Coastguard Worker 	const size_t kNumSectionsPerSlot = 2;
2204*4f2df630SAndroid Build Coastguard Worker 	const struct section_t *sections = image->sections;
2205*4f2df630SAndroid Build Coastguard Worker 
2206*4f2df630SAndroid Build Coastguard Worker 	/*
2207*4f2df630SAndroid Build Coastguard Worker 	 * String representation of FW version (<epoch>:<major>:<minor>), one
2208*4f2df630SAndroid Build Coastguard Worker 	 * string for each FW section.
2209*4f2df630SAndroid Build Coastguard Worker 	 */
2210*4f2df630SAndroid Build Coastguard Worker 	char ro_fw_ver[kNumSlots][MAX_FW_VER_LENGTH];
2211*4f2df630SAndroid Build Coastguard Worker 	char rw_fw_ver[kNumSlots][MAX_FW_VER_LENGTH];
2212*4f2df630SAndroid Build Coastguard Worker 
2213*4f2df630SAndroid Build Coastguard Worker 	uint32_t dev_id0_[kNumSlots];
2214*4f2df630SAndroid Build Coastguard Worker 	uint32_t dev_id1_[kNumSlots];
2215*4f2df630SAndroid Build Coastguard Worker 	uint32_t print_devid = 0;
2216*4f2df630SAndroid Build Coastguard Worker 
2217*4f2df630SAndroid Build Coastguard Worker 	struct board_id {
2218*4f2df630SAndroid Build Coastguard Worker 		uint32_t id;
2219*4f2df630SAndroid Build Coastguard Worker 		uint32_t mask;
2220*4f2df630SAndroid Build Coastguard Worker 		uint32_t flags;
2221*4f2df630SAndroid Build Coastguard Worker 	} bid[kNumSlots];
2222*4f2df630SAndroid Build Coastguard Worker 
2223*4f2df630SAndroid Build Coastguard Worker 	char bid_string[kNumSlots][MAX_BOARD_ID_LENGTH];
2224*4f2df630SAndroid Build Coastguard Worker 
2225*4f2df630SAndroid Build Coastguard Worker 	size_t i;
2226*4f2df630SAndroid Build Coastguard Worker 
2227*4f2df630SAndroid Build Coastguard Worker 	for (i = 0; i < NUM_SECTIONS; i++) {
2228*4f2df630SAndroid Build Coastguard Worker 		const struct typed_image_header h =
2229*4f2df630SAndroid Build Coastguard Worker 			as_header(image, sections[i].offset);
2230*4f2df630SAndroid Build Coastguard Worker 		const size_t slot_idx = i / kNumSectionsPerSlot;
2231*4f2df630SAndroid Build Coastguard Worker 
2232*4f2df630SAndroid Build Coastguard Worker 		uint32_t cur_bid;
2233*4f2df630SAndroid Build Coastguard Worker 		size_t j;
2234*4f2df630SAndroid Build Coastguard Worker 
2235*4f2df630SAndroid Build Coastguard Worker 		if (i == RO_A || i == RO_B) {
2236*4f2df630SAndroid Build Coastguard Worker 			/* RO. */
2237*4f2df630SAndroid Build Coastguard Worker 			snprintf(ro_fw_ver[slot_idx], MAX_FW_VER_LENGTH,
2238*4f2df630SAndroid Build Coastguard Worker 				 "%d.%d.%d", sections[i].shv.epoch,
2239*4f2df630SAndroid Build Coastguard Worker 				 sections[i].shv.major, sections[i].shv.minor);
2240*4f2df630SAndroid Build Coastguard Worker 			/* No need to read board ID in an RO section. */
2241*4f2df630SAndroid Build Coastguard Worker 			continue;
2242*4f2df630SAndroid Build Coastguard Worker 		} else {
2243*4f2df630SAndroid Build Coastguard Worker 			/* RW. */
2244*4f2df630SAndroid Build Coastguard Worker 			snprintf(rw_fw_ver[slot_idx], MAX_FW_VER_LENGTH,
2245*4f2df630SAndroid Build Coastguard Worker 				 "%d.%d.%d", sections[i].shv.epoch,
2246*4f2df630SAndroid Build Coastguard Worker 				 sections[i].shv.major, sections[i].shv.minor);
2247*4f2df630SAndroid Build Coastguard Worker 		}
2248*4f2df630SAndroid Build Coastguard Worker 
2249*4f2df630SAndroid Build Coastguard Worker 		/*
2250*4f2df630SAndroid Build Coastguard Worker 		 * For RW sections, retrieves the board ID fields' contents,
2251*4f2df630SAndroid Build Coastguard Worker 		 * which are stored XORed with a padding value.
2252*4f2df630SAndroid Build Coastguard Worker 		 */
2253*4f2df630SAndroid Build Coastguard Worker 		if (h.type == GSC_DEVICE_H1 || h.type == GSC_DEVICE_DT) {
2254*4f2df630SAndroid Build Coastguard Worker 			bid[slot_idx].id = h.h->board_id_type ^
2255*4f2df630SAndroid Build Coastguard Worker 					   SIGNED_HEADER_PADDING;
2256*4f2df630SAndroid Build Coastguard Worker 			bid[slot_idx].mask = h.h->board_id_type_mask ^
2257*4f2df630SAndroid Build Coastguard Worker 					     SIGNED_HEADER_PADDING;
2258*4f2df630SAndroid Build Coastguard Worker 			bid[slot_idx].flags = h.h->board_id_flags ^
2259*4f2df630SAndroid Build Coastguard Worker 					      SIGNED_HEADER_PADDING;
2260*4f2df630SAndroid Build Coastguard Worker 
2261*4f2df630SAndroid Build Coastguard Worker 			dev_id0_[slot_idx] = h.h->dev_id0_;
2262*4f2df630SAndroid Build Coastguard Worker 			dev_id1_[slot_idx] = h.h->dev_id1_;
2263*4f2df630SAndroid Build Coastguard Worker 		} else if (h.type == GSC_DEVICE_NT) {
2264*4f2df630SAndroid Build Coastguard Worker 			/*
2265*4f2df630SAndroid Build Coastguard Worker 			 * TODO(b/341348812): Get BID info from signed manifest
2266*4f2df630SAndroid Build Coastguard Worker 			 * header.
2267*4f2df630SAndroid Build Coastguard Worker 			 */
2268*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr, "BID info not support on NT yet.\n");
2269*4f2df630SAndroid Build Coastguard Worker 			bid[slot_idx].id = -1;
2270*4f2df630SAndroid Build Coastguard Worker 			bid[slot_idx].mask = -1;
2271*4f2df630SAndroid Build Coastguard Worker 			bid[slot_idx].flags = -1;
2272*4f2df630SAndroid Build Coastguard Worker 
2273*4f2df630SAndroid Build Coastguard Worker 			/* Check if devid constraints are being enforced */
2274*4f2df630SAndroid Build Coastguard Worker 			if (h.m->constraint_selector_bits & 0x6) {
2275*4f2df630SAndroid Build Coastguard Worker 				dev_id0_[slot_idx] =
2276*4f2df630SAndroid Build Coastguard Worker 					h.m->constraint_device_id[1];
2277*4f2df630SAndroid Build Coastguard Worker 				dev_id1_[slot_idx] =
2278*4f2df630SAndroid Build Coastguard Worker 					h.m->constraint_device_id[2];
2279*4f2df630SAndroid Build Coastguard Worker 			} else {
2280*4f2df630SAndroid Build Coastguard Worker 				dev_id0_[slot_idx] = 0;
2281*4f2df630SAndroid Build Coastguard Worker 				dev_id1_[slot_idx] = 0;
2282*4f2df630SAndroid Build Coastguard Worker 			}
2283*4f2df630SAndroid Build Coastguard Worker 		} else {
2284*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr, "\nERROR: Unknown image type.\n");
2285*4f2df630SAndroid Build Coastguard Worker 			exit(update_error);
2286*4f2df630SAndroid Build Coastguard Worker 		}
2287*4f2df630SAndroid Build Coastguard Worker 		/* Print the devid if any slot has a non-zero devid. */
2288*4f2df630SAndroid Build Coastguard Worker 		print_devid |= dev_id0_[slot_idx] | dev_id1_[slot_idx];
2289*4f2df630SAndroid Build Coastguard Worker 		/*
2290*4f2df630SAndroid Build Coastguard Worker 		 * If board ID is a 4-uppercase-letter string (as it ought to
2291*4f2df630SAndroid Build Coastguard Worker 		 * be), print it as 4 letters, otherwise print it as an 8-digit
2292*4f2df630SAndroid Build Coastguard Worker 		 * hex.
2293*4f2df630SAndroid Build Coastguard Worker 		 */
2294*4f2df630SAndroid Build Coastguard Worker 		cur_bid = bid[slot_idx].id;
2295*4f2df630SAndroid Build Coastguard Worker 		for (j = 0; j < sizeof(cur_bid); ++j)
2296*4f2df630SAndroid Build Coastguard Worker 			if (!isupper(((const char *)&cur_bid)[j]))
2297*4f2df630SAndroid Build Coastguard Worker 				break;
2298*4f2df630SAndroid Build Coastguard Worker 
2299*4f2df630SAndroid Build Coastguard Worker 		if (j == sizeof(cur_bid)) {
2300*4f2df630SAndroid Build Coastguard Worker 			cur_bid = be32toh(cur_bid);
2301*4f2df630SAndroid Build Coastguard Worker 			snprintf(bid_string[slot_idx], MAX_BOARD_ID_LENGTH,
2302*4f2df630SAndroid Build Coastguard Worker 				 "%.4s", (const char *)&cur_bid);
2303*4f2df630SAndroid Build Coastguard Worker 		} else {
2304*4f2df630SAndroid Build Coastguard Worker 			snprintf(bid_string[slot_idx], MAX_BOARD_ID_LENGTH,
2305*4f2df630SAndroid Build Coastguard Worker 				 "%08x", cur_bid);
2306*4f2df630SAndroid Build Coastguard Worker 		}
2307*4f2df630SAndroid Build Coastguard Worker 	}
2308*4f2df630SAndroid Build Coastguard Worker 
2309*4f2df630SAndroid Build Coastguard Worker 	if (show_machine_output) {
2310*4f2df630SAndroid Build Coastguard Worker 		print_machine_output("IMAGE_RO_FW_VER", "%s", ro_fw_ver[0]);
2311*4f2df630SAndroid Build Coastguard Worker 		print_machine_output("IMAGE_RW_FW_VER", "%s", rw_fw_ver[0]);
2312*4f2df630SAndroid Build Coastguard Worker 		print_machine_output("IMAGE_BID_STRING", "%s", bid_string[0]);
2313*4f2df630SAndroid Build Coastguard Worker 		print_machine_output("IMAGE_BID_MASK", "%08x", bid[0].mask);
2314*4f2df630SAndroid Build Coastguard Worker 		print_machine_output("IMAGE_BID_FLAGS", "%08x", bid[0].flags);
2315*4f2df630SAndroid Build Coastguard Worker 	} else {
2316*4f2df630SAndroid Build Coastguard Worker 		printf("RO_A:%s RW_A:%s[%s:%08x:%08x] ", ro_fw_ver[0],
2317*4f2df630SAndroid Build Coastguard Worker 		       rw_fw_ver[0], bid_string[0], bid[0].mask, bid[0].flags);
2318*4f2df630SAndroid Build Coastguard Worker 		printf("RO_B:%s RW_B:%s[%s:%08x:%08x]\n", ro_fw_ver[1],
2319*4f2df630SAndroid Build Coastguard Worker 		       rw_fw_ver[1], bid_string[1], bid[1].mask, bid[1].flags);
2320*4f2df630SAndroid Build Coastguard Worker 
2321*4f2df630SAndroid Build Coastguard Worker 		if (print_devid) {
2322*4f2df630SAndroid Build Coastguard Worker 			printf("DEVID: 0x%08x 0x%08x", dev_id0_[0],
2323*4f2df630SAndroid Build Coastguard Worker 			       dev_id1_[0]);
2324*4f2df630SAndroid Build Coastguard Worker 			/*
2325*4f2df630SAndroid Build Coastguard Worker 			 * Only print the second devid if it's different.
2326*4f2df630SAndroid Build Coastguard Worker 			 * Separate the devids with tabs, so it's easier to
2327*4f2df630SAndroid Build Coastguard Worker 			 * read.
2328*4f2df630SAndroid Build Coastguard Worker 			 */
2329*4f2df630SAndroid Build Coastguard Worker 			if (dev_id0_[0] != dev_id0_[1] ||
2330*4f2df630SAndroid Build Coastguard Worker 			    dev_id1_[0] != dev_id1_[1])
2331*4f2df630SAndroid Build Coastguard Worker 				printf("\t\t\t\tDEVID_B: 0x%08x 0x%08x",
2332*4f2df630SAndroid Build Coastguard Worker 				       dev_id0_[1], dev_id1_[1]);
2333*4f2df630SAndroid Build Coastguard Worker 			printf("\n");
2334*4f2df630SAndroid Build Coastguard Worker 		}
2335*4f2df630SAndroid Build Coastguard Worker 	}
2336*4f2df630SAndroid Build Coastguard Worker 
2337*4f2df630SAndroid Build Coastguard Worker 	return 0;
2338*4f2df630SAndroid Build Coastguard Worker }
2339*4f2df630SAndroid Build Coastguard Worker 
2340*4f2df630SAndroid Build Coastguard Worker /*
2341*4f2df630SAndroid Build Coastguard Worker  * The default flag value will allow to run images built for any hardware
2342*4f2df630SAndroid Build Coastguard Worker  * generation of a particular board ID.
2343*4f2df630SAndroid Build Coastguard Worker  */
2344*4f2df630SAndroid Build Coastguard Worker #define DEFAULT_BOARD_ID_FLAG 0xff00
parse_bid(const char * opt,struct board_id * bid,enum board_id_action * bid_action)2345*4f2df630SAndroid Build Coastguard Worker static int parse_bid(const char *opt, struct board_id *bid,
2346*4f2df630SAndroid Build Coastguard Worker 		     enum board_id_action *bid_action)
2347*4f2df630SAndroid Build Coastguard Worker {
2348*4f2df630SAndroid Build Coastguard Worker 	char *e;
2349*4f2df630SAndroid Build Coastguard Worker 	const char *param2;
2350*4f2df630SAndroid Build Coastguard Worker 	size_t param1_length;
2351*4f2df630SAndroid Build Coastguard Worker 
2352*4f2df630SAndroid Build Coastguard Worker 	if (!opt) {
2353*4f2df630SAndroid Build Coastguard Worker 		*bid_action = bid_get;
2354*4f2df630SAndroid Build Coastguard Worker 		return 1;
2355*4f2df630SAndroid Build Coastguard Worker 	}
2356*4f2df630SAndroid Build Coastguard Worker 
2357*4f2df630SAndroid Build Coastguard Worker 	/* Set it here to make bailing out easier later. */
2358*4f2df630SAndroid Build Coastguard Worker 	bid->flags = DEFAULT_BOARD_ID_FLAG;
2359*4f2df630SAndroid Build Coastguard Worker 
2360*4f2df630SAndroid Build Coastguard Worker 	*bid_action = bid_set; /* Ignored by caller on errors. */
2361*4f2df630SAndroid Build Coastguard Worker 
2362*4f2df630SAndroid Build Coastguard Worker 	/*
2363*4f2df630SAndroid Build Coastguard Worker 	 * Pointer to the optional second component of the command line
2364*4f2df630SAndroid Build Coastguard Worker 	 * parameter, when present - separated by a colon.
2365*4f2df630SAndroid Build Coastguard Worker 	 */
2366*4f2df630SAndroid Build Coastguard Worker 	param2 = strchr(opt, ':');
2367*4f2df630SAndroid Build Coastguard Worker 	if (param2) {
2368*4f2df630SAndroid Build Coastguard Worker 		param1_length = param2 - opt;
2369*4f2df630SAndroid Build Coastguard Worker 		param2++;
2370*4f2df630SAndroid Build Coastguard Worker 		if (!*param2)
2371*4f2df630SAndroid Build Coastguard Worker 			return 0; /* Empty second parameter. */
2372*4f2df630SAndroid Build Coastguard Worker 	} else {
2373*4f2df630SAndroid Build Coastguard Worker 		param1_length = strlen(opt);
2374*4f2df630SAndroid Build Coastguard Worker 	}
2375*4f2df630SAndroid Build Coastguard Worker 
2376*4f2df630SAndroid Build Coastguard Worker 	if (!param1_length)
2377*4f2df630SAndroid Build Coastguard Worker 		return 0; /* Colon is the first character of the string? */
2378*4f2df630SAndroid Build Coastguard Worker 
2379*4f2df630SAndroid Build Coastguard Worker 	if (param1_length <= 4) {
2380*4f2df630SAndroid Build Coastguard Worker 		unsigned i;
2381*4f2df630SAndroid Build Coastguard Worker 
2382*4f2df630SAndroid Build Coastguard Worker 		/* Input must be a symbolic board name. */
2383*4f2df630SAndroid Build Coastguard Worker 		bid->type = 0;
2384*4f2df630SAndroid Build Coastguard Worker 		for (i = 0; i < param1_length; i++)
2385*4f2df630SAndroid Build Coastguard Worker 			bid->type = (bid->type << 8) | opt[i];
2386*4f2df630SAndroid Build Coastguard Worker 	} else {
2387*4f2df630SAndroid Build Coastguard Worker 		bid->type = (uint32_t)strtoul(opt, &e, 0);
2388*4f2df630SAndroid Build Coastguard Worker 		if ((param2 && (*e != ':')) || (!param2 && *e))
2389*4f2df630SAndroid Build Coastguard Worker 			return 0;
2390*4f2df630SAndroid Build Coastguard Worker 	}
2391*4f2df630SAndroid Build Coastguard Worker 
2392*4f2df630SAndroid Build Coastguard Worker 	if (param2) {
2393*4f2df630SAndroid Build Coastguard Worker 		bid->flags = (uint32_t)strtoul(param2, &e, 0);
2394*4f2df630SAndroid Build Coastguard Worker 		if (*e)
2395*4f2df630SAndroid Build Coastguard Worker 			return 0;
2396*4f2df630SAndroid Build Coastguard Worker 	}
2397*4f2df630SAndroid Build Coastguard Worker 
2398*4f2df630SAndroid Build Coastguard Worker 	return 1;
2399*4f2df630SAndroid Build Coastguard Worker }
2400*4f2df630SAndroid Build Coastguard Worker 
2401*4f2df630SAndroid Build Coastguard Worker /*
2402*4f2df630SAndroid Build Coastguard Worker  * Reads a two-character hexadecimal byte from a string. If the string is
2403*4f2df630SAndroid Build Coastguard Worker  * ill-formed, returns 0. Otherwise, |byte| contains the byte value and the
2404*4f2df630SAndroid Build Coastguard Worker  * return value is non-zero.
2405*4f2df630SAndroid Build Coastguard Worker  */
read_hex_byte(const char * s,uint8_t * byte)2406*4f2df630SAndroid Build Coastguard Worker static int read_hex_byte(const char *s, uint8_t *byte)
2407*4f2df630SAndroid Build Coastguard Worker {
2408*4f2df630SAndroid Build Coastguard Worker 	uint8_t b = 0;
2409*4f2df630SAndroid Build Coastguard Worker 	for (const char *end = s + 2; s < end; ++s) {
2410*4f2df630SAndroid Build Coastguard Worker 		if (*s >= '0' && *s <= '9')
2411*4f2df630SAndroid Build Coastguard Worker 			b = b * 16 + *s - '0';
2412*4f2df630SAndroid Build Coastguard Worker 		else if (*s >= 'A' && *s <= 'F')
2413*4f2df630SAndroid Build Coastguard Worker 			b = b * 16 + 10 + *s - 'A';
2414*4f2df630SAndroid Build Coastguard Worker 		else if (*s >= 'a' && *s <= 'f')
2415*4f2df630SAndroid Build Coastguard Worker 			b = b * 16 + 10 + *s - 'a';
2416*4f2df630SAndroid Build Coastguard Worker 		else
2417*4f2df630SAndroid Build Coastguard Worker 			return 0;
2418*4f2df630SAndroid Build Coastguard Worker 	}
2419*4f2df630SAndroid Build Coastguard Worker 	*byte = b;
2420*4f2df630SAndroid Build Coastguard Worker 	return 1;
2421*4f2df630SAndroid Build Coastguard Worker }
2422*4f2df630SAndroid Build Coastguard Worker 
parse_sn_bits(const char * opt,uint8_t * sn_bits)2423*4f2df630SAndroid Build Coastguard Worker static int parse_sn_bits(const char *opt, uint8_t *sn_bits)
2424*4f2df630SAndroid Build Coastguard Worker {
2425*4f2df630SAndroid Build Coastguard Worker 	size_t len = strlen(opt);
2426*4f2df630SAndroid Build Coastguard Worker 
2427*4f2df630SAndroid Build Coastguard Worker 	if (!strncmp(opt, "0x", 2)) {
2428*4f2df630SAndroid Build Coastguard Worker 		opt += 2;
2429*4f2df630SAndroid Build Coastguard Worker 		len -= 2;
2430*4f2df630SAndroid Build Coastguard Worker 	}
2431*4f2df630SAndroid Build Coastguard Worker 	if (len != SN_BITS_SIZE * 2)
2432*4f2df630SAndroid Build Coastguard Worker 		return 0;
2433*4f2df630SAndroid Build Coastguard Worker 
2434*4f2df630SAndroid Build Coastguard Worker 	for (int i = 0; i < SN_BITS_SIZE; ++i, opt += 2)
2435*4f2df630SAndroid Build Coastguard Worker 		if (!read_hex_byte(opt, sn_bits++))
2436*4f2df630SAndroid Build Coastguard Worker 			return 0;
2437*4f2df630SAndroid Build Coastguard Worker 
2438*4f2df630SAndroid Build Coastguard Worker 	return 1;
2439*4f2df630SAndroid Build Coastguard Worker }
2440*4f2df630SAndroid Build Coastguard Worker 
parse_sn_inc_rma(const char * opt,uint8_t * arg)2441*4f2df630SAndroid Build Coastguard Worker static int parse_sn_inc_rma(const char *opt, uint8_t *arg)
2442*4f2df630SAndroid Build Coastguard Worker {
2443*4f2df630SAndroid Build Coastguard Worker 	uint32_t inc;
2444*4f2df630SAndroid Build Coastguard Worker 	char *e;
2445*4f2df630SAndroid Build Coastguard Worker 
2446*4f2df630SAndroid Build Coastguard Worker 	inc = (uint32_t)strtoul(opt, &e, 0);
2447*4f2df630SAndroid Build Coastguard Worker 
2448*4f2df630SAndroid Build Coastguard Worker 	if (opt == e || *e != '\0' || inc > 7)
2449*4f2df630SAndroid Build Coastguard Worker 		return 0;
2450*4f2df630SAndroid Build Coastguard Worker 
2451*4f2df630SAndroid Build Coastguard Worker 	*arg = inc;
2452*4f2df630SAndroid Build Coastguard Worker 	return 1;
2453*4f2df630SAndroid Build Coastguard Worker }
2454*4f2df630SAndroid Build Coastguard Worker 
common_process_password(struct transfer_descriptor * td,enum ccd_vendor_subcommands subcmd)2455*4f2df630SAndroid Build Coastguard Worker static uint32_t common_process_password(struct transfer_descriptor *td,
2456*4f2df630SAndroid Build Coastguard Worker 					enum ccd_vendor_subcommands subcmd)
2457*4f2df630SAndroid Build Coastguard Worker {
2458*4f2df630SAndroid Build Coastguard Worker 	size_t response_size;
2459*4f2df630SAndroid Build Coastguard Worker 	uint8_t response;
2460*4f2df630SAndroid Build Coastguard Worker 	uint32_t rv;
2461*4f2df630SAndroid Build Coastguard Worker 	char *password = NULL;
2462*4f2df630SAndroid Build Coastguard Worker 	char *password_copy = NULL;
2463*4f2df630SAndroid Build Coastguard Worker 	ssize_t copy_len;
2464*4f2df630SAndroid Build Coastguard Worker 	ssize_t len;
2465*4f2df630SAndroid Build Coastguard Worker 	size_t zero = 0;
2466*4f2df630SAndroid Build Coastguard Worker 	struct termios oldattr, newattr;
2467*4f2df630SAndroid Build Coastguard Worker 
2468*4f2df630SAndroid Build Coastguard Worker 	/* Suppress command line echo while password is being entered. */
2469*4f2df630SAndroid Build Coastguard Worker 	tcgetattr(STDIN_FILENO, &oldattr);
2470*4f2df630SAndroid Build Coastguard Worker 	newattr = oldattr;
2471*4f2df630SAndroid Build Coastguard Worker 	newattr.c_lflag &= ~ECHO;
2472*4f2df630SAndroid Build Coastguard Worker 	newattr.c_lflag |= (ICANON | ECHONL);
2473*4f2df630SAndroid Build Coastguard Worker 	tcsetattr(STDIN_FILENO, TCSANOW, &newattr);
2474*4f2df630SAndroid Build Coastguard Worker 
2475*4f2df630SAndroid Build Coastguard Worker 	/* With command line echo suppressed request password entry twice. */
2476*4f2df630SAndroid Build Coastguard Worker 	printf("Enter password:");
2477*4f2df630SAndroid Build Coastguard Worker 	len = getline(&password, &zero, stdin);
2478*4f2df630SAndroid Build Coastguard Worker 	printf("Re-enter password:");
2479*4f2df630SAndroid Build Coastguard Worker 	zero = 0;
2480*4f2df630SAndroid Build Coastguard Worker 	copy_len = getline(&password_copy, &zero, stdin);
2481*4f2df630SAndroid Build Coastguard Worker 
2482*4f2df630SAndroid Build Coastguard Worker 	/* Restore command line echo. */
2483*4f2df630SAndroid Build Coastguard Worker 	tcsetattr(STDIN_FILENO, TCSANOW, &oldattr);
2484*4f2df630SAndroid Build Coastguard Worker 
2485*4f2df630SAndroid Build Coastguard Worker 	/* Empty password will still have the newline. */
2486*4f2df630SAndroid Build Coastguard Worker 	if ((len <= 1) || !password_copy || (copy_len != len)) {
2487*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Error reading password\n");
2488*4f2df630SAndroid Build Coastguard Worker 		if (password)
2489*4f2df630SAndroid Build Coastguard Worker 			free(password);
2490*4f2df630SAndroid Build Coastguard Worker 		if (password_copy)
2491*4f2df630SAndroid Build Coastguard Worker 			free(password_copy);
2492*4f2df630SAndroid Build Coastguard Worker 		if ((copy_len >= 0) && (len >= 0) && (copy_len != len))
2493*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr, "Password length mismatch\n");
2494*4f2df630SAndroid Build Coastguard Worker 		exit(update_error);
2495*4f2df630SAndroid Build Coastguard Worker 	}
2496*4f2df630SAndroid Build Coastguard Worker 
2497*4f2df630SAndroid Build Coastguard Worker 	/* Compare the two inputs. */
2498*4f2df630SAndroid Build Coastguard Worker 	if (strcmp(password, password_copy)) {
2499*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Entered passwords don't match\n");
2500*4f2df630SAndroid Build Coastguard Worker 		free(password);
2501*4f2df630SAndroid Build Coastguard Worker 		free(password_copy);
2502*4f2df630SAndroid Build Coastguard Worker 		exit(update_error);
2503*4f2df630SAndroid Build Coastguard Worker 	}
2504*4f2df630SAndroid Build Coastguard Worker 
2505*4f2df630SAndroid Build Coastguard Worker 	/*
2506*4f2df630SAndroid Build Coastguard Worker 	 * Ok, we have a password, let's move it in the buffer to overwrite
2507*4f2df630SAndroid Build Coastguard Worker 	 * the newline and free a byte to prepend the subcommand code.
2508*4f2df630SAndroid Build Coastguard Worker 	 */
2509*4f2df630SAndroid Build Coastguard Worker 	memmove(password + 1, password, len - 1);
2510*4f2df630SAndroid Build Coastguard Worker 	password[0] = subcmd;
2511*4f2df630SAndroid Build Coastguard Worker 	response_size = sizeof(response);
2512*4f2df630SAndroid Build Coastguard Worker 	rv = send_vendor_command(td, VENDOR_CC_CCD, password, len, &response,
2513*4f2df630SAndroid Build Coastguard Worker 				 &response_size);
2514*4f2df630SAndroid Build Coastguard Worker 	free(password);
2515*4f2df630SAndroid Build Coastguard Worker 	free(password_copy);
2516*4f2df630SAndroid Build Coastguard Worker 
2517*4f2df630SAndroid Build Coastguard Worker 	if ((rv != VENDOR_RC_SUCCESS) && (rv != VENDOR_RC_IN_PROGRESS))
2518*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Error sending password: rv %d, response %d\n",
2519*4f2df630SAndroid Build Coastguard Worker 			rv, response_size ? response : 0);
2520*4f2df630SAndroid Build Coastguard Worker 
2521*4f2df630SAndroid Build Coastguard Worker 	return rv;
2522*4f2df630SAndroid Build Coastguard Worker }
2523*4f2df630SAndroid Build Coastguard Worker 
process_password(struct transfer_descriptor * td)2524*4f2df630SAndroid Build Coastguard Worker static void process_password(struct transfer_descriptor *td)
2525*4f2df630SAndroid Build Coastguard Worker {
2526*4f2df630SAndroid Build Coastguard Worker 	if (common_process_password(td, CCDV_PASSWORD) == VENDOR_RC_SUCCESS)
2527*4f2df630SAndroid Build Coastguard Worker 		return;
2528*4f2df630SAndroid Build Coastguard Worker 
2529*4f2df630SAndroid Build Coastguard Worker 	exit(update_error);
2530*4f2df630SAndroid Build Coastguard Worker }
2531*4f2df630SAndroid Build Coastguard Worker 
poll_for_pp(struct transfer_descriptor * td,uint16_t command,uint8_t poll_type)2532*4f2df630SAndroid Build Coastguard Worker void poll_for_pp(struct transfer_descriptor *td, uint16_t command,
2533*4f2df630SAndroid Build Coastguard Worker 		 uint8_t poll_type)
2534*4f2df630SAndroid Build Coastguard Worker {
2535*4f2df630SAndroid Build Coastguard Worker 	uint8_t response;
2536*4f2df630SAndroid Build Coastguard Worker 	uint8_t prev_response;
2537*4f2df630SAndroid Build Coastguard Worker 	size_t response_size;
2538*4f2df630SAndroid Build Coastguard Worker 	int rv;
2539*4f2df630SAndroid Build Coastguard Worker 
2540*4f2df630SAndroid Build Coastguard Worker 	prev_response = ~0; /* Guaranteed invalid value. */
2541*4f2df630SAndroid Build Coastguard Worker 
2542*4f2df630SAndroid Build Coastguard Worker 	while (1) {
2543*4f2df630SAndroid Build Coastguard Worker 		response_size = sizeof(response);
2544*4f2df630SAndroid Build Coastguard Worker 		rv = send_vendor_command(td, command, &poll_type,
2545*4f2df630SAndroid Build Coastguard Worker 					 sizeof(poll_type), &response,
2546*4f2df630SAndroid Build Coastguard Worker 					 &response_size);
2547*4f2df630SAndroid Build Coastguard Worker 
2548*4f2df630SAndroid Build Coastguard Worker 		if (((rv != VENDOR_RC_SUCCESS) &&
2549*4f2df630SAndroid Build Coastguard Worker 		     (rv != VENDOR_RC_IN_PROGRESS)) ||
2550*4f2df630SAndroid Build Coastguard Worker 		    (response_size != 1)) {
2551*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr, "Error: rv %d, response %d\n", rv,
2552*4f2df630SAndroid Build Coastguard Worker 				response_size ? response : 0);
2553*4f2df630SAndroid Build Coastguard Worker 			exit(update_error);
2554*4f2df630SAndroid Build Coastguard Worker 		}
2555*4f2df630SAndroid Build Coastguard Worker 
2556*4f2df630SAndroid Build Coastguard Worker 		if (response == CCD_PP_DONE) {
2557*4f2df630SAndroid Build Coastguard Worker 			printf("PP Done!\n");
2558*4f2df630SAndroid Build Coastguard Worker 			return;
2559*4f2df630SAndroid Build Coastguard Worker 		}
2560*4f2df630SAndroid Build Coastguard Worker 
2561*4f2df630SAndroid Build Coastguard Worker 		if (response == CCD_PP_CLOSED) {
2562*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr,
2563*4f2df630SAndroid Build Coastguard Worker 				"Error: Physical presence check timeout!\n");
2564*4f2df630SAndroid Build Coastguard Worker 			exit(update_error);
2565*4f2df630SAndroid Build Coastguard Worker 		}
2566*4f2df630SAndroid Build Coastguard Worker 
2567*4f2df630SAndroid Build Coastguard Worker 		if (response == CCD_PP_AWAITING_PRESS) {
2568*4f2df630SAndroid Build Coastguard Worker 			printf("Press PP button now!\n");
2569*4f2df630SAndroid Build Coastguard Worker 		} else if (response == CCD_PP_BETWEEN_PRESSES) {
2570*4f2df630SAndroid Build Coastguard Worker 			if (prev_response != response)
2571*4f2df630SAndroid Build Coastguard Worker 				printf("Another press will be required!\n");
2572*4f2df630SAndroid Build Coastguard Worker 		} else {
2573*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr, "Error: unknown poll result %d\n",
2574*4f2df630SAndroid Build Coastguard Worker 				response);
2575*4f2df630SAndroid Build Coastguard Worker 			exit(update_error);
2576*4f2df630SAndroid Build Coastguard Worker 		}
2577*4f2df630SAndroid Build Coastguard Worker 		prev_response = response;
2578*4f2df630SAndroid Build Coastguard Worker 
2579*4f2df630SAndroid Build Coastguard Worker 		usleep(500 * 1000); /* Poll every half a second. */
2580*4f2df630SAndroid Build Coastguard Worker 	}
2581*4f2df630SAndroid Build Coastguard Worker }
2582*4f2df630SAndroid Build Coastguard Worker 
2583*4f2df630SAndroid Build Coastguard Worker /* Determine the longest capability name found in the passed in table. */
longest_cap_name_len(const struct ccd_capability_info * table,size_t count)2584*4f2df630SAndroid Build Coastguard Worker static size_t longest_cap_name_len(const struct ccd_capability_info *table,
2585*4f2df630SAndroid Build Coastguard Worker 				   size_t count)
2586*4f2df630SAndroid Build Coastguard Worker {
2587*4f2df630SAndroid Build Coastguard Worker 	size_t i;
2588*4f2df630SAndroid Build Coastguard Worker 	size_t result = 0;
2589*4f2df630SAndroid Build Coastguard Worker 
2590*4f2df630SAndroid Build Coastguard Worker 	for (i = 0; i < count; i++) {
2591*4f2df630SAndroid Build Coastguard Worker 		size_t this_size;
2592*4f2df630SAndroid Build Coastguard Worker 
2593*4f2df630SAndroid Build Coastguard Worker 		this_size = strlen(table[i].name);
2594*4f2df630SAndroid Build Coastguard Worker 		if (this_size > result)
2595*4f2df630SAndroid Build Coastguard Worker 			result = this_size;
2596*4f2df630SAndroid Build Coastguard Worker 	}
2597*4f2df630SAndroid Build Coastguard Worker 	return result;
2598*4f2df630SAndroid Build Coastguard Worker }
2599*4f2df630SAndroid Build Coastguard Worker 
2600*4f2df630SAndroid Build Coastguard Worker /*
2601*4f2df630SAndroid Build Coastguard Worker  * Print the passed in capability name padded to the longest length determined
2602*4f2df630SAndroid Build Coastguard Worker  * earlier.
2603*4f2df630SAndroid Build Coastguard Worker  */
print_aligned(const char * name,size_t field_size)2604*4f2df630SAndroid Build Coastguard Worker static void print_aligned(const char *name, size_t field_size)
2605*4f2df630SAndroid Build Coastguard Worker {
2606*4f2df630SAndroid Build Coastguard Worker 	size_t name_len;
2607*4f2df630SAndroid Build Coastguard Worker 
2608*4f2df630SAndroid Build Coastguard Worker 	name_len = strlen(name);
2609*4f2df630SAndroid Build Coastguard Worker 
2610*4f2df630SAndroid Build Coastguard Worker 	printf("%s", name);
2611*4f2df630SAndroid Build Coastguard Worker 	while (name_len < field_size) {
2612*4f2df630SAndroid Build Coastguard Worker 		printf(" ");
2613*4f2df630SAndroid Build Coastguard Worker 		name_len++;
2614*4f2df630SAndroid Build Coastguard Worker 	}
2615*4f2df630SAndroid Build Coastguard Worker }
2616*4f2df630SAndroid Build Coastguard Worker 
2617*4f2df630SAndroid Build Coastguard Worker /*
2618*4f2df630SAndroid Build Coastguard Worker  * Translates "AnExampleTPMString" into "AN_EXAMPLE_TPM_STRING". Note that
2619*4f2df630SAndroid Build Coastguard Worker  * output must be large enough to contain a 150%-sized string of input.
2620*4f2df630SAndroid Build Coastguard Worker  */
to_upper_underscore(const char * input,char * output)2621*4f2df630SAndroid Build Coastguard Worker static void to_upper_underscore(const char *input, char *output)
2622*4f2df630SAndroid Build Coastguard Worker {
2623*4f2df630SAndroid Build Coastguard Worker 	bool first_char = true;
2624*4f2df630SAndroid Build Coastguard Worker 	bool needs_underscore = false;
2625*4f2df630SAndroid Build Coastguard Worker 
2626*4f2df630SAndroid Build Coastguard Worker 	while (*input != '\0') {
2627*4f2df630SAndroid Build Coastguard Worker 		*output = toupper(*input);
2628*4f2df630SAndroid Build Coastguard Worker 		/*
2629*4f2df630SAndroid Build Coastguard Worker 		 * If we encounter an upper case char in the input, we may need
2630*4f2df630SAndroid Build Coastguard Worker 		 * to add an underscore in the output before (re)writing the
2631*4f2df630SAndroid Build Coastguard Worker 		 * output char
2632*4f2df630SAndroid Build Coastguard Worker 		 */
2633*4f2df630SAndroid Build Coastguard Worker 		if (*output == *input) {
2634*4f2df630SAndroid Build Coastguard Worker 			/*
2635*4f2df630SAndroid Build Coastguard Worker 			 * See if the next input letter is lower case, that
2636*4f2df630SAndroid Build Coastguard Worker 			 * means this uppercase letter needs a '_' before it.
2637*4f2df630SAndroid Build Coastguard Worker 			 */
2638*4f2df630SAndroid Build Coastguard Worker 			if (islower(*(input + 1)) && !first_char)
2639*4f2df630SAndroid Build Coastguard Worker 				needs_underscore = true;
2640*4f2df630SAndroid Build Coastguard Worker 			if (needs_underscore) {
2641*4f2df630SAndroid Build Coastguard Worker 				needs_underscore = false;
2642*4f2df630SAndroid Build Coastguard Worker 				*output++ = '_';
2643*4f2df630SAndroid Build Coastguard Worker 				*output = *input;
2644*4f2df630SAndroid Build Coastguard Worker 			}
2645*4f2df630SAndroid Build Coastguard Worker 		} else {
2646*4f2df630SAndroid Build Coastguard Worker 			/*
2647*4f2df630SAndroid Build Coastguard Worker 			 * We encountered a lower case, so the next upper case
2648*4f2df630SAndroid Build Coastguard Worker 			 * should have a '_' before it
2649*4f2df630SAndroid Build Coastguard Worker 			 */
2650*4f2df630SAndroid Build Coastguard Worker 			needs_underscore = true;
2651*4f2df630SAndroid Build Coastguard Worker 		}
2652*4f2df630SAndroid Build Coastguard Worker 		first_char = false;
2653*4f2df630SAndroid Build Coastguard Worker 		input++;
2654*4f2df630SAndroid Build Coastguard Worker 		output++;
2655*4f2df630SAndroid Build Coastguard Worker 	}
2656*4f2df630SAndroid Build Coastguard Worker 	*output = '\0';
2657*4f2df630SAndroid Build Coastguard Worker }
2658*4f2df630SAndroid Build Coastguard Worker 
2659*4f2df630SAndroid Build Coastguard Worker /*
2660*4f2df630SAndroid Build Coastguard Worker  * Ensure that the CCD info response is well formed otherwise exits. Upon return
2661*4f2df630SAndroid Build Coastguard Worker  * the ccd_info variable will contain the structured ccd info response and the
2662*4f2df630SAndroid Build Coastguard Worker  * return value is the version of ccd info to parse with (e.g. 0 for cr50 and
2663*4f2df630SAndroid Build Coastguard Worker  * 1 for ti50).
2664*4f2df630SAndroid Build Coastguard Worker  */
validate_into_ccd_info_response(void * response,size_t response_size,struct ccd_info_response * ccd_info)2665*4f2df630SAndroid Build Coastguard Worker static uint32_t validate_into_ccd_info_response(
2666*4f2df630SAndroid Build Coastguard Worker 	void *response, size_t response_size,
2667*4f2df630SAndroid Build Coastguard Worker 	struct ccd_info_response *ccd_info)
2668*4f2df630SAndroid Build Coastguard Worker {
2669*4f2df630SAndroid Build Coastguard Worker 	struct ccd_info_response_header ccd_info_header;
2670*4f2df630SAndroid Build Coastguard Worker 	size_t i;
2671*4f2df630SAndroid Build Coastguard Worker 	uint32_t ccd_info_version;
2672*4f2df630SAndroid Build Coastguard Worker 
2673*4f2df630SAndroid Build Coastguard Worker 	if (response_size < sizeof(ccd_info_header)) {
2674*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "CCD info response too short %zd\n",
2675*4f2df630SAndroid Build Coastguard Worker 			response_size);
2676*4f2df630SAndroid Build Coastguard Worker 		exit(update_error);
2677*4f2df630SAndroid Build Coastguard Worker 	}
2678*4f2df630SAndroid Build Coastguard Worker 
2679*4f2df630SAndroid Build Coastguard Worker 	/* Let's check if this is a newer version response. */
2680*4f2df630SAndroid Build Coastguard Worker 	memcpy(&ccd_info_header, response, sizeof(ccd_info_header));
2681*4f2df630SAndroid Build Coastguard Worker 	if ((ccd_info_header.ccd_magic == CCD_INFO_MAGIC) &&
2682*4f2df630SAndroid Build Coastguard Worker 	    (ccd_info_header.ccd_size == response_size) &&
2683*4f2df630SAndroid Build Coastguard Worker 	    /* Verify that payload size matches ccd_info size. */
2684*4f2df630SAndroid Build Coastguard Worker 	    ((response_size - sizeof(ccd_info_header)) == sizeof(*ccd_info))) {
2685*4f2df630SAndroid Build Coastguard Worker 		ccd_info_version = ccd_info_header.ccd_version;
2686*4f2df630SAndroid Build Coastguard Worker 		memcpy(ccd_info,
2687*4f2df630SAndroid Build Coastguard Worker 		       (uint8_t *)response +
2688*4f2df630SAndroid Build Coastguard Worker 			       sizeof(struct ccd_info_response_header),
2689*4f2df630SAndroid Build Coastguard Worker 		       sizeof(*ccd_info));
2690*4f2df630SAndroid Build Coastguard Worker 		/*
2691*4f2df630SAndroid Build Coastguard Worker 		 * V1 CCD info structure uses little endian for transmission.
2692*4f2df630SAndroid Build Coastguard Worker 		 * No need to update to host endianness since it is already LE.
2693*4f2df630SAndroid Build Coastguard Worker 		 */
2694*4f2df630SAndroid Build Coastguard Worker 	} else if (response_size == CCD_INFO_V0_SIZE) {
2695*4f2df630SAndroid Build Coastguard Worker 		ccd_info_version = 0; /* Default, Cr50 case. */
2696*4f2df630SAndroid Build Coastguard Worker 		memcpy(ccd_info, response, sizeof(*ccd_info));
2697*4f2df630SAndroid Build Coastguard Worker 		/*
2698*4f2df630SAndroid Build Coastguard Worker 		 * V0 CCD info structure uses big endian for transmission.
2699*4f2df630SAndroid Build Coastguard Worker 		 * Update fields to host endianness.
2700*4f2df630SAndroid Build Coastguard Worker 		 */
2701*4f2df630SAndroid Build Coastguard Worker 		ccd_info->ccd_flags = be32toh(ccd_info->ccd_flags);
2702*4f2df630SAndroid Build Coastguard Worker 		for (i = 0; i < ARRAY_SIZE(ccd_info->ccd_caps_current); i++) {
2703*4f2df630SAndroid Build Coastguard Worker 			ccd_info->ccd_caps_current[i] =
2704*4f2df630SAndroid Build Coastguard Worker 				be32toh(ccd_info->ccd_caps_current[i]);
2705*4f2df630SAndroid Build Coastguard Worker 			ccd_info->ccd_caps_defaults[i] =
2706*4f2df630SAndroid Build Coastguard Worker 				be32toh(ccd_info->ccd_caps_defaults[i]);
2707*4f2df630SAndroid Build Coastguard Worker 		}
2708*4f2df630SAndroid Build Coastguard Worker 	} else {
2709*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Unexpected CCD info response size %zd\n",
2710*4f2df630SAndroid Build Coastguard Worker 			response_size);
2711*4f2df630SAndroid Build Coastguard Worker 		exit(update_error);
2712*4f2df630SAndroid Build Coastguard Worker 	}
2713*4f2df630SAndroid Build Coastguard Worker 
2714*4f2df630SAndroid Build Coastguard Worker 	return ccd_info_version;
2715*4f2df630SAndroid Build Coastguard Worker }
2716*4f2df630SAndroid Build Coastguard Worker 
print_ccd_info(void * response,size_t response_size,bool show_machine_output)2717*4f2df630SAndroid Build Coastguard Worker static void print_ccd_info(void *response, size_t response_size,
2718*4f2df630SAndroid Build Coastguard Worker 			   bool show_machine_output)
2719*4f2df630SAndroid Build Coastguard Worker {
2720*4f2df630SAndroid Build Coastguard Worker 	struct ccd_info_response ccd_info;
2721*4f2df630SAndroid Build Coastguard Worker 	size_t i;
2722*4f2df630SAndroid Build Coastguard Worker 	const struct ccd_capability_info cr50_cap_info[] = CAP_INFO_DATA;
2723*4f2df630SAndroid Build Coastguard Worker 	const char *state_names[] = CCD_STATE_NAMES;
2724*4f2df630SAndroid Build Coastguard Worker 	const char *cap_state_names[] = CCD_CAP_STATE_NAMES;
2725*4f2df630SAndroid Build Coastguard Worker 	uint32_t caps_bitmap = 0;
2726*4f2df630SAndroid Build Coastguard Worker 	uint32_t ccd_info_version;
2727*4f2df630SAndroid Build Coastguard Worker 
2728*4f2df630SAndroid Build Coastguard Worker 	/*
2729*4f2df630SAndroid Build Coastguard Worker 	 * CCD info structure is different for different GSCs. Two layouts are
2730*4f2df630SAndroid Build Coastguard Worker 	 * defined at this time, version 0 (Cr50) and version 1 (Ti50). The
2731*4f2df630SAndroid Build Coastguard Worker 	 * array below indexed by version number provides access to version
2732*4f2df630SAndroid Build Coastguard Worker 	 * specific information about the layout.
2733*4f2df630SAndroid Build Coastguard Worker 	 */
2734*4f2df630SAndroid Build Coastguard Worker 	const struct {
2735*4f2df630SAndroid Build Coastguard Worker 		size_t cap_count;
2736*4f2df630SAndroid Build Coastguard Worker 		const struct ccd_capability_info *info_table;
2737*4f2df630SAndroid Build Coastguard Worker 	} version_to_ccd[] = {
2738*4f2df630SAndroid Build Coastguard Worker 		{ CR50_CCD_CAP_COUNT, cr50_cap_info },
2739*4f2df630SAndroid Build Coastguard Worker 		{ TI50_CCD_CAP_COUNT, ti50_cap_info },
2740*4f2df630SAndroid Build Coastguard Worker 	};
2741*4f2df630SAndroid Build Coastguard Worker 
2742*4f2df630SAndroid Build Coastguard Worker 	/* Run time determined properties of the CCD info table. */
2743*4f2df630SAndroid Build Coastguard Worker 	size_t gsc_cap_count;
2744*4f2df630SAndroid Build Coastguard Worker 	const struct ccd_capability_info *gsc_capability_info;
2745*4f2df630SAndroid Build Coastguard Worker 	size_t name_column_width;
2746*4f2df630SAndroid Build Coastguard Worker 
2747*4f2df630SAndroid Build Coastguard Worker 	ccd_info_version = validate_into_ccd_info_response(
2748*4f2df630SAndroid Build Coastguard Worker 		response, response_size, &ccd_info);
2749*4f2df630SAndroid Build Coastguard Worker 
2750*4f2df630SAndroid Build Coastguard Worker 	if (ccd_info_version >= ARRAY_SIZE(version_to_ccd)) {
2751*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Unsupported CCD info version number %d\n",
2752*4f2df630SAndroid Build Coastguard Worker 			ccd_info_version);
2753*4f2df630SAndroid Build Coastguard Worker 		exit(update_error);
2754*4f2df630SAndroid Build Coastguard Worker 	}
2755*4f2df630SAndroid Build Coastguard Worker 
2756*4f2df630SAndroid Build Coastguard Worker 	/* Now report CCD state on the console. */
2757*4f2df630SAndroid Build Coastguard Worker 	const char *const state = ccd_info.ccd_state > ARRAY_SIZE(state_names) ?
2758*4f2df630SAndroid Build Coastguard Worker 					  "Error" :
2759*4f2df630SAndroid Build Coastguard Worker 					  state_names[ccd_info.ccd_state];
2760*4f2df630SAndroid Build Coastguard Worker 	const char *const password = (ccd_info.ccd_indicator_bitmap &
2761*4f2df630SAndroid Build Coastguard Worker 				      CCD_INDICATOR_BIT_HAS_PASSWORD) ?
2762*4f2df630SAndroid Build Coastguard Worker 					     "Set" :
2763*4f2df630SAndroid Build Coastguard Worker 					     "None";
2764*4f2df630SAndroid Build Coastguard Worker 	if (show_machine_output) {
2765*4f2df630SAndroid Build Coastguard Worker 		print_machine_output("STATE", "%s", state);
2766*4f2df630SAndroid Build Coastguard Worker 		print_machine_output("PASSWORD", "%s", password);
2767*4f2df630SAndroid Build Coastguard Worker 		print_machine_output("CCD_FLAGS", "%#06x", ccd_info.ccd_flags);
2768*4f2df630SAndroid Build Coastguard Worker 		print_machine_output(
2769*4f2df630SAndroid Build Coastguard Worker 			"CCD_FLAG_TESTLAB_MODE", "%c",
2770*4f2df630SAndroid Build Coastguard Worker 			(ccd_info.ccd_flags & CCD_FLAG_TEST_LAB) ? 'Y' : 'N');
2771*4f2df630SAndroid Build Coastguard Worker 		print_machine_output("CCD_FLAG_FACTORY_MODE", "%c",
2772*4f2df630SAndroid Build Coastguard Worker 				     (ccd_info.ccd_flags &
2773*4f2df630SAndroid Build Coastguard Worker 				      CCD_FLAG_FACTORY_MODE_ENABLED) ?
2774*4f2df630SAndroid Build Coastguard Worker 					     'Y' :
2775*4f2df630SAndroid Build Coastguard Worker 					     'N');
2776*4f2df630SAndroid Build Coastguard Worker 	} else {
2777*4f2df630SAndroid Build Coastguard Worker 		printf("State: %s\n", state);
2778*4f2df630SAndroid Build Coastguard Worker 		printf("Password: %s\n", password);
2779*4f2df630SAndroid Build Coastguard Worker 		printf("Flags: %#06x\n", ccd_info.ccd_flags);
2780*4f2df630SAndroid Build Coastguard Worker 		printf("Capabilities, current and default:\n");
2781*4f2df630SAndroid Build Coastguard Worker 	}
2782*4f2df630SAndroid Build Coastguard Worker 
2783*4f2df630SAndroid Build Coastguard Worker 	gsc_cap_count = version_to_ccd[ccd_info_version].cap_count;
2784*4f2df630SAndroid Build Coastguard Worker 	gsc_capability_info = version_to_ccd[ccd_info_version].info_table;
2785*4f2df630SAndroid Build Coastguard Worker 	name_column_width =
2786*4f2df630SAndroid Build Coastguard Worker 		longest_cap_name_len(gsc_capability_info, gsc_cap_count) + 1;
2787*4f2df630SAndroid Build Coastguard Worker 	for (i = 0; i < gsc_cap_count; i++) {
2788*4f2df630SAndroid Build Coastguard Worker 		int is_enabled;
2789*4f2df630SAndroid Build Coastguard Worker 		int index;
2790*4f2df630SAndroid Build Coastguard Worker 		int shift;
2791*4f2df630SAndroid Build Coastguard Worker 		int cap_current;
2792*4f2df630SAndroid Build Coastguard Worker 		int cap_default;
2793*4f2df630SAndroid Build Coastguard Worker 
2794*4f2df630SAndroid Build Coastguard Worker 		index = i / (32 / CCD_CAP_BITS);
2795*4f2df630SAndroid Build Coastguard Worker 		shift = (i % (32 / CCD_CAP_BITS)) * CCD_CAP_BITS;
2796*4f2df630SAndroid Build Coastguard Worker 
2797*4f2df630SAndroid Build Coastguard Worker 		cap_current = (ccd_info.ccd_caps_current[index] >> shift) &
2798*4f2df630SAndroid Build Coastguard Worker 			      CCD_CAP_BITMASK;
2799*4f2df630SAndroid Build Coastguard Worker 		cap_default = (ccd_info.ccd_caps_defaults[index] >> shift) &
2800*4f2df630SAndroid Build Coastguard Worker 			      CCD_CAP_BITMASK;
2801*4f2df630SAndroid Build Coastguard Worker 
2802*4f2df630SAndroid Build Coastguard Worker 		if (ccd_info.ccd_force_disabled) {
2803*4f2df630SAndroid Build Coastguard Worker 			is_enabled = 0;
2804*4f2df630SAndroid Build Coastguard Worker 		} else {
2805*4f2df630SAndroid Build Coastguard Worker 			switch (cap_current) {
2806*4f2df630SAndroid Build Coastguard Worker 			case CCD_CAP_STATE_ALWAYS:
2807*4f2df630SAndroid Build Coastguard Worker 				is_enabled = 1;
2808*4f2df630SAndroid Build Coastguard Worker 				break;
2809*4f2df630SAndroid Build Coastguard Worker 			case CCD_CAP_STATE_UNLESS_LOCKED:
2810*4f2df630SAndroid Build Coastguard Worker 				is_enabled = (ccd_info.ccd_state !=
2811*4f2df630SAndroid Build Coastguard Worker 					      CCD_STATE_LOCKED);
2812*4f2df630SAndroid Build Coastguard Worker 				break;
2813*4f2df630SAndroid Build Coastguard Worker 			default:
2814*4f2df630SAndroid Build Coastguard Worker 				is_enabled = (ccd_info.ccd_state ==
2815*4f2df630SAndroid Build Coastguard Worker 					      CCD_STATE_OPENED);
2816*4f2df630SAndroid Build Coastguard Worker 				break;
2817*4f2df630SAndroid Build Coastguard Worker 			}
2818*4f2df630SAndroid Build Coastguard Worker 		}
2819*4f2df630SAndroid Build Coastguard Worker 
2820*4f2df630SAndroid Build Coastguard Worker 		if (show_machine_output) {
2821*4f2df630SAndroid Build Coastguard Worker 			char upper[80];
2822*4f2df630SAndroid Build Coastguard Worker 
2823*4f2df630SAndroid Build Coastguard Worker 			to_upper_underscore(gsc_capability_info[i].name, upper);
2824*4f2df630SAndroid Build Coastguard Worker 			print_machine_output(upper, "%c",
2825*4f2df630SAndroid Build Coastguard Worker 					     is_enabled ? 'Y' : 'N');
2826*4f2df630SAndroid Build Coastguard Worker 		} else {
2827*4f2df630SAndroid Build Coastguard Worker 			printf("  ");
2828*4f2df630SAndroid Build Coastguard Worker 			print_aligned(gsc_capability_info[i].name,
2829*4f2df630SAndroid Build Coastguard Worker 				      name_column_width);
2830*4f2df630SAndroid Build Coastguard Worker 			printf("%c %s", is_enabled ? 'Y' : '-',
2831*4f2df630SAndroid Build Coastguard Worker 			       cap_state_names[cap_current]);
2832*4f2df630SAndroid Build Coastguard Worker 
2833*4f2df630SAndroid Build Coastguard Worker 			if (cap_current != cap_default)
2834*4f2df630SAndroid Build Coastguard Worker 				printf("  (%s)", cap_state_names[cap_default]);
2835*4f2df630SAndroid Build Coastguard Worker 
2836*4f2df630SAndroid Build Coastguard Worker 			printf("\n");
2837*4f2df630SAndroid Build Coastguard Worker 		}
2838*4f2df630SAndroid Build Coastguard Worker 
2839*4f2df630SAndroid Build Coastguard Worker 		if (is_enabled)
2840*4f2df630SAndroid Build Coastguard Worker 			caps_bitmap |= (1 << i);
2841*4f2df630SAndroid Build Coastguard Worker 	}
2842*4f2df630SAndroid Build Coastguard Worker 	if (show_machine_output) {
2843*4f2df630SAndroid Build Coastguard Worker 		print_machine_output("CCD_CAPS_BITMAP", "%#x", caps_bitmap);
2844*4f2df630SAndroid Build Coastguard Worker 		print_machine_output("CAPABILITY_MODIFIED", "%c",
2845*4f2df630SAndroid Build Coastguard Worker 				     (ccd_info.ccd_indicator_bitmap &
2846*4f2df630SAndroid Build Coastguard Worker 				      CCD_INDICATOR_BIT_ALL_CAPS_DEFAULT) ?
2847*4f2df630SAndroid Build Coastguard Worker 					     'N' :
2848*4f2df630SAndroid Build Coastguard Worker 					     'Y');
2849*4f2df630SAndroid Build Coastguard Worker 		print_machine_output("INITIAL_FACTORY_MODE", "%c",
2850*4f2df630SAndroid Build Coastguard Worker 				     (ccd_info.ccd_indicator_bitmap &
2851*4f2df630SAndroid Build Coastguard Worker 				      CCD_INDICATOR_BIT_INITIAL_FACTORY_MODE) ?
2852*4f2df630SAndroid Build Coastguard Worker 					     'Y' :
2853*4f2df630SAndroid Build Coastguard Worker 					     'N');
2854*4f2df630SAndroid Build Coastguard Worker 
2855*4f2df630SAndroid Build Coastguard Worker 	} else {
2856*4f2df630SAndroid Build Coastguard Worker 		printf("CCD caps bitmap: %#x\n", caps_bitmap);
2857*4f2df630SAndroid Build Coastguard Worker 		printf("Capabilities are %s.\n",
2858*4f2df630SAndroid Build Coastguard Worker 		       (ccd_info.ccd_indicator_bitmap &
2859*4f2df630SAndroid Build Coastguard Worker 			CCD_INDICATOR_BIT_ALL_CAPS_DEFAULT) ?
2860*4f2df630SAndroid Build Coastguard Worker 			       "default" :
2861*4f2df630SAndroid Build Coastguard Worker 			       "modified");
2862*4f2df630SAndroid Build Coastguard Worker 		if (ccd_info.ccd_indicator_bitmap &
2863*4f2df630SAndroid Build Coastguard Worker 		    CCD_INDICATOR_BIT_INITIAL_FACTORY_MODE) {
2864*4f2df630SAndroid Build Coastguard Worker 			printf("Chip factory mode.");
2865*4f2df630SAndroid Build Coastguard Worker 		}
2866*4f2df630SAndroid Build Coastguard Worker 	}
2867*4f2df630SAndroid Build Coastguard Worker }
2868*4f2df630SAndroid Build Coastguard Worker 
process_ccd_state(struct transfer_descriptor * td,int ccd_unlock,int ccd_open,int ccd_lock,int ccd_info,bool show_machine_output)2869*4f2df630SAndroid Build Coastguard Worker static void process_ccd_state(struct transfer_descriptor *td, int ccd_unlock,
2870*4f2df630SAndroid Build Coastguard Worker 			      int ccd_open, int ccd_lock, int ccd_info,
2871*4f2df630SAndroid Build Coastguard Worker 			      bool show_machine_output)
2872*4f2df630SAndroid Build Coastguard Worker {
2873*4f2df630SAndroid Build Coastguard Worker 	uint8_t payload;
2874*4f2df630SAndroid Build Coastguard Worker 	/* Max possible response size is when ccd_info is requested. */
2875*4f2df630SAndroid Build Coastguard Worker 	uint8_t response[sizeof(struct ccd_info_response_packet)];
2876*4f2df630SAndroid Build Coastguard Worker 	size_t response_size;
2877*4f2df630SAndroid Build Coastguard Worker 	int rv;
2878*4f2df630SAndroid Build Coastguard Worker 
2879*4f2df630SAndroid Build Coastguard Worker 	if (ccd_unlock)
2880*4f2df630SAndroid Build Coastguard Worker 		payload = CCDV_UNLOCK;
2881*4f2df630SAndroid Build Coastguard Worker 	else if (ccd_open)
2882*4f2df630SAndroid Build Coastguard Worker 		payload = CCDV_OPEN;
2883*4f2df630SAndroid Build Coastguard Worker 	else if (ccd_lock)
2884*4f2df630SAndroid Build Coastguard Worker 		payload = CCDV_LOCK;
2885*4f2df630SAndroid Build Coastguard Worker 	else
2886*4f2df630SAndroid Build Coastguard Worker 		payload = CCDV_GET_INFO;
2887*4f2df630SAndroid Build Coastguard Worker 
2888*4f2df630SAndroid Build Coastguard Worker 	response_size = sizeof(response);
2889*4f2df630SAndroid Build Coastguard Worker 	rv = send_vendor_command(td, VENDOR_CC_CCD, &payload, sizeof(payload),
2890*4f2df630SAndroid Build Coastguard Worker 				 &response, &response_size);
2891*4f2df630SAndroid Build Coastguard Worker 
2892*4f2df630SAndroid Build Coastguard Worker 	/*
2893*4f2df630SAndroid Build Coastguard Worker 	 * If password is required - try sending the same subcommand
2894*4f2df630SAndroid Build Coastguard Worker 	 * accompanied by user password.
2895*4f2df630SAndroid Build Coastguard Worker 	 */
2896*4f2df630SAndroid Build Coastguard Worker 	if (rv == VENDOR_RC_PASSWORD_REQUIRED)
2897*4f2df630SAndroid Build Coastguard Worker 		rv = common_process_password(td, payload);
2898*4f2df630SAndroid Build Coastguard Worker 
2899*4f2df630SAndroid Build Coastguard Worker 	if (rv == VENDOR_RC_SUCCESS) {
2900*4f2df630SAndroid Build Coastguard Worker 		if (ccd_info)
2901*4f2df630SAndroid Build Coastguard Worker 			print_ccd_info(response, response_size,
2902*4f2df630SAndroid Build Coastguard Worker 				       show_machine_output);
2903*4f2df630SAndroid Build Coastguard Worker 		return;
2904*4f2df630SAndroid Build Coastguard Worker 	}
2905*4f2df630SAndroid Build Coastguard Worker 
2906*4f2df630SAndroid Build Coastguard Worker 	if (rv != VENDOR_RC_IN_PROGRESS) {
2907*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Error: rv %d, response %d\n", rv,
2908*4f2df630SAndroid Build Coastguard Worker 			response_size ? response[0] : 0);
2909*4f2df630SAndroid Build Coastguard Worker 		exit(update_error);
2910*4f2df630SAndroid Build Coastguard Worker 	}
2911*4f2df630SAndroid Build Coastguard Worker 
2912*4f2df630SAndroid Build Coastguard Worker 	/*
2913*4f2df630SAndroid Build Coastguard Worker 	 * Physical presence process started, poll for the state the user
2914*4f2df630SAndroid Build Coastguard Worker 	 * asked for. Only two subcommands would return 'IN_PROGRESS'.
2915*4f2df630SAndroid Build Coastguard Worker 	 */
2916*4f2df630SAndroid Build Coastguard Worker 	if (ccd_unlock)
2917*4f2df630SAndroid Build Coastguard Worker 		poll_for_pp(td, VENDOR_CC_CCD, CCDV_PP_POLL_UNLOCK);
2918*4f2df630SAndroid Build Coastguard Worker 	else
2919*4f2df630SAndroid Build Coastguard Worker 		poll_for_pp(td, VENDOR_CC_CCD, CCDV_PP_POLL_OPEN);
2920*4f2df630SAndroid Build Coastguard Worker }
2921*4f2df630SAndroid Build Coastguard Worker 
2922*4f2df630SAndroid Build Coastguard Worker /*
2923*4f2df630SAndroid Build Coastguard Worker  * Ensure that the AllowUnverifiedRO capability is set to always. If called for
2924*4f2df630SAndroid Build Coastguard Worker  * Cr50 (which does not have this capability), the program will exit instead.
2925*4f2df630SAndroid Build Coastguard Worker  */
is_unverified_ro_allowed(struct transfer_descriptor * td)2926*4f2df630SAndroid Build Coastguard Worker static bool is_unverified_ro_allowed(struct transfer_descriptor *td)
2927*4f2df630SAndroid Build Coastguard Worker {
2928*4f2df630SAndroid Build Coastguard Worker 	uint8_t cmd = CCDV_GET_INFO;
2929*4f2df630SAndroid Build Coastguard Worker 	/* Max possible response size is when ccd_info is requested. */
2930*4f2df630SAndroid Build Coastguard Worker 	uint8_t response[sizeof(struct ccd_info_response_packet)];
2931*4f2df630SAndroid Build Coastguard Worker 	size_t response_size = sizeof(response);
2932*4f2df630SAndroid Build Coastguard Worker 	struct ccd_info_response ccd_info;
2933*4f2df630SAndroid Build Coastguard Worker 	uint32_t ccd_info_version;
2934*4f2df630SAndroid Build Coastguard Worker 	int allow_unverified_ro_cap;
2935*4f2df630SAndroid Build Coastguard Worker 	int rv;
2936*4f2df630SAndroid Build Coastguard Worker 
2937*4f2df630SAndroid Build Coastguard Worker 	rv = send_vendor_command(td, VENDOR_CC_CCD, &cmd, sizeof(cmd),
2938*4f2df630SAndroid Build Coastguard Worker 				 &response, &response_size);
2939*4f2df630SAndroid Build Coastguard Worker 	if (rv != VENDOR_RC_SUCCESS) {
2940*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Error: rv %d, response %d\n", rv,
2941*4f2df630SAndroid Build Coastguard Worker 			response_size ? response[0] : 0);
2942*4f2df630SAndroid Build Coastguard Worker 		exit(update_error);
2943*4f2df630SAndroid Build Coastguard Worker 	}
2944*4f2df630SAndroid Build Coastguard Worker 	ccd_info_version = validate_into_ccd_info_response(
2945*4f2df630SAndroid Build Coastguard Worker 		response, response_size, &ccd_info);
2946*4f2df630SAndroid Build Coastguard Worker 	if (ccd_info_version != 1) {
2947*4f2df630SAndroid Build Coastguard Worker 		/*
2948*4f2df630SAndroid Build Coastguard Worker 		 * We also don't know what order future ccd info versions will
2949*4f2df630SAndroid Build Coastguard Worker 		 * place the AllowUnverifiedRO capability. We need to ensure
2950*4f2df630SAndroid Build Coastguard Worker 		 * that the array lookup below is still correct for future
2951*4f2df630SAndroid Build Coastguard Worker 		 * version if/when they become available
2952*4f2df630SAndroid Build Coastguard Worker 		 */
2953*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr,
2954*4f2df630SAndroid Build Coastguard Worker 			"Error: CCD info version incorrect (%d).\n"
2955*4f2df630SAndroid Build Coastguard Worker 			"Cr50 does not support this operation.\n",
2956*4f2df630SAndroid Build Coastguard Worker 			ccd_info_version);
2957*4f2df630SAndroid Build Coastguard Worker 		exit(update_error);
2958*4f2df630SAndroid Build Coastguard Worker 	}
2959*4f2df630SAndroid Build Coastguard Worker 	/*
2960*4f2df630SAndroid Build Coastguard Worker 	 * Pull out the AllowUnverifiedRo cap from the list.
2961*4f2df630SAndroid Build Coastguard Worker 	 * See ti50_cap_info for full order of V1 capabilities
2962*4f2df630SAndroid Build Coastguard Worker 	 */
2963*4f2df630SAndroid Build Coastguard Worker 	allow_unverified_ro_cap = (ccd_info.ccd_caps_current[1] >> 10) &
2964*4f2df630SAndroid Build Coastguard Worker 				  CCD_CAP_BITMASK;
2965*4f2df630SAndroid Build Coastguard Worker 
2966*4f2df630SAndroid Build Coastguard Worker 	return allow_unverified_ro_cap == CCD_CAP_STATE_ALWAYS;
2967*4f2df630SAndroid Build Coastguard Worker }
2968*4f2df630SAndroid Build Coastguard Worker 
process_wp(struct transfer_descriptor * td,enum wp_options wp)2969*4f2df630SAndroid Build Coastguard Worker static enum exit_values process_wp(struct transfer_descriptor *td,
2970*4f2df630SAndroid Build Coastguard Worker 				   enum wp_options wp)
2971*4f2df630SAndroid Build Coastguard Worker {
2972*4f2df630SAndroid Build Coastguard Worker 	size_t response_size;
2973*4f2df630SAndroid Build Coastguard Worker 	uint8_t response;
2974*4f2df630SAndroid Build Coastguard Worker 	int rv = 0;
2975*4f2df630SAndroid Build Coastguard Worker 	uint8_t command = wp;
2976*4f2df630SAndroid Build Coastguard Worker 
2977*4f2df630SAndroid Build Coastguard Worker 	response_size = sizeof(response);
2978*4f2df630SAndroid Build Coastguard Worker 
2979*4f2df630SAndroid Build Coastguard Worker 	/*
2980*4f2df630SAndroid Build Coastguard Worker 	 * Ti50 supports enable, disable, and follow, but cr50 doesn't and will
2981*4f2df630SAndroid Build Coastguard Worker 	 * return an error from the chip. gsctool supports the superset.
2982*4f2df630SAndroid Build Coastguard Worker 	 */
2983*4f2df630SAndroid Build Coastguard Worker 	switch (wp) {
2984*4f2df630SAndroid Build Coastguard Worker 	case WP_DISABLE:
2985*4f2df630SAndroid Build Coastguard Worker 	case WP_FOLLOW:
2986*4f2df630SAndroid Build Coastguard Worker 		/* Ensure that AllowUnverifiedRo is true then fallthrough */
2987*4f2df630SAndroid Build Coastguard Worker 		if (!is_unverified_ro_allowed(td)) {
2988*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr,
2989*4f2df630SAndroid Build Coastguard Worker 				"Error: Must set AllowUnverifiedRo cap to "
2990*4f2df630SAndroid Build Coastguard Worker 				"always first.\n"
2991*4f2df630SAndroid Build Coastguard Worker 				"Otherwise changes to AP RO may cause system "
2992*4f2df630SAndroid Build Coastguard Worker 				"to no longer boot.\n"
2993*4f2df630SAndroid Build Coastguard Worker 				"Use `gsctool -I AllowUnverifiedRo:always`\n");
2994*4f2df630SAndroid Build Coastguard Worker 			return update_error;
2995*4f2df630SAndroid Build Coastguard Worker 		}
2996*4f2df630SAndroid Build Coastguard Worker 	case WP_ENABLE:
2997*4f2df630SAndroid Build Coastguard Worker 		printf("Setting WP\n");
2998*4f2df630SAndroid Build Coastguard Worker 		/* Enabling write protect doesn't require any special checks */
2999*4f2df630SAndroid Build Coastguard Worker 		rv = send_vendor_command(td, VENDOR_CC_WP, &command,
3000*4f2df630SAndroid Build Coastguard Worker 					 sizeof(command), &response,
3001*4f2df630SAndroid Build Coastguard Worker 					 &response_size);
3002*4f2df630SAndroid Build Coastguard Worker 		break;
3003*4f2df630SAndroid Build Coastguard Worker 	default:
3004*4f2df630SAndroid Build Coastguard Worker 		/* Just check the wp status without a parameter */
3005*4f2df630SAndroid Build Coastguard Worker 		printf("Getting WP\n");
3006*4f2df630SAndroid Build Coastguard Worker 		rv = send_vendor_command(td, VENDOR_CC_WP, NULL, 0, &response,
3007*4f2df630SAndroid Build Coastguard Worker 					 &response_size);
3008*4f2df630SAndroid Build Coastguard Worker 	}
3009*4f2df630SAndroid Build Coastguard Worker 
3010*4f2df630SAndroid Build Coastguard Worker 	/*
3011*4f2df630SAndroid Build Coastguard Worker 	 * If we tried to disable and we got in progress, then prompt the
3012*4f2df630SAndroid Build Coastguard Worker 	 * user for power button pushes
3013*4f2df630SAndroid Build Coastguard Worker 	 */
3014*4f2df630SAndroid Build Coastguard Worker 	if (wp == WP_DISABLE && rv == VENDOR_RC_IN_PROGRESS) {
3015*4f2df630SAndroid Build Coastguard Worker 		/* Progress physical button request then get the wp again */
3016*4f2df630SAndroid Build Coastguard Worker 		poll_for_pp(td, VENDOR_CC_CCD, CCDV_PP_POLL_WP_DISABLE);
3017*4f2df630SAndroid Build Coastguard Worker 		/* Reset expected response size and get WP status again */
3018*4f2df630SAndroid Build Coastguard Worker 		response_size = sizeof(response);
3019*4f2df630SAndroid Build Coastguard Worker 		rv = send_vendor_command(td, VENDOR_CC_WP, NULL, 0, &response,
3020*4f2df630SAndroid Build Coastguard Worker 					 &response_size);
3021*4f2df630SAndroid Build Coastguard Worker 	}
3022*4f2df630SAndroid Build Coastguard Worker 	/*
3023*4f2df630SAndroid Build Coastguard Worker 	 * Give user a more detailed error for not allowed. That means CCD
3024*4f2df630SAndroid Build Coastguard Worker 	 * must be open before we can process the command
3025*4f2df630SAndroid Build Coastguard Worker 	 */
3026*4f2df630SAndroid Build Coastguard Worker 	if (rv == VENDOR_RC_NOT_ALLOWED) {
3027*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Error: OverrideWP must be enabled first.\n"
3028*4f2df630SAndroid Build Coastguard Worker 				"Use `gsctool -I OverrideWP:always`\n");
3029*4f2df630SAndroid Build Coastguard Worker 		return update_error;
3030*4f2df630SAndroid Build Coastguard Worker 	}
3031*4f2df630SAndroid Build Coastguard Worker 
3032*4f2df630SAndroid Build Coastguard Worker 	if (rv != VENDOR_RC_SUCCESS) {
3033*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Error %d %sting write protect\n", rv,
3034*4f2df630SAndroid Build Coastguard Worker 			(wp == WP_ENABLE) ? "set" : "get");
3035*4f2df630SAndroid Build Coastguard Worker 		if (wp == WP_ENABLE) {
3036*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr,
3037*4f2df630SAndroid Build Coastguard Worker 				"Early Cr50 versions do not support setting WP"
3038*4f2df630SAndroid Build Coastguard Worker 				"\n");
3039*4f2df630SAndroid Build Coastguard Worker 		}
3040*4f2df630SAndroid Build Coastguard Worker 		return update_error;
3041*4f2df630SAndroid Build Coastguard Worker 	}
3042*4f2df630SAndroid Build Coastguard Worker 	if (response_size != sizeof(response)) {
3043*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr,
3044*4f2df630SAndroid Build Coastguard Worker 			"Unexpected response size %zd while getting "
3045*4f2df630SAndroid Build Coastguard Worker 			"write protect\n",
3046*4f2df630SAndroid Build Coastguard Worker 			response_size);
3047*4f2df630SAndroid Build Coastguard Worker 		return update_error;
3048*4f2df630SAndroid Build Coastguard Worker 	}
3049*4f2df630SAndroid Build Coastguard Worker 
3050*4f2df630SAndroid Build Coastguard Worker 	printf("WP: %08x\n", response);
3051*4f2df630SAndroid Build Coastguard Worker 	printf("Flash WP: %s%s%s\n",
3052*4f2df630SAndroid Build Coastguard Worker 	       response & WPV_FWMP_FORCE_WP_EN ? "fwmp " : "",
3053*4f2df630SAndroid Build Coastguard Worker 	       response & WPV_FORCE ? "forced " : "",
3054*4f2df630SAndroid Build Coastguard Worker 	       response & WPV_ENABLE ? "enabled" : "disabled");
3055*4f2df630SAndroid Build Coastguard Worker 	printf(" at boot: %s\n",
3056*4f2df630SAndroid Build Coastguard Worker 	       response & WPV_FWMP_FORCE_WP_EN ? "fwmp enabled" :
3057*4f2df630SAndroid Build Coastguard Worker 	       !(response & WPV_ATBOOT_SET)    ? "follow_batt_pres" :
3058*4f2df630SAndroid Build Coastguard Worker 	       response & WPV_ATBOOT_ENABLE    ? "forced enabled" :
3059*4f2df630SAndroid Build Coastguard Worker 						 "forced disabled");
3060*4f2df630SAndroid Build Coastguard Worker 	return noop;
3061*4f2df630SAndroid Build Coastguard Worker }
3062*4f2df630SAndroid Build Coastguard Worker 
process_get_chassis_open(struct transfer_descriptor * td)3063*4f2df630SAndroid Build Coastguard Worker static enum exit_values process_get_chassis_open(struct transfer_descriptor *td)
3064*4f2df630SAndroid Build Coastguard Worker {
3065*4f2df630SAndroid Build Coastguard Worker 	struct chassis_open_repsonse {
3066*4f2df630SAndroid Build Coastguard Worker 		uint8_t version;
3067*4f2df630SAndroid Build Coastguard Worker 		uint8_t chassis_open;
3068*4f2df630SAndroid Build Coastguard Worker 	} response;
3069*4f2df630SAndroid Build Coastguard Worker 	size_t response_size;
3070*4f2df630SAndroid Build Coastguard Worker 	int rv;
3071*4f2df630SAndroid Build Coastguard Worker 
3072*4f2df630SAndroid Build Coastguard Worker 	response_size = sizeof(response);
3073*4f2df630SAndroid Build Coastguard Worker 
3074*4f2df630SAndroid Build Coastguard Worker 	rv = send_vendor_command(td, VENDOR_CC_GET_CHASSIS_OPEN, NULL, 0,
3075*4f2df630SAndroid Build Coastguard Worker 				 &response, &response_size);
3076*4f2df630SAndroid Build Coastguard Worker 
3077*4f2df630SAndroid Build Coastguard Worker 	if (rv != VENDOR_RC_SUCCESS) {
3078*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Error %d getting chassis open\n", rv);
3079*4f2df630SAndroid Build Coastguard Worker 		return update_error;
3080*4f2df630SAndroid Build Coastguard Worker 	}
3081*4f2df630SAndroid Build Coastguard Worker 	if (response_size != sizeof(response)) {
3082*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr,
3083*4f2df630SAndroid Build Coastguard Worker 			"Unexpected response size %zd while getting "
3084*4f2df630SAndroid Build Coastguard Worker 			"chassis open\n",
3085*4f2df630SAndroid Build Coastguard Worker 			response_size);
3086*4f2df630SAndroid Build Coastguard Worker 		return update_error;
3087*4f2df630SAndroid Build Coastguard Worker 	}
3088*4f2df630SAndroid Build Coastguard Worker 	if (response.version != 1) {
3089*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr,
3090*4f2df630SAndroid Build Coastguard Worker 			"Unexpected response version %d while getting "
3091*4f2df630SAndroid Build Coastguard Worker 			"chassis open\n",
3092*4f2df630SAndroid Build Coastguard Worker 			response.version);
3093*4f2df630SAndroid Build Coastguard Worker 		return update_error;
3094*4f2df630SAndroid Build Coastguard Worker 	}
3095*4f2df630SAndroid Build Coastguard Worker 
3096*4f2df630SAndroid Build Coastguard Worker 	printf("Chassis Open: %s\n",
3097*4f2df630SAndroid Build Coastguard Worker 	       response.chassis_open & 1 ? "true" : "false");
3098*4f2df630SAndroid Build Coastguard Worker 	return noop;
3099*4f2df630SAndroid Build Coastguard Worker }
3100*4f2df630SAndroid Build Coastguard Worker 
process_get_dev_ids(struct transfer_descriptor * td,bool show_machine_output)3101*4f2df630SAndroid Build Coastguard Worker static enum exit_values process_get_dev_ids(struct transfer_descriptor *td,
3102*4f2df630SAndroid Build Coastguard Worker 					    bool show_machine_output)
3103*4f2df630SAndroid Build Coastguard Worker {
3104*4f2df630SAndroid Build Coastguard Worker 	struct sys_info_repsonse {
3105*4f2df630SAndroid Build Coastguard Worker 		uint32_t ro_keyid;
3106*4f2df630SAndroid Build Coastguard Worker 		uint32_t rw_keyid;
3107*4f2df630SAndroid Build Coastguard Worker 		uint32_t dev_id0;
3108*4f2df630SAndroid Build Coastguard Worker 		uint32_t dev_id1;
3109*4f2df630SAndroid Build Coastguard Worker 	} response;
3110*4f2df630SAndroid Build Coastguard Worker 	size_t response_size;
3111*4f2df630SAndroid Build Coastguard Worker 	int rv;
3112*4f2df630SAndroid Build Coastguard Worker 
3113*4f2df630SAndroid Build Coastguard Worker 	response_size = sizeof(response);
3114*4f2df630SAndroid Build Coastguard Worker 
3115*4f2df630SAndroid Build Coastguard Worker 	rv = send_vendor_command(td, VENDOR_CC_SYSINFO, NULL, 0, &response,
3116*4f2df630SAndroid Build Coastguard Worker 				 &response_size);
3117*4f2df630SAndroid Build Coastguard Worker 
3118*4f2df630SAndroid Build Coastguard Worker 	if (rv != VENDOR_RC_SUCCESS) {
3119*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Error %d getting device ids\n", rv);
3120*4f2df630SAndroid Build Coastguard Worker 		return update_error;
3121*4f2df630SAndroid Build Coastguard Worker 	}
3122*4f2df630SAndroid Build Coastguard Worker 	if (response_size != sizeof(response)) {
3123*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr,
3124*4f2df630SAndroid Build Coastguard Worker 			"Unexpected response size %zd while getting "
3125*4f2df630SAndroid Build Coastguard Worker 			"device ids\n",
3126*4f2df630SAndroid Build Coastguard Worker 			response_size);
3127*4f2df630SAndroid Build Coastguard Worker 		return update_error;
3128*4f2df630SAndroid Build Coastguard Worker 	}
3129*4f2df630SAndroid Build Coastguard Worker 
3130*4f2df630SAndroid Build Coastguard Worker 	/* Convert from BE transimision format */
3131*4f2df630SAndroid Build Coastguard Worker 	response.dev_id0 = be32toh(response.dev_id0);
3132*4f2df630SAndroid Build Coastguard Worker 	response.dev_id1 = be32toh(response.dev_id1);
3133*4f2df630SAndroid Build Coastguard Worker 
3134*4f2df630SAndroid Build Coastguard Worker 	if (show_machine_output) {
3135*4f2df630SAndroid Build Coastguard Worker 		print_machine_output("DEV_ID0", "%08x", response.dev_id0);
3136*4f2df630SAndroid Build Coastguard Worker 		print_machine_output("DEV_ID1", "%08x", response.dev_id1);
3137*4f2df630SAndroid Build Coastguard Worker 	} else {
3138*4f2df630SAndroid Build Coastguard Worker 		printf("DEVID: 0x%08x 0x%08x\n", response.dev_id0,
3139*4f2df630SAndroid Build Coastguard Worker 		       response.dev_id1);
3140*4f2df630SAndroid Build Coastguard Worker 	}
3141*4f2df630SAndroid Build Coastguard Worker 	return noop;
3142*4f2df630SAndroid Build Coastguard Worker }
3143*4f2df630SAndroid Build Coastguard Worker 
process_get_aprov_reset_counts(struct transfer_descriptor * td)3144*4f2df630SAndroid Build Coastguard Worker static enum exit_values process_get_aprov_reset_counts(
3145*4f2df630SAndroid Build Coastguard Worker 	struct transfer_descriptor *td)
3146*4f2df630SAndroid Build Coastguard Worker {
3147*4f2df630SAndroid Build Coastguard Worker 	/*
3148*4f2df630SAndroid Build Coastguard Worker 	 * We shouldn't need a version for this command since the entire
3149*4f2df630SAndroid Build Coastguard Worker 	 * command should be removed after feature launch. However, if we
3150*4f2df630SAndroid Build Coastguard Worker 	 * did need a version, the upper 7 bits of allow_unverified_ro are
3151*4f2df630SAndroid Build Coastguard Worker 	 * unused.
3152*4f2df630SAndroid Build Coastguard Worker 	 */
3153*4f2df630SAndroid Build Coastguard Worker 	struct aprov_reset_counts {
3154*4f2df630SAndroid Build Coastguard Worker 		uint8_t allow_unverified_ro;
3155*4f2df630SAndroid Build Coastguard Worker 		uint8_t settings_change;
3156*4f2df630SAndroid Build Coastguard Worker 		uint8_t external_wp;
3157*4f2df630SAndroid Build Coastguard Worker 		uint8_t internal_wp;
3158*4f2df630SAndroid Build Coastguard Worker 	} response;
3159*4f2df630SAndroid Build Coastguard Worker 	size_t response_size;
3160*4f2df630SAndroid Build Coastguard Worker 	int rv;
3161*4f2df630SAndroid Build Coastguard Worker 	int32_t allow_unverified_sign = 1;
3162*4f2df630SAndroid Build Coastguard Worker 
3163*4f2df630SAndroid Build Coastguard Worker 	response_size = sizeof(response);
3164*4f2df630SAndroid Build Coastguard Worker 
3165*4f2df630SAndroid Build Coastguard Worker 	rv = send_vendor_command(td, VENDOR_CC_GET_AP_RO_RESET_COUNTS, NULL, 0,
3166*4f2df630SAndroid Build Coastguard Worker 				 &response, &response_size);
3167*4f2df630SAndroid Build Coastguard Worker 
3168*4f2df630SAndroid Build Coastguard Worker 	if (rv != VENDOR_RC_SUCCESS) {
3169*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Error %d getting reset counts\n", rv);
3170*4f2df630SAndroid Build Coastguard Worker 		return update_error;
3171*4f2df630SAndroid Build Coastguard Worker 	}
3172*4f2df630SAndroid Build Coastguard Worker 	if (response_size != sizeof(response)) {
3173*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr,
3174*4f2df630SAndroid Build Coastguard Worker 			"Unexpected response size %zd while getting "
3175*4f2df630SAndroid Build Coastguard Worker 			"reset counts\n",
3176*4f2df630SAndroid Build Coastguard Worker 			response_size);
3177*4f2df630SAndroid Build Coastguard Worker 		return update_error;
3178*4f2df630SAndroid Build Coastguard Worker 	}
3179*4f2df630SAndroid Build Coastguard Worker 
3180*4f2df630SAndroid Build Coastguard Worker 	/* Change all of the values to negative if unverified RO is allowed. */
3181*4f2df630SAndroid Build Coastguard Worker 	if (response.allow_unverified_ro != 0)
3182*4f2df630SAndroid Build Coastguard Worker 		allow_unverified_sign = -1;
3183*4f2df630SAndroid Build Coastguard Worker 
3184*4f2df630SAndroid Build Coastguard Worker 	const uint32_t combined = response.settings_change +
3185*4f2df630SAndroid Build Coastguard Worker 				  (response.external_wp << 8) +
3186*4f2df630SAndroid Build Coastguard Worker 				  (response.internal_wp << 16);
3187*4f2df630SAndroid Build Coastguard Worker 
3188*4f2df630SAndroid Build Coastguard Worker 	/*
3189*4f2df630SAndroid Build Coastguard Worker 	 * The `cr50-metrics.conf` file depends on these string names. Do
3190*4f2df630SAndroid Build Coastguard Worker 	 * not change without updated that file.
3191*4f2df630SAndroid Build Coastguard Worker 	 */
3192*4f2df630SAndroid Build Coastguard Worker 	print_machine_output("COMBINED", "0x%08x",
3193*4f2df630SAndroid Build Coastguard Worker 			     allow_unverified_sign * combined);
3194*4f2df630SAndroid Build Coastguard Worker 	print_machine_output("SETTINGS_CHANGE", "0x%08x",
3195*4f2df630SAndroid Build Coastguard Worker 			     allow_unverified_sign * response.settings_change);
3196*4f2df630SAndroid Build Coastguard Worker 	print_machine_output("EXTERNAL_WP", "0x%08x",
3197*4f2df630SAndroid Build Coastguard Worker 			     allow_unverified_sign * response.external_wp);
3198*4f2df630SAndroid Build Coastguard Worker 	print_machine_output("INTERNAL_WP", "0x%08x",
3199*4f2df630SAndroid Build Coastguard Worker 			     allow_unverified_sign * response.internal_wp);
3200*4f2df630SAndroid Build Coastguard Worker 	return noop;
3201*4f2df630SAndroid Build Coastguard Worker }
3202*4f2df630SAndroid Build Coastguard Worker 
process_get_apro_hash(struct transfer_descriptor * td)3203*4f2df630SAndroid Build Coastguard Worker static int process_get_apro_hash(struct transfer_descriptor *td)
3204*4f2df630SAndroid Build Coastguard Worker {
3205*4f2df630SAndroid Build Coastguard Worker 	size_t response_size;
3206*4f2df630SAndroid Build Coastguard Worker 	uint8_t response[SHA256_DIGEST_SIZE];
3207*4f2df630SAndroid Build Coastguard Worker 	const char *const desc = "getting apro hash";
3208*4f2df630SAndroid Build Coastguard Worker 	int rv = 0;
3209*4f2df630SAndroid Build Coastguard Worker 	int i;
3210*4f2df630SAndroid Build Coastguard Worker 
3211*4f2df630SAndroid Build Coastguard Worker 	response_size = sizeof(response);
3212*4f2df630SAndroid Build Coastguard Worker 
3213*4f2df630SAndroid Build Coastguard Worker 	rv = send_vendor_command(td, VENDOR_CC_GET_AP_RO_HASH, NULL, 0,
3214*4f2df630SAndroid Build Coastguard Worker 				 &response, &response_size);
3215*4f2df630SAndroid Build Coastguard Worker 
3216*4f2df630SAndroid Build Coastguard Worker 	if (response_size == 1) {
3217*4f2df630SAndroid Build Coastguard Worker 		printf("get hash rc: %d ", response[0]);
3218*4f2df630SAndroid Build Coastguard Worker 		switch (response[0]) {
3219*4f2df630SAndroid Build Coastguard Worker 		case ARCVE_NOT_PROGRAMMED:
3220*4f2df630SAndroid Build Coastguard Worker 			printf("AP RO hash unprogrammed\n");
3221*4f2df630SAndroid Build Coastguard Worker 			return 0;
3222*4f2df630SAndroid Build Coastguard Worker 		case ARCVE_FLASH_READ_FAILED:
3223*4f2df630SAndroid Build Coastguard Worker 			printf("flash read failed\n");
3224*4f2df630SAndroid Build Coastguard Worker 			return 0;
3225*4f2df630SAndroid Build Coastguard Worker 		case ARCVE_BOARD_ID_BLOCKED:
3226*4f2df630SAndroid Build Coastguard Worker 			printf("board id blocked\n");
3227*4f2df630SAndroid Build Coastguard Worker 			return 0;
3228*4f2df630SAndroid Build Coastguard Worker 		default:
3229*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr, "unexpected error\n");
3230*4f2df630SAndroid Build Coastguard Worker 			return update_error;
3231*4f2df630SAndroid Build Coastguard Worker 		}
3232*4f2df630SAndroid Build Coastguard Worker 	} else if (rv != VENDOR_RC_SUCCESS) {
3233*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Error %d %s\n", rv, desc);
3234*4f2df630SAndroid Build Coastguard Worker 		return update_error;
3235*4f2df630SAndroid Build Coastguard Worker 	} else if (response_size != SHA256_DIGEST_SIZE) {
3236*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Error in the size of response, %zu.\n",
3237*4f2df630SAndroid Build Coastguard Worker 			response_size);
3238*4f2df630SAndroid Build Coastguard Worker 		return update_error;
3239*4f2df630SAndroid Build Coastguard Worker 	}
3240*4f2df630SAndroid Build Coastguard Worker 	printf("digest: ");
3241*4f2df630SAndroid Build Coastguard Worker 	for (i = 0; i < SHA256_DIGEST_SIZE; i++)
3242*4f2df630SAndroid Build Coastguard Worker 		printf("%x", response[i]);
3243*4f2df630SAndroid Build Coastguard Worker 	printf("\n");
3244*4f2df630SAndroid Build Coastguard Worker 	return 0;
3245*4f2df630SAndroid Build Coastguard Worker }
3246*4f2df630SAndroid Build Coastguard Worker 
process_get_apro_boot_status(struct transfer_descriptor * td)3247*4f2df630SAndroid Build Coastguard Worker static int process_get_apro_boot_status(struct transfer_descriptor *td)
3248*4f2df630SAndroid Build Coastguard Worker {
3249*4f2df630SAndroid Build Coastguard Worker 	size_t response_size;
3250*4f2df630SAndroid Build Coastguard Worker 	uint8_t response;
3251*4f2df630SAndroid Build Coastguard Worker 	const char *const desc = "getting apro status";
3252*4f2df630SAndroid Build Coastguard Worker 	int rv = 0;
3253*4f2df630SAndroid Build Coastguard Worker 
3254*4f2df630SAndroid Build Coastguard Worker 	response_size = sizeof(response);
3255*4f2df630SAndroid Build Coastguard Worker 
3256*4f2df630SAndroid Build Coastguard Worker 	rv = send_vendor_command(td, VENDOR_CC_GET_AP_RO_STATUS, NULL, 0,
3257*4f2df630SAndroid Build Coastguard Worker 				 &response, &response_size);
3258*4f2df630SAndroid Build Coastguard Worker 	if (rv != VENDOR_RC_SUCCESS) {
3259*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Error %d %s\n", rv, desc);
3260*4f2df630SAndroid Build Coastguard Worker 		return update_error;
3261*4f2df630SAndroid Build Coastguard Worker 	}
3262*4f2df630SAndroid Build Coastguard Worker 	if (response_size != 1) {
3263*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Unexpected response size %zd while %s\n",
3264*4f2df630SAndroid Build Coastguard Worker 			response_size, desc);
3265*4f2df630SAndroid Build Coastguard Worker 		return update_error;
3266*4f2df630SAndroid Build Coastguard Worker 	}
3267*4f2df630SAndroid Build Coastguard Worker 
3268*4f2df630SAndroid Build Coastguard Worker 	/* Print the response and meaning, as in 'enum ap_ro_status'. */
3269*4f2df630SAndroid Build Coastguard Worker 	printf("apro result (%d) : ", response);
3270*4f2df630SAndroid Build Coastguard Worker 	switch (response) {
3271*4f2df630SAndroid Build Coastguard Worker 	case AP_RO_NOT_RUN:
3272*4f2df630SAndroid Build Coastguard Worker 		printf("not run\n");
3273*4f2df630SAndroid Build Coastguard Worker 		break;
3274*4f2df630SAndroid Build Coastguard Worker 	case AP_RO_PASS:
3275*4f2df630SAndroid Build Coastguard Worker 	case AP_RO_V2_SUCCESS:
3276*4f2df630SAndroid Build Coastguard Worker 		printf("pass\n");
3277*4f2df630SAndroid Build Coastguard Worker 		break;
3278*4f2df630SAndroid Build Coastguard Worker 	case AP_RO_PASS_UNVERIFIED_GBB:
3279*4f2df630SAndroid Build Coastguard Worker 		printf("pass - unverified gbb!\n");
3280*4f2df630SAndroid Build Coastguard Worker 		break;
3281*4f2df630SAndroid Build Coastguard Worker 	case AP_RO_V2_NON_ZERO_GBB_FLAGS:
3282*4f2df630SAndroid Build Coastguard Worker 		printf("pass - except non-zero gbb flags!\n");
3283*4f2df630SAndroid Build Coastguard Worker 		break;
3284*4f2df630SAndroid Build Coastguard Worker 	case AP_RO_FAIL:
3285*4f2df630SAndroid Build Coastguard Worker 	case AP_RO_V2_FAILED_VERIFICATION:
3286*4f2df630SAndroid Build Coastguard Worker 		printf("FAIL\n");
3287*4f2df630SAndroid Build Coastguard Worker 		break;
3288*4f2df630SAndroid Build Coastguard Worker 	case AP_RO_UNSUPPORTED_TRIGGERED:
3289*4f2df630SAndroid Build Coastguard Worker 		printf("not supported\ntriggered: yes\n");
3290*4f2df630SAndroid Build Coastguard Worker 		break;
3291*4f2df630SAndroid Build Coastguard Worker 	case AP_RO_UNSUPPORTED_UNKNOWN:
3292*4f2df630SAndroid Build Coastguard Worker 		printf("not supported\ntriggered: unknown\n");
3293*4f2df630SAndroid Build Coastguard Worker 		break;
3294*4f2df630SAndroid Build Coastguard Worker 	case AP_RO_UNSUPPORTED_NOT_TRIGGERED:
3295*4f2df630SAndroid Build Coastguard Worker 		printf("not supported\ntriggered: no\n");
3296*4f2df630SAndroid Build Coastguard Worker 		break;
3297*4f2df630SAndroid Build Coastguard Worker 	case AP_RO_IN_PROGRESS:
3298*4f2df630SAndroid Build Coastguard Worker 		printf("in progress.");
3299*4f2df630SAndroid Build Coastguard Worker 		break;
3300*4f2df630SAndroid Build Coastguard Worker 	case AP_RO_V2_INCONSISTENT_GSCVD:
3301*4f2df630SAndroid Build Coastguard Worker 		printf("inconsistent gscvd\n");
3302*4f2df630SAndroid Build Coastguard Worker 		break;
3303*4f2df630SAndroid Build Coastguard Worker 	case AP_RO_V2_INCONSISTENT_KEYBLOCK:
3304*4f2df630SAndroid Build Coastguard Worker 		printf("inconsistent keyblock\n");
3305*4f2df630SAndroid Build Coastguard Worker 		break;
3306*4f2df630SAndroid Build Coastguard Worker 	case AP_RO_V2_INCONSISTENT_KEY:
3307*4f2df630SAndroid Build Coastguard Worker 		printf("inconsistent key\n");
3308*4f2df630SAndroid Build Coastguard Worker 		break;
3309*4f2df630SAndroid Build Coastguard Worker 	case AP_RO_V2_SPI_READ:
3310*4f2df630SAndroid Build Coastguard Worker 		printf("spi read failure\n");
3311*4f2df630SAndroid Build Coastguard Worker 		break;
3312*4f2df630SAndroid Build Coastguard Worker 	case AP_RO_V2_UNSUPPORTED_CRYPTO_ALGORITHM:
3313*4f2df630SAndroid Build Coastguard Worker 		printf("unsupported crypto algo\n");
3314*4f2df630SAndroid Build Coastguard Worker 		break;
3315*4f2df630SAndroid Build Coastguard Worker 	case AP_RO_V2_VERSION_MISMATCH:
3316*4f2df630SAndroid Build Coastguard Worker 		printf("header version mismatch\n");
3317*4f2df630SAndroid Build Coastguard Worker 		break;
3318*4f2df630SAndroid Build Coastguard Worker 	case AP_RO_V2_OUT_OF_MEMORY:
3319*4f2df630SAndroid Build Coastguard Worker 		printf("out of memory\n");
3320*4f2df630SAndroid Build Coastguard Worker 		break;
3321*4f2df630SAndroid Build Coastguard Worker 	case AP_RO_V2_INTERNAL:
3322*4f2df630SAndroid Build Coastguard Worker 		printf("internal\n");
3323*4f2df630SAndroid Build Coastguard Worker 		break;
3324*4f2df630SAndroid Build Coastguard Worker 	case AP_RO_V2_TOO_BIG:
3325*4f2df630SAndroid Build Coastguard Worker 		printf("too many areas\n");
3326*4f2df630SAndroid Build Coastguard Worker 		break;
3327*4f2df630SAndroid Build Coastguard Worker 	case AP_RO_V2_MISSING_GSCVD:
3328*4f2df630SAndroid Build Coastguard Worker 		printf("missing gscvd\n");
3329*4f2df630SAndroid Build Coastguard Worker 		break;
3330*4f2df630SAndroid Build Coastguard Worker 	case AP_RO_V2_BOARD_ID_MISMATCH:
3331*4f2df630SAndroid Build Coastguard Worker 		printf("board id mismatch\n");
3332*4f2df630SAndroid Build Coastguard Worker 		break;
3333*4f2df630SAndroid Build Coastguard Worker 	case AP_RO_V2_SETTING_NOT_PROVISIONED:
3334*4f2df630SAndroid Build Coastguard Worker 		printf("setting not provisioned\n");
3335*4f2df630SAndroid Build Coastguard Worker 		break;
3336*4f2df630SAndroid Build Coastguard Worker 	case AP_RO_V2_WRONG_ROOT_KEY:
3337*4f2df630SAndroid Build Coastguard Worker 		printf("key is recognized but disallowed (e.g. preMP key)\n");
3338*4f2df630SAndroid Build Coastguard Worker 		break;
3339*4f2df630SAndroid Build Coastguard Worker 	default:
3340*4f2df630SAndroid Build Coastguard Worker 		printf("unknown\n");
3341*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "unknown status\n");
3342*4f2df630SAndroid Build Coastguard Worker 		return update_error;
3343*4f2df630SAndroid Build Coastguard Worker 	}
3344*4f2df630SAndroid Build Coastguard Worker 
3345*4f2df630SAndroid Build Coastguard Worker 	return 0;
3346*4f2df630SAndroid Build Coastguard Worker }
3347*4f2df630SAndroid Build Coastguard Worker 
process_arv_config_spi_addr_mode(struct transfer_descriptor * td,int arv_config_spi_addr_mode)3348*4f2df630SAndroid Build Coastguard Worker static int process_arv_config_spi_addr_mode(struct transfer_descriptor *td,
3349*4f2df630SAndroid Build Coastguard Worker 					    int arv_config_spi_addr_mode)
3350*4f2df630SAndroid Build Coastguard Worker {
3351*4f2df630SAndroid Build Coastguard Worker 	enum ap_ro_config_spi_mode_e {
3352*4f2df630SAndroid Build Coastguard Worker 		ap_ro_spi_config_3byte = 0,
3353*4f2df630SAndroid Build Coastguard Worker 		ap_ro_spi_config_4byte = 1,
3354*4f2df630SAndroid Build Coastguard Worker 	};
3355*4f2df630SAndroid Build Coastguard Worker 
3356*4f2df630SAndroid Build Coastguard Worker 	struct __attribute__((__packed__)) ap_ro_config_spi_mode_msg {
3357*4f2df630SAndroid Build Coastguard Worker 		uint8_t version;
3358*4f2df630SAndroid Build Coastguard Worker 		uint8_t command;
3359*4f2df630SAndroid Build Coastguard Worker 		uint8_t state;
3360*4f2df630SAndroid Build Coastguard Worker 		uint8_t mode;
3361*4f2df630SAndroid Build Coastguard Worker 	};
3362*4f2df630SAndroid Build Coastguard Worker 
3363*4f2df630SAndroid Build Coastguard Worker 	struct ap_ro_config_spi_mode_msg msg = {
3364*4f2df630SAndroid Build Coastguard Worker 		.version = ARV_CONFIG_SETTING_CURRENT_VERSION,
3365*4f2df630SAndroid Build Coastguard Worker 		.command = arv_config_setting_command_spi_addressing_mode,
3366*4f2df630SAndroid Build Coastguard Worker 		.state = arv_config_setting_state_present,
3367*4f2df630SAndroid Build Coastguard Worker 		.mode = ap_ro_spi_config_4byte
3368*4f2df630SAndroid Build Coastguard Worker 	};
3369*4f2df630SAndroid Build Coastguard Worker 	size_t response_size = sizeof(msg);
3370*4f2df630SAndroid Build Coastguard Worker 	int rv = 0;
3371*4f2df630SAndroid Build Coastguard Worker 
3372*4f2df630SAndroid Build Coastguard Worker 	switch (arv_config_spi_addr_mode) {
3373*4f2df630SAndroid Build Coastguard Worker 	case arv_config_spi_addr_mode_get:
3374*4f2df630SAndroid Build Coastguard Worker 		rv = send_vendor_command(td, VENDOR_CC_GET_AP_RO_VERIFY_SETTING,
3375*4f2df630SAndroid Build Coastguard Worker 					 &msg, sizeof(msg), &msg,
3376*4f2df630SAndroid Build Coastguard Worker 					 &response_size);
3377*4f2df630SAndroid Build Coastguard Worker 		if (rv != VENDOR_RC_SUCCESS) {
3378*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr,
3379*4f2df630SAndroid Build Coastguard Worker 				"Error %d getting ap ro spi addr mode\n", rv);
3380*4f2df630SAndroid Build Coastguard Worker 			return update_error;
3381*4f2df630SAndroid Build Coastguard Worker 		}
3382*4f2df630SAndroid Build Coastguard Worker 
3383*4f2df630SAndroid Build Coastguard Worker 		if (response_size != sizeof(msg)) {
3384*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr,
3385*4f2df630SAndroid Build Coastguard Worker 				"Error getting ap ro spi addr mode response\n");
3386*4f2df630SAndroid Build Coastguard Worker 			return update_error;
3387*4f2df630SAndroid Build Coastguard Worker 		}
3388*4f2df630SAndroid Build Coastguard Worker 
3389*4f2df630SAndroid Build Coastguard Worker 		if (msg.state != arv_config_setting_state_present) {
3390*4f2df630SAndroid Build Coastguard Worker 			switch (msg.state) {
3391*4f2df630SAndroid Build Coastguard Worker 			case arv_config_setting_state_not_present:
3392*4f2df630SAndroid Build Coastguard Worker 				fprintf(stderr, "not provisioned\n");
3393*4f2df630SAndroid Build Coastguard Worker 				break;
3394*4f2df630SAndroid Build Coastguard Worker 			case arv_config_setting_state_corrupted:
3395*4f2df630SAndroid Build Coastguard Worker 				fprintf(stderr, "corrupted\n");
3396*4f2df630SAndroid Build Coastguard Worker 				break;
3397*4f2df630SAndroid Build Coastguard Worker 			case arv_config_setting_state_invalid:
3398*4f2df630SAndroid Build Coastguard Worker 				fprintf(stderr, "invalid\n");
3399*4f2df630SAndroid Build Coastguard Worker 				break;
3400*4f2df630SAndroid Build Coastguard Worker 			default:
3401*4f2df630SAndroid Build Coastguard Worker 				fprintf(stderr,
3402*4f2df630SAndroid Build Coastguard Worker 					"unexpected message response state\n");
3403*4f2df630SAndroid Build Coastguard Worker 				return update_error;
3404*4f2df630SAndroid Build Coastguard Worker 			}
3405*4f2df630SAndroid Build Coastguard Worker 			return 0;
3406*4f2df630SAndroid Build Coastguard Worker 		}
3407*4f2df630SAndroid Build Coastguard Worker 
3408*4f2df630SAndroid Build Coastguard Worker 		switch (msg.mode) {
3409*4f2df630SAndroid Build Coastguard Worker 		case ap_ro_spi_config_3byte:
3410*4f2df630SAndroid Build Coastguard Worker 			printf("3byte\n");
3411*4f2df630SAndroid Build Coastguard Worker 			break;
3412*4f2df630SAndroid Build Coastguard Worker 		case ap_ro_spi_config_4byte:
3413*4f2df630SAndroid Build Coastguard Worker 			printf("4byte\n");
3414*4f2df630SAndroid Build Coastguard Worker 			break;
3415*4f2df630SAndroid Build Coastguard Worker 		default:
3416*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr, "unknown spi mode\n");
3417*4f2df630SAndroid Build Coastguard Worker 			return update_error;
3418*4f2df630SAndroid Build Coastguard Worker 		}
3419*4f2df630SAndroid Build Coastguard Worker 
3420*4f2df630SAndroid Build Coastguard Worker 		break;
3421*4f2df630SAndroid Build Coastguard Worker 	case arv_config_spi_addr_mode_set_3byte:
3422*4f2df630SAndroid Build Coastguard Worker 		msg.mode = ap_ro_spi_config_3byte;
3423*4f2df630SAndroid Build Coastguard Worker 		/* Fallthrough */
3424*4f2df630SAndroid Build Coastguard Worker 	case arv_config_spi_addr_mode_set_4byte:
3425*4f2df630SAndroid Build Coastguard Worker 		/* The default is 4byte addressing */
3426*4f2df630SAndroid Build Coastguard Worker 		rv = send_vendor_command(td, VENDOR_CC_SET_AP_RO_VERIFY_SETTING,
3427*4f2df630SAndroid Build Coastguard Worker 					 &msg, sizeof(msg), &msg,
3428*4f2df630SAndroid Build Coastguard Worker 					 &response_size);
3429*4f2df630SAndroid Build Coastguard Worker 		if (rv != VENDOR_RC_SUCCESS) {
3430*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr,
3431*4f2df630SAndroid Build Coastguard Worker 				"Error %d setting ap ro spi addr mode\n", rv);
3432*4f2df630SAndroid Build Coastguard Worker 			return update_error;
3433*4f2df630SAndroid Build Coastguard Worker 		}
3434*4f2df630SAndroid Build Coastguard Worker 		break;
3435*4f2df630SAndroid Build Coastguard Worker 	default:
3436*4f2df630SAndroid Build Coastguard Worker 		return update_error;
3437*4f2df630SAndroid Build Coastguard Worker 	}
3438*4f2df630SAndroid Build Coastguard Worker 
3439*4f2df630SAndroid Build Coastguard Worker 	return 0;
3440*4f2df630SAndroid Build Coastguard Worker }
3441*4f2df630SAndroid Build Coastguard Worker 
3442*4f2df630SAndroid Build Coastguard Worker /*
3443*4f2df630SAndroid Build Coastguard Worker  * Reads an ascii hex byte in the following forms:
3444*4f2df630SAndroid Build Coastguard Worker  *  - 0x01
3445*4f2df630SAndroid Build Coastguard Worker  *  - 0x1
3446*4f2df630SAndroid Build Coastguard Worker  *  - 01
3447*4f2df630SAndroid Build Coastguard Worker  *  - 0
3448*4f2df630SAndroid Build Coastguard Worker  *
3449*4f2df630SAndroid Build Coastguard Worker  * 1 is returned on success, 0 on failure.
3450*4f2df630SAndroid Build Coastguard Worker  */
read_hex_byte_string(char * s,uint8_t * byte)3451*4f2df630SAndroid Build Coastguard Worker static int read_hex_byte_string(char *s, uint8_t *byte)
3452*4f2df630SAndroid Build Coastguard Worker {
3453*4f2df630SAndroid Build Coastguard Worker 	uint8_t b = 0;
3454*4f2df630SAndroid Build Coastguard Worker 
3455*4f2df630SAndroid Build Coastguard Worker 	if (!strncmp(s, "0x", 2))
3456*4f2df630SAndroid Build Coastguard Worker 		s += 2;
3457*4f2df630SAndroid Build Coastguard Worker 
3458*4f2df630SAndroid Build Coastguard Worker 	if (strlen(s) == 0)
3459*4f2df630SAndroid Build Coastguard Worker 		return 0;
3460*4f2df630SAndroid Build Coastguard Worker 
3461*4f2df630SAndroid Build Coastguard Worker 	for (const char *end = s + 2; s < end; ++s) {
3462*4f2df630SAndroid Build Coastguard Worker 		if (*s >= '0' && *s <= '9')
3463*4f2df630SAndroid Build Coastguard Worker 			b = b * 16 + *s - '0';
3464*4f2df630SAndroid Build Coastguard Worker 		else if (*s >= 'A' && *s <= 'F')
3465*4f2df630SAndroid Build Coastguard Worker 			b = b * 16 + 10 + *s - 'A';
3466*4f2df630SAndroid Build Coastguard Worker 		else if (*s >= 'a' && *s <= 'f')
3467*4f2df630SAndroid Build Coastguard Worker 			b = b * 16 + 10 + *s - 'a';
3468*4f2df630SAndroid Build Coastguard Worker 		else if (*s == '\0')
3469*4f2df630SAndroid Build Coastguard Worker 			/* Single nibble, do nothing instead of `break`
3470*4f2df630SAndroid Build Coastguard Worker 			 * to keep checkpatch happy
3471*4f2df630SAndroid Build Coastguard Worker 			 */
3472*4f2df630SAndroid Build Coastguard Worker 			;
3473*4f2df630SAndroid Build Coastguard Worker 		else
3474*4f2df630SAndroid Build Coastguard Worker 			/* Invalid nibble */
3475*4f2df630SAndroid Build Coastguard Worker 			return 0;
3476*4f2df630SAndroid Build Coastguard Worker 	}
3477*4f2df630SAndroid Build Coastguard Worker 	*byte = b;
3478*4f2df630SAndroid Build Coastguard Worker 	return 1;
3479*4f2df630SAndroid Build Coastguard Worker }
3480*4f2df630SAndroid Build Coastguard Worker 
parse_wpsrs(const char * opt,struct arv_config_wpds * wpds)3481*4f2df630SAndroid Build Coastguard Worker static int parse_wpsrs(const char *opt, struct arv_config_wpds *wpds)
3482*4f2df630SAndroid Build Coastguard Worker {
3483*4f2df630SAndroid Build Coastguard Worker 	size_t len = strlen(opt);
3484*4f2df630SAndroid Build Coastguard Worker 	char *ptr, *p, *delim = " ";
3485*4f2df630SAndroid Build Coastguard Worker 	uint8_t b;
3486*4f2df630SAndroid Build Coastguard Worker 	int rv = 0;
3487*4f2df630SAndroid Build Coastguard Worker 	struct arv_config_wpd *wpd;
3488*4f2df630SAndroid Build Coastguard Worker 
3489*4f2df630SAndroid Build Coastguard Worker 	ptr = malloc(len + 1);
3490*4f2df630SAndroid Build Coastguard Worker 	strcpy(ptr, opt);
3491*4f2df630SAndroid Build Coastguard Worker 	p = strtok(ptr, delim);
3492*4f2df630SAndroid Build Coastguard Worker 
3493*4f2df630SAndroid Build Coastguard Worker 	while (p != NULL) {
3494*4f2df630SAndroid Build Coastguard Worker 		if (read_hex_byte_string(p, &b)) {
3495*4f2df630SAndroid Build Coastguard Worker 			wpd = &wpds->data[rv / 2];
3496*4f2df630SAndroid Build Coastguard Worker 			if (rv % 2 == 0) {
3497*4f2df630SAndroid Build Coastguard Worker 				wpd->expected_value = b;
3498*4f2df630SAndroid Build Coastguard Worker 			} else {
3499*4f2df630SAndroid Build Coastguard Worker 				wpd->mask = b;
3500*4f2df630SAndroid Build Coastguard Worker 				wpd->state = arv_config_setting_state_present;
3501*4f2df630SAndroid Build Coastguard Worker 			}
3502*4f2df630SAndroid Build Coastguard Worker 			rv++;
3503*4f2df630SAndroid Build Coastguard Worker 		} else {
3504*4f2df630SAndroid Build Coastguard Worker 			break;
3505*4f2df630SAndroid Build Coastguard Worker 		}
3506*4f2df630SAndroid Build Coastguard Worker 		p = strtok(NULL, delim);
3507*4f2df630SAndroid Build Coastguard Worker 	}
3508*4f2df630SAndroid Build Coastguard Worker 	free(ptr);
3509*4f2df630SAndroid Build Coastguard Worker 
3510*4f2df630SAndroid Build Coastguard Worker 	return rv;
3511*4f2df630SAndroid Build Coastguard Worker }
3512*4f2df630SAndroid Build Coastguard Worker 
print_wpd(size_t i,struct arv_config_wpd * wpd)3513*4f2df630SAndroid Build Coastguard Worker static void print_wpd(size_t i, struct arv_config_wpd *wpd)
3514*4f2df630SAndroid Build Coastguard Worker {
3515*4f2df630SAndroid Build Coastguard Worker 	if (wpd->state == arv_config_setting_state_not_present) {
3516*4f2df630SAndroid Build Coastguard Worker 		printf("not provisioned");
3517*4f2df630SAndroid Build Coastguard Worker 		return;
3518*4f2df630SAndroid Build Coastguard Worker 	} else if (wpd->state == arv_config_setting_state_corrupted) {
3519*4f2df630SAndroid Build Coastguard Worker 		printf("corrupted");
3520*4f2df630SAndroid Build Coastguard Worker 		return;
3521*4f2df630SAndroid Build Coastguard Worker 	} else if (wpd->state == arv_config_setting_state_invalid) {
3522*4f2df630SAndroid Build Coastguard Worker 		printf("invalid");
3523*4f2df630SAndroid Build Coastguard Worker 		return;
3524*4f2df630SAndroid Build Coastguard Worker 	}
3525*4f2df630SAndroid Build Coastguard Worker 
3526*4f2df630SAndroid Build Coastguard Worker 	printf("%zu: %02x & %02x", i, wpd->expected_value, wpd->mask);
3527*4f2df630SAndroid Build Coastguard Worker }
3528*4f2df630SAndroid Build Coastguard Worker 
process_arv_config_wpds(struct transfer_descriptor * td,enum arv_config_wpsr_choice_e choice,struct arv_config_wpds * wpds)3529*4f2df630SAndroid Build Coastguard Worker static int process_arv_config_wpds(struct transfer_descriptor *td,
3530*4f2df630SAndroid Build Coastguard Worker 				   enum arv_config_wpsr_choice_e choice,
3531*4f2df630SAndroid Build Coastguard Worker 				   struct arv_config_wpds *wpds)
3532*4f2df630SAndroid Build Coastguard Worker {
3533*4f2df630SAndroid Build Coastguard Worker 	struct __attribute__((__packed__)) arv_config_wpds_message {
3534*4f2df630SAndroid Build Coastguard Worker 		uint8_t version;
3535*4f2df630SAndroid Build Coastguard Worker 		/* See `arv_config_setting_command_e` */
3536*4f2df630SAndroid Build Coastguard Worker 		uint8_t command;
3537*4f2df630SAndroid Build Coastguard Worker 		struct arv_config_wpds wpds;
3538*4f2df630SAndroid Build Coastguard Worker 	};
3539*4f2df630SAndroid Build Coastguard Worker 	int rv = 0;
3540*4f2df630SAndroid Build Coastguard Worker 
3541*4f2df630SAndroid Build Coastguard Worker 	struct arv_config_wpds_message msg = {
3542*4f2df630SAndroid Build Coastguard Worker 		.version = ARV_CONFIG_SETTING_CURRENT_VERSION,
3543*4f2df630SAndroid Build Coastguard Worker 		.command = arv_config_setting_command_write_protect_descriptors,
3544*4f2df630SAndroid Build Coastguard Worker 	};
3545*4f2df630SAndroid Build Coastguard Worker 	size_t response_size = sizeof(msg);
3546*4f2df630SAndroid Build Coastguard Worker 
3547*4f2df630SAndroid Build Coastguard Worker 	if (choice == arv_config_wpsr_choice_get) {
3548*4f2df630SAndroid Build Coastguard Worker 		rv = send_vendor_command(td, VENDOR_CC_GET_AP_RO_VERIFY_SETTING,
3549*4f2df630SAndroid Build Coastguard Worker 					 &msg, sizeof(msg), &msg,
3550*4f2df630SAndroid Build Coastguard Worker 					 &response_size);
3551*4f2df630SAndroid Build Coastguard Worker 		if (rv != VENDOR_RC_SUCCESS) {
3552*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr,
3553*4f2df630SAndroid Build Coastguard Worker 				"Error %d getting ap ro write protect descriptors\n",
3554*4f2df630SAndroid Build Coastguard Worker 				rv);
3555*4f2df630SAndroid Build Coastguard Worker 			return update_error;
3556*4f2df630SAndroid Build Coastguard Worker 		}
3557*4f2df630SAndroid Build Coastguard Worker 
3558*4f2df630SAndroid Build Coastguard Worker 		if (response_size != sizeof(msg)) {
3559*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr,
3560*4f2df630SAndroid Build Coastguard Worker 				"Error getting ap ro write protect descriptors response\n");
3561*4f2df630SAndroid Build Coastguard Worker 			return update_error;
3562*4f2df630SAndroid Build Coastguard Worker 		}
3563*4f2df630SAndroid Build Coastguard Worker 
3564*4f2df630SAndroid Build Coastguard Worker 		if (msg.wpds.data[0].state ==
3565*4f2df630SAndroid Build Coastguard Worker 		    arv_config_setting_state_present) {
3566*4f2df630SAndroid Build Coastguard Worker 			printf("expected values: ");
3567*4f2df630SAndroid Build Coastguard Worker 		}
3568*4f2df630SAndroid Build Coastguard Worker 		print_wpd(1, &msg.wpds.data[0]);
3569*4f2df630SAndroid Build Coastguard Worker 		if (msg.wpds.data[1].state !=
3570*4f2df630SAndroid Build Coastguard Worker 		    arv_config_setting_state_not_present) {
3571*4f2df630SAndroid Build Coastguard Worker 			printf(", ");
3572*4f2df630SAndroid Build Coastguard Worker 			print_wpd(2, &msg.wpds.data[1]);
3573*4f2df630SAndroid Build Coastguard Worker 		}
3574*4f2df630SAndroid Build Coastguard Worker 		if (msg.wpds.data[2].state !=
3575*4f2df630SAndroid Build Coastguard Worker 		    arv_config_setting_state_not_present) {
3576*4f2df630SAndroid Build Coastguard Worker 			printf(", ");
3577*4f2df630SAndroid Build Coastguard Worker 			print_wpd(3, &msg.wpds.data[2]);
3578*4f2df630SAndroid Build Coastguard Worker 		}
3579*4f2df630SAndroid Build Coastguard Worker 
3580*4f2df630SAndroid Build Coastguard Worker 		printf("\n");
3581*4f2df630SAndroid Build Coastguard Worker 	} else if (choice == arv_config_wpsr_choice_set) {
3582*4f2df630SAndroid Build Coastguard Worker 		msg.wpds = *wpds;
3583*4f2df630SAndroid Build Coastguard Worker 
3584*4f2df630SAndroid Build Coastguard Worker 		rv = send_vendor_command(td, VENDOR_CC_SET_AP_RO_VERIFY_SETTING,
3585*4f2df630SAndroid Build Coastguard Worker 					 &msg, sizeof(msg), &msg,
3586*4f2df630SAndroid Build Coastguard Worker 					 &response_size);
3587*4f2df630SAndroid Build Coastguard Worker 		if (rv != VENDOR_RC_SUCCESS) {
3588*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr,
3589*4f2df630SAndroid Build Coastguard Worker 				"Error %d setting ap ro write protect descriptors\n",
3590*4f2df630SAndroid Build Coastguard Worker 				rv);
3591*4f2df630SAndroid Build Coastguard Worker 			return update_error;
3592*4f2df630SAndroid Build Coastguard Worker 		}
3593*4f2df630SAndroid Build Coastguard Worker 	}
3594*4f2df630SAndroid Build Coastguard Worker 
3595*4f2df630SAndroid Build Coastguard Worker 	return 0;
3596*4f2df630SAndroid Build Coastguard Worker }
3597*4f2df630SAndroid Build Coastguard Worker 
process_get_boot_mode(struct transfer_descriptor * td)3598*4f2df630SAndroid Build Coastguard Worker static int process_get_boot_mode(struct transfer_descriptor *td)
3599*4f2df630SAndroid Build Coastguard Worker {
3600*4f2df630SAndroid Build Coastguard Worker 	size_t response_size;
3601*4f2df630SAndroid Build Coastguard Worker 	uint8_t response;
3602*4f2df630SAndroid Build Coastguard Worker 	const char *const desc = "Getting boot mode";
3603*4f2df630SAndroid Build Coastguard Worker 	int rv = 0;
3604*4f2df630SAndroid Build Coastguard Worker 
3605*4f2df630SAndroid Build Coastguard Worker 	response_size = sizeof(response);
3606*4f2df630SAndroid Build Coastguard Worker 
3607*4f2df630SAndroid Build Coastguard Worker 	rv = send_vendor_command(td, VENDOR_CC_GET_BOOT_MODE, NULL, 0,
3608*4f2df630SAndroid Build Coastguard Worker 				 &response, &response_size);
3609*4f2df630SAndroid Build Coastguard Worker 	if (rv != VENDOR_RC_SUCCESS) {
3610*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Error %d in %s\n", rv, desc);
3611*4f2df630SAndroid Build Coastguard Worker 		return update_error;
3612*4f2df630SAndroid Build Coastguard Worker 	}
3613*4f2df630SAndroid Build Coastguard Worker 	if (response_size != 1) {
3614*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Unexpected response size %zd while %s\n",
3615*4f2df630SAndroid Build Coastguard Worker 			response_size, desc);
3616*4f2df630SAndroid Build Coastguard Worker 		return update_error;
3617*4f2df630SAndroid Build Coastguard Worker 	}
3618*4f2df630SAndroid Build Coastguard Worker 
3619*4f2df630SAndroid Build Coastguard Worker 	/* Print the response and meaning, as in 'enum boot_mode'. */
3620*4f2df630SAndroid Build Coastguard Worker 	printf("Boot mode = 0x%02x: ", response);
3621*4f2df630SAndroid Build Coastguard Worker 	switch (response) {
3622*4f2df630SAndroid Build Coastguard Worker 	case 0x00:
3623*4f2df630SAndroid Build Coastguard Worker 		printf("NORMAL\n");
3624*4f2df630SAndroid Build Coastguard Worker 		break;
3625*4f2df630SAndroid Build Coastguard Worker 	case 0x01:
3626*4f2df630SAndroid Build Coastguard Worker 		printf("NO_BOOT\n");
3627*4f2df630SAndroid Build Coastguard Worker 		break;
3628*4f2df630SAndroid Build Coastguard Worker 	default:
3629*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "unknown boot mode\n");
3630*4f2df630SAndroid Build Coastguard Worker 		return update_error;
3631*4f2df630SAndroid Build Coastguard Worker 	}
3632*4f2df630SAndroid Build Coastguard Worker 
3633*4f2df630SAndroid Build Coastguard Worker 	return 0;
3634*4f2df630SAndroid Build Coastguard Worker }
3635*4f2df630SAndroid Build Coastguard Worker 
process_bid(struct transfer_descriptor * td,enum board_id_action bid_action,struct board_id * bid,bool show_machine_output)3636*4f2df630SAndroid Build Coastguard Worker void process_bid(struct transfer_descriptor *td,
3637*4f2df630SAndroid Build Coastguard Worker 		 enum board_id_action bid_action, struct board_id *bid,
3638*4f2df630SAndroid Build Coastguard Worker 		 bool show_machine_output)
3639*4f2df630SAndroid Build Coastguard Worker {
3640*4f2df630SAndroid Build Coastguard Worker 	size_t response_size;
3641*4f2df630SAndroid Build Coastguard Worker 
3642*4f2df630SAndroid Build Coastguard Worker 	if (bid_action == bid_get) {
3643*4f2df630SAndroid Build Coastguard Worker 		response_size = sizeof(*bid);
3644*4f2df630SAndroid Build Coastguard Worker 		send_vendor_command(td, VENDOR_CC_GET_BOARD_ID, bid,
3645*4f2df630SAndroid Build Coastguard Worker 				    sizeof(*bid), bid, &response_size);
3646*4f2df630SAndroid Build Coastguard Worker 
3647*4f2df630SAndroid Build Coastguard Worker 		if (response_size != sizeof(*bid)) {
3648*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr,
3649*4f2df630SAndroid Build Coastguard Worker 				"Error reading board ID: response size %zd, "
3650*4f2df630SAndroid Build Coastguard Worker 				"first byte %#02x\n",
3651*4f2df630SAndroid Build Coastguard Worker 				response_size,
3652*4f2df630SAndroid Build Coastguard Worker 				response_size ? *(uint8_t *)&bid : -1);
3653*4f2df630SAndroid Build Coastguard Worker 			exit(update_error);
3654*4f2df630SAndroid Build Coastguard Worker 		}
3655*4f2df630SAndroid Build Coastguard Worker 
3656*4f2df630SAndroid Build Coastguard Worker 		if (show_machine_output) {
3657*4f2df630SAndroid Build Coastguard Worker 			print_machine_output("BID_TYPE", "%08x",
3658*4f2df630SAndroid Build Coastguard Worker 					     be32toh(bid->type));
3659*4f2df630SAndroid Build Coastguard Worker 			print_machine_output("BID_TYPE_INV", "%08x",
3660*4f2df630SAndroid Build Coastguard Worker 					     be32toh(bid->type_inv));
3661*4f2df630SAndroid Build Coastguard Worker 			print_machine_output("BID_FLAGS", "%08x",
3662*4f2df630SAndroid Build Coastguard Worker 					     be32toh(bid->flags));
3663*4f2df630SAndroid Build Coastguard Worker 
3664*4f2df630SAndroid Build Coastguard Worker 			for (int i = 0; i < 4; i++) {
3665*4f2df630SAndroid Build Coastguard Worker 				if (!isupper(((const char *)bid)[i])) {
3666*4f2df630SAndroid Build Coastguard Worker 					print_machine_output("BID_RLZ", "%s",
3667*4f2df630SAndroid Build Coastguard Worker 							     "????");
3668*4f2df630SAndroid Build Coastguard Worker 					return;
3669*4f2df630SAndroid Build Coastguard Worker 				}
3670*4f2df630SAndroid Build Coastguard Worker 			}
3671*4f2df630SAndroid Build Coastguard Worker 
3672*4f2df630SAndroid Build Coastguard Worker 			print_machine_output("BID_RLZ", "%c%c%c%c",
3673*4f2df630SAndroid Build Coastguard Worker 					     ((const char *)bid)[0],
3674*4f2df630SAndroid Build Coastguard Worker 					     ((const char *)bid)[1],
3675*4f2df630SAndroid Build Coastguard Worker 					     ((const char *)bid)[2],
3676*4f2df630SAndroid Build Coastguard Worker 					     ((const char *)bid)[3]);
3677*4f2df630SAndroid Build Coastguard Worker 		} else {
3678*4f2df630SAndroid Build Coastguard Worker 			printf("Board ID space: %08x:%08x:%08x\n",
3679*4f2df630SAndroid Build Coastguard Worker 			       be32toh(bid->type), be32toh(bid->type_inv),
3680*4f2df630SAndroid Build Coastguard Worker 			       be32toh(bid->flags));
3681*4f2df630SAndroid Build Coastguard Worker 		}
3682*4f2df630SAndroid Build Coastguard Worker 
3683*4f2df630SAndroid Build Coastguard Worker 		return;
3684*4f2df630SAndroid Build Coastguard Worker 	}
3685*4f2df630SAndroid Build Coastguard Worker 
3686*4f2df630SAndroid Build Coastguard Worker 	if (bid_action == bid_set) {
3687*4f2df630SAndroid Build Coastguard Worker 		/* Sending just two fields: type and flags. */
3688*4f2df630SAndroid Build Coastguard Worker 		uint32_t command_body[2];
3689*4f2df630SAndroid Build Coastguard Worker 		uint8_t response;
3690*4f2df630SAndroid Build Coastguard Worker 
3691*4f2df630SAndroid Build Coastguard Worker 		command_body[0] = htobe32(bid->type);
3692*4f2df630SAndroid Build Coastguard Worker 		command_body[1] = htobe32(bid->flags);
3693*4f2df630SAndroid Build Coastguard Worker 
3694*4f2df630SAndroid Build Coastguard Worker 		response_size = sizeof(command_body);
3695*4f2df630SAndroid Build Coastguard Worker 		send_vendor_command(td, VENDOR_CC_SET_BOARD_ID, command_body,
3696*4f2df630SAndroid Build Coastguard Worker 				    sizeof(command_body), command_body,
3697*4f2df630SAndroid Build Coastguard Worker 				    &response_size);
3698*4f2df630SAndroid Build Coastguard Worker 
3699*4f2df630SAndroid Build Coastguard Worker 		/*
3700*4f2df630SAndroid Build Coastguard Worker 		 * Speculative assignment: the response is expected to be one
3701*4f2df630SAndroid Build Coastguard Worker 		 * byte in size and be placed in the first byte of the buffer.
3702*4f2df630SAndroid Build Coastguard Worker 		 */
3703*4f2df630SAndroid Build Coastguard Worker 		response = *((uint8_t *)command_body);
3704*4f2df630SAndroid Build Coastguard Worker 
3705*4f2df630SAndroid Build Coastguard Worker 		if (response_size == 1) {
3706*4f2df630SAndroid Build Coastguard Worker 			if (!response)
3707*4f2df630SAndroid Build Coastguard Worker 				return; /* Success! */
3708*4f2df630SAndroid Build Coastguard Worker 
3709*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr, "Error %d while setting board id\n",
3710*4f2df630SAndroid Build Coastguard Worker 				response);
3711*4f2df630SAndroid Build Coastguard Worker 		} else {
3712*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr,
3713*4f2df630SAndroid Build Coastguard Worker 				"Unexpected response size %zd"
3714*4f2df630SAndroid Build Coastguard Worker 				" while setting board id\n",
3715*4f2df630SAndroid Build Coastguard Worker 				response_size);
3716*4f2df630SAndroid Build Coastguard Worker 		}
3717*4f2df630SAndroid Build Coastguard Worker 		exit(update_error);
3718*4f2df630SAndroid Build Coastguard Worker 	}
3719*4f2df630SAndroid Build Coastguard Worker }
3720*4f2df630SAndroid Build Coastguard Worker 
process_sn_bits(struct transfer_descriptor * td,uint8_t * sn_bits)3721*4f2df630SAndroid Build Coastguard Worker static void process_sn_bits(struct transfer_descriptor *td, uint8_t *sn_bits)
3722*4f2df630SAndroid Build Coastguard Worker {
3723*4f2df630SAndroid Build Coastguard Worker 	int rv;
3724*4f2df630SAndroid Build Coastguard Worker 	uint8_t response_code;
3725*4f2df630SAndroid Build Coastguard Worker 	size_t response_size = sizeof(response_code);
3726*4f2df630SAndroid Build Coastguard Worker 
3727*4f2df630SAndroid Build Coastguard Worker 	rv = send_vendor_command(td, VENDOR_CC_SN_SET_HASH, sn_bits,
3728*4f2df630SAndroid Build Coastguard Worker 				 SN_BITS_SIZE, &response_code, &response_size);
3729*4f2df630SAndroid Build Coastguard Worker 
3730*4f2df630SAndroid Build Coastguard Worker 	if (rv) {
3731*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Error %d while sending vendor command\n", rv);
3732*4f2df630SAndroid Build Coastguard Worker 		exit(update_error);
3733*4f2df630SAndroid Build Coastguard Worker 	}
3734*4f2df630SAndroid Build Coastguard Worker 
3735*4f2df630SAndroid Build Coastguard Worker 	if (response_size != 1) {
3736*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr,
3737*4f2df630SAndroid Build Coastguard Worker 			"Unexpected response size while setting sn bits\n");
3738*4f2df630SAndroid Build Coastguard Worker 		exit(update_error);
3739*4f2df630SAndroid Build Coastguard Worker 	}
3740*4f2df630SAndroid Build Coastguard Worker 
3741*4f2df630SAndroid Build Coastguard Worker 	if (response_code != 0) {
3742*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Error %d while setting sn bits\n",
3743*4f2df630SAndroid Build Coastguard Worker 			response_code);
3744*4f2df630SAndroid Build Coastguard Worker 		exit(update_error);
3745*4f2df630SAndroid Build Coastguard Worker 	}
3746*4f2df630SAndroid Build Coastguard Worker }
3747*4f2df630SAndroid Build Coastguard Worker 
process_sn_inc_rma(struct transfer_descriptor * td,uint8_t arg)3748*4f2df630SAndroid Build Coastguard Worker static void process_sn_inc_rma(struct transfer_descriptor *td, uint8_t arg)
3749*4f2df630SAndroid Build Coastguard Worker {
3750*4f2df630SAndroid Build Coastguard Worker 	int rv;
3751*4f2df630SAndroid Build Coastguard Worker 	uint8_t response_code;
3752*4f2df630SAndroid Build Coastguard Worker 	size_t response_size = sizeof(response_code);
3753*4f2df630SAndroid Build Coastguard Worker 
3754*4f2df630SAndroid Build Coastguard Worker 	rv = send_vendor_command(td, VENDOR_CC_SN_INC_RMA, &arg, sizeof(arg),
3755*4f2df630SAndroid Build Coastguard Worker 				 &response_code, &response_size);
3756*4f2df630SAndroid Build Coastguard Worker 	if (rv) {
3757*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Error %d while sending vendor command\n", rv);
3758*4f2df630SAndroid Build Coastguard Worker 		exit(update_error);
3759*4f2df630SAndroid Build Coastguard Worker 	}
3760*4f2df630SAndroid Build Coastguard Worker 
3761*4f2df630SAndroid Build Coastguard Worker 	if (response_size != 1) {
3762*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Unexpected response size while "
3763*4f2df630SAndroid Build Coastguard Worker 				"incrementing sn rma count\n");
3764*4f2df630SAndroid Build Coastguard Worker 		exit(update_error);
3765*4f2df630SAndroid Build Coastguard Worker 	}
3766*4f2df630SAndroid Build Coastguard Worker 
3767*4f2df630SAndroid Build Coastguard Worker 	if (response_code != 0) {
3768*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Error %d while incrementing rma count\n",
3769*4f2df630SAndroid Build Coastguard Worker 			response_code);
3770*4f2df630SAndroid Build Coastguard Worker 		exit(update_error);
3771*4f2df630SAndroid Build Coastguard Worker 	}
3772*4f2df630SAndroid Build Coastguard Worker }
3773*4f2df630SAndroid Build Coastguard Worker 
3774*4f2df630SAndroid Build Coastguard Worker /* Get/Set the primary seed of the info1 manufacture state. */
process_endorsement_seed(struct transfer_descriptor * td,const char * endorsement_seed_str)3775*4f2df630SAndroid Build Coastguard Worker static int process_endorsement_seed(struct transfer_descriptor *td,
3776*4f2df630SAndroid Build Coastguard Worker 				    const char *endorsement_seed_str)
3777*4f2df630SAndroid Build Coastguard Worker {
3778*4f2df630SAndroid Build Coastguard Worker 	uint8_t endorsement_seed[32];
3779*4f2df630SAndroid Build Coastguard Worker 	uint8_t response_seed[32];
3780*4f2df630SAndroid Build Coastguard Worker 	size_t seed_size = sizeof(endorsement_seed);
3781*4f2df630SAndroid Build Coastguard Worker 	size_t response_size = sizeof(response_seed);
3782*4f2df630SAndroid Build Coastguard Worker 	size_t i;
3783*4f2df630SAndroid Build Coastguard Worker 	int rv;
3784*4f2df630SAndroid Build Coastguard Worker 
3785*4f2df630SAndroid Build Coastguard Worker 	if (!endorsement_seed_str) {
3786*4f2df630SAndroid Build Coastguard Worker 		rv = send_vendor_command(td, VENDOR_CC_ENDORSEMENT_SEED, NULL,
3787*4f2df630SAndroid Build Coastguard Worker 					 0, response_seed, &response_size);
3788*4f2df630SAndroid Build Coastguard Worker 		if (rv) {
3789*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr, "Error sending vendor command %d\n",
3790*4f2df630SAndroid Build Coastguard Worker 				rv);
3791*4f2df630SAndroid Build Coastguard Worker 			return update_error;
3792*4f2df630SAndroid Build Coastguard Worker 		}
3793*4f2df630SAndroid Build Coastguard Worker 		printf("Endorsement key seed: ");
3794*4f2df630SAndroid Build Coastguard Worker 		for (i = 0; i < response_size; i++)
3795*4f2df630SAndroid Build Coastguard Worker 			printf("%02x", response_seed[i]);
3796*4f2df630SAndroid Build Coastguard Worker 		printf("\n");
3797*4f2df630SAndroid Build Coastguard Worker 		return 0;
3798*4f2df630SAndroid Build Coastguard Worker 	}
3799*4f2df630SAndroid Build Coastguard Worker 	if (seed_size * 2 != strlen(endorsement_seed_str)) {
3800*4f2df630SAndroid Build Coastguard Worker 		printf("Invalid seed %s\n", endorsement_seed_str);
3801*4f2df630SAndroid Build Coastguard Worker 		return update_error;
3802*4f2df630SAndroid Build Coastguard Worker 	}
3803*4f2df630SAndroid Build Coastguard Worker 
3804*4f2df630SAndroid Build Coastguard Worker 	for (i = 0; i < seed_size; i++) {
3805*4f2df630SAndroid Build Coastguard Worker 		int nibble;
3806*4f2df630SAndroid Build Coastguard Worker 		char c;
3807*4f2df630SAndroid Build Coastguard Worker 
3808*4f2df630SAndroid Build Coastguard Worker 		c = endorsement_seed_str[2 * i];
3809*4f2df630SAndroid Build Coastguard Worker 		nibble = from_hexascii(c);
3810*4f2df630SAndroid Build Coastguard Worker 		if (nibble < 0) {
3811*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr, "Error: Non hex character in seed %c\n",
3812*4f2df630SAndroid Build Coastguard Worker 				c);
3813*4f2df630SAndroid Build Coastguard Worker 			return update_error;
3814*4f2df630SAndroid Build Coastguard Worker 		}
3815*4f2df630SAndroid Build Coastguard Worker 		endorsement_seed[i] = nibble << 4;
3816*4f2df630SAndroid Build Coastguard Worker 
3817*4f2df630SAndroid Build Coastguard Worker 		c = endorsement_seed_str[2 * i + 1];
3818*4f2df630SAndroid Build Coastguard Worker 		nibble = from_hexascii(c);
3819*4f2df630SAndroid Build Coastguard Worker 		if (nibble < 0) {
3820*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr, "Error: Non hex character in seed %c\n",
3821*4f2df630SAndroid Build Coastguard Worker 				c);
3822*4f2df630SAndroid Build Coastguard Worker 			return update_error;
3823*4f2df630SAndroid Build Coastguard Worker 		}
3824*4f2df630SAndroid Build Coastguard Worker 		endorsement_seed[i] |= nibble;
3825*4f2df630SAndroid Build Coastguard Worker 	}
3826*4f2df630SAndroid Build Coastguard Worker 
3827*4f2df630SAndroid Build Coastguard Worker 	printf("Setting seed: %s\n", endorsement_seed_str);
3828*4f2df630SAndroid Build Coastguard Worker 	rv = send_vendor_command(td, VENDOR_CC_ENDORSEMENT_SEED,
3829*4f2df630SAndroid Build Coastguard Worker 				 endorsement_seed, seed_size, response_seed,
3830*4f2df630SAndroid Build Coastguard Worker 				 &response_size);
3831*4f2df630SAndroid Build Coastguard Worker 	if (rv == VENDOR_RC_NOT_ALLOWED) {
3832*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Seed already set\n");
3833*4f2df630SAndroid Build Coastguard Worker 		return update_error;
3834*4f2df630SAndroid Build Coastguard Worker 	}
3835*4f2df630SAndroid Build Coastguard Worker 	if (rv) {
3836*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Error sending vendor command %d\n", rv);
3837*4f2df630SAndroid Build Coastguard Worker 		return update_error;
3838*4f2df630SAndroid Build Coastguard Worker 	}
3839*4f2df630SAndroid Build Coastguard Worker 	printf("Updated endorsement key seed.\n");
3840*4f2df630SAndroid Build Coastguard Worker 	return 0;
3841*4f2df630SAndroid Build Coastguard Worker }
3842*4f2df630SAndroid Build Coastguard Worker 
3843*4f2df630SAndroid Build Coastguard Worker /*
3844*4f2df630SAndroid Build Coastguard Worker  * Retrieve the RMA authentication challenge from the Cr50, print out the
3845*4f2df630SAndroid Build Coastguard Worker  * challenge on the console, then prompt the user for the authentication code,
3846*4f2df630SAndroid Build Coastguard Worker  * and send the code back to Cr50. The Cr50 would report if the code matched
3847*4f2df630SAndroid Build Coastguard Worker  * its expectations or not. Output in a machine-friendly format if
3848*4f2df630SAndroid Build Coastguard Worker  * show_machine_output is true.
3849*4f2df630SAndroid Build Coastguard Worker  */
process_rma(struct transfer_descriptor * td,const char * authcode,bool show_machine_output)3850*4f2df630SAndroid Build Coastguard Worker static void process_rma(struct transfer_descriptor *td, const char *authcode,
3851*4f2df630SAndroid Build Coastguard Worker 			bool show_machine_output)
3852*4f2df630SAndroid Build Coastguard Worker {
3853*4f2df630SAndroid Build Coastguard Worker 	char rma_response[81];
3854*4f2df630SAndroid Build Coastguard Worker 	size_t response_size = sizeof(rma_response);
3855*4f2df630SAndroid Build Coastguard Worker 	size_t i;
3856*4f2df630SAndroid Build Coastguard Worker 	size_t auth_size = 0;
3857*4f2df630SAndroid Build Coastguard Worker 
3858*4f2df630SAndroid Build Coastguard Worker 	if (!authcode) {
3859*4f2df630SAndroid Build Coastguard Worker 		send_vendor_command(td, VENDOR_CC_RMA_CHALLENGE_RESPONSE, NULL,
3860*4f2df630SAndroid Build Coastguard Worker 				    0, rma_response, &response_size);
3861*4f2df630SAndroid Build Coastguard Worker 
3862*4f2df630SAndroid Build Coastguard Worker 		if (response_size == 1) {
3863*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr, "error %d\n", rma_response[0]);
3864*4f2df630SAndroid Build Coastguard Worker 			if (td->ep_type == usb_xfer)
3865*4f2df630SAndroid Build Coastguard Worker 				shut_down(&td->uep);
3866*4f2df630SAndroid Build Coastguard Worker 			exit(update_error);
3867*4f2df630SAndroid Build Coastguard Worker 		}
3868*4f2df630SAndroid Build Coastguard Worker 
3869*4f2df630SAndroid Build Coastguard Worker 		if (show_machine_output) {
3870*4f2df630SAndroid Build Coastguard Worker 			rma_response[response_size] = '\0';
3871*4f2df630SAndroid Build Coastguard Worker 			print_machine_output("CHALLENGE", "%s", rma_response);
3872*4f2df630SAndroid Build Coastguard Worker 		} else {
3873*4f2df630SAndroid Build Coastguard Worker 			printf("Challenge:");
3874*4f2df630SAndroid Build Coastguard Worker 			for (i = 0; i < response_size; i++) {
3875*4f2df630SAndroid Build Coastguard Worker 				if (!(i % 5)) {
3876*4f2df630SAndroid Build Coastguard Worker 					if (!(i % 40))
3877*4f2df630SAndroid Build Coastguard Worker 						printf("\n");
3878*4f2df630SAndroid Build Coastguard Worker 					printf(" ");
3879*4f2df630SAndroid Build Coastguard Worker 				}
3880*4f2df630SAndroid Build Coastguard Worker 				printf("%c", rma_response[i]);
3881*4f2df630SAndroid Build Coastguard Worker 			}
3882*4f2df630SAndroid Build Coastguard Worker 			printf("\n");
3883*4f2df630SAndroid Build Coastguard Worker 		}
3884*4f2df630SAndroid Build Coastguard Worker 		return;
3885*4f2df630SAndroid Build Coastguard Worker 	}
3886*4f2df630SAndroid Build Coastguard Worker 
3887*4f2df630SAndroid Build Coastguard Worker 	if (!*authcode) {
3888*4f2df630SAndroid Build Coastguard Worker 		printf("Empty response.\n");
3889*4f2df630SAndroid Build Coastguard Worker 		exit(update_error);
3890*4f2df630SAndroid Build Coastguard Worker 		return;
3891*4f2df630SAndroid Build Coastguard Worker 	}
3892*4f2df630SAndroid Build Coastguard Worker 
3893*4f2df630SAndroid Build Coastguard Worker 	if (!strcmp(authcode, "disable")) {
3894*4f2df630SAndroid Build Coastguard Worker 		printf("Invalid arg. Try using 'gsctool -F disable'\n");
3895*4f2df630SAndroid Build Coastguard Worker 		exit(update_error);
3896*4f2df630SAndroid Build Coastguard Worker 		return;
3897*4f2df630SAndroid Build Coastguard Worker 	}
3898*4f2df630SAndroid Build Coastguard Worker 
3899*4f2df630SAndroid Build Coastguard Worker 	printf("Processing response...\n");
3900*4f2df630SAndroid Build Coastguard Worker 	auth_size = strlen(authcode);
3901*4f2df630SAndroid Build Coastguard Worker 	response_size = sizeof(rma_response);
3902*4f2df630SAndroid Build Coastguard Worker 
3903*4f2df630SAndroid Build Coastguard Worker 	send_vendor_command(td, VENDOR_CC_RMA_CHALLENGE_RESPONSE, authcode,
3904*4f2df630SAndroid Build Coastguard Worker 			    auth_size, rma_response, &response_size);
3905*4f2df630SAndroid Build Coastguard Worker 
3906*4f2df630SAndroid Build Coastguard Worker 	if (response_size == 1) {
3907*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "\nrma unlock failed, code %d ", *rma_response);
3908*4f2df630SAndroid Build Coastguard Worker 		switch (*rma_response) {
3909*4f2df630SAndroid Build Coastguard Worker 		case VENDOR_RC_BOGUS_ARGS:
3910*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr, "(wrong authcode size)\n");
3911*4f2df630SAndroid Build Coastguard Worker 			break;
3912*4f2df630SAndroid Build Coastguard Worker 		case VENDOR_RC_INTERNAL_ERROR:
3913*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr, "(authcode mismatch)\n");
3914*4f2df630SAndroid Build Coastguard Worker 			break;
3915*4f2df630SAndroid Build Coastguard Worker 		default:
3916*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr, "(unknown error)\n");
3917*4f2df630SAndroid Build Coastguard Worker 			break;
3918*4f2df630SAndroid Build Coastguard Worker 		}
3919*4f2df630SAndroid Build Coastguard Worker 		if (td->ep_type == usb_xfer)
3920*4f2df630SAndroid Build Coastguard Worker 			shut_down(&td->uep);
3921*4f2df630SAndroid Build Coastguard Worker 		exit(update_error);
3922*4f2df630SAndroid Build Coastguard Worker 	}
3923*4f2df630SAndroid Build Coastguard Worker 	printf("RMA unlock succeeded.\n");
3924*4f2df630SAndroid Build Coastguard Worker }
3925*4f2df630SAndroid Build Coastguard Worker 
3926*4f2df630SAndroid Build Coastguard Worker /*
3927*4f2df630SAndroid Build Coastguard Worker  * Enable or disable factory mode. Factory mode will only be enabled if HW
3928*4f2df630SAndroid Build Coastguard Worker  * write protect is removed.
3929*4f2df630SAndroid Build Coastguard Worker  */
process_factory_mode(struct transfer_descriptor * td,const char * arg)3930*4f2df630SAndroid Build Coastguard Worker static void process_factory_mode(struct transfer_descriptor *td,
3931*4f2df630SAndroid Build Coastguard Worker 				 const char *arg)
3932*4f2df630SAndroid Build Coastguard Worker {
3933*4f2df630SAndroid Build Coastguard Worker 	uint8_t rma_response;
3934*4f2df630SAndroid Build Coastguard Worker 	size_t response_size = sizeof(rma_response);
3935*4f2df630SAndroid Build Coastguard Worker 	char *cmd_str;
3936*4f2df630SAndroid Build Coastguard Worker 	int rv;
3937*4f2df630SAndroid Build Coastguard Worker 	uint16_t subcommand;
3938*4f2df630SAndroid Build Coastguard Worker 
3939*4f2df630SAndroid Build Coastguard Worker 	if (!strcasecmp(arg, "disable")) {
3940*4f2df630SAndroid Build Coastguard Worker 		subcommand = VENDOR_CC_DISABLE_FACTORY;
3941*4f2df630SAndroid Build Coastguard Worker 		cmd_str = "dis";
3942*4f2df630SAndroid Build Coastguard Worker 	} else if (!strcasecmp(arg, "enable")) {
3943*4f2df630SAndroid Build Coastguard Worker 		subcommand = VENDOR_CC_RESET_FACTORY;
3944*4f2df630SAndroid Build Coastguard Worker 		cmd_str = "en";
3945*4f2df630SAndroid Build Coastguard Worker 
3946*4f2df630SAndroid Build Coastguard Worker 	} else {
3947*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Invalid factory mode arg %s", arg);
3948*4f2df630SAndroid Build Coastguard Worker 		exit(update_error);
3949*4f2df630SAndroid Build Coastguard Worker 	}
3950*4f2df630SAndroid Build Coastguard Worker 
3951*4f2df630SAndroid Build Coastguard Worker 	printf("%sabling factory mode\n", cmd_str);
3952*4f2df630SAndroid Build Coastguard Worker 	rv = send_vendor_command(td, subcommand, NULL, 0, &rma_response,
3953*4f2df630SAndroid Build Coastguard Worker 				 &response_size);
3954*4f2df630SAndroid Build Coastguard Worker 	if (rv) {
3955*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr,
3956*4f2df630SAndroid Build Coastguard Worker 			"Failed %sabling factory mode\nvc error "
3957*4f2df630SAndroid Build Coastguard Worker 			"%d\n",
3958*4f2df630SAndroid Build Coastguard Worker 			cmd_str, rv);
3959*4f2df630SAndroid Build Coastguard Worker 		if (response_size == 1)
3960*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr, "ec error %d\n", rma_response);
3961*4f2df630SAndroid Build Coastguard Worker 		exit(update_error);
3962*4f2df630SAndroid Build Coastguard Worker 	}
3963*4f2df630SAndroid Build Coastguard Worker 	printf("Factory %sable succeeded.\n", cmd_str);
3964*4f2df630SAndroid Build Coastguard Worker }
3965*4f2df630SAndroid Build Coastguard Worker 
report_version(void)3966*4f2df630SAndroid Build Coastguard Worker static void report_version(void)
3967*4f2df630SAndroid Build Coastguard Worker {
3968*4f2df630SAndroid Build Coastguard Worker 	/* Get version from the generated file, ignore the underscore prefix. */
3969*4f2df630SAndroid Build Coastguard Worker 	const char *v = strchr(VERSION, '_');
3970*4f2df630SAndroid Build Coastguard Worker 
3971*4f2df630SAndroid Build Coastguard Worker 	printf("Version: %s, built on %s by %s\n", v ? v + 1 : "?", DATE,
3972*4f2df630SAndroid Build Coastguard Worker 	       BUILDER);
3973*4f2df630SAndroid Build Coastguard Worker 	exit(0);
3974*4f2df630SAndroid Build Coastguard Worker }
3975*4f2df630SAndroid Build Coastguard Worker 
3976*4f2df630SAndroid Build Coastguard Worker /*
3977*4f2df630SAndroid Build Coastguard Worker  * Either change or query TPM mode value.
3978*4f2df630SAndroid Build Coastguard Worker  */
process_tpm_mode(struct transfer_descriptor * td,const char * arg)3979*4f2df630SAndroid Build Coastguard Worker static int process_tpm_mode(struct transfer_descriptor *td, const char *arg)
3980*4f2df630SAndroid Build Coastguard Worker {
3981*4f2df630SAndroid Build Coastguard Worker 	int rv;
3982*4f2df630SAndroid Build Coastguard Worker 	size_t command_size;
3983*4f2df630SAndroid Build Coastguard Worker 	size_t response_size;
3984*4f2df630SAndroid Build Coastguard Worker 	uint8_t response;
3985*4f2df630SAndroid Build Coastguard Worker 	uint8_t command_body;
3986*4f2df630SAndroid Build Coastguard Worker 
3987*4f2df630SAndroid Build Coastguard Worker 	response_size = sizeof(response);
3988*4f2df630SAndroid Build Coastguard Worker 	if (!arg) {
3989*4f2df630SAndroid Build Coastguard Worker 		command_size = 0;
3990*4f2df630SAndroid Build Coastguard Worker 	} else if (!strcasecmp(arg, "disable")) {
3991*4f2df630SAndroid Build Coastguard Worker 		command_size = sizeof(command_body);
3992*4f2df630SAndroid Build Coastguard Worker 		command_body = (uint8_t)TPM_MODE_DISABLED;
3993*4f2df630SAndroid Build Coastguard Worker 	} else if (!strcasecmp(arg, "enable")) {
3994*4f2df630SAndroid Build Coastguard Worker 		command_size = sizeof(command_body);
3995*4f2df630SAndroid Build Coastguard Worker 		command_body = (uint8_t)TPM_MODE_ENABLED;
3996*4f2df630SAndroid Build Coastguard Worker 	} else {
3997*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Invalid tpm mode arg: %s.\n", arg);
3998*4f2df630SAndroid Build Coastguard Worker 		return update_error;
3999*4f2df630SAndroid Build Coastguard Worker 	}
4000*4f2df630SAndroid Build Coastguard Worker 
4001*4f2df630SAndroid Build Coastguard Worker 	rv = send_vendor_command(td, VENDOR_CC_TPM_MODE, &command_body,
4002*4f2df630SAndroid Build Coastguard Worker 				 command_size, &response, &response_size);
4003*4f2df630SAndroid Build Coastguard Worker 	if (rv) {
4004*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Error %d in setting TPM mode.\n", rv);
4005*4f2df630SAndroid Build Coastguard Worker 		return update_error;
4006*4f2df630SAndroid Build Coastguard Worker 	}
4007*4f2df630SAndroid Build Coastguard Worker 	if (response_size != sizeof(response)) {
4008*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr,
4009*4f2df630SAndroid Build Coastguard Worker 			"Error in the size of response,"
4010*4f2df630SAndroid Build Coastguard Worker 			" %zu.\n",
4011*4f2df630SAndroid Build Coastguard Worker 			response_size);
4012*4f2df630SAndroid Build Coastguard Worker 		return update_error;
4013*4f2df630SAndroid Build Coastguard Worker 	}
4014*4f2df630SAndroid Build Coastguard Worker 	if (response >= TPM_MODE_MAX) {
4015*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr,
4016*4f2df630SAndroid Build Coastguard Worker 			"Error in the value of response,"
4017*4f2df630SAndroid Build Coastguard Worker 			" %d.\n",
4018*4f2df630SAndroid Build Coastguard Worker 			response);
4019*4f2df630SAndroid Build Coastguard Worker 		return update_error;
4020*4f2df630SAndroid Build Coastguard Worker 	}
4021*4f2df630SAndroid Build Coastguard Worker 
4022*4f2df630SAndroid Build Coastguard Worker 	printf("TPM Mode: %s (%d)\n",
4023*4f2df630SAndroid Build Coastguard Worker 	       (response == TPM_MODE_DISABLED) ? "disabled" : "enabled",
4024*4f2df630SAndroid Build Coastguard Worker 	       response);
4025*4f2df630SAndroid Build Coastguard Worker 
4026*4f2df630SAndroid Build Coastguard Worker 	return rv;
4027*4f2df630SAndroid Build Coastguard Worker }
4028*4f2df630SAndroid Build Coastguard Worker 
4029*4f2df630SAndroid Build Coastguard Worker #define MAX_PAYLOAD_SIZE 256
4030*4f2df630SAndroid Build Coastguard Worker struct parsed_flog_entry {
4031*4f2df630SAndroid Build Coastguard Worker 	bool end_of_list;
4032*4f2df630SAndroid Build Coastguard Worker 	char payload[MAX_PAYLOAD_SIZE];
4033*4f2df630SAndroid Build Coastguard Worker 	size_t payload_size;
4034*4f2df630SAndroid Build Coastguard Worker 	uint64_t raw_timestamp;
4035*4f2df630SAndroid Build Coastguard Worker 	time_t timestamp;
4036*4f2df630SAndroid Build Coastguard Worker 	uint32_t event_type;
4037*4f2df630SAndroid Build Coastguard Worker 	bool timestamp_reliable;
4038*4f2df630SAndroid Build Coastguard Worker };
4039*4f2df630SAndroid Build Coastguard Worker 
pop_flog_dt(struct transfer_descriptor * td,struct parsed_flog_entry * parsed_entry)4040*4f2df630SAndroid Build Coastguard Worker static int pop_flog_dt(struct transfer_descriptor *td,
4041*4f2df630SAndroid Build Coastguard Worker 		       struct parsed_flog_entry *parsed_entry)
4042*4f2df630SAndroid Build Coastguard Worker {
4043*4f2df630SAndroid Build Coastguard Worker 	union dt_entry_u entry;
4044*4f2df630SAndroid Build Coastguard Worker 	size_t resp_size = sizeof(entry);
4045*4f2df630SAndroid Build Coastguard Worker 	int rv = send_vendor_command(td, VENDOR_CC_POP_LOG_ENTRY_MS,
4046*4f2df630SAndroid Build Coastguard Worker 				     &parsed_entry->raw_timestamp,
4047*4f2df630SAndroid Build Coastguard Worker 				     sizeof(parsed_entry->raw_timestamp),
4048*4f2df630SAndroid Build Coastguard Worker 				     &entry, &resp_size);
4049*4f2df630SAndroid Build Coastguard Worker 	if (rv)
4050*4f2df630SAndroid Build Coastguard Worker 		return rv;
4051*4f2df630SAndroid Build Coastguard Worker 	if (resp_size == 0) {
4052*4f2df630SAndroid Build Coastguard Worker 		parsed_entry->end_of_list = true;
4053*4f2df630SAndroid Build Coastguard Worker 		return 0;
4054*4f2df630SAndroid Build Coastguard Worker 	}
4055*4f2df630SAndroid Build Coastguard Worker 	parsed_entry->event_type = entry.evt.event_type;
4056*4f2df630SAndroid Build Coastguard Worker 	parsed_entry->payload_size =
4057*4f2df630SAndroid Build Coastguard Worker 		MIN(entry.evt.size - sizeof(entry.evt.event_type),
4058*4f2df630SAndroid Build Coastguard Worker 		    MAX_PAYLOAD_SIZE);
4059*4f2df630SAndroid Build Coastguard Worker 	memcpy(parsed_entry->payload, entry.evt.payload,
4060*4f2df630SAndroid Build Coastguard Worker 	       parsed_entry->payload_size);
4061*4f2df630SAndroid Build Coastguard Worker 	parsed_entry->raw_timestamp = entry.evt.time;
4062*4f2df630SAndroid Build Coastguard Worker 	parsed_entry->timestamp =
4063*4f2df630SAndroid Build Coastguard Worker 		(parsed_entry->raw_timestamp & ~(1ULL << 63)) / 1000;
4064*4f2df630SAndroid Build Coastguard Worker 	parsed_entry->timestamp_reliable =
4065*4f2df630SAndroid Build Coastguard Worker 		(parsed_entry->raw_timestamp >> 63) == 0;
4066*4f2df630SAndroid Build Coastguard Worker 	return rv;
4067*4f2df630SAndroid Build Coastguard Worker }
4068*4f2df630SAndroid Build Coastguard Worker 
pop_flog(struct transfer_descriptor * td,struct parsed_flog_entry * parsed_entry)4069*4f2df630SAndroid Build Coastguard Worker static int pop_flog(struct transfer_descriptor *td,
4070*4f2df630SAndroid Build Coastguard Worker 		    struct parsed_flog_entry *parsed_entry)
4071*4f2df630SAndroid Build Coastguard Worker {
4072*4f2df630SAndroid Build Coastguard Worker 	union entry_u entry;
4073*4f2df630SAndroid Build Coastguard Worker 	size_t resp_size = sizeof(entry);
4074*4f2df630SAndroid Build Coastguard Worker 	uint32_t ts = (uint32_t)parsed_entry->raw_timestamp;
4075*4f2df630SAndroid Build Coastguard Worker 	int rv = send_vendor_command(td, VENDOR_CC_POP_LOG_ENTRY, &ts,
4076*4f2df630SAndroid Build Coastguard Worker 				     sizeof(ts), &entry, &resp_size);
4077*4f2df630SAndroid Build Coastguard Worker 	if (rv)
4078*4f2df630SAndroid Build Coastguard Worker 		return rv;
4079*4f2df630SAndroid Build Coastguard Worker 	if (resp_size == 0) {
4080*4f2df630SAndroid Build Coastguard Worker 		parsed_entry->end_of_list = true;
4081*4f2df630SAndroid Build Coastguard Worker 		return 0;
4082*4f2df630SAndroid Build Coastguard Worker 	}
4083*4f2df630SAndroid Build Coastguard Worker 	parsed_entry->event_type = entry.r.type;
4084*4f2df630SAndroid Build Coastguard Worker 	parsed_entry->payload_size =
4085*4f2df630SAndroid Build Coastguard Worker 		MIN(FLASH_LOG_PAYLOAD_SIZE(entry.r.size), MAX_PAYLOAD_SIZE);
4086*4f2df630SAndroid Build Coastguard Worker 	memcpy(parsed_entry->payload, entry.r.payload,
4087*4f2df630SAndroid Build Coastguard Worker 	       parsed_entry->payload_size);
4088*4f2df630SAndroid Build Coastguard Worker 	parsed_entry->raw_timestamp = entry.r.timestamp;
4089*4f2df630SAndroid Build Coastguard Worker 	parsed_entry->timestamp = entry.r.timestamp;
4090*4f2df630SAndroid Build Coastguard Worker 	parsed_entry->timestamp_reliable = true;
4091*4f2df630SAndroid Build Coastguard Worker 	return rv;
4092*4f2df630SAndroid Build Coastguard Worker }
4093*4f2df630SAndroid Build Coastguard Worker 
4094*4f2df630SAndroid Build Coastguard Worker /*
4095*4f2df630SAndroid Build Coastguard Worker  * Retrieve from H1 flash log entries which are newer than the passed in
4096*4f2df630SAndroid Build Coastguard Worker  * timestamp.
4097*4f2df630SAndroid Build Coastguard Worker  *
4098*4f2df630SAndroid Build Coastguard Worker  * On error retry a few times just in case flash log is locked by a concurrent
4099*4f2df630SAndroid Build Coastguard Worker  * access.
4100*4f2df630SAndroid Build Coastguard Worker  */
process_get_flog(struct transfer_descriptor * td,uint64_t prev_stamp,bool show_machine_output)4101*4f2df630SAndroid Build Coastguard Worker static int process_get_flog(struct transfer_descriptor *td, uint64_t prev_stamp,
4102*4f2df630SAndroid Build Coastguard Worker 			    bool show_machine_output)
4103*4f2df630SAndroid Build Coastguard Worker {
4104*4f2df630SAndroid Build Coastguard Worker 	int rv;
4105*4f2df630SAndroid Build Coastguard Worker 	const int max_retries = 3;
4106*4f2df630SAndroid Build Coastguard Worker 	int retries = max_retries;
4107*4f2df630SAndroid Build Coastguard Worker 	bool time_zone_reported = false;
4108*4f2df630SAndroid Build Coastguard Worker 
4109*4f2df630SAndroid Build Coastguard Worker 	while (retries--) {
4110*4f2df630SAndroid Build Coastguard Worker 		struct parsed_flog_entry entry = { 0 };
4111*4f2df630SAndroid Build Coastguard Worker 		entry.raw_timestamp = prev_stamp;
4112*4f2df630SAndroid Build Coastguard Worker 		size_t i;
4113*4f2df630SAndroid Build Coastguard Worker 		struct tm loc_time;
4114*4f2df630SAndroid Build Coastguard Worker 		char date_str[25];
4115*4f2df630SAndroid Build Coastguard Worker 		if (is_ti50_device()) {
4116*4f2df630SAndroid Build Coastguard Worker 			rv = pop_flog_dt(td, &entry);
4117*4f2df630SAndroid Build Coastguard Worker 		} else {
4118*4f2df630SAndroid Build Coastguard Worker 			rv = pop_flog(td, &entry);
4119*4f2df630SAndroid Build Coastguard Worker 		}
4120*4f2df630SAndroid Build Coastguard Worker 
4121*4f2df630SAndroid Build Coastguard Worker 		if (rv) {
4122*4f2df630SAndroid Build Coastguard Worker 			/*
4123*4f2df630SAndroid Build Coastguard Worker 			 * Flash log could be momentarily locked by a
4124*4f2df630SAndroid Build Coastguard Worker 			 * concurrent access, let it settle and try again, 10
4125*4f2df630SAndroid Build Coastguard Worker 			 * ms should be enough.
4126*4f2df630SAndroid Build Coastguard Worker 			 */
4127*4f2df630SAndroid Build Coastguard Worker 			usleep(10 * 1000);
4128*4f2df630SAndroid Build Coastguard Worker 			continue;
4129*4f2df630SAndroid Build Coastguard Worker 		}
4130*4f2df630SAndroid Build Coastguard Worker 
4131*4f2df630SAndroid Build Coastguard Worker 		if (entry.end_of_list)
4132*4f2df630SAndroid Build Coastguard Worker 			return 0;
4133*4f2df630SAndroid Build Coastguard Worker 
4134*4f2df630SAndroid Build Coastguard Worker 		prev_stamp = entry.raw_timestamp;
4135*4f2df630SAndroid Build Coastguard Worker 		if (show_machine_output) {
4136*4f2df630SAndroid Build Coastguard Worker 			printf("%10" PRIu64 ":%02x", prev_stamp,
4137*4f2df630SAndroid Build Coastguard Worker 			       entry.event_type);
4138*4f2df630SAndroid Build Coastguard Worker 		} else {
4139*4f2df630SAndroid Build Coastguard Worker 			localtime_r(&entry.timestamp, &loc_time);
4140*4f2df630SAndroid Build Coastguard Worker 
4141*4f2df630SAndroid Build Coastguard Worker 			if (!time_zone_reported) {
4142*4f2df630SAndroid Build Coastguard Worker 				strftime(date_str, sizeof(date_str), "%Z",
4143*4f2df630SAndroid Build Coastguard Worker 					 &loc_time);
4144*4f2df630SAndroid Build Coastguard Worker 				printf("Log time zone is %s\n", date_str);
4145*4f2df630SAndroid Build Coastguard Worker 				time_zone_reported = true;
4146*4f2df630SAndroid Build Coastguard Worker 			}
4147*4f2df630SAndroid Build Coastguard Worker 
4148*4f2df630SAndroid Build Coastguard Worker 			/* Date format is MMM DD YY HH:mm:ss */
4149*4f2df630SAndroid Build Coastguard Worker 			strftime(date_str, sizeof(date_str), "%b %d %y %T",
4150*4f2df630SAndroid Build Coastguard Worker 				 &loc_time);
4151*4f2df630SAndroid Build Coastguard Worker 			printf("%s : %02x", date_str, entry.event_type);
4152*4f2df630SAndroid Build Coastguard Worker 		}
4153*4f2df630SAndroid Build Coastguard Worker 		for (i = 0; i < entry.payload_size; i++)
4154*4f2df630SAndroid Build Coastguard Worker 			printf(" %02x", entry.payload[i]);
4155*4f2df630SAndroid Build Coastguard Worker 		if (entry.timestamp_reliable == false)
4156*4f2df630SAndroid Build Coastguard Worker 			printf(" -- TIMESTAMP UNRELIABLE!");
4157*4f2df630SAndroid Build Coastguard Worker 		printf("\n");
4158*4f2df630SAndroid Build Coastguard Worker 		retries = max_retries;
4159*4f2df630SAndroid Build Coastguard Worker 	}
4160*4f2df630SAndroid Build Coastguard Worker 
4161*4f2df630SAndroid Build Coastguard Worker 	fprintf(stderr, "%s: error %d\n", __func__, rv);
4162*4f2df630SAndroid Build Coastguard Worker 
4163*4f2df630SAndroid Build Coastguard Worker 	return rv;
4164*4f2df630SAndroid Build Coastguard Worker }
4165*4f2df630SAndroid Build Coastguard Worker 
process_tstamp(struct transfer_descriptor * td,const char * tstamp_ascii)4166*4f2df630SAndroid Build Coastguard Worker static int process_tstamp(struct transfer_descriptor *td,
4167*4f2df630SAndroid Build Coastguard Worker 			  const char *tstamp_ascii)
4168*4f2df630SAndroid Build Coastguard Worker {
4169*4f2df630SAndroid Build Coastguard Worker 	char *e;
4170*4f2df630SAndroid Build Coastguard Worker 	size_t expected_response_size;
4171*4f2df630SAndroid Build Coastguard Worker 	size_t message_size;
4172*4f2df630SAndroid Build Coastguard Worker 	size_t response_size;
4173*4f2df630SAndroid Build Coastguard Worker 	uint32_t rv;
4174*4f2df630SAndroid Build Coastguard Worker 	uint32_t tstamp = 0;
4175*4f2df630SAndroid Build Coastguard Worker 	uint8_t max_response[sizeof(uint32_t)];
4176*4f2df630SAndroid Build Coastguard Worker 
4177*4f2df630SAndroid Build Coastguard Worker 	if (tstamp_ascii) {
4178*4f2df630SAndroid Build Coastguard Worker 		tstamp = strtoul(tstamp_ascii, &e, 10);
4179*4f2df630SAndroid Build Coastguard Worker 		if (*e) {
4180*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr, "invalid base timestamp value \"%s\"\n",
4181*4f2df630SAndroid Build Coastguard Worker 				tstamp_ascii);
4182*4f2df630SAndroid Build Coastguard Worker 			return -1;
4183*4f2df630SAndroid Build Coastguard Worker 		}
4184*4f2df630SAndroid Build Coastguard Worker 		tstamp = htobe32(tstamp);
4185*4f2df630SAndroid Build Coastguard Worker 		expected_response_size = 0;
4186*4f2df630SAndroid Build Coastguard Worker 		message_size = sizeof(tstamp);
4187*4f2df630SAndroid Build Coastguard Worker 	} else {
4188*4f2df630SAndroid Build Coastguard Worker 		expected_response_size = 4;
4189*4f2df630SAndroid Build Coastguard Worker 		message_size = 0;
4190*4f2df630SAndroid Build Coastguard Worker 	}
4191*4f2df630SAndroid Build Coastguard Worker 
4192*4f2df630SAndroid Build Coastguard Worker 	response_size = sizeof(max_response);
4193*4f2df630SAndroid Build Coastguard Worker 	rv = send_vendor_command(td, VENDOR_CC_FLOG_TIMESTAMP, &tstamp,
4194*4f2df630SAndroid Build Coastguard Worker 				 message_size, max_response, &response_size);
4195*4f2df630SAndroid Build Coastguard Worker 
4196*4f2df630SAndroid Build Coastguard Worker 	if (rv) {
4197*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "error: return value %d\n", rv);
4198*4f2df630SAndroid Build Coastguard Worker 		return rv;
4199*4f2df630SAndroid Build Coastguard Worker 	}
4200*4f2df630SAndroid Build Coastguard Worker 	if (response_size != expected_response_size) {
4201*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "error: got %zd bytes, expected %zd\n",
4202*4f2df630SAndroid Build Coastguard Worker 			response_size, expected_response_size);
4203*4f2df630SAndroid Build Coastguard Worker 		return -1; /* Should never happen. */
4204*4f2df630SAndroid Build Coastguard Worker 	}
4205*4f2df630SAndroid Build Coastguard Worker 
4206*4f2df630SAndroid Build Coastguard Worker 	if (response_size) {
4207*4f2df630SAndroid Build Coastguard Worker 		memcpy(&tstamp, max_response, sizeof(tstamp));
4208*4f2df630SAndroid Build Coastguard Worker 		printf("Current H1 time is %d\n", be32toh(tstamp));
4209*4f2df630SAndroid Build Coastguard Worker 	}
4210*4f2df630SAndroid Build Coastguard Worker 	return 0;
4211*4f2df630SAndroid Build Coastguard Worker }
4212*4f2df630SAndroid Build Coastguard Worker 
process_reboot_gsc(struct transfer_descriptor * td,size_t timeout_ms)4213*4f2df630SAndroid Build Coastguard Worker static int process_reboot_gsc(struct transfer_descriptor *td, size_t timeout_ms)
4214*4f2df630SAndroid Build Coastguard Worker {
4215*4f2df630SAndroid Build Coastguard Worker 	/* Reboot timeout in milliseconds.
4216*4f2df630SAndroid Build Coastguard Worker 	 * Maximum value is 1000ms on Ti50.
4217*4f2df630SAndroid Build Coastguard Worker 	 */
4218*4f2df630SAndroid Build Coastguard Worker 	uint16_t msg = htobe16((uint16_t)timeout_ms);
4219*4f2df630SAndroid Build Coastguard Worker 	int rv = 0;
4220*4f2df630SAndroid Build Coastguard Worker 
4221*4f2df630SAndroid Build Coastguard Worker 	rv = send_vendor_command(td, VENDOR_CC_IMMEDIATE_RESET, &msg,
4222*4f2df630SAndroid Build Coastguard Worker 				 sizeof(msg), NULL, 0);
4223*4f2df630SAndroid Build Coastguard Worker 	if (rv != VENDOR_RC_SUCCESS) {
4224*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Error %d sending immediate reset command\n",
4225*4f2df630SAndroid Build Coastguard Worker 			rv);
4226*4f2df630SAndroid Build Coastguard Worker 		return update_error;
4227*4f2df630SAndroid Build Coastguard Worker 	}
4228*4f2df630SAndroid Build Coastguard Worker 
4229*4f2df630SAndroid Build Coastguard Worker 	return 0;
4230*4f2df630SAndroid Build Coastguard Worker }
4231*4f2df630SAndroid Build Coastguard Worker 
process_start_apro_verify(struct transfer_descriptor * td)4232*4f2df630SAndroid Build Coastguard Worker static int process_start_apro_verify(struct transfer_descriptor *td)
4233*4f2df630SAndroid Build Coastguard Worker {
4234*4f2df630SAndroid Build Coastguard Worker 	int rv = 0;
4235*4f2df630SAndroid Build Coastguard Worker 
4236*4f2df630SAndroid Build Coastguard Worker 	/*
4237*4f2df630SAndroid Build Coastguard Worker 	 * For Ti50, we need to restart GSC to perform AP RO verification again.
4238*4f2df630SAndroid Build Coastguard Worker 	 */
4239*4f2df630SAndroid Build Coastguard Worker 	if (is_ti50_device())
4240*4f2df630SAndroid Build Coastguard Worker 		return process_reboot_gsc(td, 1000);
4241*4f2df630SAndroid Build Coastguard Worker 
4242*4f2df630SAndroid Build Coastguard Worker 	/* If H1 chip, then send vendor command to start AP RO verification */
4243*4f2df630SAndroid Build Coastguard Worker 	rv = send_vendor_command(td, VENDOR_CC_AP_RO_VALIDATE, NULL, 0, NULL,
4244*4f2df630SAndroid Build Coastguard Worker 				 NULL);
4245*4f2df630SAndroid Build Coastguard Worker 	if (rv != VENDOR_RC_SUCCESS) {
4246*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Error %d starting RO verify\n", rv);
4247*4f2df630SAndroid Build Coastguard Worker 		return update_error;
4248*4f2df630SAndroid Build Coastguard Worker 	}
4249*4f2df630SAndroid Build Coastguard Worker 
4250*4f2df630SAndroid Build Coastguard Worker 	return 0;
4251*4f2df630SAndroid Build Coastguard Worker }
4252*4f2df630SAndroid Build Coastguard Worker 
4253*4f2df630SAndroid Build Coastguard Worker /*
4254*4f2df630SAndroid Build Coastguard Worker  * Search the passed in zero terminated array of options_map structures for
4255*4f2df630SAndroid Build Coastguard Worker  * option 'option'.
4256*4f2df630SAndroid Build Coastguard Worker  *
4257*4f2df630SAndroid Build Coastguard Worker  * If found - set the corresponding integer to 1 and return 1. If not found -
4258*4f2df630SAndroid Build Coastguard Worker  * return 0.
4259*4f2df630SAndroid Build Coastguard Worker  */
check_boolean(const struct options_map * omap,char option)4260*4f2df630SAndroid Build Coastguard Worker static int check_boolean(const struct options_map *omap, char option)
4261*4f2df630SAndroid Build Coastguard Worker {
4262*4f2df630SAndroid Build Coastguard Worker 	do {
4263*4f2df630SAndroid Build Coastguard Worker 		if (omap->opt != option)
4264*4f2df630SAndroid Build Coastguard Worker 			continue;
4265*4f2df630SAndroid Build Coastguard Worker 
4266*4f2df630SAndroid Build Coastguard Worker 		*omap->flag = 1;
4267*4f2df630SAndroid Build Coastguard Worker 		return 1;
4268*4f2df630SAndroid Build Coastguard Worker 	} while ((++omap)->opt);
4269*4f2df630SAndroid Build Coastguard Worker 
4270*4f2df630SAndroid Build Coastguard Worker 	return 0;
4271*4f2df630SAndroid Build Coastguard Worker }
4272*4f2df630SAndroid Build Coastguard Worker 
4273*4f2df630SAndroid Build Coastguard Worker /*
4274*4f2df630SAndroid Build Coastguard Worker  * Set the long_opts table and short_opts string.
4275*4f2df630SAndroid Build Coastguard Worker  *
4276*4f2df630SAndroid Build Coastguard Worker  * This function allows to avoid maintaining two command line option
4277*4f2df630SAndroid Build Coastguard Worker  * descriptions, for short and long forms.
4278*4f2df630SAndroid Build Coastguard Worker  *
4279*4f2df630SAndroid Build Coastguard Worker  * The long_opts table is built based on the cmd_line_options table contents,
4280*4f2df630SAndroid Build Coastguard Worker  * and the short form is built based on the long_opts table contents.
4281*4f2df630SAndroid Build Coastguard Worker  *
4282*4f2df630SAndroid Build Coastguard Worker  * The 'required_argument' short options are followed by ':'.
4283*4f2df630SAndroid Build Coastguard Worker  *
4284*4f2df630SAndroid Build Coastguard Worker  * The passed in long_opts array and short_opts string are guaranteed to
4285*4f2df630SAndroid Build Coastguard Worker  * accommodate all necessary objects/characters.
4286*4f2df630SAndroid Build Coastguard Worker  */
set_opt_descriptors(struct option * long_opts,char * short_opts)4287*4f2df630SAndroid Build Coastguard Worker static void set_opt_descriptors(struct option *long_opts, char *short_opts)
4288*4f2df630SAndroid Build Coastguard Worker {
4289*4f2df630SAndroid Build Coastguard Worker 	size_t i;
4290*4f2df630SAndroid Build Coastguard Worker 	int j;
4291*4f2df630SAndroid Build Coastguard Worker 
4292*4f2df630SAndroid Build Coastguard Worker 	for (i = j = 0; i < ARRAY_SIZE(cmd_line_options); i++) {
4293*4f2df630SAndroid Build Coastguard Worker 		long_opts[i] = cmd_line_options[i].opt;
4294*4f2df630SAndroid Build Coastguard Worker 		short_opts[j++] = long_opts[i].val;
4295*4f2df630SAndroid Build Coastguard Worker 		if (long_opts[i].has_arg == required_argument)
4296*4f2df630SAndroid Build Coastguard Worker 			short_opts[j++] = ':';
4297*4f2df630SAndroid Build Coastguard Worker 	}
4298*4f2df630SAndroid Build Coastguard Worker }
4299*4f2df630SAndroid Build Coastguard Worker 
4300*4f2df630SAndroid Build Coastguard Worker /*
4301*4f2df630SAndroid Build Coastguard Worker  * Find the long_opts table index where .val field is set to the passed in
4302*4f2df630SAndroid Build Coastguard Worker  * short option value.
4303*4f2df630SAndroid Build Coastguard Worker  */
get_longindex(int short_opt,const struct option * long_opts)4304*4f2df630SAndroid Build Coastguard Worker static int get_longindex(int short_opt, const struct option *long_opts)
4305*4f2df630SAndroid Build Coastguard Worker {
4306*4f2df630SAndroid Build Coastguard Worker 	int i;
4307*4f2df630SAndroid Build Coastguard Worker 
4308*4f2df630SAndroid Build Coastguard Worker 	for (i = 0; long_opts[i].name; i++)
4309*4f2df630SAndroid Build Coastguard Worker 		if (long_opts[i].val == short_opt)
4310*4f2df630SAndroid Build Coastguard Worker 			return i;
4311*4f2df630SAndroid Build Coastguard Worker 
4312*4f2df630SAndroid Build Coastguard Worker 	/*
4313*4f2df630SAndroid Build Coastguard Worker 	 * We could never come here as the short options list is compiled
4314*4f2df630SAndroid Build Coastguard Worker 	 * based on long options table.
4315*4f2df630SAndroid Build Coastguard Worker 	 */
4316*4f2df630SAndroid Build Coastguard Worker 	fprintf(stderr, "Command line error, parameter argument missing\n");
4317*4f2df630SAndroid Build Coastguard Worker 	exit(1);
4318*4f2df630SAndroid Build Coastguard Worker 
4319*4f2df630SAndroid Build Coastguard Worker 	return -1; /* Not reached. */
4320*4f2df630SAndroid Build Coastguard Worker }
4321*4f2df630SAndroid Build Coastguard Worker 
4322*4f2df630SAndroid Build Coastguard Worker /*
4323*4f2df630SAndroid Build Coastguard Worker  * Combine searching for command line parameters and optional arguments.
4324*4f2df630SAndroid Build Coastguard Worker  *
4325*4f2df630SAndroid Build Coastguard Worker  * The canonical short options description string does not allow to specify
4326*4f2df630SAndroid Build Coastguard Worker  * that a command line argument expects an optional parameter. but gsctool
4327*4f2df630SAndroid Build Coastguard Worker  * users expect to be able to use the following styles for optional
4328*4f2df630SAndroid Build Coastguard Worker  * parameters:
4329*4f2df630SAndroid Build Coastguard Worker  *
4330*4f2df630SAndroid Build Coastguard Worker  * a)   -x <param value>
4331*4f2df630SAndroid Build Coastguard Worker  * b)  --x_long <param_value>
4332*4f2df630SAndroid Build Coastguard Worker  * c)  --x_long=<param_value>
4333*4f2df630SAndroid Build Coastguard Worker  *
4334*4f2df630SAndroid Build Coastguard Worker  * Styles a) and b) are not supported standard getopt_long(), this function
4335*4f2df630SAndroid Build Coastguard Worker  * adds ability to handle cases a) and b).
4336*4f2df630SAndroid Build Coastguard Worker  */
getopt_all(int argc,char * argv[])4337*4f2df630SAndroid Build Coastguard Worker static int getopt_all(int argc, char *argv[])
4338*4f2df630SAndroid Build Coastguard Worker {
4339*4f2df630SAndroid Build Coastguard Worker 	int longindex = -1;
4340*4f2df630SAndroid Build Coastguard Worker 	static char short_opts[2 * ARRAY_SIZE(cmd_line_options)] = {};
4341*4f2df630SAndroid Build Coastguard Worker 	static struct option long_opts[ARRAY_SIZE(cmd_line_options) + 1] = {};
4342*4f2df630SAndroid Build Coastguard Worker 	int i;
4343*4f2df630SAndroid Build Coastguard Worker 
4344*4f2df630SAndroid Build Coastguard Worker 	if (!short_opts[0])
4345*4f2df630SAndroid Build Coastguard Worker 		set_opt_descriptors(long_opts, short_opts);
4346*4f2df630SAndroid Build Coastguard Worker 
4347*4f2df630SAndroid Build Coastguard Worker 	i = getopt_long(argc, argv, short_opts, long_opts, &longindex);
4348*4f2df630SAndroid Build Coastguard Worker 	if (i != -1) {
4349*4f2df630SAndroid Build Coastguard Worker 		if (longindex < 0) {
4350*4f2df630SAndroid Build Coastguard Worker 			/*
4351*4f2df630SAndroid Build Coastguard Worker 			 * longindex is not set, this must have been the short
4352*4f2df630SAndroid Build Coastguard Worker 			 * option case, Find the long_opts table index based
4353*4f2df630SAndroid Build Coastguard Worker 			 * on the short option value.
4354*4f2df630SAndroid Build Coastguard Worker 			 */
4355*4f2df630SAndroid Build Coastguard Worker 			longindex = get_longindex(i, long_opts);
4356*4f2df630SAndroid Build Coastguard Worker 		}
4357*4f2df630SAndroid Build Coastguard Worker 
4358*4f2df630SAndroid Build Coastguard Worker 		if (long_opts[longindex].has_arg == optional_argument) {
4359*4f2df630SAndroid Build Coastguard Worker 			/*
4360*4f2df630SAndroid Build Coastguard Worker 			 * This command line option may include an argument,
4361*4f2df630SAndroid Build Coastguard Worker 			 * let's check if it is there as the next token in the
4362*4f2df630SAndroid Build Coastguard Worker 			 * command line.
4363*4f2df630SAndroid Build Coastguard Worker 			 */
4364*4f2df630SAndroid Build Coastguard Worker 			if (!optarg && argv[optind] && argv[optind][0] != '-')
4365*4f2df630SAndroid Build Coastguard Worker 				/* Yes, it is. */
4366*4f2df630SAndroid Build Coastguard Worker 				optarg = argv[optind++];
4367*4f2df630SAndroid Build Coastguard Worker 		}
4368*4f2df630SAndroid Build Coastguard Worker 	}
4369*4f2df630SAndroid Build Coastguard Worker 
4370*4f2df630SAndroid Build Coastguard Worker 	return i;
4371*4f2df630SAndroid Build Coastguard Worker }
4372*4f2df630SAndroid Build Coastguard Worker 
get_crashlog(struct transfer_descriptor * td)4373*4f2df630SAndroid Build Coastguard Worker static int get_crashlog(struct transfer_descriptor *td)
4374*4f2df630SAndroid Build Coastguard Worker {
4375*4f2df630SAndroid Build Coastguard Worker 	uint32_t rv;
4376*4f2df630SAndroid Build Coastguard Worker 	uint8_t response[2048] = { 0 };
4377*4f2df630SAndroid Build Coastguard Worker 	size_t response_size = sizeof(response);
4378*4f2df630SAndroid Build Coastguard Worker 
4379*4f2df630SAndroid Build Coastguard Worker 	rv = send_vendor_command(td, VENDOR_CC_GET_CRASHLOG, NULL, 0, response,
4380*4f2df630SAndroid Build Coastguard Worker 				 &response_size);
4381*4f2df630SAndroid Build Coastguard Worker 	if (rv != VENDOR_RC_SUCCESS) {
4382*4f2df630SAndroid Build Coastguard Worker 		printf("Get crash log failed. (%X)\n", rv);
4383*4f2df630SAndroid Build Coastguard Worker 		return 1;
4384*4f2df630SAndroid Build Coastguard Worker 	}
4385*4f2df630SAndroid Build Coastguard Worker 
4386*4f2df630SAndroid Build Coastguard Worker 	for (size_t i = 0; i < response_size; i++) {
4387*4f2df630SAndroid Build Coastguard Worker 		if (i % 64 == 0 && i > 0)
4388*4f2df630SAndroid Build Coastguard Worker 			printf("\n");
4389*4f2df630SAndroid Build Coastguard Worker 		printf("%02x", response[i]);
4390*4f2df630SAndroid Build Coastguard Worker 	}
4391*4f2df630SAndroid Build Coastguard Worker 	printf("\n");
4392*4f2df630SAndroid Build Coastguard Worker 	return 0;
4393*4f2df630SAndroid Build Coastguard Worker }
4394*4f2df630SAndroid Build Coastguard Worker 
get_console_logs(struct transfer_descriptor * td)4395*4f2df630SAndroid Build Coastguard Worker static int get_console_logs(struct transfer_descriptor *td)
4396*4f2df630SAndroid Build Coastguard Worker {
4397*4f2df630SAndroid Build Coastguard Worker 	uint32_t rv;
4398*4f2df630SAndroid Build Coastguard Worker 	uint8_t response[2048] = { 0 };
4399*4f2df630SAndroid Build Coastguard Worker 	size_t response_size = sizeof(response);
4400*4f2df630SAndroid Build Coastguard Worker 
4401*4f2df630SAndroid Build Coastguard Worker 	rv = send_vendor_command(td, VENDOR_CC_GET_CONSOLE_LOGS, NULL, 0,
4402*4f2df630SAndroid Build Coastguard Worker 				 response, &response_size);
4403*4f2df630SAndroid Build Coastguard Worker 	if (rv != VENDOR_RC_SUCCESS) {
4404*4f2df630SAndroid Build Coastguard Worker 		printf("Get console logs failed. (%X)\n", rv);
4405*4f2df630SAndroid Build Coastguard Worker 		return 1;
4406*4f2df630SAndroid Build Coastguard Worker 	}
4407*4f2df630SAndroid Build Coastguard Worker 
4408*4f2df630SAndroid Build Coastguard Worker 	printf("%s", response);
4409*4f2df630SAndroid Build Coastguard Worker 	printf("\n");
4410*4f2df630SAndroid Build Coastguard Worker 	return 0;
4411*4f2df630SAndroid Build Coastguard Worker }
4412*4f2df630SAndroid Build Coastguard Worker 
process_get_factory_config(struct transfer_descriptor * td)4413*4f2df630SAndroid Build Coastguard Worker static int process_get_factory_config(struct transfer_descriptor *td)
4414*4f2df630SAndroid Build Coastguard Worker {
4415*4f2df630SAndroid Build Coastguard Worker 	uint32_t rv;
4416*4f2df630SAndroid Build Coastguard Worker 	uint64_t response = 0;
4417*4f2df630SAndroid Build Coastguard Worker 	size_t response_size = sizeof(response);
4418*4f2df630SAndroid Build Coastguard Worker 
4419*4f2df630SAndroid Build Coastguard Worker 	rv = send_vendor_command(td, VENDOR_CC_GET_FACTORY_CONFIG, NULL, 0,
4420*4f2df630SAndroid Build Coastguard Worker 				 (uint8_t *)&response, &response_size);
4421*4f2df630SAndroid Build Coastguard Worker 	if (rv != VENDOR_RC_SUCCESS) {
4422*4f2df630SAndroid Build Coastguard Worker 		printf("Get factory config failed. (%X)\n", rv);
4423*4f2df630SAndroid Build Coastguard Worker 		return 1;
4424*4f2df630SAndroid Build Coastguard Worker 	}
4425*4f2df630SAndroid Build Coastguard Worker 
4426*4f2df630SAndroid Build Coastguard Worker 	if (response_size < sizeof(uint64_t)) {
4427*4f2df630SAndroid Build Coastguard Worker 		printf("Unexpected response size. (%zu)", response_size);
4428*4f2df630SAndroid Build Coastguard Worker 		return 2;
4429*4f2df630SAndroid Build Coastguard Worker 	}
4430*4f2df630SAndroid Build Coastguard Worker 
4431*4f2df630SAndroid Build Coastguard Worker 	uint64_t out = be64toh(response);
4432*4f2df630SAndroid Build Coastguard Worker 	bool is_x_branded = (out >> 4) & 1;
4433*4f2df630SAndroid Build Coastguard Worker 	uint8_t compliance_version = out & 0xF;
4434*4f2df630SAndroid Build Coastguard Worker 
4435*4f2df630SAndroid Build Coastguard Worker 	printf("raw value: %016" PRIX64 "\n", out);
4436*4f2df630SAndroid Build Coastguard Worker 	printf("chassis_x_branded: %s\n", is_x_branded ? "true" : "false");
4437*4f2df630SAndroid Build Coastguard Worker 	printf("hw_x_compliance_version: %02X\n", compliance_version);
4438*4f2df630SAndroid Build Coastguard Worker 	return 0;
4439*4f2df630SAndroid Build Coastguard Worker }
4440*4f2df630SAndroid Build Coastguard Worker 
process_set_factory_config(struct transfer_descriptor * td,uint64_t val)4441*4f2df630SAndroid Build Coastguard Worker static int process_set_factory_config(struct transfer_descriptor *td,
4442*4f2df630SAndroid Build Coastguard Worker 				      uint64_t val)
4443*4f2df630SAndroid Build Coastguard Worker {
4444*4f2df630SAndroid Build Coastguard Worker 	uint64_t val_be = htobe64(val);
4445*4f2df630SAndroid Build Coastguard Worker 	uint32_t rv;
4446*4f2df630SAndroid Build Coastguard Worker 
4447*4f2df630SAndroid Build Coastguard Worker 	rv = send_vendor_command(td, VENDOR_CC_SET_FACTORY_CONFIG, &val_be,
4448*4f2df630SAndroid Build Coastguard Worker 				 sizeof(val_be), NULL, NULL);
4449*4f2df630SAndroid Build Coastguard Worker 	if (rv != VENDOR_RC_SUCCESS) {
4450*4f2df630SAndroid Build Coastguard Worker 		printf("Factory config failed. (%X)\n", rv);
4451*4f2df630SAndroid Build Coastguard Worker 		return 1;
4452*4f2df630SAndroid Build Coastguard Worker 	}
4453*4f2df630SAndroid Build Coastguard Worker 
4454*4f2df630SAndroid Build Coastguard Worker 	return 0;
4455*4f2df630SAndroid Build Coastguard Worker }
4456*4f2df630SAndroid Build Coastguard Worker 
process_get_time(struct transfer_descriptor * td)4457*4f2df630SAndroid Build Coastguard Worker static int process_get_time(struct transfer_descriptor *td)
4458*4f2df630SAndroid Build Coastguard Worker {
4459*4f2df630SAndroid Build Coastguard Worker 	uint32_t rv;
4460*4f2df630SAndroid Build Coastguard Worker 	uint64_t response = 0;
4461*4f2df630SAndroid Build Coastguard Worker 	size_t response_size = sizeof(response);
4462*4f2df630SAndroid Build Coastguard Worker 
4463*4f2df630SAndroid Build Coastguard Worker 	rv = send_vendor_command(td, VENDOR_CC_GET_TIME, NULL, 0,
4464*4f2df630SAndroid Build Coastguard Worker 				 (uint8_t *)&response, &response_size);
4465*4f2df630SAndroid Build Coastguard Worker 	if (rv != VENDOR_RC_SUCCESS) {
4466*4f2df630SAndroid Build Coastguard Worker 		printf("Get time failed. (%X)\n", rv);
4467*4f2df630SAndroid Build Coastguard Worker 		return 1;
4468*4f2df630SAndroid Build Coastguard Worker 	}
4469*4f2df630SAndroid Build Coastguard Worker 
4470*4f2df630SAndroid Build Coastguard Worker 	if (response_size < sizeof(uint64_t)) {
4471*4f2df630SAndroid Build Coastguard Worker 		printf("Unexpected response size. (%zu)", response_size);
4472*4f2df630SAndroid Build Coastguard Worker 		return 2;
4473*4f2df630SAndroid Build Coastguard Worker 	}
4474*4f2df630SAndroid Build Coastguard Worker 
4475*4f2df630SAndroid Build Coastguard Worker 	uint64_t out = be64toh(response);
4476*4f2df630SAndroid Build Coastguard Worker 
4477*4f2df630SAndroid Build Coastguard Worker 	printf("%" PRIu64 "\n", out);
4478*4f2df630SAndroid Build Coastguard Worker 	return 0;
4479*4f2df630SAndroid Build Coastguard Worker }
4480*4f2df630SAndroid Build Coastguard Worker 
print_ti50_misc_status(uint32_t misc_status,uint32_t version)4481*4f2df630SAndroid Build Coastguard Worker static void print_ti50_misc_status(uint32_t misc_status, uint32_t version)
4482*4f2df630SAndroid Build Coastguard Worker {
4483*4f2df630SAndroid Build Coastguard Worker 	misc_status = be32toh(misc_status);
4484*4f2df630SAndroid Build Coastguard Worker 	printf("misc_status (%d):         %08x\n", version, misc_status);
4485*4f2df630SAndroid Build Coastguard Worker 	printf("  rdd_keepalive:         %d\n",
4486*4f2df630SAndroid Build Coastguard Worker 	       misc_status & METRICSV_RDD_KEEP_ALIVE_MASK);
4487*4f2df630SAndroid Build Coastguard Worker 	printf("  rdd_keepalive_at_boot: %d\n",
4488*4f2df630SAndroid Build Coastguard Worker 	       (misc_status & METRICSV_RDD_KEEP_ALIVE_AT_BOOT_MASK) >>
4489*4f2df630SAndroid Build Coastguard Worker 		       METRICSV_RDD_KEEP_ALIVE_AT_BOOT_SHIFT);
4490*4f2df630SAndroid Build Coastguard Worker 	printf("  ccd_mode:              %d\n",
4491*4f2df630SAndroid Build Coastguard Worker 	       (misc_status & METRICSV_CCD_MODE_MASK) >>
4492*4f2df630SAndroid Build Coastguard Worker 		       METRICSV_CCD_MODE_SHIFT);
4493*4f2df630SAndroid Build Coastguard Worker 	if (version < 3)
4494*4f2df630SAndroid Build Coastguard Worker 		return;
4495*4f2df630SAndroid Build Coastguard Worker 	/* Display metrics added in version 3 */
4496*4f2df630SAndroid Build Coastguard Worker 	printf("  wp_asserted:           %d\n",
4497*4f2df630SAndroid Build Coastguard Worker 	       (misc_status & METRICSV_WP_ASSERTED_MASK) >>
4498*4f2df630SAndroid Build Coastguard Worker 		       METRICSV_WP_ASSERTED_SHIFT);
4499*4f2df630SAndroid Build Coastguard Worker 	printf("  allow_unverified_ro:   %d\n",
4500*4f2df630SAndroid Build Coastguard Worker 	       (misc_status & METRICSV_ALLOW_UNVERIFIED_RO_MASK) >>
4501*4f2df630SAndroid Build Coastguard Worker 		       METRICSV_ALLOW_UNVERIFIED_RO_SHIFT);
4502*4f2df630SAndroid Build Coastguard Worker 	printf("  is_prod:               %d\n",
4503*4f2df630SAndroid Build Coastguard Worker 	       (misc_status & METRICSV_IS_PROD_MASK) >> METRICSV_IS_PROD_SHIFT);
4504*4f2df630SAndroid Build Coastguard Worker }
4505*4f2df630SAndroid Build Coastguard Worker 
print_ti50_stats(struct ti50_stats_v0 * stats_v0,size_t size)4506*4f2df630SAndroid Build Coastguard Worker static int print_ti50_stats(struct ti50_stats_v0 *stats_v0, size_t size)
4507*4f2df630SAndroid Build Coastguard Worker {
4508*4f2df630SAndroid Build Coastguard Worker 	stats_v0->fs_init_time = be32toh(stats_v0->fs_init_time);
4509*4f2df630SAndroid Build Coastguard Worker 	stats_v0->fs_usage = be32toh(stats_v0->fs_usage);
4510*4f2df630SAndroid Build Coastguard Worker 	stats_v0->aprov_time = be32toh(stats_v0->aprov_time);
4511*4f2df630SAndroid Build Coastguard Worker 	stats_v0->expanded_aprov_status =
4512*4f2df630SAndroid Build Coastguard Worker 		be32toh(stats_v0->expanded_aprov_status);
4513*4f2df630SAndroid Build Coastguard Worker 
4514*4f2df630SAndroid Build Coastguard Worker 	printf("fs_init_time:          %d\n", stats_v0->fs_init_time);
4515*4f2df630SAndroid Build Coastguard Worker 	printf("fs_usage:              %d\n", stats_v0->fs_usage);
4516*4f2df630SAndroid Build Coastguard Worker 	printf("aprov_time:            %d\n", stats_v0->aprov_time);
4517*4f2df630SAndroid Build Coastguard Worker 	printf("expanded_aprov_status: %X\n", stats_v0->expanded_aprov_status);
4518*4f2df630SAndroid Build Coastguard Worker 
4519*4f2df630SAndroid Build Coastguard Worker 	if (size == sizeof(struct ti50_stats_v1)) {
4520*4f2df630SAndroid Build Coastguard Worker 		struct ti50_stats_v1 *stats_v1 =
4521*4f2df630SAndroid Build Coastguard Worker 			(struct ti50_stats_v1 *)stats_v0;
4522*4f2df630SAndroid Build Coastguard Worker 		print_ti50_misc_status(stats_v1->misc_status, 1);
4523*4f2df630SAndroid Build Coastguard Worker 		return 0;
4524*4f2df630SAndroid Build Coastguard Worker 	}
4525*4f2df630SAndroid Build Coastguard Worker 	if (size >= sizeof(struct ti50_stats)) {
4526*4f2df630SAndroid Build Coastguard Worker 		struct ti50_stats *stats = (struct ti50_stats *)stats_v0;
4527*4f2df630SAndroid Build Coastguard Worker 
4528*4f2df630SAndroid Build Coastguard Worker 		stats->version = be32toh(stats->version);
4529*4f2df630SAndroid Build Coastguard Worker 		/* Version was added with v2 and therefore must be >= 2. */
4530*4f2df630SAndroid Build Coastguard Worker 		if (stats->version < 2) {
4531*4f2df630SAndroid Build Coastguard Worker 			printf("Invalid stats version %d.", stats->version);
4532*4f2df630SAndroid Build Coastguard Worker 			return 1;
4533*4f2df630SAndroid Build Coastguard Worker 		}
4534*4f2df630SAndroid Build Coastguard Worker 
4535*4f2df630SAndroid Build Coastguard Worker 		stats->filesystem_busy_count =
4536*4f2df630SAndroid Build Coastguard Worker 			be32toh(stats->filesystem_busy_count);
4537*4f2df630SAndroid Build Coastguard Worker 		stats->crypto_busy_count = be32toh(stats->crypto_busy_count);
4538*4f2df630SAndroid Build Coastguard Worker 		stats->dispatcher_busy_count =
4539*4f2df630SAndroid Build Coastguard Worker 			be32toh(stats->dispatcher_busy_count);
4540*4f2df630SAndroid Build Coastguard Worker 		stats->timeslices_expired = be32toh(stats->timeslices_expired);
4541*4f2df630SAndroid Build Coastguard Worker 		stats->crypto_init_time = be32toh(stats->crypto_init_time);
4542*4f2df630SAndroid Build Coastguard Worker 
4543*4f2df630SAndroid Build Coastguard Worker 		printf("filesystem_busy_count: %d\n",
4544*4f2df630SAndroid Build Coastguard Worker 		       stats->filesystem_busy_count);
4545*4f2df630SAndroid Build Coastguard Worker 		printf("crypto_busy_count:     %d\n", stats->crypto_busy_count);
4546*4f2df630SAndroid Build Coastguard Worker 		printf("dispatcher_busy_count: %d\n",
4547*4f2df630SAndroid Build Coastguard Worker 		       stats->dispatcher_busy_count);
4548*4f2df630SAndroid Build Coastguard Worker 		printf("timeslices_expired:    %d\n",
4549*4f2df630SAndroid Build Coastguard Worker 		       stats->timeslices_expired);
4550*4f2df630SAndroid Build Coastguard Worker 		printf("crypto_init_time:      %d\n", stats->crypto_init_time);
4551*4f2df630SAndroid Build Coastguard Worker 		print_ti50_misc_status(stats->v1.misc_status, stats->version);
4552*4f2df630SAndroid Build Coastguard Worker 	}
4553*4f2df630SAndroid Build Coastguard Worker 	return 0;
4554*4f2df630SAndroid Build Coastguard Worker }
4555*4f2df630SAndroid Build Coastguard Worker 
process_ti50_get_metrics(struct transfer_descriptor * td,bool show_machine_output)4556*4f2df630SAndroid Build Coastguard Worker static int process_ti50_get_metrics(struct transfer_descriptor *td,
4557*4f2df630SAndroid Build Coastguard Worker 				    bool show_machine_output)
4558*4f2df630SAndroid Build Coastguard Worker {
4559*4f2df630SAndroid Build Coastguard Worker 	uint32_t rv;
4560*4f2df630SAndroid Build Coastguard Worker 	/* Allocate extra space in case future versions add more data. */
4561*4f2df630SAndroid Build Coastguard Worker 	struct ti50_stats response[4];
4562*4f2df630SAndroid Build Coastguard Worker 	size_t response_size = sizeof(response);
4563*4f2df630SAndroid Build Coastguard Worker 
4564*4f2df630SAndroid Build Coastguard Worker 	rv = send_vendor_command(td, VENDOR_CC_GET_TI50_STATS, NULL, 0,
4565*4f2df630SAndroid Build Coastguard Worker 				 (uint8_t *)&response, &response_size);
4566*4f2df630SAndroid Build Coastguard Worker 	if (rv != VENDOR_RC_SUCCESS) {
4567*4f2df630SAndroid Build Coastguard Worker 		printf("Get stats failed. (%X)\n", rv);
4568*4f2df630SAndroid Build Coastguard Worker 		return 1;
4569*4f2df630SAndroid Build Coastguard Worker 	}
4570*4f2df630SAndroid Build Coastguard Worker 
4571*4f2df630SAndroid Build Coastguard Worker 	if (response_size < sizeof(struct ti50_stats_v0)) {
4572*4f2df630SAndroid Build Coastguard Worker 		printf("Unexpected response size. (%zu)\n", response_size);
4573*4f2df630SAndroid Build Coastguard Worker 		return 2;
4574*4f2df630SAndroid Build Coastguard Worker 	}
4575*4f2df630SAndroid Build Coastguard Worker 
4576*4f2df630SAndroid Build Coastguard Worker 	if (show_machine_output) {
4577*4f2df630SAndroid Build Coastguard Worker 		uint8_t *raw_response = (uint8_t *)response;
4578*4f2df630SAndroid Build Coastguard Worker 
4579*4f2df630SAndroid Build Coastguard Worker 		for (size_t i = 0; i < response_size; i++)
4580*4f2df630SAndroid Build Coastguard Worker 			printf("%02X", raw_response[i]);
4581*4f2df630SAndroid Build Coastguard Worker 	} else {
4582*4f2df630SAndroid Build Coastguard Worker 		return print_ti50_stats((struct ti50_stats_v0 *)response,
4583*4f2df630SAndroid Build Coastguard Worker 					response_size);
4584*4f2df630SAndroid Build Coastguard Worker 	}
4585*4f2df630SAndroid Build Coastguard Worker 	return 0;
4586*4f2df630SAndroid Build Coastguard Worker }
4587*4f2df630SAndroid Build Coastguard Worker 
process_cr50_get_metrics(struct transfer_descriptor * td,bool show_machine_output)4588*4f2df630SAndroid Build Coastguard Worker static int process_cr50_get_metrics(struct transfer_descriptor *td,
4589*4f2df630SAndroid Build Coastguard Worker 				    bool show_machine_output)
4590*4f2df630SAndroid Build Coastguard Worker {
4591*4f2df630SAndroid Build Coastguard Worker 	/* Allocate extra space in case future versions add more data. */
4592*4f2df630SAndroid Build Coastguard Worker 	struct cr50_stats_response response[4] = {};
4593*4f2df630SAndroid Build Coastguard Worker 	size_t response_size = sizeof(response);
4594*4f2df630SAndroid Build Coastguard Worker 	struct cr50_stats_response stats;
4595*4f2df630SAndroid Build Coastguard Worker 	uint32_t rv;
4596*4f2df630SAndroid Build Coastguard Worker 
4597*4f2df630SAndroid Build Coastguard Worker 	rv = send_vendor_command(td, VENDOR_CC_GET_CR50_METRICS, NULL, 0,
4598*4f2df630SAndroid Build Coastguard Worker 				 (uint8_t *)&response, &response_size);
4599*4f2df630SAndroid Build Coastguard Worker 	if (rv != VENDOR_RC_SUCCESS) {
4600*4f2df630SAndroid Build Coastguard Worker 		printf("Get stats failed. (%X)\n", rv);
4601*4f2df630SAndroid Build Coastguard Worker 		return 1;
4602*4f2df630SAndroid Build Coastguard Worker 	}
4603*4f2df630SAndroid Build Coastguard Worker 
4604*4f2df630SAndroid Build Coastguard Worker 	if (response_size != sizeof(stats)) {
4605*4f2df630SAndroid Build Coastguard Worker 		printf("Unexpected response size. (%zu)\n", response_size);
4606*4f2df630SAndroid Build Coastguard Worker 		return 2;
4607*4f2df630SAndroid Build Coastguard Worker 	}
4608*4f2df630SAndroid Build Coastguard Worker 
4609*4f2df630SAndroid Build Coastguard Worker 	/* Let's check if this is a newer version response. */
4610*4f2df630SAndroid Build Coastguard Worker 	memcpy(&stats, response, sizeof(stats));
4611*4f2df630SAndroid Build Coastguard Worker 
4612*4f2df630SAndroid Build Coastguard Worker 	stats.version = be32toh(stats.version);
4613*4f2df630SAndroid Build Coastguard Worker 	stats.reset_src = be32toh(stats.reset_src);
4614*4f2df630SAndroid Build Coastguard Worker 	stats.brdprop = be32toh(stats.brdprop);
4615*4f2df630SAndroid Build Coastguard Worker 	stats.reset_time_s = be64toh(stats.reset_time_s);
4616*4f2df630SAndroid Build Coastguard Worker 	stats.cold_reset_time_s = be32toh(stats.cold_reset_time_s);
4617*4f2df630SAndroid Build Coastguard Worker 	stats.misc_status = be32toh(stats.misc_status);
4618*4f2df630SAndroid Build Coastguard Worker 
4619*4f2df630SAndroid Build Coastguard Worker 	if (stats.version > CR50_METRICSV_STATS_VERSION) {
4620*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "unsupported ver - %d. supports up to %d\n",
4621*4f2df630SAndroid Build Coastguard Worker 			stats.version, CR50_METRICSV_STATS_VERSION);
4622*4f2df630SAndroid Build Coastguard Worker 	}
4623*4f2df630SAndroid Build Coastguard Worker 	printf("version:           %10u\n", stats.version);
4624*4f2df630SAndroid Build Coastguard Worker 	printf("reset_src:       0x%010x\n", stats.reset_src);
4625*4f2df630SAndroid Build Coastguard Worker 	printf("brdprop:         0x%010x\n", stats.brdprop);
4626*4f2df630SAndroid Build Coastguard Worker 	printf("cold_reset_time_s: %10u\n", stats.cold_reset_time_s);
4627*4f2df630SAndroid Build Coastguard Worker 	printf("reset_time_s:      %10u\n", stats.reset_time_s);
4628*4f2df630SAndroid Build Coastguard Worker 	printf("misc_status:     0x%010x\n", stats.misc_status);
4629*4f2df630SAndroid Build Coastguard Worker 
4630*4f2df630SAndroid Build Coastguard Worker 	printf("   rdd detected:      %7d\n",
4631*4f2df630SAndroid Build Coastguard Worker 	       (stats.misc_status >> CR50_METRICSV_RDD_IS_DETECTED_SHIFT) & 1);
4632*4f2df630SAndroid Build Coastguard Worker 	printf("   rddkeeplive en:    %7d\n",
4633*4f2df630SAndroid Build Coastguard Worker 	       (stats.misc_status >> CR50_METRICSV_RDD_KEEPALIVE_EN_SHIFT) & 1);
4634*4f2df630SAndroid Build Coastguard Worker 	printf("   rddkeeplive en atboot: %3d\n",
4635*4f2df630SAndroid Build Coastguard Worker 	       (stats.misc_status >>
4636*4f2df630SAndroid Build Coastguard Worker 		CR50_METRICSV_RDD_KEEPALIVE_EN_ATBOOT_SHIFT) &
4637*4f2df630SAndroid Build Coastguard Worker 		       1);
4638*4f2df630SAndroid Build Coastguard Worker 	printf("   ccd_mode en:       %7d\n",
4639*4f2df630SAndroid Build Coastguard Worker 	       (stats.misc_status >> CR50_METRICSV_CCD_MODE_EN_SHIFT) & 1);
4640*4f2df630SAndroid Build Coastguard Worker 	printf("   ambigous straps:   %7d\n",
4641*4f2df630SAndroid Build Coastguard Worker 	       (stats.misc_status >> CR50_METRICSV_AMBIGUOUS_STRAP_SHIFT) & 1);
4642*4f2df630SAndroid Build Coastguard Worker 
4643*4f2df630SAndroid Build Coastguard Worker 	return 0;
4644*4f2df630SAndroid Build Coastguard Worker }
4645*4f2df630SAndroid Build Coastguard Worker 
4646*4f2df630SAndroid Build Coastguard Worker /*
4647*4f2df630SAndroid Build Coastguard Worker  * The below variables and array must be held in sync with the appropriate
4648*4f2df630SAndroid Build Coastguard Worker  * counterparts in defined in ti50:common/{hil,capsules}/src/boot_tracer.rs.
4649*4f2df630SAndroid Build Coastguard Worker  */
4650*4f2df630SAndroid Build Coastguard Worker #define MAX_BOOT_TRACE_SIZE 54
4651*4f2df630SAndroid Build Coastguard Worker #define TIMESPAN_EVENT	    0
4652*4f2df630SAndroid Build Coastguard Worker #define TIME_SHIFT	    11
4653*4f2df630SAndroid Build Coastguard Worker #define MAX_TIME_MS	    (1 << TIME_SHIFT)
4654*4f2df630SAndroid Build Coastguard Worker static const char *const boot_tracer_stages[] = {
4655*4f2df630SAndroid Build Coastguard Worker 	"Timespan", /* This one will not be displayed separately. */
4656*4f2df630SAndroid Build Coastguard Worker 	"ProjectStart",	  "EcRstAsserted",    "EcRstDeasserted",
4657*4f2df630SAndroid Build Coastguard Worker 	"TpmRstAsserted", "TpmRstDeasserted", "FirstApComms",
4658*4f2df630SAndroid Build Coastguard Worker 	"PcrExtension",	  "TpmAppReady"
4659*4f2df630SAndroid Build Coastguard Worker };
4660*4f2df630SAndroid Build Coastguard Worker 
process_get_boot_trace(struct transfer_descriptor * td,bool erase,bool show_machine_output)4661*4f2df630SAndroid Build Coastguard Worker static int process_get_boot_trace(struct transfer_descriptor *td, bool erase,
4662*4f2df630SAndroid Build Coastguard Worker 				  bool show_machine_output)
4663*4f2df630SAndroid Build Coastguard Worker {
4664*4f2df630SAndroid Build Coastguard Worker 	/* zero means no erase, 1 means erase. */
4665*4f2df630SAndroid Build Coastguard Worker 	uint32_t payload = htobe32(erase);
4666*4f2df630SAndroid Build Coastguard Worker 	uint16_t boot_trace[MAX_BOOT_TRACE_SIZE / sizeof(uint16_t)];
4667*4f2df630SAndroid Build Coastguard Worker 	size_t response_size = sizeof(boot_trace);
4668*4f2df630SAndroid Build Coastguard Worker 	uint32_t rv;
4669*4f2df630SAndroid Build Coastguard Worker 	uint64_t timespan = 0;
4670*4f2df630SAndroid Build Coastguard Worker 	size_t i;
4671*4f2df630SAndroid Build Coastguard Worker 
4672*4f2df630SAndroid Build Coastguard Worker 	rv = send_vendor_command(td, VENDOR_CC_GET_BOOT_TRACE, &payload,
4673*4f2df630SAndroid Build Coastguard Worker 				 sizeof(payload), &boot_trace, &response_size);
4674*4f2df630SAndroid Build Coastguard Worker 
4675*4f2df630SAndroid Build Coastguard Worker 	if (rv != VENDOR_RC_SUCCESS) {
4676*4f2df630SAndroid Build Coastguard Worker 		printf("Get boot trace failed. (%X)\n", rv);
4677*4f2df630SAndroid Build Coastguard Worker 		return 1;
4678*4f2df630SAndroid Build Coastguard Worker 	}
4679*4f2df630SAndroid Build Coastguard Worker 
4680*4f2df630SAndroid Build Coastguard Worker 	if (response_size == 0)
4681*4f2df630SAndroid Build Coastguard Worker 		return 0; /* Trace is empty. */
4682*4f2df630SAndroid Build Coastguard Worker 
4683*4f2df630SAndroid Build Coastguard Worker 	if (!show_machine_output)
4684*4f2df630SAndroid Build Coastguard Worker 		printf("    got %zd bytes back:\n", response_size);
4685*4f2df630SAndroid Build Coastguard Worker 	if (response_size > 0) {
4686*4f2df630SAndroid Build Coastguard Worker 		for (i = 0; i < response_size / sizeof(uint16_t); i++) {
4687*4f2df630SAndroid Build Coastguard Worker 			uint16_t entry = boot_trace[i];
4688*4f2df630SAndroid Build Coastguard Worker 			uint16_t event_id = entry >> TIME_SHIFT;
4689*4f2df630SAndroid Build Coastguard Worker 			uint16_t delta_time = entry & ((1 << TIME_SHIFT) - 1);
4690*4f2df630SAndroid Build Coastguard Worker 
4691*4f2df630SAndroid Build Coastguard Worker 			if (show_machine_output) {
4692*4f2df630SAndroid Build Coastguard Worker 				printf(" %04x", entry);
4693*4f2df630SAndroid Build Coastguard Worker 				continue;
4694*4f2df630SAndroid Build Coastguard Worker 			}
4695*4f2df630SAndroid Build Coastguard Worker 
4696*4f2df630SAndroid Build Coastguard Worker 			if (event_id >= ARRAY_SIZE(boot_tracer_stages)) {
4697*4f2df630SAndroid Build Coastguard Worker 				printf("Unknown event %d\n", event_id);
4698*4f2df630SAndroid Build Coastguard Worker 				continue;
4699*4f2df630SAndroid Build Coastguard Worker 			}
4700*4f2df630SAndroid Build Coastguard Worker 
4701*4f2df630SAndroid Build Coastguard Worker 			if (event_id == TIMESPAN_EVENT) {
4702*4f2df630SAndroid Build Coastguard Worker 				timespan += (uint64_t)delta_time * MAX_TIME_MS;
4703*4f2df630SAndroid Build Coastguard Worker 				continue;
4704*4f2df630SAndroid Build Coastguard Worker 			}
4705*4f2df630SAndroid Build Coastguard Worker 			printf(" %20s: %4" PRId64 " ms\n",
4706*4f2df630SAndroid Build Coastguard Worker 			       boot_tracer_stages[event_id],
4707*4f2df630SAndroid Build Coastguard Worker 			       timespan + delta_time);
4708*4f2df630SAndroid Build Coastguard Worker 			timespan = 0;
4709*4f2df630SAndroid Build Coastguard Worker 		}
4710*4f2df630SAndroid Build Coastguard Worker 		printf("\n");
4711*4f2df630SAndroid Build Coastguard Worker 	}
4712*4f2df630SAndroid Build Coastguard Worker 	return 0;
4713*4f2df630SAndroid Build Coastguard Worker }
4714*4f2df630SAndroid Build Coastguard Worker 
4715*4f2df630SAndroid Build Coastguard Worker struct get_chip_id_response {
4716*4f2df630SAndroid Build Coastguard Worker 	uint32_t tpm_vid_pid;
4717*4f2df630SAndroid Build Coastguard Worker 	uint32_t chip_id;
4718*4f2df630SAndroid Build Coastguard Worker };
4719*4f2df630SAndroid Build Coastguard Worker 
get_chip_id_info(struct transfer_descriptor * td)4720*4f2df630SAndroid Build Coastguard Worker static struct get_chip_id_response get_chip_id_info(
4721*4f2df630SAndroid Build Coastguard Worker 	struct transfer_descriptor *td)
4722*4f2df630SAndroid Build Coastguard Worker {
4723*4f2df630SAndroid Build Coastguard Worker 	uint32_t rv;
4724*4f2df630SAndroid Build Coastguard Worker 	struct get_chip_id_response response;
4725*4f2df630SAndroid Build Coastguard Worker 	size_t response_size = sizeof(response);
4726*4f2df630SAndroid Build Coastguard Worker 
4727*4f2df630SAndroid Build Coastguard Worker 	rv = send_vendor_command(td, VENDOR_CC_GET_CHIP_ID, NULL, 0,
4728*4f2df630SAndroid Build Coastguard Worker 				 (uint8_t *)&response, &response_size);
4729*4f2df630SAndroid Build Coastguard Worker 	if (rv != VENDOR_RC_SUCCESS) {
4730*4f2df630SAndroid Build Coastguard Worker 		debug("Failed getting chip id: 0x%X. Okay for older chips\n",
4731*4f2df630SAndroid Build Coastguard Worker 		      rv);
4732*4f2df630SAndroid Build Coastguard Worker 	} else if (response_size < sizeof(response)) {
4733*4f2df630SAndroid Build Coastguard Worker 		debug("Unexpected response size. (%zu)\n", response_size);
4734*4f2df630SAndroid Build Coastguard Worker 	} else {
4735*4f2df630SAndroid Build Coastguard Worker 		/* Success, convert endianness then return */
4736*4f2df630SAndroid Build Coastguard Worker 		response.tpm_vid_pid = be32toh(response.tpm_vid_pid);
4737*4f2df630SAndroid Build Coastguard Worker 		response.chip_id = be32toh(response.chip_id);
4738*4f2df630SAndroid Build Coastguard Worker 		return response;
4739*4f2df630SAndroid Build Coastguard Worker 	}
4740*4f2df630SAndroid Build Coastguard Worker 	/* Zero memory before returning since there was an error */
4741*4f2df630SAndroid Build Coastguard Worker 	memset(&response, 0, sizeof(response));
4742*4f2df630SAndroid Build Coastguard Worker 	return response;
4743*4f2df630SAndroid Build Coastguard Worker }
4744*4f2df630SAndroid Build Coastguard Worker 
4745*4f2df630SAndroid Build Coastguard Worker /*
4746*4f2df630SAndroid Build Coastguard Worker  * Returns the GSC device type determine by how is responds to TPMV and
4747*4f2df630SAndroid Build Coastguard Worker  * version requests.
4748*4f2df630SAndroid Build Coastguard Worker  */
determine_gsc_type(struct transfer_descriptor * td)4749*4f2df630SAndroid Build Coastguard Worker static enum gsc_device determine_gsc_type(struct transfer_descriptor *td)
4750*4f2df630SAndroid Build Coastguard Worker {
4751*4f2df630SAndroid Build Coastguard Worker 	int epoch;
4752*4f2df630SAndroid Build Coastguard Worker 	int major;
4753*4f2df630SAndroid Build Coastguard Worker 	struct get_chip_id_response chip_id;
4754*4f2df630SAndroid Build Coastguard Worker 
4755*4f2df630SAndroid Build Coastguard Worker 	/*
4756*4f2df630SAndroid Build Coastguard Worker 	 * Get the firmware version first. See if this is a specific GSC version
4757*4f2df630SAndroid Build Coastguard Worker 	 * where the Ti50 FW does not response with an error code if the host
4758*4f2df630SAndroid Build Coastguard Worker 	 * tries an unknown TPMV command over USB. This prevents a USB timeout
4759*4f2df630SAndroid Build Coastguard Worker 	 * and shutting down of USB subsystem within gsctool (b/368631328).
4760*4f2df630SAndroid Build Coastguard Worker 	 */
4761*4f2df630SAndroid Build Coastguard Worker 	get_version(td, false);
4762*4f2df630SAndroid Build Coastguard Worker 	epoch = targ.shv[1].epoch;
4763*4f2df630SAndroid Build Coastguard Worker 	major = targ.shv[1].major;
4764*4f2df630SAndroid Build Coastguard Worker 	if ((epoch == 0 || epoch == 1) && (major >= 21 && major <= 26))
4765*4f2df630SAndroid Build Coastguard Worker 		return GSC_DEVICE_DT;
4766*4f2df630SAndroid Build Coastguard Worker 	/*
4767*4f2df630SAndroid Build Coastguard Worker 	 * Try the newer TPMV command. If the command isn't supported,
4768*4f2df630SAndroid Build Coastguard Worker 	 * then the GSC should respond with an error. If that happens we will
4769*4f2df630SAndroid Build Coastguard Worker 	 * fall back to the GSC version as the indicator.
4770*4f2df630SAndroid Build Coastguard Worker 	 */
4771*4f2df630SAndroid Build Coastguard Worker 	chip_id = get_chip_id_info(td);
4772*4f2df630SAndroid Build Coastguard Worker 	switch (chip_id.tpm_vid_pid) {
4773*4f2df630SAndroid Build Coastguard Worker 	case 0x50666666:
4774*4f2df630SAndroid Build Coastguard Worker 		return GSC_DEVICE_NT;
4775*4f2df630SAndroid Build Coastguard Worker 	case 0x504a6666:
4776*4f2df630SAndroid Build Coastguard Worker 		return GSC_DEVICE_DT;
4777*4f2df630SAndroid Build Coastguard Worker 	case 0x00281ae0:
4778*4f2df630SAndroid Build Coastguard Worker 		return GSC_DEVICE_H1;
4779*4f2df630SAndroid Build Coastguard Worker 	}
4780*4f2df630SAndroid Build Coastguard Worker 
4781*4f2df630SAndroid Build Coastguard Worker 	if (chip_id.tpm_vid_pid)
4782*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr, "Unregonized VID_PID 0x%X\n",
4783*4f2df630SAndroid Build Coastguard Worker 			chip_id.tpm_vid_pid);
4784*4f2df630SAndroid Build Coastguard Worker 
4785*4f2df630SAndroid Build Coastguard Worker 	/*
4786*4f2df630SAndroid Build Coastguard Worker 	 * If TPMV command doesn't exist or VID_PID is unrecognized then,
4787*4f2df630SAndroid Build Coastguard Worker 	 * use the firmware version to determine type.
4788*4f2df630SAndroid Build Coastguard Worker 	 */
4789*4f2df630SAndroid Build Coastguard Worker 	major = targ.shv[1].major;
4790*4f2df630SAndroid Build Coastguard Worker 	if (major >= 30 && major < 40)
4791*4f2df630SAndroid Build Coastguard Worker 		return GSC_DEVICE_NT;
4792*4f2df630SAndroid Build Coastguard Worker 	else if (major >= 20 && major < 30)
4793*4f2df630SAndroid Build Coastguard Worker 		return GSC_DEVICE_DT;
4794*4f2df630SAndroid Build Coastguard Worker 	else
4795*4f2df630SAndroid Build Coastguard Worker 		return GSC_DEVICE_H1;
4796*4f2df630SAndroid Build Coastguard Worker }
4797*4f2df630SAndroid Build Coastguard Worker 
main(int argc,char * argv[])4798*4f2df630SAndroid Build Coastguard Worker int main(int argc, char *argv[])
4799*4f2df630SAndroid Build Coastguard Worker {
4800*4f2df630SAndroid Build Coastguard Worker 	struct transfer_descriptor td;
4801*4f2df630SAndroid Build Coastguard Worker 	int rv = 0;
4802*4f2df630SAndroid Build Coastguard Worker 	int errorcnt;
4803*4f2df630SAndroid Build Coastguard Worker 	struct image *images = NULL;
4804*4f2df630SAndroid Build Coastguard Worker 	int num_images = 0;
4805*4f2df630SAndroid Build Coastguard Worker 	uint16_t vid = 0;
4806*4f2df630SAndroid Build Coastguard Worker 	uint16_t pid = 0;
4807*4f2df630SAndroid Build Coastguard Worker 	int i;
4808*4f2df630SAndroid Build Coastguard Worker 	int transferred_sections = 0;
4809*4f2df630SAndroid Build Coastguard Worker 	int binary_vers = 0;
4810*4f2df630SAndroid Build Coastguard Worker 	int show_fw_ver = 0;
4811*4f2df630SAndroid Build Coastguard Worker 	int rma = 0;
4812*4f2df630SAndroid Build Coastguard Worker 	const char *rma_auth_code = "";
4813*4f2df630SAndroid Build Coastguard Worker 	int get_endorsement_seed = 0;
4814*4f2df630SAndroid Build Coastguard Worker 	const char *endorsement_seed_str = "";
4815*4f2df630SAndroid Build Coastguard Worker 	int corrupt_inactive_rw = 0;
4816*4f2df630SAndroid Build Coastguard Worker 	struct board_id bid;
4817*4f2df630SAndroid Build Coastguard Worker 	enum board_id_action bid_action;
4818*4f2df630SAndroid Build Coastguard Worker 	int password = 0;
4819*4f2df630SAndroid Build Coastguard Worker 	int ccd_open = 0;
4820*4f2df630SAndroid Build Coastguard Worker 	int ccd_unlock = 0;
4821*4f2df630SAndroid Build Coastguard Worker 	int ccd_lock = 0;
4822*4f2df630SAndroid Build Coastguard Worker 	int ccd_info = 0;
4823*4f2df630SAndroid Build Coastguard Worker 	int get_flog = 0;
4824*4f2df630SAndroid Build Coastguard Worker 	uint32_t prev_log_entry = 0;
4825*4f2df630SAndroid Build Coastguard Worker 	enum wp_options wp = WP_NONE;
4826*4f2df630SAndroid Build Coastguard Worker 	int get_boot_mode = 0;
4827*4f2df630SAndroid Build Coastguard Worker 	int try_all_transfer = 0;
4828*4f2df630SAndroid Build Coastguard Worker 	int tpm_mode = 0;
4829*4f2df630SAndroid Build Coastguard Worker 	int get_apro_hash = 0;
4830*4f2df630SAndroid Build Coastguard Worker 	int get_apro_boot_status = 0;
4831*4f2df630SAndroid Build Coastguard Worker 	int start_apro_verify = 0;
4832*4f2df630SAndroid Build Coastguard Worker 	bool show_machine_output = false;
4833*4f2df630SAndroid Build Coastguard Worker 	int tstamp = 0;
4834*4f2df630SAndroid Build Coastguard Worker 	const char *tstamp_arg = NULL;
4835*4f2df630SAndroid Build Coastguard Worker 	enum arv_config_spi_addr_mode_e arv_config_spi_addr_mode =
4836*4f2df630SAndroid Build Coastguard Worker 		arv_config_spi_addr_mode_none;
4837*4f2df630SAndroid Build Coastguard Worker 	enum arv_config_wpsr_choice_e arv_config_wpsr_choice =
4838*4f2df630SAndroid Build Coastguard Worker 		arv_config_wpsr_choice_none;
4839*4f2df630SAndroid Build Coastguard Worker 	struct arv_config_wpds arv_config_wpds = { 0 };
4840*4f2df630SAndroid Build Coastguard Worker 
4841*4f2df630SAndroid Build Coastguard Worker 	const char *exclusive_opt_error =
4842*4f2df630SAndroid Build Coastguard Worker 		"Options -a, -s and -t are mutually exclusive\n";
4843*4f2df630SAndroid Build Coastguard Worker 	const char *openbox_desc_file = NULL;
4844*4f2df630SAndroid Build Coastguard Worker 	int factory_mode = 0;
4845*4f2df630SAndroid Build Coastguard Worker 	char *factory_mode_arg = "";
4846*4f2df630SAndroid Build Coastguard Worker 	char *tpm_mode_arg = NULL;
4847*4f2df630SAndroid Build Coastguard Worker 	char *serial = NULL;
4848*4f2df630SAndroid Build Coastguard Worker 	int sn_bits = 0;
4849*4f2df630SAndroid Build Coastguard Worker 	uint8_t sn_bits_arg[SN_BITS_SIZE];
4850*4f2df630SAndroid Build Coastguard Worker 	int sn_inc_rma = 0;
4851*4f2df630SAndroid Build Coastguard Worker 	uint8_t sn_inc_rma_arg = 0;
4852*4f2df630SAndroid Build Coastguard Worker 	int erase_ap_ro_hash = 0;
4853*4f2df630SAndroid Build Coastguard Worker 	int set_capability = 0;
4854*4f2df630SAndroid Build Coastguard Worker 	const char *capability_parameter = "";
4855*4f2df630SAndroid Build Coastguard Worker 	bool reboot_gsc = false;
4856*4f2df630SAndroid Build Coastguard Worker 	size_t reboot_gsc_timeout = 0;
4857*4f2df630SAndroid Build Coastguard Worker 	int get_clog = 0;
4858*4f2df630SAndroid Build Coastguard Worker 	int get_console = 0;
4859*4f2df630SAndroid Build Coastguard Worker 	int factory_config = 0;
4860*4f2df630SAndroid Build Coastguard Worker 	int set_factory_config = 0;
4861*4f2df630SAndroid Build Coastguard Worker 	uint64_t factory_config_arg = 0;
4862*4f2df630SAndroid Build Coastguard Worker 	int get_time = 0;
4863*4f2df630SAndroid Build Coastguard Worker 	bool get_boot_trace = false;
4864*4f2df630SAndroid Build Coastguard Worker 	bool erase_boot_trace = false;
4865*4f2df630SAndroid Build Coastguard Worker 	bool get_metrics = false;
4866*4f2df630SAndroid Build Coastguard Worker 	bool get_chassis_open = false;
4867*4f2df630SAndroid Build Coastguard Worker 	bool get_dev_ids = false;
4868*4f2df630SAndroid Build Coastguard Worker 	bool get_aprov_reset_counts = false;
4869*4f2df630SAndroid Build Coastguard Worker 
4870*4f2df630SAndroid Build Coastguard Worker 	/*
4871*4f2df630SAndroid Build Coastguard Worker 	 * All options which result in setting a Boolean flag to True, along
4872*4f2df630SAndroid Build Coastguard Worker 	 * with addresses of the flags. Terminated by a zeroed entry.
4873*4f2df630SAndroid Build Coastguard Worker 	 */
4874*4f2df630SAndroid Build Coastguard Worker 	const struct options_map omap[] = {
4875*4f2df630SAndroid Build Coastguard Worker 		{ 'b', &binary_vers },
4876*4f2df630SAndroid Build Coastguard Worker 		{ 'c', &corrupt_inactive_rw },
4877*4f2df630SAndroid Build Coastguard Worker 		{ 'f', &show_fw_ver },
4878*4f2df630SAndroid Build Coastguard Worker 		{ 'g', &get_boot_mode },
4879*4f2df630SAndroid Build Coastguard Worker 		{ 'H', &erase_ap_ro_hash },
4880*4f2df630SAndroid Build Coastguard Worker 		{ 'k', &ccd_lock },
4881*4f2df630SAndroid Build Coastguard Worker 		{ 'o', &ccd_open },
4882*4f2df630SAndroid Build Coastguard Worker 		{ 'P', &password },
4883*4f2df630SAndroid Build Coastguard Worker 		{ 'p', &td.post_reset },
4884*4f2df630SAndroid Build Coastguard Worker 		{ 'U', &ccd_unlock },
4885*4f2df630SAndroid Build Coastguard Worker 		{ 'u', &td.upstart_mode },
4886*4f2df630SAndroid Build Coastguard Worker 		{ 'V', &verbose_mode },
4887*4f2df630SAndroid Build Coastguard Worker 		{},
4888*4f2df630SAndroid Build Coastguard Worker 	};
4889*4f2df630SAndroid Build Coastguard Worker 
4890*4f2df630SAndroid Build Coastguard Worker 	/*
4891*4f2df630SAndroid Build Coastguard Worker 	 * Explicitly sets buffering type to line buffered so that output
4892*4f2df630SAndroid Build Coastguard Worker 	 * lines can be written to pipe instantly. This is needed when the
4893*4f2df630SAndroid Build Coastguard Worker 	 * cr50-verify-ro.sh execution in verify_ro is moved from crosh to
4894*4f2df630SAndroid Build Coastguard Worker 	 * debugd.
4895*4f2df630SAndroid Build Coastguard Worker 	 */
4896*4f2df630SAndroid Build Coastguard Worker 	setlinebuf(stdout);
4897*4f2df630SAndroid Build Coastguard Worker 
4898*4f2df630SAndroid Build Coastguard Worker 	progname = strrchr(argv[0], '/');
4899*4f2df630SAndroid Build Coastguard Worker 	if (progname)
4900*4f2df630SAndroid Build Coastguard Worker 		progname++;
4901*4f2df630SAndroid Build Coastguard Worker 	else
4902*4f2df630SAndroid Build Coastguard Worker 		progname = argv[0];
4903*4f2df630SAndroid Build Coastguard Worker 
4904*4f2df630SAndroid Build Coastguard Worker 	/* Usb transfer - default mode. */
4905*4f2df630SAndroid Build Coastguard Worker 	memset(&td, 0, sizeof(td));
4906*4f2df630SAndroid Build Coastguard Worker 	td.ep_type = usb_xfer;
4907*4f2df630SAndroid Build Coastguard Worker 
4908*4f2df630SAndroid Build Coastguard Worker 	bid_action = bid_none;
4909*4f2df630SAndroid Build Coastguard Worker 	errorcnt = 0;
4910*4f2df630SAndroid Build Coastguard Worker 	opterr = 0; /* quiet, you */
4911*4f2df630SAndroid Build Coastguard Worker 
4912*4f2df630SAndroid Build Coastguard Worker 	while ((i = getopt_all(argc, argv)) != -1) {
4913*4f2df630SAndroid Build Coastguard Worker 		if (check_boolean(omap, i))
4914*4f2df630SAndroid Build Coastguard Worker 			continue;
4915*4f2df630SAndroid Build Coastguard Worker 		switch (i) {
4916*4f2df630SAndroid Build Coastguard Worker 		case 'A':
4917*4f2df630SAndroid Build Coastguard Worker 			get_apro_hash = 1;
4918*4f2df630SAndroid Build Coastguard Worker 			break;
4919*4f2df630SAndroid Build Coastguard Worker 		case 'a':
4920*4f2df630SAndroid Build Coastguard Worker 			if (td.ep_type) {
4921*4f2df630SAndroid Build Coastguard Worker 				errorcnt++;
4922*4f2df630SAndroid Build Coastguard Worker 				fprintf(stderr, "%s", exclusive_opt_error);
4923*4f2df630SAndroid Build Coastguard Worker 				break;
4924*4f2df630SAndroid Build Coastguard Worker 			}
4925*4f2df630SAndroid Build Coastguard Worker 			try_all_transfer = 1;
4926*4f2df630SAndroid Build Coastguard Worker 			/* Try dev_xfer first. */
4927*4f2df630SAndroid Build Coastguard Worker 			td.ep_type = dev_xfer;
4928*4f2df630SAndroid Build Coastguard Worker 			break;
4929*4f2df630SAndroid Build Coastguard Worker 		case 'B':
4930*4f2df630SAndroid Build Coastguard Worker 			if (optarg && !strcmp(optarg, "start"))
4931*4f2df630SAndroid Build Coastguard Worker 				start_apro_verify = 1;
4932*4f2df630SAndroid Build Coastguard Worker 			else
4933*4f2df630SAndroid Build Coastguard Worker 				get_apro_boot_status = 1;
4934*4f2df630SAndroid Build Coastguard Worker 			break;
4935*4f2df630SAndroid Build Coastguard Worker 		case 'C':
4936*4f2df630SAndroid Build Coastguard Worker 			if (optarg && !strncmp(optarg, "3byte", strlen(optarg)))
4937*4f2df630SAndroid Build Coastguard Worker 				arv_config_spi_addr_mode =
4938*4f2df630SAndroid Build Coastguard Worker 					arv_config_spi_addr_mode_set_3byte;
4939*4f2df630SAndroid Build Coastguard Worker 			else if (optarg &&
4940*4f2df630SAndroid Build Coastguard Worker 				 !strncmp(optarg, "4byte", strlen(optarg)))
4941*4f2df630SAndroid Build Coastguard Worker 				arv_config_spi_addr_mode =
4942*4f2df630SAndroid Build Coastguard Worker 					arv_config_spi_addr_mode_set_4byte;
4943*4f2df630SAndroid Build Coastguard Worker 			else
4944*4f2df630SAndroid Build Coastguard Worker 				arv_config_spi_addr_mode =
4945*4f2df630SAndroid Build Coastguard Worker 					arv_config_spi_addr_mode_get;
4946*4f2df630SAndroid Build Coastguard Worker 			break;
4947*4f2df630SAndroid Build Coastguard Worker 		case 'D':
4948*4f2df630SAndroid Build Coastguard Worker 			/* Option is deprecated and igorned */
4949*4f2df630SAndroid Build Coastguard Worker 			break;
4950*4f2df630SAndroid Build Coastguard Worker 		case 'd':
4951*4f2df630SAndroid Build Coastguard Worker 			if (!parse_vidpid(optarg, &vid, &pid)) {
4952*4f2df630SAndroid Build Coastguard Worker 				fprintf(stderr,
4953*4f2df630SAndroid Build Coastguard Worker 					"Invalid device argument: \"%s\"\n",
4954*4f2df630SAndroid Build Coastguard Worker 					optarg);
4955*4f2df630SAndroid Build Coastguard Worker 				errorcnt++;
4956*4f2df630SAndroid Build Coastguard Worker 			}
4957*4f2df630SAndroid Build Coastguard Worker 			break;
4958*4f2df630SAndroid Build Coastguard Worker 		case 'e':
4959*4f2df630SAndroid Build Coastguard Worker 			get_endorsement_seed = 1;
4960*4f2df630SAndroid Build Coastguard Worker 			endorsement_seed_str = optarg;
4961*4f2df630SAndroid Build Coastguard Worker 			break;
4962*4f2df630SAndroid Build Coastguard Worker 		case 'E':
4963*4f2df630SAndroid Build Coastguard Worker 			if (!optarg) {
4964*4f2df630SAndroid Build Coastguard Worker 				arv_config_wpsr_choice =
4965*4f2df630SAndroid Build Coastguard Worker 					arv_config_wpsr_choice_get;
4966*4f2df630SAndroid Build Coastguard Worker 			} else if (optarg && strlen(optarg) > 0) {
4967*4f2df630SAndroid Build Coastguard Worker 				arv_config_wpds.data[0].state =
4968*4f2df630SAndroid Build Coastguard Worker 					arv_config_setting_state_not_present;
4969*4f2df630SAndroid Build Coastguard Worker 				arv_config_wpds.data[1].state =
4970*4f2df630SAndroid Build Coastguard Worker 					arv_config_setting_state_not_present;
4971*4f2df630SAndroid Build Coastguard Worker 				arv_config_wpds.data[2].state =
4972*4f2df630SAndroid Build Coastguard Worker 					arv_config_setting_state_not_present;
4973*4f2df630SAndroid Build Coastguard Worker 
4974*4f2df630SAndroid Build Coastguard Worker 				rv = parse_wpsrs(optarg, &arv_config_wpds);
4975*4f2df630SAndroid Build Coastguard Worker 				if (rv == 2 || rv == 4 || rv == 6) {
4976*4f2df630SAndroid Build Coastguard Worker 					arv_config_wpsr_choice =
4977*4f2df630SAndroid Build Coastguard Worker 						arv_config_wpsr_choice_set;
4978*4f2df630SAndroid Build Coastguard Worker 				} else {
4979*4f2df630SAndroid Build Coastguard Worker 					fprintf(stderr,
4980*4f2df630SAndroid Build Coastguard Worker 						"Invalid write protect descriptors "
4981*4f2df630SAndroid Build Coastguard Worker 						"hex string: \"%s\"\n",
4982*4f2df630SAndroid Build Coastguard Worker 						optarg);
4983*4f2df630SAndroid Build Coastguard Worker 					exit(update_error);
4984*4f2df630SAndroid Build Coastguard Worker 				}
4985*4f2df630SAndroid Build Coastguard Worker 			} else {
4986*4f2df630SAndroid Build Coastguard Worker 				fprintf(stderr,
4987*4f2df630SAndroid Build Coastguard Worker 					"Invalid the write protect descriptors "
4988*4f2df630SAndroid Build Coastguard Worker 					"hex string length\n");
4989*4f2df630SAndroid Build Coastguard Worker 				exit(update_error);
4990*4f2df630SAndroid Build Coastguard Worker 			}
4991*4f2df630SAndroid Build Coastguard Worker 
4992*4f2df630SAndroid Build Coastguard Worker 			break;
4993*4f2df630SAndroid Build Coastguard Worker 		case 'F':
4994*4f2df630SAndroid Build Coastguard Worker 			factory_mode = 1;
4995*4f2df630SAndroid Build Coastguard Worker 			factory_mode_arg = optarg;
4996*4f2df630SAndroid Build Coastguard Worker 			break;
4997*4f2df630SAndroid Build Coastguard Worker 		case 'G':
4998*4f2df630SAndroid Build Coastguard Worker 			get_time = 1;
4999*4f2df630SAndroid Build Coastguard Worker 			break;
5000*4f2df630SAndroid Build Coastguard Worker 		case 'h':
5001*4f2df630SAndroid Build Coastguard Worker 			usage(errorcnt);
5002*4f2df630SAndroid Build Coastguard Worker 			break;
5003*4f2df630SAndroid Build Coastguard Worker 		case 'I':
5004*4f2df630SAndroid Build Coastguard Worker 			if (optarg) {
5005*4f2df630SAndroid Build Coastguard Worker 				set_capability = 1;
5006*4f2df630SAndroid Build Coastguard Worker 				capability_parameter = optarg;
5007*4f2df630SAndroid Build Coastguard Worker 			} else {
5008*4f2df630SAndroid Build Coastguard Worker 				ccd_info = 1;
5009*4f2df630SAndroid Build Coastguard Worker 			}
5010*4f2df630SAndroid Build Coastguard Worker 			break;
5011*4f2df630SAndroid Build Coastguard Worker 		case 'i':
5012*4f2df630SAndroid Build Coastguard Worker 			if (!parse_bid(optarg, &bid, &bid_action)) {
5013*4f2df630SAndroid Build Coastguard Worker 				fprintf(stderr,
5014*4f2df630SAndroid Build Coastguard Worker 					"Invalid board id argument: \"%s\"\n",
5015*4f2df630SAndroid Build Coastguard Worker 					optarg);
5016*4f2df630SAndroid Build Coastguard Worker 				errorcnt++;
5017*4f2df630SAndroid Build Coastguard Worker 			}
5018*4f2df630SAndroid Build Coastguard Worker 			break;
5019*4f2df630SAndroid Build Coastguard Worker 		case 'J':
5020*4f2df630SAndroid Build Coastguard Worker 			get_boot_trace = true;
5021*4f2df630SAndroid Build Coastguard Worker 			if (!optarg)
5022*4f2df630SAndroid Build Coastguard Worker 				break;
5023*4f2df630SAndroid Build Coastguard Worker 			if (strncasecmp(optarg, "erase", strlen(optarg))) {
5024*4f2df630SAndroid Build Coastguard Worker 				fprintf(stderr,
5025*4f2df630SAndroid Build Coastguard Worker 					"Invalid boot trace argument: "
5026*4f2df630SAndroid Build Coastguard Worker 					"\"%s\"\n",
5027*4f2df630SAndroid Build Coastguard Worker 					optarg);
5028*4f2df630SAndroid Build Coastguard Worker 				errorcnt++;
5029*4f2df630SAndroid Build Coastguard Worker 			}
5030*4f2df630SAndroid Build Coastguard Worker 			erase_boot_trace = true;
5031*4f2df630SAndroid Build Coastguard Worker 			break;
5032*4f2df630SAndroid Build Coastguard Worker 		case 'K':
5033*4f2df630SAndroid Build Coastguard Worker 			if (!strncasecmp(optarg, "chassis_open",
5034*4f2df630SAndroid Build Coastguard Worker 					 strlen(optarg))) {
5035*4f2df630SAndroid Build Coastguard Worker 				get_chassis_open = true;
5036*4f2df630SAndroid Build Coastguard Worker 			} else if (!strncasecmp(optarg, "dev_ids",
5037*4f2df630SAndroid Build Coastguard Worker 						strlen(optarg))) {
5038*4f2df630SAndroid Build Coastguard Worker 				get_dev_ids = true;
5039*4f2df630SAndroid Build Coastguard Worker 			} else if (!strncasecmp(optarg,
5040*4f2df630SAndroid Build Coastguard Worker 						"aprov_gsc_reset_counts",
5041*4f2df630SAndroid Build Coastguard Worker 						strlen(optarg))) {
5042*4f2df630SAndroid Build Coastguard Worker 				/*
5043*4f2df630SAndroid Build Coastguard Worker 				 * Note: This is a temporary command that allows
5044*4f2df630SAndroid Build Coastguard Worker 				 * us to collect UMA metrics for how many times
5045*4f2df630SAndroid Build Coastguard Worker 				 * the GSC would have been reset due to the AP
5046*4f2df630SAndroid Build Coastguard Worker 				 * RO verification feature.
5047*4f2df630SAndroid Build Coastguard Worker 				 *
5048*4f2df630SAndroid Build Coastguard Worker 				 * Once the feature is rolled out, remove this
5049*4f2df630SAndroid Build Coastguard Worker 				 * command line option. That is also why this
5050*4f2df630SAndroid Build Coastguard Worker 				 * sub-command is not advertised in the help
5051*4f2df630SAndroid Build Coastguard Worker 				 * menu.
5052*4f2df630SAndroid Build Coastguard Worker 				 */
5053*4f2df630SAndroid Build Coastguard Worker 				get_aprov_reset_counts = true;
5054*4f2df630SAndroid Build Coastguard Worker 			} else {
5055*4f2df630SAndroid Build Coastguard Worker 				fprintf(stderr,
5056*4f2df630SAndroid Build Coastguard Worker 					"Invalid get_value argument: "
5057*4f2df630SAndroid Build Coastguard Worker 					"\"%s\"\n",
5058*4f2df630SAndroid Build Coastguard Worker 					optarg);
5059*4f2df630SAndroid Build Coastguard Worker 				errorcnt++;
5060*4f2df630SAndroid Build Coastguard Worker 			}
5061*4f2df630SAndroid Build Coastguard Worker 			break;
5062*4f2df630SAndroid Build Coastguard Worker 		case 'L':
5063*4f2df630SAndroid Build Coastguard Worker 			get_flog = 1;
5064*4f2df630SAndroid Build Coastguard Worker 			if (optarg)
5065*4f2df630SAndroid Build Coastguard Worker 				prev_log_entry = strtoul(optarg, NULL, 0);
5066*4f2df630SAndroid Build Coastguard Worker 			break;
5067*4f2df630SAndroid Build Coastguard Worker 		case 'l':
5068*4f2df630SAndroid Build Coastguard Worker 			get_console = 1;
5069*4f2df630SAndroid Build Coastguard Worker 			break;
5070*4f2df630SAndroid Build Coastguard Worker 		case 'M':
5071*4f2df630SAndroid Build Coastguard Worker 			show_machine_output = true;
5072*4f2df630SAndroid Build Coastguard Worker 			break;
5073*4f2df630SAndroid Build Coastguard Worker 		case 'm':
5074*4f2df630SAndroid Build Coastguard Worker 			tpm_mode = 1;
5075*4f2df630SAndroid Build Coastguard Worker 			tpm_mode_arg = optarg;
5076*4f2df630SAndroid Build Coastguard Worker 			break;
5077*4f2df630SAndroid Build Coastguard Worker 		case 'n':
5078*4f2df630SAndroid Build Coastguard Worker 			serial = optarg;
5079*4f2df630SAndroid Build Coastguard Worker 			break;
5080*4f2df630SAndroid Build Coastguard Worker 		case 'O':
5081*4f2df630SAndroid Build Coastguard Worker 			openbox_desc_file = optarg;
5082*4f2df630SAndroid Build Coastguard Worker 			break;
5083*4f2df630SAndroid Build Coastguard Worker 		case 'q':
5084*4f2df630SAndroid Build Coastguard Worker 			td.force_ro = 1;
5085*4f2df630SAndroid Build Coastguard Worker 			break;
5086*4f2df630SAndroid Build Coastguard Worker 		case 'r':
5087*4f2df630SAndroid Build Coastguard Worker 			rma = 1;
5088*4f2df630SAndroid Build Coastguard Worker 			rma_auth_code = optarg;
5089*4f2df630SAndroid Build Coastguard Worker 			break;
5090*4f2df630SAndroid Build Coastguard Worker 		case 'R':
5091*4f2df630SAndroid Build Coastguard Worker 			sn_inc_rma = 1;
5092*4f2df630SAndroid Build Coastguard Worker 			if (!parse_sn_inc_rma(optarg, &sn_inc_rma_arg)) {
5093*4f2df630SAndroid Build Coastguard Worker 				fprintf(stderr,
5094*4f2df630SAndroid Build Coastguard Worker 					"Invalid sn_rma_inc argument: \"%s\"\n",
5095*4f2df630SAndroid Build Coastguard Worker 					optarg);
5096*4f2df630SAndroid Build Coastguard Worker 				errorcnt++;
5097*4f2df630SAndroid Build Coastguard Worker 			}
5098*4f2df630SAndroid Build Coastguard Worker 
5099*4f2df630SAndroid Build Coastguard Worker 			break;
5100*4f2df630SAndroid Build Coastguard Worker 		case 's':
5101*4f2df630SAndroid Build Coastguard Worker 			if (td.ep_type || try_all_transfer) {
5102*4f2df630SAndroid Build Coastguard Worker 				errorcnt++;
5103*4f2df630SAndroid Build Coastguard Worker 				fprintf(stderr, "%s", exclusive_opt_error);
5104*4f2df630SAndroid Build Coastguard Worker 				break;
5105*4f2df630SAndroid Build Coastguard Worker 			}
5106*4f2df630SAndroid Build Coastguard Worker 			td.ep_type = dev_xfer;
5107*4f2df630SAndroid Build Coastguard Worker 			break;
5108*4f2df630SAndroid Build Coastguard Worker 		case 'S':
5109*4f2df630SAndroid Build Coastguard Worker 			sn_bits = 1;
5110*4f2df630SAndroid Build Coastguard Worker 			if (!parse_sn_bits(optarg, sn_bits_arg)) {
5111*4f2df630SAndroid Build Coastguard Worker 				fprintf(stderr,
5112*4f2df630SAndroid Build Coastguard Worker 					"Invalid sn_bits argument: \"%s\"\n",
5113*4f2df630SAndroid Build Coastguard Worker 					optarg);
5114*4f2df630SAndroid Build Coastguard Worker 				errorcnt++;
5115*4f2df630SAndroid Build Coastguard Worker 			}
5116*4f2df630SAndroid Build Coastguard Worker 
5117*4f2df630SAndroid Build Coastguard Worker 			break;
5118*4f2df630SAndroid Build Coastguard Worker 		case 't':
5119*4f2df630SAndroid Build Coastguard Worker 			if (td.ep_type || try_all_transfer) {
5120*4f2df630SAndroid Build Coastguard Worker 				errorcnt++;
5121*4f2df630SAndroid Build Coastguard Worker 				fprintf(stderr, "%s", exclusive_opt_error);
5122*4f2df630SAndroid Build Coastguard Worker 				break;
5123*4f2df630SAndroid Build Coastguard Worker 			}
5124*4f2df630SAndroid Build Coastguard Worker 			td.ep_type = ts_xfer;
5125*4f2df630SAndroid Build Coastguard Worker 			break;
5126*4f2df630SAndroid Build Coastguard Worker 		case 'T':
5127*4f2df630SAndroid Build Coastguard Worker 			tstamp = 1;
5128*4f2df630SAndroid Build Coastguard Worker 			tstamp_arg = optarg;
5129*4f2df630SAndroid Build Coastguard Worker 			break;
5130*4f2df630SAndroid Build Coastguard Worker 		case 'v':
5131*4f2df630SAndroid Build Coastguard Worker 			report_version(); /* This will call exit(). */
5132*4f2df630SAndroid Build Coastguard Worker 			break;
5133*4f2df630SAndroid Build Coastguard Worker 		case 'W':
5134*4f2df630SAndroid Build Coastguard Worker 			get_metrics = true;
5135*4f2df630SAndroid Build Coastguard Worker 			break;
5136*4f2df630SAndroid Build Coastguard Worker 		case 'w':
5137*4f2df630SAndroid Build Coastguard Worker 			if (!optarg) {
5138*4f2df630SAndroid Build Coastguard Worker 				wp = WP_CHECK;
5139*4f2df630SAndroid Build Coastguard Worker 				break;
5140*4f2df630SAndroid Build Coastguard Worker 			}
5141*4f2df630SAndroid Build Coastguard Worker 			if (!strcasecmp(optarg, "enable")) {
5142*4f2df630SAndroid Build Coastguard Worker 				wp = WP_ENABLE;
5143*4f2df630SAndroid Build Coastguard Worker 				break;
5144*4f2df630SAndroid Build Coastguard Worker 			}
5145*4f2df630SAndroid Build Coastguard Worker 			if (!strcasecmp(optarg, "disable")) {
5146*4f2df630SAndroid Build Coastguard Worker 				wp = WP_DISABLE;
5147*4f2df630SAndroid Build Coastguard Worker 				break;
5148*4f2df630SAndroid Build Coastguard Worker 			}
5149*4f2df630SAndroid Build Coastguard Worker 			if (!strcasecmp(optarg, "follow")) {
5150*4f2df630SAndroid Build Coastguard Worker 				wp = WP_FOLLOW;
5151*4f2df630SAndroid Build Coastguard Worker 				break;
5152*4f2df630SAndroid Build Coastguard Worker 			}
5153*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr, "Illegal wp option \"%s\"\n", optarg);
5154*4f2df630SAndroid Build Coastguard Worker 			errorcnt++;
5155*4f2df630SAndroid Build Coastguard Worker 			break;
5156*4f2df630SAndroid Build Coastguard Worker 		case 'x':
5157*4f2df630SAndroid Build Coastguard Worker 			get_clog = 1;
5158*4f2df630SAndroid Build Coastguard Worker 			break;
5159*4f2df630SAndroid Build Coastguard Worker 		case 'y':
5160*4f2df630SAndroid Build Coastguard Worker 			factory_config = 1;
5161*4f2df630SAndroid Build Coastguard Worker 			if (optarg) {
5162*4f2df630SAndroid Build Coastguard Worker 				set_factory_config = 1;
5163*4f2df630SAndroid Build Coastguard Worker 				factory_config_arg = strtoull(optarg, NULL, 16);
5164*4f2df630SAndroid Build Coastguard Worker 			}
5165*4f2df630SAndroid Build Coastguard Worker 			break;
5166*4f2df630SAndroid Build Coastguard Worker 		case 'z':
5167*4f2df630SAndroid Build Coastguard Worker 			reboot_gsc = true;
5168*4f2df630SAndroid Build Coastguard Worker 			/* Set a 1ms default reboot time to avoid libusb errors
5169*4f2df630SAndroid Build Coastguard Worker 			 * when the GSC resets too quickly.
5170*4f2df630SAndroid Build Coastguard Worker 			 */
5171*4f2df630SAndroid Build Coastguard Worker 			reboot_gsc_timeout = 1;
5172*4f2df630SAndroid Build Coastguard Worker 			if (optarg)
5173*4f2df630SAndroid Build Coastguard Worker 				reboot_gsc_timeout = strtoul(optarg, NULL, 0);
5174*4f2df630SAndroid Build Coastguard Worker 			break;
5175*4f2df630SAndroid Build Coastguard Worker 		case 0: /* auto-handled option */
5176*4f2df630SAndroid Build Coastguard Worker 			break;
5177*4f2df630SAndroid Build Coastguard Worker 		case '?':
5178*4f2df630SAndroid Build Coastguard Worker 			if (optopt)
5179*4f2df630SAndroid Build Coastguard Worker 				fprintf(stderr, "Unrecognized option: -%c\n",
5180*4f2df630SAndroid Build Coastguard Worker 					optopt);
5181*4f2df630SAndroid Build Coastguard Worker 			else
5182*4f2df630SAndroid Build Coastguard Worker 				fprintf(stderr, "Unrecognized option: %s\n",
5183*4f2df630SAndroid Build Coastguard Worker 					argv[optind - 1]);
5184*4f2df630SAndroid Build Coastguard Worker 			errorcnt++;
5185*4f2df630SAndroid Build Coastguard Worker 			break;
5186*4f2df630SAndroid Build Coastguard Worker 		case ':':
5187*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr, "Missing argument to %s\n",
5188*4f2df630SAndroid Build Coastguard Worker 				argv[optind - 1]);
5189*4f2df630SAndroid Build Coastguard Worker 			errorcnt++;
5190*4f2df630SAndroid Build Coastguard Worker 			break;
5191*4f2df630SAndroid Build Coastguard Worker 		default:
5192*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr, "Internal error at %s:%d\n", __FILE__,
5193*4f2df630SAndroid Build Coastguard Worker 				__LINE__);
5194*4f2df630SAndroid Build Coastguard Worker 			exit(update_error);
5195*4f2df630SAndroid Build Coastguard Worker 		}
5196*4f2df630SAndroid Build Coastguard Worker 	}
5197*4f2df630SAndroid Build Coastguard Worker 
5198*4f2df630SAndroid Build Coastguard Worker 	if (errorcnt)
5199*4f2df630SAndroid Build Coastguard Worker 		usage(errorcnt);
5200*4f2df630SAndroid Build Coastguard Worker 
5201*4f2df630SAndroid Build Coastguard Worker 	if ((bid_action == bid_none) &&
5202*4f2df630SAndroid Build Coastguard Worker 	    (arv_config_spi_addr_mode == arv_config_spi_addr_mode_none) &&
5203*4f2df630SAndroid Build Coastguard Worker 	    (arv_config_wpsr_choice == arv_config_wpsr_choice_none) &&
5204*4f2df630SAndroid Build Coastguard Worker 	    !ccd_info && !ccd_lock && !ccd_open && !ccd_unlock &&
5205*4f2df630SAndroid Build Coastguard Worker 	    !corrupt_inactive_rw && !get_apro_hash && !get_apro_boot_status &&
5206*4f2df630SAndroid Build Coastguard Worker 	    !get_boot_mode && !get_boot_trace && !get_clog && !get_console &&
5207*4f2df630SAndroid Build Coastguard Worker 	    !get_flog && !get_endorsement_seed && !get_metrics && !get_time &&
5208*4f2df630SAndroid Build Coastguard Worker 	    !factory_config && !factory_mode && !erase_ap_ro_hash &&
5209*4f2df630SAndroid Build Coastguard Worker 	    !password && !reboot_gsc && !rma && !set_capability &&
5210*4f2df630SAndroid Build Coastguard Worker 	    !show_fw_ver && !sn_bits && !sn_inc_rma && !start_apro_verify &&
5211*4f2df630SAndroid Build Coastguard Worker 	    !openbox_desc_file && !tstamp && !tpm_mode && (wp == WP_NONE) &&
5212*4f2df630SAndroid Build Coastguard Worker 	    !get_chassis_open && !get_dev_ids && !get_aprov_reset_counts) {
5213*4f2df630SAndroid Build Coastguard Worker 		num_images = argc - optind;
5214*4f2df630SAndroid Build Coastguard Worker 		if (num_images <= 0) {
5215*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr,
5216*4f2df630SAndroid Build Coastguard Worker 				"\nERROR: Missing required <binary image>\n\n");
5217*4f2df630SAndroid Build Coastguard Worker 			usage(1);
5218*4f2df630SAndroid Build Coastguard Worker 		}
5219*4f2df630SAndroid Build Coastguard Worker 
5220*4f2df630SAndroid Build Coastguard Worker 		images = malloc(sizeof(struct image) * num_images);
5221*4f2df630SAndroid Build Coastguard Worker 
5222*4f2df630SAndroid Build Coastguard Worker 		for (i = 0; i < num_images; i++) {
5223*4f2df630SAndroid Build Coastguard Worker 			images[i].data = get_file_or_die(argv[optind + i],
5224*4f2df630SAndroid Build Coastguard Worker 							 &images[i].data_len);
5225*4f2df630SAndroid Build Coastguard Worker 			images[i].file_path = argv[optind + i];
5226*4f2df630SAndroid Build Coastguard Worker 			printf("read %zd(%#zx) bytes from %s\n",
5227*4f2df630SAndroid Build Coastguard Worker 			       images[i].data_len, images[i].data_len,
5228*4f2df630SAndroid Build Coastguard Worker 			       images[i].file_path);
5229*4f2df630SAndroid Build Coastguard Worker 
5230*4f2df630SAndroid Build Coastguard Worker 			/* Validate images and locate headers within image */
5231*4f2df630SAndroid Build Coastguard Worker 			if (!locate_headers(&images[i]))
5232*4f2df630SAndroid Build Coastguard Worker 				exit(update_error);
5233*4f2df630SAndroid Build Coastguard Worker 
5234*4f2df630SAndroid Build Coastguard Worker 			if (!fetch_header_versions(&images[i]))
5235*4f2df630SAndroid Build Coastguard Worker 				exit(update_error);
5236*4f2df630SAndroid Build Coastguard Worker 
5237*4f2df630SAndroid Build Coastguard Worker 			if (binary_vers) {
5238*4f2df630SAndroid Build Coastguard Worker 				int error = show_headers_versions(
5239*4f2df630SAndroid Build Coastguard Worker 					&images[i], show_machine_output);
5240*4f2df630SAndroid Build Coastguard Worker 				if (error)
5241*4f2df630SAndroid Build Coastguard Worker 					exit(error);
5242*4f2df630SAndroid Build Coastguard Worker 			}
5243*4f2df630SAndroid Build Coastguard Worker 		}
5244*4f2df630SAndroid Build Coastguard Worker 		/* If displaying versions, exit now since we're done. */
5245*4f2df630SAndroid Build Coastguard Worker 		if (binary_vers)
5246*4f2df630SAndroid Build Coastguard Worker 			exit(0);
5247*4f2df630SAndroid Build Coastguard Worker 	} else {
5248*4f2df630SAndroid Build Coastguard Worker 		if (optind < argc)
5249*4f2df630SAndroid Build Coastguard Worker 			printf("Ignoring binary image %s\n", argv[optind]);
5250*4f2df630SAndroid Build Coastguard Worker 	}
5251*4f2df630SAndroid Build Coastguard Worker 
5252*4f2df630SAndroid Build Coastguard Worker 	if (((bid_action != bid_none) + !!rma + !!password + !!ccd_open +
5253*4f2df630SAndroid Build Coastguard Worker 	     !!ccd_unlock + !!ccd_lock + !!ccd_info + !!get_flog +
5254*4f2df630SAndroid Build Coastguard Worker 	     !!get_boot_mode + !!openbox_desc_file + !!factory_mode +
5255*4f2df630SAndroid Build Coastguard Worker 	     (wp != WP_NONE) + !!get_endorsement_seed + !!erase_ap_ro_hash +
5256*4f2df630SAndroid Build Coastguard Worker 	     !!set_capability + !!get_clog + !!get_console) > 1) {
5257*4f2df630SAndroid Build Coastguard Worker 		fprintf(stderr,
5258*4f2df630SAndroid Build Coastguard Worker 			"Error: options "
5259*4f2df630SAndroid Build Coastguard Worker 			"-e, -F, -g, -H, -I, -i, -k, -L, -l, -O, -o, -P, -r,"
5260*4f2df630SAndroid Build Coastguard Worker 			"-U, -x and -w are mutually exclusive\n");
5261*4f2df630SAndroid Build Coastguard Worker 		exit(update_error);
5262*4f2df630SAndroid Build Coastguard Worker 	}
5263*4f2df630SAndroid Build Coastguard Worker 
5264*4f2df630SAndroid Build Coastguard Worker 	if (td.ep_type == usb_xfer) {
5265*4f2df630SAndroid Build Coastguard Worker 		/* Extra variables only used to prevent 80+ character lines */
5266*4f2df630SAndroid Build Coastguard Worker 		const uint16_t subclass = USB_SUBCLASS_GOOGLE_CR50;
5267*4f2df630SAndroid Build Coastguard Worker 		const uint16_t protocol =
5268*4f2df630SAndroid Build Coastguard Worker 			USB_PROTOCOL_GOOGLE_CR50_NON_HC_FW_UPDATE;
5269*4f2df630SAndroid Build Coastguard Worker 		uint16_t pids[] = { H1_PID, D2_PID, NT_PID };
5270*4f2df630SAndroid Build Coastguard Worker 		int pid_count = ARRAY_SIZE(pids);
5271*4f2df630SAndroid Build Coastguard Worker 
5272*4f2df630SAndroid Build Coastguard Worker 		/*
5273*4f2df630SAndroid Build Coastguard Worker 		 * If no usb device information was given, use default vid and
5274*4f2df630SAndroid Build Coastguard Worker 		 * pids to search for GSC devices.
5275*4f2df630SAndroid Build Coastguard Worker 		 */
5276*4f2df630SAndroid Build Coastguard Worker 		if (!vid)
5277*4f2df630SAndroid Build Coastguard Worker 			vid = USB_VID_GOOGLE;
5278*4f2df630SAndroid Build Coastguard Worker 		if (pid) {
5279*4f2df630SAndroid Build Coastguard Worker 			pids[0] = pid;
5280*4f2df630SAndroid Build Coastguard Worker 			pid_count = 1;
5281*4f2df630SAndroid Build Coastguard Worker 		}
5282*4f2df630SAndroid Build Coastguard Worker 		if (usb_findit(serial, vid, pids, pid_count, subclass, protocol,
5283*4f2df630SAndroid Build Coastguard Worker 			       &td.uep)) {
5284*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr,
5285*4f2df630SAndroid Build Coastguard Worker 				"ERROR: Cannot find single GSC device\n");
5286*4f2df630SAndroid Build Coastguard Worker 			exit(update_error);
5287*4f2df630SAndroid Build Coastguard Worker 		}
5288*4f2df630SAndroid Build Coastguard Worker 	} else if (td.ep_type == dev_xfer) {
5289*4f2df630SAndroid Build Coastguard Worker 		td.tpm_fd = open("/dev/tpm0", O_RDWR);
5290*4f2df630SAndroid Build Coastguard Worker 		if (td.tpm_fd < 0) {
5291*4f2df630SAndroid Build Coastguard Worker 			if (!try_all_transfer) {
5292*4f2df630SAndroid Build Coastguard Worker 				perror("Could not open TPM");
5293*4f2df630SAndroid Build Coastguard Worker 				exit(update_error);
5294*4f2df630SAndroid Build Coastguard Worker 			}
5295*4f2df630SAndroid Build Coastguard Worker 			td.ep_type = ts_xfer;
5296*4f2df630SAndroid Build Coastguard Worker 		}
5297*4f2df630SAndroid Build Coastguard Worker 	}
5298*4f2df630SAndroid Build Coastguard Worker 
5299*4f2df630SAndroid Build Coastguard Worker 	/* Perform run selection of GSC device now that we have a connection */
5300*4f2df630SAndroid Build Coastguard Worker 	gsc_dev = determine_gsc_type(&td);
5301*4f2df630SAndroid Build Coastguard Worker 
5302*4f2df630SAndroid Build Coastguard Worker 	if (openbox_desc_file)
5303*4f2df630SAndroid Build Coastguard Worker 		return verify_ro(&td, openbox_desc_file, show_machine_output);
5304*4f2df630SAndroid Build Coastguard Worker 
5305*4f2df630SAndroid Build Coastguard Worker 	if (ccd_unlock || ccd_open || ccd_lock || ccd_info)
5306*4f2df630SAndroid Build Coastguard Worker 		process_ccd_state(&td, ccd_unlock, ccd_open, ccd_lock, ccd_info,
5307*4f2df630SAndroid Build Coastguard Worker 				  show_machine_output);
5308*4f2df630SAndroid Build Coastguard Worker 
5309*4f2df630SAndroid Build Coastguard Worker 	if (set_capability)
5310*4f2df630SAndroid Build Coastguard Worker 		exit(process_set_capabililty(&td, capability_parameter));
5311*4f2df630SAndroid Build Coastguard Worker 
5312*4f2df630SAndroid Build Coastguard Worker 	if (password)
5313*4f2df630SAndroid Build Coastguard Worker 		process_password(&td);
5314*4f2df630SAndroid Build Coastguard Worker 
5315*4f2df630SAndroid Build Coastguard Worker 	if (bid_action != bid_none)
5316*4f2df630SAndroid Build Coastguard Worker 		process_bid(&td, bid_action, &bid, show_machine_output);
5317*4f2df630SAndroid Build Coastguard Worker 
5318*4f2df630SAndroid Build Coastguard Worker 	if (get_endorsement_seed)
5319*4f2df630SAndroid Build Coastguard Worker 		exit(process_endorsement_seed(&td, endorsement_seed_str));
5320*4f2df630SAndroid Build Coastguard Worker 
5321*4f2df630SAndroid Build Coastguard Worker 	if (rma)
5322*4f2df630SAndroid Build Coastguard Worker 		process_rma(&td, rma_auth_code, show_machine_output);
5323*4f2df630SAndroid Build Coastguard Worker 
5324*4f2df630SAndroid Build Coastguard Worker 	if (factory_mode)
5325*4f2df630SAndroid Build Coastguard Worker 		process_factory_mode(&td, factory_mode_arg);
5326*4f2df630SAndroid Build Coastguard Worker 	if (wp != WP_NONE)
5327*4f2df630SAndroid Build Coastguard Worker 		exit(process_wp(&td, wp));
5328*4f2df630SAndroid Build Coastguard Worker 
5329*4f2df630SAndroid Build Coastguard Worker 	if (get_chassis_open)
5330*4f2df630SAndroid Build Coastguard Worker 		exit(process_get_chassis_open(&td));
5331*4f2df630SAndroid Build Coastguard Worker 
5332*4f2df630SAndroid Build Coastguard Worker 	if (get_dev_ids)
5333*4f2df630SAndroid Build Coastguard Worker 		exit(process_get_dev_ids(&td, show_machine_output));
5334*4f2df630SAndroid Build Coastguard Worker 
5335*4f2df630SAndroid Build Coastguard Worker 	if (get_aprov_reset_counts)
5336*4f2df630SAndroid Build Coastguard Worker 		exit(process_get_aprov_reset_counts(&td));
5337*4f2df630SAndroid Build Coastguard Worker 
5338*4f2df630SAndroid Build Coastguard Worker 	if (corrupt_inactive_rw)
5339*4f2df630SAndroid Build Coastguard Worker 		invalidate_inactive_rw(&td);
5340*4f2df630SAndroid Build Coastguard Worker 
5341*4f2df630SAndroid Build Coastguard Worker 	if (tpm_mode) {
5342*4f2df630SAndroid Build Coastguard Worker 		int rv = process_tpm_mode(&td, tpm_mode_arg);
5343*4f2df630SAndroid Build Coastguard Worker 
5344*4f2df630SAndroid Build Coastguard Worker 		exit(rv);
5345*4f2df630SAndroid Build Coastguard Worker 	}
5346*4f2df630SAndroid Build Coastguard Worker 
5347*4f2df630SAndroid Build Coastguard Worker 	if (tstamp)
5348*4f2df630SAndroid Build Coastguard Worker 		return process_tstamp(&td, tstamp_arg);
5349*4f2df630SAndroid Build Coastguard Worker 
5350*4f2df630SAndroid Build Coastguard Worker 	if (sn_bits)
5351*4f2df630SAndroid Build Coastguard Worker 		process_sn_bits(&td, sn_bits_arg);
5352*4f2df630SAndroid Build Coastguard Worker 
5353*4f2df630SAndroid Build Coastguard Worker 	if (sn_inc_rma)
5354*4f2df630SAndroid Build Coastguard Worker 		process_sn_inc_rma(&td, sn_inc_rma_arg);
5355*4f2df630SAndroid Build Coastguard Worker 
5356*4f2df630SAndroid Build Coastguard Worker 	if (get_apro_hash)
5357*4f2df630SAndroid Build Coastguard Worker 		exit(process_get_apro_hash(&td));
5358*4f2df630SAndroid Build Coastguard Worker 
5359*4f2df630SAndroid Build Coastguard Worker 	if (get_apro_boot_status)
5360*4f2df630SAndroid Build Coastguard Worker 		exit(process_get_apro_boot_status(&td));
5361*4f2df630SAndroid Build Coastguard Worker 
5362*4f2df630SAndroid Build Coastguard Worker 	if (start_apro_verify)
5363*4f2df630SAndroid Build Coastguard Worker 		exit(process_start_apro_verify(&td));
5364*4f2df630SAndroid Build Coastguard Worker 
5365*4f2df630SAndroid Build Coastguard Worker 	if (get_boot_mode)
5366*4f2df630SAndroid Build Coastguard Worker 		exit(process_get_boot_mode(&td));
5367*4f2df630SAndroid Build Coastguard Worker 
5368*4f2df630SAndroid Build Coastguard Worker 	if (get_flog)
5369*4f2df630SAndroid Build Coastguard Worker 		process_get_flog(&td, prev_log_entry, show_machine_output);
5370*4f2df630SAndroid Build Coastguard Worker 
5371*4f2df630SAndroid Build Coastguard Worker 	if (erase_ap_ro_hash)
5372*4f2df630SAndroid Build Coastguard Worker 		process_erase_ap_ro_hash(&td);
5373*4f2df630SAndroid Build Coastguard Worker 
5374*4f2df630SAndroid Build Coastguard Worker 	if (arv_config_spi_addr_mode)
5375*4f2df630SAndroid Build Coastguard Worker 		exit(process_arv_config_spi_addr_mode(
5376*4f2df630SAndroid Build Coastguard Worker 			&td, arv_config_spi_addr_mode));
5377*4f2df630SAndroid Build Coastguard Worker 
5378*4f2df630SAndroid Build Coastguard Worker 	if (arv_config_wpsr_choice)
5379*4f2df630SAndroid Build Coastguard Worker 		exit(process_arv_config_wpds(&td, arv_config_wpsr_choice,
5380*4f2df630SAndroid Build Coastguard Worker 					     &arv_config_wpds));
5381*4f2df630SAndroid Build Coastguard Worker 
5382*4f2df630SAndroid Build Coastguard Worker 	if (reboot_gsc)
5383*4f2df630SAndroid Build Coastguard Worker 		exit(process_reboot_gsc(&td, reboot_gsc_timeout));
5384*4f2df630SAndroid Build Coastguard Worker 
5385*4f2df630SAndroid Build Coastguard Worker 	if (get_clog)
5386*4f2df630SAndroid Build Coastguard Worker 		exit(get_crashlog(&td));
5387*4f2df630SAndroid Build Coastguard Worker 
5388*4f2df630SAndroid Build Coastguard Worker 	if (get_console)
5389*4f2df630SAndroid Build Coastguard Worker 		exit(get_console_logs(&td));
5390*4f2df630SAndroid Build Coastguard Worker 
5391*4f2df630SAndroid Build Coastguard Worker 	if (factory_config) {
5392*4f2df630SAndroid Build Coastguard Worker 		if (set_factory_config)
5393*4f2df630SAndroid Build Coastguard Worker 			exit(process_set_factory_config(&td,
5394*4f2df630SAndroid Build Coastguard Worker 							factory_config_arg));
5395*4f2df630SAndroid Build Coastguard Worker 		else
5396*4f2df630SAndroid Build Coastguard Worker 			exit(process_get_factory_config(&td));
5397*4f2df630SAndroid Build Coastguard Worker 	}
5398*4f2df630SAndroid Build Coastguard Worker 
5399*4f2df630SAndroid Build Coastguard Worker 	if (get_time) {
5400*4f2df630SAndroid Build Coastguard Worker 		exit(process_get_time(&td));
5401*4f2df630SAndroid Build Coastguard Worker 	}
5402*4f2df630SAndroid Build Coastguard Worker 
5403*4f2df630SAndroid Build Coastguard Worker 	if (get_boot_trace)
5404*4f2df630SAndroid Build Coastguard Worker 		exit(process_get_boot_trace(&td, erase_boot_trace,
5405*4f2df630SAndroid Build Coastguard Worker 					    show_machine_output));
5406*4f2df630SAndroid Build Coastguard Worker 
5407*4f2df630SAndroid Build Coastguard Worker 	if (get_metrics) {
5408*4f2df630SAndroid Build Coastguard Worker 		if (is_ti50_device())
5409*4f2df630SAndroid Build Coastguard Worker 			exit(process_ti50_get_metrics(&td,
5410*4f2df630SAndroid Build Coastguard Worker 						      show_machine_output));
5411*4f2df630SAndroid Build Coastguard Worker 		else
5412*4f2df630SAndroid Build Coastguard Worker 			exit(process_cr50_get_metrics(&td,
5413*4f2df630SAndroid Build Coastguard Worker 						      show_machine_output));
5414*4f2df630SAndroid Build Coastguard Worker 	}
5415*4f2df630SAndroid Build Coastguard Worker 
5416*4f2df630SAndroid Build Coastguard Worker 	if (images || show_fw_ver) {
5417*4f2df630SAndroid Build Coastguard Worker 		struct image *match = NULL;
5418*4f2df630SAndroid Build Coastguard Worker 
5419*4f2df630SAndroid Build Coastguard Worker 		/* Find the matching image for the runtime-determined device */
5420*4f2df630SAndroid Build Coastguard Worker 		for (i = 0; i < num_images; i++) {
5421*4f2df630SAndroid Build Coastguard Worker 			if (images[i].type == gsc_dev) {
5422*4f2df630SAndroid Build Coastguard Worker 				if (match) {
5423*4f2df630SAndroid Build Coastguard Worker 					fprintf(stderr,
5424*4f2df630SAndroid Build Coastguard Worker 						"ERROR: Must only specify a "
5425*4f2df630SAndroid Build Coastguard Worker 						"single image for each chip "
5426*4f2df630SAndroid Build Coastguard Worker 						"type.\n");
5427*4f2df630SAndroid Build Coastguard Worker 					exit(update_error);
5428*4f2df630SAndroid Build Coastguard Worker 				}
5429*4f2df630SAndroid Build Coastguard Worker 				match = &images[i];
5430*4f2df630SAndroid Build Coastguard Worker 			}
5431*4f2df630SAndroid Build Coastguard Worker 		}
5432*4f2df630SAndroid Build Coastguard Worker 
5433*4f2df630SAndroid Build Coastguard Worker 		if (images && !match) {
5434*4f2df630SAndroid Build Coastguard Worker 			fprintf(stderr,
5435*4f2df630SAndroid Build Coastguard Worker 				"ERROR: No images matches chip type.\n");
5436*4f2df630SAndroid Build Coastguard Worker 			exit(update_error);
5437*4f2df630SAndroid Build Coastguard Worker 		}
5438*4f2df630SAndroid Build Coastguard Worker 
5439*4f2df630SAndroid Build Coastguard Worker 		setup_connection(&td);
5440*4f2df630SAndroid Build Coastguard Worker 
5441*4f2df630SAndroid Build Coastguard Worker 		if (match) {
5442*4f2df630SAndroid Build Coastguard Worker 			if (num_images > 1) {
5443*4f2df630SAndroid Build Coastguard Worker 				printf("Using file for update: %s\n",
5444*4f2df630SAndroid Build Coastguard Worker 				       match->file_path);
5445*4f2df630SAndroid Build Coastguard Worker 			}
5446*4f2df630SAndroid Build Coastguard Worker 			transferred_sections = transfer_image(&td, match);
5447*4f2df630SAndroid Build Coastguard Worker 		}
5448*4f2df630SAndroid Build Coastguard Worker 
5449*4f2df630SAndroid Build Coastguard Worker 		/* Free images */
5450*4f2df630SAndroid Build Coastguard Worker 		match = NULL;
5451*4f2df630SAndroid Build Coastguard Worker 		for (i = 0; i < num_images; i++)
5452*4f2df630SAndroid Build Coastguard Worker 			free(images[i].data);
5453*4f2df630SAndroid Build Coastguard Worker 		free(images);
5454*4f2df630SAndroid Build Coastguard Worker 		images = NULL;
5455*4f2df630SAndroid Build Coastguard Worker 
5456*4f2df630SAndroid Build Coastguard Worker 		/*
5457*4f2df630SAndroid Build Coastguard Worker 		 * Move USB updater sate machine to idle state so that
5458*4f2df630SAndroid Build Coastguard Worker 		 * vendor commands can be processed later, if any.
5459*4f2df630SAndroid Build Coastguard Worker 		 */
5460*4f2df630SAndroid Build Coastguard Worker 		if (td.ep_type == usb_xfer)
5461*4f2df630SAndroid Build Coastguard Worker 			send_done(&td.uep);
5462*4f2df630SAndroid Build Coastguard Worker 
5463*4f2df630SAndroid Build Coastguard Worker 		if (transferred_sections)
5464*4f2df630SAndroid Build Coastguard Worker 			generate_reset_request(&td);
5465*4f2df630SAndroid Build Coastguard Worker 
5466*4f2df630SAndroid Build Coastguard Worker 		if (show_fw_ver) {
5467*4f2df630SAndroid Build Coastguard Worker 			if (show_machine_output) {
5468*4f2df630SAndroid Build Coastguard Worker 				print_machine_output("RO_FW_VER", "%d.%d.%d",
5469*4f2df630SAndroid Build Coastguard Worker 						     targ.shv[0].epoch,
5470*4f2df630SAndroid Build Coastguard Worker 						     targ.shv[0].major,
5471*4f2df630SAndroid Build Coastguard Worker 						     targ.shv[0].minor);
5472*4f2df630SAndroid Build Coastguard Worker 				print_machine_output("RW_FW_VER", "%d.%d.%d",
5473*4f2df630SAndroid Build Coastguard Worker 						     targ.shv[1].epoch,
5474*4f2df630SAndroid Build Coastguard Worker 						     targ.shv[1].major,
5475*4f2df630SAndroid Build Coastguard Worker 						     targ.shv[1].minor);
5476*4f2df630SAndroid Build Coastguard Worker 			} else {
5477*4f2df630SAndroid Build Coastguard Worker 				printf("Current versions:\n");
5478*4f2df630SAndroid Build Coastguard Worker 				printf("RO %d.%d.%d\n", targ.shv[0].epoch,
5479*4f2df630SAndroid Build Coastguard Worker 				       targ.shv[0].major, targ.shv[0].minor);
5480*4f2df630SAndroid Build Coastguard Worker 				printf("RW %d.%d.%d\n", targ.shv[1].epoch,
5481*4f2df630SAndroid Build Coastguard Worker 				       targ.shv[1].major, targ.shv[1].minor);
5482*4f2df630SAndroid Build Coastguard Worker 			}
5483*4f2df630SAndroid Build Coastguard Worker 		}
5484*4f2df630SAndroid Build Coastguard Worker 	}
5485*4f2df630SAndroid Build Coastguard Worker 
5486*4f2df630SAndroid Build Coastguard Worker 	if (td.ep_type == usb_xfer) {
5487*4f2df630SAndroid Build Coastguard Worker 		libusb_close(td.uep.devh);
5488*4f2df630SAndroid Build Coastguard Worker 		libusb_exit(NULL);
5489*4f2df630SAndroid Build Coastguard Worker 	}
5490*4f2df630SAndroid Build Coastguard Worker 
5491*4f2df630SAndroid Build Coastguard Worker 	if (!transferred_sections)
5492*4f2df630SAndroid Build Coastguard Worker 		return noop;
5493*4f2df630SAndroid Build Coastguard Worker 
5494*4f2df630SAndroid Build Coastguard Worker 	printf("image updated\n");
5495*4f2df630SAndroid Build Coastguard Worker 	return all_updated;
5496*4f2df630SAndroid Build Coastguard Worker }
5497