Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | /* * /dev/nvram driver for Power Macintosh. */ #define NVRAM_VERSION "1.0" #include <linux/module.h> #include <linux/types.h> #include <linux/errno.h> #include <linux/fs.h> #include <linux/miscdevice.h> #include <linux/fcntl.h> #include <linux/nvram.h> #include <linux/init.h> #include <linux/smp_lock.h> #include <asm/uaccess.h> #include <asm/nvram.h> #define NVRAM_SIZE 8192 static loff_t nvram_llseek(struct file *file, loff_t offset, int origin) { lock_kernel(); switch (origin) { case 1: offset += file->f_pos; break; case 2: offset += NVRAM_SIZE; break; } if (offset < 0) { unlock_kernel(); return -EINVAL; } file->f_pos = offset; unlock_kernel(); return file->f_pos; } static ssize_t read_nvram(struct file *file, char __user *buf, size_t count, loff_t *ppos) { unsigned int i; char __user *p = buf; if (verify_area(VERIFY_WRITE, buf, count)) return -EFAULT; if (*ppos >= NVRAM_SIZE) return 0; for (i = *ppos; count > 0 && i < NVRAM_SIZE; ++i, ++p, --count) if (__put_user(nvram_read_byte(i), p)) return -EFAULT; *ppos = i; return p - buf; } static ssize_t write_nvram(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { unsigned int i; const char __user *p = buf; char c; if (verify_area(VERIFY_READ, buf, count)) return -EFAULT; if (*ppos >= NVRAM_SIZE) return 0; for (i = *ppos; count > 0 && i < NVRAM_SIZE; ++i, ++p, --count) { if (__get_user(c, p)) return -EFAULT; nvram_write_byte(c, i); } *ppos = i; return p - buf; } static int nvram_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { switch(cmd) { case PMAC_NVRAM_GET_OFFSET: { int part, offset; if (copy_from_user(&part, (void __user*)arg, sizeof(part)) != 0) return -EFAULT; if (part < pmac_nvram_OF || part > pmac_nvram_NR) return -EINVAL; offset = pmac_get_partition(part); if (copy_to_user((void __user*)arg, &offset, sizeof(offset)) != 0) return -EFAULT; break; } default: return -EINVAL; } return 0; } struct file_operations nvram_fops = { .owner = THIS_MODULE, .llseek = nvram_llseek, .read = read_nvram, .write = write_nvram, .ioctl = nvram_ioctl, }; static struct miscdevice nvram_dev = { NVRAM_MINOR, "nvram", &nvram_fops }; int __init nvram_init(void) { printk(KERN_INFO "Macintosh non-volatile memory driver v%s\n", NVRAM_VERSION); return misc_register(&nvram_dev); } void __exit nvram_cleanup(void) { misc_deregister( &nvram_dev ); } module_init(nvram_init); module_exit(nvram_cleanup); MODULE_LICENSE("GPL"); |