devopen.c revision 1.6 1 /* $NetBSD: devopen.c,v 1.6 2008/04/28 20:23:16 martin Exp $ */
2
3 /*-
4 * Copyright (c) 2003 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Rolf Grossmann.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <lib/libsa/stand.h>
33 #include <lib/libkern/libkern.h>
34
35 #include "boot.h"
36
37 /*
38 * Parse a device spec.
39 *
40 * Format:
41 * [device:][filename]
42 */
43 int
44 devparse(const char *fname, int *dev, uint8_t *unit, uint8_t *part,
45 const char **file)
46 {
47 const char *col;
48
49 *unit = 0; /* default to wd0a */
50 *part = 0;
51 *dev = 0;
52 *file = DEFKERNELNAME;
53
54 if (fname == NULL)
55 return 0;
56
57 if ((col = strchr(fname, ':')) != NULL) {
58 int devlen;
59 uint8_t i, u, p;
60 struct devsw *dp;
61 char devname[MAXDEVNAME];
62
63 devlen = col - fname;
64 if (devlen > MAXDEVNAME)
65 return EINVAL;
66
67 #define isnum(c) (((c) >= '0') && ((c) <= '9'))
68 #define isalpha(c) (((c) >= 'a') && ((c) <= 'z'))
69
70 /* extract device name */
71 for (i = 0; isalpha(fname[i]) && (i < devlen); i++)
72 devname[i] = fname[i];
73 devname[i] = '\0';
74
75 if (strcmp(devname, "nfs") == 0) {
76 /* no unit number or partition suffix on netboot */
77 u = 0;
78 p = 0;
79 } else {
80 /* parse [disk][unit][part] (ex. wd0a) strings */
81 if (!isnum(fname[i]))
82 return EUNIT;
83
84 /* device number */
85 for (u = 0; isnum(fname[i]) && (i < devlen); i++)
86 u = u * 10 + (fname[i] - '0');
87
88 if (!isalpha(fname[i]))
89 return EPART;
90
91 /* partition number */
92 p = 0;
93 if (i < devlen)
94 p = fname[i++] - 'a';
95
96 if (i != devlen)
97 return ENXIO;
98 }
99
100 /* check device name */
101 for (dp = devsw, i = 0; i < ndevs; dp++, i++) {
102 if (dp->dv_name && !strcmp(devname, dp->dv_name))
103 break;
104 }
105
106 if (i >= ndevs)
107 return ENXIO;
108
109 *unit = u;
110 *part = p;
111 *dev = i;
112 fname = ++col;
113 }
114
115 if (*fname)
116 *file = fname;
117
118 return 0;
119 }
120
121 int
122 devopen(struct open_file *f, const char *fname, char **file)
123 {
124 struct devsw *dp;
125 uint8_t unit, part;
126 int dev, error;
127
128 DPRINTF(("devopen(%s)\n", fname));
129
130 if ((error = devparse(fname, &dev, &unit, &part,
131 (const char **)file)) != 0)
132 return error;
133
134 dp = &devsw[dev];
135 if ((void *)dp->dv_open == (void *)nodev)
136 return ENXIO;
137
138 f->f_dev = dp;
139
140 if ((error = (*dp->dv_open)(f, unit, part)) != 0)
141 printf("%s%d%c: %d = %s\n", devsw[dev].dv_name,
142 unit, 'a' + part, error, strerror(error));
143
144 return error;
145 }
146