• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17  */
18 
19 #include <linux/module.h>
20 #include <linux/kernel.h>
21 #include <linux/printk.h>
22 #include <linux/fs.h>
23 #include <linux/seq_file.h>
24 #include <linux/proc_fs.h>
25 #include <linux/slab.h>
26 #include <asm/uaccess.h>
27 #include <linux/version.h>
28 #include "securec.h"
29 #include "hi_osal.h"
30 
31 #define OSAL_PROC_DEBUG 0
32 
33 static struct osal_list_head g_list;
34 static osal_proc_entry_t *g_proc_entry = NULL;
35 
osal_seq_show(struct seq_file * s,void * p)36 static int osal_seq_show(struct seq_file *s, void *p)
37 {
38     osal_proc_entry_t *oldsentry = s->private;
39     osal_proc_entry_t sentry;
40 
41     osal_unused(p);
42     if (oldsentry == NULL) {
43         osal_trace("%s - parameter invalid!\n", __FUNCTION__);
44         return -1;
45     }
46     (void)memset_s(&sentry, sizeof(osal_proc_entry_t), 0, sizeof(osal_proc_entry_t));
47     /* only these two parameters are used */
48     sentry.seqfile = s;
49     sentry.private = oldsentry->private;
50     oldsentry->read(&sentry);
51     return 0;
52 }
53 
54 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)
osal_procwrite(struct file * file,const char __user * buf,size_t count,loff_t * ppos)55 static ssize_t osal_procwrite(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
56 {
57     osal_proc_entry_t *sentry = ((struct seq_file *)(file->private_data))->private;
58     return sentry->write(sentry, (char *)buf, count, (long long *)ppos);
59 }
60 #else
osal_procwrite(struct file * file,const char __user * buf,size_t count,loff_t * ppos)61 static ssize_t osal_procwrite(struct file *file, const char __user *buf,
62                               size_t count, loff_t *ppos)
63 {
64     osal_proc_entry_t *item = PDE_DATA(file_inode(file));
65 
66     if ((item != NULL) && (item->write != NULL)) {
67         return item->write(item, buf, count, (long long *)ppos);
68     }
69 
70     return -ENOSYS;
71 }
72 #endif
73 
osal_procopen(struct inode * inode,struct file * file)74 static int osal_procopen(struct inode *inode, struct file *file)
75 {
76 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)
77     osal_proc_entry_t *sentry = PDE(inode)->data;
78 #else
79     osal_proc_entry_t *sentry = PDE_DATA(inode);
80 #endif
81     if ((sentry != NULL) && (sentry->open != NULL)) {
82         sentry->open(sentry);
83     }
84     return single_open(file, osal_seq_show, sentry);
85 }
86 
87 #if LINUX_VERSION_CODE > KERNEL_VERSION(5,6,0)
88 static struct proc_ops g_osal_proc_ops = {
89     .proc_open = osal_procopen,
90     .proc_read = seq_read,
91     .proc_write = osal_procwrite,
92     .proc_lseek = seq_lseek,
93     .proc_release = single_release
94 };
95 #else
96 static struct file_operations g_osal_proc_ops = {
97     .owner = THIS_MODULE,
98     .open = osal_procopen,
99     .read = seq_read,
100     .write = osal_procwrite,
101     .llseek = seq_lseek,
102     .release = single_release
103 };
104 #endif
105 
osal_create_proc(const char * name,osal_proc_entry_t * parent)106 osal_proc_entry_t *osal_create_proc(const char *name, osal_proc_entry_t *parent)
107 {
108     struct proc_dir_entry *entry = NULL;
109     osal_proc_entry_t *sentry = NULL;
110     void *parent_proc_entry = NULL;
111 
112 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)
113     if (parent == NULL) {
114         osal_trace("%s - parent is NULL!\n", __FUNCTION__);
115     } else {
116         parent_proc_entry = parent->proc_dir_entry;
117         osal_trace("%s - parent is not NULL! parent=%pK\n", __FUNCTION__, parent->proc_dir_entry);
118     }
119     entry = create_proc_entry(name, 0, parent_proc_entry);
120     if (entry == NULL) {
121         osal_trace("%s - create_proc_entry failed!\n", __FUNCTION__);
122         return NULL;
123     }
124     sentry = kmalloc(sizeof(struct osal_proc_dir_entry), GFP_KERNEL);
125     if (sentry == NULL) {
126         remove_proc_entry(name, parent_proc_entry);
127         osal_trace("%s - kmalloc failed!\n", __FUNCTION__);
128         return NULL;
129     }
130 
131     (void)memset_s(sentry, sizeof(struct osal_proc_dir_entry), 0, sizeof(struct osal_proc_dir_entry));
132 
133     if (strncpy_s(sentry->name, OSAL_MAX_PROC_NAME_LEN, name, sizeof(sentry->name) - 1) != EOK) {
134         kfree(sentry);
135         remove_proc_entry(name, parent_proc_entry);
136         osal_trace("%s - strncpy_s failed!\n", __FUNCTION__);
137         return NULL;
138     }
139     sentry->proc_dir_entry = entry;
140     sentry->open = NULL;
141     entry->proc_fops = &g_osal_proc_ops;
142     entry->data = sentry;
143 #else
144     sentry = kmalloc(sizeof(struct osal_proc_dir_entry), GFP_KERNEL);
145     if (sentry == NULL) {
146         osal_trace("%s - kmalloc failed!\n", __FUNCTION__);
147         return NULL;
148     }
149 
150     (void)memset_s(sentry, sizeof(struct osal_proc_dir_entry), 0, sizeof(struct osal_proc_dir_entry));
151 
152     if (strncpy_s(sentry->name, OSAL_MAX_PROC_NAME_LEN, name, sizeof(sentry->name) - 1) != EOK) {
153         osal_trace("%s - strncpy_s failed!\n", __FUNCTION__);
154         kfree(sentry);
155         return NULL;
156     }
157     if (parent != NULL) {
158         parent_proc_entry = parent->proc_dir_entry;
159     }
160     entry = proc_create_data(name, 0, parent_proc_entry, &g_osal_proc_ops, sentry);
161     if (entry == NULL) {
162         osal_trace("%s - create_proc_entry failed!\n", __FUNCTION__);
163         kfree(sentry);
164         return NULL;
165     }
166     sentry->proc_dir_entry = entry;
167     sentry->open = NULL;
168 #endif
169     osal_list_add_tail(&(sentry->node), &g_list);
170     return sentry;
171 }
172 
osal_remove_proc(const char * name,osal_proc_entry_t * parent)173 void osal_remove_proc(const char *name, osal_proc_entry_t *parent)
174 {
175     struct osal_proc_dir_entry *sproc = NULL;
176 
177     if (name == NULL) {
178         osal_trace("%s - parameter invalid!\n", __FUNCTION__);
179         return;
180     }
181     if (parent != NULL) {
182         remove_proc_entry(name, parent->proc_dir_entry);
183     } else {
184         remove_proc_entry(name, NULL);
185     }
186     osal_list_for_each_entry(sproc, &g_list, node) {
187         if (osal_strncmp(sproc->name, name, sizeof(sproc->name)) == 0) {
188             osal_list_del(&(sproc->node));
189             kfree(sproc);
190             sproc = NULL;
191             break;
192         }
193     }
194 }
195 
osal_create_proc_entry(const char * name,osal_proc_entry_t * parent)196 osal_proc_entry_t *osal_create_proc_entry(const char *name, osal_proc_entry_t *parent)
197 {
198     parent = g_proc_entry;
199 
200     return osal_create_proc(name, parent);
201 }
202 EXPORT_SYMBOL(osal_create_proc_entry);
203 
osal_remove_proc_entry(const char * name,osal_proc_entry_t * parent)204 void osal_remove_proc_entry(const char *name, osal_proc_entry_t *parent)
205 {
206     parent = g_proc_entry;
207     osal_remove_proc(name, parent);
208     return;
209 }
210 EXPORT_SYMBOL(osal_remove_proc_entry);
211 
osal_proc_mkdir(const char * name,osal_proc_entry_t * parent)212 osal_proc_entry_t *osal_proc_mkdir(const char *name, osal_proc_entry_t *parent)
213 {
214     struct proc_dir_entry *proc = NULL;
215     struct osal_proc_dir_entry *sproc = NULL;
216     void *parent_proc_entry = NULL;
217 
218 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)
219     if (parent != NULL) {
220         parent_proc_entry = parent->proc_dir_entry;
221         proc = proc_mkdir(name, parent_proc_entry);
222         osal_trace("%s - parent is not NULL!\n", __FUNCTION__);
223     } else {
224         proc = proc_mkdir(name, parent_proc_entry);
225         osal_trace("%s - parent is NULL! proc=%pK \n", __FUNCTION__, proc);
226     }
227     if (proc == NULL) {
228         osal_trace("%s - proc_mkdir failed!\n", __FUNCTION__);
229         return NULL;
230     }
231     sproc = kmalloc(sizeof(struct osal_proc_dir_entry), GFP_KERNEL);
232     if (sproc == NULL) {
233         remove_proc_entry(name, parent_proc_entry);
234         osal_trace("%s - kmalloc failed!\n", __FUNCTION__);
235         return NULL;
236     }
237 
238     (void)memset_s(sproc, sizeof(struct osal_proc_dir_entry), 0, sizeof(struct osal_proc_dir_entry));
239 
240     if (strncpy_s(sproc->name, OSAL_MAX_PROC_NAME_LEN, name, sizeof(sproc->name) - 1) != EOK) {
241         remove_proc_entry(name, parent_proc_entry);
242         kfree(sproc);
243         osal_trace("%s - strncpy_s failed!\n", __FUNCTION__);
244         return NULL;
245     }
246     sproc->proc_dir_entry = proc;
247     proc->data = sproc;
248 #else
249     sproc = kmalloc(sizeof(struct osal_proc_dir_entry), GFP_KERNEL);
250     if (sproc == NULL) {
251         osal_trace("%s - kmalloc failed!\n", __FUNCTION__);
252         return NULL;
253     }
254 
255     (void)memset_s(sproc, sizeof(struct osal_proc_dir_entry), 0, sizeof(struct osal_proc_dir_entry));
256 
257     if (strncpy_s(sproc->name, OSAL_MAX_PROC_NAME_LEN, name, sizeof(sproc->name) - 1) != EOK) {
258         kfree(sproc);
259         osal_trace("%s - strncpy_s failed!\n", __FUNCTION__);
260         return NULL;
261     }
262     if (parent != NULL) {
263         parent_proc_entry = parent->proc_dir_entry;
264     }
265     proc = proc_mkdir_data(name, 0, parent_proc_entry, sproc);
266     if (proc == NULL) {
267         kfree(sproc);
268         osal_trace("%s - proc_mkdir failed!\n", __FUNCTION__);
269         return NULL;
270     }
271     sproc->proc_dir_entry = proc;
272 #endif
273     osal_list_add_tail(&(sproc->node), &g_list);
274     return sproc;
275 }
276 EXPORT_SYMBOL(osal_proc_mkdir);
277 
osal_remove_proc_root(const char * name,osal_proc_entry_t * parent)278 void osal_remove_proc_root(const char *name, osal_proc_entry_t *parent)
279 {
280     struct osal_proc_dir_entry *sproc = NULL;
281 
282     if (name == NULL) {
283         osal_trace("%s - parameter invalid!\n", __FUNCTION__);
284         return;
285     }
286     if (parent != NULL) {
287         remove_proc_entry(name, parent->proc_dir_entry);
288     } else {
289         remove_proc_entry(name, NULL);
290     }
291     osal_list_for_each_entry(sproc, &g_list, node) {
292         if (osal_strncmp(sproc->name, name, sizeof(sproc->name)) == 0) {
293             osal_list_del(&(sproc->node));
294             break;
295         }
296     }
297     if (sproc != NULL) {
298         kfree(sproc);
299     }
300 }
301 
osal_seq_printf(osal_proc_entry_t * entry,const char * fmt,...)302 void osal_seq_printf(osal_proc_entry_t *entry, const char *fmt, ...)
303 {
304     struct seq_file *s = (struct seq_file *)(entry->seqfile);
305     va_list args;
306 
307     va_start(args, fmt);
308 #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 3, 0)
309     (void)seq_vprintf(s, fmt, args);
310 #else
311     seq_vprintf(s, fmt, args);
312 #endif
313     va_end(args);
314 }
315 EXPORT_SYMBOL(osal_seq_printf);
316 
osal_proc_init(void)317 void osal_proc_init(void)
318 {
319     OSAL_INIT_LIST_HEAD(&g_list);
320     g_proc_entry = osal_proc_mkdir("umap", NULL);
321     if (g_proc_entry == NULL) {
322         osal_trace("test init, proc mkdir error!\n");
323     }
324 }
osal_proc_exit(void)325 void osal_proc_exit(void)
326 {
327     osal_remove_proc_root("umap", NULL);
328 }
329