Merge branch 'master-sync' of git://git.denx.de/u-boot-arm
[platform/kernel/u-boot.git] / common / hwconfig.c
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 }