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