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