1 /* 2 * Copyright 2014 Google, Inc. 3 * 4 * This software is licensed under the terms of the GNU General Public 5 * License version 2, as published by the Free Software Foundation, and 6 * may be copied, distributed, and modified under those terms. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 */ 13 14 #include <linux/cdev.h> 15 #include <linux/device.h> 16 #include <linux/fs.h> 17 #include <linux/uaccess.h> 18 #include "internal.h" 19 20 static DEFINE_MUTEX(pmsg_lock); 21 22 static ssize_t write_pmsg(struct file *file, const char __user *buf, 23 size_t count, loff_t *ppos) 24 { 25 struct pstore_record record; 26 int ret; 27 28 if (!count) 29 return 0; 30 31 pstore_record_init(&record, psinfo); 32 record.type = PSTORE_TYPE_PMSG; 33 record.size = count; 34 35 /* check outside lock, page in any data. write_user also checks */ 36 if (!access_ok(buf, count)) 37 return -EFAULT; 38 39 mutex_lock(&pmsg_lock); 40 ret = psinfo->write_user(&record, buf); 41 mutex_unlock(&pmsg_lock); 42 return ret ? ret : count; 43 } 44 45 static const struct file_operations pmsg_fops = { 46 .owner = THIS_MODULE, 47 .llseek = noop_llseek, 48 .write = write_pmsg, 49 }; 50 51 static struct class *pmsg_class; 52 static int pmsg_major; 53 #define PMSG_NAME "pmsg" 54 #undef pr_fmt 55 #define pr_fmt(fmt) PMSG_NAME ": " fmt 56 57 static char *pmsg_devnode(struct device *dev, umode_t *mode) 58 { 59 if (mode) 60 *mode = 0220; 61 return NULL; 62 } 63 64 void pstore_register_pmsg(void) 65 { 66 struct device *pmsg_device; 67 68 pmsg_major = register_chrdev(0, PMSG_NAME, &pmsg_fops); 69 if (pmsg_major < 0) { 70 pr_err("register_chrdev failed\n"); 71 goto err; 72 } 73 74 pmsg_class = class_create(THIS_MODULE, PMSG_NAME); 75 if (IS_ERR(pmsg_class)) { 76 pr_err("device class file already in use\n"); 77 goto err_class; 78 } 79 pmsg_class->devnode = pmsg_devnode; 80 81 pmsg_device = device_create(pmsg_class, NULL, MKDEV(pmsg_major, 0), 82 NULL, "%s%d", PMSG_NAME, 0); 83 if (IS_ERR(pmsg_device)) { 84 pr_err("failed to create device\n"); 85 goto err_device; 86 } 87 return; 88 89 err_device: 90 class_destroy(pmsg_class); 91 err_class: 92 unregister_chrdev(pmsg_major, PMSG_NAME); 93 err: 94 return; 95 } 96 97 void pstore_unregister_pmsg(void) 98 { 99 device_destroy(pmsg_class, MKDEV(pmsg_major, 0)); 100 class_destroy(pmsg_class); 101 unregister_chrdev(pmsg_major, PMSG_NAME); 102 } 103