[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");