summaryrefslogtreecommitdiff
path: root/chip/g/upgrade_fw.h
blob: 6296220535656a6804c249049979abf5273ca0f4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/* Copyright 2016 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef __EC_CHIP_G_UPGRADE_FW_H
#define __EC_CHIP_G_UPGRADE_FW_H

#include <stddef.h>

#include "common.h"  /* For __packed. */

/*
 * This file contains structures used to facilitate cr50 firmware updates,
 * which can be used on any g chip.
 *
 * The firmware update protocol consists of two phases: connection
 * establishment and actual image transfer.
 *
 * Image transfer is done in 1K blocks. The host supplying the image
 * encapsulates blocks in frames by prepending a header including the flash
 * offset where the block is destined and its digest.
 *
 * The CR50 device responds to each frame with a confirmation which is 1 byte
 * response. Zero value means success, non zero value is the error code
 * reported by CR50.
 *
 * To establish the connection, the host sends a different frame, which
 * contains no data and is destined to offset 0. Receiving such a frame
 * signals the CR50 that the host intends to transfer a new image.
 *
 * The connection establishment response is described by the
 * first_response_pdu structure below.
 */

#define UPGRADE_PROTOCOL_VERSION 6

/* This is the format of the update frame header. */
struct upgrade_command {
	uint32_t  block_digest;  /* first 4 bytes of sha1 of the rest of the
				  * frame.
				  */
	uint32_t  block_base;    /* Offset of this frame into the flash SPI. */
	/* The actual payload goes here. */
} __packed;

/*
 * This is the frame format the host uses when sending update PDUs over USB.
 *
 * The PDUs are up to 1K bytes in size, they are fragmented into USB chunks of
 * 64 bytes each and reassembled on the receive side before being passed to
 * the flash update function.
 *
 * The flash update function receives the unframed PDU body (starting at the
 * cmd field below), and puts its reply into the same buffer the PDU was in.
 */
struct update_frame_header {
	uint32_t block_size;    /* Total size of the block, including this
				 * field.
				 */
	struct upgrade_command cmd;
};

/*
 * A convenience structure which allows to group together various revision
 * fields of the header created by the signer.
 *
 * These fields are compared when deciding if versions of two images are the
 * same or when deciding which one of the available images to run.
 */
struct signed_header_version {
	uint32_t minor;
	uint32_t major;
	uint32_t epoch;
};

/*
 * Response to the connection establishment request.
 *
 * When responding to the very first packet of the upgrade sequence, the
 * original USB update implementation was responding with a four byte value,
 * just as to any other block of the transfer sequence.
 *
 * It became clear that there is a need to be able to enhance the upgrade
 * protocol, while staying backwards compatible.
 *
 * All newer protocol versions (starting with version 2) respond to the very
 * first packet with an 8 byte or larger response, where the first 4 bytes are
 * a version specific data, and the second 4 bytes - the protocol version
 * number.
 *
 * This way the host receiving of a four byte value in response to the first
 * packet is considered an indication of the target running the 'legacy'
 * protocol, version 1. Receiving of an 8 byte or longer response would
 * communicates the protocol version in the second 4 bytes.
 */
struct first_response_pdu {
	uint32_t return_value;

	/* The below fields are present in versions 2 and up. */
	uint32_t protocol_version;

	/* The below fields are present in versions 3 and up. */
	uint32_t  backup_ro_offset;
	uint32_t  backup_rw_offset;

	/* The below fields are present in versions 4 and up. */
	/* Versions of the currently active RO and RW sections. */
	struct signed_header_version shv[2];

	/* The below fields are present in versions 5 and up */
	/* keyids of the currently active RO and RW sections. */
	uint32_t keyid[2];
};

#define UPGRADE_DONE          0xB007AB1E

void fw_upgrade_command_handler(void *body,
				size_t cmd_size,
				size_t *response_size);

/* Used to tell fw upgrade the update ran successfully and is finished */
void fw_upgrade_complete(void);

/* Verify integrity of the PDU received over USB. */
int usb_pdu_valid(struct upgrade_command *cmd_body,
		  size_t cmd_size);

/* Various upgrade command return values. */
enum return_value {
	UPGRADE_SUCCESS = 0,
	UPGRADE_BAD_ADDR = 1,
	UPGRADE_ERASE_FAILURE = 2,
	UPGRADE_DATA_ERROR = 3,
	UPGRADE_WRITE_FAILURE = 4,
	UPGRADE_VERIFY_ERROR = 5,
	UPGRADE_GEN_ERROR = 6,
	UPGRADE_MALLOC_ERROR = 7,
	UPGRADE_ROLLBACK_ERROR = 8,
	UPGRADE_RATE_LIMIT_ERROR = 9,
	UPGRADE_UNALIGNED_BLOCK_ERROR = 10,
	UPGRADE_TRUNCATED_HEADER_ERROR = 11,
	UPGRADE_BOARD_ID_ERROR = 12,
	UPGRADE_BOARD_FLAGS_ERROR = 13,
	UPGRADE_DEV_ID_MISMATCH_ERROR = 14,
};

/*
 * This is the size of the update frame payload, unless this is the last chunk
 * of the image.
 */
#define SIGNED_TRANSFER_SIZE 1024

#endif  /* ! __EC_CHIP_G_UPGRADE_FW_H */