- skip SMM init if already done at first boot time (fixes reboot failure)
[bochs-mirror.git] / config.cc
blobdda2575c9a360150fec29a51cd6198129e4348d0
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: config.cc,v 1.125 2007/12/06 22:21:40 sshwarts 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 const char *get_builtin_variable(const 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 const 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 new bx_param_bool_c(menu,
365 "restore",
366 "Restore Bochs session",
367 "Restore Bochs session",
369 new bx_param_string_c(menu,
370 "restore_path",
371 "Path to data for restore",
372 "Path to data for restore",
374 BX_PATHNAME_LEN);
376 // benchmarking mode, set by command line arg
377 new bx_param_num_c(menu,
378 "benchmark",
379 "benchmark mode",
380 "set benchmark mode",
381 0, BX_MAX_BIT32U, 0);
383 // subtree for special menus
384 bx_list_c *special_menus = new bx_list_c(root_param, "menu", "");
386 #if BX_SUPPORT_SMP
387 #define BX_CPU_PROCESSORS_LIMIT 8
388 #define BX_CPU_CORES_LIMIT 4
389 #define BX_CPU_HT_THREADS_LIMIT 4
390 #else
391 #define BX_CPU_PROCESSORS_LIMIT 1
392 #define BX_CPU_CORES_LIMIT 1
393 #define BX_CPU_HT_THREADS_LIMIT 1
394 #endif
396 // cpu subtree
397 bx_list_c *cpu_param = new bx_list_c(root_param, "cpu", "CPU Options");
399 // cpu options
400 bx_param_num_c *nprocessors = new bx_param_num_c(cpu_param,
401 "n_processors", "Number of CPUs in SMP mode",
402 "Sets the number of CPUs for multiprocessor emulation",
403 1, BX_CPU_PROCESSORS_LIMIT,
405 nprocessors->set_enabled(BX_CPU_PROCESSORS_LIMIT > 1);
406 bx_param_num_c *ncores = new bx_param_num_c(cpu_param,
407 "n_cores", "Number of processor cores in each CPU in SMP mode",
408 "Sets the number of processor cores per CPU for multiprocessor emulation",
409 1, BX_CPU_CORES_LIMIT,
411 ncores->set_enabled(BX_CPU_CORES_LIMIT > 1);
412 bx_param_num_c *nthreads = new bx_param_num_c(cpu_param,
413 "n_threads", "Number of HT threads per each process core in SMP mode",
414 "Sets the number of HT (Intel(R) HyperThreading Technology) threads per core for multiprocessor emulation",
415 1, BX_CPU_HT_THREADS_LIMIT,
417 nthreads->set_enabled(BX_CPU_HT_THREADS_LIMIT > 1);
418 new bx_param_num_c(cpu_param,
419 "ips", "Emulated instructions per second (IPS)",
420 "Emulated instructions per second, used to calibrate bochs emulated time with wall clock time.",
421 1, BX_MAX_BIT32U,
422 2000000);
423 #if BX_SUPPORT_SMP
424 new bx_param_num_c(cpu_param,
425 "quantum", "Quantum ticks in SMP simulation",
426 "Maximum amount of instructions allowed to execute before returning control to another CPU.",
427 BX_SMP_QUANTUM_MIN, BX_SMP_QUANTUM_MAX,
429 #endif
430 new bx_param_bool_c(cpu_param,
431 "reset_on_triple_fault", "Enable CPU reset on triple fault",
432 "Enable CPU reset if triple fault occured (highly recommended)",
434 cpu_param->get_options()->set(menu->SHOW_PARENT);
436 // memory subtree
437 bx_list_c *memory = new bx_list_c(root_param, "memory", "Memory Options");
438 bx_list_c *stdmem = new bx_list_c(memory, "standard", "Standard Options");
439 bx_list_c *optrom = new bx_list_c(memory, "optrom", "Optional ROM Images");
440 bx_list_c *optram = new bx_list_c(memory, "optram", "Optional RAM Images");
441 bx_list_c *ram = new bx_list_c(stdmem, "ram", "");
442 bx_list_c *rom = new bx_list_c(stdmem, "rom", "");
443 bx_list_c *vgarom = new bx_list_c(stdmem, "vgarom", "");
445 // memory options (ram & rom)
446 bx_param_num_c *ramsize = new bx_param_num_c(ram,
447 "size",
448 "Memory size (megabytes)",
449 "Amount of RAM in megabytes",
450 1, 2048,
451 BX_DEFAULT_MEM_MEGS);
452 ramsize->set_ask_format("Enter memory size (MB): [%d] ");
453 #if BX_WITH_WX
454 ramsize->set_options(bx_param_num_c::USE_SPIN_CONTROL);
455 #endif
457 path = new bx_param_filename_c(rom,
458 "path",
459 "ROM BIOS image",
460 "Pathname of ROM image to load",
461 "", BX_PATHNAME_LEN);
462 path->set_format("Name of ROM BIOS image: %s");
463 sprintf(name, "%s/BIOS-bochs-latest", (char *)get_builtin_variable("BXSHARE"));
464 path->set_initial_val(name);
465 bx_param_num_c *romaddr = new bx_param_num_c(rom,
466 "addr",
467 "ROM BIOS address",
468 "The address at which the ROM image should be loaded",
469 0, BX_MAX_BIT32U,
471 romaddr->set_base(16);
472 romaddr->set_format("0x%05x");
473 romaddr->set_long_format("ROM BIOS address: 0x%05x");
475 path = new bx_param_filename_c(vgarom,
476 "path",
477 "VGA BIOS image",
478 "Pathname of VGA ROM image to load",
479 "", BX_PATHNAME_LEN);
480 path->set_format("Name of VGA BIOS image: %s");
481 sprintf(name, "%s/VGABIOS-lgpl-latest", get_builtin_variable("BXSHARE"));
482 path->set_initial_val(name);
484 bx_param_num_c *optaddr;
486 for (i=0; i<BX_N_OPTROM_IMAGES; i++) {
487 sprintf(name, "%d", i+1);
488 sprintf(descr, "Pathname of optional ROM image #%d to load", i+1);
489 sprintf(label, "Optional ROM image #%d", i+1);
490 bx_list_c *optnum1 = new bx_list_c(optrom, name, label);
491 path = new bx_param_filename_c(optnum1,
492 "path",
493 "Path",
494 descr,
495 "", BX_PATHNAME_LEN);
496 sprintf(label, "Name of optional ROM image #%d", i+1);
497 strcat(label, " : %s");
498 path->set_format(strdup(label));
499 sprintf(descr, "The address at which the optional ROM image #%d should be loaded", i+1);
500 optaddr = new bx_param_num_c(optnum1,
501 "addr",
502 "Address",
503 descr,
504 0, BX_MAX_BIT32U,
506 optaddr->set_base(16);
507 optaddr->set_format("0x%05x");
508 sprintf(label, "Optional ROM #%d address:", i+1);
509 strcat(label, " 0x%05x");
510 optaddr->set_long_format(strdup(label));
511 optnum1->get_options()->set(bx_list_c::SHOW_PARENT | bx_list_c::USE_BOX_TITLE);
513 optrom->get_options()->set(bx_list_c::SHOW_PARENT);
515 for (i=0; i<BX_N_OPTRAM_IMAGES; i++) {
516 sprintf(name, "%d", i+1);
517 sprintf(descr, "Pathname of optional RAM image #%d to load", i+1);
518 sprintf(label, "Optional RAM image #%d", i+1);
519 bx_list_c *optnum2 = new bx_list_c(optram, name, label);
520 path = new bx_param_filename_c(optnum2,
521 "path",
522 "Path",
523 descr,
524 "", BX_PATHNAME_LEN);
525 sprintf(label, "Name of optional RAM image #%d", i+1);
526 strcat(label, " : %s");
527 path->set_format(strdup(label));
528 sprintf(descr, "The address at which the optional RAM image #%d should be loaded", i+1);
529 optaddr = new bx_param_num_c(optnum2,
530 "addr",
531 "Address",
532 descr,
533 0, BX_MAX_BIT32U,
535 optaddr->set_base(16);
536 optaddr->set_format("0x%05x");
537 sprintf(label, "Optional RAM #%d address:", i+1);
538 strcat(label, " 0x%05x");
539 optaddr->set_long_format(strdup(label));
540 optnum2->get_options()->set(bx_list_c::SHOW_PARENT | bx_list_c::USE_BOX_TITLE);
542 optrom->get_options()->set(bx_list_c::SHOW_PARENT);
543 memory->get_options()->set(bx_list_c::USE_TAB_WINDOW);
545 bx_param_c *memory_init_list[] = {
546 SIM->get_param(BXPN_MEM_SIZE),
547 SIM->get_param(BXPN_ROM_PATH),
548 SIM->get_param(BXPN_ROM_ADDRESS),
549 SIM->get_param(BXPN_VGA_ROM_PATH),
550 SIM->get_param("memory.optrom"),
551 SIM->get_param("memory.optram"),
552 NULL
554 menu = new bx_list_c(special_menus, "memory", "Bochs Memory Options", memory_init_list);
555 menu->get_options()->set(bx_list_c::SHOW_PARENT);
557 // clock & cmos subtree
558 bx_list_c *clock_cmos = new bx_list_c(root_param, "clock_cmos", "Clock & CMOS Options");
560 // clock & cmos options
561 bx_param_enum_c *clock_sync = new bx_param_enum_c(clock_cmos,
562 "clock_sync", "Synchronisation method",
563 "Host to guest time synchronization method",
564 clock_sync_names,
565 BX_CLOCK_SYNC_NONE,
566 BX_CLOCK_SYNC_NONE);
567 bx_param_num_c *time0 = new bx_param_num_c(clock_cmos,
568 "time0",
569 "Initial CMOS time for Bochs\n(1:localtime, 2:utc, other:time in seconds)",
570 "Initial time for Bochs CMOS clock, used if you really want two runs to be identical",
571 0, BX_MAX_BIT32U,
572 BX_CLOCK_TIME0_LOCAL);
574 bx_list_c *cmosimage = new bx_list_c(clock_cmos, "cmosimage", "CMOS Image Options");
575 bx_param_bool_c *use_cmosimage = new bx_param_bool_c(cmosimage,
576 "enabled", "Use a CMOS image",
577 "Controls the usage of a CMOS image",
579 path = new bx_param_filename_c(cmosimage,
580 "path", "Pathname of CMOS image",
581 "Pathname of CMOS image",
582 "", BX_PATHNAME_LEN);
583 bx_param_bool_c *rtc_init = new bx_param_bool_c(cmosimage,
584 "rtc_init", "Initialize RTC from image",
585 "Controls whether to initialize the RTC with values stored in the image",
587 deplist = new bx_list_c(NULL, 2);
588 deplist->add(path);
589 deplist->add(rtc_init);
590 use_cmosimage->set_dependent_list(deplist);
592 time0->set_ask_format("Enter Initial CMOS time (1:localtime, 2:utc, other:time in seconds): [%d] ");
593 clock_sync->set_ask_format("Enter Synchronisation method: [%s] ");
594 clock_cmos->get_options()->set(bx_list_c::SHOW_PARENT);
595 cmosimage->get_options()->set(bx_list_c::SHOW_PARENT);
597 // pci subtree
598 bx_list_c *pci = new bx_list_c(root_param, "pci", "PCI Options");
600 // pci options
601 bx_param_c *pci_deps_list[1+BX_N_PCI_SLOTS];
602 bx_param_c **pci_deps_ptr = &pci_deps_list[0];
604 bx_param_bool_c *i440fx_support = new bx_param_bool_c(pci,
605 "i440fx_support",
606 "Enable i440FX PCI Support",
607 "Controls whether to emulate the i440FX PCI chipset",
608 BX_SUPPORT_PCI);
609 // pci slots
610 bx_list_c *slot = new bx_list_c(pci, "slot", "PCI Slots");
611 *pci_deps_ptr++ = slot;
612 for (i=0; i<BX_N_PCI_SLOTS; i++) {
613 sprintf(name, "%d", i+1);
614 sprintf (descr, "Name of the device connected to PCI slot #%d", i+1);
615 sprintf (label, "PCI slot #%d device", i+1);
616 bx_param_string_c *devname = new bx_param_string_c(slot,
617 name,
618 label,
619 descr,
620 "", BX_PATHNAME_LEN);
621 // add to deplist
622 *pci_deps_ptr++ = devname;
624 // pcidev options
625 bx_list_c *pcidev = new bx_list_c(pci, "pcidev", "Host PCI Device Mapping");
626 *pci_deps_ptr++ = pcidev;
627 bx_param_num_c *pcivid = new bx_param_num_c(pcidev,
628 "vendor",
629 "PCI Vendor ID",
630 "The vendor ID of the host PCI device to map",
631 0, 0xffff,
632 0xffff); // vendor id 0xffff = no pci device present
633 pcivid->set_base(16);
634 pcivid->set_format("0x%04x");
635 pcivid->set_long_format("PCI Vendor ID: 0x%04x");
636 #if BX_SUPPORT_PCIDEV
637 *pci_deps_ptr++ = pcivid;
638 #else
639 pcivid->set_enabled(0);
640 #endif
641 bx_param_num_c *pcidid = new bx_param_num_c(pcidev,
642 "device",
643 "PCI Device ID",
644 "The device ID of the host PCI device to map",
645 0, 0xffff,
646 0x0);
647 pcidid->set_base(16);
648 pcidid->set_format("0x%04x");
649 pcidid->set_long_format("PCI Device ID: 0x%04x");
650 #if BX_SUPPORT_PCIDEV
651 *pci_deps_ptr++ = pcidid;
652 #else
653 pcidid->set_enabled(0);
654 #endif
655 // add final NULL at the end, and build the menu
656 *pci_deps_ptr = NULL;
657 i440fx_support->set_dependent_list(new bx_list_c(NULL, "", "", pci_deps_list));
658 pci->get_options()->set(bx_list_c::SHOW_PARENT);
659 slot->get_options()->set(bx_list_c::SHOW_PARENT);
660 pcidev->get_options()->set(bx_list_c::SHOW_PARENT | bx_list_c::USE_BOX_TITLE);
662 // display subtree
663 bx_list_c *display = new bx_list_c(root_param, "display", "Bochs Display & Interface Options", 7);
665 // this is a list of gui libraries that are known to be available at
666 // compile time. The one that is listed first will be the default,
667 // which is used unless the user overrides it on the command line or
668 // in a configuration file.
669 static const char *display_library_list[] = {
670 #if BX_WITH_X11
671 "x",
672 #endif
673 #if BX_WITH_WIN32
674 "win32",
675 #endif
676 #if BX_WITH_CARBON
677 "carbon",
678 #endif
679 #if BX_WITH_BEOS
680 "beos",
681 #endif
682 #if BX_WITH_MACOS
683 "macos",
684 #endif
685 #if BX_WITH_AMIGAOS
686 "amigaos",
687 #endif
688 #if BX_WITH_SDL
689 "sdl",
690 #endif
691 #if BX_WITH_SVGA
692 "svga",
693 #endif
694 #if BX_WITH_TERM
695 "term",
696 #endif
697 #if BX_WITH_RFB
698 "rfb",
699 #endif
700 #if BX_WITH_WX
701 "wx",
702 #endif
703 #if BX_WITH_NOGUI
704 "nogui",
705 #endif
706 NULL
708 bx_param_enum_c *sel_displaylib = new bx_param_enum_c(display,
709 "display_library", "VGA Display Library",
710 "Select VGA Display Library",
711 display_library_list,
714 sel_displaylib->set_by_name(BX_DEFAULT_DISPLAY_LIBRARY);
715 sel_displaylib->set_ask_format("Choose which library to use for the Bochs display: [%s] ");
717 new bx_param_string_c(display,
718 "displaylib_options", "Display Library options",
719 "Options passed to Display Library",
721 BX_PATHNAME_LEN);
723 new bx_param_bool_c(display,
724 "private_colormap", "Use a private colormap",
725 "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.",
728 bx_param_bool_c *fullscreen = new bx_param_bool_c(display,
729 "fullscreen", "Use full screen mode",
730 "When enabled, bochs occupies the whole screen instead of just a window.",
732 bx_param_string_c *screenmode = new bx_param_string_c(display,
733 "screenmode",
734 "Screen mode name",
735 "Screen mode name",
736 "", BX_PATHNAME_LEN);
737 screenmode->set_handler(bx_param_string_handler);
738 #if !BX_WITH_AMIGAOS
739 fullscreen->set_enabled(0);
740 screenmode->set_enabled(0);
741 #endif
743 bx_param_num_c *vga_update_interval = new bx_param_num_c(display,
744 "vga_update_interval",
745 "VGA Update Interval",
746 "Number of microseconds between VGA updates",
747 1, BX_MAX_BIT32U,
748 40000);
749 vga_update_interval->set_ask_format ("Type a new value for VGA update interval: [%d] ");
751 bx_param_string_c *vga_extension = new bx_param_string_c(display,
752 "vga_extension",
753 "VGA Extension",
754 "Name of the VGA extension",
755 "none", BX_PATHNAME_LEN);
756 #if BX_SUPPORT_VBE
757 vga_extension->set_initial_val("vbe");
758 #elif BX_SUPPORT_CLGD54XX
759 vga_extension->set_initial_val("cirrus");
760 #endif
761 display->get_options()->set(bx_list_c::SHOW_PARENT);
763 // keyboard & mouse subtree
764 bx_list_c *kbd_mouse = new bx_list_c(root_param, "keyboard_mouse", "Keyboard & Mouse Options");
765 bx_list_c *keyboard = new bx_list_c(kbd_mouse, "keyboard", "Keyboard Options");
766 bx_list_c *mouse = new bx_list_c(kbd_mouse, "mouse", "Mouse Options");
768 // keyboard & mouse options
769 type = new bx_param_enum_c(keyboard,
770 "type", "Keyboard type",
771 "Keyboard type reported by the 'identify keyboard' command",
772 keyboard_type_names,
773 BX_KBD_MF_TYPE,
774 BX_KBD_XT_TYPE);
775 type->set_ask_format ("Enter keyboard type: [%s] ");
777 new bx_param_num_c(keyboard,
778 "serial_delay", "Keyboard serial delay",
779 "Approximate time in microseconds that it takes one character to be transfered from the keyboard to controller over the serial path.",
780 1, BX_MAX_BIT32U,
781 250);
782 new bx_param_num_c(keyboard,
783 "paste_delay", "Keyboard paste delay",
784 "Approximate time in microseconds between attemps to paste characters to the keyboard controller.",
785 1000, BX_MAX_BIT32U,
786 100000);
787 bx_param_bool_c *use_kbd_mapping = new bx_param_bool_c(keyboard,
788 "use_mapping", "Use keyboard mapping",
789 "Controls whether to use the keyboard mapping feature",
791 bx_param_filename_c *keymap = new bx_param_filename_c(keyboard,
792 "keymap", "Keymap filename",
793 "Pathname of the keymap file used",
794 "", BX_PATHNAME_LEN);
795 deplist = new bx_list_c(NULL, 1);
796 deplist->add(keymap);
797 use_kbd_mapping->set_dependent_list(deplist);
799 bx_param_string_c *user_shortcut = new bx_param_string_c(keyboard,
800 "user_shortcut",
801 "Userbutton shortcut",
802 "Defines the keyboard shortcut to be sent when you press the 'user' button in the headerbar.",
803 "none", 20);
804 user_shortcut->set_runtime_param(1);
806 static const char *mouse_type_list[] = {
807 "none",
808 "ps2",
809 "imps2",
810 #if BX_SUPPORT_BUSMOUSE
811 "bus",
812 #endif
813 "serial",
814 "serial_wheel",
815 "serial_msys",
816 NULL
818 type = new bx_param_enum_c(mouse,
819 "type", "Mouse type",
820 "The mouse type can be one of these: 'none', 'ps2', 'imps2', 'serial', 'serial_wheel'"
821 #if BX_SUPPORT_BUSMOUSE
822 ", 'bus'"
823 #endif
825 mouse_type_list,
826 BX_MOUSE_TYPE_PS2,
827 BX_MOUSE_TYPE_NONE);
828 type->set_ask_format("Choose the type of mouse [%s] ");
830 new bx_param_bool_c(mouse,
831 "enabled", "Enable the mouse capture",
832 "Controls whether the mouse sends events to the guest. The hardware emulation is always enabled.",
834 kbd_mouse->get_options()->set(bx_list_c::SHOW_PARENT);
835 keyboard->get_options()->set(bx_list_c::SHOW_PARENT);
836 mouse->get_options()->set(bx_list_c::SHOW_PARENT);
838 // boot parameter subtree
839 bx_list_c *boot_params = new bx_list_c(root_param, "boot_params", "Boot Options");
840 // boot sequence
841 for (i=0; i<3; i++) {
842 sprintf(name, "boot_drive%d", i+1);
843 sprintf(label, "Boot drive #%d", i+1);
844 sprintf(descr, "Name of drive #%d in boot sequence (A, C or CD)", i+1);
845 bx_param_enum_c *bootdrive = new bx_param_enum_c(boot_params,
846 name,
847 label,
848 descr,
849 &bochs_bootdisk_names[(i==0)?BX_BOOT_FLOPPYA:BX_BOOT_NONE],
850 (i==0)?BX_BOOT_FLOPPYA:BX_BOOT_NONE,
851 (i==0)?BX_BOOT_FLOPPYA:BX_BOOT_NONE);
852 bootdrive->set_ask_format("Boot from floppy drive, hard drive or cdrom ? [%s] ");
855 new bx_param_bool_c(boot_params,
856 "floppy_sig_check",
857 "Skip Floppy Boot Signature Check",
858 "Skips check for the 0xaa55 signature on floppy boot device.",
861 // loader hack
862 bx_list_c *load32bitos = new bx_list_c(boot_params, "load32bitos", "32-bit OS Loader Hack");
863 bx_param_enum_c *whichOS = new bx_param_enum_c(load32bitos,
864 "which",
865 "Which operating system?",
866 "Which OS to boot",
867 loader_os_names,
868 Load32bitOSNone,
869 Load32bitOSNone);
870 path = new bx_param_filename_c(load32bitos,
871 "path",
872 "Pathname of OS to load",
873 "Pathname of the 32-bit OS to load",
874 "", BX_PATHNAME_LEN);
875 bx_param_filename_c *iolog = new bx_param_filename_c(load32bitos,
876 "iolog",
877 "Pathname of I/O log file",
878 "I/O logfile used for initializing the hardware",
879 "", BX_PATHNAME_LEN);
880 bx_param_filename_c *initrd = new bx_param_filename_c(load32bitos,
881 "initrd",
882 "Pathname of initrd",
883 "Pathname of the initial ramdisk",
884 "", BX_PATHNAME_LEN);
885 whichOS->set_ask_format("Enter OS to load: [%s] ");
886 path->set_ask_format("Enter pathname of OS: [%s]");
887 iolog->set_ask_format("Enter pathname of I/O log: [%s] ");
888 initrd->set_ask_format("Enter pathname of initrd: [%s] ");
889 load32bitos->get_options()->set(menu->SERIES_ASK);
890 whichOS->set_handler(bx_param_handler);
891 whichOS->set(Load32bitOSNone);
892 boot_params->get_options()->set(bx_list_c::SHOW_PARENT);
894 // floppy subtree
895 bx_list_c *floppy = new bx_list_c(root_param, "floppy", "Floppy Options");
896 bx_list_c *floppya = new bx_list_c(floppy, "0", "Floppy Disk 0");
897 bx_list_c *floppyb = new bx_list_c(floppy, "1", "Floppy Disk 1");
899 bx_param_enum_c *devtype;
900 // floppy options
901 path = new bx_param_filename_c(floppya,
902 "path",
903 "First floppy image/device",
904 "Pathname of first floppy image file or device. If you're booting from floppy, this should be a bootable floppy.",
905 "", BX_PATHNAME_LEN);
906 path->set_ask_format("Enter new filename, or 'none' for no disk: [%s] ");
907 path->set_runtime_param(1);
909 devtype = new bx_param_enum_c(floppya,
910 "devtype",
911 "Type of floppy drive",
912 "Type of floppy drive",
913 floppy_type_names,
914 BX_FLOPPY_NONE,
915 BX_FLOPPY_NONE);
916 devtype->set_enabled(0); // hide devtype parameter
917 type = new bx_param_enum_c(floppya,
918 "type",
919 "Type of floppy disk",
920 "Type of floppy disk",
921 floppy_type_names,
922 BX_FLOPPY_NONE,
923 BX_FLOPPY_NONE);
924 type->set_ask_format("What type of floppy disk? (auto=detect) [%s] ");
925 type->set_runtime_param(1);
927 status = new bx_param_enum_c(floppya,
928 "status",
929 "Is floppya inserted",
930 "Inserted or ejected",
931 floppy_status_names,
932 BX_INSERTED,
933 BX_EJECTED);
934 status->set_ask_format("Is the floppy inserted or ejected? [%s] ");
935 status->set_runtime_param(1);
937 path->set_handler(bx_param_string_handler);
938 type->set_handler(bx_param_handler);
939 status->set_handler(bx_param_handler);
940 path->set_initial_val("none");
941 floppya->get_options()->set(bx_list_c::SERIES_ASK);
943 path = new bx_param_filename_c(floppyb,
944 "path",
945 "Second floppy image/device",
946 "Pathname of second floppy image file or device.",
947 "", BX_PATHNAME_LEN);
948 path->set_ask_format("Enter new filename, or 'none' for no disk: [%s] ");
949 path->set_runtime_param(1);
951 devtype = new bx_param_enum_c(floppyb,
952 "devtype",
953 "Type of floppy drive",
954 "Type of floppy drive",
955 floppy_type_names,
956 BX_FLOPPY_NONE,
957 BX_FLOPPY_NONE);
958 devtype->set_enabled(0); // hide devtype parameter
959 type = new bx_param_enum_c(floppyb,
960 "type",
961 "Type of floppy disk",
962 "Type of floppy disk",
963 floppy_type_names,
964 BX_FLOPPY_NONE,
965 BX_FLOPPY_NONE);
966 type->set_ask_format("What type of floppy disk? (auto=detect) [%s] ");
967 type->set_runtime_param(1);
969 status = new bx_param_enum_c(floppyb,
970 "status",
971 "Is floppyb inserted",
972 "Inserted or ejected",
973 floppy_status_names,
974 BX_INSERTED,
975 BX_EJECTED);
976 status->set_ask_format("Is the floppy inserted or ejected? [%s] ");
977 status->set_runtime_param(1);
979 path->set_handler(bx_param_string_handler);
980 type->set_handler(bx_param_handler);
981 status->set_handler(bx_param_handler);
982 path->set_initial_val("none");
983 floppyb->get_options()->set(bx_list_c::SERIES_ASK);
984 floppy->get_options()->set(bx_list_c::SHOW_PARENT);
986 // ATA/ATAPI subtree
987 bx_list_c *ata = new bx_list_c(root_param, "ata", "ATA/ATAPI Options");
989 // disk options
990 const char *s_atachannel[] = {
991 "ATA channel 0",
992 "ATA channel 1",
993 "ATA channel 2",
994 "ATA channel 3",
996 const char *s_atadevname[2] = {
997 "master",
998 "slave",
1000 const char *s_atadevice[4][2] = {
1001 { "First HD/CD on channel 0",
1002 "Second HD/CD on channel 0" },
1003 { "First HD/CD on channel 1",
1004 "Second HD/CD on channel 1" },
1005 { "First HD/CD on channel 2",
1006 "Second HD/CD on channel 2" },
1007 { "First HD/CD on channel 3",
1008 "Second HD/CD on channel 3" }
1010 Bit16u ata_default_ioaddr1[4] = {
1011 0x1f0, 0x170, 0x1e8, 0x168
1013 Bit16u ata_default_ioaddr2[4] = {
1014 0x3f0, 0x370, 0x3e0, 0x360
1016 Bit8u ata_default_irq[4] = {
1017 14, 15, 11, 9
1020 #define BXP_PARAMS_PER_ATA_DEVICE 12
1022 bx_list_c *ata_menu[BX_MAX_ATA_CHANNEL];
1023 bx_list_c *ata_res[BX_MAX_ATA_CHANNEL];
1025 Bit8u channel;
1026 for (channel=0; channel<BX_MAX_ATA_CHANNEL; channel++) {
1028 sprintf(name, "%d", channel);
1029 ata_menu[channel] = new bx_list_c(ata, name, s_atachannel[channel]);
1030 ata_menu[channel]->get_options()->set(bx_list_c::USE_TAB_WINDOW);
1031 ata_res[channel] = new bx_list_c(ata_menu[channel], "resources", s_atachannel[channel], 8);
1032 ata_res[channel]->get_options()->set(bx_list_c::SERIES_ASK);
1034 enabled = new bx_param_bool_c(ata_res[channel],
1035 "enabled",
1036 "Enable ATA channel",
1037 "Controls whether ata channel is installed or not",
1039 enabled->set_ask_format("Channel is enabled: [%s] ");
1041 ioaddr = new bx_param_num_c(ata_res[channel],
1042 "ioaddr1",
1043 "I/O Address 1",
1044 "IO adress of ata command block",
1045 0, 0xffff,
1046 ata_default_ioaddr1[channel]);
1047 ioaddr->set_base(16);
1048 ioaddr->set_ask_format("Enter new ioaddr1: [0x%x] ");
1050 ioaddr2 = new bx_param_num_c(ata_res[channel],
1051 "ioaddr2",
1052 "I/O Address 2",
1053 "IO adress of ata control block",
1054 0, 0xffff,
1055 ata_default_ioaddr2[channel]);
1056 ioaddr2->set_base(16);
1057 ioaddr2->set_ask_format("Enter new ioaddr2: [0x%x] ");
1059 irq = new bx_param_num_c(ata_res[channel],
1060 "irq",
1061 "IRQ",
1062 "IRQ used by this ata channel",
1063 0, 15,
1064 ata_default_irq[channel]);
1065 irq->set_ask_format("Enter new IRQ: [%d] ");
1066 irq->set_options(bx_param_num_c::USE_SPIN_CONTROL);
1068 // all items in the ata[channel] menu depend on the enabled flag.
1069 // The menu list is complete, but a few dependent_list items will
1070 // be added later. Use clone() to make a copy of the dependent_list
1071 // so that it can be changed without affecting the menu.
1072 enabled->set_dependent_list(ata_res[channel]->clone());
1074 for (Bit8u slave=0; slave<2; slave++) {
1075 menu = new bx_list_c(ata_menu[channel],
1076 s_atadevname[slave],
1077 s_atadevice[channel][slave],
1078 BXP_PARAMS_PER_ATA_DEVICE + 1);
1079 menu->get_options()->set(bx_list_c::SERIES_ASK);
1081 bx_param_bool_c *present = new bx_param_bool_c(menu,
1082 "present",
1083 "Enable this device",
1084 "Controls whether ata device is installed or not",
1086 present->set_ask_format("Device is enabled: [%s] ");
1088 type = new bx_param_enum_c(menu,
1089 "type",
1090 "Type of ATA device",
1091 "Type of ATA device (disk or cdrom)",
1092 atadevice_type_names,
1093 BX_ATA_DEVICE_DISK,
1094 BX_ATA_DEVICE_DISK);
1095 type->set_ask_format("Enter type of ATA device, disk or cdrom: [%s] ");
1097 path = new bx_param_filename_c(menu,
1098 "path",
1099 "Path or physical device name",
1100 "Pathname of the image or physical device (cdrom only)",
1101 "", BX_PATHNAME_LEN);
1102 path->set_ask_format("Enter new filename: [%s] ");
1104 mode = new bx_param_enum_c(menu,
1105 "mode",
1106 "Type of disk image",
1107 "Mode of the ATA harddisk",
1108 atadevice_mode_names,
1109 BX_ATA_MODE_FLAT,
1110 BX_ATA_MODE_FLAT);
1111 mode->set_ask_format("Enter mode of ATA device, (flat, concat, etc.): [%s] ");
1113 status = new bx_param_enum_c(menu,
1114 "status",
1115 "Inserted",
1116 "CD-ROM media status (inserted / ejected)",
1117 atadevice_status_names,
1118 BX_INSERTED,
1119 BX_EJECTED);
1120 status->set_ask_format("Is the device inserted or ejected? [%s] ");
1122 bx_param_filename_c *journal = new bx_param_filename_c(menu,
1123 "journal",
1124 "Path of journal file",
1125 "Pathname of the journal file",
1126 "", BX_PATHNAME_LEN);
1127 journal->set_ask_format("Enter path of journal file: [%s]");
1129 bx_param_num_c *cylinders = new bx_param_num_c(menu,
1130 "cylinders",
1131 "Cylinders",
1132 "Number of cylinders",
1133 0, 262143,
1135 cylinders->set_ask_format("Enter number of cylinders: [%d] ");
1136 bx_param_num_c *heads = new bx_param_num_c(menu,
1137 "heads",
1138 "Heads",
1139 "Number of heads",
1140 0, 255,
1142 heads->set_ask_format("Enter number of heads: [%d] ");
1143 bx_param_num_c *spt = new bx_param_num_c(menu,
1144 "spt",
1145 "Sectors per track",
1146 "Number of sectors per track",
1147 0, 255,
1149 spt->set_ask_format("Enter number of sectors per track: [%d] ");
1151 bx_param_string_c *model = new bx_param_string_c(menu,
1152 "model",
1153 "Model name",
1154 "String returned by the 'identify device' command",
1155 "Generic 1234", 40);
1156 model->set_ask_format("Enter new model name: [%s]");
1158 bx_param_enum_c *biosdetect = new bx_param_enum_c(menu,
1159 "biosdetect",
1160 "BIOS Detection",
1161 "Type of bios detection",
1162 atadevice_biosdetect_names,
1163 BX_ATA_BIOSDETECT_AUTO,
1164 BX_ATA_BIOSDETECT_NONE);
1165 biosdetect->set_ask_format("Enter bios detection type: [%s]");
1167 bx_param_enum_c *translation = new bx_param_enum_c(menu,
1168 "translation",
1169 "Translation type",
1170 "How the ata-disk translation is done by the bios",
1171 atadevice_translation_names,
1172 BX_ATA_TRANSLATION_AUTO,
1173 BX_ATA_TRANSLATION_NONE);
1174 translation->set_ask_format("Enter translation type: [%s]");
1176 // the menu and all items on it depend on the present flag
1177 present->set_dependent_list(menu->clone());
1178 // the present flag depends on the ATA channel's enabled flag
1179 enabled->get_dependent_list()->add(present);
1180 // the master/slave menu depends on the ATA channel's enabled flag
1181 enabled->get_dependent_list()->add(menu);
1183 type->set_handler(bx_param_handler);
1184 mode->set_handler(bx_param_handler);
1185 status->set_handler(bx_param_handler);
1186 path->set_handler(bx_param_string_handler);
1188 // Set the enable_hanlders
1189 journal->set_enable_handler(bx_param_enable_handler);
1190 status->set_enable_handler(bx_param_enable_handler);
1193 // Enable two ATA interfaces by default, disable the others.
1194 // Now that the dependence relationships are established, call set() on
1195 // the ata device present params to set all enables correctly.
1196 enabled->set_initial_val(channel<2);
1197 enabled->set(channel<2);
1200 // disk menu
1201 bx_param_c *disk_menu_init_list[] = {
1202 SIM->get_param(BXPN_FLOPPYA),
1203 SIM->get_param(BXPN_FLOPPYB),
1204 SIM->get_param(BXPN_ATA0_RES),
1205 SIM->get_param(BXPN_ATA0_MASTER),
1206 SIM->get_param(BXPN_ATA0_SLAVE),
1207 #if BX_MAX_ATA_CHANNEL>1
1208 SIM->get_param(BXPN_ATA1_RES),
1209 SIM->get_param(BXPN_ATA1_MASTER),
1210 SIM->get_param(BXPN_ATA1_SLAVE),
1211 #endif
1212 #if BX_MAX_ATA_CHANNEL>2
1213 SIM->get_param(BXPN_ATA2_RES),
1214 SIM->get_param(BXPN_ATA2_MASTER),
1215 SIM->get_param(BXPN_ATA2_SLAVE),
1216 #endif
1217 #if BX_MAX_ATA_CHANNEL>3
1218 SIM->get_param(BXPN_ATA3_RES),
1219 SIM->get_param(BXPN_ATA3_MASTER),
1220 SIM->get_param(BXPN_ATA3_SLAVE),
1221 #endif
1222 SIM->get_param("boot_params"),
1223 NULL
1225 menu = new bx_list_c(special_menus, "disk", "Bochs Disk Options", disk_menu_init_list);
1226 menu->get_options()->set(bx_list_c::SHOW_PARENT);
1228 // ports subtree
1229 bx_list_c *ports = new bx_list_c(root_param, "ports", "Serial and Parallel Port Options");
1230 ports->get_options()->set(bx_list_c::USE_TAB_WINDOW | bx_list_c::SHOW_PARENT);
1232 // parallel ports
1233 bx_list_c *parallel = new bx_list_c(ports, "parallel", "Parallel Port Options");
1234 parallel->get_options()->set(bx_list_c::SHOW_PARENT);
1235 for (i=0; i<BX_N_PARALLEL_PORTS; i++) {
1236 sprintf(name, "%d", i+1);
1237 sprintf(label, "Parallel Port %d", i+1);
1238 menu = new bx_list_c(parallel, name, label);
1239 menu->get_options()->set(bx_list_c::SERIES_ASK);
1240 sprintf(label, "Enable parallel port #%d", i+1);
1241 sprintf(descr, "Controls whether parallel port #%d is installed or not", i+1);
1242 enabled = new bx_param_bool_c(menu, "enabled", label, descr,
1243 (i==0)? 1 : 0); // only enable #1 by default
1244 sprintf(label, "Parallel port #%d output file", i+1);
1245 sprintf(descr, "Data written to parport#%d by the guest OS is written to this file", i+1);
1246 path = new bx_param_filename_c(menu, "outfile", label, descr,
1247 "", BX_PATHNAME_LEN);
1248 deplist = new bx_list_c(NULL, 1);
1249 deplist->add(path);
1250 enabled->set_dependent_list(deplist);
1253 static const char *serial_mode_list[] = {
1254 "null",
1255 "file",
1256 "term",
1257 "raw",
1258 "mouse",
1259 "socket",
1260 NULL
1263 // serial ports
1264 bx_list_c *serial = new bx_list_c(ports, "serial", "Serial Port Options");
1265 serial->get_options()->set(bx_list_c::SHOW_PARENT);
1266 for (i=0; i<BX_N_SERIAL_PORTS; i++) {
1267 sprintf(name, "%d", i+1);
1268 sprintf(label, "Serial Port %d", i+1);
1269 menu = new bx_list_c(serial, name, label);
1270 menu->get_options()->set(bx_list_c::SERIES_ASK);
1271 sprintf(label, "Enable serial port #%d (COM%d)", i+1, i+1);
1272 sprintf(descr, "Controls whether COM%d is installed or not", i+1);
1273 enabled = new bx_param_bool_c(menu, "enabled", label, descr,
1274 (i==0)?1 : 0); // only enable the first by default
1275 sprintf(label, "I/O mode of the serial device for COM%d", i+1);
1276 sprintf(descr, "The mode can be one these: 'null', 'file', 'term', 'raw', 'mouse', 'socket'");
1277 mode = new bx_param_enum_c(menu, "mode", label, descr,
1278 serial_mode_list, 0, 0);
1279 mode->set_ask_format("Choose I/O mode of the serial device [%s] ");
1280 sprintf(label, "Pathname of the serial device for COM%d", i+1);
1281 sprintf(descr, "The path can be a real serial device or a pty (X/Unix only)");
1282 path = new bx_param_filename_c(menu, "dev", label, descr,
1283 "", BX_PATHNAME_LEN);
1284 deplist = new bx_list_c(NULL, 2);
1285 deplist->add(mode);
1286 deplist->add(path);
1287 enabled->set_dependent_list(deplist);
1290 bx_param_string_c *port;
1292 // usb hubs
1293 bx_list_c *usb = new bx_list_c(ports, "usb", "USB Hub Options");
1294 usb->get_options()->set(bx_list_c::SHOW_PARENT);
1295 for (i=0; i<BX_N_USB_HUBS; i++) {
1296 sprintf(group, "USB%d", i+1);
1297 sprintf(name, "%d", i+1);
1298 sprintf(label, "USB Hub %d", i+1);
1299 menu = new bx_list_c(usb, name, label);
1300 menu->set_enabled(BX_SUPPORT_PCIUSB);
1301 sprintf(label, "Enable usb hub #%d", i+1);
1302 sprintf(descr, "Controls whether %s is installed or not", group);
1303 enabled = new bx_param_bool_c(menu, "enabled", label, descr, 0);
1304 enabled->set_enabled(BX_SUPPORT_PCIUSB);
1305 port = new bx_param_string_c(menu,
1306 "port1",
1307 "Port #1 device",
1308 "Device connected to USB port #1",
1309 "", BX_PATHNAME_LEN);
1310 port->set_group(group);
1311 port = new bx_param_string_c(menu,
1312 "port2",
1313 "Port #2 device",
1314 "Device connected to USB port #2",
1315 "", BX_PATHNAME_LEN);
1316 port->set_group(group);
1317 enabled->set_dependent_list(menu->clone());
1320 // network subtree
1321 bx_list_c *network = new bx_list_c(root_param, "network", "Network Configuration");
1322 network->get_options()->set(bx_list_c::USE_TAB_WINDOW | bx_list_c::SHOW_PARENT);
1324 // ne2k & pnic options
1325 static const char *eth_module_list[] = {
1326 "null",
1327 #if defined(ETH_LINUX)
1328 "linux",
1329 #endif
1330 #if HAVE_ETHERTAP
1331 "tap",
1332 #endif
1333 #if HAVE_TUNTAP
1334 "tuntap",
1335 #endif
1336 #if defined(ETH_WIN32)
1337 "win32",
1338 #endif
1339 #if defined(ETH_FBSD)
1340 "fbsd",
1341 #endif
1342 #ifdef ETH_ARPBACK
1343 "arpback",
1344 #endif
1345 #if HAVE_VDE
1346 "vde",
1347 #endif
1348 "vnet",
1349 NULL
1351 // ne2k options
1352 menu = new bx_list_c(network, "ne2k", "NE2000", 7);
1353 menu->get_options()->set(bx_list_c::SHOW_PARENT);
1354 menu->set_enabled(BX_SUPPORT_NE2K);
1355 enabled = new bx_param_bool_c(menu,
1356 "enabled",
1357 "Enable NE2K NIC emulation",
1358 "Enables the NE2K NIC emulation",
1360 enabled->set_enabled(BX_SUPPORT_NE2K);
1361 ioaddr = new bx_param_num_c(menu,
1362 "ioaddr",
1363 "NE2K I/O Address",
1364 "I/O base address of the emulated NE2K device",
1365 0, 0xffff,
1366 0x300);
1367 ioaddr->set_base(16);
1368 irq = new bx_param_num_c(menu,
1369 "irq",
1370 "NE2K Interrupt",
1371 "IRQ used by the NE2K device",
1372 0, 15,
1374 irq->set_options(bx_param_num_c::USE_SPIN_CONTROL);
1375 macaddr = new bx_param_string_c(menu,
1376 "macaddr",
1377 "MAC Address",
1378 "MAC address of the NE2K device. Don't use an address of a machine on your net.",
1379 "\xfe\xfd\xde\xad\xbe\xef", 6);
1380 macaddr->get_options()->set(bx_param_string_c::RAW_BYTES);
1381 macaddr->set_separator(':');
1382 ethmod = new bx_param_enum_c(menu,
1383 "ethmod",
1384 "Ethernet module",
1385 "Module used for the connection to the real net.",
1386 eth_module_list,
1389 ethmod->set_by_name("null");
1390 ethmod->set_ask_format("Choose ethernet module for the NE2K [%s] ");
1391 ethdev = new bx_param_string_c(menu,
1392 "ethdev",
1393 "Ethernet device",
1394 "Device used for the connection to the real net. This is only valid if an ethernet module other than 'null' is used.",
1395 "xl0", BX_PATHNAME_LEN);
1396 path = new bx_param_filename_c(menu,
1397 "script",
1398 "Device configuration script",
1399 "Name of the script that is executed after Bochs initializes the network interface (optional).",
1400 "none", BX_PATHNAME_LEN);
1401 path->set_ask_format("Enter new script name, or 'none': [%s] ");
1402 enabled->set_dependent_list(menu->clone());
1403 // pnic options
1404 menu = new bx_list_c(network, "pnic", "PCI Pseudo NIC");
1405 menu->get_options()->set(bx_list_c::SHOW_PARENT);
1406 menu->set_enabled(BX_SUPPORT_PCIPNIC);
1407 enabled = new bx_param_bool_c(menu,
1408 "enabled",
1409 "Enable Pseudo NIC emulation",
1410 "Enables the Pseudo NIC emulation",
1412 enabled->set_enabled(BX_SUPPORT_PCIPNIC);
1413 macaddr = new bx_param_string_c(menu,
1414 "macaddr",
1415 "MAC Address",
1416 "MAC address of the Pseudo NIC device. Don't use an address of a machine on your net.",
1417 "\xfe\xfd\xde\xad\xbe\xef", 6);
1418 macaddr->get_options()->set(bx_param_string_c::RAW_BYTES);
1419 macaddr->set_separator(':');
1420 ethmod = new bx_param_enum_c(menu,
1421 "ethmod",
1422 "Ethernet module",
1423 "Module used for the connection to the real net.",
1424 eth_module_list,
1427 ethmod->set_by_name("null");
1428 ethmod->set_ask_format("Choose ethernet module for the Pseudo NIC [%s]");
1429 ethdev = new bx_param_string_c(menu,
1430 "ethdev",
1431 "Ethernet device",
1432 "Device used for the connection to the real net. This is only valid if an ethernet module other than 'null' is used.",
1433 "xl0", BX_PATHNAME_LEN);
1434 path = new bx_param_filename_c(menu,
1435 "script",
1436 "Device configuration script",
1437 "Name of the script that is executed after Bochs initializes the network interface (optional).",
1438 "none", BX_PATHNAME_LEN);
1439 path->set_ask_format("Enter new script name, or 'none': [%s] ");
1440 enabled->set_dependent_list(menu->clone());
1442 // sound subtree
1443 bx_list_c *sound = new bx_list_c(root_param, "sound", "Sound Configuration");
1444 sound->get_options()->set(bx_list_c::SHOW_PARENT);
1445 menu = new bx_list_c(sound, "sb16", "SB16 Configuration", 8);
1446 menu->get_options()->set(bx_list_c::SHOW_PARENT);
1447 menu->set_enabled(BX_SUPPORT_SB16);
1449 // SB16 options
1450 enabled = new bx_param_bool_c(menu,
1451 "enabled",
1452 "Enable SB16 emulation",
1453 "Enables the SB16 emulation",
1455 enabled->set_enabled(BX_SUPPORT_SB16);
1456 bx_param_num_c *midimode = new bx_param_num_c(menu,
1457 "midimode",
1458 "Midi mode",
1459 "Controls the MIDI output format.",
1460 0, 3,
1462 bx_param_filename_c *midifile = new bx_param_filename_c(menu,
1463 "midifile",
1464 "MIDI file",
1465 "The filename is where the MIDI data is sent. This can be device or just a file.",
1466 "", BX_PATHNAME_LEN);
1467 bx_param_num_c *wavemode = new bx_param_num_c(menu,
1468 "wavemode",
1469 "Wave mode",
1470 "Controls the wave output format.",
1471 0, 3,
1473 bx_param_filename_c *wavefile = new bx_param_filename_c(menu,
1474 "wavefile",
1475 "Wave file",
1476 "This is the device/file where the wave output is stored",
1477 "", BX_PATHNAME_LEN);
1478 bx_param_num_c *loglevel = new bx_param_num_c(menu,
1479 "loglevel",
1480 "Log level",
1481 "Controls how verbose the SB16 emulation is (0 = no log, 5 = all errors and infos).",
1482 0, 5,
1484 bx_param_filename_c *logfile = new bx_param_filename_c(menu,
1485 "logfile",
1486 "Log file",
1487 "The file to write the SB16 emulator messages to.",
1488 "", BX_PATHNAME_LEN);
1489 bx_param_num_c *dmatimer = new bx_param_num_c(menu,
1490 "dmatimer",
1491 "DMA timer",
1492 "Microseconds per second for a DMA cycle.",
1493 0, BX_MAX_BIT32U,
1496 #if BX_WITH_WX
1497 midimode->set_options(bx_param_num_c::USE_SPIN_CONTROL);
1498 wavemode->set_options(bx_param_num_c::USE_SPIN_CONTROL);
1499 loglevel->set_options(bx_param_num_c::USE_SPIN_CONTROL);
1500 #endif
1501 loglevel->set_group("SB16");
1502 dmatimer->set_group("SB16");
1503 enabled->set_dependent_list(menu->clone());
1504 deplist = new bx_list_c(NULL, 1);
1505 deplist->add(midifile);
1506 midimode->set_dependent_list(deplist);
1507 deplist = new bx_list_c(NULL, 1);
1508 deplist->add(wavefile);
1509 wavemode->set_dependent_list(deplist);
1510 deplist = new bx_list_c(NULL, 1);
1511 deplist->add(logfile);
1512 loglevel->set_dependent_list(deplist);
1514 // misc options subtree
1515 bx_list_c *misc = new bx_list_c(root_param, "misc", "Configure Everything Else");
1516 misc->get_options()->set(bx_list_c::SHOW_PARENT);
1517 bx_param_num_c *gdbstub_opt;
1519 // text snapshot check panic
1520 new bx_param_bool_c(misc,
1521 "text_snapshot_check",
1522 "Enable text snapshot check panic",
1523 "Enable panic when text on screen matches snapchk.txt.\nUseful for regression testing.\nIn win32, turns off CR/LF in snapshots and cuts.",
1525 // GDB stub
1526 menu = new bx_list_c(misc, "gdbstub", "GDB Stub Options");
1527 menu->get_options()->set(bx_list_c::SHOW_PARENT | bx_list_c::USE_BOX_TITLE);
1528 menu->set_enabled(BX_GDBSTUB);
1529 enabled = new bx_param_bool_c(menu,
1530 "enabled",
1531 "Enable GDB stub",
1534 enabled->set_enabled(BX_GDBSTUB);
1535 gdbstub_opt = new bx_param_num_c(menu,
1536 "port",
1537 "Port",
1538 "TCP/IP port for GDB stub",
1539 0, 65535,
1540 1234);
1541 gdbstub_opt = new bx_param_num_c(menu,
1542 "text_base",
1543 "Text base",
1545 0, BX_MAX_BIT32U,
1547 gdbstub_opt = new bx_param_num_c(menu,
1548 "data_base",
1549 "Data base",
1551 0, BX_MAX_BIT32U,
1553 gdbstub_opt = new bx_param_num_c(menu,
1554 "bss_base",
1555 "BSS base",
1557 0, BX_MAX_BIT32U,
1559 enabled->set_dependent_list(menu->clone());
1561 // log options subtree
1562 menu = new bx_list_c(root_param, "log", "Logfile Options");
1564 // log options
1565 path = new bx_param_filename_c(menu,
1566 "filename",
1567 "Log filename",
1568 "Pathname of bochs log file",
1569 "-", BX_PATHNAME_LEN);
1570 path->set_ask_format("Enter log filename: [%s] ");
1572 bx_param_string_c *prefix = new bx_param_string_c(menu,
1573 "prefix",
1574 "Log output prefix",
1575 "Prefix prepended to log output",
1576 "%t%e%d", BX_PATHNAME_LEN);
1577 prefix->set_ask_format("Enter log prefix: [%s] ");
1579 path = new bx_param_filename_c(menu,
1580 "debugger_filename",
1581 "Debugger Log filename",
1582 "Pathname of debugger log file",
1583 "-", BX_PATHNAME_LEN);
1584 path->set_ask_format("Enter debugger log filename: [%s] ");
1585 path->set_enabled(BX_DEBUGGER);
1587 // runtime options
1588 bx_param_c *runtime_init_list[] = {
1589 SIM->get_param_num(BXPN_VGA_UPDATE_INTERVAL),
1590 SIM->get_param_bool(BXPN_MOUSE_ENABLED),
1591 SIM->get_param_num(BXPN_KBD_PASTE_DELAY),
1592 SIM->get_param_string(BXPN_USER_SHORTCUT),
1593 SIM->get_param_num(BXPN_SB16_DMATIMER),
1594 SIM->get_param_num(BXPN_SB16_LOGLEVEL),
1595 SIM->get_param_string(BXPN_USB1_PORT1),
1596 SIM->get_param_string(BXPN_USB1_PORT2),
1597 NULL
1599 menu = new bx_list_c(special_menus, "runtime", "Misc runtime options", runtime_init_list);
1600 menu->get_options()->set(bx_list_c::SHOW_PARENT | bx_list_c::SHOW_GROUP_NAME);
1603 void bx_reset_options()
1605 // cpu
1606 SIM->get_param("cpu")->reset();
1608 // memory (ram & rom)
1609 SIM->get_param("memory")->reset();
1611 // clock & cmos
1612 SIM->get_param("clock_cmos")->reset();
1614 // pci
1615 SIM->get_param("pci")->reset();
1617 // display & interface
1618 SIM->get_param("display")->reset();
1620 // keyboard & mouse
1621 SIM->get_param("keyboard_mouse")->reset();
1623 // boot
1624 SIM->get_param("boot_params")->reset();
1626 // floppy drives
1627 SIM->get_param("floppy")->reset();
1629 // ata/atapi drives
1630 SIM->get_param("ata")->reset();
1632 // standard ports
1633 SIM->get_param("ports")->reset();
1635 // ne2k & pnic
1636 SIM->get_param("network")->reset();
1638 // SB16
1639 SIM->get_param("sound")->reset();
1641 // misc
1642 SIM->get_param("misc")->reset();
1644 // logfile
1645 SIM->get_param("log")->reset();
1648 int bx_read_configuration(const char *rcfile)
1650 // parse rcfile first, then parse arguments in order.
1651 BX_INFO (("reading configuration from %s", rcfile));
1652 if (parse_bochsrc(rcfile) < 0) {
1653 BX_PANIC (("reading from %s failed", rcfile));
1654 return -1;
1656 // update log actions
1657 for (int level=0; level<N_LOGLEV; level++) {
1658 int action = SIM->get_default_log_action (level);
1659 io->set_log_action (level, action);
1661 return 0;
1664 int bx_parse_cmdline (int arg, int argc, char *argv[])
1666 //if (arg < argc) BX_INFO (("parsing command line arguments"));
1668 while (arg < argc) {
1669 BX_INFO (("parsing arg %d, %s", arg, argv[arg]));
1670 parse_line_unformatted("cmdline args", argv[arg]);
1671 arg++;
1673 // update log actions
1674 for (int level=0; level<N_LOGLEV; level++) {
1675 int action = SIM->get_default_log_action (level);
1676 io->set_log_action (level, action);
1678 return 0;
1681 #if BX_PROVIDE_MAIN
1682 char *bx_find_bochsrc()
1684 FILE *fd = NULL;
1685 char rcfile[512];
1686 Bit32u retry = 0, found = 0;
1687 // try several possibilities for the bochsrc before giving up
1688 while (!found) {
1689 rcfile[0] = 0;
1690 switch (retry++) {
1691 case 0: strcpy (rcfile, ".bochsrc"); break;
1692 case 1: strcpy (rcfile, "bochsrc"); break;
1693 case 2: strcpy (rcfile, "bochsrc.txt"); break;
1694 #ifdef WIN32
1695 case 3: strcpy (rcfile, "bochsrc.bxrc"); break;
1696 #elif !BX_WITH_MACOS
1697 // only try this on unix
1698 case 3:
1700 char *ptr = getenv("HOME");
1701 if (ptr) snprintf (rcfile, sizeof(rcfile), "%s/.bochsrc", ptr);
1703 break;
1704 case 4: strcpy (rcfile, "/etc/bochsrc"); break;
1705 #endif
1706 default:
1707 return NULL;
1709 if (rcfile[0]) {
1710 BX_DEBUG (("looking for configuration in %s", rcfile));
1711 fd = fopen(rcfile, "r");
1712 if (fd) found = 1;
1715 assert (fd != NULL && rcfile[0] != 0);
1716 fclose (fd);
1717 return strdup(rcfile);
1720 static int parse_bochsrc(const char *rcfile)
1722 FILE *fd = NULL;
1723 char *ret;
1724 char line[512];
1725 char context[BX_PATHNAME_LEN];
1726 Bit32u linenum = 1;
1728 // try several possibilities for the bochsrc before giving up
1730 bochsrc_include_count++;
1732 fd = fopen (rcfile, "r");
1733 if (fd == NULL) return -1;
1735 int retval = 0;
1736 do {
1737 ret = fgets(line, sizeof(line)-1, fd);
1738 line[sizeof(line) - 1] = '\0';
1739 int len = strlen(line);
1740 if ((len>0) && (line[len-1] < ' '))
1741 line[len-1] = '\0';
1742 if ((ret != NULL) && strlen(line)) {
1743 sprintf(context, "%s:%u", rcfile, linenum);
1744 if (parse_line_unformatted(context, line) < 0) {
1745 retval = -1;
1746 break; // quit parsing after first error
1749 linenum++;
1750 } while (!feof(fd));
1751 fclose(fd);
1752 bochsrc_include_count--;
1753 return retval;
1756 static const char *get_builtin_variable(const char *varname)
1758 #ifdef WIN32
1759 int code;
1760 DWORD size;
1761 DWORD type = 0;
1762 HKEY hkey;
1763 char keyname[80];
1764 static char data[MAX_PATH];
1765 #endif
1767 if (strlen(varname)<1) return NULL;
1768 else {
1769 if (!strcmp(varname, "BXSHARE")) {
1770 #ifdef WIN32
1771 wsprintf(keyname, "Software\\Bochs %s", VER_STRING);
1772 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyname, 0, KEY_READ, &hkey);
1773 if (code == ERROR_SUCCESS) {
1774 data[0] = 0;
1775 size = MAX_PATH;
1776 if (RegQueryValueEx(hkey, "", NULL, (LPDWORD)&type, (LPBYTE)data,
1777 (LPDWORD)&size ) == ERROR_SUCCESS ) {
1778 RegCloseKey(hkey);
1779 return data;
1780 } else {
1781 RegCloseKey(hkey);
1782 return NULL;
1784 } else {
1785 return NULL;
1787 #else
1788 return BX_SHARE_PATH;
1789 #endif
1791 return NULL;
1795 static Bit32s parse_line_unformatted(const char *context, char *line)
1797 #define MAX_PARAMS_LEN 40
1798 char *ptr;
1799 unsigned i, string_i = 0;
1800 char string[512];
1801 char *params[MAX_PARAMS_LEN];
1802 int num_params;
1803 bx_bool inquotes = 0;
1804 bx_bool comment = 0;
1806 memset(params, 0, sizeof(params));
1807 if (line == NULL) return 0;
1809 // if passed nothing but whitespace, just return
1810 for (i=0; i<strlen(line); i++) {
1811 if (!isspace(line[i])) break;
1813 if (i>=strlen(line))
1814 return 0;
1816 num_params = 0;
1818 if (!strncmp(line, "#include", 8))
1819 ptr = strtok(line, " ");
1820 else
1821 ptr = strtok(line, ":");
1822 while ((ptr) && (!comment)) {
1823 if (!inquotes) {
1824 string_i = 0;
1825 } else {
1826 string[string_i++] = ',';
1828 for (i=0; i<strlen(ptr); i++) {
1829 if (ptr[i] == '"')
1830 inquotes = !inquotes;
1831 else if ((ptr[i] == '#') && (strncmp(line+i, "#include", 8)) && !inquotes) {
1832 comment = 1;
1833 break;
1834 } else {
1835 #if BX_HAVE_GETENV
1836 // substitute environment variables.
1837 if (ptr[i] == '$') {
1838 char varname[512];
1839 char *pv = varname;
1840 const char *value;
1841 *pv = 0;
1842 i++;
1843 while (isalpha(ptr[i]) || ptr[i]=='_') {
1844 *pv = ptr[i]; pv++; i++;
1846 *pv = 0;
1847 if (strlen(varname)<1 || !(value = getenv(varname))) {
1848 if ((value = get_builtin_variable(varname))) {
1849 // append value to the string
1850 for (pv=(char *)value; *pv; pv++)
1851 string[string_i++] = *pv;
1852 } else {
1853 BX_PANIC (("could not look up environment variable '%s'", varname));
1855 } else {
1856 // append value to the string
1857 for (pv=(char *)value; *pv; pv++)
1858 string[string_i++] = *pv;
1861 #endif
1862 if (!isspace(ptr[i]) || inquotes) {
1863 string[string_i++] = ptr[i];
1867 string[string_i] = '\0';
1868 if (string_i == 0) break;
1869 if (!inquotes) {
1870 if (params[num_params] != NULL) {
1871 free(params[num_params]);
1872 params[num_params] = NULL;
1874 if (num_params < MAX_PARAMS_LEN) {
1875 params[num_params++] = strdup(string);
1876 } else {
1877 BX_PANIC (("too many parameters, max is %d\n", MAX_PARAMS_LEN));
1880 ptr = strtok(NULL, ",");
1882 Bit32s retval = parse_line_formatted(context, num_params, &params[0]);
1883 for (i=0; i < MAX_PARAMS_LEN; i++)
1885 if ( params[i] != NULL )
1887 free(params[i]);
1888 params[i] = NULL;
1891 return retval;
1894 // These macros are called for all parse errors, so that we can easily
1895 // change the behavior of all occurrences.
1896 #define PARSE_ERR(x) \
1897 do { BX_PANIC(x); return -1; } while (0)
1898 #define PARSE_WARN(x) \
1899 BX_ERROR(x)
1902 * this supports the "floppyx: image=" option.
1903 * the functions returns the type of the floppy
1904 * image (1.44, 360, etc.), based on the image file size.
1906 int get_floppy_type_from_image(const char *filename)
1908 struct stat stat_buf;
1910 if (stat(filename, &stat_buf))
1912 return BX_FLOPPY_NONE;
1915 switch (stat_buf.st_size)
1917 case 163840:
1918 return BX_FLOPPY_160K;
1920 case 184320:
1921 return BX_FLOPPY_180K;
1923 case 327680:
1924 return BX_FLOPPY_320K;
1926 case 368640:
1927 return BX_FLOPPY_360K;
1929 case 737280:
1930 return BX_FLOPPY_720K;
1932 case 1228800:
1933 return BX_FLOPPY_1_2;
1935 case 1474560:
1936 case 1720320:
1937 case 1763328:
1938 case 1884160:
1939 return BX_FLOPPY_1_44;
1941 case 2949120:
1942 return BX_FLOPPY_2_88;
1944 default:
1945 return BX_FLOPPY_UNKNOWN;
1949 static Bit32s parse_log_options(const char *context, char *loglev, char *param1)
1951 int level;
1953 if (!strcmp(loglev, "panic")) {
1954 level = LOGLEV_PANIC;
1955 } else if (!strcmp(loglev, "pass")) {
1956 level = LOGLEV_PASS;
1957 } else if (!strcmp(loglev, "error")) {
1958 level = LOGLEV_ERROR;
1959 } else if (!strcmp(loglev, "info")) {
1960 level = LOGLEV_INFO;
1961 } else { /* debug */
1962 level = LOGLEV_DEBUG;
1964 if (strncmp(param1, "action=", 7)) {
1965 PARSE_ERR(("%s: %s directive malformed.", context, loglev));
1967 char *action = param1 + 7;
1968 if (!strcmp(action, "fatal"))
1969 SIM->set_default_log_action (level, ACT_FATAL);
1970 else if (!strcmp (action, "report"))
1971 SIM->set_default_log_action (level, ACT_REPORT);
1972 else if (!strcmp (action, "ignore"))
1973 SIM->set_default_log_action (level, ACT_IGNORE);
1974 else if (!strcmp (action, "ask"))
1975 SIM->set_default_log_action (level, ACT_ASK);
1976 else {
1977 PARSE_ERR(("%s: %s directive malformed.", context, loglev));
1979 return 0;
1982 static Bit32s parse_line_formatted(const char *context, int num_params, char *params[])
1984 int i, slot, t;
1985 Bit8u idx;
1986 bx_list_c *base;
1988 if (num_params < 1) return 0;
1989 if (num_params < 2) {
1990 PARSE_ERR(("%s: a bochsrc option needs at least one parameter", context));
1993 if (!strcmp(params[0], "#include")) {
1994 if (num_params != 2) {
1995 PARSE_ERR(("%s: ignoring malformed #include directive.", context));
1997 if (!strcmp(params[1], context)) {
1998 PARSE_ERR(("%s: cannot include this file again.", context));
2000 if (bochsrc_include_count == 2) {
2001 PARSE_ERR(("%s: include directive in an included file not supported yet.", context));
2003 bx_read_configuration(params[1]);
2005 else if (!strcmp(params[0], "floppya")) {
2006 for (i=1; i<num_params; i++) {
2007 if (!strncmp(params[i], "2_88=", 5)) {
2008 SIM->get_param_string(BXPN_FLOPPYA_PATH)->set(&params[i][5]);
2009 SIM->get_param_enum(BXPN_FLOPPYA_TYPE)->set(BX_FLOPPY_2_88);
2011 else if (!strncmp(params[i], "1_44=", 5)) {
2012 SIM->get_param_string(BXPN_FLOPPYA_PATH)->set(&params[i][5]);
2013 SIM->get_param_enum(BXPN_FLOPPYA_TYPE)->set(BX_FLOPPY_1_44);
2015 else if (!strncmp(params[i], "1_2=", 4)) {
2016 SIM->get_param_string(BXPN_FLOPPYA_PATH)->set(&params[i][4]);
2017 SIM->get_param_enum(BXPN_FLOPPYA_TYPE)->set(BX_FLOPPY_1_2);
2019 else if (!strncmp(params[i], "720k=", 5)) {
2020 SIM->get_param_string(BXPN_FLOPPYA_PATH)->set(&params[i][5]);
2021 SIM->get_param_enum(BXPN_FLOPPYA_TYPE)->set(BX_FLOPPY_720K);
2023 else if (!strncmp(params[i], "360k=", 5)) {
2024 SIM->get_param_string(BXPN_FLOPPYA_PATH)->set(&params[i][5]);
2025 SIM->get_param_enum(BXPN_FLOPPYA_TYPE)->set(BX_FLOPPY_360K);
2027 // use CMOS reserved types?
2028 else if (!strncmp(params[i], "160k=", 5)) {
2029 SIM->get_param_string(BXPN_FLOPPYA_PATH)->set(&params[i][5]);
2030 SIM->get_param_enum(BXPN_FLOPPYA_TYPE)->set(BX_FLOPPY_160K);
2032 else if (!strncmp(params[i], "180k=", 5)) {
2033 SIM->get_param_string(BXPN_FLOPPYA_PATH)->set(&params[i][5]);
2034 SIM->get_param_enum(BXPN_FLOPPYA_TYPE)->set(BX_FLOPPY_180K);
2036 else if (!strncmp(params[i], "320k=", 5)) {
2037 SIM->get_param_string(BXPN_FLOPPYA_PATH)->set(&params[i][5]);
2038 SIM->get_param_enum(BXPN_FLOPPYA_TYPE)->set(BX_FLOPPY_320K);
2040 else if (!strncmp(params[i], "image=", 6)) {
2041 /* "image=" means we should get floppy type from image */
2042 SIM->get_param_string(BXPN_FLOPPYA_PATH)->set(&params[i][6]);
2043 t = get_floppy_type_from_image(&params[i][6]);
2044 if (t != BX_FLOPPY_UNKNOWN)
2045 SIM->get_param_enum(BXPN_FLOPPYA_TYPE)->set(t);
2046 else
2047 PARSE_ERR(("%s: floppya image size doesn't match one of the supported types.", context));
2049 else if (!strncmp(params[i], "status=", 7)) {
2050 SIM->get_param_enum(BXPN_FLOPPYA_STATUS)->set_by_name(&params[i][7]);
2052 else {
2053 PARSE_ERR(("%s: floppya attribute '%s' not understood.", context,
2054 params[i]));
2059 else if (!strcmp(params[0], "floppyb")) {
2060 for (i=1; i<num_params; i++) {
2061 if (!strncmp(params[i], "2_88=", 5)) {
2062 SIM->get_param_string(BXPN_FLOPPYB_PATH)->set(&params[i][5]);
2063 SIM->get_param_enum(BXPN_FLOPPYB_TYPE)->set(BX_FLOPPY_2_88);
2065 else if (!strncmp(params[i], "1_44=", 5)) {
2066 SIM->get_param_string(BXPN_FLOPPYB_PATH)->set(&params[i][5]);
2067 SIM->get_param_enum(BXPN_FLOPPYB_TYPE)->set(BX_FLOPPY_1_44);
2069 else if (!strncmp(params[i], "1_2=", 4)) {
2070 SIM->get_param_string(BXPN_FLOPPYB_PATH)->set(&params[i][4]);
2071 SIM->get_param_enum(BXPN_FLOPPYB_TYPE)->set(BX_FLOPPY_1_2);
2073 else if (!strncmp(params[i], "720k=", 5)) {
2074 SIM->get_param_string(BXPN_FLOPPYB_PATH)->set(&params[i][5]);
2075 SIM->get_param_enum(BXPN_FLOPPYB_TYPE)->set(BX_FLOPPY_720K);
2077 else if (!strncmp(params[i], "360k=", 5)) {
2078 SIM->get_param_string(BXPN_FLOPPYB_PATH)->set(&params[i][5]);
2079 SIM->get_param_enum(BXPN_FLOPPYB_TYPE)->set(BX_FLOPPY_360K);
2081 // use CMOS reserved types?
2082 else if (!strncmp(params[i], "160k=", 5)) {
2083 SIM->get_param_string(BXPN_FLOPPYB_PATH)->set(&params[i][5]);
2084 SIM->get_param_enum(BXPN_FLOPPYB_TYPE)->set(BX_FLOPPY_160K);
2086 else if (!strncmp(params[i], "180k=", 5)) {
2087 SIM->get_param_string(BXPN_FLOPPYB_PATH)->set(&params[i][5]);
2088 SIM->get_param_enum(BXPN_FLOPPYB_TYPE)->set(BX_FLOPPY_180K);
2090 else if (!strncmp(params[i], "320k=", 5)) {
2091 SIM->get_param_string(BXPN_FLOPPYB_PATH)->set(&params[i][5]);
2092 SIM->get_param_enum(BXPN_FLOPPYB_TYPE)->set(BX_FLOPPY_320K);
2094 else if (!strncmp(params[i], "image=", 6)) {
2095 /* "image=" means we should get floppy type from image */
2096 SIM->get_param_string(BXPN_FLOPPYB_PATH)->set(&params[i][6]);
2097 t = get_floppy_type_from_image(&params[i][6]);
2098 if (t != BX_FLOPPY_UNKNOWN)
2099 SIM->get_param_enum(BXPN_FLOPPYB_TYPE)->set(t);
2100 else
2101 PARSE_ERR(("%s: floppyb image size doesn't match one of the supported types.", context));
2103 else if (!strncmp(params[i], "status=", 7)) {
2104 SIM->get_param_enum(BXPN_FLOPPYB_STATUS)->set_by_name(&params[i][7]);
2106 else {
2107 PARSE_ERR(("%s: floppyb attribute '%s' not understood.", context,
2108 params[i]));
2113 else if ((!strncmp(params[0], "ata", 3)) && (strlen(params[0]) == 4)) {
2114 char tmpname[80];
2115 Bit8u channel = params[0][3];
2117 if ((channel < '0') || (channel > '9')) {
2118 PARSE_ERR(("%s: ataX directive malformed.", context));
2120 channel-='0';
2121 if (channel >= BX_MAX_ATA_CHANNEL) {
2122 PARSE_ERR(("%s: ataX directive malformed.", context));
2125 if ((num_params < 2) || (num_params > 5)) {
2126 PARSE_ERR(("%s: ataX directive malformed.", context));
2128 sprintf(tmpname, "ata.%d.resources", channel);
2129 base = (bx_list_c*) SIM->get_param(tmpname);
2130 if (strncmp(params[1], "enabled=", 8)) {
2131 PARSE_ERR(("%s: ataX directive malformed.", context));
2132 } else {
2133 SIM->get_param_bool("enabled", base)->set(atol(&params[1][8]));
2136 if (num_params > 2) {
2137 if (strncmp(params[2], "ioaddr1=", 8)) {
2138 PARSE_ERR(("%s: ataX directive malformed.", context));
2140 else {
2141 if ((params[2][8] == '0') && (params[2][9] == 'x'))
2142 SIM->get_param_num("ioaddr1", base)->set(strtoul(&params[2][8], NULL, 16));
2143 else
2144 SIM->get_param_num("ioaddr1", base)->set(strtoul(&params[2][8], NULL, 10));
2148 if (num_params > 3) {
2149 if (strncmp(params[3], "ioaddr2=", 8)) {
2150 PARSE_ERR(("%s: ataX directive malformed.", context));
2152 else {
2153 if ((params[3][8] == '0') && (params[3][9] == 'x'))
2154 SIM->get_param_num("ioaddr2", base)->set(strtoul(&params[3][8], NULL, 16));
2155 else
2156 SIM->get_param_num("ioaddr2", base)->set(strtoul(&params[3][8], NULL, 10));
2160 if (num_params > 4) {
2161 if (strncmp(params[4], "irq=", 4)) {
2162 PARSE_ERR(("%s: ataX directive malformed.", context));
2164 else {
2165 SIM->get_param_num("irq", base)->set(atol(&params[4][4]));
2170 // ataX-master, ataX-slave
2171 else if ((!strncmp(params[0], "ata", 3)) && (strlen(params[0]) > 4)) {
2172 Bit8u channel = params[0][3];
2173 int type = 0, mode = BX_ATA_MODE_FLAT, biosdetect = BX_ATA_BIOSDETECT_AUTO;
2174 Bit32u cylinders = 0, heads = 0, sectors = 0;
2175 char tmpname[80];
2177 if ((channel < '0') || (channel > '9')) {
2178 PARSE_ERR(("%s: ataX-master/slave directive malformed.", context));
2180 channel-='0';
2181 if (channel >= BX_MAX_ATA_CHANNEL) {
2182 PARSE_ERR(("%s: ataX-master/slave directive malformed.", context));
2185 if ((strcmp(&params[0][4], "-slave")) &&
2186 (strcmp(&params[0][4], "-master"))) {
2187 PARSE_ERR(("%s: ataX-master/slave directive malformed.", context));
2190 sprintf(tmpname, "ata.%d.%s", channel, &params[0][5]);
2191 base = (bx_list_c*) SIM->get_param(tmpname);
2192 for (i=1; i<num_params; i++) {
2193 if (!strncmp(params[i], "type=", 5)) {
2194 type = SIM->get_param_enum("type", base)->find_by_name(&params[i][5]);
2195 if (type < 0) {
2196 PARSE_ERR(("%s: ataX-master/slave: unknown type '%s'", context, &params[i][5]));
2198 } else if (!strcmp(params[i], "mode=z-undoable")) {
2199 PARSE_ERR(("%s: ataX-master/slave mode 'z-undoable' not implemented yet", context));
2200 } else if (!strcmp(params[i], "mode=z-volatile")) {
2201 PARSE_ERR(("%s: ataX-master/slave mode 'z-volatile' not implemented yet", context));
2202 } else if (!strncmp(params[i], "mode=", 5)) {
2203 mode = SIM->get_param_enum("mode", base)->find_by_name(&params[i][5]);
2204 if (mode < 0) {
2205 PARSE_ERR(("%s: ataX-master/slave: unknown mode '%s'", context, &params[i][5]));
2207 } else if (!strncmp(params[i], "path=", 5)) {
2208 SIM->get_param_string("path", base)->set(&params[i][5]);
2209 } else if (!strncmp(params[i], "cylinders=", 10)) {
2210 cylinders = atol(&params[i][10]);
2211 } else if (!strncmp(params[i], "heads=", 6)) {
2212 heads = atol(&params[i][6]);
2213 } else if (!strncmp(params[i], "spt=", 4)) {
2214 sectors = atol(&params[i][4]);
2215 } else if (!strncmp(params[i], "model=", 6)) {
2216 SIM->get_param_string("model", base)->set(&params[i][6]);
2217 } else if (!strncmp(params[i], "biosdetect=", 11)) {
2218 biosdetect = SIM->get_param_enum("biosdetect", base)->find_by_name(&params[i][11]);
2219 if (biosdetect < 0) {
2220 PARSE_ERR(("%s: ataX-master/slave: unknown biosdetect '%s'", context, &params[i][11]));
2222 } else if (!strcmp(params[i], "translation=none")) {
2223 SIM->get_param_enum("translation", base)->set(BX_ATA_TRANSLATION_NONE);
2224 } else if (!strcmp(params[i], "translation=lba")) {
2225 SIM->get_param_enum("translation", base)->set(BX_ATA_TRANSLATION_LBA);
2226 } else if (!strcmp(params[i], "translation=large")) {
2227 SIM->get_param_enum("translation", base)->set(BX_ATA_TRANSLATION_LARGE);
2228 } else if (!strcmp(params[i], "translation=echs")) { // synonym of large
2229 SIM->get_param_enum("translation", base)->set(BX_ATA_TRANSLATION_LARGE);
2230 } else if (!strcmp(params[i], "translation=rechs")) {
2231 SIM->get_param_enum("translation", base)->set(BX_ATA_TRANSLATION_RECHS);
2232 } else if (!strcmp(params[i], "translation=auto")) {
2233 SIM->get_param_enum("translation", base)->set(BX_ATA_TRANSLATION_AUTO);
2234 } else if (!strcmp(params[i], "status=ejected")) {
2235 SIM->get_param_enum("status", base)->set(BX_EJECTED);
2236 } else if (!strcmp(params[i], "status=inserted")) {
2237 SIM->get_param_enum("status", base)->set(BX_INSERTED);
2238 } else if (!strncmp(params[i], "journal=", 8)) {
2239 SIM->get_param_string("journal", base)->set(&params[i][8]);
2240 } else {
2241 PARSE_ERR(("%s: ataX-master/slave directive malformed.", context));
2245 // Enables the ata device
2246 if (strlen(SIM->get_param_string("path", base)->getptr()) > 0) {
2247 SIM->get_param_bool("present", base)->set(1);
2248 SIM->get_param_enum("type", base)->set(type);
2249 SIM->get_param_enum("mode", base)->set(mode);
2250 SIM->get_param_num("cylinders", base)->set(cylinders);
2251 SIM->get_param_num("heads", base)->set(heads);
2252 SIM->get_param_num("spt", base)->set(sectors);
2253 SIM->get_param_num("biosdetect", base)->set(biosdetect);
2254 } else {
2255 SIM->get_param_bool("present", base)->set(0);
2258 // if enabled, check if device ok
2259 if (SIM->get_param_bool("present", base)->get() == 1) {
2260 if (SIM->get_param_enum("type", base)->get() == BX_ATA_DEVICE_DISK) {
2261 if ((SIM->get_param_num("cylinders", base)->get() == 0) &&
2262 (SIM->get_param_num("heads", base)->get() ==0 ) &&
2263 (SIM->get_param_num("spt", base)->get() == 0)) {
2264 PARSE_WARN(("%s: ataX-master/slave CHS set to 0/0/0 - autodetection enabled", context));
2265 // using heads = 16 and spt = 63 for autodetection (bximage defaults)
2266 SIM->get_param_num("heads", base)->set(16);
2267 SIM->get_param_num("spt", base)->set(63);
2269 } else if (SIM->get_param_enum("type", base)->get() != BX_ATA_DEVICE_CDROM) {
2270 PARSE_WARN(("%s: ataX-master/slave: type should be specified", context));
2273 } else if (!strcmp(params[0], "boot")) {
2274 char tmppath[80];
2275 if (num_params < 2) {
2276 PARSE_ERR(("%s: boot directive malformed.", context));
2278 for (i=1; i<num_params; i++) {
2279 sprintf(tmppath, "boot_params.boot_drive%d", i);
2280 if (!strcmp(params[i], "none")) {
2281 SIM->get_param_enum(tmppath)->set(BX_BOOT_NONE);
2282 } else if (!strcmp(params[i], "a")) {
2283 SIM->get_param_enum(tmppath)->set(BX_BOOT_FLOPPYA);
2284 } else if (!strcmp(params[i], "floppy")) {
2285 SIM->get_param_enum(tmppath)->set(BX_BOOT_FLOPPYA);
2286 } else if (!strcmp(params[i], "c")) {
2287 SIM->get_param_enum(tmppath)->set(BX_BOOT_DISKC);
2288 } else if (!strcmp(params[i], "disk")) {
2289 SIM->get_param_enum(tmppath)->set(BX_BOOT_DISKC);
2290 } else if (!strcmp(params[i], "cdrom")) {
2291 SIM->get_param_enum(tmppath)->set(BX_BOOT_CDROM);
2292 } else {
2293 PARSE_ERR(("%s: boot directive with unknown boot drive '%s'. use 'floppy', 'disk' or 'cdrom'.", context, params[i]));
2296 if (SIM->get_param_enum(BXPN_BOOTDRIVE1)->get() == BX_BOOT_NONE) {
2297 PARSE_ERR(("%s: first boot drive must be one of 'floppy', 'disk' or 'cdrom'.", context));
2299 if ((SIM->get_param_enum(BXPN_BOOTDRIVE1)->get() == SIM->get_param_enum(BXPN_BOOTDRIVE2)->get()) ||
2300 (SIM->get_param_enum(BXPN_BOOTDRIVE1)->get() == SIM->get_param_enum(BXPN_BOOTDRIVE3)->get()) ||
2301 ((SIM->get_param_enum(BXPN_BOOTDRIVE3)->get() != BX_BOOT_NONE) &&
2302 (SIM->get_param_enum(BXPN_BOOTDRIVE2)->get() == SIM->get_param_enum(BXPN_BOOTDRIVE3)->get()))) {
2303 PARSE_ERR(("%s: a boot drive appears twice in boot sequence.", context));
2305 } else if (!strcmp(params[0], "floppy_bootsig_check")) {
2306 if (num_params != 2) {
2307 PARSE_ERR(("%s: floppy_bootsig_check directive malformed.", context));
2309 if (strncmp(params[1], "disabled=", 9)) {
2310 PARSE_ERR(("%s: floppy_bootsig_check directive malformed.", context));
2312 if (params[1][9] == '0')
2313 SIM->get_param_bool(BXPN_FLOPPYSIGCHECK)->set(0);
2314 else if (params[1][9] == '1')
2315 SIM->get_param_bool(BXPN_FLOPPYSIGCHECK)->set(1);
2316 else {
2317 PARSE_ERR(("%s: floppy_bootsig_check directive malformed.", context));
2319 } else if (!strcmp(params[0], "log")) {
2320 if (num_params != 2) {
2321 PARSE_ERR(("%s: log directive has wrong # args.", context));
2323 SIM->get_param_string(BXPN_LOG_FILENAME)->set(params[1]);
2324 } else if (!strcmp(params[0], "logprefix")) {
2325 if (num_params != 2) {
2326 PARSE_ERR(("%s: logprefix directive has wrong # args.", context));
2328 SIM->get_param_string(BXPN_LOG_PREFIX)->set(params[1]);
2329 } else if (!strcmp(params[0], "debugger_log")) {
2330 if (num_params != 2) {
2331 PARSE_ERR(("%s: debugger_log directive has wrong # args.", context));
2333 SIM->get_param_string(BXPN_DEBUGGER_LOG_FILENAME)->set(params[1]);
2334 } else if (!strcmp(params[0], "panic")) {
2335 if (num_params != 2) {
2336 PARSE_ERR(("%s: panic directive malformed.", context));
2338 if (parse_log_options(context, params[0], params[1]) < 0) {
2339 return -1;
2341 } else if (!strcmp(params[0], "pass")) {
2342 if (num_params != 2) {
2343 PARSE_ERR(("%s: pass directive malformed.", context));
2345 if (parse_log_options(context, params[0], params[1]) < 0) {
2346 return -1;
2348 } else if (!strcmp(params[0], "error")) {
2349 if (num_params != 2) {
2350 PARSE_ERR(("%s: error directive malformed.", context));
2352 if (parse_log_options(context, params[0], params[1]) < 0) {
2353 return -1;
2355 } else if (!strcmp(params[0], "info")) {
2356 if (num_params != 2) {
2357 PARSE_ERR(("%s: info directive malformed.", context));
2359 if (parse_log_options(context, params[0], params[1]) < 0) {
2360 return -1;
2362 } else if (!strcmp(params[0], "debug")) {
2363 if (num_params != 2) {
2364 PARSE_ERR(("%s: debug directive malformed.", context));
2366 if (parse_log_options(context, params[0], params[1]) < 0) {
2367 return -1;
2369 } else if (!strcmp(params[0], "cpu")) {
2370 if (num_params < 2) {
2371 PARSE_ERR(("%s: cpu directive malformed.", context));
2373 for (i=1; i<num_params; i++) {
2374 if (!strncmp(params[i], "count=", 6)) {
2375 unsigned processors = 1, cores = 1, threads = 1;
2376 sscanf(&params[i][6], "%u:%u:%u", &processors, &cores, &threads);
2377 unsigned smp_threads = cores*threads*processors;
2378 if (smp_threads > BX_MAX_SMP_THREADS_SUPPORTED) {
2379 PARSE_ERR(("%s: too many SMP threads defined, only %u threads supported",
2380 context, BX_MAX_SMP_THREADS_SUPPORTED));
2382 if (smp_threads < 1) {
2383 PARSE_ERR(("%s: at least one CPU thread should be defined, cpu directive malformed", context));
2385 SIM->get_param_num(BXPN_CPU_NPROCESSORS)->set(processors);
2386 SIM->get_param_num(BXPN_CPU_NCORES)->set(cores);
2387 SIM->get_param_num(BXPN_CPU_NTHREADS)->set(threads);
2388 } else if (!strncmp(params[i], "ips=", 4)) {
2389 SIM->get_param_num(BXPN_IPS)->set(atol(&params[i][4]));
2390 if (SIM->get_param_num(BXPN_IPS)->get() < BX_MIN_IPS) {
2391 PARSE_WARN(("%s: WARNING: ips is AWFULLY low!", context));
2393 #if BX_SUPPORT_SMP
2394 } else if (!strncmp(params[i], "quantum=", 8)) {
2395 SIM->get_param_num(BXPN_SMP_QUANTUM)->set(atol(&params[i][8]));
2396 #endif
2397 } else if (!strncmp(params[i], "reset_on_triple_fault=", 22)) {
2398 if (params[i][22] == '0' || params[i][22] == '1') {
2399 SIM->get_param_bool(BXPN_RESET_ON_TRIPLE_FAULT)->set (params[i][22] - '0');
2400 } else {
2401 PARSE_ERR(("%s: cpu directive malformed.", context));
2403 } else {
2404 PARSE_ERR(("%s: cpu directive malformed.", context));
2407 } else if (!strcmp(params[0], "megs")) {
2408 if (num_params != 2) {
2409 PARSE_ERR(("%s: megs directive: wrong # args.", context));
2411 SIM->get_param_num(BXPN_MEM_SIZE)->set(atol(params[1]));
2412 } else if (!strcmp(params[0], "romimage")) {
2413 if ((num_params < 2) || (num_params > 3)) {
2414 PARSE_ERR(("%s: romimage directive: wrong # args.", context));
2416 if (!strncmp(params[1], "file=", 5)) {
2417 SIM->get_param_string(BXPN_ROM_PATH)->set(&params[1][5]);
2418 } else {
2419 PARSE_ERR(("%s: romimage directive malformed.", context));
2421 if (num_params == 3) {
2422 if (!strncmp(params[2], "address=", 8)) {
2423 if ((params[2][8] == '0') && (params[2][9] == 'x'))
2424 SIM->get_param_num(BXPN_ROM_ADDRESS)->set(strtoul(&params[2][8], NULL, 16));
2425 else
2426 SIM->get_param_num(BXPN_ROM_ADDRESS)->set(strtoul(&params[2][8], NULL, 10));
2427 } else {
2428 PARSE_ERR(("%s: romimage directive malformed.", context));
2430 } else {
2431 SIM->get_param_num(BXPN_ROM_ADDRESS)->set (0);
2433 } else if (!strcmp(params[0], "vgaromimage")) {
2434 if (num_params != 2) {
2435 PARSE_ERR(("%s: vgaromimage directive: wrong # args.", context));
2437 if (!strncmp(params[1], "file=", 5)) {
2438 SIM->get_param_string(BXPN_VGA_ROM_PATH)->set(&params[1][5]);
2439 } else {
2440 BX_INFO(("WARNING: syntax has changed, please use 'vgaromimage: file=...' now"));
2441 SIM->get_param_string(BXPN_VGA_ROM_PATH)->set(params[1]);
2443 } else if (!strncmp(params[0], "optromimage", 11)) {
2444 int num = atoi(&params[0][11]);
2445 char tmppath[80], tmpaddr[80];
2446 if ((num < 1) || (num > BX_N_OPTROM_IMAGES)) {
2447 PARSE_ERR(("%s: optromimage%d: not supported", context, num));
2449 if (num_params != 3) {
2450 PARSE_ERR(("%s: optromimage%d directive: wrong # args.", context, num));
2452 sprintf(tmppath, "memory.optrom.%d.path", num);
2453 sprintf(tmpaddr, "memory.optrom.%d.addr", num);
2454 for (i=1; i<num_params; i++) {
2455 if (!strncmp(params[i], "file=", 5)) {
2456 SIM->get_param_string(tmppath)->set(&params[i][5]);
2457 } else if (!strncmp(params[i], "address=", 8)) {
2458 if ((params[i][8] == '0') && (params[2][9] == 'x'))
2459 SIM->get_param_num(tmpaddr)->set(strtoul(&params[i][8], NULL, 16));
2460 else
2461 SIM->get_param_num(tmpaddr)->set(strtoul(&params[i][8], NULL, 10));
2462 } else {
2463 PARSE_ERR(("%s: optromimage%d directive malformed.", context, num));
2466 } else if (!strncmp(params[0], "optramimage", 11)) {
2467 int num = atoi(&params[0][11]);
2468 char tmppath[80], tmpaddr[80];
2469 if ((num < 1) || (num > BX_N_OPTRAM_IMAGES)) {
2470 PARSE_ERR(("%s: optramimage%d: not supported", context, num));
2472 if (num_params != 3) {
2473 PARSE_ERR(("%s: optramimage%d directive: wrong # args.", context, num));
2475 sprintf(tmppath, "memory.optram.%d.path", num);
2476 sprintf(tmpaddr, "memory.optram.%d.addr", num);
2477 for (i=1; i<num_params; i++) {
2478 if (!strncmp(params[i], "file=", 5)) {
2479 SIM->get_param_string(tmppath)->set(&params[i][5]);
2480 } else if (!strncmp(params[i], "address=", 8)) {
2481 if ((params[i][8] == '0') && (params[2][9] == 'x'))
2482 SIM->get_param_num(tmpaddr)->set(strtoul(&params[i][8], NULL, 16));
2483 else
2484 SIM->get_param_num(tmpaddr)->set(strtoul(&params[i][8], NULL, 10));
2485 } else {
2486 PARSE_ERR(("%s: optramimage%d directive malformed.", context, num));
2489 } else if (!strcmp(params[0], "vga_update_interval")) {
2490 if (num_params != 2) {
2491 PARSE_ERR(("%s: vga_update_interval directive: wrong # args.", context));
2493 SIM->get_param_num(BXPN_VGA_UPDATE_INTERVAL)->set(atol(params[1]));
2494 if (SIM->get_param_num(BXPN_VGA_UPDATE_INTERVAL)->get() < 50000) {
2495 BX_INFO(("%s: vga_update_interval seems awfully small!", context));
2497 } else if (!strcmp(params[0], "vga")) {
2498 if (num_params != 2) {
2499 PARSE_ERR(("%s: vga directive: wrong # args.", context));
2501 if (!strncmp(params[1], "extension=", 10)) {
2502 SIM->get_param_string(BXPN_VGA_EXTENSION)->set(&params[1][10]);
2504 } else if (!strcmp(params[0], "keyboard_serial_delay")) {
2505 if (num_params != 2) {
2506 PARSE_ERR(("%s: keyboard_serial_delay directive: wrong # args.", context));
2508 SIM->get_param_num(BXPN_KBD_SERIAL_DELAY)->set(atol(params[1]));
2509 if (SIM->get_param_num(BXPN_KBD_SERIAL_DELAY)->get() < 5) {
2510 PARSE_ERR (("%s: keyboard_serial_delay not big enough!", context));
2512 } else if (!strcmp(params[0], "keyboard_paste_delay")) {
2513 if (num_params != 2) {
2514 PARSE_ERR(("%s: keyboard_paste_delay directive: wrong # args.", context));
2516 SIM->get_param_num(BXPN_KBD_PASTE_DELAY)->set(atol(params[1]));
2517 if (SIM->get_param_num(BXPN_KBD_PASTE_DELAY)->get() < 1000) {
2518 PARSE_ERR (("%s: keyboard_paste_delay not big enough!", context));
2520 } else if (!strcmp(params[0], "floppy_command_delay")) {
2521 PARSE_WARN(("%s: floppy_command_delay is DEPRECATED (now using hardware timing).", context));
2522 } else if (!strcmp(params[0], "ips")) {
2523 PARSE_WARN(("%s: ips directive is DEPRECATED (use cpu directive parameter 'ips').", context));
2524 if (num_params != 2) {
2525 PARSE_ERR(("%s: ips directive: wrong # args.", context));
2527 SIM->get_param_num(BXPN_IPS)->set(atol(params[1]));
2528 if (SIM->get_param_num(BXPN_IPS)->get() < BX_MIN_IPS) {
2529 PARSE_WARN(("%s: WARNING: ips is AWFULLY low!", context));
2531 } else if (!strcmp(params[0], "text_snapshot_check")) {
2532 if (num_params != 2) {
2533 PARSE_ERR(("%s: text_snapshot_check directive: wrong # args.", context));
2535 if (!strncmp(params[1], "enabled=", 8)) {
2536 if (params[1][8] == '0' || params[1][8] == '1')
2537 SIM->get_param_bool(BXPN_TEXT_SNAPSHOT_CHECK)->set(params[1][8] - '0');
2538 else
2539 PARSE_ERR(("%s: text_snapshot_check directive malformed.", context));
2540 } else {
2541 PARSE_ERR(("%s: text_snapshot_check directive malformed.", context));
2543 } else if (!strcmp(params[0], "mouse")) {
2544 if (num_params < 2) {
2545 PARSE_ERR(("%s: mouse directive malformed.", context));
2547 for (i=1; i<num_params; i++) {
2548 if (!strncmp(params[i], "enabled=", 8)) {
2549 if (params[i][8] == '0' || params[i][8] == '1')
2550 SIM->get_param_bool(BXPN_MOUSE_ENABLED)->set(params[i][8] - '0');
2551 else
2552 PARSE_ERR(("%s: mouse directive malformed.", context));
2553 } else if (!strncmp(params[i], "type=", 5)) {
2554 if (!SIM->get_param_enum(BXPN_MOUSE_TYPE)->set_by_name(&params[i][5]))
2555 PARSE_ERR(("%s: mouse type '%s' not available", context, &params[i][5]));
2556 } else {
2557 PARSE_ERR(("%s: mouse directive malformed.", context));
2560 } else if (!strcmp(params[0], "private_colormap")) {
2561 if (num_params != 2) {
2562 PARSE_ERR(("%s: private_colormap directive malformed.", context));
2564 if (strncmp(params[1], "enabled=", 8)) {
2565 PARSE_ERR(("%s: private_colormap directive malformed.", context));
2567 if (params[1][8] == '0' || params[1][8] == '1')
2568 SIM->get_param_bool(BXPN_PRIVATE_COLORMAP)->set(params[1][8] - '0');
2569 else {
2570 PARSE_ERR(("%s: private_colormap directive malformed.", context));
2572 } else if (!strcmp(params[0], "fullscreen")) {
2573 #if BX_WITH_AMIGAOS
2574 if (num_params != 2) {
2575 PARSE_ERR(("%s: fullscreen directive malformed.", context));
2577 if (strncmp(params[1], "enabled=", 8)) {
2578 PARSE_ERR(("%s: fullscreen directive malformed.", context));
2580 if (params[1][8] == '0' || params[1][8] == '1') {
2581 SIM->get_param_bool(BXPN_FULLSCREEN)->set(params[1][8] - '0');
2582 } else {
2583 PARSE_ERR(("%s: fullscreen directive malformed.", context));
2585 #endif
2586 } else if (!strcmp(params[0], "screenmode")) {
2587 #if BX_WITH_AMIGAOS
2588 if (num_params != 2) {
2589 PARSE_ERR(("%s: screenmode directive malformed.", context));
2591 if (strncmp(params[1], "name=", 5)) {
2592 PARSE_ERR(("%s: screenmode directive malformed.", context));
2594 SIM->get_param_string(BXPN_SCREENMODE)->set(&params[1][5]);
2595 #endif
2596 } else if (!strcmp(params[0], "sb16")) {
2597 int enable = 1;
2598 base = (bx_list_c*) SIM->get_param(BXPN_SB16);
2599 for (i=1; i<num_params; i++) {
2600 if (!strncmp(params[i], "enabled=", 8)) {
2601 enable = atol(&params[i][8]);
2602 } else if (!strncmp(params[i], "midi=", 5)) {
2603 SIM->get_param_string("midifile", base)->set(&params[i][5]);
2604 } else if (!strncmp(params[i], "midimode=", 9)) {
2605 SIM->get_param_num("midimode", base)->set(atol(&params[i][9]));
2606 } else if (!strncmp(params[i], "wave=", 5)) {
2607 SIM->get_param_string("wavefile", base)->set(&params[i][5]);
2608 } else if (!strncmp(params[i], "wavemode=", 9)) {
2609 SIM->get_param_num("wavemode", base)->set(atol(&params[i][9]));
2610 } else if (!strncmp(params[i], "log=", 4)) {
2611 SIM->get_param_string("logfile", base)->set(&params[i][4]);
2612 } else if (!strncmp(params[i], "loglevel=", 9)) {
2613 SIM->get_param_num("loglevel", base)->set(atol(&params[i][9]));
2614 } else if (!strncmp(params[i], "dmatimer=", 9)) {
2615 SIM->get_param_num("dmatimer", base)->set(atol(&params[i][9]));
2616 } else {
2617 BX_ERROR(("%s: unknown parameter for sb16 ignored.", context));
2620 if ((enable != 0) && (SIM->get_param_num("dmatimer", base)->get() > 0))
2621 SIM->get_param_bool("enabled", base)->set(1);
2622 else
2623 SIM->get_param_bool("enabled", base)->set(0);
2624 } else if ((!strncmp(params[0], "com", 3)) && (strlen(params[0]) == 4)) {
2625 char tmpname[80];
2626 idx = params[0][3];
2627 if ((idx < '1') || (idx > '9')) {
2628 PARSE_ERR(("%s: comX directive malformed.", context));
2630 idx -= '0';
2631 if (idx > BX_N_SERIAL_PORTS) {
2632 PARSE_ERR(("%s: comX port number out of range.", context));
2634 sprintf(tmpname, "ports.serial.%d", idx);
2635 base = (bx_list_c*) SIM->get_param(tmpname);
2636 for (i=1; i<num_params; i++) {
2637 if (!strncmp(params[i], "enabled=", 8)) {
2638 SIM->get_param_bool("enabled", base)->set(atol(&params[i][8]));
2639 } else if (!strncmp(params[i], "mode=", 5)) {
2640 if (!SIM->get_param_enum("mode", base)->set_by_name(&params[i][5]))
2641 PARSE_ERR(("%s: com%d serial port mode '%s' not available", context, idx, &params[i][5]));
2642 SIM->get_param_bool("enabled", base)->set(1);
2643 } else if (!strncmp(params[i], "dev=", 4)) {
2644 SIM->get_param_string("dev", base)->set(&params[i][4]);
2645 SIM->get_param_bool("enabled", base)->set(1);
2646 } else {
2647 PARSE_ERR(("%s: unknown parameter for com%d ignored.", context, idx));
2650 } else if ((!strncmp(params[0], "parport", 7)) && (strlen(params[0]) == 8)) {
2651 char tmpname[80];
2652 idx = params[0][7];
2653 if ((idx < '1') || (idx > '9')) {
2654 PARSE_ERR(("%s: parportX directive malformed.", context));
2656 idx -= '0';
2657 if (idx > BX_N_PARALLEL_PORTS) {
2658 PARSE_ERR(("%s: parportX port number out of range.", context));
2660 sprintf(tmpname, "ports.parallel.%d", idx);
2661 base = (bx_list_c*) SIM->get_param(tmpname);
2662 for (i=1; i<num_params; i++) {
2663 if (!strncmp(params[i], "enabled=", 8)) {
2664 SIM->get_param_bool("enabled", base)->set(atol(&params[i][8]));
2665 } else if (!strncmp(params[i], "file=", 5)) {
2666 SIM->get_param_string("outfile", base)->set(&params[i][5]);
2667 SIM->get_param_bool("enabled", base)->set(1);
2668 } else {
2669 BX_ERROR(("%s: unknown parameter for parport%d ignored.", context, idx));
2672 } else if ((!strncmp(params[0], "usb", 3)) && (strlen(params[0]) == 4)) {
2673 char tmpname[80];
2674 idx = params[0][3];
2675 if ((idx < '1') || (idx > '9')) {
2676 PARSE_ERR(("%s: usbX directive malformed.", context));
2678 idx -= '0';
2679 if (idx > BX_N_USB_HUBS) {
2680 PARSE_ERR(("%s: usbX hub number out of range.", context));
2682 sprintf(tmpname, "ports.usb.%d", idx);
2683 base = (bx_list_c*) SIM->get_param(tmpname);
2684 for (i=1; i<num_params; i++) {
2685 if (!strncmp(params[i], "enabled=", 8)) {
2686 SIM->get_param_bool("enabled", base)->set(atol(&params[i][8]));
2687 } else if (!strncmp(params[i], "port1=", 6)) {
2688 SIM->get_param_string("port1", base)->set(&params[i][6]);
2689 } else if (!strncmp(params[i], "option1=", 8)) {
2690 PARSE_WARN(("%s: usb port1 option is now deprecated", context));
2691 } else if (!strncmp(params[i], "port2=", 6)) {
2692 SIM->get_param_string("port2", base)->set(&params[i][6]);
2693 } else if (!strncmp(params[i], "option2=", 8)) {
2694 PARSE_WARN(("%s: usb port2 option is now deprecated", context));
2695 } else if (!strncmp(params[i], "ioaddr=", 7)) {
2696 PARSE_WARN(("%s: usb ioaddr is now DEPRECATED (assigned by BIOS).", context));
2697 } else if (!strncmp(params[i], "irq=", 4)) {
2698 PARSE_WARN(("%s: usb irq is now DEPRECATED (assigned by BIOS).", context));
2699 } else {
2700 PARSE_WARN(("%s: unknown parameter '%s' for usb%d ignored.", context, params[i], idx));
2703 } else if (!strcmp(params[0], "i440fxsupport")) {
2704 char tmpdev[80];
2705 for (i=1; i<num_params; i++) {
2706 if (!strncmp(params[i], "enabled=", 8)) {
2707 SIM->get_param_bool(BXPN_I440FX_SUPPORT)->set(atol(&params[i][8]));
2708 } else if ((!strncmp(params[i], "slot", 4)) && (params[i][5] == '=')) {
2709 slot = atol(&params[i][4]);
2710 if ((slot > 0) && (slot < 6)) {
2711 sprintf(tmpdev, "pci.slot.%d", slot);
2712 SIM->get_param_string(tmpdev)->set(&params[i][6]);
2713 } else {
2714 BX_ERROR(("%s: unknown pci slot number ignored.", context));
2716 } else {
2717 PARSE_ERR(("%s: i440fxsupport: unknown parameter '%s'.", context, params[i]));
2720 } else if (!strcmp(params[0], "pcidev")) {
2721 if (num_params != 3) {
2722 PARSE_ERR(("%s: pcidev directive malformed.", context));
2724 for (i=1; i<num_params; i++) {
2725 if (!strncmp(params[i], "vendor=", 7)) {
2726 if ( (params[i][7] == '0') && (toupper(params[i][8]) == 'X') )
2727 SIM->get_param_num(BXPN_PCIDEV_VENDOR)->set(strtoul(&params[i][7], NULL, 16));
2728 else
2729 SIM->get_param_num(BXPN_PCIDEV_VENDOR)->set(strtoul(&params[i][7], NULL, 10));
2731 else if (!strncmp(params[i], "device=", 7)) {
2732 if ( (params[i][7] == '0') && (toupper(params[i][8]) == 'X') )
2733 SIM->get_param_num(BXPN_PCIDEV_DEVICE)->set(strtoul(&params[i][7], NULL, 16));
2734 else
2735 SIM->get_param_num(BXPN_PCIDEV_DEVICE)->set(strtoul(&params[i][7], NULL, 10));
2737 else {
2738 BX_ERROR(("%s: unknown parameter for pcidev ignored.", context));
2741 } else if (!strcmp(params[0], "cmosimage")) {
2742 for (i=1; i<num_params; i++) {
2743 if (!strncmp(params[i], "file=", 5)) {
2744 SIM->get_param_string(BXPN_CMOSIMAGE_PATH)->set(&params[i][5]);
2745 } else if (!strcmp(params[i], "rtc_init=time0")) {
2746 SIM->get_param_bool(BXPN_CMOSIMAGE_RTC_INIT)->set(0);
2747 } else if (!strcmp(params[i], "rtc_init=image")) {
2748 SIM->get_param_bool(BXPN_CMOSIMAGE_RTC_INIT)->set(1);
2749 } else {
2750 // for backward compatiblity
2751 SIM->get_param_string(BXPN_CMOSIMAGE_PATH)->set(params[i]);
2754 if (strlen(SIM->get_param_string(BXPN_CMOSIMAGE_PATH)->getptr()) > 0) {
2755 SIM->get_param_bool(BXPN_CMOSIMAGE_ENABLED)->set(1);
2757 } else if (!strcmp(params[0], "clock")) {
2758 for (i=1; i<num_params; i++) {
2759 if (!strncmp(params[i], "sync=", 5)) {
2760 SIM->get_param_enum(BXPN_CLOCK_SYNC)->set_by_name(&params[i][5]);
2762 else if (!strcmp(params[i], "time0=local")) {
2763 SIM->get_param_num(BXPN_CLOCK_TIME0)->set(BX_CLOCK_TIME0_LOCAL);
2765 else if (!strcmp(params[i], "time0=utc")) {
2766 SIM->get_param_num(BXPN_CLOCK_TIME0)->set(BX_CLOCK_TIME0_UTC);
2768 else if (!strncmp(params[i], "time0=", 6)) {
2769 SIM->get_param_num(BXPN_CLOCK_TIME0)->set(atoi(&params[i][6]));
2771 else {
2772 BX_ERROR(("%s: unknown parameter for clock ignored.", context));
2776 else if (!strcmp(params[0], "gdbstub")) {
2777 #if BX_GDBSTUB
2778 if (num_params < 2) {
2779 PARSE_ERR(("%s: gdbstub directive: wrong # args.", context));
2781 base = (bx_list_c*) SIM->get_param(BXPN_GDBSTUB);
2782 for (i=1; i<num_params; i++) {
2783 if (!strncmp(params[i], "enabled=", 8)) {
2784 if (params[i][8] == '0') {
2785 SIM->get_param_bool("enabled", base)->set(0);
2786 BX_INFO(("Disabled gdbstub"));
2787 bx_dbg.gdbstub_enabled = 0;
2789 else if (params[i][8] == '1') {
2790 SIM->get_param_bool("enabled", base)->set(1);
2791 BX_INFO(("Enabled gdbstub"));
2792 bx_dbg.gdbstub_enabled = 1;
2794 else {
2795 PARSE_ERR(("%s: gdbstub directive malformed.", context));
2798 else if (!strncmp(params[i], "port=", 5)) {
2799 SIM->get_param_num("port", base)->set(atoi(&params[i][5]));
2801 else if (!strncmp(params[i], "text_base=", 10)) {
2802 SIM->get_param_num("text_base", base)->set(atoi(&params[i][10]));
2804 else if (!strncmp(params[i], "data_base=", 10)) {
2805 SIM->get_param_num("data_base", base)->set(atoi(&params[i][10]));
2807 else if (!strncmp(params[i], "bss_base=", 9)) {
2808 SIM->get_param_num("bss_base", base)->set(atoi(&params[i][9]));
2810 else {
2811 PARSE_ERR(("%s: gdbstub directive malformed.", context));
2814 #else
2815 PARSE_ERR(("%s: Bochs is not compiled with gdbstub support", context));
2816 #endif
2819 #if BX_MAGIC_BREAKPOINT
2820 else if (!strcmp(params[0], "magic_break")) {
2821 if (num_params != 2) {
2822 PARSE_ERR(("%s: magic_break directive: wrong # args.", context));
2824 if (strncmp(params[1], "enabled=", 8)) {
2825 PARSE_ERR(("%s: magic_break directive malformed.", context));
2827 if (params[1][8] == '0') {
2828 BX_INFO(("Ignoring magic break points"));
2829 bx_dbg.magic_break_enabled = 0;
2831 else if (params[1][8] == '1') {
2832 BX_INFO(("Stopping on magic break points"));
2833 bx_dbg.magic_break_enabled = 1;
2835 else {
2836 PARSE_ERR(("%s: magic_break directive malformed.", context));
2839 #endif
2840 else if (!strcmp(params[0], "print_timestamps")) {
2841 if (num_params != 2) {
2842 PARSE_ERR(("%s: print_timestamps directive: wrong # args.", context));
2844 if (strncmp(params[1], "enabled=", 8)) {
2845 PARSE_ERR(("%s: print_timestamps directive malformed.", context));
2847 if (params[1][8] == '0' || params[1][8] == '1') {
2848 bx_dbg.print_timestamps = params[1][8] - '0';
2850 else {
2851 PARSE_ERR(("%s: print_timestamps directive malformed.", context));
2854 else if (!strcmp(params[0], "ne2k")) {
2855 int tmp[6];
2856 char tmpchar[6];
2857 int valid = 0;
2858 int n;
2859 base = (bx_list_c*) SIM->get_param(BXPN_NE2K);
2860 if (!SIM->get_param_bool("enabled", base)->get()) {
2861 SIM->get_param_enum("ethmod", base)->set_by_name("null");
2863 for (i=1; i<num_params; i++) {
2864 if (!strncmp(params[i], "enabled=", 8)) {
2865 if (atol(&params[i][8]) == 0) valid |= 0x80;
2867 else if (!strncmp(params[i], "ioaddr=", 7)) {
2868 SIM->get_param_num("ioaddr", base)->set(strtoul(&params[i][7], NULL, 16));
2869 valid |= 0x01;
2871 else if (!strncmp(params[i], "irq=", 4)) {
2872 SIM->get_param_num("irq", base)->set(atol(&params[i][4]));
2873 valid |= 0x02;
2875 else if (!strncmp(params[i], "mac=", 4)) {
2876 n = sscanf(&params[i][4], "%x:%x:%x:%x:%x:%x",
2877 &tmp[0],&tmp[1],&tmp[2],&tmp[3],&tmp[4],&tmp[5]);
2878 if (n != 6) {
2879 PARSE_ERR(("%s: ne2k mac address malformed.", context));
2881 for (n=0;n<6;n++)
2882 tmpchar[n] = (unsigned char)tmp[n];
2883 SIM->get_param_string("macaddr", base)->set(tmpchar);
2884 valid |= 0x04;
2886 else if (!strncmp(params[i], "ethmod=", 7)) {
2887 if (!SIM->get_param_enum("ethmod", base)->set_by_name(&params[i][7]))
2888 PARSE_ERR(("%s: ethernet module '%s' not available", context, &params[i][7]));
2890 else if (!strncmp(params[i], "ethdev=", 7)) {
2891 SIM->get_param_string("ethdev", base)->set(&params[i][7]);
2893 else if (!strncmp(params[i], "script=", 7)) {
2894 SIM->get_param_string("script", base)->set(&params[i][7]);
2896 else {
2897 PARSE_WARN(("%s: unknown parameter '%s' for ne2k ignored.", context, params[i]));
2900 if (!SIM->get_param_bool("enabled", base)->get()) {
2901 if (valid == 0x07) {
2902 SIM->get_param_bool("enabled", base)->set(1);
2903 } else if (valid < 0x80) {
2904 PARSE_ERR(("%s: ne2k directive incomplete (ioaddr, irq and mac are required)", context));
2906 } else {
2907 if (valid & 0x80) {
2908 SIM->get_param_bool("enabled", base)->set(0);
2911 } else if (!strcmp(params[0], "pnic")) {
2912 int tmp[6];
2913 char tmpchar[6];
2914 int valid = 0;
2915 int n;
2916 base = (bx_list_c*) SIM->get_param(BXPN_PNIC);
2917 if (!SIM->get_param_bool("enabled", base)->get()) {
2918 SIM->get_param_enum("ethmod", base)->set_by_name("null");
2920 for (i=1; i<num_params; i++) {
2921 if (!strncmp(params[i], "enabled=", 8)) {
2922 if (atol(&params[i][8]) == 0) valid |= 0x80;
2923 } else if (!strncmp(params[i], "ioaddr=", 7)) {
2924 PARSE_WARN(("%s: pnic ioaddr is now DEPRECATED (assigned by BIOS).", context));
2925 } else if (!strncmp(params[i], "irq=", 4)) {
2926 PARSE_WARN(("%s: pnic irq is now DEPRECATED (assigned by BIOS).", context));
2927 } else if (!strncmp(params[i], "mac=", 4)) {
2928 n = sscanf(&params[i][4], "%x:%x:%x:%x:%x:%x",
2929 &tmp[0],&tmp[1],&tmp[2],&tmp[3],&tmp[4],&tmp[5]);
2930 if (n != 6) {
2931 PARSE_ERR(("%s: pnic mac address malformed.", context));
2933 for (n=0;n<6;n++)
2934 tmpchar[n] = (unsigned char)tmp[n];
2935 SIM->get_param_string("macaddr", base)->set(tmpchar);
2936 valid |= 0x07;
2937 } else if (!strncmp(params[i], "ethmod=", 7)) {
2938 if (!SIM->get_param_enum("ethmod", base)->set_by_name(&params[i][7]))
2939 PARSE_ERR(("%s: ethernet module '%s' not available", context, &params[i][7]));
2940 } else if (!strncmp(params[i], "ethdev=", 7)) {
2941 SIM->get_param_string("ethdev", base)->set(&params[i][7]);
2942 } else if (!strncmp(params[i], "script=", 7)) {
2943 SIM->get_param_string("script", base)->set(&params[i][7]);
2944 } else {
2945 PARSE_WARN(("%s: unknown parameter '%s' for pnic ignored.", context, params[i]));
2948 if (!SIM->get_param_bool("enabled", base)->get()) {
2949 if (valid == 0x07) {
2950 SIM->get_param_bool("enabled", base)->set(1);
2951 } else if (valid < 0x80) {
2952 PARSE_ERR(("%s: pnic directive incomplete (mac is required)", context));
2954 } else {
2955 if (valid & 0x80) {
2956 SIM->get_param_bool("enabled", base)->set(0);
2959 } else if (!strcmp(params[0], "load32bitOSImage")) {
2960 if ( (num_params!=4) && (num_params!=5) ) {
2961 PARSE_ERR(("%s: load32bitOSImage directive: wrong # args.", context));
2963 if (strncmp(params[1], "os=", 3)) {
2964 PARSE_ERR(("%s: load32bitOSImage: directive malformed.", context));
2966 if (!strcmp(&params[1][3], "nullkernel")) {
2967 SIM->get_param_enum(BXPN_LOAD32BITOS_WHICH)->set(Load32bitOSNullKernel);
2969 else if (!strcmp(&params[1][3], "linux")) {
2970 SIM->get_param_enum(BXPN_LOAD32BITOS_WHICH)->set(Load32bitOSLinux);
2972 else {
2973 PARSE_ERR(("%s: load32bitOSImage: unsupported OS.", context));
2975 if (strncmp(params[2], "path=", 5)) {
2976 PARSE_ERR(("%s: load32bitOSImage: directive malformed.", context));
2978 if (strncmp(params[3], "iolog=", 6)) {
2979 PARSE_ERR(("%s: load32bitOSImage: directive malformed.", context));
2981 SIM->get_param_string(BXPN_LOAD32BITOS_PATH)->set(&params[2][5]);
2982 SIM->get_param_string(BXPN_LOAD32BITOS_IOLOG)->set(&params[3][6]);
2983 if (num_params == 5) {
2984 if (strncmp(params[4], "initrd=", 7)) {
2985 PARSE_ERR(("%s: load32bitOSImage: directive malformed.", context));
2987 SIM->get_param_string(BXPN_LOAD32BITOS_INITRD)->set(&params[4][7]);
2990 else if (!strcmp(params[0], "keyboard_type")) {
2991 if (num_params != 2) {
2992 PARSE_ERR(("%s: keyboard_type directive: wrong # args.", context));
2994 if (!SIM->get_param_enum(BXPN_KBD_TYPE)->set_by_name(params[1])) {
2995 PARSE_ERR(("%s: keyboard_type directive: wrong arg '%s'.", context,params[1]));
2998 else if (!strcmp(params[0], "keyboard_mapping")
2999 ||!strcmp(params[0], "keyboardmapping")) {
3000 for (i=1; i<num_params; i++) {
3001 if (!strncmp(params[i], "enabled=", 8)) {
3002 SIM->get_param_bool(BXPN_KBD_USEMAPPING)->set(atol(&params[i][8]));
3004 else if (!strncmp(params[i], "map=", 4)) {
3005 SIM->get_param_string(BXPN_KBD_KEYMAP)->set(&params[i][4]);
3009 else if (!strcmp(params[0], "user_shortcut"))
3011 if (num_params != 2) {
3012 PARSE_ERR(("%s: user_shortcut directive: wrong # args.", context));
3014 if(!strncmp(params[1], "keys=", 4)) {
3015 SIM->get_param_string(BXPN_USER_SHORTCUT)->set(&params[1][5]);
3016 if ((strchr(&params[1][5], '-') == NULL) && (strlen(&params[1][5]) > 5))
3017 PARSE_WARN(("user_shortcut: old-style syntax detected"));
3018 } else {
3019 PARSE_ERR(("%s: user_shortcut directive malformed.", context));
3022 else if (!strcmp(params[0], "config_interface"))
3024 if (num_params != 2) {
3025 PARSE_ERR(("%s: config_interface directive: wrong # args.", context));
3027 if (!SIM->get_param_enum(BXPN_SEL_CONFIG_INTERFACE)->set_by_name(params[1]))
3028 PARSE_ERR(("%s: config_interface '%s' not available", context, params[1]));
3030 else if (!strcmp(params[0], "display_library")) {
3031 if ((num_params < 2) || (num_params > 3)) {
3032 PARSE_ERR(("%s: display_library directive: wrong # args.", context));
3034 if (!SIM->get_param_enum(BXPN_SEL_DISPLAY_LIBRARY)->set_by_name(params[1]))
3035 PARSE_ERR(("%s: display library '%s' not available", context, params[1]));
3036 if (num_params == 3) {
3037 if (!strncmp(params[2], "options=", 8)) {
3038 SIM->get_param_string(BXPN_DISPLAYLIB_OPTIONS)->set(&params[2][8]);
3042 // Old timing options have been replaced by the 'clock' option
3043 else if (!strcmp(params[0], "pit")) // Deprecated
3045 PARSE_ERR(("ERROR: pit directive is DEPRECATED, use clock: instead"));
3047 else if (!strcmp(params[0], "time0")) // Deprectated
3049 PARSE_ERR(("ERROR: time0 directive is DEPRECATED, use clock: instead"));
3051 // user-defined options handled by registered functions
3052 else if ((i = SIM->find_user_option(params[0])) >= 0)
3054 return SIM->parse_user_option(i, context, num_params, &params[0]);
3056 else
3058 PARSE_ERR(( "%s: directive '%s' not understood", context, params[0]));
3060 return 0;
3064 static const char *fdtypes[] = {
3065 "none", "1_2", "1_44", "2_88", "720k", "360k", "160k", "180k", "320k"
3068 int bx_write_floppy_options(FILE *fp, int drive)
3070 char path[80], type[80], status[80];
3072 BX_ASSERT(drive==0 || drive==1);
3073 sprintf(path, "floppy.%d.path", drive);
3074 sprintf(type, "floppy.%d.type", drive);
3075 sprintf(status, "floppy.%d.status", drive);
3076 if (SIM->get_param_enum(type)->get() == BX_FLOPPY_NONE) {
3077 fprintf(fp, "# no floppy%c\n", (char)'a'+drive);
3078 return 0;
3080 BX_ASSERT(SIM->get_param_enum(type)->get() > BX_FLOPPY_NONE &&
3081 SIM->get_param_enum(type)->get() <= BX_FLOPPY_LAST);
3082 fprintf(fp, "floppy%c: %s=\"%s\", status=%s\n",
3083 (char)'a'+drive,
3084 fdtypes[SIM->get_param_enum(type)->get() - BX_FLOPPY_NONE],
3085 SIM->get_param_string(path)->getptr(),
3086 SIM->get_param_enum(status)->get_selected());
3087 return 0;
3090 int bx_write_ata_options(FILE *fp, Bit8u channel, bx_list_c *base)
3092 fprintf(fp, "ata%d: enabled=%d", channel, SIM->get_param_bool("enabled", base)->get());
3094 if (SIM->get_param_bool("enabled", base)->get()) {
3095 fprintf(fp, ", ioaddr1=0x%x, ioaddr2=0x%x, irq=%d", SIM->get_param_num("ioaddr1", base)->get(),
3096 SIM->get_param_num("ioaddr2", base)->get(), SIM->get_param_num("irq", base)->get());
3099 fprintf(fp, "\n");
3100 return 0;
3103 int bx_write_atadevice_options(FILE *fp, Bit8u channel, Bit8u drive, bx_list_c *base)
3105 if (SIM->get_param_bool("present", base)->get()) {
3106 fprintf(fp, "ata%d-%s: ", channel, drive==0?"master":"slave");
3108 if (SIM->get_param_enum("type", base)->get() == BX_ATA_DEVICE_DISK) {
3109 fprintf(fp, "type=disk");
3111 fprintf(fp, ", mode=%s", SIM->get_param_enum("mode", base)->get_selected());
3112 fprintf(fp, ", translation=%s", SIM->get_param_enum("translation", base)->get_selected());
3113 fprintf(fp, ", path=\"%s\", cylinders=%d, heads=%d, spt=%d",
3114 SIM->get_param_string("path", base)->getptr(),
3115 SIM->get_param_num("cylinders", base)->get(),
3116 SIM->get_param_num("heads", base)->get(),
3117 SIM->get_param_num("spt", base)->get());
3119 if (SIM->get_param_string("journal", base)->getptr() != NULL)
3120 if (strcmp(SIM->get_param_string("journal", base)->getptr(), "") != 0)
3121 fprintf(fp, ", journal=\"%s\"", SIM->get_param_string("journal", base)->getptr());
3123 } else if (SIM->get_param_enum("type", base)->get() == BX_ATA_DEVICE_CDROM) {
3124 fprintf(fp, "type=cdrom, path=\"%s\", status=%s",
3125 SIM->get_param_string("path", base)->getptr(),
3126 SIM->get_param_enum("status", base)->get_selected());
3129 fprintf(fp, ", biosdetect=%s", SIM->get_param_enum("biosdetect", base)->get_selected());
3131 if (SIM->get_param_string("model", base)->getptr()>0) {
3132 fprintf(fp, ", model=\"%s\"", SIM->get_param_string("model", base)->getptr());
3135 fprintf(fp, "\n");
3137 return 0;
3140 int bx_write_parport_options(FILE *fp, bx_list_c *base, int n)
3142 fprintf(fp, "parport%d: enabled=%d", n, SIM->get_param_bool("enabled", base)->get());
3143 if (SIM->get_param_bool("enabled", base)->get()) {
3144 fprintf(fp, ", file=\"%s\"", SIM->get_param_string("outfile", base)->getptr());
3146 fprintf(fp, "\n");
3147 return 0;
3150 int bx_write_serial_options(FILE *fp, bx_list_c *base, int n)
3152 fprintf(fp, "com%d: enabled=%d", n, SIM->get_param_bool("enabled", base)->get());
3153 if (SIM->get_param_bool("enabled", base)->get()) {
3154 fprintf(fp, ", mode=%s", SIM->get_param_enum("mode", base)->get_selected());
3155 fprintf(fp, ", dev=\"%s\"", SIM->get_param_string("dev", base)->getptr());
3157 fprintf(fp, "\n");
3158 return 0;
3161 int bx_write_usb_options(FILE *fp, bx_list_c *base, int n)
3163 fprintf(fp, "usb%d: enabled=%d", n, SIM->get_param_bool("enabled", base)->get());
3164 if (SIM->get_param_bool("enabled", base)->get()) {
3165 fprintf(fp, ", port1=%s", SIM->get_param_string("port1", base)->getptr());
3166 fprintf(fp, ", port2=%s", SIM->get_param_string("port2", base)->getptr());
3168 fprintf(fp, "\n");
3169 return 0;
3172 int bx_write_pnic_options(FILE *fp, bx_list_c *base)
3174 fprintf (fp, "pnic: enabled=%d", SIM->get_param_bool("enabled", base)->get());
3175 if (SIM->get_param_bool("enabled", base)->get()) {
3176 char *ptr = SIM->get_param_string("macaddr", base)->getptr();
3177 fprintf (fp, ", mac=%02x:%02x:%02x:%02x:%02x:%02x, ethmod=%s, ethdev=%s, script=%s",
3178 (unsigned int)(0xff & ptr[0]),
3179 (unsigned int)(0xff & ptr[1]),
3180 (unsigned int)(0xff & ptr[2]),
3181 (unsigned int)(0xff & ptr[3]),
3182 (unsigned int)(0xff & ptr[4]),
3183 (unsigned int)(0xff & ptr[5]),
3184 SIM->get_param_enum("ethmod", base)->get_selected(),
3185 SIM->get_param_string("ethdev", base)->getptr(),
3186 SIM->get_param_string("script", base)->getptr());
3188 fprintf (fp, "\n");
3189 return 0;
3192 int bx_write_ne2k_options (FILE *fp, bx_list_c *base)
3194 fprintf(fp, "ne2k: enabled=%d", SIM->get_param_bool("enabled", base)->get());
3195 if (SIM->get_param_bool("enabled", base)->get()) {
3196 char *ptr = SIM->get_param_string("macaddr", base)->getptr();
3197 fprintf(fp, ", ioaddr=0x%x, irq=%d, mac=%02x:%02x:%02x:%02x:%02x:%02x, ethmod=%s, ethdev=%s, script=%s",
3198 SIM->get_param_num("ioaddr", base)->get(),
3199 SIM->get_param_num("irq", base)->get(),
3200 (unsigned int)(0xff & ptr[0]),
3201 (unsigned int)(0xff & ptr[1]),
3202 (unsigned int)(0xff & ptr[2]),
3203 (unsigned int)(0xff & ptr[3]),
3204 (unsigned int)(0xff & ptr[4]),
3205 (unsigned int)(0xff & ptr[5]),
3206 SIM->get_param_enum("ethmod", base)->get_selected(),
3207 SIM->get_param_string("ethdev", base)->getptr(),
3208 SIM->get_param_string("script", base)->getptr());
3210 fprintf(fp, "\n");
3211 return 0;
3214 int bx_write_sb16_options (FILE *fp, bx_list_c *base)
3216 fprintf(fp, "sb16: enabled=%d", SIM->get_param_bool("enabled", base)->get());
3217 if (SIM->get_param_bool("enabled", base)->get()) {
3218 fprintf(fp, ", midimode=%d, midi=%s, wavemode=%d, wave=%s, loglevel=%d, log=%s, dmatimer=%d",
3219 SIM->get_param_num("midimode", base)->get(),
3220 SIM->get_param_string("midifile", base)->getptr(),
3221 SIM->get_param_num("wavemode", base)->get(),
3222 SIM->get_param_string("wavefile", base)->getptr(),
3223 SIM->get_param_num("loglevel", base)->get(),
3224 SIM->get_param_string("logfile", base)->getptr(),
3225 SIM->get_param_num("dmatimer", base)->get());
3227 fprintf(fp, "\n");
3228 return 0;
3231 int bx_write_loader_options(FILE *fp)
3233 if (SIM->get_param_enum(BXPN_LOAD32BITOS_WHICH)->get() == Load32bitOSNone) {
3234 fprintf(fp, "# no loader\n");
3235 return 0;
3237 BX_ASSERT((SIM->get_param_enum(BXPN_LOAD32BITOS_WHICH)->get() == Load32bitOSLinux) ||
3238 (SIM->get_param_enum(BXPN_LOAD32BITOS_WHICH)->get() == Load32bitOSNullKernel));
3239 fprintf (fp, "load32bitOSImage: os=%s, path=%s, iolog=%s, initrd=%s\n",
3240 (SIM->get_param_enum(BXPN_LOAD32BITOS_WHICH)->get() == Load32bitOSLinux) ? "linux" : "nullkernel",
3241 SIM->get_param_string(BXPN_LOAD32BITOS_PATH)->getptr(),
3242 SIM->get_param_string(BXPN_LOAD32BITOS_IOLOG)->getptr(),
3243 SIM->get_param_string(BXPN_LOAD32BITOS_INITRD)->getptr());
3244 return 0;
3247 int bx_write_clock_cmos_options(FILE *fp)
3249 fprintf(fp, "clock: ");
3251 switch (SIM->get_param_enum(BXPN_CLOCK_SYNC)->get()) {
3252 case BX_CLOCK_SYNC_NONE:
3253 fprintf(fp, "sync=none");
3254 break;
3255 case BX_CLOCK_SYNC_REALTIME:
3256 fprintf(fp, "sync=realtime");
3257 break;
3258 case BX_CLOCK_SYNC_SLOWDOWN:
3259 fprintf(fp, "sync=slowdown");
3260 break;
3261 case BX_CLOCK_SYNC_BOTH:
3262 fprintf(fp, "sync=both");
3263 break;
3264 default:
3265 BX_PANIC(("Unknown value for sync method"));
3268 switch (SIM->get_param_num(BXPN_CLOCK_TIME0)->get()) {
3269 case 0: break;
3270 case BX_CLOCK_TIME0_LOCAL:
3271 fprintf(fp, ", time0=local");
3272 break;
3273 case BX_CLOCK_TIME0_UTC:
3274 fprintf(fp, ", time0=utc");
3275 break;
3276 default:
3277 fprintf(fp, ", time0=%u", SIM->get_param_num(BXPN_CLOCK_TIME0)->get());
3280 fprintf(fp, "\n");
3282 if (strlen(SIM->get_param_string(BXPN_CMOSIMAGE_PATH)->getptr()) > 0) {
3283 fprintf(fp, "cmosimage: file=%s, ", SIM->get_param_string(BXPN_CMOSIMAGE_PATH)->getptr());
3284 fprintf(fp, "rtc_init=%s\n", SIM->get_param_bool(BXPN_CMOSIMAGE_RTC_INIT)->get()?"image":"time0");
3285 } else {
3286 fprintf(fp, "# no cmosimage\n");
3288 return 0;
3291 int bx_write_log_options(FILE *fp, bx_list_c *base)
3293 fprintf(fp, "log: %s\n", SIM->get_param_string("filename", base)->getptr());
3294 fprintf(fp, "logprefix: %s\n", SIM->get_param_string("prefix", base)->getptr());
3295 fprintf(fp, "debugger_log: %s\n", SIM->get_param_string("debugger_filename", base)->getptr());
3296 fprintf(fp, "panic: action=%s\n",
3297 io->getaction(logfunctions::get_default_action (LOGLEV_PANIC)));
3298 fprintf(fp, "error: action=%s\n",
3299 io->getaction(logfunctions::get_default_action (LOGLEV_ERROR)));
3300 fprintf(fp, "info: action=%s\n",
3301 io->getaction(logfunctions::get_default_action (LOGLEV_INFO)));
3302 fprintf(fp, "debug: action=%s\n",
3303 io->getaction(logfunctions::get_default_action (LOGLEV_DEBUG)));
3304 fprintf(fp, "pass: action=%s\n",
3305 io->getaction(logfunctions::get_default_action (LOGLEV_PASS)));
3306 return 0;
3309 int bx_write_keyboard_options(FILE *fp)
3311 fprintf(fp, "keyboard_type: %s\n", SIM->get_param_enum(BXPN_KBD_TYPE)->get_selected());
3312 fprintf(fp, "keyboard_serial_delay: %u\n", SIM->get_param_num(BXPN_KBD_SERIAL_DELAY)->get());
3313 fprintf(fp, "keyboard_paste_delay: %u\n", SIM->get_param_num(BXPN_KBD_PASTE_DELAY)->get());
3314 fprintf(fp, "keyboard_mapping: enabled=%d, map=%s\n",
3315 SIM->get_param_bool(BXPN_KBD_USEMAPPING)->get(),
3316 SIM->get_param_string(BXPN_KBD_KEYMAP)->getptr());
3317 fprintf(fp, "user_shortcut: keys=%s\n", SIM->get_param_string(BXPN_USER_SHORTCUT)->getptr());
3318 return 0;
3321 // return values:
3322 // 0: written ok
3323 // -1: failed
3324 // -2: already exists, and overwrite was off
3325 int bx_write_configuration(const char *rc, int overwrite)
3327 int i;
3328 char *strptr, tmppath[80], tmpaddr[80], tmpdev[80];
3329 bx_list_c *base;
3330 BX_INFO(("write current configuration to %s", rc));
3331 // check if it exists. If so, only proceed if overwrite is set.
3332 FILE *fp = fopen(rc, "r");
3333 if (fp != NULL) {
3334 fclose(fp);
3335 if (!overwrite) return -2;
3337 fp = fopen(rc, "w");
3338 if (fp == NULL) return -1;
3339 // finally it's open and we can start writing.
3340 fprintf(fp, "# configuration file generated by Bochs\n");
3341 fprintf(fp, "config_interface: %s\n", SIM->get_param_enum(BXPN_SEL_CONFIG_INTERFACE)->get_selected());
3342 fprintf(fp, "display_library: %s", SIM->get_param_enum(BXPN_SEL_DISPLAY_LIBRARY)->get_selected());
3343 strptr = SIM->get_param_string(BXPN_DISPLAYLIB_OPTIONS)->getptr();
3344 if (strlen(strptr) > 0)
3345 fprintf(fp, ", options=\"%s\"\n", strptr);
3346 else
3347 fprintf(fp, "\n");
3348 fprintf(fp, "megs: %d\n", SIM->get_param_num(BXPN_MEM_SIZE)->get());
3349 strptr = SIM->get_param_string(BXPN_ROM_PATH)->getptr();
3350 if (strlen(strptr) > 0) {
3351 fprintf(fp, "romimage: file=\"%s\"", strptr);
3352 if (SIM->get_param_num(BXPN_ROM_ADDRESS)->get() != 0)
3353 fprintf(fp, ", address=0x%08x\n", (unsigned int) SIM->get_param_num(BXPN_ROM_ADDRESS)->get());
3354 else
3355 fprintf(fp, "\n");
3357 else {
3358 fprintf(fp, "# no romimage\n");
3360 strptr = SIM->get_param_string(BXPN_VGA_ROM_PATH)->getptr();
3361 if (strlen(strptr) > 0)
3362 fprintf(fp, "vgaromimage: file=\"%s\"\n", strptr);
3363 else
3364 fprintf(fp, "# no vgaromimage\n");
3365 fprintf(fp, "boot: %s", SIM->get_param_enum(BXPN_BOOTDRIVE1)->get_selected());
3366 for (i=1; i<3; i++) {
3367 sprintf(tmppath, "boot_params.boot_drive%d", i+1);
3368 if (SIM->get_param_enum(tmppath)->get() != BX_BOOT_NONE) {
3369 fprintf(fp, ", %s", SIM->get_param_enum(tmppath)->get_selected());
3372 fprintf(fp, "\n");
3373 fprintf(fp, "floppy_bootsig_check: disabled=%d\n", SIM->get_param_bool(BXPN_FLOPPYSIGCHECK)->get());
3374 // it would be nice to put this type of function as methods on
3375 // the structs like bx_floppy_options::print or something.
3376 bx_write_floppy_options(fp, 0);
3377 bx_write_floppy_options(fp, 1);
3378 for (Bit8u channel=0; channel<BX_MAX_ATA_CHANNEL; channel++) {
3379 sprintf(tmppath, "ata.%d", channel);
3380 base = (bx_list_c*) SIM->get_param(tmppath);
3381 bx_write_ata_options(fp, channel, (bx_list_c*) SIM->get_param("resources", base));
3382 bx_write_atadevice_options(fp, channel, 0, (bx_list_c*) SIM->get_param("master", base));
3383 bx_write_atadevice_options(fp, channel, 1, (bx_list_c*) SIM->get_param("slave", base));
3385 for (i=0; i<BX_N_OPTROM_IMAGES; i++) {
3386 sprintf(tmppath, "memory.optrom.%d.path", i+1);
3387 sprintf(tmpaddr, "memory.optrom.%d.addr", i+1);
3388 strptr = SIM->get_param_string(tmppath)->getptr();
3389 if (strlen(strptr) > 0)
3390 fprintf(fp, "optromimage%d: file=\"%s\", address=0x%05x\n", i+1, strptr,
3391 (unsigned int)SIM->get_param_num(tmpaddr)->get());
3393 for (i=0; i<BX_N_OPTRAM_IMAGES; i++) {
3394 sprintf(tmppath, "memory.optram.%d.path", i+1);
3395 sprintf(tmpaddr, "memory.optram.%d.addr", i+1);
3396 strptr = SIM->get_param_string(tmppath)->getptr();
3397 if (strlen(strptr) > 0)
3398 fprintf(fp, "optramimage%d: file=\"%s\", address=0x%05x\n", i+1, strptr,
3399 (unsigned int)SIM->get_param_num(tmpaddr)->get());
3401 // parallel ports
3402 for (i=0; i<BX_N_PARALLEL_PORTS; i++) {
3403 sprintf(tmpdev, "ports.parallel.%d", i+1);
3404 base = (bx_list_c*) SIM->get_param(tmpdev);
3405 bx_write_parport_options(fp, base, i+1);
3407 // serial ports
3408 for (i=0; i<BX_N_SERIAL_PORTS; i++) {
3409 sprintf(tmpdev, "ports.serial.%d", i+1);
3410 base = (bx_list_c*) SIM->get_param(tmpdev);
3411 bx_write_serial_options(fp, base, i+1);
3413 base = (bx_list_c*) SIM->get_param("ports.usb.1");
3414 bx_write_usb_options(fp, base, 1);
3415 // pci
3416 fprintf(fp, "i440fxsupport: enabled=%d",
3417 SIM->get_param_bool(BXPN_I440FX_SUPPORT)->get());
3418 if (SIM->get_param_bool(BXPN_I440FX_SUPPORT)->get()) {
3419 for (i=0; i<BX_N_PCI_SLOTS; i++) {
3420 sprintf(tmpdev, "pci.slot.%d", i+1);
3421 strptr = SIM->get_param_string(tmpdev)->getptr();
3422 if (strlen(strptr) > 0) {
3423 fprintf(fp, ", slot%d=%s", i+1, strptr);
3427 fprintf(fp, "\n");
3428 if (SIM->get_param_num(BXPN_PCIDEV_VENDOR)->get() != 0xffff) {
3429 fprintf(fp, "pcidev: vendor=0x%04x, device=0x%04x\n",
3430 SIM->get_param_num(BXPN_PCIDEV_VENDOR)->get(),
3431 SIM->get_param_num(BXPN_PCIDEV_DEVICE)->get());
3433 fprintf(fp, "vga_update_interval: %u\n", SIM->get_param_num(BXPN_VGA_UPDATE_INTERVAL)->get());
3434 fprintf(fp, "vga: extension=%s\n", SIM->get_param_string(BXPN_VGA_EXTENSION)->getptr());
3435 #if BX_SUPPORT_SMP
3436 fprintf(fp, "cpu: count=%u:%u:%u, ips=%u, quantum=%d, reset_on_triple_fault=%d\n",
3437 SIM->get_param_num(BXPN_CPU_NPROCESSORS)->get(), SIM->get_param_num(BXPN_CPU_NCORES)->get(),
3438 SIM->get_param_num(BXPN_CPU_NTHREADS)->get(), SIM->get_param_num(BXPN_IPS)->get(),
3439 SIM->get_param_num(BXPN_SMP_QUANTUM)->get(),
3440 SIM->get_param_bool(BXPN_RESET_ON_TRIPLE_FAULT)->get());
3441 #else
3442 fprintf(fp, "cpu: count=1, ips=%u, reset_on_triple_fault=%d\n",
3443 SIM->get_param_num(BXPN_IPS)->get(), SIM->get_param_bool(BXPN_RESET_ON_TRIPLE_FAULT)->get());
3444 #endif
3445 fprintf(fp, "text_snapshot_check: enabled=%d\n", SIM->get_param_bool(BXPN_TEXT_SNAPSHOT_CHECK)->get());
3446 fprintf(fp, "private_colormap: enabled=%d\n", SIM->get_param_bool(BXPN_PRIVATE_COLORMAP)->get());
3447 #if BX_WITH_AMIGAOS
3448 fprintf(fp, "fullscreen: enabled=%d\n", SIM->get_param_bool(BXPN_FULLSCREEN)->get());
3449 fprintf(fp, "screenmode: name=\"%s\"\n", SIM->get_param_string(BXPN_SCREENMODE)->getptr());
3450 #endif
3451 bx_write_clock_cmos_options(fp);
3452 bx_write_ne2k_options(fp, (bx_list_c*) SIM->get_param(BXPN_NE2K));
3453 bx_write_pnic_options(fp, (bx_list_c*) SIM->get_param(BXPN_PNIC));
3454 bx_write_sb16_options(fp, (bx_list_c*) SIM->get_param(BXPN_SB16));
3455 bx_write_loader_options(fp);
3456 bx_write_log_options(fp, (bx_list_c*) SIM->get_param("log"));
3457 bx_write_keyboard_options(fp);
3458 fprintf(fp, "mouse: enabled=%d, type=%s\n",
3459 SIM->get_param_bool(BXPN_MOUSE_ENABLED)->get(),
3460 SIM->get_param_enum(BXPN_MOUSE_TYPE)->get_selected());
3461 SIM->save_user_options(fp);
3462 fclose(fp);
3463 return 0;
3466 #endif // #if BX_PROVIDE_MAIN