1 /*
2  * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /**
21  * DOC: UCFG APIs for the configuration component.
22  *
23  * Logically, configuration exists at the psoc level. This means, each psoc can
24  * have its own custom configuration, and calls to lookup configuration take a
25  * psoc parameter for reference. E.g.
26  *
27  *	int32_t value = cfg_get(psoc, WLAN_SOME_INTEGER_CONFIG_ID);
28  *
29  * Configuration is cascading, and lookups happen in this order:
30  *
31  *	1) use psoc value, if configured
32  *	2) use global value, if configured
33  *	3) fallback to the default value for the configuration item
34  *
35  * This means a psoc configuration is a specialization of the global
36  * configuration, and does not need to explicitly set the same values if they
37  * would match the global config.
38  *
39  * In order to load and parse the global config, call cfg_parse(). In order to
40  * load and parse psoc configs, call cfg_psoc_parse(). cfg_parse() MUST be
41  * called before cfg_psoc_parse(), as global configuration will be consulted
42  * during the psoc parsing process.
43  *
44  * There are two basic lifecycles supported:
45  *
46  * 1) The type and number of psocs is *not* known at load time
47  *
48  *	// driver is loading
49  *	cfg_parse("/path/to/config");
50  *
51  *	...
52  *
53  *	// a psoc has just been created
54  *	cfg_psoc_parse(psoc, "/path/to/psoc/config");
55  *
56  *	...
57  *
58  *	// driver is unloading
59  *	cfg_release();
60  *
61  * 2) The type and number of psocs *is* known at load time
62  *
63  *	// driver is loading
64  *	cfg_parse("/path/to/config");
65  *
66  *	...
67  *
68  *	// for each psoc
69  *		cfg_psoc_parse(psoc, "/path/to/psoc/config");
70  *
71  *	// no further psocs will be created after this point
72  *	cfg_release();
73  *
74  *	...
75  *
76  *	// driver is unloaded later
77  *
78  * Each configuration store is reference counted to reduce memory footprint, and
79  * the configuration component itself will hold one ref count on the global
80  * config store. All psocs for which psoc-specific configurations have *not*
81  * been provided will reference the global config store. Psocs for which psoc-
82  * specific configurations *have* been provided will check for existings stores
83  * with a matching path to use, before parsing the specified configuration file.
84  *
85  * If, at some point in time, it is known that no further psocs will ever be
86  * created, a call to cfg_release() will release the global ref count held by
87  * the configuration component. For systems which specify psoc-specific configs
88  * for all psocs, this will release the unnecessary memory used by the global
89  * config store. Otherwise, calling cfg_release() at unload time will ensure
90  * the global config store is properly freed.
91  */
92 
93 #ifndef __CFG_UCFG_H
94 #define __CFG_UCFG_H
95 
96 #include "cfg_all.h"
97 #include "cfg_define.h"
98 #include "i_cfg.h"
99 #include "qdf_status.h"
100 #include "qdf_str.h"
101 #include "qdf_types.h"
102 #include "wlan_objmgr_psoc_obj.h"
103 
104 /**
105  * cfg_parse() - parse an ini file, and populate the global config storei
106  * @path: The full file path of the ini file to parse
107  *
108  * Note: A matching cfg_release() call is required to release allocated
109  * resources.
110  *
111  * The *.ini file format is a simple format consisting of a list of key/value
112  * pairs, separated by an '=' character. e.g.
113  *
114  *	gConfigItem1=some string value
115  *	gConfigItem2=0xabc
116  *
117  * Comments are also supported, initiated with the '#' character:
118  *
119  *	# This is a comment. It will be ignored by the *.ini parser
120  *	gConfigItem3=aa:bb:cc:dd:ee:ff # this is also a comment
121  *
122  * Several datatypes are natively supported:
123  *
124  *	gInt=-123 # bin (0b), octal (0o), hex (0x), and decimal supported
125  *	gUint=123 # a non-negative integer value
126  *	gBool=y # (1, Y, y) -> true; (0, N, n) -> false
127  *	gString=any string # strings are useful for representing complex types
128  *	gMacAddr=aa:bb:cc:dd:ee:ff # colons are optional, upper and lower case
129  *	gIpv4Addr=127.0.0.1 # uses typical dot-decimal notation
130  *	gIpv6Addr=::1 # typical notation, supporting zero-compression
131  *
132  * Return: QDF_STATUS
133  */
134 QDF_STATUS cfg_parse(const char *path);
135 
136 /**
137  * cfg_release() - release the global configuration store
138  *
139  * This API releases the configuration component's reference to the global
140  * config store.
141  *
142  * See also: this file's DOC section.
143  *
144  * Return: None
145  */
146 void cfg_release(void);
147 
148 /**
149  * cfg_psoc_parse() - specialize the config store for @psoc by parsing @path
150  * @psoc: The psoc whose config store should be specialized
151  * @path: The full file path of the ini file to parse
152  *
153  * See also: cfg_parse(), and this file's DOC section.
154  *
155  * Return: QDF_STATUS
156  */
157 QDF_STATUS cfg_psoc_parse(struct wlan_objmgr_psoc *psoc, const char *path);
158 
159 /**
160  * cfg_parse_to_psoc_store() - Parse file @path and update psoc ini store
161  * @psoc: The psoc whose config store should be updated
162  * @path: The full file path of the ini file to parse
163  *
164  * Return: QDF_STATUS
165  */
166 QDF_STATUS cfg_parse_to_psoc_store(struct wlan_objmgr_psoc *psoc,
167 				   const char *path);
168 
169 /**
170  * cfg_section_parse_to_psoc_store() - Parse specific section from file @path
171  *                                     and update psoc ini store
172  * @psoc: The psoc whose config store should be updated
173  * @path: The full file path of the ini file to parse
174  * @section_name: Section name to be parsed
175  *
176  * Return: QDF_STATUS
177  */
178 QDF_STATUS cfg_section_parse_to_psoc_store(struct wlan_objmgr_psoc *psoc,
179 					   const char *path,
180 					   const char *section_name);
181 
182 /**
183  * cfg_parse_to_global_store() - Parse file @path and update global ini store
184  * @path: The full file path of the ini file to parse
185  *
186  * Return: QDF_STATUS
187  */
188 QDF_STATUS cfg_parse_to_global_store(const char *path);
189 
190 /**
191  * ucfg_cfg_store_print() - prints the cfg ini/non ini logs
192  * @psoc: psoc
193  *
194  * Return: QDF_STATUS
195  */
196 QDF_STATUS ucfg_cfg_store_print(struct wlan_objmgr_psoc *psoc);
197 
198 /**
199  * ucfg_cfg_ini_config_print() - prints the cfg ini/non ini to buffer
200  * @psoc: psoc
201  * @buf: cache to save ini config
202  * @plen: the pointer to length
203  * @buflen: total buf length
204  *
205  * Return: QDF_STATUS
206  */
207 QDF_STATUS ucfg_cfg_ini_config_print(struct wlan_objmgr_psoc *psoc,
208 				     uint8_t *buf, ssize_t *plen,
209 				     ssize_t buflen);
210 /**
211  * cfg_valid_ini_check() - check ini file for invalid characters
212  * @path: path to ini file
213  *
214  * Return: true if no invalid characters found, false otherwise
215  */
216 bool cfg_valid_ini_check(const char *path);
217 
218 /**
219  * cfg_get() - lookup the configured value for @id from @psoc
220  * @psoc: The psoc from which to lookup the configured value
221  * @id: The id of the configured value to lookup
222  *
223  * E.g.
224  *
225  *	int32_t value = cfg_get(psoc, WLAN_SOME_INTEGER_CONFIG_ID);
226  *
227  * Return: The configured value
228  */
229 #define cfg_get(psoc, id) __cfg_get(psoc, __##id)
230 
231 /* Configuration Access APIs */
232 #define __do_call(op, args...) op(args)
233 #define do_call(op, args) __do_call(op, rm_parens args)
234 
235 #define cfg_id(id) #id
236 
237 #define __cfg_mtype(ini, mtype, ctype, name, min, max, fallback, desc, def...) \
238 	mtype
239 #define cfg_mtype(id) do_call(__cfg_mtype, id)
240 
241 #define __cfg_type(ini, mtype, ctype, name, min, max, fallback, desc, def...) \
242 	ctype
243 #define cfg_type(id) do_call(__cfg_type, id)
244 
245 #define __cfg_name(ini, mtype, ctype, name, min, max, fallback, desc, def...) \
246 	name
247 #define cfg_name(id) do_call(__cfg_name, id)
248 
249 #define __cfg_min(ini, mtype, ctype, name, min, max, fallback, desc, def...) \
250 	min
251 #define cfg_min(id) do_call(__cfg_min, id)
252 
253 #define __cfg_max(ini, mtype, ctype, name, min, max, fallback, desc, def...) \
254 	max
255 #define cfg_max(id) do_call(__cfg_max, id)
256 
257 #define __cfg_fb(ini, mtype, ctype, name, min, max, fallback, desc, def...) \
258 	fallback
259 #define cfg_fallback(id) do_call(__cfg_fb, id)
260 
261 #define __cfg_desc(ini, mtype, ctype, name, min, max, fallback, desc, def...) \
262 	desc
263 #define cfg_description(id) do_call(__cfg_desc, id)
264 
265 #define __cfg_def(ini, mtype, ctype, name, min, max, fallback, desc, def...) \
266 	def
267 #define cfg_default(id) do_call(__cfg_def, id)
268 
269 #define __cfg_str(id...) #id
270 #define cfg_str(id) #id __cfg_str(id)
271 
272 /* validate APIs */
273 static inline bool
cfg_string_in_range(const char * value,qdf_size_t min_len,qdf_size_t max_len)274 cfg_string_in_range(const char *value, qdf_size_t min_len, qdf_size_t max_len)
275 {
276 	qdf_size_t len = qdf_str_len(value);
277 
278 	return len >= min_len && len <= max_len;
279 }
280 
281 #define __cfg_INT_in_range(value, min, max) (value >= min && value <= max)
282 #define __cfg_UINT_in_range(value, min, max) (value >= min && value <= max)
283 #define __cfg_STRING_in_range(value, min_len, max_len) \
284 	cfg_string_in_range(value, min_len, max_len)
285 
286 #define __cfg_in_range(id, value, mtype) \
287 	__cfg_ ## mtype ## _in_range(value, cfg_min(id), cfg_max(id))
288 
289 /* this may look redundant, but forces @mtype to be expanded */
290 #define __cfg_in_range_type(id, value, mtype) \
291 	__cfg_in_range(id, value, mtype)
292 
293 #define cfg_in_range(id, value) __cfg_in_range_type(id, value, cfg_mtype(id))
294 
295 /* Value-or-Default APIs */
296 #define __cfg_value_or_default(id, value, def) \
297 	(cfg_in_range(id, value) ? value : def)
298 
299 #define cfg_value_or_default(id, value) \
300 	__cfg_value_or_default(id, value, cfg_default(id))
301 
302 /* Value-or-Clamped APIs */
303 #define __cfg_clamp(val, min, max) (val < min ? min : (val > max ? max : val))
304 #define cfg_clamp(id, value) __cfg_clamp(value, cfg_min(id), cfg_max(id))
305 
306 #endif /* __CFG_UCFG_H */
307 
308