1 /////////////////////////////////////////////////////////////////////////
2 // $Id: siminterface.cc,v 1.182 2008/09/19 21:31:08 sshwarts 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() { return 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() { return N_LOGLEV
; }
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(const char *filename
, int maxlen
, const char *prompt
, const char *the_default
, int flags
);
96 virtual int ask_yes_no(const char *title
, const 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
);
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_bochs_root() {
154 return (bx_list_c
*)get_param("bochs", NULL
);
156 virtual bx_bool
restore_bochs_param(bx_list_c
*root
, const char *sr_path
, const char *restore_name
);
159 bx_bool
save_sr_param(FILE *fp
, bx_param_c
*node
, const char *sr_path
, int level
);
162 // recursive function to find parameters from the path
163 static bx_param_c
*find_param(const char *full_pname
, const char *rest_of_pname
, bx_param_c
*base
)
165 const char *from
= rest_of_pname
;
166 char component
[BX_PATHNAME_LEN
];
167 char *to
= component
;
168 // copy the first piece of pname into component, stopping at first separator
169 // or at the end of the string
170 while (*from
!= 0 && *from
!= '.') {
177 BX_PANIC(("find_param: found empty component in parameter name '%s'", full_pname
));
178 // or does that mean that we're done?
180 if (base
->get_type() != BXT_LIST
) {
181 BX_PANIC(("find_param: base was not a list!"));
183 BX_DEBUG(("searching for component '%s' in list '%s'", component
, base
->get_name()));
185 // find the component in the list.
186 bx_list_c
*list
= (bx_list_c
*)base
;
187 bx_param_c
*child
= list
->get_by_name(component
);
188 // if child not found, there is nothing else that can be done. return NULL.
189 if (child
== NULL
) return NULL
;
191 // that was the end of the path, we're done
194 // continue parsing the path
195 BX_ASSERT(from
[0] == '.');
196 from
++; // skip over the separator
197 return find_param(full_pname
, from
, child
);
200 bx_param_c
*bx_real_sim_c::get_param(const char *pname
, bx_param_c
*base
)
204 // to access top level object, look for parameter "."
205 if (pname
[0] == '.' && pname
[1] == 0)
207 return find_param(pname
, pname
, base
);
210 bx_param_num_c
*bx_real_sim_c::get_param_num (const char *pname
, bx_param_c
*base
)
212 bx_param_c
*generic
= get_param(pname
, base
);
214 BX_ERROR(("get_param_num(%s) could not find a parameter", pname
));
217 int type
= generic
->get_type();
218 if (type
== BXT_PARAM_NUM
|| type
== BXT_PARAM_BOOL
|| type
== BXT_PARAM_ENUM
)
219 return (bx_param_num_c
*)generic
;
220 BX_ERROR(("get_param_num(%s) could not find an integer parameter with that name", pname
));
224 bx_param_string_c
*bx_real_sim_c::get_param_string(const char *pname
, bx_param_c
*base
)
226 bx_param_c
*generic
= get_param(pname
, base
);
228 BX_ERROR(("get_param_string(%s) could not find a parameter", pname
));
231 if (generic
->get_type() == BXT_PARAM_STRING
)
232 return (bx_param_string_c
*)generic
;
233 BX_ERROR(("get_param_string(%s) could not find an integer parameter with that name", pname
));
237 bx_param_bool_c
*bx_real_sim_c::get_param_bool(const char *pname
, bx_param_c
*base
)
239 bx_param_c
*generic
= get_param(pname
, base
);
241 BX_ERROR(("get_param_bool(%s) could not find a parameter", pname
));
244 if (generic
->get_type () == BXT_PARAM_BOOL
)
245 return (bx_param_bool_c
*)generic
;
246 BX_ERROR(("get_param_bool(%s) could not find a bool parameter with that name", pname
));
250 bx_param_enum_c
*bx_real_sim_c::get_param_enum(const char *pname
, bx_param_c
*base
)
252 bx_param_c
*generic
= get_param(pname
, base
);
254 BX_ERROR(("get_param_enum(%s) could not find a parameter", pname
));
257 if (generic
->get_type() == BXT_PARAM_ENUM
)
258 return (bx_param_enum_c
*)generic
;
259 BX_ERROR(("get_param_enum(%s) could not find a enum parameter with that name", pname
));
263 void bx_init_siminterface()
265 siminterface_log
= new logfunctions();
266 siminterface_log
->put("CTRL");
267 siminterface_log
->settype(CTRLLOG
);
269 SIM
= new bx_real_sim_c();
270 if (root_param
== NULL
) {
271 root_param
= new bx_list_c(NULL
,
273 "list of top level bochs parameters",
278 bx_real_sim_c::bx_real_sim_c()
280 bxevent_callback
= NULL
;
281 bxevent_callback_data
= NULL
;
283 ci_callback_data
= NULL
;
284 is_sim_thread_func
= NULL
;
291 param_id
= BXP_NEW_PARAM_ID
;
295 void bx_real_sim_c::reset_all_param()
300 int bx_real_sim_c::get_n_log_modules()
302 return io
->get_n_logfns();
305 char *bx_real_sim_c::get_prefix(int mod
)
307 logfunc_t
*logfn
= io
->get_logfn(mod
);
308 return logfn
->getprefix();
311 int bx_real_sim_c::get_log_action(int mod
, int level
)
313 logfunc_t
*logfn
= io
->get_logfn(mod
);
314 return logfn
->getonoff(level
);
317 void bx_real_sim_c::set_log_action(int mod
, int level
, int action
)
321 logfunc_t
*logfn
= io
->get_logfn(mod
);
322 logfn
->setonoff(level
, action
);
325 // if called with mod<0 loop over all
326 int nmod
= get_n_log_modules ();
327 for (mod
=0; mod
<nmod
; mod
++)
328 set_log_action(mod
, level
, action
);
331 char *bx_real_sim_c::get_action_name(int action
)
333 return io
->getaction(action
);
336 const char *bx_real_sim_c::get_log_level_name(int level
)
338 return io
->getlevel(level
);
341 void bx_real_sim_c::quit_sim(int code
)
343 BX_INFO(("quit_sim called with exit code %d", code
));
346 // use longjmp to quit cleanly, no matter where in the stack we are.
347 if (quit_context
!= NULL
) {
348 longjmp(*quit_context
, 1);
349 BX_PANIC(("in bx_real_sim_c::quit_sim, longjmp should never return"));
351 // use exit() to stop the application.
353 BX_PANIC(("Quit simulation command"));
358 int bx_real_sim_c::get_default_rc(char *path
, int len
)
360 char *rc
= bx_find_bochsrc();
361 if (rc
== NULL
) return -1;
362 strncpy(path
, rc
, len
);
367 int bx_real_sim_c::read_rc(const char *rc
)
369 return bx_read_configuration(rc
);
375 // -2: already exists, and overwrite was off
376 int bx_real_sim_c::write_rc(const char *rc
, int overwrite
)
378 return bx_write_configuration(rc
, overwrite
);
381 int bx_real_sim_c::get_log_file(char *path
, int len
)
383 strncpy(path
, SIM
->get_param_string(BXPN_LOG_FILENAME
)->getptr(), len
);
387 int bx_real_sim_c::set_log_file(char *path
)
389 SIM
->get_param_string(BXPN_LOG_FILENAME
)->set(path
);
393 int bx_real_sim_c::get_log_prefix(char *prefix
, int len
)
395 strncpy(prefix
, SIM
->get_param_string(BXPN_LOG_PREFIX
)->getptr(), len
);
399 int bx_real_sim_c::set_log_prefix(char *prefix
)
401 SIM
->get_param_string(BXPN_LOG_PREFIX
)->set(prefix
);
405 int bx_real_sim_c::get_debugger_log_file(char *path
, int len
)
407 strncpy(path
, SIM
->get_param_string(BXPN_DEBUGGER_LOG_FILENAME
)->getptr(), len
);
411 int bx_real_sim_c::set_debugger_log_file(char *path
)
413 SIM
->get_param_string(BXPN_DEBUGGER_LOG_FILENAME
)->set(path
);
417 int bx_real_sim_c::get_cdrom_options(int level
, bx_list_c
**out
, int *where
)
421 for (Bit8u channel
=0; channel
<BX_MAX_ATA_CHANNEL
; channel
++) {
422 for (Bit8u device
=0; device
<2; device
++) {
423 sprintf(pname
, "ata.%d.%s", channel
, (device
==0)?"master":"slave");
424 bx_list_c
*devlist
= (bx_list_c
*) SIM
->get_param(pname
);
425 if (SIM
->get_param_enum("type", devlist
)->get() == BX_ATA_DEVICE_CDROM
) {
428 if (where
!= NULL
) *where
= (channel
* 2) + device
;
439 const char *bochs_start_names
[] = { "quick", "load", "edit", "run" };
441 const char *floppy_type_names
[] = { "none", "1.2M", "1.44M", "2.88M", "720K", "360K", "160K", "180K", "320K", "auto", NULL
};
442 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 };
443 const char *floppy_status_names
[] = { "ejected", "inserted", NULL
};
445 const char *bochs_bootdisk_names
[] = { "none", "floppy", "disk","cdrom", "network", NULL
};
446 const char *loader_os_names
[] = { "none", "linux", "nullkernel", NULL
};
447 const char *keyboard_type_names
[] = { "xt", "at", "mf", NULL
};
449 const char *atadevice_type_names
[] = { "disk", "cdrom", NULL
};
450 //const char *atadevice_mode_names[] = { "flat", "concat", "external", "dll", "sparse", "vmware3", "vmware4", "undoable", "growing", "volatile", "z-undoable", "z-volatile", NULL };
451 const char *atadevice_mode_names
[] = { "flat", "concat", "external", "dll", "sparse", "vmware3", "vmware4", "undoable", "growing", "volatile", NULL
};
452 const char *atadevice_status_names
[] = { "ejected", "inserted", NULL
};
453 const char *atadevice_biosdetect_names
[] = { "none", "auto", "cmos", NULL
};
454 const char *atadevice_translation_names
[] = { "none", "lba", "large", "rechs", "auto", NULL
};
455 const char *clock_sync_names
[] = { "none", "realtime", "slowdown", "both", NULL
};
458 void bx_real_sim_c::set_notify_callback(bxevent_handler func
, void *arg
)
460 bxevent_callback
= func
;
461 bxevent_callback_data
= arg
;
464 void bx_real_sim_c::get_notify_callback(bxevent_handler
*func
, void **arg
)
466 *func
= bxevent_callback
;
467 *arg
= bxevent_callback_data
;
470 BxEvent
*bx_real_sim_c::sim_to_ci_event(BxEvent
*event
)
472 if (bxevent_callback
== NULL
) {
473 BX_ERROR(("notify called, but no bxevent_callback function is registered"));
476 return (*bxevent_callback
)(bxevent_callback_data
, event
);
480 // returns 0 for continue, 1 for alwayscontinue, 2 for die.
481 int bx_real_sim_c::log_msg(const char *prefix
, int level
, const char *msg
)
484 be
.type
= BX_SYNC_EVT_LOG_ASK
;
485 be
.u
.logmsg
.prefix
= prefix
;
486 be
.u
.logmsg
.level
= level
;
487 be
.u
.logmsg
.msg
= msg
;
488 // default return value in case something goes wrong.
489 be
.retcode
= BX_LOG_NOTIFY_FAILED
;
491 sim_to_ci_event (&be
);
495 // Called by simulator whenever it needs the user to choose a new value
496 // for a registered parameter. Create a synchronous ASK_PARAM event,
497 // send it to the CI, and wait for the response. The CI will call the
498 // set() method on the parameter if the user changes the value.
499 int bx_real_sim_c::ask_param(bx_param_c
*param
)
501 BX_ASSERT(param
!= NULL
);
502 // create appropriate event
504 event
.type
= BX_SYNC_EVT_ASK_PARAM
;
505 event
.u
.param
.param
= param
;
506 sim_to_ci_event(&event
);
507 return event
.retcode
;
510 int bx_real_sim_c::ask_param(const char *pname
)
512 bx_param_c
*paramptr
= SIM
->get_param(pname
);
513 BX_ASSERT(paramptr
!= NULL
);
514 // create appropriate event
516 event
.type
= BX_SYNC_EVT_ASK_PARAM
;
517 event
.u
.param
.param
= paramptr
;
518 sim_to_ci_event(&event
);
519 return event
.retcode
;
522 int bx_real_sim_c::ask_filename(const char *filename
, int maxlen
, const char *prompt
, const char *the_default
, int flags
)
525 bx_param_string_c
param(NULL
, "filename", prompt
, "", the_default
, maxlen
);
526 flags
|= param
.IS_FILENAME
;
527 param
.get_options()->set(flags
);
528 event
.type
= BX_SYNC_EVT_ASK_PARAM
;
529 event
.u
.param
.param
= ¶m
;
530 sim_to_ci_event(&event
);
531 if (event
.retcode
>= 0)
532 memcpy((char *)filename
, param
.getptr(), maxlen
);
533 return event
.retcode
;
536 int bx_real_sim_c::ask_yes_no(const char *title
, const char *prompt
, bx_bool the_default
)
541 bx_param_bool_c
param(NULL
, "yes_no", title
, prompt
, the_default
);
542 sprintf(format
, "%s\n\n%s [%%s] ", title
, prompt
);
543 param
.set_ask_format(format
);
544 event
.type
= BX_SYNC_EVT_ASK_PARAM
;
545 event
.u
.param
.param
= ¶m
;
546 sim_to_ci_event(&event
);
547 if (event
.retcode
>= 0) {
551 return event
.retcode
;
555 void bx_real_sim_c::periodic()
557 // give the GUI a chance to do periodic things on the bochs thread. in
558 // particular, notice if the thread has been asked to die.
560 tick
.type
= BX_SYNC_EVT_TICK
;
561 sim_to_ci_event (&tick
);
562 if (tick
.retcode
< 0) {
563 BX_INFO(("Bochs thread has been asked to quit."));
571 static int refresh_counter
= 0;
572 if (++refresh_counter
== 50) {
573 // only ask the CI to refresh every 50 times periodic() is called.
574 // This should obviously be configurable because system speeds and
575 // user preferences vary.
581 // create a disk image file called filename, size=512 bytes * sectors.
582 // If overwrite is 0 and the file exists, returns -1 without changing it.
583 // Otherwise, opens up the image and starts writing. Returns -2 if
584 // the image could not be opened, or -3 if there are failures during
585 // write, e.g. disk full.
587 // wxWidgets: This may be called from the gui thread.
588 int bx_real_sim_c::create_disk_image(const char *filename
, int sectors
, bx_bool overwrite
)
592 // check for existence first
593 fp
= fopen(filename
, "r");
600 fp
= fopen(filename
, "w");
604 sprintf(buffer
, "while opening '%s' for writing", filename
);
606 // not sure how to get this back into the CI
612 * seek to sec*512-1 and write a single character.
613 * can't just do: fseek(fp, 512*sec-1, SEEK_SET)
614 * because 512*sec may be too large for signed int.
618 /* temp <-- min(sec, 4194303)
619 * 4194303 is (int)(0x7FFFFFFF/512)
621 int temp
= ((sec
< 4194303) ? sec
: 4194303);
622 fseek(fp
, 512*temp
, SEEK_CUR
);
626 fseek(fp
, -1, SEEK_CUR
);
627 if (fputc('\0', fp
) == EOF
)
636 void bx_real_sim_c::refresh_ci()
638 if (SIM
->has_debug_gui()) {
639 // presently, only wxWidgets interface uses these events
640 // It's an async event, so allocate a pointer and send it.
641 // The event will be freed by the recipient.
642 BxEvent
*event
= new BxEvent();
643 event
->type
= BX_ASYNC_EVT_REFRESH
;
644 sim_to_ci_event(event
);
648 bx_param_c
*bx_real_sim_c::get_first_atadevice(Bit32u search_type
)
651 for (int channel
=0; channel
<BX_MAX_ATA_CHANNEL
; channel
++) {
652 sprintf(pname
, "ata.%d.resources.enabled", channel
);
653 if (!SIM
->get_param_bool(pname
)->get())
655 for (int slave
=0; slave
<2; slave
++) {
656 sprintf(pname
, "ata.%d.%s.present", channel
, (slave
==0)?"master":"slave");
657 Bit32u present
= SIM
->get_param_bool(pname
)->get();
658 sprintf(pname
, "ata.%d.%s.type", channel
, (slave
==0)?"master":"slave");
659 Bit32u type
= SIM
->get_param_enum(pname
)->get();
660 if (present
&& (type
== search_type
)) {
661 sprintf(pname
, "ata.%d.%s", channel
, (slave
==0)?"master":"slave");
662 return SIM
->get_param(pname
);
671 // this can be safely called from either thread.
672 void bx_real_sim_c::debug_break()
677 // this should only be called from the sim_thread.
678 void bx_real_sim_c::debug_interpret_cmd(char *cmd
)
680 if (!is_sim_thread()) {
681 fprintf(stderr
, "ERROR: debug_interpret_cmd called but not from sim_thread\n");
684 bx_dbg_interpret_line(cmd
);
687 char *bx_real_sim_c::debug_get_next_command()
690 event
.type
= BX_SYNC_EVT_GET_DBG_COMMAND
;
691 BX_DEBUG(("asking for next debug command"));
692 sim_to_ci_event (&event
);
693 BX_DEBUG(("received next debug command: '%s'", event
.u
.debugcmd
.command
));
694 if (event
.retcode
>= 0)
695 return event
.u
.debugcmd
.command
;
699 void bx_real_sim_c::debug_puts(const char *text
)
701 if (SIM
->has_debug_gui()) {
702 // send message to the wxWidgets debugger
703 BxEvent
*event
= new BxEvent();
704 event
->type
= BX_ASYNC_EVT_DBG_MSG
;
705 event
->u
.logmsg
.msg
= text
;
706 sim_to_ci_event(event
);
707 // the event will be freed by the recipient
709 // text mode debugger: just write to console
711 delete [] (char *)text
;
716 void bx_real_sim_c::register_configuration_interface(
718 config_interface_callback_t callback
,
721 ci_callback
= callback
;
722 ci_callback_data
= userdata
;
723 registered_ci_name
= name
;
726 int bx_real_sim_c::configuration_interface(const char *ignore
, ci_command_t command
)
728 bx_param_enum_c
*ci_param
= SIM
->get_param_enum(BXPN_SEL_CONFIG_INTERFACE
);
729 const char *name
= ci_param
->get_selected();
731 BX_PANIC(("no configuration interface was loaded"));
734 if (strcmp(name
, registered_ci_name
) != 0) {
735 BX_PANIC(("siminterface does not support loading one configuration interface and then calling another"));
738 if (!strcmp(name
, "wx"))
742 // enter configuration mode, just while running the configuration interface
743 set_display_mode(DISP_MODE_CONFIG
);
744 int retval
= (*ci_callback
)(ci_callback_data
, command
);
745 set_display_mode(DISP_MODE_SIM
);
749 int bx_real_sim_c::begin_simulation(int argc
, char *argv
[])
751 return bx_begin_simulation(argc
, argv
);
754 bx_bool
bx_real_sim_c::is_sim_thread()
756 if (is_sim_thread_func
== NULL
) return 1;
757 return (*is_sim_thread_func
)();
760 // check if the text console exists. On some platforms, if Bochs is
761 // started from the "Start Menu" or by double clicking on it on a Mac,
762 // there may be nothing attached to stdin/stdout/stderr. This function
763 // tests if stdin/stdout/stderr are usable and returns 0 if not.
764 bx_bool
bx_real_sim_c::test_for_text_console()
767 // In a Carbon application, you have a text console if you run the app from
768 // the command line, but if you start it from the finder you don't.
769 if(!isatty(STDIN_FILENO
)) return 0;
775 int bx_real_sim_c::find_user_option(const char *keyword
)
778 while (i
< n_user_options
) {
779 if (!strcmp(keyword
, user_option_name
[i
])) {
787 bx_bool
bx_real_sim_c::register_user_option(const char *keyword
, user_option_parser_t parser
,
788 user_option_save_t save_func
)
790 if (n_user_options
>= BX_MAX_USER_OPTIONS
) {
793 int idx
= find_user_option(keyword
);
795 if (parser
== user_option_parser
[idx
]) {
796 // parse handler already registered
799 // keyword already exists
803 user_option_name
[n_user_options
] = keyword
;
804 user_option_parser
[n_user_options
] = parser
;
805 user_option_save
[n_user_options
++] = save_func
;
810 Bit32s
bx_real_sim_c::parse_user_option(int idx
, const char *context
, int num_params
, char *params
[])
812 if ((idx
< 0) || (idx
>= n_user_options
)) {
815 return (*user_option_parser
[idx
])(context
, num_params
, params
);
818 Bit32s
bx_real_sim_c::save_user_options(FILE *fp
)
820 for (int i
= 0; i
< n_user_options
; i
++) {
821 if (user_option_save
[i
] != NULL
) {
822 (*user_option_save
[i
])(fp
);
828 void bx_real_sim_c::init_save_restore()
832 if ((list
= get_bochs_root()) != NULL
) {
835 list
= new bx_list_c(root_param
,
837 "subtree for save/restore",
838 30 + BX_MAX_SMP_THREADS_SUPPORTED
);
842 bx_bool
bx_real_sim_c::save_state(const char *checkpoint_path
)
844 char sr_file
[BX_PATHNAME_LEN
];
846 int i
, dev
, ndev
= SIM
->get_n_log_modules();
847 int type
, ntype
= SIM
->get_max_log_level();
849 sprintf(sr_file
, "%s/config", checkpoint_path
);
850 if (write_rc(sr_file
, 1) < 0)
852 sprintf(sr_file
, "%s/logopts", checkpoint_path
);
853 FILE *fp
= fopen(sr_file
, "w");
855 for (dev
=0; dev
<ndev
; dev
++) {
856 strcpy(prefix
, get_prefix(dev
));
857 strcpy(prefix
, prefix
+1);
858 prefix
[strlen(prefix
) - 1] = 0;
859 i
= strlen(prefix
) - 1;
860 while ((i
>= 0) && (prefix
[i
] == ' ')) prefix
[i
--] = 0;
861 if (strlen(prefix
) > 0) {
862 fprintf(fp
, "%s: ", prefix
);
863 for (type
=0; type
<ntype
; type
++) {
864 if (type
> 0) fprintf(fp
, ", ");
865 fprintf(fp
, "%s=%s", get_log_level_name(type
), get_action_name(get_log_action(dev
, type
)));
874 bx_list_c
*sr_list
= get_bochs_root();
875 ndev
= sr_list
->get_size();
876 for (dev
=0; dev
<ndev
; dev
++) {
877 sprintf(sr_file
, "%s/%s", checkpoint_path
, sr_list
->get(dev
)->get_name());
878 fp
= fopen(sr_file
, "w");
880 save_sr_param(fp
, sr_list
->get(dev
), checkpoint_path
, 0);
889 bx_bool
bx_real_sim_c::restore_config()
891 char config
[BX_PATHNAME_LEN
];
892 sprintf(config
, "%s/config", get_param_string(BXPN_RESTORE_PATH
)->getptr());
893 BX_INFO(("restoring '%s'", config
));
894 return (read_rc(config
) >= 0);
897 bx_bool
bx_real_sim_c::restore_logopts()
899 char logopts
[BX_PATHNAME_LEN
];
900 char line
[512], string
[512], prefix
[8];
902 int d
, i
, j
, dev
= 0, type
= 0, action
= 0;
903 int ndev
= SIM
->get_n_log_modules();
906 sprintf(logopts
, "%s/logopts", get_param_string(BXPN_RESTORE_PATH
)->getptr());
907 BX_INFO(("restoring '%s'", logopts
));
908 fp
= fopen(logopts
, "r");
911 ret
= fgets(line
, sizeof(line
)-1, fp
);
912 line
[sizeof(line
) - 1] = '\0';
913 int len
= strlen(line
);
914 if ((len
>0) && (line
[len
-1] < ' '))
917 if ((ret
!= NULL
) && strlen(line
)) {
918 ptr
= strtok(line
, ":");
921 while (isspace(string
[0])) strcpy(string
, string
+1);
922 while (isspace(string
[strlen(string
)-1])) string
[strlen(string
)-1] = 0;
924 sprintf(prefix
, "[%-5s]", string
);
926 for (d
= 0; d
< ndev
; d
++) {
927 if (!strcmp(prefix
, get_prefix(d
))) {
931 } else if (dev
>= 0) {
933 if (!strncmp(string
, "DEBUG=", 6)) {
935 } else if (!strncmp(string
, "INFO=", 5)) {
938 } else if (!strncmp(string
, "ERROR=", 6)) {
940 } else if (!strncmp(string
, "PANIC=", 6)) {
942 } else if (!strncmp(string
, "PASS=", 5)) {
946 if (!strcmp(string
+j
, "ignore")) {
948 } else if (!strcmp(string
+j
, "report")) {
950 } else if (!strcmp(string
+j
, "ask")) {
952 } else if (!strcmp(string
+j
, "fatal")) {
955 set_log_action(dev
, type
, action
);
958 BX_ERROR(("restore_logopts(): log module '%s' not found", prefix
));
962 ptr
= strtok(NULL
, ",");
973 bx_bool
bx_real_sim_c::restore_bochs_param(bx_list_c
*root
, const char *sr_path
, const char *restore_name
)
975 char devstate
[BX_PATHNAME_LEN
], devdata
[BX_PATHNAME_LEN
];
976 char line
[512], buf
[512], pname
[80];
980 bx_param_c
*param
= NULL
;
983 if (root
->get_by_name(restore_name
) == NULL
) {
984 BX_ERROR(("restore_bochs_param(): unknown parameter to restore"));
988 sprintf(devstate
, "%s/%s", sr_path
, restore_name
);
989 BX_INFO(("restoring '%s'", devstate
));
990 bx_list_c
*base
= root
;
991 fp
= fopen(devstate
, "r");
994 ret
= fgets(line
, sizeof(line
)-1, fp
);
995 line
[sizeof(line
) - 1] = '\0';
996 int len
= strlen(line
);
997 if ((len
>0) && (line
[len
-1] < ' '))
1000 if ((ret
!= NULL
) && strlen(line
)) {
1001 ptr
= strtok(line
, " ");
1004 if (!strcmp(ptr
, "}")) {
1005 base
= (bx_list_c
*)base
->get_parent();
1008 param
= get_param(ptr
, base
);
1010 } else if (i
== 2) {
1011 if (param
->get_type() != BXT_LIST
) {
1012 param
->get_param_path(pname
, 80);
1013 BX_DEBUG(("restoring parameter '%s'", pname
));
1015 switch (param
->get_type()) {
1017 if ((ptr
[0] == '0') && (ptr
[1] == 'x')) {
1018 ((bx_param_num_c
*)param
)->set(strtoull(ptr
, NULL
, 16));
1020 ((bx_param_num_c
*)param
)->set(strtoull(ptr
, NULL
, 10));
1023 case BXT_PARAM_BOOL
:
1024 ((bx_param_bool_c
*)param
)->set(!strcmp(ptr
, "true"));
1026 case BXT_PARAM_ENUM
:
1027 ((bx_param_enum_c
*)param
)->set_by_name(ptr
);
1029 case BXT_PARAM_STRING
:
1030 if (((bx_param_string_c
*)param
)->get_options()->get() & bx_param_string_c::RAW_BYTES
) {
1032 for (j
= 0; j
< ((bx_param_string_c
*)param
)->get_maxsize(); j
++) {
1033 if (ptr
[p
] == ((bx_param_string_c
*)param
)->get_separator()) {
1036 if (sscanf(ptr
+p
, "%02x", &n
) == 1) {
1041 ((bx_param_string_c
*)param
)->set(buf
);
1043 ((bx_param_string_c
*)param
)->set(ptr
);
1046 case BXT_PARAM_DATA
:
1047 sprintf(devdata
, "%s/%s", sr_path
, ptr
);
1048 fp2
= fopen(devdata
, "rb");
1050 fread(((bx_shadow_data_c
*)param
)->getptr(), 1, ((bx_shadow_data_c
*)param
)->get_size(), fp2
);
1055 base
= (bx_list_c
*)param
;
1058 BX_ERROR(("restore_sr_param(): unknown parameter type"));
1062 ptr
= strtok(NULL
, " ");
1065 } while (!feof(fp
));
1068 BX_ERROR(("restore_bochs_param(): error in file open"));
1075 bx_bool
bx_real_sim_c::restore_hardware()
1077 bx_list_c
*sr_list
= get_bochs_root();
1078 int ndev
= sr_list
->get_size();
1079 for (int dev
=0; dev
<ndev
; dev
++) {
1080 if (!restore_bochs_param(sr_list
, get_param_string(BXPN_RESTORE_PATH
)->getptr(), sr_list
->get(dev
)->get_name()))
1086 bx_bool
bx_real_sim_c::save_sr_param(FILE *fp
, bx_param_c
*node
, const char *sr_path
, int level
)
1090 char tmpstr
[BX_PATHNAME_LEN
], tmpbyte
[4];
1093 for (i
=0; i
<level
; i
++)
1096 BX_ERROR(("NULL pointer"));
1099 fprintf(fp
, "%s = ", node
->get_name());
1100 switch (node
->get_type()) {
1102 value
= ((bx_param_num_c
*)node
)->get64();
1103 if (((bx_param_num_c
*)node
)->get_base() == BASE_DEC
) {
1104 if (((bx_param_num_c
*)node
)->get_min() >= BX_MIN_BIT64U
) {
1105 if ((Bit64u
)((bx_param_num_c
*)node
)->get_max() > BX_MAX_BIT32U
) {
1106 fprintf(fp
, FMT_LL
"u\n", value
);
1108 fprintf(fp
, "%u\n", (Bit32u
) value
);
1111 fprintf(fp
, "%d\n", (Bit32s
) value
);
1114 if (node
->get_format()) {
1115 fprintf(fp
, node
->get_format(), value
);
1117 if ((Bit64u
)((bx_param_num_c
*)node
)->get_max() > BX_MAX_BIT32U
) {
1118 fprintf(fp
, "0x"FMT_LL
"x", (Bit64u
) value
);
1120 fprintf(fp
, "0x%x", (Bit32u
) value
);
1126 case BXT_PARAM_BOOL
:
1127 fprintf(fp
, "%s\n", ((bx_param_bool_c
*)node
)->get()?"true":"false");
1129 case BXT_PARAM_ENUM
:
1130 fprintf(fp
, "%s\n", ((bx_param_enum_c
*)node
)->get_selected());
1132 case BXT_PARAM_STRING
:
1133 if (((bx_param_string_c
*)node
)->get_options()->get() & bx_param_string_c::RAW_BYTES
) {
1135 for (i
= 0; i
< ((bx_param_string_c
*)node
)->get_maxsize(); i
++) {
1137 tmpbyte
[0] = ((bx_param_string_c
*)node
)->get_separator();
1139 strcat(tmpstr
, tmpbyte
);
1141 sprintf(tmpbyte
, "%02x", (Bit8u
)((bx_param_string_c
*)node
)->getptr()[i
]);
1142 strcat(tmpstr
, tmpbyte
);
1144 fprintf(fp
, "%s\n", tmpstr
);
1146 fprintf(fp
, "%s\n", ((bx_param_string_c
*)node
)->getptr());
1149 case BXT_PARAM_DATA
:
1150 fprintf(fp
, "%s.%s\n", node
->get_parent()->get_name(), node
->get_name());
1152 sprintf(tmpstr
, "%s/%s.%s", sr_path
, node
->get_parent()->get_name(), node
->get_name());
1154 sprintf(tmpstr
, "%s.%s", node
->get_parent()->get_name(), node
->get_name());
1155 fp2
= fopen(tmpstr
, "wb");
1157 fwrite(((bx_shadow_data_c
*)node
)->getptr(), 1, ((bx_shadow_data_c
*)node
)->get_size(), fp2
);
1164 bx_list_c
*list
= (bx_list_c
*)node
;
1165 for (i
=0; i
< list
->get_size(); i
++) {
1166 save_sr_param(fp
, list
->get(i
), sr_path
, level
+1);
1168 for (i
=0; i
<level
; i
++)
1174 BX_ERROR(("save_sr_param(): unknown parameter type"));
1181 /////////////////////////////////////////////////////////////////////////
1182 // define methods of bx_param_* and family
1183 /////////////////////////////////////////////////////////////////////////
1185 const char* bx_param_c::default_text_format
= NULL
;
1187 bx_param_c::bx_param_c(Bit32u id
, const char *param_name
, const char *param_desc
)
1195 set_type(BXT_PARAM
);
1196 this->name
= new char[strlen(param_name
)+1];
1197 strcpy(this->name
, param_name
);
1198 set_description(param_desc
);
1199 this->text_format
= default_text_format
;
1200 this->long_text_format
= default_text_format
;
1201 this->runtime_param
= 0;
1205 bx_param_c::bx_param_c(Bit32u id
, const char *param_name
, const char *param_label
, const char *param_desc
)
1213 set_type(BXT_PARAM
);
1214 this->name
= new char[strlen(param_name
)+1];
1215 strcpy(this->name
, param_name
);
1216 set_description(param_desc
);
1217 set_label(param_label
);
1218 this->text_format
= default_text_format
;
1219 this->long_text_format
= default_text_format
;
1220 this->runtime_param
= 0;
1224 bx_param_c::~bx_param_c()
1228 delete [] description
;
1229 delete [] ask_format
;
1230 delete [] group_name
;
1233 void bx_param_c::set_description(const char *text
)
1235 delete [] this->description
;
1237 this->description
= new char[strlen(text
)+1];
1238 strcpy(this->description
, text
);
1240 this->description
= NULL
;
1244 void bx_param_c::set_label(const char *text
)
1246 delete [] this->label
;
1248 this->label
= new char[strlen(text
)+1];
1249 strcpy(this->label
, text
);
1255 void bx_param_c::set_ask_format(const char *format
)
1257 delete [] this->ask_format
;
1259 this->ask_format
= new char[strlen(format
)+1];
1260 strcpy(this->ask_format
, format
);
1262 this->ask_format
= NULL
;
1266 void bx_param_c::set_group(const char *group
)
1268 delete [] this->group_name
;
1270 this->group_name
= new char[strlen(group
)+1];
1271 strcpy(this->group_name
, group
);
1273 this->group_name
= NULL
;
1277 int bx_param_c::get_param_path(char *path_out
, int maxlen
)
1279 if ((get_parent() == NULL
) || (get_parent() == root_param
)) {
1280 // Start with an empty string.
1281 // Never print the name of the root param.
1284 // build path of the parent, add a period, add path of this node
1285 if (get_parent()->get_param_path(path_out
, maxlen
) > 0) {
1286 strncat(path_out
, ".", maxlen
);
1289 strncat(path_out
, name
, maxlen
);
1290 return strlen(path_out
);
1293 const char* bx_param_c::set_default_format(const char *f
)
1295 const char *old
= default_text_format
;
1296 default_text_format
= f
;
1300 bx_param_num_c::bx_param_num_c(bx_param_c
*parent
,
1303 const char *description
,
1304 Bit64s min
, Bit64s max
, Bit64s initial_val
,
1306 : bx_param_c(SIM
->gen_param_id(), name
, label
, description
)
1308 set_type(BXT_PARAM_NUM
);
1311 this->initial_val
= initial_val
;
1312 this->val
.number
= initial_val
;
1313 this->handler
= NULL
;
1314 this->save_handler
= NULL
;
1315 this->restore_handler
= NULL
;
1316 this->enable_handler
= NULL
;
1317 this->base
= default_base
;
1318 this->is_shadow
= is_shadow
;
1319 // dependent_list must be initialized before the set(),
1320 // because set calls update_dependents().
1321 dependent_list
= NULL
;
1326 BX_ASSERT(parent
->get_type() == BXT_LIST
);
1327 this->parent
= (bx_list_c
*)parent
;
1328 this->parent
->add(this);
1332 Bit32u
bx_param_num_c::default_base
= BASE_DEC
;
1334 Bit32u
bx_param_num_c::set_default_base(Bit32u val
)
1336 Bit32u old
= default_base
;
1341 void bx_param_num_c::set_handler(param_event_handler handler
)
1343 this->handler
= handler
;
1344 // now that there's a handler, call set once to run the handler immediately
1348 void bx_param_num_c::set_sr_handlers(void *devptr
, param_sr_handler save
, param_sr_handler restore
)
1350 this->sr_devptr
= devptr
;
1351 this->save_handler
= save
;
1352 this->restore_handler
= restore
;
1355 void bx_param_num_c::set_dependent_list(bx_list_c
*l
)
1358 update_dependents();
1361 Bit64s
bx_param_num_c::get64()
1364 return (*save_handler
)(sr_devptr
, this, val
.number
);
1367 // the handler can decide what value to return and/or do some side effect
1368 return (*handler
)(this, 0, val
.number
);
1370 // just return the value
1375 void bx_param_num_c::set(Bit64s newval
)
1378 // the handler can override the new value and/or perform some side effect
1379 val
.number
= newval
;
1380 (*handler
)(this, 1, newval
);
1382 // just set the value. This code does not check max/min.
1383 val
.number
= newval
;
1385 if (restore_handler
) {
1386 val
.number
= newval
;
1387 (*restore_handler
)(sr_devptr
, this, newval
);
1389 if ((val
.number
< min
|| val
.number
> max
) && (Bit64u
)max
!= BX_MAX_BIT64U
)
1390 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
));
1391 if (dependent_list
!= NULL
) update_dependents();
1394 void bx_param_num_c::set_range(Bit64u min
, Bit64u max
)
1400 void bx_param_num_c::set_initial_val(Bit64s initial_val
)
1402 this->val
.number
= this->initial_val
= initial_val
;
1405 void bx_param_num_c::update_dependents()
1407 if (dependent_list
) {
1408 int en
= val
.number
&& enabled
;
1409 for (int i
=0; i
<dependent_list
->get_size(); i
++) {
1410 bx_param_c
*param
= dependent_list
->get(i
);
1412 param
->set_enabled(en
);
1417 void bx_param_num_c::set_enabled(int en
)
1419 // The enable handler may wish to allow/disallow the action
1420 if (enable_handler
) {
1421 en
= (*enable_handler
)(this, en
);
1423 bx_param_c::set_enabled(en
);
1424 update_dependents();
1428 bx_shadow_num_c::bx_shadow_num_c(bx_param_c
*parent
,
1430 Bit64s
*ptr_to_real_val
,
1434 : bx_param_num_c(parent
, name
, NULL
, NULL
, BX_MIN_BIT64S
, BX_MAX_BIT64S
, *ptr_to_real_val
, 1)
1437 this->lowbit
= lowbit
;
1438 this->mask
= ((BX_MAX_BIT64S
>> (63 - (highbit
- lowbit
))) << lowbit
);
1439 val
.p64bit
= ptr_to_real_val
;
1440 if (base
== BASE_HEX
) {
1442 this->text_format
= "0x"FMT_LL
"x";
1447 bx_shadow_num_c::bx_shadow_num_c(bx_param_c
*parent
,
1449 Bit64u
*ptr_to_real_val
,
1453 : bx_param_num_c(parent
, name
, NULL
, NULL
, BX_MIN_BIT64U
, BX_MAX_BIT64U
, *ptr_to_real_val
, 1)
1456 this->lowbit
= lowbit
;
1457 this->mask
= ((BX_MAX_BIT64U
>> (63 - (highbit
- lowbit
))) << lowbit
);
1458 val
.p64bit
= (Bit64s
*) ptr_to_real_val
;
1459 if (base
== BASE_HEX
) {
1461 this->text_format
= "0x"FMT_LL
"x";
1466 bx_shadow_num_c::bx_shadow_num_c(bx_param_c
*parent
,
1468 Bit32s
*ptr_to_real_val
,
1472 : bx_param_num_c(parent
, name
, NULL
, NULL
, BX_MIN_BIT32S
, BX_MAX_BIT32S
, *ptr_to_real_val
, 1)
1475 this->lowbit
= lowbit
;
1476 this->mask
= ((BX_MAX_BIT32S
>> (31 - (highbit
- lowbit
))) << lowbit
);
1477 val
.p32bit
= ptr_to_real_val
;
1478 if (base
== BASE_HEX
) {
1480 this->text_format
= "0x%08x";
1485 bx_shadow_num_c::bx_shadow_num_c(bx_param_c
*parent
,
1487 Bit32u
*ptr_to_real_val
,
1491 : bx_param_num_c(parent
, name
, NULL
, NULL
, BX_MIN_BIT32U
, BX_MAX_BIT32U
, *ptr_to_real_val
, 1)
1494 this->lowbit
= lowbit
;
1495 this->mask
= ((BX_MAX_BIT32U
>> (31 - (highbit
- lowbit
))) << lowbit
);
1496 val
.p32bit
= (Bit32s
*) ptr_to_real_val
;
1497 if (base
== BASE_HEX
) {
1499 this->text_format
= "0x%08x";
1504 bx_shadow_num_c::bx_shadow_num_c(bx_param_c
*parent
,
1506 Bit16s
*ptr_to_real_val
,
1510 : bx_param_num_c(parent
, name
, NULL
, NULL
, BX_MIN_BIT16S
, BX_MAX_BIT16S
, *ptr_to_real_val
, 1)
1513 this->lowbit
= lowbit
;
1514 this->mask
= ((BX_MAX_BIT16S
>> (15 - (highbit
- lowbit
))) << lowbit
);
1515 val
.p16bit
= ptr_to_real_val
;
1516 if (base
== BASE_HEX
) {
1518 this->text_format
= "0x%04x";
1523 bx_shadow_num_c::bx_shadow_num_c(bx_param_c
*parent
,
1525 Bit16u
*ptr_to_real_val
,
1529 : bx_param_num_c(parent
, name
, NULL
, NULL
, BX_MIN_BIT16U
, BX_MAX_BIT16U
, *ptr_to_real_val
, 1)
1532 this->lowbit
= lowbit
;
1533 this->mask
= ((BX_MAX_BIT16U
>> (15 - (highbit
- lowbit
))) << lowbit
);
1534 val
.p16bit
= (Bit16s
*) ptr_to_real_val
;
1535 if (base
== BASE_HEX
) {
1537 this->text_format
= "0x%04x";
1542 bx_shadow_num_c::bx_shadow_num_c(bx_param_c
*parent
,
1544 Bit8s
*ptr_to_real_val
,
1548 : bx_param_num_c(parent
, name
, NULL
, NULL
, BX_MIN_BIT8S
, BX_MAX_BIT8S
, *ptr_to_real_val
, 1)
1551 this->lowbit
= lowbit
;
1552 this->mask
= ((BX_MAX_BIT8S
>> (7 - (highbit
- lowbit
))) << lowbit
);
1553 this->mask
= (1 << (highbit
- lowbit
)) - 1;
1554 val
.p8bit
= ptr_to_real_val
;
1555 if (base
== BASE_HEX
) {
1557 this->text_format
= "0x%02x";
1562 bx_shadow_num_c::bx_shadow_num_c(bx_param_c
*parent
,
1564 Bit8u
*ptr_to_real_val
,
1568 : bx_param_num_c(parent
, name
, NULL
, NULL
, BX_MIN_BIT8U
, BX_MAX_BIT8U
, *ptr_to_real_val
, 1)
1571 this->lowbit
= lowbit
;
1572 this->mask
= ((BX_MAX_BIT8U
>> (7 - (highbit
- lowbit
))) << lowbit
);
1573 val
.p8bit
= (Bit8s
*) ptr_to_real_val
;
1574 if (base
== BASE_HEX
) {
1576 this->text_format
= "0x%02x";
1580 Bit64s
bx_shadow_num_c::get64()
1584 case 8: current
= *(val
.p8bit
); break;
1585 case 16: current
= *(val
.p16bit
); break;
1586 case 32: current
= *(val
.p32bit
); break;
1587 case 64: current
= *(val
.p64bit
); break;
1588 default: BX_PANIC(("unsupported varsize %d", varsize
));
1590 current
= (current
>> lowbit
) & mask
;
1592 // the handler can decide what value to return and/or do some side effect
1593 return (*handler
)(this, 0, current
) & mask
;
1595 // just return the value
1600 void bx_shadow_num_c::set(Bit64s newval
)
1603 if (((newval
< min
) || (newval
> max
)) && (min
!= BX_MIN_BIT64S
) && ((Bit64u
)max
!= BX_MAX_BIT64U
))
1604 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
));
1607 tmp
= *(val
.p8bit
) & ~(mask
<< lowbit
);
1608 tmp
|= (newval
& mask
) << lowbit
;
1609 *(val
.p8bit
) = (Bit8s
)tmp
;
1612 tmp
= *(val
.p16bit
) & ~(mask
<< lowbit
);
1613 tmp
|= (newval
& mask
) << lowbit
;
1614 *(val
.p16bit
) = (Bit16s
)tmp
;
1617 tmp
= *(val
.p32bit
) & ~(mask
<< lowbit
);
1618 tmp
|= (newval
& mask
) << lowbit
;
1619 *(val
.p32bit
) = (Bit32s
)tmp
;
1622 tmp
= *(val
.p64bit
) & ~(mask
<< lowbit
);
1623 tmp
|= (newval
& mask
) << lowbit
;
1624 *(val
.p64bit
) = (Bit64s
)tmp
;
1627 BX_PANIC(("unsupported varsize %d", varsize
));
1630 // the handler can override the new value and/or perform some side effect
1631 (*handler
)(this, 1, tmp
);
1635 void bx_shadow_num_c::reset()
1637 BX_PANIC(("reset not supported on bx_shadow_num_c yet"));
1640 bx_param_bool_c::bx_param_bool_c(bx_param_c
*parent
,
1643 const char *description
,
1646 : bx_param_num_c(parent
, name
, label
, description
, 0, 1, initial_val
, is_shadow
)
1648 set_type(BXT_PARAM_BOOL
);
1651 bx_shadow_bool_c::bx_shadow_bool_c(bx_param_c
*parent
,
1654 bx_bool
*ptr_to_real_val
,
1656 : bx_param_bool_c(parent
, name
, label
, NULL
, (Bit64s
) *ptr_to_real_val
, 1)
1658 val
.pbool
= ptr_to_real_val
;
1659 this->bitnum
= bitnum
;
1662 bx_shadow_bool_c::bx_shadow_bool_c(bx_param_c
*parent
,
1664 bx_bool
*ptr_to_real_val
,
1666 : bx_param_bool_c(parent
, name
, NULL
, NULL
, (Bit64s
) *ptr_to_real_val
, 1)
1668 val
.pbool
= ptr_to_real_val
;
1669 this->bitnum
= bitnum
;
1672 Bit64s
bx_shadow_bool_c::get64()
1675 // the handler can decide what value to return and/or do some side effect
1676 Bit64s ret
= (*handler
)(this, 0, (Bit64s
) *(val
.pbool
));
1677 return (ret
>>bitnum
) & 1;
1679 // just return the value
1680 return (*(val
.pbool
)) & 1;
1684 void bx_shadow_bool_c::set(Bit64s newval
)
1686 // only change the bitnum bit
1687 Bit64s tmp
= (newval
&1) << bitnum
;
1688 *(val
.pbool
) &= ~tmp
;
1689 *(val
.pbool
) |= tmp
;
1691 // the handler can override the new value and/or perform some side effect
1692 (*handler
)(this, 1, newval
&1);
1696 bx_param_enum_c::bx_param_enum_c(bx_param_c
*parent
,
1699 const char *description
,
1700 const char **choices
,
1703 : bx_param_num_c(parent
, name
, label
, description
, value_base
, BX_MAX_BIT64S
, initial_val
)
1705 set_type(BXT_PARAM_ENUM
);
1706 this->choices
= choices
;
1707 // count number of choices, set max
1708 const char **p
= choices
;
1709 while (*p
!= NULL
) p
++;
1710 this->min
= value_base
;
1711 // now that the max is known, replace the BX_MAX_BIT64S sent to the parent
1712 // class constructor with the real max.
1713 this->max
= value_base
+ (p
- choices
- 1);
1717 int bx_param_enum_c::find_by_name(const char *string
)
1720 for (p
=&choices
[0]; *p
; p
++) {
1721 if (!strcmp(string
, *p
))
1727 bx_bool
bx_param_enum_c::set_by_name(const char *string
)
1729 int n
= find_by_name(string
);
1735 bx_param_string_c::bx_param_string_c(bx_param_c
*parent
,
1738 const char *description
,
1739 const char *initial_val
,
1741 : bx_param_c(SIM
->gen_param_id(), name
, label
, description
)
1743 set_type(BXT_PARAM_STRING
);
1744 int initial_val_size
= strlen(initial_val
) + 1;
1746 maxsize
= initial_val_size
;
1747 this->val
= new char[maxsize
];
1748 this->initial_val
= new char[maxsize
];
1749 this->handler
= NULL
;
1750 this->enable_handler
= NULL
;
1751 this->maxsize
= maxsize
;
1752 strncpy(this->val
, initial_val
, initial_val_size
);
1753 if (maxsize
> initial_val_size
)
1754 memset(this->val
+ initial_val_size
, 0, maxsize
- initial_val_size
);
1755 strncpy(this->initial_val
, initial_val
, maxsize
);
1756 this->options
= new bx_param_num_c(NULL
,
1757 "stringoptions", NULL
, NULL
, 0, BX_MAX_BIT64S
, 0);
1760 BX_ASSERT(parent
->get_type() == BXT_LIST
);
1761 this->parent
= (bx_list_c
*)parent
;
1762 this->parent
->add(this);
1766 bx_param_filename_c::bx_param_filename_c(bx_param_c
*parent
,
1769 const char *description
,
1770 const char *initial_val
,
1772 : bx_param_string_c(parent
, name
, label
, description
, initial_val
, maxsize
)
1774 get_options()->set(IS_FILENAME
);
1777 bx_param_string_c::~bx_param_string_c()
1779 if (val
!= NULL
) delete [] val
;
1780 if (initial_val
!= NULL
) delete [] initial_val
;
1781 if (options
!= NULL
) delete options
;
1784 void bx_param_string_c::reset()
1786 strncpy(val
, initial_val
, maxsize
);
1789 void bx_param_string_c::set_handler(param_string_event_handler handler
)
1791 this->handler
= handler
;
1792 // now that there's a handler, call set once to run the handler immediately
1796 void bx_param_string_c::set_enable_handler(param_enable_handler handler
)
1798 this->enable_handler
= handler
;
1801 void bx_param_string_c::set_enabled(int en
)
1803 // The enable handler may wish to allow/disallow the action
1804 if (enable_handler
) {
1805 en
= (*enable_handler
)(this, en
);
1807 bx_param_c::set_enabled(en
);
1810 Bit32s
bx_param_string_c::get(char *buf
, int len
)
1812 if (options
->get() & RAW_BYTES
)
1813 memcpy(buf
, val
, len
);
1815 strncpy(buf
, val
, len
);
1817 // the handler can choose to replace the value in val/len. Also its
1818 // return value is passed back as the return value of get.
1819 (*handler
)(this, 0, buf
, len
);
1824 void bx_param_string_c::set(const char *buf
)
1826 if (options
->get() & RAW_BYTES
)
1827 memcpy(val
, buf
, maxsize
);
1829 strncpy(val
, buf
, maxsize
);
1830 val
[maxsize
- 1] = 0;
1833 // the handler can return a different char* to be copied into the value
1834 buf
= (*handler
)(this, 1, buf
, -1);
1838 bx_bool
bx_param_string_c::equals(const char *buf
)
1840 if (options
->get() & RAW_BYTES
)
1841 return (memcmp(val
, buf
, maxsize
) == 0);
1843 return (strncmp(val
, buf
, maxsize
) == 0);
1846 void bx_param_string_c::set_initial_val(const char *buf
)
1848 if (options
->get() & RAW_BYTES
)
1849 memcpy(initial_val
, buf
, maxsize
);
1851 strncpy(initial_val
, buf
, maxsize
);
1855 bx_shadow_data_c::bx_shadow_data_c(bx_param_c
*parent
,
1859 : bx_param_c(SIM
->gen_param_id(), name
, "")
1861 set_type(BXT_PARAM_DATA
);
1862 this->data_ptr
= ptr_to_data
;
1863 this->data_size
= data_size
;
1865 BX_ASSERT(parent
->get_type() == BXT_LIST
);
1866 this->parent
= (bx_list_c
*)parent
;
1867 this->parent
->add(this);
1871 bx_list_c::bx_list_c(bx_param_c
*parent
, int maxsize
)
1872 : bx_param_c(SIM
->gen_param_id(), "list", "")
1876 this->maxsize
= maxsize
;
1877 this->list
= new bx_param_c
* [maxsize
];
1878 this->parent
= NULL
;
1880 BX_ASSERT(parent
->get_type() == BXT_LIST
);
1881 this->parent
= (bx_list_c
*)parent
;
1882 this->parent
->add(this);
1887 bx_list_c::bx_list_c(bx_param_c
*parent
, const char *name
, int maxsize
)
1888 : bx_param_c(SIM
->gen_param_id(), name
, "")
1890 set_type (BXT_LIST
);
1892 this->maxsize
= maxsize
;
1893 this->list
= new bx_param_c
* [maxsize
];
1894 this->parent
= NULL
;
1896 BX_ASSERT(parent
->get_type() == BXT_LIST
);
1897 this->parent
= (bx_list_c
*)parent
;
1898 this->parent
->add(this);
1903 bx_list_c::bx_list_c(bx_param_c
*parent
, const char *name
, const char *title
,
1905 : bx_param_c(SIM
->gen_param_id(), name
, "")
1907 set_type (BXT_LIST
);
1909 this->maxsize
= maxsize
;
1910 this->list
= new bx_param_c
* [maxsize
];
1911 this->parent
= NULL
;
1913 BX_ASSERT(parent
->get_type() == BXT_LIST
);
1914 this->parent
= (bx_list_c
*)parent
;
1915 this->parent
->add(this);
1920 bx_list_c::bx_list_c(bx_param_c
*parent
, const char *name
, const char *title
, bx_param_c
**init_list
)
1921 : bx_param_c(SIM
->gen_param_id(), name
, "")
1925 while (init_list
[this->size
] != NULL
)
1927 this->maxsize
= this->size
;
1928 this->list
= new bx_param_c
* [maxsize
];
1929 for (int i
=0; i
<this->size
; i
++)
1930 this->list
[i
] = init_list
[i
];
1931 this->parent
= NULL
;
1933 BX_ASSERT(parent
->get_type() == BXT_LIST
);
1934 this->parent
= (bx_list_c
*)parent
;
1935 this->parent
->add(this);
1940 bx_list_c::~bx_list_c()
1943 for (int i
=0; i
<this->size
; i
++) {
1948 if (title
!= NULL
) delete title
;
1949 if (options
!= NULL
) delete options
;
1950 if (choice
!= NULL
) delete choice
;
1953 void bx_list_c::init(const char *list_title
)
1955 // the title defaults to the name
1956 this->title
= new bx_param_string_c(NULL
,
1960 if ((list_title
!= NULL
) && (strlen(list_title
) > 0)) {
1961 this->title
->set((char *)list_title
);
1963 this->options
= new bx_param_num_c(NULL
,
1964 "list_option", "", "", 0, BX_MAX_BIT64S
, 0);
1965 this->choice
= new bx_param_num_c(NULL
,
1966 "list_choice", "", "", 0, BX_MAX_BIT64S
, 1);
1969 void bx_list_c::set_parent(bx_param_c
*newparent
)
1972 // if this object already had a parent, the correct thing
1973 // to do would be to remove this object from the parent's
1974 // list of children. Deleting children is currently
1976 BX_PANIC(("bx_list_c::set_parent: changing from one parent to another is not supported"));
1979 BX_ASSERT(newparent
->get_type() == BXT_LIST
);
1980 this->parent
= (bx_list_c
*)newparent
;
1981 this->parent
->add(this);
1985 bx_list_c
* bx_list_c::clone()
1987 bx_list_c
*newlist
= new bx_list_c(NULL
, name
, title
->getptr(), maxsize
);
1988 for (int i
=0; i
<get_size(); i
++)
1989 newlist
->add(get(i
));
1990 newlist
->get_options()->set(options
->get());
1994 void bx_list_c::add(bx_param_c
*param
)
1996 if (size
>= maxsize
)
1997 BX_PANIC(("add param '%s' to bx_list_c '%s': list capacity exceeded",
1998 param
->get_name(), get_name()));
2003 bx_param_c
* bx_list_c::get(int index
)
2005 BX_ASSERT(index
>= 0 && index
< size
);
2009 bx_param_c
* bx_list_c::get_by_name(const char *name
)
2011 int imax
= get_size();
2012 for (int i
=0; i
<imax
; i
++) {
2013 bx_param_c
*p
= get(i
);
2014 if (0 == strcmp (name
, p
->get_name())) {
2021 void bx_list_c::reset()
2023 int imax
= get_size();
2024 for (int i
=0; i
<imax
; i
++) {
2029 void bx_list_c::clear()
2031 int imax
= get_size();
2032 for (int i
=0; i
<imax
; i
++) {
2033 bx_param_c
*param
= get(i
);