mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-20 14:16:02 +00:00
![Arjan van de Ven](/assets/img/avatar_default.png)
Many struct file_operations in the kernel can be "const". Marking them const moves these to the .rodata section, which avoids false sharing with potential dirty data. In addition it'll catch accidental writes at compile time to these shared resources. [akpm@sdl.org: dvb fix] Signed-off-by: Arjan van de Ven <arjan@linux.intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
131 lines
2.5 KiB
C
131 lines
2.5 KiB
C
/*
|
|
* /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 (!access_ok(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 (!access_ok(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;
|
|
}
|
|
|
|
const 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");
|