subr_hints.c revision 79696
178135Speter/*- 278135Speter * Copyright (c) 2000,2001 Peter Wemm <peter@FreeBSD.org> 378135Speter * All rights reserved. 478135Speter * 578135Speter * Redistribution and use in source and binary forms, with or without 678135Speter * modification, are permitted provided that the following conditions 778135Speter * are met: 878135Speter * 1. Redistributions of source code must retain the above copyright 978135Speter * notice, this list of conditions and the following disclaimer. 1078135Speter * 2. Redistributions in binary form must reproduce the above copyright 1178135Speter * notice, this list of conditions and the following disclaimer in the 1278135Speter * documentation and/or other materials provided with the distribution. 1378135Speter * 1478135Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1578135Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1678135Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1778135Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1878135Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1978135Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2078135Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2178135Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2278135Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2378135Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2478135Speter * SUCH DAMAGE. 2578135Speter * 2678135Speter * $FreeBSD: head/sys/kern/subr_hints.c 79696 2001-07-14 00:23:10Z peter $ 2778135Speter */ 2878135Speter 2978135Speter#include <sys/param.h> 3078135Speter#include <sys/systm.h> 3178135Speter#include <sys/bus.h> 3278135Speter 3378135Speter/* 3478135Speter * Access functions for device resources. 3578135Speter */ 3678135Speter 3778135Speterextern char static_hints[]; /* by config for now */ 3879696Speterextern int hintmode; /* 0 = off. 1 = config, 2 = fallback */ 3979696Speterstatic char *hintp; 4078135Speter 4178135Speter/* 4278135Speter * Evil wildcarding resource string lookup. 4378135Speter * This walks the supplied env string table and returns a match. 4478135Speter * The start point can be remembered for incremental searches. 4578135Speter */ 4678135Speterstatic int 4779696Speterres_find(int *line, int *startln, 4878135Speter const char *name, int *unit, const char *resname, const char *value, 4978135Speter const char **ret_name, int *ret_namelen, int *ret_unit, 5078135Speter const char **ret_resname, int *ret_resnamelen, const char **ret_value) 5178135Speter{ 5278135Speter int n = 0, hit; 5378135Speter char r_name[32]; 5478135Speter int r_unit; 5578135Speter char r_resname[32]; 5678135Speter char r_value[128]; 5779696Speter const char *s, *cp; 5878135Speter char *p; 5978135Speter 6079696Speter if (hintp == NULL) { 6179696Speter switch (hintmode) { 6279696Speter case 0: /* config supplied nothing */ 6379696Speter hintp = kern_envp; 6479696Speter break; 6579696Speter case 1: /* static hints only */ 6679696Speter hintp = static_hints; 6779696Speter break; 6879696Speter case 2: /* fallback mode */ 6979696Speter cp = kern_envp; 7079696Speter while (cp) { 7179696Speter if (strncmp(cp, "hint.", 5) == 0) { 7279696Speter cp = NULL; 7379696Speter hintp = kern_envp; 7479696Speter break; 7579696Speter } 7679696Speter while (*cp != '\0') 7779696Speter cp++; 7879696Speter cp++; 7979696Speter if (*cp == '\0') { 8079696Speter cp = NULL; 8179696Speter hintp = static_hints; 8279696Speter break; 8379696Speter } 8479696Speter } 8579696Speter break; 8679696Speter default: 8779696Speter break; 8879696Speter } 8979696Speter if (hintp == NULL) 9079696Speter hintp = kern_envp; 9179696Speter } 9279696Speter 9379696Speter cp = hintp; 9478135Speter while (cp) { 9578135Speter hit = 1; 9678135Speter (*line)++; 9778135Speter if (strncmp(cp, "hint.", 5) != 0) 9878135Speter hit = 0; 9978135Speter else 10078135Speter n = sscanf(cp, "hint.%32[^.].%d.%32[^=]=%128s", 10178135Speter r_name, &r_unit, r_resname, r_value); 10278135Speter if (hit && n != 4) { 10378135Speter printf("CONFIG: invalid hint '%s'\n", cp); 10478135Speter /* XXX: abuse bogus index() declaration */ 10578135Speter p = index(cp, 'h'); 10678135Speter *p = 'H'; 10778135Speter hit = 0; 10878135Speter } 10978135Speter if (hit && startln && *startln >= 0 && *line < *startln) 11078135Speter hit = 0; 11178135Speter if (hit && name && strcmp(name, r_name) != 0) 11278135Speter hit = 0; 11378135Speter if (hit && unit && *unit != r_unit) 11478135Speter hit = 0; 11578135Speter if (hit && resname && strcmp(resname, r_resname) != 0) 11678135Speter hit = 0; 11778135Speter if (hit && value && strcmp(value, r_value) != 0) 11878135Speter hit = 0; 11978135Speter if (hit) 12078135Speter break; 12178135Speter while (*cp != '\0') 12278135Speter cp++; 12378135Speter cp++; 12478135Speter if (*cp == '\0') { 12578135Speter cp = NULL; 12678135Speter break; 12778135Speter } 12878135Speter } 12978135Speter if (cp == NULL) 13078135Speter return ENOENT; 13178135Speter 13278135Speter s = cp; 13378135Speter /* This is a bit of a hack, but at least is reentrant */ 13478135Speter /* Note that it returns some !unterminated! strings. */ 13578135Speter s = index(s, '.') + 1; /* start of device */ 13678135Speter if (ret_name) 13778135Speter *ret_name = s; 13878135Speter s = index(s, '.') + 1; /* start of unit */ 13978135Speter if (ret_namelen) 14078135Speter *ret_namelen = s - *ret_name - 1; /* device length */ 14178135Speter if (ret_unit) 14278135Speter *ret_unit = r_unit; 14378135Speter s = index(s, '.') + 1; /* start of resname */ 14478135Speter if (ret_resname) 14578135Speter *ret_resname = s; 14678135Speter s = index(s, '=') + 1; /* start of value */ 14778135Speter if (ret_resnamelen) 14878135Speter *ret_resnamelen = s - *ret_resname - 1; /* value len */ 14978135Speter if (ret_value) 15078135Speter *ret_value = s; 15178135Speter if (startln) /* line number for anchor */ 15278135Speter *startln = *line + 1; 15378135Speter return 0; 15478135Speter} 15578135Speter 15678135Speter/* 15778135Speter * Search all the data sources for matches to our query. We look for 15878135Speter * dynamic hints first as overrides for static or fallback hints. 15978135Speter */ 16078135Speterstatic int 16178135Speterresource_find(int *line, int *startln, 16278135Speter const char *name, int *unit, const char *resname, const char *value, 16378135Speter const char **ret_name, int *ret_namelen, int *ret_unit, 16478135Speter const char **ret_resname, int *ret_resnamelen, const char **ret_value) 16578135Speter{ 16678135Speter int i; 16778135Speter int un; 16878135Speter 16978135Speter *line = 0; 17078135Speter 17178135Speter /* Search for exact unit matches first */ 17279696Speter i = res_find(line, startln, name, unit, resname, value, 17378135Speter ret_name, ret_namelen, ret_unit, ret_resname, ret_resnamelen, 17478135Speter ret_value); 17578135Speter if (i == 0) 17678135Speter return 0; 17778135Speter if (unit == NULL) 17878135Speter return ENOENT; 17978135Speter /* If we are still here, search for wildcard matches */ 18078135Speter un = -1; 18179696Speter i = res_find(line, startln, name, &un, resname, value, 18278135Speter ret_name, ret_namelen, ret_unit, ret_resname, ret_resnamelen, 18378135Speter ret_value); 18478135Speter if (i == 0) 18578135Speter return 0; 18678135Speter return ENOENT; 18778135Speter} 18878135Speter 18978135Speterint 19078135Speterresource_int_value(const char *name, int unit, const char *resname, int *result) 19178135Speter{ 19278135Speter int error; 19378135Speter const char *str; 19478135Speter char *op; 19578135Speter unsigned long val; 19678135Speter int line; 19778135Speter 19878135Speter line = 0; 19978135Speter error = resource_find(&line, NULL, name, &unit, resname, NULL, 20078135Speter NULL, NULL, NULL, NULL, NULL, &str); 20178135Speter if (error) 20278135Speter return error; 20378135Speter if (*str == '\0') 20478135Speter return EFTYPE; 20578135Speter val = strtoul(str, &op, 0); 20678135Speter if (*op != '\0') 20778135Speter return EFTYPE; 20878135Speter *result = val; 20978135Speter return 0; 21078135Speter} 21178135Speter 21278135Speterint 21378135Speterresource_long_value(const char *name, int unit, const char *resname, 21478135Speter long *result) 21578135Speter{ 21678135Speter int error; 21778135Speter const char *str; 21878135Speter char *op; 21978135Speter unsigned long val; 22078135Speter int line; 22178135Speter 22278135Speter line = 0; 22378135Speter error = resource_find(&line, NULL, name, &unit, resname, NULL, 22478135Speter NULL, NULL, NULL, NULL, NULL, &str); 22578135Speter if (error) 22678135Speter return error; 22778135Speter if (*str == '\0') 22878135Speter return EFTYPE; 22978135Speter val = strtoul(str, &op, 0); 23078135Speter if (*op != '\0') 23178135Speter return EFTYPE; 23278135Speter *result = val; 23378135Speter return 0; 23478135Speter} 23578135Speter 23678135Speterint 23778135Speterresource_string_value(const char *name, int unit, const char *resname, 23878135Speter const char **result) 23978135Speter{ 24078135Speter int error; 24178135Speter const char *str; 24278135Speter int line; 24378135Speter 24478135Speter line = 0; 24578135Speter error = resource_find(&line, NULL, name, &unit, resname, NULL, 24678135Speter NULL, NULL, NULL, NULL, NULL, &str); 24778135Speter if (error) 24878135Speter return error; 24978135Speter *result = str; 25078135Speter return 0; 25178135Speter} 25278135Speter 25378135Speter/* 25478135Speter * This is a bit nasty, but allows us to not modify the env strings. 25578135Speter */ 25678135Speterstatic const char * 25778135Speterresource_string_copy(const char *s, int len) 25878135Speter{ 25978135Speter static char stringbuf[256]; 26078135Speter static int offset = 0; 26178135Speter const char *ret; 26278135Speter 26378135Speter if (len == 0) 26478135Speter len = strlen(s); 26578135Speter if (len > 255) 26678135Speter return NULL; 26778135Speter if ((offset + len + 1) > 255) 26878135Speter offset = 0; 26978135Speter bcopy(s, &stringbuf[offset], len); 27078135Speter stringbuf[offset + len] = '\0'; 27178135Speter ret = &stringbuf[offset]; 27278135Speter offset += len + 1; 27378135Speter return ret; 27478135Speter} 27578135Speter 27678135Speter/* 27778135Speter * err = resource_find_at(&anchor, &name, &unit, resname, value) 27878135Speter * Iteratively fetch a list of devices wired "at" something 27978135Speter * res and value are restrictions. eg: "at", "scbus0". 28078135Speter * For practical purposes, res = required, value = optional. 28178135Speter * *name and *unit are set. 28278135Speter * set *anchor to zero before starting. 28378135Speter */ 28478135Speterint 28578135Speterresource_find_match(int *anchor, const char **name, int *unit, 28678135Speter const char *resname, const char *value) 28778135Speter{ 28878135Speter const char *found_name; 28978135Speter int found_namelen; 29078135Speter int found_unit; 29178135Speter int ret; 29278135Speter int newln; 29378135Speter 29478135Speter newln = *anchor; 29578135Speter ret = resource_find(anchor, &newln, NULL, NULL, resname, value, 29678135Speter &found_name, &found_namelen, &found_unit, NULL, NULL, NULL); 29778135Speter if (ret == 0) { 29878135Speter *name = resource_string_copy(found_name, found_namelen); 29978135Speter *unit = found_unit; 30078135Speter } 30178135Speter *anchor = newln; 30278135Speter return ret; 30378135Speter} 30478135Speter 30578135Speter 30678135Speter/* 30778135Speter * err = resource_find_dev(&anchor, name, &unit, res, value); 30878135Speter * Iterate through a list of devices, returning their unit numbers. 30978135Speter * res and value are optional restrictions. eg: "at", "scbus0". 31078135Speter * *unit is set to the value. 31178135Speter * set *anchor to zero before starting. 31278135Speter */ 31378135Speterint 31478135Speterresource_find_dev(int *anchor, const char *name, int *unit, 31578135Speter const char *resname, const char *value) 31678135Speter{ 31778135Speter int found_unit; 31878135Speter int newln; 31978135Speter int ret; 32078135Speter 32178135Speter newln = *anchor; 32278135Speter ret = resource_find(anchor, &newln, name, NULL, resname, value, 32378135Speter NULL, NULL, &found_unit, NULL, NULL, NULL); 32478135Speter if (ret == 0) { 32578135Speter *unit = found_unit; 32678135Speter } 32778135Speter *anchor = newln; 32878135Speter return ret; 32978135Speter} 330