devicename.c revision 123703
138465Smsmith/*-
238465Smsmith * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
338465Smsmith * All rights reserved.
438465Smsmith *
538465Smsmith * Redistribution and use in source and binary forms, with or without
638465Smsmith * modification, are permitted provided that the following conditions
738465Smsmith * are met:
838465Smsmith * 1. Redistributions of source code must retain the above copyright
938465Smsmith *    notice, this list of conditions and the following disclaimer.
1038465Smsmith * 2. Redistributions in binary form must reproduce the above copyright
1138465Smsmith *    notice, this list of conditions and the following disclaimer in the
1238465Smsmith *    documentation and/or other materials provided with the distribution.
1338465Smsmith *
1438465Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1538465Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1638465Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1738465Smsmith * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1838465Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1938465Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2038465Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2138465Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2238465Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2338465Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2438465Smsmith * SUCH DAMAGE.
2538465Smsmith *
2650477Speter * $FreeBSD: head/sys/boot/ofw/libofw/devicename.c 123703 2003-12-21 12:38:25Z grehan $
2738465Smsmith */
2838465Smsmith
2938465Smsmith#include <stand.h>
3067227Sobrien#include "libofw.h"
3138465Smsmith
32106738Sjakestatic int ofw_parsedev(struct ofw_devdesc **, const char *, const char **);
3338465Smsmith
3438465Smsmith/*
3538465Smsmith * Point (dev) at an allocated device specifier for the device matching the
3638465Smsmith * path in (devspec). If it contains an explicit device specification,
3738465Smsmith * use that.  If not, use the default device.
3838465Smsmith */
3938465Smsmithint
4067227Sobrienofw_getdev(void **vdev, const char *devspec, const char **path)
4138465Smsmith{
4267227Sobrien    struct ofw_devdesc **dev = (struct ofw_devdesc **)vdev;
4338465Smsmith    int				rv;
44106738Sjake
4538465Smsmith    /*
4638465Smsmith     * If it looks like this is just a path and no
4738465Smsmith     * device, go with the current device.
4838465Smsmith     */
4938465Smsmith    if ((devspec == NULL) ||
50123703Sgrehan	((strchr(devspec, '@') == NULL) &&
51123703Sgrehan	(strchr(devspec, ':') == NULL))) {
5238465Smsmith
5367227Sobrien	if (((rv = ofw_parsedev(dev, getenv("currdev"), NULL)) == 0) &&
5438465Smsmith	    (path != NULL))
5538465Smsmith		*path = devspec;
5638465Smsmith	return(rv);
5738465Smsmith    }
5838465Smsmith
5938465Smsmith    /*
6038465Smsmith     * Try to parse the device name off the beginning of the devspec
6138465Smsmith     */
6267227Sobrien    return(ofw_parsedev(dev, devspec, path));
6338465Smsmith}
6438465Smsmith
6538465Smsmith/*
6638465Smsmith * Point (dev) at an allocated device specifier matching the string version
6738465Smsmith * at the beginning of (devspec).  Return a pointer to the remaining
6838465Smsmith * text in (path).
6938465Smsmith */
7038465Smsmithstatic int
7167227Sobrienofw_parsedev(struct ofw_devdesc **dev, const char *devspec, const char **path)
7238465Smsmith{
73106738Sjake    struct ofw_devdesc	*idev;
7438465Smsmith    struct devsw	*dv;
75106738Sjake    phandle_t		handle;
76106738Sjake    const char		*p;
77106738Sjake    const char		*s;
78106738Sjake    char		name[256];
79106738Sjake    char		type[64];
80106738Sjake    int			len;
81106738Sjake    int			i;
8238465Smsmith
83106738Sjake    for (p = s = devspec; *s != '\0'; p = s) {
84106738Sjake	if ((s = strchr(p + 1, '/')) == NULL)
85106738Sjake	    s = strchr(p, '\0');
86106738Sjake	len = s - devspec;
87106738Sjake	bcopy(devspec, name, len);
88106738Sjake	name[len] = '\0';
89106738Sjake	if ((handle = OF_finddevice(name)) == -1)
9038465Smsmith	    break;
91106738Sjake	if (OF_getprop(handle, "device_type", type, sizeof(type)) == -1)
92106738Sjake	    continue;
93106738Sjake	for (i = 0; (dv = devsw[i]) != NULL; i++) {
94107483Sjake	    if (strncmp(dv->dv_name, type, strlen(dv->dv_name)) == 0)
95106738Sjake		goto found;
9638465Smsmith	}
9738465Smsmith    }
98106738Sjake    return(ENOENT);
9938465Smsmith
100106738Sjakefound:
101106738Sjake    if (*s != '\0')
102106738Sjake	*path = s;
10367227Sobrien    idev = malloc(sizeof(struct ofw_devdesc));
104106738Sjake    strcpy(idev->d_path, name);
10538465Smsmith    idev->d_dev = dv;
10638465Smsmith    idev->d_type = dv->dv_type;
10738475Sdfr    if (dev == NULL) {
10838475Sdfr	free(idev);
10938475Sdfr    } else {
11038465Smsmith	*dev = idev;
11138475Sdfr    }
11238465Smsmith    return(0);
11338465Smsmith}
11468548Sbenno
11584968Srobertint
116123703Sgrehanofw_setcurrdev(struct env_var *ev, int flags, const void *value)
11768548Sbenno{
118106738Sjake    struct ofw_devdesc	*ncurr;
119106738Sjake    int			rv;
12068548Sbenno
121106738Sjake    if ((rv = ofw_parsedev(&ncurr, value, NULL)) != 0)
122106738Sjake	return rv;
12368548Sbenno
124106738Sjake    free(ncurr);
125106738Sjake    env_setenv(ev->ev_name, flags | EV_NOHOOK, value, NULL, NULL);
126106738Sjake    return 0;
12768548Sbenno}
128