/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" #include #include char * prom_path_gettoken(register char *from, register char *to) { while (*from) { switch (*from) { case '/': case '@': case ':': case ',': *to = '\0'; return (from); default: *to++ = *from++; } } *to = '\0'; return (from); } /* * Given an OBP pathname, do the best we can to fully expand * the OBP pathname, in place in the callers buffer. * * If we have to complete the addrspec of any component, we can * only handle devices that have a maximum of NREGSPECS "reg" specs. * We cannot allocate memory inside this function. */ void prom_pathname(char *pathname) { char tmp[OBP_MAXPATHLEN]; char *from = tmp; char *to = pathname; char *p; cell_t ci[7]; #ifdef PROM_32BIT_ADDRS char *opathname = NULL; #endif /* PROM_32BIT_ADDRS */ if ((to == (char *)0) || (*to == (char)0)) return; #ifdef PROM_32BIT_ADDRS if ((uintptr_t)pathname > (uint32_t)-1) { opathname = pathname; pathname = promplat_alloc(OBP_MAXPATHLEN); if (pathname == NULL) { return; } (void) prom_strcpy(pathname, opathname); to = pathname; } if ((uintptr_t)from > (uint32_t)-1) { from = promplat_alloc(OBP_MAXPATHLEN); if (from == NULL) { if (opathname != NULL) promplat_free(pathname, OBP_MAXPATHLEN); return; } } #endif /* PROM_32BIT_ADDRS */ promif_preprom(); (void) prom_strcpy(from, to); *to = (char)0; ci[0] = p1275_ptr2cell("canon"); /* Service name */ ci[1] = (cell_t)3; /* #argument cells */ ci[2] = (cell_t)1; /* #result cells */ ci[3] = p1275_ptr2cell(from); /* Arg1: token */ ci[4] = p1275_ptr2cell(to); /* Arg2: buffer address */ ci[5] = p1275_uint2cell(OBP_MAXPATHLEN); /* Arg3: buffer length */ (void) p1275_cif_handler(&ci); promif_postprom(); #ifdef PROM_32BIT_ADDRS if (opathname != NULL) { (void) prom_strcpy(opathname, pathname); promplat_free(pathname, OBP_MAXPATHLEN); to = pathname = opathname; } if (from != tmp) { (void) prom_strcpy(tmp, from); promplat_free(from, OBP_MAXPATHLEN); from = tmp; } #endif /* PROM_32BIT_ADDRS */ /* * workaround for bugid 1218110, the prom strips the * options from the input string ... save options at * at the end of the string if the prom didn't. * NB: The workaround only preserves options in the last * component of the string. */ /* * If there are any options in the last component of the * output, the prom has copied them; No workaround required. */ if ((p = prom_strrchr(to, '/')) == 0) return; if ((p = prom_strchr(p, ':')) != 0) return; /* * If there are no options in the input ... there's * nothing to preserve; return. */ if ((p = prom_strrchr(from, '/')) == 0) p = from; if ((p = prom_strchr(p, ':')) == 0) return; /* * Concatenate the options we found to the end of the output string. */ (void) prom_strcat(to, p); } /* * Strip any options strings from an OBP pathname. * Output buffer (to) expected to be as large as input buffer (from). */ void prom_strip_options(char *from, char *to) { while (*from != (char)0) { if (*from == ':') { while ((*from != (char)0) && (*from != '/')) ++from; } else *to++ = *from++; } *to = (char)0; }