1f08c3bdfSopenharmony_ci/* 2f08c3bdfSopenharmony_ci * Copyright (c) 2013 Oracle and/or its affiliates. All Rights Reserved. 3f08c3bdfSopenharmony_ci * 4f08c3bdfSopenharmony_ci * This program is free software; you can redistribute it and/or 5f08c3bdfSopenharmony_ci * modify it under the terms of the GNU General Public License as 6f08c3bdfSopenharmony_ci * published by the Free Software Foundation; either version 2 of 7f08c3bdfSopenharmony_ci * the License, or (at your option) any later version. 8f08c3bdfSopenharmony_ci * 9f08c3bdfSopenharmony_ci * This program is distributed in the hope that it would be useful, 10f08c3bdfSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 11f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12f08c3bdfSopenharmony_ci * GNU General Public License for more details. 13f08c3bdfSopenharmony_ci * 14f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License 15f08c3bdfSopenharmony_ci * along with this program; if not, write the Free Software Foundation, 16f08c3bdfSopenharmony_ci * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17f08c3bdfSopenharmony_ci * 18f08c3bdfSopenharmony_ci * Author: Alexey Kodanev <alexey.kodanev@oracle.com> 19f08c3bdfSopenharmony_ci * 20f08c3bdfSopenharmony_ci */ 21f08c3bdfSopenharmony_ci 22f08c3bdfSopenharmony_ci#include <linux/module.h> 23f08c3bdfSopenharmony_ci#include <linux/device.h> 24f08c3bdfSopenharmony_ci#include <linux/uaccess.h> 25f08c3bdfSopenharmony_ci#include "ltp_uaccess.h" 26f08c3bdfSopenharmony_ci 27f08c3bdfSopenharmony_ciMODULE_AUTHOR("Alexey Kodanev <alexey.kodanev@oracle.com>"); 28f08c3bdfSopenharmony_ciMODULE_DESCRIPTION("User-space access LTP test"); 29f08c3bdfSopenharmony_ciMODULE_LICENSE("GPL"); 30f08c3bdfSopenharmony_ci 31f08c3bdfSopenharmony_ci#define prk_err(fmt, ...) \ 32f08c3bdfSopenharmony_ci pr_err(DEV_NAME ": " fmt "\n", ##__VA_ARGS__) 33f08c3bdfSopenharmony_ci#define prk_info(fmt, ...) \ 34f08c3bdfSopenharmony_ci pr_info(DEV_NAME ": " fmt "\n", ##__VA_ARGS__) 35f08c3bdfSopenharmony_ci 36f08c3bdfSopenharmony_ci/* 37f08c3bdfSopenharmony_ci * Test-case result, 38f08c3bdfSopenharmony_ci * if test is passed, value will be set to 0 39f08c3bdfSopenharmony_ci */ 40f08c3bdfSopenharmony_cistatic int test_result; 41f08c3bdfSopenharmony_ci 42f08c3bdfSopenharmony_cistatic void device_release(struct device *dev) 43f08c3bdfSopenharmony_ci{ 44f08c3bdfSopenharmony_ci prk_info("device released"); 45f08c3bdfSopenharmony_ci} 46f08c3bdfSopenharmony_ci 47f08c3bdfSopenharmony_cistatic struct device tdev = { 48f08c3bdfSopenharmony_ci .init_name = DEV_NAME, 49f08c3bdfSopenharmony_ci .release = device_release 50f08c3bdfSopenharmony_ci}; 51f08c3bdfSopenharmony_ci 52f08c3bdfSopenharmony_cistatic ssize_t sys_result(struct device *dev, 53f08c3bdfSopenharmony_ci struct device_attribute *attr, char *buf) 54f08c3bdfSopenharmony_ci{ 55f08c3bdfSopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%d\n", test_result); 56f08c3bdfSopenharmony_ci} 57f08c3bdfSopenharmony_cistatic DEVICE_ATTR(result, S_IRUSR, sys_result, NULL); 58f08c3bdfSopenharmony_ci 59f08c3bdfSopenharmony_ci 60f08c3bdfSopenharmony_cistatic ssize_t sys_tcase(struct device *dev, 61f08c3bdfSopenharmony_ci struct device_attribute *attr, const char *buf, size_t count) 62f08c3bdfSopenharmony_ci{ 63f08c3bdfSopenharmony_ci unsigned long ptr = 0; 64f08c3bdfSopenharmony_ci int tc = 0; 65f08c3bdfSopenharmony_ci char *str, ch, buffer[str_size]; 66f08c3bdfSopenharmony_ci 67f08c3bdfSopenharmony_ci sscanf(buf, "%d %lu", &tc, &ptr); 68f08c3bdfSopenharmony_ci str = (char *) ptr; 69f08c3bdfSopenharmony_ci test_result = 0; 70f08c3bdfSopenharmony_ci 71f08c3bdfSopenharmony_ci switch (tc) { 72f08c3bdfSopenharmony_ci case TC_READ_USER: 73f08c3bdfSopenharmony_ci if (copy_from_user(buffer, str, str_size)) 74f08c3bdfSopenharmony_ci prk_err("copy_from_user() failed"); 75f08c3bdfSopenharmony_ci test_result = strncmp(test_str, buffer, str_size) ? 1 : 0; 76f08c3bdfSopenharmony_ci if (get_user(ch, str)) 77f08c3bdfSopenharmony_ci prk_err("get_user() failed"); 78f08c3bdfSopenharmony_ci test_result |= ch != test_str[0]; 79f08c3bdfSopenharmony_ci break; 80f08c3bdfSopenharmony_ci case TC_WRITE_USER: 81f08c3bdfSopenharmony_ci if (copy_to_user(str + 1, test_str + 1, str_size - 1)) { 82f08c3bdfSopenharmony_ci prk_err("copy_to_user() failed"); 83f08c3bdfSopenharmony_ci test_result = 1; 84f08c3bdfSopenharmony_ci } 85f08c3bdfSopenharmony_ci /* write the first skipped character */ 86f08c3bdfSopenharmony_ci if (put_user(test_str[0], str)) { 87f08c3bdfSopenharmony_ci prk_err("put_user() failed"); 88f08c3bdfSopenharmony_ci test_result |= 1; 89f08c3bdfSopenharmony_ci } 90f08c3bdfSopenharmony_ci break; 91f08c3bdfSopenharmony_ci } 92f08c3bdfSopenharmony_ci 93f08c3bdfSopenharmony_ci return count; 94f08c3bdfSopenharmony_ci} 95f08c3bdfSopenharmony_cistatic DEVICE_ATTR(tcase, S_IWUSR, NULL, sys_tcase); 96f08c3bdfSopenharmony_ci 97f08c3bdfSopenharmony_cistatic int uaccess_init(void) 98f08c3bdfSopenharmony_ci{ 99f08c3bdfSopenharmony_ci int err = 0; 100f08c3bdfSopenharmony_ci prk_info("Starting module"); 101f08c3bdfSopenharmony_ci 102f08c3bdfSopenharmony_ci err = device_register(&tdev); 103f08c3bdfSopenharmony_ci if (err) { 104f08c3bdfSopenharmony_ci prk_err("Unable to register device"); 105f08c3bdfSopenharmony_ci goto err0; 106f08c3bdfSopenharmony_ci } 107f08c3bdfSopenharmony_ci prk_info("device registered"); 108f08c3bdfSopenharmony_ci 109f08c3bdfSopenharmony_ci err = device_create_file(&tdev, &dev_attr_result); 110f08c3bdfSopenharmony_ci if (err) { 111f08c3bdfSopenharmony_ci prk_err("Can't create sysfs file 'result'"); 112f08c3bdfSopenharmony_ci goto err1; 113f08c3bdfSopenharmony_ci } 114f08c3bdfSopenharmony_ci 115f08c3bdfSopenharmony_ci err = device_create_file(&tdev, &dev_attr_tcase); 116f08c3bdfSopenharmony_ci if (err) { 117f08c3bdfSopenharmony_ci prk_err(": Can't create sysfs file 'tc'"); 118f08c3bdfSopenharmony_ci goto err2; 119f08c3bdfSopenharmony_ci } 120f08c3bdfSopenharmony_ci 121f08c3bdfSopenharmony_ci return 0; 122f08c3bdfSopenharmony_ci 123f08c3bdfSopenharmony_cierr2: 124f08c3bdfSopenharmony_ci device_remove_file(&tdev, &dev_attr_result); 125f08c3bdfSopenharmony_cierr1: 126f08c3bdfSopenharmony_ci device_unregister(&tdev); 127f08c3bdfSopenharmony_cierr0: 128f08c3bdfSopenharmony_ci return err; 129f08c3bdfSopenharmony_ci} 130f08c3bdfSopenharmony_cimodule_init(uaccess_init) 131f08c3bdfSopenharmony_ci 132f08c3bdfSopenharmony_cistatic void uaccess_exit(void) 133f08c3bdfSopenharmony_ci{ 134f08c3bdfSopenharmony_ci prk_info("Unloading module"); 135f08c3bdfSopenharmony_ci 136f08c3bdfSopenharmony_ci device_remove_file(&tdev, &dev_attr_result); 137f08c3bdfSopenharmony_ci device_remove_file(&tdev, &dev_attr_tcase); 138f08c3bdfSopenharmony_ci device_unregister(&tdev); 139f08c3bdfSopenharmony_ci} 140f08c3bdfSopenharmony_cimodule_exit(uaccess_exit) 141