Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/stand/uboot/devicename.c
34677 views
1
/*-
2
* Copyright (c) 1998 Michael Smith <[email protected]>
3
* All rights reserved.
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
7
* are met:
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright
11
* notice, this list of conditions and the following disclaimer in the
12
* documentation and/or other materials provided with the distribution.
13
*
14
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24
* SUCH DAMAGE.
25
*/
26
27
#include <stand.h>
28
#include <string.h>
29
30
#include "bootstrap.h"
31
#include "disk.h"
32
#include "libuboot.h"
33
34
static int uboot_parsedev(struct uboot_devdesc **dev, const char *devspec,
35
const char **path);
36
37
/*
38
* Point (dev) at an allocated device specifier for the device matching the
39
* path in (devspec). If it contains an explicit device specification,
40
* use that. If not, use the default device.
41
*/
42
int
43
uboot_getdev(void **vdev, const char *devspec, const char **path)
44
{
45
struct uboot_devdesc **dev = (struct uboot_devdesc **)vdev;
46
int rv;
47
48
/*
49
* If it looks like this is just a path and no
50
* device, go with the current device.
51
*/
52
if ((devspec == NULL) || (devspec[0] == '/') ||
53
(strchr(devspec, ':') == NULL)) {
54
55
if (((rv = uboot_parsedev(dev, getenv("currdev"), NULL)) == 0)
56
&& (path != NULL))
57
*path = devspec;
58
return(rv);
59
}
60
61
/*
62
* Try to parse the device name off the beginning of the devspec.
63
*/
64
return (uboot_parsedev(dev, devspec, path));
65
}
66
67
/*
68
* Point (dev) at an allocated device specifier matching the string version
69
* at the beginning of (devspec). Return a pointer to the remaining
70
* text in (path).
71
*
72
* In all cases, the beginning of (devspec) is compared to the names
73
* of known devices in the device switch, and then any following text
74
* is parsed according to the rules applied to the device type.
75
*
76
* For disk-type devices, the syntax is:
77
*
78
* disk<unit>[<partition>]:
79
*
80
*/
81
static int
82
uboot_parsedev(struct uboot_devdesc **dev, const char *devspec,
83
const char **path)
84
{
85
struct uboot_devdesc *idev;
86
struct devsw *dv;
87
char *cp;
88
const char *np;
89
int i, unit, err;
90
91
/* minimum length check */
92
if (strlen(devspec) < 2)
93
return(EINVAL);
94
95
/* look for a device that matches */
96
for (i = 0, dv = NULL; devsw[i] != NULL; i++) {
97
if (!strncmp(devspec, devsw[i]->dv_name,
98
strlen(devsw[i]->dv_name))) {
99
dv = devsw[i];
100
break;
101
}
102
}
103
if (dv == NULL)
104
return(ENOENT);
105
idev = malloc(sizeof(struct uboot_devdesc));
106
err = 0;
107
np = (devspec + strlen(dv->dv_name));
108
109
switch(dv->dv_type) {
110
case DEVT_NONE:
111
break;
112
113
#ifdef LOADER_DISK_SUPPORT
114
case DEVT_DISK:
115
free(idev);
116
err = disk_parsedev((struct devdesc **)&idev, devspec, path);
117
if (err != 0)
118
goto fail;
119
break;
120
#endif
121
122
case DEVT_NET:
123
unit = 0;
124
125
if (*np && (*np != ':')) {
126
/* get unit number if present */
127
unit = strtol(np, &cp, 0);
128
if (cp == np) {
129
err = EUNIT;
130
goto fail;
131
}
132
}
133
if (*cp && (*cp != ':')) {
134
err = EINVAL;
135
goto fail;
136
}
137
idev->dd.d_unit = unit;
138
139
if (path != NULL)
140
*path = (*cp == 0) ? cp : cp + 1;
141
break;
142
143
default:
144
err = EINVAL;
145
goto fail;
146
}
147
idev->dd.d_dev = dv;
148
/*
149
* dev can be NULL, since uboot_getdev calls us directly, rather than via
150
* dv_parsedev in devparse() which otherwise ensures that it can't be NULL.
151
*/
152
if (dev == NULL) {
153
free(idev);
154
} else {
155
*dev = idev;
156
}
157
return (0);
158
159
fail:
160
free(idev);
161
return (err);
162
}
163
164
165
/*
166
* Set currdev to suit the value being supplied in (value).
167
*/
168
int
169
uboot_setcurrdev(struct env_var *ev, int flags, const void *value)
170
{
171
struct uboot_devdesc *ncurr;
172
int rv;
173
174
if ((rv = uboot_parsedev(&ncurr, value, NULL)) != 0)
175
return (rv);
176
free(ncurr);
177
178
return (mount_currdev(ev, flags, value));
179
}
180
181