1*93f9dcf9SAnton Vorontsov /* 2*93f9dcf9SAnton Vorontsov * An inteface for configuring a hardware via u-boot environment. 3*93f9dcf9SAnton Vorontsov * 4*93f9dcf9SAnton Vorontsov * Copyright (c) 2009 MontaVista Software, Inc. 5*93f9dcf9SAnton Vorontsov * 6*93f9dcf9SAnton Vorontsov * Author: Anton Vorontsov <avorontsov@ru.mvista.com> 7*93f9dcf9SAnton Vorontsov * 8*93f9dcf9SAnton Vorontsov * This program is free software; you can redistribute it and/or 9*93f9dcf9SAnton Vorontsov * modify it under the terms of the GNU General Public License as 10*93f9dcf9SAnton Vorontsov * published by the Free Software Foundation; either version 2 of 11*93f9dcf9SAnton Vorontsov * the License, or (at your option) any later version. 12*93f9dcf9SAnton Vorontsov */ 13*93f9dcf9SAnton Vorontsov 14*93f9dcf9SAnton Vorontsov #include <config.h> 15*93f9dcf9SAnton Vorontsov #include <common.h> 16*93f9dcf9SAnton Vorontsov #include <exports.h> 17*93f9dcf9SAnton Vorontsov #include <hwconfig.h> 18*93f9dcf9SAnton Vorontsov #include <linux/types.h> 19*93f9dcf9SAnton Vorontsov #include <linux/string.h> 20*93f9dcf9SAnton Vorontsov 21*93f9dcf9SAnton Vorontsov static const char *hwconfig_parse(const char *opts, size_t maxlen, 22*93f9dcf9SAnton Vorontsov const char *opt, char stopch, char eqch, 23*93f9dcf9SAnton Vorontsov size_t *arglen) 24*93f9dcf9SAnton Vorontsov { 25*93f9dcf9SAnton Vorontsov size_t optlen = strlen(opt); 26*93f9dcf9SAnton Vorontsov char *str; 27*93f9dcf9SAnton Vorontsov const char *start = opts; 28*93f9dcf9SAnton Vorontsov const char *end; 29*93f9dcf9SAnton Vorontsov 30*93f9dcf9SAnton Vorontsov next: 31*93f9dcf9SAnton Vorontsov str = strstr(opts, opt); 32*93f9dcf9SAnton Vorontsov end = str + optlen; 33*93f9dcf9SAnton Vorontsov if (end - start > maxlen) 34*93f9dcf9SAnton Vorontsov return NULL; 35*93f9dcf9SAnton Vorontsov 36*93f9dcf9SAnton Vorontsov if (str && (str == opts || str[-1] == stopch) && 37*93f9dcf9SAnton Vorontsov (*end == stopch || *end == eqch || *end == '\0')) { 38*93f9dcf9SAnton Vorontsov const char *arg_end; 39*93f9dcf9SAnton Vorontsov 40*93f9dcf9SAnton Vorontsov if (!arglen) 41*93f9dcf9SAnton Vorontsov return str; 42*93f9dcf9SAnton Vorontsov 43*93f9dcf9SAnton Vorontsov if (*end != eqch) 44*93f9dcf9SAnton Vorontsov return NULL; 45*93f9dcf9SAnton Vorontsov 46*93f9dcf9SAnton Vorontsov arg_end = strchr(str, stopch); 47*93f9dcf9SAnton Vorontsov if (!arg_end) 48*93f9dcf9SAnton Vorontsov *arglen = min(maxlen, strlen(str)) - optlen - 1; 49*93f9dcf9SAnton Vorontsov else 50*93f9dcf9SAnton Vorontsov *arglen = arg_end - end - 1; 51*93f9dcf9SAnton Vorontsov 52*93f9dcf9SAnton Vorontsov return end + 1; 53*93f9dcf9SAnton Vorontsov } else if (str) { 54*93f9dcf9SAnton Vorontsov opts = end; 55*93f9dcf9SAnton Vorontsov goto next; 56*93f9dcf9SAnton Vorontsov } 57*93f9dcf9SAnton Vorontsov return NULL; 58*93f9dcf9SAnton Vorontsov } 59*93f9dcf9SAnton Vorontsov 60*93f9dcf9SAnton Vorontsov const char *cpu_hwconfig __attribute__((weak)); 61*93f9dcf9SAnton Vorontsov const char *board_hwconfig __attribute__((weak)); 62*93f9dcf9SAnton Vorontsov 63*93f9dcf9SAnton Vorontsov static const char *__hwconfig(const char *opt, size_t *arglen) 64*93f9dcf9SAnton Vorontsov { 65*93f9dcf9SAnton Vorontsov const char *env_hwconfig = getenv("hwconfig"); 66*93f9dcf9SAnton Vorontsov 67*93f9dcf9SAnton Vorontsov if (env_hwconfig) 68*93f9dcf9SAnton Vorontsov return hwconfig_parse(env_hwconfig, strlen(env_hwconfig), 69*93f9dcf9SAnton Vorontsov opt, ';', ':', arglen); 70*93f9dcf9SAnton Vorontsov 71*93f9dcf9SAnton Vorontsov if (board_hwconfig) 72*93f9dcf9SAnton Vorontsov return hwconfig_parse(board_hwconfig, strlen(board_hwconfig), 73*93f9dcf9SAnton Vorontsov opt, ';', ':', arglen); 74*93f9dcf9SAnton Vorontsov 75*93f9dcf9SAnton Vorontsov if (cpu_hwconfig) 76*93f9dcf9SAnton Vorontsov return hwconfig_parse(cpu_hwconfig, strlen(cpu_hwconfig), 77*93f9dcf9SAnton Vorontsov opt, ';', ':', arglen); 78*93f9dcf9SAnton Vorontsov 79*93f9dcf9SAnton Vorontsov return NULL; 80*93f9dcf9SAnton Vorontsov } 81*93f9dcf9SAnton Vorontsov 82*93f9dcf9SAnton Vorontsov /* 83*93f9dcf9SAnton Vorontsov * hwconfig - query if a particular hwconfig option is specified 84*93f9dcf9SAnton Vorontsov * @opt: a string representing an option 85*93f9dcf9SAnton Vorontsov * 86*93f9dcf9SAnton Vorontsov * This call can be used to find out whether U-Boot should configure 87*93f9dcf9SAnton Vorontsov * a particular hardware option. 88*93f9dcf9SAnton Vorontsov * 89*93f9dcf9SAnton Vorontsov * Returns non-zero value if the hardware option can be used and thus 90*93f9dcf9SAnton Vorontsov * should be configured, 0 otherwise. 91*93f9dcf9SAnton Vorontsov * 92*93f9dcf9SAnton Vorontsov * This function also returns non-zero value if CONFIG_HWCONFIG is 93*93f9dcf9SAnton Vorontsov * undefined. 94*93f9dcf9SAnton Vorontsov * 95*93f9dcf9SAnton Vorontsov * Returning non-zero value without CONFIG_HWCONFIG has its crucial 96*93f9dcf9SAnton Vorontsov * purpose: the hwconfig() call should be a "transparent" interface, 97*93f9dcf9SAnton Vorontsov * e.g. if a board doesn't need hwconfig facility, then we assume 98*93f9dcf9SAnton Vorontsov * that the board file only calls things that are actually used, so 99*93f9dcf9SAnton Vorontsov * hwconfig() will always return true result. 100*93f9dcf9SAnton Vorontsov */ 101*93f9dcf9SAnton Vorontsov int hwconfig(const char *opt) 102*93f9dcf9SAnton Vorontsov { 103*93f9dcf9SAnton Vorontsov return !!__hwconfig(opt, NULL); 104*93f9dcf9SAnton Vorontsov } 105*93f9dcf9SAnton Vorontsov 106*93f9dcf9SAnton Vorontsov /* 107*93f9dcf9SAnton Vorontsov * hwconfig_arg - get hwconfig option's argument 108*93f9dcf9SAnton Vorontsov * @opt: a string representing an option 109*93f9dcf9SAnton Vorontsov * @arglen: a pointer to an allocated size_t variable 110*93f9dcf9SAnton Vorontsov * 111*93f9dcf9SAnton Vorontsov * Unlike hwconfig() function, this function returns a pointer to the 112*93f9dcf9SAnton Vorontsov * start of the hwconfig arguments, if option is not found or it has 113*93f9dcf9SAnton Vorontsov * no specified arguments, the function returns NULL pointer. 114*93f9dcf9SAnton Vorontsov * 115*93f9dcf9SAnton Vorontsov * If CONFIG_HWCONFIG is undefined, the function returns "", and 116*93f9dcf9SAnton Vorontsov * arglen is set to 0. 117*93f9dcf9SAnton Vorontsov */ 118*93f9dcf9SAnton Vorontsov const char *hwconfig_arg(const char *opt, size_t *arglen) 119*93f9dcf9SAnton Vorontsov { 120*93f9dcf9SAnton Vorontsov return __hwconfig(opt, arglen); 121*93f9dcf9SAnton Vorontsov } 122*93f9dcf9SAnton Vorontsov 123*93f9dcf9SAnton Vorontsov /* 124*93f9dcf9SAnton Vorontsov * hwconfig_arg_cmp - compare hwconfig option's argument 125*93f9dcf9SAnton Vorontsov * @opt: a string representing an option 126*93f9dcf9SAnton Vorontsov * @arg: a string for comparing an option's argument 127*93f9dcf9SAnton Vorontsov * 128*93f9dcf9SAnton Vorontsov * This call is similar to hwconfig_arg, but instead of returning 129*93f9dcf9SAnton Vorontsov * hwconfig argument and its length, it is comparing it to @arg. 130*93f9dcf9SAnton Vorontsov * 131*93f9dcf9SAnton Vorontsov * Returns non-zero value if @arg matches, 0 otherwise. 132*93f9dcf9SAnton Vorontsov * 133*93f9dcf9SAnton Vorontsov * If CONFIG_HWCONFIG is undefined, the function returns a non-zero 134*93f9dcf9SAnton Vorontsov * value, i.e. the argument matches. 135*93f9dcf9SAnton Vorontsov */ 136*93f9dcf9SAnton Vorontsov int hwconfig_arg_cmp(const char *opt, const char *arg) 137*93f9dcf9SAnton Vorontsov { 138*93f9dcf9SAnton Vorontsov const char *argstr; 139*93f9dcf9SAnton Vorontsov size_t arglen; 140*93f9dcf9SAnton Vorontsov 141*93f9dcf9SAnton Vorontsov argstr = hwconfig_arg(opt, &arglen); 142*93f9dcf9SAnton Vorontsov if (!argstr || arglen != strlen(arg)) 143*93f9dcf9SAnton Vorontsov return 0; 144*93f9dcf9SAnton Vorontsov 145*93f9dcf9SAnton Vorontsov return !strncmp(argstr, arg, arglen); 146*93f9dcf9SAnton Vorontsov } 147*93f9dcf9SAnton Vorontsov 148*93f9dcf9SAnton Vorontsov /* 149*93f9dcf9SAnton Vorontsov * hwconfig_sub - query if a particular hwconfig sub-option is specified 150*93f9dcf9SAnton Vorontsov * @opt: a string representing an option 151*93f9dcf9SAnton Vorontsov * @subopt: a string representing a sub-option 152*93f9dcf9SAnton Vorontsov * 153*93f9dcf9SAnton Vorontsov * This call is similar to hwconfig(), except that it takes additional 154*93f9dcf9SAnton Vorontsov * argument @subopt. In this example: 155*93f9dcf9SAnton Vorontsov * "dr_usb:mode=peripheral" 156*93f9dcf9SAnton Vorontsov * "dr_usb" is an option, "mode" is a sub-option, and "peripheral" is its 157*93f9dcf9SAnton Vorontsov * argument. 158*93f9dcf9SAnton Vorontsov */ 159*93f9dcf9SAnton Vorontsov int hwconfig_sub(const char *opt, const char *subopt) 160*93f9dcf9SAnton Vorontsov { 161*93f9dcf9SAnton Vorontsov size_t arglen; 162*93f9dcf9SAnton Vorontsov const char *arg; 163*93f9dcf9SAnton Vorontsov 164*93f9dcf9SAnton Vorontsov arg = __hwconfig(opt, &arglen); 165*93f9dcf9SAnton Vorontsov if (!arg) 166*93f9dcf9SAnton Vorontsov return 0; 167*93f9dcf9SAnton Vorontsov return !!hwconfig_parse(arg, arglen, subopt, ',', '=', NULL); 168*93f9dcf9SAnton Vorontsov } 169*93f9dcf9SAnton Vorontsov 170*93f9dcf9SAnton Vorontsov /* 171*93f9dcf9SAnton Vorontsov * hwconfig_subarg - get hwconfig sub-option's argument 172*93f9dcf9SAnton Vorontsov * @opt: a string representing an option 173*93f9dcf9SAnton Vorontsov * @subopt: a string representing a sub-option 174*93f9dcf9SAnton Vorontsov * @subarglen: a pointer to an allocated size_t variable 175*93f9dcf9SAnton Vorontsov * 176*93f9dcf9SAnton Vorontsov * This call is similar to hwconfig_arg(), except that it takes an additional 177*93f9dcf9SAnton Vorontsov * argument @subopt, and so works with sub-options. 178*93f9dcf9SAnton Vorontsov */ 179*93f9dcf9SAnton Vorontsov const char *hwconfig_subarg(const char *opt, const char *subopt, 180*93f9dcf9SAnton Vorontsov size_t *subarglen) 181*93f9dcf9SAnton Vorontsov { 182*93f9dcf9SAnton Vorontsov size_t arglen; 183*93f9dcf9SAnton Vorontsov const char *arg; 184*93f9dcf9SAnton Vorontsov 185*93f9dcf9SAnton Vorontsov arg = __hwconfig(opt, &arglen); 186*93f9dcf9SAnton Vorontsov if (!arg) 187*93f9dcf9SAnton Vorontsov return NULL; 188*93f9dcf9SAnton Vorontsov return hwconfig_parse(arg, arglen, subopt, ',', '=', subarglen); 189*93f9dcf9SAnton Vorontsov } 190*93f9dcf9SAnton Vorontsov 191*93f9dcf9SAnton Vorontsov /* 192*93f9dcf9SAnton Vorontsov * hwconfig_arg_cmp - compare hwconfig sub-option's argument 193*93f9dcf9SAnton Vorontsov * @opt: a string representing an option 194*93f9dcf9SAnton Vorontsov * @subopt: a string representing a sub-option 195*93f9dcf9SAnton Vorontsov * @subarg: a string for comparing an sub-option's argument 196*93f9dcf9SAnton Vorontsov * 197*93f9dcf9SAnton Vorontsov * This call is similar to hwconfig_arg_cmp, except that it takes an additional 198*93f9dcf9SAnton Vorontsov * argument @subopt, and so works with sub-options. 199*93f9dcf9SAnton Vorontsov */ 200*93f9dcf9SAnton Vorontsov int hwconfig_subarg_cmp(const char *opt, const char *subopt, const char *subarg) 201*93f9dcf9SAnton Vorontsov { 202*93f9dcf9SAnton Vorontsov const char *argstr; 203*93f9dcf9SAnton Vorontsov size_t arglen; 204*93f9dcf9SAnton Vorontsov 205*93f9dcf9SAnton Vorontsov argstr = hwconfig_subarg(opt, subopt, &arglen); 206*93f9dcf9SAnton Vorontsov if (!argstr || arglen != strlen(subarg)) 207*93f9dcf9SAnton Vorontsov return 0; 208*93f9dcf9SAnton Vorontsov 209*93f9dcf9SAnton Vorontsov return !strncmp(argstr, subarg, arglen); 210*93f9dcf9SAnton Vorontsov } 211