summaryrefslogtreecommitdiffstats
path: root/src/include/gpxe/settings.h
blob: f32d3ec9a9edb3ccca9dcaa906451c50d285a9ed (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
#ifndef _GPXE_SETTINGS_H
#define _GPXE_SETTINGS_H

/** @file
 *
 * Configuration settings
 *
 */

#include <stdint.h>
#include <gpxe/tables.h>
#include <gpxe/list.h>
#include <gpxe/refcnt.h>
#include <gpxe/dhcpopts.h>

struct settings;
struct in_addr;

/** Settings block operations */
struct settings_operations {
	/** Store value of setting
	 *
	 * @v settings		Settings block
	 * @v tag		Setting tag number
	 * @v data		Setting data, or NULL to clear setting
	 * @v len		Length of setting data
	 * @ret rc		Return status code
	 */
	int ( * store ) ( struct settings *settings, unsigned int tag,
			  const void *data, size_t len );
	/** Fetch value of setting
	 *
	 * @v settings		Settings block
	 * @v tag		Setting tag number
	 * @v data		Buffer to fill with setting data
	 * @v len		Length of buffer
	 * @ret len		Length of setting data, or negative error
	 *
	 * The actual length of the setting will be returned even if
	 * the buffer was too small.
	 */
	int ( * fetch ) ( struct settings *settings, unsigned int tag,
			  void *data, size_t len );
};

/** A settings block */
struct settings {
	/** Reference counter */
	struct refcnt *refcnt;
	/** Name */
	const char *name;
	/** Parent settings block */
	struct settings *parent;
	/** Sibling settings blocks */
	struct list_head siblings;
	/** Child settings blocks */
	struct list_head children;
	/** Settings block operations */
	struct settings_operations *op;
};

/**
 * A setting type
 *
 * This represents a type of setting (e.g. string, IPv4 address,
 * etc.).
 */
struct setting_type {
	/** Name
	 *
	 * This is the name exposed to the user (e.g. "string").
	 */
	const char *name;
	/** Parse and set value of setting
	 *
	 * @v settings		Settings block
	 * @v tag		Setting tag number
	 * @v value		Formatted setting data
	 * @ret rc		Return status code
	 */
	int ( * storef ) ( struct settings *settings, unsigned int tag,
			   const char *value );
	/** Fetch and format value of setting
	 *
	 * @v settings		Settings block, or NULL to search all blocks
	 * @v tag		Setting tag number
	 * @v buf		Buffer to contain formatted value
	 * @v len		Length of buffer
	 * @ret len		Length of formatted value, or negative error
	 */
	int ( * fetchf ) ( struct settings *settings, unsigned int tag,
			   char *buf, size_t len );
};

/** Declare a configuration setting type */
#define	__setting_type \
	__table ( struct setting_type, setting_types, 01 )

/**
 * A named setting
 *
 * This represents a single setting (e.g. "hostname"), encapsulating
 * the information about the setting's tag number and type.
 */
struct named_setting {
	/** Name
	 *
	 * This is the human-readable name for the setting.
	 */
	const char *name;
	/** Description */
	const char *description;
	/** Setting tag number */
	unsigned int tag;
	/** Setting type
	 *
	 * This identifies the type of setting (e.g. string, IPv4
	 * address, etc.).
	 */
	struct setting_type *type;
};

/** Declare a configuration setting */
#define	__named_setting __table ( struct named_setting, named_settings, 01 )

/**
 * A settings applicator
 *
 */
struct settings_applicator {
	/** Apply updated settings
	 *
	 * @ret rc		Return status code
	 */
	int ( * apply ) ( void );
};

/** Declare a settings applicator */
#define __settings_applicator \
	__table ( struct settings_applicator, settings_applicators, 01 )

/**
 * A simple settings block
 *
 */
struct simple_settings {
	/** Settings block */
	struct settings settings;
	/** DHCP options */
	struct dhcp_options dhcpopts;
};

extern struct settings_operations simple_settings_operations;

extern int simple_settings_store ( struct settings *settings, unsigned int tag,
				   const void *data, size_t len );
extern int simple_settings_fetch ( struct settings *settings, unsigned int tag,
				   void *data, size_t len );
extern int register_settings ( struct settings *settings,
			       struct settings *parent );
extern void unregister_settings ( struct settings *settings );
extern int store_setting ( struct settings *settings, unsigned int tag,
			   const void *data, size_t len );
extern int fetch_setting ( struct settings *settings, unsigned int tag,
			   void *data, size_t len );
extern int copy_settings ( struct settings *dest, struct settings *source );
extern int fetch_setting_len ( struct settings *settings, unsigned int tag );
extern int fetch_string_setting ( struct settings *settings, unsigned int tag,
				  char *data, size_t len );
extern int fetch_ipv4_setting ( struct settings *settings, unsigned int tag,
				struct in_addr *inp );
extern int fetch_int_setting ( struct settings *settings, unsigned int tag,
			       long *value );
extern int fetch_uint_setting ( struct settings *settings, unsigned int tag,
				unsigned long *value );
extern long fetch_intz_setting ( struct settings *settings, unsigned int tag );
extern unsigned long fetch_uintz_setting ( struct settings *settings,
					   unsigned int tag );
extern struct settings * find_child_settings ( struct settings *parent,
					       const char *name );
extern struct settings * find_settings ( const char *name );
extern int store_typed_setting ( struct settings *settings,
				 unsigned int tag, struct setting_type *type,
				 const char *value );
extern int store_named_setting ( const char *name, const char *value );
extern int fetch_named_setting ( const char *name, char *buf, size_t len );

extern struct setting_type setting_type_ __setting_type;
extern struct setting_type setting_type_string __setting_type;
extern struct setting_type setting_type_ipv4 __setting_type;
extern struct setting_type setting_type_int8 __setting_type;
extern struct setting_type setting_type_int16 __setting_type;
extern struct setting_type setting_type_int32 __setting_type;
extern struct setting_type setting_type_uint8 __setting_type;
extern struct setting_type setting_type_uint16 __setting_type;
extern struct setting_type setting_type_uint32 __setting_type;
extern struct setting_type setting_type_hex __setting_type;

/**
 * Initialise a settings block
 *
 * @v settings		Settings block
 * @v op		Settings block operations
 * @v refcnt		Containing object reference counter, or NULL
 * @v name		Settings block name
 */
static inline void settings_init ( struct settings *settings,
				   struct settings_operations *op,
				   struct refcnt *refcnt,
				   const char *name ) {
	INIT_LIST_HEAD ( &settings->siblings );
	INIT_LIST_HEAD ( &settings->children );
	settings->op = op;
	settings->refcnt = refcnt;
	settings->name = name;
}

/**
 * Initialise a settings block
 *
 * @v simple		Simple settings block
 * @v refcnt		Containing object reference counter, or NULL
 * @v name		Settings block name
 */
static inline void simple_settings_init ( struct simple_settings *simple,
					  struct refcnt *refcnt,
					  const char *name ) {
	settings_init ( &simple->settings, &simple_settings_operations,
			refcnt, name );
}

/**
 * Delete setting
 *
 * @v settings		Settings block
 * @v tag		Setting tag number
 * @ret rc		Return status code
 */
static inline int delete_setting ( struct settings *settings,
				   unsigned int tag ) {
	return store_setting ( settings, tag, NULL, 0 );
}

/**
 * Fetch and format value of setting
 *
 * @v settings		Settings block, or NULL to search all blocks
 * @v tag		Setting tag number
 * @v type		Settings type
 * @v buf		Buffer to contain formatted value
 * @v len		Length of buffer
 * @ret len		Length of formatted value, or negative error
 */
static inline int fetch_typed_setting ( struct settings *settings,
					unsigned int tag,
					struct setting_type *type,
					char *buf, size_t len ) {
	return type->fetchf ( settings, tag, buf, len );
}

/**
 * Delete named setting
 *
 * @v name		Name of setting
 * @ret rc		Return status code
 */
static inline int delete_named_setting ( const char *name ) {
	return store_named_setting ( name, NULL );
}

#endif /* _GPXE_SETTINGS_H */