12398f0cdSPeter Wemm /*- 22398f0cdSPeter Wemm * Copyright (c) 2000,2001 Peter Wemm <peter@FreeBSD.org> 32398f0cdSPeter Wemm * All rights reserved. 42398f0cdSPeter Wemm * 52398f0cdSPeter Wemm * Redistribution and use in source and binary forms, with or without 62398f0cdSPeter Wemm * modification, are permitted provided that the following conditions 72398f0cdSPeter Wemm * are met: 82398f0cdSPeter Wemm * 1. Redistributions of source code must retain the above copyright 92398f0cdSPeter Wemm * notice, this list of conditions and the following disclaimer. 102398f0cdSPeter Wemm * 2. Redistributions in binary form must reproduce the above copyright 112398f0cdSPeter Wemm * notice, this list of conditions and the following disclaimer in the 122398f0cdSPeter Wemm * documentation and/or other materials provided with the distribution. 132398f0cdSPeter Wemm * 142398f0cdSPeter Wemm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 152398f0cdSPeter Wemm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 162398f0cdSPeter Wemm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 172398f0cdSPeter Wemm * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 182398f0cdSPeter Wemm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 192398f0cdSPeter Wemm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 202398f0cdSPeter Wemm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 212398f0cdSPeter Wemm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 222398f0cdSPeter Wemm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 232398f0cdSPeter Wemm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 242398f0cdSPeter Wemm * SUCH DAMAGE. 252398f0cdSPeter Wemm */ 262398f0cdSPeter Wemm 27677b542eSDavid E. O'Brien #include <sys/cdefs.h> 28677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 29677b542eSDavid E. O'Brien 302398f0cdSPeter Wemm #include <sys/param.h> 31d786139cSMaxime Henrion #include <sys/lock.h> 3270da14c4SAleksandr Rybalko #include <sys/malloc.h> 33e3546a75SScott Long #include <sys/mutex.h> 3470da14c4SAleksandr Rybalko #include <sys/sysctl.h> 351bccd863SAleksandr Rybalko #include <sys/systm.h> 362398f0cdSPeter Wemm #include <sys/bus.h> 372398f0cdSPeter Wemm 382398f0cdSPeter Wemm /* 392398f0cdSPeter Wemm * Access functions for device resources. 402398f0cdSPeter Wemm */ 412398f0cdSPeter Wemm 42d786139cSMaxime Henrion static int checkmethod = 1; 434f033348SPeter Wemm static int use_kenv; 449516fbd6SPeter Wemm static char *hintp; 452398f0cdSPeter Wemm 462398f0cdSPeter Wemm /* 4770da14c4SAleksandr Rybalko * Define kern.hintmode sysctl, which only accept value 2, that cause to 4870da14c4SAleksandr Rybalko * switch from Static KENV mode to Dynamic KENV. So systems that have hints 4970da14c4SAleksandr Rybalko * compiled into kernel will be able to see/modify KENV (and hints too). 5070da14c4SAleksandr Rybalko */ 5170da14c4SAleksandr Rybalko 5270da14c4SAleksandr Rybalko static int 5370da14c4SAleksandr Rybalko sysctl_hintmode(SYSCTL_HANDLER_ARGS) 5470da14c4SAleksandr Rybalko { 5570da14c4SAleksandr Rybalko const char *cp; 5670da14c4SAleksandr Rybalko char *line, *eq; 571bccd863SAleksandr Rybalko int eqidx, error, from_kenv, i, value; 5870da14c4SAleksandr Rybalko 5970da14c4SAleksandr Rybalko from_kenv = 0; 6070da14c4SAleksandr Rybalko cp = kern_envp; 6170da14c4SAleksandr Rybalko value = hintmode; 6270da14c4SAleksandr Rybalko 6370da14c4SAleksandr Rybalko /* Fetch candidate for new hintmode value */ 6470da14c4SAleksandr Rybalko error = sysctl_handle_int(oidp, &value, 0, req); 651bccd863SAleksandr Rybalko if (error || req->newptr == NULL) 6670da14c4SAleksandr Rybalko return (error); 6770da14c4SAleksandr Rybalko 6870da14c4SAleksandr Rybalko if (value != 2) 6970da14c4SAleksandr Rybalko /* Only accept swithing to hintmode 2 */ 7070da14c4SAleksandr Rybalko return (EINVAL); 7170da14c4SAleksandr Rybalko 7270da14c4SAleksandr Rybalko /* Migrate from static to dynamic hints */ 7370da14c4SAleksandr Rybalko switch (hintmode) { 7470da14c4SAleksandr Rybalko case 0: 756a8dada2SAleksandr Rybalko if (dynamic_kenv) { 761bccd863SAleksandr Rybalko /* 771bccd863SAleksandr Rybalko * Already here. But assign hintmode to 2, to not 781bccd863SAleksandr Rybalko * check it in the future. 791bccd863SAleksandr Rybalko */ 801bccd863SAleksandr Rybalko hintmode = 2; 8170da14c4SAleksandr Rybalko return (0); 826a8dada2SAleksandr Rybalko } 8370da14c4SAleksandr Rybalko from_kenv = 1; 8470da14c4SAleksandr Rybalko cp = kern_envp; 8570da14c4SAleksandr Rybalko break; 8670da14c4SAleksandr Rybalko case 1: 8770da14c4SAleksandr Rybalko cp = static_hints; 8870da14c4SAleksandr Rybalko break; 8970da14c4SAleksandr Rybalko case 2: 9070da14c4SAleksandr Rybalko /* Nothing to do, hintmode already 2 */ 9170da14c4SAleksandr Rybalko return (0); 9270da14c4SAleksandr Rybalko } 9370da14c4SAleksandr Rybalko 9470da14c4SAleksandr Rybalko while (cp) { 9570da14c4SAleksandr Rybalko i = strlen(cp); 9670da14c4SAleksandr Rybalko if (i == 0) 9770da14c4SAleksandr Rybalko break; 9870da14c4SAleksandr Rybalko if (from_kenv) { 9970da14c4SAleksandr Rybalko if (strncmp(cp, "hint.", 5) != 0) 10070da14c4SAleksandr Rybalko /* kenv can have not only hints */ 10170da14c4SAleksandr Rybalko continue; 10270da14c4SAleksandr Rybalko } 10370da14c4SAleksandr Rybalko eq = strchr(cp, '='); 1041bccd863SAleksandr Rybalko if (eq == NULL) 10570da14c4SAleksandr Rybalko /* Bad hint value */ 10670da14c4SAleksandr Rybalko continue; 10770da14c4SAleksandr Rybalko eqidx = eq - cp; 10870da14c4SAleksandr Rybalko 10970da14c4SAleksandr Rybalko line = malloc(i+1, M_TEMP, M_WAITOK); 11070da14c4SAleksandr Rybalko strcpy(line, cp); 11170da14c4SAleksandr Rybalko line[eqidx] = '\0'; 1122be111bfSDavide Italiano kern_setenv(line, line + eqidx + 1); 11370da14c4SAleksandr Rybalko free(line, M_TEMP); 11470da14c4SAleksandr Rybalko cp += i + 1; 11570da14c4SAleksandr Rybalko } 11670da14c4SAleksandr Rybalko 11770da14c4SAleksandr Rybalko hintmode = value; 11870da14c4SAleksandr Rybalko use_kenv = 1; 11970da14c4SAleksandr Rybalko return (0); 12070da14c4SAleksandr Rybalko } 12170da14c4SAleksandr Rybalko 12270da14c4SAleksandr Rybalko SYSCTL_PROC(_kern, OID_AUTO, hintmode, CTLTYPE_INT|CTLFLAG_RW, 12370da14c4SAleksandr Rybalko &hintmode, 0, sysctl_hintmode, "I", "Get/set current hintmode"); 12470da14c4SAleksandr Rybalko 12570da14c4SAleksandr Rybalko /* 1262398f0cdSPeter Wemm * Evil wildcarding resource string lookup. 1272398f0cdSPeter Wemm * This walks the supplied env string table and returns a match. 1282398f0cdSPeter Wemm * The start point can be remembered for incremental searches. 1292398f0cdSPeter Wemm */ 1302398f0cdSPeter Wemm static int 1319516fbd6SPeter Wemm res_find(int *line, int *startln, 1322398f0cdSPeter Wemm const char *name, int *unit, const char *resname, const char *value, 1332398f0cdSPeter Wemm const char **ret_name, int *ret_namelen, int *ret_unit, 1342398f0cdSPeter Wemm const char **ret_resname, int *ret_resnamelen, const char **ret_value) 1352398f0cdSPeter Wemm { 1364f033348SPeter Wemm int n = 0, hit, i = 0; 1372398f0cdSPeter Wemm char r_name[32]; 1382398f0cdSPeter Wemm int r_unit; 1392398f0cdSPeter Wemm char r_resname[32]; 1402398f0cdSPeter Wemm char r_value[128]; 1419516fbd6SPeter Wemm const char *s, *cp; 1422398f0cdSPeter Wemm char *p; 1432398f0cdSPeter Wemm 144d786139cSMaxime Henrion if (checkmethod) { 14532069af6SAlexander Leidinger hintp = NULL; 14632069af6SAlexander Leidinger 1479516fbd6SPeter Wemm switch (hintmode) { 1486692ac66SPeter Wemm case 0: /* loader hints in environment only */ 1499516fbd6SPeter Wemm break; 1509516fbd6SPeter Wemm case 1: /* static hints only */ 1519516fbd6SPeter Wemm hintp = static_hints; 152d786139cSMaxime Henrion checkmethod = 0; 1539516fbd6SPeter Wemm break; 1549516fbd6SPeter Wemm case 2: /* fallback mode */ 155d786139cSMaxime Henrion if (dynamic_kenv) { 156e3546a75SScott Long mtx_lock(&kenv_lock); 157d786139cSMaxime Henrion cp = kenvp[0]; 158d786139cSMaxime Henrion for (i = 0; cp != NULL; cp = kenvp[++i]) { 159d786139cSMaxime Henrion if (!strncmp(cp, "hint.", 5)) { 160d786139cSMaxime Henrion use_kenv = 1; 161d786139cSMaxime Henrion checkmethod = 0; 162d786139cSMaxime Henrion break; 163d786139cSMaxime Henrion } 164d786139cSMaxime Henrion } 165e3546a75SScott Long mtx_unlock(&kenv_lock); 166d786139cSMaxime Henrion } else { 1679516fbd6SPeter Wemm cp = kern_envp; 1689516fbd6SPeter Wemm while (cp) { 1699516fbd6SPeter Wemm if (strncmp(cp, "hint.", 5) == 0) { 1709516fbd6SPeter Wemm cp = NULL; 1719516fbd6SPeter Wemm hintp = kern_envp; 1729516fbd6SPeter Wemm break; 1739516fbd6SPeter Wemm } 1749516fbd6SPeter Wemm while (*cp != '\0') 1759516fbd6SPeter Wemm cp++; 1769516fbd6SPeter Wemm cp++; 1779516fbd6SPeter Wemm if (*cp == '\0') { 1789516fbd6SPeter Wemm cp = NULL; 1799516fbd6SPeter Wemm hintp = static_hints; 1809516fbd6SPeter Wemm break; 1819516fbd6SPeter Wemm } 1829516fbd6SPeter Wemm } 183d786139cSMaxime Henrion } 1849516fbd6SPeter Wemm break; 1859516fbd6SPeter Wemm default: 1869516fbd6SPeter Wemm break; 1879516fbd6SPeter Wemm } 188d786139cSMaxime Henrion if (hintp == NULL) { 189d786139cSMaxime Henrion if (dynamic_kenv) { 190d786139cSMaxime Henrion use_kenv = 1; 191d786139cSMaxime Henrion checkmethod = 0; 192d786139cSMaxime Henrion } else 1939516fbd6SPeter Wemm hintp = kern_envp; 1949516fbd6SPeter Wemm } 195d786139cSMaxime Henrion } 1969516fbd6SPeter Wemm 197d786139cSMaxime Henrion if (use_kenv) { 198e3546a75SScott Long mtx_lock(&kenv_lock); 199d786139cSMaxime Henrion i = 0; 200d786139cSMaxime Henrion cp = kenvp[0]; 201d786139cSMaxime Henrion if (cp == NULL) { 202e3546a75SScott Long mtx_unlock(&kenv_lock); 203d786139cSMaxime Henrion return (ENOENT); 204d786139cSMaxime Henrion } 2056692ac66SPeter Wemm } else 2069516fbd6SPeter Wemm cp = hintp; 2072398f0cdSPeter Wemm while (cp) { 2082398f0cdSPeter Wemm hit = 1; 2092398f0cdSPeter Wemm (*line)++; 2102398f0cdSPeter Wemm if (strncmp(cp, "hint.", 5) != 0) 2112398f0cdSPeter Wemm hit = 0; 2122398f0cdSPeter Wemm else 21354bb5530SSergey Kandaurov n = sscanf(cp, "hint.%32[^.].%d.%32[^=]=%127s", 2142398f0cdSPeter Wemm r_name, &r_unit, r_resname, r_value); 2152398f0cdSPeter Wemm if (hit && n != 4) { 2162398f0cdSPeter Wemm printf("CONFIG: invalid hint '%s'\n", cp); 217dc15eac0SEd Schouten p = strchr(cp, 'h'); 2182398f0cdSPeter Wemm *p = 'H'; 2192398f0cdSPeter Wemm hit = 0; 2202398f0cdSPeter Wemm } 2212398f0cdSPeter Wemm if (hit && startln && *startln >= 0 && *line < *startln) 2222398f0cdSPeter Wemm hit = 0; 2232398f0cdSPeter Wemm if (hit && name && strcmp(name, r_name) != 0) 2242398f0cdSPeter Wemm hit = 0; 2252398f0cdSPeter Wemm if (hit && unit && *unit != r_unit) 2262398f0cdSPeter Wemm hit = 0; 2272398f0cdSPeter Wemm if (hit && resname && strcmp(resname, r_resname) != 0) 2282398f0cdSPeter Wemm hit = 0; 2292398f0cdSPeter Wemm if (hit && value && strcmp(value, r_value) != 0) 2302398f0cdSPeter Wemm hit = 0; 2312398f0cdSPeter Wemm if (hit) 2322398f0cdSPeter Wemm break; 2334f033348SPeter Wemm if (use_kenv) { 234d786139cSMaxime Henrion cp = kenvp[++i]; 2354f033348SPeter Wemm if (cp == NULL) 2364f033348SPeter Wemm break; 2374f033348SPeter Wemm } else { 2382398f0cdSPeter Wemm while (*cp != '\0') 2392398f0cdSPeter Wemm cp++; 2402398f0cdSPeter Wemm cp++; 2412398f0cdSPeter Wemm if (*cp == '\0') { 2422398f0cdSPeter Wemm cp = NULL; 2432398f0cdSPeter Wemm break; 2442398f0cdSPeter Wemm } 2452398f0cdSPeter Wemm } 2464f033348SPeter Wemm } 247d786139cSMaxime Henrion if (use_kenv) 248e3546a75SScott Long mtx_unlock(&kenv_lock); 2492398f0cdSPeter Wemm if (cp == NULL) 2502398f0cdSPeter Wemm return ENOENT; 2512398f0cdSPeter Wemm 2522398f0cdSPeter Wemm s = cp; 2532398f0cdSPeter Wemm /* This is a bit of a hack, but at least is reentrant */ 2542398f0cdSPeter Wemm /* Note that it returns some !unterminated! strings. */ 255dc15eac0SEd Schouten s = strchr(s, '.') + 1; /* start of device */ 2562398f0cdSPeter Wemm if (ret_name) 2572398f0cdSPeter Wemm *ret_name = s; 258dc15eac0SEd Schouten s = strchr(s, '.') + 1; /* start of unit */ 25985c36f3dSJohn Baldwin if (ret_namelen && ret_name) 2602398f0cdSPeter Wemm *ret_namelen = s - *ret_name - 1; /* device length */ 2612398f0cdSPeter Wemm if (ret_unit) 2622398f0cdSPeter Wemm *ret_unit = r_unit; 263dc15eac0SEd Schouten s = strchr(s, '.') + 1; /* start of resname */ 2642398f0cdSPeter Wemm if (ret_resname) 2652398f0cdSPeter Wemm *ret_resname = s; 266dc15eac0SEd Schouten s = strchr(s, '=') + 1; /* start of value */ 26785c36f3dSJohn Baldwin if (ret_resnamelen && ret_resname) 2682398f0cdSPeter Wemm *ret_resnamelen = s - *ret_resname - 1; /* value len */ 2692398f0cdSPeter Wemm if (ret_value) 2702398f0cdSPeter Wemm *ret_value = s; 2712398f0cdSPeter Wemm if (startln) /* line number for anchor */ 2722398f0cdSPeter Wemm *startln = *line + 1; 2732398f0cdSPeter Wemm return 0; 2742398f0cdSPeter Wemm } 2752398f0cdSPeter Wemm 2762398f0cdSPeter Wemm /* 2772398f0cdSPeter Wemm * Search all the data sources for matches to our query. We look for 2782398f0cdSPeter Wemm * dynamic hints first as overrides for static or fallback hints. 2792398f0cdSPeter Wemm */ 2802398f0cdSPeter Wemm static int 2812398f0cdSPeter Wemm resource_find(int *line, int *startln, 2822398f0cdSPeter Wemm const char *name, int *unit, const char *resname, const char *value, 2832398f0cdSPeter Wemm const char **ret_name, int *ret_namelen, int *ret_unit, 2842398f0cdSPeter Wemm const char **ret_resname, int *ret_resnamelen, const char **ret_value) 2852398f0cdSPeter Wemm { 2862398f0cdSPeter Wemm int i; 2872398f0cdSPeter Wemm int un; 2882398f0cdSPeter Wemm 2892398f0cdSPeter Wemm *line = 0; 2902398f0cdSPeter Wemm 2912398f0cdSPeter Wemm /* Search for exact unit matches first */ 2929516fbd6SPeter Wemm i = res_find(line, startln, name, unit, resname, value, 2932398f0cdSPeter Wemm ret_name, ret_namelen, ret_unit, ret_resname, ret_resnamelen, 2942398f0cdSPeter Wemm ret_value); 2952398f0cdSPeter Wemm if (i == 0) 2962398f0cdSPeter Wemm return 0; 2972398f0cdSPeter Wemm if (unit == NULL) 2982398f0cdSPeter Wemm return ENOENT; 2992398f0cdSPeter Wemm /* If we are still here, search for wildcard matches */ 3002398f0cdSPeter Wemm un = -1; 3019516fbd6SPeter Wemm i = res_find(line, startln, name, &un, resname, value, 3022398f0cdSPeter Wemm ret_name, ret_namelen, ret_unit, ret_resname, ret_resnamelen, 3032398f0cdSPeter Wemm ret_value); 3042398f0cdSPeter Wemm if (i == 0) 3052398f0cdSPeter Wemm return 0; 3062398f0cdSPeter Wemm return ENOENT; 3072398f0cdSPeter Wemm } 3082398f0cdSPeter Wemm 3092398f0cdSPeter Wemm int 3102398f0cdSPeter Wemm resource_int_value(const char *name, int unit, const char *resname, int *result) 3112398f0cdSPeter Wemm { 3122398f0cdSPeter Wemm int error; 3132398f0cdSPeter Wemm const char *str; 3142398f0cdSPeter Wemm char *op; 3152398f0cdSPeter Wemm unsigned long val; 3162398f0cdSPeter Wemm int line; 3172398f0cdSPeter Wemm 3182398f0cdSPeter Wemm line = 0; 3192398f0cdSPeter Wemm error = resource_find(&line, NULL, name, &unit, resname, NULL, 3202398f0cdSPeter Wemm NULL, NULL, NULL, NULL, NULL, &str); 3212398f0cdSPeter Wemm if (error) 3222398f0cdSPeter Wemm return error; 3232398f0cdSPeter Wemm if (*str == '\0') 3242398f0cdSPeter Wemm return EFTYPE; 3252398f0cdSPeter Wemm val = strtoul(str, &op, 0); 3262398f0cdSPeter Wemm if (*op != '\0') 3272398f0cdSPeter Wemm return EFTYPE; 3282398f0cdSPeter Wemm *result = val; 3292398f0cdSPeter Wemm return 0; 3302398f0cdSPeter Wemm } 3312398f0cdSPeter Wemm 3322398f0cdSPeter Wemm int 3332398f0cdSPeter Wemm resource_long_value(const char *name, int unit, const char *resname, 3342398f0cdSPeter Wemm long *result) 3352398f0cdSPeter Wemm { 3362398f0cdSPeter Wemm int error; 3372398f0cdSPeter Wemm const char *str; 3382398f0cdSPeter Wemm char *op; 3392398f0cdSPeter Wemm unsigned long val; 3402398f0cdSPeter Wemm int line; 3412398f0cdSPeter Wemm 3422398f0cdSPeter Wemm line = 0; 3432398f0cdSPeter Wemm error = resource_find(&line, NULL, name, &unit, resname, NULL, 3442398f0cdSPeter Wemm NULL, NULL, NULL, NULL, NULL, &str); 3452398f0cdSPeter Wemm if (error) 3462398f0cdSPeter Wemm return error; 3472398f0cdSPeter Wemm if (*str == '\0') 3482398f0cdSPeter Wemm return EFTYPE; 3492398f0cdSPeter Wemm val = strtoul(str, &op, 0); 3502398f0cdSPeter Wemm if (*op != '\0') 3512398f0cdSPeter Wemm return EFTYPE; 3522398f0cdSPeter Wemm *result = val; 3532398f0cdSPeter Wemm return 0; 3542398f0cdSPeter Wemm } 3552398f0cdSPeter Wemm 3562398f0cdSPeter Wemm int 3572398f0cdSPeter Wemm resource_string_value(const char *name, int unit, const char *resname, 3582398f0cdSPeter Wemm const char **result) 3592398f0cdSPeter Wemm { 3602398f0cdSPeter Wemm int error; 3612398f0cdSPeter Wemm const char *str; 3622398f0cdSPeter Wemm int line; 3632398f0cdSPeter Wemm 3642398f0cdSPeter Wemm line = 0; 3652398f0cdSPeter Wemm error = resource_find(&line, NULL, name, &unit, resname, NULL, 3662398f0cdSPeter Wemm NULL, NULL, NULL, NULL, NULL, &str); 3672398f0cdSPeter Wemm if (error) 3682398f0cdSPeter Wemm return error; 3692398f0cdSPeter Wemm *result = str; 3702398f0cdSPeter Wemm return 0; 3712398f0cdSPeter Wemm } 3722398f0cdSPeter Wemm 3732398f0cdSPeter Wemm /* 3742398f0cdSPeter Wemm * This is a bit nasty, but allows us to not modify the env strings. 3752398f0cdSPeter Wemm */ 3762398f0cdSPeter Wemm static const char * 3772398f0cdSPeter Wemm resource_string_copy(const char *s, int len) 3782398f0cdSPeter Wemm { 3792398f0cdSPeter Wemm static char stringbuf[256]; 3802398f0cdSPeter Wemm static int offset = 0; 3812398f0cdSPeter Wemm const char *ret; 3822398f0cdSPeter Wemm 3832398f0cdSPeter Wemm if (len == 0) 3842398f0cdSPeter Wemm len = strlen(s); 3852398f0cdSPeter Wemm if (len > 255) 3862398f0cdSPeter Wemm return NULL; 3872398f0cdSPeter Wemm if ((offset + len + 1) > 255) 3882398f0cdSPeter Wemm offset = 0; 3892398f0cdSPeter Wemm bcopy(s, &stringbuf[offset], len); 3902398f0cdSPeter Wemm stringbuf[offset + len] = '\0'; 3912398f0cdSPeter Wemm ret = &stringbuf[offset]; 3922398f0cdSPeter Wemm offset += len + 1; 3932398f0cdSPeter Wemm return ret; 3942398f0cdSPeter Wemm } 3952398f0cdSPeter Wemm 3962398f0cdSPeter Wemm /* 39774e62047SJohn-Mark Gurney * err = resource_find_match(&anchor, &name, &unit, resname, value) 3982398f0cdSPeter Wemm * Iteratively fetch a list of devices wired "at" something 3992398f0cdSPeter Wemm * res and value are restrictions. eg: "at", "scbus0". 4002398f0cdSPeter Wemm * For practical purposes, res = required, value = optional. 4012398f0cdSPeter Wemm * *name and *unit are set. 4022398f0cdSPeter Wemm * set *anchor to zero before starting. 4032398f0cdSPeter Wemm */ 4042398f0cdSPeter Wemm int 4052398f0cdSPeter Wemm resource_find_match(int *anchor, const char **name, int *unit, 4062398f0cdSPeter Wemm const char *resname, const char *value) 4072398f0cdSPeter Wemm { 4082398f0cdSPeter Wemm const char *found_name; 4092398f0cdSPeter Wemm int found_namelen; 4102398f0cdSPeter Wemm int found_unit; 4112398f0cdSPeter Wemm int ret; 4122398f0cdSPeter Wemm int newln; 4132398f0cdSPeter Wemm 4142398f0cdSPeter Wemm newln = *anchor; 4152398f0cdSPeter Wemm ret = resource_find(anchor, &newln, NULL, NULL, resname, value, 4162398f0cdSPeter Wemm &found_name, &found_namelen, &found_unit, NULL, NULL, NULL); 4172398f0cdSPeter Wemm if (ret == 0) { 4182398f0cdSPeter Wemm *name = resource_string_copy(found_name, found_namelen); 4192398f0cdSPeter Wemm *unit = found_unit; 4202398f0cdSPeter Wemm } 4212398f0cdSPeter Wemm *anchor = newln; 4222398f0cdSPeter Wemm return ret; 4232398f0cdSPeter Wemm } 4242398f0cdSPeter Wemm 4252398f0cdSPeter Wemm 4262398f0cdSPeter Wemm /* 4272398f0cdSPeter Wemm * err = resource_find_dev(&anchor, name, &unit, res, value); 4282398f0cdSPeter Wemm * Iterate through a list of devices, returning their unit numbers. 4292398f0cdSPeter Wemm * res and value are optional restrictions. eg: "at", "scbus0". 4302398f0cdSPeter Wemm * *unit is set to the value. 4312398f0cdSPeter Wemm * set *anchor to zero before starting. 4322398f0cdSPeter Wemm */ 4332398f0cdSPeter Wemm int 4342398f0cdSPeter Wemm resource_find_dev(int *anchor, const char *name, int *unit, 4352398f0cdSPeter Wemm const char *resname, const char *value) 4362398f0cdSPeter Wemm { 4372398f0cdSPeter Wemm int found_unit; 4382398f0cdSPeter Wemm int newln; 4392398f0cdSPeter Wemm int ret; 4402398f0cdSPeter Wemm 4412398f0cdSPeter Wemm newln = *anchor; 4422398f0cdSPeter Wemm ret = resource_find(anchor, &newln, name, NULL, resname, value, 4432398f0cdSPeter Wemm NULL, NULL, &found_unit, NULL, NULL, NULL); 4442398f0cdSPeter Wemm if (ret == 0) { 4452398f0cdSPeter Wemm *unit = found_unit; 4462398f0cdSPeter Wemm } 4472398f0cdSPeter Wemm *anchor = newln; 4482398f0cdSPeter Wemm return ret; 4492398f0cdSPeter Wemm } 4506591b310SJohn Baldwin 4516591b310SJohn Baldwin /* 4526591b310SJohn Baldwin * Check to see if a device is disabled via a disabled hint. 4536591b310SJohn Baldwin */ 4546591b310SJohn Baldwin int 4556591b310SJohn Baldwin resource_disabled(const char *name, int unit) 4566591b310SJohn Baldwin { 4576591b310SJohn Baldwin int error, value; 4586591b310SJohn Baldwin 4596591b310SJohn Baldwin error = resource_int_value(name, unit, "disabled", &value); 4606591b310SJohn Baldwin if (error) 4616591b310SJohn Baldwin return (0); 4626591b310SJohn Baldwin return (value); 4636591b310SJohn Baldwin } 464*64de8019SJohn Baldwin 465*64de8019SJohn Baldwin /* 466*64de8019SJohn Baldwin * Clear a value associated with a device by removing it from 467*64de8019SJohn Baldwin * the kernel environment. This only removes a hint for an 468*64de8019SJohn Baldwin * exact unit. 469*64de8019SJohn Baldwin */ 470*64de8019SJohn Baldwin int 471*64de8019SJohn Baldwin resource_unset_value(const char *name, int unit, const char *resname) 472*64de8019SJohn Baldwin { 473*64de8019SJohn Baldwin char varname[128]; 474*64de8019SJohn Baldwin const char *retname, *retvalue; 475*64de8019SJohn Baldwin int error, line; 476*64de8019SJohn Baldwin size_t len; 477*64de8019SJohn Baldwin 478*64de8019SJohn Baldwin line = 0; 479*64de8019SJohn Baldwin error = resource_find(&line, NULL, name, &unit, resname, NULL, 480*64de8019SJohn Baldwin &retname, NULL, NULL, NULL, NULL, &retvalue); 481*64de8019SJohn Baldwin if (error) 482*64de8019SJohn Baldwin return (error); 483*64de8019SJohn Baldwin 484*64de8019SJohn Baldwin retname -= strlen("hint."); 485*64de8019SJohn Baldwin len = retvalue - retname - 1; 486*64de8019SJohn Baldwin if (len > sizeof(varname) - 1) 487*64de8019SJohn Baldwin return (ENAMETOOLONG); 488*64de8019SJohn Baldwin memcpy(varname, retname, len); 489*64de8019SJohn Baldwin varname[len] = '\0'; 490*64de8019SJohn Baldwin return (kern_unsetenv(varname)); 491*64de8019SJohn Baldwin } 492