1 /*
2 * mf_proc.c
3 * Copyright (C) 2001 Kyle A. Lucke IBM Corporation
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20
21 /* Change Activity: */
22 /* End Change Activity */
23
24 #ifndef _MF_PROC_H
25 #include <asm/iSeries/mf_proc.h>
26 #endif
27 #ifndef MF_H_INCLUDED
28 #include <asm/iSeries/mf.h>
29 #endif
30 #include <asm/uaccess.h>
31
32 static struct proc_dir_entry *mf_proc_root = NULL;
33
34 int proc_mf_dump_cmdline
35 (char *page, char **start, off_t off, int count, int *eof, void *data);
36
37 int proc_mf_dump_vmlinux
38 (char *page, char **start, off_t off, int count, int *eof, void *data);
39
40 int proc_mf_dump_side
41 (char *page, char **start, off_t off, int count, int *eof, void *data);
42
43 int proc_mf_change_side
44 (struct file *file, const char *buffer, unsigned long count, void *data);
45
46 int proc_mf_dump_src
47 (char *page, char **start, off_t off, int count, int *eof, void *data);
48 int proc_mf_change_src (struct file *file, const char *buffer, unsigned long count, void *data);
49 int proc_mf_change_cmdline(struct file *file, const char *buffer, unsigned long count, void *data);
50 int proc_mf_change_vmlinux(struct file *file, const char *buffer, unsigned long count, void *data);
51
52
mf_proc_init(struct proc_dir_entry * iSeries_proc)53 void mf_proc_init(struct proc_dir_entry *iSeries_proc)
54 {
55 struct proc_dir_entry *ent = NULL;
56 struct proc_dir_entry *mf_a = NULL;
57 struct proc_dir_entry *mf_b = NULL;
58 struct proc_dir_entry *mf_c = NULL;
59 struct proc_dir_entry *mf_d = NULL;
60
61 mf_proc_root = proc_mkdir("mf", iSeries_proc);
62 if (!mf_proc_root) return;
63
64 mf_a = proc_mkdir("A", mf_proc_root);
65 if (!mf_a) return;
66
67 ent = create_proc_entry("cmdline", S_IFREG|S_IRUSR|S_IWUSR, mf_a);
68 if (!ent) return;
69 ent->nlink = 1;
70 ent->data = (void *)0;
71 ent->read_proc = proc_mf_dump_cmdline;
72 ent->write_proc = proc_mf_change_cmdline;
73
74 ent = create_proc_entry("vmlinux", S_IFREG|S_IWUSR, mf_a);
75 if (!ent) return;
76 ent->nlink = 1;
77 ent->data = (void *)0;
78 ent->write_proc = proc_mf_change_vmlinux;
79 ent->read_proc = NULL;
80
81 mf_b = proc_mkdir("B", mf_proc_root);
82 if (!mf_b) return;
83
84 ent = create_proc_entry("cmdline", S_IFREG|S_IRUSR|S_IWUSR, mf_b);
85 if (!ent) return;
86 ent->nlink = 1;
87 ent->data = (void *)1;
88 ent->read_proc = proc_mf_dump_cmdline;
89 ent->write_proc = proc_mf_change_cmdline;
90
91 ent = create_proc_entry("vmlinux", S_IFREG|S_IWUSR, mf_b);
92 if (!ent) return;
93 ent->nlink = 1;
94 ent->data = (void *)1;
95 ent->write_proc = proc_mf_change_vmlinux;
96 ent->read_proc = NULL;
97
98 mf_c = proc_mkdir("C", mf_proc_root);
99 if (!mf_c) return;
100
101 ent = create_proc_entry("cmdline", S_IFREG|S_IRUSR|S_IWUSR, mf_c);
102 if (!ent) return;
103 ent->nlink = 1;
104 ent->data = (void *)2;
105 ent->read_proc = proc_mf_dump_cmdline;
106 ent->write_proc = proc_mf_change_cmdline;
107
108 ent = create_proc_entry("vmlinux", S_IFREG|S_IWUSR, mf_c);
109 if (!ent) return;
110 ent->nlink = 1;
111 ent->data = (void *)2;
112 ent->write_proc = proc_mf_change_vmlinux;
113 ent->read_proc = NULL;
114
115 mf_d = proc_mkdir("D", mf_proc_root);
116 if (!mf_d) return;
117
118
119 ent = create_proc_entry("cmdline", S_IFREG|S_IRUSR|S_IWUSR, mf_d);
120 if (!ent) return;
121 ent->nlink = 1;
122 ent->data = (void *)3;
123 ent->read_proc = proc_mf_dump_cmdline;
124 ent->write_proc = proc_mf_change_cmdline;
125 #if 0
126 ent = create_proc_entry("vmlinux", S_IFREG|S_IRUSR, mf_d);
127 if (!ent) return;
128 ent->nlink = 1;
129 ent->data = (void *)3;
130 ent->read_proc = proc_mf_dump_vmlinux;
131 ent->write_proc = NULL;
132 #endif
133 ent = create_proc_entry("side", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root);
134 if (!ent) return;
135 ent->nlink = 1;
136 ent->data = (void *)0;
137 ent->read_proc = proc_mf_dump_side;
138 ent->write_proc = proc_mf_change_side;
139
140 ent = create_proc_entry("src", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root);
141 if (!ent) return;
142 ent->nlink = 1;
143 ent->data = (void *)0;
144 ent->read_proc = proc_mf_dump_src;
145 ent->write_proc = proc_mf_change_src;
146 }
147
proc_mf_dump_cmdline(char * page,char ** start,off_t off,int count,int * eof,void * data)148 int proc_mf_dump_cmdline
149 (char *page, char **start, off_t off, int count, int *eof, void *data)
150 {
151 int len = count;
152 char *p;
153
154 len = mf_getCmdLine(page, &len, (u64)data);
155
156 p = page + len - 1;
157 while ( p > page ) {
158 if ( (*p == 0) || (*p == ' ') )
159 --p;
160 else
161 break;
162 }
163 if ( *p != '\n' ) {
164 ++p;
165 *p = '\n';
166 }
167 ++p;
168 *p = 0;
169 len = p - page;
170
171 len -= off;
172 if (len < count) {
173 *eof = 1;
174 if (len <= 0)
175 return 0;
176 } else
177 len = count;
178 *start = page + off;
179 return len;
180 }
181
proc_mf_dump_vmlinux(char * page,char ** start,off_t off,int count,int * eof,void * data)182 int proc_mf_dump_vmlinux
183 (char *page, char **start, off_t off, int count, int *eof, void *data)
184 {
185 int sizeToGet = count;
186 if (!capable(CAP_SYS_ADMIN))
187 return -EACCES;
188
189 if (mf_getVmlinuxChunk(page, &sizeToGet, off, (u64)data) == 0)
190 {
191 if (sizeToGet != 0)
192 {
193 *start = page + off;
194 return sizeToGet;
195 } else {
196 *eof = 1;
197 return 0;
198 }
199 } else {
200 *eof = 1;
201 return 0;
202 }
203 }
204
proc_mf_dump_side(char * page,char ** start,off_t off,int count,int * eof,void * data)205 int proc_mf_dump_side
206 (char *page, char **start, off_t off, int count, int *eof, void *data)
207 {
208 int len = 0;
209
210 char mf_current_side = mf_getSide();
211 len = sprintf(page, "%c\n", mf_current_side);
212
213 if (len <= off+count) *eof = 1;
214 *start = page + off;
215 len -= off;
216 if (len>count) len = count;
217 if (len<0) len = 0;
218 return len;
219 }
220
proc_mf_change_side(struct file * file,const char * buffer,unsigned long count,void * data)221 int proc_mf_change_side(struct file *file, const char *buffer, unsigned long count, void *data)
222 {
223 char side;
224
225 if (!capable(CAP_SYS_ADMIN))
226 return -EACCES;
227 if (count == 0)
228 return 0;
229 if (get_user(side, buffer))
230 return -EFAULT;
231
232 if ((side != 'A') && (side != 'B') && (side != 'C') && (side != 'D'))
233 {
234 printk(KERN_ERR "mf_proc.c: proc_mf_change_side: invalid side\n");
235 return -EINVAL;
236 }
237
238 mf_setSide(side);
239
240 return count;
241 }
242
proc_mf_dump_src(char * page,char ** start,off_t off,int count,int * eof,void * data)243 int proc_mf_dump_src
244 (char *page, char **start, off_t off, int count, int *eof, void *data)
245 {
246 int len = 0;
247 mf_getSrcHistory(page, count);
248 len = count;
249 len -= off;
250 if (len < count) {
251 *eof = 1;
252 if (len <= 0)
253 return 0;
254 } else
255 len = count;
256 *start = page + off;
257 return len;
258 }
259
proc_mf_change_src(struct file * file,const char * buffer,unsigned long count,void * data)260 int proc_mf_change_src(struct file *file, const char *buffer, unsigned long count, void *data)
261 {
262 char stkbuf[10];
263 if (!capable(CAP_SYS_ADMIN))
264 return -EACCES;
265
266 if ((count < 4) && (count != 1)) {
267 printk(KERN_ERR "mf_proc: invalid src\n");
268 return -EINVAL;
269 }
270
271 if (count > 9)
272 count = 9;
273 if (copy_from_user (stkbuf, buffer, count))
274 return -EFAULT;
275
276 if ((count == 1) && ((*stkbuf) == '\0')) {
277 mf_clearSrc();
278 } else {
279 mf_displaySrc(*(u32 *)stkbuf);
280 }
281
282 return count;
283 }
284
proc_mf_change_cmdline(struct file * file,const char * buffer,unsigned long count,void * data)285 int proc_mf_change_cmdline(struct file *file, const char *buffer, unsigned long count, void *data)
286 {
287 if (!capable(CAP_SYS_ADMIN))
288 return -EACCES;
289
290 mf_setCmdLine(buffer, count, (u64)data);
291
292 return count;
293 }
294
proc_mf_change_vmlinux(struct file * file,const char * buffer,unsigned long count,void * data)295 int proc_mf_change_vmlinux(struct file *file, const char *buffer, unsigned long count, void *data)
296 {
297 if (!capable(CAP_SYS_ADMIN))
298 return -EACCES;
299
300 mf_setVmlinuxChunk(buffer, count, file->f_pos, (u64)data);
301 file->f_pos += count;
302
303 return count;
304 }
305