12398f0cdSPeter Wemm /*- 28a36da99SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 38a36da99SPedro F. Giffuni * 42398f0cdSPeter Wemm * Copyright (c) 2000,2001 Peter Wemm <peter@FreeBSD.org> 52398f0cdSPeter Wemm * All rights reserved. 62398f0cdSPeter Wemm * 72398f0cdSPeter Wemm * Redistribution and use in source and binary forms, with or without 82398f0cdSPeter Wemm * modification, are permitted provided that the following conditions 92398f0cdSPeter Wemm * are met: 102398f0cdSPeter Wemm * 1. Redistributions of source code must retain the above copyright 112398f0cdSPeter Wemm * notice, this list of conditions and the following disclaimer. 122398f0cdSPeter Wemm * 2. Redistributions in binary form must reproduce the above copyright 132398f0cdSPeter Wemm * notice, this list of conditions and the following disclaimer in the 142398f0cdSPeter Wemm * documentation and/or other materials provided with the distribution. 152398f0cdSPeter Wemm * 162398f0cdSPeter Wemm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 172398f0cdSPeter Wemm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 182398f0cdSPeter Wemm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 192398f0cdSPeter Wemm * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 202398f0cdSPeter Wemm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 212398f0cdSPeter Wemm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 222398f0cdSPeter Wemm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 232398f0cdSPeter Wemm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 242398f0cdSPeter Wemm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 252398f0cdSPeter Wemm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 262398f0cdSPeter Wemm * SUCH DAMAGE. 272398f0cdSPeter Wemm */ 282398f0cdSPeter Wemm 29677b542eSDavid E. O'Brien #include <sys/cdefs.h> 30677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 31677b542eSDavid E. O'Brien 322398f0cdSPeter Wemm #include <sys/param.h> 33d786139cSMaxime Henrion #include <sys/lock.h> 3470da14c4SAleksandr Rybalko #include <sys/malloc.h> 35e3546a75SScott Long #include <sys/mutex.h> 3670da14c4SAleksandr Rybalko #include <sys/sysctl.h> 371bccd863SAleksandr Rybalko #include <sys/systm.h> 382398f0cdSPeter Wemm #include <sys/bus.h> 392398f0cdSPeter Wemm 40*770488d2SKyle Evans #define HINTMODE_KENV 0 41*770488d2SKyle Evans #define HINTMODE_STATIC 1 42*770488d2SKyle Evans #define HINTMODE_FALLBACK 2 43*770488d2SKyle Evans 442398f0cdSPeter Wemm /* 452398f0cdSPeter Wemm * Access functions for device resources. 462398f0cdSPeter Wemm */ 472398f0cdSPeter Wemm 48d786139cSMaxime Henrion static int checkmethod = 1; 499516fbd6SPeter Wemm static char *hintp; 502398f0cdSPeter Wemm 512398f0cdSPeter Wemm /* 5270da14c4SAleksandr Rybalko * Define kern.hintmode sysctl, which only accept value 2, that cause to 5370da14c4SAleksandr Rybalko * switch from Static KENV mode to Dynamic KENV. So systems that have hints 5470da14c4SAleksandr Rybalko * compiled into kernel will be able to see/modify KENV (and hints too). 5570da14c4SAleksandr Rybalko */ 5670da14c4SAleksandr Rybalko 5770da14c4SAleksandr Rybalko static int 5870da14c4SAleksandr Rybalko sysctl_hintmode(SYSCTL_HANDLER_ARGS) 5970da14c4SAleksandr Rybalko { 6070da14c4SAleksandr Rybalko const char *cp; 6170da14c4SAleksandr Rybalko char *line, *eq; 62*770488d2SKyle Evans int eqidx, error, i, value; 6370da14c4SAleksandr Rybalko 6470da14c4SAleksandr Rybalko value = hintmode; 6570da14c4SAleksandr Rybalko 6670da14c4SAleksandr Rybalko /* Fetch candidate for new hintmode value */ 6770da14c4SAleksandr Rybalko error = sysctl_handle_int(oidp, &value, 0, req); 681bccd863SAleksandr Rybalko if (error || req->newptr == NULL) 6970da14c4SAleksandr Rybalko return (error); 7070da14c4SAleksandr Rybalko 71*770488d2SKyle Evans if (value != HINTMODE_FALLBACK) 7270da14c4SAleksandr Rybalko /* Only accept swithing to hintmode 2 */ 7370da14c4SAleksandr Rybalko return (EINVAL); 7470da14c4SAleksandr Rybalko 751bccd863SAleksandr Rybalko /* 76*770488d2SKyle Evans * The rest of the sysctl handler is just making sure that our 77*770488d2SKyle Evans * environment is consistent with the world we've already seen. 78*770488d2SKyle Evans * If we came from kenv at all, then we have nothing to do: static 79*770488d2SKyle Evans * kenv will get merged into dynamic kenv as soon as kmem becomes 80*770488d2SKyle Evans * available, dynamic kenv is the environment we'd be setting these 81*770488d2SKyle Evans * things in anyways. Therefore, we have nothing left to do unless 82*770488d2SKyle Evans * we came from a static hints configuration. 831bccd863SAleksandr Rybalko */ 84*770488d2SKyle Evans if (hintmode != HINTMODE_STATIC) { 85*770488d2SKyle Evans hintmode = value; 8670da14c4SAleksandr Rybalko return (0); 8770da14c4SAleksandr Rybalko } 8870da14c4SAleksandr Rybalko 89*770488d2SKyle Evans cp = static_hints; 90*770488d2SKyle Evans while (cp && *cp != '\0') { 9170da14c4SAleksandr Rybalko eq = strchr(cp, '='); 921bccd863SAleksandr Rybalko if (eq == NULL) 9370da14c4SAleksandr Rybalko /* Bad hint value */ 9470da14c4SAleksandr Rybalko continue; 9570da14c4SAleksandr Rybalko eqidx = eq - cp; 9670da14c4SAleksandr Rybalko 97*770488d2SKyle Evans i = strlen(cp); 9870da14c4SAleksandr Rybalko line = malloc(i+1, M_TEMP, M_WAITOK); 9970da14c4SAleksandr Rybalko strcpy(line, cp); 10070da14c4SAleksandr Rybalko line[eqidx] = '\0'; 1012be111bfSDavide Italiano kern_setenv(line, line + eqidx + 1); 10270da14c4SAleksandr Rybalko free(line, M_TEMP); 10370da14c4SAleksandr Rybalko cp += i + 1; 10470da14c4SAleksandr Rybalko } 10570da14c4SAleksandr Rybalko 10670da14c4SAleksandr Rybalko hintmode = value; 10770da14c4SAleksandr Rybalko return (0); 10870da14c4SAleksandr Rybalko } 10970da14c4SAleksandr Rybalko 11070da14c4SAleksandr Rybalko SYSCTL_PROC(_kern, OID_AUTO, hintmode, CTLTYPE_INT|CTLFLAG_RW, 11170da14c4SAleksandr Rybalko &hintmode, 0, sysctl_hintmode, "I", "Get/set current hintmode"); 11270da14c4SAleksandr Rybalko 11370da14c4SAleksandr Rybalko /* 1142398f0cdSPeter Wemm * Evil wildcarding resource string lookup. 1152398f0cdSPeter Wemm * This walks the supplied env string table and returns a match. 1162398f0cdSPeter Wemm * The start point can be remembered for incremental searches. 1172398f0cdSPeter Wemm */ 1182398f0cdSPeter Wemm static int 1199516fbd6SPeter Wemm res_find(int *line, int *startln, 1202398f0cdSPeter Wemm const char *name, int *unit, const char *resname, const char *value, 1212398f0cdSPeter Wemm const char **ret_name, int *ret_namelen, int *ret_unit, 1222398f0cdSPeter Wemm const char **ret_resname, int *ret_resnamelen, const char **ret_value) 1232398f0cdSPeter Wemm { 1244f033348SPeter Wemm int n = 0, hit, i = 0; 1252398f0cdSPeter Wemm char r_name[32]; 126*770488d2SKyle Evans int r_unit, use_kenv = (hintmode == HINTMODE_FALLBACK); 1272398f0cdSPeter Wemm char r_resname[32]; 1282398f0cdSPeter Wemm char r_value[128]; 1299516fbd6SPeter Wemm const char *s, *cp; 1302398f0cdSPeter Wemm char *p; 1312398f0cdSPeter Wemm 132d786139cSMaxime Henrion if (checkmethod) { 13332069af6SAlexander Leidinger hintp = NULL; 13432069af6SAlexander Leidinger 1359516fbd6SPeter Wemm switch (hintmode) { 136*770488d2SKyle Evans case HINTMODE_KENV: /* loader hints in environment only */ 1379516fbd6SPeter Wemm break; 138*770488d2SKyle Evans case HINTMODE_STATIC: /* static hints only */ 1399516fbd6SPeter Wemm hintp = static_hints; 140d786139cSMaxime Henrion checkmethod = 0; 1419516fbd6SPeter Wemm break; 142*770488d2SKyle Evans case HINTMODE_FALLBACK: /* fallback mode */ 143d786139cSMaxime Henrion if (dynamic_kenv) { 144e3546a75SScott Long mtx_lock(&kenv_lock); 145d786139cSMaxime Henrion cp = kenvp[0]; 146d786139cSMaxime Henrion for (i = 0; cp != NULL; cp = kenvp[++i]) { 147d786139cSMaxime Henrion if (!strncmp(cp, "hint.", 5)) { 148d786139cSMaxime Henrion use_kenv = 1; 149d786139cSMaxime Henrion checkmethod = 0; 150d786139cSMaxime Henrion break; 151d786139cSMaxime Henrion } 152d786139cSMaxime Henrion } 153e3546a75SScott Long mtx_unlock(&kenv_lock); 154d786139cSMaxime Henrion } else { 1559516fbd6SPeter Wemm cp = kern_envp; 1569516fbd6SPeter Wemm while (cp) { 1579516fbd6SPeter Wemm if (strncmp(cp, "hint.", 5) == 0) { 1589516fbd6SPeter Wemm cp = NULL; 1599516fbd6SPeter Wemm hintp = kern_envp; 1609516fbd6SPeter Wemm break; 1619516fbd6SPeter Wemm } 1629516fbd6SPeter Wemm while (*cp != '\0') 1639516fbd6SPeter Wemm cp++; 1649516fbd6SPeter Wemm cp++; 1659516fbd6SPeter Wemm if (*cp == '\0') { 1669516fbd6SPeter Wemm cp = NULL; 1679516fbd6SPeter Wemm hintp = static_hints; 1689516fbd6SPeter Wemm break; 1699516fbd6SPeter Wemm } 1709516fbd6SPeter Wemm } 171d786139cSMaxime Henrion } 1729516fbd6SPeter Wemm break; 1739516fbd6SPeter Wemm default: 1749516fbd6SPeter Wemm break; 1759516fbd6SPeter Wemm } 176d786139cSMaxime Henrion if (hintp == NULL) { 177d786139cSMaxime Henrion if (dynamic_kenv) { 178d786139cSMaxime Henrion use_kenv = 1; 179d786139cSMaxime Henrion checkmethod = 0; 180d786139cSMaxime Henrion } else 1819516fbd6SPeter Wemm hintp = kern_envp; 1829516fbd6SPeter Wemm } 183d786139cSMaxime Henrion } 1849516fbd6SPeter Wemm 185d786139cSMaxime Henrion if (use_kenv) { 186e3546a75SScott Long mtx_lock(&kenv_lock); 187d786139cSMaxime Henrion i = 0; 188d786139cSMaxime Henrion cp = kenvp[0]; 189d786139cSMaxime Henrion if (cp == NULL) { 190e3546a75SScott Long mtx_unlock(&kenv_lock); 191d786139cSMaxime Henrion return (ENOENT); 192d786139cSMaxime Henrion } 1936692ac66SPeter Wemm } else 1949516fbd6SPeter Wemm cp = hintp; 1952398f0cdSPeter Wemm while (cp) { 1962398f0cdSPeter Wemm hit = 1; 1972398f0cdSPeter Wemm (*line)++; 1982398f0cdSPeter Wemm if (strncmp(cp, "hint.", 5) != 0) 1992398f0cdSPeter Wemm hit = 0; 2002398f0cdSPeter Wemm else 20154bb5530SSergey Kandaurov n = sscanf(cp, "hint.%32[^.].%d.%32[^=]=%127s", 2022398f0cdSPeter Wemm r_name, &r_unit, r_resname, r_value); 2032398f0cdSPeter Wemm if (hit && n != 4) { 2042398f0cdSPeter Wemm printf("CONFIG: invalid hint '%s'\n", cp); 205dc15eac0SEd Schouten p = strchr(cp, 'h'); 2062398f0cdSPeter Wemm *p = 'H'; 2072398f0cdSPeter Wemm hit = 0; 2082398f0cdSPeter Wemm } 2092398f0cdSPeter Wemm if (hit && startln && *startln >= 0 && *line < *startln) 2102398f0cdSPeter Wemm hit = 0; 2112398f0cdSPeter Wemm if (hit && name && strcmp(name, r_name) != 0) 2122398f0cdSPeter Wemm hit = 0; 2132398f0cdSPeter Wemm if (hit && unit && *unit != r_unit) 2142398f0cdSPeter Wemm hit = 0; 2152398f0cdSPeter Wemm if (hit && resname && strcmp(resname, r_resname) != 0) 2162398f0cdSPeter Wemm hit = 0; 2172398f0cdSPeter Wemm if (hit && value && strcmp(value, r_value) != 0) 2182398f0cdSPeter Wemm hit = 0; 2192398f0cdSPeter Wemm if (hit) 2202398f0cdSPeter Wemm break; 2214f033348SPeter Wemm if (use_kenv) { 222d786139cSMaxime Henrion cp = kenvp[++i]; 2234f033348SPeter Wemm if (cp == NULL) 2244f033348SPeter Wemm break; 2254f033348SPeter Wemm } else { 2262398f0cdSPeter Wemm while (*cp != '\0') 2272398f0cdSPeter Wemm cp++; 2282398f0cdSPeter Wemm cp++; 2292398f0cdSPeter Wemm if (*cp == '\0') { 2302398f0cdSPeter Wemm cp = NULL; 2312398f0cdSPeter Wemm break; 2322398f0cdSPeter Wemm } 2332398f0cdSPeter Wemm } 2344f033348SPeter Wemm } 235d786139cSMaxime Henrion if (use_kenv) 236e3546a75SScott Long mtx_unlock(&kenv_lock); 2372398f0cdSPeter Wemm if (cp == NULL) 2382398f0cdSPeter Wemm return ENOENT; 2392398f0cdSPeter Wemm 2402398f0cdSPeter Wemm s = cp; 2412398f0cdSPeter Wemm /* This is a bit of a hack, but at least is reentrant */ 2422398f0cdSPeter Wemm /* Note that it returns some !unterminated! strings. */ 243dc15eac0SEd Schouten s = strchr(s, '.') + 1; /* start of device */ 2442398f0cdSPeter Wemm if (ret_name) 2452398f0cdSPeter Wemm *ret_name = s; 246dc15eac0SEd Schouten s = strchr(s, '.') + 1; /* start of unit */ 24785c36f3dSJohn Baldwin if (ret_namelen && ret_name) 2482398f0cdSPeter Wemm *ret_namelen = s - *ret_name - 1; /* device length */ 2492398f0cdSPeter Wemm if (ret_unit) 2502398f0cdSPeter Wemm *ret_unit = r_unit; 251dc15eac0SEd Schouten s = strchr(s, '.') + 1; /* start of resname */ 2522398f0cdSPeter Wemm if (ret_resname) 2532398f0cdSPeter Wemm *ret_resname = s; 254dc15eac0SEd Schouten s = strchr(s, '=') + 1; /* start of value */ 25585c36f3dSJohn Baldwin if (ret_resnamelen && ret_resname) 2562398f0cdSPeter Wemm *ret_resnamelen = s - *ret_resname - 1; /* value len */ 2572398f0cdSPeter Wemm if (ret_value) 2582398f0cdSPeter Wemm *ret_value = s; 2592398f0cdSPeter Wemm if (startln) /* line number for anchor */ 2602398f0cdSPeter Wemm *startln = *line + 1; 2612398f0cdSPeter Wemm return 0; 2622398f0cdSPeter Wemm } 2632398f0cdSPeter Wemm 2642398f0cdSPeter Wemm /* 2652398f0cdSPeter Wemm * Search all the data sources for matches to our query. We look for 2662398f0cdSPeter Wemm * dynamic hints first as overrides for static or fallback hints. 2672398f0cdSPeter Wemm */ 2682398f0cdSPeter Wemm static int 2692398f0cdSPeter Wemm resource_find(int *line, int *startln, 2702398f0cdSPeter Wemm const char *name, int *unit, const char *resname, const char *value, 2712398f0cdSPeter Wemm const char **ret_name, int *ret_namelen, int *ret_unit, 2722398f0cdSPeter Wemm const char **ret_resname, int *ret_resnamelen, const char **ret_value) 2732398f0cdSPeter Wemm { 2742398f0cdSPeter Wemm int i; 2752398f0cdSPeter Wemm int un; 2762398f0cdSPeter Wemm 2772398f0cdSPeter Wemm *line = 0; 2782398f0cdSPeter Wemm 2792398f0cdSPeter Wemm /* Search for exact unit matches first */ 2809516fbd6SPeter Wemm i = res_find(line, startln, name, unit, resname, value, 2812398f0cdSPeter Wemm ret_name, ret_namelen, ret_unit, ret_resname, ret_resnamelen, 2822398f0cdSPeter Wemm ret_value); 2832398f0cdSPeter Wemm if (i == 0) 2842398f0cdSPeter Wemm return 0; 2852398f0cdSPeter Wemm if (unit == NULL) 2862398f0cdSPeter Wemm return ENOENT; 2872398f0cdSPeter Wemm /* If we are still here, search for wildcard matches */ 2882398f0cdSPeter Wemm un = -1; 2899516fbd6SPeter Wemm i = res_find(line, startln, name, &un, resname, value, 2902398f0cdSPeter Wemm ret_name, ret_namelen, ret_unit, ret_resname, ret_resnamelen, 2912398f0cdSPeter Wemm ret_value); 2922398f0cdSPeter Wemm if (i == 0) 2932398f0cdSPeter Wemm return 0; 2942398f0cdSPeter Wemm return ENOENT; 2952398f0cdSPeter Wemm } 2962398f0cdSPeter Wemm 2972398f0cdSPeter Wemm int 2982398f0cdSPeter Wemm resource_int_value(const char *name, int unit, const char *resname, int *result) 2992398f0cdSPeter Wemm { 3002398f0cdSPeter Wemm int error; 3012398f0cdSPeter Wemm const char *str; 3022398f0cdSPeter Wemm char *op; 3032398f0cdSPeter Wemm unsigned long val; 3042398f0cdSPeter Wemm int line; 3052398f0cdSPeter Wemm 3062398f0cdSPeter Wemm line = 0; 3072398f0cdSPeter Wemm error = resource_find(&line, NULL, name, &unit, resname, NULL, 3082398f0cdSPeter Wemm NULL, NULL, NULL, NULL, NULL, &str); 3092398f0cdSPeter Wemm if (error) 3102398f0cdSPeter Wemm return error; 3112398f0cdSPeter Wemm if (*str == '\0') 3122398f0cdSPeter Wemm return EFTYPE; 3132398f0cdSPeter Wemm val = strtoul(str, &op, 0); 3142398f0cdSPeter Wemm if (*op != '\0') 3152398f0cdSPeter Wemm return EFTYPE; 3162398f0cdSPeter Wemm *result = val; 3172398f0cdSPeter Wemm return 0; 3182398f0cdSPeter Wemm } 3192398f0cdSPeter Wemm 3202398f0cdSPeter Wemm int 3212398f0cdSPeter Wemm resource_long_value(const char *name, int unit, const char *resname, 3222398f0cdSPeter Wemm long *result) 3232398f0cdSPeter Wemm { 3242398f0cdSPeter Wemm int error; 3252398f0cdSPeter Wemm const char *str; 3262398f0cdSPeter Wemm char *op; 3272398f0cdSPeter Wemm unsigned long val; 3282398f0cdSPeter Wemm int line; 3292398f0cdSPeter Wemm 3302398f0cdSPeter Wemm line = 0; 3312398f0cdSPeter Wemm error = resource_find(&line, NULL, name, &unit, resname, NULL, 3322398f0cdSPeter Wemm NULL, NULL, NULL, NULL, NULL, &str); 3332398f0cdSPeter Wemm if (error) 3342398f0cdSPeter Wemm return error; 3352398f0cdSPeter Wemm if (*str == '\0') 3362398f0cdSPeter Wemm return EFTYPE; 3372398f0cdSPeter Wemm val = strtoul(str, &op, 0); 3382398f0cdSPeter Wemm if (*op != '\0') 3392398f0cdSPeter Wemm return EFTYPE; 3402398f0cdSPeter Wemm *result = val; 3412398f0cdSPeter Wemm return 0; 3422398f0cdSPeter Wemm } 3432398f0cdSPeter Wemm 3442398f0cdSPeter Wemm int 3452398f0cdSPeter Wemm resource_string_value(const char *name, int unit, const char *resname, 3462398f0cdSPeter Wemm const char **result) 3472398f0cdSPeter Wemm { 3482398f0cdSPeter Wemm int error; 3492398f0cdSPeter Wemm const char *str; 3502398f0cdSPeter Wemm int line; 3512398f0cdSPeter Wemm 3522398f0cdSPeter Wemm line = 0; 3532398f0cdSPeter Wemm error = resource_find(&line, NULL, name, &unit, resname, NULL, 3542398f0cdSPeter Wemm NULL, NULL, NULL, NULL, NULL, &str); 3552398f0cdSPeter Wemm if (error) 3562398f0cdSPeter Wemm return error; 3572398f0cdSPeter Wemm *result = str; 3582398f0cdSPeter Wemm return 0; 3592398f0cdSPeter Wemm } 3602398f0cdSPeter Wemm 3612398f0cdSPeter Wemm /* 3622398f0cdSPeter Wemm * This is a bit nasty, but allows us to not modify the env strings. 3632398f0cdSPeter Wemm */ 3642398f0cdSPeter Wemm static const char * 3652398f0cdSPeter Wemm resource_string_copy(const char *s, int len) 3662398f0cdSPeter Wemm { 3672398f0cdSPeter Wemm static char stringbuf[256]; 3682398f0cdSPeter Wemm static int offset = 0; 3692398f0cdSPeter Wemm const char *ret; 3702398f0cdSPeter Wemm 3712398f0cdSPeter Wemm if (len == 0) 3722398f0cdSPeter Wemm len = strlen(s); 3732398f0cdSPeter Wemm if (len > 255) 3742398f0cdSPeter Wemm return NULL; 3752398f0cdSPeter Wemm if ((offset + len + 1) > 255) 3762398f0cdSPeter Wemm offset = 0; 3772398f0cdSPeter Wemm bcopy(s, &stringbuf[offset], len); 3782398f0cdSPeter Wemm stringbuf[offset + len] = '\0'; 3792398f0cdSPeter Wemm ret = &stringbuf[offset]; 3802398f0cdSPeter Wemm offset += len + 1; 3812398f0cdSPeter Wemm return ret; 3822398f0cdSPeter Wemm } 3832398f0cdSPeter Wemm 3842398f0cdSPeter Wemm /* 38574e62047SJohn-Mark Gurney * err = resource_find_match(&anchor, &name, &unit, resname, value) 3862398f0cdSPeter Wemm * Iteratively fetch a list of devices wired "at" something 3872398f0cdSPeter Wemm * res and value are restrictions. eg: "at", "scbus0". 3882398f0cdSPeter Wemm * For practical purposes, res = required, value = optional. 3892398f0cdSPeter Wemm * *name and *unit are set. 3902398f0cdSPeter Wemm * set *anchor to zero before starting. 3912398f0cdSPeter Wemm */ 3922398f0cdSPeter Wemm int 3932398f0cdSPeter Wemm resource_find_match(int *anchor, const char **name, int *unit, 3942398f0cdSPeter Wemm const char *resname, const char *value) 3952398f0cdSPeter Wemm { 3962398f0cdSPeter Wemm const char *found_name; 3972398f0cdSPeter Wemm int found_namelen; 3982398f0cdSPeter Wemm int found_unit; 3992398f0cdSPeter Wemm int ret; 4002398f0cdSPeter Wemm int newln; 4012398f0cdSPeter Wemm 4022398f0cdSPeter Wemm newln = *anchor; 4032398f0cdSPeter Wemm ret = resource_find(anchor, &newln, NULL, NULL, resname, value, 4042398f0cdSPeter Wemm &found_name, &found_namelen, &found_unit, NULL, NULL, NULL); 4052398f0cdSPeter Wemm if (ret == 0) { 4062398f0cdSPeter Wemm *name = resource_string_copy(found_name, found_namelen); 4072398f0cdSPeter Wemm *unit = found_unit; 4082398f0cdSPeter Wemm } 4092398f0cdSPeter Wemm *anchor = newln; 4102398f0cdSPeter Wemm return ret; 4112398f0cdSPeter Wemm } 4122398f0cdSPeter Wemm 4132398f0cdSPeter Wemm 4142398f0cdSPeter Wemm /* 4152398f0cdSPeter Wemm * err = resource_find_dev(&anchor, name, &unit, res, value); 4162398f0cdSPeter Wemm * Iterate through a list of devices, returning their unit numbers. 4172398f0cdSPeter Wemm * res and value are optional restrictions. eg: "at", "scbus0". 4182398f0cdSPeter Wemm * *unit is set to the value. 4192398f0cdSPeter Wemm * set *anchor to zero before starting. 4202398f0cdSPeter Wemm */ 4212398f0cdSPeter Wemm int 4222398f0cdSPeter Wemm resource_find_dev(int *anchor, const char *name, int *unit, 4232398f0cdSPeter Wemm const char *resname, const char *value) 4242398f0cdSPeter Wemm { 4252398f0cdSPeter Wemm int found_unit; 4262398f0cdSPeter Wemm int newln; 4272398f0cdSPeter Wemm int ret; 4282398f0cdSPeter Wemm 4292398f0cdSPeter Wemm newln = *anchor; 4302398f0cdSPeter Wemm ret = resource_find(anchor, &newln, name, NULL, resname, value, 4312398f0cdSPeter Wemm NULL, NULL, &found_unit, NULL, NULL, NULL); 4322398f0cdSPeter Wemm if (ret == 0) { 4332398f0cdSPeter Wemm *unit = found_unit; 4342398f0cdSPeter Wemm } 4352398f0cdSPeter Wemm *anchor = newln; 4362398f0cdSPeter Wemm return ret; 4372398f0cdSPeter Wemm } 4386591b310SJohn Baldwin 4396591b310SJohn Baldwin /* 4406591b310SJohn Baldwin * Check to see if a device is disabled via a disabled hint. 4416591b310SJohn Baldwin */ 4426591b310SJohn Baldwin int 4436591b310SJohn Baldwin resource_disabled(const char *name, int unit) 4446591b310SJohn Baldwin { 4456591b310SJohn Baldwin int error, value; 4466591b310SJohn Baldwin 4476591b310SJohn Baldwin error = resource_int_value(name, unit, "disabled", &value); 4486591b310SJohn Baldwin if (error) 4496591b310SJohn Baldwin return (0); 4506591b310SJohn Baldwin return (value); 4516591b310SJohn Baldwin } 45264de8019SJohn Baldwin 45364de8019SJohn Baldwin /* 45464de8019SJohn Baldwin * Clear a value associated with a device by removing it from 45564de8019SJohn Baldwin * the kernel environment. This only removes a hint for an 45664de8019SJohn Baldwin * exact unit. 45764de8019SJohn Baldwin */ 45864de8019SJohn Baldwin int 45964de8019SJohn Baldwin resource_unset_value(const char *name, int unit, const char *resname) 46064de8019SJohn Baldwin { 46164de8019SJohn Baldwin char varname[128]; 46264de8019SJohn Baldwin const char *retname, *retvalue; 46364de8019SJohn Baldwin int error, line; 46464de8019SJohn Baldwin size_t len; 46564de8019SJohn Baldwin 46664de8019SJohn Baldwin line = 0; 46764de8019SJohn Baldwin error = resource_find(&line, NULL, name, &unit, resname, NULL, 46864de8019SJohn Baldwin &retname, NULL, NULL, NULL, NULL, &retvalue); 46964de8019SJohn Baldwin if (error) 47064de8019SJohn Baldwin return (error); 47164de8019SJohn Baldwin 47264de8019SJohn Baldwin retname -= strlen("hint."); 47364de8019SJohn Baldwin len = retvalue - retname - 1; 47464de8019SJohn Baldwin if (len > sizeof(varname) - 1) 47564de8019SJohn Baldwin return (ENAMETOOLONG); 47664de8019SJohn Baldwin memcpy(varname, retname, len); 47764de8019SJohn Baldwin varname[len] = '\0'; 47864de8019SJohn Baldwin return (kern_unsetenv(varname)); 47964de8019SJohn Baldwin } 480