- updates for release 2.3.5
[bochs-mirror.git] / config.cc
blob396c0f685cc969ad39ef13cd578f3b7213cdeec6
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: config.cc,v 1.119 2007/04/08 15:02:50 vruppert Exp $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (C) 2002 MandrakeSoft S.A.
6 //
7 // MandrakeSoft S.A.
8 // 43, rue d'Aboukir
9 // 75002 Paris - France
10 // http://www.linux-mandrake.com/
11 // http://www.mandrakesoft.com/
13 // This library is free software; you can redistribute it and/or
14 // modify it under the terms of the GNU Lesser General Public
15 // License as published by the Free Software Foundation; either
16 // version 2 of the License, or (at your option) any later version.
18 // This library is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 // Lesser General Public License for more details.
23 // You should have received a copy of the GNU Lesser General Public
24 // License along with this library; if not, write to the Free Software
25 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include "bochs.h"
28 #include "iodev/iodev.h"
29 #include <assert.h>
31 #ifdef HAVE_LOCALE_H
32 #include <locale.h>
33 #endif
35 #if defined(macintosh)
36 // Work around a bug in SDL 1.2.4 on MacOS X, which redefines getenv to
37 // SDL_getenv, but then neglects to provide SDL_getenv. It happens
38 // because we are defining -Dmacintosh.
39 #undef getenv
40 #endif
43 int bochsrc_include_count = 0;
45 #define LOG_THIS genlog->
47 extern bx_debug_t bx_dbg;
49 static char *get_builtin_variable(char *varname);
50 static Bit32s parse_line_unformatted(const char *context, char *line);
51 static Bit32s parse_line_formatted(const char *context, int num_params, char *params[]);
52 static int parse_bochsrc(const char *rcfile);
53 static int get_floppy_type_from_image(const char *filename);
55 static Bit64s bx_param_handler(bx_param_c *param, int set, Bit64s val)
57 char pname[BX_PATHNAME_LEN];
58 Bit8u channel, device;
60 bx_list_c *base = (bx_list_c*) param->get_parent();
61 base->get_param_path(pname, BX_PATHNAME_LEN);
62 if (!strncmp(pname, "ata.", 4)) {
63 channel = pname[4] - '0';
64 if (!strcmp(base->get_name(), "master")) {
65 device = 0;
66 } else {
67 device = 1;
69 if (!strcmp(param->get_name(), "status")) {
70 if ((set) && (SIM->get_init_done())) {
71 Bit32u handle = DEV_hd_get_device_handle(channel, device);
72 DEV_hd_set_cd_media_status(handle, val == BX_INSERTED);
73 bx_gui->update_drive_status_buttons();
75 } else if (!strcmp(param->get_name(), "mode")) {
76 if (set) {
77 switch (val) {
78 case BX_ATA_MODE_UNDOABLE:
79 case BX_ATA_MODE_VOLATILE:
80 // case BX_ATA_MODE_Z_UNDOABLE:
81 // case BX_ATA_MODE_Z_VOLATILE:
82 SIM->get_param("journal", base)->set_enabled(1);
83 break;
84 default:
85 SIM->get_param("journal", base)->set_enabled(0);
88 } else if (!strcmp(param->get_name(), "type")) {
89 if (set) {
90 switch (val) {
91 case BX_ATA_DEVICE_DISK:
92 SIM->get_param_num("present", base)->set(1);
93 SIM->get_param("mode", base)->set_enabled(1);
94 SIM->get_param("path", base)->set_enabled(1);
95 //SIM->get_param("journal", base)->set_enabled(1);
96 SIM->get_param("cylinders", base)->set_enabled(1);
97 SIM->get_param("heads", base)->set_enabled(1);
98 SIM->get_param("spt", base)->set_enabled(1);
99 SIM->get_param("status", base)->set_enabled(0);
100 SIM->get_param("model", base)->set_enabled(1);
101 SIM->get_param("biosdetect", base)->set_enabled(1);
102 SIM->get_param("translation", base)->set_enabled(1);
103 SIM->get_param("path", base)->set_runtime_param(0);
104 SIM->get_param("status", base)->set_runtime_param(0);
105 break;
106 case BX_ATA_DEVICE_CDROM:
107 SIM->get_param_num("present", base)->set(1);
108 SIM->get_param("mode", base)->set_enabled(0);
109 SIM->get_param("path", base)->set_enabled(1);
110 SIM->get_param("journal", base)->set_enabled(0);
111 SIM->get_param("cylinders", base)->set_enabled(0);
112 SIM->get_param("heads", base)->set_enabled(0);
113 SIM->get_param("spt", base)->set_enabled(0);
114 SIM->get_param("status", base)->set_enabled(1);
115 SIM->get_param("model", base)->set_enabled(1);
116 SIM->get_param("biosdetect", base)->set_enabled(1);
117 SIM->get_param("translation", base)->set_enabled(0);
118 SIM->get_param("path", base)->set_runtime_param(1);
119 SIM->get_param("status", base)->set_runtime_param(1);
120 break;
124 } else {
125 param->get_param_path(pname, BX_PATHNAME_LEN);
126 if (!strcmp(pname, BXPN_LOAD32BITOS_WHICH)) {
127 if (set) {
128 int enable = (val != Load32bitOSNone);
129 SIM->get_param(BXPN_LOAD32BITOS_PATH)->set_enabled(enable);
130 SIM->get_param(BXPN_LOAD32BITOS_IOLOG)->set_enabled(enable);
131 SIM->get_param(BXPN_LOAD32BITOS_INITRD)->set_enabled(enable);
133 } else if (!strcmp(pname, BXPN_FLOPPYA_TYPE)) {
134 if (set) {
135 if (val == BX_FLOPPY_AUTO) {
136 val = get_floppy_type_from_image(SIM->get_param_string(BXPN_FLOPPYA_PATH)->getptr());
137 SIM->get_param_enum(BXPN_FLOPPYA_TYPE)->set(val);
138 } else if (!SIM->get_init_done()) {
139 SIM->get_param_enum(BXPN_FLOPPYA_DEVTYPE)->set(val);
142 } else if (!strcmp(pname, BXPN_FLOPPYB_TYPE)) {
143 if (set) {
144 if (val == BX_FLOPPY_AUTO) {
145 val = get_floppy_type_from_image(SIM->get_param_string(BXPN_FLOPPYB_PATH)->getptr());
146 SIM->get_param_enum(BXPN_FLOPPYB_TYPE)->set(val);
147 } else if (!SIM->get_init_done()) {
148 SIM->get_param_enum(BXPN_FLOPPYB_DEVTYPE)->set(val);
151 } else if (!strcmp(pname, BXPN_FLOPPYA_STATUS)) {
152 if ((set) && (SIM->get_init_done())) {
153 DEV_floppy_set_media_status(0, val == BX_INSERTED);
154 bx_gui->update_drive_status_buttons();
156 } else if (!strcmp(pname, BXPN_FLOPPYB_STATUS)) {
157 if ((set) && (SIM->get_init_done())) {
158 DEV_floppy_set_media_status(1, val == BX_INSERTED);
159 bx_gui->update_drive_status_buttons();
161 } else {
162 BX_PANIC(("bx_param_handler called with unknown parameter '%s'", pname));
163 return -1;
166 return val;
169 const char *bx_param_string_handler(bx_param_string_c *param, int set, const char *val, int maxlen)
171 char pname[BX_PATHNAME_LEN];
172 Bit8u channel, device;
174 int empty = 0;
175 if ((strlen(val) < 1) || !strcmp ("none", val)) {
176 empty = 1;
177 val = "none";
179 bx_list_c *base = (bx_list_c*) param->get_parent();
180 base->get_param_path(pname, BX_PATHNAME_LEN);
181 if (!strncmp(pname, "ata.", 4)) {
182 channel = pname[4] - '0';
183 if (!strcmp(base->get_name(), "master")) {
184 device = 0;
185 } else {
186 device = 1;
188 if (!strcmp(param->get_name(), "path")) {
189 if (set==1) {
190 if (SIM->get_init_done()) {
191 Bit32u handle = DEV_hd_get_device_handle(channel, device);
192 if (empty) {
193 DEV_hd_set_cd_media_status(handle, 0);
194 bx_gui->update_drive_status_buttons();
195 } else {
196 if (!SIM->get_param_num("present", base)->get()) {
197 BX_ERROR(("Cannot add a cdrom drive at runtime"));
198 SIM->get_param_num("present", base)->set(0);
200 if (SIM->get_param_num("type", base)->get() != BX_ATA_DEVICE_CDROM) {
201 BX_ERROR(("Device is not a cdrom drive"));
202 SIM->get_param_num("present", base)->set(0);
205 if (DEV_hd_present() &&
206 (SIM->get_param_num("status", base)->get() == BX_INSERTED) &&
207 (SIM->get_param_num("type", base)->get() == BX_ATA_DEVICE_CDROM)) {
208 // tell the device model that we removed, then inserted the cd
209 DEV_hd_set_cd_media_status(handle, 0);
210 DEV_hd_set_cd_media_status(handle, 1);
215 } else {
216 param->get_param_path(pname, BX_PATHNAME_LEN);
217 if (!strcmp(pname, BXPN_SCREENMODE)) {
218 if (set==1) {
219 BX_INFO(("Screen mode changed to %s", val));
221 } else if (!strcmp(pname, BXPN_FLOPPYA_PATH)) {
222 if (set==1) {
223 if (SIM->get_init_done()) {
224 if (empty) {
225 DEV_floppy_set_media_status(0, 0);
226 bx_gui->update_drive_status_buttons();
227 } else {
228 if (!SIM->get_param_num(BXPN_FLOPPYA_TYPE)->get_enabled()) {
229 BX_ERROR(("Cannot add a floppy drive at runtime"));
230 SIM->get_param_string(BXPN_FLOPPYA_PATH)->set("none");
233 if ((DEV_floppy_present()) &&
234 (SIM->get_param_enum(BXPN_FLOPPYA_STATUS)->get() == BX_INSERTED)) {
235 // tell the device model that we removed, then inserted the disk
236 DEV_floppy_set_media_status(0, 0);
237 DEV_floppy_set_media_status(0, 1);
239 } else {
240 SIM->get_param_enum(BXPN_FLOPPYA_TYPE)->set_enabled(!empty);
241 SIM->get_param_enum(BXPN_FLOPPYA_STATUS)->set_enabled(!empty);
244 } else if (!strcmp(pname, BXPN_FLOPPYB_PATH)) {
245 if (set==1) {
246 if (SIM->get_init_done()) {
247 if (empty) {
248 DEV_floppy_set_media_status(1, 0);
249 bx_gui->update_drive_status_buttons();
250 } else {
251 if (!SIM->get_param_num(BXPN_FLOPPYB_TYPE)->get_enabled()) {
252 BX_ERROR(("Cannot add a floppy drive at runtime"));
253 SIM->get_param_string(BXPN_FLOPPYB_PATH)->set("none");
256 if ((DEV_floppy_present()) &&
257 (SIM->get_param_enum(BXPN_FLOPPYB_STATUS)->get() == BX_INSERTED)) {
258 // tell the device model that we removed, then inserted the disk
259 DEV_floppy_set_media_status(1, 0);
260 DEV_floppy_set_media_status(1, 1);
262 } else {
263 SIM->get_param_enum(BXPN_FLOPPYB_TYPE)->set_enabled(!empty);
264 SIM->get_param_enum(BXPN_FLOPPYB_STATUS)->set_enabled(!empty);
267 } else {
268 BX_PANIC(("bx_param_string_handler called with unknown parameter '%s'", pname));
271 return val;
274 static int bx_param_enable_handler (bx_param_c *param, int val)
276 char pname[BX_PATHNAME_LEN];
277 Bit8u channel, device;
279 bx_list_c *base = (bx_list_c*) param->get_parent();
280 base->get_param_path(pname, BX_PATHNAME_LEN);
281 if (!strncmp(pname, "ata.", 4)) {
282 channel = pname[4] - '0';
283 if (!strcmp(base->get_name(), "master")) {
284 device = 0;
285 } else {
286 device = 1;
288 if (!strcmp(param->get_name(), "status")) {
289 if (val != 0) {
290 switch (SIM->get_param_enum("type", base)->get()) {
291 case BX_ATA_DEVICE_CDROM:
292 return (1);
293 break;
296 } else if (!strcmp(param->get_name(), "journal")) {
297 if (val != 0) {
298 switch (SIM->get_param_enum("type", base)->get()) {
299 case BX_ATA_DEVICE_DISK:
300 switch (SIM->get_param_enum("mode", base)->get()) {
301 case BX_ATA_MODE_UNDOABLE:
302 case BX_ATA_MODE_VOLATILE:
303 // case BX_ATA_MODE_Z_UNDOABLE:
304 // case BX_ATA_MODE_Z_VOLATILE:
305 return (1);
306 break;
310 return (0);
311 } else {
312 BX_PANIC(("bx_param_enable_handler called with unknown parameter '%s'", pname));
314 } else {
315 BX_PANIC(("bx_param_enable_handler called with unknown parameter '%s'", pname));
317 return val;
320 void bx_init_options()
322 int i;
323 bx_list_c *menu;
324 bx_list_c *deplist;
325 bx_param_num_c *ioaddr, *ioaddr2, *irq;
326 bx_param_bool_c *enabled;
327 bx_param_enum_c *mode, *status, *type, *ethmod;
328 bx_param_string_c *macaddr, *ethdev;
329 bx_param_filename_c *path;
330 char name[BX_PATHNAME_LEN], descr[512], group[16], label[512];
332 bx_param_c *root_param = SIM->get_param(".");
334 // general options subtree
335 menu = new bx_list_c(root_param, "general", "");
337 // config interface option, set in bochsrc or command line
338 static char *config_interface_list[] = {
339 #if BX_USE_TEXTCONFIG
340 "textconfig",
341 #endif
342 #if BX_WITH_WX
343 "wx",
344 #endif
345 NULL
347 bx_param_enum_c *sel_config = new bx_param_enum_c(menu,
348 "config_interface", "Configuration interface",
349 "Select configuration interface",
350 config_interface_list,
353 sel_config->set_by_name(BX_DEFAULT_CONFIG_INTERFACE);
355 // quick start option, set by command line arg
356 new bx_param_enum_c(menu,
357 "start_mode",
358 "Bochs start types",
359 "Bochs start types",
360 bochs_start_names,
361 BX_RUN_START,
362 BX_QUICK_START);
364 #if BX_SUPPORT_SAVE_RESTORE
365 new bx_param_bool_c(menu,
366 "restore",
367 "Restore Bochs session",
368 "Restore Bochs session",
370 new bx_param_string_c(menu,
371 "restore_path",
372 "Path to data for restore",
373 "Path to data for restore",
375 BX_PATHNAME_LEN);
376 #endif
378 // subtree for special menus
379 bx_list_c *special_menus = new bx_list_c(root_param, "menu", "");
381 #if BX_SUPPORT_SMP
382 #define BX_CPU_PROCESSORS_LIMIT 8
383 #define BX_CPU_CORES_LIMIT 4
384 #define BX_CPU_HT_THREADS_LIMIT 4
385 #else
386 #define BX_CPU_PROCESSORS_LIMIT 1
387 #define BX_CPU_CORES_LIMIT 1
388 #define BX_CPU_HT_THREADS_LIMIT 1
389 #endif
391 // cpu subtree
392 bx_list_c *cpu_param = new bx_list_c(root_param, "cpu", "CPU Options");
394 // cpu options
395 bx_param_num_c *nprocessors = new bx_param_num_c(cpu_param,
396 "n_processors", "Number of CPUs in SMP mode",
397 "Sets the number of CPUs for multiprocessor emulation",
398 1, BX_CPU_PROCESSORS_LIMIT,
400 nprocessors->set_enabled(BX_CPU_PROCESSORS_LIMIT > 1);
401 bx_param_num_c *ncores = new bx_param_num_c(cpu_param,
402 "n_cores", "Number of processor cores in each CPU in SMP mode",
403 "Sets the number of processor cores per CPU for multiprocessor emulation",
404 1, BX_CPU_CORES_LIMIT,
406 ncores->set_enabled(BX_CPU_CORES_LIMIT > 1);
407 bx_param_num_c *nthreads = new bx_param_num_c(cpu_param,
408 "n_threads", "Number of HT threads per each process core in SMP mode",
409 "Sets the number of HT (Intel(R) HyperThreading Technology) threads per core for multiprocessor emulation",
410 1, BX_CPU_HT_THREADS_LIMIT,
412 nthreads->set_enabled(BX_CPU_HT_THREADS_LIMIT > 1);
413 new bx_param_num_c(cpu_param,
414 "ips", "Emulated instructions per second (IPS)",
415 "Emulated instructions per second, used to calibrate bochs emulated time with wall clock time.",
416 1, BX_MAX_BIT32U,
417 2000000);
418 #if BX_SUPPORT_SMP
419 new bx_param_num_c(cpu_param,
420 "quantum", "Quantum ticks in SMP simulation",
421 "Maximum amount of instructions allowed to execute before returning control to another CPU.",
422 BX_SMP_QUANTUM_MIN, BX_SMP_QUANTUM_MAX,
424 #endif
425 new bx_param_bool_c(cpu_param,
426 "reset_on_triple_fault", "Enable CPU reset on triple fault",
427 "Enable CPU reset if triple fault occured (highly recommended)",
429 cpu_param->get_options()->set(menu->SHOW_PARENT);
431 // memory subtree
432 bx_list_c *memory = new bx_list_c(root_param, "memory", "Memory Options");
433 bx_list_c *stdmem = new bx_list_c(memory, "standard", "Standard Options");
434 bx_list_c *optrom = new bx_list_c(memory, "optrom", "Optional ROM Images");
435 bx_list_c *optram = new bx_list_c(memory, "optram", "Optional RAM Images");
436 bx_list_c *ram = new bx_list_c(stdmem, "ram", "");
437 bx_list_c *rom = new bx_list_c(stdmem, "rom", "");
438 bx_list_c *vgarom = new bx_list_c(stdmem, "vgarom", "");
440 // memory options (ram & rom)
441 bx_param_num_c *ramsize = new bx_param_num_c(ram,
442 "size",
443 "Memory size (megabytes)",
444 "Amount of RAM in megabytes",
445 1, 2048,
446 BX_DEFAULT_MEM_MEGS);
447 ramsize->set_ask_format("Enter memory size (MB): [%d] ");
448 #if BX_WITH_WX
449 ramsize->set_options(bx_param_num_c::USE_SPIN_CONTROL);
450 #endif
452 path = new bx_param_filename_c(rom,
453 "path",
454 "ROM BIOS image",
455 "Pathname of ROM image to load",
456 "", BX_PATHNAME_LEN);
457 path->set_format("Name of ROM BIOS image: %s");
458 sprintf(name, "%s/BIOS-bochs-latest", get_builtin_variable("BXSHARE"));
459 path->set_initial_val(name);
460 bx_param_num_c *romaddr = new bx_param_num_c(rom,
461 "addr",
462 "ROM BIOS address",
463 "The address at which the ROM image should be loaded",
464 0, BX_MAX_BIT32U,
466 romaddr->set_base(16);
467 romaddr->set_format("0x%05x");
468 romaddr->set_long_format("ROM BIOS address: 0x%05x");
470 path = new bx_param_filename_c(vgarom,
471 "path",
472 "VGA BIOS image",
473 "Pathname of VGA ROM image to load",
474 "", BX_PATHNAME_LEN);
475 path->set_format("Name of VGA BIOS image: %s");
476 sprintf(name, "%s/VGABIOS-lgpl-latest", get_builtin_variable("BXSHARE"));
477 path->set_initial_val(name);
479 bx_param_num_c *optaddr;
481 for (i=0; i<BX_N_OPTROM_IMAGES; i++) {
482 sprintf(name, "%d", i+1);
483 sprintf(descr, "Pathname of optional ROM image #%d to load", i+1);
484 sprintf(label, "Optional ROM image #%d", i+1);
485 bx_list_c *optnum1 = new bx_list_c(optrom, name, label);
486 path = new bx_param_filename_c(optnum1,
487 "path",
488 "Path",
489 descr,
490 "", BX_PATHNAME_LEN);
491 sprintf(label, "Name of optional ROM image #%d", i+1);
492 strcat(label, " : %s");
493 path->set_format(strdup(label));
494 sprintf(descr, "The address at which the optional ROM image #%d should be loaded", i+1);
495 optaddr = new bx_param_num_c(optnum1,
496 "addr",
497 "Address",
498 descr,
499 0, BX_MAX_BIT32U,
501 optaddr->set_base(16);
502 optaddr->set_format("0x%05x");
503 sprintf(label, "Optional ROM #%d address:", i+1);
504 strcat(label, " 0x%05x");
505 optaddr->set_long_format(strdup(label));
506 optnum1->get_options()->set(bx_list_c::SHOW_PARENT | bx_list_c::USE_BOX_TITLE);
508 optrom->get_options()->set(bx_list_c::SHOW_PARENT);
510 for (i=0; i<BX_N_OPTRAM_IMAGES; i++) {
511 sprintf(name, "%d", i+1);
512 sprintf(descr, "Pathname of optional RAM image #%d to load", i+1);
513 sprintf(label, "Optional RAM image #%d", i+1);
514 bx_list_c *optnum2 = new bx_list_c(optram, name, label);
515 path = new bx_param_filename_c(optnum2,
516 "path",
517 "Path",
518 descr,
519 "", BX_PATHNAME_LEN);
520 sprintf(label, "Name of optional RAM image #%d", i+1);
521 strcat(label, " : %s");
522 path->set_format(strdup(label));
523 sprintf(descr, "The address at which the optional RAM image #%d should be loaded", i+1);
524 optaddr = new bx_param_num_c(optnum2,
525 "addr",
526 "Address",
527 descr,
528 0, BX_MAX_BIT32U,
530 optaddr->set_base(16);
531 optaddr->set_format("0x%05x");
532 sprintf(label, "Optional RAM #%d address:", i+1);
533 strcat(label, " 0x%05x");
534 optaddr->set_long_format(strdup(label));
535 optnum2->get_options()->set(bx_list_c::SHOW_PARENT | bx_list_c::USE_BOX_TITLE);
537 optrom->get_options()->set(bx_list_c::SHOW_PARENT);
538 memory->get_options()->set(bx_list_c::USE_TAB_WINDOW);
540 bx_param_c *memory_init_list[] = {
541 SIM->get_param(BXPN_MEM_SIZE),
542 SIM->get_param(BXPN_ROM_PATH),
543 SIM->get_param(BXPN_ROM_ADDRESS),
544 SIM->get_param(BXPN_VGA_ROM_PATH),
545 SIM->get_param("memory.optrom"),
546 SIM->get_param("memory.optram"),
547 NULL
549 menu = new bx_list_c(special_menus, "memory", "Bochs Memory Options", memory_init_list);
550 menu->get_options()->set(bx_list_c::SHOW_PARENT);
552 // clock & cmos subtree
553 bx_list_c *clock_cmos = new bx_list_c(root_param, "clock_cmos", "Clock & CMOS Options");
555 // clock & cmos options
556 bx_param_enum_c *clock_sync = new bx_param_enum_c(clock_cmos,
557 "clock_sync", "Synchronisation method",
558 "Host to guest time synchronization method",
559 clock_sync_names,
560 BX_CLOCK_SYNC_NONE,
561 BX_CLOCK_SYNC_NONE);
562 bx_param_num_c *time0 = new bx_param_num_c(clock_cmos,
563 "time0",
564 "Initial CMOS time for Bochs\n(1:localtime, 2:utc, other:time in seconds)",
565 "Initial time for Bochs CMOS clock, used if you really want two runs to be identical",
566 0, BX_MAX_BIT32U,
567 BX_CLOCK_TIME0_LOCAL);
569 bx_list_c *cmosimage = new bx_list_c(clock_cmos, "cmosimage", "CMOS Image Options");
570 bx_param_bool_c *use_cmosimage = new bx_param_bool_c(cmosimage,
571 "enabled", "Use a CMOS image",
572 "Controls the usage of a CMOS image",
574 path = new bx_param_filename_c(cmosimage,
575 "path", "Pathname of CMOS image",
576 "Pathname of CMOS image",
577 "", BX_PATHNAME_LEN);
578 bx_param_bool_c *rtc_init = new bx_param_bool_c(cmosimage,
579 "rtc_init", "Initialize RTC from image",
580 "Controls whether to initialize the RTC with values stored in the image",
582 deplist = new bx_list_c(NULL, 2);
583 deplist->add(path);
584 deplist->add(rtc_init);
585 use_cmosimage->set_dependent_list(deplist);
587 time0->set_ask_format("Enter Initial CMOS time (1:localtime, 2:utc, other:time in seconds): [%d] ");
588 clock_sync->set_ask_format("Enter Synchronisation method: [%s] ");
589 clock_cmos->get_options()->set(bx_list_c::SHOW_PARENT);
590 cmosimage->get_options()->set(bx_list_c::SHOW_PARENT);
592 // pci subtree
593 bx_list_c *pci = new bx_list_c(root_param, "pci", "PCI Options");
595 // pci options
596 bx_param_c *pci_deps_list[1+BX_N_PCI_SLOTS];
597 bx_param_c **pci_deps_ptr = &pci_deps_list[0];
599 bx_param_bool_c *i440fx_support = new bx_param_bool_c(pci,
600 "i440fx_support",
601 "Enable i440FX PCI Support",
602 "Controls whether to emulate the i440FX PCI chipset",
603 BX_SUPPORT_PCI);
604 // pci slots
605 bx_list_c *slot = new bx_list_c(pci, "slot", "PCI Slots");
606 *pci_deps_ptr++ = slot;
607 for (i=0; i<BX_N_PCI_SLOTS; i++) {
608 sprintf(name, "%d", i+1);
609 sprintf (descr, "Name of the device connected to PCI slot #%d", i+1);
610 sprintf (label, "PCI slot #%d device", i+1);
611 bx_param_string_c *devname = new bx_param_string_c(slot,
612 name,
613 label,
614 descr,
615 "", BX_PATHNAME_LEN);
616 // add to deplist
617 *pci_deps_ptr++ = devname;
619 // pcidev options
620 bx_list_c *pcidev = new bx_list_c(pci, "pcidev", "Host PCI Device Mapping");
621 *pci_deps_ptr++ = pcidev;
622 bx_param_num_c *pcivid = new bx_param_num_c(pcidev,
623 "vendor",
624 "PCI Vendor ID",
625 "The vendor ID of the host PCI device to map",
626 0, 0xffff,
627 0xffff); // vendor id 0xffff = no pci device present
628 pcivid->set_base(16);
629 pcivid->set_format("0x%04x");
630 pcivid->set_long_format("PCI Vendor ID: 0x%04x");
631 #if BX_SUPPORT_PCIDEV
632 *pci_deps_ptr++ = pcivid;
633 #else
634 pcivid->set_enabled(0);
635 #endif
636 bx_param_num_c *pcidid = new bx_param_num_c(pcidev,
637 "device",
638 "PCI Device ID",
639 "The device ID of the host PCI device to map",
640 0, 0xffff,
641 0x0);
642 pcidid->set_base(16);
643 pcidid->set_format("0x%04x");
644 pcidid->set_long_format("PCI Device ID: 0x%04x");
645 #if BX_SUPPORT_PCIDEV
646 *pci_deps_ptr++ = pcidid;
647 #else
648 pcidid->set_enabled(0);
649 #endif
650 // add final NULL at the end, and build the menu
651 *pci_deps_ptr = NULL;
652 i440fx_support->set_dependent_list(new bx_list_c(NULL, "", "", pci_deps_list));
653 pci->get_options()->set(bx_list_c::SHOW_PARENT);
654 slot->get_options()->set(bx_list_c::SHOW_PARENT);
655 pcidev->get_options()->set(bx_list_c::SHOW_PARENT | bx_list_c::USE_BOX_TITLE);
657 // display subtree
658 bx_list_c *display = new bx_list_c(root_param, "display", "Bochs Display & Interface Options", 7);
660 // this is a list of gui libraries that are known to be available at
661 // compile time. The one that is listed first will be the default,
662 // which is used unless the user overrides it on the command line or
663 // in a configuration file.
664 static char *display_library_list[] = {
665 #if BX_WITH_X11
666 "x",
667 #endif
668 #if BX_WITH_WIN32
669 "win32",
670 #endif
671 #if BX_WITH_CARBON
672 "carbon",
673 #endif
674 #if BX_WITH_BEOS
675 "beos",
676 #endif
677 #if BX_WITH_MACOS
678 "macos",
679 #endif
680 #if BX_WITH_AMIGAOS
681 "amigaos",
682 #endif
683 #if BX_WITH_SDL
684 "sdl",
685 #endif
686 #if BX_WITH_SVGA
687 "svga",
688 #endif
689 #if BX_WITH_TERM
690 "term",
691 #endif
692 #if BX_WITH_RFB
693 "rfb",
694 #endif
695 #if BX_WITH_WX
696 "wx",
697 #endif
698 #if BX_WITH_NOGUI
699 "nogui",
700 #endif
701 NULL
703 bx_param_enum_c *sel_displaylib = new bx_param_enum_c(display,
704 "display_library", "VGA Display Library",
705 "Select VGA Display Library",
706 display_library_list,
709 sel_displaylib->set_by_name(BX_DEFAULT_DISPLAY_LIBRARY);
710 sel_displaylib->set_ask_format("Choose which library to use for the Bochs display: [%s] ");
712 new bx_param_string_c(display,
713 "displaylib_options", "Display Library options",
714 "Options passed to Display Library",
716 BX_PATHNAME_LEN);
718 new bx_param_bool_c(display,
719 "private_colormap", "Use a private colormap",
720 "Request that the GUI create and use it's own non-shared colormap. This colormap will be used when in the bochs window. If not enabled, a shared colormap scheme may be used. Not implemented on all GUI's.",
723 bx_param_bool_c *fullscreen = new bx_param_bool_c(display,
724 "fullscreen", "Use full screen mode",
725 "When enabled, bochs occupies the whole screen instead of just a window.",
727 bx_param_string_c *screenmode = new bx_param_string_c(display,
728 "screenmode",
729 "Screen mode name",
730 "Screen mode name",
731 "", BX_PATHNAME_LEN);
732 screenmode->set_handler(bx_param_string_handler);
733 #if !BX_WITH_AMIGAOS
734 fullscreen->set_enabled(0);
735 screenmode->set_enabled(0);
736 #endif
738 bx_param_num_c *vga_update_interval = new bx_param_num_c(display,
739 "vga_update_interval",
740 "VGA Update Interval",
741 "Number of microseconds between VGA updates",
742 1, BX_MAX_BIT32U,
743 40000);
744 vga_update_interval->set_ask_format ("Type a new value for VGA update interval: [%d] ");
746 bx_param_string_c *vga_extension = new bx_param_string_c(display,
747 "vga_extension",
748 "VGA Extension",
749 "Name of the VGA extension",
750 "none", BX_PATHNAME_LEN);
751 #if BX_SUPPORT_VBE
752 vga_extension->set_initial_val("vbe");
753 #elif BX_SUPPORT_CLGD54XX
754 vga_extension->set_initial_val("cirrus");
755 #endif
756 display->get_options()->set(bx_list_c::SHOW_PARENT);
758 // keyboard & mouse subtree
759 bx_list_c *kbd_mouse = new bx_list_c(root_param, "keyboard_mouse", "Keyboard & Mouse Options");
760 bx_list_c *keyboard = new bx_list_c(kbd_mouse, "keyboard", "Keyboard Options");
761 bx_list_c *mouse = new bx_list_c(kbd_mouse, "mouse", "Mouse Options");
763 // keyboard & mouse options
764 type = new bx_param_enum_c(keyboard,
765 "type", "Keyboard type",
766 "Keyboard type reported by the 'identify keyboard' command",
767 keyboard_type_names,
768 BX_KBD_MF_TYPE,
769 BX_KBD_XT_TYPE);
770 type->set_ask_format ("Enter keyboard type: [%s] ");
772 new bx_param_num_c(keyboard,
773 "serial_delay", "Keyboard serial delay",
774 "Approximate time in microseconds that it takes one character to be transfered from the keyboard to controller over the serial path.",
775 1, BX_MAX_BIT32U,
776 250);
777 new bx_param_num_c(keyboard,
778 "paste_delay", "Keyboard paste delay",
779 "Approximate time in microseconds between attemps to paste characters to the keyboard controller.",
780 1000, BX_MAX_BIT32U,
781 100000);
782 bx_param_bool_c *use_kbd_mapping = new bx_param_bool_c(keyboard,
783 "use_mapping", "Use keyboard mapping",
784 "Controls whether to use the keyboard mapping feature",
786 bx_param_filename_c *keymap = new bx_param_filename_c(keyboard,
787 "keymap", "Keymap filename",
788 "Pathname of the keymap file used",
789 "", BX_PATHNAME_LEN);
790 deplist = new bx_list_c(NULL, 1);
791 deplist->add(keymap);
792 use_kbd_mapping->set_dependent_list(deplist);
794 bx_param_string_c *user_shortcut = new bx_param_string_c(keyboard,
795 "user_shortcut",
796 "Userbutton shortcut",
797 "Defines the keyboard shortcut to be sent when you press the 'user' button in the headerbar.",
798 "none", 20);
799 user_shortcut->set_runtime_param(1);
801 static char *mouse_type_list[] = {
802 "none",
803 "ps2",
804 "imps2",
805 #if BX_SUPPORT_BUSMOUSE
806 "bus",
807 #endif
808 "serial",
809 "serial_wheel",
810 "serial_msys",
811 NULL
813 type = new bx_param_enum_c(mouse,
814 "type", "Mouse type",
815 "The mouse type can be one of these: 'none', 'ps2', 'imps2', 'serial', 'serial_wheel'"
816 #if BX_SUPPORT_BUSMOUSE
817 ", 'bus'"
818 #endif
820 mouse_type_list,
821 BX_MOUSE_TYPE_PS2,
822 BX_MOUSE_TYPE_NONE);
823 type->set_ask_format("Choose the type of mouse [%s] ");
825 new bx_param_bool_c(mouse,
826 "enabled", "Enable the mouse capture",
827 "Controls whether the mouse sends events to the guest. The hardware emulation is always enabled.",
829 kbd_mouse->get_options()->set(bx_list_c::SHOW_PARENT);
830 keyboard->get_options()->set(bx_list_c::SHOW_PARENT);
831 mouse->get_options()->set(bx_list_c::SHOW_PARENT);
833 // boot parameter subtree
834 bx_list_c *boot_params = new bx_list_c(root_param, "boot_params", "Boot Options");
835 // boot sequence
836 for (i=0; i<3; i++) {
837 sprintf(name, "boot_drive%d", i+1);
838 sprintf(label, "Boot drive #%d", i+1);
839 sprintf(descr, "Name of drive #%d in boot sequence (A, C or CD)", i+1);
840 bx_param_enum_c *bootdrive = new bx_param_enum_c(boot_params,
841 name,
842 label,
843 descr,
844 &bochs_bootdisk_names[(i==0)?BX_BOOT_FLOPPYA:BX_BOOT_NONE],
845 (i==0)?BX_BOOT_FLOPPYA:BX_BOOT_NONE,
846 (i==0)?BX_BOOT_FLOPPYA:BX_BOOT_NONE);
847 bootdrive->set_ask_format("Boot from floppy drive, hard drive or cdrom ? [%s] ");
850 new bx_param_bool_c(boot_params,
851 "floppy_sig_check",
852 "Skip Floppy Boot Signature Check",
853 "Skips check for the 0xaa55 signature on floppy boot device.",
856 // loader hack
857 bx_list_c *load32bitos = new bx_list_c(boot_params, "load32bitos", "32-bit OS Loader Hack");
858 bx_param_enum_c *whichOS = new bx_param_enum_c(load32bitos,
859 "which",
860 "Which operating system?",
861 "Which OS to boot",
862 loader_os_names,
863 Load32bitOSNone,
864 Load32bitOSNone);
865 path = new bx_param_filename_c(load32bitos,
866 "path",
867 "Pathname of OS to load",
868 "Pathname of the 32-bit OS to load",
869 "", BX_PATHNAME_LEN);
870 bx_param_filename_c *iolog = new bx_param_filename_c(load32bitos,
871 "iolog",
872 "Pathname of I/O log file",
873 "I/O logfile used for initializing the hardware",
874 "", BX_PATHNAME_LEN);
875 bx_param_filename_c *initrd = new bx_param_filename_c(load32bitos,
876 "initrd",
877 "Pathname of initrd",
878 "Pathname of the initial ramdisk",
879 "", BX_PATHNAME_LEN);
880 whichOS->set_ask_format("Enter OS to load: [%s] ");
881 path->set_ask_format("Enter pathname of OS: [%s]");
882 iolog->set_ask_format("Enter pathname of I/O log: [%s] ");
883 initrd->set_ask_format("Enter pathname of initrd: [%s] ");
884 load32bitos->get_options()->set(menu->SERIES_ASK);
885 whichOS->set_handler(bx_param_handler);
886 whichOS->set(Load32bitOSNone);
887 boot_params->get_options()->set(bx_list_c::SHOW_PARENT);
889 // floppy subtree
890 bx_list_c *floppy = new bx_list_c(root_param, "floppy", "Floppy Options");
891 bx_list_c *floppya = new bx_list_c(floppy, "0", "Floppy Disk 0");
892 bx_list_c *floppyb = new bx_list_c(floppy, "1", "Floppy Disk 1");
894 bx_param_enum_c *devtype;
895 // floppy options
896 path = new bx_param_filename_c(floppya,
897 "path",
898 "First floppy image/device",
899 "Pathname of first floppy image file or device. If you're booting from floppy, this should be a bootable floppy.",
900 "", BX_PATHNAME_LEN);
901 path->set_ask_format("Enter new filename, or 'none' for no disk: [%s] ");
902 path->set_runtime_param(1);
904 devtype = new bx_param_enum_c(floppya,
905 "devtype",
906 "Type of floppy drive",
907 "Type of floppy drive",
908 floppy_type_names,
909 BX_FLOPPY_NONE,
910 BX_FLOPPY_NONE);
911 devtype->set_enabled(0); // hide devtype parameter
912 type = new bx_param_enum_c(floppya,
913 "type",
914 "Type of floppy disk",
915 "Type of floppy disk",
916 floppy_type_names,
917 BX_FLOPPY_NONE,
918 BX_FLOPPY_NONE);
919 type->set_ask_format("What type of floppy disk? (auto=detect) [%s] ");
920 type->set_runtime_param(1);
922 status = new bx_param_enum_c(floppya,
923 "status",
924 "Is floppya inserted",
925 "Inserted or ejected",
926 floppy_status_names,
927 BX_INSERTED,
928 BX_EJECTED);
929 status->set_ask_format("Is the floppy inserted or ejected? [%s] ");
930 status->set_runtime_param(1);
932 path->set_handler(bx_param_string_handler);
933 type->set_handler(bx_param_handler);
934 status->set_handler(bx_param_handler);
935 path->set_initial_val("none");
936 floppya->get_options()->set(bx_list_c::SERIES_ASK);
938 path = new bx_param_filename_c(floppyb,
939 "path",
940 "Second floppy image/device",
941 "Pathname of second floppy image file or device.",
942 "", BX_PATHNAME_LEN);
943 path->set_ask_format("Enter new filename, or 'none' for no disk: [%s] ");
944 path->set_runtime_param(1);
946 devtype = new bx_param_enum_c(floppyb,
947 "devtype",
948 "Type of floppy drive",
949 "Type of floppy drive",
950 floppy_type_names,
951 BX_FLOPPY_NONE,
952 BX_FLOPPY_NONE);
953 devtype->set_enabled(0); // hide devtype parameter
954 type = new bx_param_enum_c(floppyb,
955 "type",
956 "Type of floppy disk",
957 "Type of floppy disk",
958 floppy_type_names,
959 BX_FLOPPY_NONE,
960 BX_FLOPPY_NONE);
961 type->set_ask_format("What type of floppy disk? (auto=detect) [%s] ");
962 type->set_runtime_param(1);
964 status = new bx_param_enum_c(floppyb,
965 "status",
966 "Is floppyb inserted",
967 "Inserted or ejected",
968 floppy_status_names,
969 BX_INSERTED,
970 BX_EJECTED);
971 status->set_ask_format("Is the floppy inserted or ejected? [%s] ");
972 status->set_runtime_param(1);
974 path->set_handler(bx_param_string_handler);
975 type->set_handler(bx_param_handler);
976 status->set_handler(bx_param_handler);
977 path->set_initial_val("none");
978 floppyb->get_options()->set(bx_list_c::SERIES_ASK);
979 floppy->get_options()->set(bx_list_c::SHOW_PARENT);
981 // ATA/ATAPI subtree
982 bx_list_c *ata = new bx_list_c(root_param, "ata", "ATA/ATAPI Options");
984 // disk options
985 char *s_atachannel[] = {
986 "ATA channel 0",
987 "ATA channel 1",
988 "ATA channel 2",
989 "ATA channel 3",
991 char *s_atadevname[2] = {
992 "master",
993 "slave",
995 char *s_atadevice[4][2] = {
996 { "First HD/CD on channel 0",
997 "Second HD/CD on channel 0" },
998 { "First HD/CD on channel 1",
999 "Second HD/CD on channel 1" },
1000 { "First HD/CD on channel 2",
1001 "Second HD/CD on channel 2" },
1002 { "First HD/CD on channel 3",
1003 "Second HD/CD on channel 3" }
1005 Bit16u ata_default_ioaddr1[4] = {
1006 0x1f0, 0x170, 0x1e8, 0x168
1008 Bit16u ata_default_ioaddr2[4] = {
1009 0x3f0, 0x370, 0x3e0, 0x360
1011 Bit8u ata_default_irq[4] = {
1012 14, 15, 11, 9
1015 #define BXP_PARAMS_PER_ATA_DEVICE 12
1017 bx_list_c *ata_menu[BX_MAX_ATA_CHANNEL];
1018 bx_list_c *ata_res[BX_MAX_ATA_CHANNEL];
1020 Bit8u channel;
1021 for (channel=0; channel<BX_MAX_ATA_CHANNEL; channel++) {
1023 sprintf(name, "%d", channel);
1024 ata_menu[channel] = new bx_list_c(ata, name, s_atachannel[channel]);
1025 ata_menu[channel]->get_options()->set(bx_list_c::USE_TAB_WINDOW);
1026 ata_res[channel] = new bx_list_c(ata_menu[channel], "resources", s_atachannel[channel], 8);
1027 ata_res[channel]->get_options()->set(bx_list_c::SERIES_ASK);
1029 enabled = new bx_param_bool_c(ata_res[channel],
1030 "enabled",
1031 "Enable ATA channel",
1032 "Controls whether ata channel is installed or not",
1034 enabled->set_ask_format("Channel is enabled: [%s] ");
1036 ioaddr = new bx_param_num_c(ata_res[channel],
1037 "ioaddr1",
1038 "I/O Address 1",
1039 "IO adress of ata command block",
1040 0, 0xffff,
1041 ata_default_ioaddr1[channel]);
1042 ioaddr->set_base(16);
1043 ioaddr->set_ask_format("Enter new ioaddr1: [0x%x] ");
1045 ioaddr2 = new bx_param_num_c(ata_res[channel],
1046 "ioaddr2",
1047 "I/O Address 2",
1048 "IO adress of ata control block",
1049 0, 0xffff,
1050 ata_default_ioaddr2[channel]);
1051 ioaddr2->set_base(16);
1052 ioaddr2->set_ask_format("Enter new ioaddr2: [0x%x] ");
1054 irq = new bx_param_num_c(ata_res[channel],
1055 "irq",
1056 "IRQ",
1057 "IRQ used by this ata channel",
1058 0, 15,
1059 ata_default_irq[channel]);
1060 irq->set_ask_format("Enter new IRQ: [%d] ");
1061 irq->set_options(bx_param_num_c::USE_SPIN_CONTROL);
1063 // all items in the ata[channel] menu depend on the enabled flag.
1064 // The menu list is complete, but a few dependent_list items will
1065 // be added later. Use clone() to make a copy of the dependent_list
1066 // so that it can be changed without affecting the menu.
1067 enabled->set_dependent_list(ata_res[channel]->clone());
1069 for (Bit8u slave=0; slave<2; slave++) {
1070 menu = new bx_list_c(ata_menu[channel],
1071 s_atadevname[slave],
1072 s_atadevice[channel][slave],
1073 BXP_PARAMS_PER_ATA_DEVICE + 1);
1074 menu->get_options()->set(bx_list_c::SERIES_ASK);
1076 bx_param_bool_c *present = new bx_param_bool_c(menu,
1077 "present",
1078 "Enable this device",
1079 "Controls whether ata device is installed or not",
1081 present->set_ask_format("Device is enabled: [%s] ");
1083 type = new bx_param_enum_c(menu,
1084 "type",
1085 "Type of ATA device",
1086 "Type of ATA device (disk or cdrom)",
1087 atadevice_type_names,
1088 BX_ATA_DEVICE_DISK,
1089 BX_ATA_DEVICE_DISK);
1090 type->set_ask_format("Enter type of ATA device, disk or cdrom: [%s] ");
1092 path = new bx_param_filename_c(menu,
1093 "path",
1094 "Path or physical device name",
1095 "Pathname of the image or physical device (cdrom only)",
1096 "", BX_PATHNAME_LEN);
1097 path->set_ask_format("Enter new filename: [%s] ");
1099 mode = new bx_param_enum_c(menu,
1100 "mode",
1101 "Type of disk image",
1102 "Mode of the ATA harddisk",
1103 atadevice_mode_names,
1104 BX_ATA_MODE_FLAT,
1105 BX_ATA_MODE_FLAT);
1106 mode->set_ask_format("Enter mode of ATA device, (flat, concat, etc.): [%s] ");
1108 status = new bx_param_enum_c(menu,
1109 "status",
1110 "Inserted",
1111 "CD-ROM media status (inserted / ejected)",
1112 atadevice_status_names,
1113 BX_INSERTED,
1114 BX_EJECTED);
1115 status->set_ask_format("Is the device inserted or ejected? [%s] ");
1117 bx_param_filename_c *journal = new bx_param_filename_c(menu,
1118 "journal",
1119 "Path of journal file",
1120 "Pathname of the journal file",
1121 "", BX_PATHNAME_LEN);
1122 journal->set_ask_format("Enter path of journal file: [%s]");
1124 bx_param_num_c *cylinders = new bx_param_num_c(menu,
1125 "cylinders",
1126 "Cylinders",
1127 "Number of cylinders",
1128 0, 262143,
1130 cylinders->set_ask_format("Enter number of cylinders: [%d] ");
1131 bx_param_num_c *heads = new bx_param_num_c(menu,
1132 "heads",
1133 "Heads",
1134 "Number of heads",
1135 0, 255,
1137 heads->set_ask_format("Enter number of heads: [%d] ");
1138 bx_param_num_c *spt = new bx_param_num_c(menu,
1139 "spt",
1140 "Sectors per track",
1141 "Number of sectors per track",
1142 0, 255,
1144 spt->set_ask_format("Enter number of sectors per track: [%d] ");
1146 bx_param_string_c *model = new bx_param_string_c(menu,
1147 "model",
1148 "Model name",
1149 "String returned by the 'identify device' command",
1150 "Generic 1234", 40);
1151 model->set_ask_format("Enter new model name: [%s]");
1153 bx_param_enum_c *biosdetect = new bx_param_enum_c(menu,
1154 "biosdetect",
1155 "BIOS Detection",
1156 "Type of bios detection",
1157 atadevice_biosdetect_names,
1158 BX_ATA_BIOSDETECT_AUTO,
1159 BX_ATA_BIOSDETECT_NONE);
1160 biosdetect->set_ask_format("Enter bios detection type: [%s]");
1162 bx_param_enum_c *translation = new bx_param_enum_c(menu,
1163 "translation",
1164 "Translation type",
1165 "How the ata-disk translation is done by the bios",
1166 atadevice_translation_names,
1167 BX_ATA_TRANSLATION_AUTO,
1168 BX_ATA_TRANSLATION_NONE);
1169 translation->set_ask_format("Enter translation type: [%s]");
1171 // the menu and all items on it depend on the present flag
1172 present->set_dependent_list(menu->clone());
1173 // the present flag depends on the ATA channel's enabled flag
1174 enabled->get_dependent_list()->add(present);
1175 // the master/slave menu depends on the ATA channel's enabled flag
1176 enabled->get_dependent_list()->add(menu);
1178 type->set_handler(bx_param_handler);
1179 mode->set_handler(bx_param_handler);
1180 status->set_handler(bx_param_handler);
1181 path->set_handler(bx_param_string_handler);
1183 // Set the enable_hanlders
1184 journal->set_enable_handler(bx_param_enable_handler);
1185 status->set_enable_handler(bx_param_enable_handler);
1188 // Enable two ATA interfaces by default, disable the others.
1189 // Now that the dependence relationships are established, call set() on
1190 // the ata device present params to set all enables correctly.
1191 enabled->set_initial_val(channel<2);
1192 enabled->set(channel<2);
1195 // disk menu
1196 bx_param_c *disk_menu_init_list[] = {
1197 SIM->get_param(BXPN_FLOPPYA),
1198 SIM->get_param(BXPN_FLOPPYB),
1199 SIM->get_param(BXPN_ATA0_RES),
1200 SIM->get_param(BXPN_ATA0_MASTER),
1201 SIM->get_param(BXPN_ATA0_SLAVE),
1202 #if BX_MAX_ATA_CHANNEL>1
1203 SIM->get_param(BXPN_ATA1_RES),
1204 SIM->get_param(BXPN_ATA1_MASTER),
1205 SIM->get_param(BXPN_ATA1_SLAVE),
1206 #endif
1207 #if BX_MAX_ATA_CHANNEL>2
1208 SIM->get_param(BXPN_ATA2_RES),
1209 SIM->get_param(BXPN_ATA2_MASTER),
1210 SIM->get_param(BXPN_ATA2_SLAVE),
1211 #endif
1212 #if BX_MAX_ATA_CHANNEL>3
1213 SIM->get_param(BXPN_ATA3_RES),
1214 SIM->get_param(BXPN_ATA3_MASTER),
1215 SIM->get_param(BXPN_ATA3_SLAVE),
1216 #endif
1217 SIM->get_param("boot_params"),
1218 NULL
1220 menu = new bx_list_c(special_menus, "disk", "Bochs Disk Options", disk_menu_init_list);
1221 menu->get_options()->set(bx_list_c::SHOW_PARENT);
1223 // ports subtree
1224 bx_list_c *ports = new bx_list_c(root_param, "ports", "Serial and Parallel Port Options");
1225 ports->get_options()->set(bx_list_c::USE_TAB_WINDOW | bx_list_c::SHOW_PARENT);
1227 // parallel ports
1228 bx_list_c *parallel = new bx_list_c(ports, "parallel", "Parallel Port Options");
1229 parallel->get_options()->set(bx_list_c::SHOW_PARENT);
1230 for (i=0; i<BX_N_PARALLEL_PORTS; i++) {
1231 sprintf(name, "%d", i+1);
1232 sprintf(label, "Parallel Port %d", i+1);
1233 menu = new bx_list_c(parallel, name, label);
1234 menu->get_options()->set(bx_list_c::SERIES_ASK);
1235 sprintf(label, "Enable parallel port #%d", i+1);
1236 sprintf(descr, "Controls whether parallel port #%d is installed or not", i+1);
1237 enabled = new bx_param_bool_c(menu, "enabled", label, descr,
1238 (i==0)? 1 : 0); // only enable #1 by default
1239 sprintf(label, "Parallel port #%d output file", i+1);
1240 sprintf(descr, "Data written to parport#%d by the guest OS is written to this file", i+1);
1241 path = new bx_param_filename_c(menu, "outfile", label, descr,
1242 "", BX_PATHNAME_LEN);
1243 deplist = new bx_list_c(NULL, 1);
1244 deplist->add(path);
1245 enabled->set_dependent_list(deplist);
1248 static char *serial_mode_list[] = {
1249 "null",
1250 "file",
1251 "term",
1252 "raw",
1253 "mouse",
1254 "socket",
1255 NULL
1258 // serial ports
1259 bx_list_c *serial = new bx_list_c(ports, "serial", "Serial Port Options");
1260 serial->get_options()->set(bx_list_c::SHOW_PARENT);
1261 for (i=0; i<BX_N_SERIAL_PORTS; i++) {
1262 sprintf(name, "%d", i+1);
1263 sprintf(label, "Serial Port %d", i+1);
1264 menu = new bx_list_c(serial, name, label);
1265 menu->get_options()->set(bx_list_c::SERIES_ASK);
1266 sprintf(label, "Enable serial port #%d (COM%d)", i+1, i+1);
1267 sprintf(descr, "Controls whether COM%d is installed or not", i+1);
1268 enabled = new bx_param_bool_c(menu, "enabled", label, descr,
1269 (i==0)?1 : 0); // only enable the first by default
1270 sprintf(label, "I/O mode of the serial device for COM%d", i+1);
1271 sprintf(descr, "The mode can be one these: 'null', 'file', 'term', 'raw', 'mouse', 'socket'");
1272 mode = new bx_param_enum_c(menu, "mode", label, descr,
1273 serial_mode_list, 0, 0);
1274 mode->set_ask_format("Choose I/O mode of the serial device [%s] ");
1275 sprintf(label, "Pathname of the serial device for COM%d", i+1);
1276 sprintf(descr, "The path can be a real serial device or a pty (X/Unix only)");
1277 path = new bx_param_filename_c(menu, "dev", label, descr,
1278 "", BX_PATHNAME_LEN);
1279 deplist = new bx_list_c(NULL, 2);
1280 deplist->add(mode);
1281 deplist->add(path);
1282 enabled->set_dependent_list(deplist);
1285 bx_param_string_c *port;
1287 // usb hubs
1288 bx_list_c *usb = new bx_list_c(ports, "usb", "USB Hub Options");
1289 usb->get_options()->set(bx_list_c::SHOW_PARENT);
1290 for (i=0; i<BX_N_USB_HUBS; i++) {
1291 sprintf(group, "USB%d", i+1);
1292 sprintf(name, "%d", i+1);
1293 sprintf(label, "USB Hub %d", i+1);
1294 menu = new bx_list_c(usb, name, label);
1295 menu->set_enabled(BX_SUPPORT_PCIUSB);
1296 sprintf(label, "Enable usb hub #%d", i+1);
1297 sprintf(descr, "Controls whether %s is installed or not", group);
1298 enabled = new bx_param_bool_c(menu, "enabled", label, descr, 0);
1299 enabled->set_enabled(BX_SUPPORT_PCIUSB);
1300 port = new bx_param_string_c(menu,
1301 "port1",
1302 "Port #1 device",
1303 "Device connected to USB port #1",
1304 "", BX_PATHNAME_LEN);
1305 port->set_group(group);
1306 port = new bx_param_string_c(menu,
1307 "port2",
1308 "Port #2 device",
1309 "Device connected to USB port #2",
1310 "", BX_PATHNAME_LEN);
1311 port->set_group(group);
1312 enabled->set_dependent_list(menu->clone());
1315 // network subtree
1316 bx_list_c *network = new bx_list_c(root_param, "network", "Network Configuration");
1317 network->get_options()->set(bx_list_c::USE_TAB_WINDOW | bx_list_c::SHOW_PARENT);
1319 // ne2k & pnic options
1320 static char *eth_module_list[] = {
1321 "null",
1322 #if defined(ETH_LINUX)
1323 "linux",
1324 #endif
1325 #if HAVE_ETHERTAP
1326 "tap",
1327 #endif
1328 #if HAVE_TUNTAP
1329 "tuntap",
1330 #endif
1331 #if defined(ETH_WIN32)
1332 "win32",
1333 #endif
1334 #if defined(ETH_FBSD)
1335 "fbsd",
1336 #endif
1337 #ifdef ETH_ARPBACK
1338 "arpback",
1339 #endif
1340 #if HAVE_VDE
1341 "vde",
1342 #endif
1343 "vnet",
1344 NULL
1346 // ne2k options
1347 menu = new bx_list_c(network, "ne2k", "NE2000", 7);
1348 menu->get_options()->set(bx_list_c::SHOW_PARENT);
1349 menu->set_enabled(BX_SUPPORT_NE2K);
1350 enabled = new bx_param_bool_c(menu,
1351 "enabled",
1352 "Enable NE2K NIC emulation",
1353 "Enables the NE2K NIC emulation",
1355 enabled->set_enabled(BX_SUPPORT_NE2K);
1356 ioaddr = new bx_param_num_c(menu,
1357 "ioaddr",
1358 "NE2K I/O Address",
1359 "I/O base address of the emulated NE2K device",
1360 0, 0xffff,
1361 0x300);
1362 ioaddr->set_base(16);
1363 irq = new bx_param_num_c(menu,
1364 "irq",
1365 "NE2K Interrupt",
1366 "IRQ used by the NE2K device",
1367 0, 15,
1369 irq->set_options(bx_param_num_c::USE_SPIN_CONTROL);
1370 macaddr = new bx_param_string_c(menu,
1371 "macaddr",
1372 "MAC Address",
1373 "MAC address of the NE2K device. Don't use an address of a machine on your net.",
1374 "\xfe\xfd\xde\xad\xbe\xef", 6);
1375 macaddr->get_options()->set(bx_param_string_c::RAW_BYTES);
1376 macaddr->set_separator(':');
1377 ethmod = new bx_param_enum_c(menu,
1378 "ethmod",
1379 "Ethernet module",
1380 "Module used for the connection to the real net.",
1381 eth_module_list,
1384 ethmod->set_by_name("null");
1385 ethmod->set_ask_format("Choose ethernet module for the NE2K [%s] ");
1386 ethdev = new bx_param_string_c(menu,
1387 "ethdev",
1388 "Ethernet device",
1389 "Device used for the connection to the real net. This is only valid if an ethernet module other than 'null' is used.",
1390 "xl0", BX_PATHNAME_LEN);
1391 path = new bx_param_filename_c(menu,
1392 "script",
1393 "Device configuration script",
1394 "Name of the script that is executed after Bochs initializes the network interface (optional).",
1395 "none", BX_PATHNAME_LEN);
1396 path->set_ask_format("Enter new script name, or 'none': [%s] ");
1397 enabled->set_dependent_list(menu->clone());
1398 // pnic options
1399 menu = new bx_list_c(network, "pnic", "PCI Pseudo NIC");
1400 menu->get_options()->set(bx_list_c::SHOW_PARENT);
1401 menu->set_enabled(BX_SUPPORT_PCIPNIC);
1402 enabled = new bx_param_bool_c(menu,
1403 "enabled",
1404 "Enable Pseudo NIC emulation",
1405 "Enables the Pseudo NIC emulation",
1407 enabled->set_enabled(BX_SUPPORT_PCIPNIC);
1408 macaddr = new bx_param_string_c(menu,
1409 "macaddr",
1410 "MAC Address",
1411 "MAC address of the Pseudo NIC device. Don't use an address of a machine on your net.",
1412 "\xfe\xfd\xde\xad\xbe\xef", 6);
1413 macaddr->get_options()->set(bx_param_string_c::RAW_BYTES);
1414 macaddr->set_separator(':');
1415 ethmod = new bx_param_enum_c(menu,
1416 "ethmod",
1417 "Ethernet module",
1418 "Module used for the connection to the real net.",
1419 eth_module_list,
1422 ethmod->set_by_name("null");
1423 ethmod->set_ask_format("Choose ethernet module for the Pseudo NIC [%s]");
1424 ethdev = new bx_param_string_c(menu,
1425 "ethdev",
1426 "Ethernet device",
1427 "Device used for the connection to the real net. This is only valid if an ethernet module other than 'null' is used.",
1428 "xl0", BX_PATHNAME_LEN);
1429 path = new bx_param_filename_c(menu,
1430 "script",
1431 "Device configuration script",
1432 "Name of the script that is executed after Bochs initializes the network interface (optional).",
1433 "none", BX_PATHNAME_LEN);
1434 path->set_ask_format("Enter new script name, or 'none': [%s] ");
1435 enabled->set_dependent_list(menu->clone());
1437 // sound subtree
1438 bx_list_c *sound = new bx_list_c(root_param, "sound", "Sound Configuration");
1439 sound->get_options()->set(bx_list_c::SHOW_PARENT);
1440 menu = new bx_list_c(sound, "sb16", "SB16 Configuration", 8);
1441 menu->get_options()->set(bx_list_c::SHOW_PARENT);
1442 menu->set_enabled(BX_SUPPORT_SB16);
1444 // SB16 options
1445 enabled = new bx_param_bool_c(menu,
1446 "enabled",
1447 "Enable SB16 emulation",
1448 "Enables the SB16 emulation",
1450 enabled->set_enabled(BX_SUPPORT_SB16);
1451 bx_param_num_c *midimode = new bx_param_num_c(menu,
1452 "midimode",
1453 "Midi mode",
1454 "Controls the MIDI output format.",
1455 0, 3,
1457 bx_param_filename_c *midifile = new bx_param_filename_c(menu,
1458 "midifile",
1459 "MIDI file",
1460 "The filename is where the MIDI data is sent. This can be device or just a file.",
1461 "", BX_PATHNAME_LEN);
1462 bx_param_num_c *wavemode = new bx_param_num_c(menu,
1463 "wavemode",
1464 "Wave mode",
1465 "Controls the wave output format.",
1466 0, 3,
1468 bx_param_filename_c *wavefile = new bx_param_filename_c(menu,
1469 "wavefile",
1470 "Wave file",
1471 "This is the device/file where the wave output is stored",
1472 "", BX_PATHNAME_LEN);
1473 bx_param_num_c *loglevel = new bx_param_num_c(menu,
1474 "loglevel",
1475 "Log level",
1476 "Controls how verbose the SB16 emulation is (0 = no log, 5 = all errors and infos).",
1477 0, 5,
1479 bx_param_filename_c *logfile = new bx_param_filename_c(menu,
1480 "logfile",
1481 "Log file",
1482 "The file to write the SB16 emulator messages to.",
1483 "", BX_PATHNAME_LEN);
1484 bx_param_num_c *dmatimer = new bx_param_num_c(menu,
1485 "dmatimer",
1486 "DMA timer",
1487 "Microseconds per second for a DMA cycle.",
1488 0, BX_MAX_BIT32U,
1491 #if BX_WITH_WX
1492 midimode->set_options(bx_param_num_c::USE_SPIN_CONTROL);
1493 wavemode->set_options(bx_param_num_c::USE_SPIN_CONTROL);
1494 loglevel->set_options(bx_param_num_c::USE_SPIN_CONTROL);
1495 #endif
1496 loglevel->set_group("SB16");
1497 dmatimer->set_group("SB16");
1498 enabled->set_dependent_list(menu->clone());
1499 deplist = new bx_list_c(NULL, 1);
1500 deplist->add(midifile);
1501 midimode->set_dependent_list(deplist);
1502 deplist = new bx_list_c(NULL, 1);
1503 deplist->add(wavefile);
1504 wavemode->set_dependent_list(deplist);
1505 deplist = new bx_list_c(NULL, 1);
1506 deplist->add(logfile);
1507 loglevel->set_dependent_list(deplist);
1509 // misc options subtree
1510 bx_list_c *misc = new bx_list_c(root_param, "misc", "Configure Everything Else");
1511 misc->get_options()->set(bx_list_c::SHOW_PARENT);
1512 bx_param_num_c *gdbstub_opt;
1514 // text snapshot check panic
1515 new bx_param_bool_c(misc,
1516 "text_snapshot_check",
1517 "Enable text snapshot check panic",
1518 "Enable panic when text on screen matches snapchk.txt.\nUseful for regression testing.\nIn win32, turns off CR/LF in snapshots and cuts.",
1520 // GDB stub
1521 menu = new bx_list_c(misc, "gdbstub", "GDB Stub Options");
1522 menu->get_options()->set(bx_list_c::SHOW_PARENT | bx_list_c::USE_BOX_TITLE);
1523 menu->set_enabled(BX_GDBSTUB);
1524 enabled = new bx_param_bool_c(menu,
1525 "enabled",
1526 "Enable GDB stub",
1529 enabled->set_enabled(BX_GDBSTUB);
1530 gdbstub_opt = new bx_param_num_c(menu,
1531 "port",
1532 "Port",
1533 "TCP/IP port for GDB stub",
1534 0, 65535,
1535 1234);
1536 gdbstub_opt = new bx_param_num_c(menu,
1537 "text_base",
1538 "Text base",
1540 0, BX_MAX_BIT32U,
1542 gdbstub_opt = new bx_param_num_c(menu,
1543 "data_base",
1544 "Data base",
1546 0, BX_MAX_BIT32U,
1548 gdbstub_opt = new bx_param_num_c(menu,
1549 "bss_base",
1550 "BSS base",
1552 0, BX_MAX_BIT32U,
1554 enabled->set_dependent_list(menu->clone());
1556 // log options subtree
1557 menu = new bx_list_c(root_param, "log", "Logfile Options");
1559 // log options
1560 path = new bx_param_filename_c(menu,
1561 "filename",
1562 "Log filename",
1563 "Pathname of bochs log file",
1564 "-", BX_PATHNAME_LEN);
1565 path->set_ask_format("Enter log filename: [%s] ");
1567 bx_param_string_c *prefix = new bx_param_string_c(menu,
1568 "prefix",
1569 "Log output prefix",
1570 "Prefix prepended to log output",
1571 "%t%e%d", BX_PATHNAME_LEN);
1572 prefix->set_ask_format("Enter log prefix: [%s] ");
1574 path = new bx_param_filename_c(menu,
1575 "debugger_filename",
1576 "Debugger Log filename",
1577 "Pathname of debugger log file",
1578 "-", BX_PATHNAME_LEN);
1579 path->set_ask_format("Enter debugger log filename: [%s] ");
1580 path->set_enabled(BX_DEBUGGER);
1582 // runtime options
1583 bx_param_c *runtime_init_list[] = {
1584 SIM->get_param_num(BXPN_VGA_UPDATE_INTERVAL),
1585 SIM->get_param_bool(BXPN_MOUSE_ENABLED),
1586 SIM->get_param_num(BXPN_KBD_PASTE_DELAY),
1587 SIM->get_param_string(BXPN_USER_SHORTCUT),
1588 SIM->get_param_num(BXPN_SB16_DMATIMER),
1589 SIM->get_param_num(BXPN_SB16_LOGLEVEL),
1590 SIM->get_param_string(BXPN_USB1_PORT1),
1591 SIM->get_param_string(BXPN_USB1_PORT2),
1592 NULL
1594 menu = new bx_list_c(special_menus, "runtime", "Misc runtime options", runtime_init_list);
1595 menu->get_options()->set(bx_list_c::SHOW_PARENT | bx_list_c::SHOW_GROUP_NAME);
1598 void bx_reset_options()
1600 // cpu
1601 SIM->get_param("cpu")->reset();
1603 // memory (ram & rom)
1604 SIM->get_param("memory")->reset();
1606 // clock & cmos
1607 SIM->get_param("clock_cmos")->reset();
1609 // pci
1610 SIM->get_param("pci")->reset();
1612 // display & interface
1613 SIM->get_param("display")->reset();
1615 // keyboard & mouse
1616 SIM->get_param("keyboard_mouse")->reset();
1618 // boot
1619 SIM->get_param("boot_params")->reset();
1621 // floppy drives
1622 SIM->get_param("floppy")->reset();
1624 // ata/atapi drives
1625 SIM->get_param("ata")->reset();
1627 // standard ports
1628 SIM->get_param("ports")->reset();
1630 // ne2k & pnic
1631 SIM->get_param("network")->reset();
1633 // SB16
1634 SIM->get_param("sound")->reset();
1636 // misc
1637 SIM->get_param("misc")->reset();
1639 // logfile
1640 SIM->get_param("log")->reset();
1643 int bx_read_configuration(const char *rcfile)
1645 // parse rcfile first, then parse arguments in order.
1646 BX_INFO (("reading configuration from %s", rcfile));
1647 if (parse_bochsrc(rcfile) < 0) {
1648 BX_PANIC (("reading from %s failed", rcfile));
1649 return -1;
1651 // update log actions
1652 for (int level=0; level<N_LOGLEV; level++) {
1653 int action = SIM->get_default_log_action (level);
1654 io->set_log_action (level, action);
1656 return 0;
1659 int bx_parse_cmdline (int arg, int argc, char *argv[])
1661 //if (arg < argc) BX_INFO (("parsing command line arguments"));
1663 while (arg < argc) {
1664 BX_INFO (("parsing arg %d, %s", arg, argv[arg]));
1665 parse_line_unformatted("cmdline args", argv[arg]);
1666 arg++;
1668 // update log actions
1669 for (int level=0; level<N_LOGLEV; level++) {
1670 int action = SIM->get_default_log_action (level);
1671 io->set_log_action (level, action);
1673 return 0;
1676 #if BX_PROVIDE_MAIN
1677 char *bx_find_bochsrc()
1679 FILE *fd = NULL;
1680 char rcfile[512];
1681 Bit32u retry = 0, found = 0;
1682 // try several possibilities for the bochsrc before giving up
1683 while (!found) {
1684 rcfile[0] = 0;
1685 switch (retry++) {
1686 case 0: strcpy (rcfile, ".bochsrc"); break;
1687 case 1: strcpy (rcfile, "bochsrc"); break;
1688 case 2: strcpy (rcfile, "bochsrc.txt"); break;
1689 #ifdef WIN32
1690 case 3: strcpy (rcfile, "bochsrc.bxrc"); break;
1691 #elif !BX_WITH_MACOS
1692 // only try this on unix
1693 case 3:
1695 char *ptr = getenv("HOME");
1696 if (ptr) snprintf (rcfile, sizeof(rcfile), "%s/.bochsrc", ptr);
1698 break;
1699 case 4: strcpy (rcfile, "/etc/bochsrc"); break;
1700 #endif
1701 default:
1702 return NULL;
1704 if (rcfile[0]) {
1705 BX_DEBUG (("looking for configuration in %s", rcfile));
1706 fd = fopen(rcfile, "r");
1707 if (fd) found = 1;
1710 assert (fd != NULL && rcfile[0] != 0);
1711 fclose (fd);
1712 return strdup(rcfile);
1715 static int parse_bochsrc(const char *rcfile)
1717 FILE *fd = NULL;
1718 char *ret;
1719 char line[512];
1720 char context[BX_PATHNAME_LEN];
1721 Bit32u linenum = 1;
1723 // try several possibilities for the bochsrc before giving up
1725 bochsrc_include_count++;
1727 fd = fopen (rcfile, "r");
1728 if (fd == NULL) return -1;
1730 int retval = 0;
1731 do {
1732 ret = fgets(line, sizeof(line)-1, fd);
1733 line[sizeof(line) - 1] = '\0';
1734 int len = strlen(line);
1735 if ((len>0) && (line[len-1] < ' '))
1736 line[len-1] = '\0';
1737 if ((ret != NULL) && strlen(line)) {
1738 sprintf(context, "%s:%u", rcfile, linenum);
1739 if (parse_line_unformatted(context, line) < 0) {
1740 retval = -1;
1741 break; // quit parsing after first error
1744 linenum++;
1745 } while (!feof(fd));
1746 fclose(fd);
1747 bochsrc_include_count--;
1748 return retval;
1751 static char *get_builtin_variable(char *varname)
1753 #ifdef WIN32
1754 int code;
1755 DWORD size;
1756 DWORD type = 0;
1757 HKEY hkey;
1758 char keyname[80];
1759 static char data[MAX_PATH];
1760 #endif
1762 if (strlen(varname)<1) return NULL;
1763 else {
1764 if (!strcmp(varname, "BXSHARE")) {
1765 #ifdef WIN32
1766 wsprintf(keyname, "Software\\Bochs %s", VER_STRING);
1767 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyname, 0, KEY_READ, &hkey);
1768 if (code == ERROR_SUCCESS) {
1769 data[0] = 0;
1770 size = MAX_PATH;
1771 if (RegQueryValueEx(hkey, "", NULL, (LPDWORD)&type, (LPBYTE)data,
1772 (LPDWORD)&size ) == ERROR_SUCCESS ) {
1773 RegCloseKey(hkey);
1774 return data;
1775 } else {
1776 RegCloseKey(hkey);
1777 return NULL;
1779 } else {
1780 return NULL;
1782 #else
1783 return BX_SHARE_PATH;
1784 #endif
1786 return NULL;
1790 static Bit32s parse_line_unformatted(const char *context, char *line)
1792 #define MAX_PARAMS_LEN 40
1793 char *ptr;
1794 unsigned i, string_i = 0;
1795 char string[512];
1796 char *params[MAX_PARAMS_LEN];
1797 int num_params;
1798 bx_bool inquotes = 0;
1799 bx_bool comment = 0;
1801 memset(params, 0, sizeof(params));
1802 if (line == NULL) return 0;
1804 // if passed nothing but whitespace, just return
1805 for (i=0; i<strlen(line); i++) {
1806 if (!isspace(line[i])) break;
1808 if (i>=strlen(line))
1809 return 0;
1811 num_params = 0;
1813 if (!strncmp(line, "#include", 8))
1814 ptr = strtok(line, " ");
1815 else
1816 ptr = strtok(line, ":");
1817 while ((ptr) && (!comment)) {
1818 if (!inquotes) {
1819 string_i = 0;
1820 } else {
1821 string[string_i++] = ',';
1823 for (i=0; i<strlen(ptr); i++) {
1824 if (ptr[i] == '"')
1825 inquotes = !inquotes;
1826 else if ((ptr[i] == '#') && (strncmp(line+i, "#include", 8)) && !inquotes) {
1827 comment = 1;
1828 break;
1829 } else {
1830 #if BX_HAVE_GETENV
1831 // substitute environment variables.
1832 if (ptr[i] == '$') {
1833 char varname[512];
1834 char *pv = varname;
1835 char *value;
1836 *pv = 0;
1837 i++;
1838 while (isalpha(ptr[i]) || ptr[i]=='_') {
1839 *pv = ptr[i]; pv++; i++;
1841 *pv = 0;
1842 if (strlen(varname)<1 || !(value = getenv(varname))) {
1843 if ((value = get_builtin_variable(varname))) {
1844 // append value to the string
1845 for (pv=value; *pv; pv++)
1846 string[string_i++] = *pv;
1847 } else {
1848 BX_PANIC (("could not look up environment variable '%s'", varname));
1850 } else {
1851 // append value to the string
1852 for (pv=value; *pv; pv++)
1853 string[string_i++] = *pv;
1856 #endif
1857 if (!isspace(ptr[i]) || inquotes) {
1858 string[string_i++] = ptr[i];
1862 string[string_i] = '\0';
1863 if (string_i == 0) break;
1864 if (!inquotes) {
1865 if (params[num_params] != NULL) {
1866 free(params[num_params]);
1867 params[num_params] = NULL;
1869 if (num_params < MAX_PARAMS_LEN) {
1870 params[num_params++] = strdup(string);
1871 } else {
1872 BX_PANIC (("too many parameters, max is %d\n", MAX_PARAMS_LEN));
1875 ptr = strtok(NULL, ",");
1877 Bit32s retval = parse_line_formatted(context, num_params, &params[0]);
1878 for (i=0; i < MAX_PARAMS_LEN; i++)
1880 if ( params[i] != NULL )
1882 free(params[i]);
1883 params[i] = NULL;
1886 return retval;
1889 // These macros are called for all parse errors, so that we can easily
1890 // change the behavior of all occurrences.
1891 #define PARSE_ERR(x) \
1892 do { BX_PANIC(x); return -1; } while (0)
1893 #define PARSE_WARN(x) \
1894 BX_ERROR(x)
1897 * this supports the "floppyx: image=" option.
1898 * the functions returns the type of the floppy
1899 * image (1.44, 360, etc.), based on the image file size.
1901 int get_floppy_type_from_image(const char *filename)
1903 struct stat stat_buf;
1905 if (stat(filename, &stat_buf))
1907 return BX_FLOPPY_NONE;
1910 switch (stat_buf.st_size)
1912 case 163840:
1913 return BX_FLOPPY_160K;
1915 case 184320:
1916 return BX_FLOPPY_180K;
1918 case 327680:
1919 return BX_FLOPPY_320K;
1921 case 368640:
1922 return BX_FLOPPY_360K;
1924 case 737280:
1925 return BX_FLOPPY_720K;
1927 case 1228800:
1928 return BX_FLOPPY_1_2;
1930 case 1474560:
1931 case 1720320:
1932 case 1763328:
1933 case 1884160:
1934 return BX_FLOPPY_1_44;
1936 case 2949120:
1937 return BX_FLOPPY_2_88;
1939 default:
1940 return BX_FLOPPY_UNKNOWN;
1944 static Bit32s parse_log_options(const char *context, char *loglev, char *param1)
1946 int level;
1948 if (!strcmp(loglev, "panic")) {
1949 level = LOGLEV_PANIC;
1950 } else if (!strcmp(loglev, "pass")) {
1951 level = LOGLEV_PASS;
1952 } else if (!strcmp(loglev, "error")) {
1953 level = LOGLEV_ERROR;
1954 } else if (!strcmp(loglev, "info")) {
1955 level = LOGLEV_INFO;
1956 } else { /* debug */
1957 level = LOGLEV_DEBUG;
1959 if (strncmp(param1, "action=", 7)) {
1960 PARSE_ERR(("%s: %s directive malformed.", context, loglev));
1962 char *action = param1 + 7;
1963 if (!strcmp(action, "fatal"))
1964 SIM->set_default_log_action (level, ACT_FATAL);
1965 else if (!strcmp (action, "report"))
1966 SIM->set_default_log_action (level, ACT_REPORT);
1967 else if (!strcmp (action, "ignore"))
1968 SIM->set_default_log_action (level, ACT_IGNORE);
1969 else if (!strcmp (action, "ask"))
1970 SIM->set_default_log_action (level, ACT_ASK);
1971 else {
1972 PARSE_ERR(("%s: %s directive malformed.", context, loglev));
1974 return 0;
1977 static Bit32s parse_line_formatted(const char *context, int num_params, char *params[])
1979 int i, slot, t;
1980 Bit8u idx;
1981 bx_list_c *base;
1983 if (num_params < 1) return 0;
1984 if (num_params < 2) {
1985 PARSE_ERR(("%s: a bochsrc option needs at least one parameter", context));
1988 if (!strcmp(params[0], "#include")) {
1989 if (num_params != 2) {
1990 PARSE_ERR(("%s: ignoring malformed #include directive.", context));
1992 if (!strcmp(params[1], context)) {
1993 PARSE_ERR(("%s: cannot include this file again.", context));
1995 if (bochsrc_include_count == 2) {
1996 PARSE_ERR(("%s: include directive in an included file not supported yet.", context));
1998 bx_read_configuration(params[1]);
2000 else if (!strcmp(params[0], "floppya")) {
2001 for (i=1; i<num_params; i++) {
2002 if (!strncmp(params[i], "2_88=", 5)) {
2003 SIM->get_param_string(BXPN_FLOPPYA_PATH)->set(&params[i][5]);
2004 SIM->get_param_enum(BXPN_FLOPPYA_TYPE)->set(BX_FLOPPY_2_88);
2006 else if (!strncmp(params[i], "1_44=", 5)) {
2007 SIM->get_param_string(BXPN_FLOPPYA_PATH)->set(&params[i][5]);
2008 SIM->get_param_enum(BXPN_FLOPPYA_TYPE)->set(BX_FLOPPY_1_44);
2010 else if (!strncmp(params[i], "1_2=", 4)) {
2011 SIM->get_param_string(BXPN_FLOPPYA_PATH)->set(&params[i][4]);
2012 SIM->get_param_enum(BXPN_FLOPPYA_TYPE)->set(BX_FLOPPY_1_2);
2014 else if (!strncmp(params[i], "720k=", 5)) {
2015 SIM->get_param_string(BXPN_FLOPPYA_PATH)->set(&params[i][5]);
2016 SIM->get_param_enum(BXPN_FLOPPYA_TYPE)->set(BX_FLOPPY_720K);
2018 else if (!strncmp(params[i], "360k=", 5)) {
2019 SIM->get_param_string(BXPN_FLOPPYA_PATH)->set(&params[i][5]);
2020 SIM->get_param_enum(BXPN_FLOPPYA_TYPE)->set(BX_FLOPPY_360K);
2022 // use CMOS reserved types?
2023 else if (!strncmp(params[i], "160k=", 5)) {
2024 SIM->get_param_string(BXPN_FLOPPYA_PATH)->set(&params[i][5]);
2025 SIM->get_param_enum(BXPN_FLOPPYA_TYPE)->set(BX_FLOPPY_160K);
2027 else if (!strncmp(params[i], "180k=", 5)) {
2028 SIM->get_param_string(BXPN_FLOPPYA_PATH)->set(&params[i][5]);
2029 SIM->get_param_enum(BXPN_FLOPPYA_TYPE)->set(BX_FLOPPY_180K);
2031 else if (!strncmp(params[i], "320k=", 5)) {
2032 SIM->get_param_string(BXPN_FLOPPYA_PATH)->set(&params[i][5]);
2033 SIM->get_param_enum(BXPN_FLOPPYA_TYPE)->set(BX_FLOPPY_320K);
2035 else if (!strncmp(params[i], "image=", 6)) {
2036 /* "image=" means we should get floppy type from image */
2037 SIM->get_param_string(BXPN_FLOPPYA_PATH)->set(&params[i][6]);
2038 t = get_floppy_type_from_image(&params[i][6]);
2039 if (t != BX_FLOPPY_UNKNOWN)
2040 SIM->get_param_enum(BXPN_FLOPPYA_TYPE)->set(t);
2041 else
2042 PARSE_ERR(("%s: floppya image size doesn't match one of the supported types.", context));
2044 else if (!strncmp(params[i], "status=", 7)) {
2045 SIM->get_param_enum(BXPN_FLOPPYA_STATUS)->set_by_name(&params[i][7]);
2047 else {
2048 PARSE_ERR(("%s: floppya attribute '%s' not understood.", context,
2049 params[i]));
2054 else if (!strcmp(params[0], "floppyb")) {
2055 for (i=1; i<num_params; i++) {
2056 if (!strncmp(params[i], "2_88=", 5)) {
2057 SIM->get_param_string(BXPN_FLOPPYB_PATH)->set(&params[i][5]);
2058 SIM->get_param_enum(BXPN_FLOPPYB_TYPE)->set(BX_FLOPPY_2_88);
2060 else if (!strncmp(params[i], "1_44=", 5)) {
2061 SIM->get_param_string(BXPN_FLOPPYB_PATH)->set(&params[i][5]);
2062 SIM->get_param_enum(BXPN_FLOPPYB_TYPE)->set(BX_FLOPPY_1_44);
2064 else if (!strncmp(params[i], "1_2=", 4)) {
2065 SIM->get_param_string(BXPN_FLOPPYB_PATH)->set(&params[i][4]);
2066 SIM->get_param_enum(BXPN_FLOPPYB_TYPE)->set(BX_FLOPPY_1_2);
2068 else if (!strncmp(params[i], "720k=", 5)) {
2069 SIM->get_param_string(BXPN_FLOPPYB_PATH)->set(&params[i][5]);
2070 SIM->get_param_enum(BXPN_FLOPPYB_TYPE)->set(BX_FLOPPY_720K);
2072 else if (!strncmp(params[i], "360k=", 5)) {
2073 SIM->get_param_string(BXPN_FLOPPYB_PATH)->set(&params[i][5]);
2074 SIM->get_param_enum(BXPN_FLOPPYB_TYPE)->set(BX_FLOPPY_360K);
2076 // use CMOS reserved types?
2077 else if (!strncmp(params[i], "160k=", 5)) {
2078 SIM->get_param_string(BXPN_FLOPPYB_PATH)->set(&params[i][5]);
2079 SIM->get_param_enum(BXPN_FLOPPYB_TYPE)->set(BX_FLOPPY_160K);
2081 else if (!strncmp(params[i], "180k=", 5)) {
2082 SIM->get_param_string(BXPN_FLOPPYB_PATH)->set(&params[i][5]);
2083 SIM->get_param_enum(BXPN_FLOPPYB_TYPE)->set(BX_FLOPPY_180K);
2085 else if (!strncmp(params[i], "320k=", 5)) {
2086 SIM->get_param_string(BXPN_FLOPPYB_PATH)->set(&params[i][5]);
2087 SIM->get_param_enum(BXPN_FLOPPYB_TYPE)->set(BX_FLOPPY_320K);
2089 else if (!strncmp(params[i], "image=", 6)) {
2090 /* "image=" means we should get floppy type from image */
2091 SIM->get_param_string(BXPN_FLOPPYB_PATH)->set(&params[i][6]);
2092 t = get_floppy_type_from_image(&params[i][6]);
2093 if (t != BX_FLOPPY_UNKNOWN)
2094 SIM->get_param_enum(BXPN_FLOPPYB_TYPE)->set(t);
2095 else
2096 PARSE_ERR(("%s: floppyb image size doesn't match one of the supported types.", context));
2098 else if (!strncmp(params[i], "status=", 7)) {
2099 SIM->get_param_enum(BXPN_FLOPPYB_STATUS)->set_by_name(&params[i][7]);
2101 else {
2102 PARSE_ERR(("%s: floppyb attribute '%s' not understood.", context,
2103 params[i]));
2108 else if ((!strncmp(params[0], "ata", 3)) && (strlen(params[0]) == 4)) {
2109 char tmpname[80];
2110 Bit8u channel = params[0][3];
2112 if ((channel < '0') || (channel > '9')) {
2113 PARSE_ERR(("%s: ataX directive malformed.", context));
2115 channel-='0';
2116 if (channel >= BX_MAX_ATA_CHANNEL) {
2117 PARSE_ERR(("%s: ataX directive malformed.", context));
2120 if ((num_params < 2) || (num_params > 5)) {
2121 PARSE_ERR(("%s: ataX directive malformed.", context));
2123 sprintf(tmpname, "ata.%d.resources", channel);
2124 base = (bx_list_c*) SIM->get_param(tmpname);
2125 if (strncmp(params[1], "enabled=", 8)) {
2126 PARSE_ERR(("%s: ataX directive malformed.", context));
2127 } else {
2128 SIM->get_param_bool("enabled", base)->set(atol(&params[1][8]));
2131 if (num_params > 2) {
2132 if (strncmp(params[2], "ioaddr1=", 8)) {
2133 PARSE_ERR(("%s: ataX directive malformed.", context));
2135 else {
2136 if ((params[2][8] == '0') && (params[2][9] == 'x'))
2137 SIM->get_param_num("ioaddr1", base)->set(strtoul(&params[2][8], NULL, 16));
2138 else
2139 SIM->get_param_num("ioaddr1", base)->set(strtoul(&params[2][8], NULL, 10));
2143 if (num_params > 3) {
2144 if (strncmp(params[3], "ioaddr2=", 8)) {
2145 PARSE_ERR(("%s: ataX directive malformed.", context));
2147 else {
2148 if ((params[3][8] == '0') && (params[3][9] == 'x'))
2149 SIM->get_param_num("ioaddr2", base)->set(strtoul(&params[3][8], NULL, 16));
2150 else
2151 SIM->get_param_num("ioaddr2", base)->set(strtoul(&params[3][8], NULL, 10));
2155 if (num_params > 4) {
2156 if (strncmp(params[4], "irq=", 4)) {
2157 PARSE_ERR(("%s: ataX directive malformed.", context));
2159 else {
2160 SIM->get_param_num("irq", base)->set(atol(&params[4][4]));
2165 // ataX-master, ataX-slave
2166 else if ((!strncmp(params[0], "ata", 3)) && (strlen(params[0]) > 4)) {
2167 Bit8u channel = params[0][3];
2168 int type = 0, mode = BX_ATA_MODE_FLAT, biosdetect = BX_ATA_BIOSDETECT_AUTO;
2169 Bit32u cylinders = 0, heads = 0, sectors = 0;
2170 char tmpname[80];
2172 if ((channel < '0') || (channel > '9')) {
2173 PARSE_ERR(("%s: ataX-master/slave directive malformed.", context));
2175 channel-='0';
2176 if (channel >= BX_MAX_ATA_CHANNEL) {
2177 PARSE_ERR(("%s: ataX-master/slave directive malformed.", context));
2180 if ((strcmp(&params[0][4], "-slave")) &&
2181 (strcmp(&params[0][4], "-master"))) {
2182 PARSE_ERR(("%s: ataX-master/slave directive malformed.", context));
2185 sprintf(tmpname, "ata.%d.%s", channel, &params[0][5]);
2186 base = (bx_list_c*) SIM->get_param(tmpname);
2187 for (i=1; i<num_params; i++) {
2188 if (!strncmp(params[i], "type=", 5)) {
2189 type = SIM->get_param_enum("type", base)->find_by_name(&params[i][5]);
2190 if (type < 0) {
2191 PARSE_ERR(("%s: ataX-master/slave: unknown type '%s'", context, &params[i][5]));
2193 } else if (!strcmp(params[i], "mode=z-undoable")) {
2194 PARSE_ERR(("%s: ataX-master/slave mode 'z-undoable' not implemented yet", context));
2195 } else if (!strcmp(params[i], "mode=z-volatile")) {
2196 PARSE_ERR(("%s: ataX-master/slave mode 'z-volatile' not implemented yet", context));
2197 } else if (!strncmp(params[i], "mode=", 5)) {
2198 mode = SIM->get_param_enum("mode", base)->find_by_name(&params[i][5]);
2199 if (mode < 0) {
2200 PARSE_ERR(("%s: ataX-master/slave: unknown mode '%s'", context, &params[i][5]));
2202 } else if (!strncmp(params[i], "path=", 5)) {
2203 SIM->get_param_string("path", base)->set(&params[i][5]);
2204 } else if (!strncmp(params[i], "cylinders=", 10)) {
2205 cylinders = atol(&params[i][10]);
2206 } else if (!strncmp(params[i], "heads=", 6)) {
2207 heads = atol(&params[i][6]);
2208 } else if (!strncmp(params[i], "spt=", 4)) {
2209 sectors = atol(&params[i][4]);
2210 } else if (!strncmp(params[i], "model=", 6)) {
2211 SIM->get_param_string("model", base)->set(&params[i][6]);
2212 } else if (!strncmp(params[i], "biosdetect=", 11)) {
2213 biosdetect = SIM->get_param_enum("biosdetect", base)->find_by_name(&params[i][11]);
2214 if (biosdetect < 0) {
2215 PARSE_ERR(("%s: ataX-master/slave: unknown biosdetect '%s'", context, &params[i][11]));
2217 } else if (!strcmp(params[i], "translation=none")) {
2218 SIM->get_param_enum("translation", base)->set(BX_ATA_TRANSLATION_NONE);
2219 } else if (!strcmp(params[i], "translation=lba")) {
2220 SIM->get_param_enum("translation", base)->set(BX_ATA_TRANSLATION_LBA);
2221 } else if (!strcmp(params[i], "translation=large")) {
2222 SIM->get_param_enum("translation", base)->set(BX_ATA_TRANSLATION_LARGE);
2223 } else if (!strcmp(params[i], "translation=echs")) { // synonym of large
2224 SIM->get_param_enum("translation", base)->set(BX_ATA_TRANSLATION_LARGE);
2225 } else if (!strcmp(params[i], "translation=rechs")) {
2226 SIM->get_param_enum("translation", base)->set(BX_ATA_TRANSLATION_RECHS);
2227 } else if (!strcmp(params[i], "translation=auto")) {
2228 SIM->get_param_enum("translation", base)->set(BX_ATA_TRANSLATION_AUTO);
2229 } else if (!strcmp(params[i], "status=ejected")) {
2230 SIM->get_param_enum("status", base)->set(BX_EJECTED);
2231 } else if (!strcmp(params[i], "status=inserted")) {
2232 SIM->get_param_enum("status", base)->set(BX_INSERTED);
2233 } else if (!strncmp(params[i], "journal=", 8)) {
2234 SIM->get_param_string("journal", base)->set(&params[i][8]);
2235 } else {
2236 PARSE_ERR(("%s: ataX-master/slave directive malformed.", context));
2240 // Enables the ata device
2241 if (strlen(SIM->get_param_string("path", base)->getptr()) > 0) {
2242 SIM->get_param_bool("present", base)->set(1);
2243 SIM->get_param_enum("type", base)->set(type);
2244 SIM->get_param_enum("mode", base)->set(mode);
2245 SIM->get_param_num("cylinders", base)->set(cylinders);
2246 SIM->get_param_num("heads", base)->set(heads);
2247 SIM->get_param_num("spt", base)->set(sectors);
2248 SIM->get_param_num("biosdetect", base)->set(biosdetect);
2249 } else {
2250 SIM->get_param_bool("present", base)->set(0);
2253 // if enabled, check if device ok
2254 if (SIM->get_param_bool("present", base)->get() == 1) {
2255 if (SIM->get_param_enum("type", base)->get() == BX_ATA_DEVICE_DISK) {
2256 if ((SIM->get_param_num("cylinders", base)->get() == 0) &&
2257 (SIM->get_param_num("heads", base)->get() ==0 ) &&
2258 (SIM->get_param_num("spt", base)->get() == 0)) {
2259 PARSE_WARN(("%s: ataX-master/slave CHS set to 0/0/0 - autodetection enabled", context));
2260 // using heads = 16 and spt = 63 for autodetection (bximage defaults)
2261 SIM->get_param_num("heads", base)->set(16);
2262 SIM->get_param_num("spt", base)->set(63);
2264 } else if (SIM->get_param_enum("type", base)->get() != BX_ATA_DEVICE_CDROM) {
2265 PARSE_WARN(("%s: ataX-master/slave: type should be specified", context));
2268 } else if (!strcmp(params[0], "boot")) {
2269 char tmppath[80];
2270 if (num_params < 2) {
2271 PARSE_ERR(("%s: boot directive malformed.", context));
2273 for (i=1; i<num_params; i++) {
2274 sprintf(tmppath, "boot_params.boot_drive%d", i);
2275 if (!strcmp(params[i], "none")) {
2276 SIM->get_param_enum(tmppath)->set(BX_BOOT_NONE);
2277 } else if (!strcmp(params[i], "a")) {
2278 SIM->get_param_enum(tmppath)->set(BX_BOOT_FLOPPYA);
2279 } else if (!strcmp(params[i], "floppy")) {
2280 SIM->get_param_enum(tmppath)->set(BX_BOOT_FLOPPYA);
2281 } else if (!strcmp(params[i], "c")) {
2282 SIM->get_param_enum(tmppath)->set(BX_BOOT_DISKC);
2283 } else if (!strcmp(params[i], "disk")) {
2284 SIM->get_param_enum(tmppath)->set(BX_BOOT_DISKC);
2285 } else if (!strcmp(params[i], "cdrom")) {
2286 SIM->get_param_enum(tmppath)->set(BX_BOOT_CDROM);
2287 } else {
2288 PARSE_ERR(("%s: boot directive with unknown boot drive '%s'. use 'floppy', 'disk' or 'cdrom'.", context, params[i]));
2291 if (SIM->get_param_enum(BXPN_BOOTDRIVE1)->get() == BX_BOOT_NONE) {
2292 PARSE_ERR(("%s: first boot drive must be one of 'floppy', 'disk' or 'cdrom'.", context));
2294 if ((SIM->get_param_enum(BXPN_BOOTDRIVE1)->get() == SIM->get_param_enum(BXPN_BOOTDRIVE2)->get()) ||
2295 (SIM->get_param_enum(BXPN_BOOTDRIVE1)->get() == SIM->get_param_enum(BXPN_BOOTDRIVE3)->get()) ||
2296 ((SIM->get_param_enum(BXPN_BOOTDRIVE3)->get() != BX_BOOT_NONE) &&
2297 (SIM->get_param_enum(BXPN_BOOTDRIVE2)->get() == SIM->get_param_enum(BXPN_BOOTDRIVE3)->get()))) {
2298 PARSE_ERR(("%s: a boot drive appears twice in boot sequence.", context));
2300 } else if (!strcmp(params[0], "floppy_bootsig_check")) {
2301 if (num_params != 2) {
2302 PARSE_ERR(("%s: floppy_bootsig_check directive malformed.", context));
2304 if (strncmp(params[1], "disabled=", 9)) {
2305 PARSE_ERR(("%s: floppy_bootsig_check directive malformed.", context));
2307 if (params[1][9] == '0')
2308 SIM->get_param_bool(BXPN_FLOPPYSIGCHECK)->set(0);
2309 else if (params[1][9] == '1')
2310 SIM->get_param_bool(BXPN_FLOPPYSIGCHECK)->set(1);
2311 else {
2312 PARSE_ERR(("%s: floppy_bootsig_check directive malformed.", context));
2314 } else if (!strcmp(params[0], "log")) {
2315 if (num_params != 2) {
2316 PARSE_ERR(("%s: log directive has wrong # args.", context));
2318 SIM->get_param_string(BXPN_LOG_FILENAME)->set(params[1]);
2319 } else if (!strcmp(params[0], "logprefix")) {
2320 if (num_params != 2) {
2321 PARSE_ERR(("%s: logprefix directive has wrong # args.", context));
2323 SIM->get_param_string(BXPN_LOG_PREFIX)->set(params[1]);
2324 } else if (!strcmp(params[0], "debugger_log")) {
2325 if (num_params != 2) {
2326 PARSE_ERR(("%s: debugger_log directive has wrong # args.", context));
2328 SIM->get_param_string(BXPN_DEBUGGER_LOG_FILENAME)->set(params[1]);
2329 } else if (!strcmp(params[0], "panic")) {
2330 if (num_params != 2) {
2331 PARSE_ERR(("%s: panic directive malformed.", context));
2333 if (parse_log_options(context, params[0], params[1]) < 0) {
2334 return -1;
2336 } else if (!strcmp(params[0], "pass")) {
2337 if (num_params != 2) {
2338 PARSE_ERR(("%s: pass directive malformed.", context));
2340 if (parse_log_options(context, params[0], params[1]) < 0) {
2341 return -1;
2343 } else if (!strcmp(params[0], "error")) {
2344 if (num_params != 2) {
2345 PARSE_ERR(("%s: error directive malformed.", context));
2347 if (parse_log_options(context, params[0], params[1]) < 0) {
2348 return -1;
2350 } else if (!strcmp(params[0], "info")) {
2351 if (num_params != 2) {
2352 PARSE_ERR(("%s: info directive malformed.", context));
2354 if (parse_log_options(context, params[0], params[1]) < 0) {
2355 return -1;
2357 } else if (!strcmp(params[0], "debug")) {
2358 if (num_params != 2) {
2359 PARSE_ERR(("%s: debug directive malformed.", context));
2361 if (parse_log_options(context, params[0], params[1]) < 0) {
2362 return -1;
2364 } else if (!strcmp(params[0], "cpu")) {
2365 if (num_params < 2) {
2366 PARSE_ERR(("%s: cpu directive malformed.", context));
2368 for (i=1; i<num_params; i++) {
2369 if (!strncmp(params[i], "count=", 6)) {
2370 unsigned processors = 1, cores = 1, threads = 1;
2371 sscanf(&params[i][6], "%u:%u:%u", &processors, &cores, &threads);
2372 unsigned smp_threads = cores*threads*processors;
2373 if (smp_threads > BX_MAX_SMP_THREADS_SUPPORTED) {
2374 PARSE_ERR(("%s: too many SMP threads defined, only %u threads supported",
2375 context, BX_MAX_SMP_THREADS_SUPPORTED));
2377 if (smp_threads < 1) {
2378 PARSE_ERR(("%s: at least one CPU thread should be defined, cpu directive malformed", context));
2380 SIM->get_param_num(BXPN_CPU_NPROCESSORS)->set(processors);
2381 SIM->get_param_num(BXPN_CPU_NCORES)->set(cores);
2382 SIM->get_param_num(BXPN_CPU_NTHREADS)->set(threads);
2383 } else if (!strncmp(params[i], "ips=", 4)) {
2384 SIM->get_param_num(BXPN_IPS)->set(atol(&params[i][4]));
2385 if (SIM->get_param_num(BXPN_IPS)->get() < BX_MIN_IPS) {
2386 PARSE_WARN(("%s: WARNING: ips is AWFULLY low!", context));
2388 #if BX_SUPPORT_SMP
2389 } else if (!strncmp(params[i], "quantum=", 8)) {
2390 SIM->get_param_num(BXPN_SMP_QUANTUM)->set(atol(&params[i][8]));
2391 #endif
2392 } else if (!strncmp(params[i], "reset_on_triple_fault=", 22)) {
2393 if (params[i][22] == '0' || params[i][22] == '1') {
2394 SIM->get_param_bool(BXPN_RESET_ON_TRIPLE_FAULT)->set (params[i][22] - '0');
2395 } else {
2396 PARSE_ERR(("%s: cpu directive malformed.", context));
2398 } else {
2399 PARSE_ERR(("%s: cpu directive malformed.", context));
2402 } else if (!strcmp(params[0], "megs")) {
2403 if (num_params != 2) {
2404 PARSE_ERR(("%s: megs directive: wrong # args.", context));
2406 SIM->get_param_num(BXPN_MEM_SIZE)->set(atol(params[1]));
2407 } else if (!strcmp(params[0], "romimage")) {
2408 if ((num_params < 2) || (num_params > 3)) {
2409 PARSE_ERR(("%s: romimage directive: wrong # args.", context));
2411 if (!strncmp(params[1], "file=", 5)) {
2412 SIM->get_param_string(BXPN_ROM_PATH)->set(&params[1][5]);
2413 } else {
2414 PARSE_ERR(("%s: romimage directive malformed.", context));
2416 if (num_params == 3) {
2417 if (!strncmp(params[2], "address=", 8)) {
2418 if ((params[2][8] == '0') && (params[2][9] == 'x'))
2419 SIM->get_param_num(BXPN_ROM_ADDRESS)->set(strtoul(&params[2][8], NULL, 16));
2420 else
2421 SIM->get_param_num(BXPN_ROM_ADDRESS)->set(strtoul(&params[2][8], NULL, 10));
2422 } else {
2423 PARSE_ERR(("%s: romimage directive malformed.", context));
2425 } else {
2426 SIM->get_param_num(BXPN_ROM_ADDRESS)->set (0);
2428 } else if (!strcmp(params[0], "vgaromimage")) {
2429 if (num_params != 2) {
2430 PARSE_ERR(("%s: vgaromimage directive: wrong # args.", context));
2432 if (!strncmp(params[1], "file=", 5)) {
2433 SIM->get_param_string(BXPN_VGA_ROM_PATH)->set(&params[1][5]);
2434 } else {
2435 BX_INFO(("WARNING: syntax has changed, please use 'vgaromimage: file=...' now"));
2436 SIM->get_param_string(BXPN_VGA_ROM_PATH)->set(params[1]);
2438 } else if (!strncmp(params[0], "optromimage", 11)) {
2439 int num = atoi(&params[0][11]);
2440 char tmppath[80], tmpaddr[80];
2441 if ((num < 1) || (num > BX_N_OPTROM_IMAGES)) {
2442 PARSE_ERR(("%s: optromimage%d: not supported", context, num));
2444 if (num_params != 3) {
2445 PARSE_ERR(("%s: optromimage%d directive: wrong # args.", context, num));
2447 sprintf(tmppath, "memory.optrom.%d.path", num);
2448 sprintf(tmpaddr, "memory.optrom.%d.addr", num);
2449 for (i=1; i<num_params; i++) {
2450 if (!strncmp(params[i], "file=", 5)) {
2451 SIM->get_param_string(tmppath)->set(&params[i][5]);
2452 } else if (!strncmp(params[i], "address=", 8)) {
2453 if ((params[i][8] == '0') && (params[2][9] == 'x'))
2454 SIM->get_param_num(tmpaddr)->set(strtoul(&params[i][8], NULL, 16));
2455 else
2456 SIM->get_param_num(tmpaddr)->set(strtoul(&params[i][8], NULL, 10));
2457 } else {
2458 PARSE_ERR(("%s: optromimage%d directive malformed.", context, num));
2461 } else if (!strncmp(params[0], "optramimage", 11)) {
2462 int num = atoi(&params[0][11]);
2463 char tmppath[80], tmpaddr[80];
2464 if ((num < 1) || (num > BX_N_OPTRAM_IMAGES)) {
2465 PARSE_ERR(("%s: optramimage%d: not supported", context, num));
2467 if (num_params != 3) {
2468 PARSE_ERR(("%s: optramimage%d directive: wrong # args.", context, num));
2470 sprintf(tmppath, "memory.optram.%d.path", num);
2471 sprintf(tmpaddr, "memory.optram.%d.addr", num);
2472 for (i=1; i<num_params; i++) {
2473 if (!strncmp(params[i], "file=", 5)) {
2474 SIM->get_param_string(tmppath)->set(&params[i][5]);
2475 } else if (!strncmp(params[i], "address=", 8)) {
2476 if ((params[i][8] == '0') && (params[2][9] == 'x'))
2477 SIM->get_param_num(tmpaddr)->set(strtoul(&params[i][8], NULL, 16));
2478 else
2479 SIM->get_param_num(tmpaddr)->set(strtoul(&params[i][8], NULL, 10));
2480 } else {
2481 PARSE_ERR(("%s: optramimage%d directive malformed.", context, num));
2484 } else if (!strcmp(params[0], "vga_update_interval")) {
2485 if (num_params != 2) {
2486 PARSE_ERR(("%s: vga_update_interval directive: wrong # args.", context));
2488 SIM->get_param_num(BXPN_VGA_UPDATE_INTERVAL)->set(atol(params[1]));
2489 if (SIM->get_param_num(BXPN_VGA_UPDATE_INTERVAL)->get() < 50000) {
2490 BX_INFO(("%s: vga_update_interval seems awfully small!", context));
2492 } else if (!strcmp(params[0], "vga")) {
2493 if (num_params != 2) {
2494 PARSE_ERR(("%s: vga directive: wrong # args.", context));
2496 if (!strncmp(params[1], "extension=", 10)) {
2497 SIM->get_param_string(BXPN_VGA_EXTENSION)->set(&params[1][10]);
2499 } else if (!strcmp(params[0], "keyboard_serial_delay")) {
2500 if (num_params != 2) {
2501 PARSE_ERR(("%s: keyboard_serial_delay directive: wrong # args.", context));
2503 SIM->get_param_num(BXPN_KBD_SERIAL_DELAY)->set(atol(params[1]));
2504 if (SIM->get_param_num(BXPN_KBD_SERIAL_DELAY)->get() < 5) {
2505 PARSE_ERR (("%s: keyboard_serial_delay not big enough!", context));
2507 } else if (!strcmp(params[0], "keyboard_paste_delay")) {
2508 if (num_params != 2) {
2509 PARSE_ERR(("%s: keyboard_paste_delay directive: wrong # args.", context));
2511 SIM->get_param_num(BXPN_KBD_PASTE_DELAY)->set(atol(params[1]));
2512 if (SIM->get_param_num(BXPN_KBD_PASTE_DELAY)->get() < 1000) {
2513 PARSE_ERR (("%s: keyboard_paste_delay not big enough!", context));
2515 } else if (!strcmp(params[0], "floppy_command_delay")) {
2516 PARSE_WARN(("%s: floppy_command_delay is DEPRECATED (now using hardware timing).", context));
2517 } else if (!strcmp(params[0], "ips")) {
2518 PARSE_WARN(("%s: ips directive is DEPRECATED (use cpu directive parameter 'ips').", context));
2519 if (num_params != 2) {
2520 PARSE_ERR(("%s: ips directive: wrong # args.", context));
2522 SIM->get_param_num(BXPN_IPS)->set(atol(params[1]));
2523 if (SIM->get_param_num(BXPN_IPS)->get() < BX_MIN_IPS) {
2524 PARSE_WARN(("%s: WARNING: ips is AWFULLY low!", context));
2526 } else if (!strcmp(params[0], "text_snapshot_check")) {
2527 if (num_params != 2) {
2528 PARSE_ERR(("%s: text_snapshot_check directive: wrong # args.", context));
2530 if (!strncmp(params[1], "enabled=", 8)) {
2531 if (params[1][8] == '0' || params[1][8] == '1')
2532 SIM->get_param_bool(BXPN_TEXT_SNAPSHOT_CHECK)->set(params[1][8] - '0');
2533 else
2534 PARSE_ERR(("%s: text_snapshot_check directive malformed.", context));
2535 } else {
2536 PARSE_ERR(("%s: text_snapshot_check directive malformed.", context));
2538 } else if (!strcmp(params[0], "mouse")) {
2539 if (num_params < 2) {
2540 PARSE_ERR(("%s: mouse directive malformed.", context));
2542 for (i=1; i<num_params; i++) {
2543 if (!strncmp(params[i], "enabled=", 8)) {
2544 if (params[i][8] == '0' || params[i][8] == '1')
2545 SIM->get_param_bool(BXPN_MOUSE_ENABLED)->set(params[i][8] - '0');
2546 else
2547 PARSE_ERR(("%s: mouse directive malformed.", context));
2548 } else if (!strncmp(params[i], "type=", 5)) {
2549 if (!SIM->get_param_enum(BXPN_MOUSE_TYPE)->set_by_name(&params[i][5]))
2550 PARSE_ERR(("%s: mouse type '%s' not available", context, &params[i][5]));
2551 } else {
2552 PARSE_ERR(("%s: mouse directive malformed.", context));
2555 } else if (!strcmp(params[0], "private_colormap")) {
2556 if (num_params != 2) {
2557 PARSE_ERR(("%s: private_colormap directive malformed.", context));
2559 if (strncmp(params[1], "enabled=", 8)) {
2560 PARSE_ERR(("%s: private_colormap directive malformed.", context));
2562 if (params[1][8] == '0' || params[1][8] == '1')
2563 SIM->get_param_bool(BXPN_PRIVATE_COLORMAP)->set(params[1][8] - '0');
2564 else {
2565 PARSE_ERR(("%s: private_colormap directive malformed.", context));
2567 } else if (!strcmp(params[0], "fullscreen")) {
2568 #if BX_WITH_AMIGAOS
2569 if (num_params != 2) {
2570 PARSE_ERR(("%s: fullscreen directive malformed.", context));
2572 if (strncmp(params[1], "enabled=", 8)) {
2573 PARSE_ERR(("%s: fullscreen directive malformed.", context));
2575 if (params[1][8] == '0' || params[1][8] == '1') {
2576 SIM->get_param_bool(BXPN_FULLSCREEN)->set(params[1][8] - '0');
2577 } else {
2578 PARSE_ERR(("%s: fullscreen directive malformed.", context));
2580 #endif
2581 } else if (!strcmp(params[0], "screenmode")) {
2582 #if BX_WITH_AMIGAOS
2583 if (num_params != 2) {
2584 PARSE_ERR(("%s: screenmode directive malformed.", context));
2586 if (strncmp(params[1], "name=", 5)) {
2587 PARSE_ERR(("%s: screenmode directive malformed.", context));
2589 SIM->get_param_string(BXPN_SCREENMODE)->set(&params[1][5]);
2590 #endif
2591 } else if (!strcmp(params[0], "sb16")) {
2592 int enable = 1;
2593 base = (bx_list_c*) SIM->get_param(BXPN_SB16);
2594 for (i=1; i<num_params; i++) {
2595 if (!strncmp(params[i], "enabled=", 8)) {
2596 enable = atol(&params[i][8]);
2597 } else if (!strncmp(params[i], "midi=", 5)) {
2598 SIM->get_param_string("midifile", base)->set(&params[i][5]);
2599 } else if (!strncmp(params[i], "midimode=", 9)) {
2600 SIM->get_param_num("midimode", base)->set(atol(&params[i][9]));
2601 } else if (!strncmp(params[i], "wave=", 5)) {
2602 SIM->get_param_string("wavefile", base)->set(&params[i][5]);
2603 } else if (!strncmp(params[i], "wavemode=", 9)) {
2604 SIM->get_param_num("wavemode", base)->set(atol(&params[i][9]));
2605 } else if (!strncmp(params[i], "log=", 4)) {
2606 SIM->get_param_string("logfile", base)->set(&params[i][4]);
2607 } else if (!strncmp(params[i], "loglevel=", 9)) {
2608 SIM->get_param_num("loglevel", base)->set(atol(&params[i][9]));
2609 } else if (!strncmp(params[i], "dmatimer=", 9)) {
2610 SIM->get_param_num("dmatimer", base)->set(atol(&params[i][9]));
2611 } else {
2612 BX_ERROR(("%s: unknown parameter for sb16 ignored.", context));
2615 if ((enable != 0) && (SIM->get_param_num("dmatimer", base)->get() > 0))
2616 SIM->get_param_bool("enabled", base)->set(1);
2617 else
2618 SIM->get_param_bool("enabled", base)->set(0);
2619 } else if ((!strncmp(params[0], "com", 3)) && (strlen(params[0]) == 4)) {
2620 char tmpname[80];
2621 idx = params[0][3];
2622 if ((idx < '1') || (idx > '9')) {
2623 PARSE_ERR(("%s: comX directive malformed.", context));
2625 idx -= '0';
2626 if (idx > BX_N_SERIAL_PORTS) {
2627 PARSE_ERR(("%s: comX port number out of range.", context));
2629 sprintf(tmpname, "ports.serial.%d", idx);
2630 base = (bx_list_c*) SIM->get_param(tmpname);
2631 for (i=1; i<num_params; i++) {
2632 if (!strncmp(params[i], "enabled=", 8)) {
2633 SIM->get_param_bool("enabled", base)->set(atol(&params[i][8]));
2634 } else if (!strncmp(params[i], "mode=", 5)) {
2635 if (!SIM->get_param_enum("mode", base)->set_by_name(&params[i][5]))
2636 PARSE_ERR(("%s: com%d serial port mode '%s' not available", context, idx, &params[i][5]));
2637 SIM->get_param_bool("enabled", base)->set(1);
2638 } else if (!strncmp(params[i], "dev=", 4)) {
2639 SIM->get_param_string("dev", base)->set(&params[i][4]);
2640 SIM->get_param_bool("enabled", base)->set(1);
2641 } else {
2642 PARSE_ERR(("%s: unknown parameter for com%d ignored.", context, idx));
2645 } else if ((!strncmp(params[0], "parport", 7)) && (strlen(params[0]) == 8)) {
2646 char tmpname[80];
2647 idx = params[0][7];
2648 if ((idx < '1') || (idx > '9')) {
2649 PARSE_ERR(("%s: parportX directive malformed.", context));
2651 idx -= '0';
2652 if (idx > BX_N_PARALLEL_PORTS) {
2653 PARSE_ERR(("%s: parportX port number out of range.", context));
2655 sprintf(tmpname, "ports.parallel.%d", idx);
2656 base = (bx_list_c*) SIM->get_param(tmpname);
2657 for (i=1; i<num_params; i++) {
2658 if (!strncmp(params[i], "enabled=", 8)) {
2659 SIM->get_param_bool("enabled", base)->set(atol(&params[i][8]));
2660 } else if (!strncmp(params[i], "file=", 5)) {
2661 SIM->get_param_string("outfile", base)->set(&params[i][5]);
2662 SIM->get_param_bool("enabled", base)->set(1);
2663 } else {
2664 BX_ERROR(("%s: unknown parameter for parport%d ignored.", context, idx));
2667 } else if ((!strncmp(params[0], "usb", 3)) && (strlen(params[0]) == 4)) {
2668 char tmpname[80];
2669 idx = params[0][3];
2670 if ((idx < '1') || (idx > '9')) {
2671 PARSE_ERR(("%s: usbX directive malformed.", context));
2673 idx -= '0';
2674 if (idx > BX_N_USB_HUBS) {
2675 PARSE_ERR(("%s: usbX hub number out of range.", context));
2677 sprintf(tmpname, "ports.usb.%d", idx);
2678 base = (bx_list_c*) SIM->get_param(tmpname);
2679 for (i=1; i<num_params; i++) {
2680 if (!strncmp(params[i], "enabled=", 8)) {
2681 SIM->get_param_bool("enabled", base)->set(atol(&params[i][8]));
2682 } else if (!strncmp(params[i], "port1=", 6)) {
2683 SIM->get_param_string("port1", base)->set(&params[i][6]);
2684 } else if (!strncmp(params[i], "option1=", 8)) {
2685 PARSE_WARN(("%s: usb port1 option is now deprecated", context));
2686 } else if (!strncmp(params[i], "port2=", 6)) {
2687 SIM->get_param_string("port2", base)->set(&params[i][6]);
2688 } else if (!strncmp(params[i], "option2=", 8)) {
2689 PARSE_WARN(("%s: usb port2 option is now deprecated", context));
2690 } else if (!strncmp(params[i], "ioaddr=", 7)) {
2691 PARSE_WARN(("%s: usb ioaddr is now DEPRECATED (assigned by BIOS).", context));
2692 } else if (!strncmp(params[i], "irq=", 4)) {
2693 PARSE_WARN(("%s: usb irq is now DEPRECATED (assigned by BIOS).", context));
2694 } else {
2695 PARSE_WARN(("%s: unknown parameter '%s' for usb%d ignored.", context, params[i], idx));
2698 } else if (!strcmp(params[0], "i440fxsupport")) {
2699 char tmpdev[80];
2700 for (i=1; i<num_params; i++) {
2701 if (!strncmp(params[i], "enabled=", 8)) {
2702 SIM->get_param_bool(BXPN_I440FX_SUPPORT)->set(atol(&params[i][8]));
2703 } else if ((!strncmp(params[i], "slot", 4)) && (params[i][5] == '=')) {
2704 slot = atol(&params[i][4]);
2705 if ((slot > 0) && (slot < 6)) {
2706 sprintf(tmpdev, "pci.slot.%d", slot);
2707 SIM->get_param_string(tmpdev)->set(&params[i][6]);
2708 } else {
2709 BX_ERROR(("%s: unknown pci slot number ignored.", context));
2711 } else {
2712 PARSE_ERR(("%s: i440fxsupport: unknown parameter '%s'.", context, params[i]));
2715 } else if (!strcmp(params[0], "pcidev")) {
2716 if (num_params != 3) {
2717 PARSE_ERR(("%s: pcidev directive malformed.", context));
2719 for (i=1; i<num_params; i++) {
2720 if (!strncmp(params[i], "vendor=", 7)) {
2721 if ( (params[i][7] == '0') && (toupper(params[i][8]) == 'X') )
2722 SIM->get_param_num(BXPN_PCIDEV_VENDOR)->set(strtoul(&params[i][7], NULL, 16));
2723 else
2724 SIM->get_param_num(BXPN_PCIDEV_VENDOR)->set(strtoul(&params[i][7], NULL, 10));
2726 else if (!strncmp(params[i], "device=", 7)) {
2727 if ( (params[i][7] == '0') && (toupper(params[i][8]) == 'X') )
2728 SIM->get_param_num(BXPN_PCIDEV_DEVICE)->set(strtoul(&params[i][7], NULL, 16));
2729 else
2730 SIM->get_param_num(BXPN_PCIDEV_DEVICE)->set(strtoul(&params[i][7], NULL, 10));
2732 else {
2733 BX_ERROR(("%s: unknown parameter for pcidev ignored.", context));
2736 } else if (!strcmp(params[0], "cmosimage")) {
2737 for (i=1; i<num_params; i++) {
2738 if (!strncmp(params[i], "file=", 5)) {
2739 SIM->get_param_string(BXPN_CMOSIMAGE_PATH)->set(&params[i][5]);
2740 } else if (!strcmp(params[i], "rtc_init=time0")) {
2741 SIM->get_param_bool(BXPN_CMOSIMAGE_RTC_INIT)->set(0);
2742 } else if (!strcmp(params[i], "rtc_init=image")) {
2743 SIM->get_param_bool(BXPN_CMOSIMAGE_RTC_INIT)->set(1);
2744 } else {
2745 // for backward compatiblity
2746 SIM->get_param_string(BXPN_CMOSIMAGE_PATH)->set(params[i]);
2749 if (strlen(SIM->get_param_string(BXPN_CMOSIMAGE_PATH)->getptr()) > 0) {
2750 SIM->get_param_bool(BXPN_CMOSIMAGE_ENABLED)->set(1);
2752 } else if (!strcmp(params[0], "clock")) {
2753 for (i=1; i<num_params; i++) {
2754 if (!strncmp(params[i], "sync=", 5)) {
2755 SIM->get_param_enum(BXPN_CLOCK_SYNC)->set_by_name(&params[i][5]);
2757 else if (!strcmp(params[i], "time0=local")) {
2758 SIM->get_param_num(BXPN_CLOCK_TIME0)->set(BX_CLOCK_TIME0_LOCAL);
2760 else if (!strcmp(params[i], "time0=utc")) {
2761 SIM->get_param_num(BXPN_CLOCK_TIME0)->set(BX_CLOCK_TIME0_UTC);
2763 else if (!strncmp(params[i], "time0=", 6)) {
2764 SIM->get_param_num(BXPN_CLOCK_TIME0)->set(atoi(&params[i][6]));
2766 else {
2767 BX_ERROR(("%s: unknown parameter for clock ignored.", context));
2771 else if (!strcmp(params[0], "gdbstub")) {
2772 #if BX_GDBSTUB
2773 if (num_params < 2) {
2774 PARSE_ERR(("%s: gdbstub directive: wrong # args.", context));
2776 base = (bx_list_c*) SIM->get_param(BXPN_GDBSTUB);
2777 for (i=1; i<num_params; i++) {
2778 if (!strncmp(params[i], "enabled=", 8)) {
2779 if (params[i][8] == '0') {
2780 SIM->get_param_bool("enabled", base)->set(0);
2781 BX_INFO(("Disabled gdbstub"));
2782 bx_dbg.gdbstub_enabled = 0;
2784 else if (params[i][8] == '1') {
2785 SIM->get_param_bool("enabled", base)->set(1);
2786 BX_INFO(("Enabled gdbstub"));
2787 bx_dbg.gdbstub_enabled = 1;
2789 else {
2790 PARSE_ERR(("%s: gdbstub directive malformed.", context));
2793 else if (!strncmp(params[i], "port=", 5)) {
2794 SIM->get_param_num("port", base)->set(atoi(&params[i][5]));
2796 else if (!strncmp(params[i], "text_base=", 10)) {
2797 SIM->get_param_num("text_base", base)->set(atoi(&params[i][10]));
2799 else if (!strncmp(params[i], "data_base=", 10)) {
2800 SIM->get_param_num("data_base", base)->set(atoi(&params[i][10]));
2802 else if (!strncmp(params[i], "bss_base=", 9)) {
2803 SIM->get_param_num("bss_base", base)->set(atoi(&params[i][9]));
2805 else {
2806 PARSE_ERR(("%s: gdbstub directive malformed.", context));
2809 #else
2810 PARSE_ERR(("%s: Bochs is not compiled with gdbstub support", context));
2811 #endif
2814 #if BX_MAGIC_BREAKPOINT
2815 else if (!strcmp(params[0], "magic_break")) {
2816 if (num_params != 2) {
2817 PARSE_ERR(("%s: magic_break directive: wrong # args.", context));
2819 if (strncmp(params[1], "enabled=", 8)) {
2820 PARSE_ERR(("%s: magic_break directive malformed.", context));
2822 if (params[1][8] == '0') {
2823 BX_INFO(("Ignoring magic break points"));
2824 bx_dbg.magic_break_enabled = 0;
2826 else if (params[1][8] == '1') {
2827 BX_INFO(("Stopping on magic break points"));
2828 bx_dbg.magic_break_enabled = 1;
2830 else {
2831 PARSE_ERR(("%s: magic_break directive malformed.", context));
2834 #endif
2835 else if (!strcmp(params[0], "ne2k")) {
2836 int tmp[6];
2837 char tmpchar[6];
2838 int valid = 0;
2839 int n;
2840 base = (bx_list_c*) SIM->get_param(BXPN_NE2K);
2841 if (!SIM->get_param_bool("enabled", base)->get()) {
2842 SIM->get_param_enum("ethmod", base)->set_by_name("null");
2844 for (i=1; i<num_params; i++) {
2845 if (!strncmp(params[i], "enabled=", 8)) {
2846 if (atol(&params[i][8]) == 0) valid |= 0x80;
2848 else if (!strncmp(params[i], "ioaddr=", 7)) {
2849 SIM->get_param_num("ioaddr", base)->set(strtoul(&params[i][7], NULL, 16));
2850 valid |= 0x01;
2852 else if (!strncmp(params[i], "irq=", 4)) {
2853 SIM->get_param_num("irq", base)->set(atol(&params[i][4]));
2854 valid |= 0x02;
2856 else if (!strncmp(params[i], "mac=", 4)) {
2857 n = sscanf(&params[i][4], "%x:%x:%x:%x:%x:%x",
2858 &tmp[0],&tmp[1],&tmp[2],&tmp[3],&tmp[4],&tmp[5]);
2859 if (n != 6) {
2860 PARSE_ERR(("%s: ne2k mac address malformed.", context));
2862 for (n=0;n<6;n++)
2863 tmpchar[n] = (unsigned char)tmp[n];
2864 SIM->get_param_string("macaddr", base)->set(tmpchar);
2865 valid |= 0x04;
2867 else if (!strncmp(params[i], "ethmod=", 7)) {
2868 if (!SIM->get_param_enum("ethmod", base)->set_by_name(&params[i][7]))
2869 PARSE_ERR(("%s: ethernet module '%s' not available", context, &params[i][7]));
2871 else if (!strncmp(params[i], "ethdev=", 7)) {
2872 SIM->get_param_string("ethdev", base)->set(&params[i][7]);
2874 else if (!strncmp(params[i], "script=", 7)) {
2875 SIM->get_param_string("script", base)->set(&params[i][7]);
2877 else {
2878 PARSE_WARN(("%s: unknown parameter '%s' for ne2k ignored.", context, params[i]));
2881 if (!SIM->get_param_bool("enabled", base)->get()) {
2882 if (valid == 0x07) {
2883 SIM->get_param_bool("enabled", base)->set(1);
2884 } else if (valid < 0x80) {
2885 PARSE_ERR(("%s: ne2k directive incomplete (ioaddr, irq and mac are required)", context));
2887 } else {
2888 if (valid & 0x80) {
2889 SIM->get_param_bool("enabled", base)->set(0);
2892 } else if (!strcmp(params[0], "pnic")) {
2893 int tmp[6];
2894 char tmpchar[6];
2895 int valid = 0;
2896 int n;
2897 base = (bx_list_c*) SIM->get_param(BXPN_PNIC);
2898 if (!SIM->get_param_bool("enabled", base)->get()) {
2899 SIM->get_param_enum("ethmod", base)->set_by_name("null");
2901 for (i=1; i<num_params; i++) {
2902 if (!strncmp(params[i], "enabled=", 8)) {
2903 if (atol(&params[i][8]) == 0) valid |= 0x80;
2904 } else if (!strncmp(params[i], "ioaddr=", 7)) {
2905 PARSE_WARN(("%s: pnic ioaddr is now DEPRECATED (assigned by BIOS).", context));
2906 } else if (!strncmp(params[i], "irq=", 4)) {
2907 PARSE_WARN(("%s: pnic irq is now DEPRECATED (assigned by BIOS).", context));
2908 } else if (!strncmp(params[i], "mac=", 4)) {
2909 n = sscanf(&params[i][4], "%x:%x:%x:%x:%x:%x",
2910 &tmp[0],&tmp[1],&tmp[2],&tmp[3],&tmp[4],&tmp[5]);
2911 if (n != 6) {
2912 PARSE_ERR(("%s: pnic mac address malformed.", context));
2914 for (n=0;n<6;n++)
2915 tmpchar[n] = (unsigned char)tmp[n];
2916 SIM->get_param_string("macaddr", base)->set(tmpchar);
2917 valid |= 0x07;
2918 } else if (!strncmp(params[i], "ethmod=", 7)) {
2919 if (!SIM->get_param_enum("ethmod", base)->set_by_name(&params[i][7]))
2920 PARSE_ERR(("%s: ethernet module '%s' not available", context, &params[i][7]));
2921 } else if (!strncmp(params[i], "ethdev=", 7)) {
2922 SIM->get_param_string("ethdev", base)->set(&params[i][7]);
2923 } else if (!strncmp(params[i], "script=", 7)) {
2924 SIM->get_param_string("script", base)->set(&params[i][7]);
2925 } else {
2926 PARSE_WARN(("%s: unknown parameter '%s' for pnic ignored.", context, params[i]));
2929 if (!SIM->get_param_bool("enabled", base)->get()) {
2930 if (valid == 0x07) {
2931 SIM->get_param_bool("enabled", base)->set(1);
2932 } else if (valid < 0x80) {
2933 PARSE_ERR(("%s: pnic directive incomplete (mac is required)", context));
2935 } else {
2936 if (valid & 0x80) {
2937 SIM->get_param_bool("enabled", base)->set(0);
2940 } else if (!strcmp(params[0], "load32bitOSImage")) {
2941 if ( (num_params!=4) && (num_params!=5) ) {
2942 PARSE_ERR(("%s: load32bitOSImage directive: wrong # args.", context));
2944 if (strncmp(params[1], "os=", 3)) {
2945 PARSE_ERR(("%s: load32bitOSImage: directive malformed.", context));
2947 if (!strcmp(&params[1][3], "nullkernel")) {
2948 SIM->get_param_enum(BXPN_LOAD32BITOS_WHICH)->set(Load32bitOSNullKernel);
2950 else if (!strcmp(&params[1][3], "linux")) {
2951 SIM->get_param_enum(BXPN_LOAD32BITOS_WHICH)->set(Load32bitOSLinux);
2953 else {
2954 PARSE_ERR(("%s: load32bitOSImage: unsupported OS.", context));
2956 if (strncmp(params[2], "path=", 5)) {
2957 PARSE_ERR(("%s: load32bitOSImage: directive malformed.", context));
2959 if (strncmp(params[3], "iolog=", 6)) {
2960 PARSE_ERR(("%s: load32bitOSImage: directive malformed.", context));
2962 SIM->get_param_string(BXPN_LOAD32BITOS_PATH)->set(&params[2][5]);
2963 SIM->get_param_string(BXPN_LOAD32BITOS_IOLOG)->set(&params[3][6]);
2964 if (num_params == 5) {
2965 if (strncmp(params[4], "initrd=", 7)) {
2966 PARSE_ERR(("%s: load32bitOSImage: directive malformed.", context));
2968 SIM->get_param_string(BXPN_LOAD32BITOS_INITRD)->set(&params[4][7]);
2971 else if (!strcmp(params[0], "keyboard_type")) {
2972 if (num_params != 2) {
2973 PARSE_ERR(("%s: keyboard_type directive: wrong # args.", context));
2975 if (!SIM->get_param_enum(BXPN_KBD_TYPE)->set_by_name(params[1])) {
2976 PARSE_ERR(("%s: keyboard_type directive: wrong arg '%s'.", context,params[1]));
2979 else if (!strcmp(params[0], "keyboard_mapping")
2980 ||!strcmp(params[0], "keyboardmapping")) {
2981 for (i=1; i<num_params; i++) {
2982 if (!strncmp(params[i], "enabled=", 8)) {
2983 SIM->get_param_bool(BXPN_KBD_USEMAPPING)->set(atol(&params[i][8]));
2985 else if (!strncmp(params[i], "map=", 4)) {
2986 SIM->get_param_string(BXPN_KBD_KEYMAP)->set(&params[i][4]);
2990 else if (!strcmp(params[0], "user_shortcut"))
2992 if (num_params != 2) {
2993 PARSE_ERR(("%s: user_shortcut directive: wrong # args.", context));
2995 if(!strncmp(params[1], "keys=", 4)) {
2996 SIM->get_param_string(BXPN_USER_SHORTCUT)->set(&params[1][5]);
2997 if ((strchr(&params[1][5], '-') == NULL) && (strlen(&params[1][5]) > 5))
2998 PARSE_WARN(("user_shortcut: old-style syntax detected"));
2999 } else {
3000 PARSE_ERR(("%s: user_shortcut directive malformed.", context));
3003 else if (!strcmp(params[0], "config_interface"))
3005 if (num_params != 2) {
3006 PARSE_ERR(("%s: config_interface directive: wrong # args.", context));
3008 if (!SIM->get_param_enum(BXPN_SEL_CONFIG_INTERFACE)->set_by_name(params[1]))
3009 PARSE_ERR(("%s: config_interface '%s' not available", context, params[1]));
3011 else if (!strcmp(params[0], "display_library")) {
3012 if ((num_params < 2) || (num_params > 3)) {
3013 PARSE_ERR(("%s: display_library directive: wrong # args.", context));
3015 if (!SIM->get_param_enum(BXPN_SEL_DISPLAY_LIBRARY)->set_by_name(params[1]))
3016 PARSE_ERR(("%s: display library '%s' not available", context, params[1]));
3017 if (num_params == 3) {
3018 if (!strncmp(params[2], "options=", 8)) {
3019 SIM->get_param_string(BXPN_DISPLAYLIB_OPTIONS)->set(&params[2][8]);
3023 // Old timing options have been replaced by the 'clock' option
3024 else if (!strcmp(params[0], "pit")) // Deprecated
3026 PARSE_ERR(("ERROR: pit directive is DEPRECATED, use clock: instead"));
3028 else if (!strcmp(params[0], "time0")) // Deprectated
3030 PARSE_ERR(("ERROR: time0 directive is DEPRECATED, use clock: instead"));
3032 // user-defined options handled by registered functions
3033 else if ((i = SIM->find_user_option(params[0])) >= 0)
3035 return SIM->parse_user_option(i, context, num_params, &params[0]);
3037 else
3039 PARSE_ERR(( "%s: directive '%s' not understood", context, params[0]));
3041 return 0;
3045 static char *fdtypes[] = {
3046 "none", "1_2", "1_44", "2_88", "720k", "360k", "160k", "180k", "320k"
3049 int bx_write_floppy_options(FILE *fp, int drive)
3051 char path[80], type[80], status[80];
3053 BX_ASSERT(drive==0 || drive==1);
3054 sprintf(path, "floppy.%d.path", drive);
3055 sprintf(type, "floppy.%d.type", drive);
3056 sprintf(status, "floppy.%d.status", drive);
3057 if (SIM->get_param_enum(type)->get() == BX_FLOPPY_NONE) {
3058 fprintf(fp, "# no floppy%c\n", (char)'a'+drive);
3059 return 0;
3061 BX_ASSERT(SIM->get_param_enum(type)->get() > BX_FLOPPY_NONE &&
3062 SIM->get_param_enum(type)->get() <= BX_FLOPPY_LAST);
3063 fprintf(fp, "floppy%c: %s=\"%s\", status=%s\n",
3064 (char)'a'+drive,
3065 fdtypes[SIM->get_param_enum(type)->get() - BX_FLOPPY_NONE],
3066 SIM->get_param_string(path)->getptr(),
3067 SIM->get_param_enum(status)->get_selected());
3068 return 0;
3071 int bx_write_ata_options(FILE *fp, Bit8u channel, bx_list_c *base)
3073 fprintf(fp, "ata%d: enabled=%d", channel, SIM->get_param_bool("enabled", base)->get());
3075 if (SIM->get_param_bool("enabled", base)->get()) {
3076 fprintf(fp, ", ioaddr1=0x%x, ioaddr2=0x%x, irq=%d", SIM->get_param_num("ioaddr1", base)->get(),
3077 SIM->get_param_num("ioaddr2", base)->get(), SIM->get_param_num("irq", base)->get());
3080 fprintf(fp, "\n");
3081 return 0;
3084 int bx_write_atadevice_options(FILE *fp, Bit8u channel, Bit8u drive, bx_list_c *base)
3086 if (SIM->get_param_bool("present", base)->get()) {
3087 fprintf(fp, "ata%d-%s: ", channel, drive==0?"master":"slave");
3089 if (SIM->get_param_enum("type", base)->get() == BX_ATA_DEVICE_DISK) {
3090 fprintf(fp, "type=disk");
3092 fprintf(fp, ", mode=%s", SIM->get_param_enum("mode", base)->get_selected());
3093 fprintf(fp, ", translation=%s", SIM->get_param_enum("translation", base)->get_selected());
3094 fprintf(fp, ", path=\"%s\", cylinders=%d, heads=%d, spt=%d",
3095 SIM->get_param_string("path", base)->getptr(),
3096 SIM->get_param_num("cylinders", base)->get(),
3097 SIM->get_param_num("heads", base)->get(),
3098 SIM->get_param_num("spt", base)->get());
3100 if (SIM->get_param_string("journal", base)->getptr() != NULL)
3101 if (strcmp(SIM->get_param_string("journal", base)->getptr(), "") != 0)
3102 fprintf(fp, ", journal=\"%s\"", SIM->get_param_string("journal", base)->getptr());
3104 } else if (SIM->get_param_enum("type", base)->get() == BX_ATA_DEVICE_CDROM) {
3105 fprintf(fp, "type=cdrom, path=\"%s\", status=%s",
3106 SIM->get_param_string("path", base)->getptr(),
3107 SIM->get_param_enum("status", base)->get_selected());
3110 fprintf(fp, ", biosdetect=%s", SIM->get_param_enum("biosdetect", base)->get_selected());
3112 if (SIM->get_param_string("model", base)->getptr()>0) {
3113 fprintf(fp, ", model=\"%s\"", SIM->get_param_string("model", base)->getptr());
3116 fprintf(fp, "\n");
3118 return 0;
3121 int bx_write_parport_options(FILE *fp, bx_list_c *base, int n)
3123 fprintf(fp, "parport%d: enabled=%d", n, SIM->get_param_bool("enabled", base)->get());
3124 if (SIM->get_param_bool("enabled", base)->get()) {
3125 fprintf(fp, ", file=\"%s\"", SIM->get_param_string("outfile", base)->getptr());
3127 fprintf(fp, "\n");
3128 return 0;
3131 int bx_write_serial_options(FILE *fp, bx_list_c *base, int n)
3133 fprintf(fp, "com%d: enabled=%d", n, SIM->get_param_bool("enabled", base)->get());
3134 if (SIM->get_param_bool("enabled", base)->get()) {
3135 fprintf(fp, ", mode=%s", SIM->get_param_enum("mode", base)->get_selected());
3136 fprintf(fp, ", dev=\"%s\"", SIM->get_param_string("dev", base)->getptr());
3138 fprintf(fp, "\n");
3139 return 0;
3142 int bx_write_usb_options(FILE *fp, bx_list_c *base, int n)
3144 fprintf(fp, "usb%d: enabled=%d", n, SIM->get_param_bool("enabled", base)->get());
3145 if (SIM->get_param_bool("enabled", base)->get()) {
3146 fprintf(fp, ", port1=%s", SIM->get_param_string("port1", base)->getptr());
3147 fprintf(fp, ", port2=%s", SIM->get_param_string("port2", base)->getptr());
3149 fprintf(fp, "\n");
3150 return 0;
3153 int bx_write_pnic_options(FILE *fp, bx_list_c *base)
3155 fprintf (fp, "pnic: enabled=%d", SIM->get_param_bool("enabled", base)->get());
3156 if (SIM->get_param_bool("enabled", base)->get()) {
3157 char *ptr = SIM->get_param_string("macaddr", base)->getptr();
3158 fprintf (fp, ", mac=%02x:%02x:%02x:%02x:%02x:%02x, ethmod=%s, ethdev=%s, script=%s",
3159 (unsigned int)(0xff & ptr[0]),
3160 (unsigned int)(0xff & ptr[1]),
3161 (unsigned int)(0xff & ptr[2]),
3162 (unsigned int)(0xff & ptr[3]),
3163 (unsigned int)(0xff & ptr[4]),
3164 (unsigned int)(0xff & ptr[5]),
3165 SIM->get_param_enum("ethmod", base)->get_selected(),
3166 SIM->get_param_string("ethdev", base)->getptr(),
3167 SIM->get_param_string("script", base)->getptr());
3169 fprintf (fp, "\n");
3170 return 0;
3173 int bx_write_ne2k_options (FILE *fp, bx_list_c *base)
3175 fprintf(fp, "ne2k: enabled=%d", SIM->get_param_bool("enabled", base)->get());
3176 if (SIM->get_param_bool("enabled", base)->get()) {
3177 char *ptr = SIM->get_param_string("macaddr", base)->getptr();
3178 fprintf(fp, ", ioaddr=0x%x, irq=%d, mac=%02x:%02x:%02x:%02x:%02x:%02x, ethmod=%s, ethdev=%s, script=%s",
3179 SIM->get_param_num("ioaddr", base)->get(),
3180 SIM->get_param_num("irq", base)->get(),
3181 (unsigned int)(0xff & ptr[0]),
3182 (unsigned int)(0xff & ptr[1]),
3183 (unsigned int)(0xff & ptr[2]),
3184 (unsigned int)(0xff & ptr[3]),
3185 (unsigned int)(0xff & ptr[4]),
3186 (unsigned int)(0xff & ptr[5]),
3187 SIM->get_param_enum("ethmod", base)->get_selected(),
3188 SIM->get_param_string("ethdev", base)->getptr(),
3189 SIM->get_param_string("script", base)->getptr());
3191 fprintf(fp, "\n");
3192 return 0;
3195 int bx_write_sb16_options (FILE *fp, bx_list_c *base)
3197 fprintf(fp, "sb16: enabled=%d", SIM->get_param_bool("enabled", base)->get());
3198 if (SIM->get_param_bool("enabled", base)->get()) {
3199 fprintf(fp, ", midimode=%d, midi=%s, wavemode=%d, wave=%s, loglevel=%d, log=%s, dmatimer=%d",
3200 SIM->get_param_num("midimode", base)->get(),
3201 SIM->get_param_string("midifile", base)->getptr(),
3202 SIM->get_param_num("wavemode", base)->get(),
3203 SIM->get_param_string("wavefile", base)->getptr(),
3204 SIM->get_param_num("loglevel", base)->get(),
3205 SIM->get_param_string("logfile", base)->getptr(),
3206 SIM->get_param_num("dmatimer", base)->get());
3208 fprintf(fp, "\n");
3209 return 0;
3212 int bx_write_loader_options(FILE *fp)
3214 if (SIM->get_param_enum(BXPN_LOAD32BITOS_WHICH)->get() == Load32bitOSNone) {
3215 fprintf(fp, "# no loader\n");
3216 return 0;
3218 BX_ASSERT((SIM->get_param_enum(BXPN_LOAD32BITOS_WHICH)->get() == Load32bitOSLinux) ||
3219 (SIM->get_param_enum(BXPN_LOAD32BITOS_WHICH)->get() == Load32bitOSNullKernel));
3220 fprintf (fp, "load32bitOSImage: os=%s, path=%s, iolog=%s, initrd=%s\n",
3221 (SIM->get_param_enum(BXPN_LOAD32BITOS_WHICH)->get() == Load32bitOSLinux) ? "linux" : "nullkernel",
3222 SIM->get_param_string(BXPN_LOAD32BITOS_PATH)->getptr(),
3223 SIM->get_param_string(BXPN_LOAD32BITOS_IOLOG)->getptr(),
3224 SIM->get_param_string(BXPN_LOAD32BITOS_INITRD)->getptr());
3225 return 0;
3228 int bx_write_clock_cmos_options(FILE *fp)
3230 fprintf(fp, "clock: ");
3232 switch (SIM->get_param_enum(BXPN_CLOCK_SYNC)->get()) {
3233 case BX_CLOCK_SYNC_NONE:
3234 fprintf(fp, "sync=none");
3235 break;
3236 case BX_CLOCK_SYNC_REALTIME:
3237 fprintf(fp, "sync=realtime");
3238 break;
3239 case BX_CLOCK_SYNC_SLOWDOWN:
3240 fprintf(fp, "sync=slowdown");
3241 break;
3242 case BX_CLOCK_SYNC_BOTH:
3243 fprintf(fp, "sync=both");
3244 break;
3245 default:
3246 BX_PANIC(("Unknown value for sync method"));
3249 switch (SIM->get_param_num(BXPN_CLOCK_TIME0)->get()) {
3250 case 0: break;
3251 case BX_CLOCK_TIME0_LOCAL:
3252 fprintf(fp, ", time0=local");
3253 break;
3254 case BX_CLOCK_TIME0_UTC:
3255 fprintf(fp, ", time0=utc");
3256 break;
3257 default:
3258 fprintf(fp, ", time0=%u", SIM->get_param_num(BXPN_CLOCK_TIME0)->get());
3261 fprintf(fp, "\n");
3263 if (strlen(SIM->get_param_string(BXPN_CMOSIMAGE_PATH)->getptr()) > 0) {
3264 fprintf(fp, "cmosimage: file=%s, ", SIM->get_param_string(BXPN_CMOSIMAGE_PATH)->getptr());
3265 fprintf(fp, "rtc_init=%s", SIM->get_param_bool(BXPN_CMOSIMAGE_RTC_INIT)->get()?"image":"time0");
3266 } else {
3267 fprintf(fp, "# no cmosimage\n");
3269 return 0;
3272 int bx_write_log_options(FILE *fp, bx_list_c *base)
3274 fprintf(fp, "log: %s\n", SIM->get_param_string("filename", base)->getptr());
3275 fprintf(fp, "logprefix: %s\n", SIM->get_param_string("prefix", base)->getptr());
3276 fprintf(fp, "debugger_log: %s\n", SIM->get_param_string("debugger_filename", base)->getptr());
3277 fprintf(fp, "panic: action=%s\n",
3278 io->getaction(logfunctions::get_default_action (LOGLEV_PANIC)));
3279 fprintf(fp, "error: action=%s\n",
3280 io->getaction(logfunctions::get_default_action (LOGLEV_ERROR)));
3281 fprintf(fp, "info: action=%s\n",
3282 io->getaction(logfunctions::get_default_action (LOGLEV_INFO)));
3283 fprintf(fp, "debug: action=%s\n",
3284 io->getaction(logfunctions::get_default_action (LOGLEV_DEBUG)));
3285 fprintf(fp, "pass: action=%s\n",
3286 io->getaction(logfunctions::get_default_action (LOGLEV_PASS)));
3287 return 0;
3290 int bx_write_keyboard_options(FILE *fp)
3292 fprintf(fp, "keyboard_type: %s\n", SIM->get_param_enum(BXPN_KBD_TYPE)->get_selected());
3293 fprintf(fp, "keyboard_serial_delay: %u\n", SIM->get_param_num(BXPN_KBD_SERIAL_DELAY)->get());
3294 fprintf(fp, "keyboard_paste_delay: %u\n", SIM->get_param_num(BXPN_KBD_PASTE_DELAY)->get());
3295 fprintf(fp, "keyboard_mapping: enabled=%d, map=%s\n",
3296 SIM->get_param_bool(BXPN_KBD_USEMAPPING)->get(),
3297 SIM->get_param_string(BXPN_KBD_KEYMAP)->getptr());
3298 fprintf(fp, "user_shortcut: keys=%s\n", SIM->get_param_string(BXPN_USER_SHORTCUT)->getptr());
3299 return 0;
3302 // return values:
3303 // 0: written ok
3304 // -1: failed
3305 // -2: already exists, and overwrite was off
3306 int bx_write_configuration(const char *rc, int overwrite)
3308 int i;
3309 char *strptr, tmppath[80], tmpaddr[80], tmpdev[80];
3310 bx_list_c *base;
3311 BX_INFO(("write current configuration to %s", rc));
3312 // check if it exists. If so, only proceed if overwrite is set.
3313 FILE *fp = fopen(rc, "r");
3314 if (fp != NULL) {
3315 fclose(fp);
3316 if (!overwrite) return -2;
3318 fp = fopen(rc, "w");
3319 if (fp == NULL) return -1;
3320 // finally it's open and we can start writing.
3321 fprintf(fp, "# configuration file generated by Bochs\n");
3322 fprintf(fp, "config_interface: %s\n", SIM->get_param_enum(BXPN_SEL_CONFIG_INTERFACE)->get_selected());
3323 fprintf(fp, "display_library: %s", SIM->get_param_enum(BXPN_SEL_DISPLAY_LIBRARY)->get_selected());
3324 strptr = SIM->get_param_string(BXPN_DISPLAYLIB_OPTIONS)->getptr();
3325 if (strlen(strptr) > 0)
3326 fprintf(fp, ", options=\"%s\"\n", strptr);
3327 else
3328 fprintf(fp, "\n");
3329 fprintf(fp, "megs: %d\n", SIM->get_param_num(BXPN_MEM_SIZE)->get());
3330 strptr = SIM->get_param_string(BXPN_ROM_PATH)->getptr();
3331 if (strlen(strptr) > 0) {
3332 fprintf(fp, "romimage: file=\"%s\"", strptr);
3333 if (SIM->get_param_num(BXPN_ROM_ADDRESS)->get() != 0)
3334 fprintf(fp, ", address=0x%08x\n", (unsigned int) SIM->get_param_num(BXPN_ROM_ADDRESS)->get());
3335 else
3336 fprintf(fp, "\n");
3338 else {
3339 fprintf(fp, "# no romimage\n");
3341 strptr = SIM->get_param_string(BXPN_VGA_ROM_PATH)->getptr();
3342 if (strlen(strptr) > 0)
3343 fprintf(fp, "vgaromimage: file=\"%s\"\n", strptr);
3344 else
3345 fprintf(fp, "# no vgaromimage\n");
3346 fprintf(fp, "boot: %s", SIM->get_param_enum(BXPN_BOOTDRIVE1)->get_selected());
3347 for (i=1; i<3; i++) {
3348 sprintf(tmppath, "boot_params.boot_drive%d", i+1);
3349 if (SIM->get_param_enum(tmppath)->get() != BX_BOOT_NONE) {
3350 fprintf(fp, ", %s", SIM->get_param_enum(tmppath)->get_selected());
3353 fprintf(fp, "\n");
3354 fprintf(fp, "floppy_bootsig_check: disabled=%d\n", SIM->get_param_bool(BXPN_FLOPPYSIGCHECK)->get());
3355 // it would be nice to put this type of function as methods on
3356 // the structs like bx_floppy_options::print or something.
3357 bx_write_floppy_options(fp, 0);
3358 bx_write_floppy_options(fp, 1);
3359 for (Bit8u channel=0; channel<BX_MAX_ATA_CHANNEL; channel++) {
3360 sprintf(tmppath, "ata.%d", channel);
3361 base = (bx_list_c*) SIM->get_param(tmppath);
3362 bx_write_ata_options(fp, channel, (bx_list_c*) SIM->get_param("resources", base));
3363 bx_write_atadevice_options(fp, channel, 0, (bx_list_c*) SIM->get_param("master", base));
3364 bx_write_atadevice_options(fp, channel, 1, (bx_list_c*) SIM->get_param("slave", base));
3366 for (i=0; i<BX_N_OPTROM_IMAGES; i++) {
3367 sprintf(tmppath, "memory.optrom.%d.path", i+1);
3368 sprintf(tmpaddr, "memory.optrom.%d.addr", i+1);
3369 strptr = SIM->get_param_string(tmppath)->getptr();
3370 if (strlen(strptr) > 0)
3371 fprintf(fp, "optromimage%d: file=\"%s\", address=0x%05x\n", i+1, strptr,
3372 (unsigned int)SIM->get_param_num(tmpaddr)->get());
3374 for (i=0; i<BX_N_OPTRAM_IMAGES; i++) {
3375 sprintf(tmppath, "memory.optram.%d.path", i+1);
3376 sprintf(tmpaddr, "memory.optram.%d.addr", i+1);
3377 strptr = SIM->get_param_string(tmppath)->getptr();
3378 if (strlen(strptr) > 0)
3379 fprintf(fp, "optramimage%d: file=\"%s\", address=0x%05x\n", i+1, strptr,
3380 (unsigned int)SIM->get_param_num(tmpaddr)->get());
3382 // parallel ports
3383 for (i=0; i<BX_N_PARALLEL_PORTS; i++) {
3384 sprintf(tmpdev, "ports.parallel.%d", i+1);
3385 base = (bx_list_c*) SIM->get_param(tmpdev);
3386 bx_write_parport_options(fp, base, i+1);
3388 // serial ports
3389 for (i=0; i<BX_N_SERIAL_PORTS; i++) {
3390 sprintf(tmpdev, "ports.serial.%d", i+1);
3391 base = (bx_list_c*) SIM->get_param(tmpdev);
3392 bx_write_serial_options(fp, base, i+1);
3394 base = (bx_list_c*) SIM->get_param("ports.usb.1");
3395 bx_write_usb_options(fp, base, 1);
3396 // pci
3397 fprintf(fp, "i440fxsupport: enabled=%d",
3398 SIM->get_param_bool(BXPN_I440FX_SUPPORT)->get());
3399 if (SIM->get_param_bool(BXPN_I440FX_SUPPORT)->get()) {
3400 for (i=0; i<BX_N_PCI_SLOTS; i++) {
3401 sprintf(tmpdev, "pci.slot.%d", i+1);
3402 strptr = SIM->get_param_string(tmpdev)->getptr();
3403 if (strlen(strptr) > 0) {
3404 fprintf(fp, ", slot%d=%s", i+1, strptr);
3408 fprintf(fp, "\n");
3409 if (SIM->get_param_num(BXPN_PCIDEV_VENDOR)->get() != 0xffff) {
3410 fprintf(fp, "pcidev: vendor=0x%04x, device=0x%04x\n",
3411 SIM->get_param_num(BXPN_PCIDEV_VENDOR)->get(),
3412 SIM->get_param_num(BXPN_PCIDEV_DEVICE)->get());
3414 fprintf(fp, "vga_update_interval: %u\n", SIM->get_param_num(BXPN_VGA_UPDATE_INTERVAL)->get());
3415 fprintf(fp, "vga: extension=%s\n", SIM->get_param_string(BXPN_VGA_EXTENSION)->getptr());
3416 #if BX_SUPPORT_SMP
3417 fprintf(fp, "cpu: count=%u:%u:%u, ips=%u, quantum=%d, reset_on_triple_fault=%d\n",
3418 SIM->get_param_num(BXPN_CPU_NPROCESSORS)->get(), SIM->get_param_num(BXPN_CPU_NCORES)->get(),
3419 SIM->get_param_num(BXPN_CPU_NTHREADS)->get(), SIM->get_param_num(BXPN_IPS)->get(),
3420 SIM->get_param_num(BXPN_SMP_QUANTUM)->get(),
3421 SIM->get_param_bool(BXPN_RESET_ON_TRIPLE_FAULT)->get());
3422 #else
3423 fprintf(fp, "cpu: count=1, ips=%u, reset_on_triple_fault=%d\n",
3424 SIM->get_param_num(BXPN_IPS)->get(), SIM->get_param_bool(BXPN_RESET_ON_TRIPLE_FAULT)->get());
3425 #endif
3426 fprintf(fp, "text_snapshot_check: enabled=%d\n", SIM->get_param_bool(BXPN_TEXT_SNAPSHOT_CHECK)->get());
3427 fprintf(fp, "private_colormap: enabled=%d\n", SIM->get_param_bool(BXPN_PRIVATE_COLORMAP)->get());
3428 #if BX_WITH_AMIGAOS
3429 fprintf(fp, "fullscreen: enabled=%d\n", SIM->get_param_bool(BXPN_FULLSCREEN)->get());
3430 fprintf(fp, "screenmode: name=\"%s\"\n", SIM->get_param_string(BXPN_SCREENMODE)->getptr());
3431 #endif
3432 bx_write_clock_cmos_options(fp);
3433 bx_write_ne2k_options(fp, (bx_list_c*) SIM->get_param(BXPN_NE2K));
3434 bx_write_pnic_options(fp, (bx_list_c*) SIM->get_param(BXPN_PNIC));
3435 bx_write_sb16_options(fp, (bx_list_c*) SIM->get_param(BXPN_SB16));
3436 bx_write_loader_options(fp);
3437 bx_write_log_options(fp, (bx_list_c*) SIM->get_param("log"));
3438 bx_write_keyboard_options(fp);
3439 fprintf(fp, "mouse: enabled=%d, type=%s\n",
3440 SIM->get_param_bool(BXPN_MOUSE_ENABLED)->get(),
3441 SIM->get_param_enum(BXPN_MOUSE_TYPE)->get_selected());
3442 SIM->save_user_options(fp);
3443 fclose(fp);
3444 return 0;
3447 #endif // #if BX_PROVIDE_MAIN