diff options
author | Seungho Lee <sh1006.lee@samsung.com> | 2016-07-04 16:22:05 +0900 |
---|---|---|
committer | jino.cho <jino.cho@samsung.com> | 2017-03-03 17:02:45 +0900 |
commit | d3ef33a80d7655791726b9fb8e8acb92ed6204b7 (patch) | |
tree | d7ac05a2543220e8f44c8d55e85da983e1932e8a | |
parent | fff132a2bce94614020152701acfd32c3ed5b4da (diff) | |
download | linux-3.10-artik-d3ef33a80d7655791726b9fb8e8acb92ed6204b7.tar.gz linux-3.10-artik-d3ef33a80d7655791726b9fb8e8acb92ed6204b7.tar.bz2 linux-3.10-artik-d3ef33a80d7655791726b9fb8e8acb92ed6204b7.zip |
misc: artiktee: Support 64bit kernel with compat_ and Add tzinfo for debugging
This patch to support 32bit user mode on 64bit kernel, so compat_ioctl
is added to file operations. tzinfo file is to fetch TEE information for
debugging. tzinfo can be enabled when Secure OS is built in debug mode.
Change-Id: Ida28ce1c241f90997f5c056c877b8c801d31a5d2
Signed-off-by: Seungho Lee <sh1006.lee@samsung.com>
30 files changed, 1754 insertions, 122 deletions
diff --git a/drivers/misc/artiktee/Kconfig b/drivers/misc/artiktee/Kconfig index 156767da8c8..484c8c4ef5f 100644 --- a/drivers/misc/artiktee/Kconfig +++ b/drivers/misc/artiktee/Kconfig @@ -10,4 +10,12 @@ config ARTIK_TRUSTZONE_DRIVER help This driver allows you can communicate with ARTIK Secure OS. When you use this driver, the platform has to support Secure OS. + +config ARTIK_FETCH_TEE_INFO + bool "ARTIK Fetch TEE information" + depends on (ARTIK_TRUSTZONE_DRIVER) + default n + help + This driver supports to fetch information in TEE side for ARTIK. + If Secure OS is built in Debug mode, you can use this feature. endmenu diff --git a/drivers/misc/artiktee/Makefile b/drivers/misc/artiktee/Makefile index bed729e5648..f0c743c56b2 100644 --- a/drivers/misc/artiktee/Makefile +++ b/drivers/misc/artiktee/Makefile @@ -1,10 +1,15 @@ MODULE_NAME := tzdev ccflags-y := -DCONFIG_SECOS_NO_RPMB=1 -DCONFIG_PSCI=1 +ifeq ($(CONFIG_ARTIK_FETCH_TEE_INFO),y) +ccflags-y += -DCONFIG_FETCH_TEE_INFO=1 +endif obj-$(CONFIG_ARTIK_TRUSTZONE_DRIVER) += $(MODULE_NAME).o $(MODULE_NAME)-objs += tzdev_main.o -$(MODULE_NAME)-objs += tzlog.o +$(MODULE_NAME)-objs += tzlog_print.o +$(MODULE_NAME)-objs += tzlog_core.o +$(MODULE_NAME)-objs += tzlog_process.o $(MODULE_NAME)-objs += sstransaction.o $(MODULE_NAME)-objs += tzpage.o $(MODULE_NAME)-objs += ss_core.o @@ -17,3 +22,6 @@ $(MODULE_NAME)-objs += tzlinkmgr.o $(MODULE_NAME)-objs += tzwsm.o $(MODULE_NAME)-objs += tzmem.o $(MODULE_NAME)-objs += tzdev_plat.o +ifeq ($(CONFIG_ARTIK_FETCH_TEE_INFO),y) +$(MODULE_NAME)-objs += tzinfo.o +endif diff --git a/drivers/misc/artiktee/circular_buffer.h b/drivers/misc/artiktee/circular_buffer.h index cf66c442893..c8bfc4d7894 100644 --- a/drivers/misc/artiktee/circular_buffer.h +++ b/drivers/misc/artiktee/circular_buffer.h @@ -34,7 +34,7 @@ #include <linux/uaccess.h> #include <linux/uio.h> #include <linux/slab.h> -#include "tzdev_internal.h" +#include "tzlog_print.h" #endif #else #include <sys/types.h> diff --git a/drivers/misc/artiktee/log_level_ree.h b/drivers/misc/artiktee/log_level_ree.h new file mode 100644 index 00000000000..1fb95f9aea6 --- /dev/null +++ b/drivers/misc/artiktee/log_level_ree.h @@ -0,0 +1,92 @@ +/********************************************************* + * Copyright (C) 2011 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * Author: Jungkyuen <jklolo.lee@samsung.com> + * 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 version 2 and no 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 St, Fifth Floor, Boston, MA 02110-1301 USA + * + *********************************************************/ + +#ifndef __LOG_LEVEL_H__ +#define __LOG_LEVEL_H__ + +typedef enum { +#ifndef LOG_DEBUG + LOG_EMERG = 0, + LOG_ALERT, + LOG_CRIT, + LOG_ERR, + LOG_WARNING, + LOG_NOTICE, + LOG_INFO, + LOG_DEBUG, +#endif + LOG_SILENT = 8, +} usr_log_level; + +typedef enum { + K_EMERG = 0, + K_ALERT, + K_CRIT, + K_ERR, + K_WARNING, + K_NOTICE, + K_INFO, + K_DEBUG, + K_SILENT, +} kernel_log_level; + +typedef enum { + SWD_USERMODE = 1, + SWD_KERNMODE, + NWD_USERMODE, + NWD_KERNMODE, + SWD_ENC_USERMODE, + SWD_ENC_KERNMODE, +} log_header_info; + +/* Ree World */ +#ifndef NDEBUG +#define TZDAEMON_DLOG_KERN_LOG_LEVEL LOG_DEBUG /* OutPut Default */ +#define TZDAEMON_DLOG_TA_LOG_LEVEL LOG_DEBUG /* OutPut Default */ +#define TZDAEMON_FILE_LOG_LEVEL LOG_DEBUG /* OutPut Default */ +#define TZDAEMON_SYSLOG_LOG_LEVEL LOG_DEBUG /* Output Default */ +#define TZDEV_TEE_LOG_LEVEL K_INFO /* OutPut Default */ + +#define TZDAEMON_LOCAL_DLOG_LOG_LEVEL LOG_DEBUG /* OutPut Default */ +#define TZDAEMON_LOCAL_FILE_LOG_LEVEL LOG_DEBUG /* OutPut Default */ +#define TZDAEMON_LOCAL_SYSLOG_LOG_LEVEL LOG_DEBUG /* OutPut Default */ +#define TZDEV_LOCAL_LOG_LEVEL K_INFO /* OutPut Default */ + +#define NO_HEADER_LOG_LEVEL LOG_INFO /* Generation Default */ +#else +#define TZDAEMON_DLOG_KERN_LOG_LEVEL LOG_ERR /* OutPut Default */ +#define TZDAEMON_DLOG_TA_LOG_LEVEL LOG_ERR /* OutPut Default */ +#define TZDAEMON_FILE_LOG_LEVEL LOG_ERR /* OutPut Default */ +#define TZDAEMON_SYSLOG_LOG_LEVEL LOG_SILENT /* Output Default */ +#define TZDEV_TEE_LOG_LEVEL K_ERR /* OutPut Default */ + +#define TZDAEMON_LOCAL_DLOG_LOG_LEVEL LOG_ALERT /* OutPut Default */ +#define TZDAEMON_LOCAL_FILE_LOG_LEVEL LOG_ALERT /* OutPut Default */ +#define TZDAEMON_LOCAL_SYSLOG_LOG_LEVEL LOG_ALERT /* OutPut Default */ +#define TZDEV_LOCAL_LOG_LEVEL K_ALERT /* OutPut Default */ + +#define NO_HEADER_LOG_LEVEL LOG_INFO /* Generation Default */ +#endif + +/* For Old Log Level */ +#define TZLOG_DEBUG K_DEBUG +#define TZLOG_INFO K_INFO +#define TZLOG_WARNING K_WARNING +#define TZLOG_ERROR K_ERR + +#endif diff --git a/drivers/misc/artiktee/log_system_api_ext.h b/drivers/misc/artiktee/log_system_api_ext.h new file mode 100644 index 00000000000..0e2c67fa07e --- /dev/null +++ b/drivers/misc/artiktee/log_system_api_ext.h @@ -0,0 +1,152 @@ +/********************************************************* + * Copyright (C) 2011 - 2016 Samsung Electronics Co., Ltd All Rights Reserved + * Author: Soonhong Kwon <aron.kwon@samsung.com> + * 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 version 2 and no 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 St, Fifth Floor, Boston, MA 02110-1301 USA + * + *********************************************************/ + +#ifndef __LOG_SYSTEM_API_REE_H__ +#define __LOG_SYSTEM_API_REE_H__ + +/* Changable */ +#define LOG_HD_MAGIC_SIZE 4 +#define LOG_HD_GP_SIZE 1 +#define LOG_HD_LEVEL_SIZE 1 +#define LOG_HD_LABEL_SIZE 2 +#define LOG_HD_BODY_SIZE 3 +#define LOG_HD_PID_SIZE 4 + +/* Do Not Change */ +#define LOG_HD_MAGIC_POS 0 +#define LOG_HD_GP_POS ((LOG_HD_MAGIC_POS) + (LOG_HD_MAGIC_SIZE)) +#define LOG_HD_LEVEL_POS ((LOG_HD_GP_POS) + (LOG_HD_GP_SIZE)) +#define LOG_HD_LABEL_POS ((LOG_HD_LEVEL_POS) + (LOG_HD_LEVEL_SIZE)) +#define LOG_HD_BODY_POS ((LOG_HD_LABEL_POS) + (LOG_HD_LABEL_SIZE)) +#define LOG_HD_PID_POS ((LOG_HD_BODY_POS) + (LOG_HD_BODY_SIZE)) +#define LHDSIZE ((LOG_HD_PID_POS) + (LOG_HD_PID_SIZE)) +#define LOG_HD_MAGIC_VAL 0xAE18 +#define LOG_MAGIC "AE18" + +typedef struct { + uint32_t magic; + uint32_t log_gen_point; + uint32_t log_level; + uint32_t log_label_size; + uint32_t log_body_size; + uint32_t log_pid; +} log_header_type; + +enum { + NO_MAGIC = 0, + TRUNCATED_MAGIC, + COMPLETE_MAGIC, +}; + +#define MIN(a, b) ((a > b) ? b : a) + +static inline uint32_t hex2int(char ch) +{ + if (ch >= '0' && ch <= '9') + return (uint32_t) (ch - '0'); + else if (ch >= 'a' && ch <= 'f') + return (uint32_t) (ch - 'a' + 10); + else if (ch >= 'A' && ch <= 'F') + return (uint32_t) (ch - 'A' + 10); + else + return 0; +} + +static inline uint32_t get_log_gp(char *buffer) +{ /* 1 Byte */ + if (buffer == NULL) + return 0; + + return hex2int(buffer[0]); +} + +static inline uint32_t get_log_level(char *buffer) +{ /* 1 Byte */ + if (buffer == NULL) + return 0; + + return hex2int(buffer[0]); +} + +static inline uint32_t get_log_label_size(char *buffer) +{ /* 2 Byte */ + if (buffer == NULL) + return 0; + + return (hex2int(buffer[0]) << 4) + (hex2int(buffer[1])); +} + +static inline uint32_t get_log_body_size(char *buffer) +{ /* 3 Byte */ + if (buffer == NULL) + return 0; + + return (hex2int(buffer[0]) << 8) + + (hex2int(buffer[1]) << 4) + (hex2int(buffer[2])); +} + +static inline uint32_t get_log_pid(char *buffer) +{ + if (buffer == NULL) + return 0; + + return (hex2int(buffer[0]) << 12) + + (hex2int(buffer[1]) << 8) + + (hex2int(buffer[2]) << 4) + (hex2int(buffer[3])); +} + +static inline uint32_t get_log_header(char *buffer, log_header_type *header) +{ + int i = 0; + char temp[5] = LOG_MAGIC; + + if (buffer == NULL || header == NULL) + return 0; + + for (i = 0; i < 4; ++i) { + if (temp[i] != buffer[i]) + return 0; + } + header->log_gen_point = get_log_gp(buffer + LOG_HD_GP_POS); + header->log_level = get_log_level(buffer + LOG_HD_LEVEL_POS); + header->log_label_size = get_log_label_size(buffer + LOG_HD_LABEL_POS); + header->log_body_size = get_log_body_size(buffer + LOG_HD_BODY_POS); + header->log_pid = get_log_pid(buffer + LOG_HD_PID_POS); + return 1; +} + +static inline uint32_t get_check_magic(char *buffer) +{ + int i = 0; + char temp[5] = LOG_MAGIC; + + uint32_t ret = NO_MAGIC; + if (buffer == NULL) + return 0; + + for (i = 0; i < 4; ++i) { + if (temp[i] != buffer[i]) { + if (buffer[i] == 0) + ret = TRUNCATED_MAGIC; + break; + } else + ret = COMPLETE_MAGIC; + } + return ret; +} +#endif diff --git a/drivers/misc/artiktee/smc_interface.h b/drivers/misc/artiktee/smc_interface.h index f63bbbc6465..57ac9c75229 100644 --- a/drivers/misc/artiktee/smc_interface.h +++ b/drivers/misc/artiktee/smc_interface.h @@ -46,6 +46,10 @@ #define SMC_STD_REGISTER_PHYS_WSM 14 +#ifdef CONFIG_FETCH_TEE_INFO +#define SMC_STD_FETCH_TEE_INFO 16 +#endif /* !CONFIG_FETCH_TEE_INFO */ + /* TODO: this should be sent to PSCI */ #define SMC_PM_CPU_OFF 0 #define SMC_PM_SYSTEM_OFF 1 diff --git a/drivers/misc/artiktee/ss_core.c b/drivers/misc/artiktee/ss_core.c index e7794375f31..1e1ccf759d0 100755..100644 --- a/drivers/misc/artiktee/ss_core.c +++ b/drivers/misc/artiktee/ss_core.c @@ -40,6 +40,7 @@ #include "tzdev_smc.h" #include "sstransaction.h" +#include "tzlog_print.h" #ifndef CONFIG_SECOS_NO_SECURE_STORAGE diff --git a/drivers/misc/artiktee/ss_dev.c b/drivers/misc/artiktee/ss_dev.c index a12b18fea3d..d111ffd7527 100644 --- a/drivers/misc/artiktee/ss_dev.c +++ b/drivers/misc/artiktee/ss_dev.c @@ -36,7 +36,7 @@ #include "ss_rpmb.h" #include "ss_core.h" #include "ss_dev.h" -#include "tzdev_internal.h" +#include "tzlog_print.h" #ifndef CONFIG_SECOS_NO_SECURE_STORAGE @@ -96,6 +96,9 @@ static const struct file_operations storage_fops = { .release = storage_release, .mmap = storage_mmap, .unlocked_ioctl = storage_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = storage_ioctl, +#endif }; static struct miscdevice storage = { diff --git a/drivers/misc/artiktee/ss_file.c b/drivers/misc/artiktee/ss_file.c index 00d5134f3cc..4f1ecfad079 100755..100644 --- a/drivers/misc/artiktee/ss_file.c +++ b/drivers/misc/artiktee/ss_file.c @@ -25,7 +25,7 @@ #include <linux/fs.h> #include "ss_file.h" -#include "tzdev_internal.h" +#include "tzlog_print.h" #ifndef CONFIG_SECOS_NO_SECURE_STORAGE diff --git a/drivers/misc/artiktee/ss_rpmb.c b/drivers/misc/artiktee/ss_rpmb.c index 2928818b3bc..ce607bb8b43 100644 --- a/drivers/misc/artiktee/ss_rpmb.c +++ b/drivers/misc/artiktee/ss_rpmb.c @@ -32,7 +32,7 @@ #if defined(CONFIG_MMC) && (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) #include "ss_rpmb.h" -#include "tzdev_internal.h" +#include "tzlog_print.h" #define RPMB_DEVICE "mmcblk0rpmb" diff --git a/drivers/misc/artiktee/sstransaction.c b/drivers/misc/artiktee/sstransaction.c index d6c3fd8f2f0..31e3e2b0364 100644 --- a/drivers/misc/artiktee/sstransaction.c +++ b/drivers/misc/artiktee/sstransaction.c @@ -31,6 +31,9 @@ #include "sstransaction.h" #include "tzdev.h" #include "tzdev_internal.h" +#include "tzlog_print.h" + +/* If you update this, also update sstransaction.h in Secure Kernel */ #define SSTRANSACTION_CHANNEL_SSDEV 1 diff --git a/drivers/misc/artiktee/tzdev.h b/drivers/misc/artiktee/tzdev.h index 5f86e46c2a8..92bf555f010 100755..100644 --- a/drivers/misc/artiktee/tzdev.h +++ b/drivers/misc/artiktee/tzdev.h @@ -31,33 +31,49 @@ #define TZ_IOC_MAGIC 'c' -#define TZIO_SMC _IOWR(TZ_IOC_MAGIC, 102, struct tzio_message *) -#define TZIO_WAIT_EVT _IOR(TZ_IOC_MAGIC, 112, unsigned long *) +#define TZIO_SMC _IOWR(TZ_IOC_MAGIC, 102, struct tzio_message) #define TZIO_DBG_START _IOR(TZ_IOC_MAGIC, 113, unsigned long) -#define TZMEM_EXPORT_MEMORY _IOWR(TZ_IOC_MAGIC, 122, struct tzmem_region *) +#define TZMEM_EXPORT_MEMORY _IOWR(TZ_IOC_MAGIC, 122, struct tzmem_region) #define TZMEM_RELEASE_MEMORY _IOWR(TZ_IOC_MAGIC, 123, int) -#define TZMEM_CHECK_MEMORY _IOR(TZ_IOC_MAGIC, 124, struct tzmem_region *) +#define TZMEM_CHECK_MEMORY _IOR(TZ_IOC_MAGIC, 124, struct tzmem_region) struct tzio_message { __u32 type; __u32 endpoint; __u32 length; - int32_t context_id; - uint32_t timeout_seconds; - uint32_t boost_flag; - char payload[]; + __s32 context_id; + __u32 timeout_seconds; + __u32 boost_flag; + __u8 payload[]; }; struct tzmem_region { - pid_t pid; /* Memory region owner's PID (in) */ - const void *ptr; /* Memory region start (in) */ - size_t size; /* Memory region size (in) */ - int id; /* Memory region ID (out) */ - unsigned long tee_ctx_id; /* (in) */ - int writable; + __s32 pid; /* Memory region owner's PID (in) */ + const void *ptr; /* Memory region start (in) */ + __s32 size; /* Memory region size (in) */ + __s32 id; /* Memory region ID (out) */ + __u32 tee_ctx_id; /* (in) */ + __s32 writable; }; +#ifdef CONFIG_COMPAT + +#define TZMEM_COMPAT_EXPORT_MEMORY \ + _IOWR(TZ_IOC_MAGIC, 122, struct tzmem_region32) +#define TZMEM_COMPAT_CHECK_MEMORY \ + _IOR(TZ_IOC_MAGIC, 124, struct tzmem_region32) + +struct tzmem_region32 { + __s32 pid; /* Memory region owner's PID (in) */ + __u32 ptr; /* Memory region start (in) */ + __s32 size; /* Memory region size (in) */ + __s32 id; /* Memory region ID (out) */ + __u32 tee_ctx_id; /* (in) */ + __s32 writable; +}; +#endif + #ifdef __KERNEL__ typedef unsigned long tzdev_page_handle; @@ -66,19 +82,24 @@ tzdev_page_handle tzdev_alloc_watch_page(void); void *tzdev_get_virt_addr(tzdev_page_handle h); phys_addr_t tzdev_get_phys_addr(tzdev_page_handle h); void tzdev_free_watch_page(tzdev_page_handle pg); -int tzdev_scm_watch(unsigned long dev_id, unsigned long func_id, unsigned long param1, unsigned long param2, unsigned long param3); +int tzdev_scm_watch(unsigned long dev_id, unsigned long func_id, + unsigned long param1, + unsigned long param2, + unsigned long param3); -typedef void (*tzdev_notify_handler_t)(uint32_t target_id, const void *buffer, size_t data_size, void *user_data); +typedef void (*tzdev_notify_handler_t)(uint32_t target_id, + const void *buffer, size_t data_size, void *user_data); /* * * Register notification handler for commands send using scm_send_notification() * - * WARNING: Commands may be executed on any thread and any CPU ! Please keep the handler as - * short possible (for example only notify completion) and avoid waiting on resources. + * WARNING: Commands may be executed on any thread and any CPU ! + * Please keep the handler as short possible + * (for example only notify completion) and avoid waiting on resources. * - * WARNING 2: Do not send messages from notify handler to SecureOS. This will cause - * deadlock. + * WARNING 2: Do not send messages from notify handler to SecureOS. + * This will cause deadlock. * */ int tzdev_register_notify_handler(uint32_t target_id, tzdev_notify_handler_t handler, void *user_data); diff --git a/drivers/misc/artiktee/tzdev_init.h b/drivers/misc/artiktee/tzdev_init.h index 2da7317e563..ad863e6ede3 100644 --- a/drivers/misc/artiktee/tzdev_init.h +++ b/drivers/misc/artiktee/tzdev_init.h @@ -20,7 +20,6 @@ #define SOURCE_TZDEV_INIT_H_ void tzsys_init(void); -void tzlog_init(void); void tzmem_init(void); int init_storage(void); void tzio_link_init(void); diff --git a/drivers/misc/artiktee/tzdev_internal.h b/drivers/misc/artiktee/tzdev_internal.h index fde66031888..e83429df96f 100644 --- a/drivers/misc/artiktee/tzdev_internal.h +++ b/drivers/misc/artiktee/tzdev_internal.h @@ -56,36 +56,6 @@ struct scm_mux_link { #define WSM_FLAG_PERSIST 0x00000001 -#define TZLOG_ERROR 1 /* Error condition */ -#define TZLOG_WARNING 2 /* Warning condition */ -#define TZLOG_INFO 3 /* Informational */ -#define TZLOG_DEBUG 4 /* Debug-level message */ - -#define tzlog_print(lvl, fmt, ...) \ - do { \ - if (lvl <= tzlog_loglevel) { \ - switch (lvl) { \ - case TZLOG_ERROR: \ - printk(KERN_ERR "[TZDEV_ERR]%s:"fmt, __func__, ##__VA_ARGS__); \ - break; \ - case TZLOG_WARNING: \ - printk(KERN_WARNING "[TZDEV_WARN]%s:"fmt, __func__, ##__VA_ARGS__); \ - break; \ - case TZLOG_INFO: \ - printk(KERN_INFO "[TZDEV_INFO]%s:"fmt, __func__, ##__VA_ARGS__); \ - break; \ - case TZLOG_DEBUG: \ - printk(KERN_DEBUG "[TZDEV_DBG]%s:"fmt, __func__, ##__VA_ARGS__); \ - break; \ - default: \ - break; \ - } \ - } \ - } while (0) - -extern int tzlog_loglevel; - -void tzlog_notify(void); void tzsys_crash_check(void); struct secos_syspage { diff --git a/drivers/misc/artiktee/tzdev_main.c b/drivers/misc/artiktee/tzdev_main.c index 1034c63cce0..464d6ade47b 100644 --- a/drivers/misc/artiktee/tzdev_main.c +++ b/drivers/misc/artiktee/tzdev_main.c @@ -48,12 +48,17 @@ #include "tzdev_smc.h" #include "tzdev_plat.h" +#ifdef CONFIG_FETCH_TEE_INFO +#include "tzinfo.h" +#endif /* !CONFIG_FETCH_TEE_INFO */ +#include "tzlog_core.h" +#include "tzlog_print.h" + #define TZDEV_MAJOR_VERSION "007" #define TZDEV_MINOR_VERSION "0" -module_param(tzlog_loglevel, int, 0); -MODULE_PARM_DESC(tzlog_loglevel, - "Loglevel of tz driver (8 - debug, 7 - info, 6 - notice, 5 - warning, 4 - error, ...)"); +MODULE_PARM_DESC(default_tzdev_local_log_level, + "Loglevel of tz driver (7 - debug, 6 - info, 5 - notice, 4 - warning, 3 - error, ...)"); /*#define CONFIG_TZDEV_CPU_IDLE*/ #ifdef CONFIG_TZDEV_CPU_IDLE @@ -104,8 +109,6 @@ struct tzdevext_function { */ static struct tzdev_ipc_data tzdev_ipc; -int tzlog_loglevel = TZLOG_INFO; - static DEFINE_SPINLOCK(tzio_context_slock); static DEFINE_IDR(tzio_context_idr); static LIST_HEAD(tzio_context_delete_q); @@ -820,8 +823,8 @@ int tzio_message_wait(struct tzio_message *__user msg, put_user(0, &msg->context_id); if (context->payload_size) { - if (copy_to_user - (msg->payload, context->payload, context->payload_size)) { + if (copy_to_user( + msg->payload, context->payload, context->payload_size)) { tzlog_print(TZLOG_ERROR, "Can't copy data back to userspace\n"); ret = -EFAULT; @@ -1409,6 +1412,9 @@ static const struct file_operations tzdev_fops = { .open = tzio_open, .release = tzio_release, .mmap = tzio_mmap, +#ifdef CONFIG_COMPAT + .compat_ioctl = tzio_ioctl, +#endif .unlocked_ioctl = tzio_ioctl, .poll = tzio_poll, .read = tzio_read @@ -1419,6 +1425,9 @@ static const struct file_operations tzlog_fops = { .open = tzlog_open, .read = tzlog_read, .write = tzlog_write, +#ifdef CONFIG_COMPAT + .compat_ioctl = tzlog_ioctl, +#endif .unlocked_ioctl = tzlog_ioctl, .release = tzlog_release, }; @@ -1483,7 +1492,8 @@ static ssize_t tzdev_store(struct kobject *kobj, struct kobj_attribute *attr, static ssize_t tzlog_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { - return snprintf(buf, 256, "current loglevel = %d\n", tzlog_loglevel); + return snprintf(buf, 256, "current loglevel = %d\n", + default_tzdev_local_log_level); } static ssize_t tzlog_store(struct kobject *kobj, struct kobj_attribute *attr, @@ -1492,10 +1502,9 @@ static ssize_t tzlog_store(struct kobject *kobj, struct kobj_attribute *attr, int var; sscanf(buf, "%d", &var); - tzlog_print(TZLOG_DEBUG, "Change Loglevel = %d\n", var); - if (var >= TZLOG_ERROR && var <= TZLOG_DEBUG) { - tzlog_loglevel = var; - } + tzlog_print(K_DEBUG, "Change Loglevel = %d\n", var); + if (var >= K_EMERG && var <= K_DEBUG) + default_tzdev_local_log_level = var; return count; } @@ -1506,6 +1515,23 @@ static ssize_t tzmem_show(struct kobject *kobj, struct kobj_attribute *attr, return snprintf(buf, 256, "TZMEM Show Test\n"); } +#ifdef CONFIG_FETCH_TEE_INFO +static ssize_t tzinfo_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +{ + int ret; + char *info; + + ret = tzinfo_fetch_info(&info); + + if (ret >= PAGE_SIZE) + tzlog_print(TZLOG_WARNING, + "Extracted TEE information is suppressed"); + + return snprintf(buf, PAGE_SIZE, "%s\n", info); +} +#endif /* !CONFIG_FETCH_TEE_INFO */ + static ssize_t tzmem_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) { @@ -1549,6 +1575,11 @@ __ATTR(tzlog, 0660, tzlog_show, tzlog_store); static struct kobj_attribute tzmem_attr = __ATTR(tzmem, 0660, tzmem_show, tzmem_store); +#ifdef CONFIG_FETCH_TEE_INFO +static struct kobj_attribute tzinfo_attr = +__ATTR(tzinfo, 0440, tzinfo_show, NULL); +#endif /* !CONFIG_FETCH_TEE_INFO */ + #ifndef CONFIG_PSCI static struct kobj_attribute tzpm_attr = __ATTR(tzpm, 0660, tzpm_show, tzpm_store); @@ -1558,6 +1589,9 @@ static struct attribute *tzdev_attrs[] = { &tzdev_attr.attr, &tzlog_attr.attr, &tzmem_attr.attr, +#ifdef CONFIG_FETCH_TEE_INFO + &tzinfo_attr.attr, +#endif /* !CONFIG_FETCH_TEE_INFO */ #ifndef CONFIG_PSCI &tzpm_attr.attr, #endif /* !CONFIG_PSCI */ @@ -1698,6 +1732,15 @@ static int __init init_tzdev(void) init_storage(); #endif +#ifdef CONFIG_FETCH_TEE_INFO + rc = tzinfo_init(); + if (rc != 0) { + sysfs_remove_file(tzdev_kobj, &tzinfo_attr.attr); + + tzlog_print(TZLOG_WARNING, "Failed to register tzinfo node\n"); + } +#endif + sstransaction_init(); for_each_possible_cpu(cpu) { diff --git a/drivers/misc/artiktee/tzdev_plat.c b/drivers/misc/artiktee/tzdev_plat.c index c39d67dd8ec..f8f4958794c 100644 --- a/drivers/misc/artiktee/tzdev_plat.c +++ b/drivers/misc/artiktee/tzdev_plat.c @@ -35,9 +35,8 @@ int plat_preprocess(void) { int ret = 0; - if (pm_qos_request_active(&min_cpu_qos)) { + if (pm_qos_request_active(&min_cpu_qos)) pm_qos_update_request(&min_cpu_qos, 1000000); - } return ret; } @@ -46,9 +45,8 @@ int plat_postprocess(void) { int ret = 0; - if (pm_qos_request_active(&min_cpu_qos)) { + if (pm_qos_request_active(&min_cpu_qos)) pm_qos_update_request(&min_cpu_qos, -1); - } return ret; } diff --git a/drivers/misc/artiktee/tzdev_smc.c b/drivers/misc/artiktee/tzdev_smc.c index c1eba10c872..d4a6492e99a 100644 --- a/drivers/misc/artiktee/tzdev_smc.c +++ b/drivers/misc/artiktee/tzdev_smc.c @@ -23,6 +23,7 @@ #include "tzdev_internal.h" #include "tzdev_smc.h" #include "tzpage.h" +#include "tzlog_print.h" static inline void __do_call_smc_internal(struct monitor_arguments *args, struct monitor_result *result) @@ -287,6 +288,27 @@ int scm_register_phys_wsm(phys_addr_t arg_pfn) return res.res[0]; } +#ifdef CONFIG_FETCH_TEE_INFO +int scm_fetch_tzinfo(int cmd, int arg) +{ + struct monitor_arguments args = { 0, }; + struct monitor_result res = { {0,} }; + + args.function_id = + SMC_32CALL | SMC_STANDARD_CALL | SMC_ENTITY_SECUREOS | + SMC_STD_FETCH_TEE_INFO; + + args.arg[0] = cmd; + args.arg[1] = arg; + args.arg[2] = 0; + args.arg[3] = 0; + + __do_call_smc_internal(&args, &res); + + return res.res[0]; +} +#endif /* !CONFIG_FETCH_TEE_INFO */ + #ifndef CONFIG_PSCI int scm_cpu_suspend(void) { diff --git a/drivers/misc/artiktee/tzdev_smc.h b/drivers/misc/artiktee/tzdev_smc.h index e6a0ed90b7f..26625564172 100644 --- a/drivers/misc/artiktee/tzdev_smc.h +++ b/drivers/misc/artiktee/tzdev_smc.h @@ -94,6 +94,10 @@ int scm_watch(unsigned long devfn, unsigned long a0, unsigned long a1, unsigned long a2); int scm_register_phys_wsm(phys_addr_t arg_pfn); +#ifdef CONFIG_FETCH_TEE_INFO +int scm_fetch_tzinfo(int cmd, int arg); +#endif /* !CONFIG_FETCH_TEE_INFO */ + #ifndef CONFIG_PSCI int scm_cpu_suspend(void); int scm_cpu_resume(void); diff --git a/drivers/misc/artiktee/tzinfo.c b/drivers/misc/artiktee/tzinfo.c new file mode 100644 index 00000000000..e7b749caa07 --- /dev/null +++ b/drivers/misc/artiktee/tzinfo.c @@ -0,0 +1,94 @@ +/********************************************************* + * Copyright (C) 2011 - 2016 Samsung Electronics Co., Ltd 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 version 2 and no 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 St, Fifth Floor, Boston, MA 02110-1301 USA + * + *********************************************************/ + +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/cpu.h> +#include <linux/vmalloc.h> + +#include "tzdev_smc.h" +#include "tzwsm.h" +#include "tzdev_internal.h" +#include "log_level_ree.h" +#include "tzlog_print.h" + +#define TZINFO_CMD_REGISTER 0 +#define TZINFO_CMD_FETCH 1 + +static char *tee_info_data; +static const char *info_msg = "Not Supported"; + +int tzinfo_fetch_info(char **buf) +{ + int rc; + + if (buf == NULL) + return 0; + + rc = scm_fetch_tzinfo(TZINFO_CMD_FETCH, 0); + + *buf = tee_info_data; + if (rc < 0) + return sizeof(info_msg); + + return rc; +} + +int tzinfo_init(void) +{ + void *tzinfo_page; + int tzinfo_wsm; + int rc; + + /* Single page for tz_info */ + tzinfo_page = vmalloc(PAGE_SIZE); + if (tzinfo_page == NULL) { + tzlog_print(K_ERR, + "Failed to allocate memory for tzinfo\n"); + tee_info_data = (char *)info_msg; + return -ENOMEM; + } + + tee_info_data = (char *)tzinfo_page; + + memset(tee_info_data, 0, PAGE_SIZE); + + tzinfo_wsm = + tzwsm_register_kernel_memory(tzinfo_page, PAGE_SIZE, + GFP_KERNEL); + + if (tzinfo_wsm < 0) { + tzlog_print(K_ERR, + "Failed to register WSM for tzinfo\n"); + vfree(tzinfo_page); + tee_info_data = (char *)info_msg; + return -EFAULT; + } + + rc = scm_fetch_tzinfo(TZINFO_CMD_REGISTER, tzinfo_wsm); + if (rc < 0) { + tzlog_print(K_WARNING, + "Failed to register tzinfo\n"); + tzwsm_unregister_kernel_memory(tzinfo_wsm); + vfree(tzinfo_page); + tee_info_data = (char *)info_msg; + return -EFAULT; + } + + return 0; +} diff --git a/drivers/misc/artiktee/tzinfo.h b/drivers/misc/artiktee/tzinfo.h new file mode 100644 index 00000000000..cf0cef6d9f9 --- /dev/null +++ b/drivers/misc/artiktee/tzinfo.h @@ -0,0 +1,25 @@ +/********************************************************* + * Copyright (C) 2011 - 2016 Samsung Electronics Co., Ltd 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 version 2 and no 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 St, Fifth Floor, Boston, MA 02110-1301 USA + * + *********************************************************/ + +#ifndef SOURCE_TZDEV_TZINFO_H_ +#define SOURCE_TZDEV_TZINFO_H_ + +int tzinfo_init(void); +int tzinfo_fetch_info(char **buf); + +#endif /* SOURCE_TZDEV_TZINFO_H_ */ diff --git a/drivers/misc/artiktee/tzlinkmgr.c b/drivers/misc/artiktee/tzlinkmgr.c index 1efc05fbfe9..4cdb4aeeff6 100644 --- a/drivers/misc/artiktee/tzlinkmgr.c +++ b/drivers/misc/artiktee/tzlinkmgr.c @@ -22,6 +22,7 @@ #include "tzdev_internal.h" #include "tzpage.h" #include "tzdev_smc.h" +#include "tzlog_print.h" static DEFINE_SPINLOCK(tzio_free_lock); static LIST_HEAD(tzio_free_links); diff --git a/drivers/misc/artiktee/tzlog_core.c b/drivers/misc/artiktee/tzlog_core.c new file mode 100644 index 00000000000..2f3524df5ab --- /dev/null +++ b/drivers/misc/artiktee/tzlog_core.c @@ -0,0 +1,300 @@ +/********************************************************* + * Copyright (C) 2011 - 2016 Samsung Electronics Co., Ltd 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 version 2 and no 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 St, Fifth Floor, Boston, MA 02110-1301 USA + * + *********************************************************/ + +#include <linux/kthread.h> +#include <linux/freezer.h> +#include <linux/semaphore.h> +#include <linux/miscdevice.h> +#include <linux/fs.h> +#include <linux/wait.h> +#include <linux/poll.h> +#include <linux/namei.h> +#include <linux/path.h> +#include <linux/vmalloc.h> + +#include <asm/barrier.h> + +#include "circular_buffer.h" +#include "tzdev.h" +#include "tzdev_internal.h" +#include "tzpage.h" +#include "tzdev_smc.h" +#include "ss_file.h" + +#include "tzlog_process.h" +#include "tzlog_core.h" + +#ifdef CONFIG_INSTANCE_DEBUG +#include <linux/vmalloc.h> +/* it should be change to removing Duplicated code(tzsys.c ) */ +#define ERROR_PARENT_DIR_PATH "/opt/usr/apps/" +#define ERROR_DIR_NAME_DEPTH1 "save_error_log" +#define ERROR_DIR_NAME_DEPTH2 "error_log" +#define ERROR_LOG_PARENT_DIR_PATH "/opt/usr/apps/save_error_log/error_log/" +#define ERROR_LOG_DIR_NAME "secureos_log" +#define SYSLOG_ENCRYPT_MEM_SIZE (PAGE_SIZE * 8) +#endif +#define TZLOG_TYPE_PURE 1 +#define TZLOG_TYPE_ENCRYPT 2 + +#define TZLOG_PAGE_ORDER 0 + +extern void tzdev_notify_worker(void); + +static s_tzlog_data log_data = { + .ring = NULL, + .sem = __SEMAPHORE_INITIALIZER(log_data.sem, 0), + .lock = __MUTEX_INITIALIZER(log_data.lock), +}; + +#ifdef CONFIG_INSTANCE_DEBUG +static s_tzlog_data encrypt_log_data = { + .ring = NULL, +}; +#endif + +/* it should be change to support creating two depth of folder */ +int tzlog_create_dir(char *parnet_dir_name, char *dir_name) +{ + char path[128]; + struct dentry *dentry; + struct path p; + int err; + struct inode *inode; + + snprintf(path, sizeof(path), "%s%s", parnet_dir_name, dir_name); + + dentry = kern_path_create(AT_FDCWD, path, &p, LOOKUP_DIRECTORY); + + if (IS_ERR(dentry)) + return PTR_ERR(dentry); + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)) + inode = p.dentry->d_inode; +#else + inode = d_inode(p.dentry); +#endif + + err = vfs_mkdir(inode, dentry, S_IRWXU | S_IRWXG | S_IRWXO); + + done_path_create(&p, dentry); + return err; +} + +#ifdef CONFIG_INSTANCE_DEBUG +int tzlog_output_do_dump(int is_kernel); +static int tzlog_output_to_error_log(char *data, int data_size, + int is_kernel_error) +{ + char path[128]; + unsigned long long T; + struct timeval now; + tzlog_create_dir(ERROR_PARENT_DIR_PATH, ERROR_DIR_NAME_DEPTH1); + snprintf(path, sizeof(path), "%s%s/", ERROR_PARENT_DIR_PATH, + ERROR_DIR_NAME_DEPTH1); + tzlog_create_dir(path, ERROR_DIR_NAME_DEPTH2); + tzlog_create_dir(ERROR_LOG_PARENT_DIR_PATH, ERROR_LOG_DIR_NAME); + + do_gettimeofday(&now); + T = (now.tv_sec * 1000ULL) + (now.tv_usec / 1000LL); + snprintf(path, sizeof(path), "%s%s/minilog_%s_%lld.log", + ERROR_LOG_PARENT_DIR_PATH, ERROR_LOG_DIR_NAME, + ((is_kernel_error == 1) ? "os" : "app"), T); + + return ss_file_create_object(path, data, data_size); +} +#endif + +static int tzlog_worker(void *arg) +{ +#ifdef CONFIG_INSTANCE_DEBUG + int is_need_enc = 0; + int enc_ret = 0; + int complete = 0; + int body_size = 0; + char *data = NULL; + + int header_offset = 0; + int complete_offset = sizeof(int); + int body_offset = sizeof(int) * 2; + + data = (char *)encrypt_log_data.ring; + *(int *)((char *)data + complete_offset) = 0; + *(int *)((char *)data + header_offset) = 0; + is_need_enc = 1; +#endif + + tzlog_print(TZLOG_DEBUG, "Start tzlog worker thread\n"); + + mutex_lock(&log_data.lock); + while (!kthread_should_stop()) { + int ret; + + do { + ret = scm_syslog(log_data.log_wsm_id, TZLOG_TYPE_PURE); + + if (chimera_ring_buffer_readable(log_data.ring)) { + /* + * We may need to process tasks + * after reading back all + */ + tzdev_notify_worker(); + /* Drain syslog data further */ + tzlog_transfer_to_tzdaemon(&log_data, + PAGE_SIZE << + TZLOG_PAGE_ORDER); + tzlog_transfer_to_local(&log_data, + PAGE_SIZE << + TZLOG_PAGE_ORDER); + chimera_ring_buffer_clear(log_data.ring); + } +#ifdef CONFIG_INSTANCE_DEBUG + if (is_need_enc == 1) { + *(int *)((char *)data + complete_offset) = 0; + *(int *)((char *)data + header_offset) = 0; + + tzlog_print(TZLOG_DEBUG, + "tzlog before scm_syslog(encrypt)\n"); + + enc_ret = + scm_syslog(encrypt_log_data.log_wsm_id, + TZLOG_TYPE_ENCRYPT); + + body_size = + *(int *)((char *)data + header_offset); + complete = + *(int *)((char *)data + complete_offset); + + tzlog_print(TZLOG_DEBUG, + "tzlog returned %d size = %d(encrypt)\n", + complete, body_size); + + if (enc_ret == -1) + is_need_enc = 0; + else { + if (complete & 0x01 && body_size != 0) { + tzlog_print(TZLOG_DEBUG, + "tzlog process start(encrypt)\n"); + + tzdev_notify_worker(); + tzlog_output_to_error_log( + ((char *)data+body_offset), + body_size, + ((complete & 0x10) ? 1 : 0)); + + if (!(complete & 0x10)) + tzlog_output_do_dump(0); + + tzlog_print(TZLOG_DEBUG, + "tzlog process complete(encrypt)\n"); + } else { + tzlog_print(TZLOG_DEBUG, + "There's no data in tzlog yet(encrypt)\n"); + } + } + } +#endif + } while (ret > 0); + + mutex_unlock(&log_data.lock); + ret = down_timeout(&log_data.sem, HZ * 2); + + (void)ret; + + /* Ignore other semaphore down calls */ + while (down_trylock(&log_data.sem) == 0) + ; /* NULL */ + + mutex_lock(&log_data.lock); + } + + mutex_unlock(&log_data.lock); + return 0; +} + +void tzlog_notify(void) +{ + tz_syspage->tzlog_data_avail = 0; + up(&log_data.sem); +} + +void __init tzlog_init(void) +{ + int ret; + +#ifdef CONFIG_INSTANCE_DEBUG + void *large_page = vmalloc(SYSLOG_ENCRYPT_MEM_SIZE); +#endif + + ret = init_log_processing_resources(); + if (ret < 0) + panic("Can't register tzlog device (%d)\n", ret); + + log_data.log_page = + alloc_pages(GFP_KERNEL | __GFP_ZERO, TZLOG_PAGE_ORDER); + + if (!log_data.log_page) + panic("Can't allocate tzlog page\n"); + + log_data.ring = + chimera_create_ring_buffer_etc(page_address(log_data.log_page), + PAGE_SIZE << TZLOG_PAGE_ORDER, 0, + GFP_KERNEL); + + tzlog_print(TZLOG_DEBUG, "TZLOG ring at %p\n", log_data.ring); + if (log_data.ring != NULL) + tzlog_print(TZLOG_DEBUG, "ring size %d\n", log_data.ring->size); + + log_data.log_wsm_id = + tzswm_register_tzdev_memory(0, &log_data.log_page, + 1U << TZLOG_PAGE_ORDER, GFP_KERNEL, 1); + + if (log_data.log_wsm_id < 0) + panic("Can't register log WSM\n"); + + tzlog_print(TZLOG_DEBUG, "Registered TZLOG WSM with id %d\n", + log_data.log_wsm_id); + +#ifdef CONFIG_INSTANCE_DEBUG + if (large_page == NULL) + panic("Can't allocate tzlog page(encrypt)\n"); + + encrypt_log_data.ring = large_page; + memset(large_page, 0, SYSLOG_ENCRYPT_MEM_SIZE); + + tzlog_print(TZLOG_DEBUG, "TZLOG ring at %p(encrypt)\n", + encrypt_log_data.ring); + tzlog_print(TZLOG_DEBUG, "ring size %d(encrypt)\n", + (int)SYSLOG_ENCRYPT_MEM_SIZE); + + encrypt_log_data.log_wsm_id = + tzwsm_register_kernel_memory(large_page, + SYSLOG_ENCRYPT_MEM_SIZE, GFP_KERNEL); + + if (encrypt_log_data.log_wsm_id < 0) + panic("Can't register log WSM\n"); + + tzlog_print(TZLOG_DEBUG, + "Registered TZLOG WSM with id %d(encrypt)\n", + encrypt_log_data.log_wsm_id); +#endif + log_data.task = kthread_run(tzlog_worker, NULL, "tzlogd"); + + if (IS_ERR(log_data.task)) + panic("Can't create tzlog worker\n"); +} diff --git a/drivers/misc/artiktee/tzlog_core.h b/drivers/misc/artiktee/tzlog_core.h new file mode 100644 index 00000000000..38e55d64eef --- /dev/null +++ b/drivers/misc/artiktee/tzlog_core.h @@ -0,0 +1,45 @@ +/********************************************************* + * Copyright (C) 2011 - 2016 Samsung Electronics Co., Ltd 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 version 2 and no 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 St, Fifth Floor, Boston, MA 02110-1301 USA + * + *********************************************************/ + +#include <linux/kthread.h> +#include <linux/freezer.h> +#include <linux/semaphore.h> +#include <linux/miscdevice.h> +#include <linux/fs.h> +#include <linux/wait.h> +#include <linux/poll.h> +#include <linux/namei.h> +#include <linux/dcache.h> +#include <linux/path.h> + +#ifndef __TZLOG_CORE_H__ +#define __TZLOG_CORE_H__ + +typedef struct tzlog_data { + int log_wsm_id; + struct chimera_ring_buffer *ring; + struct semaphore sem; + struct task_struct *task; + struct mutex lock; + struct page *log_page; +} s_tzlog_data; + +void tzlog_notify(void); +void tzlog_init(void); + +#endif diff --git a/drivers/misc/artiktee/tzlog_print.c b/drivers/misc/artiktee/tzlog_print.c new file mode 100644 index 00000000000..155b0eb9d6d --- /dev/null +++ b/drivers/misc/artiktee/tzlog_print.c @@ -0,0 +1,224 @@ +/********************************************************* + * Copyright (C) 2011 - 2016 Samsung Electronics Co., Ltd 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 version 2 and no 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 St, Fifth Floor, Boston, MA 02110-1301 USA + * + *********************************************************/ + +#include <linux/kernel.h> +#include <linux/vmalloc.h> + +#include "tzlog_print.h" + +kernel_log_level default_tzdev_tee_log_level = TZDEV_TEE_LOG_LEVEL; +kernel_log_level default_tzdev_local_log_level = TZDEV_LOCAL_LOG_LEVEL; + +#define DEFAULT_MEM_SIZE PAGE_SIZE +/* #define ENABLE_LOG_DEBUG */ + +static char buf_for_local[DEFAULT_MEM_SIZE]; +static char buf_for_tee[DEFAULT_MEM_SIZE]; + +static int tzlog_print_common(log_header_info header_info, + kernel_log_level level, + const char *label, + int is_ree, + va_list *ap, + const char *fmt) +{ + int write_len = 0; + int buf_size = 0; + char *printk_buf = NULL; + if (is_ree == 1) { + printk_buf = buf_for_local; + buf_size = sizeof(buf_for_local); + } else { + printk_buf = buf_for_tee; + buf_size = sizeof(buf_for_tee); + } + + if (is_ree == 1) { + switch (level) { + case K_DEBUG: + write_len = snprintf(printk_buf, + buf_size, "[REE][TZDEV][DEBUG]"); + break; + case K_INFO: + write_len = snprintf(printk_buf, + buf_size, "[REE][TZDEV][INFO]"); + break; + case K_NOTICE: + write_len = snprintf(printk_buf, + buf_size, "[REE][TZDEV][NOTI]"); + break; + case K_WARNING: + write_len = snprintf(printk_buf, + buf_size, "[REE][TZDEV][WARN]"); + break; + case K_ERR: + write_len = snprintf(printk_buf, + buf_size, "[REE][TZDEV][ERR]"); + break; + case K_CRIT: + write_len = snprintf(printk_buf, + buf_size, "[REE][TZDEV][CRIT]"); + break; + case K_ALERT: + write_len = snprintf(printk_buf, + buf_size, "[REE][TZDEV][ALERT]"); + break; + case K_EMERG: + write_len = snprintf(printk_buf, + buf_size, "[REE][TZDEV][EMERG]"); + break; + default: + break; + } + } else { + switch (header_info) { + case SWD_USERMODE: + write_len = snprintf(printk_buf, + buf_size, "[TEE][TA]"); + break; + case SWD_KERNMODE: + write_len = snprintf(printk_buf, + buf_size, "[TEE][KERN]"); + break; + default: + write_len = snprintf(printk_buf, + buf_size, "[TEE]"); + break; + } + + switch (level) { + case K_DEBUG: + write_len += snprintf(printk_buf + write_len, + buf_size - 1 - write_len, "[DEBUG]"); + break; + case K_INFO: + write_len += snprintf(printk_buf + write_len, + buf_size - 1 - write_len, "[INFO]"); + break; + case K_NOTICE: + write_len += snprintf(printk_buf + write_len, + buf_size - 1 - write_len, "[NOTI]"); + break; + case K_WARNING: + write_len += snprintf(printk_buf + write_len, + buf_size - 1 - write_len, "[WARN]"); + break; + case K_ERR: + write_len += snprintf(printk_buf + write_len, + buf_size - 1 - write_len, "[ERR]"); + break; + case K_CRIT: + write_len += snprintf(printk_buf + write_len, + buf_size - 1 - write_len, "[CRIT]"); + break; + case K_ALERT: + write_len += snprintf(printk_buf + write_len, + buf_size - 1 - write_len, "[ALERT]"); + break; + case K_EMERG: + write_len += snprintf(printk_buf + write_len, + buf_size - 1 - write_len, "[EMERG]"); + break; + default: + break; + } + + if (label != NULL) + write_len += snprintf(printk_buf + write_len, + buf_size - 1 - write_len, "[%s]", + label); + } + + write_len += vsnprintf(printk_buf + write_len, + buf_size - 1 - write_len, fmt, *ap); + + if (write_len + 1 >= buf_size) /* buffer is not enough */ + pr_err("buffer is not enough(ree(%d) / cur : %d )\n", + is_ree, buf_size); + + switch (level) { + case K_DEBUG: + pr_debug("%s", printk_buf); + break; + case K_INFO: + pr_info("%s", printk_buf); + break; + case K_NOTICE: + pr_notice("%s", printk_buf); + break; + case K_WARNING: + pr_warn("%s", printk_buf); + break; + case K_ERR: + pr_err("%s", printk_buf); + break; + case K_CRIT: + pr_crit("%s", printk_buf); + break; + case K_ALERT: + pr_alert("%s", printk_buf); + break; + case K_EMERG: + pr_emerg("%s", printk_buf); + break; + default: + break; + } + return 0; +} + +/* + will be use bit flag for decreasing parameter count. + we can change log_header_info to use bit flag + */ +void tzlog_print_for_tee(log_header_info header_info, + kernel_log_level level, + const char *label, + const char *fmt, ...) +{ + int ret; + va_list ap; + if (!(default_tzdev_tee_log_level >= level)) + return; + + va_start(ap, fmt); + ret = tzlog_print_common(header_info, level, label, 0, &ap, fmt); + va_end(ap); + +#ifdef ENABLE_LOG_DEBUG + if (ret == -1) + pr_err("tzlog_print_common return err\n"); +#endif +} + +void tzlog_print(kernel_log_level level, const char *fmt, ...) +{ + int ret; + va_list ap; + if (!(default_tzdev_local_log_level >= level)) + return; + + va_start(ap, fmt); + ret = tzlog_print_common(0, level, NULL, 1, &ap, fmt); + va_end(ap); + +#ifdef ENABLE_LOG_DEBUG + if (ret == -1) + pr_err("tzlog_print_common return err\n"); +#endif +} diff --git a/drivers/misc/artiktee/tzlog_print.h b/drivers/misc/artiktee/tzlog_print.h new file mode 100644 index 00000000000..152ee5a3041 --- /dev/null +++ b/drivers/misc/artiktee/tzlog_print.h @@ -0,0 +1,32 @@ +/********************************************************* + * Copyright (C) 2011 - 2016 Samsung Electronics Co., Ltd 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 version 2 and no 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 St, Fifth Floor, Boston, MA 02110-1301 USA + * + *********************************************************/ + +#ifndef __TZLOG_PRINT_H__ +#define __TZLOG_PRINT_H__ + +#include "log_level_ree.h" + +extern kernel_log_level default_tzdev_local_log_level; /* OutPut */ + +void tzlog_print(kernel_log_level level, const char *fmt, ...); +void tzlog_print_for_tee(log_header_info header_info, + kernel_log_level level, + const char *label, + const char *fmt, ...); + +#endif diff --git a/drivers/misc/artiktee/tzlog_process.c b/drivers/misc/artiktee/tzlog_process.c new file mode 100644 index 00000000000..ee23bea5c70 --- /dev/null +++ b/drivers/misc/artiktee/tzlog_process.c @@ -0,0 +1,490 @@ +/********************************************************* + * Copyright (C) 2011 - 2016 Samsung Electronics Co., Ltd 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 version 2 and no 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 St, Fifth Floor, Boston, MA 02110-1301 USA + * + *********************************************************/ + +#include <linux/kthread.h> +#include <linux/freezer.h> +#include <linux/semaphore.h> +#include <linux/miscdevice.h> +#include <linux/fs.h> +#include <linux/wait.h> +#include <linux/poll.h> +#include <linux/namei.h> +#include <linux/dcache.h> +#include <linux/path.h> +#include <linux/vmalloc.h> + +#include "circular_buffer.h" +#include "log_level_ree.h" +#include "tzlog_process.h" +#include "tzlog_print.h" +#include "log_system_api_ext.h" + +/*#define ENABLE_LOG_DEBUG*/ + +#define TZLOG_LOCAL_BUFFERING_SIZE (PAGE_SIZE * 2) +#define TZLOG_TZDAEMON_BUFFERING_SIZE (PAGE_SIZE * 10) +#define TZLOG_COPY_TEMP_SIZE 1024 +#define TZLOG_LABEL_SIZE 64 + +static char buf_label[TZLOG_LABEL_SIZE]; + +/* Log For Tzdaemon */ +static ssize_t tzlog_read(struct file *filp, char __user *buffer, size_t size, + loff_t *off); +static unsigned int tzlog_poll(struct file *file, poll_table *wait); +static int tzlog_fasync(int fd, struct file *filp, int on); +static struct fasync_struct *fasync; + +typedef struct tzlog_process { + struct chimera_ring_buffer *ring; + /* Log For Tzdaemon */ + struct mutex ring_lock; + struct mutex read_lock; + wait_queue_head_t empty_wait; + wait_queue_head_t full_wait; +} s_tzlog_process; + +static s_tzlog_process log_data_for_local = { + .ring = NULL, +}; + +static s_tzlog_process log_data_for_tzdaemon = { + .ring = NULL, + .ring_lock = __MUTEX_INITIALIZER(log_data_for_tzdaemon.ring_lock), + /* Log For Tzdaemon */ + .read_lock = __MUTEX_INITIALIZER(log_data_for_tzdaemon.read_lock), + .empty_wait = + __WAIT_QUEUE_HEAD_INITIALIZER(log_data_for_tzdaemon.empty_wait), + .full_wait = + __WAIT_QUEUE_HEAD_INITIALIZER(log_data_for_tzdaemon.full_wait), +}; + +/* Log For Tzdaemon */ +static const struct file_operations tzlog_file_operations = { + .owner = THIS_MODULE, + .read = tzlog_read, + .poll = tzlog_poll, + .fasync = tzlog_fasync, + .llseek = noop_llseek +}; + +static struct miscdevice tzlog_device = { + .minor = MISC_DYNAMIC_MINOR, + .name = "tzlog", + .fops = &tzlog_file_operations, + .mode = 0400 +}; + +int init_log_processing_resources(void) +{ + int ret = -1; + void *buffering_memory_local = + (void *)vmalloc(TZLOG_LOCAL_BUFFERING_SIZE); + void *buffering_memory_tzdaemon = + (void *)vmalloc(TZLOG_TZDAEMON_BUFFERING_SIZE); + + if (buffering_memory_tzdaemon) { + log_data_for_tzdaemon.ring = + chimera_create_ring_buffer_etc(buffering_memory_tzdaemon, + TZLOG_TZDAEMON_BUFFERING_SIZE, + 0, GFP_KERNEL); + if (log_data_for_tzdaemon.ring != NULL) + chimera_ring_buffer_clear(log_data_for_tzdaemon.ring); + } else + goto exit_processing_resources; + + if (buffering_memory_local) { + log_data_for_local.ring = + chimera_create_ring_buffer_etc(buffering_memory_local, + TZLOG_LOCAL_BUFFERING_SIZE, + 0, GFP_KERNEL); + if (log_data_for_local.ring != NULL) + chimera_ring_buffer_clear(log_data_for_local.ring); + } else + goto exit_processing_resources; + + ret = misc_register(&tzlog_device); + return ret; + +exit_processing_resources: + if (buffering_memory_local != NULL) + vfree(buffering_memory_local); + + if (buffering_memory_tzdaemon != NULL) + vfree(buffering_memory_tzdaemon); + + return ret; +} + +static ssize_t tzlog_read(struct file *filp, char __user *buffer, size_t size, + loff_t *off) +{ +#ifdef ENABLE_LOG_DEBUG + tzlog_print(K_INFO, "tzlog_read called\n"); +#endif + int error = mutex_lock_interruptible(&log_data_for_tzdaemon.read_lock); + ssize_t result; + + if (error < 0) + return error; + +#ifdef ENABLE_LOG_DEBUG + tzlog_print(K_INFO, "TZLOG read %d size = %d, in = %d, out = %d\n", + (int)size, log_data_for_tzdaemon.ring->size, + log_data_for_tzdaemon.ring->in, + log_data_for_tzdaemon.ring->first); +#endif + + result = + chimera_ring_buffer_user_read(log_data_for_tzdaemon.ring, + (uint8_t *) buffer, size, + TZLOG_TZDAEMON_BUFFERING_SIZE); + +#ifdef ENABLE_LOG_DEBUG + tzlog_print(K_INFO, + "TZLOG read result %d size = %d, in = %d, out = %d\n", + (int)result, log_data_for_tzdaemon.ring->size, + log_data_for_tzdaemon.ring->in, + log_data_for_tzdaemon.ring->first); +#endif + + if (result > 0) + wake_up(&log_data_for_tzdaemon.full_wait); + + mutex_unlock(&log_data_for_tzdaemon.read_lock); + + return result; +} + +static unsigned int tzlog_poll(struct file *file, poll_table *wait) +{ + unsigned int mask; +#ifdef ENABLE_LOG_DEBUG + tzlog_print(K_INFO, "tzlog_poll call\n"); +#endif + poll_wait(file, &log_data_for_tzdaemon.empty_wait, wait); +#ifdef ENABLE_LOG_DEBUG + tzlog_print(K_INFO, "tzlog_poll call end\n"); +#endif + mask = 0; + + if (chimera_ring_buffer_readable(log_data_for_tzdaemon.ring)) + mask |= POLLIN | POLLRDNORM; + + return mask; +} + +static int tzlog_fasync(int fd, struct file *filp, int on) +{ + return fasync_helper(fd, filp, on, &fasync); +} + +static int tzlog_copy_buffer(s_tzlog_process *dst_data, int dst_buffer_size, + s_tzlog_data *src_data, int src_buffer_size) +{ + struct iovec iov[2]; + int i; + size_t n_written = 0; + int nvec = + chimera_ring_buffer_get_vecs(src_data->ring, iov, src_buffer_size); + for (i = 0; i < nvec; ++i) { + ssize_t written = chimera_ring_buffer_write(dst_data->ring, + (const uint8_t *) + iov[i].iov_base, + iov[i].iov_len, + dst_buffer_size); + + if (written < 0) { + /* Occur error */ + break; + } + + if (written == 0) { + /* Can not write All Log */ + break; + } + n_written += written; + } + return n_written; +} + +void tzlog_transfer_to_tzdaemon(s_tzlog_data *src_data, int src_buffer_size) +{ + size_t ret_write = 0; + size_t src_size = 0; + size_t origin_size = 0; + size_t avail = 0; + + src_size = chimera_ring_buffer_readable(src_data->ring); + mutex_lock(&log_data_for_tzdaemon.ring_lock); + + /* If we can not completely write, we should be wait for tzdaemon */ + avail = chimera_ring_buffer_writable(log_data_for_tzdaemon.ring); + if (avail < src_size) { + wake_up_interruptible(&log_data_for_tzdaemon.empty_wait); + kill_fasync(&fasync, SIGIO, POLL_IN); + + /* Wait for tzdaemon's read */ + { + DEFINE_WAIT(__wait); + tzlog_print(K_INFO, + "tzdaemon log full. wait for drain(src:%d,avail:%d)\n", + src_size, avail); + + while (chimera_ring_buffer_writable + (log_data_for_tzdaemon.ring) < src_size) { + prepare_to_wait(&log_data_for_tzdaemon. + full_wait, &__wait, + TASK_UNINTERRUPTIBLE); + mutex_unlock(&log_data_for_tzdaemon.ring_lock); + schedule(); + mutex_lock(&log_data_for_tzdaemon.ring_lock); + } + finish_wait(&log_data_for_tzdaemon.full_wait, &__wait); + } + } + + /* Copy to tzdaemon-ring-buffer from src_data */ + origin_size = chimera_ring_buffer_readable(log_data_for_tzdaemon.ring); + ret_write = + tzlog_copy_buffer(&log_data_for_tzdaemon, + TZLOG_TZDAEMON_BUFFERING_SIZE, src_data, + src_buffer_size); + if (src_size != ret_write || ret_write == 0) { + int stored_size = + chimera_ring_buffer_readable(log_data_for_tzdaemon.ring); + if (stored_size - origin_size != src_size) { + tzlog_print(K_ERR, + "log can loss for tzdaemon(src size : %d, written size: %d stored size : %d)\n", + src_size, ret_write, stored_size); + } + } + mutex_unlock(&log_data_for_tzdaemon.ring_lock); + + wake_up_interruptible(&log_data_for_tzdaemon.empty_wait); + kill_fasync(&fasync, SIGIO, POLL_IN); +} + +static void tzlog_print_with_header(log_header_type *header, int body_size) +{ + char *read_body = NULL; + char *temp_read_body = NULL; + static char keep_read_body[TZLOG_COPY_TEMP_SIZE] = { 0, }; + memset(keep_read_body, 0, sizeof(keep_read_body)); + + if (sizeof(keep_read_body) - 1 > body_size) { + /* If the buffer is sufficient */ + read_body = keep_read_body; + } else { + /* If the buffer is not sufficient */ + temp_read_body = (char *)vmalloc(body_size + 1); + if (temp_read_body != NULL) { + memset(temp_read_body, 0, body_size + 1); + read_body = temp_read_body; + } + } + + /* output log */ + if (read_body != NULL) { + chimera_ring_buffer_read(log_data_for_local.ring, + (uint8_t *) read_body, body_size, + TZLOG_LOCAL_BUFFERING_SIZE); + if (header != NULL) { + memset(buf_label, 0, sizeof(buf_label)); + if (header->log_label_size <= sizeof(buf_label)) { + memcpy(buf_label, read_body, + header->log_label_size); + } + tzlog_print_for_tee(header->log_gen_point, + header->log_level, buf_label, + (read_body + + header->log_label_size)); + } else + tzlog_print_for_tee(0, NO_HEADER_LOG_LEVEL, NULL, + read_body); + } + + if (temp_read_body != NULL) { + vfree(temp_read_body); + temp_read_body = NULL; + } +} + +void tzlog_transfer_to_local(s_tzlog_data *src_data, int src_buffer_size) +{ + size_t ret_write = 0; + size_t src_size = 0; + size_t ring_data_origin_size = 0; + int ring_data_remain_size = 0; + int is_need_continue = 0; + + ring_data_origin_size = + chimera_ring_buffer_readable(log_data_for_local.ring); + src_size = chimera_ring_buffer_readable(src_data->ring); +#ifdef ENABLE_LOG_DEBUG + tzlog_print(K_INFO, "tzdev receive log(%d) ori(%d)\n", src_size, + ring_data_origin_size); + if (ring_data_origin_size > 0) { + char temp_buf[1024] = { 0, }; + chimera_ring_buffer_peek(log_data_for_local.ring, 0, temp_buf, + sizeof(temp_buf), + TZLOG_LOCAL_BUFFERING_SIZE); + tzlog_print(K_INFO, "tzdev ori log(%s)\n", temp_buf); + } +#endif + ret_write = + tzlog_copy_buffer(&log_data_for_local, TZLOG_LOCAL_BUFFERING_SIZE, + src_data, src_buffer_size); + if (src_size != ret_write || ret_write == 0) { + int stored_size = + chimera_ring_buffer_readable(log_data_for_local.ring); + if (stored_size - ring_data_origin_size != src_size) { + tzlog_print(K_INFO, + "log can loss for tzdev(src size : %d, written size: %d stored size : %d)\n", + src_size, ret_write, stored_size); + } + } + +continue_read: + + ring_data_remain_size = + chimera_ring_buffer_readable(log_data_for_local.ring); + if (ring_data_remain_size >= LHDSIZE) { + log_header_type log_header; + int head_size = LHDSIZE; + int body_size = 0; + char header[LHDSIZE + 1] = { 0, }; + chimera_ring_buffer_peek(log_data_for_local.ring, 0, header, + LHDSIZE, TZLOG_LOCAL_BUFFERING_SIZE); + + if (get_log_header(header, &log_header) != 1) { + int is_find_header = 0; + int find_cnt = 0; + int find_max_cnt = ring_data_remain_size - LHDSIZE + 1; +#ifdef ENABLE_LOG_DEBUG + /* Magic Check */ + tzlog_print(K_INFO, "Magic compare (%c %c %c %c)\n", + header[0], header[1], header[2], header[3]); +#endif + +#ifdef ENABLE_LOG_DEBUG + tzlog_print(K_INFO, "Header is not compete\n"); +#endif + for (; find_cnt < find_max_cnt; find_cnt++) { + chimera_ring_buffer_peek( + log_data_for_local.ring, + find_cnt, + header, + LHDSIZE, + TZLOG_LOCAL_BUFFERING_SIZE); + if (get_log_header(header, &log_header) == 1) { +#ifdef ENABLE_LOG_DEBUG + tzlog_print(K_INFO, "Header find\n"); +#endif + is_find_header = 1; + break; + } + } + + if (is_find_header == 1) { +#ifdef ENABLE_LOG_DEBUG + tzlog_print(K_INFO, + "print msg(without magic-case-1)\n"); +#endif + tzlog_print_with_header(NULL, find_cnt); + goto continue_read; + } else { +#ifdef ENABLE_LOG_DEBUG + tzlog_print(K_INFO, + "print msg(without magic-case-2)\n"); +#endif + tzlog_print_with_header(NULL, + ring_data_remain_size); + } + } else { +#ifdef ENABLE_LOG_DEBUG + if (log_header.log_body_size == 0 + || log_header.log_label_size == 0) { + tzlog_print(K_INFO, "Header is compete(%s)\n", + header); + tzlog_print(K_INFO, + "gp is %d / body size is %d / label size is %d / level %d / pid %d\n", + log_header.log_gen_point, + log_header.log_body_size, + log_header.log_label_size, + log_header.log_level, + log_header.log_pid); + } +#endif + is_need_continue = 1; + /* + * if header ok & body size is enough, + * will be processing + */ + body_size = log_header.log_body_size; + if (chimera_ring_buffer_readable + (log_data_for_local.ring) >= + (head_size + body_size)) { +#ifdef ENABLE_LOG_DEBUG + tzlog_print(K_INFO, "Can receive body data\n"); +#endif + chimera_ring_buffer_read( + log_data_for_local.ring, + (uint8_t *) header, + head_size, + TZLOG_LOCAL_BUFFERING_SIZE); + tzlog_print_with_header(&log_header, body_size); + } else { +#ifdef ENABLE_LOG_DEBUG + tzlog_print(K_INFO, + "gp is %d / body size is %d / label size is %d / level %d / pid %d\n", + log_header.log_gen_point, + log_header.log_body_size, + log_header.log_label_size, + log_header.log_level, + log_header.log_pid); + tzlog_print(K_INFO, + "Header + Body size is not enough(%d,%d)\n", + head_size, body_size); +#endif + is_need_continue = 0; + } + if (is_need_continue == 1) + goto continue_read; + } + } else { + if (ring_data_remain_size > 0) { + int magic_ret = 0; + char header[LHDSIZE + 1] = { 0, }; + chimera_ring_buffer_peek(log_data_for_local.ring, 0, + header, ring_data_remain_size, + TZLOG_LOCAL_BUFFERING_SIZE); + magic_ret = get_check_magic(header); + if (magic_ret == NO_MAGIC) { + tzlog_print_with_header(NULL, + ring_data_remain_size); +#ifdef ENABLE_LOG_DEBUG + tzlog_print(K_INFO, + "Find NO_MAGIC Data - (size : %d) (%s)\n", + ring_data_remain_size, + (char *)header); +#endif + } + } + } +} diff --git a/drivers/misc/artiktee/tzlog_process.h b/drivers/misc/artiktee/tzlog_process.h new file mode 100644 index 00000000000..fe07937b17c --- /dev/null +++ b/drivers/misc/artiktee/tzlog_process.h @@ -0,0 +1,29 @@ +/********************************************************* + * Copyright (C) 2011 - 2016 Samsung Electronics Co., Ltd 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 version 2 and no 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 St, Fifth Floor, Boston, MA 02110-1301 USA + * + *********************************************************/ + +#ifndef __TZLOG_PROCESS_H__ +#define __TZLOG_PROCESS_H__ + +#include "tzlog_core.h" + +int init_log_processing_resources(void); +void tzlog_transfer_to_tzdaemon(s_tzlog_data *src_data, int src_buffer_size); +void tzlog_transfer_to_local(s_tzlog_data *src_data, int src_buffer_size); + +#endif + diff --git a/drivers/misc/artiktee/tzmem.c b/drivers/misc/artiktee/tzmem.c index 3f5232a5478..12006cca8ee 100644 --- a/drivers/misc/artiktee/tzmem.c +++ b/drivers/misc/artiktee/tzmem.c @@ -32,6 +32,7 @@ #include "tzdev.h" #include "tzdev_internal.h" +#include "tzlog_print.h" #include "sstransaction.h" #include "tzpage.h" #include "tzdev_smc.h" @@ -117,6 +118,81 @@ static long tzmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return ret; } +#ifdef CONFIG_COMPAT +static long tzmem_compat_ioctl(struct file *file, + unsigned int cmd, unsigned long arg) +{ + int ret = 0; + + switch (cmd) { + case TZMEM_COMPAT_EXPORT_MEMORY: + { + struct tzmem_region32 __user *argp, s; + + argp = (struct tzmem_region32 __user *)arg; + if (copy_from_user + (&s, argp, sizeof(struct tzmem_region32))) { + ret = -EFAULT; + break; + } + + ret = register_user_memory(file, + (unsigned long)s.ptr, + s.size, + s.tee_ctx_id, s.writable); + + if (ret < 0) + break; + + s.pid = current->tgid; + s.id = ret; + ret = 0; + + if (copy_to_user(argp, &s, + sizeof(struct tzmem_region32))) { + unregister_user_memory(file, s.id); + ret = -EFAULT; + break; + } + + break; + } + case TZMEM_RELEASE_MEMORY: + { + int id; + + if (copy_from_user(&id, + (int __user *)arg, sizeof(int))) { + ret = -EFAULT; + break; + } + + ret = unregister_user_memory(file, id); + break; + } + case TZMEM_COMPAT_CHECK_MEMORY: + { + struct tzmem_region32 __user *argp, s; + + argp = (struct tzmem_region32 __user *)arg; + if (copy_from_user + (&s, argp, sizeof(struct tzmem_region32))) { + ret = -EFAULT; + break; + } + + ret = verify_client_memory(s.id, s.pid, s.tee_ctx_id); + break; + } + default: + tzlog_print(TZLOG_ERROR, "Unknown TZMEM Command: %d\n", cmd); + ret = -EINVAL; + } + + return ret; +} +#endif + struct tzmem_file { struct list_head nodes; spinlock_t lock; @@ -345,6 +421,9 @@ static const struct file_operations tzmem_fops = { .owner = THIS_MODULE, .open = tzmem_open, .release = tzmem_release, +#ifdef CONFIG_COMPAT + .compat_ioctl = tzmem_compat_ioctl, +#endif .unlocked_ioctl = tzmem_ioctl, }; diff --git a/drivers/misc/artiktee/tzsys.c b/drivers/misc/artiktee/tzsys.c index 727604e4cef..3ae83076c24 100644 --- a/drivers/misc/artiktee/tzsys.c +++ b/drivers/misc/artiktee/tzsys.c @@ -30,16 +30,16 @@ #include "tzdev_internal.h" #include "tzpage.h" #include "tzdev_smc.h" +#include "tzlog_print.h" +#include "ss_file.h" -#ifndef CONFIG_VD_RELEASE -/*#define CONFIG_TZDEV_MINIDUMP*/ -#endif - -/*#define CONFIG_INSTANCE_DEBUG*/ #ifdef CONFIG_INSTANCE_DEBUG +#include <linux/vmalloc.h> +/* it should be change to removing Duplicated code(tzlog.c ) */ #define CONFIG_TZDEV_MINIDUMP -#define ERROR_PARENT_DIR_PATH "/opt/usr/apps/save_error_log/" -#define ERROR_DIR_NAME "error_log" +#define ERROR_PARENT_DIR_PATH "/opt/usr/apps/" +#define ERROR_DIR_NAME_DEPTH1 "save_error_log" +#define ERROR_DIR_NAME_DEPTH2 "error_log" #define ERROR_DUMP_PARENT_DIR_PATH "/opt/usr/apps/save_error_log/error_log/" #define ERROR_DUMP_DIR_NAME "secureos_dump" #endif @@ -81,7 +81,7 @@ void __init tzsys_init(void) BUG_ON(rc < 0); #ifdef CONFIG_TZDEV_MINIDUMP - tzlog_print(TZLOG_INFO, "Register MiniDump\n"); + tzlog_print(K_INFO, "Register MiniDump\n"); /* 1MB for minidump */ minipage = vmalloc(MINIDUMP_PAGES * PAGE_SIZE); @@ -98,7 +98,7 @@ void __init tzsys_init(void) rc = scm_minidump_register(miniwsm); - tzlog_print(TZLOG_INFO, "This tzdev has minidump system enabled !!!\n"); + tzlog_print(K_INFO, "This tzdev has minidump system enabled !!!\n"); #endif } @@ -106,8 +106,7 @@ void __init tzsys_init(void) int tzlog_create_dir(char *parnet_dir_name, char *dir_name); int tzlog_output_do_dump(int is_kernel) { - struct file *file; - mm_segment_t old_fs; + int write_size; char path[128]; struct timeval now; unsigned long long T; @@ -122,11 +121,14 @@ int tzlog_output_do_dump(int is_kernel) } if (is_kernel == 1) - tzlog_print(TZLOG_ERROR, "SecureOS Crash detected\n"); + tzlog_print(K_ERR, "SecureOS Crash detected\n"); else - tzlog_print(TZLOG_ERROR, "TA Crash detected\n"); + tzlog_print(K_ERR, "TA Crash detected\n"); - tzlog_create_dir(ERROR_PARENT_DIR_PATH, ERROR_DIR_NAME); + tzlog_create_dir(ERROR_PARENT_DIR_PATH, ERROR_DIR_NAME_DEPTH1); + snprintf(path, sizeof(path), "%s%s/", + ERROR_PARENT_DIR_PATH, ERROR_DIR_NAME_DEPTH1); + tzlog_create_dir(path, ERROR_DIR_NAME_DEPTH2); tzlog_create_dir(ERROR_DUMP_PARENT_DIR_PATH, ERROR_DUMP_DIR_NAME); do_gettimeofday(&now); @@ -137,60 +139,43 @@ int tzlog_output_do_dump(int is_kernel) ERROR_DUMP_PARENT_DIR_PATH, ERROR_DUMP_DIR_NAME, ((is_kernel == 1) ? "os" : "app"), T); - file = filp_open(path, O_CREAT | O_RDWR | O_SYNC, 0600); - - if (IS_ERR(file)) { - if (is_kernel == 1) - tzlog_print(TZLOG_ERROR, - "error occured while opening file %s, exiting...\n", - path); - else - tzlog_print(TZLOG_DEBUG, - "error occured while opening file %s, exiting...\n", - path); + write_size = ss_file_create_object(path, tz_minidump_data, + tz_syspage->minidump_size); + + if (write_size <= 0) { + tzlog_print(K_ERR, + "error occured while opening file %s, exiting...\n", + path); goto out; } if (is_kernel == 1) - tzlog_print(TZLOG_ERROR, "Writing SecureOS minidump to %s\n", - path); + tzlog_print(K_ERR, "Writing SecureOS minidump to %s\n", path); else - tzlog_print(TZLOG_DEBUG, "Writing TA minidump to %s\n", path); - - old_fs = get_fs(); - set_fs(KERNEL_DS); - - file->f_op->llseek(file, 0, SEEK_SET); - file->f_op->write(file, tz_minidump_data, tz_syspage->minidump_size, - &file->f_pos); - - set_fs(old_fs); - - vfs_fsync(file, 0); - vfs_fsync(file, 1); - - filp_close(file, NULL); + tzlog_print(K_INFO, "Writing TA minidump to %s\n", path); if (is_kernel == 1) - tzlog_print(TZLOG_ERROR, "Minidump stored %u bytes\n", + tzlog_print(K_ERR, "Minidump stored %u bytes\n", tz_syspage->minidump_size); else - tzlog_print(TZLOG_DEBUG, + tzlog_print(K_INFO, "Minidump TA stored %u bytespc)(uuid:%s)\n", tz_syspage->minidump_size, tz_syspage->uid); memset(tz_minidump_data, 0, tz_syspage->minidump_size); - tz_syspage->minidump_size = 0; + memset(tz_syspage->uid, 0, sizeof(tz_syspage->uid)); #ifdef CONFIG_INSTANCE_DEBUG #ifdef CONFIG_CALL_SAVELOG - if (is_kernel == 1) { + if (is_kernel == 1) set_kpi_fault(0, 0, "main", "TrustWare", "TZ"); - } else { + else set_kpi_fault(0, 0, "main", tz_syspage->uid, "TZ"); - } #endif #endif + + /* End of writing the dump file */ + tz_syspage->minidump_size = 0; out: return 0; } @@ -226,7 +211,7 @@ void tzsys_crash_check(void) if (!IS_ERR(task)) { wake_up_process(task); } else { - tzlog_print(TZLOG_ERROR, + tzlog_print(K_ERR, "Can't spawn worker for minidump. Execute now\n"); tz_crash_worker(NULL); } diff --git a/drivers/misc/artiktee/tzwsm.c b/drivers/misc/artiktee/tzwsm.c index bbe6d3ce73f..73c1e19a853 100644 --- a/drivers/misc/artiktee/tzwsm.c +++ b/drivers/misc/artiktee/tzwsm.c @@ -23,10 +23,10 @@ #include <linux/uaccess.h> #include <linux/slab.h> #include "tzdev.h" -#include "tzdev_internal.h" #include "tzpage.h" #include "tzdev_smc.h" #include "wsm.h" +#include "tzlog_print.h" int tzswm_register_tzdev_memory(uint64_t ctx_id, struct page **pages, size_t num_pages, gfp_t gfp, int for_kernel) |