1 // SPDX-License-Identifier: GPL-2.0 1 2 /* 3 * tree.c: Basic device tree traversal/scannin 4 * prom library. 5 * 6 * Copyright (C) 1995 David S. Miller (davem@c 7 */ 8 9 #include <linux/string.h> 10 #include <linux/types.h> 11 #include <linux/kernel.h> 12 #include <linux/sched.h> 13 #include <linux/ctype.h> 14 #include <linux/module.h> 15 16 #include <asm/openprom.h> 17 #include <asm/oplib.h> 18 19 extern void restore_current(void); 20 21 static char promlib_buf[128]; 22 23 /* Internal version of prom_getchild that does 24 static phandle __prom_getchild(phandle node) 25 { 26 unsigned long flags; 27 phandle cnode; 28 29 spin_lock_irqsave(&prom_lock, flags); 30 cnode = prom_nodeops->no_child(node); 31 restore_current(); 32 spin_unlock_irqrestore(&prom_lock, fla 33 34 return cnode; 35 } 36 37 /* Return the child of node 'node' or zero if 38 * direct descendent. 39 */ 40 phandle prom_getchild(phandle node) 41 { 42 phandle cnode; 43 44 if ((s32)node == -1) 45 return 0; 46 47 cnode = __prom_getchild(node); 48 if (cnode == 0 || (s32)cnode == -1) 49 return 0; 50 51 return cnode; 52 } 53 EXPORT_SYMBOL(prom_getchild); 54 55 /* Internal version of prom_getsibling that do 56 static phandle __prom_getsibling(phandle node) 57 { 58 unsigned long flags; 59 phandle cnode; 60 61 spin_lock_irqsave(&prom_lock, flags); 62 cnode = prom_nodeops->no_nextnode(node 63 restore_current(); 64 spin_unlock_irqrestore(&prom_lock, fla 65 66 return cnode; 67 } 68 69 /* Return the next sibling of node 'node' or z 70 * at this level of depth in the tree. 71 */ 72 phandle prom_getsibling(phandle node) 73 { 74 phandle sibnode; 75 76 if ((s32)node == -1) 77 return 0; 78 79 sibnode = __prom_getsibling(node); 80 if (sibnode == 0 || (s32)sibnode == -1 81 return 0; 82 83 return sibnode; 84 } 85 EXPORT_SYMBOL(prom_getsibling); 86 87 /* Return the length in bytes of property 'pro 88 * Return -1 on error. 89 */ 90 int prom_getproplen(phandle node, const char * 91 { 92 int ret; 93 unsigned long flags; 94 95 if((!node) || (!prop)) 96 return -1; 97 98 spin_lock_irqsave(&prom_lock, flags); 99 ret = prom_nodeops->no_proplen(node, p 100 restore_current(); 101 spin_unlock_irqrestore(&prom_lock, fla 102 return ret; 103 } 104 EXPORT_SYMBOL(prom_getproplen); 105 106 /* Acquire a property 'prop' at node 'node' an 107 * 'buffer' which has a size of 'bufsize'. If 108 * was successful the length will be returned, 109 */ 110 int prom_getproperty(phandle node, const char 111 { 112 int plen, ret; 113 unsigned long flags; 114 115 plen = prom_getproplen(node, prop); 116 if((plen > bufsize) || (plen == 0) || 117 return -1; 118 /* Ok, things seem all right. */ 119 spin_lock_irqsave(&prom_lock, flags); 120 ret = prom_nodeops->no_getprop(node, p 121 restore_current(); 122 spin_unlock_irqrestore(&prom_lock, fla 123 return ret; 124 } 125 EXPORT_SYMBOL(prom_getproperty); 126 127 /* Acquire an integer property and return its 128 * on failure. 129 */ 130 int prom_getint(phandle node, char *prop) 131 { 132 static int intprop; 133 134 if(prom_getproperty(node, prop, (char 135 return intprop; 136 137 return -1; 138 } 139 EXPORT_SYMBOL(prom_getint); 140 141 /* Acquire an integer property, upon error ret 142 * integer. 143 */ 144 int prom_getintdefault(phandle node, char *pro 145 { 146 int retval; 147 148 retval = prom_getint(node, property); 149 if(retval == -1) return deflt; 150 151 return retval; 152 } 153 EXPORT_SYMBOL(prom_getintdefault); 154 155 /* Acquire a boolean property, 1=TRUE 0=FALSE. 156 int prom_getbool(phandle node, char *prop) 157 { 158 int retval; 159 160 retval = prom_getproplen(node, prop); 161 if(retval == -1) return 0; 162 return 1; 163 } 164 EXPORT_SYMBOL(prom_getbool); 165 166 /* Acquire a property whose value is a string, 167 * string on error. The char pointer is the u 168 * buffer. 169 */ 170 void prom_getstring(phandle node, char *prop, 171 { 172 int len; 173 174 len = prom_getproperty(node, prop, use 175 if(len != -1) return; 176 user_buf[0] = 0; 177 } 178 EXPORT_SYMBOL(prom_getstring); 179 180 181 /* Search siblings at 'node_start' for a node 182 * 'nodename'. Return node if successful, zer 183 */ 184 phandle prom_searchsiblings(phandle node_start 185 { 186 187 phandle thisnode; 188 int error; 189 190 for(thisnode = node_start; thisnode; 191 thisnode=prom_getsibling(thisnode) 192 error = prom_getproperty(thisn 193 sizeo 194 /* Should this ever happen? */ 195 if(error == -1) continue; 196 if(strcmp(nodename, promlib_bu 197 } 198 199 return 0; 200 } 201 EXPORT_SYMBOL(prom_searchsiblings); 202 203 /* Interal version of nextprop that does not a 204 static char *__prom_nextprop(phandle node, cha 205 { 206 unsigned long flags; 207 char *prop; 208 209 spin_lock_irqsave(&prom_lock, flags); 210 prop = prom_nodeops->no_nextprop(node, 211 restore_current(); 212 spin_unlock_irqrestore(&prom_lock, fla 213 214 return prop; 215 } 216 217 /* Return the property type string after prope 218 * at node 'node' . Returns empty string if n 219 * property types for this node. 220 */ 221 char *prom_nextprop(phandle node, char *oprop, 222 { 223 if (node == 0 || (s32)node == -1) 224 return ""; 225 226 return __prom_nextprop(node, oprop); 227 } 228 EXPORT_SYMBOL(prom_nextprop); 229 230 phandle prom_finddevice(char *name) 231 { 232 char nbuf[128]; 233 char *s = name, *d; 234 phandle node = prom_root_node, node2; 235 unsigned int which_io, phys_addr; 236 struct linux_prom_registers reg[PROMRE 237 238 while (*s++) { 239 if (!*s) return node; /* path 240 node = prom_getchild(node); 241 242 for (d = nbuf; *s != 0 && *s ! 243 *d++ = *s++; 244 *d = 0; 245 246 node = prom_searchsiblings(nod 247 if (!node) 248 return 0; 249 250 if (*s == '@') { 251 if (isxdigit(s[1]) && 252 which_io = sim 253 phys_addr = si 254 if (d != s + 3 255 && d <= s 256 node2 257 while 258 259 260 261 262 263 264 265 266 267 268 } 269 } 270 } 271 while (*s != 0 && *s ! 272 } 273 } 274 return node; 275 } 276 EXPORT_SYMBOL(prom_finddevice); 277 278 /* Set property 'pname' at node 'node' to valu 279 * of 'size' bytes. Return the number of byte 280 */ 281 int prom_setprop(phandle node, const char *pna 282 { 283 unsigned long flags; 284 int ret; 285 286 if (size == 0) 287 return 0; 288 if ((pname == NULL) || (value == NULL) 289 return 0; 290 spin_lock_irqsave(&prom_lock, flags); 291 ret = prom_nodeops->no_setprop(node, p 292 restore_current(); 293 spin_unlock_irqrestore(&prom_lock, fla 294 return ret; 295 } 296 EXPORT_SYMBOL(prom_setprop); 297 298 phandle prom_inst2pkg(int inst) 299 { 300 phandle node; 301 unsigned long flags; 302 303 spin_lock_irqsave(&prom_lock, flags); 304 node = (*romvec->pv_v2devops.v2_inst2p 305 restore_current(); 306 spin_unlock_irqrestore(&prom_lock, fla 307 if ((s32)node == -1) 308 return 0; 309 return node; 310 } 311
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.