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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
|
/*
* include/uapi/linux/nvhvivc_mempool_ioctl.h
*
* nvhvivc_mempool_ioctl.h- Access CPC storage blocks through i2c bus
*
* Copyright (c) 2016-2020, NVIDIA CORPORATION. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __UAPI_TEGRA_CPC_H
#define __UAPI_TEGRA_CPC_H
#include <linux/ioctl.h>
#include <linux/types.h>
enum req_resp_t {
CPC_READ_M_COUNT = 0x2,
CPC_WRITE_FRAME,
CPC_READ_FRAME,
CPC_GET_RESULT = 0x5,
CPC_GET_VERSION = 0x6,
};
enum result_t {
CPC_RESULT_OK = 0x0,
CPC_RESULT_GENERAL_FAILURE,
CPC_RESULT_AUTH_FAILURE,
CPC_RESULT_COUNTER_FAILURE,
CPC_RESULT_ADDR_FAILURE,
CPC_RESULT_WRITE_FAILURE = 0x5,
CPC_RESULT_READ_FAILURE,
CPC_RESULT_UNKNOWN_REQUEST,
CPC_RESULT_KEY_PROG_SEQ_FAILURE,
CPC_RESULT_KEY_PROG_PG_CORRUPT,
CPC_RESULT_KEY_PROG_DONE_PRIOR = 0xA,
CPC_RESULT_DATA_LENGTH_MISMATCH,
CPC_RESULT_UNEXPECTED_CONDITION,
CPC_RESULT_CONTROLLER_BUSY
};
#define CPC_MAX_DATA_SIZE 48
#define CPC_KEY_SIZE 32
#define CPC_HMAC_SIZE 32
#define CPC_DERIVATION_SIZE 28
#define CPC_NONCE_SIZE 4
#define CPC_COUNTER_SIZE 4
#define CPC_MAJOR_VER_SIZE 3
#define CPC_MINOR_VER_SIZE 1
/*
* CPC field description
*
* req is a command ID
* result is the status as returned by uC. If the communication to uC was
* not successful, this value will be set by the host
* len is the byte indicating how many bytes in data are valid data
* For read, this tells the kernel what is the expected size of
* data which will be returned by uC
* For write, this tells the kernel how many bytes in the data
* field are valid data.
* The range of this is 0 < n && n <= CPC_MAX_DATA_SIZE
* nonce is the counter which will be used for HMAC calculation. It is
* also used to correlate the response to the request. Host
* uses this value to match the response and the request
* write_counter
* The counter which indicates how many successful commits have
* been made by uC for the life time of uC
* data is the field which the client of uC could use to send / receive
* data which will be stored permanently by uC.
* derivation_value
* This field should be used to pass the unique data during
* read counter, which will be used for encryption later by
* both parties
* HMAC is the field which the client of uC could use to authenticate
* packets sent to and received from uC. If this field does not
* match uC's expectation, the packet will be rejected.
* HMAC is sent last tegra=>uC
* HMAC is sent first uC=>tegra
*/
/*
* Structs used for serialization and deserialization. The implementation is
* order sensitive. Any change to the struct would require a change to
* oneshot serialization / deserialization
*
* Notation: "Used for *" applies to all fields below until the end of struct
*/
struct tegra_cpc_read_counter_data {
/* Used for request */
__u8 nonce[CPC_NONCE_SIZE];
/* Used for response */
__u8 write_counter[CPC_COUNTER_SIZE];
/* Used for request */
__u8 derivation_value[CPC_DERIVATION_SIZE];
/* Used for response */
__u8 hmac[CPC_HMAC_SIZE];
} __packed;
struct tegra_cpc_write_frame_data {
/* Used for request */
__u8 length;
__u8 nonce[CPC_NONCE_SIZE];
__u8 write_counter[CPC_COUNTER_SIZE];
__u8 data[CPC_MAX_DATA_SIZE];
__u8 hmac[CPC_HMAC_SIZE];
} __packed;
struct tegra_cpc_read_frame_data {
/* Used for request */
__u8 length;
__u8 nonce[CPC_NONCE_SIZE];
/* Not used by kernel or uC as of now */
__u8 write_counter[CPC_COUNTER_SIZE];
/* Used for response */
__u8 data[CPC_MAX_DATA_SIZE];
__u8 hmac[CPC_HMAC_SIZE];
} __packed;
struct tegra_cpc_get_version_data {
/* Used for request */
__u8 nonce[CPC_NONCE_SIZE];
/* Used for response */
__u8 minor_ver[CPC_MINOR_VER_SIZE];
__u8 major_ver[CPC_MAJOR_VER_SIZE];
} __packed;
union tegra_cpc_cmd_data {
struct tegra_cpc_read_counter_data read_counter;
struct tegra_cpc_read_frame_data read_frame;
struct tegra_cpc_write_frame_data write_frame;
struct tegra_cpc_get_version_data get_version;
};
struct tegra_cpc_frame {
/* Used for request */
__u8 req;
/* Used for both request and response */
union tegra_cpc_cmd_data cmd_data;
/* Used for response of GET_STATUS */
__u8 hmac[CPC_HMAC_SIZE];
__u8 result;
__u8 nonce[CPC_NONCE_SIZE];
} __packed;
#define CPC_CMD_FIELD_SIZE(target_type, field) \
sizeof(((struct target_type *) 0)->field)
#define CPC_FIELD_SIZE(field) \
CPC_CMD_FIELD_SIZE(struct tegra_cpc_frame, field)
#define NVCPC_IOC_MAGIC 'C'
/*
* Returns 0 if a communication with uC was successful, regardless of operation
* pass or fail.
*/
#define NVCPC_IOCTL_DO_IO _IOWR(NVCPC_IOC_MAGIC, 2, \
struct tegra_cpc_frame)
#endif
|