mirror of https://github.com/OpenIPC/firmware.git
137 lines
3.7 KiB
Diff
137 lines
3.7 KiB
Diff
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 <linux/mtd/mtd.h>
|
|
#include <linux/mtd/partitions.h>
|
|
#include <linux/mtd/map.h>
|
|
+#include <linux/mtd/aw-spinand.h>
|
|
|
|
#include <asm/uaccess.h>
|
|
|
|
@@ -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;
|