285 lines
7.6 KiB
C
Executable File
285 lines
7.6 KiB
C
Executable File
/*
|
|
* TZ ICCC Support
|
|
*
|
|
*/
|
|
|
|
#include <asm/uaccess.h>
|
|
#include <linux/list.h>
|
|
#include <linux/device.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/kobject.h>
|
|
#include <linux/module.h>
|
|
#include <linux/miscdevice.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/syscalls.h>
|
|
#include <linux/init.h>
|
|
#include <linux/types.h>
|
|
#include <linux/proc_fs.h>
|
|
#include <linux/delay.h>
|
|
#include "tz_iccc.h"
|
|
|
|
/* ICCC implementation for kernel */
|
|
int is_iccc_ready;
|
|
#define DRIVER_DESC "A kernel module to read boot_completed status"
|
|
|
|
uint8_t *iccc_tci = NULL;
|
|
struct mc_session_handle iccc_mchandle;
|
|
|
|
uint32_t Iccc_SaveData_Kernel(uint32_t type, uint32_t value)
|
|
{
|
|
enum mc_result mc_ret;
|
|
struct mc_uuid_t uuid = TL_TZ_ICCC_UUID;
|
|
int ret = 0;
|
|
tciMessage_t *msg;
|
|
|
|
printk(KERN_ERR "ICCC : Iccc_SaveData_Kernel \n");
|
|
|
|
if (!is_iccc_ready) {
|
|
ret = RET_ICCC_FAIL;
|
|
pr_err("%s: Not ready! type:%#x, ret:%d\n", __func__, type, ret);
|
|
goto iccc_ret;
|
|
}
|
|
|
|
if(ICCC_SECTION_TYPE(type) != KERN_ICCC_TYPE_START) {
|
|
if (type != SELINUX_STATUS) {
|
|
ret = RET_ICCC_FAIL;
|
|
pr_err("iccc permission denied! ret = 0x%x", ret);
|
|
ret = RET_ICCC_FAIL;
|
|
goto iccc_ret;
|
|
}
|
|
}
|
|
|
|
/* open device for iccc trustlet */
|
|
mc_ret = mc_open_device(MC_DEVICE_ID_DEFAULT);
|
|
if (mc_ret != MC_DRV_OK) {
|
|
pr_err("ICCC --cannot get mobicore handle from kernel. %d\n",mc_ret);
|
|
ret = RET_ICCC_FAIL;
|
|
goto iccc_ret;
|
|
}
|
|
|
|
/* alloc world shared memory for iccc trustlet */
|
|
mc_ret = mc_malloc_wsm(MC_DEVICE_ID_DEFAULT, 0, sizeof(tciMessage_t),&iccc_tci, 0);
|
|
if (mc_ret != MC_DRV_OK) {
|
|
pr_err("ICCC --cannot alloc world shared memory.%d\n",mc_ret);
|
|
ret = RET_ICCC_FAIL;
|
|
goto iccc_close_device;
|
|
}
|
|
|
|
memset(&iccc_mchandle, 0, sizeof(struct mc_session_handle));
|
|
iccc_mchandle.device_id = MC_DEVICE_ID_DEFAULT;
|
|
|
|
/* open session for iccc trustlet */
|
|
mc_ret = mc_open_session(&iccc_mchandle, &uuid, iccc_tci,sizeof(tciMessage_t));
|
|
if (mc_ret != MC_DRV_OK) {
|
|
pr_err("ICCC : --cannot open mobicore session from kernel. %d\n",mc_ret);
|
|
ret = RET_ICCC_FAIL;
|
|
goto iccc_free_wsm;
|
|
}
|
|
|
|
msg = (tciMessage_t *)iccc_tci;
|
|
|
|
msg->header.id = CMD_ICCC_SAVEDATA;
|
|
msg->payload.generic.content.iccc_req.cmd_id = CMD_ICCC_SAVEDATA;
|
|
msg->payload.generic.content.iccc_req.type = type;
|
|
msg->payload.generic.content.iccc_req.value = value;
|
|
|
|
/* Send the command to the tl. */
|
|
mc_ret = mc_notify(&iccc_mchandle);
|
|
if (mc_ret != MC_DRV_OK) {
|
|
pr_err("ICCC--mc_notify failed.\n");
|
|
ret = RET_ICCC_FAIL;
|
|
goto iccc_close_session;
|
|
}
|
|
|
|
retry1:
|
|
mc_ret = mc_wait_notification(&iccc_mchandle, -1);
|
|
if (MC_DRV_ERR_INTERRUPTED_BY_SIGNAL == mc_ret) {
|
|
usleep_range(1000, 5000);
|
|
goto retry1;
|
|
}
|
|
|
|
if (mc_ret != MC_DRV_OK) {
|
|
pr_err("ICCC--wait_notify failed.\n");
|
|
ret = RET_ICCC_FAIL;
|
|
goto iccc_close_session;
|
|
}
|
|
|
|
pr_warn("ICCC--wait_notify completed.\n");
|
|
|
|
if (msg->payload.generic.content.iccc_rsp.ret == RET_ICCC_SUCCESS) {
|
|
pr_info("ICCC : Successfully write\n");
|
|
ret = RET_ICCC_SUCCESS;
|
|
}
|
|
else {
|
|
pr_err("ICCC : write failed with error (%d)\n",msg->payload.generic.content.iccc_rsp.ret);
|
|
ret = RET_ICCC_FAIL;
|
|
}
|
|
|
|
iccc_close_session:
|
|
if (mc_close_session(&iccc_mchandle) != MC_DRV_OK) {
|
|
pr_err("ICCC--failed to close mobicore session.\n");
|
|
}
|
|
|
|
iccc_free_wsm:
|
|
if (mc_free_wsm(MC_DEVICE_ID_DEFAULT, iccc_tci) != MC_DRV_OK) {
|
|
pr_err("ICCC--failed to free wsm.\n");
|
|
}
|
|
|
|
iccc_close_device:
|
|
if (mc_close_device(MC_DEVICE_ID_DEFAULT) != MC_DRV_OK) {
|
|
pr_err("ICCC--failed to shutdown mobicore instance.\n");
|
|
}
|
|
|
|
iccc_ret:
|
|
return ret;
|
|
}
|
|
|
|
uint32_t Iccc_ReadData_Kernel(uint32_t type, uint32_t *value)
|
|
{
|
|
enum mc_result mc_ret;
|
|
struct mc_uuid_t uuid = TL_TZ_ICCC_UUID;
|
|
int ret = 0;
|
|
tciMessage_t *msg;
|
|
|
|
printk(KERN_ERR "ICCC Iccc_ReadData_Kernel \n");
|
|
|
|
if (!is_iccc_ready) {
|
|
ret = RET_ICCC_FAIL;
|
|
pr_err("%s: Not ready! type:%#x, ret:%d\n", __func__, type, ret);
|
|
goto iccc_ret;
|
|
}
|
|
|
|
/* open device for iccc trustlet */
|
|
mc_ret = mc_open_device(MC_DEVICE_ID_DEFAULT);
|
|
if (mc_ret != MC_DRV_OK) {
|
|
pr_err("ICCC --cannot get mobicore handle from kernel. %d\n",mc_ret);
|
|
ret = RET_ICCC_FAIL;
|
|
goto iccc_ret;
|
|
}
|
|
|
|
/* alloc world shared memory for iccc trustlet */
|
|
mc_ret = mc_malloc_wsm(MC_DEVICE_ID_DEFAULT, 0, sizeof(tciMessage_t),&iccc_tci, 0);
|
|
if (mc_ret != MC_DRV_OK) {
|
|
pr_err("ICCC--cannot alloc world shared memory.%d\n",mc_ret);
|
|
ret = RET_ICCC_FAIL;
|
|
goto iccc_close_device;
|
|
}
|
|
memset(&iccc_mchandle, 0, sizeof(struct mc_session_handle));
|
|
iccc_mchandle.device_id = MC_DEVICE_ID_DEFAULT;
|
|
|
|
/* open session for iccc trustlet */
|
|
mc_ret = mc_open_session(&iccc_mchandle, &uuid, iccc_tci,sizeof(tciMessage_t));
|
|
if (mc_ret != MC_DRV_OK) {
|
|
pr_err("ICCC--cannot open mobicore session from kernel. %d\n",mc_ret);
|
|
ret = RET_ICCC_FAIL;
|
|
goto iccc_free_wsm;
|
|
}
|
|
|
|
/* Load message */
|
|
msg = (tciMessage_t *)iccc_tci;
|
|
msg->header.id = CMD_ICCC_READDATA;
|
|
msg->payload.generic.content.iccc_req.cmd_id = CMD_ICCC_READDATA;
|
|
msg->payload.generic.content.iccc_req.type = type;
|
|
|
|
/* Send the command to the tl. */
|
|
mc_ret = mc_notify(&iccc_mchandle);
|
|
if (mc_ret != MC_DRV_OK) {
|
|
pr_err("ICCC mc_notify failed.\n");
|
|
ret = RET_ICCC_FAIL;
|
|
goto iccc_close_session;
|
|
}
|
|
|
|
retry2:
|
|
mc_ret = mc_wait_notification(&iccc_mchandle, -1);
|
|
if (MC_DRV_ERR_INTERRUPTED_BY_SIGNAL == mc_ret) {
|
|
usleep_range(1000, 5000);
|
|
goto retry2;
|
|
}
|
|
if (mc_ret != MC_DRV_OK) {
|
|
pr_err("ICCC--wait_notify failed.\n");
|
|
ret = RET_ICCC_FAIL;
|
|
goto iccc_close_session;
|
|
}
|
|
|
|
pr_warn("ICCC--wait_notify completed.\n");
|
|
|
|
if (msg->payload.generic.content.iccc_rsp.ret == RET_ICCC_SUCCESS) {
|
|
pr_info("ICCC : Iccc_ReadData_Kernel successful\n");
|
|
ret = RET_ICCC_SUCCESS;
|
|
*value = msg->payload.generic.content.iccc_rsp.value;
|
|
}
|
|
else {
|
|
pr_err("ICCC : Iccc_ReadData_Kernel failed with error (%d)\n",msg->payload.generic.content.iccc_rsp.ret);
|
|
ret = RET_ICCC_FAIL;
|
|
}
|
|
|
|
iccc_close_session:
|
|
if (mc_close_session(&iccc_mchandle) != MC_DRV_OK) {
|
|
pr_err("ICCC--failed to close mobicore session.\n");
|
|
}
|
|
|
|
iccc_free_wsm:
|
|
if (mc_free_wsm(MC_DEVICE_ID_DEFAULT, iccc_tci) != MC_DRV_OK) {
|
|
pr_err("ICCC--failed to free wsm.\n");
|
|
}
|
|
|
|
iccc_close_device:
|
|
if (mc_close_device(MC_DEVICE_ID_DEFAULT) != MC_DRV_OK) {
|
|
pr_err("ICCC--failed to shutdown mobicore instance.\n");
|
|
}
|
|
|
|
iccc_ret:
|
|
return ret;
|
|
}
|
|
|
|
static ssize_t iccc_write(struct file *fp, const char __user *buf, size_t len, loff_t *off)
|
|
{
|
|
// uint32_t ret;
|
|
printk(KERN_ERR "%s:\n", __func__);
|
|
is_iccc_ready = 1;
|
|
|
|
#if 0//defined(CONFIG_SECURITY_SELINUX)
|
|
printk(KERN_INFO "%s: selinux_enabled:%d, selinux_enforcing:%d\n",__func__, selinux_is_enabled(), selinux_is_enforcing());
|
|
if (selinux_is_enabled() && selinux_is_enforcing()) {
|
|
if (0 != (ret = Iccc_SaveData_Kernel(SELINUX_STATUS,0x0))) {
|
|
printk(KERN_ERR "%s: Iccc_SaveData_Kernel failed, type = %x, value =%x\n", __func__,SELINUX_STATUS,0x0);
|
|
}
|
|
}
|
|
else {
|
|
if (0 != (ret = Iccc_SaveData_Kernel(SELINUX_STATUS,0x1))) {
|
|
printk(KERN_ERR "%s: Iccc_SaveData_Kernel failed, type = %x, value =%x\n", __func__,SELINUX_STATUS,0x1);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// len bytes successfully written
|
|
return len;
|
|
}
|
|
|
|
static const struct file_operations iccc_proc_fops = {
|
|
.write = iccc_write,
|
|
};
|
|
|
|
static int __init iccc_init(void)
|
|
{
|
|
printk(KERN_INFO"%s:\n", __func__);
|
|
|
|
if (proc_create("iccc_ready", 0644, NULL, &iccc_proc_fops) == NULL) {
|
|
printk(KERN_ERR "%s: proc_create() failed\n",__func__);
|
|
return -1;
|
|
}
|
|
printk(KERN_INFO"%s: registered /proc/iccc_boot_completed interface\n", __func__);
|
|
return 0;
|
|
}
|
|
|
|
static void __exit iccc_exit(void)
|
|
{
|
|
printk(KERN_INFO"deregistering /proc/iccc_boot_completed interface\n");
|
|
remove_proc_entry("iccc_ready", NULL);
|
|
}
|
|
|
|
module_init(iccc_init);
|
|
module_exit(iccc_exit);
|
|
|
|
MODULE_DESCRIPTION(DRIVER_DESC);
|
|
/* END ICCC implementation for kernel */ |