Commit 20e07af7 authored by Finn Thain's avatar Finn Thain Committed by Greg Kroah-Hartman
Browse files

powerpc: Adopt nvram module for PPC64



Adopt nvram module to reduce code duplication. This means CONFIG_NVRAM
becomes available to PPC64 builds. Previously it was only available to
PPC32 builds because it depended on CONFIG_GENERIC_NVRAM.

The IOC_NVRAM_GET_OFFSET ioctl as implemented on PPC64 validates the
offset returned by pmac_get_partition(). Do the same in the nvram module.

Note that the old PPC32 generic_nvram module lacked this test.
So when CONFIG_PPC32 && CONFIG_PPC_PMAC, the IOC_NVRAM_GET_OFFSET ioctl
would have returned 0 (always). But when CONFIG_PPC64 && CONFIG_PPC_PMAC,
the IOC_NVRAM_GET_OFFSET ioctl would have returned -1 (which is -EPERM)
when the requested partition was not found.

With this patch, the result is now -EINVAL on both PPC32 and PPC64 when
the requested PowerMac NVRAM partition is not found. This is a userspace-
visible change, in the non-existent partition case, which would be in
an error path for an IOC_NVRAM_GET_OFFSET ioctl syscall.

Tested-by: default avatarStan Johnson <userm57@yahoo.com>
Signed-off-by: default avatarFinn Thain <fthain@telegraphics.com.au>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 537f3286
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -178,7 +178,7 @@ config PPC
	select HAVE_ARCH_KGDB
	select HAVE_ARCH_MMAP_RND_BITS
	select HAVE_ARCH_MMAP_RND_COMPAT_BITS	if COMPAT
	select HAVE_ARCH_NVRAM_OPS		if PPC32
	select HAVE_ARCH_NVRAM_OPS
	select HAVE_ARCH_SECCOMP_FILTER
	select HAVE_ARCH_TRACEHOOK
	select HAVE_CBPF_JIT			if !PPC64
+2 −156
Original line number Diff line number Diff line
@@ -7,12 +7,6 @@
 *      2 of the License, or (at your option) any later version.
 *
 * /dev/nvram driver for PPC64
 *
 * This perhaps should live in drivers/char
 *
 * TODO: Split the /dev/nvram part (that one can use
 *       drivers/char/generic_nvram.c) from the arch & partition
 *       parsing code.
 */

#include <linux/types.h>
@@ -714,137 +708,6 @@ static void oops_to_nvram(struct kmsg_dumper *dumper,
	spin_unlock_irqrestore(&lock, flags);
}

static loff_t dev_nvram_llseek(struct file *file, loff_t offset, int origin)
{
	if (ppc_md.nvram_size == NULL)
		return -ENODEV;
	return generic_file_llseek_size(file, offset, origin, MAX_LFS_FILESIZE,
					ppc_md.nvram_size());
}


static ssize_t dev_nvram_read(struct file *file, char __user *buf,
			  size_t count, loff_t *ppos)
{
	ssize_t ret;
	char *tmp = NULL;
	ssize_t size;

	if (!ppc_md.nvram_size) {
		ret = -ENODEV;
		goto out;
	}

	size = ppc_md.nvram_size();
	if (size < 0) {
		ret = size;
		goto out;
	}

	if (*ppos >= size) {
		ret = 0;
		goto out;
	}

	count = min_t(size_t, count, size - *ppos);
	count = min(count, PAGE_SIZE);

	tmp = kmalloc(count, GFP_KERNEL);
	if (!tmp) {
		ret = -ENOMEM;
		goto out;
	}

	ret = ppc_md.nvram_read(tmp, count, ppos);
	if (ret <= 0)
		goto out;

	if (copy_to_user(buf, tmp, ret))
		ret = -EFAULT;

out:
	kfree(tmp);
	return ret;

}

static ssize_t dev_nvram_write(struct file *file, const char __user *buf,
			  size_t count, loff_t *ppos)
{
	ssize_t ret;
	char *tmp = NULL;
	ssize_t size;

	ret = -ENODEV;
	if (!ppc_md.nvram_size)
		goto out;

	ret = 0;
	size = ppc_md.nvram_size();
	if (*ppos >= size || size < 0)
		goto out;

	count = min_t(size_t, count, size - *ppos);
	count = min(count, PAGE_SIZE);

	tmp = memdup_user(buf, count);
	if (IS_ERR(tmp)) {
		ret = PTR_ERR(tmp);
		goto out;
	}

	ret = ppc_md.nvram_write(tmp, count, ppos);

	kfree(tmp);
out:
	return ret;
}

static long dev_nvram_ioctl(struct file *file, unsigned int cmd,
			    unsigned long arg)
{
	switch(cmd) {
#ifdef CONFIG_PPC_PMAC
	case OBSOLETE_PMAC_NVRAM_GET_OFFSET:
		printk(KERN_WARNING "nvram: Using obsolete PMAC_NVRAM_GET_OFFSET ioctl\n");
		/* fall through */
	case IOC_NVRAM_GET_OFFSET: {
		int part, offset;

		if (!machine_is(powermac))
			return -EINVAL;
		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 (offset < 0)
			return offset;
		if (copy_to_user((void __user*)arg, &offset, sizeof(offset)) != 0)
			return -EFAULT;
		return 0;
	}
#endif /* CONFIG_PPC_PMAC */
	default:
		return -EINVAL;
	}
}

static const struct file_operations nvram_fops = {
	.owner		= THIS_MODULE,
	.llseek		= dev_nvram_llseek,
	.read		= dev_nvram_read,
	.write		= dev_nvram_write,
	.unlocked_ioctl	= dev_nvram_ioctl,
};

static struct miscdevice nvram_dev = {
	NVRAM_MINOR,
	"nvram",
	&nvram_fops
};


#ifdef DEBUG_NVRAM
static void __init nvram_print_partitions(char * label)
{
@@ -992,6 +855,8 @@ loff_t __init nvram_create_partition(const char *name, int sig,
	long size = 0;
	int rc;

	BUILD_BUG_ON(NVRAM_BLOCK_LEN != 16);

	/* Convert sizes from bytes to blocks */
	req_size = _ALIGN_UP(req_size, NVRAM_BLOCK_LEN) / NVRAM_BLOCK_LEN;
	min_size = _ALIGN_UP(min_size, NVRAM_BLOCK_LEN) / NVRAM_BLOCK_LEN;
@@ -1192,22 +1057,3 @@ int __init nvram_scan_partitions(void)
	kfree(header);
	return err;
}

static int __init nvram_init(void)
{
	int rc;
	
	BUILD_BUG_ON(NVRAM_BLOCK_LEN != 16);

	if (ppc_md.nvram_size == NULL || ppc_md.nvram_size() <= 0)
		return  -ENODEV;

  	rc = misc_register(&nvram_dev);
	if (rc != 0) {
		printk(KERN_ERR "nvram_init: failed to register device\n");
		return rc;
	}
  	
  	return rc;
}
device_initcall(nvram_init);
+0 −2
Original line number Diff line number Diff line
@@ -15,7 +15,5 @@ obj-$(CONFIG_PMAC_BACKLIGHT) += backlight.o
# need this to be a bool.  Cheat here and pretend CONFIG_NVRAM=m is really
# CONFIG_NVRAM=y
obj-$(CONFIG_NVRAM:m=y)		+= nvram.o
# ppc64 pmac doesn't define CONFIG_NVRAM but needs nvram stuff
obj-$(CONFIG_PPC64)		+= nvram.o
obj-$(CONFIG_PPC32)		+= bootx_init.o
obj-$(CONFIG_SMP)		+= smp.o
+1 −1
Original line number Diff line number Diff line
@@ -316,7 +316,7 @@ static void __init pmac_setup_arch(void)
	find_via_pmu();
	smu_init();

#if IS_ENABLED(CONFIG_NVRAM) || defined(CONFIG_PPC64)
#if IS_ENABLED(CONFIG_NVRAM)
	pmac_nvram_init();
#endif
#ifdef CONFIG_PPC32
+1 −1
Original line number Diff line number Diff line
@@ -68,7 +68,7 @@
long __init pmac_time_init(void)
{
	s32 delta = 0;
#ifdef CONFIG_NVRAM
#if defined(CONFIG_NVRAM) && defined(CONFIG_PPC32)
	int dst;
	
	delta = ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x9)) << 16;
Loading