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