2 * Copyright (c) 2000,2001 Peter Wemm <peter@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
30 #include <sys/param.h>
32 #include <sys/mutex.h>
33 #include <sys/systm.h>
37 * Access functions for device resources.
40 static int checkmethod
= 1;
45 * Evil wildcarding resource string lookup.
46 * This walks the supplied env string table and returns a match.
47 * The start point can be remembered for incremental searches.
50 res_find(int *line
, int *startln
,
51 const char *name
, int *unit
, const char *resname
, const char *value
,
52 const char **ret_name
, int *ret_namelen
, int *ret_unit
,
53 const char **ret_resname
, int *ret_resnamelen
, const char **ret_value
)
55 int n
= 0, hit
, i
= 0;
67 case 0: /* loader hints in environment only */
69 case 1: /* static hints only */
73 case 2: /* fallback mode */
77 for (i
= 0; cp
!= NULL
; cp
= kenvp
[++i
]) {
78 if (!strncmp(cp
, "hint.", 5)) {
84 mtx_unlock(&kenv_lock
);
88 if (strncmp(cp
, "hint.", 5) == 0) {
117 mtx_lock(&kenv_lock
);
121 mtx_unlock(&kenv_lock
);
129 if (strncmp(cp
, "hint.", 5) != 0)
132 n
= sscanf(cp
, "hint.%32[^.].%d.%32[^=]=%128s",
133 r_name
, &r_unit
, r_resname
, r_value
);
135 printf("CONFIG: invalid hint '%s'\n", cp
);
136 /* XXX: abuse bogus index() declaration */
141 if (hit
&& startln
&& *startln
>= 0 && *line
< *startln
)
143 if (hit
&& name
&& strcmp(name
, r_name
) != 0)
145 if (hit
&& unit
&& *unit
!= r_unit
)
147 if (hit
&& resname
&& strcmp(resname
, r_resname
) != 0)
149 if (hit
&& value
&& strcmp(value
, r_value
) != 0)
168 mtx_unlock(&kenv_lock
);
173 /* This is a bit of a hack, but at least is reentrant */
174 /* Note that it returns some !unterminated! strings. */
175 s
= index(s
, '.') + 1; /* start of device */
178 s
= index(s
, '.') + 1; /* start of unit */
179 if (ret_namelen
&& ret_name
)
180 *ret_namelen
= s
- *ret_name
- 1; /* device length */
183 s
= index(s
, '.') + 1; /* start of resname */
186 s
= index(s
, '=') + 1; /* start of value */
187 if (ret_resnamelen
&& ret_resname
)
188 *ret_resnamelen
= s
- *ret_resname
- 1; /* value len */
191 if (startln
) /* line number for anchor */
192 *startln
= *line
+ 1;
197 * Search all the data sources for matches to our query. We look for
198 * dynamic hints first as overrides for static or fallback hints.
201 resource_find(int *line
, int *startln
,
202 const char *name
, int *unit
, const char *resname
, const char *value
,
203 const char **ret_name
, int *ret_namelen
, int *ret_unit
,
204 const char **ret_resname
, int *ret_resnamelen
, const char **ret_value
)
211 /* Search for exact unit matches first */
212 i
= res_find(line
, startln
, name
, unit
, resname
, value
,
213 ret_name
, ret_namelen
, ret_unit
, ret_resname
, ret_resnamelen
,
219 /* If we are still here, search for wildcard matches */
221 i
= res_find(line
, startln
, name
, &un
, resname
, value
,
222 ret_name
, ret_namelen
, ret_unit
, ret_resname
, ret_resnamelen
,
230 resource_int_value(const char *name
, int unit
, const char *resname
, int *result
)
239 error
= resource_find(&line
, NULL
, name
, &unit
, resname
, NULL
,
240 NULL
, NULL
, NULL
, NULL
, NULL
, &str
);
245 val
= strtoul(str
, &op
, 0);
253 resource_long_value(const char *name
, int unit
, const char *resname
,
263 error
= resource_find(&line
, NULL
, name
, &unit
, resname
, NULL
,
264 NULL
, NULL
, NULL
, NULL
, NULL
, &str
);
269 val
= strtoul(str
, &op
, 0);
277 resource_string_value(const char *name
, int unit
, const char *resname
,
285 error
= resource_find(&line
, NULL
, name
, &unit
, resname
, NULL
,
286 NULL
, NULL
, NULL
, NULL
, NULL
, &str
);
294 * This is a bit nasty, but allows us to not modify the env strings.
297 resource_string_copy(const char *s
, int len
)
299 static char stringbuf
[256];
300 static int offset
= 0;
307 if ((offset
+ len
+ 1) > 255)
309 bcopy(s
, &stringbuf
[offset
], len
);
310 stringbuf
[offset
+ len
] = '\0';
311 ret
= &stringbuf
[offset
];
317 * err = resource_find_match(&anchor, &name, &unit, resname, value)
318 * Iteratively fetch a list of devices wired "at" something
319 * res and value are restrictions. eg: "at", "scbus0".
320 * For practical purposes, res = required, value = optional.
321 * *name and *unit are set.
322 * set *anchor to zero before starting.
325 resource_find_match(int *anchor
, const char **name
, int *unit
,
326 const char *resname
, const char *value
)
328 const char *found_name
;
335 ret
= resource_find(anchor
, &newln
, NULL
, NULL
, resname
, value
,
336 &found_name
, &found_namelen
, &found_unit
, NULL
, NULL
, NULL
);
338 *name
= resource_string_copy(found_name
, found_namelen
);
347 * err = resource_find_dev(&anchor, name, &unit, res, value);
348 * Iterate through a list of devices, returning their unit numbers.
349 * res and value are optional restrictions. eg: "at", "scbus0".
350 * *unit is set to the value.
351 * set *anchor to zero before starting.
354 resource_find_dev(int *anchor
, const char *name
, int *unit
,
355 const char *resname
, const char *value
)
362 ret
= resource_find(anchor
, &newln
, name
, NULL
, resname
, value
,
363 NULL
, NULL
, &found_unit
, NULL
, NULL
, NULL
);
372 * Check to see if a device is disabled via a disabled hint.
375 resource_disabled(const char *name
, int unit
)
379 error
= resource_int_value(name
, unit
, "disabled", &value
);