diff -drupN a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c --- a/drivers/mtd/mtdchar.c 2018-08-06 17:23:04.000000000 +0300 +++ b/drivers/mtd/mtdchar.c 2022-06-12 05:28:14.000000000 +0300 @@ -36,6 +36,7 @@ #include #include #include +#include #include @@ -52,6 +53,19 @@ struct mtd_file_info { enum mtd_file_modes mode; }; +struct burn_param_t { + void *buffer; + long length; +}; + +#if IS_ENABLED(CONFIG_AW_SPINAND_SECURE_STORAGE) +struct secblc_op_t { + int item; + unsigned char *buf; + unsigned int len; +}; +#endif + static loff_t mtdchar_lseek(struct file *file, loff_t offset, int orig) { struct mtd_file_info *mfi = file->private_data; @@ -664,6 +678,12 @@ static int mtdchar_ioctl(struct file *fi int ret = 0; u_long size; struct mtd_info_user info; + struct burn_param_t burn_param; + char *boot0_kbuf, *boot1_kbuf; +#if IS_ENABLED(CONFIG_AW_SPINAND_SECURE_STORAGE) + struct secblc_op_t sec_op_st; + char *buf_secure; +#endif pr_debug("MTD_ioctl\n"); @@ -678,6 +698,91 @@ static int mtdchar_ioctl(struct file *fi } switch (cmd) { + case BLKBURNBOOT0: + if (copy_from_user(&burn_param, + (struct burn_param_t __user *)arg, + sizeof(burn_param))) { + pr_err("nand ioctl input arg err\n"); + return -EINVAL; + } + + boot0_kbuf = vmalloc(burn_param.length + 16 * 1024); + if (!boot0_kbuf) + return -ENOMEM; + + if (copy_from_user(boot0_kbuf, + (const void *)burn_param.buffer, burn_param.length)) { + pr_err("nand ioctl input buffer err\n"); + vfree(boot0_kbuf); + return -EINVAL; + } + ret = aw_spinand_mtd_download_boot0(mtd->priv, + burn_param.length, boot0_kbuf); + vfree(boot0_kbuf); + break; + case BLKBURNBOOT1: + if (copy_from_user(&burn_param, + (struct burn_param_t __user *)arg, + sizeof(burn_param))) { + pr_err("nand ioctl input arg err\n"); + return -EINVAL; + } + boot1_kbuf = vmalloc(burn_param.length + 0x10000); + if (!boot1_kbuf) + return -ENOMEM; + + if (copy_from_user(boot1_kbuf, + (const void *)burn_param.buffer, burn_param.length)) { + pr_err("nand ioctl input buffer err\n"); + vfree(boot1_kbuf); + return -EINVAL; + } + ret = aw_spinand_mtd_download_uboot(mtd->priv, + burn_param.length, boot1_kbuf); + vfree(boot1_kbuf); + break; +#if IS_ENABLED(CONFIG_AW_SPINAND_SECURE_STORAGE) + case SECBLK_READ: + if (copy_from_user(&sec_op_st, + (struct secblc_op_t __user *)arg, + sizeof(sec_op_st))) { + pr_err("nand_ioctl input arg err\n"); + return -EINVAL; + } + buf_secure = kmalloc(sec_op_st.len, GFP_KERNEL); + if (buf_secure == NULL) { + pr_err("buf_secure malloc fail!\n"); + return -ENOMEM; + } + ret = aw_spinand_mtd_read_secure_storage(mtd->priv, + sec_op_st.item, buf_secure, sec_op_st.len); + if (copy_to_user(sec_op_st.buf, buf_secure, sec_op_st.len)) + ret = -EFAULT; + kfree(buf_secure); + break; + case SECBLK_WRITE: + if (copy_from_user(&sec_op_st, + (struct secblc_op_t __user *)arg, + sizeof(sec_op_st))) { + pr_err("nand_ioctl input arg err\n"); + return -EINVAL; + } + buf_secure = kmalloc(sec_op_st.len, GFP_KERNEL); + if (buf_secure == NULL) { + pr_err("buf_secure malloc fail!\n"); + return -ENOMEM; + } + if (copy_from_user(buf_secure, + (const void *)sec_op_st.buf, sec_op_st.len)) + ret = -EFAULT; + + ret = aw_spinand_mtd_write_secure_storage(mtd->priv, + sec_op_st.item, buf_secure, sec_op_st.len); + if (copy_to_user(sec_op_st.buf, buf_secure, sec_op_st.len)) + ret = -EFAULT; + kfree(buf_secure); + break; +#endif case MEMGETREGIONCOUNT: if (copy_to_user(argp, &(mtd->numeraseregions), sizeof(int))) return -EFAULT;