static int __init prom_common_nextprop(phandle node, char *prev, char *buf) { const char *name; buf[0] = '\0'; name = prom_nextprop(node, prev, buf); return handle_nextprop_quirks(buf, name); }
static struct property * __init build_one_prop(phandle node, char *prev, char *special_name, void *special_val, int special_len) { static struct property *tmp = NULL; struct property *p; const char *name; if (tmp) { p = tmp; memset(p, 0, sizeof(*p) + 32); tmp = NULL; } else { p = prom_early_alloc(sizeof(struct property) + 32); p->unique_id = prom_unique_id++; } p->name = (char *) (p + 1); if (special_name) { strcpy(p->name, special_name); p->length = special_len; p->value = prom_early_alloc(special_len); memcpy(p->value, special_val, special_len); } else { if (prev == NULL) { name = prom_firstprop(node, p->name); } else { name = prom_nextprop(node, prev, p->name); } if (!name || strlen(name) == 0) { tmp = p; return NULL; } #ifdef CONFIG_SPARC32 strcpy(p->name, name); #endif p->length = prom_getproplen(node, p->name); if (p->length <= 0) { p->length = 0; } else { int len; p->value = prom_early_alloc(p->length + 1); len = prom_getproperty(node, p->name, p->value, p->length); if (len <= 0) p->length = 0; ((unsigned char *)p->value)[p->length] = '\0'; } } return p; }
int prom_node_has_property(int node, char *prop) { char *current_property = ""; do { current_property = prom_nextprop(node, current_property, NULL); if(!strcmp(current_property, prop)) return 1; } while (*current_property); return 0; }
int prom_node_has_property(phandle node, const char *prop) { char buf [32]; *buf = 0; do { prom_nextprop(node, buf, buf); if (!strcmp(buf, prop)) return 1; } while (*buf); return 0; }
ddi_prop_t * get_proplist(char *name) { ddi_prop_t *plist, *npp, *plast; char *curprop, *newprop; unsigned char *propval; unsigned long id; plist = NULL; plast = NULL; id = prom_findnode_byname(prom_rootnode(), name); if (id == 0) return (plist); curprop = ""; while (newprop = (char *)prom_nextprop(curprop)) { curprop = strdup(newprop); npp = (ddi_prop_t *)malloc(sizeof (ddi_prop_t)); if (npp == 0) exit(_error(PERROR, mfail)); propval = prom_getprop(curprop, &npp->prop_len); npp->prop_name = curprop; if (propval != NULL) { npp->prop_val = (char *)malloc(npp->prop_len); if (npp->prop_val == 0) exit(_error(PERROR, mfail)); memcpy(npp->prop_val, propval, npp->prop_len); } else npp->prop_val = NULL; npp->prop_next = NULL; if (plast == NULL) { plist = npp; } else { plast->prop_next = npp; } plast = npp; } return (plist); }
static ssize_t property_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { struct inode *inode = filp->f_dentry->d_inode; int i, j, k; u32 node; char *p, *s; u32 *q; openprom_property *op; char buffer[64]; if (filp->f_pos >= 0xffffff || count >= 0xffffff) return -EINVAL; if (!filp->private_data) { node = nodes[(u16)((long)inode->u.generic_ip)].node; i = ((u32)(long)inode->u.generic_ip) >> 16; if ((u16)((long)inode->u.generic_ip) == aliases) { if (i >= aliases_nodes) p = NULL; else p = alias_names [i]; } else for (p = prom_firstprop (node, buffer); i && p && *p; p = prom_nextprop (node, p, buffer), i--) /* nothing */ ; if (!p || !*p) return -EIO; i = prom_getproplen (node, p); if (i < 0) { if ((u16)((long)inode->u.generic_ip) == aliases) i = 0; else return -EIO; } k = i; if (i < 64) i = 64; filp->private_data = kmalloc (sizeof (openprom_property) + (j = strlen (p)) + 2 * i, GFP_KERNEL); if (!filp->private_data) return -ENOMEM; op = (openprom_property *)filp->private_data; op->flag = 0; op->alloclen = 2 * i; strcpy (op->name, p); op->value = (char *)(((unsigned long)(op->name + j + 4)) & ~3); op->len = k; if (k && prom_getproperty (node, p, op->value, i) < 0) return -EIO; op->value [k] = 0; if (k) { for (s = NULL, p = op->value; p < op->value + k; p++) { if ((*p >= ' ' && *p <= '~') || *p == '\n') { op->flag |= OPP_STRING; s = p; continue; } if (p > op->value && !*p && s == p - 1) { if (p < op->value + k - 1) op->flag |= OPP_STRINGLIST; else op->flag |= OPP_ASCIIZ; continue; } if (k == 1 && !*p) { op->flag |= (OPP_STRING|OPP_ASCIIZ); break; } op->flag &= ~(OPP_STRING|OPP_STRINGLIST); if (k & 3) op->flag |= OPP_HEXSTRING; else op->flag |= OPP_BINARY; break; } if (op->flag & OPP_STRINGLIST) op->flag &= ~(OPP_STRING); if (op->flag & OPP_ASCIIZ) op->len--; } } else
/* * NetBSD /dev/openprom ioctl calls. */ static int openprom_bsd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) { DATA *data = (DATA *) file->private_data; struct opiocdesc op; unsigned long flags; int error, node, len; char *str, *tmp; char buffer[64]; static int cnt; switch (cmd) { case OPIOCGET: if (copy_from_user(&op, (void *)arg, sizeof(op))) return -EFAULT; if (!goodnode(op.op_nodeid,data)) return -EINVAL; error = copyin_string(op.op_name, op.op_namelen, &str); if (error) return error; save_and_cli(flags); len = prom_getproplen(op.op_nodeid,str); restore_flags(flags); if (len > op.op_buflen) { kfree(str); return -ENOMEM; } op.op_buflen = len; if (len <= 0) { kfree(str); /* Verified by the above copy_from_user */ if (__copy_to_user((void *)arg, &op, sizeof(op))) return -EFAULT; return 0; } tmp = kmalloc(len + 1, GFP_KERNEL); if (!tmp) { kfree(str); return -ENOMEM; } save_and_cli(flags); prom_getproperty(op.op_nodeid, str, tmp, len); restore_flags(flags); tmp[len] = '\0'; error = __copy_to_user((void *)arg, &op, sizeof(op)); if (!error) error = copy_to_user(op.op_buf, tmp, len); kfree(tmp); kfree(str); return error; case OPIOCNEXTPROP: if (copy_from_user(&op, (void *)arg, sizeof(op))) return -EFAULT; if (!goodnode(op.op_nodeid,data)) return -EINVAL; error = copyin_string(op.op_name, op.op_namelen, &str); if (error) return error; save_and_cli(flags); tmp = prom_nextprop(op.op_nodeid,str,buffer); restore_flags(flags); if (tmp) { len = strlen(tmp); if (len > op.op_buflen) len = op.op_buflen; else op.op_buflen = len; } else { len = op.op_buflen = 0; } error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(op)); if (error) { kfree(str); return error; } error = verify_area(VERIFY_WRITE, op.op_buf, len); if (error) { kfree(str); return error; } error = __copy_to_user((void *)arg, &op, sizeof(op)); if (!error) error = __copy_to_user(op.op_buf, tmp, len); kfree(str); return error; case OPIOCSET: if (copy_from_user(&op, (void *)arg, sizeof(op))) return -EFAULT; if (!goodnode(op.op_nodeid,data)) return -EINVAL; error = copyin_string(op.op_name, op.op_namelen, &str); if (error) return error; error = copyin_string(op.op_buf, op.op_buflen, &tmp); if (error) { kfree(str); return error; } save_and_cli(flags); len = prom_setprop(op.op_nodeid,str,tmp,op.op_buflen+1); restore_flags(flags); if (len != op.op_buflen) return -EINVAL; kfree(str); kfree(tmp); return 0; case OPIOCGETOPTNODE: if (copy_to_user((void *)arg, &options_node, sizeof(int))) return -EFAULT; return 0; case OPIOCGETNEXT: case OPIOCGETCHILD: if (copy_from_user(&node, (void *)arg, sizeof(int))) return -EFAULT; save_and_cli(flags); if (cmd == OPIOCGETNEXT) node = __prom_getsibling(node); else node = __prom_getchild(node); restore_flags(flags); if (__copy_to_user((void *)arg, &node, sizeof(int))) return -EFAULT; return 0; default: if (cnt++ < 10) printk(KERN_INFO "openprom_bsd_ioctl: cmd 0x%X\n", cmd); return -EINVAL; } }
/* * SunOS and Solaris /dev/openprom ioctl calls. */ static int openprom_sunos_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg, int node) { DATA *data = (DATA *) file->private_data; char buffer[OPROMMAXPARAM+1], *buf; struct openpromio *opp; unsigned long flags; int bufsize, len, error = 0; extern char saved_command_line[]; static int cnt; if (cmd == OPROMSETOPT) bufsize = getstrings((void *)arg, &opp); else bufsize = copyin((void *)arg, &opp); if (bufsize < 0) return bufsize; switch (cmd) { case OPROMGETOPT: case OPROMGETPROP: save_and_cli(flags); len = prom_getproplen(node, opp->oprom_array); restore_flags(flags); if (len <= 0 || len > bufsize) { error = copyout((void *)arg, opp, sizeof(int)); break; } save_and_cli(flags); len = prom_getproperty(node, opp->oprom_array, buffer, bufsize); restore_flags(flags); memcpy(opp->oprom_array, buffer, len); opp->oprom_array[len] = '\0'; opp->oprom_size = len; error = copyout((void *)arg, opp, sizeof(int) + bufsize); break; case OPROMNXTOPT: case OPROMNXTPROP: save_and_cli(flags); buf = prom_nextprop(node, opp->oprom_array, buffer); restore_flags(flags); len = strlen(buf); if (len == 0 || len + 1 > bufsize) { error = copyout((void *)arg, opp, sizeof(int)); break; } memcpy(opp->oprom_array, buf, len); opp->oprom_array[len] = '\0'; opp->oprom_size = ++len; error = copyout((void *)arg, opp, sizeof(int) + bufsize); break; case OPROMSETOPT: case OPROMSETOPT2: buf = opp->oprom_array + strlen(opp->oprom_array) + 1; len = opp->oprom_array + bufsize - buf; save_and_cli(flags); error = prom_setprop(options_node, opp->oprom_array, buf, len); restore_flags(flags); if (error < 0) error = -EINVAL; break; case OPROMNEXT: case OPROMCHILD: case OPROMSETCUR: if (bufsize < sizeof(int)) { error = -EINVAL; break; } node = *((int *) opp->oprom_array); save_and_cli(flags); switch (cmd) { case OPROMNEXT: node = __prom_getsibling(node); break; case OPROMCHILD: node = __prom_getchild(node); break; case OPROMSETCUR: break; } restore_flags(flags); data->current_node = node; *((int *)opp->oprom_array) = node; opp->oprom_size = sizeof(int); error = copyout((void *)arg, opp, bufsize + sizeof(int)); break; case OPROMPCI2NODE: error = -EINVAL; if (bufsize >= 2*sizeof(int)) { #ifdef CONFIG_PCI struct pci_dev *pdev; struct pcidev_cookie *pcp; pdev = pci_find_slot (((int *) opp->oprom_array)[0], ((int *) opp->oprom_array)[1]); pcp = pdev->sysdata; if (pcp != NULL && pcp->prom_node != -1 && pcp->prom_node) { node = pcp->prom_node; data->current_node = node; *((int *)opp->oprom_array) = node; opp->oprom_size = sizeof(int); error = copyout((void *)arg, opp, bufsize + sizeof(int)); } #endif } break; case OPROMPATH2NODE: save_and_cli(flags); node = prom_finddevice(opp->oprom_array); restore_flags(flags); data->current_node = node; *((int *)opp->oprom_array) = node; opp->oprom_size = sizeof(int); error = copyout((void *)arg, opp, bufsize + sizeof(int)); break; case OPROMGETBOOTARGS: buf = saved_command_line; len = strlen(buf); if (len > bufsize) { error = -EINVAL; break; } strcpy(opp->oprom_array, buf); opp->oprom_size = len; error = copyout((void *)arg, opp, bufsize + sizeof(int)); break; case OPROMU2P: case OPROMGETCONS: case OPROMGETFBNAME: if (cnt++ < 10) printk(KERN_INFO "openprom_sunos_ioctl: unimplemented ioctl\n"); error = -EINVAL; break; default: if (cnt++ < 10) printk(KERN_INFO "openprom_sunos_ioctl: cmd 0x%X, arg 0x%lX\n", cmd, arg); error = -EINVAL; break; } kfree(opp); return error; }
int openpromioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l) { struct opiocdesc *op; int node, optionsnode, len, ok, error, s; char *name, *value, *nextprop; optionsnode = prom_getoptionsnode(); /* All too easy... */ if (cmd == OPIOCGETOPTNODE) { *(int *)data = optionsnode; return (0); } /* Verify node id */ op = (struct opiocdesc *)data; node = op->op_nodeid; if (node != 0 && node != lastnode && node != optionsnode) { /* Not an easy one, must search for it */ s = splhigh(); ok = openpromcheckid(findroot(), node); splx(s); if (!ok) return (EINVAL); lastnode = node; } name = value = NULL; error = 0; switch (cmd) { case OPIOCGET: if ((flags & FREAD) == 0) return (EBADF); if (node == 0) return (EINVAL); error = openpromgetstr(op->op_namelen, op->op_name, &name); if (error) break; s = splhigh(); len = prom_proplen(node, name); splx(s); if (len > op->op_buflen) { error = ENOMEM; break; } op->op_buflen = len; /* -1 means no entry; 0 means no value */ if (len <= 0) break; value = malloc(len, M_TEMP, M_WAITOK); s = splhigh(); error = prom_getprop(node, name, 1, &len, &value); splx(s); if (error != 0) break; error = copyout(value, op->op_buf, len); break; case OPIOCSET: if ((flags & FWRITE) == 0) return (EBADF); if (node == 0) return (EINVAL); error = openpromgetstr(op->op_namelen, op->op_name, &name); if (error) break; error = openpromgetstr(op->op_buflen, op->op_buf, &value); if (error) break; s = splhigh(); len = prom_setprop(node, name, value, op->op_buflen + 1); splx(s); if (len != op->op_buflen) error = EINVAL; break; case OPIOCNEXTPROP: if ((flags & FREAD) == 0) return (EBADF); if (node == 0) return (EINVAL); error = openpromgetstr(op->op_namelen, op->op_name, &name); if (error) break; s = splhigh(); nextprop = prom_nextprop(node, name); splx(s); len = strlen(nextprop); if (len > op->op_buflen) len = op->op_buflen; else op->op_buflen = len; error = copyout(nextprop, op->op_buf, len); break; case OPIOCGETNEXT: if ((flags & FREAD) == 0) return (EBADF); s = splhigh(); node = nextsibling(node); splx(s); *(int *)data = lastnode = node; break; case OPIOCGETCHILD: if ((flags & FREAD) == 0) return (EBADF); if (node == 0) return (EINVAL); s = splhigh(); node = firstchild(node); splx(s); *(int *)data = lastnode = node; break; case OPIOCFINDDEVICE: if ((flags & FREAD) == 0) return (EBADF); error = openpromgetstr(op->op_namelen, op->op_name, &name); if (error) break; node = prom_finddevice(name); if (node == 0 || node == -1) { error = ENOENT; break; } op->op_nodeid = lastnode = node; break; default: return (ENOTTY); } if (name) free(name, M_TEMP); if (value) free(value, M_TEMP); return (error); }