From 9beac5423ea3d3e27f482854faa34004832f4b69 Mon Sep 17 00:00:00 2001 From: Mallikarjun S T Date: Wed, 20 Jul 2022 11:35:00 +0530 Subject: [PATCH] NFC: driver: Add NFC secure zone status query in driver Implemented secure zone status query calls in NFC driver Change-Id: If41681ec14dbc53401182667df1256d5818f8576 --- Android.mk | 5 +++ Kbuild | 3 ++ nfc/common.c | 104 ++++++++++++++++++++++++++++++++++++++++++-------- nfc/common.h | 17 +++++++++ nfc/i2c_drv.c | 19 +++++++-- 5 files changed, 128 insertions(+), 20 deletions(-) diff --git a/Android.mk b/Android.mk index dbc37f40b0..c7c41cddd1 100644 --- a/Android.mk +++ b/Android.mk @@ -5,6 +5,11 @@ DLKM_DIR := $(TOP)/device/qcom/common/dlkm LOCAL_PATH := $(call my-dir) +KBUILD_OPTIONS += KBUILD_EXTRA_SYMBOLS=$(PWD)/$(call intermediates-dir-for,DLKM,sec-module-symvers)/Module.symvers + +LOCAL_REQUIRED_MODULES := sec-module-symvers +LOCAL_ADDITIONAL_DEPENDENCIES += $(call intermediates-dir-for,DLKM,sec-module-symvers)/Module.symvers + include $(CLEAR_VARS) LOCAL_MODULE := nxp-nci.ko diff --git a/Kbuild b/Kbuild index 93012c8f01..616e151d33 100644 --- a/Kbuild +++ b/Kbuild @@ -6,6 +6,9 @@ LINUXINCLUDE += -I$(NFC_ROOT)/include/uapi/linux/nfc LINUXINCLUDE += -include $(NFC_ROOT)/config/gki_nfc_conf.h +LINUXINCLUDE += -I$(NFC_ROOT)/../../../qcom/opensource/securemsm-kernel/smcinvoke/ +LINUXINCLUDE += -I$(NFC_ROOT)/../../../qcom/opensource/securemsm-kernel/linux/ + obj-$(CONFIG_NXP_NFC_I2C) += nxp-nci.o #source files diff --git a/nfc/common.c b/nfc/common.c index 7e82bfe86b..6e03a97918 100644 --- a/nfc/common.c +++ b/nfc/common.c @@ -27,7 +27,6 @@ #include "common.h" -static int secure_zone = 1; int nfc_parse_dt(struct device *dev, struct platform_configs *nfc_configs, uint8_t interface) @@ -131,14 +130,15 @@ int get_valid_gpio(int gpio) void gpio_set_ven(struct nfc_dev *nfc_dev, int value) { struct platform_gpio *nfc_gpio = &nfc_dev->configs.gpio; + if(!nfc_dev->secure_zone) { + if (gpio_get_value(nfc_gpio->ven) != value) { + pr_debug("%s: value %d\n", __func__, value); - if (gpio_get_value(nfc_gpio->ven) != value) { - pr_debug("%s: value %d\n", __func__, value); - - gpio_set_value(nfc_gpio->ven, value); - /* hardware dependent delay */ - usleep_range(NFC_GPIO_SET_WAIT_TIME_US, - NFC_GPIO_SET_WAIT_TIME_US + 100); + gpio_set_value(nfc_gpio->ven, value); + /* hardware dependent delay */ + usleep_range(NFC_GPIO_SET_WAIT_TIME_US, + NFC_GPIO_SET_WAIT_TIME_US + 100); + } } } @@ -407,9 +407,12 @@ long nfc_dev_compat_ioctl(struct file *pfile, unsigned int cmd, int nfc_post_init(struct nfc_dev *nfc_dev) { int ret=0; + static int post_init_success; struct platform_configs nfc_configs; struct platform_gpio *nfc_gpio; + if(post_init_success) + return 0; if (!nfc_dev) return -ENODEV; @@ -449,12 +452,79 @@ int nfc_post_init(struct nfc_dev *nfc_dev) /*Initialising sempahore to disbale NFC Ven GPIO only after eSE is power off flag is set */ sema_init(&sem_eSE_pwr_off,0); + post_init_success = 1; pr_info("%s success\n", __func__); return 0; } +/** + * nfc_hw_secure_check() - Checks the NFC secure zone status + * + * Queries the TZ secure libraries if NFC is in secure zone statue or not. + * + * Return: 0 if FEATURE_NOT_SUPPORTED/PERIPHERAL_NOT_FOUND/state is 2 and + * return 1(non-secure) otherwise + */ + + bool nfc_hw_secure_check(void) + { + struct Object client_env; + struct Object app_object; + u32 wifi_uid = HW_NFC_UID; + union ObjectArg obj_arg[2] = {{{0, 0}}}; + int ret; + bool retstat = 1; + u8 state = 0; + + /* get rootObj */ + ret = get_client_env_object(&client_env); + if (ret) { + pr_err("Failed to get client_env_object, ret: %d\n", ret); + return 1; + } + + ret = IClientEnv_open(client_env, HW_STATE_UID, &app_object); + if (ret) { + pr_debug("Failed to get app_object, ret: %d\n", ret); + if (ret == FEATURE_NOT_SUPPORTED) { + retstat = 0; /* Do not Assert */ + pr_debug("Secure HW feature not supported\n"); + } + goto exit_release_clientenv; + } + + obj_arg[0].b = (struct ObjectBuf) {&wifi_uid, sizeof(u32)}; + obj_arg[1].b = (struct ObjectBuf) {&state, sizeof(u8)}; + ret = Object_invoke(app_object, HW_OP_GET_STATE, obj_arg, + ObjectCounts_pack(1, 1, 0, 0)); + + pr_info("SMC invoke ret: %d state: %d\n", ret, state); + if (ret) { + if (ret == PERIPHERAL_NOT_FOUND) { + retstat = 0; /* Do not Assert */ + pr_debug("Secure HW mode is not updated. Peripheral not found\n"); + } + goto exit_release_app_obj; + } + + if (state == 1) { + /*Secure Zone*/ + retstat = 1; + } else { + /*Non-Secure Zone*/ + retstat = 0; + } + +exit_release_app_obj: + Object_release(app_object); +exit_release_clientenv: + Object_release(client_env); + + return retstat; + } + /** * nfc_dynamic_protection_ioctl() - dynamic protection control * @nfc_dev: nfc device data structure @@ -491,7 +561,7 @@ int nfc_dynamic_protection_ioctl(struct nfc_dev *nfc_dev, unsigned long sec_zone } ret = nfc_ioctl_power_states(nfc_dev, 0); /*set driver as secure zone, such that no ioctl calls are allowed*/ - secure_zone=1; + nfc_dev->secure_zone = true; pr_info("Driver Secure flag set successful\n"); } else { ret = -1; @@ -499,7 +569,7 @@ int nfc_dynamic_protection_ioctl(struct nfc_dev *nfc_dev, unsigned long sec_zone } else if(sec_zone_trans == 0) { chk_eSE_pwr_off = 0; - secure_zone=0; + nfc_dev->secure_zone = false; if(init_flag) { /*Initialize once,only during the first non-secure entry*/ @@ -508,7 +578,8 @@ int nfc_dynamic_protection_ioctl(struct nfc_dev *nfc_dev, unsigned long sec_zone init_flag=0; } else { - ret = nfc_ioctl_power_states(nfc_dev, 1); + if(!gpio_get_value(nfc_gpio->ven)) + ret = nfc_ioctl_power_states(nfc_dev, 1); } pr_info("Func Driver Secure flag clear successful\n"); } else { @@ -541,7 +612,7 @@ long nfc_dev_ioctl(struct file *pfile, unsigned int cmd, unsigned long arg) return -ENODEV; /*Avoiding ioctl call in secure zone*/ - if(secure_zone) { + if(nfc_dev->secure_zone) { if(cmd!=NFC_SECURE_ZONE) { pr_debug("nfc_dev_ioctl failed\n"); return -1; @@ -665,10 +736,11 @@ int nfc_dev_close(struct inode *inode, struct file *filp) int validate_nfc_state_nci(struct nfc_dev *nfc_dev) { struct platform_gpio *nfc_gpio = &nfc_dev->configs.gpio; - - if (!gpio_get_value(nfc_gpio->ven)) { - pr_err("%s: ven low - nfcc powered off\n", __func__); - return -ENODEV; + if(!nfc_dev->secure_zone) { + if (!gpio_get_value(nfc_gpio->ven)) { + pr_err("%s: ven low - nfcc powered off\n", __func__); + return -ENODEV; + } } if (get_valid_gpio(nfc_gpio->dwl_req) == 1) { pr_err("%s: fw download in-progress\n", __func__); diff --git a/nfc/common.h b/nfc/common.h index 32c923f667..404333f120 100644 --- a/nfc/common.h +++ b/nfc/common.h @@ -33,6 +33,11 @@ #include "i2c_drv.h" #include "ese_cold_reset.h" +/*secure library headers*/ +#include "smcinvoke.h" +#include "smcinvoke_object.h" +#include "IClientEnv.h" + /* Max device count for this driver */ #define DEV_COUNT 1 /* i2c device class */ @@ -115,6 +120,13 @@ #define NFC_VDDIO_MAX 1950000 //in uV #define NFC_CURRENT_MAX 157000 //in uA +//NFC ID for registration with secure libraries +#define HW_STATE_UID 0x108 +#define HW_OP_GET_STATE 1 +#define HW_NFC_UID 0x506 +#define FEATURE_NOT_SUPPORTED 12 +#define PERIPHERAL_NOT_FOUND 10 + #define NUM_OF_IPC_LOG_PAGES (2) #define PKT_MAX_LEN (4) // no of max bytes to print for cmd/resp @@ -135,6 +147,7 @@ do { \ static struct semaphore sem_eSE_pwr_off; static chk_eSE_pwr_off; + enum ese_ioctl_request { /* eSE POWER ON */ ESE_POWER_ON = 0, @@ -262,6 +275,9 @@ struct nfc_dev { union nqx_uinfo nqx_info; + /*secure zone state*/ + bool secure_zone; + /* CLK control */ bool clk_run; struct clk *s_clk; @@ -305,4 +321,5 @@ int nfc_clock_select(struct nfc_dev *nfc_dev); int nfc_clock_deselect(struct nfc_dev *nfc_dev); int nfc_post_init(struct nfc_dev *nfc_dev); int nfc_dynamic_protection_ioctl(struct nfc_dev *nfc_dev, unsigned long sec_zone_trans); +bool nfc_hw_secure_check(void); #endif /* _COMMON_H_ */ diff --git a/nfc/i2c_drv.c b/nfc/i2c_drv.c index 4b47ef10a5..7c9108ac90 100644 --- a/nfc/i2c_drv.c +++ b/nfc/i2c_drv.c @@ -156,10 +156,12 @@ int i2c_read(struct nfc_dev *nfc_dev, char *buf, size_t count, int timeout) if (gpio_get_value(nfc_gpio->irq)) break; - if (!gpio_get_value(nfc_gpio->ven)) { - pr_info("%s: releasing read\n", __func__); - ret = -EIO; - goto err; + if(!nfc_dev->secure_zone) { + if (!gpio_get_value(nfc_gpio->ven)) { + pr_info("%s: releasing read\n", __func__); + ret = -EIO; + goto err; + } } /* * NFC service wanted to close the driver so, @@ -413,6 +415,15 @@ int nfc_i2c_dev_probe(struct i2c_client *client, const struct i2c_device_id *id) goto err_ldo_config_failed; } + /*Check NFC Secure Zone status*/ + if(!nfc_hw_secure_check()) { + nfc_post_init(nfc_dev); + nfc_dev->secure_zone = false; + } + else + nfc_dev->secure_zone = true; + pr_info("%s:nfc_dev->secure_zone = %s", __func__, nfc_dev->secure_zone ? "true" : "false"); + if(nfc_dev->configs.clk_pin_voting) nfc_dev->clk_run = false; else