[T106][ZXW-22]7520V3SCV2.01.01.02P42U09_VEC_V0.8_AP_VEC origin source commit

Change-Id: Ic6e05d89ecd62fc34f82b23dcf306c93764aec4b
diff --git a/ap/os/linux/linux-3.4.x/drivers/cpnv/Kconfig b/ap/os/linux/linux-3.4.x/drivers/cpnv/Kconfig
new file mode 100755
index 0000000..846958b
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/drivers/cpnv/Kconfig
@@ -0,0 +1,6 @@
+# cp nv for libcpnv
+config CPNV
+	bool "Read/Write cp nv for application via libcpnv"
+	default n
+	---help---
+	  read/write cp nv for application
diff --git a/ap/os/linux/linux-3.4.x/drivers/cpnv/Makefile b/ap/os/linux/linux-3.4.x/drivers/cpnv/Makefile
new file mode 100755
index 0000000..ad68313
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/drivers/cpnv/Makefile
@@ -0,0 +1,3 @@
+EXTRA_CFLAGS   += 
+
+obj-$(CONFIG_CPNV)  += cpnv.o
diff --git a/ap/os/linux/linux-3.4.x/drivers/cpnv/cpnv.c b/ap/os/linux/linux-3.4.x/drivers/cpnv/cpnv.c
new file mode 100755
index 0000000..9282fc2
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/drivers/cpnv/cpnv.c
@@ -0,0 +1,271 @@
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/proc_fs.h>
+#include <linux/uaccess.h>
+#include <linux/cdev.h>
+#include <linux/cpnv.h>
+#include <linux/vmalloc.h>
+#include <linux/string.h>
+#include <linux/cp_types.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/syscalls.h>
+
+#ifndef USE_CPPS_KO
+extern UINT32 zOss_NvItemWrite(UINT32 NvItemID, UINT8 * NvItemData, UINT32 NvItemLen);
+extern UINT32 zOss_NvItemRead(UINT32 NvItemID, UINT8 * NvItemData, UINT32 NvItemLen);
+extern UINT32 zOss_ResetNVFactory(VOID);
+extern UINT32 zOss_NvramFlush(VOID);
+extern UINT32 zOss_NvItemWriteFactory(UINT32 NvItemID, UINT8 * NvItemData, UINT32 NvItemLen);
+#endif
+
+extern int quick_gc_wait_done(const char *mtd_name);
+
+#define CPNV_DEVNAME "cpnv"
+struct class *class_cpnv;
+static struct semaphore cpnv_sem;
+
+struct cpnv_dev_t {
+	struct cdev cdev;
+	dev_t devt;
+} cpnv_dev;
+
+static int cpnv_open(struct inode *inode, struct file *file)
+{
+	file->private_data = (void *)(&cpnv_dev);
+
+	return 0;
+}
+
+static int cpnv_release(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+static ssize_t cpnv_read(struct file *file, char *buf, size_t count, loff_t * ppos)
+{
+	char tmp[128] = { 0 };
+	char *itemBuf = tmp;
+	UINT32 NvItemID = 0;
+	ssize_t ret;
+	UINT32 zoss_ret;
+
+	if (!buf) {
+		printk(KERN_WARNING "Error cpnv :  %s %d\n", __FILE__, __LINE__);
+		return -ENODATA;
+	}
+
+	if (count > sizeof(tmp)) {
+		itemBuf = vmalloc(count);
+		if (NULL == itemBuf) {
+			printk(KERN_ERR "cpnv_read vmalloc fail \n");
+			return -ENOMEM;
+		}
+	}
+
+	if (copy_from_user(itemBuf, buf, count)) {
+		printk(KERN_WARNING "cpnv_read() copy_from_user error! \n");
+		ret = -EFAULT;
+		goto out;
+	}
+	memcpy(&NvItemID, itemBuf, sizeof(NvItemID));
+
+	down(&cpnv_sem);
+	zoss_ret = CPPS_FUNC(cpps_callbacks, zOss_NvItemRead)(NvItemID, itemBuf, count);
+	up(&cpnv_sem);
+	if (zoss_ret != ZOSS_SUCCESS) {
+		ret = -EFAULT;
+		goto out;
+	}
+
+	if (copy_to_user(buf, itemBuf, count)) {
+		ret = -EFAULT;
+		goto out;
+	}
+	ret = count;
+
+out:
+	if (itemBuf != tmp) {
+		vfree(itemBuf);
+	}
+
+	return ret;
+}
+
+static ssize_t cpnv_write(struct file *file, const char *buf, size_t count, loff_t * ppos)
+{
+	char tmp[128] = { 0 };
+	char *tmpBuf = tmp;
+	ssize_t ret = 0;
+	UINT32 zoss_ret = ZOSS_ERROR;
+	struct cpnv_readwrite_head *phead = (struct cpnv_readwrite_head *)buf;
+
+	if (!phead) {
+		printk(KERN_WARNING "Error:  %s %d\n", __FILE__, __LINE__);
+		return -ENODATA;
+	}
+
+	if (count > sizeof(tmp)) {
+		if (!(tmpBuf = vmalloc(count))) {
+			printk(KERN_ERR "cpnv_write() vmalloc fail \n");
+			return -ENOMEM;
+		}
+	}
+
+	if (copy_from_user(tmpBuf, buf, count)) {
+		ret = -EFAULT;
+		goto out;
+	}
+
+	down(&cpnv_sem);
+	switch (phead->direction) {
+	case TO_NVRO:
+	case TO_NVRW:
+		zoss_ret = CPPS_FUNC(cpps_callbacks, zOss_NvItemWrite)(phead->NvItemID, phead->NvItemData, phead->NvItemLen);
+		break;
+	case TO_NVFAC:
+		CPPS_FUNC(cpps_callbacks, zOss_NvItemWriteFactory)(phead->NvItemID, phead->NvItemData, phead->NvItemLen);
+		zoss_ret = 0;
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	up(&cpnv_sem);
+
+	if (zoss_ret == ZOSS_SUCCESS)
+		ret = count;
+	else {
+		printk(KERN_ERR "cpnv_write error\n");
+		ret = -EFAULT;
+	}
+
+out:
+	if (tmpBuf != tmp) {
+		vfree(tmpBuf);
+	}
+	return ret;
+}
+
+static long cpnv_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	long ret = 0;
+	UINT32 zoss_ret = ZOSS_ERROR;
+
+	switch (cmd) {
+	case CPNV_IOIOCTL_FLUSH:
+		down(&cpnv_sem);
+		zoss_ret = CPPS_FUNC(cpps_callbacks, zOss_NvramFlush)();
+		if (ZOSS_SUCCESS != zoss_ret) {
+			ret = -EFAULT;
+			printk(KERN_ERR "cpnv CPNV_IOIOCTL_FLUSH error\n");
+		}
+		up(&cpnv_sem);
+		break;
+
+	case CPNV_IOIOCTL_RESETNVFACTORY:
+		down(&cpnv_sem);
+		zoss_ret = CPPS_FUNC(cpps_callbacks, zOss_ResetNVFactory)();
+		if (ZOSS_SUCCESS != zoss_ret) {
+			ret = -EFAULT;
+			printk(KERN_ERR "cpnv CPNV_IOIOCTL_RESETNVFACTORY error\n");
+		}
+		up(&cpnv_sem);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static int cpnv_Remount(char *DevName, char *DirName, char *Type, unsigned int Flag)
+{
+	int ret = 0;
+	mm_segment_t old_fs = get_fs();
+
+	set_fs(KERNEL_DS);
+	ret = sys_mount(DevName, DirName, Type, Flag , 0);
+	if(ret == EBUSY)
+		ret = -1;
+	set_fs(old_fs);
+
+	return ret;
+}
+
+int cpnv_ChangeNvroAttr(int writable)
+{
+	int ret = 0;
+
+	if(writable) {
+		ret = cpnv_Remount("mtd:nvrofs", "/mnt/nvrofs", "jffs2", MS_REMOUNT |MS_VERBOSE);
+	}
+	else {
+		quick_gc_wait_done("nvrofs");
+		ret = cpnv_Remount("mtd:nvrofs", "/mnt/nvrofs", "jffs2", MS_REMOUNT |MS_VERBOSE|MS_RDONLY);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(cpnv_ChangeNvroAttr);
+
+struct file_operations cpnv_fops = {
+	.owner = THIS_MODULE,
+	.open = cpnv_open,
+	.release = cpnv_release,
+	.read = cpnv_read,
+	.write = cpnv_write,
+	.unlocked_ioctl = cpnv_ioctl,
+	.mmap = NULL,
+};
+
+static int cpnv_init(void)
+{
+	int error = 0;
+
+	printk(KERN_DEBUG "Load cpnv driver\n");
+	cdev_init(&cpnv_dev.cdev, &cpnv_fops);
+	error = alloc_chrdev_region(&cpnv_dev.devt, 0, 1, CPNV_DEVNAME);
+	if (error) {
+		printk(KERN_ERR "cpnv alloc_chrdev_region error\n");
+		return error;
+	}
+
+	class_cpnv = class_create(THIS_MODULE, "cpnv_class");
+	if (class_cpnv == NULL) {
+		unregister_chrdev(cpnv_dev.devt, CPNV_DEVNAME);
+		return -1;
+	}
+
+	if (device_create(class_cpnv, NULL, cpnv_dev.devt, NULL, "cpnv") == NULL) {
+		class_destroy(class_cpnv);
+		unregister_chrdev(cpnv_dev.devt, CPNV_DEVNAME);
+		return -1;
+	}
+
+	error = cdev_add(&cpnv_dev.cdev, cpnv_dev.devt, 1);
+	if (error) {
+		printk(KERN_ERR "cpnv cdev_add error\n");
+		device_destroy(class_cpnv, cpnv_dev.devt);
+		class_destroy(class_cpnv);
+		unregister_chrdev(cpnv_dev.devt, CPNV_DEVNAME);
+		return error;
+	}
+	sema_init(&cpnv_sem, 1);
+
+	return error;
+}
+
+static void cpnv_exit(void)
+{
+	printk(KERN_DEBUG "cpnv driver exit\n");
+	device_destroy(class_cpnv, cpnv_dev.devt);
+	class_destroy(class_cpnv);
+	unregister_chrdev(cpnv_dev.devt, CPNV_DEVNAME);
+	cdev_del(&cpnv_dev.cdev);
+}
+
+late_initcall(cpnv_init);
+module_exit(cpnv_exit);
+MODULE_LICENSE("GPLv2");