/*
 * 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)
{
	int rc, *pos;

	if (erst_disable)
		return -ENODEV;

	pos = (int *)&file->private_data;

	rc = erst_get_record_id_begin(pos);
	if (rc)
		return rc;

	return nonseekable_open(inode, file);
}

static int erst_dbg_release(struct inode *inode, struct file *file)
{
	erst_get_record_id_end();

	return 0;
}

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, *pos;
	ssize_t len = 0;
	u64 id;

	if (*off)
		return -EINVAL;

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

	pos = (int *)&filp->private_data;

retry_next:
	rc = erst_get_record_id_next(pos, &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,
	.release	= erst_dbg_release,
	.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");
