brintos

brintos / linux-shallow public Read only

0
0
Text · 1.9 KiB · 55f139a Raw
95 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright 2014  Google, Inc.4 */5 6#include <linux/cdev.h>7#include <linux/device.h>8#include <linux/fs.h>9#include <linux/uaccess.h>10#include "internal.h"11 12static DEFINE_MUTEX(pmsg_lock);13 14static ssize_t write_pmsg(struct file *file, const char __user *buf,15			  size_t count, loff_t *ppos)16{17	struct pstore_record record;18	int ret;19 20	if (!count)21		return 0;22 23	pstore_record_init(&record, psinfo);24	record.type = PSTORE_TYPE_PMSG;25	record.size = count;26 27	/* check outside lock, page in any data. write_user also checks */28	if (!access_ok(buf, count))29		return -EFAULT;30 31	mutex_lock(&pmsg_lock);32	ret = psinfo->write_user(&record, buf);33	mutex_unlock(&pmsg_lock);34	return ret ? ret : count;35}36 37static const struct file_operations pmsg_fops = {38	.owner		= THIS_MODULE,39	.llseek		= noop_llseek,40	.write		= write_pmsg,41};42 43static struct class *pmsg_class;44static int pmsg_major;45#define PMSG_NAME "pmsg"46#undef pr_fmt47#define pr_fmt(fmt) PMSG_NAME ": " fmt48 49static char *pmsg_devnode(const struct device *dev, umode_t *mode)50{51	if (mode)52		*mode = 0220;53	return NULL;54}55 56void pstore_register_pmsg(void)57{58	struct device *pmsg_device;59 60	pmsg_major = register_chrdev(0, PMSG_NAME, &pmsg_fops);61	if (pmsg_major < 0) {62		pr_err("register_chrdev failed\n");63		goto err;64	}65 66	pmsg_class = class_create(PMSG_NAME);67	if (IS_ERR(pmsg_class)) {68		pr_err("device class file already in use\n");69		goto err_class;70	}71	pmsg_class->devnode = pmsg_devnode;72 73	pmsg_device = device_create(pmsg_class, NULL, MKDEV(pmsg_major, 0),74					NULL, "%s%d", PMSG_NAME, 0);75	if (IS_ERR(pmsg_device)) {76		pr_err("failed to create device\n");77		goto err_device;78	}79	return;80 81err_device:82	class_destroy(pmsg_class);83err_class:84	unregister_chrdev(pmsg_major, PMSG_NAME);85err:86	return;87}88 89void pstore_unregister_pmsg(void)90{91	device_destroy(pmsg_class, MKDEV(pmsg_major, 0));92	class_destroy(pmsg_class);93	unregister_chrdev(pmsg_major, PMSG_NAME);94}95