1 /* $NetBSD: ofw_subr.c,v 1.6 2000/03/13 23:52:36 soren Exp $ */ 2 3 /* 4 * Copyright 1998 5 * Digital Equipment Corporation. All rights reserved. 6 * 7 * This software is furnished under license and may be used and 8 * copied only in accordance with the following terms and conditions. 9 * Subject to these conditions, you may download, copy, install, 10 * use, modify and distribute this software in source and/or binary 11 * form. No title or ownership is transferred hereby. 12 * 13 * 1) Any source code used, modified or distributed must reproduce 14 * and retain this copyright notice and list of conditions as 15 * they appear in the source file. 16 * 17 * 2) No right is granted to use any trade name, trademark, or logo of 18 * Digital Equipment Corporation. Neither the "Digital Equipment 19 * Corporation" name nor any trademark or logo of Digital Equipment 20 * Corporation may be used to endorse or promote products derived 21 * from this software without the prior written permission of 22 * Digital Equipment Corporation. 23 * 24 * 3) This software is provided "AS-IS" and any express or implied 25 * warranties, including but not limited to, any implied warranties 26 * of merchantability, fitness for a particular purpose, or 27 * non-infringement are disclaimed. In no event shall DIGITAL be 28 * liable for any damages whatsoever, and in particular, DIGITAL 29 * shall not be liable for special, indirect, consequential, or 30 * incidental damages or damages for lost profits, loss of 31 * revenue or loss of use, whether such damages arise in contract, 32 * negligence, tort, under statute, in equity, at law or otherwise, 33 * even if advised of the possibility of such damage. 34 */ 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/malloc.h> 39 #include <dev/ofw/openfirm.h> 40 41 #define OFW_MAX_STACK_BUF_SIZE 256 42 #define OFW_PATH_BUF_SIZE 512 43 44 /* 45 * int of_decode_int(p) 46 * 47 * This routine converts OFW encoded-int datums 48 * into the integer format of the host machine. 49 * 50 * It is primarily used to convert integer properties 51 * returned by the OF_getprop routine. 52 * 53 * Arguments: 54 * p pointer to unsigned char array which is an 55 * OFW-encoded integer. 56 * 57 * Return Value: 58 * Decoded integer value of argument p. 59 * 60 * Side Effects: 61 * None. 62 */ 63 int 64 of_decode_int(p) 65 const unsigned char *p; 66 { 67 unsigned int i = *p++ << 8; 68 i = (i + *p++) << 8; 69 i = (i + *p++) << 8; 70 return (i + *p); 71 } 72 73 /* 74 * int of_compatible(phandle, strings) 75 * 76 * This routine checks an OFW node's "compatible" entry to see if 77 * it matches any of the provided strings. 78 * 79 * It should be used when determining whether a driver can drive 80 * a partcular device. 81 * 82 * Arguments: 83 * phandle OFW phandle of device to be checked for 84 * compatibility. 85 * strings Array of containing expected "compatibility" 86 * property values, presence of any of which 87 * indicates compatibility. 88 * 89 * Return Value: 90 * -1 if none of the strings are found in phandle's "compatiblity" 91 * property, or the index of the string in "strings" of the first 92 * string found in phandle's "compatibility" property. 93 * 94 * Side Effects: 95 * None. 96 */ 97 int 98 of_compatible(phandle, strings) 99 int phandle; 100 const char * const *strings; 101 { 102 int len, allocated, rv; 103 char *buf; 104 const char *sp, *nsp; 105 106 len = OF_getproplen(phandle, "compatible"); 107 if (len <= 0) 108 return (-1); 109 110 if (len > OFW_MAX_STACK_BUF_SIZE) { 111 buf = malloc(len, M_TEMP, M_WAITOK); 112 allocated = 1; 113 } else { 114 buf = alloca(len); 115 allocated = 0; 116 } 117 118 /* 'compatible' size should not change. */ 119 if (OF_getprop(phandle, "compatible", buf, len) != len) { 120 rv = -1; 121 goto out; 122 } 123 124 sp = buf; 125 while (len && (nsp = memchr(sp, 0, len)) != NULL) { 126 /* look for a match among the strings provided */ 127 for (rv = 0; strings[rv] != NULL; rv++) 128 if (strcmp(sp, strings[rv]) == 0) 129 goto out; 130 131 nsp++; /* skip over NUL char */ 132 len -= (nsp - sp); 133 sp = nsp; 134 } 135 rv = -1; 136 137 out: 138 if (allocated) 139 free(buf, M_TEMP); 140 return (rv); 141 142 } 143 144 /* 145 * int of_packagename(phandle, buf, bufsize) 146 * 147 * This routine places the last component of an OFW node's name 148 * into a user-provided buffer. 149 * 150 * It can be used during autoconfiguration to make printing of 151 * device names more informative. 152 * 153 * Arguments: 154 * phandle OFW phandle of device whose name name is 155 * desired. 156 * buf Buffer to contain device name, provided by 157 * caller. (For now, must be at least 4 158 * bytes long.) 159 * bufsize Length of buffer referenced by 'buf', in 160 * bytes. 161 * 162 * Return Value: 163 * -1 if the device path name could not be obtained or would 164 * not fit in the allocated temporary buffer, or zero otherwise 165 * (meaning that the leaf node name was successfully extracted). 166 * 167 * Side Effects: 168 * If the leaf node name was successfully extracted, 'buf' is 169 * filled in with at most 'bufsize' bytes of the leaf node 170 * name. If the leaf node was not successfully extracted, a 171 * somewhat meaningful string is placed in the buffer. In 172 * either case, the contents of 'buf' will be NUL-terminated. 173 */ 174 int 175 of_packagename(phandle, buf, bufsize) 176 int phandle; 177 char *buf; 178 int bufsize; 179 { 180 char *pbuf; 181 const char *lastslash; 182 int l, rv; 183 184 pbuf = malloc(OFW_PATH_BUF_SIZE, M_TEMP, M_WAITOK); 185 l = OF_package_to_path(phandle, pbuf, OFW_PATH_BUF_SIZE); 186 187 /* check that we could get the name, and that it's not too long. */ 188 if (l < 0 || 189 (l == OFW_PATH_BUF_SIZE && pbuf[OFW_PATH_BUF_SIZE - 1] != '\0')) { 190 /* XXX should use snprintf! */ 191 if (bufsize >= 25) 192 sprintf(buf, "??? (phandle 0x%x)", phandle); 193 else if (bufsize >= 4) 194 strcpy(buf, "???"); 195 else 196 panic("of_packagename: bufsize = %d is silly", 197 bufsize); 198 rv = -1; 199 } else { 200 pbuf[l] = '\0'; 201 lastslash = strrchr(pbuf, '/'); 202 strncpy(buf, (lastslash == NULL) ? pbuf : (lastslash + 1), 203 bufsize); 204 buf[bufsize - 1] = '\0'; /* in case it's fills the buffer. */ 205 rv = 0; 206 } 207 208 free(pbuf, M_TEMP); 209 return (rv); 210 } 211