17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*d0495a01Sedp  * Common Development and Distribution License (the "License").
6*d0495a01Sedp  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*d0495a01Sedp  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate #include <sys/promif.h>
297c478bd9Sstevel@tonic-gate #include <sys/promimpl.h>
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate char *
prom_path_gettoken(register char * from,register char * to)327c478bd9Sstevel@tonic-gate prom_path_gettoken(register char *from, register char *to)
337c478bd9Sstevel@tonic-gate {
347c478bd9Sstevel@tonic-gate 	while (*from) {
357c478bd9Sstevel@tonic-gate 		switch (*from) {
367c478bd9Sstevel@tonic-gate 		case '/':
377c478bd9Sstevel@tonic-gate 		case '@':
387c478bd9Sstevel@tonic-gate 		case ':':
397c478bd9Sstevel@tonic-gate 		case ',':
407c478bd9Sstevel@tonic-gate 			*to = '\0';
417c478bd9Sstevel@tonic-gate 			return (from);
427c478bd9Sstevel@tonic-gate 		default:
437c478bd9Sstevel@tonic-gate 			*to++ = *from++;
447c478bd9Sstevel@tonic-gate 		}
457c478bd9Sstevel@tonic-gate 	}
467c478bd9Sstevel@tonic-gate 	*to = '\0';
477c478bd9Sstevel@tonic-gate 	return (from);
487c478bd9Sstevel@tonic-gate }
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate /*
517c478bd9Sstevel@tonic-gate  * Given an OBP pathname, do the best we can to fully expand
527c478bd9Sstevel@tonic-gate  * the OBP pathname, in place in the callers buffer.
537c478bd9Sstevel@tonic-gate  *
547c478bd9Sstevel@tonic-gate  * If we have to complete the addrspec of any component, we can
557c478bd9Sstevel@tonic-gate  * only handle devices that have a maximum of NREGSPECS "reg" specs.
567c478bd9Sstevel@tonic-gate  * We cannot allocate memory inside this function.
577c478bd9Sstevel@tonic-gate  */
587c478bd9Sstevel@tonic-gate void
prom_pathname(char * pathname)597c478bd9Sstevel@tonic-gate prom_pathname(char *pathname)
607c478bd9Sstevel@tonic-gate {
61*d0495a01Sedp 	char tmp[OBP_MAXPATHLEN];
62*d0495a01Sedp 	char *from = tmp;
637c478bd9Sstevel@tonic-gate 	char *to = pathname;
647c478bd9Sstevel@tonic-gate 	char *p;
657c478bd9Sstevel@tonic-gate 	cell_t ci[7];
667c478bd9Sstevel@tonic-gate #ifdef PROM_32BIT_ADDRS
677c478bd9Sstevel@tonic-gate 	char *opathname = NULL;
68*d0495a01Sedp #endif /* PROM_32BIT_ADDRS */
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate 	if ((to == (char *)0) || (*to == (char)0))
717c478bd9Sstevel@tonic-gate 		return;
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate #ifdef PROM_32BIT_ADDRS
747c478bd9Sstevel@tonic-gate 	if ((uintptr_t)pathname > (uint32_t)-1) {
757c478bd9Sstevel@tonic-gate 		opathname = pathname;
767c478bd9Sstevel@tonic-gate 		pathname = promplat_alloc(OBP_MAXPATHLEN);
777c478bd9Sstevel@tonic-gate 		if (pathname == NULL) {
787c478bd9Sstevel@tonic-gate 			return;
797c478bd9Sstevel@tonic-gate 		}
807c478bd9Sstevel@tonic-gate 		(void) prom_strcpy(pathname, opathname);
817c478bd9Sstevel@tonic-gate 		to = pathname;
827c478bd9Sstevel@tonic-gate 	}
83*d0495a01Sedp 	if ((uintptr_t)from > (uint32_t)-1) {
84*d0495a01Sedp 		from = promplat_alloc(OBP_MAXPATHLEN);
85*d0495a01Sedp 		if (from == NULL) {
86*d0495a01Sedp 			if (opathname != NULL)
87*d0495a01Sedp 				promplat_free(pathname, OBP_MAXPATHLEN);
88*d0495a01Sedp 			return;
89*d0495a01Sedp 		}
90*d0495a01Sedp 	}
91*d0495a01Sedp #endif /* PROM_32BIT_ADDRS */
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate 	promif_preprom();
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate 	(void) prom_strcpy(from, to);
967c478bd9Sstevel@tonic-gate 	*to = (char)0;
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate 	ci[0] = p1275_ptr2cell("canon");	/* Service name */
997c478bd9Sstevel@tonic-gate 	ci[1] = (cell_t)3;			/* #argument cells */
1007c478bd9Sstevel@tonic-gate 	ci[2] = (cell_t)1;			/* #result cells */
1017c478bd9Sstevel@tonic-gate 	ci[3] = p1275_ptr2cell(from);		/* Arg1: token */
1027c478bd9Sstevel@tonic-gate 	ci[4] = p1275_ptr2cell(to);		/* Arg2: buffer address */
1037c478bd9Sstevel@tonic-gate 	ci[5] = p1275_uint2cell(OBP_MAXPATHLEN); /* Arg3: buffer length */
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate 	(void) p1275_cif_handler(&ci);
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate 	promif_postprom();
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate #ifdef PROM_32BIT_ADDRS
1107c478bd9Sstevel@tonic-gate 	if (opathname != NULL) {
1117c478bd9Sstevel@tonic-gate 		(void) prom_strcpy(opathname, pathname);
1127c478bd9Sstevel@tonic-gate 		promplat_free(pathname, OBP_MAXPATHLEN);
1137c478bd9Sstevel@tonic-gate 		to = pathname = opathname;
1147c478bd9Sstevel@tonic-gate 	}
115*d0495a01Sedp 	if (from != tmp) {
116*d0495a01Sedp 		(void) prom_strcpy(tmp, from);
117*d0495a01Sedp 		promplat_free(from, OBP_MAXPATHLEN);
118*d0495a01Sedp 		from = tmp;
119*d0495a01Sedp 	}
120*d0495a01Sedp #endif /* PROM_32BIT_ADDRS */
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate 	/*
1237c478bd9Sstevel@tonic-gate 	 * workaround for bugid 1218110, the prom strips the
1247c478bd9Sstevel@tonic-gate 	 * options from the input string ... save options at
1257c478bd9Sstevel@tonic-gate 	 * at the end of the string if the prom didn't.
1267c478bd9Sstevel@tonic-gate 	 * NB: The workaround only preserves options in the last
1277c478bd9Sstevel@tonic-gate 	 * component of the string.
1287c478bd9Sstevel@tonic-gate 	 */
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate 	/*
1317c478bd9Sstevel@tonic-gate 	 * If there are any options in the last component of the
1327c478bd9Sstevel@tonic-gate 	 * output, the prom has copied them; No workaround required.
1337c478bd9Sstevel@tonic-gate 	 */
1347c478bd9Sstevel@tonic-gate 	if ((p = prom_strrchr(to, '/')) == 0)
1357c478bd9Sstevel@tonic-gate 		return;
1367c478bd9Sstevel@tonic-gate 	if ((p = prom_strchr(p, ':')) != 0)
1377c478bd9Sstevel@tonic-gate 		return;
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate 	/*
1407c478bd9Sstevel@tonic-gate 	 * If there are no options in the input ... there's
1417c478bd9Sstevel@tonic-gate 	 * nothing to preserve; return.
1427c478bd9Sstevel@tonic-gate 	 */
1437c478bd9Sstevel@tonic-gate 	if ((p = prom_strrchr(from, '/')) == 0)
1447c478bd9Sstevel@tonic-gate 		p = from;
1457c478bd9Sstevel@tonic-gate 	if ((p = prom_strchr(p, ':')) == 0)
1467c478bd9Sstevel@tonic-gate 		return;
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 	/*
1497c478bd9Sstevel@tonic-gate 	 * Concatenate the options we found to the end of the output string.
1507c478bd9Sstevel@tonic-gate 	 */
1517c478bd9Sstevel@tonic-gate 	(void) prom_strcat(to, p);
1527c478bd9Sstevel@tonic-gate }
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate /*
1557c478bd9Sstevel@tonic-gate  * Strip any options strings from an OBP pathname.
1567c478bd9Sstevel@tonic-gate  * Output buffer (to) expected to be as large as input buffer (from).
1577c478bd9Sstevel@tonic-gate  */
1587c478bd9Sstevel@tonic-gate void
prom_strip_options(char * from,char * to)1597c478bd9Sstevel@tonic-gate prom_strip_options(char *from, char *to)
1607c478bd9Sstevel@tonic-gate {
1617c478bd9Sstevel@tonic-gate 	while (*from != (char)0)  {
1627c478bd9Sstevel@tonic-gate 		if (*from == ':')  {
1637c478bd9Sstevel@tonic-gate 			while ((*from != (char)0) && (*from != '/'))
1647c478bd9Sstevel@tonic-gate 				++from;
1657c478bd9Sstevel@tonic-gate 		} else
1667c478bd9Sstevel@tonic-gate 			*to++ = *from++;
1677c478bd9Sstevel@tonic-gate 	}
1687c478bd9Sstevel@tonic-gate 	*to = (char)0;
1697c478bd9Sstevel@tonic-gate }
170