1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <sys/promif.h>
29 #include <sys/promimpl.h>
30 
31 char *
prom_path_gettoken(register char * from,register char * to)32 prom_path_gettoken(register char *from, register char *to)
33 {
34 	while (*from) {
35 		switch (*from) {
36 		case '/':
37 		case '@':
38 		case ':':
39 		case ',':
40 			*to = '\0';
41 			return (from);
42 		default:
43 			*to++ = *from++;
44 		}
45 	}
46 	*to = '\0';
47 	return (from);
48 }
49 
50 /*
51  * Given an OBP pathname, do the best we can to fully expand
52  * the OBP pathname, in place in the callers buffer.
53  *
54  * If we have to complete the addrspec of any component, we can
55  * only handle devices that have a maximum of NREGSPECS "reg" specs.
56  * We cannot allocate memory inside this function.
57  */
58 void
prom_pathname(char * pathname)59 prom_pathname(char *pathname)
60 {
61 	char tmp[OBP_MAXPATHLEN];
62 	char *from = tmp;
63 	char *to = pathname;
64 	char *p;
65 	cell_t ci[7];
66 #ifdef PROM_32BIT_ADDRS
67 	char *opathname = NULL;
68 #endif /* PROM_32BIT_ADDRS */
69 
70 	if ((to == (char *)0) || (*to == (char)0))
71 		return;
72 
73 #ifdef PROM_32BIT_ADDRS
74 	if ((uintptr_t)pathname > (uint32_t)-1) {
75 		opathname = pathname;
76 		pathname = promplat_alloc(OBP_MAXPATHLEN);
77 		if (pathname == NULL) {
78 			return;
79 		}
80 		(void) prom_strcpy(pathname, opathname);
81 		to = pathname;
82 	}
83 	if ((uintptr_t)from > (uint32_t)-1) {
84 		from = promplat_alloc(OBP_MAXPATHLEN);
85 		if (from == NULL) {
86 			if (opathname != NULL)
87 				promplat_free(pathname, OBP_MAXPATHLEN);
88 			return;
89 		}
90 	}
91 #endif /* PROM_32BIT_ADDRS */
92 
93 	promif_preprom();
94 
95 	(void) prom_strcpy(from, to);
96 	*to = (char)0;
97 
98 	ci[0] = p1275_ptr2cell("canon");	/* Service name */
99 	ci[1] = (cell_t)3;			/* #argument cells */
100 	ci[2] = (cell_t)1;			/* #result cells */
101 	ci[3] = p1275_ptr2cell(from);		/* Arg1: token */
102 	ci[4] = p1275_ptr2cell(to);		/* Arg2: buffer address */
103 	ci[5] = p1275_uint2cell(OBP_MAXPATHLEN); /* Arg3: buffer length */
104 
105 	(void) p1275_cif_handler(&ci);
106 
107 	promif_postprom();
108 
109 #ifdef PROM_32BIT_ADDRS
110 	if (opathname != NULL) {
111 		(void) prom_strcpy(opathname, pathname);
112 		promplat_free(pathname, OBP_MAXPATHLEN);
113 		to = pathname = opathname;
114 	}
115 	if (from != tmp) {
116 		(void) prom_strcpy(tmp, from);
117 		promplat_free(from, OBP_MAXPATHLEN);
118 		from = tmp;
119 	}
120 #endif /* PROM_32BIT_ADDRS */
121 
122 	/*
123 	 * workaround for bugid 1218110, the prom strips the
124 	 * options from the input string ... save options at
125 	 * at the end of the string if the prom didn't.
126 	 * NB: The workaround only preserves options in the last
127 	 * component of the string.
128 	 */
129 
130 	/*
131 	 * If there are any options in the last component of the
132 	 * output, the prom has copied them; No workaround required.
133 	 */
134 	if ((p = prom_strrchr(to, '/')) == 0)
135 		return;
136 	if ((p = prom_strchr(p, ':')) != 0)
137 		return;
138 
139 	/*
140 	 * If there are no options in the input ... there's
141 	 * nothing to preserve; return.
142 	 */
143 	if ((p = prom_strrchr(from, '/')) == 0)
144 		p = from;
145 	if ((p = prom_strchr(p, ':')) == 0)
146 		return;
147 
148 	/*
149 	 * Concatenate the options we found to the end of the output string.
150 	 */
151 	(void) prom_strcat(to, p);
152 }
153 
154 /*
155  * Strip any options strings from an OBP pathname.
156  * Output buffer (to) expected to be as large as input buffer (from).
157  */
158 void
prom_strip_options(char * from,char * to)159 prom_strip_options(char *from, char *to)
160 {
161 	while (*from != (char)0)  {
162 		if (*from == ':')  {
163 			while ((*from != (char)0) && (*from != '/'))
164 				++from;
165 		} else
166 			*to++ = *from++;
167 	}
168 	*to = (char)0;
169 }
170