tegrakernel/kernel/nvidia/include/uapi/linux/tegra_cpc.h

176 lines
5.0 KiB
C

/*
* 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