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