source: rtems-libbsd/freebsd/kern/subr_hints.c @ a51d36d2

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since a51d36d2 was a51d36d2, checked in by Jennifer Averett <jennifer.averett@…>, on 05/01/12 at 18:10:10

Added globals for hints and hintmode.

  • Property mode set to 100644
File size: 9.3 KB
Line 
1#include <freebsd/machine/rtems-bsd-config.h>
2
3/*-
4 * Copyright (c) 2000,2001 Peter Wemm <peter@FreeBSD.org>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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.
15 *
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
26 * SUCH DAMAGE.
27 */
28
29#include <freebsd/sys/cdefs.h>
30__FBSDID("$FreeBSD$");
31
32#include <freebsd/sys/param.h>
33#include <freebsd/sys/lock.h>
34#include <freebsd/sys/mutex.h>
35#include <freebsd/sys/systm.h>
36#include <freebsd/sys/bus.h>
37
38/*
39 * Access functions for device resources.
40 */
41
42static int checkmethod = 1;
43static int use_kenv;
44static char *hintp;
45#ifdef __rtems__
46char static_hints[] = {};
47int hintmode = 2;
48#endif /* __rtems__ */
49
50/*
51 * Evil wildcarding resource string lookup.
52 * This walks the supplied env string table and returns a match.
53 * The start point can be remembered for incremental searches.
54 */
55static int
56res_find(int *line, int *startln,
57    const char *name, int *unit, const char *resname, const char *value,
58    const char **ret_name, int *ret_namelen, int *ret_unit,
59    const char **ret_resname, int *ret_resnamelen, const char **ret_value)
60{
61        int n = 0, hit, i = 0;
62        char r_name[32];
63        int r_unit;
64        char r_resname[32];
65        char r_value[128];
66        const char *s, *cp;
67        char *p;
68
69        if (checkmethod) {
70                hintp = NULL;
71
72                switch (hintmode) {
73                case 0:         /* loader hints in environment only */
74                        break;
75                case 1:         /* static hints only */
76                        hintp = static_hints;
77                        checkmethod = 0;
78                        break;
79                case 2:         /* fallback mode */
80                        if (dynamic_kenv) {
81                                mtx_lock(&kenv_lock);
82                                cp = kenvp[0];
83                                for (i = 0; cp != NULL; cp = kenvp[++i]) {
84                                        if (!strncmp(cp, "hint.", 5)) {
85                                                use_kenv = 1;
86                                                checkmethod = 0;
87                                                break;
88                                        }
89                                }
90                                mtx_unlock(&kenv_lock);
91                        } else {
92                                cp = kern_envp;
93                                while (cp) {
94                                        if (strncmp(cp, "hint.", 5) == 0) {
95                                                cp = NULL;
96                                                hintp = kern_envp;
97                                                break;
98                                        }
99                                        while (*cp != '\0')
100                                                cp++;
101                                        cp++;
102                                        if (*cp == '\0') {
103                                                cp = NULL;
104                                                hintp = static_hints;
105                                                break;
106                                        }
107                                }
108                        }
109                        break;
110                default:
111                        break;
112                }
113                if (hintp == NULL) {
114                        if (dynamic_kenv) {
115                                use_kenv = 1;
116                                checkmethod = 0;
117                        } else
118                                hintp = kern_envp;
119                }
120        }
121
122        if (use_kenv) {
123                mtx_lock(&kenv_lock);
124                i = 0;
125                cp = kenvp[0];
126                if (cp == NULL) {
127                        mtx_unlock(&kenv_lock);
128                        return (ENOENT);
129                }
130        } else
131                cp = hintp;
132        while (cp) {
133                hit = 1;
134                (*line)++;
135                if (strncmp(cp, "hint.", 5) != 0)
136                        hit = 0;
137                else
138                        n = sscanf(cp, "hint.%32[^.].%d.%32[^=]=%128s",
139                            r_name, &r_unit, r_resname, r_value);
140                if (hit && n != 4) {
141                        printf("CONFIG: invalid hint '%s'\n", cp);
142                        /* XXX: abuse bogus index() declaration */
143                        p = index(cp, 'h');
144                        *p = 'H';
145                        hit = 0;
146                }
147                if (hit && startln && *startln >= 0 && *line < *startln)
148                        hit = 0;
149                if (hit && name && strcmp(name, r_name) != 0)
150                        hit = 0;
151                if (hit && unit && *unit != r_unit)
152                        hit = 0;
153                if (hit && resname && strcmp(resname, r_resname) != 0)
154                        hit = 0;
155                if (hit && value && strcmp(value, r_value) != 0)
156                        hit = 0;
157                if (hit)
158                        break;
159                if (use_kenv) {
160                        cp = kenvp[++i];
161                        if (cp == NULL)
162                                break;
163                } else {
164                        while (*cp != '\0')
165                                cp++;
166                        cp++;
167                        if (*cp == '\0') {
168                                cp = NULL;
169                                break;
170                        }
171                }
172        }
173        if (use_kenv)
174                mtx_unlock(&kenv_lock);
175        if (cp == NULL)
176                return ENOENT;
177
178        s = cp;
179        /* This is a bit of a hack, but at least is reentrant */
180        /* Note that it returns some !unterminated! strings. */
181        s = index(s, '.') + 1;          /* start of device */
182        if (ret_name)
183                *ret_name = s;
184        s = index(s, '.') + 1;          /* start of unit */
185        if (ret_namelen && ret_name)
186                *ret_namelen = s - *ret_name - 1; /* device length */
187        if (ret_unit)
188                *ret_unit = r_unit;
189        s = index(s, '.') + 1;          /* start of resname */
190        if (ret_resname)
191                *ret_resname = s;
192        s = index(s, '=') + 1;          /* start of value */
193        if (ret_resnamelen && ret_resname)
194                *ret_resnamelen = s - *ret_resname - 1; /* value len */
195        if (ret_value)
196                *ret_value = s;
197        if (startln)                    /* line number for anchor */
198                *startln = *line + 1;
199        return 0;
200}
201
202/*
203 * Search all the data sources for matches to our query.  We look for
204 * dynamic hints first as overrides for static or fallback hints.
205 */
206static int
207resource_find(int *line, int *startln,
208    const char *name, int *unit, const char *resname, const char *value,
209    const char **ret_name, int *ret_namelen, int *ret_unit,
210    const char **ret_resname, int *ret_resnamelen, const char **ret_value)
211{
212        int i;
213        int un;
214
215        *line = 0;
216
217        /* Search for exact unit matches first */
218        i = res_find(line, startln, name, unit, resname, value,
219            ret_name, ret_namelen, ret_unit, ret_resname, ret_resnamelen,
220            ret_value);
221        if (i == 0)
222                return 0;
223        if (unit == NULL)
224                return ENOENT;
225        /* If we are still here, search for wildcard matches */
226        un = -1;
227        i = res_find(line, startln, name, &un, resname, value,
228            ret_name, ret_namelen, ret_unit, ret_resname, ret_resnamelen,
229            ret_value);
230        if (i == 0)
231                return 0;
232        return ENOENT;
233}
234
235int
236resource_int_value(const char *name, int unit, const char *resname, int *result)
237{
238        int error;
239        const char *str;
240        char *op;
241        unsigned long val;
242        int line;
243
244        line = 0;
245        error = resource_find(&line, NULL, name, &unit, resname, NULL,
246            NULL, NULL, NULL, NULL, NULL, &str);
247        if (error)
248                return error;
249        if (*str == '\0')
250                return EFTYPE;
251        val = strtoul(str, &op, 0);
252        if (*op != '\0')
253                return EFTYPE;
254        *result = val;
255        return 0;
256}
257
258#ifndef __rtems__
259int
260resource_long_value(const char *name, int unit, const char *resname,
261    long *result)
262{
263        int error;
264        const char *str;
265        char *op;
266        unsigned long val;
267        int line;
268
269        line = 0;
270        error = resource_find(&line, NULL, name, &unit, resname, NULL,
271            NULL, NULL, NULL, NULL, NULL, &str);
272        if (error)
273                return error;
274        if (*str == '\0')
275                return EFTYPE;
276        val = strtoul(str, &op, 0);
277        if (*op != '\0')
278                return EFTYPE;
279        *result = val;
280        return 0;
281}
282#endif /* __rtems__ */
283
284int
285resource_string_value(const char *name, int unit, const char *resname,
286    const char **result)
287{
288        int error;
289        const char *str;
290        int line;
291
292        line = 0;
293        error = resource_find(&line, NULL, name, &unit, resname, NULL,
294            NULL, NULL, NULL, NULL, NULL, &str);
295        if (error)
296                return error;
297        *result = str;
298        return 0;
299}
300
301/*
302 * This is a bit nasty, but allows us to not modify the env strings.
303 */
304static const char *
305resource_string_copy(const char *s, int len)
306{
307        static char stringbuf[256];
308        static int offset = 0;
309        const char *ret;
310
311        if (len == 0)
312                len = strlen(s);
313        if (len > 255)
314                return NULL;
315        if ((offset + len + 1) > 255)
316                offset = 0;
317        bcopy(s, &stringbuf[offset], len);
318        stringbuf[offset + len] = '\0';
319        ret = &stringbuf[offset];
320        offset += len + 1;
321        return ret;
322}
323
324/*
325 * err = resource_find_match(&anchor, &name, &unit, resname, value)
326 * Iteratively fetch a list of devices wired "at" something
327 * res and value are restrictions.  eg: "at", "scbus0".
328 * For practical purposes, res = required, value = optional.
329 * *name and *unit are set.
330 * set *anchor to zero before starting.
331 */
332int
333resource_find_match(int *anchor, const char **name, int *unit,
334    const char *resname, const char *value)
335{
336        const char *found_name;
337        int found_namelen;
338        int found_unit;
339        int ret;
340        int newln;
341
342        newln = *anchor;
343        ret = resource_find(anchor, &newln, NULL, NULL, resname, value,
344            &found_name, &found_namelen, &found_unit, NULL, NULL, NULL);
345        if (ret == 0) {
346                *name = resource_string_copy(found_name, found_namelen);
347                *unit = found_unit;
348        }
349        *anchor = newln;
350        return ret;
351}
352
353#ifndef __rtems__
354
355/*
356 * err = resource_find_dev(&anchor, name, &unit, res, value);
357 * Iterate through a list of devices, returning their unit numbers.
358 * res and value are optional restrictions.  eg: "at", "scbus0".
359 * *unit is set to the value.
360 * set *anchor to zero before starting.
361 */
362int
363resource_find_dev(int *anchor, const char *name, int *unit,
364    const char *resname, const char *value)
365{
366        int found_unit;
367        int newln;
368        int ret;
369
370        newln = *anchor;
371        ret = resource_find(anchor, &newln, name, NULL, resname, value,
372            NULL, NULL, &found_unit, NULL, NULL, NULL);
373        if (ret == 0) {
374                *unit = found_unit;
375        }
376        *anchor = newln;
377        return ret;
378}
379
380/*
381 * Check to see if a device is disabled via a disabled hint.
382 */
383int
384resource_disabled(const char *name, int unit)
385{
386        int error, value;
387
388        error = resource_int_value(name, unit, "disabled", &value);
389        if (error)
390               return (0);
391        return (value);
392}
393#endif /* __rtems__ */
Note: See TracBrowser for help on using the repository browser.