1 /////////////////////////////////////////////////////////////////////////
2 // $Id: siminterface.cc,v 1.175 2007/08/01 17:09:51 vruppert Exp $
3 /////////////////////////////////////////////////////////////////////////
5 // See siminterface.h for description of the siminterface concept.
6 // Basically, the siminterface is visible from both the simulator and
7 // the configuration user interface, and allows them to talk to each other.
12 bx_simulator_interface_c
*SIM
= NULL
;
13 logfunctions
*siminterface_log
= NULL
;
14 bx_list_c
*root_param
= NULL
;
15 #define LOG_THIS siminterface_log->
17 #define BX_MAX_USER_OPTIONS 16
19 // bx_simulator_interface just defines the interface that the Bochs simulator
20 // and the gui will use to talk to each other. None of the methods of
21 // bx_simulator_interface are implemented; they are all virtual. The
22 // bx_real_sim_c class is a child of bx_simulator_interface_c, and it
23 // implements all the methods. The idea is that a gui needs to know only
24 // definition of bx_simulator_interface to talk to Bochs. The gui should
25 // not need to include bochs.h.
27 // I made this separation to ensure that all guis use the siminterface to do
28 // access bochs internals, instead of accessing things like
29 // bx_keyboard.s.internal_buffer[4] (or whatever) directly. -Bryce
32 class bx_real_sim_c
: public bx_simulator_interface_c
{
33 bxevent_handler bxevent_callback
;
34 void *bxevent_callback_data
;
35 const char *registered_ci_name
;
36 config_interface_callback_t ci_callback
;
37 void *ci_callback_data
;
39 user_option_parser_t user_option_parser
[BX_MAX_USER_OPTIONS
];
40 user_option_save_t user_option_save
[BX_MAX_USER_OPTIONS
];
41 const char *user_option_name
[BX_MAX_USER_OPTIONS
];
44 // save context to jump to if we must quit unexpectedly
45 jmp_buf *quit_context
;
50 virtual ~bx_real_sim_c() {}
51 virtual void set_quit_context(jmp_buf *context
) { quit_context
= context
; }
52 virtual int get_init_done() { return init_done
; }
53 virtual int set_init_done(int n
) { init_done
= n
; return 0;}
54 virtual void reset_all_param();
56 virtual bx_param_c
*get_param(const char *pname
, bx_param_c
*base
=NULL
);
57 virtual bx_param_num_c
*get_param_num(const char *pname
, bx_param_c
*base
=NULL
);
58 virtual bx_param_string_c
*get_param_string(const char *pname
, bx_param_c
*base
=NULL
);
59 virtual bx_param_bool_c
*get_param_bool(const char *pname
, bx_param_c
*base
=NULL
);
60 virtual bx_param_enum_c
*get_param_enum(const char *pname
, bx_param_c
*base
=NULL
);
61 virtual Bit32u
gen_param_id();
62 virtual int get_n_log_modules();
63 virtual char *get_prefix(int mod
);
64 virtual int get_log_action(int mod
, int level
);
65 virtual void set_log_action(int mod
, int level
, int action
);
66 virtual char *get_action_name(int action
);
67 virtual int get_default_log_action(int level
) {
68 return logfunctions::get_default_action(level
);
70 virtual void set_default_log_action(int level
, int action
) {
71 logfunctions::set_default_action(level
, action
);
73 virtual const char *get_log_level_name(int level
);
74 virtual int get_max_log_level();
75 virtual void quit_sim(int code
);
76 virtual int get_exit_code() { return exit_code
; }
77 virtual int get_default_rc(char *path
, int len
);
78 virtual int read_rc(const char *path
);
79 virtual int write_rc(const char *path
, int overwrite
);
80 virtual int get_log_file(char *path
, int len
);
81 virtual int set_log_file(char *path
);
82 virtual int get_log_prefix(char *prefix
, int len
);
83 virtual int set_log_prefix(char *prefix
);
84 virtual int get_debugger_log_file(char *path
, int len
);
85 virtual int set_debugger_log_file(char *path
);
86 virtual int get_cdrom_options(int drive
, bx_list_c
**out
, int *device
= NULL
);
87 virtual void set_notify_callback(bxevent_handler func
, void *arg
);
88 virtual void get_notify_callback(bxevent_handler
*func
, void **arg
);
89 virtual BxEvent
* sim_to_ci_event(BxEvent
*event
);
90 virtual int log_msg(const char *prefix
, int level
, const char *msg
);
91 virtual int ask_param(bx_param_c
*param
);
92 virtual int ask_param(const char *pname
);
93 // ask the user for a pathname
94 virtual int ask_filename(char *filename
, int maxlen
, char *prompt
, char *the_default
, int flags
);
96 virtual int ask_yes_no(char *title
, char *prompt
, bx_bool the_default
);
97 // called at a regular interval, currently by the keyboard handler.
98 virtual void periodic ();
99 virtual int create_disk_image (const char *filename
, int sectors
, bx_bool overwrite
);
100 virtual void refresh_ci ();
101 virtual void refresh_vga () {
102 // maybe need to check if something has been initialized yet?
105 virtual void handle_events () {
106 // maybe need to check if something has been initialized yet?
107 bx_gui
->handle_events ();
109 // find first hard drive or cdrom
110 bx_param_c
*get_first_atadevice(Bit32u search_type
);
111 bx_param_c
*get_first_cdrom() {
112 return get_first_atadevice(BX_ATA_DEVICE_CDROM
);
114 bx_param_c
*get_first_hd() {
115 return get_first_atadevice(BX_ATA_DEVICE_DISK
);
118 virtual void debug_break ();
119 virtual void debug_interpret_cmd (char *cmd
);
120 virtual char *debug_get_next_command ();
121 virtual void debug_puts (const char *cmd
);
123 virtual void register_configuration_interface (
125 config_interface_callback_t callback
,
127 virtual int configuration_interface(const char* name
, ci_command_t command
);
128 virtual int begin_simulation (int argc
, char *argv
[]);
129 virtual void set_sim_thread_func(is_sim_thread_func_t func
) {}
130 virtual bx_bool
is_sim_thread();
132 virtual void set_debug_gui(bx_bool val
) { debug_gui
= val
; }
133 virtual bx_bool
has_debug_gui() { return debug_gui
; }
134 // provide interface to bx_gui->set_display_mode() method for config
135 // interfaces to use.
136 virtual void set_display_mode(disp_mode_t newmode
) {
138 bx_gui
->set_display_mode(newmode
);
140 virtual bx_bool
test_for_text_console();
141 // user-defined option support
142 virtual int find_user_option(const char *keyword
);
143 virtual bx_bool
register_user_option(const char *keyword
, user_option_parser_t parser
, user_option_save_t save_func
);
144 virtual Bit32s
parse_user_option(int idx
, const char *context
, int num_params
, char *params
[]);
145 virtual Bit32s
save_user_options(FILE *fp
);
146 #if BX_SUPPORT_SAVE_RESTORE
147 // save/restore support
148 virtual void init_save_restore();
149 virtual bx_bool
save_state(const char *checkpoint_path
);
150 virtual bx_bool
restore_config();
151 virtual bx_bool
restore_logopts();
152 virtual bx_bool
restore_hardware();
153 virtual bx_list_c
*get_sr_root() {
154 return (bx_list_c
*)get_param("save_restore", NULL
);
157 void save_sr_param(FILE *fp
, bx_param_c
*node
, const char *sr_path
, int level
);
161 // recursive function to find parameters from the path
162 static bx_param_c
*find_param(const char *full_pname
, const char *rest_of_pname
, bx_param_c
*base
)
164 const char *from
= rest_of_pname
;
165 char component
[BX_PATHNAME_LEN
];
166 char *to
= component
;
167 // copy the first piece of pname into component, stopping at first separator
168 // or at the end of the string
169 while (*from
!= 0 && *from
!= '.') {
176 BX_PANIC (("find_param: found empty component in parameter name '%s'", full_pname
));
177 // or does that mean that we're done?
179 if (base
->get_type() != BXT_LIST
) {
180 BX_PANIC (("find_param: base was not a list!"));
182 BX_DEBUG(("searching for component '%s' in list '%s'", component
, base
->get_name()));
184 // find the component in the list.
185 bx_list_c
*list
= (bx_list_c
*)base
;
186 bx_param_c
*child
= list
->get_by_name(component
);
187 // if child not found, there is nothing else that can be done. return NULL.
188 if (child
== NULL
) return NULL
;
190 // that was the end of the path, we're done
193 // continue parsing the path
194 BX_ASSERT(from
[0] == '.');
195 from
++; // skip over the separator
196 return find_param(full_pname
, from
, child
);
199 bx_param_c
*bx_real_sim_c::get_param(const char *pname
, bx_param_c
*base
)
203 // to access top level object, look for parameter "."
204 if (pname
[0] == '.' && pname
[1] == 0)
206 return find_param(pname
, pname
, base
);
209 bx_param_num_c
*bx_real_sim_c::get_param_num (const char *pname
, bx_param_c
*base
)
211 bx_param_c
*generic
= get_param(pname
, base
);
213 BX_PANIC(("get_param_num(%s) could not find a parameter", pname
));
216 int type
= generic
->get_type();
217 if (type
== BXT_PARAM_NUM
|| type
== BXT_PARAM_BOOL
|| type
== BXT_PARAM_ENUM
)
218 return (bx_param_num_c
*)generic
;
219 BX_PANIC(("get_param_num(%s) could not find an integer parameter with that name", pname
));
223 bx_param_string_c
*bx_real_sim_c::get_param_string(const char *pname
, bx_param_c
*base
)
225 bx_param_c
*generic
= get_param(pname
, base
);
227 BX_PANIC (("get_param_string(%s) could not find a parameter", pname
));
230 if (generic
->get_type() == BXT_PARAM_STRING
)
231 return (bx_param_string_c
*)generic
;
232 BX_PANIC(("get_param_string(%s) could not find an integer parameter with that name", pname
));
236 bx_param_bool_c
*bx_real_sim_c::get_param_bool(const char *pname
, bx_param_c
*base
)
238 bx_param_c
*generic
= get_param(pname
, base
);
240 BX_PANIC(("get_param_bool(%s) could not find a parameter", pname
));
243 if (generic
->get_type () == BXT_PARAM_BOOL
)
244 return (bx_param_bool_c
*)generic
;
245 BX_PANIC(("get_param_bool(%s) could not find a bool parameter with that name", pname
));
249 bx_param_enum_c
*bx_real_sim_c::get_param_enum(const char *pname
, bx_param_c
*base
)
251 bx_param_c
*generic
= get_param(pname
, base
);
253 BX_PANIC(("get_param_enum(%s) could not find a parameter", pname
));
256 if (generic
->get_type() == BXT_PARAM_ENUM
)
257 return (bx_param_enum_c
*)generic
;
258 BX_PANIC(("get_param_enum(%s) could not find a enum parameter with that name", pname
));
262 Bit32u
bx_real_sim_c::gen_param_id()
267 void bx_init_siminterface()
269 siminterface_log
= new logfunctions();
270 siminterface_log
->put("CTRL");
271 siminterface_log
->settype(CTRLLOG
);
273 SIM
= new bx_real_sim_c();
274 if (root_param
== NULL
) {
275 root_param
= new bx_list_c(NULL
,
277 "list of top level bochs parameters",
282 bx_real_sim_c::bx_real_sim_c()
284 bxevent_callback
= NULL
;
285 bxevent_callback_data
= NULL
;
287 ci_callback_data
= NULL
;
288 is_sim_thread_func
= NULL
;
295 param_id
= BXP_NEW_PARAM_ID
;
299 void bx_real_sim_c::reset_all_param()
304 int bx_real_sim_c::get_n_log_modules()
306 return io
->get_n_logfns();
309 char *bx_real_sim_c::get_prefix(int mod
)
311 logfunc_t
*logfn
= io
->get_logfn(mod
);
312 return logfn
->getprefix();
315 int bx_real_sim_c::get_log_action(int mod
, int level
)
317 logfunc_t
*logfn
= io
->get_logfn(mod
);
318 return logfn
->getonoff(level
);
321 void bx_real_sim_c::set_log_action(int mod
, int level
, int action
)
325 logfunc_t
*logfn
= io
->get_logfn(mod
);
326 logfn
->setonoff(level
, action
);
329 // if called with mod<0 loop over all
330 int nmod
= get_n_log_modules ();
331 for (mod
=0; mod
<nmod
; mod
++)
332 set_log_action(mod
, level
, action
);
335 char *bx_real_sim_c::get_action_name(int action
)
337 return io
->getaction(action
);
340 const char *bx_real_sim_c::get_log_level_name(int level
)
342 return io
->getlevel(level
);
345 int bx_real_sim_c::get_max_log_level()
350 void bx_real_sim_c::quit_sim(int code
) {
351 BX_INFO(("quit_sim called with exit code %d", code
));
354 // use longjmp to quit cleanly, no matter where in the stack we are.
355 if (quit_context
!= NULL
) {
356 longjmp(*quit_context
, 1);
357 BX_PANIC(("in bx_real_sim_c::quit_sim, longjmp should never return"));
359 // use exit() to stop the application.
361 BX_PANIC(("Quit simulation command"));
366 int bx_real_sim_c::get_default_rc(char *path
, int len
)
368 char *rc
= bx_find_bochsrc();
369 if (rc
== NULL
) return -1;
370 strncpy(path
, rc
, len
);
375 int bx_real_sim_c::read_rc(const char *rc
)
377 return bx_read_configuration(rc
);
383 // -2: already exists, and overwrite was off
384 int bx_real_sim_c::write_rc(const char *rc
, int overwrite
)
386 return bx_write_configuration(rc
, overwrite
);
389 int bx_real_sim_c::get_log_file(char *path
, int len
)
391 strncpy(path
, SIM
->get_param_string(BXPN_LOG_FILENAME
)->getptr(), len
);
395 int bx_real_sim_c::set_log_file(char *path
)
397 SIM
->get_param_string(BXPN_LOG_FILENAME
)->set(path
);
401 int bx_real_sim_c::get_log_prefix(char *prefix
, int len
)
403 strncpy(prefix
, SIM
->get_param_string(BXPN_LOG_PREFIX
)->getptr(), len
);
407 int bx_real_sim_c::set_log_prefix(char *prefix
)
409 SIM
->get_param_string(BXPN_LOG_PREFIX
)->set(prefix
);
413 int bx_real_sim_c::get_debugger_log_file(char *path
, int len
)
415 strncpy(path
, SIM
->get_param_string(BXPN_DEBUGGER_LOG_FILENAME
)->getptr(), len
);
419 int bx_real_sim_c::set_debugger_log_file(char *path
)
421 SIM
->get_param_string(BXPN_DEBUGGER_LOG_FILENAME
)->set(path
);
425 int bx_real_sim_c::get_cdrom_options(int level
, bx_list_c
**out
, int *where
)
430 for (Bit8u channel
=0; channel
<BX_MAX_ATA_CHANNEL
; channel
++) {
431 for (Bit8u device
=0; device
<2; device
++) {
432 sprintf(pname
, "ata.%d.%s", channel
, (device
==0)?"master":"slave");
433 devlist
= (bx_list_c
*) SIM
->get_param(pname
);
434 if (SIM
->get_param_enum("type", devlist
)->get() == BX_ATA_DEVICE_CDROM
) {
437 if (where
!= NULL
) *where
= (channel
* 2) + device
;
448 char *bochs_start_names
[] = { "quick", "load", "edit", "run" };
450 char *floppy_type_names
[] = { "none", "1.2M", "1.44M", "2.88M", "720K", "360K", "160K", "180K", "320K", "auto", NULL
};
451 int floppy_type_n_sectors
[] = { -1, 80*2*15, 80*2*18, 80*2*36, 80*2*9, 40*2*9, 40*1*8, 40*1*9, 40*2*8, -1 };
452 char *floppy_status_names
[] = { "ejected", "inserted", NULL
};
454 char *bochs_bootdisk_names
[] = { "none", "floppy", "disk","cdrom", "network", NULL
};
455 char *loader_os_names
[] = { "none", "linux", "nullkernel", NULL
};
456 char *keyboard_type_names
[] = { "xt", "at", "mf", NULL
};
458 char *atadevice_type_names
[] = { "disk", "cdrom", NULL
};
459 //char *atadevice_mode_names[] = { "flat", "concat", "external", "dll", "sparse", "vmware3", "vmware4", "undoable", "growing", "volatile", "z-undoable", "z-volatile", NULL };
460 char *atadevice_mode_names
[] = { "flat", "concat", "external", "dll", "sparse", "vmware3", "vmware4", "undoable", "growing", "volatile", NULL
};
461 char *atadevice_status_names
[] = { "ejected", "inserted", NULL
};
462 char *atadevice_biosdetect_names
[] = { "none", "auto", "cmos", NULL
};
463 char *atadevice_translation_names
[] = { "none", "lba", "large", "rechs", "auto", NULL
};
464 char *clock_sync_names
[] = { "none", "realtime", "slowdown", "both", NULL
};
467 void bx_real_sim_c::set_notify_callback(bxevent_handler func
, void *arg
)
469 bxevent_callback
= func
;
470 bxevent_callback_data
= arg
;
473 void bx_real_sim_c::get_notify_callback(
474 bxevent_handler
*func
,
477 *func
= bxevent_callback
;
478 *arg
= bxevent_callback_data
;
481 BxEvent
*bx_real_sim_c::sim_to_ci_event(BxEvent
*event
)
483 if (bxevent_callback
== NULL
) {
484 BX_ERROR(("notify called, but no bxevent_callback function is registered"));
487 return (*bxevent_callback
)(bxevent_callback_data
, event
);
491 // returns 0 for continue, 1 for alwayscontinue, 2 for die.
492 int bx_real_sim_c::log_msg(const char *prefix
, int level
, const char *msg
)
495 be
.type
= BX_SYNC_EVT_LOG_ASK
;
496 be
.u
.logmsg
.prefix
= prefix
;
497 be
.u
.logmsg
.level
= level
;
498 be
.u
.logmsg
.msg
= msg
;
499 // default return value in case something goes wrong.
500 be
.retcode
= BX_LOG_NOTIFY_FAILED
;
502 sim_to_ci_event (&be
);
506 // Called by simulator whenever it needs the user to choose a new value
507 // for a registered parameter. Create a synchronous ASK_PARAM event,
508 // send it to the CI, and wait for the response. The CI will call the
509 // set() method on the parameter if the user changes the value.
510 int bx_real_sim_c::ask_param(bx_param_c
*param
)
512 BX_ASSERT(param
!= NULL
);
513 // create appropriate event
515 event
.type
= BX_SYNC_EVT_ASK_PARAM
;
516 event
.u
.param
.param
= param
;
517 sim_to_ci_event(&event
);
518 return event
.retcode
;
521 int bx_real_sim_c::ask_param(const char *pname
)
523 bx_param_c
*paramptr
= SIM
->get_param(pname
);
524 BX_ASSERT(paramptr
!= NULL
);
525 // create appropriate event
527 event
.type
= BX_SYNC_EVT_ASK_PARAM
;
528 event
.u
.param
.param
= paramptr
;
529 sim_to_ci_event(&event
);
530 return event
.retcode
;
533 int bx_real_sim_c::ask_filename(char *filename
, int maxlen
, char *prompt
, char *the_default
, int flags
)
536 bx_param_string_c
param(NULL
, "filename", prompt
, "", the_default
, maxlen
);
537 flags
|= param
.IS_FILENAME
;
538 param
.get_options()->set(flags
);
539 event
.type
= BX_SYNC_EVT_ASK_PARAM
;
540 event
.u
.param
.param
= ¶m
;
541 sim_to_ci_event(&event
);
542 if (event
.retcode
>= 0)
543 memcpy(filename
, param
.getptr(), maxlen
);
544 return event
.retcode
;
547 int bx_real_sim_c::ask_yes_no(char *title
, char *prompt
, bx_bool the_default
)
552 bx_param_bool_c
param(NULL
, "yes_no", title
, prompt
, the_default
);
553 sprintf(format
, "%s\n\n%s [%%s] ", title
, prompt
);
554 param
.set_ask_format(format
);
555 event
.type
= BX_SYNC_EVT_ASK_PARAM
;
556 event
.u
.param
.param
= ¶m
;
557 sim_to_ci_event(&event
);
558 if (event
.retcode
>= 0) {
561 return event
.retcode
;
565 void bx_real_sim_c::periodic()
567 // give the GUI a chance to do periodic things on the bochs thread. in
568 // particular, notice if the thread has been asked to die.
570 tick
.type
= BX_SYNC_EVT_TICK
;
571 sim_to_ci_event (&tick
);
572 if (tick
.retcode
< 0) {
573 BX_INFO(("Bochs thread has been asked to quit."));
581 static int refresh_counter
= 0;
582 if (++refresh_counter
== 50) {
583 // only ask the CI to refresh every 50 times periodic() is called.
584 // This should obviously be configurable because system speeds and
585 // user preferences vary.
591 // create a disk image file called filename, size=512 bytes * sectors.
592 // If overwrite is 0 and the file exists, returns -1 without changing it.
593 // Otherwise, opens up the image and starts writing. Returns -2 if
594 // the image could not be opened, or -3 if there are failures during
595 // write, e.g. disk full.
597 // wxWidgets: This may be called from the gui thread.
598 int bx_real_sim_c::create_disk_image(
599 const char *filename
,
605 // check for existence first
606 fp
= fopen(filename
, "r");
613 fp
= fopen(filename
, "w");
617 sprintf(buffer
, "while opening '%s' for writing", filename
);
619 // not sure how to get this back into the CI
625 * seek to sec*512-1 and write a single character.
626 * can't just do: fseek(fp, 512*sec-1, SEEK_SET)
627 * because 512*sec may be too large for signed int.
631 /* temp <-- min(sec, 4194303)
632 * 4194303 is (int)(0x7FFFFFFF/512)
634 int temp
= ((sec
< 4194303) ? sec
: 4194303);
635 fseek(fp
, 512*temp
, SEEK_CUR
);
639 fseek(fp
, -1, SEEK_CUR
);
640 if (fputc('\0', fp
) == EOF
)
649 void bx_real_sim_c::refresh_ci() {
650 if (SIM
->has_debug_gui()) {
651 // presently, only wxWidgets interface uses these events
652 // It's an async event, so allocate a pointer and send it.
653 // The event will be freed by the recipient.
654 BxEvent
*event
= new BxEvent();
655 event
->type
= BX_ASYNC_EVT_REFRESH
;
656 sim_to_ci_event(event
);
660 bx_param_c
*bx_real_sim_c::get_first_atadevice(Bit32u search_type
) {
662 for (int channel
=0; channel
<BX_MAX_ATA_CHANNEL
; channel
++) {
663 sprintf(pname
, "ata.%d.resources.enabled", channel
);
664 if (!SIM
->get_param_bool(pname
)->get())
666 for (int slave
=0; slave
<2; slave
++) {
667 sprintf(pname
, "ata.%d.%s.present", channel
, (slave
==0)?"master":"slave");
668 Bit32u present
= SIM
->get_param_bool(pname
)->get();
669 sprintf(pname
, "ata.%d.%s.type", channel
, (slave
==0)?"master":"slave");
670 Bit32u type
= SIM
->get_param_enum(pname
)->get();
671 if (present
&& (type
== search_type
)) {
672 sprintf(pname
, "ata.%d.%s", channel
, (slave
==0)?"master":"slave");
673 return SIM
->get_param(pname
);
682 // this can be safely called from either thread.
683 void bx_real_sim_c::debug_break()
688 // this should only be called from the sim_thread.
689 void bx_real_sim_c::debug_interpret_cmd(char *cmd
)
691 if (!is_sim_thread()) {
692 fprintf(stderr
, "ERROR: debug_interpret_cmd called but not from sim_thread\n");
695 bx_dbg_interpret_line(cmd
);
698 char *bx_real_sim_c::debug_get_next_command()
701 event
.type
= BX_SYNC_EVT_GET_DBG_COMMAND
;
702 BX_DEBUG(("asking for next debug command"));
703 sim_to_ci_event (&event
);
704 BX_DEBUG(("received next debug command: '%s'", event
.u
.debugcmd
.command
));
705 if (event
.retcode
>= 0)
706 return event
.u
.debugcmd
.command
;
710 void bx_real_sim_c::debug_puts(const char *text
)
712 if (SIM
->has_debug_gui()) {
713 // send message to the wxWidgets debugger
714 BxEvent
*event
= new BxEvent();
715 event
->type
= BX_ASYNC_EVT_DBG_MSG
;
716 event
->u
.logmsg
.msg
= text
;
717 sim_to_ci_event(event
);
718 // the event will be freed by the recipient
720 // text mode debugger: just write to console
722 delete [] (char *)text
;
727 void bx_real_sim_c::register_configuration_interface(
729 config_interface_callback_t callback
,
732 ci_callback
= callback
;
733 ci_callback_data
= userdata
;
734 registered_ci_name
= name
;
737 int bx_real_sim_c::configuration_interface(const char *ignore
, ci_command_t command
)
739 bx_param_enum_c
*ci_param
= SIM
->get_param_enum(BXPN_SEL_CONFIG_INTERFACE
);
740 char *name
= ci_param
->get_selected();
742 BX_PANIC(("no configuration interface was loaded"));
745 if (strcmp(name
, registered_ci_name
) != 0) {
746 BX_PANIC(("siminterface does not support loading one configuration interface and then calling another"));
749 if (!strcmp(name
, "wx"))
753 // enter configuration mode, just while running the configuration interface
754 set_display_mode(DISP_MODE_CONFIG
);
755 int retval
= (*ci_callback
)(ci_callback_data
, command
);
756 set_display_mode(DISP_MODE_SIM
);
760 int bx_real_sim_c::begin_simulation(int argc
, char *argv
[])
762 return bx_begin_simulation(argc
, argv
);
765 bx_bool
bx_real_sim_c::is_sim_thread()
767 if (is_sim_thread_func
== NULL
) return 1;
768 return (*is_sim_thread_func
)();
771 // check if the text console exists. On some platforms, if Bochs is
772 // started from the "Start Menu" or by double clicking on it on a Mac,
773 // there may be nothing attached to stdin/stdout/stderr. This function
774 // tests if stdin/stdout/stderr are usable and returns 0 if not.
775 bx_bool
bx_real_sim_c::test_for_text_console()
778 // In a Carbon application, you have a text console if you run the app from
779 // the command line, but if you start it from the finder you don't.
780 if(!isatty(STDIN_FILENO
)) return 0;
786 int bx_real_sim_c::find_user_option(const char *keyword
)
789 while (i
< n_user_options
) {
790 if (!strcmp(keyword
, user_option_name
[i
])) {
798 bx_bool
bx_real_sim_c::register_user_option(const char *keyword
, user_option_parser_t parser
,
799 user_option_save_t save_func
)
803 if (n_user_options
>= BX_MAX_USER_OPTIONS
) {
806 idx
= find_user_option(keyword
);
808 if (parser
== user_option_parser
[idx
]) {
809 // parse handler already registered
812 // keyword already exists
816 user_option_name
[n_user_options
] = keyword
;
817 user_option_parser
[n_user_options
] = parser
;
818 user_option_save
[n_user_options
++] = save_func
;
823 Bit32s
bx_real_sim_c::parse_user_option(int idx
, const char *context
, int num_params
, char *params
[])
825 if ((idx
< 0) || (idx
>= n_user_options
)) {
828 return (*user_option_parser
[idx
])(context
, num_params
, params
);
831 Bit32s
bx_real_sim_c::save_user_options(FILE *fp
)
833 for (int i
= 0; i
< n_user_options
; i
++) {
834 if (user_option_save
[i
] != NULL
) {
835 (*user_option_save
[i
])(fp
);
841 #if BX_SUPPORT_SAVE_RESTORE
842 void bx_real_sim_c::init_save_restore()
846 if ((list
= get_sr_root()) != NULL
) {
849 list
= new bx_list_c(root_param
,
851 "subtree for save/restore",
857 BX_MAX_SMP_THREADS_SUPPORTED
);
860 bx_bool
bx_real_sim_c::save_state(const char *checkpoint_path
)
862 char sr_file
[BX_PATHNAME_LEN
];
864 int i
, dev
, ndev
= SIM
->get_n_log_modules();
865 int type
, ntype
= SIM
->get_max_log_level();
868 sprintf(sr_file
, "%s/config", checkpoint_path
);
869 if (write_rc(sr_file
, 1) < 0)
871 sprintf(sr_file
, "%s/logopts", checkpoint_path
);
872 fp
= fopen(sr_file
, "w");
874 for (dev
=0; dev
<ndev
; dev
++) {
875 strcpy(prefix
, get_prefix(dev
));
876 strcpy(prefix
, prefix
+1);
877 prefix
[strlen(prefix
) - 1] = 0;
878 i
= strlen(prefix
) - 1;
879 while ((i
>= 0) && (prefix
[i
] == ' ')) prefix
[i
--] = 0;
880 if (strlen(prefix
) > 0) {
881 fprintf(fp
, "%s: ", prefix
);
882 for (type
=0; type
<ntype
; type
++) {
883 if (type
> 0) fprintf(fp
, ", ");
884 fprintf(fp
, "%s=%s", get_log_level_name(type
), get_action_name(get_log_action(dev
, type
)));
893 bx_list_c
*sr_list
= get_sr_root();
894 ndev
= sr_list
->get_size();
895 for (dev
=0; dev
<ndev
; dev
++) {
896 sprintf(sr_file
, "%s/%s", checkpoint_path
, sr_list
->get(dev
)->get_name());
897 fp
= fopen(sr_file
, "w");
899 save_sr_param(fp
, sr_list
->get(dev
), checkpoint_path
, 0);
908 bx_bool
bx_real_sim_c::restore_config()
910 char config
[BX_PATHNAME_LEN
];
912 sprintf(config
, "%s/config", get_param_string(BXPN_RESTORE_PATH
)->getptr());
913 BX_INFO(("restoring '%s'", config
));
914 return (read_rc(config
) >= 0);
917 bx_bool
bx_real_sim_c::restore_logopts()
919 char logopts
[BX_PATHNAME_LEN
];
920 char line
[512], string
[512], prefix
[8];
922 int d
, i
, j
, dev
= 0, type
= 0, action
= 0;
923 int ndev
= SIM
->get_n_log_modules();
926 sprintf(logopts
, "%s/logopts", get_param_string(BXPN_RESTORE_PATH
)->getptr());
927 BX_INFO(("restoring '%s'", logopts
));
928 fp
= fopen(logopts
, "r");
931 ret
= fgets(line
, sizeof(line
)-1, fp
);
932 line
[sizeof(line
) - 1] = '\0';
933 int len
= strlen(line
);
934 if ((len
>0) && (line
[len
-1] < ' '))
937 if ((ret
!= NULL
) && strlen(line
)) {
938 ptr
= strtok(line
, ":");
941 while (isspace(string
[0])) strcpy(string
, string
+1);
942 while (isspace(string
[strlen(string
)-1])) string
[strlen(string
)-1] = 0;
944 sprintf(prefix
, "[%-5s]", string
);
946 for (d
= 0; d
< ndev
; d
++) {
947 if (!strcmp(prefix
, get_prefix(d
))) {
951 } else if (dev
>= 0) {
953 if (!strncmp(string
, "DEBUG=", 6)) {
955 } else if (!strncmp(string
, "INFO=", 5)) {
958 } else if (!strncmp(string
, "ERROR=", 6)) {
960 } else if (!strncmp(string
, "PANIC=", 6)) {
962 } else if (!strncmp(string
, "PASS=", 5)) {
966 if (!strcmp(string
+j
, "ignore")) {
968 } else if (!strcmp(string
+j
, "report")) {
970 } else if (!strcmp(string
+j
, "ask")) {
972 } else if (!strcmp(string
+j
, "fatal")) {
975 set_log_action(dev
, type
, action
);
978 BX_ERROR(("restore_logopts(): log module '%s' not found", prefix
));
982 ptr
= strtok(NULL
, ",");
993 bx_bool
bx_real_sim_c::restore_hardware()
995 char devstate
[BX_PATHNAME_LEN
], devdata
[BX_PATHNAME_LEN
];
996 char line
[512], buf
[512], pname
[80];
998 int i
, j
, p
, dev
, ndev
;
1000 bx_param_c
*param
= NULL
;
1004 bx_list_c
*sr_list
= get_sr_root();
1005 ndev
= sr_list
->get_size();
1006 for (dev
=0; dev
<ndev
; dev
++) {
1007 sprintf(devstate
, "%s/%s", get_param_string(BXPN_RESTORE_PATH
)->getptr(), sr_list
->get(dev
)->get_name());
1008 BX_INFO(("restoring '%s'", devstate
));
1010 fp
= fopen(devstate
, "r");
1013 ret
= fgets(line
, sizeof(line
)-1, fp
);
1014 line
[sizeof(line
) - 1] = '\0';
1015 int len
= strlen(line
);
1016 if ((len
>0) && (line
[len
-1] < ' '))
1019 if ((ret
!= NULL
) && strlen(line
)) {
1020 ptr
= strtok(line
, " ");
1023 if (!strcmp(ptr
, "}")) {
1024 base
= (bx_list_c
*)base
->get_parent();
1027 param
= get_param(ptr
, base
);
1029 } else if (i
== 2) {
1030 if (param
->get_type() != BXT_LIST
) {
1031 param
->get_param_path(pname
, 80);
1032 BX_DEBUG(("restoring parameter '%s'", pname
));
1034 switch (param
->get_type()) {
1036 if ((ptr
[0] == '0') && (ptr
[1] == 'x')) {
1037 ((bx_param_num_c
*)param
)->set(strtoull(ptr
, NULL
, 16));
1039 ((bx_param_num_c
*)param
)->set(strtoull(ptr
, NULL
, 10));
1042 case BXT_PARAM_BOOL
:
1043 ((bx_param_bool_c
*)param
)->set(!strcmp(ptr
, "true"));
1045 case BXT_PARAM_ENUM
:
1046 ((bx_param_enum_c
*)param
)->set_by_name(ptr
);
1048 case BXT_PARAM_STRING
:
1049 if (((bx_param_string_c
*)param
)->get_options()->get() & bx_param_string_c::RAW_BYTES
) {
1051 for (j
= 0; j
< ((bx_param_string_c
*)param
)->get_maxsize(); j
++) {
1052 if (ptr
[p
] == ((bx_param_string_c
*)param
)->get_separator()) {
1055 if (sscanf(ptr
+p
, "%02x", &n
) == 1) {
1060 ((bx_param_string_c
*)param
)->set(buf
);
1062 ((bx_param_string_c
*)param
)->set(ptr
);
1065 case BXT_PARAM_DATA
:
1066 sprintf(devdata
, "%s/%s", get_param_string(BXPN_RESTORE_PATH
)->getptr(), ptr
);
1067 fp2
= fopen(devdata
, "rb");
1069 fread(((bx_shadow_data_c
*)param
)->getptr(), 1, ((bx_shadow_data_c
*)param
)->get_size(), fp2
);
1074 base
= (bx_list_c
*)param
;
1077 BX_ERROR(("restore_hardware(): unknown parameter type"));
1081 ptr
= strtok(NULL
, " ");
1084 } while (!feof(fp
));
1093 void bx_real_sim_c::save_sr_param(FILE *fp
, bx_param_c
*node
, const char *sr_path
, int level
)
1097 char tmpstr
[BX_PATHNAME_LEN
], tmpbyte
[4];
1100 for (i
=0; i
<level
; i
++)
1103 BX_ERROR(("NULL pointer"));
1106 fprintf(fp
, "%s = ", node
->get_name());
1107 switch (node
->get_type()) {
1109 value
= ((bx_param_num_c
*)node
)->get64();
1110 if (((bx_param_num_c
*)node
)->get_base() == BASE_DEC
) {
1111 if (((bx_param_num_c
*)node
)->get_min() >= BX_MIN_BIT64U
) {
1112 if ((Bit64u
)((bx_param_num_c
*)node
)->get_max() > BX_MAX_BIT32U
) {
1113 fprintf(fp
, FMT_LL
"u\n", value
);
1115 fprintf(fp
, "%u\n", (Bit32u
) value
);
1118 fprintf(fp
, "%d\n", (Bit32s
) value
);
1121 if (node
->get_format()) {
1122 fprintf(fp
, node
->get_format(), value
);
1124 if ((Bit64u
)((bx_param_num_c
*)node
)->get_max() > BX_MAX_BIT32U
) {
1125 fprintf(fp
, "0x"FMT_LL
"x", (Bit64u
) value
);
1127 fprintf(fp
, "0x%x", (Bit32u
) value
);
1133 case BXT_PARAM_BOOL
:
1134 fprintf(fp
, "%s\n", ((bx_param_bool_c
*)node
)->get()?"true":"false");
1136 case BXT_PARAM_ENUM
:
1137 fprintf(fp
, "%s\n", ((bx_param_enum_c
*)node
)->get_selected());
1139 case BXT_PARAM_STRING
:
1140 if (((bx_param_string_c
*)node
)->get_options()->get() & bx_param_string_c::RAW_BYTES
) {
1142 for (i
= 0; i
< ((bx_param_string_c
*)node
)->get_maxsize(); i
++) {
1144 tmpbyte
[0] = ((bx_param_string_c
*)node
)->get_separator();
1146 strcat(tmpstr
, tmpbyte
);
1148 sprintf(tmpbyte
, "%02x", (Bit8u
)((bx_param_string_c
*)node
)->getptr()[i
]);
1149 strcat(tmpstr
, tmpbyte
);
1151 fprintf(fp
, "%s\n", tmpstr
);
1153 fprintf(fp
, "%s\n", ((bx_param_string_c
*)node
)->getptr());
1156 case BXT_PARAM_DATA
:
1157 fprintf(fp
, "%s.%s\n", node
->get_parent()->get_name(), node
->get_name());
1159 sprintf(tmpstr
, "%s/%s.%s", sr_path
, node
->get_parent()->get_name(), node
->get_name());
1161 sprintf(tmpstr
, "%s.%s", node
->get_parent()->get_name(), node
->get_name());
1162 fp2
= fopen(tmpstr
, "wb");
1164 fwrite(((bx_shadow_data_c
*)node
)->getptr(), 1, ((bx_shadow_data_c
*)node
)->get_size(), fp2
);
1171 bx_list_c
*list
= (bx_list_c
*)node
;
1172 for (i
=0; i
< list
->get_size(); i
++) {
1173 save_sr_param(fp
, list
->get(i
), sr_path
, level
+1);
1175 for (i
=0; i
<level
; i
++)
1181 BX_ERROR(("save_sr_param(): unknown parameter type"));
1187 /////////////////////////////////////////////////////////////////////////
1188 // define methods of bx_param_* and family
1189 /////////////////////////////////////////////////////////////////////////
1191 const char* bx_param_c::default_text_format
= NULL
;
1193 bx_param_c::bx_param_c(Bit32u id
, const char *param_name
, const char *param_desc
)
1201 set_type(BXT_PARAM
);
1202 this->name
= new char[strlen(param_name
)+1];
1203 strcpy(this->name
, param_name
);
1204 set_description(param_desc
);
1205 this->text_format
= default_text_format
;
1206 this->long_text_format
= default_text_format
;
1207 this->runtime_param
= 0;
1211 bx_param_c::bx_param_c(Bit32u id
, const char *param_name
, const char *param_label
, const char *param_desc
)
1219 set_type(BXT_PARAM
);
1220 this->name
= new char[strlen(param_name
)+1];
1221 strcpy(this->name
, param_name
);
1222 set_description(param_desc
);
1223 set_label(param_label
);
1224 this->text_format
= default_text_format
;
1225 this->long_text_format
= default_text_format
;
1226 this->runtime_param
= 0;
1230 bx_param_c::~bx_param_c()
1234 delete [] description
;
1235 delete [] ask_format
;
1236 delete [] group_name
;
1239 void bx_param_c::set_description(const char *text
)
1241 delete [] this->description
;
1243 this->description
= new char[strlen(text
)+1];
1244 strcpy(this->description
, text
);
1246 this->description
= NULL
;
1250 void bx_param_c::set_label(const char *text
)
1252 delete [] this->label
;
1254 this->label
= new char[strlen(text
)+1];
1255 strcpy(this->label
, text
);
1261 void bx_param_c::set_ask_format(const char *format
)
1263 delete [] this->ask_format
;
1265 this->ask_format
= new char[strlen(format
)+1];
1266 strcpy(this->ask_format
, format
);
1268 this->ask_format
= NULL
;
1272 void bx_param_c::set_group(const char *group
)
1274 delete [] this->group_name
;
1276 this->group_name
= new char[strlen(group
)+1];
1277 strcpy(this->group_name
, group
);
1279 this->group_name
= NULL
;
1283 int bx_param_c::get_param_path(char *path_out
, int maxlen
)
1285 if ((get_parent() == NULL
) || (get_parent() == root_param
)) {
1286 // Start with an empty string.
1287 // Never print the name of the root param.
1290 // build path of the parent, add a period, add path of this node
1291 if (get_parent()->get_param_path(path_out
, maxlen
) > 0) {
1292 strncat(path_out
, ".", maxlen
);
1295 strncat(path_out
, name
, maxlen
);
1296 return strlen(path_out
);
1299 const char* bx_param_c::set_default_format(const char *f
)
1301 const char *old
= default_text_format
;
1302 default_text_format
= f
;
1306 bx_param_num_c::bx_param_num_c(bx_param_c
*parent
,
1309 const char *description
,
1310 Bit64s min
, Bit64s max
, Bit64s initial_val
,
1312 : bx_param_c(SIM
->gen_param_id(), name
, label
, description
)
1314 set_type(BXT_PARAM_NUM
);
1317 this->initial_val
= initial_val
;
1318 this->val
.number
= initial_val
;
1319 this->handler
= NULL
;
1320 #if BX_SUPPORT_SAVE_RESTORE
1321 this->save_handler
= NULL
;
1322 this->restore_handler
= NULL
;
1324 this->enable_handler
= NULL
;
1325 this->base
= default_base
;
1326 this->is_shadow
= is_shadow
;
1327 // dependent_list must be initialized before the set(),
1328 // because set calls update_dependents().
1329 dependent_list
= NULL
;
1334 BX_ASSERT(parent
->get_type() == BXT_LIST
);
1335 this->parent
= (bx_list_c
*)parent
;
1336 this->parent
->add(this);
1340 Bit32u
bx_param_num_c::default_base
= BASE_DEC
;
1342 Bit32u
bx_param_num_c::set_default_base(Bit32u val
)
1344 Bit32u old
= default_base
;
1349 void bx_param_num_c::reset()
1351 this->val
.number
= initial_val
;
1354 void bx_param_num_c::set_handler(param_event_handler handler
)
1356 this->handler
= handler
;
1357 // now that there's a handler, call set once to run the handler immediately
1361 #if BX_SUPPORT_SAVE_RESTORE
1362 void bx_param_num_c::set_sr_handlers(void *devptr
, param_sr_handler save
, param_sr_handler restore
)
1364 this->sr_devptr
= devptr
;
1365 this->save_handler
= save
;
1366 this->restore_handler
= restore
;
1370 void bx_param_num_c::set_enable_handler(param_enable_handler handler
)
1372 this->enable_handler
= handler
;
1375 void bx_param_num_c::set_dependent_list(bx_list_c
*l
) {
1377 update_dependents();
1380 Bit64s
bx_param_num_c::get64()
1382 #if BX_SUPPORT_SAVE_RESTORE
1384 return (*save_handler
)(sr_devptr
, this, val
.number
);
1388 // the handler can decide what value to return and/or do some side effect
1389 return (*handler
)(this, 0, val
.number
);
1391 // just return the value
1396 void bx_param_num_c::set(Bit64s newval
)
1399 // the handler can override the new value and/or perform some side effect
1400 val
.number
= newval
;
1401 (*handler
)(this, 1, newval
);
1403 // just set the value. This code does not check max/min.
1404 val
.number
= newval
;
1406 #if BX_SUPPORT_SAVE_RESTORE
1407 if (restore_handler
) {
1408 val
.number
= newval
;
1409 (*restore_handler
)(sr_devptr
, this, newval
);
1412 if ((val
.number
< min
|| val
.number
> max
) && (Bit64u
)max
!= BX_MAX_BIT64U
)
1413 BX_PANIC(("numerical parameter '%s' was set to " FMT_LL
"d, which is out of range " FMT_LL
"d to " FMT_LL
"d", get_name (), val
.number
, min
, max
));
1414 if (dependent_list
!= NULL
) update_dependents();
1417 void bx_param_num_c::set_range(Bit64u min
, Bit64u max
)
1423 void bx_param_num_c::set_initial_val(Bit64s initial_val
)
1425 this->val
.number
= this->initial_val
= initial_val
;
1428 void bx_param_num_c::update_dependents()
1430 if (dependent_list
) {
1431 int en
= val
.number
&& enabled
;
1432 for (int i
=0; i
<dependent_list
->get_size(); i
++) {
1433 bx_param_c
*param
= dependent_list
->get(i
);
1435 param
->set_enabled(en
);
1440 void bx_param_num_c::set_enabled(int en
)
1442 // The enable handler may wish to allow/disallow the action
1443 if (enable_handler
) {
1444 en
= (*enable_handler
)(this, en
);
1446 bx_param_c::set_enabled(en
);
1447 update_dependents();
1451 bx_shadow_num_c::bx_shadow_num_c(bx_param_c
*parent
,
1453 Bit64s
*ptr_to_real_val
,
1457 : bx_param_num_c(parent
, name
, NULL
, NULL
, BX_MIN_BIT64S
, BX_MAX_BIT64S
, *ptr_to_real_val
, 1)
1460 this->lowbit
= lowbit
;
1461 this->mask
= ((BX_MAX_BIT64S
>> (63 - (highbit
- lowbit
))) << lowbit
);
1462 val
.p64bit
= ptr_to_real_val
;
1463 if (base
== BASE_HEX
) {
1465 this->text_format
= "0x"FMT_LL
"x";
1470 bx_shadow_num_c::bx_shadow_num_c(bx_param_c
*parent
,
1472 Bit64u
*ptr_to_real_val
,
1476 : bx_param_num_c(parent
, name
, NULL
, NULL
, BX_MIN_BIT64U
, BX_MAX_BIT64U
, *ptr_to_real_val
, 1)
1479 this->lowbit
= lowbit
;
1480 this->mask
= ((BX_MAX_BIT64U
>> (63 - (highbit
- lowbit
))) << lowbit
);
1481 val
.p64bit
= (Bit64s
*) ptr_to_real_val
;
1482 if (base
== BASE_HEX
) {
1484 this->text_format
= "0x"FMT_LL
"x";
1489 bx_shadow_num_c::bx_shadow_num_c(bx_param_c
*parent
,
1491 Bit32s
*ptr_to_real_val
,
1495 : bx_param_num_c(parent
, name
, NULL
, NULL
, BX_MIN_BIT32S
, BX_MAX_BIT32S
, *ptr_to_real_val
, 1)
1498 this->lowbit
= lowbit
;
1499 this->mask
= ((BX_MAX_BIT32S
>> (31 - (highbit
- lowbit
))) << lowbit
);
1500 val
.p32bit
= ptr_to_real_val
;
1501 if (base
== BASE_HEX
) {
1503 this->text_format
= "0x%08x";
1508 bx_shadow_num_c::bx_shadow_num_c(bx_param_c
*parent
,
1510 Bit32u
*ptr_to_real_val
,
1514 : bx_param_num_c(parent
, name
, NULL
, NULL
, BX_MIN_BIT32U
, BX_MAX_BIT32U
, *ptr_to_real_val
, 1)
1517 this->lowbit
= lowbit
;
1518 this->mask
= ((BX_MAX_BIT32U
>> (31 - (highbit
- lowbit
))) << lowbit
);
1519 val
.p32bit
= (Bit32s
*) ptr_to_real_val
;
1520 if (base
== BASE_HEX
) {
1522 this->text_format
= "0x%08x";
1527 bx_shadow_num_c::bx_shadow_num_c(bx_param_c
*parent
,
1529 Bit16s
*ptr_to_real_val
,
1533 : bx_param_num_c(parent
, name
, NULL
, NULL
, BX_MIN_BIT16S
, BX_MAX_BIT16S
, *ptr_to_real_val
, 1)
1536 this->lowbit
= lowbit
;
1537 this->mask
= ((BX_MAX_BIT16S
>> (15 - (highbit
- lowbit
))) << lowbit
);
1538 val
.p16bit
= ptr_to_real_val
;
1539 if (base
== BASE_HEX
) {
1541 this->text_format
= "0x%04x";
1546 bx_shadow_num_c::bx_shadow_num_c(bx_param_c
*parent
,
1548 Bit16u
*ptr_to_real_val
,
1552 : bx_param_num_c(parent
, name
, NULL
, NULL
, BX_MIN_BIT16U
, BX_MAX_BIT16U
, *ptr_to_real_val
, 1)
1555 this->lowbit
= lowbit
;
1556 this->mask
= ((BX_MAX_BIT16U
>> (15 - (highbit
- lowbit
))) << lowbit
);
1557 val
.p16bit
= (Bit16s
*) ptr_to_real_val
;
1558 if (base
== BASE_HEX
) {
1560 this->text_format
= "0x%04x";
1565 bx_shadow_num_c::bx_shadow_num_c(bx_param_c
*parent
,
1567 Bit8s
*ptr_to_real_val
,
1571 : bx_param_num_c(parent
, name
, NULL
, NULL
, BX_MIN_BIT8S
, BX_MAX_BIT8S
, *ptr_to_real_val
, 1)
1574 this->lowbit
= lowbit
;
1575 this->mask
= ((BX_MAX_BIT8S
>> (7 - (highbit
- lowbit
))) << lowbit
);
1576 this->mask
= (1 << (highbit
- lowbit
)) - 1;
1577 val
.p8bit
= ptr_to_real_val
;
1578 if (base
== BASE_HEX
) {
1580 this->text_format
= "0x%02x";
1585 bx_shadow_num_c::bx_shadow_num_c(bx_param_c
*parent
,
1587 Bit8u
*ptr_to_real_val
,
1591 : bx_param_num_c(parent
, name
, NULL
, NULL
, BX_MIN_BIT8U
, BX_MAX_BIT8U
, *ptr_to_real_val
, 1)
1594 this->lowbit
= lowbit
;
1595 this->mask
= ((BX_MAX_BIT8U
>> (7 - (highbit
- lowbit
))) << lowbit
);
1596 val
.p8bit
= (Bit8s
*) ptr_to_real_val
;
1597 if (base
== BASE_HEX
) {
1599 this->text_format
= "0x%02x";
1603 Bit64s
bx_shadow_num_c::get64()
1607 case 8: current
= *(val
.p8bit
); break;
1608 case 16: current
= *(val
.p16bit
); break;
1609 case 32: current
= *(val
.p32bit
); break;
1610 case 64: current
= *(val
.p64bit
); break;
1611 default: BX_PANIC(("unsupported varsize %d", varsize
));
1613 current
= (current
>> lowbit
) & mask
;
1615 // the handler can decide what value to return and/or do some side effect
1616 return (*handler
)(this, 0, current
) & mask
;
1618 // just return the value
1623 void bx_shadow_num_c::set(Bit64s newval
)
1626 if (((newval
< min
) || (newval
> max
)) && (min
!= BX_MIN_BIT64S
) && ((Bit64u
)max
!= BX_MAX_BIT64U
))
1627 BX_PANIC (("numerical parameter %s was set to " FMT_LL
"d, which is out of range " FMT_LL
"d to " FMT_LL
"d", get_name (), newval
, min
, max
));
1630 tmp
= *(val
.p8bit
) & ~(mask
<< lowbit
);
1631 tmp
|= (newval
& mask
) << lowbit
;
1632 *(val
.p8bit
) = (Bit8s
)tmp
;
1635 tmp
= *(val
.p16bit
) & ~(mask
<< lowbit
);
1636 tmp
|= (newval
& mask
) << lowbit
;
1637 *(val
.p16bit
) = (Bit16s
)tmp
;
1640 tmp
= *(val
.p32bit
) & ~(mask
<< lowbit
);
1641 tmp
|= (newval
& mask
) << lowbit
;
1642 *(val
.p32bit
) = (Bit32s
)tmp
;
1645 tmp
= *(val
.p64bit
) & ~(mask
<< lowbit
);
1646 tmp
|= (newval
& mask
) << lowbit
;
1647 *(val
.p64bit
) = (Bit64s
)tmp
;
1650 BX_PANIC(("unsupported varsize %d", varsize
));
1653 // the handler can override the new value and/or perform some side effect
1654 (*handler
)(this, 1, tmp
);
1658 void bx_shadow_num_c::reset()
1660 BX_PANIC(("reset not supported on bx_shadow_num_c yet"));
1663 bx_param_bool_c::bx_param_bool_c(bx_param_c
*parent
,
1666 const char *description
,
1669 : bx_param_num_c(parent
, name
, label
, description
, 0, 1, initial_val
, is_shadow
)
1671 set_type(BXT_PARAM_BOOL
);
1674 bx_shadow_bool_c::bx_shadow_bool_c(bx_param_c
*parent
,
1677 bx_bool
*ptr_to_real_val
,
1679 : bx_param_bool_c(parent
, name
, label
, NULL
, (Bit64s
) *ptr_to_real_val
, 1)
1681 val
.pbool
= ptr_to_real_val
;
1682 this->bitnum
= bitnum
;
1685 bx_shadow_bool_c::bx_shadow_bool_c(bx_param_c
*parent
,
1687 bx_bool
*ptr_to_real_val
,
1689 : bx_param_bool_c(parent
, name
, NULL
, NULL
, (Bit64s
) *ptr_to_real_val
, 1)
1691 val
.pbool
= ptr_to_real_val
;
1692 this->bitnum
= bitnum
;
1695 Bit64s
bx_shadow_bool_c::get64()
1698 // the handler can decide what value to return and/or do some side effect
1699 Bit64s ret
= (*handler
)(this, 0, (Bit64s
) *(val
.pbool
));
1700 return (ret
>>bitnum
) & 1;
1702 // just return the value
1703 return (*(val
.pbool
)) & 1;
1707 void bx_shadow_bool_c::set(Bit64s newval
)
1709 // only change the bitnum bit
1710 Bit64s tmp
= (newval
&1) << bitnum
;
1711 *(val
.pbool
) &= ~tmp
;
1712 *(val
.pbool
) |= tmp
;
1714 // the handler can override the new value and/or perform some side effect
1715 (*handler
)(this, 1, newval
&1);
1719 bx_param_enum_c::bx_param_enum_c(bx_param_c
*parent
,
1722 const char *description
,
1726 : bx_param_num_c(parent
, name
, label
, description
, value_base
, BX_MAX_BIT64S
, initial_val
)
1728 set_type(BXT_PARAM_ENUM
);
1729 this->choices
= choices
;
1730 // count number of choices, set max
1732 while (*p
!= NULL
) p
++;
1733 this->min
= value_base
;
1734 // now that the max is known, replace the BX_MAX_BIT64S sent to the parent
1735 // class constructor with the real max.
1736 this->max
= value_base
+ (p
- choices
- 1);
1740 int bx_param_enum_c::find_by_name(const char *string
)
1743 for (p
=&choices
[0]; *p
; p
++) {
1744 if (!strcmp(string
, *p
))
1750 bx_bool
bx_param_enum_c::set_by_name(const char *string
)
1752 int n
= find_by_name(string
);
1758 bx_param_string_c::bx_param_string_c(bx_param_c
*parent
,
1761 const char *description
,
1762 const char *initial_val
,
1764 : bx_param_c(SIM
->gen_param_id(), name
, label
, description
)
1766 set_type(BXT_PARAM_STRING
);
1768 maxsize
= strlen(initial_val
) + 1;
1769 this->val
= new char[maxsize
];
1770 this->initial_val
= new char[maxsize
];
1771 this->handler
= NULL
;
1772 this->enable_handler
= NULL
;
1773 this->maxsize
= maxsize
;
1774 strncpy(this->val
, initial_val
, maxsize
);
1775 strncpy(this->initial_val
, initial_val
, maxsize
);
1776 this->options
= new bx_param_num_c(NULL
,
1777 "stringoptions", NULL
, NULL
, 0, BX_MAX_BIT64S
, 0);
1780 BX_ASSERT(parent
->get_type() == BXT_LIST
);
1781 this->parent
= (bx_list_c
*)parent
;
1782 this->parent
->add(this);
1786 bx_param_filename_c::bx_param_filename_c(bx_param_c
*parent
,
1789 const char *description
,
1790 const char *initial_val
,
1792 : bx_param_string_c(parent
, name
, label
, description
, initial_val
, maxsize
)
1794 get_options()->set(IS_FILENAME
);
1797 bx_param_string_c::~bx_param_string_c()
1799 if (val
!= NULL
) delete [] val
;
1800 if (initial_val
!= NULL
) delete [] initial_val
;
1801 if (options
!= NULL
) delete options
;
1804 void bx_param_string_c::reset()
1806 strncpy(val
, initial_val
, maxsize
);
1809 void bx_param_string_c::set_handler(param_string_event_handler handler
)
1811 this->handler
= handler
;
1812 // now that there's a handler, call set once to run the handler immediately
1816 void bx_param_string_c::set_enable_handler(param_enable_handler handler
)
1818 this->enable_handler
= handler
;
1821 void bx_param_string_c::set_enabled(int en
)
1823 // The enable handler may wish to allow/disallow the action
1824 if (enable_handler
) {
1825 en
= (*enable_handler
)(this, en
);
1827 bx_param_c::set_enabled(en
);
1830 Bit32s
bx_param_string_c::get(char *buf
, int len
)
1832 if (options
->get() & RAW_BYTES
)
1833 memcpy(buf
, val
, len
);
1835 strncpy(buf
, val
, len
);
1837 // the handler can choose to replace the value in val/len. Also its
1838 // return value is passed back as the return value of get.
1839 (*handler
)(this, 0, buf
, len
);
1844 void bx_param_string_c::set(const char *buf
)
1846 if (options
->get() & RAW_BYTES
)
1847 memcpy(val
, buf
, maxsize
);
1849 strncpy(val
, buf
, maxsize
);
1850 val
[maxsize
- 1] = 0;
1853 // the handler can return a different char* to be copied into the value
1854 buf
= (*handler
)(this, 1, buf
, -1);
1858 bx_bool
bx_param_string_c::equals(const char *buf
)
1860 if (options
->get() & RAW_BYTES
)
1861 return (memcmp(val
, buf
, maxsize
) == 0);
1863 return (strncmp(val
, buf
, maxsize
) == 0);
1866 void bx_param_string_c::set_initial_val(const char *buf
)
1868 if (options
->get() & RAW_BYTES
)
1869 memcpy(initial_val
, buf
, maxsize
);
1871 strncpy(initial_val
, buf
, maxsize
);
1875 #if BX_SUPPORT_SAVE_RESTORE
1876 bx_shadow_data_c::bx_shadow_data_c(bx_param_c
*parent
,
1880 : bx_param_c(SIM
->gen_param_id(), name
, "")
1882 set_type(BXT_PARAM_DATA
);
1883 this->data_ptr
= ptr_to_data
;
1884 this->data_size
= data_size
;
1886 BX_ASSERT(parent
->get_type() == BXT_LIST
);
1887 this->parent
= (bx_list_c
*)parent
;
1888 this->parent
->add(this);
1893 bx_list_c::bx_list_c(bx_param_c
*parent
, int maxsize
)
1894 : bx_param_c(SIM
->gen_param_id(), "list", "")
1898 this->maxsize
= maxsize
;
1899 this->list
= new bx_param_c
* [maxsize
];
1900 this->parent
= NULL
;
1902 BX_ASSERT(parent
->get_type() == BXT_LIST
);
1903 this->parent
= (bx_list_c
*)parent
;
1904 this->parent
->add(this);
1909 bx_list_c::bx_list_c(bx_param_c
*parent
, const char *name
, int maxsize
)
1910 : bx_param_c(SIM
->gen_param_id(), name
, "")
1912 set_type (BXT_LIST
);
1914 this->maxsize
= maxsize
;
1915 this->list
= new bx_param_c
* [maxsize
];
1916 this->parent
= NULL
;
1918 BX_ASSERT(parent
->get_type() == BXT_LIST
);
1919 this->parent
= (bx_list_c
*)parent
;
1920 this->parent
->add(this);
1925 bx_list_c::bx_list_c(bx_param_c
*parent
, const char *name
, char *title
,
1927 : bx_param_c(SIM
->gen_param_id(), name
, "")
1929 set_type (BXT_LIST
);
1931 this->maxsize
= maxsize
;
1932 this->list
= new bx_param_c
* [maxsize
];
1933 this->parent
= NULL
;
1935 BX_ASSERT(parent
->get_type() == BXT_LIST
);
1936 this->parent
= (bx_list_c
*)parent
;
1937 this->parent
->add(this);
1942 bx_list_c::bx_list_c(bx_param_c
*parent
, const char *name
, char *title
, bx_param_c
**init_list
)
1943 : bx_param_c(SIM
->gen_param_id(), name
, "")
1947 while (init_list
[this->size
] != NULL
)
1949 this->maxsize
= this->size
;
1950 this->list
= new bx_param_c
* [maxsize
];
1951 for (int i
=0; i
<this->size
; i
++)
1952 this->list
[i
] = init_list
[i
];
1953 this->parent
= NULL
;
1955 BX_ASSERT(parent
->get_type() == BXT_LIST
);
1956 this->parent
= (bx_list_c
*)parent
;
1957 this->parent
->add(this);
1962 bx_list_c::~bx_list_c()
1965 for (int i
=0; i
<this->size
; i
++) {
1970 if (title
!= NULL
) delete title
;
1971 if (options
!= NULL
) delete options
;
1972 if (choice
!= NULL
) delete choice
;
1975 void bx_list_c::init(const char *list_title
)
1977 // the title defaults to the name
1978 this->title
= new bx_param_string_c(NULL
,
1982 if ((list_title
!= NULL
) && (strlen(list_title
) > 0)) {
1983 this->title
->set((char *)list_title
);
1985 this->options
= new bx_param_num_c(NULL
,
1986 "list_option", "", "", 0, BX_MAX_BIT64S
, 0);
1987 this->choice
= new bx_param_num_c(NULL
,
1988 "list_choice", "", "", 0, BX_MAX_BIT64S
, 1);
1991 void bx_list_c::set_parent(bx_param_c
*newparent
)
1994 // if this object already had a parent, the correct thing
1995 // to do would be to remove this object from the parent's
1996 // list of children. Deleting children is currently
1998 BX_PANIC(("bx_list_c::set_parent: changing from one parent to another is not supported"));
2001 BX_ASSERT(newparent
->get_type() == BXT_LIST
);
2002 this->parent
= (bx_list_c
*)newparent
;
2003 this->parent
->add(this);
2007 bx_list_c
* bx_list_c::clone()
2009 bx_list_c
*newlist
= new bx_list_c(NULL
, name
, title
->getptr(), maxsize
);
2010 for (int i
=0; i
<get_size(); i
++)
2011 newlist
->add(get(i
));
2012 newlist
->get_options()->set(options
->get());
2016 void bx_list_c::add(bx_param_c
*param
)
2018 if (this->size
>= this->maxsize
)
2019 BX_PANIC(("add param '%s' to bx_list_c '%s': list capacity exceeded",
2020 param
->get_name(), get_name()));
2025 bx_param_c
* bx_list_c::get(int index
)
2027 BX_ASSERT(index
>= 0 && index
< size
);
2031 bx_param_c
* bx_list_c::get_by_name(const char *name
)
2033 int i
, imax
= get_size();
2034 for (i
=0; i
<imax
; i
++) {
2035 bx_param_c
*p
= get(i
);
2036 if (0 == strcmp (name
, p
->get_name())) {
2043 void bx_list_c::reset()
2045 int i
, imax
= get_size();
2046 for (i
=0; i
<imax
; i
++) {
2051 void bx_list_c::clear()
2053 int i
, imax
= get_size();
2055 for (i
=0; i
<imax
; i
++) {