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
31char *
32prom_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 */
58void
59prom_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 */
158void
159prom_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