blob: 1acebc5393d6425a3fd86f8aa9839d31b6449937 [file] [log] [blame]
/*
* Copyright (c) 2013-2014 NVIDIA Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __OTE_PROTOCOL_H__
#define __OTE_PROTOCOL_H__
#ifdef CONFIG_TRUSTY
#include <linux/trusty/smcall.h>
#endif
#include "ote_types.h"
#define TE_IOCTL_MAGIC_NUMBER ('t')
#define TE_IOCTL_OPEN_CLIENT_SESSION \
_IOWR(TE_IOCTL_MAGIC_NUMBER, 0x10, union te_cmd)
#define TE_IOCTL_CLOSE_CLIENT_SESSION \
_IOWR(TE_IOCTL_MAGIC_NUMBER, 0x11, union te_cmd)
#define TE_IOCTL_LAUNCH_OPERATION \
_IOWR(TE_IOCTL_MAGIC_NUMBER, 0x14, union te_cmd)
/* ioctls using new structs (eventually to replace current ioctls) */
#define TE_IOCTL_OPEN_CLIENT_SESSION_COMPAT \
_IOWR(TE_IOCTL_MAGIC_NUMBER, 0x10, union te_cmd_compat)
#define TE_IOCTL_CLOSE_CLIENT_SESSION_COMPAT \
_IOWR(TE_IOCTL_MAGIC_NUMBER, 0x11, union te_cmd_compat)
#define TE_IOCTL_LAUNCH_OPERATION_COMPAT \
_IOWR(TE_IOCTL_MAGIC_NUMBER, 0x14, union te_cmd_compat)
#define TE_IOCTL_SS_NEW_REQ_LEGACY \
_IOR(TE_IOCTL_MAGIC_NUMBER, 0x20, struct te_ss_op_legacy)
#define TE_IOCTL_SS_REQ_COMPLETE_LEGACY \
_IOWR(TE_IOCTL_MAGIC_NUMBER, 0x21, struct te_ss_op_legacy)
/* ioctls using new SS structs (eventually to replace current SS ioctls) */
#define TE_IOCTL_SS_NEW_REQ \
_IOR(TE_IOCTL_MAGIC_NUMBER, 0x20, struct te_ss_op)
#define TE_IOCTL_SS_REQ_COMPLETE \
_IOWR(TE_IOCTL_MAGIC_NUMBER, 0x21, struct te_ss_op)
/* secure storage ioctl */
#define TE_IOCTL_SS_CMD \
_IOR(TE_IOCTL_MAGIC_NUMBER, 0x30, int)
#define TE_IOCTL_SS_CMD_GET_NEW_REQ 1
#define TE_IOCTL_SS_CMD_REQ_COMPLETE 2
#define TE_IOCTL_MIN_NR _IOC_NR(TE_IOCTL_OPEN_CLIENT_SESSION)
#define TE_IOCTL_MAX_NR _IOC_NR(TE_IOCTL_SS_CMD)
/* shared buffer is 2 pages: 1st are requests, 2nd are params */
#define TE_CMD_DESC_MAX (PAGE_SIZE / sizeof(struct te_request))
#define TE_PARAM_MAX (PAGE_SIZE / sizeof(struct te_oper_param))
#define TE_CMD_DESC_MAX_COMPAT \
(PAGE_SIZE / sizeof(struct te_request_compat))
#define TE_PARAM_MAX_COMPAT \
(PAGE_SIZE / sizeof(struct te_oper_param_compat))
#define MAX_EXT_SMC_ARGS 12
struct tlk_info;
extern struct mutex smc_lock;
extern struct tlk_device tlk_dev;
uint32_t _tlk_generic_smc(uint32_t arg0, uintptr_t arg1, uintptr_t arg2);
uint32_t tlk_generic_smc(struct tlk_info *info, uint32_t arg0,
uintptr_t arg1, uintptr_t arg2, uintptr_t arg3);
uint32_t _tlk_extended_smc(uintptr_t *args);
uint32_t tlk_extended_smc(struct tlk_info *info, uintptr_t *args);
void tlk_irq_handler(void);
int tlk_device_init(struct tlk_info *info);
/* errors returned by secure world in reponse to SMC calls */
enum {
TE_ERROR_PREEMPT_BY_IRQ = 0xFFFFFFFD,
TE_ERROR_PREEMPT_BY_FS = 0xFFFFFFFE,
};
struct tlk_device {
struct te_request *req_addr;
dma_addr_t req_addr_phys;
struct te_oper_param *param_addr;
dma_addr_t param_addr_phys;
struct te_oper_param_page_info *param_pages;
dma_addr_t param_pages_phys;
size_t param_pages_size;
size_t param_pages_tail;
struct te_request_compat *req_addr_compat;
struct te_oper_param_compat *param_addr_compat;
char *req_param_buf;
unsigned long *param_bitmap;
struct list_head used_cmd_list;
struct list_head free_cmd_list;
struct tlk_info *tlk_info;
};
struct te_cmd_req_desc {
struct te_request *req_addr;
struct list_head list;
};
struct te_cmd_req_desc_compat {
struct te_request_compat *req_addr;
struct list_head list;
};
struct te_shmem_desc {
struct list_head list;
uint32_t type;
void *buffer;
size_t size;
unsigned long nrpages;
struct page *pages[];
};
struct te_session {
struct rb_node node;
uint32_t session_id;
struct list_head persist_shmem_list;
};
struct tlk_context {
struct tlk_device *dev;
struct rb_root sessions;
struct list_head temp_shmem_list;
struct list_head temp_persist_shmem_list;
bool is_ss_daemon;
};
enum {
#ifndef CONFIG_TRUSTY
/* Trusted Application Calls */
TE_SMC_OPEN_SESSION = 0x30000001,
TE_SMC_CLOSE_SESSION = 0x30000002,
TE_SMC_LAUNCH_OPERATION = 0x30000003,
/* Trusted OS calls */
TE_SMC_REGISTER_REQ_BUF = 0x32000002,
TE_SMC_REGISTER_IRQ_HANDLER = 0x32000004,
TE_SMC_NS_IRQ_DONE = 0x32000005,
TE_SMC_INIT_LOGGER = 0x32000007,
TE_SMC_SS_REGISTER_HANDLER_LEGACY = 0x32000008,
TE_SMC_SS_REQ_COMPLETE = 0x32000009,
TE_SMC_SS_REGISTER_HANDLER = 0x32000010,
/* SIP (SOC specific) calls. */
TE_SMC_PROGRAM_VPR = 0x82000003,
#else
TE_SMC_OPEN_SESSION = SMC_STDCALL_NR(SMC_ENTITY_TRUSTED_APP, 1),
TE_SMC_CLOSE_SESSION = SMC_STDCALL_NR(SMC_ENTITY_TRUSTED_APP, 2),
TE_SMC_LAUNCH_OPERATION = SMC_STDCALL_NR(SMC_ENTITY_TRUSTED_APP, 3),
TE_SMC_NS_CB_COMPLETE = SMC_STDCALL_NR(SMC_ENTITY_TRUSTED_APP, 4),
TE_SMC_FC_HAS_NS_WORK = SMC_FASTCALL_NR(SMC_ENTITY_TRUSTED_APP, 1),
/* Trusted OS calls */
TE_SMC_REGISTER_REQ_BUF = SMC_STDCALL_NR(SMC_ENTITY_TRUSTED_OS, 2),
TE_SMC_REGISTER_IRQ_HANDLER = SMC_STDCALL_NR(SMC_ENTITY_TRUSTED_OS, 4),
TE_SMC_NS_IRQ_DONE = SMC_STDCALL_NR(SMC_ENTITY_TRUSTED_OS, 5),
TE_SMC_INIT_LOGGER = SMC_STDCALL_NR(SMC_ENTITY_TRUSTED_OS, 7),
TE_SMC_SS_REGISTER_HANDLER_LEGACY = SMC_STDCALL_NR(SMC_ENTITY_TRUSTED_OS, 8),
TE_SMC_SS_REQ_COMPLETE = SMC_STDCALL_NR(SMC_ENTITY_TRUSTED_OS, 9),
TE_SMC_SS_REGISTER_HANDLER = SMC_STDCALL_NR(SMC_ENTITY_TRUSTED_OS, 10),
/* SIP (SOC specific) calls. */
TE_SMC_PROGRAM_VPR = SMC_STDCALL_NR(SMC_ENTITY_SIP, 3)
#endif
};
enum {
TE_PARAM_TYPE_NONE = 0x0,
TE_PARAM_TYPE_INT_RO = 0x1,
TE_PARAM_TYPE_INT_RW = 0x2,
TE_PARAM_TYPE_MEM_RO = 0x3,
TE_PARAM_TYPE_MEM_RW = 0x4,
TE_PARAM_TYPE_PERSIST_MEM_RO = 0x100,
TE_PARAM_TYPE_PERSIST_MEM_RW = 0x101,
};
struct te_oper_param {
uint32_t index;
uint32_t type;
union {
struct {
uint32_t val;
} Int;
struct {
void *base;
uint32_t len;
} Mem;
} u;
void *next_ptr_user;
};
struct te_oper_param_page_info {
uint64_t attr;
};
struct te_oper_param_compat {
uint32_t index;
uint32_t type;
union {
struct {
uint32_t val;
} Int;
struct {
uint64_t base;
uint32_t len;
} Mem;
} u;
uint64_t next_ptr_user;
};
struct te_operation {
uint32_t command;
struct te_oper_param *list_head;
/* Maintain a pointer to tail of list to easily add new param node */
struct te_oper_param *list_tail;
uint32_t list_count;
uint32_t status;
uint32_t iterface_side;
};
struct te_service_id {
uint32_t time_low;
uint16_t time_mid;
uint16_t time_hi_and_version;
uint8_t clock_seq_and_node[8];
};
/*
* OpenSession
*/
struct te_opensession {
struct te_service_id dest_uuid;
struct te_operation operation;
uint32_t answer;
};
/*
* CloseSession
*/
struct te_closesession {
uint32_t session_id;
uint32_t answer;
};
/*
* LaunchOperation
*/
struct te_launchop {
uint32_t session_id;
struct te_operation operation;
uint32_t answer;
};
union te_cmd {
struct te_opensession opensession;
struct te_closesession closesession;
struct te_launchop launchop;
};
/*
* Compat versions of the original structs (eventually to replace
* the old structs, once the lib/TLK kernel changes are in).
*/
struct te_operation_compat {
uint32_t command;
uint32_t status;
uint64_t list_head;
uint64_t list_tail;
uint32_t list_count;
uint32_t interface_side;
};
/*
* OpenSession
*/
struct te_opensession_compat {
struct te_service_id dest_uuid;
struct te_operation_compat operation;
uint64_t answer;
};
/*
* CloseSession
*/
struct te_closesession_compat {
uint32_t session_id;
uint64_t answer;
};
/*
* LaunchOperation
*/
struct te_launchop_compat {
uint32_t session_id;
struct te_operation_compat operation;
uint64_t answer;
};
union te_cmd_compat {
struct te_opensession_compat opensession;
struct te_closesession_compat closesession;
struct te_launchop_compat launchop;
};
struct te_request {
uint32_t type;
uint32_t session_id;
uint32_t command_id;
struct te_oper_param *params;
uint32_t params_size;
uint32_t dest_uuid[4];
uint32_t result;
uint32_t result_origin;
};
struct te_request_compat {
uint32_t type;
uint32_t session_id;
uint32_t command_id;
uint64_t params;
uint32_t params_size;
uint32_t dest_uuid[4];
uint32_t result;
uint32_t result_origin;
};
struct te_answer {
uint32_t result;
uint32_t session_id;
uint32_t result_origin;
};
void te_open_session(struct te_opensession *cmd,
struct te_request *request,
struct tlk_context *context);
void te_close_session(struct te_closesession *cmd,
struct te_request *request,
struct tlk_context *context);
void te_launch_operation(struct te_launchop *cmd,
struct te_request *request,
struct tlk_context *context);
void te_open_session_compat(struct te_opensession_compat *cmd,
struct te_request_compat *request,
struct tlk_context *context);
void te_close_session_compat(struct te_closesession_compat *cmd,
struct te_request_compat *request,
struct tlk_context *context);
void te_launch_operation_compat(struct te_launchop_compat *cmd,
struct te_request_compat *request,
struct tlk_context *context);
#define SS_OP_MAX_DATA_SIZE 0x1000
struct te_ss_op {
uint32_t req_size;
uint8_t data[SS_OP_MAX_DATA_SIZE];
};
int tlk_ss_init(struct tlk_info *info);
int tlk_ss_init_legacy(struct tlk_info *info);
struct te_ss_op_legacy {
uint8_t data[SS_OP_MAX_DATA_SIZE];
};
int te_handle_ss_ioctl_legacy(struct file *file, unsigned int ioctl_num,
unsigned long ioctl_param);
int te_handle_ss_ioctl(struct file *file, unsigned int ioctl_num,
unsigned long ioctl_param);
int te_handle_fs_ioctl(struct file *file, unsigned int ioctl_num,
unsigned long ioctl_param);
int ote_logger_init(struct tlk_info *tlk_info);
void ote_print_logs(void);
uint32_t tlk_ss_op(void);
void tlk_ss_close(void);
int te_fill_page_info(struct te_oper_param_page_info *pg_inf,
unsigned long start, struct page *page,
struct vm_area_struct *vma);
#endif