Loading drivers/soc/qcom/spss_utils.c +202 −286 Original line number Diff line number Diff line Loading @@ -65,35 +65,53 @@ static u32 spss_emul_type_reg_addr; /* TCSR_SOC_EMULATION_TYPE */ static void *iar_notif_handle; static struct notifier_block *iar_nb; static bool is_iar_active; static bool is_ssr_disabled; #define CMAC_SIZE_IN_BYTES (128/8) /* 128 bit = 16 bytes */ #define CMAC_SIZE_IN_DWORDS (CMAC_SIZE_IN_BYTES/sizeof(u32)) /* 4 dwords */ /* Asym , Crypt , Keym */ #define NUM_UEFI_APPS 3 static u32 pil_addr; static u32 pil_size; static u32 cmac_buf[CMAC_SIZE_IN_DWORDS]; /* saved cmac */ static u32 pbl_cmac_buf[CMAC_SIZE_IN_DWORDS]; /* pbl cmac */ static u32 calc_apps_cmac[NUM_UEFI_APPS][CMAC_SIZE_IN_DWORDS]; static u32 saved_apps_cmac[NUM_UEFI_APPS][CMAC_SIZE_IN_DWORDS]; /* * The saved fw cmac is stored in file in IAR-DB. * It is provided via ioctl from user space spu service. */ static u32 saved_fw_cmac[CMAC_SIZE_IN_DWORDS]; /* saved fw cmac */ #define FW_AND_APPS_CMAC_SIZE \ (CMAC_SIZE_IN_DWORDS + NUM_UEFI_APPS*CMAC_SIZE_IN_DWORDS) /* * The calculated fw cmac is calculated by SPU PBL. * It is read from shared memory and provided back to user space service * via device attribute. */ static u32 calc_fw_cmac[CMAC_SIZE_IN_DWORDS]; /* calculated pbl fw cmac */ static u32 iar_state; static bool is_iar_enabled; static bool ssr_disabled_flag; /* * The saved apps cmac is stored in file in IAR-DB. * It is provided via ioctl from user space spu service. */ static u32 saved_apps_cmac[MAX_SPU_UEFI_APPS][CMAC_SIZE_IN_DWORDS]; /* * The calculated apps cmac is calculated by SPU firmware. * It is read from shared memory and provided back to user space service * via device attribute. */ static u32 calc_apps_cmac[MAX_SPU_UEFI_APPS][CMAC_SIZE_IN_DWORDS]; static void __iomem *cmac_mem; static size_t cmac_mem_size = SZ_4K; /* XPU align to 4KB */ static phys_addr_t cmac_mem_addr; #define CMAC_MEM_SIZE SZ_4K /* XPU align to 4KB */ #define SPSS_BASE_ADDR_MASK 0xFFFF0000 #define SPSS_RMB_CODE_SIZE_REG_OFFSET 0x1008 #define SPU_EMULATUION (BIT(0) | BIT(1)) #define SPU_PRESENT_IN_EMULATION BIT(0) /* IOCTL max request size is 1KB */ #define MAX_IOCTL_REQ_SIZE 1024 /* Events notification */ static struct completion spss_events[SPSS_NUM_EVENTS]; static bool spss_events_signaled[SPSS_NUM_EVENTS]; Loading @@ -117,12 +135,12 @@ struct spss_utils_device { static struct spss_utils_device *spss_utils_dev; /* static functions declaration */ static int spss_set_fw_cmac(u32 *cmac, size_t cmac_size); static int spss_get_pbl_and_apps_calc_cmac(void); static int spss_get_saved_uefi_apps_cmac(void); static int spss_set_saved_fw_cmac(u32 *cmac, size_t cmac_size); static int spss_set_saved_uefi_apps_cmac(void); static int spss_get_fw_calc_cmac(void); static int spss_get_apps_calc_cmac(void); /*==========================================================================*/ /* Device Sysfs */ /*==========================================================================*/ Loading Loading @@ -213,85 +231,26 @@ static ssize_t spss_debug_reg_show(struct device *dev, static DEVICE_ATTR_RO(spss_debug_reg); static ssize_t cmac_buf_show(struct device *dev, static ssize_t calc_fw_cmac_show(struct device *dev, struct device_attribute *attr, char *buf) { int ret = 0; if (!dev || !attr || !buf) { pr_err("invalid param.\n"); return -EINVAL; } ret = snprintf(buf, PAGE_SIZE, "0x%08x,0x%08x,0x%08x,0x%08x\n", cmac_buf[0], cmac_buf[1], cmac_buf[2], cmac_buf[3]); return ret; } static DEVICE_ATTR_RO(cmac_buf); /* first make sure the calc cmac is updated */ spss_get_fw_calc_cmac(); static ssize_t iar_state_show(struct device *dev, struct device_attribute *attr, char *buf) { int ret = 0; memcpy(buf, calc_fw_cmac, sizeof(calc_fw_cmac)); if (!dev || !attr || !buf) { pr_err("invalid param.\n"); return -EINVAL; } /* show IAR-STATE from soc fuse */ ret = snprintf(buf, PAGE_SIZE, "0x%x\n", iar_state); return ret; } static DEVICE_ATTR_RO(iar_state); static ssize_t iar_enabled_show(struct device *dev, struct device_attribute *attr, char *buf) { int ret = 0; if (!dev || !attr || !buf) { pr_err("invalid param.\n"); return -EINVAL; } ret = snprintf(buf, PAGE_SIZE, "0x%x\n", is_iar_enabled); return ret; return sizeof(calc_fw_cmac); } static DEVICE_ATTR_RO(iar_enabled); static DEVICE_ATTR_RO(calc_fw_cmac); static ssize_t pbl_cmac_show(struct device *dev, struct device_attribute *attr, char *buf) { int ret = 0; if (!dev || !attr || !buf) { pr_err("invalid param.\n"); return -EINVAL; } /* first make sure the pbl cmac is updated */ spss_get_pbl_and_apps_calc_cmac(); ret = snprintf(buf, PAGE_SIZE, "0x%08x,0x%08x,0x%08x,0x%08x\n", pbl_cmac_buf[0], pbl_cmac_buf[1], pbl_cmac_buf[2], pbl_cmac_buf[3]); return ret; } static DEVICE_ATTR_RO(pbl_cmac); static ssize_t apps_cmac_show(struct device *dev, static ssize_t calc_apps_cmac_show(struct device *dev, struct device_attribute *attr, char *buf) { if (!dev || !attr || !buf) { Loading @@ -299,15 +258,15 @@ static ssize_t apps_cmac_show(struct device *dev, return -EINVAL; } /* first make sure the pbl cmac is updated */ spss_get_pbl_and_apps_calc_cmac(); /* first make sure the calc cmac is updated */ spss_get_apps_calc_cmac(); memcpy(buf, calc_apps_cmac, sizeof(calc_apps_cmac)); return sizeof(calc_apps_cmac); } static DEVICE_ATTR_RO(apps_cmac); static DEVICE_ATTR_RO(calc_apps_cmac); /*--------------------------------------------------------------------------*/ static int spss_create_sysfs(struct device *dev) Loading @@ -332,47 +291,23 @@ static int spss_create_sysfs(struct device *dev) goto remove_test_fuse_state; } ret = device_create_file(dev, &dev_attr_cmac_buf); ret = device_create_file(dev, &dev_attr_calc_fw_cmac); if (ret < 0) { pr_err("failed to create sysfs file for cmac_buf.\n"); pr_err("failed to create sysfs file for calc_fw_cmac.\n"); goto remove_spss_debug_reg; } ret = device_create_file(dev, &dev_attr_iar_state); if (ret < 0) { pr_err("failed to create sysfs file for iar_state.\n"); goto remove_cmac_buf; } ret = device_create_file(dev, &dev_attr_iar_enabled); if (ret < 0) { pr_err("failed to create sysfs file for iar_enabled.\n"); goto remove_iar_state; } ret = device_create_file(dev, &dev_attr_pbl_cmac); if (ret < 0) { pr_err("failed to create sysfs file for pbl_cmac.\n"); goto remove_iar_enabled; } ret = device_create_file(dev, &dev_attr_apps_cmac); ret = device_create_file(dev, &dev_attr_calc_apps_cmac); if (ret < 0) { pr_err("failed to create sysfs file for apps_cmac.\n"); goto remove_pbl_cmac; pr_err("failed to create sysfs file for calc_apps_cmac.\n"); goto remove_calc_fw_cmac; } return 0; remove_pbl_cmac: device_remove_file(dev, &dev_attr_pbl_cmac); remove_iar_enabled: device_remove_file(dev, &dev_attr_iar_enabled); remove_iar_state: device_remove_file(dev, &dev_attr_iar_state); remove_cmac_buf: device_remove_file(dev, &dev_attr_cmac_buf); remove_calc_fw_cmac: device_remove_file(dev, &dev_attr_calc_fw_cmac); remove_spss_debug_reg: device_remove_file(dev, &dev_attr_spss_debug_reg); remove_test_fuse_state: Loading @@ -385,11 +320,8 @@ static int spss_create_sysfs(struct device *dev) static void spss_destroy_sysfs(struct device *dev) { device_remove_file(dev, &dev_attr_apps_cmac); device_remove_file(dev, &dev_attr_pbl_cmac); device_remove_file(dev, &dev_attr_iar_enabled); device_remove_file(dev, &dev_attr_iar_state); device_remove_file(dev, &dev_attr_cmac_buf); device_remove_file(dev, &dev_attr_calc_apps_cmac); device_remove_file(dev, &dev_attr_calc_fw_cmac); device_remove_file(dev, &dev_attr_spss_debug_reg); device_remove_file(dev, &dev_attr_test_fuse_state); device_remove_file(dev, &dev_attr_firmware_name); Loading Loading @@ -499,16 +431,70 @@ static int spss_is_event_signaled(struct spss_ioc_is_signaled *req) return 0; } static int spss_handle_set_fw_and_apps_cmac(struct spss_ioc_set_fw_and_apps_cmac *req) { int ret = 0; u32 cmac_buf_size = req->cmac_buf_size; void __user *cmac_buf_ptr = u64_to_user_ptr(req->cmac_buf_ptr); u32 num_of_cmacs = req->num_of_cmacs; /* Saved cmacs of spu firmware and UEFI loaded spu apps */ u32 fw_and_apps_cmacs[1+MAX_SPU_UEFI_APPS][CMAC_SIZE_IN_DWORDS]; pr_debug("cmac_buf_size [0x%x].\n", (int) req->cmac_buf_size); pr_debug("cmac_buf_ptr [0x%x].\n", (int) req->cmac_buf_ptr); pr_debug("num_of_cmacs [0x%x].\n", (int) req->num_of_cmacs); if (cmac_buf_size != sizeof(fw_and_apps_cmacs)) { pr_err("cmac_buf_size [0x%x] invalid.\n", cmac_buf_size); return -EINVAL; } if (num_of_cmacs > (u32)(MAX_SPU_UEFI_APPS+1)) { pr_err("num_of_cmacs [0x%x] invalid.\n", num_of_cmacs); return -EINVAL; } /* copy the saved cmacs from user buffer to loacl variable */ ret = copy_from_user(fw_and_apps_cmacs, cmac_buf_ptr, cmac_buf_size); if (ret < 0) { pr_err("copy_from_user() from cmac_buf_ptr failed.\n"); return -EFAULT; } /* store the saved fw cmac */ memcpy(saved_fw_cmac, fw_and_apps_cmacs[0], sizeof(saved_fw_cmac)); pr_debug("saved fw cmac: 0x%08x,0x%08x,0x%08x,0x%08x\n", saved_fw_cmac[0], saved_fw_cmac[1], saved_fw_cmac[2], saved_fw_cmac[3]); /* store the saved apps cmac */ memcpy(saved_apps_cmac, fw_and_apps_cmacs[1], sizeof(saved_apps_cmac)); /* * SPSS is loaded now by UEFI, * so PIL-IAR-callback is not being called on power-up by PIL. * therefore get the saved spu fw cmac and apps cmac from ioctl. * The PIL-IAR-callback shall be called on spss SSR. * The saved cmacs are used on SUBSYS_BEFORE_AUTH_AND_RESET event ! */ spss_set_saved_fw_cmac(saved_fw_cmac, sizeof(saved_fw_cmac)); spss_set_saved_uefi_apps_cmac(); pr_debug("completed ok\n"); return 0; } static long spss_utils_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int ret; void *buf = (void *) arg; unsigned char data[64] = {0}; uint8_t data[MAX_IOCTL_REQ_SIZE] = {0}; size_t size = 0; u32 i = 0; /* Saved cmacs of spu firmware and UEFI loaded spu apps */ u32 fw_and_apps_cmacs[FW_AND_APPS_CMAC_SIZE]; void *req = (void *) data; if (buf == NULL) { Loading @@ -532,36 +518,23 @@ static long spss_utils_ioctl(struct file *file, } switch (cmd) { case SPSS_IOC_SET_FW_CMAC: if (size != sizeof(fw_and_apps_cmacs)) { pr_err("cmd [0x%x] invalid size [0x%x]\n", cmd, size); return -EINVAL; } case SPSS_IOC_SET_FW_AND_APPS_CMAC: pr_debug("ioctl [SPSS_IOC_SET_FW_AND_APPS_CMAC]\n"); /* spdaemon uses this ioctl only when IAR is active */ is_iar_active = true; memcpy(fw_and_apps_cmacs, data, sizeof(fw_and_apps_cmacs)); memcpy(cmac_buf, fw_and_apps_cmacs, sizeof(cmac_buf)); for (i = 0; i < NUM_UEFI_APPS; ++i) { int x = (i+1)*CMAC_SIZE_IN_DWORDS; memcpy(saved_apps_cmac[i], fw_and_apps_cmacs + x, CMAC_SIZE_IN_BYTES); if (cmac_mem == NULL) { cmac_mem = ioremap_nocache(cmac_mem_addr, CMAC_MEM_SIZE); if (!cmac_mem) { pr_err("can't map cmac_mem.\n"); return -EFAULT; } } /* * SPSS is loaded now by UEFI, * so IAR callback is not being called on power-up by PIL. * therefore read the spu pbl fw cmac and apps cmac from ioctl. * The callback shall be called on spss SSR. */ pr_debug("read pbl cmac from shared memory\n"); spss_set_fw_cmac(cmac_buf, sizeof(cmac_buf)); spss_set_saved_uefi_apps_cmac(); spss_get_saved_uefi_apps_cmac(); ret = spss_handle_set_fw_and_apps_cmac(req); if (ret < 0) return ret; break; case SPSS_IOC_WAIT_FOR_EVENT: Loading Loading @@ -608,9 +581,9 @@ static long spss_utils_ioctl(struct file *file, } if (is_iar_active) { memcpy(&ssr_disabled_flag, data, size); memcpy(&is_ssr_disabled, data, size); pr_debug("SSR disabled state updated to: %d\n", ssr_disabled_flag); is_ssr_disabled); } break; Loading Loading @@ -700,6 +673,30 @@ static void spss_utils_destroy_chardev(void) /* Device Tree */ /*==========================================================================*/ /* get the ACTUAL spss PIL firmware size from spu reg */ static int get_pil_size(phys_addr_t base_addr) { u32 spss_code_size_addr = 0; void __iomem *spss_code_size_reg = NULL; u32 pil_size = 0; spss_code_size_addr = base_addr + SPSS_RMB_CODE_SIZE_REG_OFFSET; spss_code_size_reg = ioremap_nocache(spss_code_size_addr, sizeof(u32)); if (!spss_code_size_reg) { pr_err("can't map spss_code_size_addr\n"); return -EINVAL; } pil_size = readl_relaxed(spss_code_size_reg); iounmap(spss_code_size_reg); if (pil_size % SZ_4K) { pr_err("pil_size [0x%08x] is not 4K aligned.\n", pil_size); return -EFAULT; } return pil_size; } /** * spss_parse_dt() - Parse Device Tree info. */ Loading @@ -714,22 +711,13 @@ static int spss_parse_dt(struct device_node *node) u32 spss_fuse2_bit = 0; u32 spss_fuse2_mask = 0; void __iomem *spss_fuse2_reg = NULL; /* IAR_FEATURE_ENABLED soc fuse */ u32 spss_fuse3_addr = 0; u32 spss_fuse3_bit = 0; u32 spss_fuse3_mask = 0; void __iomem *spss_fuse3_reg = NULL; /* IAR_STATE soc fuses */ u32 spss_fuse4_addr = 0; u32 spss_fuse4_bit = 0; u32 spss_fuse4_mask = 0; void __iomem *spss_fuse4_reg = NULL; struct device_node *np; struct resource r; u32 val1 = 0; u32 val2 = 0; void __iomem *spss_emul_type_reg = NULL; u32 spss_emul_type_val = 0; phys_addr_t spss_regs_base_addr = 0; ret = of_property_read_string(node, "qcom,spss-dev-firmware-name", &dev_firmware_name); Loading Loading @@ -884,12 +872,14 @@ static int spss_parse_dt(struct device_node *node) pil_addr = (u32)r.start; } ret = of_property_read_u32(node, "qcom,pil-size", &pil_size); spss_regs_base_addr = (spss_debug_reg_addr & SPSS_BASE_ADDR_MASK); ret = get_pil_size(spss_regs_base_addr); if (ret < 0) { pr_err("can't get pil_size\n"); pr_err("failed to get pil_size.\n"); return -EFAULT; } pil_size = (u32) ret; pr_debug("pil_addr [0x%08x].\n", pil_addr); pr_debug("pil_size [0x%08x].\n", pil_size); Loading @@ -898,146 +888,64 @@ static int spss_parse_dt(struct device_node *node) cmac_mem_addr = pil_addr + pil_size; pr_info("iar_buf_addr [0x%08x].\n", cmac_mem_addr); ret = of_property_read_u32(node, "qcom,spss-fuse3-addr", &spss_fuse3_addr); if (ret < 0) { pr_err("can't get fuse3 addr.\n"); return -EFAULT; } ret = of_property_read_u32(node, "qcom,spss-fuse3-bit", &spss_fuse3_bit); if (ret < 0) { pr_err("can't get fuse3 bit.\n"); return -EFAULT; } spss_fuse3_reg = ioremap_nocache(spss_fuse3_addr, sizeof(u32)); if (!spss_fuse3_reg) { pr_err("can't map fuse3 addr.\n"); return -EFAULT; } /* read IAR_FEATURE_ENABLED from soc fuse */ val1 = readl_relaxed(spss_fuse3_reg); iounmap(spss_fuse3_reg); spss_fuse3_mask = (1<<spss_fuse3_bit); pr_debug("iar_enabled fuse, addr [0x%x] val [0x%x] mask [0x%x].\n", spss_fuse3_addr, val1, spss_fuse3_mask); if (val1 & spss_fuse3_mask) is_iar_enabled = true; else is_iar_enabled = false; memset(cmac_buf, 0xA5, sizeof(cmac_buf)); ret = of_property_read_u32(node, "qcom,spss-fuse4-addr", &spss_fuse4_addr); if (ret < 0) { pr_err("can't get fuse4 addr.\n"); return -EFAULT; } ret = of_property_read_u32(node, "qcom,spss-fuse4-bit", &spss_fuse4_bit); if (ret < 0) { pr_err("can't get fuse4 bit.\n"); return -EFAULT; } spss_fuse4_reg = ioremap_nocache(spss_fuse4_addr, sizeof(u32)); if (!spss_fuse4_reg) { pr_err("can't map fuse4 addr.\n"); return -EFAULT; } val1 = readl_relaxed(spss_fuse4_reg); iounmap(spss_fuse4_reg); spss_fuse4_mask = (0x07 << spss_fuse4_bit); /* 3 bits */ pr_debug("IAR_STATE fuse, addr [0x%x] val [0x%x] mask [0x%x].\n", spss_fuse4_addr, val1, spss_fuse4_mask); val1 = ((val1 & spss_fuse4_mask) >> spss_fuse4_bit) & 0x07; iar_state = val1; pr_debug("iar_state [%d]\n", iar_state); memset(saved_fw_cmac, 0xA5, sizeof(saved_fw_cmac)); memset(saved_apps_cmac, 0xA5, sizeof(saved_apps_cmac)); return 0; } static int spss_set_fw_cmac(u32 *cmac, size_t cmac_size) static int spss_set_saved_fw_cmac(u32 *cmac, size_t cmac_size) { u8 __iomem *reg = NULL; int i; if (cmac_mem == NULL) { cmac_mem = ioremap_nocache(cmac_mem_addr, cmac_mem_size); if (!cmac_mem) { pr_err("can't map cmac_mem.\n"); pr_err("invalid cmac_mem.\n"); return -EFAULT; } } pr_debug("pil_addr [0x%x]\n", pil_addr); pr_debug("pil_size [0x%x]\n", pil_size); pr_debug("cmac_mem [%pK]\n", cmac_mem); reg = cmac_mem; pr_debug("reg [%pK]\n", reg); for (i = 0; i < cmac_size/4; i++) { for (i = 0; i < cmac_size/sizeof(u32); i++) writel_relaxed(cmac[i], reg + i*sizeof(u32)); pr_debug("cmac[%d] [0x%x]\n", i, cmac[i]); } reg += cmac_size; pr_debug("saved fw cmac: 0x%08x,0x%08x,0x%08x,0x%08x\n", cmac[0], cmac[1], cmac[2], cmac[3]); return 0; } static int spss_get_pbl_and_apps_calc_cmac(void) static int spss_get_fw_calc_cmac(void) { u8 __iomem *reg = NULL; int i, j; int i; u32 val; if (cmac_mem == NULL) if (cmac_mem == NULL) { pr_err("invalid cmac_mem.\n"); return -EFAULT; } reg = cmac_mem; /* IAR buffer base */ reg += CMAC_SIZE_IN_BYTES; /* skip the saved cmac */ pr_debug("reg [%pK]\n", reg); /* get pbl fw cmac from ddr */ for (i = 0; i < CMAC_SIZE_IN_DWORDS; i++) { val = readl_relaxed(reg); pbl_cmac_buf[i] = val; reg += sizeof(u32); } reg += CMAC_SIZE_IN_BYTES; /* skip the saved cmac */ pr_debug("pbl_cmac_buf : 0x%08x,0x%08x,0x%08x,0x%08x\n", pbl_cmac_buf[0], pbl_cmac_buf[1], pbl_cmac_buf[2], pbl_cmac_buf[3]); memset(calc_fw_cmac, 0, sizeof(calc_fw_cmac)); /* get apps cmac from ddr */ for (j = 0; j < NUM_UEFI_APPS; j++) { /* get pbl fw cmac from ddr */ for (i = 0; i < CMAC_SIZE_IN_DWORDS; i++) { val = readl_relaxed(reg); calc_apps_cmac[j][i] = val; calc_fw_cmac[i] = val; reg += sizeof(u32); } reg += CMAC_SIZE_IN_BYTES; /* skip the saved cmac */ pr_debug("app [%d] cmac : 0x%08x,0x%08x,0x%08x,0x%08x\n", j, calc_apps_cmac[j][0], calc_apps_cmac[j][1], calc_apps_cmac[j][2], calc_apps_cmac[j][3]); } pr_debug("calc_fw_cmac : 0x%08x,0x%08x,0x%08x,0x%08x\n", calc_fw_cmac[0], calc_fw_cmac[1], calc_fw_cmac[2], calc_fw_cmac[3]); return 0; } static int spss_get_saved_uefi_apps_cmac(void) static int spss_get_apps_calc_cmac(void) { u8 __iomem *reg = NULL; int i, j; Loading @@ -1047,22 +955,29 @@ static int spss_get_saved_uefi_apps_cmac(void) return -EFAULT; reg = cmac_mem; /* IAR buffer base */ reg += (2*CMAC_SIZE_IN_BYTES); /* skip the saved and calc fw cmac */ pr_debug("reg [%pK]\n", reg); reg += CMAC_SIZE_IN_BYTES; /* skip the saved fw cmac */ reg += CMAC_SIZE_IN_BYTES; /* skip the calc fw cmac */ reg += CMAC_SIZE_IN_BYTES; /* skip the saved 1st app cmac */ /* get saved apps cmac from ddr - were written by UEFI spss driver */ for (j = 0; j < NUM_UEFI_APPS; j++) { memset(calc_apps_cmac, 0, sizeof(calc_apps_cmac)); /* get apps cmac from ddr */ for (j = 0; j < ARRAY_SIZE(calc_apps_cmac); j++) { for (i = 0; i < CMAC_SIZE_IN_DWORDS; i++) { val = readl_relaxed(reg); saved_apps_cmac[j][i] = val; calc_apps_cmac[j][i] = val; reg += sizeof(u32); } reg += CMAC_SIZE_IN_BYTES; /* skip the calc cmac */ reg += CMAC_SIZE_IN_BYTES; /* skip the saved cmac */ pr_debug("app[%d] saved cmac: 0x%08x,0x%08x,0x%08x,0x%08x\n", j, saved_apps_cmac[j][0], saved_apps_cmac[j][1], saved_apps_cmac[j][2], saved_apps_cmac[j][3]); /* check for any pattern to mark end of cmacs */ if (saved_apps_cmac[j][0] == saved_apps_cmac[j][1]) { memset(calc_apps_cmac[j], 0, sizeof(calc_apps_cmac[j])); break; /* no more cmacs */ } pr_debug("app [%d] cmac : 0x%08x,0x%08x,0x%08x,0x%08x\n", j, calc_apps_cmac[j][0], calc_apps_cmac[j][1], calc_apps_cmac[j][2], calc_apps_cmac[j][3]); } return 0; Loading @@ -1079,10 +994,11 @@ static int spss_set_saved_uefi_apps_cmac(void) reg = cmac_mem; /* IAR buffer base */ reg += (2*CMAC_SIZE_IN_BYTES); /* skip the saved and calc fw cmac */ pr_debug("reg [%pK]\n", reg); /* get saved apps cmac from ddr - were written by UEFI spss driver */ for (j = 0; j < NUM_UEFI_APPS; j++) { for (j = 0; j < MAX_SPU_UEFI_APPS; j++) { if (saved_apps_cmac[j][0] == saved_apps_cmac[j][1]) break; /* no more cmacs */ for (i = 0; i < CMAC_SIZE_IN_DWORDS; i++) { val = saved_apps_cmac[j][i]; writel_relaxed(val, reg); Loading Loading @@ -1132,8 +1048,8 @@ static int spss_utils_pil_callback(struct notifier_block *nb, break; case SUBSYS_BEFORE_POWERUP: pr_debug("[SUBSYS_BEFORE_POWERUP] event.\n"); if (is_iar_active && ssr_disabled_flag) { pr_warn("SPSS SSR disabled, requesting reboot\n"); if (is_iar_active && is_ssr_disabled) { pr_err("SPSS SSR disabled, requesting reboot\n"); kernel_restart("SPSS SSR disabled, requesting reboot"); } break; Loading @@ -1159,12 +1075,12 @@ static int spss_utils_pil_callback(struct notifier_block *nb, pr_debug("[SUBSYS_PROXY_UNVOTE] event.\n"); break; case SUBSYS_BEFORE_AUTH_AND_RESET: pr_debug("[SUBSYS_BEFORE_AUTH_AND_RESET] event.\n"); /* do nothing if IAR is not active */ if (!is_iar_active) return NOTIFY_OK; pr_debug("[SUBSYS_BEFORE_AUTH_AND_RESET] event.\n"); /* Called on SSR as spss firmware is loaded by UEFI */ spss_set_fw_cmac(cmac_buf, sizeof(cmac_buf)); /* Called on SSR as spss firmware is loaded by UEFI on boot */ spss_set_saved_fw_cmac(saved_fw_cmac, sizeof(saved_fw_cmac)); spss_set_saved_uefi_apps_cmac(); break; default: Loading Loading @@ -1253,7 +1169,7 @@ static int spss_probe(struct platform_device *pdev) } mutex_init(&event_lock); ssr_disabled_flag = false; is_ssr_disabled = false; pr_info("Probe completed successfully, [%s].\n", firmware_name); Loading include/uapi/linux/spss_utils.h +25 −2 Original line number Diff line number Diff line Loading @@ -19,12 +19,14 @@ #define SPSS_IOC_MAGIC 'S' /* ---------- set fw cmac --------------------------------- */ #define NUM_SPU_UEFI_APPS 3 #define OLD_NUM_SPU_UEFI_APPS 3 /* Obsolete */ #define CMAC_SIZE_IN_WORDS 4 /* Obsolete struct, keep for backward compatible */ struct spss_ioc_set_fw_cmac { __u32 cmac[CMAC_SIZE_IN_WORDS]; __u32 app_cmacs[NUM_SPU_UEFI_APPS][CMAC_SIZE_IN_WORDS]; __u32 apps_cmac[OLD_NUM_SPU_UEFI_APPS][CMAC_SIZE_IN_WORDS]; } __packed; #define SPSS_IOC_SET_FW_CMAC \ Loading Loading @@ -78,7 +80,28 @@ struct spss_ioc_is_signaled { #define SPSS_IOC_IS_EVENT_SIGNALED \ _IOWR(SPSS_IOC_MAGIC, 4, struct spss_ioc_is_signaled) /* ---------- set ssr state ------------------------------ */ #define SPSS_IOC_SET_SSR_STATE \ _IOWR(SPSS_IOC_MAGIC, 5, __u32) /* ---------- set fw and apps cmac --------------------------------- */ /* Asym , Crypt , Keym + 3rd party uefi apps */ #define MAX_SPU_UEFI_APPS 8 /** use variable-size-array for future growth */ struct spss_ioc_set_fw_and_apps_cmac { __u64 cmac_buf_ptr; /* * expected cmac_buf_size is: * (1+MAX_SPU_UEFI_APPS)*CMAC_SIZE_IN_WORDS*sizeof(uint32_t) */ __u32 cmac_buf_size; __u32 num_of_cmacs; } __attribute__((packed)); #define SPSS_IOC_SET_FW_AND_APPS_CMAC \ _IOWR(SPSS_IOC_MAGIC, 6, struct spss_ioc_set_fw_and_apps_cmac) #endif /* _UAPI_SPSS_UTILS_H_ */ Loading
drivers/soc/qcom/spss_utils.c +202 −286 Original line number Diff line number Diff line Loading @@ -65,35 +65,53 @@ static u32 spss_emul_type_reg_addr; /* TCSR_SOC_EMULATION_TYPE */ static void *iar_notif_handle; static struct notifier_block *iar_nb; static bool is_iar_active; static bool is_ssr_disabled; #define CMAC_SIZE_IN_BYTES (128/8) /* 128 bit = 16 bytes */ #define CMAC_SIZE_IN_DWORDS (CMAC_SIZE_IN_BYTES/sizeof(u32)) /* 4 dwords */ /* Asym , Crypt , Keym */ #define NUM_UEFI_APPS 3 static u32 pil_addr; static u32 pil_size; static u32 cmac_buf[CMAC_SIZE_IN_DWORDS]; /* saved cmac */ static u32 pbl_cmac_buf[CMAC_SIZE_IN_DWORDS]; /* pbl cmac */ static u32 calc_apps_cmac[NUM_UEFI_APPS][CMAC_SIZE_IN_DWORDS]; static u32 saved_apps_cmac[NUM_UEFI_APPS][CMAC_SIZE_IN_DWORDS]; /* * The saved fw cmac is stored in file in IAR-DB. * It is provided via ioctl from user space spu service. */ static u32 saved_fw_cmac[CMAC_SIZE_IN_DWORDS]; /* saved fw cmac */ #define FW_AND_APPS_CMAC_SIZE \ (CMAC_SIZE_IN_DWORDS + NUM_UEFI_APPS*CMAC_SIZE_IN_DWORDS) /* * The calculated fw cmac is calculated by SPU PBL. * It is read from shared memory and provided back to user space service * via device attribute. */ static u32 calc_fw_cmac[CMAC_SIZE_IN_DWORDS]; /* calculated pbl fw cmac */ static u32 iar_state; static bool is_iar_enabled; static bool ssr_disabled_flag; /* * The saved apps cmac is stored in file in IAR-DB. * It is provided via ioctl from user space spu service. */ static u32 saved_apps_cmac[MAX_SPU_UEFI_APPS][CMAC_SIZE_IN_DWORDS]; /* * The calculated apps cmac is calculated by SPU firmware. * It is read from shared memory and provided back to user space service * via device attribute. */ static u32 calc_apps_cmac[MAX_SPU_UEFI_APPS][CMAC_SIZE_IN_DWORDS]; static void __iomem *cmac_mem; static size_t cmac_mem_size = SZ_4K; /* XPU align to 4KB */ static phys_addr_t cmac_mem_addr; #define CMAC_MEM_SIZE SZ_4K /* XPU align to 4KB */ #define SPSS_BASE_ADDR_MASK 0xFFFF0000 #define SPSS_RMB_CODE_SIZE_REG_OFFSET 0x1008 #define SPU_EMULATUION (BIT(0) | BIT(1)) #define SPU_PRESENT_IN_EMULATION BIT(0) /* IOCTL max request size is 1KB */ #define MAX_IOCTL_REQ_SIZE 1024 /* Events notification */ static struct completion spss_events[SPSS_NUM_EVENTS]; static bool spss_events_signaled[SPSS_NUM_EVENTS]; Loading @@ -117,12 +135,12 @@ struct spss_utils_device { static struct spss_utils_device *spss_utils_dev; /* static functions declaration */ static int spss_set_fw_cmac(u32 *cmac, size_t cmac_size); static int spss_get_pbl_and_apps_calc_cmac(void); static int spss_get_saved_uefi_apps_cmac(void); static int spss_set_saved_fw_cmac(u32 *cmac, size_t cmac_size); static int spss_set_saved_uefi_apps_cmac(void); static int spss_get_fw_calc_cmac(void); static int spss_get_apps_calc_cmac(void); /*==========================================================================*/ /* Device Sysfs */ /*==========================================================================*/ Loading Loading @@ -213,85 +231,26 @@ static ssize_t spss_debug_reg_show(struct device *dev, static DEVICE_ATTR_RO(spss_debug_reg); static ssize_t cmac_buf_show(struct device *dev, static ssize_t calc_fw_cmac_show(struct device *dev, struct device_attribute *attr, char *buf) { int ret = 0; if (!dev || !attr || !buf) { pr_err("invalid param.\n"); return -EINVAL; } ret = snprintf(buf, PAGE_SIZE, "0x%08x,0x%08x,0x%08x,0x%08x\n", cmac_buf[0], cmac_buf[1], cmac_buf[2], cmac_buf[3]); return ret; } static DEVICE_ATTR_RO(cmac_buf); /* first make sure the calc cmac is updated */ spss_get_fw_calc_cmac(); static ssize_t iar_state_show(struct device *dev, struct device_attribute *attr, char *buf) { int ret = 0; memcpy(buf, calc_fw_cmac, sizeof(calc_fw_cmac)); if (!dev || !attr || !buf) { pr_err("invalid param.\n"); return -EINVAL; } /* show IAR-STATE from soc fuse */ ret = snprintf(buf, PAGE_SIZE, "0x%x\n", iar_state); return ret; } static DEVICE_ATTR_RO(iar_state); static ssize_t iar_enabled_show(struct device *dev, struct device_attribute *attr, char *buf) { int ret = 0; if (!dev || !attr || !buf) { pr_err("invalid param.\n"); return -EINVAL; } ret = snprintf(buf, PAGE_SIZE, "0x%x\n", is_iar_enabled); return ret; return sizeof(calc_fw_cmac); } static DEVICE_ATTR_RO(iar_enabled); static DEVICE_ATTR_RO(calc_fw_cmac); static ssize_t pbl_cmac_show(struct device *dev, struct device_attribute *attr, char *buf) { int ret = 0; if (!dev || !attr || !buf) { pr_err("invalid param.\n"); return -EINVAL; } /* first make sure the pbl cmac is updated */ spss_get_pbl_and_apps_calc_cmac(); ret = snprintf(buf, PAGE_SIZE, "0x%08x,0x%08x,0x%08x,0x%08x\n", pbl_cmac_buf[0], pbl_cmac_buf[1], pbl_cmac_buf[2], pbl_cmac_buf[3]); return ret; } static DEVICE_ATTR_RO(pbl_cmac); static ssize_t apps_cmac_show(struct device *dev, static ssize_t calc_apps_cmac_show(struct device *dev, struct device_attribute *attr, char *buf) { if (!dev || !attr || !buf) { Loading @@ -299,15 +258,15 @@ static ssize_t apps_cmac_show(struct device *dev, return -EINVAL; } /* first make sure the pbl cmac is updated */ spss_get_pbl_and_apps_calc_cmac(); /* first make sure the calc cmac is updated */ spss_get_apps_calc_cmac(); memcpy(buf, calc_apps_cmac, sizeof(calc_apps_cmac)); return sizeof(calc_apps_cmac); } static DEVICE_ATTR_RO(apps_cmac); static DEVICE_ATTR_RO(calc_apps_cmac); /*--------------------------------------------------------------------------*/ static int spss_create_sysfs(struct device *dev) Loading @@ -332,47 +291,23 @@ static int spss_create_sysfs(struct device *dev) goto remove_test_fuse_state; } ret = device_create_file(dev, &dev_attr_cmac_buf); ret = device_create_file(dev, &dev_attr_calc_fw_cmac); if (ret < 0) { pr_err("failed to create sysfs file for cmac_buf.\n"); pr_err("failed to create sysfs file for calc_fw_cmac.\n"); goto remove_spss_debug_reg; } ret = device_create_file(dev, &dev_attr_iar_state); if (ret < 0) { pr_err("failed to create sysfs file for iar_state.\n"); goto remove_cmac_buf; } ret = device_create_file(dev, &dev_attr_iar_enabled); if (ret < 0) { pr_err("failed to create sysfs file for iar_enabled.\n"); goto remove_iar_state; } ret = device_create_file(dev, &dev_attr_pbl_cmac); if (ret < 0) { pr_err("failed to create sysfs file for pbl_cmac.\n"); goto remove_iar_enabled; } ret = device_create_file(dev, &dev_attr_apps_cmac); ret = device_create_file(dev, &dev_attr_calc_apps_cmac); if (ret < 0) { pr_err("failed to create sysfs file for apps_cmac.\n"); goto remove_pbl_cmac; pr_err("failed to create sysfs file for calc_apps_cmac.\n"); goto remove_calc_fw_cmac; } return 0; remove_pbl_cmac: device_remove_file(dev, &dev_attr_pbl_cmac); remove_iar_enabled: device_remove_file(dev, &dev_attr_iar_enabled); remove_iar_state: device_remove_file(dev, &dev_attr_iar_state); remove_cmac_buf: device_remove_file(dev, &dev_attr_cmac_buf); remove_calc_fw_cmac: device_remove_file(dev, &dev_attr_calc_fw_cmac); remove_spss_debug_reg: device_remove_file(dev, &dev_attr_spss_debug_reg); remove_test_fuse_state: Loading @@ -385,11 +320,8 @@ static int spss_create_sysfs(struct device *dev) static void spss_destroy_sysfs(struct device *dev) { device_remove_file(dev, &dev_attr_apps_cmac); device_remove_file(dev, &dev_attr_pbl_cmac); device_remove_file(dev, &dev_attr_iar_enabled); device_remove_file(dev, &dev_attr_iar_state); device_remove_file(dev, &dev_attr_cmac_buf); device_remove_file(dev, &dev_attr_calc_apps_cmac); device_remove_file(dev, &dev_attr_calc_fw_cmac); device_remove_file(dev, &dev_attr_spss_debug_reg); device_remove_file(dev, &dev_attr_test_fuse_state); device_remove_file(dev, &dev_attr_firmware_name); Loading Loading @@ -499,16 +431,70 @@ static int spss_is_event_signaled(struct spss_ioc_is_signaled *req) return 0; } static int spss_handle_set_fw_and_apps_cmac(struct spss_ioc_set_fw_and_apps_cmac *req) { int ret = 0; u32 cmac_buf_size = req->cmac_buf_size; void __user *cmac_buf_ptr = u64_to_user_ptr(req->cmac_buf_ptr); u32 num_of_cmacs = req->num_of_cmacs; /* Saved cmacs of spu firmware and UEFI loaded spu apps */ u32 fw_and_apps_cmacs[1+MAX_SPU_UEFI_APPS][CMAC_SIZE_IN_DWORDS]; pr_debug("cmac_buf_size [0x%x].\n", (int) req->cmac_buf_size); pr_debug("cmac_buf_ptr [0x%x].\n", (int) req->cmac_buf_ptr); pr_debug("num_of_cmacs [0x%x].\n", (int) req->num_of_cmacs); if (cmac_buf_size != sizeof(fw_and_apps_cmacs)) { pr_err("cmac_buf_size [0x%x] invalid.\n", cmac_buf_size); return -EINVAL; } if (num_of_cmacs > (u32)(MAX_SPU_UEFI_APPS+1)) { pr_err("num_of_cmacs [0x%x] invalid.\n", num_of_cmacs); return -EINVAL; } /* copy the saved cmacs from user buffer to loacl variable */ ret = copy_from_user(fw_and_apps_cmacs, cmac_buf_ptr, cmac_buf_size); if (ret < 0) { pr_err("copy_from_user() from cmac_buf_ptr failed.\n"); return -EFAULT; } /* store the saved fw cmac */ memcpy(saved_fw_cmac, fw_and_apps_cmacs[0], sizeof(saved_fw_cmac)); pr_debug("saved fw cmac: 0x%08x,0x%08x,0x%08x,0x%08x\n", saved_fw_cmac[0], saved_fw_cmac[1], saved_fw_cmac[2], saved_fw_cmac[3]); /* store the saved apps cmac */ memcpy(saved_apps_cmac, fw_and_apps_cmacs[1], sizeof(saved_apps_cmac)); /* * SPSS is loaded now by UEFI, * so PIL-IAR-callback is not being called on power-up by PIL. * therefore get the saved spu fw cmac and apps cmac from ioctl. * The PIL-IAR-callback shall be called on spss SSR. * The saved cmacs are used on SUBSYS_BEFORE_AUTH_AND_RESET event ! */ spss_set_saved_fw_cmac(saved_fw_cmac, sizeof(saved_fw_cmac)); spss_set_saved_uefi_apps_cmac(); pr_debug("completed ok\n"); return 0; } static long spss_utils_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int ret; void *buf = (void *) arg; unsigned char data[64] = {0}; uint8_t data[MAX_IOCTL_REQ_SIZE] = {0}; size_t size = 0; u32 i = 0; /* Saved cmacs of spu firmware and UEFI loaded spu apps */ u32 fw_and_apps_cmacs[FW_AND_APPS_CMAC_SIZE]; void *req = (void *) data; if (buf == NULL) { Loading @@ -532,36 +518,23 @@ static long spss_utils_ioctl(struct file *file, } switch (cmd) { case SPSS_IOC_SET_FW_CMAC: if (size != sizeof(fw_and_apps_cmacs)) { pr_err("cmd [0x%x] invalid size [0x%x]\n", cmd, size); return -EINVAL; } case SPSS_IOC_SET_FW_AND_APPS_CMAC: pr_debug("ioctl [SPSS_IOC_SET_FW_AND_APPS_CMAC]\n"); /* spdaemon uses this ioctl only when IAR is active */ is_iar_active = true; memcpy(fw_and_apps_cmacs, data, sizeof(fw_and_apps_cmacs)); memcpy(cmac_buf, fw_and_apps_cmacs, sizeof(cmac_buf)); for (i = 0; i < NUM_UEFI_APPS; ++i) { int x = (i+1)*CMAC_SIZE_IN_DWORDS; memcpy(saved_apps_cmac[i], fw_and_apps_cmacs + x, CMAC_SIZE_IN_BYTES); if (cmac_mem == NULL) { cmac_mem = ioremap_nocache(cmac_mem_addr, CMAC_MEM_SIZE); if (!cmac_mem) { pr_err("can't map cmac_mem.\n"); return -EFAULT; } } /* * SPSS is loaded now by UEFI, * so IAR callback is not being called on power-up by PIL. * therefore read the spu pbl fw cmac and apps cmac from ioctl. * The callback shall be called on spss SSR. */ pr_debug("read pbl cmac from shared memory\n"); spss_set_fw_cmac(cmac_buf, sizeof(cmac_buf)); spss_set_saved_uefi_apps_cmac(); spss_get_saved_uefi_apps_cmac(); ret = spss_handle_set_fw_and_apps_cmac(req); if (ret < 0) return ret; break; case SPSS_IOC_WAIT_FOR_EVENT: Loading Loading @@ -608,9 +581,9 @@ static long spss_utils_ioctl(struct file *file, } if (is_iar_active) { memcpy(&ssr_disabled_flag, data, size); memcpy(&is_ssr_disabled, data, size); pr_debug("SSR disabled state updated to: %d\n", ssr_disabled_flag); is_ssr_disabled); } break; Loading Loading @@ -700,6 +673,30 @@ static void spss_utils_destroy_chardev(void) /* Device Tree */ /*==========================================================================*/ /* get the ACTUAL spss PIL firmware size from spu reg */ static int get_pil_size(phys_addr_t base_addr) { u32 spss_code_size_addr = 0; void __iomem *spss_code_size_reg = NULL; u32 pil_size = 0; spss_code_size_addr = base_addr + SPSS_RMB_CODE_SIZE_REG_OFFSET; spss_code_size_reg = ioremap_nocache(spss_code_size_addr, sizeof(u32)); if (!spss_code_size_reg) { pr_err("can't map spss_code_size_addr\n"); return -EINVAL; } pil_size = readl_relaxed(spss_code_size_reg); iounmap(spss_code_size_reg); if (pil_size % SZ_4K) { pr_err("pil_size [0x%08x] is not 4K aligned.\n", pil_size); return -EFAULT; } return pil_size; } /** * spss_parse_dt() - Parse Device Tree info. */ Loading @@ -714,22 +711,13 @@ static int spss_parse_dt(struct device_node *node) u32 spss_fuse2_bit = 0; u32 spss_fuse2_mask = 0; void __iomem *spss_fuse2_reg = NULL; /* IAR_FEATURE_ENABLED soc fuse */ u32 spss_fuse3_addr = 0; u32 spss_fuse3_bit = 0; u32 spss_fuse3_mask = 0; void __iomem *spss_fuse3_reg = NULL; /* IAR_STATE soc fuses */ u32 spss_fuse4_addr = 0; u32 spss_fuse4_bit = 0; u32 spss_fuse4_mask = 0; void __iomem *spss_fuse4_reg = NULL; struct device_node *np; struct resource r; u32 val1 = 0; u32 val2 = 0; void __iomem *spss_emul_type_reg = NULL; u32 spss_emul_type_val = 0; phys_addr_t spss_regs_base_addr = 0; ret = of_property_read_string(node, "qcom,spss-dev-firmware-name", &dev_firmware_name); Loading Loading @@ -884,12 +872,14 @@ static int spss_parse_dt(struct device_node *node) pil_addr = (u32)r.start; } ret = of_property_read_u32(node, "qcom,pil-size", &pil_size); spss_regs_base_addr = (spss_debug_reg_addr & SPSS_BASE_ADDR_MASK); ret = get_pil_size(spss_regs_base_addr); if (ret < 0) { pr_err("can't get pil_size\n"); pr_err("failed to get pil_size.\n"); return -EFAULT; } pil_size = (u32) ret; pr_debug("pil_addr [0x%08x].\n", pil_addr); pr_debug("pil_size [0x%08x].\n", pil_size); Loading @@ -898,146 +888,64 @@ static int spss_parse_dt(struct device_node *node) cmac_mem_addr = pil_addr + pil_size; pr_info("iar_buf_addr [0x%08x].\n", cmac_mem_addr); ret = of_property_read_u32(node, "qcom,spss-fuse3-addr", &spss_fuse3_addr); if (ret < 0) { pr_err("can't get fuse3 addr.\n"); return -EFAULT; } ret = of_property_read_u32(node, "qcom,spss-fuse3-bit", &spss_fuse3_bit); if (ret < 0) { pr_err("can't get fuse3 bit.\n"); return -EFAULT; } spss_fuse3_reg = ioremap_nocache(spss_fuse3_addr, sizeof(u32)); if (!spss_fuse3_reg) { pr_err("can't map fuse3 addr.\n"); return -EFAULT; } /* read IAR_FEATURE_ENABLED from soc fuse */ val1 = readl_relaxed(spss_fuse3_reg); iounmap(spss_fuse3_reg); spss_fuse3_mask = (1<<spss_fuse3_bit); pr_debug("iar_enabled fuse, addr [0x%x] val [0x%x] mask [0x%x].\n", spss_fuse3_addr, val1, spss_fuse3_mask); if (val1 & spss_fuse3_mask) is_iar_enabled = true; else is_iar_enabled = false; memset(cmac_buf, 0xA5, sizeof(cmac_buf)); ret = of_property_read_u32(node, "qcom,spss-fuse4-addr", &spss_fuse4_addr); if (ret < 0) { pr_err("can't get fuse4 addr.\n"); return -EFAULT; } ret = of_property_read_u32(node, "qcom,spss-fuse4-bit", &spss_fuse4_bit); if (ret < 0) { pr_err("can't get fuse4 bit.\n"); return -EFAULT; } spss_fuse4_reg = ioremap_nocache(spss_fuse4_addr, sizeof(u32)); if (!spss_fuse4_reg) { pr_err("can't map fuse4 addr.\n"); return -EFAULT; } val1 = readl_relaxed(spss_fuse4_reg); iounmap(spss_fuse4_reg); spss_fuse4_mask = (0x07 << spss_fuse4_bit); /* 3 bits */ pr_debug("IAR_STATE fuse, addr [0x%x] val [0x%x] mask [0x%x].\n", spss_fuse4_addr, val1, spss_fuse4_mask); val1 = ((val1 & spss_fuse4_mask) >> spss_fuse4_bit) & 0x07; iar_state = val1; pr_debug("iar_state [%d]\n", iar_state); memset(saved_fw_cmac, 0xA5, sizeof(saved_fw_cmac)); memset(saved_apps_cmac, 0xA5, sizeof(saved_apps_cmac)); return 0; } static int spss_set_fw_cmac(u32 *cmac, size_t cmac_size) static int spss_set_saved_fw_cmac(u32 *cmac, size_t cmac_size) { u8 __iomem *reg = NULL; int i; if (cmac_mem == NULL) { cmac_mem = ioremap_nocache(cmac_mem_addr, cmac_mem_size); if (!cmac_mem) { pr_err("can't map cmac_mem.\n"); pr_err("invalid cmac_mem.\n"); return -EFAULT; } } pr_debug("pil_addr [0x%x]\n", pil_addr); pr_debug("pil_size [0x%x]\n", pil_size); pr_debug("cmac_mem [%pK]\n", cmac_mem); reg = cmac_mem; pr_debug("reg [%pK]\n", reg); for (i = 0; i < cmac_size/4; i++) { for (i = 0; i < cmac_size/sizeof(u32); i++) writel_relaxed(cmac[i], reg + i*sizeof(u32)); pr_debug("cmac[%d] [0x%x]\n", i, cmac[i]); } reg += cmac_size; pr_debug("saved fw cmac: 0x%08x,0x%08x,0x%08x,0x%08x\n", cmac[0], cmac[1], cmac[2], cmac[3]); return 0; } static int spss_get_pbl_and_apps_calc_cmac(void) static int spss_get_fw_calc_cmac(void) { u8 __iomem *reg = NULL; int i, j; int i; u32 val; if (cmac_mem == NULL) if (cmac_mem == NULL) { pr_err("invalid cmac_mem.\n"); return -EFAULT; } reg = cmac_mem; /* IAR buffer base */ reg += CMAC_SIZE_IN_BYTES; /* skip the saved cmac */ pr_debug("reg [%pK]\n", reg); /* get pbl fw cmac from ddr */ for (i = 0; i < CMAC_SIZE_IN_DWORDS; i++) { val = readl_relaxed(reg); pbl_cmac_buf[i] = val; reg += sizeof(u32); } reg += CMAC_SIZE_IN_BYTES; /* skip the saved cmac */ pr_debug("pbl_cmac_buf : 0x%08x,0x%08x,0x%08x,0x%08x\n", pbl_cmac_buf[0], pbl_cmac_buf[1], pbl_cmac_buf[2], pbl_cmac_buf[3]); memset(calc_fw_cmac, 0, sizeof(calc_fw_cmac)); /* get apps cmac from ddr */ for (j = 0; j < NUM_UEFI_APPS; j++) { /* get pbl fw cmac from ddr */ for (i = 0; i < CMAC_SIZE_IN_DWORDS; i++) { val = readl_relaxed(reg); calc_apps_cmac[j][i] = val; calc_fw_cmac[i] = val; reg += sizeof(u32); } reg += CMAC_SIZE_IN_BYTES; /* skip the saved cmac */ pr_debug("app [%d] cmac : 0x%08x,0x%08x,0x%08x,0x%08x\n", j, calc_apps_cmac[j][0], calc_apps_cmac[j][1], calc_apps_cmac[j][2], calc_apps_cmac[j][3]); } pr_debug("calc_fw_cmac : 0x%08x,0x%08x,0x%08x,0x%08x\n", calc_fw_cmac[0], calc_fw_cmac[1], calc_fw_cmac[2], calc_fw_cmac[3]); return 0; } static int spss_get_saved_uefi_apps_cmac(void) static int spss_get_apps_calc_cmac(void) { u8 __iomem *reg = NULL; int i, j; Loading @@ -1047,22 +955,29 @@ static int spss_get_saved_uefi_apps_cmac(void) return -EFAULT; reg = cmac_mem; /* IAR buffer base */ reg += (2*CMAC_SIZE_IN_BYTES); /* skip the saved and calc fw cmac */ pr_debug("reg [%pK]\n", reg); reg += CMAC_SIZE_IN_BYTES; /* skip the saved fw cmac */ reg += CMAC_SIZE_IN_BYTES; /* skip the calc fw cmac */ reg += CMAC_SIZE_IN_BYTES; /* skip the saved 1st app cmac */ /* get saved apps cmac from ddr - were written by UEFI spss driver */ for (j = 0; j < NUM_UEFI_APPS; j++) { memset(calc_apps_cmac, 0, sizeof(calc_apps_cmac)); /* get apps cmac from ddr */ for (j = 0; j < ARRAY_SIZE(calc_apps_cmac); j++) { for (i = 0; i < CMAC_SIZE_IN_DWORDS; i++) { val = readl_relaxed(reg); saved_apps_cmac[j][i] = val; calc_apps_cmac[j][i] = val; reg += sizeof(u32); } reg += CMAC_SIZE_IN_BYTES; /* skip the calc cmac */ reg += CMAC_SIZE_IN_BYTES; /* skip the saved cmac */ pr_debug("app[%d] saved cmac: 0x%08x,0x%08x,0x%08x,0x%08x\n", j, saved_apps_cmac[j][0], saved_apps_cmac[j][1], saved_apps_cmac[j][2], saved_apps_cmac[j][3]); /* check for any pattern to mark end of cmacs */ if (saved_apps_cmac[j][0] == saved_apps_cmac[j][1]) { memset(calc_apps_cmac[j], 0, sizeof(calc_apps_cmac[j])); break; /* no more cmacs */ } pr_debug("app [%d] cmac : 0x%08x,0x%08x,0x%08x,0x%08x\n", j, calc_apps_cmac[j][0], calc_apps_cmac[j][1], calc_apps_cmac[j][2], calc_apps_cmac[j][3]); } return 0; Loading @@ -1079,10 +994,11 @@ static int spss_set_saved_uefi_apps_cmac(void) reg = cmac_mem; /* IAR buffer base */ reg += (2*CMAC_SIZE_IN_BYTES); /* skip the saved and calc fw cmac */ pr_debug("reg [%pK]\n", reg); /* get saved apps cmac from ddr - were written by UEFI spss driver */ for (j = 0; j < NUM_UEFI_APPS; j++) { for (j = 0; j < MAX_SPU_UEFI_APPS; j++) { if (saved_apps_cmac[j][0] == saved_apps_cmac[j][1]) break; /* no more cmacs */ for (i = 0; i < CMAC_SIZE_IN_DWORDS; i++) { val = saved_apps_cmac[j][i]; writel_relaxed(val, reg); Loading Loading @@ -1132,8 +1048,8 @@ static int spss_utils_pil_callback(struct notifier_block *nb, break; case SUBSYS_BEFORE_POWERUP: pr_debug("[SUBSYS_BEFORE_POWERUP] event.\n"); if (is_iar_active && ssr_disabled_flag) { pr_warn("SPSS SSR disabled, requesting reboot\n"); if (is_iar_active && is_ssr_disabled) { pr_err("SPSS SSR disabled, requesting reboot\n"); kernel_restart("SPSS SSR disabled, requesting reboot"); } break; Loading @@ -1159,12 +1075,12 @@ static int spss_utils_pil_callback(struct notifier_block *nb, pr_debug("[SUBSYS_PROXY_UNVOTE] event.\n"); break; case SUBSYS_BEFORE_AUTH_AND_RESET: pr_debug("[SUBSYS_BEFORE_AUTH_AND_RESET] event.\n"); /* do nothing if IAR is not active */ if (!is_iar_active) return NOTIFY_OK; pr_debug("[SUBSYS_BEFORE_AUTH_AND_RESET] event.\n"); /* Called on SSR as spss firmware is loaded by UEFI */ spss_set_fw_cmac(cmac_buf, sizeof(cmac_buf)); /* Called on SSR as spss firmware is loaded by UEFI on boot */ spss_set_saved_fw_cmac(saved_fw_cmac, sizeof(saved_fw_cmac)); spss_set_saved_uefi_apps_cmac(); break; default: Loading Loading @@ -1253,7 +1169,7 @@ static int spss_probe(struct platform_device *pdev) } mutex_init(&event_lock); ssr_disabled_flag = false; is_ssr_disabled = false; pr_info("Probe completed successfully, [%s].\n", firmware_name); Loading
include/uapi/linux/spss_utils.h +25 −2 Original line number Diff line number Diff line Loading @@ -19,12 +19,14 @@ #define SPSS_IOC_MAGIC 'S' /* ---------- set fw cmac --------------------------------- */ #define NUM_SPU_UEFI_APPS 3 #define OLD_NUM_SPU_UEFI_APPS 3 /* Obsolete */ #define CMAC_SIZE_IN_WORDS 4 /* Obsolete struct, keep for backward compatible */ struct spss_ioc_set_fw_cmac { __u32 cmac[CMAC_SIZE_IN_WORDS]; __u32 app_cmacs[NUM_SPU_UEFI_APPS][CMAC_SIZE_IN_WORDS]; __u32 apps_cmac[OLD_NUM_SPU_UEFI_APPS][CMAC_SIZE_IN_WORDS]; } __packed; #define SPSS_IOC_SET_FW_CMAC \ Loading Loading @@ -78,7 +80,28 @@ struct spss_ioc_is_signaled { #define SPSS_IOC_IS_EVENT_SIGNALED \ _IOWR(SPSS_IOC_MAGIC, 4, struct spss_ioc_is_signaled) /* ---------- set ssr state ------------------------------ */ #define SPSS_IOC_SET_SSR_STATE \ _IOWR(SPSS_IOC_MAGIC, 5, __u32) /* ---------- set fw and apps cmac --------------------------------- */ /* Asym , Crypt , Keym + 3rd party uefi apps */ #define MAX_SPU_UEFI_APPS 8 /** use variable-size-array for future growth */ struct spss_ioc_set_fw_and_apps_cmac { __u64 cmac_buf_ptr; /* * expected cmac_buf_size is: * (1+MAX_SPU_UEFI_APPS)*CMAC_SIZE_IN_WORDS*sizeof(uint32_t) */ __u32 cmac_buf_size; __u32 num_of_cmacs; } __attribute__((packed)); #define SPSS_IOC_SET_FW_AND_APPS_CMAC \ _IOWR(SPSS_IOC_MAGIC, 6, struct spss_ioc_set_fw_and_apps_cmac) #endif /* _UAPI_SPSS_UTILS_H_ */