/*
 * APEI Error Record Serialization Table debug support
 *
 * ERST is a way provided by APEI to save and retrieve hardware error
 * information to and from a persistent store. This file provide the
 * debugging/testing support for ERST kernel support and firmware
 * implementation.
 *
 * Copyright 2010 Intel Corp.
 *   Author: Huang Ying <ying.huang@intel.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License version
 * 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/uaccess.h>
#include <acpi/apei.h>
#include <linux/miscdevice.h>

#include "apei-internal.h"

#define ERST_DBG_PFX			"ERST DBG: "

#define ERST_DBG_RECORD_LEN_MAX		4096

static void *erst_dbg_buf;
static unsigned int erst_dbg_buf_len;

/* Prevent erst_dbg_read/write from being invoked concurrently */
static DEFINE_MUTEX(erst_dbg_mutex);

static int erst_dbg_open(struct inode *inode, struct file *file)
{
	if (erst_disable)
		return -ENODEV;

	return nonseekable_open(inode, file);
}

static long erst_dbg_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
{
	int rc;
	u64 record_id;
	u32 record_count;

	switch (cmd) {
	case APEI_ERST_CLEAR_RECORD:
		rc = copy_from_user(&record_id, (void __user *)arg,
				    sizeof(record_id));
		if (rc)
			return -EFAULT;
		return erst_clear(record_id);
	case APEI_ERST_GET_RECORD_COUNT:
		rc = erst_get_record_count();
		if (rc < 0)
			return rc;
		record_count = rc;
		rc = put_user(record_count, (u32 __user *)arg);
		if (rc)
			return rc;
		return 0;
	default:
		return -ENOTTY;
	}
}

static ssize_t erst_dbg_read(struct file *filp, char __user *ubuf,
			     size_t usize, loff_t *off)
{
	int rc;
	ssize_t len = 0;
	u64 id;

	if (*off != 0)
		return -EINVAL;

	if (mutex_lock_interruptible(&erst_dbg_mutex) != 0)
		return -EINTR;

retry_next:
	rc = erst_get_next_record_id(&id);
	if (rc)
		goto out;
	/* no more record */
	if (id == APEI_ERST_INVALID_RECORD_ID)
		goto out;
retry:
	rc = len = erst_read(id, erst_dbg_buf, erst_dbg_buf_len);
	/* The record may be cleared by others, try read next record */
	if (rc == -ENOENT)
		goto retry_next;
	if (rc < 0)
		goto out;
	if (len > ERST_DBG_RECORD_LEN_MAX) {
		pr_warning(ERST_DBG_PFX
			   "Record (ID: 0x%llx) length is too long: %zd\n",
			   id, len);
		rc = -EIO;
		goto out;
	}
	if (len > erst_dbg_buf_len) {
		void *p;
		rc = -ENOMEM;
		p = kmalloc(len, GFP_KERNEL);
		if (!p)
			goto out;
		kfree(erst_dbg_buf);
		erst_dbg_buf = p;
		erst_dbg_buf_len = len;
		goto retry;
	}

	rc = -EINVAL;
	if (len > usize)
		goto out;

	rc = -EFAULT;
	if (copy_to_user(ubuf, erst_dbg_buf, len))
		goto out;
	rc = 0;
out:
	mutex_unlock(&erst_dbg_mutex);
	return rc ? rc : len;
}

static ssize_t erst_dbg_write(struct file *filp, const char __user *ubuf,
			      size_t usize, loff_t *off)
{
	int rc;
	struct cper_record_header *rcd;

	if (!capable(CAP_SYS_ADMIN))
		return -EPERM;

	if (usize > ERST_DBG_RECORD_LEN_MAX) {
		pr_err(ERST_DBG_PFX "Too long record to be written\n");
		return -EINVAL;
	}

	if (mutex_lock_interruptible(&erst_dbg_mutex))
		return -EINTR;
	if (usize > erst_dbg_buf_len) {
		void *p;
		rc = -ENOMEM;
		p = kmalloc(usize, GFP_KERNEL);
		if (!p)
			goto out;
		kfree(erst_dbg_buf);
		erst_dbg_buf = p;
		erst_dbg_buf_len = usize;
	}
	rc = copy_from_user(erst_dbg_buf, ubuf, usize);
	if (rc) {
		rc = -EFAULT;
		goto out;
	}
	rcd = erst_dbg_buf;
	rc = -EINVAL;
	if (rcd->record_length != usize)
		goto out;

	rc = erst_write(erst_dbg_buf);

out:
	mutex_unlock(&erst_dbg_mutex);
	return rc < 0 ? rc : usize;
}

static const struct file_operations erst_dbg_ops = {
	.owner		= THIS_MODULE,
	.open		= erst_dbg_open,
	.read		= erst_dbg_read,
	.write		= erst_dbg_write,
	.unlocked_ioctl	= erst_dbg_ioctl,
	.llseek		= no_llseek,
};

static struct miscdevice erst_dbg_dev = {
	.minor	= MISC_DYNAMIC_MINOR,
	.name	= "erst_dbg",
	.fops	= &erst_dbg_ops,
};

static __init int erst_dbg_init(void)
{
	return misc_register(&erst_dbg_dev);
}

static __exit void erst_dbg_exit(void)
{
	misc_deregister(&erst_dbg_dev);
	kfree(erst_dbg_buf);
}

module_init(erst_dbg_init);
module_exit(erst_dbg_exit);

MODULE_AUTHOR("Huang Ying");
MODULE_DESCRIPTION("APEI Error Record Serialization Table debug support");
MODULE_LICENSE("GPL");
