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 stopch, 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 || str[-1] == stopch) && 37 (*end == stopch || *end == eqch || *end == '\0')) { 38 const char *arg_end; 39 40 if (!arglen) 41 return str; 42 43 if (*end != eqch) 44 return NULL; 45 46 arg_end = strchr(str, stopch); 47 if (!arg_end) 48 *arglen = min(maxlen, strlen(str)) - optlen - 1; 49 else 50 *arglen = arg_end - end - 1; 51 52 return end + 1; 53 } else if (str) { 54 opts = end; 55 goto next; 56 } 57 return NULL; 58 } 59 60 const char *cpu_hwconfig __attribute__((weak)); 61 const char *board_hwconfig __attribute__((weak)); 62 63 static const char *__hwconfig(const char *opt, size_t *arglen) 64 { 65 const char *env_hwconfig = getenv("hwconfig"); 66 67 if (env_hwconfig) 68 return hwconfig_parse(env_hwconfig, strlen(env_hwconfig), 69 opt, ';', ':', arglen); 70 71 if (board_hwconfig) 72 return hwconfig_parse(board_hwconfig, strlen(board_hwconfig), 73 opt, ';', ':', arglen); 74 75 if (cpu_hwconfig) 76 return hwconfig_parse(cpu_hwconfig, strlen(cpu_hwconfig), 77 opt, ';', ':', arglen); 78 79 return NULL; 80 } 81 82 /* 83 * hwconfig - query if a particular hwconfig option is specified 84 * @opt: a string representing an option 85 * 86 * This call can be used to find out whether U-Boot should configure 87 * a particular hardware option. 88 * 89 * Returns non-zero value if the hardware option can be used and thus 90 * should be configured, 0 otherwise. 91 * 92 * This function also returns non-zero value if CONFIG_HWCONFIG is 93 * undefined. 94 * 95 * Returning non-zero value without CONFIG_HWCONFIG has its crucial 96 * purpose: the hwconfig() call should be a "transparent" interface, 97 * e.g. if a board doesn't need hwconfig facility, then we assume 98 * that the board file only calls things that are actually used, so 99 * hwconfig() will always return true result. 100 */ 101 int hwconfig(const char *opt) 102 { 103 return !!__hwconfig(opt, NULL); 104 } 105 106 /* 107 * hwconfig_arg - get hwconfig option's argument 108 * @opt: a string representing an option 109 * @arglen: a pointer to an allocated size_t variable 110 * 111 * Unlike hwconfig() function, this function returns a pointer to the 112 * start of the hwconfig arguments, if option is not found or it has 113 * no specified arguments, the function returns NULL pointer. 114 * 115 * If CONFIG_HWCONFIG is undefined, the function returns "", and 116 * arglen is set to 0. 117 */ 118 const char *hwconfig_arg(const char *opt, size_t *arglen) 119 { 120 return __hwconfig(opt, arglen); 121 } 122 123 /* 124 * hwconfig_arg_cmp - compare hwconfig option's argument 125 * @opt: a string representing an option 126 * @arg: a string for comparing an option's argument 127 * 128 * This call is similar to hwconfig_arg, but instead of returning 129 * hwconfig argument and its length, it is comparing it to @arg. 130 * 131 * Returns non-zero value if @arg matches, 0 otherwise. 132 * 133 * If CONFIG_HWCONFIG is undefined, the function returns a non-zero 134 * value, i.e. the argument matches. 135 */ 136 int hwconfig_arg_cmp(const char *opt, const char *arg) 137 { 138 const char *argstr; 139 size_t arglen; 140 141 argstr = hwconfig_arg(opt, &arglen); 142 if (!argstr || arglen != strlen(arg)) 143 return 0; 144 145 return !strncmp(argstr, arg, arglen); 146 } 147 148 /* 149 * hwconfig_sub - query if a particular hwconfig sub-option is specified 150 * @opt: a string representing an option 151 * @subopt: a string representing a sub-option 152 * 153 * This call is similar to hwconfig(), except that it takes additional 154 * argument @subopt. In this example: 155 * "dr_usb:mode=peripheral" 156 * "dr_usb" is an option, "mode" is a sub-option, and "peripheral" is its 157 * argument. 158 */ 159 int hwconfig_sub(const char *opt, const char *subopt) 160 { 161 size_t arglen; 162 const char *arg; 163 164 arg = __hwconfig(opt, &arglen); 165 if (!arg) 166 return 0; 167 return !!hwconfig_parse(arg, arglen, subopt, ',', '=', NULL); 168 } 169 170 /* 171 * hwconfig_subarg - get hwconfig sub-option's argument 172 * @opt: a string representing an option 173 * @subopt: a string representing a sub-option 174 * @subarglen: a pointer to an allocated size_t variable 175 * 176 * This call is similar to hwconfig_arg(), except that it takes an additional 177 * argument @subopt, and so works with sub-options. 178 */ 179 const char *hwconfig_subarg(const char *opt, const char *subopt, 180 size_t *subarglen) 181 { 182 size_t arglen; 183 const char *arg; 184 185 arg = __hwconfig(opt, &arglen); 186 if (!arg) 187 return NULL; 188 return hwconfig_parse(arg, arglen, subopt, ',', '=', subarglen); 189 } 190 191 /* 192 * hwconfig_arg_cmp - compare hwconfig sub-option's argument 193 * @opt: a string representing an option 194 * @subopt: a string representing a sub-option 195 * @subarg: a string for comparing an sub-option's argument 196 * 197 * This call is similar to hwconfig_arg_cmp, except that it takes an additional 198 * argument @subopt, and so works with sub-options. 199 */ 200 int hwconfig_subarg_cmp(const char *opt, const char *subopt, const char *subarg) 201 { 202 const char *argstr; 203 size_t arglen; 204 205 argstr = hwconfig_subarg(opt, subopt, &arglen); 206 if (!argstr || arglen != strlen(subarg)) 207 return 0; 208 209 return !strncmp(argstr, subarg, arglen); 210 } 211