mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
tzcom: Trustzone communicator driver
- The Trustzone Communicator driver provides interface for userspace to communicate with TrustZone. Change-Id: Id0dadacb9997d4a50e88f48ceb03540e1897df93 Signed-off-by: Sachin Shah <sachins@codeaurora.org>
This commit is contained in:
parent
4490e07b47
commit
67026061d7
7 changed files with 1687 additions and 0 deletions
181
Documentation/tzcom.txt
Normal file
181
Documentation/tzcom.txt
Normal file
|
@ -0,0 +1,181 @@
|
|||
Introduction
|
||||
============
|
||||
|
||||
The tzcom (TrustZone Communicator) device driver provides IOCTLs for userspace
|
||||
to communicate with TrustZone Operating Environment (TZBSP) using Secure
|
||||
Channel Manager (SCM) interface. It also provides a way for TZBSP to utilize
|
||||
services in HLOS.
|
||||
|
||||
Hardware description
|
||||
====================
|
||||
|
||||
The hardware interaction is specified in Secure Channel Manager for TZBSP design
|
||||
document. This driver exercises the SCM interface (scm_call).
|
||||
|
||||
Software description
|
||||
====================
|
||||
|
||||
This driver is a character device driver and following operations are registered:
|
||||
- tzcom_open()
|
||||
- tzcom_release()
|
||||
- tzcom_ioctl()
|
||||
|
||||
|
||||
This driver provides following IOCTL methods:
|
||||
TZCOM_IOCTL_REGISTER_SERVICE_REQ - to register HLOS service
|
||||
TZCOM_IOCTL_UNREGISTER_SERVICE_REQ - to unregister HLOS service
|
||||
TZCOM_IOCTL_SEND_CMD_REQ - send a command to a service
|
||||
TZCOM_IOCTL_READ_NEXT_CMD_REQ - wait for a cmd from TZBSP to use HLOS service
|
||||
TZCOM_IOCTL_CONTINUE_CMD_REQ - continue the last incomplete cmd on TZBSP
|
||||
|
||||
TZCOM_IOCTL_REGISTER_SERVICE_REQ sequence diagram:
|
||||
|
||||
+--------------+ +---------------+
|
||||
| USERSPACE | | TZCOM |
|
||||
+------+-------+ +-------+-------+
|
||||
| REGISTER_SERVICE |
|
||||
|----------------->| ___
|
||||
| |,-' ``.
|
||||
| + verify &`.
|
||||
| | add |
|
||||
| | service |
|
||||
| | to a list|
|
||||
| registered |<-.._,,,,/
|
||||
|<-----------------|
|
||||
| |
|
||||
|
||||
TZCOM_IOCTL_READ_NEXT_CMD_REQ, TZCOM_IOCTL_SEND_CMD_REQ and
|
||||
TZCOM_IOCTL_CONTINUE_CMD_REQ sequence:
|
||||
|
||||
+--------------+ +---------------+ +-------------+ +----------------+
|
||||
| USERSPACE | | TZCOM | | SCM | | TZBSP |
|
||||
+---+--+-------+ +-------+-------+ +------+------+ +-------+--------+
|
||||
| | READ_NEXT_CMD | | |
|
||||
+--|----------------->| | |
|
||||
| | |.--------. | |
|
||||
| | || BLOCKED| | |
|
||||
| | |`--------' | |
|
||||
| | | | |
|
||||
| | | | |
|
||||
| | SEND_CMD | | |
|
||||
| +----------------->| | |
|
||||
| | | scm_call | |
|
||||
| | +---------------->| SEND_CMD |
|
||||
| | | +---------------->|
|
||||
| | | | cmd incomplete |
|
||||
| | | scm_call returns|<----------------+
|
||||
| | |<----------------+ |
|
||||
| | | | |
|
||||
| | |,-'''-. | |
|
||||
| | + READ `. | |
|
||||
| | | NEXT | | |
|
||||
| | | CMD / | |
|
||||
| | READ_NEXT_CMD ret|<.____,' | |
|
||||
|<-|------------------+ | |
|
||||
,---. | | | | |
|
||||
/ \ | | | | |
|
||||
/perform\| | | | |
|
||||
received) | | | |
|
||||
\command/| | | | |
|
||||
\ / | | | | |
|
||||
`---' | | | | |
|
||||
| | | | |
|
||||
| | CONTINUE_CMD | | |
|
||||
+--|----------------->| | |
|
||||
| | returns | _,... | |
|
||||
| | immediately |' `. | |
|
||||
| | | fill in`. | |
|
||||
| | | incomplete | |
|
||||
| | | cmd ; | |
|
||||
| |<-...---' | |
|
||||
| | scm_call | |
|
||||
| +---------------->| SEND_CMD |
|
||||
| | +---------------->|
|
||||
| | | cmd complete |
|
||||
| | scm_call returns|<----------------+
|
||||
|SEND_CMD return |<----------------+ |
|
||||
|<-----------------+ | |
|
||||
| | | |
|
||||
|
||||
|
||||
|
||||
There are three shared buffers between TZCOM driver and TZBSP.
|
||||
1) For command and response buffers for SEND_CMD requests
|
||||
2) For commands originated from TZBSP and their corresponding responses
|
||||
3) For debug service
|
||||
|
||||
When calling IOCTL_SEND_CMD_REQ from userspace, command request and response
|
||||
buffers are initialized and provided in the IOCTL arguments. Where request and
|
||||
response buffers will be passed as an arguments to the smc_call method.
|
||||
|
||||
The requests are synchronous. The driver will put the process to sleep,
|
||||
waiting for the completion of the requests using wait_for_completion().
|
||||
|
||||
This driver uses kmalloc for shared buffer pools which get initialized at driver
|
||||
initialization. There are three buffers each 20 KB. If any of the buffers fail
|
||||
to initialize then driver will fail to load. Assumption is the allocated
|
||||
memory for buffers is contiguous.
|
||||
|
||||
|
||||
Design
|
||||
======
|
||||
|
||||
The goal of this driver is to provide a communication API for the userspace
|
||||
application to execute services in TrustZone as well as TrustZone operating
|
||||
environment to access services in HLOS.
|
||||
|
||||
Currently TZ->HLOS communication happens from a blocking call to READ_NEXT_CMD
|
||||
that is initiated from the userspace and on receiving a command request from TZ
|
||||
service, command is placed on a queue to unblock READ_NEXT_CMD call. This could
|
||||
have been solved by using a callback, but the practice of invoking callbacks in
|
||||
userspace from kernel is discouraged.
|
||||
|
||||
Power Management
|
||||
================
|
||||
|
||||
n/a
|
||||
|
||||
SMP/multi-core
|
||||
==============
|
||||
|
||||
TZCOM allows multiple services being registered from HLOS and multiple processes
|
||||
or threads can call IOCTL_READ_NEXT_MSG. These services will block until new
|
||||
data arrives on the shared buffer (buffer #2 as mentioned in Software
|
||||
Description). This is achieved using wait queues.
|
||||
|
||||
Security
|
||||
========
|
||||
|
||||
Please refer to Security Channel Manager design document.
|
||||
|
||||
Performance
|
||||
===========
|
||||
|
||||
Every scm_call is a context switch between non-trusted and trusted operating
|
||||
environment. There are no performance related matrix for scm_call available as
|
||||
of now.
|
||||
|
||||
Interface
|
||||
=========
|
||||
|
||||
This driver will have a /dev/tzcom node and following IOCTL calls can be made.
|
||||
|
||||
Userspace API (ioctl calls):
|
||||
TZCOM_IOCTL_REGISTER_SERVICE_REQ - to register HLOS service
|
||||
TZCOM_IOCTL_UNREGISTER_SERVICE_REQ - to unregister HLOS service
|
||||
TZCOM_IOCTL_SEND_CMD_REQ - send a command to a service
|
||||
TZCOM_IOCTL_READ_NEXT_CMD_REQ - wait for a cmd from TZBSP to use HLOS service
|
||||
TZCOM_IOCTL_CONTINUE_CMD_REQ - continue the last incomplete cmd on TZBSP
|
||||
|
||||
|
||||
Dependencies
|
||||
============
|
||||
|
||||
This driver interacts with Trustzone operating environment, thus depends on
|
||||
the TZBSP supported architecture.
|
||||
|
||||
|
||||
To do
|
||||
=====
|
||||
|
||||
TBD
|
|
@ -609,6 +609,14 @@ config PMIC8058_XOADC
|
|||
PMIC8058. Driver interface to program registers of the ADC over
|
||||
AMUX channels, devices on programmable MPP's and xotherm.
|
||||
|
||||
config TZCOM
|
||||
tristate "Trustzone Communicator driver"
|
||||
default n
|
||||
help
|
||||
Provides a communication interface between userspace and
|
||||
TrustZone Operating Environment (TZBSP) using Secure Channel
|
||||
Manager (SCM) interface.
|
||||
|
||||
source "drivers/misc/c2port/Kconfig"
|
||||
source "drivers/misc/eeprom/Kconfig"
|
||||
source "drivers/misc/cb710/Kconfig"
|
||||
|
|
|
@ -62,3 +62,4 @@ obj-$(CONFIG_PMIC8XXX_VIBRATOR) += pm8xxx-vibrator.o
|
|||
obj-$(CONFIG_PMIC8XXX_NFC) += pm8xxx-nfc.o
|
||||
obj-$(CONFIG_PMIC8XXX_UPL) += pm8xxx-upl.o
|
||||
obj-$(CONFIG_PMIC8058_XOADC) += pmic8058-xoadc.o
|
||||
obj-$(CONFIG_TZCOM) += tzcom.o
|
||||
|
|
1248
drivers/misc/tzcom.c
Normal file
1248
drivers/misc/tzcom.c
Normal file
File diff suppressed because it is too large
Load diff
112
drivers/misc/tzcomi.h
Normal file
112
drivers/misc/tzcomi.h
Normal file
|
@ -0,0 +1,112 @@
|
|||
/* Qualcomm TrustZone communicator driver
|
||||
*
|
||||
* Copyright (c) 2011, Code Aurora Forum. 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 version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* 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 __TZCOMI_H_
|
||||
#define __TZCOMI_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
enum tz_sched_cmd_id {
|
||||
TZ_SCHED_CMD_ID_INVALID = 0,
|
||||
TZ_SCHED_CMD_ID_INIT_SB_OUT, /**< Initialize the shared buffer */
|
||||
TZ_SCHED_CMD_ID_INIT_SB_LOG, /**< Initialize the logging shared buf */
|
||||
TZ_SCHED_CMD_ID_UNKNOWN = 0x7FFFFFFE,
|
||||
TZ_SCHED_CMD_ID_MAX = 0x7FFFFFFF
|
||||
};
|
||||
|
||||
enum tz_sched_cmd_type {
|
||||
TZ_SCHED_CMD_INVALID = 0,
|
||||
TZ_SCHED_CMD_NEW, /** New TZ Scheduler Command */
|
||||
TZ_SCHED_CMD_PENDING, /** Pending cmd...sched will restore stack */
|
||||
TZ_SCHED_CMD_COMPLETE, /** TZ sched command is complete */
|
||||
TZ_SCHED_CMD_MAX = 0x7FFFFFFF
|
||||
};
|
||||
|
||||
enum tz_sched_cmd_status {
|
||||
TZ_SCHED_STATUS_INCOMPLETE = 0,
|
||||
TZ_SCHED_STATUS_COMPLETE,
|
||||
TZ_SCHED_STATUS_MAX = 0x7FFFFFFF
|
||||
};
|
||||
|
||||
/** Command structure for initializing shared buffers (SB_OUT
|
||||
and SB_LOG)
|
||||
*/
|
||||
__packed struct tz_pr_init_sb_req_s {
|
||||
/** First 4 bytes should always be command id
|
||||
* from enum tz_sched_cmd_id */
|
||||
uint32_t pr_cmd;
|
||||
/** Pointer to the physical location of sb_out buffer */
|
||||
uint32_t sb_ptr;
|
||||
/** length of shared buffer */
|
||||
uint32_t sb_len;
|
||||
};
|
||||
|
||||
|
||||
__packed struct tz_pr_init_sb_rsp_s {
|
||||
/** First 4 bytes should always be command id
|
||||
* from enum tz_sched_cmd_id */
|
||||
uint32_t pr_cmd;
|
||||
/** Return code, 0 for success, Approp error code otherwise */
|
||||
int32_t ret;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* struct tzcom_command - tzcom command buffer
|
||||
* @cmd_type: value from enum tz_sched_cmd_type
|
||||
* @sb_in_cmd_addr: points to physical location of command
|
||||
* buffer
|
||||
* @sb_in_cmd_len: length of command buffer
|
||||
*/
|
||||
__packed struct tzcom_command {
|
||||
uint32_t cmd_type;
|
||||
uint8_t *sb_in_cmd_addr;
|
||||
uint32_t sb_in_cmd_len;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct tzcom_response - tzcom response buffer
|
||||
* @cmd_status: value from enum tz_sched_cmd_status
|
||||
* @sb_in_rsp_addr: points to physical location of response
|
||||
* buffer
|
||||
* @sb_in_rsp_len: length of command response
|
||||
*/
|
||||
__packed struct tzcom_response {
|
||||
uint32_t cmd_status;
|
||||
uint8_t *sb_in_rsp_addr;
|
||||
uint32_t sb_in_rsp_len;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct tzcom_callback - tzcom callback buffer
|
||||
* @cmd_id: command to run in registered service
|
||||
* @sb_out_rsp_addr: points to physical location of response
|
||||
* buffer
|
||||
* @sb_in_cmd_len: length of command response
|
||||
*
|
||||
* A callback buffer would be laid out in sb_out as follows:
|
||||
*
|
||||
* --------------------- <--- struct tzcom_callback
|
||||
* | callback header |
|
||||
* --------------------- <--- tzcom_callback.sb_out_cb_data_off
|
||||
* | callback data |
|
||||
* ---------------------
|
||||
*/
|
||||
__packed struct tzcom_callback {
|
||||
uint32_t cmd_id;
|
||||
uint32_t sb_out_cb_data_len;
|
||||
uint32_t sb_out_cb_data_off;
|
||||
};
|
||||
|
||||
#endif /* __TZCOMI_H_ */
|
|
@ -416,5 +416,6 @@ header-y += xattr.h
|
|||
header-y += xfrm.h
|
||||
header-y += msm_mdp.h
|
||||
header-y += msm_rotator.h
|
||||
header-y += tzcom.h
|
||||
header-y += qcedev.h
|
||||
header-y += genlock.h
|
||||
|
|
136
include/linux/tzcom.h
Normal file
136
include/linux/tzcom.h
Normal file
|
@ -0,0 +1,136 @@
|
|||
/* Qualcomm TrustZone communicator API */
|
||||
|
||||
#ifndef __TZCOM_H_
|
||||
#define __TZCOM_H_
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/ioctl.h>
|
||||
|
||||
#define MAX_ION_FD 4
|
||||
/**
|
||||
* struct tzcom_register_svc_op_req - for register service ioctl request
|
||||
* @svc_id - service id (shared between userspace and TZ)
|
||||
* @cmd_id_low - low number in cmd_id range (shared between userspace and TZ)
|
||||
* @cmd_id_high - high number in cmd_id range (shared between userspace and TZ)
|
||||
* @instance_id - unique id for the given service generated by tzcom driver
|
||||
*/
|
||||
struct tzcom_register_svc_op_req {
|
||||
uint32_t svc_id; /* in */
|
||||
uint32_t cmd_id_low; /* in */
|
||||
uint32_t cmd_id_high; /* in */
|
||||
uint32_t instance_id; /* out */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct tzcom_unregister_svc_op_req - for unregister service ioctl request
|
||||
* @svc_id - service id to unregister (provided in register_service request)
|
||||
* @instance_id - instance id generated in register service request
|
||||
*/
|
||||
struct tzcom_unregister_svc_op_req {
|
||||
uint32_t svc_id; /* in */
|
||||
uint32_t instance_id; /* in */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct tzcom_next_cmd_op_req - for read next command ioctl request
|
||||
* @svc_id - has to be a registered svc_id (see @tzcom_register_svc_op_req)
|
||||
* @instance_id - unique id for the given service (see @tzcom_register_svc_op_req)
|
||||
* @cmd_id - command to execute on the given service, received from TZ
|
||||
* @req_len - request buffer length, received from TZ
|
||||
* @req - request buffer, received from TZ
|
||||
*/
|
||||
struct tzcom_next_cmd_op_req {
|
||||
uint32_t svc_id; /* in */
|
||||
uint32_t instance_id; /* in */
|
||||
uint32_t cmd_id; /* out */
|
||||
unsigned int req_len; /* in/out */
|
||||
void *req_buf; /* in/out */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct tzcom_send_cmd_op_req - for send command ioctl request
|
||||
* @cmd_id - command to execute on TZBSP side
|
||||
* @ifd_data_fd - ion handle to some memory allocated in user space
|
||||
* @cmd_buf_offset - command buffer offset
|
||||
* @cmd_len - command buffer length
|
||||
* @cmd_buf - command buffer
|
||||
* @resp_len - response buffer length
|
||||
* @resp_buf - response buffer
|
||||
*/
|
||||
struct tzcom_send_cmd_op_req {
|
||||
uint32_t cmd_id; /* in */
|
||||
unsigned int cmd_len; /* in */
|
||||
void *cmd_buf; /* in */
|
||||
unsigned int resp_len; /* in/out */
|
||||
void *resp_buf; /* in/out */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct tzcom_ion_fd_info - ion fd handle data information
|
||||
* @fd - ion handle to some memory allocated in user space
|
||||
* @cmd_buf_offset - command buffer offset
|
||||
*/
|
||||
struct tzcom_ion_fd_info {
|
||||
int32_t fd;
|
||||
uint32_t cmd_buf_offset;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct tzcom_send_cmd_op_req - for send command ioctl request
|
||||
* @cmd_id - command to execute on TZBSP side
|
||||
* @ifd_data_fd - ion handle to some memory allocated in user space
|
||||
* @cmd_buf_offset - command buffer offset
|
||||
* @cmd_len - command buffer length
|
||||
* @cmd_buf - command buffer
|
||||
* @resp_len - response buffer length
|
||||
* @resp_buf - response buffer
|
||||
*/
|
||||
struct tzcom_send_cmd_fd_op_req {
|
||||
uint32_t cmd_id; /* in */
|
||||
struct tzcom_ion_fd_info ifd_data[MAX_ION_FD];
|
||||
unsigned int cmd_len; /* in */
|
||||
void *cmd_buf; /* in */
|
||||
unsigned int resp_len; /* in/out */
|
||||
void *resp_buf; /* in/out */
|
||||
};
|
||||
/**
|
||||
* struct tzcom_cont_cmd_op_req - for continue command ioctl request. used
|
||||
* as a trigger from HLOS service to notify TZCOM that it's done with its
|
||||
* operation and provide the response for TZCOM can continue the incomplete
|
||||
* command execution
|
||||
* @cmd_id - Command to continue filled in by tzcom as tzcom knows about the
|
||||
* last incomplete command.
|
||||
* @instance_id - Instance id of the svc
|
||||
* @resp_len - Length of the response
|
||||
* @resp_buf - Response buffer where the response of the cmd should go.
|
||||
*/
|
||||
struct tzcom_cont_cmd_op_req {
|
||||
uint32_t cmd_id; /* out */
|
||||
uint32_t instance_id; /* in */
|
||||
unsigned int resp_len; /* in */
|
||||
void *resp_buf; /* in */
|
||||
};
|
||||
|
||||
#define TZCOM_IOC_MAGIC 0x97
|
||||
|
||||
/* For HLOS service */
|
||||
#define TZCOM_IOCTL_REGISTER_SERVICE_REQ \
|
||||
_IOWR(TZCOM_IOC_MAGIC, 1, struct tzcom_register_svc_op_req)
|
||||
/* For HLOS service */
|
||||
#define TZCOM_IOCTL_UNREGISTER_SERVICE_REQ \
|
||||
_IOWR(TZCOM_IOC_MAGIC, 2, struct tzcom_unregister_svc_op_req)
|
||||
/* For TZ service */
|
||||
#define TZCOM_IOCTL_SEND_CMD_REQ \
|
||||
_IOWR(TZCOM_IOC_MAGIC, 3, struct tzcom_send_cmd_op_req)
|
||||
/* For HLOS service */
|
||||
#define TZCOM_IOCTL_READ_NEXT_CMD_REQ \
|
||||
_IOWR(TZCOM_IOC_MAGIC, 4, struct tzcom_next_cmd_op_req)
|
||||
/* For TZ service */
|
||||
#define TZCOM_IOCTL_CONTINUE_CMD_REQ \
|
||||
_IOWR(TZCOM_IOC_MAGIC, 5, struct tzcom_cont_cmd_op_req)
|
||||
|
||||
#define TZCOM_IOCTL_ABORT_REQ _IO(TZCOM_IOC_MAGIC, 6)
|
||||
/* For TZ service */
|
||||
#define TZCOM_IOCTL_SEND_CMD_FD_REQ \
|
||||
_IOWR(TZCOM_IOC_MAGIC, 7, struct tzcom_send_cmd_fd_op_req)
|
||||
#endif /* __TZCOM_H_ */
|
Loading…
Reference in a new issue