1 /* $NetBSD: devicename.c,v 1.3 2006/11/24 19:38:55 christos Exp $ */
4 * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 #include <sys/cdefs.h>
31 /* __FBSDID("$FreeBSD: src/sys/boot/efi/libefi/devicename.c,v 1.3 2004/01/04 23:28:16 obrien Exp $"); */
33 #include <lib/libsa/stand.h>
34 #include <lib/libsa/loadfile.h>
35 #include <sys/disklabel.h>
37 #include <bootstrap.h>
43 static int efi_parsedev(struct efi_devdesc
**dev
, const char *devspec
, const char **path
);
46 * Point (dev) at an allocated device specifier for the device matching the
47 * path in (devspec). If it contains an explicit device specification,
48 * use that. If not, use the default device.
51 efi_getdev(void **vdev
, const char *devspec
, const char **path
)
53 struct efi_devdesc
**dev
= (struct efi_devdesc
**)vdev
;
57 * If it looks like this is just a path and no
58 * device, go with the current device.
60 if ((devspec
== NULL
) ||
61 (devspec
[0] == '/') ||
62 (strchr(devspec
, ':') == NULL
)) {
64 if (((rv
= efi_parsedev(dev
, getenv("currdev"), NULL
)) == 0) &&
71 * Try to parse the device name off the beginning of the devspec
73 return(efi_parsedev(dev
, devspec
, path
));
77 * Point (dev) at an allocated device specifier matching the string version
78 * at the beginning of (devspec). Return a pointer to the remaining
81 * In all cases, the beginning of (devspec) is compared to the names
82 * of known devices in the device switch, and then any following text
83 * is parsed according to the rules applied to the device type.
85 * For disk-type devices, the syntax is:
87 * disk<unit>[s<slice>][<partition>]:
91 efi_parsedev(struct efi_devdesc
**dev
, const char *devspec
, const char **path
)
93 struct efi_devdesc
*idev
;
96 int i
, unit
, slice
, partition
, err
;
100 /* minimum length check */
101 if (strlen(devspec
) < 2)
104 /* look for a device that matches */
105 for (i
= 0, dv
= NULL
; i
< ndevs
; i
++) {
106 if (!strncmp(devspec
, devsw
[i
].dv_name
, strlen(devsw
[i
].dv_name
))) {
114 idev
= alloc(sizeof(struct efi_devdesc
));
116 np
= (devspec
+ strlen(dv
->dv_name
));
119 if (!strncmp("disk", dv
->dv_name
, 4)) dv_type
= DEVT_DISK
;
120 if (!strncmp("net", dv
->dv_name
, 3)) dv_type
= DEVT_DISK
;
123 case DEVT_NONE
: /* XXX what to do here? Do we care? */
130 if (*np
&& (*np
!= ':')) {
131 unit
= strtol(np
, &cp
, 10); /* next comes the unit number */
136 if (*cp
== 's') { /* got a slice number */
138 slice
= strtol(np
, &cp
, 10);
140 err
= EPART
; /* XXX : NetBSD calls a FreeBSD SLICE, a Partition! */
144 if (*cp
&& (*cp
!= ':')) {
145 partition
= *cp
- 'a'; /* get a partition number */
146 if ((partition
< 0) || (partition
>= MAXPARTITIONS
)) {
153 if (*cp
&& (*cp
!= ':')) {
158 idev
->d_kind
.efidisk
.unit
= unit
;
159 idev
->d_kind
.efidisk
.slice
= slice
;
160 idev
->d_kind
.efidisk
.partition
= partition
;
163 *path
= (*cp
== 0) ? cp
: cp
+ 1;
169 if (*np
&& (*np
!= ':')) {
170 unit
= strtol(np
, &cp
, 0); /* get unit number if present */
176 if (*cp
&& (*cp
!= ':')) {
181 idev
->d_kind
.netif
.unit
= unit
;
183 *path
= (*cp
== 0) ? cp
: cp
+ 1;
191 idev
->d_type
= dv_type
;
206 efi_fmtdev(void *vdev
)
208 struct efi_devdesc
*dev
= (struct efi_devdesc
*)vdev
;
209 static char buf
[128]; /* XXX device length constant? */
212 switch(dev
->d_type
) {
214 strcpy(buf
, "(no device)");
219 cp
+= sprintf(cp
, "%s%d", dev
->d_dev
->dv_name
, dev
->d_kind
.efidisk
.unit
);
220 if (dev
->d_kind
.efidisk
.slice
> 0)
221 cp
+= sprintf(cp
, "s%d", dev
->d_kind
.efidisk
.slice
);
222 if (dev
->d_kind
.efidisk
.partition
>= 0)
223 cp
+= sprintf(cp
, "%c", dev
->d_kind
.efidisk
.partition
+ 'a');
228 sprintf(buf
, "%s%d:", dev
->d_dev
->dv_name
, dev
->d_kind
.netif
.unit
);
236 * Set currdev to suit the value being supplied in (value)
239 efi_setcurrdev(struct env_var
*ev
, int flags
, void *value
)
241 struct efi_devdesc
*ncurr
;
244 if ((rv
= efi_parsedev(&ncurr
, value
, NULL
)) != 0)
247 env_setenv(ev
->ev_name
, flags
| EV_NOHOOK
, value
, NULL
, NULL
);