Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d09483fe authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "soc: qcom: spss_utils: IAR 3rd party uefi app"

parents 9d792039 f19ffc28
Loading
Loading
Loading
Loading
+202 −286
Original line number Diff line number Diff line
@@ -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];
@@ -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 */
/*==========================================================================*/
@@ -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) {
@@ -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)
@@ -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:
@@ -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);
@@ -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) {
@@ -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:
@@ -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;

@@ -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.
 */
@@ -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);
@@ -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);
@@ -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;
@@ -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;
@@ -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);
@@ -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;
@@ -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:
@@ -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);

+25 −2
Original line number Diff line number Diff line
@@ -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 \
@@ -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_ */