1 /////////////////////////////////////////////////////////////////////////
2 // $Id: paramtree.h 14206 2021-03-28 06:31:03Z vruppert $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 //  Copyright (C) 2010-2021  The Bochs Project
6 //
7 //  This library is free software; you can redistribute it and/or
8 //  modify it under the terms of the GNU Lesser General Public
9 //  License as published by the Free Software Foundation; either
10 //  version 2 of the License, or (at your option) any later version.
11 //
12 //  This library is distributed in the hope that it will be useful,
13 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 //  Lesser General Public License for more details.
16 //
17 //  You should have received a copy of the GNU Lesser General Public
18 //  License along with this library; if not, write to the Free Software
19 //  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
20 //
21 /////////////////////////////////////////////////////////////////////////
22 
23 #ifndef BX_PARAM_TREE_H
24 #define BX_PARAM_TREE_H
25 
26 ////////////////////////////////////////////////////////////////////
27 // parameter classes: bx_param_c and family
28 ////////////////////////////////////////////////////////////////////
29 //
30 // All variables that can be configured through the CI are declared as
31 // "parameters" or objects of type bx_param_*.  There is a bx_param_*
32 // class for each type of data that the user would need to see and
33 // edit, e.g. integer, boolean, enum, string, filename, or list of
34 // other parameters.  The purpose of the bx_param_* class, in addition
35 // to storing the parameter's value, is to hold the name, description,
36 // and constraints on the value.  The bx_param_* class should hold
37 // everything that the CI would need to display the value and allow
38 // the user to modify it.  For integer parameters, the minimum and
39 // maximum allowed value can be defined, and the base in which it
40 // should be displayed and interpreted.  For enums, the
41 // bx_param_enum_c structure includes the list of values which the
42 // parameter can have.
43 //
44 // Also, some parameter classes support get/set callback functions to
45 // allow arbitrary code to be executed when the parameter is get/set.
46 // An example of where this is useful: if you disable the NE2K card,
47 // the set() handler for that parameter can tell the user interface
48 // that the NE2K's irq, I/O address, and mac address should be
49 // disabled (greyed out, hidden, or made inaccessible).  The get/set
50 // methods can also check if the set() value is acceptable using
51 // whatever means and override it.
52 //
53 // The parameter concept is similar to the use of parameters in JavaBeans.
54 
55 // list of possible types for bx_param_c and descendant objects
56 typedef enum {
57   BXT_OBJECT = 201,
58   BXT_PARAM,
59   BXT_PARAM_NUM,
60   BXT_PARAM_BOOL,
61   BXT_PARAM_ENUM,
62   BXT_PARAM_STRING,
63   BXT_PARAM_BYTESTRING,
64   BXT_PARAM_DATA,
65   BXT_PARAM_FILEDATA,
66   BXT_LIST
67 } bx_objtype;
68 
69 class bx_object_c;
70 class bx_param_c;
71 class bx_param_num_c;
72 class bx_param_enum_c;
73 class bx_param_bool_c;
74 class bx_param_string_c;
75 class bx_param_filename_c;
76 class bx_list_c;
77 
78 class BOCHSAPI bx_object_c {
79 private:
80   Bit32u id;
81   bx_objtype type;
82 protected:
set_type(bx_objtype _type)83   void set_type(bx_objtype _type) { type = _type; }
84 public:
bx_object_c(Bit32u _id)85   bx_object_c(Bit32u _id): id(_id), type(BXT_OBJECT) {}
~bx_object_c()86   virtual ~bx_object_c() {}
get_id()87   Bit32u get_id() const { return id; }
get_type()88   Bit8u get_type() const { return type; }
89 };
90 
91 #define BASE_DEC 10
92 #define BASE_HEX 16
93 #define BASE_FLOAT 32
94 #define BASE_DOUBLE 64
95 
96 class BOCHSAPI bx_param_c : public bx_object_c {
97   BOCHSAPI_CYGONLY static const char *default_text_format;
98 protected:
99   bx_list_c *parent;
100   char *name;
101   char *description;
102   char *label; // label string for text menus and gui dialogs
103   const char *text_format;  // printf format string. %d for ints, %s for strings, etc.
104   const char *long_text_format;  // printf format string. %d for ints, %s for strings, etc.
105   char *ask_format;  // format string for asking for a new value
106   char *group_name;  // name of the group the param belongs to
107   bool runtime_param;
108   bool enabled;
109   Bit32u options;
110   // The dependent_list is initialized to NULL.  If dependent_list is modified
111   // to point to a bx_list_c of other parameters, the set() method of the
112   // parameter type will enable those parameters when the enable condition is
113   // true, and disable them it is false.
114   bx_list_c *dependent_list;
115   void *device;
116 public:
117   enum {
118     // If set, this parameter is available in CI only. In bochsrc, it is set
119     // indirectly from one or more other options (e.g. cpu count)
120     CI_ONLY = (1<<31)
121   } bx_param_opt_bits;
122 
123   bx_param_c(Bit32u id, const char *name, const char *description);
124   bx_param_c(Bit32u id, const char *name, const char *label, const char *description);
125   virtual ~bx_param_c();
126 
reset()127   virtual void reset() {}
128 
get_name()129   const char *get_name() const { return name; }
get_parent()130   bx_param_c *get_parent() { return (bx_param_c *) parent; }
131 
132   int get_param_path(char *path_out, int maxlen);
133 
set_format(const char * format)134   void set_format(const char *format) {text_format = format;}
get_format()135   const char *get_format() const {return text_format;}
136 
set_long_format(const char * format)137   void set_long_format(const char *format) {long_text_format = format;}
get_long_format()138   const char *get_long_format() const {return long_text_format;}
139 
140   void set_ask_format(const char *format);
get_ask_format()141   const char *get_ask_format() const {return ask_format;}
142 
143   void set_label(const char *text);
get_label()144   const char *get_label() const {return label;}
145 
146   void set_description(const char *text);
get_description()147   const char *get_description() const { return description; }
148 
set_runtime_param(bool val)149   virtual void set_runtime_param(bool val) { runtime_param = val; }
get_runtime_param()150   bool get_runtime_param() const { return runtime_param; }
151 
152   void set_group(const char *group);
get_group()153   const char *get_group() const {return group_name;}
154 
get_enabled()155   bool get_enabled() const { return enabled; }
set_enabled(bool _enabled)156   virtual void set_enabled(bool _enabled) { enabled = _enabled; }
157 
158   static const char* set_default_format(const char *f);
get_default_format()159   static const char *get_default_format() { return default_text_format; }
160 
get_dependent_list()161   bx_list_c *get_dependent_list() { return dependent_list; }
162 
set_options(Bit32u _options)163   void set_options(Bit32u _options) { options = _options; }
get_options()164   Bit32u get_options() const { return options; }
165 
set_device_param(void * dev)166   void set_device_param(void *dev) { device = dev; }
get_device_param()167   void *get_device_param() { return device; }
168 
parse_param(const char * value)169   virtual int parse_param(const char *value) { return -1; }
170 
dump_param(FILE * fp)171   virtual void dump_param(FILE *fp) {}
172   virtual int dump_param(char *buf, int buflen, bool dquotes = false) { return 0; }
173 };
174 
175 typedef Bit64s (*param_event_handler)(class bx_param_c *, bool set, Bit64s val);
176 typedef Bit64s (*param_save_handler)(void *devptr, class bx_param_c *);
177 typedef void (*param_restore_handler)(void *devptr, class bx_param_c *, Bit64s val);
178 typedef bool (*param_enable_handler)(class bx_param_c *, bool en);
179 
180 class BOCHSAPI bx_param_num_c : public bx_param_c {
181   BOCHSAPI_CYGONLY static Bit32u default_base;
182   void update_dependents();
183 protected:
184   Bit64s min, max, initial_val;
185   union _uval_ {
186     Bit64s number;   // used by bx_param_num_c
187     Bit64s *p64bit;  // used by bx_shadow_num_c
188     Bit32s *p32bit;  // used by bx_shadow_num_c
189     Bit16s *p16bit;  // used by bx_shadow_num_c
190     Bit8s  *p8bit;   // used by bx_shadow_num_c
191     float  *pfloat;  // used by bx_shadow_num_c
192     double *pdouble; // used by bx_shadow_num_c
193     bool   *pbool;   // used by bx_shadow_bool_c
194   } val;
195   param_event_handler handler;
196   void *sr_devptr;
197   param_save_handler save_handler;
198   param_restore_handler restore_handler;
199   param_enable_handler enable_handler;
200   int base;
201   bool is_shadow;
202 public:
203   enum {
204     // When a bx_param_num_c is displayed in dialog, USE_SPIN_CONTROL controls
205     // whether a spin control should be used instead of a simple text control.
206     USE_SPIN_CONTROL = (1<<0)
207   } bx_numopt_bits;
208   bx_param_num_c(bx_param_c *parent,
209       const char *name,
210       const char *label,
211       const char *description,
212       Bit64s min, Bit64s max, Bit64s initial_val,
213       bool is_shadow = 0);
reset()214   virtual void reset() { set(initial_val); }
215   void set_handler(param_event_handler handler);
216   void set_sr_handlers(void *devptr, param_save_handler save, param_restore_handler restore);
set_enable_handler(param_enable_handler handler)217   void set_enable_handler(param_enable_handler handler) { enable_handler = handler; }
218   void set_dependent_list(bx_list_c *l);
219   virtual void set_enabled(bool enabled);
get()220   virtual Bit32s get() { return (Bit32s) get64(); }
221   virtual Bit64s get64();
222   virtual void set(Bit64s val);
set_base(int _base)223   void set_base(int _base) { base = _base; }
224   void set_initial_val(Bit64s initial_val);
get_base()225   int get_base() const { return base; }
226   void set_range(Bit64u min, Bit64u max);
get_min()227   Bit64s get_min() const { return min; }
get_max()228   Bit64s get_max() const { return max; }
229   static Bit32u set_default_base(Bit32u val);
get_default_base()230   static Bit32u get_default_base() { return default_base; }
231   virtual int parse_param(const char *value);
232   virtual void dump_param(FILE *fp);
233   virtual int dump_param(char *buf, int buflen, bool dquotes = false);
234 };
235 
236 // a bx_shadow_num_c is like a bx_param_num_c except that it doesn't
237 // store the actual value with its data. Instead, it uses val.p32bit
238 // to keep a pointer to the actual data.  This is used to register
239 // existing variables as parameters, without having to access it via
240 // set/get methods.
241 class BOCHSAPI bx_shadow_num_c : public bx_param_num_c {
242   Bit8u varsize;   // must be 64, 32, 16, or 8
243   Bit8u lowbit;   // range of bits associated with this param
244   Bit64u mask;     // mask is ANDed with value before it is returned from get
245 public:
246   bx_shadow_num_c(bx_param_c *parent,
247       const char *name,
248       Bit64s *ptr_to_real_val,
249       int base = BASE_DEC,
250       Bit8u highbit = 63,
251       Bit8u lowbit = 0);
252   bx_shadow_num_c(bx_param_c *parent,
253       const char *name,
254       Bit64u *ptr_to_real_val,
255       int base = BASE_DEC,
256       Bit8u highbit = 63,
257       Bit8u lowbit = 0);
258   bx_shadow_num_c(bx_param_c *parent,
259       const char *name,
260       Bit32s *ptr_to_real_val,
261       int base = BASE_DEC,
262       Bit8u highbit = 31,
263       Bit8u lowbit = 0);
264   bx_shadow_num_c(bx_param_c *parent,
265       const char *name,
266       Bit32u *ptr_to_real_val,
267       int base = BASE_DEC,
268       Bit8u highbit = 31,
269       Bit8u lowbit = 0);
270   bx_shadow_num_c(bx_param_c *parent,
271       const char *name,
272       Bit16s *ptr_to_real_val,
273       int base = BASE_DEC,
274       Bit8u highbit = 15,
275       Bit8u lowbit = 0);
276   bx_shadow_num_c(bx_param_c *parent,
277       const char *name,
278       Bit16u *ptr_to_real_val,
279       int base = BASE_DEC,
280       Bit8u highbit = 15,
281       Bit8u lowbit = 0);
282   bx_shadow_num_c(bx_param_c *parent,
283       const char *name,
284       Bit8s *ptr_to_real_val,
285       int base = BASE_DEC,
286       Bit8u highbit = 7,
287       Bit8u lowbit = 0);
288   bx_shadow_num_c(bx_param_c *parent,
289       const char *name,
290       Bit8u *ptr_to_real_val,
291       int base = BASE_DEC,
292       Bit8u highbit = 7,
293       Bit8u lowbit = 0);
294   bx_shadow_num_c(bx_param_c *parent,
295       const char *name,
296       double *ptr_to_real_val);
297   bx_shadow_num_c(bx_param_c *parent,
298       const char *name,
299       float *ptr_to_real_val);
300   virtual Bit64s get64();
301   virtual void set(Bit64s val);
302   virtual void reset();
303 };
304 
305 class BOCHSAPI bx_param_bool_c : public bx_param_num_c {
306   // many boolean variables are used to enable/disable modules.  In the
307   // user interface, the enable variable should enable/disable all the
308   // other parameters associated with that module.
309 public:
310   bx_param_bool_c(bx_param_c *parent,
311       const char *name,
312       const char *label,
313       const char *description,
314       Bit64s initial_val,
315       bool is_shadow = 0);
316   virtual int parse_param(const char *value);
317   virtual void dump_param(FILE *fp);
318   virtual int dump_param(char *buf, int buflen, bool dquotes = false);
319 };
320 
321 // a bx_shadow_bool_c is a shadow param based on bx_param_bool_c.
322 class BOCHSAPI bx_shadow_bool_c : public bx_param_bool_c {
323 public:
324   bx_shadow_bool_c(bx_param_c *parent,
325       const char *name,
326       const char *label,
327       bool *ptr_to_real_val);
328   bx_shadow_bool_c(bx_param_c *parent,
329       const char *name,
330       bool *ptr_to_real_val);
331   virtual Bit64s get64();
332   virtual void set(Bit64s val);
333 };
334 
335 
336 class BOCHSAPI bx_param_enum_c : public bx_param_num_c {
337   const char **choices;
338   Bit64u *deps_bitmap;
339   void update_dependents();
340 public:
341   bx_param_enum_c(bx_param_c *parent,
342       const char *name,
343       const char *label,
344       const char *description,
345       const char **choices,
346       Bit64s initial_val,
347       Bit64s value_base = 0);
348   virtual ~bx_param_enum_c();
get_choice(int n)349   const char *get_choice(int n) { return choices[n]; }
get_choices()350   const char **get_choices() { return choices; }
get_selected()351   const char *get_selected() { return choices[val.number - min]; }
352   int find_by_name(const char *s);
353   virtual void set(Bit64s val);
354   bool set_by_name(const char *s);
355   void set_dependent_list(bx_list_c *l, bool enable_all);
356   void set_dependent_bitmap(Bit64s value, Bit64u bitmap);
357   Bit64u get_dependent_bitmap(Bit64s value);
358   virtual void set_enabled(bool enabled);
359   virtual int parse_param(const char *value);
360   virtual void dump_param(FILE *fp);
361   virtual int dump_param(char *buf, int buflen, bool dquotes = false);
362 };
363 
364 typedef const char* (*param_string_event_handler)(class bx_param_string_c *,
365                      bool set, const char *oldval, const char *newval, int maxlen);
366 
367 class BOCHSAPI bx_param_string_c : public bx_param_c {
368 protected:
369   int maxsize;
370   char *val, *initial_val;
371   param_string_event_handler handler;
372   param_enable_handler enable_handler;
373   void update_dependents();
374 public:
375   enum {
376     IS_FILENAME = 1,       // 1=yes it's a filename, 0=not a filename.
377                            // Some guis have a file browser. This
378                            // bit suggests that they use it.
379     SAVE_FILE_DIALOG = 2,  // Use save dialog opposed to open file dialog
380     SELECT_FOLDER_DLG = 4  // Use folder selection dialog
381   } bx_string_opt_bits;
382   bx_param_string_c(bx_param_c *parent,
383       const char *name,
384       const char *label,
385       const char *description,
386       const char *initial_val,
387       int maxsize=-1);
388   virtual ~bx_param_string_c();
389   virtual void reset();
390   void set_handler(param_string_event_handler handler);
391   void set_enable_handler(param_enable_handler handler);
get_enable_handler()392   param_enable_handler get_enable_handler() { return enable_handler; }
393   virtual void set_enabled(bool enabled);
394   void set_dependent_list(bx_list_c *l);
395   Bit32s get(char *buf, int len);
getptr()396   char *getptr() {return val; }
getptr()397   const char *getptr() const {return val; }
398   void set(const char *buf);
399   bool equals(const char *buf) const;
get_maxsize()400   int get_maxsize() const {return maxsize; }
401   void set_initial_val(const char *buf);
402   bool isempty() const;
403   virtual int parse_param(const char *value);
404   virtual void dump_param(FILE *fp);
405   virtual int dump_param(char *buf, int buflen, bool dquotes = false);
406 };
407 
408 class BOCHSAPI bx_param_bytestring_c : public bx_param_string_c {
409   char separator;
410 public:
bx_param_bytestring_c(bx_param_c * parent,const char * name,const char * label,const char * description,const char * initial_val,int maxsize)411   bx_param_bytestring_c(bx_param_c *parent,
412       const char *name,
413       const char *label,
414       const char *description,
415       const char *initial_val,
416       int maxsize) : bx_param_string_c(parent, name, label, description, initial_val, maxsize)
417   {
418     set_type(BXT_PARAM_BYTESTRING);
419   }
420 
set_separator(char sep)421   void set_separator(char sep) {separator = sep; }
get_separator()422   char get_separator() const {return separator; }
423 
424   Bit32s get(char *buf, int len);
425   void set(const char *buf);
426   bool equals(const char *buf) const;
427   void set_initial_val(const char *buf);
428   bool isempty() const;
429 
430   virtual int parse_param(const char *value);
431   virtual int dump_param(char *buf, int buflen, bool dquotes = false);
432 };
433 
434 // Declare a filename class.  It is identical to a string, except that
435 // it initializes the options differently.  This is just a shortcut
436 // for declaring a string param and setting the options with IS_FILENAME.
437 class BOCHSAPI bx_param_filename_c : public bx_param_string_c {
438 const char *ext;
439 public:
440   bx_param_filename_c(bx_param_c *parent,
441       const char *name,
442       const char *label,
443       const char *description,
444       const char *initial_val,
445       int maxsize=-1);
get_extension()446   const char *get_extension() const {return ext;}
set_extension(const char * newext)447   void set_extension(const char *newext) {ext = newext;}
448 };
449 
450 class BOCHSAPI bx_shadow_data_c : public bx_param_c {
451   Bit32u data_size;
452   Bit8u *data_ptr;
453   bool is_text;
454 public:
455   bx_shadow_data_c(bx_param_c *parent,
456       const char *name,
457       Bit8u *ptr_to_data,
458       Bit32u data_size, bool is_text=0);
getptr()459   Bit8u *getptr() {return data_ptr;}
getptr()460   const Bit8u *getptr() const {return data_ptr;}
get_size()461   Bit32u get_size() const {return data_size;}
is_text_format()462   bool is_text_format() const {return is_text;}
463   Bit8u get(Bit32u index);
464   void set(Bit32u index, Bit8u value);
465 };
466 
467 typedef void (*filedata_save_handler)(void *devptr, FILE *save_fp);
468 typedef void (*filedata_restore_handler)(void *devptr, FILE *save_fp);
469 
470 class BOCHSAPI bx_shadow_filedata_c : public bx_param_c {
471 protected:
472   FILE **scratch_fpp;       // Point to scratch file used for backing store
473   void *sr_devptr;
474   filedata_save_handler    save_handler;
475   filedata_restore_handler restore_handler;
476 
477 public:
478   bx_shadow_filedata_c(bx_param_c *parent,
479       const char *name, FILE **scratch_file_ptr_ptr);
480   void set_sr_handlers(void *devptr, filedata_save_handler save, filedata_restore_handler restore);
get_fpp()481   FILE **get_fpp() {return scratch_fpp;}
482   void save(FILE *save_file);
483   void restore(FILE *save_file);
484 };
485 
486 typedef struct _bx_listitem_t {
487   bx_param_c *param;
488   struct _bx_listitem_t *next;
489 } bx_listitem_t;
490 
491 typedef void (*list_restore_handler)(void *devptr, class bx_list_c *);
492 
493 class BOCHSAPI bx_list_c : public bx_param_c {
494 protected:
495   // chained list of bx_listitem_t
496   bx_listitem_t *list;
497   int size;
498   // for a menu, the value of choice before the call to "ask" is default.
499   // After ask, choice holds the value that the user chose. Choice defaults
500   // to 1 in the constructor.
501   Bit32u choice; // type Bit32u is compatible with ask_uint
502   // title of the menu or series
503   char *title;
504   void init(const char *list_title);
505   // save / restore support
506   void *sr_devptr;
507   list_restore_handler restore_handler;
508 public:
509   enum {
510     // When a bx_list_c is displayed as a menu, SHOW_PARENT controls whether or
511     // not the menu shows a "Return to parent menu" choice or not.
512     SHOW_PARENT = (1<<0),
513     // Some lists are best displayed shown as menus, others as a series of
514     // related questions.  This bit suggests to the CI that the series of
515     // questions format is preferred.
516     SERIES_ASK = (1<<1),
517     // When a bx_list_c is displayed in a dialog, USE_TAB_WINDOW suggests
518     // to the CI that each item in the list should be shown as a separate
519     // tab.  This would be most appropriate when each item is another list
520     // of parameters.
521     USE_TAB_WINDOW = (1<<2),
522     // When a bx_list_c is displayed in a dialog, the list name is used as the
523     // label of the group box if USE_BOX_TITLE is set. This is only necessary if
524     // more than one list appears in a dialog box.
525     USE_BOX_TITLE = (1<<3),
526     // When a bx_list_c is displayed as a menu, SHOW_GROUP_NAME controls whether
527     // or not the name of group the item belongs to is added to the name of the
528     // item (used in the runtime menu).
529     SHOW_GROUP_NAME = (1<<4),
530     // When a bx_list_c is displayed in a dialog, USE_SCROLL_WINDOW suggests
531     // to the CI that the list items should be displayed in a scrollable dialog
532     // window. Large lists can make the dialog unusable and using this flag
533     // can force the CI to limit the dialog height with all items accessible.
534     USE_SCROLL_WINDOW = (1<<5)
535   } bx_listopt_bits;
536   bx_list_c(bx_param_c *parent);
537   bx_list_c(bx_param_c *parent, const char *name);
538   bx_list_c(bx_param_c *parent, const char *name, const char *title);
539   bx_list_c(bx_param_c *parent, const char *name, const char *title, bx_param_c **init_list);
540   virtual ~bx_list_c();
541   bx_list_c *clone();
542   void add(bx_param_c *param);
543   bx_param_c *get(int index);
544   bx_param_c *get_by_name(const char *name);
get_size()545   int get_size() const { return size; }
get_choice()546   Bit32u get_choice() const { return choice; }
set_choice(Bit32u new_choice)547   void set_choice(Bit32u new_choice) { choice = new_choice; }
get_title()548   char *get_title() { return title; }
549   void set_parent(bx_param_c *newparent);
get_parent()550   bx_param_c *get_parent() { return parent; }
551   virtual void reset();
552   virtual void clear();
553   virtual void remove(const char *name);
554   virtual void set_runtime_param(bool val);
555   void set_restore_handler(void *devptr, list_restore_handler restore);
556   void restore();
557 };
558 
559 #endif
560