2 * arch/ppc64/kernel/proc_ppc64.c
4 * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen IBM Corporation
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <linux/config.h>
22 #include <linux/init.h>
24 #include <linux/proc_fs.h>
25 #include <linux/slab.h>
26 #include <linux/kernel.h>
28 #include <asm/systemcfg.h>
30 #include <asm/uaccess.h>
33 static loff_t page_map_seek( struct file *file, loff_t off, int whence);
34 static ssize_t page_map_read( struct file *file, char __user *buf, size_t nbytes,
36 static int page_map_mmap( struct file *file, struct vm_area_struct *vma );
38 static struct file_operations page_map_fops = {
39 .llseek = page_map_seek,
40 .read = page_map_read,
44 #ifdef CONFIG_PPC_PSERIES
45 /* routines for /proc/ppc64/ofdt */
46 static ssize_t ofdt_write(struct file *, const char __user *, size_t, loff_t *);
47 static void proc_ppc64_create_ofdt(void);
48 static int do_remove_node(char *);
49 static int do_add_node(char *, size_t);
50 static void release_prop_list(const struct property *);
51 static struct property *new_property(const char *, const int, const unsigned char *, struct property *);
52 static char * parse_next_property(char *, char *, char **, int *, unsigned char**);
53 static struct file_operations ofdt_fops = {
59 * Create the ppc64 and ppc64/rtas directories early. This allows us to
60 * assume that they have been previously created in drivers.
62 static int __init proc_ppc64_create(void)
64 struct proc_dir_entry *root;
66 root = proc_mkdir("ppc64", NULL);
70 if (!(systemcfg->platform & PLATFORM_PSERIES))
73 if (!proc_mkdir("rtas", root))
76 if (!proc_symlink("rtas", NULL, "ppc64/rtas"))
81 core_initcall(proc_ppc64_create);
83 static int __init proc_ppc64_init(void)
85 struct proc_dir_entry *pde;
87 pde = create_proc_entry("ppc64/systemcfg", S_IFREG|S_IRUGO, NULL);
91 pde->data = systemcfg;
93 pde->proc_fops = &page_map_fops;
95 #ifdef CONFIG_PPC_PSERIES
96 if ((systemcfg->platform & PLATFORM_PSERIES))
97 proc_ppc64_create_ofdt();
102 __initcall(proc_ppc64_init);
104 static loff_t page_map_seek( struct file *file, loff_t off, int whence)
107 struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
114 new = file->f_pos + off;
117 new = dp->size + off;
122 if ( new < 0 || new > dp->size )
124 return (file->f_pos = new);
127 static ssize_t page_map_read( struct file *file, char __user *buf, size_t nbytes,
130 struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
131 return simple_read_from_buffer(buf, nbytes, ppos, dp->data, dp->size);
134 static int page_map_mmap( struct file *file, struct vm_area_struct *vma )
136 struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);
138 vma->vm_flags |= VM_SHM | VM_LOCKED;
140 if ((vma->vm_end - vma->vm_start) > dp->size)
143 remap_pfn_range(vma, vma->vm_start, __pa(dp->data) >> PAGE_SHIFT,
144 dp->size, vma->vm_page_prot);
148 #ifdef CONFIG_PPC_PSERIES
149 /* create /proc/ppc64/ofdt write-only by root */
150 static void proc_ppc64_create_ofdt(void)
152 struct proc_dir_entry *ent;
154 ent = create_proc_entry("ppc64/ofdt", S_IWUSR, NULL);
159 ent->proc_fops = &ofdt_fops;
164 * ofdt_write - perform operations on the Open Firmware device tree
167 * @buf: command and arguments
168 * @count: size of the command buffer
171 * Operations supported at this time are addition and removal of
172 * whole nodes along with their properties. Operations on individual
173 * properties are not implemented (yet).
175 static ssize_t ofdt_write(struct file *file, const char __user *buf, size_t count,
182 if (!(kbuf = kmalloc(count + 1, GFP_KERNEL))) {
186 if (copy_from_user(kbuf, buf, count)) {
193 tmp = strchr(kbuf, ' ');
201 if (!strcmp(kbuf, "add_node"))
202 rv = do_add_node(tmp, count - (tmp - kbuf));
203 else if (!strcmp(kbuf, "remove_node"))
204 rv = do_remove_node(tmp);
209 return rv ? rv : count;
212 static int do_remove_node(char *buf)
214 struct device_node *node;
217 if ((node = of_find_node_by_path(buf)))
218 rv = of_remove_node(node);
224 static int do_add_node(char *buf, size_t bufsize)
226 char *path, *end, *name;
227 struct device_node *np;
228 struct property *prop = NULL;
229 unsigned char* value;
234 buf = strchr(buf, ' ');
240 if ((np = of_find_node_by_path(path))) {
245 /* rv = build_prop_list(tmp, bufsize - (tmp - buf), &proplist); */
247 (buf = parse_next_property(buf, end, &name, &length, &value))) {
248 struct property *last = prop;
250 prop = new_property(name, length, value, last);
262 rv = of_add_node(path, prop);
266 release_prop_list(prop);
270 static struct property *new_property(const char *name, const int length,
271 const unsigned char *value, struct property *last)
273 struct property *new = kmalloc(sizeof(*new), GFP_KERNEL);
277 memset(new, 0, sizeof(*new));
279 if (!(new->name = kmalloc(strlen(name) + 1, GFP_KERNEL)))
281 if (!(new->value = kmalloc(length + 1, GFP_KERNEL)))
284 strcpy(new->name, name);
285 memcpy(new->value, value, length);
286 *(((char *)new->value) + length) = 0;
287 new->length = length;
301 * parse_next_property - process the next property from raw input buffer
302 * @buf: input buffer, must be nul-terminated
303 * @end: end of the input buffer + 1, for validation
304 * @name: return value; set to property name in buf
305 * @length: return value; set to length of value
306 * @value: return value; set to the property value in buf
308 * Note that the caller must make copies of the name and value returned,
309 * this function does no allocation or copying of the data. Return value
310 * is set to the next name in buf, or NULL on error.
312 static char * parse_next_property(char *buf, char *end, char **name, int *length,
313 unsigned char **value)
319 tmp = strchr(buf, ' ');
321 printk(KERN_ERR "property parse failed in %s at line %d\n",
322 __FUNCTION__, __LINE__);
328 printk(KERN_ERR "property parse failed in %s at line %d\n",
329 __FUNCTION__, __LINE__);
333 /* now we're on the length */
335 *length = simple_strtoul(tmp, &tmp, 10);
337 printk(KERN_ERR "property parse failed in %s at line %d\n",
338 __FUNCTION__, __LINE__);
341 if (*tmp != ' ' || ++tmp >= end) {
342 printk(KERN_ERR "property parse failed in %s at line %d\n",
343 __FUNCTION__, __LINE__);
347 /* now we're on the value */
351 printk(KERN_ERR "property parse failed in %s at line %d\n",
352 __FUNCTION__, __LINE__);
355 else if (tmp < end && *tmp != ' ' && *tmp != '\0') {
356 printk(KERN_ERR "property parse failed in %s at line %d\n",
357 __FUNCTION__, __LINE__);
362 /* and now we should be on the next name, or the end */
366 static void release_prop_list(const struct property *prop)
368 struct property *next;
369 for (; prop; prop = next) {
377 #endif /* defined(CONFIG_PPC_PSERIES) */